192 lines
6.3 KiB
C
192 lines
6.3 KiB
C
#include "serial_control.h"
|
|
#include "usart.h"
|
|
#include "charger_gbt.h"
|
|
#include "edcan_config.h"
|
|
#include "string.h"
|
|
|
|
static uint32_t calculate_crc32(const uint8_t *data, uint16_t length);
|
|
static uint16_t encode_packet(const uint8_t *payload, uint16_t payload_len, uint8_t *output, uint8_t response_code);
|
|
static uint8_t parse_packet(const uint8_t *packet_data, uint16_t packet_len, ReceivedCommand_t *out_cmd);
|
|
static uint8_t process_received_packet(SerialControl_t *ctx, const uint8_t *packet_data, uint16_t packet_len);
|
|
static void SC_ArmUart2Rx(void);
|
|
|
|
SerialControl_t serial_control;
|
|
static SerialControl_t serial_iso;
|
|
volatile SC_Source_t g_sc_command_source = SC_SOURCE_UART2;
|
|
|
|
GBT_MonitorPacket_t gbtMonitorPacket = {
|
|
.connector_type = 0x01,
|
|
};
|
|
|
|
CCS_MonitorPacket_t ccsMonitorPacket = {
|
|
.connector_type = 0x02,
|
|
};
|
|
|
|
InfoPacket_t infoPacket = {
|
|
.serialNumber = 0,
|
|
.boardVersion = 0,
|
|
.stationType = 0,
|
|
.fw_version_major = 0,
|
|
.fw_version_minor = 0,
|
|
.fw_version_patch = 0,
|
|
};
|
|
|
|
void SC_Init(void) {
|
|
memset(&serial_control, 0, sizeof(serial_control));
|
|
memset(&serial_iso, 0, sizeof(serial_iso));
|
|
}
|
|
|
|
void SC_Task(void) {
|
|
SC_ArmUart2Rx();
|
|
if ((&huart5)->RxState == HAL_UART_STATE_READY) {
|
|
(void)HAL_UARTEx_ReceiveToIdle_IT(&huart5, serial_iso.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
|
|
}
|
|
|
|
if (huart2.gState == HAL_UART_STATE_BUSY_TX && serial_control.tx_tick != 0U) {
|
|
if ((HAL_GetTick() - serial_control.tx_tick) > 100U) {
|
|
HAL_UART_Abort_IT(&huart2);
|
|
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
|
|
serial_control.tx_tick = 0U;
|
|
}
|
|
}
|
|
|
|
if (serial_control.command_ready && (huart2.gState != HAL_UART_STATE_BUSY_TX)) {
|
|
SC_CommandHandler((ReceivedCommand_t *)&serial_control.received_command);
|
|
serial_control.command_ready = 0U;
|
|
SC_ArmUart2Rx();
|
|
}
|
|
|
|
if (serial_control.response_pending && (huart2.gState != HAL_UART_STATE_BUSY_TX)) {
|
|
SC_SendPacket(NULL, 0, serial_control.response_code);
|
|
serial_control.response_pending = 0U;
|
|
}
|
|
}
|
|
|
|
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) {
|
|
if (huart->Instance == huart2.Instance) {
|
|
if (!process_received_packet(&serial_control, serial_control.rx_buffer, Size)) {
|
|
serial_control.response_pending = 1U;
|
|
serial_control.response_code = RESP_INVALID;
|
|
SC_ArmUart2Rx();
|
|
} else {
|
|
g_sc_command_source = SC_SOURCE_UART2;
|
|
}
|
|
} else if (huart->Instance == huart5.Instance) {
|
|
if (process_received_packet(&serial_iso, serial_iso.rx_buffer, Size)) {
|
|
g_sc_command_source = SC_SOURCE_UART5;
|
|
SC_CommandHandler((ReceivedCommand_t *)&serial_iso.received_command);
|
|
}
|
|
(void)HAL_UARTEx_ReceiveToIdle_IT(&huart5, serial_iso.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
|
|
}
|
|
}
|
|
|
|
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) {
|
|
if (huart->Instance == huart2.Instance) {
|
|
SC_ArmUart2Rx();
|
|
}
|
|
}
|
|
|
|
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
|
|
if (huart->Instance == huart2.Instance) {
|
|
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
|
|
serial_control.tx_tick = 0U;
|
|
}
|
|
}
|
|
|
|
static void SC_ArmUart2Rx(void) {
|
|
if ((&huart2)->RxState == HAL_UART_STATE_READY && serial_control.command_ready == 0U) {
|
|
(void)HAL_UARTEx_ReceiveToIdle_IT(&huart2, serial_control.rx_buffer, MAX_RX_BUFFER_SIZE - 1);
|
|
}
|
|
}
|
|
|
|
static uint32_t calculate_crc32(const uint8_t *data, uint16_t length) {
|
|
uint32_t crc = 0xFFFFFFFFu;
|
|
|
|
for (uint16_t i = 0; i < length; i++) {
|
|
crc ^= data[i];
|
|
for (uint8_t bit = 0; bit < 8; bit++) {
|
|
if (crc & 0x1u) {
|
|
crc = (crc >> 1) ^ CRC32_POLYNOMIAL;
|
|
} else {
|
|
crc >>= 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
return crc ^ 0xFFFFFFFFu;
|
|
}
|
|
|
|
static uint16_t encode_packet(const uint8_t *payload, uint16_t payload_len, uint8_t *output, uint8_t response_code) {
|
|
uint16_t out_index = 0;
|
|
|
|
output[out_index++] = response_code;
|
|
|
|
if (payload != NULL) {
|
|
for (uint16_t i = 0; i < payload_len; i++) {
|
|
output[out_index++] = payload[i];
|
|
if (out_index >= MAX_TX_BUFFER_SIZE - 5) {
|
|
return 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
uint32_t crc = calculate_crc32(output, out_index);
|
|
uint8_t *crc_bytes = (uint8_t *)&crc;
|
|
|
|
for (uint8_t i = 0; i < 4; i++) {
|
|
output[out_index++] = crc_bytes[i];
|
|
if (out_index >= MAX_TX_BUFFER_SIZE - 1) {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
return out_index;
|
|
}
|
|
|
|
void SC_SendPacket(const uint8_t *payload, uint16_t payload_len, uint8_t response_code) {
|
|
uint16_t packet_len = encode_packet(payload, payload_len, serial_control.tx_buffer, response_code);
|
|
|
|
if (packet_len > 0U) {
|
|
if (huart2.gState == HAL_UART_STATE_BUSY_TX) {
|
|
HAL_UART_Abort_IT(&huart2);
|
|
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_RESET);
|
|
}
|
|
|
|
HAL_GPIO_WritePin(USART2_DIR_GPIO_Port, USART2_DIR_Pin, GPIO_PIN_SET);
|
|
HAL_UART_Transmit_IT(&huart2, serial_control.tx_buffer, packet_len);
|
|
serial_control.tx_tick = HAL_GetTick();
|
|
}
|
|
}
|
|
|
|
static uint8_t parse_packet(const uint8_t *packet_data, uint16_t packet_len, ReceivedCommand_t *out_cmd) {
|
|
if (packet_len < 5U || packet_len > MAX_RX_BUFFER_SIZE) {
|
|
return 0U;
|
|
}
|
|
|
|
uint16_t payload_length = packet_len - 4U;
|
|
uint32_t received_checksum =
|
|
((uint32_t)packet_data[payload_length] << 0) |
|
|
((uint32_t)packet_data[payload_length + 1U] << 8) |
|
|
((uint32_t)packet_data[payload_length + 2U] << 16) |
|
|
((uint32_t)packet_data[payload_length + 3U] << 24);
|
|
|
|
uint32_t calculated_checksum = calculate_crc32(packet_data, payload_length);
|
|
if (received_checksum != calculated_checksum) {
|
|
return 0U;
|
|
}
|
|
|
|
out_cmd->command = packet_data[0];
|
|
out_cmd->argument = (void *)&packet_data[1];
|
|
out_cmd->argument_length = (uint8_t)(payload_length - 1U);
|
|
return 1U;
|
|
}
|
|
|
|
static uint8_t process_received_packet(SerialControl_t *ctx, const uint8_t *packet_data, uint16_t packet_len) {
|
|
if (!parse_packet(packet_data, packet_len, (ReceivedCommand_t *)&ctx->received_command)) {
|
|
return 0U;
|
|
}
|
|
|
|
ctx->command_ready = 1U;
|
|
return 1U;
|
|
}
|