MMMoyier 2024-01-13 21:07 采纳率: 60%
浏览 7
已结题

stm32 IAP升级异常

bootloader整片擦除Flash,烧写进去之后进行Ymodem协议IAP升级可以正常下载和跳转,立即重新上电然后再IAP升级也没问题.
但是程序运行一段时间,再去下载升级就会报错 Verification failed! 这是什么原因。这是我Ymodem下载部分的代码

int32_t Ymodem_Receive(uint8_t *buf)
{
  uint8_t packet_data[PACKET_1K_SIZE + PACKET_OVERHEAD], file_size[FILE_SIZE_LENGTH], *file_ptr, *buf_ptr;
  int32_t i, j, packet_length, session_done, file_done, packets_received, errors, session_begin, size = 0;

  /* Initialize FlashDestination variable */
  FlashDestination = ApplicationAddress;

  for (session_done = 0, errors = 0, session_begin = 0;;)
  {
    for (packets_received = 0, file_done = 0, buf_ptr = buf;;)
    {
      switch (Receive_Packet(packet_data, &packet_length, NAK_TIMEOUT))
      {
      case 0:
        errors = 0;
        switch (packet_length)
        {
        /* Abort by sender */
        case -1:
          Send_Byte(ACK);
          return 0;
        /* End of transmission */
        case 0:
          Send_Byte(ACK);
          file_done = 1;
          break;
        /* Normal packet */
        default:
          if ((packet_data[PACKET_SEQNO_INDEX] & 0xff) != (packets_received & 0xff))
          {
            Send_Byte(NAK);
          }
          else
          {
            if (packets_received == 0)
            {
              /* Filename packet */
              if (packet_data[PACKET_HEADER] != 0)
              {
                /* Filename packet has valid data */
                for (i = 0, file_ptr = packet_data + PACKET_HEADER; (*file_ptr != 0) && (i < FILE_NAME_LENGTH);)
                {
                  file_name[i++] = *file_ptr++;
                }
                file_name[i++] = '\0';
                for (i = 0, file_ptr++; (*file_ptr != ' ') && (i < FILE_SIZE_LENGTH);)
                {
                  file_size[i++] = *file_ptr++;
                }
                file_size[i++] = '\0';
                Str2Int(file_size, &size);

                /* Test the size of the image to be sent */
                /* Image size is greater than Flash size */
                if (size > (FLASH_SIZE - 1))
                {
                  /* End session */
                  Send_Byte(CA);
                  Send_Byte(CA);
                  return -1;
                }

                /* Erase the needed pages where the user application will be loaded */
                /* Define the number of page to be erased */
                NbrOfPage = FLASH_PagesMask(size);

                /* Erase the FLASH pages */
                for (EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
                {
                  FLASHStatus = FLASH_ErasePage(FlashDestination + (PageSize * EraseCounter));
                }
                Send_Byte(ACK);
                Send_Byte(CRC16);
              }
              /* Filename packet is empty, end session */
              else
              {
                Send_Byte(ACK);
                file_done = 1;
                session_done = 1;
                break;
              }
            }
            /* Data packet */
            else
            {
              memcpy(buf_ptr, packet_data + PACKET_HEADER, packet_length);
              RamSource = (uint32_t)buf;
              for (j = 0; (j < packet_length) && (FlashDestination < ApplicationAddress + size); j += 4)
              {
                /* Program the data received into STM32F10x Flash */
                // FLASH_ProgramWord(FlashDestination, *(uint32_t *)RamSource);
                HAL_FLASH_Unlock();
                HAL_FLASH_Program(0x02U, FlashDestination, *(uint32_t *)RamSource);
                if (*(uint32_t *)FlashDestination != *(uint32_t *)RamSource)
                {
                  /* End session */
                  Send_Byte(CA);
                  Send_Byte(CA);
                  return -2;
                }
                FlashDestination += 4;
                RamSource += 4;
              }
              Send_Byte(ACK);
              HAL_FLASH_Lock();
            }
            packets_received++;
            session_begin = 1;
          }
        }
        break;
      case 1:
        Send_Byte(CA);
        Send_Byte(CA);
        return -3;
      default:
        if (session_begin > 0)
        {
          errors++;
        }
        if (errors > MAX_ERRORS)
        {
          Send_Byte(CA);
          Send_Byte(CA);
          return 0;
        }
        Send_Byte(CRC16);
        break;
      }
      if (file_done != 0)
      {
        break;
      }
    }
    if (session_done != 0)
    {
      break;
    }
  }
  return (int32_t)size;
}


  • 写回答

2条回答 默认 最新

  • ChatGPTᴼᴾᴱᴺᴬᴵ 2024-01-13 23:07
    关注

    所有内容均由人工智能模型输出,其内容的准确性和完整性无法保证,不代表我的态度或观点。


    该回答引用通义千问大模型,仅提供参考,不保证完全正确
    目前为通义千问大模型专栏,版本:V2.1.1(2023.12.16)
    根据您提供的Ymodem协议接收文件的代码,当程序运行一段时间后再进行IAP升级时出现 "Verification failed!" 错误,可能的原因有以下几点:

    1. 内存干扰:在程序运行过程中,如果对 Flash 的其他区域进行了写操作,可能会造成 IAP 升级区域的数据被意外修改,导致校验失败。

    2. 电源稳定性:在程序长时间运行后,电源系统可能存在波动或瞬态干扰,影响 Flash 写入和读取的稳定性,从而导致校验错误。

    3. Flash磨损/寿命问题:虽然 STM32 的 Flash 有一定的擦写次数限制,但在一般应用场景下不太可能出现这种情况。但如果设备长时间频繁地进行擦写操作,Flash 的数据完整性可能会受到影响。

    4. HAL_FLASH_Program函数调用异常:检查 HAL_FLASH_Unlock 和 HAL_FLASH_Lock 是否在正确的时间点调用,确保每次编程操作前解锁并在完成之后立即锁定 Flash。

    5. CRC校验不一致:Ymodem协议中每接收到一个数据包都会做CRC校验,这里未显示CRC校验部分的代码,需要确保接收到的数据包在写入Flash前已经通过了CRC校验,并且在写入后能正确读出并验证其内容。

    6. Flash擦除不足:如果新下载的固件大小有所增加,而之前擦除Flash时没有考虑到这部分增量,可能会导致后续的数据覆盖原有的有效数据,进而校验失败。

    建议您在每次升级前重新执行一次擦除操作,并加强 Flash 写入和读取过程中的错误处理和状态检测。同时,在软件设计上,尽量避免在升级期间进行其他可能影响 Flash 操作的任务。


    图片转文字可能造成误差,不代表模型真实水平

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

问题事件

  • 系统已结题 1月23日
  • 已采纳回答 1月15日
  • 创建了问题 1月13日

悬赏问题

  • ¥15 编辑cmake lists 明明写了project项目名,但是还是报错怎么回事
  • ¥15 关于#计算机视觉#的问题:求一份高质量桥梁多病害数据集
  • ¥15 特定网页无法访问,已排除网页问题
  • ¥50 如何将脑的图像投影到颅骨上
  • ¥15 提问一个关于vscode相关的环境配置问题,就是输入中文但是显示不出来,代码在idea可以显示中文,但在vscode不行,不知道怎么配置环境
  • ¥15 netcore使用PuppeteerSharp截图
  • ¥20 这张图页头,页脚具体代码该怎么写?
  • ¥15 关于#sql#的问题,请各位专家解答!
  • ¥20 WPF MVVM模式 handycontrol 框架, hc:SearchBar 控件 Text="{Binding NavMenusKeyWords}" 绑定取不到值
  • ¥15 需要手写数字信号处理Dsp三个简单题 不用太复杂