onchip_flash.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451
  1. #include "onechip_include_header.h"
  2. // 用户数据存储地址——选择Flash末尾区域,避免覆盖程序代码
  3. // STM32F103RE Flash: 0x08000000 ~ 0x0807FFFF (512KB)
  4. #define CFG_PARAM_START_ADDR 0x0807F800 // 最后1页(2KB)起始地址
  5. #define onechip_name "Onechip602"
  6. #define onechip_pswd "onechip1003"
  7. #define onechip_IP "192.168.1.10"
  8. #define onechip_PORT "8003"
  9. #define default_SN "2603001"
  10. /**
  11. * @brief 从指定Flash地址读取32位数据
  12. */
  13. uint32_t Flash_ReadWord(uint32_t address)
  14. {
  15. return *(__IO uint32_t*)address;
  16. }
  17. /**
  18. * @brief 从指定Flash地址读取16位数据
  19. */
  20. uint16_t Flash_ReadHalfWord(uint32_t address)
  21. {
  22. return *(__IO uint16_t*)address;
  23. }
  24. /**
  25. * @brief 向Flash写入16位数据(半字)
  26. * @param address 目标地址(必须为偶数,2字节对齐)
  27. * @param data 要写入的数据(16位)
  28. * @retval HAL_OK 成功,否则失败
  29. */
  30. HAL_StatusTypeDef Flash_WriteHalfWord(uint32_t address, uint16_t data)
  31. {
  32. HAL_StatusTypeDef status = HAL_ERROR;
  33. // 1. 解锁Flash
  34. HAL_FLASH_Unlock();
  35. // 2. 写入半字数据
  36. status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_HALFWORD, address, data);
  37. // 3. 锁定Flash
  38. HAL_FLASH_Lock();
  39. return status;
  40. }
  41. /**
  42. * @brief 向Flash写入32位数据(字)
  43. * @param address 目标地址(必须为4字节对齐)
  44. * @param data 要写入的数据(32位)
  45. */
  46. HAL_StatusTypeDef Flash_WriteWord(uint32_t address, uint32_t data)
  47. {
  48. HAL_StatusTypeDef status = HAL_ERROR;
  49. HAL_FLASH_Unlock();
  50. status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, address, data);
  51. HAL_FLASH_Lock();
  52. return status;
  53. }
  54. /**
  55. * @brief 擦除指定Flash页
  56. * @param page_address 页起始地址(必须是页边界对齐)
  57. */
  58. HAL_StatusTypeDef Flash_ErasePage(uint32_t page_address)
  59. {
  60. HAL_StatusTypeDef status = HAL_ERROR;
  61. FLASH_EraseInitTypeDef EraseInitStruct;
  62. uint32_t PageError = 0;
  63. // 计算页号
  64. // uint32_t page_num = (page_address - FLASH_BASE) / FLASH_PAGE_SIZE;
  65. HAL_FLASH_Unlock();
  66. EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;
  67. EraseInitStruct.PageAddress = page_address;
  68. EraseInitStruct.NbPages = 1;
  69. status = HAL_FLASHEx_Erase(&EraseInitStruct, &PageError);
  70. HAL_FLASH_Lock();
  71. return status;
  72. }
  73. /**
  74. * @brief 向Flash写入多个半字数据(自动处理擦除)
  75. * @param start_addr 起始地址
  76. * @param pBuffer 数据缓冲区
  77. * @param NumToWrite 要写入的半字数量
  78. */
  79. void Flash_WriteBuffer(uint32_t start_addr, uint8_t *pBuffer, uint32_t NumToWrite)
  80. {
  81. // 1. 擦除目标页
  82. uint32_t page_start = start_addr - (start_addr % FLASH_PAGE_SIZE);
  83. Flash_ErasePage(page_start);
  84. // 2. 依次写入每个半字
  85. for (uint32_t i = 0; i < NumToWrite; i=i+4) {
  86. Flash_WriteWord(start_addr + i, *(uint32_t *)(pBuffer+i));
  87. }
  88. }
  89. /**
  90. * @brief 向Flash写入多个半字数据(自动处理擦除)
  91. * @param start_addr 起始地址
  92. * @param pBuffer 数据缓冲区
  93. * @param NumToWrite 要写入的半字数量
  94. */
  95. void Flash_ReadBuffer(uint32_t start_addr, uint8_t *pBuffer, uint32_t NumToWrite){
  96. for (uint32_t i = 0; i < NumToWrite; i=i+4) {
  97. *(uint32_t *)(pBuffer+i) = *(__IO uint32_t*)(start_addr + i);
  98. }
  99. }
  100. /********************************************************************
  101. * checksum_calc()
  102. *
  103. *描述:接收数据checksum计算
  104. *参数:pdata:要计算的数据
  105. * len:要计算的数据长度
  106. *返回:checksum值
  107. *其他:无
  108. *--------------------------------------------------------------------
  109. *记录:
  110. ********************************************************************/
  111. uint32_t checksum_calc(uint8_t *pdata, uint8_t len)
  112. {
  113. uint8_t *tmp = pdata;
  114. uint32_t checksum = 0;
  115. for(uint8_t i = 0; i < len; i++)
  116. {
  117. checksum += tmp[i];
  118. }
  119. return checksum;
  120. }
  121. /********************************************************************
  122. * checksum_calc()
  123. *
  124. *描述:接收数据checksum计算
  125. *参数:pdata:要计算的数据
  126. * len:要计算的数据长度
  127. *返回:checksum值
  128. *其他:无
  129. *--------------------------------------------------------------------
  130. *记录:
  131. ********************************************************************/
  132. uint32_t checksum_calc1(uint8_t *wdata, int len)
  133. {
  134. uint32_t checksum = 0;
  135. for(int i = 0; i < len; i++)
  136. {
  137. checksum += wdata[i];
  138. }
  139. return checksum;
  140. }
  141. /********************************************************************
  142. * cfg_load_default_param()
  143. *
  144. *描述:加载默认参数
  145. *参数:无
  146. *返回:无
  147. *其他:无
  148. *--------------------------------------------------------------------
  149. *记录:
  150. ********************************************************************/
  151. void cfg_load_default_param(void)
  152. {
  153. sysinf.lysis_offset = 0;
  154. sysinf.lysis_overHeat = 3;
  155. sysinf.lysis_overHeatTime = 10;
  156. sysinf.lysis_Kp = 5;
  157. sysinf.lysis_Ki = 0.01;
  158. sysinf.lysis_Kd = 0;
  159. sysinf.amplif_Kp = 20;
  160. sysinf.amplif_Ki = 0.05;
  161. sysinf.amplif_Kd = 0;
  162. sysinf.PresetTempVal = 72;
  163. sysinf.PresetTempTime = 5;
  164. sysinf.SetTempVal = 68;
  165. sysinf.holdTemp = 63.5;
  166. sysinf.PreHeatTime = 1;
  167. sysinf.readyTemp = 65.5;
  168. sysinf.adjtemp = -0.5;
  169. sysinf.log_level = 0;
  170. sysinf.skip_CheckOrRun = 0;
  171. sysinf.timeinner = 6000;
  172. sysinf.swingtime = 100;
  173. sysinf.swingspeed = 60;
  174. sysinf.swingtimeRight = 40;
  175. sysinf.swingtimePause = 100;
  176. sysinf.runLoopTime = 600;
  177. sysinf.runLoopSpeed = 80;
  178. strcpy(sysinf.wifiname, onechip_name);
  179. strcpy(sysinf.password, onechip_pswd);
  180. strcpy(sysinf.TCP_IP_Addr, onechip_IP);
  181. strcpy(sysinf.TCP_IP_PORT, onechip_PORT);
  182. memset(sysinf.SN, 0 ,sizeof(sysinf.SN));
  183. strcpy(sysinf.SN, default_SN);
  184. }
  185. /********************************************************************
  186. * cfg_param_verify()
  187. *
  188. *描述:配置参数校验
  189. *参数:无
  190. *返回:0/1:校验不通过/通过
  191. *其他:无
  192. *--------------------------------------------------------------------
  193. *记录:
  194. ********************************************************************/
  195. uint8_t cfg_param_verify(void)
  196. {
  197. unsigned char pramlen = sizeof(oneChipSysdef) - offsetof(oneChipSysdef, SN);
  198. uint32_t saveCrc = *(uint32_t *)(CFG_PARAM_START_ADDR + (pramlen-4));
  199. uint32_t calCrc = checksum_calc((uint8_t *)CFG_PARAM_START_ADDR, (pramlen-4));
  200. if((saveCrc == calCrc) && (saveCrc != 0xffffffff)) {
  201. Flash_ReadBuffer(CFG_PARAM_START_ADDR,(uint8_t *)&sysinf.SN, pramlen);
  202. }
  203. }
  204. /********************************************************************
  205. * cfg_save_cfg_param()
  206. *
  207. *描述:保存配置参数
  208. *参数:无
  209. *返回:0/1:保存失败/成功
  210. *其他:无
  211. *--------------------------------------------------------------------
  212. *记录:
  213. ********************************************************************/
  214. uint8_t cfg_save_cfg_param(void)
  215. {
  216. unsigned char pramlen = sizeof(oneChipSysdef) - offsetof(oneChipSysdef, SN);
  217. sysinf.checksum = (uint32_t)checksum_calc((uint8_t *)&sysinf.SN, (pramlen-4));
  218. Flash_WriteBuffer(CFG_PARAM_START_ADDR, (uint8_t *)&sysinf.SN, pramlen);
  219. return cfg_param_verify();
  220. }
  221. /********************************************************************
  222. * cfg_param_init()
  223. *
  224. *描述:配置参数初始化
  225. *参数:无
  226. *返回:0/1:初始化失败/成功
  227. *其他:无
  228. *--------------------------------------------------------------------
  229. *记录:
  230. ********************************************************************/
  231. uint8_t cfg_param_init(void)
  232. {
  233. uint8_t rlt = 0;
  234. uint32_t findSN = 1;
  235. Flash_ReadBuffer(CFG_PARAM_START_ADDR,(uint8_t *)&sysinf.SN, sizeof(sysinf.SN));
  236. for(unsigned i=0;i<sizeof(sysinf.SN);i++)
  237. {
  238. if((sysinf.SN[i]<'0' || sysinf.SN[i]>'9')){
  239. findSN = 0;
  240. break;
  241. }
  242. }
  243. if(findSN == 0){
  244. strcpy(sysinf.SN, default_SN);
  245. }
  246. return rlt;
  247. }
  248. /**
  249. * @brief 跳转到应用程序段(执行APP)
  250. * @param appxaddr : 应用程序的起始地址
  251. * @retval 无
  252. */
  253. void iap_load_app(uint32_t appxaddr)
  254. {
  255. if (((*(volatile uint32_t *)appxaddr) & 0x2FFE0000) == 0x20000000) /* 检查栈顶地址是否合法.可以放在内部SRAM共64KB(0x20000000) */
  256. {
  257. // uint32_t msp_value = *(volatile uint32_t*)appxaddr;
  258. // uint32_t reset_vector = *(volatile uint32_t*)(appxaddr + 4);
  259. // // 1. 检查栈顶地址是否在合法SRAM范围(STM32F103 64KB)
  260. // if ((msp_value < 0x20000000) || (msp_value > 0x2000FFFF))
  261. // return;
  262. // // 2. 检查复位向量是否为有效的Thumb地址(最低位为1)
  263. // if ((reset_vector & 0x1) == 0)
  264. // return;
  265. // // 3. 关闭全局中断
  266. // __disable_irq();
  267. // // 4. 关闭所有外设时钟(可选,但推荐)
  268. // HAL_RCC_DeInit();
  269. // // 5. 复位HAL库
  270. // HAL_DeInit();
  271. // // 6. 清除所有挂起的中断(清除NVIC挂起状态)
  272. // for (int i = 0; i < 8; i++) {
  273. // NVIC->ICPR[i] = 0xFFFFFFFF; // 清挂起
  274. // NVIC->ICER[i] = 0xFFFFFFFF; // 禁用所有中断
  275. // }
  276. // // 7. 关闭SysTick(避免其产生中断)
  277. // SysTick->CTRL = 0;
  278. // SysTick->LOAD = 0;
  279. // SysTick->VAL = 0;
  280. // // 8. 数据与指令同步屏障
  281. // __DSB();
  282. // __ISB();
  283. // // 9. 设置主堆栈指针
  284. // __set_MSP(msp_value);
  285. // __DSB();
  286. // __ISB();
  287. // //10. 跳转到复位地址(强制Thumb模式)
  288. // volatile iapfun jump2app = (iapfun)(reset_vector );
  289. // jump2app();
  290. /* 用户代码区第二个字为程序开始地址(复位地址) */
  291. volatile iapfun jump2app = (iapfun) * (volatile uint32_t *)(appxaddr + 4);
  292. // __disable_irq();
  293. // HAL_DeInit();
  294. /* 初始化APP堆栈指针(用户代码区的第一个字用于存放栈顶地址) */
  295. __set_MSP(*(volatile uint32_t *)appxaddr);
  296. /* 跳转到APP */
  297. jump2app();
  298. }
  299. }
  300. /**
  301. * @brief IAP写入一页
  302. * @param appxaddr : 应用程序的起始地址
  303. * @param appbuf : 应用程序CODE
  304. * @param appsize : 应用程序大小(字节)
  305. * @retval 无
  306. */
  307. void iap_write_apppage(uint32_t start_addr, uint8_t *pBuffer, uint32_t appsize)
  308. {
  309. // 1. 擦除目标页
  310. uint32_t page_start = start_addr - (start_addr % FLASH_PAGE_SIZE);
  311. if(start_addr % FLASH_PAGE_SIZE){
  312. return ;
  313. }
  314. Flash_ErasePage(start_addr);
  315. // 2. 依次写入每个半字
  316. for (uint32_t i = 0; i < appsize; i=i+4) {
  317. Flash_WriteWord(start_addr + i, *(uint32_t *)(pBuffer+i));
  318. }
  319. }
  320. int app_image_copy(uint32_t src,uint32_t dst,uint32_t page_size,uint32_t len)
  321. {
  322. uint32_t src_addr = src;
  323. uint32_t dst_addr = dst;
  324. uint32_t errorTime = 0;
  325. uint32_t remain_size = len;
  326. uint8_t *pBuffer;
  327. Van_Device_Printf(VAN_LOG_ALLPRINT, "cope app from:%x to:%x size:%x\n\r",src_addr,dst_addr,remain_size);
  328. while (remain_size > 0) {
  329. Refresh_IWDG();
  330. iap_write_apppage(dst_addr, (uint8_t *)src_addr, page_size);
  331. Van_Device_Printf(VAN_LOG_ALLPRINT, "cope app from:%x to:%x size:%x\n\r",src_addr,dst_addr,remain_size);
  332. /* 验证写入是否正确(可选) */
  333. for (uint32_t i = 0; i < page_size; i=i+4) {
  334. if (*(uint32_t *)(dst_addr + i) != *(uint32_t *)(src_addr + i)) {
  335. errorTime++;
  336. if(errorTime > FLASH_APP_COPY_EERTIME) {
  337. /*多长拷贝失败,返回失败*/
  338. return 0;
  339. Van_Device_Printf(VAN_LOG_ALLPRINT, "cope error at%x\n\r");
  340. }
  341. continue;
  342. }
  343. }
  344. src_addr += page_size;
  345. dst_addr += page_size;
  346. errorTime = 0;
  347. remain_size -= page_size;
  348. }
  349. Van_Device_Printf(VAN_LOG_ALLPRINT, "cope end..\n\r");
  350. return 1;
  351. }
  352. uint32_t check_main_App(void){
  353. if(*(uint32_t *)(FLASH_APP1_ADDR + FLASH_APP_VERSION_OFFSET) == 0xffffffff){
  354. if(*(uint32_t *)(FLASH_APP2_ADDR + FLASH_APP_VERSION_OFFSET) != 0xffffffff){
  355. Van_Device_Printf(VAN_LOG_ALLPRINT, "run flag error cope back..\n\r");
  356. app_image_copy(FLASH_APP2_ADDR,FLASH_APP1_ADDR,FLASH_PAGE_SIZE,FLASH_APP2_SIZE);
  357. }
  358. }
  359. uint32_t mps;
  360. uint32_t app;
  361. mps = (*(volatile uint32_t *)FLASH_APP1_ADDR);
  362. app = *(volatile uint32_t *)(FLASH_APP1_ADDR + 4);
  363. if ((( mps& 0x2FFE0000) != 0x20000000)||
  364. ((app < 0x08010000) || (app > 0x08030000))) {
  365. /*头非法*/
  366. if(*(uint32_t *)(FLASH_APP2_ADDR + FLASH_APP_VERSION_OFFSET) != 0xffffffff){
  367. Van_Device_Printf(VAN_LOG_ALLPRINT, "head error cope back..\n\r");
  368. app_image_copy(FLASH_APP2_ADDR,FLASH_APP1_ADDR,FLASH_PAGE_SIZE,FLASH_APP2_SIZE);
  369. }
  370. }
  371. mps = (*(volatile uint32_t *)FLASH_APP1_ADDR);
  372. app = *(volatile uint32_t *)(FLASH_APP1_ADDR + 4);
  373. if((*(uint32_t *)(FLASH_APP1_ADDR + FLASH_APP_VERSION_OFFSET) == 0xffffffff)||
  374. (( mps& 0x2FFE0000) != 0x20000000)||
  375. ((app < 0x08010000) || (app > 0x08030000))){
  376. return 0;
  377. }
  378. return 1;
  379. }