Dumb SPI question

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

Dumb SPI question

364 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mubes on Sat Nov 23 17:13:23 MST 2013
Help!

I've got a simple SPI configuration problem, but I can't see the wood for the trees....in its distilled form, I've produced it below just using loopback to send an output back into the input again, and I've pulled the register setting apart just to make it all slightly more obvious what I'm doing.

The problem is that I can only read back 0x01FF0000 from the RXDAT register...but then it gets confusing. If I go to the LPCExpresso Peripheral Browser I _do_ see the correct value for RXDAT (i.e. incrementing), but if I look at memory location 0x40058014 in LPCExpresso I see the value that I am reading back....this is deeply confusing to me.

I'm not expecting instant answers or anything, but this is the second evening I've spent battling this and I'd really appreciate a few pointers where to look next.  I'm 100% sure it'll be a facepalm when I find it, but can I the hell as like get to the bottom of it at the moment...

If it's useful to anyone I'll produce an executable version of the code below so you can experience the problem for yourself.  Board is in standard config and I've reproduced the problem both on an LPCExpresso and my own 812 based board.  Only very slightly odd thing is that I'm using the internal oscillator, but I can't understand why that would cause a problem.

Thanks in advance for any pointers.

DAVE


#include "config.h"
#include "printf.h"

#define SPIPORT LPC_SPI0
#define SPI_FRAMELEN  15

static volatile uint32_t rxedData=0;


void spiInit(void)

{
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<11); // Enable SPI0
LPC_SYSCON->PRESETCTRL &= ~(1<<0);
LPC_SYSCON->PRESETCTRL |= (1<<0);// Reset SPI0

LPC_SWM->PINASSIGN3=(LPC_SWM->PINASSIGN3&0x00FFFFFF)|(8<<24); // CLK on P0_8
LPC_SWM->PINASSIGN4=(LPC_SWM->PINASSIGN4&0xFF000000);
LPC_SWM->PINASSIGN4|=(9<<16);
LPC_SWM->PINASSIGN4|=(15<<8); // CS on P0_9, MISO on P0_15
LPC_SWM->PINASSIGN4|=(1<<0);// MOSI on P0_1

SPIPORT->DIV=1000;  // Don't need anything too fast - there's not much else going on!
SPIPORT->DLY=0;
SPIPORT->CFG=0;

SPIPORT->CFG=(1<<0)|(1<<2)|(1<<7);   // Enabled, master mode,
}
// ============================================================================================
void spiGet_sample(void)

{
static uint32_t i=0;

while (1)
{
// This will trigger a reception - we don't care about the sent data
SPIPORT->TXDATCTL=i++|(SPI_FRAMELEN<<24)|(1<<20)|(1<<21);
while (!(SPIPORT->STAT&1));
rxedData=SPIPORT->RXDAT;
printf("%X\n",rxedData);
}
}
Labels (1)
0 Kudos
4 Replies

311 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mubes on Sun Nov 24 13:30:35 MST 2013
Nope, it's facepalm time.  In case anyone else encounters a similar problem....

Although I'm not using the crystal (and running at 12MHz directly from the Internal Osc) the startup code was still connecting the XTAL pins to the PLL....so I was using P0_8 for two functions; XTAL and CLK Out.  Strangely the CLK was coming out perfectly, but bits of the chip were obviously not talking to each other properly internally with the very very odd results I saw.

All sorted now...thanks to Noah for the sounding board and suggestion for a direction to investigate.

One other gotchya for people to be aware of - the loopback only appears to work if you've got a pin defined for both  MISO and MOSI....it's not done 'internally' so to speak.

Final code, released to public domain, is below, for archival purposes and in case it's useful to someone. This reads samples from a MAX6675 thermocouple sensor.

DAVE

#include "config.h"
#include "flags.h"
#include "uart.h"
#include "printf.h"

#ifdef SENSOR_THERMOCOUPLE

#define SPIPORT   LPC_SPI0
#define SPI_CLK    8
#define SPI_MISO   15
#define SPI_SEL   9
#define SPI_FRAMELEN  15

static volatile uint32_t rxedData=0;

// ============================================================================================
void SPI0_IRQHandler(void)

{
rxedData=SPIPORT->RXDAT;
uartPuti(rxedData,UART_BASE_HEX);
flag_post(FLAG_GOTTEMP);
}
// ============================================================================================
// ============================================================================================
// ============================================================================================
// Externally available routines
// ============================================================================================
// ============================================================================================
// ============================================================================================
void spiInit(void)

{
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<11); // Enable SPI0
LPC_SYSCON->PRESETCTRL &= ~(1<<0);
LPC_SYSCON->PRESETCTRL |= (1<<0);// Reset SPI0

LPC_SWM->PINASSIGN3=(LPC_SWM->PINASSIGN3&0x00FFFFFF)|(SPI_CLK<<24);
LPC_SWM->PINASSIGN4=(LPC_SWM->PINASSIGN4&0xFF0000FF)|(SPI_SEL<<16)|(SPI_MISO<<8);

SPIPORT->DIV=1000;  // Don't need anything too fast - there's not much else going on!
SPIPORT->DLY=0;
SPIPORT->INTENSET=(1<<0);  // Interrupt on RX data available
NVIC_DisableIRQ(SPI0_IRQn);
NVIC_ClearPendingIRQ(SPI0_IRQn);
NVIC_EnableIRQ(SPI0_IRQn);
SPIPORT->CFG=(1<<0)|(1<<2);   // Enabled, master mode
}
// ============================================================================================
void spiGet_sample(void)

{
// This will trigger a reception - we don't care about the sent data
SPIPORT->TXDATCTL=(SPI_FRAMELEN<<24)|(1<<20)|(1<<21);
}
// ============================================================================================
uint32_t spiResult(void)

{
return rxedData;
}
// ============================================================================================
#endif

0 Kudos

311 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mubes on Sun Nov 24 08:20:48 MST 2013
In case anyone is looking at this, I think I've cracked it. Noahs comment about the CLK set me thinking. If I move the CLK away from pin 8 then I seem to get valid readings. Will investigate further and report back later, but the hypothesis is that you can't put the SPI clock onto pin 8, even when you're not using an XTAL. This might be documented somewhere that I've not paid attention to... Wonder if NXP offers a bug bounty? :-)

DAVE
0 Kudos

311 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by mubes on Sun Nov 24 02:16:12 MST 2013
Hi Noah,

Thanks for the reply.

Yup, I've got Clocks and SEL coming out perfectly, with various DLY settings etc...no problems at all.  When the peripheral is connected (a simple thermocouple ADC) I get sane readings out of its DO (MISO) pin.  If I short the MISO pin to 0V or Vcc on the CPU I don't get any change in output reading though in the software.  I switched over to loopback because it shows the same problem but doesn't require anyone to set up any additional hardware.

I feel pretty dumb not being able to sort this one, and I'm not looking forwards to a third evening of chasing it down :-(

DAVE
0 Kudos

311 Views
lpcware
NXP Employee
NXP Employee
Content originally posted in LPCWare by noahk on Sat Nov 23 19:08:36 MST 2013
Hi Dave,

Can you verify that the clock appears on P0_8? I believe loopback mode only connects data, but the slave select and clock must be routed to and back from the pads. If that doesn't work that could explain what you are seeing. You could try changing pin assignment for the clock and see if that helps.

Noah
0 Kudos