SPI Configuration Problem in LPC 1777

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

SPI Configuration Problem in LPC 1777

1,141 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by anandana on Thu Nov 28 00:13:23 MST 2013
Hi,

I am trying to configure SPI in LPC1777 as per chapter 17. But after configuring that I am getting Hard fault error. Here I have attached my pieace of code. Please suggest how i can proceed..

#define LPC_APB0_BASE         (0x40000000UL)
#define LPC_SPI_BASE(LPC_APB0_BASE+0x20000)
#define LPC_SPI((LPC_SPI_TypeDef*)LPC_SPI_BASE )

LPC_SC->PCONP=  0x0508939E; 8th bit high to enable SPI

LPC_IOCON->P0_15  |= 3;
LPC_IOCON->P0_18  |= 3;

typedef struct
{
  __IO uint32_t SPCR;
  __I  uint32_t SPSR;
  __IO uint32_t SPDR;
  __IO uint32_t SPCCR;
  __IO uint32_t SPTCR;
       uint32_t RESERVED0[2];
  __IO uint32_t SPINT;
} LPC_SPI_TypeDef;

LPC_SPI->SPCR = 0x00000820;             //1010  0100
LPC_SPI->SPCCR = 0x00000008; 

When it reaches the above instucion it goes to Hard fault error.

Please somebody help me if there is any error..






Labels (1)
0 Kudos
12 Replies

905 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by anandana on Fri Nov 29 07:48:22 MST 2013
Hi,

Thank U, definitely I will use ur suggestions.

I have one dount... In LPC2468IRC,  IRC stands for what?

This is the way I configured SPI in 1777 for master mode.

void SPI0Enable(void)
{
     LPC_SSP0->CR0=0x00000007;  //8bit and master mode
     LPC_SSP0->CR1=0x00000002;   // SSE High
     LPC_SSP0->CPSR=0x00000008;  //Clock
}


void SPI0Send(unsigned char TxDat)  //write command 
{
        LPC_SSP0->DR = TxDat;                             //8 Bit Data;
        for(;(LPC_SSP0->SR&0x10)==0x10;);          //Wait loop for Busy
}


Regards
Anandan A
0 Kudos

905 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by Pacman on Thu Nov 28 17:17:54 MST 2013
I have a strong advice about hex-values
Please use the #defines from the library header files.
You don't need to compile any library .c files in order to use the header files.
But hex-values are completely unreadable; especially when you ask other people for help, the hex values have to be decoded first, then checked.

So 0x10 and (1 << 4) should really be replaced by the #define that you find in the header files.

When you're returning to your source code after a one month break, you will surely wonder what the hex values mean.
Perhaps the comment helps you, but if there is a bug somewhere, and you really want to find the bug, it will be much quicker to just rewrite everything from scratch.

-And in addition to what wmues writes below...

It's a fairly good idea to put constants on the left hand side of '==', as sometimes you will experience that you might not hit the '=' twice...

while(a = 10)
{
...
}


The above will build just fine and code will seem to run as you intended it to.
For a while maybe.

Perhaps you wanted to write ==, perhaps you wanted to write >= or <=, maybe even !=.
If you start putting constants on the left side of the '=', you'll get a compile-error, when you try to build this:

while(10 = a)
{
...
}


...so that will help you catch those kind of errors immediately.
0 Kudos

905 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by wmues on Thu Nov 28 14:13:16 MST 2013
Hmmm...

while((LPC_SSP0->SR & 0x10) != 0); Checking for Busy stae..


In C, every value != 0 is true. So you write

while(LPC_SSP0->SR & 0x10)


More elegance, less characters, less errors.

Programming is art.
0 Kudos

905 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by capiman on Thu Nov 28 04:46:23 MST 2013
Hi Anandana,

congratulation! It was a pleasure for me to help you!

Can you perhaps share your working version, so others can find this version, when they are looking into this thread?

Many thanks!

Best regards,

Martin

0 Kudos

905 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by anandana on Thu Nov 28 04:42:33 MST 2013
Hi Martin,

      Thanks for ur inputs. Actually I made a mistake in CR1. Now I enabled SSE bit in CR1 register. Now it is working fine.. Thank u very much for immediate responses..

Regards
Anandan A
0 Kudos

905 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by capiman on Thu Nov 28 03:52:02 MST 2013
Can you post what values your SSP registers (especially configuration registers) contain?
0 Kudos

