#include "ql_api_osi.h" #include "ql_log.h" #include "ql_uart.h" #include "ql_gpio.h" #include "drv_uart.h" #include "osi_api.h" #include "stdlib.h" #include "../EC600U_t2n/include/t2n.h" #include "../EC600U_t2n/include/ModbusS.h" #include "./inc/esp32flash.h" #include "./inc/EC600U_port.h" #include "ql_api_datacall.h" #include "ql_http_client.h" #include "ql_fs.h" #include "ql_api_fota.h" #include "ql_power.h" #include "ql_api_dev.h" #include "ql_log.h" #define LOGI(msg, ...) QL_LOG(QL_LOG_LEVEL_INFO, "uart1_modbus", msg, ##__VA_ARGS__) osiThread_t *uart1_thread = NULL; //串口驱动modbus的线程句柄 drvUart_t *drvuart1 = NULL; //串口传输modbus的uart驱动句柄 static uint8_t uart_rxbuf[256 + 8]; extern uint16_t gWordVar[]; extern int com_poll_modbus_master_on_revice(int ch, uint8_t *rxbuf, int length); extern void com_poll_init(void); extern void com_poll_modbus_master_poll(int n); extern uint8_t download_file_to_SD(void); void Timeroutcallback(void *param) { //LOGI("enter Timeroutcallback"); osiEvent_t event; event.id = 10; if(uart1_thread != NULL){ if(osiEventSend(uart1_thread, &event)){ //LOGI("osiEventSend event id 10 sucess"); } else{ //LOGI("osiEventSend event id 10 fail"); } } } void uart1_modbus_event_cb(void *param, uint32_t evt) { //LOGI("enter uart1_event_cb"); if (evt & QL_UART_EVENT_TX_COMPLETE) // 发送完成 { //LOGI("QL_UART_EVENT_TX_COMPLETE"); } else if (evt & QL_UART_EVENT_RX_ARRIVED) // 接收完成 { //LOGI("QL_UART_EVENT_RX_ARRIVED"); osiEvent_t event; event.id = 9; // if (uart1_thread != NULL) { if(osiEventSend(uart1_thread, &event)){ //LOGI("osiEventSend event id 9 sucess"); } else{ //LOGI("osiEventSend event id 9 fail"); } } } } void uart1_task_thread(void *param) { LOGI("uart1_task_thread start"); // int ret = 0; int run_loop = 1; int rx_length = 0; osiTimer_t *ptimer = NULL; drvUartCfg_t uart_cfg = { .baud = 115200, .data_bits = DRV_UART_DATA_BITS_8, .stop_bits = DRV_UART_STOP_BITS_1, .parity = DRV_UART_NO_PARITY, .event_cb = uart1_modbus_event_cb, .event_mask = DRV_UART_EVENT_RX_OVERFLOW | DRV_UART_EVENT_TX_COMPLETE | DRV_UART_EVENT_RX_ARRIVED, .rx_buf_size = 128, .tx_buf_size = 128, .event_cb_ctx = NULL, .cts_enable = false, .rts_enable = false, }; uart1_thread = osiThreadCurrent(); restart: if (drvuart1 == NULL) { drvuart1 = drvUartCreate(DRV_NAME_UART1, &uart_cfg); if (drvuart1 == NULL){ LOGI("drvuart1 create faild!"); goto err1; } LOGI("drvuart1 create OK!"); if(drvUartOpen(drvuart1)){ LOGI("drvuart1 open OK"); } else{ LOGI("drvuart1 open faild!"); goto err1; } } LOGI("drvuart1 init end"); if (ptimer == NULL){ ptimer = osiTimerCreate(uart1_thread, Timeroutcallback, NULL); } if(ptimer != NULL){ LOGI("osiTimerCreate sucess"); } else{ LOGI("osiTimerCreate fail"); } if(osiTimerStart(ptimer, 10)){ LOGI("osiTimerStart ok"); } else{ LOGI("osiTimerStart fail"); } com_poll_init(); LOGI("com_poll_init end"); run_loop = 1; while (run_loop) { //LOGI("enter while"); osiEvent_t waitevent; if(osiEventTryWait(osiThreadCurrent(), &waitevent, 1000)) { //LOGI("event happend"); // 响应到事件发生 switch (waitevent.id) { case 9: { //LOGI("event id = 9"); int len = drvUartReceive(drvuart1, &uart_rxbuf[rx_length], sizeof(uart_rxbuf) - rx_length); if (len > 0) { //LOGI("receive data sucess, length is %d\n",len); rx_length += len; if (uart_rxbuf[1] == 0x03 || uart_rxbuf[1] == 0x04)//判断什么的? { //LOGI("uart_rxbuf[1] == 0x03 || uart_rxbuf[1] == 0x04"); if (rx_length >= uart_rxbuf[2] + 5)//判断依据? { com_poll_modbus_master_on_revice(0, uart_rxbuf, rx_length); rx_length = 0; } } else { com_poll_modbus_master_on_revice(0, uart_rxbuf, rx_length); rx_length = 0; } }else{ //LOGI("receive data fail"); } } break; case 10: // 10ms timmer { //LOGI("event id = 10"); if(osiTimerStart(ptimer, 10)){ //LOGI("osiTimerStart sucess"); } else{ //LOGI("osiTimerStart fail"); } com_poll_modbus_master_poll(0); //LOGI("com_poll_modbus_master_poll end"); break; } #if 0 case 0x2000: LOGI("event id = 0x2000"); ModbusSetLocalReg(waitevent.param1, waitevent.param2); //error:intersection fail //error:set boot/raet value fail break; #endif case 0x3299: { LOGI("event id= 0x3299, http download"); uint8_t err = download_file_to_SD(); LOGI("download_file_to_SD err = %d",err); break; } #if 0 //获取url,通过url将代码下载到文件中 case 0x3299: { LOGI("event id = 0x3299"); if (waitevent.param1 != 0) { LOGI("waitevent.param1 != 0"); gWordVar[REG_UPDATE_STATUS] = 1; setESP32BootValue(1); //根据waitevent.param1获取url,然后将bin文件下载到SD卡的指定文件中 http_dowload((char *)waitevent.param1,DOWNLOAD_FILENAME); int fd = ql_fopen(DOWNLOAD_FILENAME, "r"); if (fd > 0){ LOGI("open file sucess"); }else{ LOGI("open file fail"); } int file_size = ql_fsize(fd); ql_fclose(fd); free((void *)waitevent.param1); gWordVar[REG_UPDATE_STATUS] = file_size; waitevent.param1 = 0; /*将本地bin文件刷写到esp32中*/ if (file_size > 0) { LOGI("file size = %d",file_size); drvUartClose(drvuart1); drvUartDestroy(drvuart1); drvuart1 = NULL; LOGI("drvUartDestroy drvuart1 end"); gWordVar[REG_UPDATE_STATUS] = 3; uint8_t transmit_ret = ESP32DownloadFile("SD:EC600U_http_download.txt", 0x10000); if(transmit_ret ==0 ){ LOGI("ESP32DownloadFile sucess\n"); }else{ LOGI("ESP32DownloadFile fail\n"); } gWordVar[REG_UPDATE_STATUS] = transmit_ret; setESP32BootValue(0); loader_port_reset_target(); }else{ LOGI("file may be empty or no exist,file size = %d\n",file_size); } }else{ LOGI("no waitevent.param1"); } run_loop = 0; break; } #endif #if 1 //通过本地文件刷写esp32s3程序 case 0x3203: { LOGI("event id = 0x3203"); gWordVar[REG_UPDATE_STATUS] = 1; uint8_t res = 0; /*关闭超时定时器*/ osiTimerStop(ptimer); LOGI("osiTimerStop ptimer end"); /*关闭当前modbus串口*/ drvUartClose(drvuart1); drvUartDestroy(drvuart1); drvuart1 = NULL; LOGI("drvUartDestroy drvuart1 end"); ql_rtos_task_sleep_ms(500); /*初始化bootloader串口*/ res = bootloader_uart_init(115200); LOGI("bootloader_uart_init res = %d",res); ql_rtos_task_sleep_ms(500); /*使esp32进入bootloader模式*/ res = esp32_enter_bootloader(); LOGI("esp32_enter_bootloader res = %d",res); ql_rtos_task_sleep_ms(500); /*刷写*/ res = flash_to_esp32(); gWordVar[REG_UPDATE_STATUS] = res; LOGI("flash_to_esp32 res = %d",res); /*使esp32退出bootloader模式*/ res = esp32_exit_bootloader(); LOGI("esp32_exit_bootloader res = %d",res); ql_rtos_task_sleep_ms(500); /*解初始化bootloader串口*/ res = bootloader_uart_deinit(); LOGI("bootloader_uart_deinit res = %d",res); ql_rtos_task_sleep_ms(500); run_loop = 0; LOGI("case 0x3203 end"); break; } #endif #if 0 //应用程序镜像升级 case 0x5700: { LOGI("event id = 0x5700"); if (strncmp((char *)waitevent.param1, "http://", 7) == 0) { LOGI("waitevent.param1: http://"); drvUartClose(drvuart1); drvUartDestroy(drvuart1); drvuart1 = NULL; LOGI("drvUartDestroy drvuart1 end"); if(osiTimerStop(ptimer)){ LOGI("osiTimerStop sucess"); } else{ LOGI("osiTimerStop fail"); } if(AppImageUpgradeFotaEntry(waitevent.param1) == 0){ LOGI("AppImageUpgradeFotaEntry sucess"); } else{ LOGI("AppImageUpgradeFotaEntry fail"); osiThreadSleep(6000); /*重启*/ } free((void *)waitevent.param1); waitevent.param1 = 0; }else{ LOGI("waitevent.param1 error"); } break; } #endif default: break; } waitevent.id = 0; } else { LOGI("no event happend"); } } goto restart; err1: osiThreadExit(); } ql_task_t uart1_task = NULL; void uart1_app_init(void){ /*用于esp32的reset和boot*/ LOGI("ql_pin_set_func(33,0) err = %d",ql_pin_set_func(33,0)); LOGI("ql_pin_set_func(34,0) err = %d",ql_pin_set_func(34,0)); LOGI("ql_gpio_init GPIO_18 err = %d",ql_gpio_init(GPIO_18,GPIO_OUTPUT,PULL_DOWN,LVL_LOW)); LOGI("ql_gpio_init GPIO_19 err = %d",ql_gpio_init(GPIO_19,GPIO_OUTPUT,PULL_DOWN,LVL_LOW)); // ql_pin_set_func(33,0); // ql_pin_set_func(34,0); // ql_gpio_set_direction(GPIO_19,GPIO_OUTPUT); // ql_gpio_set_direction(GPIO_18,GPIO_OUTPUT); // ql_gpio_set_level(GPIO_19,LVL_LOW); // ql_gpio_set_level(GPIO_18,LVL_LOW); ql_rtos_task_create(&uart1_task, 4096, APP_PRIORITY_NORMAL, "uart1_task", uart1_task_thread, NULL, 5); } /** * 测试: * A:在连接modbus之前空测了一遍,然后连接modbus,连续测试 * B:上电后直接连接modbus进行连续测试 * 概率性问题: * 1.连上modbus后进行测试系统卡死,卡死后,ec600的电源就不供电了,esp32断电后ec600也断电 * 2.ec600的端口经常性检测不到,怀疑端口松动 * 3.ec600正常工作,log抓取不到,多次重启cooltools也无效的现象,只能重新插拔ec600重新抓取 * 4.程序执行串口读取不到规定次数,也没有返回值,但是程序又重新正常执行了 * * 未卡死次数48,读到非0数据次数11 * * 1.将项目编译成功,并提交 ok * 2.恢复数据结构体为紧凑型,尝试接收到数据0xC0 * A:0x00,0x00,0xF9,0x00,0x00,0x00,0x9C,0x00,卡死 * B:0x00,0xEC,0x00,0x00,0x00,卡死 * 3.将sync_cmd的size属性由sizof(sync_command_t)->sizeof(sync_cmd) * 烧录后屏幕不亮,log能抓取到,又重新烧录了好几遍才恢复正常 * A:卡死 * A2:0x00,0x00,抓不到log * A3:0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,卡死 * B:0x80,0x00,0x00,0x00,0x00,0xEC,卡死 * 4.将进入bootloader放到loader_port_start_timer之前,紧挨着 * A:0x00,0x67,0x00,0x00,0x64,0x27,卡死 * A1:0x00,0x00,0x00,0x00,0x00,0x00,卡死 * B:卡死 * B2:抓不到log * B3:0x77,0xff,0x00,0x00,0x00,0x00,0x03,0x00,0x96,0x00,0x00,卡死 * 5.读取次数改成300次 * 超过256就会系统卡死 * 6.test进行多次循环 * {0x20,0x20},{0x00,fail},{} * 7.sync改成全局变量 */ /* * 修改bootloader模式的上电时序, * 进入:boot高100ms,reset高500ms,reset低500ms * 退出:boot低100ms,reset高500ms,reset低500ms * 1.单次读取串口数据 & 进入bootloader后直接返回(原来是读取数据直到结束才返回) * a1:卡死 * a2:0x00,0x00,0x00,0x00,0x00,0x65,0x00,0x10,0x00,0x00,0x00,0x00,0x00,卡死 * 2.单次读取串口数据 & 进入bootloader后读取数据直到结束才返回,打印数据 * a1:打印数据后系统卡死,可能是esp的连接松动问题 * a2: */