// // 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, 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) { if (AtCmdRxBeginWithStatic(&env->At, "T")) { uint8_t data[8]; //uint32_t adr = iAsciiStringParseUnsignedLongDecimalNumber(&env->At.rxBuffer.data[1], // &env->At.rxBuffer.data[7]); 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]; uint8_t len = &env->At.rxBuffer.data[env->At.rxBuffer.len] - &env->At.rxBuffer.data[7] - 2; if (len > 16) { len = 16; } size = iAsciiStringParseHexBytes(data, &env->At.rxBuffer.data[7], 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) { 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")) { 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) { 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, "V")) { sendVers(&env->At); sendOk(&env->At); } } } //конец ------------------------------Парсер команд-------------------------------------------------------------------- //конец ------------------------------Парсер команд-------------------------------------------------------------------- //конец ------------------------------Парсер команд-------------------------------------------------------------------- //начало ------------------------------Обработчик UART команд----------------------------------------------------------- //начало ------------------------------Обработчик UART команд----------------------------------------------------------- //начало ------------------------------Обработчик UART команд----------------------------------------------------------- void TaskSerialUART_Init(tTaskSerial *env, spontany_from_uart from_uart, tSerialPortIO *ioUART, tSerialPortFrameIO *ioCAN, osMessageQueueId_t txDataQueue_Spontany, osMessageQueueId_t txDataQueue_Cyclic0, osMessageQueueId_t txDataQueue_Cyclic1 ) { env->access = osMutexNew(NULL); 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( &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, spontany_from_uart from_uart, tSerialPortIO *ioUART, tSerialPortFrameIO *ioCAN, osMessageQueueId_t txDataQueue_Spontany, osMessageQueueId_t txDataQueue_Cyclic0, osMessageQueueId_t txDataQueue_Cyclic1 ) { env->access = osMutexNew(NULL); 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( &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 команд-------------------------------------------------------