524 lines
20 KiB
C
524 lines
20 KiB
C
//
|
||
// 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 команд-------------------------------------------------------
|