HVAC_DEV_ArbiterCommand/ArbiterCommand.c

524 lines
20 KiB
C
Raw Permalink 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
) {
// 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"), 1000);
} else {
env->ioUART->transmit(env->ioUSB->env, (uint8_t *) "OK\r\n", sizeof("OK\r\n"), 1000);
}
} else {
if (data.from_uart == FROM_UART) {
env->ioUART->transmit(env->ioUART->env, (uint8_t *) "ERROR\r\n", sizeof("ERROR\r\n"), 1000);
} else {
env->ioUART->transmit(env->ioUSB->env, (uint8_t *) "ERROR\r\n", sizeof("ERROR\r\n"), 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"), 1000);
} else {
env->ioUART->transmit(env->ioUSB->env, (uint8_t *) "OK\r\n", sizeof("OK\r\n"), 1000);
}
} else {
if (data.from_uart == FROM_UART) {
env->ioUART->transmit(env->ioUART->env, (uint8_t *) "ERROR\r\n", sizeof("ERROR\r\n"), 1000);
} else {
env->ioUART->transmit(env->ioUSB->env, (uint8_t *) "ERROR\r\n", sizeof("ERROR\r\n"), 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"), 1000);
env->ioUART->transmit(env->ioUART->env, (uint8_t *) "OK\r\n", sizeof("OK\r\n"), 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 команд-------------------------------------------------------