I am having trouble using the ECSPI from the Cortex-M4 of the i.MX8MM with the functions available in fsl_ecspi.c.
Eventually, I need to communicate with complex ADC and DAC devices. To try and simplify things to prove the interface I have gone back to an SPI flash device and trying to read the manufacturer ID. The flash data sheet shows the following diagram:
Looking at the SPI bus on a logic analyser I don't ever seem to see any data coming from the device. I appear to have 4 bytes being written to the slave device and the CS# going high then low between each byte being sent.
The setup of the ESCPI controller is as per the SDK sample:
/* Master config:
* masterConfig.channel = kECSPI_Channel0;
* masterConfig.burstLength = 8;
* masterConfig.samplePeriodClock = kECSPI_spiClock;
* masterConfig.baudRate_Bps = TRANSFER_BAUDRATE;
* masterConfig.chipSelectDelay = 0;
* masterConfig.samplePeriod = 0;
* masterConfig.txFifoThreshold = 1;
* masterConfig.rxFifoThreshold = 0;
*/
ECSPI_MasterGetDefaultConfig(&masterConfig);
masterConfig.baudRate_Bps = TRANSFER_BAUDRATE;
ECSPI_MasterInit(EXAMPLE_ECSPI_MASTER_BASEADDR, &masterConfig, ECSPI_MASTER_CLK_FREQ);
Anyone got any ideas how I make this work?
-Andy.
Solved! Go to Solution.
Hi,
Thank you for sharing more information, from the piece of code you have shared and the analyzer image, it seems that the output you're seeing after 0x9f are random stuff because you have set a datasize of 4.
masterXfer.dataSize = 4;
Since only the first byte have a value the other 3 bytes will be dummy data, and you could see this in the ecspi driver located at: SDK_2_11_0_EVK-MIMX8MM\devices\MIMX8MM6\drivers\fsl_ecspi.c
while (xfer->dataSize > 0UL)
{
/* ECSPI will transmit and receive at the same time, if txData is NULL,
* instance will transmit dummy data, the dummy data can be set by user.
* if rxData is NULL, data will be read from RX FIFO buffer, but the
* data will be ignored by driver.
* Note that, txData and rxData cannot be both NULL.
*/
state = ECSPI_WriteBlocking(base, xfer->txData, dataCounts);
if (kStatus_Success != state)
{
return state;
}
if (NULL != xfer->txData)
{
xfer->txData += dataCounts;
}
state = ECSPI_ReadBlocking(base, xfer->rxData, dataCounts);
if (kStatus_Success != state)
{
return state;
}
if (NULL != xfer->rxData)
{
xfer->rxData += dataCounts;
}
xfer->dataSize -= dataCounts;
}
Also, if you need the SS to stay active, you'll need to have SS_CTL clear and after looking into the driver code this is not supported, but that does not mean it could not be added on your side, you may refer to the reference manual for more information on this:
Please refer to the fsl_ecspi.c function:
void ECSPI_SetChannelConfig(ECSPI_Type *base, ecspi_channel_source_t channel, const ecspi_channel_config_t *config)
Best regards,
Aldo.
Hi @AldoG
Let me try to explain better...
The ECSPI interface is being configured as per the driver/ecspi/polling_b2b_transfer/master example in the SDK (I have SDK v2.11.0). I then run the following code to try to query the SPI flash for it's manufacturer ID:
Hi,
Thank you for sharing more information, from the piece of code you have shared and the analyzer image, it seems that the output you're seeing after 0x9f are random stuff because you have set a datasize of 4.
masterXfer.dataSize = 4;
Since only the first byte have a value the other 3 bytes will be dummy data, and you could see this in the ecspi driver located at: SDK_2_11_0_EVK-MIMX8MM\devices\MIMX8MM6\drivers\fsl_ecspi.c
while (xfer->dataSize > 0UL)
{
/* ECSPI will transmit and receive at the same time, if txData is NULL,
* instance will transmit dummy data, the dummy data can be set by user.
* if rxData is NULL, data will be read from RX FIFO buffer, but the
* data will be ignored by driver.
* Note that, txData and rxData cannot be both NULL.
*/
state = ECSPI_WriteBlocking(base, xfer->txData, dataCounts);
if (kStatus_Success != state)
{
return state;
}
if (NULL != xfer->txData)
{
xfer->txData += dataCounts;
}
state = ECSPI_ReadBlocking(base, xfer->rxData, dataCounts);
if (kStatus_Success != state)
{
return state;
}
if (NULL != xfer->rxData)
{
xfer->rxData += dataCounts;
}
xfer->dataSize -= dataCounts;
}
Also, if you need the SS to stay active, you'll need to have SS_CTL clear and after looking into the driver code this is not supported, but that does not mean it could not be added on your side, you may refer to the reference manual for more information on this:
Please refer to the fsl_ecspi.c function:
void ECSPI_SetChannelConfig(ECSPI_Type *base, ecspi_channel_source_t channel, const ecspi_channel_config_t *config)
Best regards,
Aldo.
Hi @AldoG
Thanks for the additional information.
Can I just confirm that in order to keep the SS signal active I need to set the SS_CTL bit to be 0?
Looking at the Reference Manual and the source code for ECSPI_MasterInit() then it looks like currently that bit is being ignored as the SMC bit in ECSPI_CONREG is set to 1.
I'm guessing that means that I need to modify ECSPI_MasterInit() to make the SMC bit configurable and if SMC bit is cleared then the transfers need to be initiated by setting the XCH bit.
Can you confirm all of the above is correct.
-Andy.
Hello,
Yes, you're correct
Best regards,
Aldo.
Hi @AldoG
Apologies for re-opening this but I have made all of the changes that I anticipated to the ECSPI functions in the SDK but I cannot get the SPI interface to work.
When I try to initiate the transfer, I am never seeing the slave select signal go low. I have added some debug to ECSPI_MasterTransferBlocking() to look at the contents of the SPI registers and they appear correct.
DEBUG : In ECSPI_MasterTransferBlocking
DEBUG : Selected SPI channel 0
DEBUG : burstLength = 8, dataCounts = 1
DEBUG : CONREG = 0x00704511
DEBUG : CONFIGREG = 0x00010100
DEBUG : INTREG = 0x00000000
DEBUG : STATREG = 0x00000003
DEBUG : PERIODREG = 0x00000000
Immediately after that debug is output I have the following added code:
Any idea what I have missed?
-Andy.
Hello,
I do not understand clearly which part is not responding, I believe it is the slave right?
I think it would be better to try an ECSPI example, i.e. b2b_transfer so you could see the SPI bus with you analyzer.
Best regards,
Aldo.
I am using i.MX8MP and Cortex M7 and I have the same issue that the SS is not going low for multiple bursts. The comments in fsl_ecspi.h
I also have same issue on M4.
Any configurations are not effective I thought.
The best is configuring independent GPIO as Chip Select if possible.
Hi - I followed wonky-andy's advice and it worked. To note, the 32 bit transfer, it only used the bottom byte of every 32bits. Also was not what I was expecting. But this has solved my issue. Something wrong with their driver and their examples don't use the SPI interface fully so is decieving.
Good luck.
I never did manage to get this to work properly using the chip select pin (SS0) configured as part of the ECSPI interface.
To work around it, I configure the pin as a GPIO:
gpio_pin_config_t xGpioConfig = { kGPIO_DigitalOutput, 1, kGPIO_NoIntmode };
IOMUXC_SetPinMux(IOMUXC_ECSPI1_MISO_ECSPI1_MISO, 0U);
IOMUXC_SetPinConfig(IOMUXC_ECSPI1_MISO_ECSPI1_MISO,
IOMUXC_SW_PAD_CTL_PAD_DSE(6U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
IOMUXC_SetPinMux(IOMUXC_ECSPI1_MOSI_ECSPI1_MOSI, 0U);
IOMUXC_SetPinConfig(IOMUXC_ECSPI1_MOSI_ECSPI1_MOSI,
IOMUXC_SW_PAD_CTL_PAD_DSE(6U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK);
IOMUXC_SetPinMux(IOMUXC_ECSPI1_SCLK_ECSPI1_SCLK, 0U);
IOMUXC_SetPinConfig(IOMUXC_ECSPI1_SCLK_ECSPI1_SCLK,
IOMUXC_SW_PAD_CTL_PAD_DSE(6U) |
IOMUXC_SW_PAD_CTL_PAD_HYS_MASK |
IOMUXC_SW_PAD_CTL_PAD_PE_MASK);
IOMUXC_SetPinMux(IOMUXC_ECSPI1_SS0_GPIO5_IO09, 0U);
GPIO_PinInit(GPIO3, 19, &xGpioConfig);