- /* add user code begin Header */
- /**
- **************************************************************************
- * [url=home.php?mod=space&uid=288409]@file[/url] main.c
- * [url=home.php?mod=space&uid=247401]@brief[/url] main program
- **************************************************************************
- * Copyright notice & Disclaimer
- *
- * The software Board Support Package (BSP) that is made available to
- * download from Artery official website is the copyrighted work of Artery.
- * Artery authorizes customers to use, copy, and distribute the BSP
- * software and its related documentation for the purpose of design and
- * development in conjunction with Artery microcontrollers. Use of the
- * software is governed by this copyright notice and the following disclaimer.
- *
- * THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
- * GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
- * TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
- * STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
- * INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
- *
- **************************************************************************
- */
- /* add user code end Header */
- /* Includes ------------------------------------------------------------------*/
- #include "at32f423_wk_config.h"
- /* private includes ----------------------------------------------------------*/
- /* add user code begin private includes */
- #include <string.h>
- /* add user code end private includes */
- /* private typedef -----------------------------------------------------------*/
- /* add user code begin private typedef */
- /* add user code end private typedef */
- /* private define ------------------------------------------------------------*/
- /* add user code begin private define */
- /* add user code end private define */
- /* private macro -------------------------------------------------------------*/
- /* add user code begin private macro */
- #define MS_TICK (system_core_clock / 8 / 1000U)
- #define TX_BUF_SIZE 1024
- #define RX_BUF_SIZE 1024
- #define FLASH_START_ADDR ((uint32_t)0x08000000U)
- #define FLASH_BANK_START_ADDR FLASH_START_ADDR
- #define FLASH_BANK_SECTOR_SIZE ((uint32_t)0x00000800U) /* 2KB */
- #define FLASH_BANK_SECTOR_NUM 127
- #define FLASH_BANK_SIZE \
- (FLASH_BANK_SECTOR_NUM * FLASH_BANK_SECTOR_SIZE)
- #define FLASH_BANK_END_ADDR \
- (FLASH_BANK_START_ADDR + FLASH_BANK_SIZE - 1)
- #define FLASH_SIZE FLASH_BANK_SIZE
- #define FLASH_END_ADDR (FLASH_START_ADDR + FLASH_SIZE - 1)
- #define USER_DATA_START_ADDR ((uint32_t)0x0803F000U)
- /* add user code end private macro */
- /* private variables ---------------------------------------------------------*/
- /* add user code begin private variables */
- static volatile uint32_t sys_tick;
- uint8_t tx_buf[TX_BUF_SIZE]; /* uart 发送缓冲区 */
- volatile uint16_t tx_len; /* uart 实际发送数据长度 */
- volatile uint8_t tx_flag; /* uart 发送繁忙标志 */
- uint8_t rx_buf[RX_BUF_SIZE]; /* uart 接收缓冲区 */
- volatile uint16_t rx_len; /* uart 实际接收数据长度 */
- volatile uint8_t rx_flag; /* uart 接收完成标志 */
- static const char *start_msg = "The demo is started!\n";
- /* add user code end private variables */
- /* private function prototypes --------------------------------------------*/
- /* add user code begin function prototypes */
- /* add user code end function prototypes */
- /* private user code ---------------------------------------------------------*/
- /* add user code begin 0 */
- static void systick_init(void)
- {
- SysTick_Config(MS_TICK);
- systick_clock_source_config(SYSTICK_CLOCK_SOURCE_AHBCLK_DIV8);
- }
- static void sys_tick_increament(void)
- {
- sys_tick++;
- }
- uint32_t sys_tick_get(void)
- {
- return sys_tick;
- }
- void SysTick_Handler(void)
- {
- sys_tick_increament();
- }
- uint8_t flash_erase(uint32_t addr, uint32_t size)
- {
- uint32_t end_addr;
- uint32_t start_sector_addr, end_sector_addr;
- if (addr < FLASH_START_ADDR || size == 0)
- return 0;
-
- end_addr = addr + size - 1;
- if (end_addr > FLASH_END_ADDR)
- return 0;
- /* 解锁 flash 编程/擦除操作 */
- flash_unlock();
- /* 清除标志位 */
- flash_flag_clear(FLASH_PRGMERR_FLAG | FLASH_EPPERR_FLAG);
- /* 计算擦除的起始 sector 地址和结束 sector 地址
- * 地址需要对齐到物理 sector 地址,
- * 即必须是 FLASH_START_ADDR + n * FLASH_BANK_SECTOR_SIZE
- */
- start_sector_addr = FLASH_BANK_START_ADDR +
- (addr - FLASH_BANK_START_ADDR) /
- FLASH_BANK_SECTOR_SIZE * FLASH_BANK_SECTOR_SIZE;
- end_sector_addr = FLASH_BANK_START_ADDR +
- (end_addr - FLASH_BANK_START_ADDR) /
- FLASH_BANK_SECTOR_SIZE * FLASH_BANK_SECTOR_SIZE;
- /* 擦除 flash */
- while (start_sector_addr <= end_sector_addr) {
- if (flash_sector_erase(start_sector_addr) != FLASH_OPERATE_DONE) {
- flash_lock();
- return 0;
- }
- start_sector_addr += FLASH_BANK_SECTOR_SIZE;
- }
- /* 锁定 flash 编程/擦除操作 */
- flash_lock();
- return 1;
- }
- uint8_t flash_program_byte(uint32_t addr, uint8_t *data, uint32_t size)
- {
- uint32_t end_addr;
- if (addr < FLASH_START_ADDR || addr % 4 != 0)
- return 0;
-
- end_addr = addr + size - 1;
- if (end_addr > FLASH_END_ADDR)
- return 0;
- /* 解锁 flash 编程/擦除操作 */
- flash_unlock();
- /* 清除标志位 */
- flash_flag_clear(FLASH_PRGMERR_FLAG | FLASH_EPPERR_FLAG);
- /* 编程 flash */
- while (addr <= end_addr) {
- if (flash_byte_program(addr, *data++) != FLASH_OPERATE_DONE) {
- flash_lock();
- return 0;
- }
- addr++;
- }
- /* 锁定 flash 编程/擦除操作 */
- flash_lock();
-
- return 1;
- }
- uint8_t flash_erase_check(uint32_t addr, uint32_t size)
- {
- uint32_t end_addr;
- if (addr < FLASH_START_ADDR)
- return 0;
-
- end_addr = addr + size - 1;
- if (end_addr > FLASH_END_ADDR)
- return 0;
- while (addr <= end_addr) {
- if (*(uint8_t *)addr != 0xFF)
- return 0;
- addr++;
- }
- return 1;
- }
- uint8_t flash_program_byte_check(uint32_t addr, uint8_t *data, uint32_t size)
- {
- uint32_t end_addr;
- if (addr < FLASH_START_ADDR)
- return 0;
-
- end_addr = addr + size - 1;
- if (end_addr > FLASH_END_ADDR)
- return 0;
- while (addr <= end_addr) {
- if (*(uint8_t *)addr != *data++)
- return 0;
- addr++;
- }
- return 1;
- }
- static void uart_send(uint8_t *data, uint16_t size)
- {
- wk_dma_channel_config(DMA1_CHANNEL2, (uint32_t)&USART1->dt, (uint32_t)data, size);
- dma_interrupt_enable(DMA1_CHANNEL2, DMA_FDT_INT, TRUE); /* 打开 dma 发送完成中断 */
- dma_channel_enable(DMA1_CHANNEL2, TRUE); /* 启动 dma 通道传输 */
- }
- /* add user code end 0 */
- /**
- * @brief take some delay for waiting power stable, delay is about 60ms with frequency 8MHz.
- * @param none
- * @retval none
- */
- static void wk_wait_for_power_stable(void)
- {
- volatile uint32_t delay = 0;
- for(delay = 0; delay < 50000; delay++);
- }
- /**
- * @brief main function.
- * @param none
- * @retval none
- */
- int main(void)
- {
- /* add user code begin 1 */
- uint32_t start_tick;
- /* add user code end 1 */
- /* add a necessary delay to ensure that Vdd is higher than the operating
- voltage of battery powered domain (2.57V) when the battery powered
- domain is powered on for the first time and being operated. */
- wk_wait_for_power_stable();
-
- /* system clock config. */
- wk_system_clock_config();
- /* config periph clock. */
- wk_periph_clock_config();
- /* nvic config. */
- wk_nvic_config();
- /* init dma1 channel1 */
- wk_dma1_channel1_init();
- /* config dma channel transfer parameter */
- /* user need to modify parameters memory_base_addr and buffer_size */
- wk_dma_channel_config(DMA1_CHANNEL1, (uint32_t)&USART1->dt, (uint32_t)rx_buf, RX_BUF_SIZE);
- dma_channel_enable(DMA1_CHANNEL1, TRUE);
- /* init dma1 channel2 */
- wk_dma1_channel2_init();
- /* config dma channel transfer parameter */
- /* user need to modify parameters memory_base_addr and buffer_size */
- wk_dma_channel_config(DMA1_CHANNEL2, (uint32_t)&USART1->dt, (uint32_t)start_msg, strlen(start_msg));
- dma_channel_enable(DMA1_CHANNEL2, TRUE);
- /* init usart1 function. */
- wk_usart1_init();
- /* init gpio function. */
- wk_gpio_config();
- /* add user code begin 2 */
- systick_init();
-
- dma_interrupt_enable(DMA1_CHANNEL2, DMA_FDT_INT, TRUE); /* 打开 dma 发送完成中断 */
- rx_len = RX_BUF_SIZE; /* 设置接收的最大长度 */
- dma_flag_clear(DMA1_FDT1_FLAG); /* 清除 uart dma 传输完成标志 */
- usart_flag_clear(USART1, USART_IDLEF_FLAG); /* 清除空闲中断标志 */
- dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE); /* 打开 uart dma 接收完成中断 */
- usart_interrupt_enable(USART1, USART_IDLE_INT, TRUE); /* 打开 uart 空闲中断 */
-
- start_tick = sys_tick_get();
- /* add user code end 2 */
- while(1)
- {
- /* add user code begin 3 */
- if (rx_flag) {
- rx_flag = 0;
-
- while (tx_flag == 0); /* 等待发送就绪 */
-
- if (rx_len) {
- memcpy(tx_buf, rx_buf, rx_len); /* 拷贝接收数据 */
- /* 编程到 flash */
- if (!flash_erase(USER_DATA_START_ADDR, rx_len)) {
- uart_send((uint8_t *)"flash erase failed!\n", strlen("flash erase failed!\n"));
- } else if (!flash_erase_check(USER_DATA_START_ADDR, rx_len)) {
- uart_send((uint8_t *)"flash erase check failed!", strlen("flash erase check failed!"));
- } else if (!flash_program_byte(USER_DATA_START_ADDR, tx_buf, rx_len)) {
- uart_send((uint8_t *)"flash program failed!", strlen("flash program failed!"));
- } else if (!flash_program_byte_check(USER_DATA_START_ADDR, tx_buf, rx_len)) {
- uart_send((uint8_t *)"flash program check failed!", strlen("flash program check failed!"));
- } else {
- uart_send((uint8_t *)"flash program succeed!\n", strlen("flash program succeed!\n"));
- tx_flag = 0;
- while (tx_flag == 0);
- uart_send((uint8_t *)"program data is:\n", strlen("program data is:\n"));
- tx_flag = 0;
- while (tx_flag == 0);
- uart_send(tx_buf, rx_len);
- tx_flag = 0;
- while (tx_flag == 0);
- uart_send((uint8_t *)"\n", strlen("\n"));
- }
-
- tx_flag = 0; /* 设置发送繁忙标志 */
- }
- // else {
- // while (1);
- // }
- /* 重新启动 uart dma 接收 */
- dma_flag_clear(DMA1_FDT1_FLAG); /* 清除 uart dma 传输完成标志 */
- usart_flag_clear(USART1, USART_IDLEF_FLAG); /* 清除空闲中断标志 */
- dma_interrupt_enable(DMA1_CHANNEL1, DMA_FDT_INT, TRUE); /* 打开 uart dma 接收完成中断 */
- usart_interrupt_enable(USART1, USART_IDLE_INT, TRUE); /* 打开 uart 空闲中断 */
- rx_len = RX_BUF_SIZE; /* 设置接收的最大长度 */
- /* 重新配置 dma 接收参数 */
- wk_dma_channel_config(DMA1_CHANNEL1, (uint32_t)&USART1->dt, (uint32_t)rx_buf, RX_BUF_SIZE);
- dma_channel_enable(DMA1_CHANNEL1, TRUE); /* 打开 dma 通道传输 */
- }
-
- if (sys_tick_get() - start_tick >= 500) { /* 每隔 500 ms 翻转一次 LED */
- start_tick = sys_tick_get();
- gpio_bits_toggle(LED2_GPIO_PORT, LED2_PIN);
- gpio_bits_toggle(LED3_GPIO_PORT, LED3_PIN);
- gpio_bits_toggle(LED4_GPIO_PORT, LED4_PIN);
- }
- /* add user code end 3 */
- }
- }
3、测试
可以看到,uart 打印信息显示,flash 擦除、编程成功。使用 ArteryICPProgrammer 工具读出来的 flash 对应位置的数据和 program 的一致。