硬汉嵌入式论坛

 找回密码
 立即注册
查看: 906|回复: 11
收起左侧

[BOOT/IAP] bootloader升级程序,bin文件超过ram大小,分段存储,中断接收出现问题,求解!

[复制链接]

5

主题

16

回帖

31

积分

新手上路

积分
31
发表于 2024-12-10 10:00:56 | 显示全部楼层 |阅读模式
问题描述:
需要用到bootloader串口中断接收app程序写入flash,但由于hex分段(根据代码,在0x081FE000区域生成CRC)导致bin文件大小1.87MB超过ram大小,所以需要分段写入。
串口中断设置了两个缓冲区,每个缓冲区大小128KB,每接收128KB就切换另一个缓冲区接收,并将已经接收的128KB写入flash。
在测试过程中发现接收128KB并写入后串口中断不响应了,没有继续接收。但是我已经将中断向量表重映射到ram,并且中断服务函数也加载到ram里执行了。
有大神能帮忙看看哪里出问题了么,我把代码附上:

回复

使用道具 举报

5

主题

16

回帖

31

积分

新手上路

积分
31
 楼主| 发表于 2024-12-10 10:01:22 | 显示全部楼层
RAMFUNC_SECTION void USART1_IRQHandler(void)
{
  /* USER CODE BEGIN USART1_IRQn 0 */
    uint8_t rxData;
    if((__HAL_UART_GET_FLAG(&huart1, UART_FLAG_RXNE) != RESET))
    {
        HAL_UART_Receive(&huart1, &rxData, 1, 10);
        uartRxBytes++;
        if(bufferChangeFlags == 0U && buffer1_write_flash_flag == 0U)
        {
            uartRxBuffer1[uartRxBuffer1_Bytes] = rxData;
            uartRxBuffer1_Bytes++;
            if(uartRxBuffer1_Bytes >= UART_RX_MAX_BYTES)
            {
                bufferChangeFlags = 1U;
                uartRxBuffer1_Bytes = 0U;
                buffer1_write_flash_flag = 1U;
            }
        }
        else if(bufferChangeFlags == 1U && buffer2_write_flash_flag == 0U)
        {
            uartRxBuffer2[uartRxBuffer2_Bytes] = rxData;
            uartRxBuffer2_Bytes++;
            if(uartRxBuffer2_Bytes >= UART_RX_MAX_BYTES)
            {
                bufferChangeFlags = 0U;
                uartRxBuffer2_Bytes = 0U;
                buffer2_write_flash_flag = 1U;
            }
        }
        else
        {
            printf("error\r\n");
        }
    }
  /* USER CODE END USART1_IRQn 0 */
  HAL_UART_IRQHandler(&huart1);
  /* USER CODE BEGIN USART1_IRQn 1 */

  /* USER CODE END USART1_IRQn 1 */
}
回复

使用道具 举报

5

主题

16

回帖

31

积分

新手上路

积分
31
 楼主| 发表于 2024-12-10 10:02:27 | 显示全部楼层
        memcpy(vector_t, (void*)0x08000000, 0x298);
    SCB->VTOR = 0x24001000;

   
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */
        // 使能DWT外设
    DEMCR |= (uint32_t)DEM_CR_TRCENA;
        // DWT CYCCNT寄存器计数清0
    DWT_CYCCNT = (uint32_t)0U;
        // 使能 DWT CYCCNT寄存器
    DWT_CTRL |= (uint32_t)DWT_CR_CYCCNTENA;
  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */

    printf("start\r\n");
    startTick = HAL_GetTick();
    do
    {
        usedTick = HAL_GetTick() - startTick;
    } while (usedTick < 2000 && buffer1_write_flash_flag == 0U);

    startTick = ((uint32_t)DWT_CYCCNT);
    if(buffer1_write_flash_flag == 1)
    {
        if(firstFlag == 1U)
        {
            if(((*(__IO uint32_t*)(0x24020000 + 4)) & 0xFF000000) != 0x08000000)
            {
                printf("The application is invalid.\r\n");
                printf("Loading the original application.\r\n");
                iap_load_app(APP_ADDR_START);
            }
        }
        iap_write_appbin(addrToWriteNow_main, uartRxBuffer1, UART_RX_MAX_BYTES);
        buffer1_write_flash_flag = 0U;
        addrToWriteNow_main += UART_RX_MAX_BYTES;
        // usedTick = ((uint32_t)DWT_CYCCNT) - startTick;
        // printf("128k:%d, %d\r\n", usedTick / (SystemCoreClock / 1000000U), uartRxBytes);


        while(1)
        {
            startTick = HAL_GetTick();
            do
            {
                usedTick = HAL_GetTick() - startTick;
            } while (usedTick < 2000 && buffer1_write_flash_flag == 0U && buffer2_write_flash_flag == 0U && uartRxBytes != 1966080U);

            if(buffer1_write_flash_flag == 1U)
            {
                iap_write_appbin(addrToWriteNow_main, uartRxBuffer1, UART_RX_MAX_BYTES);
                buffer1_write_flash_flag = 0U;
                addrToWriteNow_main += UART_RX_MAX_BYTES;
                printf("1\r\n");
            }
            else if(buffer2_write_flash_flag == 1U)
            {
                iap_write_appbin(addrToWriteNow_main, uartRxBuffer2, UART_RX_MAX_BYTES);
                buffer2_write_flash_flag = 0U;
                addrToWriteNow_main += UART_RX_MAX_BYTES;
                printf("2\r\n");
            }
            else if(uartRxBytes == 1966080U)
            {
                break;
            }
            else
            {
                printf("%d\r\n", uartRxBytes);
                break;
            }
        }

        printf("uartRxBytes : %d\r\n", uartRxBytes);
        HAL_Delay(100);
        printf("Loading the new application.\r\n");
        iap_load_app(APP_ADDR_START);
    }
    else
    {
        printf("No serial port data received. %d\r\n", uartRxBytes);
        printf("Loading the original application.\r\n");
        iap_load_app(APP_ADDR_START);
    }

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
    while (1)
    {
        printf("Please reset and then transmit the application through the serial port again.\r\n");
        HAL_Delay(1000);

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
    }
  /* USER CODE END 3 */
}
回复

