I'm working on a SPI example to learn how to work with SPI on ChibiOS, but it seems to be a problem with it, specifically the clock signal.
Platform: STM32F4xx
Board: NUCLEO64-F401RE (STM32F401RE chip)
ChibiOS version: (github branch: master . Commit: 9d34e55d210c26b669a0ff8f3f32a01b6739a426 (Mar 27, 2025))
Example code is based on: https://github.com/ChibiOS/ChibiOS/tree ... E-NUCLEO64
The idea is to have it work with a sensor module (cheap module named GY-91 that includes a MPU-9250). I have already tested the module with an arduino, confirming that the module works with existing libraries for Arduino.
I have the source code of the main.c-file here: https://gist.github.com/engemil/6c8dcef ... 4056486c9d
Code: Select all
#include "ch.h"
#include "hal.h"
#include "chprintf.h"
#define MPU9250_RW_BIT_READ 0x01
#define MPU9250_RW_BIT_WRITE 0x00
#define MPU9250_WHO_AM_I 0x75
/* NUCLEO64 F401RE board.h file:
* https://github.com/ChibiOS/ChibiOS/blob/master/os/hal/boards/ST_NUCLEO64_F401RE/board.h
*/
#define SPI_MOSI_LINE LINE_ARD_D11
#define SPI_MISO_LINE LINE_ARD_D12
#define SPI_SCLK_LINE LINE_ARD_D13
#define SPI_CS_MPU9250_LINE LINE_ARD_D10
#define SPI_CS_BMP280_LINE LINE_ARD_D9
#define LED_INDICATOR_LINE LINE_LED_GREEN
/*
* Non-circular SPI.
* CR1: CPOL = 0, CPHA = 0, BR = 656,25kHz, Word Size: 8-bit
*/
static SPIConfig spicfg = {
.circular = false, // Non-circular mode
.slave = false, // Master mode
.data_cb = NULL, // No callback
.error_cb = NULL, // No callback
.ssline = SPI_CS_MPU9250_LINE, // Chip Select Pin
.cr1 = SPI_CR1_BR_2 | SPI_CR1_BR_1 | // Prescaler = 128 (for (656,25kHz) ~1MHz at 84 MHz PCLK2)
0, // CPOL = 0, CPHA = 0 (Mode 0), LSBFIRST = 0 (MSB first), SPI_CR1_DFF = 0 (8-bit data frame)
.cr2 = 0 // Default 8-bit data
};
/* Buffer declaration. */
static uint8_t txbuf[2], rxbuf[2];
/* Serial Configuration for Virtual COM Port (USART2) */
static SerialConfig serial_cfg = {
.speed = 115200, // Baud rate
.cr1 = 0, // No parity, 8-bit data (default)
.cr2 = 0, // No specific control settings
.cr3 = 0 // No hardware flow control
};
int main(void) {
/* System initializations. */
halInit();
chSysInit();
/* Configure Serial Driver SD2 (USART2) for Virtual COM Port */
palSetPadMode(GPIOA, GPIOA_USART2_TX, PAL_MODE_ALTERNATE(7) |
PAL_STM32_OSPEED_MID2 |
PAL_STM32_PUPDR_FLOATING |
PAL_STM32_OTYPE_PUSHPULL);
palSetPadMode(GPIOA, GPIOA_USART2_RX, PAL_MODE_ALTERNATE(7) |
PAL_STM32_OSPEED_MID2 |
PAL_STM32_PUPDR_FLOATING |
PAL_STM32_OTYPE_PUSHPULL);
sdStart(&SD2, &serial_cfg); // Start Serial Driver 2
/* Print initial message */
chprintf((BaseSequentialStream*)&SD2, "Starting MPU9250 Test...\r\n");
/* Configuring the GPIOs used by the SPI1. */
palSetLineMode(SPI_CS_MPU9250_LINE, PAL_MODE_OUTPUT_PUSHPULL);
palSetLineMode(SPI_CS_BMP280_LINE, PAL_MODE_OUTPUT_PUSHPULL);
palSetLineMode(SPI_MOSI_LINE, PAL_MODE_ALTERNATE(5) | PAL_STM32_OSPEED_HIGHEST);
palSetLineMode(SPI_MISO_LINE, PAL_MODE_ALTERNATE(5) | PAL_STM32_OSPEED_HIGHEST);
palSetLineMode(SPI_SCLK_LINE, PAL_MODE_ALTERNATE(5) | PAL_STM32_OSPEED_HIGHEST);
/* Configure the board LED Light as digital output push-pull. */
palSetLineMode(LED_INDICATOR_LINE, PAL_MODE_OUTPUT_PUSHPULL);
/* Set Chip Select Pins HIGH, to keep them "inactive" */
palSetLine(SPI_CS_BMP280_LINE);
palSetLine(SPI_CS_MPU9250_LINE);
/* Activating the SPID1 with the chosen configuration. */
spiStart(&SPID1, &spicfg);
/* Print debug message before reading WHO_AM_I */
chprintf((BaseSequentialStream*)&SD2, "Reading WHO_AM_I register...\r\n");
/* Preparing the first word with the command to read the WHO_AM_I register.
NB! Remember for out case W/R-bit is at MSB position. */
txbuf[0] = (MPU9250_RW_BIT_READ << 7) | (MPU9250_WHO_AM_I << 0);
chprintf((BaseSequentialStream*)&SD2, "Sending txbuf[0]: 0x%02X , txbuf[1]: 0x%02X\r\n", txbuf[0],txbuf[1]);
while(true) {
chThdSleepMilliseconds(5000);
/* Performing an exchange. */
spiSelect(&SPID1);
spiExchange(&SPID1, 2, txbuf, rxbuf);
spiUnselect(&SPID1);
/* The value of the register is at this point
stored in rxbuf[1]. */
/* Print the received WHO_AM_I value */
chprintf((BaseSequentialStream*)&SD2, "Receiving rxbuf[0]: 0x%02X , rxbuf[1]: 0x%02X\r\n", rxbuf[0],rxbuf[1]);
chprintf((BaseSequentialStream*)&SD2, "WHO_AM_I value: 0x%02X\r\n", rxbuf[1]);
/* Use LED light to indicate if it is as expected */
if(rxbuf[1] != 0x00){
palSetLine(LED_INDICATOR_LINE);
chprintf((BaseSequentialStream*)&SD2, "MPU9250/9255 detected!\r\n");
}else{
palClearLine(LED_INDICATOR_LINE);
chprintf((BaseSequentialStream*)&SD2, "Unknown device detected.\r\n");
}
}
}
I have made sure to enable the needed variables in cfg/halconf.h:
Code: Select all
#define HAL_USE_SPI TRUE
and in cfg/mcuconf.h
Code: Select all
#define STM32_SPI_USE_SPI1 TRUE
The code runs fine, I also added the virtual COM port to print out for me. However, it seems like the clock line for the SPI isn't operating, as shown here:

We are seeing the READ bit (1) at the beginning + 0x75 which equals 0b 1111 0101. But no clock signal.
What could be possible reasons for the clock line not working?