LPCopen Sdcard on LPC15xx

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

LPCopen Sdcard on LPC15xx

1,022 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by bobi-one on Tue Apr 08 04:08:41 MST 2014
Have someone used sdcard with lpc open files on the new micro controllers?
Regards,
Boyko
Labels (1)
0 Kudos
12 Replies

826 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Gideon196 on Wed Apr 23 15:29:59 MST 2014
It isn't specifically the _WFI() that is deprecated.  It's invoking and waiting for a lengthy interrupt driven process from another interrupt service routine that's the issue.  At minimum, such a design requires nested interrupts, careful tuning of interrupt priorities and exhaustive design review to make sure the rest of the system has adequate interrupt latency/response times.

But this is a separate issue from the 13uS delay between frames.  Because it works at all (it doesn't hang) the interrupt priorities must be OK--the SPI interrupt is able to interrupt the RIT interrupt service routine.

You might try using Chip_SPI_RWFrames_Blocking() instead of Chip_SPI_Int_RWFrames().  The transfers  in this function are done using polling techniques rather than being interrupt driven.

This approach will still spend longer in the RIT interrupt service routine than I would recommend (the duration of two SPI frames), but I would like to find out if this reduces the delay between frames.
0 Kudos

826 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by bobi-one on Wed Apr 23 00:10:14 MST 2014
Hi,
I removed the  _WFI loop but it wasnt the cause for the delay. The time between two byte excnage is still around 13uS which is too much.  Perhaps a new optimised instance of Chip_SPI_Int_RWFrames  must be created
Status Chip_SPI_Int_RWFrames(LPC_SPI_T *pSPI, SPI_DATA_SETUP_T *pXfSetup)
{
uint32_t Status;

Status = Chip_SPI_GetStatus(pSPI);
/* Check  error in STAT register */
if (Status & (SPI_STAT_RXOV | SPI_STAT_TXUR)) {
/* Clear errors */
Chip_SPI_ClearStatus(pSPI, SPI_STAT_CLR_RXOV | SPI_STAT_CLR_TXUR);
return ERROR;
}

if (pXfSetup->TxCnt == 0) {
if (pXfSetup->pRx == NULL) {
Chip_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, pXfSetup->ssel | SPI_TXCTL_EOF | SPI_TXCTL_RXIGNORE);
}
else {
Chip_SPI_SetControlInfo(pSPI, pXfSetup->DataSize, pXfSetup->ssel | SPI_TXCTL_EOF);
}
}

if (pXfSetup->pRx == NULL) {
if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
SPI_Send_Data_RxIgnore(pSPI, pXfSetup);
}
}
else {
/* check if Tx ready */
if ((Status & SPI_STAT_TXRDY) && (pXfSetup->TxCnt < pXfSetup->Length)) {
SPI_Send_Data(pSPI, pXfSetup);
}

/* check if RX FIFO contains data */
if ((Status & SPI_STAT_RXRDY) && (pXfSetup->RxCnt < pXfSetup->Length)) {
SPI_Receive_Data(pSPI, pXfSetup);
}
}

return SUCCESS;
}
0 Kudos

826 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Gideon196 on Tue Apr 22 10:42:29 MST 2014
The simple byte exchange method seems fine.

It should continue to work fine on LPC1549 and LPC open 2.x.  Your approach is good.
0 Kudos

826 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Gideon196 on Tue Apr 22 09:40:22 MST 2014
Hello Boyko,

SPIRecieveByte() isn't really designed to be called from interrupt context.  Notice that at the end of WriteSpiMssg() (called by SPIReceiveByte()) there is a while loop that calls __WFI().  That's usually a bad thing to do in an ISR.

It might be possible to get this to work.  The SPI interrupt will need to be at a higher priority than the RIT.  But such a design is usually deprecated.

I hope this helps!
0 Kudos

826 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by bobi-one on Tue Apr 22 00:31:30 MST 2014
Hi
I tried the changes to the code,
but sending two bytes brings a lot of delay between the two transmissions
here i am calling it with a RIT interrupt and there is significant delay between the two bytes. ( probably because the spi submits  16 bits)
void RIT_IRQHandler(void)
{
/* Clear interrupt */
Chip_RIT_ClearIntStatus(LPC_RITIMER);
SPIReceiveByte(0xBB);
SPIReceiveByte(0xCC);
}
Regards,
Boyko
0 Kudos

826 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by capiman on Sat Apr 19 04:07:08 MST 2014
Hi,
sorry, I have not used the LPC1549 before, but what is so different to LPC1343? The SPI itself is usually not so different, therefore easy to port.
And SPI is only a very small part of the complete SD-Card implemention. Which problem occured?
Best regards,
Martin
0 Kudos

826 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by bobi-one on Sat Apr 19 03:32:33 MST 2014
Hi, I have sd lib that i used with my lpc1343. The core of its structure was simple byte exchange(spi send and receive) . but now when i migrated to lpc1549 and lpc open (2.08b) things are done differently.
0 Kudos

