开发板在线升级和远程升级


***************************************2017.6.6***************************************

  最近在研究开发板远程升级的事情,稍微记录一下而已。功能大概是这样的:一台放在室外的板子,需

要通过服务器给开发板上的4G模块下发指令来进行远程升级。

  看了网上好多资料,多数人的方法和串口IAP在线升级是一个套路。大致就是如下:上电,从boot区启动检测有没有新

的新用户程序,有就跳入处理,没有就跳到用户代码。具体的是,给开发板一个升级命令,下载升级包(注意校验),置更

新升级标志,将升级包写入到flash,清除更新升级标志,复位启动。我说的太简单,具体实现我还是有许多问题不知道怎

么实现,还需要在研究。

  公司大牛前辈有给我指导,我也询问了一些问题。首先,他建议我先实现串口在线升级。他说的过程大致如下,先给一

个开发板一个升级指令,开发板收到命令之后,跳转到bootloader,置升级标志位,开始接收数据,校验正确写入RAM,一

包接收成功给外界一个回应,外界收到正确回应之后,继续发送下一包数据......收到全部数据之后,写入flash,清除升级标

志位,复位启动。下面我说一些我的疑问和需要解决的问题。

(串口在线升级可以参考STM32F10x_AN2557_FW_V3.3.0示例代码)

  1.主要还是接收数据包的问题,怎么传输,校验用什么方法校验?

  STM32F103串口升级用的是YModem这个文件传输协议,传输还是自拟协议好了,需要带ACK;校验的话我本来准备

用CRC16校验,前辈建议我用XOR校验。

  2.怎么跳转到相应的地址以及bootloader的地址是什么?

  #define jump(TargetAddr ) (*((void(*)())(TargetAddr))()

  bootloader是哪个地址?

  3.怎么擦除flash,写入flash?

  4.RTC里面有个备份程序区,可以把更新升级标志位放在那里,不会因为断电重启而改变。

  ......姑且就这么多,一步一步解决吧。明天继续

 

***************************************2017.6.7***************************************

  1./*软复位*/

  NVIC_SystemReset(void);

  2.stm32在线升级中的主要函数如下:

void Main_Menu(void)
{
  uint8_t key = 0;
 
  /* Get the number of block (4 or 2 pages) from where the user program will be loaded */
  BlockNbr = (FlashDestination - 0x08000000) >> 12;

  /* Compute the mask to test if the Flash memory, where the user program will be
     loaded, is write protected */
#if defined (STM32F10X_MD) || defined (STM32F10X_MD_VL)
  UserMemoryMask = ((uint32_t)~((1 << BlockNbr) - 1));
#else /* USE_STM3210E_EVAL */
  if (BlockNbr < 62)
  {
    UserMemoryMask = ((uint32_t)~((1 << BlockNbr) - 1));
  }
  else
  {
    UserMemoryMask = ((uint32_t)0x80000000);
  }
#endif /* (STM32F10X_MD) || (STM32F10X_MD_VL) */


  /* Test if any page of Flash memory where program user will be loaded is write protected */
  if ((FLASH_GetWriteProtectionOptionByte() & UserMemoryMask) != UserMemoryMask)
  {
    FlashProtection = 1;
  }
  else
  {
    FlashProtection = 0;
  }

  while (1)
  {
    SerialPutString("\r\n================== Main Menu ============================\r\n\n");
    SerialPutString("  Download Image To the STM32F10x Internal Flash ------- 1\r\n\n");
    SerialPutString("  Upload Image From the STM32F10x Internal Flash ------- 2\r\n\n");
    SerialPutString("  Execute The New Program ------------------------------ 3\r\n\n");
    
    if(FlashProtection != 0)
    {
      SerialPutString("  Disable the write protection ------------------------- 4\r\n\n");
    }
    
    SerialPutString("==========================================================\r\n\n");
    
    key = GetKey();

    if (key == 0x31)
    {
      /* Download user application in the Flash */
      SerialDownload();
    }
    else if (key == 0x32)
    {
      /* Upload user application from the Flash */
      SerialUpload();
    }
    else if (key == 0x33)
    {
      JumpAddress = *(__IO uint32_t*) (ApplicationAddress + 4);

      /* Jump to user application */
      Jump_To_Application = (pFunction) JumpAddress;
      /* Initialize user application's Stack Pointer */
      __set_MSP(*(__IO uint32_t*) ApplicationAddress);
      Jump_To_Application();
    }
    else if ((key == 0x34) && (FlashProtection == 1))
    {
      /* Disable the write protection of desired pages */
      FLASH_DisableWriteProtectionPages();
    }
    else
    {
      if (FlashProtection == 0)
      {
        SerialPutString("Invalid Number ! ==> The number should be either 1, 2 or 3\r");
      }
      else
      {
        SerialPutString("Invalid Number ! ==> The number should be either 1, 2, 3 or 4\r");
      }
    }
  }
}

  3.flash的地址(看datesheet)

  program flash  start_address:0x0000_0000   end_address:0x0007_FFFF

 