905 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by anandana on Thu Nov 28 03:43:28 MST 2013
Hi,

I am configuring master to Slave communication only and I have changed the code as per ur suggestion.  No data and no clock signal is coming.

Regards
Anandan A
0 Kudos

905 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by capiman on Thu Nov 28 02:43:46 MST 2013
Please also check the real values and bits you write to CR0 and CR1
0 Kudos

905 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by capiman on Thu Nov 28 02:38:22 MST 2013
Only some quick hints:
- Have you perhaps forgotten P0_17?
- I usually control SSEL (as GPIO) by myself
- This does not work:

for(;LPC_SSP0->SR==0x10;); Checking for Busy stae..

You are not only getting one bit (0x10), bot usually also other bits.
You must "and" the bits out, e.g.

for(;(LPC_SSP0->SR & 0x10) == 0x10;); Checking for Busy stae..

I usually write

for(;(LPC_SSP0->SR & 0x10) != 0;); Checking for Busy stae..

or even

while((LPC_SSP0->SR & 0x10) != 0); Checking for Busy stae..

Note: I have not checked if bit number and polarity is something valid.

- This could be dangerous:

LPC_IOCON->P0_15 |= 2;

Why not set it? E.g. when (some of the) bits were already set (e.g. previous configuration was value 1, then you get 3 instead of 2):

LPC_IOCON->P0_15 = 2;

BTW: What is not working? Do you see the clock? Do you see outgoing data? Do you get incoming data?

0 Kudos

905 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by anandana on Thu Nov 28 02:26:13 MST 2013
Hi Martin,
Thank U for ur response. U r right, Actually I was using UM LPC17xx. Now I configured SSP0 in SPI mode. But still it is not working.. Here i am giving the configuration details. Please check and tell if anything is wrong.

(LPC_SC->PCONP) =  0x0528929E; //21st bit is high to enable SSP0  


LPC_IOCON->P0_15  |= 2;
LPC_IOCON->P0_16  |= 2;
LPC_IOCON->P0_18  |= 2;

void SSP_ConfigStructInit(SSP_CFG_Type *SSP_InitStruct)
{
SSP_InitStruct->CPHA = SSP_CPHA_FIRST;    //0
SSP_InitStruct->CPOL = SSP_CPOL_HI;          //0
SSP_InitStruct->ClockRate = 1000000;                      //1 Mhz
SSP_InitStruct->Databit = SSP_DATABIT_8;    //8 8bit data length
SSP_InitStruct->Mode = SSP_MASTER_MODE;    //0 Master Mode
SSP_InitStruct->FrameFormat = SSP_FRAME_SPI;  //Motorola SPI Mode
}


void SSP_Init(LPC_SSP_TypeDef *SSPx, SSP_CFG_Type *SSP_ConfigStruct)
{
uint32_t tmp;

/* Configure SSP, interrupt is disable, LoopBack mode is disable,
* SSP is disable, Slave output is disable as default
*/
tmp = ((SSP_ConfigStruct->CPHA) | (SSP_ConfigStruct->CPOL) \
| (SSP_ConfigStruct->FrameFormat) | (SSP_ConfigStruct->Databit))
& SSP_CR0_BITMASK;
// write back to SSP control register
SSPx->CR0 = tmp;

tmp = SSP_ConfigStruct->Mode & SSP_CR1_BITMASK;
// Write back to CR1
SSPx->CR1 = tmp;

// Set clock rate for SSP peripheral
setSSPclock(SSPx, SSP_ConfigStruct->ClockRate);
}


static void setSSPclock (LPC_SSP_TypeDef *SSPx, uint32_t target_clock)
{
    uint32_t prescale, cr0_div, cmp_clk, ssp_clk;
//    ssp_clk = PeripheralClock;

/* Find closest divider to get at or under the target frequency.
   Use smallest prescale possible and rely on the divider to get
   the closest target frequency */
cr0_div = 0;
cmp_clk = 0xFFFFFFFF;
prescale = 2;
while (cmp_clk > target_clock)
{
cmp_clk = ssp_clk / ((cr0_div + 1) * prescale);
if (cmp_clk > target_clock)
{
cr0_div++;
if (cr0_div > 0xFF)
{
cr0_div = 0;   prescale += 2;
}
}
}

    /* Write computed prescaler and divider back to register */
    SSPx->CR0 &= ~(SSP_CR0_SCR(0xFF)) & SSP_CR0_BITMASK;
    SSPx->CR0 |= (SSP_CR0_SCR(cr0_div)) & SSP_CR0_BITMASK;
    SSPx->CPSR = prescale & SSP_CPSR_BITMASK;
}


