From 432176a0db862db565efa8332bd7ed3b50014e93 Mon Sep 17 00:00:00 2001 From: cfif Date: Mon, 23 Mar 2026 17:37:39 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B0=D1=87=D0=B0=D0=BB=D0=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ArbiterCommand.c | 328 +++++++++++++++++++++++++++++++++++++++++++++-- ArbiterCommand.h | 95 +++++++++++++- 2 files changed, 403 insertions(+), 20 deletions(-) diff --git a/ArbiterCommand.c b/ArbiterCommand.c index 91560f6..d2ab03c 100644 --- a/ArbiterCommand.c +++ b/ArbiterCommand.c @@ -7,6 +7,8 @@ #include "SerialPort.h" #include "AtCmdCommonProtected.h" #include "AsciiStringParsingUtils.h" +#include "memory.h" + void sendOk(tAtCmd *AtCmd) { AtCmdPrepare(AtCmd); @@ -16,6 +18,14 @@ void sendOk(tAtCmd *AtCmd) { AtCmdRxClear(AtCmd); } +void sendError(tAtCmd *AtCmd) { + AtCmdPrepare(AtCmd); + AtCmdTxClear(AtCmd); + AtCmdTxAddStatic(AtCmd, "ERROR"); + AtCmdTxSendLn(AtCmd); + AtCmdRxClear(AtCmd); +} + void sendVers(tAtCmd *AtCmd) { AtCmdPrepare(AtCmd); AtCmdTxClear(AtCmd); @@ -24,6 +34,205 @@ void sendVers(tAtCmd *AtCmd) { AtCmdRxClear(AtCmd); } + + +//начало ------------------------------Отправка без подтверждения------------------------------------------------------- +//начало ------------------------------Отправка без подтверждения------------------------------------------------------- +//начало ------------------------------Отправка без подтверждения------------------------------------------------------- + +void TaskSerialToCanCyclic0_Init(tTaskSerialToCanCyclic *env, + tSerialPortFrameIO *ioCAN, + osMessageQueueId_t txDataQueue +) { + + env->access = osMutexNew(NULL); + env->ioCAN = ioCAN; + env->txDataQueue = txDataQueue; + + InitThreadAtrStatic(&env->thread.attr, "SerialCyclic", env->thread.controlBlock, env->thread.stack, + osPriorityNormal); +} + + +static _Noreturn void Serial_ToCanCyclic0_Thread(tTaskSerialToCanCyclic *env) { + for (;;) { + + if (osMutexAcquire(env->access, 1000) == osOK) { + + can_rx_message_type data; + if (osMessageQueueGet(env->txDataQueue, &data, NULL, 1000) == osOK) { + + if (data.id_type == CAN_ID_STANDARD) { + uint16_t sent = env->ioCAN->transmit(env->ioCAN->env, data.data, data.dlc, data.standard_id, 0, 0, + 1000); + } else { + uint16_t sent = env->ioCAN->transmit(env->ioCAN->env, data.data, data.dlc, data.extended_id, 1, 0, + 1000); + } + } + + osMutexRelease(env->access); + } + } +} + +void TaskSerialToCanCyclic0_StartThread(tTaskSerialToCanCyclic *env) { + if (!env->thread.id) { + env->thread.id = osThreadNew((osThreadFunc_t) (Serial_ToCanCyclic0_Thread), (void *) (env), &env->thread.attr); + } +} + +//конец ------------------------------Отправка без подтверждения------------------------------------------------------- +//конец ------------------------------Отправка без подтверждения------------------------------------------------------- +//конец ------------------------------Отправка без подтверждения------------------------------------------------------- + +//начало ------------------------------Отправка без подтверждения------------------------------------------------------- +//начало ------------------------------Отправка без подтверждения------------------------------------------------------- +//начало ------------------------------Отправка без подтверждения------------------------------------------------------- + +void TaskSerialToCanCyclic1_Init(tTaskSerialToCanCyclic *env, + tSerialPortFrameIO *ioCAN, + osMessageQueueId_t txDataQueue + +) { + + env->access = osMutexNew(NULL); + env->ioCAN = ioCAN; + env->txDataQueue = txDataQueue; + + InitThreadAtrStatic(&env->thread.attr, "SerialCyclic", env->thread.controlBlock, env->thread.stack, + osPriorityNormal); +} + + +static _Noreturn void Serial_ToCanCyclic1_Thread(tTaskSerialToCanCyclic *env) { + for (;;) { + + if (osMutexAcquire(env->access, 1000) == osOK) { + + can_rx_message_type data; + if (osMessageQueueGet(env->txDataQueue, &data, NULL, 1000) == osOK) { + + if (data.id_type == CAN_ID_STANDARD) { + uint16_t sent = env->ioCAN->transmit(env->ioCAN->env, data.data, data.dlc, data.standard_id, 0, 1, + 1000); + } else { + uint16_t sent = env->ioCAN->transmit(env->ioCAN->env, data.data, data.dlc, data.extended_id, 1, 1, + 1000); + } + } + + osMutexRelease(env->access); + } + } +} + +void TaskSerialToCanCyclic1_StartThread(tTaskSerialToCanCyclic *env) { + if (!env->thread.id) { + env->thread.id = osThreadNew((osThreadFunc_t) (Serial_ToCanCyclic1_Thread), (void *) (env), &env->thread.attr); + } +} + +//конец ------------------------------Отправка без подтверждения------------------------------------------------------- +//конец ------------------------------Отправка без подтверждения------------------------------------------------------- +//конец ------------------------------Отправка без подтверждения------------------------------------------------------- + + +//начало ------------------------------Отправка с подтверждением------------------------------------------------------- +//начало ------------------------------Отправка с подтверждением------------------------------------------------------- +//начало ------------------------------Отправка с подтверждением------------------------------------------------------- + +void TaskSerialToCanSpontany_Init(tTaskSerialToCanSpontany *env, + tSerialPortFrameIO *ioCAN, + osMessageQueueId_t txDataQueue, + tAtCmd *At_UART, + tAtCmd *At_UART_USB + +) { + + env->access = osMutexNew(NULL); + env->ioCAN = ioCAN; + + env->At_UART = At_UART; + env->At_UART_USB = At_UART_USB; + + env->txDataQueue = txDataQueue; + + InitThreadAtrStatic(&env->thread.attr, "SerialSpontany", env->thread.controlBlock, env->thread.stack, + osPriorityNormal); +} + + +static _Noreturn void Serial_ToCanSpontany_Thread(tTaskSerialToCanSpontany *env) { + for (;;) { + + if (osMutexAcquire(env->access, 1000) == osOK) { + + can_rx_message_Spontany data; + if (osMessageQueueGet(env->txDataQueue, &data, NULL, 1000) == osOK) { + + if (data.can_rx_message.id_type == CAN_ID_STANDARD) { + uint16_t sent = env->ioCAN->transmit(env->ioCAN->env, data.can_rx_message.data, + data.can_rx_message.dlc, data.can_rx_message.standard_id, 0, 2, + 1000); + if (sent) { + if (data.from_uart == SPONTANY_FROM_UART) { + sendOk(env->At_UART); + } else { + sendOk(env->At_UART_USB); + } + } else { + if (data.from_uart == SPONTANY_FROM_UART) { + sendError(env->At_UART); + } else { + sendError(env->At_UART_USB); + } + } + + } else { + uint16_t sent = env->ioCAN->transmit(env->ioCAN->env, data.can_rx_message.data, + data.can_rx_message.dlc, data.can_rx_message.extended_id, 1, 2, + 1000); + + if (sent) { + if (data.from_uart == SPONTANY_FROM_UART) { + sendOk(env->At_UART); + } else { + sendOk(env->At_UART_USB); + } + } else { + if (data.from_uart == SPONTANY_FROM_UART) { + sendError(env->At_UART); + } else { + sendError(env->At_UART_USB); + } + } + + } + } + + osMutexRelease(env->access); + } + } +} + +void TaskSerialToCanSpontany_StartThread(tTaskSerialToCanSpontany *env) { + if (!env->thread.id) { + env->thread.id = osThreadNew((osThreadFunc_t) (Serial_ToCanSpontany_Thread), (void *) (env), &env->thread.attr); + } +} + +//конец ------------------------------Отправка с подтверждением------------------------------------------------------- +//конец ------------------------------Отправка с подтверждением------------------------------------------------------- +//конец ------------------------------Отправка с подтверждением------------------------------------------------------- + + + + +//начало ------------------------------Парсер команд-------------------------------------------------------------------- +//начало ------------------------------Парсер команд-------------------------------------------------------------------- +//начало ------------------------------Парсер команд-------------------------------------------------------------------- + void SerialCommand_Scheduler(tTaskSerial *env) { while (AtCmdReceiveNextLine(&env->At, SystemWaitForever) == AT_OK) { @@ -34,7 +243,13 @@ void SerialCommand_Scheduler(tTaskSerial *env) { //uint32_t adr = iAsciiStringParseUnsignedLongDecimalNumber(&env->At.rxBuffer.data[1], // &env->At.rxBuffer.data[7]); - uint8_t size = iAsciiStringParseHexBytes(data, &env->At.rxBuffer.data[3], 4); + uint8_t size = iAsciiStringParseHexBytes(data, &env->At.rxBuffer.data[0], 1); + uint8_t opt = data[0]; + + size = iAsciiStringParseHexBytes(data, &env->At.rxBuffer.data[1], 1); + uint8_t remote = data[0]; + + size = iAsciiStringParseHexBytes(data, &env->At.rxBuffer.data[3], 4); uint32_t adr = (data[0] << 8) | data[1]; @@ -46,9 +261,30 @@ void SerialCommand_Scheduler(tTaskSerial *env) { size = iAsciiStringParseHexBytes(data, &env->At.rxBuffer.data[7], len); - uint16_t sent = env->ioCAN->transmit(env->ioCAN->env, data, size, adr, 0, env->numberMailBox, 1000); - sendOk(&env->At); + can_rx_message_Spontany dataCan; + dataCan.from_uart = env->from_uart; + dataCan.can_rx_message.dlc = size; + dataCan.can_rx_message.id_type = CAN_ID_STANDARD; + dataCan.can_rx_message.standard_id = adr; + dataCan.can_rx_message.frame_type = remote; + dataCan.can_rx_message.filter_index = 0; + dataCan.can_rx_message.extended_id = 0; + memcpy(dataCan.can_rx_message.data, data, size); + + if (opt) { + osMessageQueuePut(env->txDataQueue_Spontany, &dataCan, 0x0, 0U); + } else { + + uint32_t count0 = osMessageQueueGetCount(env->txDataQueue_Cyclic0); + uint32_t count1 = osMessageQueueGetCount(env->txDataQueue_Cyclic1); + + if (count0 <= count1) { + osMessageQueuePut(env->txDataQueue_Cyclic0, &dataCan.can_rx_message, 0x0, 0U); + } else { + osMessageQueuePut(env->txDataQueue_Cyclic1, &dataCan.can_rx_message, 0x0, 0U); + } + } } if (AtCmdRxBeginWithStatic(&env->At, "t")) { @@ -57,8 +293,14 @@ void SerialCommand_Scheduler(tTaskSerial *env) { //uint32_t adr = iAsciiStringParseUnsignedLongDecimalNumber(&env->At.rxBuffer.data[1], // &env->At.rxBuffer.data[9]); - uint8_t size = iAsciiStringParseHexBytes(data, &env->At.rxBuffer.data[3], 8); - uint32_t adr = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3] << 0); + uint8_t size = iAsciiStringParseHexBytes(data, &env->At.rxBuffer.data[0], 1); + uint8_t opt = data[0]; + + size = iAsciiStringParseHexBytes(data, &env->At.rxBuffer.data[1], 1); + uint8_t remote = data[0]; + + size = iAsciiStringParseHexBytes(data, &env->At.rxBuffer.data[3], 8); + uint32_t adr = (data[0] << 24) | (data[1] << 16) | (data[2] << 8) | (data[3] << 0); uint8_t len = &env->At.rxBuffer.data[env->At.rxBuffer.len] - &env->At.rxBuffer.data[9] - 2; @@ -68,9 +310,30 @@ void SerialCommand_Scheduler(tTaskSerial *env) { size = iAsciiStringParseHexBytes(data, &env->At.rxBuffer.data[9], len); - env->ioCAN->transmit(env->ioCAN->env, data, size, adr, 1, env->numberMailBox, 1000); + can_rx_message_Spontany dataCan; + dataCan.from_uart = env->from_uart; + dataCan.can_rx_message.dlc = size; + dataCan.can_rx_message.id_type = CAN_ID_EXTENDED; + dataCan.can_rx_message.extended_id = adr; + dataCan.can_rx_message.frame_type = remote; + dataCan.can_rx_message.filter_index = 0; + dataCan.can_rx_message.standard_id = 0; + memcpy(dataCan.can_rx_message.data, data, size); + + if (opt) { + osMessageQueuePut(env->txDataQueue_Spontany, &dataCan, 0x0, 0U); + } else { + + uint32_t count0 = osMessageQueueGetCount(env->txDataQueue_Cyclic0); + uint32_t count1 = osMessageQueueGetCount(env->txDataQueue_Cyclic1); + + if (count0 <= count1) { + osMessageQueuePut(env->txDataQueue_Cyclic0, &dataCan.can_rx_message, 0x0, 0U); + } else { + osMessageQueuePut(env->txDataQueue_Cyclic1, &dataCan.can_rx_message, 0x0, 0U); + } + } - sendOk(&env->At); } if (AtCmdRxBeginWithStatic(&env->At, "V")) { @@ -81,19 +344,37 @@ void SerialCommand_Scheduler(tTaskSerial *env) { } +//конец ------------------------------Парсер команд-------------------------------------------------------------------- +//конец ------------------------------Парсер команд-------------------------------------------------------------------- +//конец ------------------------------Парсер команд-------------------------------------------------------------------- + + + +//начало ------------------------------Обработчик UART команд----------------------------------------------------------- +//начало ------------------------------Обработчик UART команд----------------------------------------------------------- +//начало ------------------------------Обработчик UART команд----------------------------------------------------------- void TaskSerialUART_Init(tTaskSerial *env, - uint8_t numberMailBox, + spontany_from_uart from_uart, tSerialPortIO *ioUART, - tSerialPortFrameIO *ioCAN + tSerialPortFrameIO *ioCAN, + osMessageQueueId_t txDataQueue_Spontany, + osMessageQueueId_t txDataQueue_Cyclic0, + osMessageQueueId_t txDataQueue_Cyclic1 + + ) { env->access = osMutexNew(NULL); - env->numberMailBox = numberMailBox; + env->from_uart = from_uart; env->ioUART = ioUART; env->ioCAN = ioCAN; + env->txDataQueue_Spontany = txDataQueue_Spontany; + env->txDataQueue_Cyclic0 = txDataQueue_Cyclic0; + env->txDataQueue_Cyclic1 = txDataQueue_Cyclic1; + SerialPortClearRxBuffer(env->ioUART); AtCmdInit( @@ -127,19 +408,34 @@ void TaskSerialUART_StartThread(tTaskSerial *env) { } } +//конец ------------------------------Обработчик UART команд----------------------------------------------------------- +//конец ------------------------------Обработчик UART команд----------------------------------------------------------- +//конец ------------------------------Обработчик UART команд----------------------------------------------------------- + + +//начало ------------------------------Обработчик UART USB команд------------------------------------------------------- +//начало ------------------------------Обработчик UART USB команд------------------------------------------------------- +//начало ------------------------------Обработчик UART USB команд------------------------------------------------------- void TaskSerialUSB_Init(tTaskSerial *env, - uint8_t numberMailBox, + spontany_from_uart from_uart, tSerialPortIO *ioUART, - tSerialPortFrameIO *ioCAN + tSerialPortFrameIO *ioCAN, + osMessageQueueId_t txDataQueue_Spontany, + osMessageQueueId_t txDataQueue_Cyclic0, + osMessageQueueId_t txDataQueue_Cyclic1 ) { env->access = osMutexNew(NULL); - env->numberMailBox = numberMailBox; + env->from_uart = from_uart; env->ioUART = ioUART; env->ioCAN = ioCAN; + env->txDataQueue_Spontany = txDataQueue_Spontany; + env->txDataQueue_Cyclic0 = txDataQueue_Cyclic0; + env->txDataQueue_Cyclic1 = txDataQueue_Cyclic1; + SerialPortClearRxBuffer(env->ioUART); AtCmdInit( @@ -171,4 +467,8 @@ void TaskSerialUSB_StartThread(tTaskSerial *env) { if (!env->thread.id) { env->thread.id = osThreadNew((osThreadFunc_t) (Serial_USB_Thread), (void *) (env), &env->thread.attr); } -} \ No newline at end of file +} + +//конец ------------------------------Обработчик UART USB команд------------------------------------------------------- +//конец ------------------------------Обработчик UART USB команд------------------------------------------------------- +//конец ------------------------------Обработчик UART USB команд------------------------------------------------------- \ No newline at end of file diff --git a/ArbiterCommand.h b/ArbiterCommand.h index de33125..81edd8d 100644 --- a/ArbiterCommand.h +++ b/ArbiterCommand.h @@ -10,6 +10,11 @@ #include "AtCmdCommon.h" #include "CanSerialPortFrame.h" +typedef enum { + SPONTANY_FROM_UART, + SPONTANY_FROM_UART_USB +} spontany_from_uart; + typedef struct { tAtCmd At; @@ -18,9 +23,13 @@ typedef struct { tSerialPortIO *ioUART; tSerialPortFrameIO *ioCAN; - uint8_t numberMailBox; + spontany_from_uart from_uart; osMutexId_t access; + osMessageQueueId_t txDataQueue_Spontany; + osMessageQueueId_t txDataQueue_Cyclic0; + osMessageQueueId_t txDataQueue_Cyclic1; + struct { osThreadId_t id; uint32_t stack[1024]; @@ -31,19 +40,93 @@ typedef struct { } tTaskSerial; + +typedef struct { + + tSerialPortFrameIO *ioCAN; + osMutexId_t access; + osMessageQueueId_t txDataQueue; + + struct { + osThreadId_t id; + uint32_t stack[1024]; + StaticTask_t controlBlock; + osThreadAttr_t attr; + } thread; + + +} tTaskSerialToCanCyclic; + +typedef struct { + can_rx_message_type can_rx_message; + spontany_from_uart from_uart; +} can_rx_message_Spontany; + +typedef struct { + + tSerialPortFrameIO *ioCAN; + osMutexId_t access; + osMessageQueueId_t txDataQueue; + + tAtCmd *At_UART; + tAtCmd *At_UART_USB; + + struct { + osThreadId_t id; + uint32_t stack[1024]; + StaticTask_t controlBlock; + osThreadAttr_t attr; + } thread; + + +} tTaskSerialToCanSpontany; + void TaskSerialUART_Init(tTaskSerial *env, - uint8_t numberMailBox, + spontany_from_uart from_uart, tSerialPortIO *ioUART, - tSerialPortFrameIO *ioCAN + tSerialPortFrameIO *ioCAN, + osMessageQueueId_t txDataQueue_Spontany, + osMessageQueueId_t txDataQueue_Cyclic0, + osMessageQueueId_t txDataQueue_Cyclic1 ); + void TaskSerialUART_StartThread(tTaskSerial *env); void TaskSerialUSB_Init(tTaskSerial *env, - uint8_t numberMailBox, - tSerialPortIO *ioUART, - tSerialPortFrameIO *ioCAN + spontany_from_uart from_uart, + tSerialPortIO *ioUART, + tSerialPortFrameIO *ioCAN, + osMessageQueueId_t txDataQueue_Spontany, + osMessageQueueId_t txDataQueue_Cyclic0, + osMessageQueueId_t txDataQueue_Cyclic1 + ); + void TaskSerialUSB_StartThread(tTaskSerial *env); +void TaskSerialToCanCyclic0_Init(tTaskSerialToCanCyclic *env, + tSerialPortFrameIO *ioCAN, + osMessageQueueId_t txDataQueue +); + +void TaskSerialToCanCyclic0_StartThread(tTaskSerialToCanCyclic *env); + + +void TaskSerialToCanCyclic1_Init(tTaskSerialToCanCyclic *env, + tSerialPortFrameIO *ioCAN, + osMessageQueueId_t txDataQueue); + +void TaskSerialToCanCyclic1_StartThread(tTaskSerialToCanCyclic *env); + +void TaskSerialToCanSpontany_Init(tTaskSerialToCanSpontany *env, + tSerialPortFrameIO *ioCAN, + osMessageQueueId_t txDataQueue, + tAtCmd *At_UART, + tAtCmd *At_UART_USB + +); + +void TaskSerialToCanSpontany_StartThread(tTaskSerialToCanSpontany *env); + #endif //HVAC_DEV_ARBITERCOMMAND_H