From ab8b68313bcdbb165762f8c8d05b1b10bbcfae66 Mon Sep 17 00:00:00 2001 From: Erick Ahmed Date: Mon, 15 Jun 2026 14:06:15 +0200 Subject: [PATCH 1/7] Transition from timer based to task based LED signal - Remove RTOS timers - Create LED task - Avoid polling, instead wait for semaphore --- Core/Inc/canlog.h | 1 - Core/Src/canlog.c | 46 ++++++++++++++++++++-------------------------- Core/Src/main.c | 42 ++++++++++++++++++++---------------------- 3 files changed, 40 insertions(+), 49 deletions(-) diff --git a/Core/Inc/canlog.h b/Core/Inc/canlog.h index d741aff..72ea736 100644 --- a/Core/Inc/canlog.h +++ b/Core/Inc/canlog.h @@ -45,7 +45,6 @@ typedef struct { typedef struct { LED_Config *led; osSemaphoreId_t semaphore; - osTimerId_t timer; } LEDContext; /* USER CODE END PTD */ diff --git a/Core/Src/canlog.c b/Core/Src/canlog.c index 45b2935..94fc414 100644 --- a/Core/Src/canlog.c +++ b/Core/Src/canlog.c @@ -97,23 +97,21 @@ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) */ void vCANLoggerListen(void *argument) { - /* CODE BEGIN */ - CAN_HandleTypeDef *hcan = (CAN_HandleTypeDef*)argument; - osMessageQueueId_t queue; + /* CODE BEGIN */ + CAN_HandleTypeDef *hcan = (CAN_HandleTypeDef*)argument; + osMessageQueueId_t queue; CanMessage_t message; - queue = (hcan->Instance == CAN1) ? xCAN1RxQueue : xCAN2RxQueue; + queue = (hcan->Instance == CAN1) ? xCAN1RxQueue : xCAN2RxQueue; - for (;;) - { - if (osMessageQueueGet(queue, &message, NULL, osWaitForever) == osOK) - { - osSemaphoreRelease( (hcan->Instance == CAN1) ? xSemaphoreCAN1 : xSemaphoreCAN2 ); - // TODO: use this semaphore - } - - } - /* CODE END */ + for (;;) + { + if (osMessageQueueGet(queue, &message, NULL, osWaitForever) == osOK) + { + osSemaphoreRelease( (hcan->Instance == CAN1) ? xSemaphoreCAN1 : xSemaphoreCAN2 ); + } + } + /* CODE END */ } /* END vCANLoggerListen */ @@ -125,19 +123,15 @@ void vCANLoggerListen(void *argument) */ void vLEDHeartbeat(void *argument) { - /* CODE BEGIN */ - LEDContext *context = (LEDContext*)argument; + /* CODE BEGIN */ + LEDContext *context = (LEDContext*)argument; - if (osSemaphoreAcquire(context->semaphore, 0U) == osOK) - { - HAL_GPIO_WritePin(context->led->port, context->led->pin, GPIO_PIN_SET); - osTimerStart(context->timer, 25U); - } - else - { - HAL_GPIO_WritePin(context->led->port, context->led->pin, GPIO_PIN_RESET); - } - /* CODE END */ + for (;;) + { + if (osSemaphoreAcquire(context->semaphore, 25U) == osOK) HAL_GPIO_WritePin(context->led->port, context->led->pin, GPIO_PIN_SET); + else HAL_GPIO_WritePin(context->led->port, context->led->pin, GPIO_PIN_RESET); + } + /* CODE END */ } /* END vLEDHeartbeat */ /* USER CODE END FunctionPrototypes */ diff --git a/Core/Src/main.c b/Core/Src/main.c index ff7bb39..3f926a9 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -55,9 +55,6 @@ LEDContext ledContextCAN2; osSemaphoreId_t xSemaphoreCAN1; osSemaphoreId_t xSemaphoreCAN2; -osTimerId_t xHeartbeatTimerCAN1; -osTimerId_t xHeartbeatTimerCAN2; - osMessageQueueId_t xCAN1RxQueue; osMessageQueueId_t xCAN2RxQueue; /* USER CODE END PV */ @@ -126,12 +123,27 @@ int main(void) .stack_size = 128 * 4, .priority = (osPriority_t) osPriorityRealtime1, }; + osThreadId_t xCAN2rx; const osThreadAttr_t CAN2rxAttributes = { .name = "CAN2rx", .stack_size = 128 * 4, .priority = (osPriority_t) osPriorityRealtime, }; + + osThreadId_t xLEDHeartbeatCAN1; + const osThreadAttr_t LEDHeartbeatCAN1Attributes = { + .name = "LED_HB_CAN1", + .stack_size = 128 * 4, + .priority = (osPriority_t) osPriorityVeryLow1, + }; + + osThreadId_t xLEDHeartbeatCAN2; + const osThreadAttr_t LEDHeartbeatCAN2Attributes = { + .name = "LED_HB_CAN2", + .stack_size = 128 * 4, + .priority = (osPriority_t) osPriorityVeryLow, + }; /* USER END RTOS_TASKS */ /* USER CODE BEGIN RTOS_MUTEX */ @@ -139,8 +151,8 @@ int main(void) /* USER CODE END RTOS_MUTEX */ /* USER CODE BEGIN RTOS_SEMAPHORES */ - xSemaphoreCAN1 = osSemaphoreNew(10, 0, NULL); - xSemaphoreCAN2 = osSemaphoreNew(10, 0, NULL); + xSemaphoreCAN1 = osSemaphoreNew(32, 0, NULL); + xSemaphoreCAN2 = osSemaphoreNew(32, 0, NULL); if (xSemaphoreCAN1 == NULL || xSemaphoreCAN2 == NULL) Error_Handler(); @@ -151,21 +163,14 @@ int main(void) /* USER CODE END RTOS_SEMAPHORES */ /* USER CODE BEGIN RTOS_TIMERS */ - xHeartbeatTimerCAN1 = osTimerNew(vLEDHeartbeat, osTimerOnce, &ledContextCAN1, NULL); - xHeartbeatTimerCAN2 = osTimerNew(vLEDHeartbeat, osTimerOnce, &ledContextCAN2, NULL); - - osTimerStart(xHeartbeatTimerCAN1, 25U); - osTimerStart(xHeartbeatTimerCAN2, 25U); - - if (xHeartbeatTimerCAN1 == NULL || xHeartbeatTimerCAN2 == NULL) Error_Handler(); - - ledContextCAN1.timer = xHeartbeatTimerCAN1; - ledContextCAN2.timer = xHeartbeatTimerCAN2; + /* add timers, ... */ /* USER CODE END RTOS_TIMERS */ /* USER CODE BEGIN RTOS_QUEUES */ xCAN1RxQueue = osMessageQueueNew(32, sizeof(CanMessage_t), NULL); xCAN2RxQueue = osMessageQueueNew(32, sizeof(CanMessage_t), NULL); + xLEDHeartbeatCAN1 = osThreadNew(vLEDHeartbeat, &ledContextCAN1, &LEDHeartbeatCAN1Attributes); + xLEDHeartbeatCAN2 = osThreadNew(vLEDHeartbeat, &ledContextCAN2, &LEDHeartbeatCAN2Attributes); if (xCAN1RxQueue == NULL || xCAN2RxQueue == NULL) Error_Handler(); /* USER CODE END RTOS_QUEUES */ @@ -180,13 +185,6 @@ int main(void) /* USER CODE END RTOS_EVENTS */ /* USER CODE BEGIN 3 */ - ledContextCAN1.led = &led_can1; - ledContextCAN1.semaphore = xSemaphoreCAN1; - ledContextCAN1.timer = xHeartbeatTimerCAN1; - - ledContextCAN2.led = &led_can2; - ledContextCAN2.semaphore = xSemaphoreCAN2; - ledContextCAN2.timer = xHeartbeatTimerCAN2; /* USER CODE END 3 */ /* Start scheduler */ From 8c8fe93d5b9d90882021a7e74744ff93c20b55e3 Mon Sep 17 00:00:00 2001 From: Erick Ahmed Date: Mon, 15 Jun 2026 14:09:51 +0200 Subject: [PATCH 2/7] Release CANrx semaphore in ISR --- Core/Src/canlog.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Core/Src/canlog.c b/Core/Src/canlog.c index 94fc414..e48755c 100644 --- a/Core/Src/canlog.c +++ b/Core/Src/canlog.c @@ -85,6 +85,9 @@ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) // send errors like queue full via UART } + + osSemaphoreId_t semaphore = (hcan->Instance == CAN1) ? xSemaphoreCAN1 : xSemaphoreCAN2; + osSemaphoreRelease(semaphore); /* CODE END */ } /* END HAL_CAN_RxFifo0MsgPendingCallback */ From ce85e473b3f64748a00ce118384f2f5bb524fc3f Mon Sep 17 00:00:00 2001 From: Erick Ahmed Date: Mon, 15 Jun 2026 14:11:11 +0200 Subject: [PATCH 3/7] Move before starting scheduler to avoid race condition - If a CAN message arrives during boot time ISR will fire and try to put data into xCAN1RxQueue. At that time queue is NULL: calling RTOS APIs on NULL handles will cause a HardFault --- Core/Src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Src/main.c b/Core/Src/main.c index 3f926a9..a72f6e6 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -110,7 +110,6 @@ int main(void) MX_SDIO_SD_Init(); /* USER CODE BEGIN 2 */ - CAN_Logger_Init(&hcan1, &hcan2); /* USER CODE END 2 */ /* Init scheduler */ @@ -185,6 +184,7 @@ int main(void) /* USER CODE END RTOS_EVENTS */ /* USER CODE BEGIN 3 */ + CAN_Logger_Init(&hcan1, &hcan2); /* USER CODE END 3 */ /* Start scheduler */ From c1d2e65e207bf7425c101bd428369a0f7481a772 Mon Sep 17 00:00:00 2001 From: Erick Ahmed Date: Mon, 15 Jun 2026 14:12:47 +0200 Subject: [PATCH 4/7] Move to RTOS_THREADS - ops... --- Core/Src/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Core/Src/main.c b/Core/Src/main.c index a72f6e6..c0532bb 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -168,8 +168,6 @@ int main(void) /* USER CODE BEGIN RTOS_QUEUES */ xCAN1RxQueue = osMessageQueueNew(32, sizeof(CanMessage_t), NULL); xCAN2RxQueue = osMessageQueueNew(32, sizeof(CanMessage_t), NULL); - xLEDHeartbeatCAN1 = osThreadNew(vLEDHeartbeat, &ledContextCAN1, &LEDHeartbeatCAN1Attributes); - xLEDHeartbeatCAN2 = osThreadNew(vLEDHeartbeat, &ledContextCAN2, &LEDHeartbeatCAN2Attributes); if (xCAN1RxQueue == NULL || xCAN2RxQueue == NULL) Error_Handler(); /* USER CODE END RTOS_QUEUES */ @@ -177,6 +175,8 @@ int main(void) /* USER CODE BEGIN RTOS_THREADS */ xCAN1rx = osThreadNew(vCANLoggerListen, &hcan1, &CAN1rxAttributes); xCAN2rx = osThreadNew(vCANLoggerListen, &hcan2, &CAN2rxAttributes); + xLEDHeartbeatCAN1 = osThreadNew(vLEDHeartbeat, &ledContextCAN1, &LEDHeartbeatCAN1Attributes); + xLEDHeartbeatCAN2 = osThreadNew(vLEDHeartbeat, &ledContextCAN2, &LEDHeartbeatCAN2Attributes); /* USER CODE END RTOS_THREADS */ /* USER CODE BEGIN RTOS_EVENTS */ From b1744ce941a0da5dd9a30484db8c54ceb4ce3d86 Mon Sep 17 00:00:00 2001 From: Erick Ahmed Date: Mon, 15 Jun 2026 14:17:12 +0200 Subject: [PATCH 5/7] Fix double semaphore release --- Core/Src/canlog.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Core/Src/canlog.c b/Core/Src/canlog.c index e48755c..2a091b0 100644 --- a/Core/Src/canlog.c +++ b/Core/Src/canlog.c @@ -111,7 +111,7 @@ void vCANLoggerListen(void *argument) { if (osMessageQueueGet(queue, &message, NULL, osWaitForever) == osOK) { - osSemaphoreRelease( (hcan->Instance == CAN1) ? xSemaphoreCAN1 : xSemaphoreCAN2 ); + // } } /* CODE END */ From 975acb8c3e1cc49e20df68036fe00bdb35523cbb Mon Sep 17 00:00:00 2001 From: Erick Ahmed Date: Mon, 15 Jun 2026 14:27:05 +0200 Subject: [PATCH 6/7] Indentation fixes --- Core/Src/canlog.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Core/Src/canlog.c b/Core/Src/canlog.c index 2a091b0..94bb578 100644 --- a/Core/Src/canlog.c +++ b/Core/Src/canlog.c @@ -101,19 +101,21 @@ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan) void vCANLoggerListen(void *argument) { /* CODE BEGIN */ - CAN_HandleTypeDef *hcan = (CAN_HandleTypeDef*)argument; - osMessageQueueId_t queue; - CanMessage_t message; + CAN_HandleTypeDef *hcan = (CAN_HandleTypeDef*)argument; + osMessageQueueId_t queue; + CanMessage_t message; - queue = (hcan->Instance == CAN1) ? xCAN1RxQueue : xCAN2RxQueue; + CAN_Logger_Init(&hcan1, &hcan2); - for (;;) + queue = (hcan->Instance == CAN1) ? xCAN1RxQueue : xCAN2RxQueue; + + for (;;) + { + if (osMessageQueueGet(queue, &message, NULL, osWaitForever) == osOK) { - if (osMessageQueueGet(queue, &message, NULL, osWaitForever) == osOK) - { // - } } + } /* CODE END */ } /* END vCANLoggerListen */ From 2c14d095f7ba9f5929abe6ff101c9208489e6fa0 Mon Sep 17 00:00:00 2001 From: Erick Ahmed Date: Mon, 15 Jun 2026 14:30:35 +0200 Subject: [PATCH 7/7] Better way to avoid race condition, only notification lives in CAN task - Runs only once - Only critical notification is inside task - CAN message during boot will not be lost, instead put inside FIFO0 --- Core/Src/canlog.c | 13 ++++--------- Core/Src/main.c | 2 +- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/Core/Src/canlog.c b/Core/Src/canlog.c index 94bb578..b7ebeee 100644 --- a/Core/Src/canlog.c +++ b/Core/Src/canlog.c @@ -47,14 +47,11 @@ void CAN_Logger_Init(CAN_HandleTypeDef *hcan1, CAN_HandleTypeDef *hcan2) filter.FilterBank = 0; if (HAL_CAN_ConfigFilter(hcan1, &filter) != HAL_OK) Error_Handler(); + if (HAL_CAN_Start(hcan1) != HAL_OK) Error_Handler(); + filter.FilterBank = 14; if (HAL_CAN_ConfigFilter(hcan2, &filter) != HAL_OK) Error_Handler(); - - if (HAL_CAN_Start(hcan1) != HAL_OK) Error_Handler(); if (HAL_CAN_Start(hcan2) != HAL_OK) Error_Handler(); - - if (HAL_CAN_ActivateNotification(hcan1, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) Error_Handler(); - if (HAL_CAN_ActivateNotification(hcan2, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) Error_Handler(); } /* END CAN_Logger_Init */ @@ -102,12 +99,10 @@ void vCANLoggerListen(void *argument) { /* CODE BEGIN */ CAN_HandleTypeDef *hcan = (CAN_HandleTypeDef*)argument; - osMessageQueueId_t queue; + osMessageQueueId_t queue = (hcan->Instance == CAN1) ? xCAN1RxQueue : xCAN2RxQueue; CanMessage_t message; - CAN_Logger_Init(&hcan1, &hcan2); - - queue = (hcan->Instance == CAN1) ? xCAN1RxQueue : xCAN2RxQueue; + HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING); for (;;) { diff --git a/Core/Src/main.c b/Core/Src/main.c index c0532bb..d6ac9e5 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -110,6 +110,7 @@ int main(void) MX_SDIO_SD_Init(); /* USER CODE BEGIN 2 */ + CAN_Logger_Init(&hcan1, &hcan2); /* USER CODE END 2 */ /* Init scheduler */ @@ -184,7 +185,6 @@ int main(void) /* USER CODE END RTOS_EVENTS */ /* USER CODE BEGIN 3 */ - CAN_Logger_Init(&hcan1, &hcan2); /* USER CODE END 3 */ /* Start scheduler */