myBootloader.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321
  1. #include "myBootloader.h"
  2. #include "flash.h"
  3. #include "stdio.h"
  4. #include "sys.h"
  5. #include "eventUnit.h"
  6. #include "myUart.h"
  7. #include "stm32f10x_it.h"
  8. #define POST_EVENT_TIMEOUT_QUIT_BOOTLOAD 7
  9. #define BOOT_TIMEOUT_10MS 300
  10. UPDATE_STATUS_te update_status = UPDATE_PRE;
  11. CMD_CTR_STEP cmd_ctr_flag=CMD_CTR_IDLE;
  12. CMD_DATA_STRUCT cmd_data_struct;
  13. CMD_DATA_STEP cmd_data_flag=CMD_DATA_IDLE;
  14. static uint8_t cmd_addr_cnt=0;
  15. static uint32_t cmd_data_cnt=0;
  16. static uint32_t timeOutCount=0;
  17. static uint32_t firm_len;
  18. static uint8_t spliteLen;
  19. const uint8_t ACK_OK[] = {0xCC, 0xDD};
  20. const uint8_t ACK_ERROR[] = {0xEE, 0xFF};
  21. const uint8_t IAP_START1[] = {0x5A, 0xA5};
  22. const uint8_t IAP_START2[] = {0x5A, 0x01};
  23. const uint8_t IAP_DATA_DONE[] = {0x5A, 0x02};
  24. static uint8_t setDataSrc=0;
  25. iapfun jump2app;
  26. extern void recoveryQuitBootloadEvent(void);
  27. // extern void clearQuitBootloadEvent(void);
  28. // extern void bootloadOverGotoApp(void);
  29. //跳转到应用程序段
  30. //appxaddr:用户代码起始地址.
  31. #if defined (__CC_ARM)
  32. #pragma O0 //IAP_Load_APP不进行优化
  33. #elif defined (__ICCARM__)
  34. #pragma optimize=s none
  35. #endif
  36. void myFlash_setBootloadFlag(void)
  37. {
  38. uint16_t flag = IAP_UPGRADE_FLAG;
  39. FLASH_Write(IAP_UPGRADE_FLAG_ADDR, (uint16_t *)flag, 2);
  40. }
  41. void myFlash_clearBootloadFlag(void)
  42. {
  43. uint16_t flag = 0;
  44. FLASH_Write(IAP_UPGRADE_FLAG_ADDR, (uint16_t *)flag, 2);
  45. }
  46. bool myFlash_checkFlag(void)
  47. {
  48. return ((*(vu32*)IAP_UPGRADE_FLAG_ADDR) == IAP_UPGRADE_FLAG ? true : false);
  49. }
  50. void IAP_Load_APP(uint32_t appxaddr)
  51. {
  52. if( ((*(vu32*)appxaddr)-0x20000000) < (SRAM_SIZE*1024) ) //检查栈顶地址是否合法.
  53. {
  54. jump2app=(iapfun)*(vu32*)(appxaddr+4); //用户代码区第二个字为程序开始地址(复位地址)
  55. MSR_MSP(*(vu32*)appxaddr); //初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址)
  56. jump2app(); //跳转到APP.
  57. }
  58. }
  59. void bootDelay(uint32_t time_ms)
  60. {
  61. uint32_t i, j;
  62. i = time_ms;
  63. while (i --)
  64. {
  65. for ( j = 0; j < 20000; j++)
  66. {
  67. ;
  68. }
  69. }
  70. }
  71. void Back_Ok( )
  72. {
  73. bootDelay(10);
  74. myUart1_sendArray((uint8_t *)ACK_OK, 2);
  75. }
  76. void Back_Err( )
  77. {
  78. bootDelay(10);
  79. myUart1_sendArray((uint8_t *)ACK_ERROR, 2);
  80. cmd_data_flag=CMD_DATA_IDLE;
  81. cmd_ctr_flag=CMD_CTR_IDLE;
  82. update_status=UPDATE_PRE;
  83. cmd_addr_cnt=0;
  84. cmd_data_cnt=0;
  85. // TIME_IRA_CNT=0;
  86. // GetDaraFromUSART_Flag=0;
  87. // myPrintf2("Back_Err\r\n");
  88. }
  89. void Back_FirmErr( )
  90. {
  91. bootDelay(10);
  92. myUart1_sendArray((uint8_t *)ACK_ERROR, 2);
  93. cmd_data_flag=CMD_DATA_IDLE;
  94. cmd_addr_cnt=0;
  95. cmd_data_cnt=0;
  96. // myPrintf2("Back_FirmErr\r\n");
  97. }
  98. // #define myPrintf2(args...) //do{{printf("\r\ndecodeBootLoadData-\r\n");printf(args);}}while(0)
  99. uint8_t decodeBootLoadData(uint8_t *src, uint16_t len)
  100. {
  101. static uint8_t ret = CMD_PRO_IDLE;
  102. switch (update_status)
  103. {
  104. case UPDATE_PRE:
  105. {
  106. switch (cmd_ctr_flag)
  107. {
  108. case CMD_CTR_IDLE:
  109. {
  110. if (len == 2 && (memcmp(src, IAP_START1, 2) == 0))
  111. {
  112. //1、准备开始固件升级
  113. cmd_ctr_flag = CMD_CTR_INIT;
  114. // myPrintf2("begin bootload\r\n");
  115. Back_Ok();
  116. timeOutCount = BOOT_TIMEOUT_10MS;
  117. ret = CMD_PRO_START;
  118. }
  119. }break;
  120. case CMD_CTR_INIT:
  121. {
  122. if (len == 7 && (memcmp(src, IAP_START2, 2) == 0))
  123. {
  124. //2、开始固件升级
  125. cmd_ctr_flag = CMD_CTR_IDLE;
  126. update_status = UPDATE_ING;
  127. spliteLen = src[2];
  128. firm_len = (src[3]<<24)+(src[4]<<16)+(src[5]<<8)+src[6];
  129. Back_Ok();
  130. timeOutCount = BOOT_TIMEOUT_10MS;
  131. // myPrintf2("start bootload\r\n");
  132. ret = CMD_PRO_GET_INIT;
  133. }
  134. }break;
  135. default:
  136. break;
  137. }
  138. }break;
  139. case UPDATE_ING:
  140. {
  141. switch(cmd_data_flag)
  142. {
  143. case CMD_DATA_IDLE:
  144. {
  145. if(src[0]==0x31)
  146. {
  147. //3、接收IAP写入地址
  148. cmd_data_flag = CMD_DATA_ADDR;
  149. // myPrintf2("begin receive addr\r\n");
  150. Back_Ok();
  151. timeOutCount = BOOT_TIMEOUT_10MS;
  152. }
  153. if (len == 2 && (memcmp(src, IAP_DATA_DONE, 2) == 0))
  154. {
  155. break;
  156. }
  157. }
  158. case CMD_DATA_ADDR:
  159. {
  160. uint32_t addr;
  161. //4、成功接收IAP写入地址,准备接收固件数据
  162. memcpy(cmd_data_struct.cmd_addr, src+1, 4);
  163. cmd_data_flag = CMD_DATA_BUF;
  164. addr = (cmd_data_struct.cmd_addr[0]<<24)+(cmd_data_struct.cmd_addr[1]<<16)+(cmd_data_struct.cmd_addr[2]<<8)+cmd_data_struct.cmd_addr[3];
  165. len = len - 5;
  166. ret = CMD_PRO_GET_OFFSET_ADDR;
  167. }
  168. break;
  169. case CMD_DATA_BUF:
  170. {
  171. ret = CMD_PRO_RECV_ING;
  172. //5、接收固件数据,满2k字节写入一次IAP
  173. timeOutCount = BOOT_TIMEOUT_10MS;
  174. memcpy(cmd_data_struct.cmd_buf+cmd_data_cnt, src, len);
  175. cmd_data_cnt += len;
  176. if(cmd_data_cnt == 2048)
  177. {
  178. //6、满2k字节后先校验数据
  179. cmd_data_flag=CMD_DATA_CHACK;
  180. cmd_data_cnt=0;
  181. Back_Ok();
  182. }
  183. else
  184. {
  185. //接收固件数据包时必须整包接收
  186. //否则认为是错误包,
  187. if (len == spliteLen)
  188. {
  189. Back_Ok();
  190. }
  191. else
  192. {
  193. Back_FirmErr();
  194. }
  195. }
  196. }
  197. break;
  198. case CMD_DATA_CHACK:
  199. {
  200. uint8_t Val,checksum;
  201. u16 i;
  202. timeOutCount = BOOT_TIMEOUT_10MS;
  203. //7、检验数据
  204. checksum=0x31;
  205. for(i=0;i<4;i++)
  206. {
  207. checksum+=cmd_data_struct.cmd_addr[i];
  208. }
  209. for(i=0;i<2048;i++)
  210. {
  211. checksum+=cmd_data_struct.cmd_buf[i];
  212. }
  213. if(checksum==src[0])
  214. {
  215. //8、IAP写入固件
  216. uint32_t write_addr=0;
  217. write_addr = (cmd_data_struct.cmd_addr[0]<<24)+(cmd_data_struct.cmd_addr[1]<<16)+(cmd_data_struct.cmd_addr[2]<<8)+cmd_data_struct.cmd_addr[3];
  218. if((write_addr>=APP_START_ADDR)&&(write_addr<FLASH_BASE+1024*FLASH_SIZE))
  219. {
  220. ret = CMD_PRO_WRITE_2KBYTE;
  221. FLASH_Write_2KB(write_addr, cmd_data_struct.cmd_buf);
  222. cmd_data_flag = CMD_DATA_IDLE;
  223. cmd_data_cnt = 0;
  224. Back_Ok();
  225. myFlash_setBootloadFlag();
  226. }
  227. else
  228. {
  229. cmd_data_flag = CMD_DATA_IDLE;
  230. Back_FirmErr();
  231. }
  232. }
  233. else
  234. {
  235. cmd_data_flag = CMD_DATA_IDLE;
  236. cmd_data_cnt = 0;
  237. Back_FirmErr();
  238. ret = CMD_PRO_CRC_ERROR;
  239. }
  240. }break;
  241. default:
  242. break;
  243. }
  244. if (len == 2 && (memcmp(src, IAP_DATA_DONE, 2) == 0))
  245. {
  246. //9、固件接收完毕
  247. timeOutCount = 0;
  248. // cmd_ctr_flag = CMD_CTR_DONE;
  249. cmd_ctr_flag = CMD_CTR_IDLE;
  250. update_status = UPDATE_ING;
  251. Back_Ok();
  252. bootDelay(50);
  253. if(((*(vu32*)(APP_START_ADDR+4))&0xFF000000)==0x08000000) //判断是否为0x08XXXXXX.
  254. {
  255. ret = CMD_PRO_BOOT_DONE;
  256. myFlash_clearBootloadFlag();
  257. printf("goto app\r\n\r\n");
  258. bootDelay(50);
  259. RCC->APB1RSTR = 0xFFFFFFFF;
  260. RCC->APB2RSTR = 0xFFFFFFFF;
  261. RCC->APB1RSTR = 0x00000000;
  262. RCC->APB2RSTR = 0x00000000;
  263. IAP_Load_APP(APP_START_ADDR);//执行FLASH APP代码
  264. }
  265. else
  266. {
  267. ret = CMD_PRO_ADDR_ERROR;
  268. Back_Err();
  269. }
  270. }
  271. }break;
  272. case UPDATE_DONE:
  273. {
  274. }break;
  275. default:
  276. break;
  277. }
  278. return ret;
  279. }
  280. static irqCallback_ts myIrqCallback_tim1;
  281. /**
  282. * @brief tim1中断函数
  283. * 通过API@TIM1_callbackRegiste注册到@stm32f10x_it.c中的真正的中断函数
  284. *
  285. * @param status
  286. * @param param
  287. */
  288. static void tim1_callback(uint8_t status, uint32_t param) //TIM1中断
  289. {
  290. static uint8_t timeCnt_1ms = 0;
  291. if(timeCnt_1ms ++ == 50)
  292. {
  293. timeCnt_1ms = 0;
  294. if(timeOutCount)
  295. {
  296. timeOutCount --;
  297. if (timeOutCount == 0)
  298. {
  299. Back_Err();
  300. }
  301. }
  302. }
  303. }
  304. void bootloader_init(void)
  305. {
  306. myIrqCallback_tim1.thisCb = tim1_callback;
  307. TIM1_callbackRegiste(&myIrqCallback_tim1);
  308. }