找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開始

搜索
查看: 8297|回復(fù): 4
打印 上一主題 下一主題
收起左側(cè)

分享一個(gè)STM32 BootLoader遠(yuǎn)程更新例程

  [復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
#
ID:629287 發(fā)表于 2019-10-24 10:40 | 只看該作者 回帖獎(jiǎng)勵(lì) |正序?yàn)g覽 |閱讀模式
第一次來這里分享自己的心得,在電子網(wǎng)轉(zhuǎn)了很久也沒見到一份精簡的代碼(優(yōu)秀的代碼不少啊),今天給大家講講STM8的IAP

STM8 IAP可以做什么
    做遠(yuǎn)程程序更新,我們只需要燒入底層程序(boot),就可以像手機(jī)更新系統(tǒng)那樣來更新我們單片機(jī)的軟件,當(dāng)然出廠也是可以連boot和app都燒進(jìn)去的
這里不多廢話 上傳代碼,不會(huì)的留言

單片機(jī)源程序如下:
  1. #include "usart.h"
  2. #include "string.h"
  3. ///////////////////////////////////////////////////////////////////
  4. //函數(shù)名稱:main                                                ///
  5. //功能描述:程序入口,處理程序更新                              ///
  6. //作    者:baishuyuan                                          ///
  7. //注意事項(xiàng):程序不可大于APP起始地址                             ///
  8. ///////////////////////////////////////////////////////////////////
  9. const u8 FLASHKEY = 0xFF;//APP標(biāo)志位
  10. #define MAIN_USER_Start_ADDR     ((uint32_t)0x8000+0xB00-4)//用戶代碼的起始地址
  11. #define MIN_USER_Start_ADDR     (MAIN_USER_Start_ADDR+4)//用戶代碼的起始地址 字節(jié)偏移5個(gè)字節(jié)
  12. u16 APP_BIT_ADDR   =  0x1000;//用戶代碼的起始地址
  13. #define PWR_HOLD_GPIO           GPIOD
  14. #define PWR_HOLD_GPIO_Pin           GPIO_Pin_0
  15. /*******************************************************************************
  16. **函數(shù)名稱:void delay(unsigned int ms)     Name: void delay(unsigned int ms)
  17. **功能描述:大概延時(shí)
  18. **入口參數(shù):unsigned int ms   輸入大概延時(shí)數(shù)值
  19. **輸出:無
  20. ******************************************************************************/
  21. void delay(unsigned int ms)
  22. {
  23.   unsigned int x , y;
  24.   for(x = ms; x > 0; x--)           /*  通過一定周期循環(huán)進(jìn)行延時(shí)*/
  25.     for(y = 1000 ;  y > 0 ; y--);
  26. }

  27. //定義指向函數(shù)的指針類型
  28. typedef void ( *AppMainTyp)(void);

  29. uint32_t FLASH_ReadWord(uint32_t Address)
  30. {
  31. return(*(PointerAttr uint32_t *) (uint16_t)Address);      
  32. }

  33. #include "stm8l15x_itc.h"
  34.    //重新初始化STM8的中斷向量表  把它重新定義到APP的中斷向量中
  35. void STM8_HanderIqr_Init(void)
  36. {
  37.   disableInterrupts();   //關(guān)閉中斷  
  38.   uint8_t Index;       
  39.   FLASH_Unlock(FLASH_MemType_Program);
  40.   for(Index = 1; Index < 0X20;Index++)
  41.   {
  42.    if(FLASH_ReadWord(0X8000+4*Index)!=(0X82000000+MIN_USER_Start_ADDR+Index*4))
  43.    {
  44.     FLASH_ProgramWord(0X8000+4*Index,0X82000000+MIN_USER_Start_ADDR+Index*4);
  45.    }
  46.   }
  47.   FLASH_Lock(FLASH_MemType_Program);
  48. }
  49. //跳轉(zhuǎn)到用戶代碼
  50. void goto_app(void)
  51. {
  52.     //重定義STM8的中斷向量
  53.     STM8_HanderIqr_Init();
  54.     //跳轉(zhuǎn)至APP
  55.     asm("LDW X,  SP ");
  56.     asm("LD  A,  $FF");
  57.     asm("LD  XL, A  ");
  58.     asm("LDW SP, X  ");
  59.     asm("JPF $8B00");
  60. }
  61.    
  62. /*******************************************************************************
  63. **函數(shù)名稱:void EEPROM_Byte_Write(unsigned int address , unsigned char date)
  64. **功能描述:向EEPROM中固定地址寫入一個(gè)字節(jié)數(shù)據(jù)
  65. **入口參數(shù):unsigned int address , unsigned char date
  66.             address  :要寫入數(shù)據(jù)的存儲(chǔ)地址
  67.               date   :一個(gè)字節(jié)數(shù)據(jù)
  68. **輸出:無
  69. *******************************************************************************/
  70. void EEPROM_Byte_Write(unsigned int address , unsigned char date)
  71. {
  72.   
  73.   FLASH_SetProgrammingTime(FLASH_ProgramTime_TProg); //設(shè)定編程時(shí)間為標(biāo)準(zhǔn)編程時(shí)間
  74.   
  75.   //MASS 密鑰,解除EEPROM的保護(hù)
  76.   FLASH_Unlock(FLASH_MemType_Data);
  77.   
  78.   FLASH_ProgramByte(address , date);  //把數(shù)據(jù)寫入相應(yīng)的存儲(chǔ)地址

  79. while(FLASH_GetFlagStatus(FLASH_FLAG_EOP) == 1);     //等待編程結(jié)束
  80. }
  81. /**********************************************************************
  82. * 函數(shù)名稱:  XOR_Inverted_Check
  83. * 功能描述:數(shù)據(jù)的異或取反校驗(yàn)
  84. * para:
  85. inBuf: 需檢測的字符串
  86. inLen: 所需檢測的字符串長度
  87. ***********************************************************************/
  88. u8  XOR_Inverted_Check(unsigned char* inBuf, unsigned char inLen)
  89. {
  90.   u8 check = 0, i;

  91.   for (i = 0; i < inLen; i++)
  92.   {
  93.     check ^= inBuf[i];
  94.   }
  95.   check = ~check;
  96.   return check;
  97. }
  98. u8 Write_App(u8 * Write_Data,u8 Write_Len)
  99. {
  100.     static u32 addr = MIN_USER_Start_ADDR;//得到flash地址
  101.     u8 i = 0;
  102.     for(i=3;i<(Write_Len-1);i++)
  103.     {
  104.       if(i<(Write_Len-1))
  105.       {
  106.         FLASH_ProgramByte(addr , USART_RX_BUF[i]);  //把數(shù)據(jù)寫入相應(yīng)的存儲(chǔ)地址
  107.       }
  108.       addr++;//為下次寫入做準(zhǔn)備
  109.     }
  110.     if(Write_Len<24)
  111.     {
  112.       EEPROM_Byte_Write(APP_BIT_ADDR,FLASHKEY);
  113.       addr=MAIN_USER_Start_ADDR;//重置flash寫地址
  114.     }
  115.     return i;

  116. }
  117.                                                    

  118. void Memset()
  119. {
  120.   memset(USART_RX_BUF,0,USART_RX_STA);
  121.   USART_RX_STA=0;
  122. }
  123. void main()
  124. {
  125.   u8 STR[]={0x7b,0x05,0xf2,0x03,0x70,'\r','\n','\0'};
  126.   u32 i=0;
  127.   disableInterrupts();   //關(guān)閉系統(tǒng)總中斷
  128.    GPIO_DeInit(GPIOD);
  129. /* Port D in output push-pull 0 */
  130.   GPIO_Init(GPIOD,GPIO_Pin_All, GPIO_Mode_Out_PP_Low_Slow);
  131.   GPIO_Init(PWR_HOLD_GPIO, PWR_HOLD_GPIO_Pin, GPIO_Mode_Out_PP_Low_Slow); //默認(rèn)all電源為關(guān) D0 推挽-輸出低-高速
  132.   GPIO_SetBits(PWR_HOLD_GPIO, PWR_HOLD_GPIO_Pin);
  133.   CLK_SYSCLKDivConfig(CLK_SYSCLKDiv_1); //內(nèi)部時(shí)鐘為1分頻 = 16Mhz
  134.   FLASH_Unlock(FLASH_MemType_Program);//MASS 密鑰,解除FLASH的保護(hù)
  135.   FLASH_Unlock(FLASH_MemType_Data);//MASS 密鑰,解除EEPROM的保護(hù)
  136.   FLASH_SetProgrammingTime(FLASH_ProgramTime_TProg); //設(shè)定編程時(shí)間為標(biāo)準(zhǔn)編程時(shí)間
  137.   while(FLASH_GetFlagStatus(FLASH_FLAG_PUL) == RESET);
  138.   //如果用戶代碼更新完成標(biāo)記存在  則表示當(dāng)前已經(jīng)有APP代碼  直接運(yùn)行
  139.   if(FLASH_ReadByte(APP_BIT_ADDR+1)==0 && FLASH_ReadByte(MIN_USER_Start_ADDR)==0x82)//出廠首次燒錄入口
  140.   {
  141. //    FLASH_ProgramByte(APP_BIT_ADDR , FLASHKEY);  //寫入更新完成標(biāo)志位
  142. //    goto_app();  //運(yùn)行APP
  143.   }
  144.   else if(FLASH_ReadByte(MIN_USER_Start_ADDR)==0x82 && FLASH_ReadByte(APP_BIT_ADDR)==FLASHKEY && FLASH_ReadByte(APP_BIT_ADDR+1)!=0)//關(guān)機(jī)重啟設(shè)備入口
  145.   {
  146. //    goto_app();  //運(yùn)行APP
  147.   }
  148.   else//更新APP入口
  149.   {
  150. //    if( FLASH_ReadByte(APP_BIT_ADDR)!=0x00)//標(biāo)志位清空 這段是APP的
  151. //    {
  152. //      FLASH_EraseByte(APP_BIT_ADDR);
  153. //    }
  154. //    for(i=MAIN_USER_Start_ADDR;i<0x9FF0;i++)//限定地址不可超過0x9FF0,清空flash
  155. //    {
  156. //      FLASH_EraseByte(i);  //把數(shù)據(jù)寫入相應(yīng)的存儲(chǔ)地址
  157. //    }
  158.   }
  159.   enableInterrupts();   //使能系統(tǒng)總中斷
  160.   //等待USART1接收字符中斷產(chǎn)生,中斷服務(wù)函數(shù)在  stm8l15x_it.c文件里的 函數(shù) INTERRUPT_HANDLER(USART1_RX_TIM5_CC_IRQHandler,28)
  161.   UART1_Init(9600);//串口初始化
  162.   UART1_TX_STR(STR);//接收第一幀數(shù)據(jù)
  163.   while(1)  
  164.   {  
  165.     UART1_TX_STR(STR);//發(fā)送測試數(shù)據(jù)
  166.     delay(1000);//短暫延遲
  167.     i=0xFFFFF;
  168.     while(i>10)
  169.     {
  170.       i--;
  171.     };
  172.     if(UPDATE_APP_OK)UPDATE_APP_OK++;//串口接收完成標(biāo)志位
  173.     if(UPDATE_APP_OK>5)//接收完成了
  174.     {
  175.       UPDATE_APP_OK=0;
  176.       if((USART_RX_BUF[USART_RX_STA-1])==//CRC
  177.          (XOR_Inverted_Check(USART_RX_BUF,USART_RX_STA-1)))
  178.       {
  179.         if(USART_RX_STA>5 && USART_RX_STA<=USART_RX_LEN)
  180.         {
  181.           if(Write_App(USART_RX_BUF,USART_RX_STA)==(USART_RX_LEN-1))
  182.           {
  183.             UART1_TX_STR(STR);//持續(xù)接收
  184.           }
  185.           else
  186.           {
  187.             Memset();
  188.             STR[3]=0x05;
  189.             STR[4]=0x76;
  190.             UART1_TX_STR(STR);//go to app sending data
  191. //            goto_app();//進(jìn)入更新后的APP
  192.           }
  193.         }
  194.       }
  195.       Memset();
  196.     }
  197.   }
  198. }
復(fù)制代碼

所有資料51hei提供下載:
實(shí)驗(yàn)1boot.7z (1.68 MB, 下載次數(shù): 115)

評(píng)分

參與人數(shù) 1黑幣 +50 收起 理由
admin + 50 共享資料的黑幣獎(jiǎng)勵(lì)!

查看全部評(píng)分

分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏9 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

地板
ID:373684 發(fā)表于 2022-7-8 22:54 | 只看該作者
那STM8是不是要連上互聯(lián)網(wǎng)?
回復(fù)

使用道具 舉報(bào)

板凳
ID:87000 發(fā)表于 2022-7-8 09:55 | 只看該作者
請(qǐng)問樓主STM8 IAP 同STM32  IAP  相同嗎?
回復(fù)

使用道具 舉報(bào)

沙發(fā)
ID:59363 發(fā)表于 2021-8-4 17:02 | 只看該作者
多謝分享,能做個(gè)使用教程就好了
回復(fù)

使用道具 舉報(bào)

樓主
ID:25310 發(fā)表于 2019-11-26 09:03 | 只看該作者
請(qǐng)問樓主STM8 IAP 同STM32  IAP  相同嗎?
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

手機(jī)版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表