Csm bringup#233
Conversation
…cation-specific CAN messages. Changed the CAN mode to normal. Waiting to validate whether or not CAN works on the car.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
There was a problem hiding this comment.
Code Review
This pull request introduces the firmware for the Corner Sensor Module (CSM) targeting the STM32G491xx, incorporating drivers for the LSM6DSV32X IMU and AFBR-S50 ride height sensor alongside ADC-based readouts for strain gauges and suspension potentiometers. The system is integrated with FreeRTOS and includes a CAN communication interface. Feedback highlights several critical issues, such as unresolved merge conflict markers in the configuration files and a mismatch in the Bazel build defines. Technical concerns include incorrect voltage calculations for differential ADC inputs, potential race conditions in the ride height driver, and insufficient mutex protection for shared SPI resources. Additionally, the reviewer suggests optimizing IMU burst reads, reducing excessive task stack sizes, and replacing blocking delays with RTOS-aware delays to prevent system hangs.
| @@ -1,4 +1,5 @@ | |||
| { | |||
| <<<<<<< HEAD | |||
|
|
||
| // Read strain gauge | ||
| int32_t strain_raw = strainGaugeGetVal(&hadc1, ADC_CHANNEL_4); | ||
| float strain_voltage = ((float)strain_raw / 4095.0f) * 5000.0f; |
There was a problem hiding this comment.
The strain gauge ADC (ADC1) is configured in differential mode. In this mode on STM32G4, the result is a 12-bit signed value in 2's complement format (ranging from -2048 to 2047). The current calculation treats it as a 12-bit unsigned value (0-4095), which will lead to incorrect voltage readings when the differential input is negative. Additionally, ensure that the raw value is properly sign-extended if necessary.
| return status; | ||
| } | ||
|
|
||
| status_t S2PI_TransferFrame(s2pi_slave_t slave, uint8_t const * txData, uint8_t * rxData, size_t frameSize, s2pi_callback_t callback, void * callbackData) |
There was a problem hiding this comment.
The S2PI_TransferFrame implementation does not appear to use the spi1_mutex defined in spi_mutex.h. Since SPI1 is shared between the IMU and the Ride Height sensor, and the IMU driver uses spi1_mutex, the Ride Height driver must also use the same mutex to prevent bus contention. The current use of myS2PIHnd.SpiMutexBlocked is insufficient as it is independent of the IMU's locking mechanism.
| linker_script = "STM32G491XX_FLASH.ld", | ||
| startup_script = "startup_stm32g491xx.s", | ||
| defines = [ | ||
| "STM32G474xx", |
There was a problem hiding this comment.
| const osThreadAttr_t accelRideHeightTask_attributes = { | ||
| .name = "accelRideHeightTask", | ||
| .priority = (osPriority_t) osPriorityNormal, | ||
| .stack_size = 4096 * 4 |
There was a problem hiding this comment.
| static void imu_read_all_axes(uint8_t reg, uint8_t *buf, uint8_t len) { | ||
| for (uint8_t i = 0; i < len; i++) { | ||
| buf[i] = imu_read(reg + i); | ||
| } | ||
| } |
There was a problem hiding this comment.
The current implementation of imu_read_all_axes performs individual 1-byte SPI reads for each register. This is highly inefficient as it involves multiple mutex acquisitions and CS toggles. The LSM6DSV32X supports auto-incrementing burst reads. You should perform a single SPI transaction to read all 6 bytes of the axis data.
static void imu_read_all_axes(uint8_t reg, uint8_t *buf, uint8_t len) {
osMutexAcquire(spi1_mutex, osWaitForever);
uint8_t tx = reg | 0x80;
IMU_PULL_CS_LOW();
HAL_SPI_Transmit(_hspi, &tx, 1, IMU_TIMEOUT);
HAL_SPI_Receive(_hspi, buf, len, IMU_TIMEOUT);
IMU_PULL_CS_HIGH();
osMutexRelease(spi1_mutex);
}| imu_write(LSM6DSV32X_CTRL2_G, CTRL2_G_CONFIG); // 0x5C: 208Hz ±4000dps | ||
| } | ||
|
|
||
| HAL_Delay(10); |
| xyz_t gyro_reading; | ||
|
|
||
| for (int i = 0; i < CALIBRATION_SAMPLES; i++) { | ||
| while (!IMU_GyroStatus()); |
| } | ||
|
|
||
| float ride_height_get_distance_mm() { | ||
| if (!myDataReadyEvents) { // shouldn't myDataReadyEvents be a boolean value? right now its an 8-bit uint value. also with the change we would also have to change the other code that references it |
There was a problem hiding this comment.
The check if (!myDataReadyEvents) is performed outside of any synchronization mechanism, while the variable is modified in an ISR and decremented under an IRQ lock later. This is a race condition. Although myDataReadyEvents is volatile, the check and subsequent logic should be handled more robustly to ensure atomicity.
|
|
||
| HAL_ADC_ConfigChannel(hadc, &sConfig); | ||
| HAL_ADC_Start(hadc); | ||
| HAL_ADC_PollForConversion(hadc, HAL_MAX_DELAY); |
There was a problem hiding this comment.
Using HAL_MAX_DELAY in HAL_ADC_PollForConversion is risky. If the ADC hardware fails to complete a conversion, the task will hang indefinitely. It is safer to use a reasonable timeout and handle the error case.
| HAL_ADC_PollForConversion(hadc, HAL_MAX_DELAY); | |
| if (HAL_ADC_PollForConversion(hadc, 10) != HAL_OK) return 0; |
Implements firmware for the Corner Sensor Module (CSM) supporting all four corner boards (FL, FR, RL, RR).
Suspension potentiometer (ADC2) — reading
Strain gauge (ADC1 differential) — reading
IMU (LSM6DSV32XTR) — accel and gyro validated, calibration on boot
Ride height sensor (AFBR-S50) — initialized and reading distances
CAN (FDCAN2) — validated on oscilloscope in external loopback mode (before adding the gyro packet)
RGB LED — ride height distance visualized as blue→red gradient
Key Notes
AFBR-S50 requires SPI Mode 3 (CPOL=1, CPHA=1), not Mode 0
IMU and ride height share SPI1 — protected by FreeRTOS mutex in spi_mutex.c
Location-specific CAN IDs handled via BOARD_FL/FR/RL/RR defines from Bazel build system
Gyro packets added to can_packets.csv (0x508-0x50B) and can_ids.h regenerated