boot.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #include "gd32f10x.h"
  2. #include "boot.h"
  3. #include "main.h"
  4. #include "delay.h"
  5. #include "fmc.h"
  6. #include "w25q32.h"
  7. #include <stdio.h>
  8. #include "ota_message.h"
  9. #include "ec800m.h"
  10. #include "usart.h"
  11. #define APP_PROGRAMMER_BLOCK 2 //程序在W25Q32中存放的位置
  12. load_a load_A;
  13. /**
  14. * @brief 用strstr函数找出字节数组中的指定字符位置,如果没有返回NULL
  15. *
  16. * @param strs 字节数组
  17. * @param str 指定字符串
  18. * @param first 字节数组偏移量
  19. * @param len 字节数组长度
  20. * @return char* 指定字符地址,如果没有返回NULL
  21. */
  22. static char* find_string(char *strs, char *str,int first, int len)
  23. {
  24. int i = 0;
  25. char *start = NULL;
  26. strs = strs + first;
  27. while(i < len){
  28. start = strstr(strs, str);
  29. if(start != NULL){
  30. break;
  31. }
  32. i++;
  33. strs++;
  34. }
  35. if(i == len + 1){
  36. return NULL;
  37. }
  38. return start;
  39. }
  40. /**
  41. * @brief 等待解析读文件命令发送完的返回数据
  42. *
  43. * @param data 将解析的数据复制到data数组内
  44. * @param timeout 超时时间
  45. * @param datalen 需要复制的数据字节长度
  46. * @return int 成功则返回复制的字节长度,失败返回-1
  47. */
  48. int WaitForReadData(uint8_t* data,int timeout,int datalen)
  49. {
  50. uint32_t len = 0;
  51. bool timeoutFlag = false;
  52. if (timeout >= 0)
  53. {
  54. timeoutFlag = true;
  55. }
  56. while (1)
  57. {
  58. Delay_Ms(50);
  59. if ((UART0_RX_STAT > 0) && (find_string((char *)&UART0_RX_BUF, "\r\nOK\r\n",datalen, sizeof(UART0_RX_BUF))))
  60. {
  61. UART0_RX_STAT = 0;
  62. // char *p = strstr((char *)&UART0_RX_BUF, "CONNECT ");
  63. // if (p)
  64. // {
  65. // p += 8;
  66. // sscanf(p, "%u\r", &len); // 读取长度
  67. // if(len == datalen)
  68. // {
  69. // p = strchr(p, '\n') + 1; // 跳过换行
  70. memcpy(data,(char *)&UART0_RX_BUF,datalen);
  71. Clear_DMA_Buffer();
  72. return datalen;
  73. // }
  74. // else
  75. // {
  76. // Clear_DMA_Buffer();
  77. // return len;
  78. // }
  79. }
  80. timeout -= 50;
  81. if (timeoutFlag == true && timeout <= 0)
  82. {
  83. Clear_DMA_Buffer();
  84. return -1;
  85. }
  86. }
  87. }
  88. //进入bootloader更新
  89. void BootLoader_Brance(uint32_t app_byte)
  90. {
  91. GD32_EraseFlash(GD32_A_START_PAGE,GD32_A_PAGE_NUM);//擦除A区原有程序
  92. /* 打开UFS:otaDATA.txt */
  93. EC800MSendCmd(CLOSE_otaDATA_FILE,strlen(CLOSE_otaDATA_FILE));
  94. WaitResponse("QFCLOSE",1000);
  95. EC800MSendCmd(OPEN_otaDATA_FILE,strlen(OPEN_otaDATA_FILE));
  96. if(WaitResponse("QFOPEN:", 2000) == 0)
  97. return;
  98. for(uint8_t i=0;i<app_byte/1024;i++) //1KB写一次
  99. {
  100. uint8_t app_programmer[1024];
  101. memset(app_programmer,0,1024);
  102. // uint32_t addr=APP_PROGRAMMER_BLOCK*64*1024+i*1024; //其在w25q32中的地址
  103. // W25Q32_Read(app_programmer,addr,1024);
  104. while(1)
  105. {
  106. task_fwdgt_reload();
  107. int x = 0;
  108. EC800MSendCmd(READ_otaDATA_FILE,strlen(READ_otaDATA_FILE));
  109. Delay_Ms(200); //必要的200ms延迟
  110. x = WaitForReadData(app_programmer,2000,1024);
  111. // if((x != 1024) && (x != -1))
  112. // {
  113. // char* SEEK_otaDATA_FILE = "";
  114. // sprintf(SEEK_otaDATA_FILE,"AT+QFSEEK=1,%d,2\r\n",x);
  115. // EC800MSendCmd(SEEK_otaDATA_FILE,strlen(SEEK_otaDATA_FILE)); //出错的话文件指针向左偏移1024个字节
  116. // }
  117. // else
  118. if(x == 1024)
  119. {
  120. break;
  121. }
  122. }
  123. GD32_WriteFlash(GD32_A_SADDR+i*1024,(uint32_t *)&app_programmer,1024); //将读出的数据按页写入数据
  124. Delay_Ms(50);
  125. }
  126. //将不满1024数据单独写入
  127. if(app_byte % 1024 != 0)
  128. {
  129. uint32_t startAddress=(app_byte/1024)*1024;
  130. uint8_t app_programmer[1024];
  131. memset(app_programmer,0,1024);
  132. // uint32_t addr=APP_PROGRAMMER_BLOCK*64*1024+(app_byte/1024)*1024; //其在w25q32中的地址
  133. // W25Q32_Read(app_programmer,addr,app_byte%1024);
  134. while(1)
  135. {
  136. task_fwdgt_reload();
  137. int x = 0;
  138. EC800MSendCmd(READ_otaDATA_FILE,strlen(READ_otaDATA_FILE));
  139. Delay_Ms(200); //必要的200ms延迟
  140. x = WaitForReadData(app_programmer,2000,app_byte % 1024);
  141. // if(x != (app_byte % 1024) && (x != -1))
  142. // {
  143. // char* SEEK_otaDATA_FILE = "";
  144. // sprintf(SEEK_otaDATA_FILE,"AT+QFSEEK=1,%d,2\r\n",x);
  145. // EC800MSendCmd(SEEK_otaDATA_FILE,strlen(SEEK_otaDATA_FILE)); //出错的话文件指针向左偏移读取字节数
  146. // }
  147. // else
  148. if(x == (app_byte % 1024))
  149. {
  150. break;
  151. }
  152. }
  153. GD32_WriteFlash(GD32_A_SADDR+(app_byte/1024)*1024,(uint32_t *)&app_programmer,app_byte % 1024);
  154. Delay_Ms(50);
  155. }
  156. // 保存UFS文件
  157. while(1)
  158. {
  159. EC800MSendCmd(CLOSE_otaDATA_FILE,strlen(CLOSE_otaDATA_FILE));
  160. if(WaitResponse("OK", 2000) == 1)
  161. {
  162. break;
  163. }
  164. }
  165. Delay_Ms(50);
  166. clear_ota_message_config_block();
  167. LOAD_A(GD32_A_SADDR);
  168. }
  169. /*-------------------------------------------------*/
  170. /*函数名:设置SP */
  171. /*参 数:addr:栈顶指针初始值 */
  172. /*返回值:无 */
  173. /*-------------------------------------------------*/
  174. __asm void MSR_SP(uint32_t addr)
  175. {
  176. MSR MSP, r0
  177. BX r14
  178. }
  179. /*-------------------------------------------------*/
  180. /*函数名:跳转到A区 */
  181. /*参 数:addr:A区的起始地址 */
  182. /*返回值:无 */
  183. /*-------------------------------------------------*/
  184. void LOAD_A(uint32_t addr)
  185. {
  186. if((*(uint32_t *)addr>=0x20000000)&&(*(uint32_t *)addr<=0x20017FFF)){
  187. MSR_SP(*(uint32_t *)addr);
  188. load_A = (load_a)*(uint32_t *)(addr+4);
  189. BootLoader_Clear();
  190. load_A();
  191. }else ;
  192. }
  193. /*-------------------------------------------------*/
  194. /*函数名:清除B区使用的外设 */
  195. /*参 数:无 */
  196. /*返回值:无 */
  197. /*-------------------------------------------------*/
  198. void BootLoader_Clear(void)
  199. {
  200. gpio_deinit(GPIOA);
  201. gpio_deinit(GPIOB);
  202. }