2018-05-08 05:24 AM
Hey there,
I'm using SPI3 on an STM32F767ZI (on a nucleo board for now)
I'm using HAL and DMA based multi-byte transfer. (but still feel kind of new to it) I'm trying to just setup a basic SPI master and wanted to be able to use the nSS signal... What I want to do for this peripheral, is have the nSS go down (assert) at the start of a data frame, and then have it stay down till the end, then pop up (deassert) when finished.so I setup nSS as a hardware output in cubemx, and generated the code.When I call HAL_SPI_TransmitReceive_DMA(...) I get no nSS action. (though clock and dummy data frame go perfectly)
I tried the same thing with SPI2 with the same settings, and had the same results... But SPI2 has an option called nSS pulse mode, and when I tried enabling that it automatically generates nSS transition to deasserted then asserted every 8 bits... And when disabled the nSS stays down all the time, just like with SPI3...I have tried taking the nSS pin back to a GPIO, and then manually asserting that GPIO nSS signal at the start of a transmission, then using HAL_SPI_TxRxCpltCallback() to toggle the GPIO pin back at the end of my data frame, but at 6MHz SPI rate for just a few bytes in a frame, I'm spending more time at the end of my SPI frame waiting for nSS to deassert than the entire frame takes!
Anyway - this could be a noob error, I am new to HAL and I may be approaching this wrong - but I'd really love a way to be able to have nSS do gown for a multiple byte DMA frame, and then pop right back up again straight after the last bit... can anyone suggest anything that might help?
#stm32f7 #hal-spi2018-05-08 09:07 AM
can anyone suggest anything that might help?
No, this is the way how NSS with SPI in STM32 works.
I'm spending more time at the end of my SPI frame waiting for nSS to deassert than the entire frame takes
Use the RXNE interrupt, you won't be waiting. I don't know what's the incantation for that in Cube.
You may want to read the SPI chapter in the RM.
JW
2018-05-08 04:44 PM
Thanks Jan,
I had looked up the RM, but to be honest I find it a bit light on in detail when you get to specific features of the SPI being combined. In fact from my reading of the RM, and looking at things like the master full duplex communication drawing on P1326 of the latest reference manual for the F7, it *should* work how I'm expecting it to...there's some guff about needing to disable the SPI port after a transmission.. I'll look into trying that and see if that does what I want.
Also there's some kind of 'software controlled' NSS, which, reading the RM, implies that rather that using the pin as a GPIO, I can simply write to an bit in an SPI register to manually flick the nSS pin up and down... but in the same paragraph it goes on to say that 'the nSS pin can be used for other tings' which makes me wonder WHAT ON EARTH the software controlled nSS feature even is if it doesn't even need a pin??!?!?Anyway - I'll look up and see what relates to RXNE
in HAL, and how I can hang a function off it....
is it an SPI device specific interrupt? (ie is there the one of these interrupts for each different SPI device?) there is only oneHAL_SPI_TxRxCpltCallback() function to setup, and using it to do end of DMA stuff with multiple SPI devices (actual application has 3 different SPI peripherals enabled) is getting pretty clunky and making my code a bit spaghetti-like.. on top of being absolutely inappropriate in terms of response time for a 6MHz SPI channel...
2018-05-09 01:45 AM
I had looked up the RM, but to be honest I find it a bit light on in detail
Yes it surely is, and the wording is not the clearest at places.
In following, I will use 'byte' for 'whatever is set in SPIx_CR2.DS to be one unit output by SPI'. I am reluctant to use 'frame' as it may mean both - one 'byte' or 'a number of bytes you want to frame by NSS signal'.
As master, you have essentially 4 options:
- SPIx_CR1.SSM=0, SPIx_CR2.SSOE=0 - here, internal NSS signal of the SPI module is brought in from the NSS pin (as assigned by AF in GPIO) as input and if pulled low externally, SPI will go automatically into slave mode (software is notified by hardware setting SPIx_SR.MODF)
- SPIx_CR1.SSM=0, SPIx_CR2.SSOE=1 - here, internal NSS signal of the SPI module is output to NSS pin, and goes down when the first data are transmitter, and will never go up again (until SPI is reenabled)
- a variant on the above, found only in newer STM32 (as you've found out, it works in yours), if SPIx_CR2.NSSP = 1, NSS pin is output and frames eachbyte
- SPIx_CR1.SSM=1 - here, NSS signal is not tied to pin but to internally to the SPIx_CR1.SSI bit; in master mode you want SSI be 1, otherwise it will go into slave mode as in the first case
None of these will help you - you could set the second option and disable SPI after each bunch of data (I am reluctant to use 'frame' here as it's used in the RM for the number of data transmitted in one cycle of SPI itself) but that's the same amount of work than output that signal 'manually' using GPIO.
RXNE is the flag (and if enabled, causes interrupt) upon receiving a byte. I meant, you can hook on the interrupt coming from this byte just after the TxDMA finished, i.e. waiting for the last byte to be received (and doing this carefully not to miss that, i.e. just before the last byte) - the FIFO and data packing found in newer STM32 may make this relatively hard to use. If you use DMA, you may be better off using the DMA interrupt of the receiver. I'd say this all is already built into Cube/HAL, but, as you've remarked, as it's designed to be 'universal', it's also cumbersome and potentially slow; then you may want to roll out your customized solution.
They may be more ways to skin the cat, for example you may use a timer to output a pulse of calculated length; again taking appropriate care e.g. to avoid some other ISR to insert unwanted delay between the pulse beginning and the point where data start to output from SPI.
JW
2018-05-22 04:26 AM
yeah yeah , I also have this problem,set NSSP want to
automatically generates NSS pulse. but it not work.
Finally, set SPI1_Handler.Init.CLKPhase=SPI_PHASE_1EDGE; the MCU
automatically generates NSS pulse.
that is mean
SPI1_Handler.Init.CLKPhase=SPI_PHASE_1EDGE;
SPI1_Handler.Init.NSSPMode = SPI_NSS_PULSE_ENABLE ;
NOT:
SPI1_Handler.Init.CLKPhase=SPI_PHASE_2EDGE;
SPI1_Handler.Init.NSSPMode = SPI_NSS_PULSE_ENABLE ;