SPI timing
Hello,
I am familiarizing myself with the SPI controller on a NUCLEO-F303K8 development board using the CMSIS device headers. I have written a program to send and receive a single byte using polling or interrupts. While functionally it appears correct, I am a bit confused on the timing diagrams generated by my logic analyzer.
Overall configuration: System clock is HSI at 8MHz. SPI clock has default prescaler of 2, so 4MHz.

The above is the result for a polling transaction.
Interval 0: SPI enable to CS low, 6 cycles - makes sense
Interval 1: CS low to shift register filled with tx data, 3 cycles (1 CPU cycle to store, 1 SPI cycle to put it on the line?)
Interval 2: Shift register filled with tx data to transaction start, 3 cycles - not sure what happens here
Interval 3: The transaction, 16 CPU/8 SPI cycles - makes sense
Interval 5 (manually added): Reading the shift register and setting CS low - should be 4 cycles (marked it wrong in diagram)
As the SPI is configured with CPOL = CPHA = 0, I would expect RXNE to go high as soon as Marker 4 as the last rx bit is latched, but I suppose there could be more overhead with the FIFO. The left end of Interval 6 is where I would expect the CPU to find RXNE high (a few cycles in a loop), read the shift register, and set CS low, but this does not happen until Interval 5 - around 12 cycles later. Interval 6 is what I'm interested in. I found similar results using interrupts to respond to RXNE.

Above is the interrupt transaction. Similar intervals are highlighted, although Interval 5 and Interval 4 make up the expected Cortex M4 interrupt latency (12 cycles) and reading the shift register/setting CS low, respectively. The interval of interest here is Marker 3 to the left end of Interval 5.
Finally, here is the code.
#include <stdint.h>
#include "stm32f3xx.h"
#include "core_cm4.h"
/*
* SCK = PA5, MOSI = PB5, MISO = PB4, CS = PB6
*/
#define GPIO_MODE_OUTPUT 0b01
#define GPIO_MODE_ALTERNATE 0b10
#define GPIO_SPEED_HIGH 0b10
#define GPIO_PULLUP 01
#define GPIO_SPI_ALTERNATE 5
/*
* SCK: PA5, push-pull, high speed, no pull, alternate function mode
* MOSI: PB5, push-pull, high speed, no pull, alternate function mode
* MISO: PB4, push-pull, high speed, no pull, alternate function mode
* CS: PB6, push-pull, high speed, pullup, output mode
*/
void gpio_init(void)
{
GPIOA->MODER |= (GPIO_MODE_ALTERNATE << GPIO_MODER_MODER5_Pos);
GPIOA->OTYPER = 0;
GPIOA->OSPEEDR = (GPIO_SPEED_HIGH << GPIO_OSPEEDER_OSPEEDR5_Pos);
GPIOA->PUPDR = 0;
GPIOA->AFR[0] = (GPIO_SPI_ALTERNATE << GPIO_AFRL_AFRL5_Pos);
GPIOB->MODER = (GPIO_MODE_ALTERNATE << GPIO_MODER_MODER4_Pos)
| (GPIO_MODE_ALTERNATE << GPIO_MODER_MODER5_Pos)
| (GPIO_MODE_OUTPUT << GPIO_MODER_MODER6_Pos);
GPIOB->OTYPER = 0;
GPIOB->OSPEEDR = (GPIO_SPEED_HIGH << GPIO_OSPEEDER_OSPEEDR4_Pos)
| (GPIO_SPEED_HIGH << GPIO_OSPEEDER_OSPEEDR5_Pos)
| (GPIO_SPEED_HIGH << GPIO_OSPEEDER_OSPEEDR6_Pos);
GPIOB->PUPDR = (GPIO_PULLUP << GPIO_PUPDR_PUPDR6_Pos);
GPIOB->AFR[0] = (GPIO_SPI_ALTERNATE << GPIO_AFRL_AFRL4_Pos)
| (GPIO_SPI_ALTERNATE << GPIO_AFRL_AFRL5_Pos);
GPIOB->BSRR = GPIO_BSRR_BS_6;
}
/*
* Master mode, software NSS management, 8-bit receive FIFO threshold
*/
void spi_init(void)
{
SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_SSM | SPI_CR1_SSI;
SPI1->CR2 = SPI_CR2_FRXTH;
SPI1->CR1 |= SPI_CR1_SPE;
}
/*
* Polled SPI transaction
*/
void spi_tx_rx_poll(void)
{
GPIOB->BRR = GPIO_BRR_BR_6;
*((volatile uint8_t*)&SPI1->DR) = 0xAA;
while (!(SPI1->SR & SPI_SR_RXNE)) {}
uint8_t rx = *((volatile uint8_t*)&SPI1->DR);
GPIOB->BSRR = GPIO_BSRR_BS_6;
}
/*
* Interrupt SPI transaction
*/
void spi_tx_rx_int(void)
{
SPI1->CR2 |= SPI_CR2_RXNEIE;
NVIC_EnableIRQ(SPI1_IRQn);
GPIOB->BRR = GPIO_BRR_BR_6;
*((volatile uint8_t*)&SPI1->DR) = 0xAA;
}
void SPI1_IRQHandler(void)
{
uint8_t rx = *((volatile uint8_t*)&SPI1->DR);
GPIOB->BSRR = GPIO_BSRR_BS_6;
}
int main(void)
{
RCC->AHBENR = RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN;
RCC->APB2ENR = RCC_APB2ENR_SPI1EN;
gpio_init();
spi_init();
spi_tx_rx_poll();
spi_tx_rx_int();
while (1) {}
}Thanks in advance for any clarification on these timings, and let me know if there's any other information I can provide or experiments I could run.
