I have a problem with a simple SPI example program. Part: LPC2129 PCK: 14.7 MHz Mode: Master, CPOL=0, CPHA=0, LSIF=0. I initialise the SPI like this:- void SPI_Init(void) { S0SPCCR = 0x26; // Divides PCK to give about 400kHz S0SPCR = 0x20; // Select Master mode } And then use the SPI like this:- void SPI_Transfer( char *buf, int count) { int r = 0, i = 0; for( ; i < count; i++ ) { S0SPDR = buf[i]; // Write data do{ r = S0SPSR; }while(!(r & 0x80));// Wait for SPIF // Read status - to be done buf[i] = S0SPDR; // Read data } } Sometimes I power up the device and this function runs correctly with problem whatsoever. Other times the function just hangs. If I attach a JTAG debugger (Keil ULINK) I find that the function is hanging at the line "do{ r = S0SPSR; }while(!(r & 0x80));" on the first itteration. There is no hardware attached to the SPI port. I figured that the device should put data out onto an unconnected pin without any problem and that I should be able to get the software working before thinking about ading hardware. Has anyone got any ideas what might be going wrong? Thanks, Paul
SPI Code hangs
Started by ●March 8, 2006
Reply by ●March 8, 20062006-03-08
brightside_design wrote: >I have a problem with a simple SPI example program. >Part: LPC2129 >PCK: 14.7 MHz >Mode: Master, CPOL=0, CPHA=0, LSIF=0. > >I initialise the SPI like this:- >void SPI_Init(void) > { > S0SPCCR = 0x26; // Divides PCK to give about 400kHz > S0SPCR = 0x20; // Select Master mode > } > >And then use the SPI like this:- >void SPI_Transfer( char *buf, int count) >{ > int r = 0, i = 0; > > for( ; i < count; i++ ) > { > S0SPDR = buf[i]; // Write data > do{ r = S0SPSR; }while(!(r & 0x80));// Wait for SPIF > // Read status - to be done > buf[i] = S0SPDR; // Read data > } >} > > > Try writing it this way: void SPI_Transfer( char *buf, int count) { volatile int r = 0; volatile int i = 0; for( ; i < count; i++ ) { S0SPDR = buf[i]; // Write data do{ r = S0SPSR; }while(!(r & 0x80));// Wait for SPIF // Read status - to be done buf[i] = S0SPDR; // Read data } } If you look deeper at the underlying assembly language via the JTAG, I'm fairly confident you will find that it reads "r" once, then loops on the resultant value. Essentially, the volatile keyword tells the compiler to assume nothing about the variables' value it holds, to actually check it rather than to optimize the reference. YMMV, but your function would probably work if you turned off all optimizations (-O0). TomW >Sometimes I power up the device and this function runs correctly >with problem whatsoever. Other times the function just hangs. If I >attach a JTAG debugger (Keil ULINK) I find that the function is >hanging at the line "do{ r = S0SPSR; }while(!(r & 0x80));" on the >first itteration. > >There is no hardware attached to the SPI port. I figured that the >device should put data out onto an unconnected pin without any >problem and that I should be able to get the software working before >thinking about ading hardware. > >Has anyone got any ideas what might be going wrong? > >Thanks, > >Paul > > > > > > >Yahoo! Groups Links > > > > > > > > > -- Tom Walsh - WN3L - Embedded Systems Consultant http://openhardware.net, http://cyberiansoftware.com "Windows? No thanks, I have work to do..." ----------------
Reply by ●March 9, 20062006-03-09
--- In lpc2000@lpc2..., Tom Walsh <tom@...> wrote: > > brightside_design wrote: > > >I have a problem with a simple SPI example program. > >Part: LPC2129 > >PCK: 14.7 MHz > >Mode: Master, CPOL=0, CPHA=0, LSIF=0. > > > >I initialise the SPI like this:- > >void SPI_Init(void) > > { > > S0SPCCR = 0x26; // Divides PCK to give about 400kHz > > S0SPCR = 0x20; // Select Master mode > > } > > > >And then use the SPI like this:- > >void SPI_Transfer( char *buf, int count) > >{ > > int r = 0, i = 0; > > > > for( ; i < count; i++ ) > > { > > S0SPDR = buf[i]; // Write data > > do{ r = S0SPSR; }while(!(r & 0x80));// Wait for SPIF > > // Read status - to be done > > buf[i] = S0SPDR; // Read data > > } > >} > > > > > > > > Try writing it this way: > > void SPI_Transfer( char *buf, int count) > { > volatile int r = 0; > volatile int i = 0; > for( ; i < count; i++ ) > { > S0SPDR = buf[i]; // Write data > do{ r = S0SPSR; }while(!(r & 0x80));// Wait for SPIF > // Read status - to be done > buf[i] = S0SPDR; // Read data > } > } > > > If you look deeper at the underlying assembly language via the JTAG, I'm > fairly confident you will find that it reads "r" once, then loops on the > resultant value. Essentially, the volatile keyword tells the compiler > to assume nothing about the variables' value it holds, to actually check > it rather than to optimize the reference. > > YMMV, but your function would probably work if you turned off all > optimizations (-O0). > > TomW > > > >Sometimes I power up the device and this function runs correctly > >with problem whatsoever. Other times the function just hangs. If I > >attach a JTAG debugger (Keil ULINK) I find that the function is > >hanging at the line "do{ r = S0SPSR; }while(!(r & 0x80));" on the > >first itteration. > > > >There is no hardware attached to the SPI port. I figured that the > >device should put data out onto an unconnected pin without any > >problem and that I should be able to get the software working before > >thinking about ading hardware. > > > >Has anyone got any ideas what might be going wrong? > > > >Thanks, > > > >Paul > > > -- > Tom Walsh - WN3L - Embedded Systems Consultant > http://openhardware.net, http://cyberiansoftware.com > "Windows? No thanks, I have work to do..." > ---------------- > Thanks Tom, I will try that when I have a moment but I don't think thats the answer. I've just read through the disassemby for that function and it is reading the register each time through. Also the problem is intermittant, sometimes it works fine, other times it hangs. Paul
Reply by ●March 9, 20062006-03-09
brightside_design wrote: >--- In lpc2000@lpc2..., Tom Walsh <tom@...> wrote: > > >>brightside_design wrote: >> >> >> >>>I have a problem with a simple SPI example program. >>>Part: LPC2129 >>>PCK: 14.7 MHz >>>Mode: Master, CPOL=0, CPHA=0, LSIF=0. >>> >>>I initialise the SPI like this:- >>>void SPI_Init(void) >>> { >>> S0SPCCR = 0x26; // Divides PCK to give about 400kHz >>> S0SPCR = 0x20; // Select Master mode >>> } >>> >>>And then use the SPI like this:- >>>void SPI_Transfer( char *buf, int count) >>>{ >>> int r = 0, i = 0; >>> >>> for( ; i < count; i++ ) >>> { >>> S0SPDR = buf[i]; // Write data >>> do{ r = S0SPSR; }while(!(r & 0x80));// Wait for SPIF >>> // Read status - to be done >>> buf[i] = S0SPDR; // Read data >>> } >>>} >>> >>> >>> >>> >>> >>Try writing it this way: >> >>void SPI_Transfer( char *buf, int count) >>{ >>volatile int r = 0; >>volatile int i = 0; >> for( ; i < count; i++ ) >> { >> S0SPDR = buf[i]; // Write data >> do{ r = S0SPSR; }while(!(r & 0x80));// Wait for SPIF >> // Read status - to be done >> buf[i] = S0SPDR; // Read data >> } >>} >> >> >>If you look deeper at the underlying assembly language via the >> >> >JTAG, I'm > > >>fairly confident you will find that it reads "r" once, then loops >> >> >on the > > >>resultant value. Essentially, the volatile keyword tells the >> >> >compiler > > >>to assume nothing about the variables' value it holds, to actually >> >> >check > > >>it rather than to optimize the reference. >> >>YMMV, but your function would probably work if you turned off all >>optimizations (-O0). >> >>TomW >> >> >> >> >>>Sometimes I power up the device and this function runs correctly >>>with problem whatsoever. Other times the function just hangs. If >>> >>> >I > > >>>attach a JTAG debugger (Keil ULINK) I find that the function is >>>hanging at the line "do{ r = S0SPSR; }while(!(r & 0x80));" on the >>>first itteration. >>> >>>There is no hardware attached to the SPI port. I figured that the >>>device should put data out onto an unconnected pin without any >>>problem and that I should be able to get the software working >>> >>> >before > > >>>thinking about ading hardware. >>> >>>Has anyone got any ideas what might be going wrong? >>> >>>Thanks, >>> >>>Paul >>> >>> >>-- >>Tom Walsh - WN3L - Embedded Systems Consultant >>http://openhardware.net, http://cyberiansoftware.com >>"Windows? No thanks, I have work to do..." >>---------------- >> >> >> > >Thanks Tom, I will try that when I have a moment but I don't think >thats the answer. I've just read through the disassemby for that >function and it is reading the register each time through. Also the >problem is intermittant, sometimes it works fine, other times it >hangs. > > > I have a state machine which is servicing three MAX3100 UARTS on the SPI circuit. The state machine steps are governed by the SPI interrupt. Each time an SPI interrupt fires, the state machine advances one step. The machine runs until all UARTS are "quiet", meaning nothing to transmit and nothing in the recievers. Then the machine shuts down. The state machine is driven by the SPI interrupt, however, the initial "kick-off" of putting the machine into motion is handled by two external conditions: 1) EXTINT0 is triggered by a wired-OR of the IRQ output of the MAX3100's (interrupt asserted only on RX data available). 2) Data has been entered into one of the transmit queues. In which case, the EXTINT0 ISR is soft triggered via VICSoftInt bit. That is the structure of my ISR and it's relation to the other software in the system. What I'd found was that this state machine / VICSoftInt mechanism would run fine for a while, then randomly the SPI ISR would deadlock looking for the SPI completion bit. The only way I've found out of that deadlock was to put a timeout in the code which looks at the completion bit: ================= begin spiISR() =============void spi0ISR (void) {// state machine to service the uarts. volatile ushort byt; for (byt=0x80; byt; byt--) if (SPSR & 0x80) break; switch (spiState) { ///////////////////////////////////////// // handler for serial2 ///////////////////////////////////////// case Srx2step0: // begin the walk down all three uarts. // assume shutdown in final state... // but any activty will force a new cycle to run. AllIsQuietOnSpi = True; dataWord = getS2DataTosend(); // send first byte on its way. IOCLR = SEL2_BIT; spiState = Srx2step1; SPDR = (dataWord >> 8); break; ... ================== snip =============== This works for me. I don't like it, but it works. I'd spent several days trying to work out why the SPI would deadlock and could not find any explanation. What I did find out is that the SPI interrupt would fire well before the SPIF completion bit was set!!! This was proven by examining the value of the "byt" variable in my above routine. It always showed that a significant number of loops occurred before the SPIF bit was seen. There were random intervals in which the for() loop would expire to full count (zero). After some testing, I arrived at the value of 0x80 as the loop value which was twice the worst case delay count awaiting the SPIF bit (when it did not goto zero). So, I would arrive at the spiISR service and have to wait for the completion bit. Sometimes there would be an interrupt, but never a completion bit. I also found that I had to wait until that bit appeared otherwise if I assumed that because I was in the ISR due to a completed cycle and simply load the next byte into the SPI data register, the SPI would sometimes die with a WCOL write collision! According to the docs, there is absolutely no information nor timing diagrams detailing the relationship of: the SPIF bit, shift clock, and interrupts. Again, the Philips docs are sadly lacking in detail on critical issues (see discussion in this group messages regarding the ADC leakage). This is with the LPC2106 processor. Interestingly, the SSI of the LPC2138 does not suffer from this problem... So, there appears to be an as yet documented failure / weakness in the LCP2106 SPI controller. Given that I was three months into this new board, had my first prototype and was commited to using the Philips part, I had to "deal with it". Not like I've been here before. :-/ The random deadlock is explained as a race condition between when the interrupt fired and when I actually reloaded the SPI TX register. Most times I would be outside of the time between the SPI interrupt and SPIF flagging, but sometimes I would hit it and lockup the SPI controller. I cannot explain why the SPIF bit is missed however. That appears to be a race condition in the silicon where a co-incidence of reading from the SPI status register vs. the AHB writing into the status register... ??? Regards, TomW -- Tom Walsh - WN3L - Embedded Systems Consultant http://openhardware.net, http://cyberiansoftware.com "Windows? No thanks, I have work to do..." ----------------
Reply by ●March 9, 20062006-03-09
brightside_design wrote: >--- In lpc2000@lpc2..., Tom Walsh <tom@...> wrote: > > >>brightside_design wrote: >> >> >> >>>I have a problem with a simple SPI example program. >>>Part: LPC2129 >>>PCK: 14.7 MHz >>>Mode: Master, CPOL=0, CPHA=0, LSIF=0. >>> >>>I initialise the SPI like this:- >>>void SPI_Init(void) >>> { >>> S0SPCCR = 0x26; // Divides PCK to give about 400kHz >>> S0SPCR = 0x20; // Select Master mode >>> } >>> >>>And then use the SPI like this:- >>>void SPI_Transfer( char *buf, int count) >>>{ >>> int r = 0, i = 0; >>> >>> for( ; i < count; i++ ) >>> { >>> S0SPDR = buf[i]; // Write data >>> do{ r = S0SPSR; }while(!(r & 0x80));// Wait for SPIF >>> // Read status - to be done >>> buf[i] = S0SPDR; // Read data >>> } >>>} >>> >>> >>> >>> >>> >>Try writing it this way: >> >>void SPI_Transfer( char *buf, int count) >>{ >>volatile int r = 0; >>volatile int i = 0; >> for( ; i < count; i++ ) >> { >> S0SPDR = buf[i]; // Write data >> do{ r = S0SPSR; }while(!(r & 0x80));// Wait for SPIF >> // Read status - to be done >> buf[i] = S0SPDR; // Read data >> } >>} >> >> >>If you look deeper at the underlying assembly language via the >> >> >JTAG, I'm > > >>fairly confident you will find that it reads "r" once, then loops >> >> >on the > > >>resultant value. Essentially, the volatile keyword tells the >> >> >compiler > > >>to assume nothing about the variables' value it holds, to actually >> >> >check > > >>it rather than to optimize the reference. >> >>YMMV, but your function would probably work if you turned off all >>optimizations (-O0). >> >>TomW >> >> >> >> >>>Sometimes I power up the device and this function runs correctly >>>with problem whatsoever. Other times the function just hangs. If >>> >>> >I > > >>>attach a JTAG debugger (Keil ULINK) I find that the function is >>>hanging at the line "do{ r = S0SPSR; }while(!(r & 0x80));" on the >>>first itteration. >>> >>>There is no hardware attached to the SPI port. I figured that the >>>device should put data out onto an unconnected pin without any >>>problem and that I should be able to get the software working >>> >>> >before > > >>>thinking about ading hardware. >>> >>>Has anyone got any ideas what might be going wrong? >>> >>>Thanks, >>> >>>Paul >>> >>> >>-- >>Tom Walsh - WN3L - Embedded Systems Consultant >>http://openhardware.net, http://cyberiansoftware.com >>"Windows? No thanks, I have work to do..." >>---------------- >> >> >> > >Thanks Tom, I will try that when I have a moment but I don't think >thats the answer. I've just read through the disassemby for that >function and it is reading the register each time through. Also the >problem is intermittant, sometimes it works fine, other times it >hangs. > > > Oh, just some further information. The LPC2106 is running the SPI under interrupts while the LCP2138 is not. Here is a sample of the SSI bit polling on the LPC2138: ========== begin spiPutByte() =========== static void spiPutByte(uchar inBuf) {// spit a byte of data at the MMC. SSPDR = (REG16) inBuf; while (SSPSR & SSP_BSY); // dummy read clears SPI BSY flag on LPC2xxx processors. dummyReader = (uchar) SSPDR; } =============== snip ============== I am not yet using the SPI on the LPC2138, so that doesn't prove anything other than the SSI is more durable? TomW -- Tom Walsh - WN3L - Embedded Systems Consultant http://openhardware.net, http://cyberiansoftware.com "Windows? No thanks, I have work to do..." ----------------
Reply by ●March 9, 20062006-03-09
Hi. I had no time to enter in depth regarding your problem but when I read your phrase: "I cannot explain why the SPIF bit is missed however. That appears to be a race condition in the silicon where a co-incidence of reading from the SPI status register vs. the AHB writing into the status register... ???" I remembered the errata document for the LPC2138 processor where similar problems are documented for both the timer and the uart. If you write a register via software at the same time that hardware want to write the same register, the hardware write is not performed. For timer this occurs when you are clearing a timer match interrupt (ex. interrupt on match0) and another match occurs at the same time (ex. match1): the match interrupt is never generated. For uart this occurs if you read the IIR register, clearing the THRE bit and at the same time the transmitter register become empty so that hardware want to set the THRE bit: the bit is never set, the interrupt is never generated. The consequence is: if timers and uarts have these problems, why not the SPI? Have you checked the ERRATA for the LPC2106? Anyway, I agree that "there is absolutely no information nor timing diagrams detailing the relationship of: the SPIF bit, shift clock, and interrupts. Again, the Philips docs are sadly lacking in detail on critical issues (see discussion in this group messages regarding the ADC leakage)." I know of my colleague working with SPI on LPC2138 and finding a lot of problems. I think that Philips failed create a microcontroller with "robust" peripherals to be used in industrial environment. Unfortunately (or fortunately??) it is very cheap, and this attract the marketing peoples (the programmers will patch the code in one mode or another...) Good luck, Carlo --- In lpc2000@lpc2..., Tom Walsh <tom@...> wrote: > > Oh, just some further information. The LPC2106 is running the SPI > under interrupts while the LCP2138 is not. Here is a sample of the SSI > bit polling on the LPC2138: > > ========== begin spiPutByte() ===========> > static void spiPutByte(uchar inBuf) > {// spit a byte of data at the MMC. > SSPDR = (REG16) inBuf; while (SSPSR & SSP_BSY); > // dummy read clears SPI BSY flag on LPC2xxx processors. > dummyReader = (uchar) SSPDR; > } > > =============== snip ==============> > I am not yet using the SPI on the LPC2138, so that doesn't prove > anything other than the SSI is more durable? > > TomW > > > -- > Tom Walsh - WN3L - Embedded Systems Consultant > http://openhardware.net, http://cyberiansoftware.com > "Windows? No thanks, I have work to do..." > ---------------- >
Reply by ●March 9, 20062006-03-09
c.barbaro wrote: >Hi. > >I had no time to enter in depth regarding your problem but when >I read your phrase: >"I cannot explain why the SPIF bit is missed however. That appears to >be a race condition in the silicon where a co-incidence of reading >from the SPI status register vs. the AHB writing into the status >register... ???" > >I remembered the errata document for the LPC2138 processor where >similar problems are documented for both the timer and the uart. >If you write a register via software at the same time that hardware >want to write the same register, the hardware write is not performed. >For timer this occurs when you are clearing a timer match interrupt >(ex. interrupt on match0) and another match occurs at the same time >(ex. match1): the match interrupt is never generated. >For uart this occurs if you read the IIR register, clearing the THRE >bit and at the same time the transmitter register become empty so that >hardware want to set the THRE bit: the bit is never set, the interrupt >is never generated. > >The consequence is: if timers and uarts have these problems, why not >the SPI? >Have you checked the ERRATA for the LPC2106? > > > Yes, and I do think that you are correct. It may be an inherent design failure of the AHB. The discussion in apnote AN10414 strongly suggests to me that there are such flaws in the hardware mechanisms between the ARM core and the peripheral bus. >Anyway, I agree that "there is absolutely no information nor timing >diagrams detailing the relationship of: the SPIF bit, shift clock, and >interrupts. Again, the Philips docs are sadly lacking in detail on >critical issues (see discussion in this group messages regarding the >ADC leakage)." > >I know of my colleague working with SPI on LPC2138 and finding a lot >of problems. >I think that Philips failed create a microcontroller with "robust" >peripherals to be used in industrial environment. >Unfortunately (or fortunately??) it is very cheap, and this attract >the marketing peoples (the programmers will patch the code in one mode >or another...) > > > Well, I don't think that we can really fault Philips for some of this. IMO, ARM Inc. itself shares some of this blame. I see that ARM Inc. is the one pushing / offering the AHB peripheral bus. I suspect that Philips collected the LPC2000 series together, Ala Carte, from a menu of IP available from ARM. So, design flaws in the AHB are being promulgated into customers' silicon. The documentation issue is a real black-eye though. I've been designing systems for a long time now and the documentation for the LPC2000 series is atrocious! The documentation is okay for writing software, but the hardware documentation is simply terrible! For example: refer to Philips document UM10120 "LPC213x User Manual". Look at Section 12.4.5 "SPI Interrupt register (S0SPINT - 0xE002 001C)". The only mention of the relationship of the SPI data register shifting to an empty state and the occurance of the interrupt is: "SPI interrupt flag. Set by the SPI interface to generate an interrupt. Cleared by writing a 1 to this bit. Note: this bit will be set once when SPIE = 1 and at least one of SPIF and WCOL bits is 1. However, only when the SPI Interrupt bit is set and SPI0 Interrupt is enabled in the VIC, SPI based interrupt can be processed by interrupt handling software." That is it! No timing diagram or flow chart to explain the process. Just a vague statement that the interrupt bit is used to set an interrupt condition. This is a childish explanation, thoroughly lacking in any detail. Any embedded engineer knows what an interrupt does, we need to know WHEN you set the interrupt, what is the relationship of the SPIF + SPINT? 1) Which comes first, the SPIF or SPINT? 2) At what clock & edge does the SPIF become asserted? 3) At what clock & edge does SPINT get asserted? Those are questions that hardware + software engineers need to have answered. Not some silly pablum about what an interrupt is. The documentation is okay as far as identifying where the registers are and what bits are used for... The documentation is littered with these omissions. Another example, what is the characteristic input capacitance of the clock circuits? I have an 18pf crystal, how many picofarads will the processor pins represent when calculating the additional load capacitance for proper crystal operation? If the range is, say, from 3pf..13pf then document that so that we are aware that the loading capacitance may have to be altered in production due to silicon fabrication differences. Another example, what is the characteristic input resistance of the ADC circuit? Is that resistance a fixed value or does it change significantly during conversion (conversion loading)? Now, my question is, if this is not the definitive document we should be looking at for this information: WHERE IS THE "REAL" DOCUMENTATION??? I just get very annoyed at having to spend days trying to 'get it right' due to the lack of adequate documentation. I am not a hobbyist, I do this for a living. TomW -- Tom Walsh - WN3L - Embedded Systems Consultant http://openhardware.net, http://cyberiansoftware.com "Windows? No thanks, I have work to do..." ----------------
Reply by ●March 9, 20062006-03-09
A quick sanity check:
You say you have no hardware attached.
You know you need a pull-up resistor on the SSEL pin,
which MUST be routed to the SPI block in PINSEL0.
The user manual tells you that you can't use the SSEL pin for GPIO
on devices earlier than the 2148 - even if you only ever use SSP as a master!
Without this, if the pin (or when wired as GPIO, the internal floating net)
goes low, the SPI will automatically be a slave.
imho this should be in an official "gotcha" document even if it is not
an errata item.
Hope this helps,
Danish
--- In lpc2000@lpc2..., "brightside_design"
<brightside_design@...> wrote:
>
> I have a problem with a simple SPI example program.
> Part: LPC2129
> PCK: 14.7 MHz
> Mode: Master, CPOL=0, CPHA=0, LSIF=0.
>
> ...
> Sometimes I power up the device and this function runs correctly
> with problem whatsoever. Other times the function just hangs. If I
> attach a JTAG debugger (Keil ULINK) I find that the function is
> hanging at the line "do{ r = S0SPSR; }while(!(r & 0x80));" on
the
> first itteration.
>
> There is no hardware attached to the SPI port. I figured that the
> device should put data out onto an unconnected pin without any
> problem and that I should be able to get the software working before
> thinking about ading hardware.
>
> Has anyone got any ideas what might be going wrong?
>
> Thanks,
>
> Paul
>
Reply by ●March 9, 20062006-03-09
Quoting Danish Ali <danish@dani...>: > A quick sanity check: > You say you have no hardware attached. > You know you need a pull-up resistor on the SSEL pin, > which MUST be routed to the SPI block in PINSEL0. > > The user manual tells you that you can't use the SSEL pin for GPIO > on devices earlier than the 2148 - even if you only ever use SSP as a master! > Without this, if the pin (or when wired as GPIO, the internal floating net) > goes low, the SPI will automatically be a slave. > > imho this should be in an official "gotcha" document even if it is > not an errata item. See http://www.open-research.org.uk/ARMuC/LPC2100Tips.html Robert
Reply by ●March 10, 20062006-03-10
--- In lpc2000@lpc2..., Robert Adsett <subscriptions@...> wrote: > > Quoting Danish Ali <danish@...>: > > > A quick sanity check: > > You say you have no hardware attached. > > You know you need a pull-up resistor on the SSEL pin, > > which MUST be routed to the SPI block in PINSEL0. > > > > The user manual tells you that you can't use the SSEL pin for GPIO > > on devices earlier than the 2148 - even if you only ever use SSP as a master! > > Without this, if the pin (or when wired as GPIO, the internal floating net) > > goes low, the SPI will automatically be a slave. > > > > imho this should be in an official "gotcha" document even if it is > > not an errata item. > > See http://www.open-research.org.uk/ARMuC/LPC2100Tips.html > > Robert > I just added a pull-up to SSEL and it appears to be working! Thanks for the help Danish and thank you Robert for the link; I'm sure I would have been falling into one of the other "gotchas" in the next few days! Paul