ADSP-21569
Recommended for New Designs
Reaching speeds of up to 1 GHz, the ADSP-2156x processors are members of the SHARC® family of products. The ADSP-2156x processor is based on the SHARC...
Datasheet
ADSP-21569 on Analog.com
Hello there,
I've been struggling for a few days against how to correctly configure SPI1 peripheral using ADI drivers to shift out bytes on MISO pin in slave mode.
This will be just the first episode of my series, tomorrow I will open a new discussion about the sequel.
Trying to avoid any misunderstanding, I'll try to describe the exact scenario in the following.
<---- this is from SPIDMAMode.h
<--- and this is from SPIDMAMode.c main() function
where, for practical reasons, I decided to use SSEL_EN_6 line for SPI2 chip select, and I lowered SPI CLK frequency generated by SPI2 master down to around 1.2Mbps
Hoping I haven't forgotten anything in the description above, when I run the application what I can see on the lines is the following:
So, my question is: how is it possible that SPI1 is shifting out 1s on MISO line during DMA receive, while the only two possible settings about what SPI must do when TXFIFO is empty are "shift 0s" or "send last word"?
For the sole purpose of testing, I later added in EnableSPIChannel() ADI function the code line highlighted in red below:
and voilà, I obtained the behavior that I expected to see, MISO pin shifting out 0s while receiving.
Thanks in advance to anyone who wants to contribute.
Hi,
In the ADSP-21569 evaluation board, SPI2 is connected to the flash chip and a pull-up resistor is placed between the MISO lines.As a result, the SPI2_MISO line remains in a high state in your application. Please refer to the image below for clarification.
The adi_spi_MisoEnable() API only enables the MISO line on the slave side, it does not initiate transmission. Therefore, the slave (SPI1) will not drive the MISO line, and its state will remain unchanged.
However, when you call the adi_spi_DMAWrite() API for the slave device, it triggers the transmission operation on the MISO line and begins driving the line based on the SPI_TXCTL.TDU configuration, once the transmit buffer is empty. This process is handled internally within the driver API. Please refer to the image below for clarification.
Thus, the SPI1 is not transmitting 1s on the MISO line during DMA reception. The reason for the high state is pull-up resistor on the SPI2_MISO line.
It is not good practice to modify the driver file directly, it will cause some unexpected behaviors.
Regards,
Nandini C
Hello Nandini,
first of all thanks for your comprehensive reply.
Yes, I know that MISO line is pulled up to +3V rail by means of a resistor, but then MISO stays high as long as MISO pin stays in Hi-Z state on the slave side.
What looks not clear (and coherent) to me is why after explicitly calling adi_spi_Open() with ADI_SPI_DIR_BIDIRECTION argument, there's first (a) the need of explicitly calling adi_spi_EnableMISO(), and (b) the chance that EN is not set in TXCTL register during SPI operation, allowing MISO line to be sometimes driven and other times not. This is, essentially, the core of my post and my question.
The end result of acting like that is that, if I start my code by receiving some data using adi_spi_DMARead() SPI Master is reading 1s while clocking the slave as "no data" value, but later if I start transmiting data using adi_spi_DMAWrite() SPI Master is reading 0s while clocking the slave if DMA transfer has completed as "no data" value since TXFIFO underrun occurs and TDU bit is cleared in TXCTL register.
P.S. It is not good practice to modify the driver file directly ---> yes, in fact I explicitly mentioned that I've done so for the sole purpose of testing.
Hi,
The ADI_SPI_DIR_BIDIRECTION argument in the adi_spi_Open() API is used solely to allocate sufficient memory and create a handle for SPI driver operations. The SPI registers are configured in the adi_spi_Open() API based on the static file adi_spi_config_2156x.h, which is located in the system>drivers>spi path of the project.
To enable the MISO line, you can set the #define ADI_SPI1_CFG_ENABLE_MISO macro to 0x1ul without needing to call the adi_spi_EnableMISO() API explicitly. This will enable the MISO line for SPI1 when calling the open API. The adi_spi_EnableMISO() API is provided for enabling and disabling the MISO line at runtime.
The adi_spi_DMARead() and adi_spi_DMAWrite() APIs are designed for unidirectional communication and cannot be used for full-duplex operation. This means data cannot be transmitted and received simultaneously with these APIs. Specifically, adi_spi_DMAWrite() enables the TXCTL, while adi_spi_DMARead() enables the RXCTL of the corresponding SPI, as well as the SPI_CTL enable operation. Therefore, on the slave side, you need to use the adi_spi_DMAWrite() API to enable the transmission operation and the SPI interface. This will ensure that the slave transmits zeros if no data is available in the TXFIFO.
For full-duplex communication, we recommended to use the adi_spi_DMATransceiver() API for both the slave and master. This API enables both the TXCTL and RXCTL of the corresponding SPI and activates the SPI interface, allowing for simultaneous transmission and reception of data. Could you please try with this API instead of the adi_spi_DMAWrite() and adi_spi_DMARead() APIs in your application and share the results with us.
Regards,
Nandini C
Hello Nandini and thanks for your suggestion,
I already switched, in my final project using custom hardware, to adi_spi_DMATransceiver() and I can confirm that it obviously works.
The reason for my question is that being forced to use adi_spi_DMATransceiver() when you have no real TX data to send out and just want to see MISO line shifting zeros is a waste of memory and MIPS that could be avoided by just setting EN bit in TXCTL register.
How can I accomplish this "by hand" in my user code right after adi_spi_DMARead() call, since ADI SPI driver is hiding all the datatypes and definitions to tweak registers by hand?
Hi,
We understand the issues you're encountering in your application. However, as we mentioned previously adi_spi_DMARead() API is designed specifically for half-duplex communication. We can use this API when the ADI_SPI_DIR_RECEIVE argument is passed in the adi_spi_Open() API. In this case, it will only allocate memory and create the necessary handles for the receiver part.
To shift 0s onto the MISO line, we recommend using the adi_spi_DMATransceiver() API with NULL as the transmitter structure pointer and transmit buffer size. If this does not resolve the issue, please try adding the following line before calling the adi_spi_DMARead() API in your application and share the results with us:
*pREG_SPI1_TXCTL = ENUM_SPI_TXCTL_ZERO | ENUM_SPI_TXCTL_TX_EN;
We hope this helps.
Regards,
Nandini C
Hi, sorry but these days I'm busy on other tasks, I'll be back as soon as possible. Thank you
Here I am, sorry again for the delay in responding.
As I imagined, even if it would have been the most elegant solution, using your recommended solution doesn't work since ConfigureSPIChannel() - called by adi_spi_DMATransceiver() - expects a non-null descriptor size for TX then crashes even in Release:
while the second, dirty solution of manually overriding REG_SPI1_TXCTL content works as expected, even if really unelegant from an ADI API use point of view:
If working around like this is the only solution I could expect from ADI, I think we can close this thread since at least one solution has been found and tested by me.