I know, this is not Keil related (well sort of, I use the tools :) but I know there are a lot of people here with a lot of knowledge!
Device is a LPC11C24 which is connected to a SD card using SSP1 (CS is done "manually", not using SSEL functionality).
I have used some of the example code for the TX and RX routines (non interrupt driven), and for some odd reason I can get both functions to lock up!
The transmit and receive routines:
void sspSend (uint8_t *buf, uint32_t length) { uint32_t i; uint8_t Dummy = Dummy; for (i = 0; i < length; i++) { /* Move on only if NOT busy and TX FIFO not full. */ while ((LPC_SSP1->SR & (SSP_SR_TNF_NOTFULL | SSP_SR_BSY_BUSY)) != SSP_SR_TNF_NOTFULL); LPC_SSP1->DR = *buf; buf++; // !!!! while ( (LPC_SSP1->SR & (SSP_SR_BSY_BUSY|SSP_SR_RNE_NOTEMPTY)) != SSP_SR_RNE_NOTEMPTY ); while ((LPC_SSP1->SR & SSP_SR_BSY_BUSY)); /* Whenever a byte is written, MISO FIFO counter increments, Clear FIFO on MISO. Otherwise, when sspReceive is called, previous data byte is left in the FIFO. */ Dummy = LPC_SSP1->DR; } return; } void sspReceive(uint8_t *buf, uint32_t length) { uint32_t i; for ( i = 0; i < length; i++ ) { /* As long as the receive FIFO is not empty, data can be received. */ LPC_SSP1->DR = 0xFF; /* Wait until the Busy bit is cleared */ // !!!! while ( (LPC_SSP1->SR & (SSP_SR_BSY_BUSY|SSP_SR_RNE_NOTEMPTY)) != SSP_SR_RNE_NOTEMPTY ); while ((LPC_SSP1->SR & SSP_SR_BSY_BUSY)); *buf = LPC_SSP1->DR; buf++; } return; }
If the original example code is used (the code after // !!!!) they will once in a while, lock up. However, if I only use the SSP_SR_BSY_BUSY flag they both work perfectly (AFAIK) I have had a counter increment in the while loop, and I can see that some time elapses (as it should) waiting for the BSY bit to become 0.
So, basically what I'm saying is the code is working (now) with the modified while loop, but I don't feel too comfortable as all the examples I have found uses the original while loop (looking at the TNF/RNE bit together with the BSY bit).
No one seeing the same/having any ideas of what could be wrong ?
while ( (LPC_SSP1->SR & (SSP_SR_BSY_BUSY|SSP_SR_RNE_NOTEMPTY)) != SSP_SR_RNE_NOTEMPTY ); means you want anything but RNE to be cleared.
while ((LPC_SSP1->SR & SSP_SR_BSY_BUSY)); means you want only BUSY to be cleared.
----------------------------------------------> My mistake.
Thanks John, I know what the code does in both cases. What puzzles me is why the original code (that also comes with all the samples etc) will stop working at some point. If I only check the BUSY bit will it continue to work.
My guess:
1. You sspSend() n Bytes. 2. You sspReceive() m Bytes. 3. When you are doing
void sspReceive(uint8_t *buf, uint32_t length) { LPC_SSP1->DR = 0xFF;
FIFO is still full. So you can only receive (m-k) Bytes. 4. When you are doing
while ( (LPC_SSP1->SR & (SSP_SR_BSY_BUSY|SSP_SR_RNE_NOTEMPTY)) != SSP_SR_RNE_NOTEMPTY );
SSP is not busy, but FIFO keeps empty.
Maybe try:
while ( LPC_SSP1->SR & SSP_SR_BSY_BUSY ) { /* Do some check. */ } while ( ! ( LPC_SSP1->SR & SSP_SR_RNE_NOTEMPTY ) ) { /* Do some check. */ }