stm32f103串口iap在线升级bootloader

串口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代码
        }

以上仅贴部分代码做记录,资源已上传,需要可下载。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值