8 Commits

Author SHA1 Message Date
eeeck 74bf4bde77 Implement identical queue drain for CAN2 to that of CAN1 2026-06-16 21:29:32 +02:00
eeeck 3691918196 Non-blocking on CAN1 queue check
- Check queue instantly
- Use DMA to move tx_buffer to UART peripheral
- Use a semaphore to DMA is being done, to avoid moving to next loop
  iteration and overwriting tx_buffer
- HAL_UART_TxCpltCallback will release semaphore when DMA done
2026-06-16 21:27:52 +02:00
eeeck 79f317cec5 Wait until CAN1 or CAN2 save anything to FIFO buffer
- Moving CAN event flag to vCANLoggerListen to avoid possible race
  condition and to make ISR leaner
2026-06-16 21:06:32 +02:00
eeeck da1c13fcb0 Fix comment blocks and function descriptions 2026-06-16 21:02:15 +02:00
eeeck 59274272d3 Remove not useful comment blocks
- Not really used by CubeMX so worth removing
2026-06-16 20:25:21 +02:00
eeeck bc71cd7371 Add comment headers 2026-06-16 20:06:21 +02:00
eeeck 84980d2378 Implement hex converter
- Avoids snprintf
- Can be read from minicom/screen, but it's also friendly for other MCU
- This single function was AI generated
2026-06-16 19:55:44 +02:00
eeeck 8b1b3b7ff3 Implement safe UART semaphore release inside ISR
- It uses safe way to release semaphore
- Yields in case task interrupted was of lower priority: UART has
  minimal latency