void SPI0Send(unsigned char TxDat)  //write command 
{


LPC_SSP0->DR = 0xAA;
for(;LPC_SSP0->SR==0x10;);   Checking for Busy stae..
}


My code struck in above mentioned for loop.. Busy bit not cleared in SR register..

Please check and tell me

Regards
Anandan
0 Kudos

905 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by anandana on Thu Nov 28 02:25:38 MST 2013
Hi Martin,
Thank U for ur response. U r right, Actually I was using UM LPC17xx. Now I configured SSP0 in SPI mode. But still it is not working.. Here i am giving the configuration details. Please check and tell if anything is wrong.

(LPC_SC->PCONP) =  0x0528929E; //21st bit is high to enable SSP0  


LPC_IOCON->P0_15  |= 2;
LPC_IOCON->P0_16  |= 2;
LPC_IOCON->P0_18  |= 2;

void SSP_ConfigStructInit(SSP_CFG_Type *SSP_InitStruct)
{
SSP_InitStruct->CPHA = SSP_CPHA_FIRST;    //0
SSP_InitStruct->CPOL = SSP_CPOL_HI;          //0
SSP_InitStruct->ClockRate = 1000000;                      //1 Mhz
SSP_InitStruct->Databit = SSP_DATABIT_8;    //8 8bit data length
SSP_InitStruct->Mode = SSP_MASTER_MODE;    //0 Master Mode
SSP_InitStruct->FrameFormat = SSP_FRAME_SPI;  //Motorola SPI Mode
}


void SSP_Init(LPC_SSP_TypeDef *SSPx, SSP_CFG_Type *SSP_ConfigStruct)
{
uint32_t tmp;

/* Configure SSP, interrupt is disable, LoopBack mode is disable,
* SSP is disable, Slave output is disable as default
*/
tmp = ((SSP_ConfigStruct->CPHA) | (SSP_ConfigStruct->CPOL) \
| (SSP_ConfigStruct->FrameFormat) | (SSP_ConfigStruct->Databit))
& SSP_CR0_BITMASK;
// write back to SSP control register
SSPx->CR0 = tmp;

tmp = SSP_ConfigStruct->Mode & SSP_CR1_BITMASK;
// Write back to CR1
SSPx->CR1 = tmp;

// Set clock rate for SSP peripheral
setSSPclock(SSPx, SSP_ConfigStruct->ClockRate);
}


static void setSSPclock (LPC_SSP_TypeDef *SSPx, uint32_t target_clock)
{
    uint32_t prescale, cr0_div, cmp_clk, ssp_clk;
//    ssp_clk = PeripheralClock;

/* Find closest divider to get at or under the target frequency.
   Use smallest prescale possible and rely on the divider to get
   the closest target frequency */
cr0_div = 0;
cmp_clk = 0xFFFFFFFF;
prescale = 2;
while (cmp_clk > target_clock)
{
cmp_clk = ssp_clk / ((cr0_div + 1) * prescale);
if (cmp_clk > target_clock)
{
cr0_div++;
if (cr0_div > 0xFF)
{
cr0_div = 0;   prescale += 2;
}
}
}

    /* Write computed prescaler and divider back to register */
    SSPx->CR0 &= ~(SSP_CR0_SCR(0xFF)) & SSP_CR0_BITMASK;
    SSPx->CR0 |= (SSP_CR0_SCR(cr0_div)) & SSP_CR0_BITMASK;
    SSPx->CPSR = prescale & SSP_CPSR_BITMASK;
}


void SPI0Send(unsigned char TxDat)  //write command 
{


LPC_SSP0->DR = 0xAA;
for(;LPC_SSP0->SR==0x10;);   Checking for Busy stae..
}


My code hangs in above mentioned for loop.. Busy bit not cleared in SR register..

Please check and tell me

Regards
Anandan
0 Kudos

905 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by capiman on Thu Nov 28 00:21:20 MST 2013
Hello Anandana,

there is a user manual for LPC1777, which is different from user manual for LPC17xx.
Especially the chapter for SPI is not contained in UM of LPC1777.
You can use SSP instead. SSP is located on different addresses
and perhaps (please check yourself) has different registers and/or different bits inside the registers.

Best regards,

Martin
0 Kudos