main.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. /*
  2. * Copyright (c) 2006-2018, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-09-22 Warfalcon first version
  9. */
  10. //链接地址
  11. //https://gitee.com/spunky_973/rt-fota
  12. #include <rtthread.h>
  13. #include <rtdevice.h>
  14. #include <board.h>
  15. #if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH)
  16. #include <finsh.h>
  17. #include <shell.h>
  18. #endif
  19. #include <fal.h>
  20. #include <rt_fota.h>
  21. #include <fal_def.h>
  22. #define DBG_ENABLE
  23. #define DBG_SECTION_NAME "main"
  24. #ifdef RT_MAIN_DEBUG
  25. #define DBG_LEVEL DBG_LOG
  26. #else
  27. #define DBG_LEVEL DBG_INFO
  28. #endif
  29. #define DBG_COLOR
  30. #include <rtdbg.h>
  31. #include "sys_config.h"
  32. #include <easyflash.h>
  33. #define BL_VERSION "1.1.4"
  34. #define COMPILE "20230901"
  35. #define RTU_DTU GET_PIN(B,13)
  36. #define Beep GET_PIN(B, 4)
  37. #define HMI_THREAD_PRIORITY 5 //线程优先级
  38. #define HMI_THREAD_STACK_SIZE 2048 //线程栈空间大小
  39. #define HMI_THREAD_TIMESLICE 5 //时间片
  40. #define MAX_SIZE 512
  41. /* 消息队列控制块 */
  42. static struct rt_messagequeue rx_mq;//接收数据消息队列
  43. struct serial_configure otaconfig = RT_SERIAL_CONFIG_DEFAULT; /*初始化配置参数*/
  44. rt_device_t otaserial; /*串口设备句柄*/
  45. const char boot_log_buf[] =
  46. " ____ _____ _____ ___ _____ _ \r\n\
  47. | _ \\_ _| | ___/ _ \\ _ _|/ \\ \r\n\
  48. | |_) || |_____ | |_ || || | | / _ \\ \r\n\
  49. | _ < | |_____ | _| ||_|| | |/ ___ \\ \r\n\
  50. |_| \\_\\|_| |_| \\___/ |_/_/ \\_\\ \r\n";
  51. static char msg_pool[256];
  52. static char rx_buffer[256];
  53. static rt_err_t uart_input(rt_device_t dev, rt_size_t size);
  54. extern void HMI_WRITE(char *fmt,...);
  55. int HMI_Thread(void);
  56. static void Hmi_thread_entry(void *parameter);
  57. static rt_thread_t hmi1 = RT_NULL;
  58. /* 串口接收消息结构*/
  59. struct rx_msg
  60. {
  61. rt_device_t dev;
  62. rt_size_t size;
  63. };
  64. void rt_fota_print_log(void)
  65. {
  66. LOG_RAW("%s", boot_log_buf);
  67. LOG_RAW("2016 - 2019 Copyright by Radiation @ warfalcon \r\n");
  68. LOG_RAW("Version: %s build %s\r\n\r\n", RT_FOTA_SW_VERSION, __DATE__);
  69. }
  70. void Beep_Tip(uint16_t volnum)
  71. {
  72. rt_pin_mode(Beep, PIN_MODE_OUTPUT);
  73. rt_pin_write(Beep, 1);
  74. rt_thread_mdelay(volnum);
  75. rt_pin_write(Beep, 0);
  76. }
  77. int Ota_uart2_init(void)
  78. {
  79. otaserial = rt_device_find("uart4");
  80. /*修改串口配置参数*/
  81. otaconfig.baud_rate = BAUD_RATE_115200; //修改波特率115200
  82. otaconfig.data_bits = DATA_BITS_8; //数据位8
  83. otaconfig.stop_bits = STOP_BITS_1; //停止位1
  84. otaconfig.bufsz = 1024; //缓冲区1k
  85. otaconfig.parity = PARITY_NONE; //无奇偶校验
  86. /* step3:控制串口设备。通过控制接口传入命令控制字,与控制参数 */
  87. rt_device_control(otaserial, RT_DEVICE_CTRL_CONFIG, &otaconfig);
  88. /* step4:打开串口设备。以中断接收及轮询发送模式打开串口设备 */
  89. if(rt_device_open(otaserial, RT_DEVICE_FLAG_DMA_RX)==RT_EOK){
  90. rt_kprintf("HMI Init Success!!\n");
  91. HMI_WRITE("sleep=%d",1);
  92. HMI_WRITE("sleep=%d",1);
  93. HMI_WRITE("sleep=%d",1);
  94. return 0;
  95. }
  96. else {
  97. rt_kprintf("HMI Init Failed!!\n");
  98. return RT_EOK;
  99. }
  100. }
  101. /* 接收数据回调函数 */
  102. static rt_err_t uart_input(rt_device_t dev, rt_size_t size)
  103. {
  104. struct rx_msg msg;
  105. rt_err_t result;
  106. msg.dev = dev;
  107. msg.size = size;
  108. result = rt_mq_send(&rx_mq, &msg, sizeof(msg));
  109. if ( result == -RT_EFULL)
  110. {
  111. /* 消息队列满 */
  112. rt_kprintf("message queue full!\n");
  113. }
  114. return result;
  115. }
  116. /*串口屏写数据*/
  117. void HMI_WRITE(char *fmt, ...)
  118. {
  119. va_list ap;
  120. //末尾需要拼接的3个ff
  121. const char hmi_hex[2]={0x0D,0X0A};
  122. //末尾需要拼接的3个ff
  123. const char hmi_end[3]={0xff,0xff,0xff};
  124. static char str[MAX_SIZE];
  125. memset(str,'\0',sizeof(str));
  126. rt_size_t str_length;
  127. va_start(ap,fmt);
  128. str_length = rt_vsnprintf(str, sizeof(str) - 1, fmt, ap);
  129. if (str_length > MAX_SIZE - 1)
  130. str_length = MAX_SIZE - 1;
  131. rt_device_write(otaserial, 0, str, str_length);
  132. va_end(ap);
  133. if(strstr(str, "sleep")!=NULL)
  134. {
  135. rt_device_write(otaserial, 0,hmi_end,3);
  136. }
  137. else if (strstr(str, "t7.txt")!=NULL) {
  138. rt_device_write(otaserial, 0,hmi_end,3);
  139. }
  140. else if (strstr(str, "t5.txt")!=NULL) {
  141. rt_device_write(otaserial, 0,hmi_end,3);
  142. }
  143. else if (strstr(str, "update.val")!=NULL) {
  144. rt_device_write(otaserial, 0,hmi_end,3);
  145. }
  146. else {
  147. rt_device_write(otaserial, 0,hmi_hex,2);
  148. }
  149. }
  150. static void HMI_Decode(char *cmd,uint8_t cmd_len)
  151. {
  152. //擦除APP分区,将df_area分区固件搬运至app分区
  153. if(strstr(rx_buffer,"resetapp")!=NULL)
  154. {
  155. rt_kprintf("固件恢复!!!\n");
  156. HMI_WRITE("固件恢复!!!");
  157. const char *dst_part_name = "app";
  158. const char *src_part_name = "df_area";
  159. const struct fal_partition *dst_part;
  160. const struct fal_partition *src_part;
  161. dst_part = fal_partition_find(dst_part_name);
  162. src_part = fal_partition_find(src_part_name);
  163. if (dst_part == RT_NULL || src_part == RT_NULL)
  164. {
  165. if (dst_part == RT_NULL)
  166. rt_kprintf("%s partition is not exist!\n", dst_part_name);
  167. if (src_part == RT_NULL)
  168. rt_kprintf("%s partition is not exist!\n", src_part_name);
  169. }
  170. else
  171. {
  172. rt_kprintf("Clone %s partition to %s partition:\n", src_part_name, dst_part_name);
  173. HMI_WRITE("Clone %s partition to %s partition:", src_part_name, dst_part_name);
  174. if (fal_partition_erase(dst_part, 0, dst_part->len) >= 0)
  175. {
  176. int clone_pos = 0;
  177. int clone_len = 0, clone_tol_len;
  178. static int clone_num;
  179. rt_uint8_t *buf = rt_malloc(4096);
  180. if (dst_part->len < src_part->len)
  181. clone_tol_len = dst_part->len;
  182. else
  183. clone_tol_len = src_part->len;
  184. while ((clone_pos < clone_tol_len) && (buf != RT_NULL))
  185. {
  186. clone_len = fal_partition_read(src_part, clone_pos, buf, 4096);
  187. if (clone_len < 0)
  188. {
  189. rt_kprintf("\nread %s partition failed, clone stop!\n", src_part_name);
  190. break;
  191. }
  192. if (fal_partition_write(dst_part, clone_pos, buf, clone_len) < 0)
  193. {
  194. rt_kprintf("\nwrite %s partition failed, clone stop!\n", dst_part_name);
  195. break;
  196. }
  197. clone_pos += clone_len;
  198. clone_num++;
  199. HMI_WRITE("debug.update.val=%d",clone_num);
  200. if(clone_num==99) clone_num = 0;
  201. }
  202. if (clone_pos >= clone_tol_len)
  203. {
  204. HMI_WRITE("Clone partition success, total %d bytes!", clone_tol_len);
  205. rt_kprintf("\nClone partition success, total %d bytes!\n", clone_tol_len);
  206. HMI_WRITE("debug.update.val=100");
  207. HMI_WRITE("debug.update.val=100");
  208. HMI_WRITE("debug.update.val=100");
  209. }
  210. else
  211. {
  212. HMI_WRITE("Clone partition failed!");
  213. rt_kprintf("Clone partition failed!");
  214. }
  215. if (buf)
  216. rt_free(buf);
  217. }
  218. }
  219. }
  220. //备份app分区至df_area分区
  221. else if(strstr(rx_buffer, "backupapp")!=NULL)
  222. {
  223. }
  224. //启动程序
  225. else if(strstr(rx_buffer, "startup")!=NULL)
  226. {
  227. rt_fota_start_application();
  228. }
  229. //重启bootloader
  230. else if(strstr(rx_buffer, "bootloader")!=NULL)
  231. {
  232. uint8_t boot=1;
  233. if(easyflash_init()==EF_NO_ERR)
  234. {
  235. ef_set_env_blob("stop_in_bootloader", &boot, sizeof(boot));
  236. }
  237. rt_hw_cpu_reset();
  238. }
  239. //擦除app分区
  240. else if (strstr(rx_buffer, "eraseapp")!=NULL) {
  241. struct fal_partition fal_erase;
  242. fal_erase.offset=204800;
  243. rt_sprintf(fal_erase.name, "%s","app");
  244. rt_sprintf(fal_erase.flash_name, "%s","onchip_flash");
  245. fal_partition_erase(&fal_erase,0,319488);
  246. }
  247. //擦除easyflash
  248. else if(strstr(rx_buffer, "eraseeasyflash")!=NULL){
  249. rt_kprintf("erase easyflash...\n");
  250. //uint8_t isave = 0;
  251. ef_env_set_default();
  252. //ef_set_env_blob("iSave", &isave, sizeof(isave));
  253. HMI_WRITE("easyflash擦除成功!");
  254. }
  255. else if(strstr(rx_buffer, "erasedf_area")!=NULL){
  256. struct fal_partition fal_erase;
  257. fal_erase.offset=15729152;
  258. rt_sprintf(fal_erase.name, "%s","df_area");
  259. rt_sprintf(fal_erase.flash_name, "%s","w25q16m");
  260. fal_partition_erase(&fal_erase,0,524288);
  261. }
  262. }
  263. /*HMI*/
  264. int HMI_Thread(void)
  265. {
  266. Ota_uart2_init();
  267. rt_err_t ret = RT_EOK;
  268. /* 初始化消息队列 */
  269. rt_mq_init(&rx_mq, "rx_mq",
  270. msg_pool, /* 存放消息的缓冲区 */
  271. sizeof(struct rx_msg), /* 一条消息的最大长度 */
  272. sizeof(msg_pool), /* 存放消息的缓冲区大小 */
  273. RT_IPC_FLAG_FIFO); /* 如果有多个线程等待,按照先来先得到的方法分配消息 */
  274. /* 创建线程*/
  275. hmi1 = rt_thread_create("Hmi_Fresh_thread",
  276. Hmi_thread_entry,
  277. RT_NULL,
  278. HMI_THREAD_STACK_SIZE,
  279. HMI_THREAD_PRIORITY,
  280. HMI_THREAD_TIMESLICE);
  281. /* 如果获得线程控制块,启动这个线程 */
  282. if (hmi1 != RT_NULL)
  283. {
  284. rt_thread_startup(hmi1);
  285. }
  286. else
  287. {
  288. ret = RT_ERROR;
  289. }
  290. return ret;
  291. }
  292. /*入口函数*/
  293. static void Hmi_thread_entry(void *parameter)
  294. {
  295. /* 设置接收回调函数 */
  296. rt_device_set_rx_indicate(otaserial, uart_input);
  297. struct rx_msg msg;
  298. rt_err_t result;
  299. rt_uint32_t rx_length;
  300. rt_uint32_t start_timeout = 0;
  301. ef_set_env_blob("driver_bl", &BL_VERSION, sizeof(BL_VERSION));
  302. ef_set_env_blob("driver_compile", &COMPILE, sizeof(COMPILE));
  303. HMI_WRITE("debug.t5.txt=\"%s\"",BL_VERSION);
  304. HMI_WRITE("debug.t7.txt=\"%s\"",COMPILE);
  305. while(1)
  306. {
  307. rt_memset(&msg, 0, sizeof(msg));
  308. /* 从消息队列中读取消息*/
  309. result = rt_mq_recv(&rx_mq, &msg, sizeof(msg), 1000);
  310. if (result == RT_EOK)
  311. {
  312. rx_length = rt_device_read(msg.dev, 0, rx_buffer, msg.size);
  313. rx_buffer[rx_length] = '\0';
  314. LOG_I("%s\n",rx_buffer);
  315. HMI_Decode(rx_buffer,rx_length);
  316. }
  317. else{
  318. //rt_device_write(otaserial, 0, &rx_buffer[0], rx_length);
  319. HMI_WRITE("bootloader mode");
  320. //rt_kprintf("bootloader mode");
  321. start_timeout++;
  322. if(start_timeout==300)
  323. {
  324. rt_fota_start_application();
  325. start_timeout = 0;
  326. }
  327. }
  328. /*********************************************************************************************************************/
  329. //rt_kprintf("%04d-%02d-%02d %02d:%02d:%02d\n",tm.tm_year+1900,tm.tm_mon+1,tm.tm_mday,tm.tm_hour,tm.tm_min,tm.tm_sec);
  330. //rt_kprintf("workSta.vbat.txt=%c%d.%02d%c\n",hmi_str,voltage/100,voltage%100,hmi_str);
  331. }
  332. }
  333. int main(void)
  334. {
  335. #if defined(RT_USING_FINSH) && defined(FINSH_USING_MSH)
  336. finsh_set_prompt("rt-fota />");
  337. #endif
  338. extern void rt_fota_init(void);
  339. easyflash_init();
  340. rt_fota_init();
  341. HMI_Thread();
  342. Beep_Tip(100);
  343. return RT_EOK;
  344. }
  345. //INIT_DEVICE_EXPORT(Ota_uart2_init);