826 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Gideon196 on Fri Apr 18 14:16:03 MST 2014
Is the sd card lib supplied by NXP?  (If so, what version? Which device?)

Also, which version/device of LPC Open?
0 Kudos

826 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by bobi-one on Fri Apr 18 12:07:07 MST 2014
Thanks for the answer. Otherwise said the sd card lib cannot be made to work effectivly with the spi from lpc ooen lib.
Regards,
Boyko
0 Kudos

826 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Gideon196 on Fri Apr 18 10:04:44 MST 2014
In other words...  the Chip_SPI_xxx routines operate on 16 bit words (uint16_t), not 8 bit bytes (uint8_t).
0 Kudos

826 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Gideon196 on Thu Apr 17 17:46:10 MST 2014
Greetings Boyko,

My guess is you are getting compile errors.

Notice that the structure members spi1Setup.pTx and spi1Setup.pRx are pointers to uint16_t not uint8_t (word pointers not byte pointers).

Likewise the xferPtr parameter to WriteSpiMssg() is a pointer to a uint16_t (not uint8_t).

The array rx_buff[] is defined as an array of type uint8_t.

To get this to compile, try these changes...

//   This needs to be an array of words...
//
uint16_t rx_buff[100];

<snip>

//   Note the type changes here as well...
//
uint8_t SPIReceiveByte(uint8_t data)
{
//   Must send a pointer to a word to WriteSpiMssg.
// put the value to send in a word.
//
uint16_t wordToSend = data;

//   Pass the address of wordToSend (the pointer to wordToSend).
// 
WriteSpiMssg( &wordToSend, 1);

return (uint8_t) rx_buff[0];
}


I don't expect this to fix everything.  But it will at least get it to compile.  You then probably have some debug to do.

Good luck!
0 Kudos

826 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by bobi-one on Thu Apr 17 06:30:32 MST 2014
If this is the prototype for  SPI function in LPC open:
/* Interrupt error code (used as semaphore) */
static volatile int intErrCode;
/* SPI Transfer Setup */
static SPI_DATA_SETUP_T spi1Setup;
uint8_t rx_buff[100];
 void WriteSpiMssg(uint16_t *xferPtr, uint32_t xferSize)
 {
 /* Init variable used as semaphore */
 intErrCode = -1;
 // Setup Transfer structure, this data should be retained for the entire transmission
 spi1Setup.pTx = xferPtr;//Transmit Buffer
 spi1Setup.pRx = rx_buff;//Receive Buffer
 spi1Setup.DataSize =8;//Data size ( bits)
 spi1Setup.Length = xferSize;//total frame length
 spi1Setup.ssel = SPI_TXCTL_ASSERT_SSEL0 | SPI_TXCTL_DEASSERT_SSEL1 | SPI_TXCTL_DEASSERT_SSEL2 | SPI_TXCTL_DEASSERT_SSEL3; //assert SSEL0
 spi1Setup.TxCnt = 0;
 spi1Setup.RxCnt = 0;
 if (Chip_SPI_Int_RWFrames(LPC_SPI1, &spi1Setup) == ERROR) {
 errorSPI();
 }
 
 Chip_SPI_Int_Cmd(LPC_SPI1, SPI_INTENSET_RXRDYEN | SPI_INTENSET_TXRDYEN | SPI_INTENSET_RXOVEN | SPI_INTENSET_TXUREN, ENABLE);
 // Enable Interrupt when receiver data is available
 // Enable Interrupt when the transmitter holding register is available.
 // Enable Interrupt when a receiver overrun occurs
 // Enable Interrupt when a transmitter underrun occurs (In Slave Mode Only)

 /* Sleep until transfer is complete, but allow IRQ to wake system
    to handle SPI IRQ */
 while (intErrCode == -1) {
 __WFI();
 }
 uint8_t SPIReceiveByte(uint8_t data)
 {
 WriteSpiMssg(data, 1);

  return *rx_buff;
 }

 void SPI1_IRQHandler(void)
 {
 uint32_t i;

 if (spi1Setup.RxCnt < spi1Setup.Length) {
 /* Call driver function until transmission is complete */
 if (Chip_SPI_Int_RWFrames(LPC_SPI1, &spi1Setup) == ERROR) {
 errorSPI();
 }
 }
 else {
 /* Disable interrupts after transmission is complete */
 Chip_SPI_Int_Cmd(LPC_SPI1, SPI_INTENSET_RXRDYEN | SPI_INTENSET_TXRDYEN | SPI_INTENSET_RXOVEN | SPI_INTENSET_TXUREN, DISABLE);
  
 intErrCode = (int) LPC_OK;
 }
 }
 }

Why simple byte exchange like the one  below doesn't work?
 uint8_t SPIReceiveByte(uint8_t data)
 {
 WriteSpiMssg(data, 1);

return *rx_buff;
 }


I am sorry if it is something obvious but when it gets to pointers and arrays my head gets dizzy.  SPIReceiveByte is the core of my working sdcard library (at least it was working with lpc1343).
I will appreciate any assistance or guidance how i can get my code up and running.
Regards,
Boyko
0 Kudos