commit 00cad94ce9bc02004818586839460642d5d46540 Author: cfif Date: Mon Mar 30 14:25:13 2026 +0300 Init diff --git a/ArbiterCommand.c b/ArbiterCommand.c new file mode 100644 index 0000000..a8d801d --- /dev/null +++ b/ArbiterCommand.c @@ -0,0 +1,524 @@ +// +// Created by cfif on 13.03.2026. +// +#include "ArbiterCommand.h" +#include "CmsisRtosThreadUtils.h" +#include "SystemDelayInterface.h" +#include "SerialPort.h" +#include "AtCmdCommonProtected.h" +#include "AsciiStringParsingUtils.h" +#include "memory.h" + +/* +void sendOk(tAtCmd *AtCmd) { + AtCmdPrepare(AtCmd); + AtCmdTxClear(AtCmd); + AtCmdTxAddStatic(AtCmd, "OK"); + AtCmdTxSendLn(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); + AtCmdTxAddStatic(AtCmd, "v001"); + AtCmdTxSendLn(AtCmd); + AtCmdRxClear(AtCmd); +} +*/ + + +//начало ------------------------------Отправка без подтверждения------------------------------------------------------- +//начало ------------------------------Отправка без подтверждения------------------------------------------------------- +//начало ------------------------------Отправка без подтверждения------------------------------------------------------- + +void TaskSerialToCanCyclic0_Init(tTaskSerialToCanCyclic *env, + tSerialPortFrameIO *ioCAN +) { + +// env->access = osMutexNew(NULL); + env->ioCAN = ioCAN; + env->txDataQueue = osMessageQueueNew(20, sizeof(can_rx_message_type), NULL); + + 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); +// } + } +} + +uint32_t GetCountQueueCanCyclic0(tTaskSerialToCanCyclic *env) { + uint32_t count = 0; + +// if (osMutexAcquire(env->access, 1000) == osOK) { + count = osMessageQueueGetCount(env->txDataQueue); +// osMutexRelease(env->access); +// } + + return count; +} + +osStatus_t PutQueueCanCyclic0(tTaskSerialToCanCyclic *env, can_rx_message_type *dataCan) { + osStatus_t status = osErrorTimeout; + +// if (osMutexAcquire(env->access, 1000) == osOK) { + status = osMessageQueuePut(env->txDataQueue, dataCan, 0x0, 0U); +// osMutexRelease(env->access); +// } + + return status; +} + + +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 + +) { + +// env->access = osMutexNew(NULL); + env->ioCAN = ioCAN; + env->txDataQueue = osMessageQueueNew(20, sizeof(can_rx_message_type), NULL); + + 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); +// } + } +} + +uint32_t GetCountQueueCanCyclic1(tTaskSerialToCanCyclic *env) { + uint32_t count = 0; + +// if (osMutexAcquire(env->access, 1000) == osOK) { + count = osMessageQueueGetCount(env->txDataQueue); +// osMutexRelease(env->access); +// } + + return count; +} + +osStatus_t PutQueueCanCyclic1(tTaskSerialToCanCyclic *env, can_rx_message_type *dataCan) { + osStatus_t status = osErrorTimeout; + +// if (osMutexAcquire(env->access, 1000) == osOK) { + status = osMessageQueuePut(env->txDataQueue, dataCan, 0x0, 0U); +// osMutexRelease(env->access); +// } + + return status; +} + +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, + tSerialPortIO *ioUART, + tSerialPortIO *ioUSB + +) { + +// env->access = osMutexNew(NULL); + env->ioCAN = ioCAN; + + env->ioUART = ioUART; + env->ioUSB = ioUSB; + + env->txDataQueue = osMessageQueueNew(20, sizeof(can_rx_message_Spontany), NULL); + + 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 == FROM_UART) { + env->ioUART->transmit(env->ioUART->env, (uint8_t *) "OK\r\n", sizeof("OK\r\n") - 1, 1000); + } else { + env->ioUSB->transmit(env->ioUSB->env, (uint8_t *) "OK\r\n", sizeof("OK\r\n") - 1, 1000); + } + } else { + if (data.from_uart == FROM_UART) { + env->ioUART->transmit(env->ioUART->env, (uint8_t *) "ERROR\r\n", sizeof("ERROR\r\n") - 1, 1000); + } else { + env->ioUSB->transmit(env->ioUSB->env, (uint8_t *) "ERROR\r\n", sizeof("ERROR\r\n") - 1, 1000); + } + } + + } 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 == FROM_UART) { + env->ioUART->transmit(env->ioUART->env, (uint8_t *) "OK\r\n", sizeof("OK\r\n") - 1, 1000); + } else { + env->ioUSB->transmit(env->ioUSB->env, (uint8_t *) "OK\r\n", sizeof("OK\r\n") - 1, 1000); + } + } else { + if (data.from_uart == FROM_UART) { + env->ioUART->transmit(env->ioUART->env, (uint8_t *) "ERROR\r\n", sizeof("ERROR\r\n") - 1, 1000); + } else { + env->ioUSB->transmit(env->ioUSB->env, (uint8_t *) "ERROR\r\n", sizeof("ERROR\r\n") - 1, 1000); + } + } + + } + } + +// osMutexRelease(env->access); +// } + } +} + +osStatus_t PutQueueCanSpontany(tTaskSerialToCanSpontany *env, can_rx_message_Spontany *dataCan) { + osStatus_t status = osErrorTimeout; + +// if (osMutexAcquire(env->access, 1000) == osOK) { + status = osMessageQueuePut(env->txDataQueue, dataCan, 0x0, 0U); +// osMutexRelease(env->access); +// } + + return status; +} + +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) { + + osStatus_t status; + + while (AtCmdReceiveNextLine(&env->At, SystemWaitForever) == AT_OK) { + + if (AtCmdRxBeginWithStatic(&env->At, "T")) { + + uint8_t data[8]; + + uint8_t size = iAsciiStringParseHexBytes(data, &env->At.rxBuffer.data[1], 2); + uint8_t opt = data[0]; + + size = iAsciiStringParseHexBytes(data, &env->At.rxBuffer.data[3], 2); + uint8_t remote = data[0]; + + size = iAsciiStringParseHexBytes(data, &env->At.rxBuffer.data[5], 4); + uint32_t adr = (data[0] << 8) | data[1]; + + uint8_t len = &env->At.rxBuffer.data[env->At.rxBuffer.len] - &env->At.rxBuffer.data[9] - 2; + + if (len > 16) { + len = 16; + } + + size = iAsciiStringParseHexBytes(data, &env->At.rxBuffer.data[9], len); + + + 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) { + + status = PutQueueCanSpontany(env->TaskSerialToCanSpontany, &dataCan); + + } else { + + uint32_t count0 = GetCountQueueCanCyclic0(env->TaskSerialToCanCyclic0); + uint32_t count1 = GetCountQueueCanCyclic1(env->TaskSerialToCanCyclic1); + + if (count0 <= count1) { + status = PutQueueCanCyclic0(env->TaskSerialToCanCyclic0, &dataCan.can_rx_message); + } else { + status = PutQueueCanCyclic1(env->TaskSerialToCanCyclic1, &dataCan.can_rx_message); + } + } + } + + if (AtCmdRxBeginWithStatic(&env->At, "t")) { + + uint8_t data[8]; + //uint32_t adr = iAsciiStringParseUnsignedLongDecimalNumber(&env->At.rxBuffer.data[1], + // &env->At.rxBuffer.data[9]); + + 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; + + if (len > 16) { + len = 16; + } + + size = iAsciiStringParseHexBytes(data, &env->At.rxBuffer.data[9], len); + + 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) { + + status = PutQueueCanSpontany(env->TaskSerialToCanSpontany, &dataCan); + + } else { + + uint32_t count0 = GetCountQueueCanCyclic0(env->TaskSerialToCanCyclic0); + uint32_t count1 = GetCountQueueCanCyclic1(env->TaskSerialToCanCyclic1); + + if (count0 <= count1) { + status = PutQueueCanCyclic0(env->TaskSerialToCanCyclic0, &dataCan.can_rx_message); + } else { + status = PutQueueCanCyclic1(env->TaskSerialToCanCyclic1, &dataCan.can_rx_message); + } + } + } + + if (AtCmdRxBeginWithStatic(&env->At, "V")) { + env->ioUART->transmit(env->ioUART->env, (uint8_t *) "v001\r\n", sizeof("v001\r\n") - 1, 1000); + env->ioUART->transmit(env->ioUART->env, (uint8_t *) "OK\r\n", sizeof("OK\r\n") - 1, 1000); + } + } + +} + +//конец ------------------------------Парсер команд-------------------------------------------------------------------- +//конец ------------------------------Парсер команд-------------------------------------------------------------------- +//конец ------------------------------Парсер команд-------------------------------------------------------------------- + + + +//начало ------------------------------Обработчик UART команд----------------------------------------------------------- +//начало ------------------------------Обработчик UART команд----------------------------------------------------------- +//начало ------------------------------Обработчик UART команд----------------------------------------------------------- + +void TaskSerialUART_Init(tTaskSerial *env, + tFrom_uart from_uart, + tSerialPortIO *ioUART, + tTaskSerialToCanCyclic *TaskSerialToCanCyclic0, + tTaskSerialToCanCyclic *TaskSerialToCanCyclic1, + tTaskSerialToCanSpontany *TaskSerialToCanSpontany + +) { + +// env->access = osMutexNew(NULL); + env->from_uart = from_uart; + + env->ioUART = ioUART; + + env->TaskSerialToCanCyclic0 = TaskSerialToCanCyclic0; + env->TaskSerialToCanCyclic1 = TaskSerialToCanCyclic1; + env->TaskSerialToCanSpontany = TaskSerialToCanSpontany; + + SerialPortClearRxBuffer(env->ioUART); + + AtCmdInit( + &env->At, env->ioUART, + env->AtRx, sizeof(env->AtRx), + env->AtTx, sizeof(env->AtTx), + 2000, 2000 + ); + + InitThreadAtrStatic(&env->thread.attr, "SerialUART", env->thread.controlBlock, env->thread.stack, osPriorityNormal); +} + + +static _Noreturn void Serial_UART_Thread(tTaskSerial *env) { + for (;;) { + +// if (osMutexAcquire(env->access, 1000) == osOK) { + + SerialCommand_Scheduler(env); + +// osMutexRelease(env->access); +// } + + SystemDelayMs(1); + } +} + +void TaskSerialUART_StartThread(tTaskSerial *env) { + if (!env->thread.id) { + env->thread.id = osThreadNew((osThreadFunc_t) (Serial_UART_Thread), (void *) (env), &env->thread.attr); + } +} + +//конец ------------------------------Обработчик UART команд----------------------------------------------------------- +//конец ------------------------------Обработчик UART команд----------------------------------------------------------- +//конец ------------------------------Обработчик UART команд----------------------------------------------------------- + + +//начало ------------------------------Обработчик UART USB команд------------------------------------------------------- +//начало ------------------------------Обработчик UART USB команд------------------------------------------------------- +//начало ------------------------------Обработчик UART USB команд------------------------------------------------------- + +void TaskSerialUSB_Init(tTaskSerial *env, + tFrom_uart from_uart, + tSerialPortIO *ioUART, + tTaskSerialToCanCyclic *TaskSerialToCanCyclic0, + tTaskSerialToCanCyclic *TaskSerialToCanCyclic1, + tTaskSerialToCanSpontany *TaskSerialToCanSpontany +) { + +// env->access = osMutexNew(NULL); + env->from_uart = from_uart; + + env->ioUART = ioUART; + + env->TaskSerialToCanCyclic0 = TaskSerialToCanCyclic0; + env->TaskSerialToCanCyclic1 = TaskSerialToCanCyclic1; + env->TaskSerialToCanSpontany = TaskSerialToCanSpontany; + + SerialPortClearRxBuffer(env->ioUART); + + AtCmdInit( + &env->At, env->ioUART, + env->AtRx, sizeof(env->AtRx), + env->AtTx, sizeof(env->AtTx), + 2000, 2000 + ); + + InitThreadAtrStatic(&env->thread.attr, "SerialUSB", env->thread.controlBlock, env->thread.stack, osPriorityNormal); +} + + +static _Noreturn void Serial_USB_Thread(tTaskSerial *env) { + for (;;) { + +// if (osMutexAcquire(env->access, 1000) == osOK) { + + SerialCommand_Scheduler(env); + +// osMutexRelease(env->access); +// } + + SystemDelayMs(1); + } +} + +void TaskSerialUSB_StartThread(tTaskSerial *env) { + if (!env->thread.id) { + env->thread.id = osThreadNew((osThreadFunc_t) (Serial_USB_Thread), (void *) (env), &env->thread.attr); + } +} + +//конец ------------------------------Обработчик UART USB команд------------------------------------------------------- +//конец ------------------------------Обработчик UART USB команд------------------------------------------------------- +//конец ------------------------------Обработчик UART USB команд------------------------------------------------------- \ No newline at end of file diff --git a/ArbiterCommand.h b/ArbiterCommand.h new file mode 100644 index 0000000..cc78893 --- /dev/null +++ b/ArbiterCommand.h @@ -0,0 +1,127 @@ +// +// Created by cfif on 13.03.2026. +// + +#ifndef HVAC_DEV_ARBITERCOMMAND_H +#define HVAC_DEV_ARBITERCOMMAND_H + +#include +#include "SerialPortIO.h" +#include "AtCmdCommon.h" +#include "CanSerialPortFrame.h" + + +typedef enum { + FROM_UART, + FROM_UART_USB +} tFrom_uart; + +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; + tFrom_uart from_uart; +} can_rx_message_Spontany; + +typedef struct { + + tSerialPortFrameIO *ioCAN; +// osMutexId_t access; + osMessageQueueId_t txDataQueue; + + tSerialPortIO *ioUART; + tSerialPortIO *ioUSB; + + struct { + osThreadId_t id; + uint32_t stack[1024]; + StaticTask_t controlBlock; + osThreadAttr_t attr; + } thread; + + +} tTaskSerialToCanSpontany; + +typedef struct { + + tAtCmd At; + uint8_t AtRx[255]; + uint8_t AtTx[255]; + + tSerialPortIO *ioUART; + tFrom_uart from_uart; +// osMutexId_t access; + + tTaskSerialToCanCyclic *TaskSerialToCanCyclic0; + tTaskSerialToCanCyclic *TaskSerialToCanCyclic1; + tTaskSerialToCanSpontany *TaskSerialToCanSpontany; + + struct { + osThreadId_t id; + uint32_t stack[1024]; + StaticTask_t controlBlock; + osThreadAttr_t attr; + } thread; + + +} tTaskSerial; + + +void TaskSerialUART_Init(tTaskSerial *env, + tFrom_uart from_uart, + tSerialPortIO *ioUART, + tTaskSerialToCanCyclic *TaskSerialToCanCyclic0, + tTaskSerialToCanCyclic *TaskSerialToCanCyclic1, + tTaskSerialToCanSpontany *TaskSerialToCanSpontany +); + +void TaskSerialUART_StartThread(tTaskSerial *env); + +void TaskSerialUSB_Init(tTaskSerial *env, + tFrom_uart from_uart, + tSerialPortIO *ioUART, + tTaskSerialToCanCyclic *TaskSerialToCanCyclic0, + tTaskSerialToCanCyclic *TaskSerialToCanCyclic1, + tTaskSerialToCanSpontany *TaskSerialToCanSpontany + +); + +void TaskSerialUSB_StartThread(tTaskSerial *env); + + +void TaskSerialToCanCyclic0_Init(tTaskSerialToCanCyclic *env, + tSerialPortFrameIO *ioCAN +); + +void TaskSerialToCanCyclic0_StartThread(tTaskSerialToCanCyclic *env); + + +void TaskSerialToCanCyclic1_Init(tTaskSerialToCanCyclic *env, + tSerialPortFrameIO *ioCAN); + +void TaskSerialToCanCyclic1_StartThread(tTaskSerialToCanCyclic *env); + +void TaskSerialToCanSpontany_Init(tTaskSerialToCanSpontany *env, + tSerialPortFrameIO *ioCAN, + tSerialPortIO *ioUART, + tSerialPortIO *ioUSB + +); + +void TaskSerialToCanSpontany_StartThread(tTaskSerialToCanSpontany *env); + +#endif //HVAC_DEV_ARBITERCOMMAND_H diff --git a/modular.json b/modular.json new file mode 100644 index 0000000..0dd1901 --- /dev/null +++ b/modular.json @@ -0,0 +1,10 @@ +{ + "cmake": { + "inc_dirs": [ + "./" + ], + "srcs": [ + "./**.c" + ] + } +} \ No newline at end of file