開發板在線升級和遠程升級


***************************************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