427 lines
14 KiB
C
427 lines
14 KiB
C
|
|
|||
|
|
|||
|
#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:
|
|||
|
*/
|