SPI with DMA incorrect NSS behavior
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-27 12:01 PM
HI.
My MCU is STM32L071CZ, CubeMX latest version on this period of time.
I try to communicate with an external SPI-Flash IC. The SPI uses software NSS. The communication is good but only if I'm not using DMA.
When I try to communicate with flash using HAL_SPI_TransmitReceive_DMA() function and try to transmit or receive more than 2 bytes, the communication fails. Because of on second transmitted byte NSS goes into High (unactive) mode.
I also try to use TxRx transmit complete callback, but the behavior is the same.
What I do wrong? How to force NSS pin rise up when the transaction is complete?
- Labels:
-
DMA
-
SPI
-
STM32Cube MCU Packages
-
STM32L0 Series
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-27 12:09 PM
I read in a book that NSS is an open collector output so that you can connect multiple CPUs together in a multi-master configuration, and to get NSS to work as you'd expect you need a pull-up resistor.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-27 12:17 PM
Hi Andrei.
Yes, but in my case I use a software NSS. It's a simple configured GPIO in to out. It initialized with high level and when I need to start SPI transaction I put it manualy into low stater, which indicate for external flash that transaction is started, prepare to listen a comands...
On the same spi bus I plan to use one more SPI device, thets whay I'm not use hardware NSS
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-27 12:25 PM
The DMA system doesn't know anything about your software control of NSS. It will not call your code.
If you were to assert NSS, then start the DMA, then deassert NSS, assume that the DMA start takes no time. At that point it is all in the hands of the hardware.
You can see in your plot that SCK starts before NSS gets deasserted. This is the start of the DMA hardware doing the transfers, but control is given back to your code and you deassert NSS.
Assume that HAL_SPI_TransmitReceive_DMA is asynchronous. You shouldn't deassert until you get the DMA complete interrupt.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-27 12:41 PM
"Assume that HAL_SPI_TransmitReceive_DMA is asynchronous. You shouldn't deassert until you get the DMA complete interrupt."
Yes, I try to do that with registered "HAL_SPI_TxRxCpltCallback" callback, but it fires before the transaction was compleat.
I register it by using this function "HAL_SPI_RegisterCallback(&hspi1, HAL_SPI_TX_RX_COMPLETE_CB_ID, HAL_SPI_TxRxCpltCallback);"
Also I found two another callbacks
" HAL_SPI_RegisterCallback(&hspi1, HAL_SPI_TX_COMPLETE_CB_ID, HAL_SPIDMA_TxCpltCallback);
HAL_SPI_RegisterCallback(&hspi1, HAL_SPI_RX_COMPLETE_CB_ID, HAL_SPIDMA_RxCpltCallback);"
But thous two dosn't work at all.
In this callback, I check the Transmit Compleat flag for each channel and that behaves as I describe above
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
if (SPI1 == hspi->Instance)
{
if (__HAL_DMA_GET_FLAG(&hdma_spi1_tx, DMA_FLAG_TC3))
{
__HAL_DMA_ENABLE_IT(&hdma_spi1_tx, DMA_IT_TC);
flashspi1.isSpiTransmite = false;
}
if (__HAL_DMA_GET_FLAG(&hdma_spi1_rx, DMA_FLAG_TC2))
{
__HAL_DMA_ENABLE_IT(&hdma_spi1_rx, DMA_IT_TC);
flashspi1.isSpiReceive = false;
}
}
}
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-27 1:01 PM
Wouldn't those give you a callback when a SPI transaction (1 byte or so) go out? I think you need the DMA complete interrupt.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2019-08-27 1:17 PM
It seems that I use the wrong register callback function. I found this "HAL_DMA_RegisterCallback()" I will try it tomorrow. Thanks!
