| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107 |
- #include "mcu_ctrl_board.h"
- #include "../../rtu_linux_modules/swapi/subjects/serial/serial.h"
- #include "lwjson/lwjson.h"
- // 模块名称
- static const char MODULE_NAME[] = "MCUCtrlBoard";
- // 定义与单片机进行通讯的结构体, 同时定义结构体对象
- typedef struct
- {
- void *h;
- lwjson_stream_parser_t parser;
- unsigned long jsonStartTick; // JSON数据包开始接收时的单调计时基准, 用于超时判断
- } SMCBCom;
- static SMCBCom s_myCom = { 0 };
- // 声明Go中处理串口请求并返回应答结果的函数(供C调用)
- extern char *RTU_JsonMsgProcCb(const char *jsonStr);
- // 接收处理来自MCU控制板的数据报文帧, 串口-数据回调
- static int comio_data_recv_proc(unsigned long wParam/*传递打开的串口句柄*/, unsigned long lParam/*保留暂未使用*/)
- {
- SMCBCom *pComIO = &s_myCom; void *pSerial = pComIO->h;
- const unsigned char *pRecvBuf = serial_get_recv_buffer(pSerial); int nRecvBytes = serial_get_recv_buffer_bytes(pSerial);
- const char *log_prefix = serial_get_log_prefix(pSerial); lwjsonr_t ret;
- ret = lwjson_stream_parse(&pComIO->parser, pRecvBuf[nRecvBytes - 1]); // 把串口数据逐字节的喂给解析器去解析
- switch(ret)
- {
- case lwjsonERRJSON: // 1, 无效的字符
- case lwjsonSTREAMWAITFIRSTCHAR: // 2, 等待首字符
- serial_printf_recv_buffer(pSerial, LEVEL_TRACE);
- sw_log_warn("[%s] %s discarding invalid JSON byte: 0x%02X(buffer length: %d)!", MODULE_NAME, log_prefix, pRecvBuf[0], nRecvBytes);
- serial_clear_recv_buffer(pSerial);
- break;
- case lwjsonSTREAMINPROG: // 3, 正在解析中
- if(0 == pComIO->jsonStartTick) xgettickcount(&pComIO->jsonStartTick);
- break;
- case lwjsonSTREAMDONE: // 4, 解析已完成
- sw_log_debug("[%s] %s received a request(%d bytes): %s", MODULE_NAME, log_prefix, nRecvBytes, pRecvBuf);
- char *pResponse = RTU_JsonMsgProcCb((const char *)pRecvBuf);
- if(pResponse)
- {
- int nRspBytes = strlen(pResponse);
- int sendBytes = serial_send_data(pSerial, (const unsigned char *)pResponse, nRspBytes);
- if(sendBytes == nRspBytes) sw_log_debug("[%s] %s send a response(%d bytes): %s", MODULE_NAME, log_prefix, nRspBytes, pResponse);
- else sw_log_error("[%s] %s failed to send a response(%d bytes, ret=%d): %s!!", MODULE_NAME, log_prefix, nRspBytes, sendBytes, pResponse);
- free(pResponse);
- }
- pComIO->jsonStartTick = 0; serial_clear_recv_buffer(pSerial); lwjson_stream_reset(&pComIO->parser);
- break;
- case lwjsonERRMEM: // 5, 嵌套的太深("LWJSON_CFG_STREAM_STACK_SIZE")
- sw_log_error("[%s] %s parser stack overflow (ERRMEM), resetting parser!", MODULE_NAME, log_prefix);
- pComIO->jsonStartTick = 0; serial_clear_recv_buffer(pSerial); lwjson_stream_reset(&pComIO->parser);
- break;
- default: // 流式解析时, 其它的返回值, 都不应该出现
- sw_log_fatal("[%s] %s internal error, lwjson_stream_parse() returned: %d, data receive thread will exit!!!", MODULE_NAME, log_prefix, ret);
- return -1;
- }
- return 1;
- }
- // 接收处理来自MCU控制板的数据报文帧, 串口-空闲回调
- static int comio_data_idle_proc(unsigned long wParam/*传递打开的串口句柄*/, unsigned long lParam/*保留暂未使用*/)
- {
- SMCBCom *pComIO = &s_myCom; void *pSerial = pComIO->h;
- const unsigned char *pRecvBuf = serial_get_recv_buffer(pSerial); int nRecvBytes = serial_get_recv_buffer_bytes(pSerial);
- const char *log_prefix = serial_get_log_prefix(pSerial); unsigned long nowTick;
- xgettickcount(&nowTick);
- if(pComIO->jsonStartTick > 0 && (nowTick - pComIO->jsonStartTick) > 50/*空闲超时单位: ms*/)
- {
- sw_log_warn("[%s] %s timeout occurred while receiving a request(%d bytes): %s!", MODULE_NAME, log_prefix, nRecvBytes, pRecvBuf);
- pComIO->jsonStartTick = 0; serial_clear_recv_buffer(pSerial); lwjson_stream_reset(&pComIO->parser);
- }
- return 1;
- }
- // 打开与MCU控制板的串口通讯, 返回: 0成功, <0时失败
- int MCBComInit()
- {
- lwjson_stream_init(&s_myCom.parser, NULL);
- const char *serialName = "/dev/ttymxc2"; int baudrate = 115200;
- const char *parityCheck = "none"; // 无校检
- s_myCom.h = serial_open(serialName, baudrate, parityCheck, \
- comio_data_recv_proc, comio_data_idle_proc, NULL);
- if(!s_myCom.h)
- {
- sw_log_error("[%s] failed to open the \"%s:%d(%s parity)\" device!!", \
- MODULE_NAME, serialName, baudrate, parityCheck);
- MCBComExit(); return -1;
- }
- return 0;
- }
- // 关闭与MCU控制板的串口通讯, 返回: 0成功, <0时失败
- int MCBComExit()
- {
- if(s_myCom.h) serial_close(s_myCom.h, WAITTHRD_SAFEEXIT_TIMEOUT);
- memset(&s_myCom, 0, sizeof(s_myCom));
- return 0;
- }
|