HVAC_DEV_ArbiterCommand/ArbiterCommand.c

474 lines
19 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

//
// 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 команд-------------------------------------------------------