***************************************2017.6.8***************************************

1.前面的细节好像还没有解决,先实现通过串口向开发板传输bin文件,大小是80KB,怎么分包传输,怎么校验?

  一包数据1.2KB,大概需要60包左右。我思考的是,70KB的文件怎么分包方便,怎么校验

校验部分:

uint8_t xor(char* source)  
{  
  int j;  
  int slen=strlen(source);   
  uint8_t tmpstr = 0;
  for(j=0;j<slen;j++)  
  {  
    tmpstr=tmpstr^source[j];  
    if(!tmpstr)  
      tmpstr=source[j];  
  }    
  source[j] = tmpstr;
  return tmpstr;  

上面参考的是网上的,下面是我自己调试可用的异或校验:

uint8_t xor(uint8_t* source, uint16_t length)  
{  
  uint16_t j;    
  uint8_t tmpstr = 0;
 
  for(j=0;j<length-2;j++)  
  {  
    tmpstr=tmpstr^source[j];  
    tmpstr=source[j];  
  }   
  return tmpstr;
 // if(tmpstr == source[length-3])//去掉0D,0A的帧尾
 //    return true;
 // else
 //  return false;

 

分包部分:最大预算80包,每包1260个字节,开通的全局buffer是boot_array[80][1300];

接下来是分包组包,写入flash。

 

***************************************2017.6.8***************************************

1.定义的buffer不能是boot_array[80][1300];,网上查了一下,好像是超过128KB的ram允许的范围了,改为boot_array[75][1300];

网上说的原因:由于Kinetis K系列芯片使用的是ARM Cortex M4内核,其使用哈弗架构,内部的SRAM被分成了两部分,通过不同的总线访问。也就是说,SRAM分成了两部分,虽然逻辑地址是连续的,但是这两部分SRAM不能当成一个连续空间来使用。因此,请避免将heap大小设置超过1/2 SRAM大小,否则在使用过程中会产生错误。

2.定义分包协议

  包头:2个字节,包括总包数和现在第几包。

  内容:1250个字节

  校验:(XOR) 1个字节

  帧尾:0x0D,0x0A

3.使用串口工具将bin文件发给板子,存在boot_arrat中,第1包就放在boot_array[0]中,第2包放在boot_array[1]中,第13包放在boot_array[12]中,类似存入buffer中。

  *****问*****

  怎么判定最后一包,且之前的每一包都正确收到???

  ————>每一包正确收到之后,会有反馈,收到反馈之后继续发送下一包。如果某一包不成功,那就重新发送这一包。等能够收到总包数和现在的包数一样时,不就证明是最后一包了吗,收到反馈之后,擦除flash,写入falsh。

4.研究怎么擦除flash,怎么写入flash

  网上查资料和跑官网上给的flash例程。知道了怎么擦出一个大小是2KB的扇区,怎么检验是不是被擦除,怎么写入一个扇区。

  知道了flash扇区的每一块的地址和总的地址范围。

 

***************************************2017.6.16***************************************

这么多天没写,第一个就是突然插入支持其他的项目,然后每次调试的时候,flash擦除,读写有问题,一直拖到现在。刚才把flash读写搞定,发现擦除,写入还是有一些讲究的,擦出多大,写入多少。。。

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM