15 Commits

Author SHA1 Message Date
eeeck 7f461970f2 Fix allocation on wrong line 2026-06-16 00:58:06 +02:00
eeeck e8ffa4cd05 Fix array bound not integer error 2026-06-16 00:56:32 +02:00
eeeck 498d19fd90 Add queue attributes 2026-06-16 00:56:22 +02:00
eeeck 52b373c82e Put control banks and queue memories into CCRAM 2026-06-16 00:45:32 +02:00
eeeck a9e6bbecba Use private define for queue length 2026-06-16 00:44:34 +02:00
eeeck 92b59615d5 Configure thread attributes to use memory stacks in CCRAM 2026-06-16 00:35:33 +02:00
eeeck d348159c20 Allocate CAN stack arrays into CCMRAM 2026-06-16 00:33:56 +02:00
eeeck b737c27b49 Merge pull request 'Remove complex timer based toggling and switch to RTOS task with semaphore based delay' (#18) from dev-rtos-semaphore into main
Reviewed-on: erickahmed/j1939_logger#18
2026-06-15 14:33:38 +02:00
eeeck 2c14d095f7 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
2026-06-15 14:30:35 +02:00
eeeck 975acb8c3e Indentation fixes 2026-06-15 14:27:05 +02:00
eeeck b1744ce941 Fix double semaphore release 2026-06-15 14:17:12 +02:00
eeeck c1d2e65e20 Move to RTOS_THREADS
- ops...
2026-06-15 14:12:47 +02:00
eeeck ce85e473b3 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
2026-06-15 14:11:11 +02:00
eeeck 8c8fe93d5b Release CANrx semaphore in ISR 2026-06-15 14:09:51 +02:00
eeeck ab8b68313b Transition from timer based to task based LED signal
- Remove RTOS timers
- Create LED task
- Avoid polling, instead wait for semaphore
2026-06-15 14:06:51 +02:00
2 changed files with 65 additions and 33 deletions
+18 -24
View File
@@ -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 */
@@ -85,6 +82,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 */
@@ -98,13 +98,20 @@ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
void vCANLoggerListen(void *argument)
{
/* CODE BEGIN */
LEDContext *context = (LEDContext*)argument;
CAN_HandleTypeDef *hcan = (CAN_HandleTypeDef*)argument;
osMessageQueueId_t queue = (hcan->Instance == CAN1) ? xCAN1RxQueue : xCAN2RxQueue;
CanMessage_t message;
HAL_CAN_ActivateNotification(hcan, CAN_IT_RX_FIFO0_MSG_PENDING);
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 */
if (osMessageQueueGet(queue, &message, NULL, osWaitForever) == osOK)
{
//
}
}
/* CODE END */
}
/* END vCANLoggerListen */
@@ -121,21 +128,8 @@ void vLEDHeartbeat(void *argument)
for (;;)
{
// BLOCK for UP TO 25ms.
// - Returns osOK instantly if CAN traffic arrives.
// - Returns osTimeout if 25ms pass with NO traffic.
if (osSemaphoreAcquire(context->semaphore, 25U) == osOK)
{
// Traffic detected! Turn ON LED.
// Loop immediately to wait for the next message.
HAL_GPIO_WritePin(context->led->port, context->led->pin, GPIO_PIN_SET);
}
else
{
// Timeout! No CAN traffic for 25ms. Turn OFF LED.
// Loop and block again.
HAL_GPIO_WritePin(context->led->port, context->led->pin, GPIO_PIN_RESET);
}
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 */
}
+47 -9
View File
@@ -28,12 +28,28 @@
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define CAN_QUEUE_DEPTH 32
#define CAN_TASK_STACK_WORDS 128
#define CAN_QUEUE_CB_SIZE 128
#define CAN_MSG_SIZE sizeof(CanMessage_t)
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
//CCRAM: stack; control bank; queue memory
__attribute__((section(".ccmram")))
StackType_t xCAN1_Stack[CAN_TASK_STACK_WORDS];
__attribute__((section(".ccmram"), aligned(4)))
uint8_t can1_queue_cb[CAN_QUEUE_CB_SIZE];
__attribute__((section(".ccmram"), aligned(4)))
uint8_t can1_queue_mq[CAN_QUEUE_DEPTH * CAN_MSG_SIZE];
__attribute__((section(".ccmram")))
StackType_t xCAN2_Stack[CAN_TASK_STACK_WORDS];
__attribute__((section(".ccmram"), aligned(4)))
uint8_t can2_queue_cb[CAN_QUEUE_CB_SIZE];
__attribute__((section(".ccmram"), aligned(4)))
uint8_t can2_queue_mq[CAN_QUEUE_DEPTH * CAN_MSG_SIZE];
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
@@ -120,20 +136,26 @@ int main(void)
osThreadId_t xCAN1rx;
const osThreadAttr_t CAN1rxAttributes = {
.name = "CAN1rx",
.stack_size = 128 * 4,
.stack_size = sizeof(xCAN1_Stack),
.priority = (osPriority_t) osPriorityRealtime1,
};
osThreadId_t xCAN2rx;
const osThreadAttr_t CAN2rxAttributes = {
.name = "CAN2rx",
.stack_size = 128 * 4,
.cb_mem = NULL,
.cb_size = 0U,
.stack_mem = xCAN2_Stack,
.stack_size = sizeof(xCAN2_Stack),
.priority = (osPriority_t) osPriorityRealtime,
};
osThreadId_t xLEDHeartbeatCAN1;
const osThreadAttr_t LEDHeartbeatCAN1Attributes = {
.name = "LED_HB_CAN1",
.cb_mem = NULL,
.cb_size = 0U,
.stack_mem = xCAN2_Stack,
.stack_size = 128 * 4,
.priority = (osPriority_t) osPriorityVeryLow1,
};
@@ -151,8 +173,8 @@ int main(void)
/* USER CODE END RTOS_MUTEX */
/* USER CODE BEGIN RTOS_SEMAPHORES */
xSemaphoreCAN1 = osSemaphoreNew(32, 0, NULL);
xSemaphoreCAN2 = osSemaphoreNew(32, 0, NULL);
xSemaphoreCAN1 = osSemaphoreNew(CAN_QUEUE_DEPTH, 0, NULL);
xSemaphoreCAN2 = osSemaphoreNew(CAN_QUEUE_DEPTH, 0, NULL);
if (xSemaphoreCAN1 == NULL || xSemaphoreCAN2 == NULL) Error_Handler();
@@ -167,10 +189,24 @@ int main(void)
/* 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);
const osMessageQueueAttr_t can1_queue_attr = {
.name = "CAN1_Q",
.cb_mem = can1_queue_cb,
.cb_size = sizeof(can1_queue_cb),
.mq_mem = can1_queue_mq,
.mq_size = sizeof(can1_queue_mq)
};
const osMessageQueueAttr_t can2_queue_attr = {
.name = "CAN2_Q",
.cb_mem = can2_queue_cb,
.cb_size = sizeof(can2_queue_cb),
.mq_mem = can2_queue_mq,
.mq_size = sizeof(can2_queue_mq)
};
xCAN1RxQueue = osMessageQueueNew(CAN_QUEUE_DEPTH, sizeof(CanMessage_t), &can1_queue_attr);
xCAN2RxQueue = osMessageQueueNew(CAN_QUEUE_DEPTH, sizeof(CanMessage_t), &can2_queue_attr);
if (xCAN1RxQueue == NULL || xCAN2RxQueue == NULL) Error_Handler();
/* USER CODE END RTOS_QUEUES */
@@ -178,6 +214,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 */