SPI on F4

Limited support for STM32F4 Discovery, Nucleo and custom F4 boards
ag123
Posts: 742
Joined: Thu Jul 21, 2016 4:24 pm

SPI on F4

Post by ag123 » Fri May 05, 2017 3:12 pm

out of sheer curiosity i took a peek at the SPI section in RM0009 reference manual for F4
http://www.st.com/content/ccc/resource/ ... 031020.pdf
vs RM0008 reference manual for F1*
http://www.st.com/content/ccc/resource/ ... 171190.pdf

there a a lot of parts that looked literally 'identical', how i hoped pdf viewers can do a 'diff' and just tell me what are the differences :D

i noted the following as 1 of the difference:
STM32F1 RM0008 p710 25.3.3 Configuring the SPI in master mode
25.3.3 Configuring the SPI in master mode
Procedure
1. Select the BR[2:0] bits to define the serial clock baud rate (see SPI_CR1 register).
2. Select the CPOL and CPHA bits to define one of the four relationships between the data transfer and the serial clock (see Figure 239).
3. Set the DFF bit to define 8- or 16-bit data frame format
4. Configure the LSBFIRST bit in the SPI_CR1 register to define the frame format.
5. If the NSS pin is required in input mode, in hardware mode, connect the NSS pin to a high-level signal during the complete byte transmit sequence. In NSS software mode, set the SSM and SSI bits in the SPI_CR1 register. If the NSS pin is required in output
mode, the SSOE bit only should be set.
6. The MSTR and SPE bits must be set (they remain set only if the NSS pin is connected
to a high-level signal). In this configuration the MOSI pin is a data output and the MISO pin is a data input.
STM32F1 RM0009 p887 28.3.3. Configuring the SPI in master mode
28.3.3. Configuring the SPI in master mode
In the master configuration, the serial clock is generated on the SCK pin.
Procedure
1. Select the BR[2:0] bits to define the serial clock baud rate (see SPI_CR1 register).
2. Select the CPOL and CPHA bits to define one of the four relationships between the data transfer and the serial clock (see Figure 248). This step is not required when the TI mode is selected.
3. Set the DFF bit to define 8- or 16-bit data frame format
4. Configure the LSBFIRST bit in the SPI_CR1 register to define the frame format. This step is not required when the TI mode is selected.
5. If the NSS pin is required in input mode, in hardware mode, connect the NSS pin to a high-level signal during the complete byte transmit sequence. In NSS software mode, set the SSM and SSI bits in the SPI_CR1 register. If the NSS pin is required in output mode, the SSOE bit only should be set. This step is not required when the TI mode is selected.
6. Set the FRF bit in SPI_CR2 to select the TI protocol for serial communications.
7. The MSTR and SPE bits must be set (they remain set only if the NSS pin is connected to a high-level signal).
configuration the MOSI pin is a data output and the MISO pin is a data input.
while this is unlikely to be the only difference what seem rather distinct is this addition of the 'TI mode'
a timing diagram is given on p887 RM0009 SPI TI protocol in master mode
apparently the 'TI mode' seemed to have things like 'triggering edge' and 'sampling edge' and it seem to start with single NSS high pulse sequence
the other 'strange' thing about this P887 RM0009 SPI TI protocol timing diagram is it seem to label MOSI as 'input' while MISO as 'output' this doesn't seem to match the notions of how we'd usually do SPI since stm32 is the 'master' (seemed more like an error in the diagram)
my thoughts are in step (6) above, we'd need to *switch off* TI mode to get the 'regular' SPI we'd expect
in particular if we do use the NSS pin as a custom /CS pin for the SPI devices (i always do that so as not to 'waste') pins :lol:
but then the default for SPI_CR2 FRF at reset seem to be 0 motorola mode (rather than 1 TI mode)

just 2 cents

ag123
Posts: 742
Joined: Thu Jul 21, 2016 4:24 pm

Re: SPI on F4

Post by ag123 » Fri May 05, 2017 3:37 pm

nope, this doesn't seem like a meaningful difference since TI mode is off by default

stm32 also use the same boundary addresses and register addresses for SPI1 and SPI2, SPI3
0x4001 3000 - 0x4001 33FF SPI1
0x4000 3800 - 0x4000 3BFF SPI2/I2S
0x4000 3C00 - 0x4000 3FFF SPI3 / I2S3
Last edited by ag123 on Fri May 05, 2017 3:43 pm, edited 1 time in total.

stevestrong
Posts: 1612
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: SPI on F4

Post by stevestrong » Fri May 05, 2017 3:38 pm

ag123 wrote:the default for SPI_CR2 FRF at reset seem to be 0 motorola mode (rather than 1 TI mode)
Exactly, so if we don't set it, it remains "0", and the rest should be compatible with F1.

ag123
Posts: 742
Joined: Thu Jul 21, 2016 4:24 pm

Re: SPI on F4

Post by ag123 » Fri May 05, 2017 3:44 pm

i'm starting to suspect if it may be something related to the AHB clocks / prescalers or APB clocks / prescalers
as after all the F4 runs at 168 mhz while an F1 runs at 72 mhz, lots of things to hunt down to figure out differences esp if things don't work

the TI mode it seemed is that additional use of the NSS pin which based on the RM is default off and motorola mode is used instead

another thing which we may need to check may be to see if a particular peripheral bus is clocked.

