### HTTP Server Initialization and Handling in C Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/EMAC_Ethernet_MAC_Controller.md Illustrates the setup and operation of an HTTP server on the AT32F435/437 microcontroller. This example configures the system, initializes the EMAC and lwIP stack, and then starts the HTTP daemon. It prints the server's IP address for connection. Dependencies include AT32 HAL, EMAC driver, netconf, and httpd headers. ```c #include "at32f435_437.h" #include "at32_emac.h" #include "netconf.h" #include "httpd.h" int main(void) { system_clock_config(); at32_board_init(); nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); delay_init(); // Initialize EMAC if(emac_system_init() == ERROR) { while(1); // Failed to initialize } // Initialize TCP/IP stack tcpip_stack_init(); // Start HTTP server httpd_init(); printf("HTTP Server started!\r\n"); printf("Connect to: http://%d.%d.%d.%d\r\n", IP_ADDR0, IP_ADDR1, IP_ADDR2, IP_ADDR3); while(1) { lwip_rx_loop_handler(); lwip_periodic_handle(local_time); } } ``` -------------------------------- ### Example 1: Basic WDT Reset Protection Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/WDT_Watchdog_Timer.md This example demonstrates a basic WDT configuration providing 300ms timeout protection. It includes system initialization, WDT setup, and a loop that continuously feeds the watchdog. ```APIDOC ## Example 1: Basic WDT Reset Protection This example demonstrates a basic WDT configuration providing 300ms timeout protection. It includes system initialization, WDT setup, and a loop that continuously feeds the watchdog. ### Code ```c #include "at32f435_437_board.h" #include "at32f435_437_clock.h" /** * @brief Basic WDT configuration with 300ms timeout * LED3 toggles normally, button press causes WDT reset */ int main(void) { system_clock_config(); at32_board_init(); /* Check if reset was caused by WDT */ if (crm_flag_get(CRM_WDT_RESET_FLAG) != RESET) { crm_flag_clear(CRM_WDT_RESET_FLAG); at32_led_on(LED4); /* Indicate WDT reset occurred */ } else { at32_led_off(LED4); } /* Enable write access to WDT registers */ wdt_register_write_enable(TRUE); /* Set prescaler: LICK / 4 = 10,000 Hz */ wdt_divider_set(WDT_CLK_DIV_4); /* Set reload value for 300ms timeout * timeout = (RLD + 1) * prescaler / LICK * 0.3 = (RLD + 1) * 4 / 40000 * RLD = 2999 */ wdt_reload_value_set(3000 - 1); /* Initial counter reload */ wdt_counter_reload(); /* Enable WDT - cannot be disabled once enabled! */ wdt_enable(); while (1) { /* Feed the watchdog - must be called before timeout */ wdt_counter_reload(); at32_led_toggle(LED3); delay_ms(200); /* Less than 300ms timeout */ /* Button press simulates software hang (no reload) */ if (at32_button_press() == USER_BUTTON) { while (1); /* Infinite loop - WDT will reset */ } } } ``` ### Explanation 1. **Initialization**: System clocks and board peripherals are initialized. 2. **WDT Reset Check**: The code checks if the microcontroller was reset due to a WDT timeout and indicates this with LED4. 3. **Write Enable**: Write access to WDT registers is enabled using `wdt_register_write_enable(TRUE)`. 4. **Prescaler Configuration**: The prescaler is set to divide the LICK frequency by 4 (`WDT_CLK_DIV_4`), resulting in a WDT clock of 10,000 Hz. 5. **Reload Value**: The reload value is set to `2999`. With the prescaler of 4 and LICK frequency of 40,000 Hz, this results in a timeout of approximately 300ms: `(2999 + 1) * 4 / 40000 = 0.3` seconds. 6. **Initial Reload & Enable**: The counter is initially reloaded, and then the WDT is enabled using `wdt_enable()`. Note that enabling the WDT is irreversible. 7. **Main Loop**: Inside the `while(1)` loop: * `wdt_counter_reload()` is called periodically to reset the watchdog timer before it times out. * LED3 is toggled every 200ms, which is less than the 300ms timeout. * If the user button is pressed, the program enters an infinite loop (`while(1);`), preventing `wdt_counter_reload()` from being called. This will cause the WDT to time out and reset the microcontroller. ``` -------------------------------- ### Main Function: System Initialization and DVP Setup Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/DVP_Digital_Video_Port.md The main function orchestrates the system initialization, including clock configuration, board setup, and NVIC priority grouping. It then configures the DVP module and starts the video capture process. Placeholder comments indicate where camera-specific initialization and DMA buffer setup would occur. ```c int main(void) { system_clock_config(); at32_board_init(); nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); /* Initialize camera (OV5640 specific - not shown) */ /* ov5640_init(); */ /* ov5640_rgb565_mode(); */ /* ov5640_outsize_set(0, 0, LCD_W, LCD_H); */ /* Configure DVP */ dvp_config(); /* Configure DMA - LCD data address, buffer for one frame */ /* dvp_dma_init((uint32_t)XMC_LCD_DATA, LCD_W * LCD_H / 2); */ /* Start capture */ dvp_start(); while(1) { /* Application code */ } } ``` -------------------------------- ### Basic WWDT Configuration with Window Protection (C) Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/WWDT_Window_Watchdog_Timer.md Demonstrates a basic setup for the Window Watchdog Timer (WWDT) with window protection enabled. This example configures the system clock, initializes the board, checks for WWDT reset flags, enables the WWDT clock, sets the prescaler and window values, and then enters a loop where the WWDT counter is reloaded. It also includes logic to detect button presses that would intentionally cause a WWDT reset. ```c #include "at32f435_437_board.h" #include "at32f435_437_clock.h" /** * @brief Basic WWDT configuration with window mode * Counter: 0x7F, Window: 0x6F * Must reload when counter is between 0x6F and 0x40 */ int main(void) { system_clock_config(); at32_board_init(); /* Check if reset was caused by WWDT */ if (crm_flag_get(CRM_WWDT_RESET_FLAG) != RESET) { crm_flag_clear(CRM_WWDT_RESET_FLAG); at32_led_on(LED4); /* Indicate WWDT reset */ } else { at32_led_off(LED4); } /* Enable WWDT clock (on APB1) */ crm_periph_clock_enable(CRM_WWDT_PERIPH_CLOCK, TRUE); /* Set prescaler: PCLK1 / 32768 * At PCLK1 = 144 MHz: counter clock = 144M / 4096 / 8 = 4394.5 Hz */ wwdt_divider_set(WWDT_PCLK1_DIV_32768); /* Set window value: 0x6F * Reload is valid only when counter <= 0x6F * Window time = (0x7F - 0x6F) * 32768 / 144MHz = 3.64 ms */ wwdt_window_counter_set(0x6F); /* Enable WWDT with counter = 0x7F * Timeout = (0x7F - 0x3F) * 32768 / 144MHz = 14.56 ms * Valid reload window: 3.64 ms to 14.56 ms after reload */ wwdt_enable(0x7F); while (1) { at32_led_toggle(LED3); /* Wait for window to open (must be > 3.64 ms) */ delay_ms(6); /* Reload counter - must be in valid window */ wwdt_counter_set(0x7F); /* Button press causes infinite loop - WWDT will reset */ if (at32_button_press() == USER_BUTTON) { while (1); } } } ``` -------------------------------- ### Main Function: Full-Duplex I2S Example Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/I2S_Inter_IC_Sound.md The main function demonstrates the setup and execution of full-duplex I2S communication. It initializes the system clock, fills the transmit buffer, configures GPIO, DMA, and I2S peripherals, then enables DMA channels and I2S. It waits for the receive DMA transfer to complete. Requires AT32F435/437 HAL library. ```c int main(void) { uint32_t i; system_clock_config(); /* Fill TX buffer */ for(i = 0; i < BUFFER_SIZE; i++) { i2s_tx_buffer[i] = i; } i2s_fullduplex_gpio_init(); i2s_fullduplex_dma_init(); i2s_fullduplex_init(); /* Enable DMA channels */ dma_channel_enable(DMA1_CHANNEL2, TRUE); /* RX first */ dma_channel_enable(DMA1_CHANNEL1, TRUE); /* TX */ /* Enable I2S */ i2s_enable(SPI2, TRUE); i2s_enable(I2S2EXT, TRUE); /* Wait for RX complete */ while(dma_flag_get(DMA1_FDT2_FLAG) == RESET); /* Data transmitted and received */ while(1); } ``` -------------------------------- ### QSPI Interrupt-Based Command Completion Example (C) Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/QSPI_Quad_SPI.md This C code example demonstrates how to configure and use QSPI interrupts to detect the completion of asynchronous commands. It includes interrupt handler setup, command transmission, and waiting for completion. This method is crucial for non-blocking operations in embedded systems. ```c #include "at32f435_437_board.h" #include "at32f435_437_clock.h" volatile uint8_t cmd_complete = 0; void QSPI1_IRQHandler(void) { if(qspi_interrupt_flag_get(QSPI1, QSPI_CMDSTS_FLAG) != RESET) { qspi_flag_clear(QSPI1, QSPI_CMDSTS_FLAG); cmd_complete = 1; } } void qspi_cmd_send_async(qspi_cmd_type* cmd) { cmd_complete = 0; qspi_cmd_operation_kick(QSPI1, cmd); } void qspi_wait_complete(void) { while(cmd_complete == 0); } int main(void) { system_clock_config(); at32_board_init(); nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); qspi_gpio_config(); qspi_xip_enable(QSPI1, FALSE); qspi_clk_division_set(QSPI1, QSPI_CLK_DIV_4); qspi_sck_mode_set(QSPI1, QSPI_SCK_MODE_0); qspi_busy_config(QSPI1, QSPI_BUSY_OFFSET_0); qspi_auto_ispc_enable(QSPI1); /* Enable interrupt */ nvic_irq_enable(QSPI1_IRQn, 0, 0); qspi_interrupt_enable(QSPI1, TRUE); /* Send command asynchronously */ qspi_cmd_type cmd_rdid = { FALSE, 0, 0x9F, QSPI_CMD_INSLEN_1_BYTE, 0, QSPI_CMD_ADRLEN_0_BYTE, 3, 0, QSPI_OPERATE_MODE_111, QSPI_RSTSC_HW_AUTO, FALSE, FALSE }; qspi_cmd_send_async(&cmd_rdid); /* Do other work... */ at32_led_on(LED2); /* Wait for completion */ qspi_wait_complete(); /* Read ID bytes */ uint8_t mfr_id = qspi_byte_read(QSPI1); uint8_t dev_id1 = qspi_byte_read(QSPI1); uint8_t dev_id2 = qspi_byte_read(QSPI1); at32_led_on(LED3); while(1); } ``` -------------------------------- ### WinUSB Device Example for AT32F435/437 Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/USB_Device_Universal_Serial_Bus.md Implements a custom WinUSB device on the AT32F435/437, enabling automatic driver installation on Windows. The code initializes the USB device stack and includes a loop for receiving data from the host, processing it, and sending a response back. This is suitable for custom USB communication protocols. ```c /** * @brief WinUSB Device Example * @note Custom USB device with automatic Windows driver installation */ #include "at32f435_437_board.h" #include "at32f435_437_clock.h" #include "usb_conf.h" #include "usb_core.h" #include "usbd_int.h" #include "winusb_class.h" #include "winusb_desc.h" otg_core_type otg_core_struct; uint8_t rx_buffer[512]; uint8_t tx_buffer[512]; int main(void) { uint16_t rx_len; nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); system_clock_config(); at32_board_init(); usb_gpio_config(); crm_periph_clock_enable(CRM_OTGFS1_PERIPH_CLOCK, TRUE); crm_usb_clock_div_set(CRM_USB_DIV_3); nvic_irq_enable(OTGFS1_IRQn, 0, 0); /* Initialize WinUSB device */ usbd_init(&otg_core_struct, USB_FULL_SPEED_CORE_ID, USB_OTG1_ID, &winusb_class_handler, &winusb_desc_handler); while(1) { /* Receive data from host */ rx_len = winusb_get_rxdata(&otg_core_struct.dev, rx_buffer); if(rx_len > 0) { /* Process received data and prepare response */ process_command(rx_buffer, rx_len, tx_buffer); /* Send response to host */ winusb_send_data(&otg_core_struct.dev, tx_buffer, tx_len); } } } ``` -------------------------------- ### MQTT Client Example for AT32F435/437 Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/EMAC_Ethernet_MAC_Controller.md This C code demonstrates how to implement an MQTT client on the AT32F435/437 microcontroller. It includes connecting to an MQTT broker, subscribing to topics, and publishing sensor data. Dependencies include the AT32 HAL, EMAC driver, and an MQTT client library. The example takes temperature data as input and publishes it to a specified topic. ```c #include "at32f435_437.h" #include "at32_emac.h" #include "mqtt_client.h" #define MQTT_BROKER_IP "192.168.1.100" #define MQTT_BROKER_PORT 1883 #define MQTT_CLIENT_ID "at32f437_client" #define MQTT_TOPIC "sensors/temperature" mqtt_client_t mqtt_client; void mqtt_connection_cb(mqtt_client_t *client, void *arg, mqtt_connection_status_t status) { if(status == MQTT_CONNECT_ACCEPTED) { printf("MQTT Connected!\r\n"); // Subscribe to topic mqtt_subscribe(client, "commands/#", 0, mqtt_incoming_cb, NULL); } } void mqtt_publish_data(float temperature) { char payload[32]; sprintf(payload, "{\"temp\":%.1f}", temperature); mqtt_publish(&mqtt_client, MQTT_TOPIC, payload, strlen(payload), 0, 0, mqtt_publish_cb, NULL); } int main(void) { system_clock_config(); at32_board_init(); // Initialize EMAC emac_system_init(); tcpip_stack_init(); // Initialize MQTT client mqtt_client_init(&mqtt_client); // Connect to broker ip_addr_t broker_ip; IP4_ADDR(&broker_ip, 192, 168, 1, 100); mqtt_client_connect(&mqtt_client, &broker_ip, MQTT_BROKER_PORT, mqtt_connection_cb, NULL, NULL); while(1) { lwip_rx_loop_handler(); lwip_periodic_handle(local_time); // Publish data periodically if(publish_timer_expired()) { mqtt_publish_data(read_temperature()); } } } ``` -------------------------------- ### Main Function: Initialize and Start Timer (C) Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/EXINT_External_Interrupt.md The main function initializes the system clock, NVIC, configures the EXINT line and TMR1, and then starts the timer. The program enters an infinite loop where sw_trigger_count is incremented every second by the interrupt handlers. ```c int main(void) { system_clock_config(); nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); exint_software_trigger_config(); tmr1_config(); /* Start timer */ tmr_counter_enable(TMR1, TRUE); while(1) { /* sw_trigger_count increments every second */ } } ``` -------------------------------- ### Enter Sleep Mode with Timer Wakeup Example Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/PWC_Power_Controller.md Example demonstrating how to enter sleep mode and configure a timer (TMR2) to wake up the MCU periodically. ```APIDOC ## Example: Sleep Mode with Timer Wakeup ### Description This example shows how to put the microcontroller into sleep mode and configure TMR2 to generate an overflow interrupt, which will wake up the MCU. The main loop toggles an LED upon waking. ### Method C Code Example ### Endpoint N/A ### Parameters N/A ### Request Example ```c #include "at32f435_437_board.h" #include "at32f435_437_clock.h" void tmr2_config(void) { crm_clocks_freq_type crm_clocks; /* Enable TMR2 clock */ crm_periph_clock_enable(CRM_TMR2_PERIPH_CLOCK, TRUE); /* Get system clock */ crm_clocks_freq_get(&crm_clocks); /* Configure for 1Hz (1 second period) */ /* (systemclock/(systemclock/10000))/10000 = 1Hz */ tmr_base_init(TMR2, 9999, (crm_clocks.sclk_freq / 10000 - 1)); tmr_cnt_dir_set(TMR2, TMR_COUNT_UP); tmr_clock_source_div_set(TMR2, TMR_CLOCK_DIV1); /* Enable overflow interrupt */ tmr_interrupt_enable(TMR2, TMR_OVF_INT, TRUE); nvic_irq_enable(TMR2_GLOBAL_IRQn, 0, 0); /* Start timer */ tmr_counter_enable(TMR2, TRUE); } int main(void) { __IO uint32_t systick_index = 0; system_clock_config(); at32_board_init(); nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); /* Enable PWC clock */ crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE); /* Configure TMR2 for wakeup */ tmr2_config(); at32_led_on(LED2); while(1) { at32_led_off(LED2); /* Save and disable SysTick */ systick_index = SysTick->CTRL; systick_index &= ~((uint32_t)0xFFFFFFFE); SysTick->CTRL &= (uint32_t)0xFFFFFFFE; /* Enter sleep mode - wakeup on TMR2 interrupt */ pwc_sleep_mode_enter(PWC_SLEEP_ENTER_WFI); /* Restore SysTick after wakeup */ SysTick->CTRL |= systick_index; /* Woken up by TMR2 */ at32_led_on(LED2); delay_ms(500); } } /* TMR2 interrupt handler */ void TMR2_GLOBAL_IRQHandler(void) { if(tmr_flag_get(TMR2, TMR_OVF_FLAG) == SET) { tmr_flag_clear(TMR2, TMR_OVF_FLAG); /* Wakeup processing done in main loop */ } } ``` ### Response N/A #### Success Response N/A #### Response Example N/A ``` -------------------------------- ### Basic Flash Write and Read Example in C Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/FLASH_Memory_Controller.md This C code example demonstrates how to write an array of words to flash memory and then read it back for verification on the AT32f435/437 microcontroller. It includes functions for writing and reading words, erasing sectors, unlocking/locking flash, and a main function to orchestrate the process. This example is crucial for applications requiring persistent data storage. ```c #include "at32f435_437.h" #define FLASH_TEST_ADDR (0x08000000 + 0x10000) /* 64KB offset */ #define TEST_DATA_SIZE 64 uint32_t write_buffer[TEST_DATA_SIZE]; uint32_t read_buffer[TEST_DATA_SIZE]; /** * @brief Write array of words to flash */ flash_status_type flash_write_words(uint32_t address, uint32_t *data, uint32_t count) { flash_status_type status; uint32_t i; for(i = 0; i < count; i++) { status = flash_word_program(address + (i * 4), data[i]); if(status != FLASH_OPERATE_DONE) return status; } return FLASH_OPERATE_DONE; } /** * @brief Read array of words from flash */ void flash_read_words(uint32_t address, uint32_t *data, uint32_t count) { uint32_t i; for(i = 0; i < count; i++) { data[i] = *(__IO uint32_t*)(address + (i * 4)); } } int main(void) { flash_status_type status; uint32_t i; system_clock_config(); /* Initialize test data */ for(i = 0; i < TEST_DATA_SIZE; i++) { write_buffer[i] = 0xDEADBEEF + i; } /* Unlock flash */ flash_unlock(); /* Erase sector first (flash can only write 1->0) */ status = flash_sector_erase(FLASH_TEST_ADDR); if(status != FLASH_OPERATE_DONE) { flash_lock(); while(1); /* Error handling */ } /* Write data */ status = flash_write_words(FLASH_TEST_ADDR, write_buffer, TEST_DATA_SIZE); if(status != FLASH_OPERATE_DONE) { flash_lock(); while(1); /* Error handling */ } /* Lock flash */ flash_lock(); /* Read back and verify */ flash_read_words(FLASH_TEST_ADDR, read_buffer, TEST_DATA_SIZE); for(i = 0; i < TEST_DATA_SIZE; i++) { if(read_buffer[i] != write_buffer[i]) { while(1); /* Verification failed */ } } /* Success */ while(1); } ``` -------------------------------- ### C: AT32F435/437 CDC Host (Virtual COM Port) Example Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/USB_Host_Universal_Serial_Bus.md This C code implements a CDC Host (Virtual COM Port) for the AT32F435/437 microcontroller. It includes header files for board, clock, USB configuration, core, interrupts, CDC class, and user callbacks. It defines transmit and receive buffers and callback functions for transmission completion and reception completion. The user_enumeration_done function is called when the device is ready, and user_application handles the initial setup and transmission. The main function initializes the system, USB, and CDC host, and enters a loop for USB event handling and button-triggered transmissions. ```c #include "at32f435_437_board.h" #include "at32f435_437_clock.h" #include "usb_conf.h" #include "usb_core.h" #include "usbh_int.h" #include "usbh_cdc_class.h" #include "usbh_user.h" otg_core_type otg_core_struct; uint8_t tx_buffer[64] = "AT32 USB Host CDC Test\r\n"; uint8_t rx_buffer[64]; /* Called when transmission completes */ void cdc_transmit_complete(usbh_core_type *uhost) { printf("TX Complete\r\n"); /* Start reception after transmission */ cdc_start_reception(&otg_core_struct.host, rx_buffer, sizeof(rx_buffer)); } /* Called when reception completes */ void cdc_receive_complete(usbh_core_type *uhost) { usbh_cdc_type *pcdc = (usbh_cdc_type *)uhost->class_handler->pdata; uint32_t rx_len = uhost->hch[pcdc->data_interface.in_channel].trans_count; if (rx_len > 0) { printf("RX (%lu bytes): ", rx_len); for (uint32_t i = 0; i < rx_len; i++) { printf("%02X ", rx_buffer[i]); } printf("\r\n"); } /* Continue reception */ cdc_start_reception(&otg_core_struct.host, rx_buffer, sizeof(rx_buffer)); } static usb_sts_type user_enumeration_done(void) { printf("CDC Device Ready\r\n"); return USB_OK; } static usb_sts_type user_application(void) { static uint8_t started = 0; /* Start communication once when device is ready */ if (!started) { started = 1; /* Configure line coding (115200, 8N1) */ usbh_cdc.linecoding.line_coding_b.data_baudrate = 115200; usbh_cdc.linecoding.line_coding_b.data_bits = 8; usbh_cdc.linecoding.line_coding_b.char_format = 0; /* 1 stop bit */ usbh_cdc.linecoding.line_coding_b.parity_type = 0; /* No parity */ /* Start transmission */ cdc_start_transmission(&otg_core_struct.host, tx_buffer, strlen((char *)tx_buffer)); } return USB_OK; } int main(void) { nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); system_clock_config(); at32_board_init(); usb_gpio_config(); crm_periph_clock_enable(CRM_OTGFS1_PERIPH_CLOCK, TRUE); usb_clock48m_select(); nvic_irq_enable(OTGFS1_IRQn, 0, 0); /* Initialize USB host with CDC class */ usbh_init(&otg_core_struct, USB_FULL_SPEED_CORE_ID, USB_ID1, &uhost_cdc_class_handler, &usbh_user_handle); while (1) { usbh_loop_handler(&otg_core_struct.host); /* Button press triggers new transmission */ if (at32_button_press() == USER_BUTTON) { cdc_start_transmission(&otg_core_struct.host, tx_buffer, strlen((char *)tx_buffer)); } } } ``` -------------------------------- ### C Basic Output LED Toggle Example Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/GPIO_General_Purpose_IO.md Demonstrates basic GPIO configuration for output and toggling an LED. It initializes a pin (PC13) as a push-pull output and uses a simple XOR operation on the output data register for toggling. This example requires including the relevant header file and system clock configuration. ```c #include "at32f435_437.h" /** * @brief Configure PC13 as push-pull output for LED */ void led_gpio_init(void) { gpio_init_type gpio_init_struct; /* Enable GPIOC clock */ crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE); /* Initialize structure with defaults */ gpio_default_para_init(&gpio_init_struct); /* Configure PC13 as output */ gpio_init_struct.gpio_pins = GPIO_PINS_13; gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT; gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL; gpio_init_struct.gpio_pull = GPIO_PULL_NONE; gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER; gpio_init(GPIOC, &gpio_init_struct); } /** * @brief Toggle LED */ void led_toggle(void) { GPIOC->odt ^= GPIO_PINS_13; /* XOR to toggle */ } int main(void) { system_clock_config(); led_gpio_init(); while(1) { led_toggle(); delay_ms(500); } } ``` -------------------------------- ### Keil MDK Scatter File: Example for Extended SRAM Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/SRAM_Extended_Internal_Memory.md This is an example of a scatter file for the Keil MDK build environment. It demonstrates how to define memory regions for flash and SRAM, specifically showing the configuration for a 2MB Flash and a 512KB SRAM. This file needs to be updated to reflect the desired SRAM size after reconfiguration. ```armasm LR_IROM1 0x08000000 0x00200000 { ; 2MB Flash ER_IROM1 0x08000000 0x00200000 { *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } ; For 512KB SRAM configuration RW_IRAM1 0x20000000 0x00080000 { ; 512KB SRAM .ANY (+RW +ZI) } } ``` -------------------------------- ### Basic Timer with Overflow Interrupt Example Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/TMR_Timer.md Example demonstrating how to configure a timer (TMR1) to generate an overflow interrupt every second (1 Hz). It includes system clock configuration, timer initialization, interrupt enabling, NVIC setup, and starting the timer. The interrupt handler toggles an LED. ```c #include "at32f435_437_board.h" #include "at32f435_437_clock.h" crm_clocks_freq_type crm_clocks_freq; void TMR1_OVF_TMR10_IRQHandler(void) { if(tmr_interrupt_flag_get(TMR1, TMR_OVF_FLAG) == SET) { at32_led_toggle(LED2); tmr_flag_clear(TMR1, TMR_OVF_FLAG); } } int main(void) { system_clock_config(); at32_board_init(); crm_clocks_freq_get(&crm_clocks_freq); /* Enable TMR1 clock */ crm_periph_clock_enable(CRM_TMR1_PERIPH_CLOCK, TRUE); /* Configure timer for 1 Hz (1 second overflow) Timer clock = APB2 * 2 = 288 MHz Period = 10000, Prescaler = (288MHz/10000/1Hz) - 1 = 28799 */ tmr_base_init(TMR1, 9999, (crm_clocks_freq.apb2_freq * 2 / 10000) - 1); tmr_cnt_dir_set(TMR1, TMR_COUNT_UP); /* Enable overflow interrupt */ tmr_interrupt_enable(TMR1, TMR_OVF_INT, TRUE); /* Configure NVIC */ nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); nvic_irq_enable(TMR1_OVF_TMR10_IRQn, 1, 0); /* Start timer */ tmr_counter_enable(TMR1, TRUE); while(1) { } } ``` -------------------------------- ### Get SLIB Protection Status Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/FLASH_Memory_Controller.md Provides information about the Security Library (SLIB) protection, including its current state (enabled/disabled), remaining password attempts, and the configured start, instruction start, and end sectors. ```c /** * @brief Get SLIB state * @retval flag_status: SET (enabled) or RESET (disabled) */ flag_status flash_slib_state_get(void); /** * @brief Get remaining SLIB password attempts (256 max) * @retval uint32_t: remaining attempts */ uint32_t flash_slib_remaining_count_get(void); /** * @brief Get SLIB start sector * @retval uint16_t: sector number */ uint16_t flash_slib_start_sector_get(void); /** * @brief Get SLIB instruction start sector * @retval uint16_t: sector number */ uint16_t flash_slib_inststart_sector_get(void); /** * @brief Get SLIB end sector * @retval uint16_t: sector number */ uint16_t flash_slib_end_sector_get(void); ``` -------------------------------- ### Initialization APIs Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/QSPI_Quad_SPI.md APIs for initializing and configuring the QSPI peripheral. ```APIDOC ## void qspi_reset(qspi_type* qspi_x) ### Description Reset QSPI peripheral to default values. ### Method void ### Endpoint N/A (Function Call) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```c qspi_reset(QSPI1); ``` ### Response #### Success Response (void) None #### Response Example N/A ``` ```APIDOC ## void qspi_clk_division_set(qspi_type* qspi_x, qspi_clk_div_type new_clkdiv) ### Description Set the QSPI clock division. ### Method void ### Endpoint N/A (Function Call) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **qspi_x** (qspi_type*) - QSPI1 or QSPI2 - **new_clkdiv** (qspi_clk_div_type) - Clock divider: `QSPI_CLK_DIV_2` to `QSPI_CLK_DIV_12` ### Request Example ```c qspi_clk_division_set(QSPI2, QSPI_CLK_DIV_4); ``` ### Response #### Success Response (void) None #### Response Example N/A ``` ```APIDOC ## void qspi_sck_mode_set(qspi_type* qspi_x, qspi_clk_mode_type new_mode) ### Description Set the SCK clock mode. ### Method void ### Endpoint N/A (Function Call) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **qspi_x** (qspi_type*) - QSPI1 or QSPI2 - **new_mode** (qspi_clk_mode_type) - `QSPI_SCK_MODE_0` or `QSPI_SCK_MODE_3` ### Request Example ```c qspi_sck_mode_set(QSPI1, QSPI_SCK_MODE_0); ``` ### Response #### Success Response (void) None #### Response Example N/A ``` ```APIDOC ## void qspi_busy_config(qspi_type* qspi_x, qspi_busy_pos_type busy_pos) ### Description Configure the position of WIP (Write In Progress) bit in flash status register. ### Method void ### Endpoint N/A (Function Call) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **qspi_x** (qspi_type*) - QSPI1 or QSPI2 - **busy_pos** (qspi_busy_pos_type) - `QSPI_BUSY_OFFSET_0` to `QSPI_BUSY_OFFSET_7` ### Request Example ```c qspi_busy_config(QSPI2, QSPI_BUSY_OFFSET_0); ``` ### Response #### Success Response (void) None #### Response Example N/A ``` ```APIDOC ## void qspi_auto_ispc_enable(qspi_type* qspi_x) ### Description Enable automatic input sampling phase correction for high-speed operation. ### Method void ### Endpoint N/A (Function Call) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **qspi_x** (qspi_type*) - QSPI1 or QSPI2 ### Request Example ```c qspi_auto_ispc_enable(QSPI1); ``` ### Response #### Success Response (void) None #### Response Example N/A ``` -------------------------------- ### SysTick Interrupt Example (1ms Tick) - C Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/Cortex_M4_Core_Features.md Example demonstrating how to configure the SysTick timer for a 1ms interrupt interval and toggle an LED every 200ms. This showcases periodic timer functionality suitable for RTOS-like scheduling. It includes necessary headers, interrupt handler, configuration function, and main setup. ```c #include "at32f435_437_board.h" #include "at32f435_437_clock.h" /******************************************************************************* * SysTick Interrupt Example * * Configures SysTick for 1ms interrupts and toggles LED every 200ms. * Demonstrates periodic timer functionality for RTOS-like scheduling. ******************************************************************************/ #define MS_TICK (system_core_clock / 1000U) /* Ticks for 1ms */ #define DELAY 200 /* Toggle every 200ms */ /* SysTick interrupt handler (called every 1ms) */ void systick_handler(void) { static uint32_t ticks = 0; ticks++; /* Toggle LED every DELAY milliseconds */ if(ticks > DELAY) { at32_led_toggle(LED2); ticks = 0; } } /* Configure SysTick with interrupt */ static uint32_t systick_interrupt_config(uint32_t ticks) { /* Validate reload value (24-bit max) */ if((ticks - 1UL) > SysTick_LOAD_RELOAD_Msk) { return 1UL; /* Error: reload value too large */ } /* Set reload value */ SysTick->LOAD = (uint32_t)(ticks - 1UL); /* Set lowest priority for SysTick interrupt */ NVIC_SetPriority(SysTick_IRQn, (1UL << __NVIC_PRIO_BITS) - 1UL); /* Reset counter */ SysTick->VAL = 0UL; /* Enable SysTick with interrupt */ SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk | /* Enable interrupt */ SysTick_CTRL_ENABLE_Msk; /* Enable counter */ return 0UL; /* Success */ } int main(void) { system_clock_config(); /* Select SysTick clock source (full AHB clock) */ systick_clock_source_config(SYSTICK_CLOCK_SOURCE_AHBCLK_NODIV); /* Configure 1ms SysTick interrupt */ systick_interrupt_config(MS_TICK); /* Initialize LED */ at32_led_init(LED2); /* Main loop - work done in interrupt */ while(1) { /* Can add low-priority tasks here */ } } ``` -------------------------------- ### TCP Client Initialization and Handling in C Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/EMAC_Ethernet_MAC_Controller.md Demonstrates the initialization and main loop handling for a TCP client using the AT32 EMAC driver and lwIP stack. It includes system clock configuration, EMAC initialization, TCP/IP stack setup, and periodic handling of network events. Dependencies include AT32 HAL, EMAC driver, netconf, and tcp_client headers. ```c #include "at32f435_437.h" #include "at32_emac.h" #include "netconf.h" #include "tcp_client.h" volatile uint32_t local_time = 0; int main(void) { error_status status; system_clock_config(); at32_board_init(); uart_print_init(115200); nvic_priority_group_config(NVIC_PRIORITY_GROUP_4); delay_init(); // Initialize EMAC status = emac_system_init(); while(status == ERROR); // Initialize TCP/IP stack (lwIP) tcpip_stack_init(); // Initialize TCP client tcp_client_init(TCP_LOCAL_PORT, TCP_SERVER_PORT, TCP_SERVER_IP); while(1) { // lwIP receive handling lwip_rx_loop_handler(); // Periodic timeout handling lwip_periodic_handle(local_time); } } // SysTick handler for lwIP timing void SysTick_Handler(void) { local_time += 10; } // EMAC interrupt handler void EMAC_IRQHandler(void) { if(emac_dma_flag_get(EMAC_DMA_RI_FLAG)) { // Frame received - set flag for lwIP ethernetif_input_handler(); emac_dma_flag_clear(EMAC_DMA_RI_FLAG); } emac_dma_flag_clear(EMAC_DMA_NIS_FLAG); } ``` -------------------------------- ### Initialize and Fill LCD with Color (C) Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/XMC_External_Memory_Controller.md Initializes the LCD, then fills the entire screen with a specified color (red in this example) by iterating through each pixel and setting its color. Assumes lcd_init(), lcd_set_pixel(), and associated helper functions are defined elsewhere. ```c int main(void) { system_clock_config(); at32_board_init(); lcd_init(); /* Fill screen with color */ for (int y = 0; y < 240; y++) { for (int x = 0; x < 320; x++) { lcd_set_pixel(x, y, 0xF800); /* Red */ } } while (1) {} } ``` -------------------------------- ### Modified Startup File Example Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/SRAM_Extended_Internal_Memory.md Illustrates the necessary modifications to the Keil MDK startup assembly file (`startup_at32f435_437_ext_ram.s`) to incorporate the SRAM extension function call before `SystemInit` and `main`. ```APIDOC ## Implementation Requirements ### Modified Startup File When extending SRAM, the startup file must be modified to call the SRAM extension function **before** `SystemInit` and `main` are called. This is critical because: 1. The default stack pointer may be outside the valid SRAM range 2. The SRAM configuration must be set before any memory operations **Keil MDK Startup Assembly (startup_at32f435_437_ext_ram.s):** ```asm ; Reset handler Reset_Handler PROC EXPORT Reset_Handler [WEAK] IMPORT __main IMPORT SystemInit ; Add for extend SRAM IMPORT extend_sram MOV32 R0, #0x20001000 ; Set temporary stack in safe SRAM area MOV SP, R0 LDR R0, =extend_sram ; Call SRAM extension function BLX R0 MOV32 R0, #0x08000000 ; Restore stack from vector table LDR SP, [R0] LDR R0, =SystemInit BLX R0 LDR R0, =__main BX R0 ENDP ``` ``` -------------------------------- ### I2C Start Mode Configuration (C) Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/I2C_Inter_Integrated_Circuit.md Configures the generation of START conditions during I2C communication. Options include continuing without a START, generating a START condition followed by a read operation, or generating a START condition followed by a write operation. ```c typedef enum { I2C_WITHOUT_START = 0x00000000, /* Continue without START */ I2C_GEN_START_READ = 0x00002400, /* Generate START + Read */ I2C_GEN_START_WRITE = 0x00002000 /* Generate START + Write */ } i2c_start_mode_type; ``` -------------------------------- ### AT32 LED Control Example Source: https://github.com/xyphrodite/at32f435-437-docs/blob/master/docs/XMC_External_Memory_Controller.md Demonstrates basic LED control using the at32_led_on function. This snippet assumes the AT32 library is included and configured. It shows how to turn on a specific LED (LED2) after a condition is met. ```c if (pass) at32_led_on(LED2); while (1) {} ```