2026-06-16 19:49:13 +02:00
3 changed files with 115 additions and 16 deletions
-5
View File
@@ -45,11 +45,6 @@ typedef struct {
} CanMessage_t;
/* USER CODE END PTD */
/**
* @brief Initializes the CAN logger modules, OS threads, queues, and hardware.
* @param hcan1 Pointer to the CAN1 handle
* @param hcan2 Pointer to the CAN2 handle
*/
void CAN_Logger_Init(CAN_HandleTypeDef *hcan1, CAN_HandleTypeDef *hcan2);
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan);
void vCANLoggerListen(void *argument);
+5 -9
View File
@@ -31,10 +31,10 @@ extern osEventFlagsId_t xCanEventFlags;
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
/* BEGIN CAN_Logger_Init */
/**
* @brief Initialize CAN bus logger.
* @param argument: hcan1, hcan2
* @brief Initializes the CAN logger modules, OS threads, queues, and hardware.
* @param hcan1 Pointer to the CAN1 handle
* @param hcan2 Pointer to the CAN2 handle
* @retval None
*/
void CAN_Logger_Init(CAN_HandleTypeDef *hcan1, CAN_HandleTypeDef *hcan2)
@@ -63,12 +63,11 @@ void CAN_Logger_Init(CAN_HandleTypeDef *hcan1, CAN_HandleTypeDef *hcan2)
/* BEGIN HAL_CAN_RxFifo0MsgPendingCallback */
/**
* @brief ISR for CAN message pending in FIFO0
* @param argument: Can handle hcan (hcan1 or hcan2)
* @param hcan: CAN handle hcan (hcan1 or hcan2)
* @retval None
*/
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{
/* CODE BEGIN */
CanMessage_t message;
CAN_RxHeaderTypeDef rxHeader;
uint8_t data[8];
@@ -100,7 +99,6 @@ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
if (osMessageQueuePut(queue, &message, 0U, 0U) == osOK)
{
osEventFlagsSet(xCanEventFlags, flag);
osThreadFlagsSet(led_task, 0x01);
}
else
@@ -121,7 +119,6 @@ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
*/
void vCANLoggerListen(void *argument)
{
/* CODE BEGIN */
CAN_HandleTypeDef *hcan = (CAN_HandleTypeDef*)argument;
osMessageQueueId_t queue = (hcan->Instance == CAN1) ? xCAN1RxQueue : xCAN2RxQueue;
CanMessage_t message;
@@ -132,7 +129,7 @@ void vCANLoggerListen(void *argument)
{
if (osMessageQueueGet(queue, &message, NULL, osWaitForever) == osOK)
{
osEventFlagsSet(xCanEventFlags, flag);
}
}
/* CODE END */
@@ -147,7 +144,6 @@ void vCANLoggerListen(void *argument)
*/
void vLEDHeartbeat(void *argument)
{
/* CODE BEGIN */
LED_Config *led = (LED_Config*)argument;
for (;;)
+110 -2
View File
@@ -20,5 +20,113 @@
#include "cmsis_os.h"
/* USER CODE END Includes */
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart);
void vUARTLogger(void *argument);
/* BEGIN format_can_message */
/**
* @brief Format CAN message for friendly reading on terminal emulators and other MCUs.
* @param arguments: buffer, sourse, message
* @retval None
*/
static void format_can_message(char *buf, uint8_t source, const CanMessage_t *msg)
{
const char hex[] = "0123456789ABCDEF";
buf[0] = 'C';
buf[1] = (source == 1) ? '1' : '2';
buf[2] = ':';
buf[3] = hex[(msg->id >> 28) & 0x0F];
buf[4] = hex[(msg->id >> 24) & 0x0F];
buf[5] = hex[(msg->id >> 20) & 0x0F];
buf[6] = hex[(msg->id >> 16) & 0x0F];
buf[7] = hex[(msg->id >> 12) & 0x0F];
buf[8] = hex[(msg->id >> 8) & 0x0F];
buf[9] = hex[(msg->id >> 4) & 0x0F];
buf[10] = hex[msg->id & 0x0F];
buf[11] = ' ';
buf[12] = hex[(msg->dlc >> 4) & 0x0F];
buf[13] = hex[msg->dlc & 0x0F];
buf[14] = ' ';
int idx = 15;
for (int i = 0; i < 8; i++)
{
if (i < msg->dlc)
{
buf[idx++] = hex[(msg->payload[i] >> 4) & 0x0F];
buf[idx++] = hex[msg->payload[i] & 0x0F];
}
else
{
buf[idx++] = ' ';
buf[idx++] = ' ';
}
if (i < 7) buf[idx++] = ' ';
}
buf[idx++] = '\r';
buf[idx++] = '\n';
}
/* END format_can_message */
/* BEGIN HAL_UART_TxCpltCallback */
/**
* @brief Safely release UART semaphore inside ISR and yield task if possible.
* @param argument: UART handle
* @retval None
*/
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
if (huart->Instance == USART1)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
osSemaphoreReleaseFromISR(xUartDmaSem, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
}
/* END HAL_UART_TxCpltCallback */
/* BEGIN vUARTLoggerListen */
/**
* @brief Send CAN bus traffic saved in FIFO buffer to USART1
* @param argument: Not used
* @retval None
*/
void vUARTLogger(void *argument)
{
CanMessage_t message;
char tx_buffer[45]; // converted extended frame
bool queues_empty;
for (;;)
{
osEventFlagsWait(xCanEventFlags, 0x03, osFlagsWaitAny, osWaitForever);
do
{
queues_empty = true;
if (osMessageQueueGet(xCAN1RxQueue, &message, NULL, 0U) == osOK)
{
format_can_message(tx_buffer, 1, &message);
HAL_UART_Transmit_DMA(&huart1, (uint8_t*)tx_buffer, 44);
osSemaphoreAcquire(xUartDmaSem, osWaitForever);
quesues_empty = false;
}
if (osMessageQueueGet(xCAN2RxQueue, &message, NULL, 0U) == osOK)
{
format_can_message(tx_buffer, 2, &message);
HAL_UART_Transmit_DMA(&huart1, (uint8_t*)tx_buffer, 44);
osSemaphoreAcquire(xUartDmaSem, osWaitForever);
queues_empty = false;
}
}
while (!queues_empty);
}
}
/* END vUARTLoggerListen */