leaf_ota.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. #include "leaf_ota.h"
  2. #include "usart.h"
  3. #include "stdio.h"
  4. #include "string.h"
  5. #include "TerminalSlave485.h"
  6. #include "md5c.h"
  7. #include "main.h"
  8. /**
  9. * @brief 根据输入的地址给出它所在的sector
  10. * 例如:
  11. uwStartSector = GetSector(FLASH_USER_START_ADDR);
  12. uwEndSector = GetSector(FLASH_USER_END_ADDR);
  13. * @param Address:地址
  14. * @retval 地址所在的sector
  15. */
  16. static uint32_t GetSector(uint32_t Address)
  17. {
  18. uint32_t sector = 0;
  19. if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
  20. {
  21. sector = FLASH_SECTOR_0;
  22. }
  23. else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
  24. {
  25. sector = FLASH_SECTOR_1;
  26. }
  27. else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
  28. {
  29. sector = FLASH_SECTOR_2;
  30. }
  31. else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
  32. {
  33. sector = FLASH_SECTOR_3;
  34. }
  35. else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
  36. {
  37. sector = FLASH_SECTOR_4;
  38. }
  39. else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
  40. {
  41. sector = FLASH_SECTOR_5;
  42. }
  43. else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
  44. {
  45. sector = FLASH_SECTOR_6;
  46. }
  47. else/*(Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_23))*/
  48. {
  49. sector = FLASH_SECTOR_7;
  50. }
  51. return sector;
  52. }
  53. //uint8_t Erase_page(uint32_t pageaddr, uint32_t num)
  54. //{
  55. // /*要擦除的起始扇区(包含)及结束扇区(不包含),如8-12,表示擦除8、9、10、11扇区*/
  56. // uint32_t FirstSector = 0;
  57. // uint32_t NbOfSectors = 0;
  58. // uint32_t SECTORError = 0;
  59. // static FLASH_EraseInitTypeDef EraseInitStruct;
  60. // __disable_irq();
  61. // HAL_FLASH_Unlock();
  62. //
  63. // FirstSector = GetSector(pageaddr);
  64. // NbOfSectors = GetSector(num)- FirstSector + 1;
  65. // /* 擦除用户区域 (用户区域指程序本身没有使用的空间,可以自定义)**/
  66. // /* Fill EraseInit structure*/
  67. // EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
  68. // EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;/* 以“字”的大小进行操作 */
  69. // EraseInitStruct.Sector = FirstSector;
  70. // EraseInitStruct.NbSectors = 1;
  71. // /* 开始擦除操作 */
  72. // if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
  73. // {
  74. // /*擦除出错,返回,实际应用中可加入处理 */
  75. // return -1;
  76. // }
  77. //
  78. //
  79. // HAL_FLASH_Lock();
  80. // __enable_irq();
  81. // return 1;
  82. //}
  83. int App2_MD5_Check(uint32_t addr,unsigned int all_len)
  84. {
  85. unsigned char digest[16];
  86. // unsigned char *md5_ptr=(unsigned char *)(StartMode_Addr+72);
  87. unsigned int i,update_len;
  88. MD5_CTX md5c;
  89. all_len -= 16;
  90. MD5Init(&md5c);
  91. for(i=0;i<all_len;)
  92. {
  93. if(all_len>(i+512))
  94. update_len = 512;
  95. else
  96. update_len = all_len-i;
  97. memcpy(USART1_TX_BUF,(const void *)(addr+i),update_len);
  98. MD5Update (&md5c, USART1_TX_BUF, update_len);
  99. i += update_len;
  100. HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
  101. }
  102. MD5Final(digest,&md5c);
  103. memcpy(USART1_TX_BUF,(const void *)(addr+all_len),16);
  104. for(i=0;i<16;++i)
  105. {
  106. if(digest[i]!=USART1_TX_BUF[i])
  107. break;
  108. }
  109. if(i>=16)
  110. return 1;
  111. else
  112. return 0;
  113. }
  114. /**
  115. * @bieaf 擦除页
  116. *
  117. * @param pageaddr 起始地址
  118. * @param num 擦除的页数
  119. * @return 1
  120. */
  121. uint8_t Erase_page(uint32_t pageaddr, uint32_t num)
  122. {
  123. __disable_irq();
  124. HAL_FLASH_Unlock();
  125. /* 擦除FLASH*/
  126. FLASH_EraseInitTypeDef FlashSet;
  127. FlashSet.TypeErase = FLASH_TYPEERASE_SECTORS;
  128. FlashSet.VoltageRange = FLASH_VOLTAGE_RANGE_3;
  129. FlashSet.Sector = GetSector(pageaddr);
  130. //FlashSet.NbSectors =(pageaddr+num-1);
  131. FlashSet.NbSectors=1;
  132. /*设置PageError,调用擦除函数*/
  133. uint32_t PageError = 0;
  134. HAL_FLASHEx_Erase(&FlashSet, &PageError);
  135. HAL_FLASH_Lock();
  136. __enable_irq();
  137. return 1;
  138. }
  139. /**
  140. * @bieaf 写若干个数据
  141. *
  142. * @param addr 写入的地址
  143. * @param buff 写入数据的起始地址
  144. * @param word_size 长度
  145. * @return
  146. */
  147. static void WriteFlash(uint32_t addr, uint32_t * buff, int word_size)
  148. {
  149. /* 1/4解锁FLASH*/
  150. HAL_FLASH_Unlock();
  151. for(int i = 0; i < word_size; i++)
  152. {
  153. /* 3/4对FLASH烧写*/
  154. HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr + 4 * i, buff[i]);
  155. }
  156. /* 4/4锁住FLASH*/
  157. HAL_FLASH_Lock();
  158. }
  159. /**
  160. * @bieaf 读若干个数据
  161. *
  162. * @param addr 读数据的地址
  163. * @param buff 读出数据的数组指针
  164. * @param word_size 长度
  165. * @return
  166. */
  167. static void ReadFlash(uint32_t addr, uint32_t * buff, uint16_t word_size)
  168. {
  169. //uint32_t get=0;
  170. for(int i =0; i < word_size; i++)
  171. {
  172. buff[i] = *(__IO uint32_t*)(addr + 4 * i);
  173. //buff[i] =((get&0x000000ff)<< 24)| ((get&0x0000ff00 ) << 8 )| (( get&0x00ff0000 ) >> 8 ) | ((get&0xff000000 )>> 24 );
  174. }
  175. return;
  176. }
  177. /* 读取启动模式 */
  178. unsigned int Read_Start_Mode(void)
  179. {
  180. unsigned int mode = 0;
  181. //ReadFlash((Application_2_Addr + Application_Size - 4), &mode, 1);
  182. ReadFlash(StartMode_Addr, &mode, 1);
  183. return mode;
  184. }
  185. /**
  186. * @bieaf 写若干个数据
  187. *
  188. * @param addr 写入的地址
  189. * @param buff 写入数据的起始地址
  190. * @param word_size 长度
  191. * @return
  192. */
  193. void WriteFlash2(uint32_t addr, uint32_t *buff, int word_size)
  194. {
  195. /* 1/4解锁FLASH*/
  196. HAL_FLASH_Unlock();
  197. for(int i = 0; i < word_size; i++)
  198. {
  199. /* 3/4对FLASH烧写*/
  200. HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, addr + 4 * i, buff[i]);
  201. }
  202. /* 4/4锁住FLASH*/
  203. HAL_FLASH_Lock();
  204. }
  205. /* 标记升级完成 */
  206. void Set_Update_Down(void)
  207. {
  208. unsigned int update_flag = Startup_Update; ///< 对应bootloader的启动步骤
  209. memcpy(USART1_TX_BUF,(void *)StartMode_Addr,256);
  210. memcpy(USART1_TX_BUF,&update_flag,4);
  211. Erase_page(StartMode_Addr, Appear_si);
  212. WriteFlash2(StartMode_Addr, (uint32_t *)USART1_TX_BUF, 64);
  213. }
  214. /**
  215. * @bieaf 进行程序的覆盖
  216. * @detail 1.擦除目的地址
  217. * 2.源地址的代码拷贝到目的地址
  218. * 3.擦除源地址
  219. *
  220. * @param 搬运的源地址
  221. * @param 搬运的目的地址
  222. * @return 搬运的程序大小
  223. */
  224. void MoveCode(unsigned int src_addr, unsigned int des_addr, unsigned int byte_size)
  225. {
  226. /*1.擦除目的地址*/
  227. //printf("> Start erase des flash......\r\n");
  228. //Erase_page(des_addr, (byte_size/PageSize));
  229. HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
  230. Erase_page(des_addr, Appear_si);
  231. HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
  232. //printf("> Erase des flash down......\r\n");
  233. /*2.开始拷贝*/
  234. unsigned int temp[128]={0};
  235. //printf("> Start copy......\r\n");
  236. for(int i = 0; i < (byte_size+511)/512; i++)
  237. {
  238. HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
  239. ReadFlash((src_addr + i*512), temp, 128);
  240. HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
  241. WriteFlash((des_addr + i*512), temp, 128);
  242. HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
  243. }
  244. //printf("> Copy down......\r\n");
  245. /*3.擦除源地址*/
  246. //printf("> Start erase src flash......\r\n");
  247. //Erase_page(src_addr, (byte_size/PageSize));
  248. HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
  249. ;//Erase_page(src_addr, Appear_si);
  250. HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
  251. //HAL_NVIC_SystemReset();
  252. //printf("> Erase src flash down......\r\n");
  253. }
  254. ///* 采用汇编设置栈的值 */
  255. //__asm void MSR_MSP (uint32_t ulAddr)
  256. //{
  257. // MSR MSP, r0 //set Main Stack value
  258. // BX r14
  259. //}
  260. ///* 程序跳转函数 */
  261. //typedef void (*Jump_Fun)(void);
  262. //void IAP_ExecuteApp (uint32_t App_Addr)
  263. //{
  264. // Jump_Fun JumpToApp;
  265. //
  266. //// if ( ( ( * ( __IO uint32_t * ) App_Addr ) & 0x2FE00000 ) == 0x20000000 ) //检查栈顶地址是否合法.
  267. //// {
  268. // JumpToApp = (Jump_Fun) * ( __IO uint32_t *)(App_Addr + 4); //用户代码区第二个字为程序开始地址(复位地址)
  269. // MSR_MSP( * ( __IO uint32_t * ) App_Addr ); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
  270. // __disable_irq();
  271. // JumpToApp(); //跳转到APP.
  272. //// }
  273. //}
  274. /*
  275. *********************************************************************************************************
  276. * 函 数 名: JumpToBootloader
  277. * 功能说明: 跳转到系统BootLoader
  278. * 形 参: 无
  279. * 返 回 值: 无
  280. *********************************************************************************************************
  281. */
  282. void JumpToBootloader(void)
  283. {
  284. uint32_t i=0;
  285. GPIO_InitTypeDef GPIO_InitStruct = {0};
  286. void (*SysMemBootJump)(void); /* 声明一个函数指针 */
  287. __IO uint32_t BootAddr = Application_1_Addr; /* STM32F4的系统BootLoader地址 */
  288. HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
  289. /* 关闭全局中断 */
  290. DISABLE_INT();
  291. /* 关闭滴答定时器,复位到默认值 */
  292. SysTick->CTRL = 0;
  293. SysTick->LOAD = 0;
  294. SysTick->VAL = 0;
  295. HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
  296. /* 设置所有时钟到默认状态,使用HSI时钟 */
  297. HAL_RCC_DeInit();
  298. __HAL_RCC_GPIOC_CLK_ENABLE();
  299. //看门狗配置 初始化
  300. /*Configure GPIO pin : PtPin */
  301. GPIO_InitStruct.Pin = GPIO_PIN_2;
  302. if(0)//看门狗sp706
  303. //if(1)//打开看门狗sp706
  304. {
  305. //
  306. GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  307. }
  308. else
  309. {
  310. GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  311. }
  312. GPIO_InitStruct.Pull = GPIO_NOPULL;
  313. GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
  314. HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
  315. // HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
  316. /* 关闭所有中断,清除所有中断挂起标志 */
  317. for (i = 0; i < 8; i++)
  318. {
  319. NVIC->ICER[i]=0xFFFFFFFF;
  320. NVIC->ICPR[i]=0xFFFFFFFF;
  321. }
  322. // HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
  323. /* 使能全局中断 */
  324. ENABLE_INT();
  325. /* 跳转到系统BootLoader,首地址是MSP,地址+4是复位中断服务程序地址 */
  326. SysMemBootJump = (void (*)(void)) (*((uint32_t *) (BootAddr + 4)));
  327. /* 设置主堆栈指针 */
  328. __set_MSP(*(uint32_t *)BootAddr);
  329. // /* 在RTOS工程,这条语句很重要,设置为特权级模式,使用MSP指针 */
  330. __set_CONTROL(0);
  331. /* 跳转到系统BootLoader */
  332. // HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
  333. SysMemBootJump();
  334. /* 跳转成功的话,不会执行到这里,用户可以在这里添加代码 */
  335. while (1)
  336. {
  337. }
  338. }
  339. /**
  340. * @bieaf 进行BootLoader的启动
  341. *
  342. * @param none
  343. * @return none
  344. */
  345. void Start_BootLoader(void)
  346. {
  347. unsigned int update_flag = 0xAAAAAAAA; ///< 对应bootloader的启动步骤
  348. unsigned int ModeStart;
  349. unsigned int i,all_len;
  350. // HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
  351. ModeStart=Read_Start_Mode();
  352. switch(ModeStart) ///< 读取是否启动应用程序 */
  353. {
  354. case Startup_Normal: ///< 正常启动 */ //在APP2中可以设定此标志位 使得下次重启之后进入APP1
  355. {
  356. ;//printf("> Normal start......\r\n");
  357. break;
  358. }
  359. case Startup_Update: ///< 升级再启动 */
  360. {
  361. HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2); //看门狗sp706
  362. for (i = 0, all_len = 0; i < 4; ++i)
  363. {
  364. all_len = all_len << 8;
  365. all_len |= *(unsigned char *)(StartMode_Addr + 68 + i);
  366. }
  367. if ((*(unsigned int*)(Application_Buffer_Addr+6144)==Application_2_Addr) && App2_MD5_Check(Application_Buffer_Addr,all_len))
  368. {
  369. MoveCode(Application_Buffer_Addr, Application_2_Addr, all_len);//假定程序大小为100k
  370. HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
  371. // printf("> Update down......\r\n");
  372. update_flag = Startup_APP2;
  373. memcpy(USART1_TX_BUF,(void *)StartMode_Addr,256);
  374. Erase_page(StartMode_Addr, Appear_si);
  375. memcpy(USART1_TX_BUF,&update_flag,4);
  376. memcpy(USART1_TX_BUF+132,USART1_TX_BUF+68,4);
  377. WriteFlash2(StartMode_Addr, (uint32_t *)USART1_TX_BUF, 64);
  378. HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);
  379. /*for (i = 0, all_len = 0; i < 4; ++i)
  380. {
  381. all_len = all_len << 8;
  382. all_len |= *(unsigned char *)(StartMode_Addr + 68 + i);
  383. }
  384. if(App2_MD5_Check(Application_2_Addr,all_len))
  385. JumpToAPP2();//
  386. */
  387. }
  388. // break;
  389. }
  390. case Startup_APP2: ///跳转到APP2
  391. {
  392. for (i = 0, all_len = 0; i < 4; ++i)
  393. {
  394. all_len = all_len << 8;
  395. all_len |= *(unsigned char *)(StartMode_Addr + 132 + i);
  396. }
  397. if((*(unsigned int*)(Application_2_Addr+6144)==Application_2_Addr) && App2_MD5_Check(Application_2_Addr,all_len))
  398. JumpToAPP2();//
  399. break;
  400. }
  401. case Startup_Reset: ///< 恢复出厂设置 目前没使用 */
  402. {
  403. // printf("> Restore to factory program......\r\n");
  404. break;
  405. }
  406. default: ///< 启动失败
  407. {
  408. // printf("> Error:%X!!!......\r\n", Read_Start_Mode());
  409. return;
  410. }
  411. }
  412. // /* 跳转到应用程序 */
  413. //// HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_2);//看门狗sp706
  414. // printf("> Start up......\r\n\r\n");
  415. // //IAP_ExecuteApp(Application_1_Addr);
  416. // JumpToBootloader();
  417. }