Hey,
I'm encountering a strange problem with the hardware SPI of the 
STM32F407 [2] (discovery board). I'm trying to communicate with an UM7 
IMU [1] over its SPI interface.
When I try to read its firmware revision, I receive ASCII 'T71E' instead 
of the expected 'U71D'. You can see the SPI transmission recorded using 
a logic analyzer in the pictures, with the closeup showing the 
transmission for the last byte, which should be 'D' but is 'E'.
To me at least it looks like the data is transmitted correctly by the 
UM7, but somehow the STM reads the last bit incorrectly.
The behavior is reproducible, i.e. the first and last byte always have 
the last bit flipped.
Are there any pitfalls for the STM SPI I should aware of? Or am I doing 
something else wrong?
Regards,
Mirko
[1] Datasheet UM7: https://www.chrobotics.com/docs/UM7_Datasheet.pdf
[2] Datasheet STM32F407: 
http://www2.st.com/content/ccc/resource/technical/document/reference_manual/3d/6d/5a/66/b4/99/40/d4/DM00031020.pdf/files/DM00031020.pdf/jcr:content/translations/en.DM00031020.pdf
Code, in case I just made a dumb error somewhere...
| 1 | void spi_init(void) {
 | 
| 2 |       hspi.Instance = SPI1;
 | 
| 3 |       hspi.Init.Mode = SPI_MODE_MASTER;
 | 
| 4 |       hspi.Init.Direction = SPI_DIRECTION_2LINES;
 | 
| 5 |       hspi.Init.DataSize = SPI_DATASIZE_8BIT;
 | 
| 6 |       hspi.Init.CLKPolarity = SPI_POLARITY_LOW;
 | 
| 7 |       hspi.Init.CLKPhase = SPI_PHASE_1EDGE;
 | 
| 8 |       hspi.Init.NSS = SPI_NSS_SOFT;
 | 
| 9 |       hspi.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256;
 | 
| 10 |       hspi.Init.FirstBit = SPI_FIRSTBIT_MSB;
 | 
| 11 |       hspi.Init.TIMode = SPI_TIMODE_DISABLE;
 | 
| 12 |       hspi.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
 | 
| 13 |       hspi.Init.CRCPolynomial = 10;
 | 
| 14 |       HAL_SPI_Init(&hspi);
 | 
| 15 | }
 | 
| 16 | 
 | 
| 17 | uint8_t transceive_byte(uint8_t data) {
 | 
| 18 |     uint8_t recv = 0x00;
 | 
| 19 |     HAL_SPI_TransmitReceive(&hspi, &data, &recv, 1, HAL_MAX_DELAY);
 | 
| 20 |     return recv;
 | 
| 21 | }
 | 
| 22 | 
 | 
| 23 | uint32_t transceive_packet(uint8_t mode, uint8_t addr, uint8_t* data) {
 | 
| 24 | 
 | 
| 25 |     HAL_GPIO_WritePin(GPIO_IMU_SS_GPIO_Port, GPIO_IMU_SS_Pin, GPIO_PIN_RESET);
 | 
| 26 |     delay(10); // delay is in uS
 | 
| 27 |     transceive_byte(mode);
 | 
| 28 |     delay(20);
 | 
| 29 |     transceive_byte(addr);
 | 
| 30 | 
 | 
| 31 |     uint32_t recv_data = 0;
 | 
| 32 |     for(int i = 0; i < 4; i++) {
 | 
| 33 |         delay(20);
 | 
| 34 |         recv_data |= transceive_byte(data[i]) << (i * 8);
 | 
| 35 |     }
 | 
| 36 | 
 | 
| 37 |     HAL_GPIO_WritePin(GPIO_IMU_SS_GPIO_Port, GPIO_IMU_SS_Pin, GPIO_PIN_SET);
 | 
| 38 | 
 | 
| 39 |     return recv_data;
 | 
| 40 | }
 | 
| 41 | 
 | 
| 42 | void imu_spi_test() {
 | 
| 43 |     delay_init();
 | 
| 44 |     spi_init();
 | 
| 45 | 
 | 
| 46 |     uint32_t cmd = 0;
 | 
| 47 |     char fw_version[5] = {0};
 | 
| 48 |     *((uint32_t*)fw_version)= transceive_packet(CMD_WRITE, 0xAA, &cmd);
 | 
| 49 | 
 | 
| 50 |     trace("FW: %s\n", fw_version);
 | 
| 51 | }
 |