found a web that seemed useful on the topic of clocks
https://stm32f4-discovery.net/2015/01/p ... x-devices/
settings seem to match that used on steves F4 black branch, the PLL multipliers seemed similar
https://github.com/stevstrong/Arduino_S ... cF4.c#L431

Code: Select all

void SetupClock168MHz() { 
...
// save bus clock values
rcc_dev_clk_speed_table[RCC_AHB1] = (SystemCoreClock/1);
rcc_dev_clk_speed_table[RCC_APB2] = (SystemCoreClock/2);
rcc_dev_clk_speed_table[RCC_APB1] = (SystemCoreClock/4);
system clock runs at 168 mhz, APB1 runs at 42 mhz (SPI2/SPI3 lives here), APB2 (SPI1 lives here) runs at 84 mhz, AHB runs at 168 mhz

while on F1 on roger's branch it seemed to be setup in the variant itself e.g. maple mini
https://github.com/rogerclarkmelbourne/ ... up.cpp#L71

Code: Select all

__weak void board_setup_clock_prescalers(void) {
rcc_set_prescaler(RCC_PRESCALER_AHB, RCC_AHB_SYSCLK_DIV_1);
rcc_set_prescaler(RCC_PRESCALER_APB1, RCC_APB1_HCLK_DIV_2);
rcc_set_prescaler(RCC_PRESCALER_APB2, RCC_APB2_HCLK_DIV_1);
system clock runs at 72 mhz, APB1 (SPI2/SPI3 lives here) runs at 36 mhz, APB2 (SPI1 lives here) runs at 72 mhz, AHB runs at 72 mhz

this is simply from reading the codes, i'm not too sure if it is correct and if they matter after all
perhaps when starting with SPI tests (esp SPI1 APB2 at 84mhz) it may help to use a bigger SPI clock divisor / lower speeds for a start :?

stevestrong
Posts: 1612
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: SPI on F4

Post by stevestrong » Fri May 05, 2017 6:11 pm

Good news, it started to work with libmaple code, the scope shows the SPI_CLK pulses (SPI3), and it does not freezes anymore.
Now need to determine which of my changes made it.
More to come.

michael_l
Posts: 337
Joined: Mon Aug 24, 2015 6:11 pm

Re: SPI on F4

Post by michael_l » Fri May 05, 2017 8:09 pm

stevestrong wrote:Good news, it started to work with libmaple code, the scope shows the SPI_CLK pulses (SPI3), and it does not freezes anymore.
Now need to determine which of my changes made it.
More to come.

Image

stevestrong
Posts: 1612
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: SPI on F4

Post by stevestrong » Sun May 07, 2017 3:22 pm

The actual bench values using SdFat beta, SPI3 21MHz, no DMA, card: 16GB SanDisk ultra class 10:

Code: Select all

Type any character to start
FreeStack: 117044
Type is FAT32
Card size: 15.93 GB (GB = 1E9 bytes)

Manufacturer ID: 0X3
OEM ID: SD
Product: SL16G
Version: 8.0
Serial number: 0X72F2CA43
Manufacturing date: 8/2015

File size 5 MB
Buffer size 512 bytes
Starting write test, please wait.

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
375.32,122150,759,1363
387.66,18954,1021,1319

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
945.83,1574,529,540
946.01,1071,529,540

Done
The SdFat"Ex" version does not bring any improvements.

For comparison, same test on F1, SPI2 18MHz + DMA:

Code: Select all

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
371.61,98875,1064,1376
374.45,11895,1067,1365

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
1166.24,1086,428,437
1166.51,865,428,437
... and here F1 no DMA:

Code: Select all

write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
364.41,121015,1092,1403
368.79,11924,1089,1386

Starting read test, please wait.

read speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
684.04,1483,735,747
684.14,1481,734,747
The latest working libmaple core (including PIN_MAP moved to flash) is committed to Black_F4 branch.
Attachments
STM32F4_SD_bench.ino.txt
(6.17 KiB) Downloaded 6 times
Last edited by stevestrong on Sun May 07, 2017 10:34 pm, edited 1 time in total.

ag123
Posts: 742
Joined: Thu Jul 21, 2016 4:24 pm

Re: SPI on F4

Post by ag123 » Sun May 07, 2017 4:41 pm

+5 good achievement :D

writing speed seem to have reached sd native limiting speed, for read speed, my thoughts are that if a bigger buffer is used e.g. 1k it may narrow the difference so much that DMA would not make too much difference

stevestrong
Posts: 1612
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: SPI on F4

Post by stevestrong » Sun May 07, 2017 5:39 pm

It seems that a buffer size of 4096 or 8182 is the best option if RAM is tidy (see table of the next post).
Last edited by stevestrong on Mon May 08, 2017 8:51 am, edited 4 times in total.

stevestrong
Posts: 1612
Joined: Mon Oct 19, 2015 12:06 am
Location: Munich, Germany

Re: SPI on F4

Post by stevestrong » Sun May 07, 2017 10:20 pm

I have completed the table with bench results using SPI = 42MHz, all without DMA.
stm32_sd_performance.jpg
stm32_sd_performance.jpg (162.89 KiB) Viewed 418 times
Last edited by stevestrong on Mon May 08, 2017 8:52 am, edited 1 time in total.

Post Reply