I'm working with an SPI barometer trying to get the K22F reading SPI responses using an SPIMaster_LDD PE component. I've scoped the bus lines - everything looks correct. K22F sends a "read address" byte, barometer then clocks out the values for the byte, then CS is set high. I'm manually driving CS to ensure that it stays low between request/read transmissions.
I've had to add a work-around for the PE SPI driver bug where the function SM1_GetBlockReceivedStatus returns before the byte is actually recieved by adding a fixed delay afterwards:
char RecieveByteSPI1()
{
char b, dummy;
dummy = 0;
LDD_TError er;
er = SM1_ReceiveBlock(SPI1DeviceDataPtr, &b, 1);
er = SM1_SendBlock(SPI1DeviceDataPtr, &dummy, 1);
while (!SM1_GetBlockSentStatus(SPI1DeviceDataPtr)) {
SM1_Main(SPI1DeviceDataPtr);
}
// /* Wait until data block is transmitted/received */
while (!SM1_GetBlockReceivedStatus(SPI1DeviceDataPtr)) {
SM1_Main(SPI1DeviceDataPtr);
}
WAIT1_Waitms(2);
return b;
}
Using the delay, I can see that the SPI bus transaction happens correctly at the electrical level. However, the variable b is not populated when the code returns. The SPI1 register POPR/RXDATA shows that it holds the expected value just before this function returns.
SPI1 is configured to *not* use interrupts. Aside from that, it's basically at default settings. Any idea what could be going wrong here?
----------------------------------------------------------------------------------------------
Updates:
1) Manually reading from POPR after receiving seems to fix the issue. Not sure why this is necessary:
b = (uint16_t)SPI_PDD_ReadPopRxFIFOReg(SPI1_BASE_PTR); /* Read character from receiver */
2) I found other reports (Is anyone really using PE Generated SPI driver with MQXLite? How? ) of PE SPI issues where GetBlockReceivedStatus wasn't working and a different flag was used to check if reception was complete. However, it looks like the receive-commplete flag is never set, and my SendByteSPI1 function hangs on this line:
while (!(SPI_PDD_GetInterruptFlags(SPI1_BASE_PTR) & SPI_SR_EOQF_MASK));//wait for the end of transfer
I just noticed this issue related to using a GPIO for CS, although I'm using a different MCU:
SPI with no CS. Problem with PE
---------
Edit 2017-07-11
Here are a couple of discussions on what may be the same issue:
Hello Earl.
To solve your problem, we need to know your SW version:
- Start the IDE and click on Help | About CodeWarrior(KDS) Development Studio. Send me the version and build id.
- send me your demo code.
I will check it from my side. Thanks.
Have a great day,
Jennie Zhang
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
I'm using KDS 3.2.0, I've pasted a screenshot of my Version IDs (build numbers?) for KDS prerequisites:
My PE SPI settings are pasted below. This screenshot was taken today when I'd temporarily disabled the SPI module for unrelated reasons, but at the time I was debugging, it was enabled.
Code samples:
------------------------------------------------------------------------------------------------------------------------------------
LDD_TDeviceData * SPI1DeviceDataPtr;
void InitSPI()
{
SPI1DeviceDataPtr = SM1_Init(NULL);
return;
}
void SendByteSPI1(byte data)
{
LDD_TError er = ERR_OK;
er = SM1_SendBlock(SPI1DeviceDataPtr, &data, 1);
while (!SM1_GetBlockSentStatus(SPI1DeviceDataPtr)) {
SM1_Main(SPI1DeviceDataPtr);
}
if (er != ERR_OK)
{
printf("Error sending byte on SPI1\n");
}
return;
}
char RecieveByteSPI1()
{
char b, dummy;
byte inBuffer [2];
dummy = 0;
LDD_TError er;
LDD_TData * receivePtr = &b;
er = SM1_ReceiveBlock(SPI1DeviceDataPtr, (LDD_TData*) &inBuffer, 1);
WAIT1_Waitms(2);
er = SM1_SendBlock(SPI1DeviceDataPtr, &dummy, 1);
WAIT1_Waitms(2);
while (!SM1_GetBlockSentStatus(SPI1DeviceDataPtr)) {
SM1_Main(SPI1DeviceDataPtr);
}
WAIT1_Waitms(2);
//TODO: Shouldn't be necessary to manually read from POPR register
b = (uint16_t)SPI_PDD_ReadPopRxFIFOReg(SPI1_BASE_PTR); /* Read character from receiver */
return b;
}
It's still not clear why you are spinning on a SENT status while waiting for a RECEIVE byte/word. TX is 'done' at least 1/2 Sclk before RX.
I can't find the post now but at one point I saw another issue where the user was seeing that the RECEIVE flag was never being set. I used the SENT status as the next-best thing based on the idea that they're clocked in/out at the same time.
It didn't occur to me that there would be a difference between recieve-complete and send-complete in this situation, but I see what you mean about the 1/2 Sclk difference. That could have been part of the issue.
Anyway, this issue is on hold for me since it's not pressing. I will post a cut-down example when I get a chance.
Finally had a chance to update this issue. I've created a minimal example to demo this issue here:
https://u59343634.dl.dropboxusercontent.com/u/59343634/Minimal%20SPI%20Issue%20Demo.zip
This project just sets up SPI1 and attempts to talk to a device on the other end. To recap, the current issues I'm seeing are:
1) The received bytes have to be read manually from POPR, they don't appear in the user-supplied receive buffer
2) A mysterious 10ms delay is necessary between transmit and receive.
Thanks,
Alex
Hi Alex,
Please send us your demo project rather than a piece of code.
you posted a SPI setting screenshot, what is it related with your original question?
Jennie
Hi Jennie
Just wanted to bump this issue - I've uploaded a demo project to reproduce the issue. I don't know if you'll be able to reproduce without having another SPI device attached, but at least you can take a look.
EOQ (end of queue) IS NOT a 'receive complete' flag. That is a 'TX-FIFO flag' block-send can use. Receive-data-available is RFDF. As for CS, look into the CONT bit-setting to keep CS 'active' between 'parts' of an otherwise contiguous set of SPI transfers.