使用道具 举报

5

主题

16

回帖

31

积分

新手上路

积分
31
 楼主| 发表于 2024-12-10 10:03:07 | 显示全部楼层
LR_IROM1 0x08000000 0x00200000  {    ; load region size_region
  ER_IROM1 0x08000000 0x00200000  {  ; load address = execution address
   *.o (RESET, +First)
   *(InRoot$$Sections)
   .ANY (+RO)
   .ANY (+XO)
  }
  RW_IRAM1 0x20000000 0x00020000  {  ; RW data
   *.o (.ramfunc)
   .ANY (+RW +ZI)
  }
  RW_IRAM2 0x24000000 0x00080000  {
   .ANY (+RW +ZI)
  }
}
回复

使用道具 举报

3

主题

295

回帖

304

积分

高级会员

积分
304
发表于 2024-12-10 11:11:52 | 显示全部楼层
写入成功了吗,可能是写入的问题,写个简单的分两次写入的程序验证一下。
楼主是想边写flash边串口接收?建议不要这么做,写完一包以后再接收新的,实际时间不会差太多。
你真要实现边写边接收的话,中断函数里用到的所有函数和变量都要放到RAM里,像HAL_UART_Receive这个就必须放到RAM里
回复

使用道具 举报

5

主题

16

回帖

31

积分

新手上路

积分
31
 楼主| 发表于 2024-12-10 14:59:24 | 显示全部楼层
skyshine 发表于 2024-12-10 11:11
写入成功了吗,可能是写入的问题,写个简单的分两次写入的程序验证一下。
楼主是想边写flash边串口接收? ...

因为hex分段了在0x081FE000开始增加了CRC,中间部分填充了0xFF,所以导致bin文件过大。
修改了分散加载文件将串口中断服务函数加载到ram里了,还是只要操作在操作flash,中断就不响应了。。
回复

使用道具 举报

1

主题

123

回帖

131

积分

初级会员

积分
131
发表于 2024-12-10 15:46:30 | 显示全部楼层
我都是1K,1k的写
回复

使用道具 举报

3

主题

295

回帖

304

积分

高级会员

积分
304
发表于 2024-12-10 16:50:47 | 显示全部楼层
SRIlyy 发表于 2024-12-10 14:59
因为hex分段了在0x081FE000开始增加了CRC,中间部分填充了0xFF,所以导致bin文件过大。
修改了分散加载 ...

写片上flash的时候单片机一般是不能响应中断的,想实现写flash的时候同时能响应中断要搞骚操作,把中断函数相关的所有函数和变量都放到RAM里
回复

使用道具 举报

3

主题

295

回帖

304

积分

高级会员

积分
304
发表于 2024-12-10 17:01:37 | 显示全部楼层
按硬汉哥的教程来吧,应该是你写入flash这部分有问题,可能和中断关系不大,写入以后再用调试器读一下,看有没有写进去

https://www.armbbs.cn/forum.php?mod=viewthread&tid=112792
回复

使用道具 举报

4

主题

178

回帖

190

积分

初级会员

积分
190
发表于 2024-12-10 17:59:53 | 显示全部楼层
是这样的,写入过程中中断就是不响应,即使调用HAL_FLASH_IT写flash一样的有问题,有个简单办法,每次分包小一点,比如2k 4k配合上位机就很好解决了
回复

使用道具 举报

6

主题

679

回帖

697

积分

金牌会员

积分
697
QQ
发表于 2024-12-10 22:32:21 | 显示全部楼层
为什么把CRC添加到那么靠后的位置,直接添加到代码最后的位置就可以啊
回复

使用道具 举报

5

主题

16

回帖

31

积分

新手上路

积分
31
 楼主| 发表于 2025-1-9 18:29:25 | 显示全部楼层
yklstudent 发表于 2024-12-10 22:32
为什么把CRC添加到那么靠后的位置,直接添加到代码最后的位置就可以啊

添加CRC是调用了STProgramer这个程序自动添加,所以会在最后面
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-4-26 06:07 , Processed in 0.263806 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表