CAN status and tasks stuff#13
Conversation
There was a problem hiding this comment.
Code Review
This pull request modularizes the Power Distribution Unit (PDU) Mk1 firmware by splitting tasks into dedicated files under tasks/ and adding test suites under test/, alongside introducing CAN status transmission. Several critical issues were identified in the review: FreeRTOS task functions must be updated to accept a void * parameter to match the expected prototype and avoid undefined behavior; an unaligned memory access in Task_CANSendStatus.c should be resolved using byte shifting; and the hfdcan3 pointer must be properly declared/initialized before dereferencing. Additionally, non-standard emojis in macro names should be replaced with ASCII, copy-paste task names in tests should be corrected, and a redundant loop around Error_Handler() should be cleaned up.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| void Task_ReadCurrents() | ||
| { |
There was a problem hiding this comment.
FreeRTOS task functions must match the TaskFunction_t prototype, which is defined as void (*)(void *). Defining a task function with no parameters (i.e., void Task_Name(void)) and passing it to xTaskCreateStatic results in a function pointer signature mismatch, which is undefined behavior in C and can lead to stack corruption or register mismatches depending on the compiler and calling convention. Please update the signature to accept a void * parameter.
| void Task_ReadCurrents() | |
| { | |
| void Task_ReadCurrents(void *argument) | |
| { |
| void Task_CanSendStatus() | ||
| { |
There was a problem hiding this comment.
FreeRTOS task functions must match the TaskFunction_t prototype, which is defined as void (*)(void *). Defining a task function with no parameters (i.e., void Task_Name(void)) and passing it to xTaskCreateStatic results in a function pointer signature mismatch, which is undefined behavior in C and can lead to stack corruption or register mismatches depending on the compiler and calling convention. Please update the signature to accept a void * parameter.
void Task_CanSendStatus(void *argument)
{| *((uint16_t*) (ch_data+PDU_MK1_CAN_PDUSTATUS_VOLTAGE_INDEX)) = ((uint16_t) (0)); // no voltage data yet | ||
| *((uint16_t*) (ch_data+PDU_MK1_CAN_PDUSTATUS_CURRENT_INDEX)) = ((uint16_t) (PDU_Mk1_CurrentSensing_GetCurrentsPtr()[ch_to_send]*PDU_MK1_CAN_PDUSTATUS_CURRENT_INVFACTOR)); |
There was a problem hiding this comment.
Casting ch_data + PDU_MK1_CAN_PDUSTATUS_CURRENT_INDEX (which resolves to an odd address, 3) to a uint16_t* and dereferencing it performs an unaligned memory access. On some ARM Cortex-M processors, this can trigger a HardFault. Furthermore, it violates strict aliasing rules in C, which can lead to undefined compiler optimizations. A safer, portable, and standard-compliant approach is to use byte shifting to serialize the 16-bit values into the byte array.
uint16_t voltage = 0;
ch_data[PDU_MK1_CAN_PDUSTATUS_VOLTAGE_INDEX] = voltage & 0xFF;
ch_data[PDU_MK1_CAN_PDUSTATUS_VOLTAGE_INDEX + 1] = (voltage >> 8) & 0xFF;
uint16_t current = (uint16_t)(PDU_Mk1_CurrentSensing_GetCurrentsPtr()[ch_to_send] * PDU_MK1_CAN_PDUSTATUS_CURRENT_INVFACTOR);
ch_data[PDU_MK1_CAN_PDUSTATUS_CURRENT_INDEX] = current & 0xFF;
ch_data[PDU_MK1_CAN_PDUSTATUS_CURRENT_INDEX + 1] = (current >> 8) & 0xFF;| void Task_HSSControl() | ||
| { |
There was a problem hiding this comment.
FreeRTOS task functions must match the TaskFunction_t prototype, which is defined as void (*)(void *). Defining a task function with no parameters (i.e., void Task_Name(void)) and passing it to xTaskCreateStatic results in a function pointer signature mismatch, which is undefined behavior in C and can lead to stack corruption or register mismatches depending on the compiler and calling convention. Please update the signature to accept a void * parameter.
| void Task_HSSControl() | |
| { | |
| void Task_HSSControl(void *argument) | |
| { |
| void Task_Init() | ||
| { |
There was a problem hiding this comment.
FreeRTOS task functions must match the TaskFunction_t prototype, which is defined as void (*)(void *). Defining a task function with no parameters (i.e., void Task_Name(void)) and passing it to xTaskCreateStatic results in a function pointer signature mismatch, which is undefined behavior in C and can lead to stack corruption or register mismatches depending on the compiler and calling convention. Please update the signature to accept a void * parameter.
| void Task_Init() | |
| { | |
| void Task_Init(void *argument) | |
| { |
| if (can_fd_send(hfdcan3, &tx_header, ch_data, portMAX_DELAY) != CAN_OK){ | ||
| while(1) | ||
| { | ||
| printf("ERROR:CAN_SEND_PDUSTATUS\n"); | ||
| Error_Handler(); | ||
| } | ||
| } |
There was a problem hiding this comment.
The while(1) loop around Error_Handler() is redundant because Error_Handler() already contains an infinite loop and never returns. Simplifying this block improves code readability.
if (can_fd_send(hfdcan3, &tx_header, ch_data, portMAX_DELAY) != CAN_OK){
printf("ERROR:CAN_SEND_PDUSTATUS\n");
Error_Handler();
}| task_hsscontrol = xTaskCreateStatic(Task_HSSControl, | ||
| "Current Sense Task", |
There was a problem hiding this comment.
The task name is set to "Current Sense Task", but the task function being created is Task_HSSControl. This copy-paste error can make debugging and task monitoring confusing when using FreeRTOS tools. Please update the task name to "HSS Control Task".
task_hsscontrol = xTaskCreateStatic(Task_HSSControl,
"HSS Control Task",| task_hsscontrol = xTaskCreateStatic(Task_HSSControl, | ||
| "Current Sense Task", |
There was a problem hiding this comment.
The task name is set to "Current Sense Task", but the task function being created is Task_HSSControl. This copy-paste error can make debugging and task monitoring confusing when using FreeRTOS tools. Please update the task name to "HSS Control Task".
task_hsscontrol = xTaskCreateStatic(Task_HSSControl,
"HSS Control Task",| hfdcan3->Instance = FDCAN3; | ||
| hfdcan3->Init.ClockDivider = FDCAN_CLOCK_DIV1; | ||
| hfdcan3->Init.FrameFormat = FDCAN_FRAME_CLASSIC; | ||
| hfdcan3->Init.Mode = FDCAN_MODE_EXTERNAL_LOOPBACK; |
There was a problem hiding this comment.
FDCAN_MODE_NORMAL?
|
|
||
| // DEFINES -------------------------------------------------------------------- | ||
|
|
||
| #define TASK_CANSENDSTATUS_STACK_SIZE configMINIMAL_STACK_SIZE+3000 |
There was a problem hiding this comment.
Maybe see if CAN make less f a t?
|
|
||
| // DEFINES -------------------------------------------------------------------- | ||
|
|
||
| #define TASK_INIT_STACK_SIZE configMINIMAL_STACK_SIZE+5000 |
There was a problem hiding this comment.
Oops remove file for now
|
|
||
| // DEFINES -------------------------------------------------------------------- | ||
|
|
||
| #define TASK_READCURRENTS_STACK_SIZE configMINIMAL_STACK_SIZE+3000 |
| } | ||
| } | ||
|
|
||
|
|
There was a problem hiding this comment.
Remove extra line.
|
|
||
| vTaskDelay(pdMS_TO_TICKS(TASK_HSSCONTROL_INTERVAL_MS)); | ||
| } | ||
| } No newline at end of file |
There was a problem hiding this comment.
Add blank line.
| PDU_Mk1_StartTasks(); | ||
| // task kills itself | ||
| vTaskDelete(NULL); | ||
| } No newline at end of file |
There was a problem hiding this comment.
Add blank line.
There was a problem hiding this comment.
Oops remove file for now
No description provided.