串口iap在线升级,bootloader调试记录,基于gd32f103
1.cubemx新建工程
2.新增串口中断接收代码
在这里基于stm32常用方法是初始化完成后,调用HAL_UART_Receive_IT(&huart1, (uint8_t *)u8UartRxBuf, 1))函数开启串口中断,然后再中断函数中再次调用该函数,实现数据的接收。
作者在用gd32f103测试时发现发现上面的方式在接收大量数据时,会出现丢数据的现象,所以作者采用在串口初始化完成后,调用__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE)函数开启接收中断。
void HAL_UART_MspInit(UART_HandleTypeDef* uartHandle)
{
/* USER CODE BEGIN USART1_MspInit 1 */
// __HAL_UART_ENABLE_IT(&huart1,UART_IT_IDLE);
__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);
/* USER CODE END USART1_MspInit 1 */
}
串口中断接收代码如下
uart.h文件
#define C_USART_RCV_LEN 1024 * 10 //定义100K的数据缓存区
extern uint8_t g_u8UartRxBuf[C_USART_RCV_LEN]; // 接收缓冲,最大USART_REC_LEN个字节,起始地址为0X20001000.
extern uint32_t g_u32UartRxCnt; // 接收的字节数
extern uint8_t g_u8CodeUpdateFlag;
#define C_UART_DATE_ADDR 0X20002000
uart.c文件
uint8_t g_u8UartRxBuf[C_USART_RCV_LEN] __attribute__((at(C_UART_DATE_ADDR))); // 接收缓冲,最大USART_REC_LEN个字节,起始地址为C_UART_DATE_ADDR.
uint32_t g_u32UartRxCnt = 0; // 接收的字节数
uint8_t g_u8CodeUpdateFlag = 0; // App代码更新标志
void UART_IRQ(UART_HandleTypeDef *huart)
{
g_u8UartRxBuf[g_u32UartRxCnt] = (uint8_t)(huart->Instance->DR & 0xFF);
g_u32UartRxCnt++;
}
stm32f1xx_it.c中断文件
extern void UART_IRQ(UART_HandleTypeDef *huart);
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
// HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
UART_IRQ(&huart1);
/* USER CODE END USART1_IRQn 1 */
}
最后在主函数里运行,实现代码的接收和flash的写入
if (g_u32UartRxCnt)
{
if (oldcount == g_u32UartRxCnt) /* 新周期内,没有收到任何数据,认为本次数据接收完成 */
{
applenth = g_u32UartRxCnt;
oldcount = 0;
g_u32UartRxCnt = 0;
Debugprintf("\r\n user code rcv ok!\r\n");
Debugprintf("code length:%dBytes\r\n", applenth);
}
else
{
oldcount = g_u32UartRxCnt;
}
}
HAL_Delay(100); // 给以串口中断的时间,判断是否接收完成
if (applenth)
{
Debugprintf("start update...\r\n");
if (((*(volatile uint32_t *)(C_UART_DATE_ADDR + 4)) & 0xFF000000) == 0x08000000) // 判断是否为0X08XXXXXX
{
iap_write_appbin(FLASH_APP1_ADDR, g_u8UartRxBuf, applenth); // 更新FLASH代码
Debugprintf("update success!\r\n");
HAL_Delay(1000); // 固件更新成功后,等待一秒再执行app程序
mod_iap_load_app(FLASH_APP1_ADDR); // 执行FLASH APP代码
}
else
{
Debugprintf("is not a flash code!\r\n");
}
}
else
{
Debugprintf("there is no user code app!\r\n");
}
}
else // 有程序,直接运行
{
Debugprintf("already have an app!\r\n");
Debugprintf("start run user app!\r\n\r\n");
HAL_Delay(10);
mod_iap_load_app(FLASH_APP1_ADDR); // 执行FLASH APP代码
}
以上仅贴部分代码做记录,资源已上传,需要可下载。