|
|
@@ -1,5 +1,6 @@
|
|
|
#include "mcu_ctrl_board.h"
|
|
|
#include "../../rtu_linux_modules/swapi/subjects/serial/serial.h"
|
|
|
+#include "lwjson/lwjson.h"
|
|
|
|
|
|
// 模块名称
|
|
|
static const char MODULE_NAME[] = "MCUCtrlBoard";
|
|
|
@@ -8,27 +9,86 @@ 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 };
|
|
|
|
|
|
-// 接收处理来自MCU控制板的数据报文帧, 串口-线程回调
|
|
|
+// 声明Go中处理串口请求并返回应答结果的函数(供C调用)
|
|
|
+extern char *RTU_ProcessCommand(const char *request);
|
|
|
+
|
|
|
+// 接收处理来自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 discarded %d bytes before JSON frame start!", MODULE_NAME, log_prefix, nRecvBytes);
|
|
|
+ serial_clear_recv_buffer(pSerial);
|
|
|
+ goto retp;
|
|
|
+ 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_ProcessCommand((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);
|
|
|
+ goto retp;
|
|
|
+ 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);
|
|
|
+ goto retp;
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+retp:
|
|
|
+ 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()
|
|
|
{
|
|
|
-#ifdef _DEBUG // 上位机单元测试时使用
|
|
|
- const char *serialName = "/dev/ttyS0"; int baudrate = 115200;
|
|
|
-#else
|
|
|
+ lwjson_stream_init(&s_myCom.parser, NULL);
|
|
|
+
|
|
|
const char *serialName = "/dev/ttymxc2"; int baudrate = 115200;
|
|
|
-#endif
|
|
|
const char *parityCheck = "none"; // 无校检
|
|
|
s_myCom.h = serial_open(serialName, baudrate, parityCheck, \
|
|
|
- comio_data_recv_proc, comio_data_recv_proc, NULL);
|
|
|
+ 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!!", \
|