LPC812 SPI initialling based on the LPCOPEN - Page 1
Forum section: electronics / general

author: dizgah
author_rank: Regular Contributor
timestamp: June 19, 2016, 03:43:12 am
content: I'm trying to customize LPCOPEN SPI examples for LPC812 MCU's. Both periph_spi & periph_spi_sm_int examples run correctly on my LPC812 board and I'm able to trace signals on the MCU's pins by logic analyzer.But when I make my own project based on this examples ,I can't see any data on the MCU's pin , although that compiled successfully. below is my own project's codes:Code:#include "chip.h"/****************************************************************************** Private types/enumerations/variables****************************************************************************/#define SPI_MODE_TEST (SPI_MODE_MASTER)// #define SPI_MODE_TEST (SPI_MODE_SLAVE)#define POLLING_MODE 1#define LPC_SPI LPC_SPI0#define SPI_IRQ SPI0_IRQn#define SPIIRQHANDLER SPI0_IRQHandler// static SPI_CONFIG_T ConfigStruct;static SPI_DELAY_CONFIG_T DelayConfigStruct;static SPI_DATA_SETUP_T XfSetup;/****************************************************************************** Public types/enumerations/variables****************************************************************************//****************************************************************************** Private functions****************************************************************************//* Initializes pin muxing for SPI1 interface - note that SystemInit() mayalready setup your pin muxing at system startup */static void Init_SPI_PinMux(void){/** Initialize SSP0 pins connect* SCK1: PINASSIGN4[31:24]: Select P0.12* MOSI1: PINASSIGN5[7:0]: Select P0.14* MISO1: PINASSIGN5[15:8] : Select P0.6* SSEL1: PINASSIGN5[23:16]: Select P0.13*/Chip_SWM_DisableFixedPin(SWM_FIXED_VDDCMP);Chip_SWM_MovablePinAssign(SWM_SPI1_SCK_IO, 12);Chip_SWM_MovablePinAssign(SWM_SPI1_MOSI_IO, 14);Chip_SWM_MovablePinAssign(SWM_SPI1_MISO_IO, 6);Chip_SWM_MovablePinAssign(SWM_SPI1_SSEL_IO, 13);/* Disable the clock to the Switch Matrix to save power */Chip_Clock_DisablePeriphClock(SYSCTL_CLOCK_SWM);}void Board_SystemInit(void);int main(void){SystemCoreClockUpdate();/* SPI initialization */Init_SPI_PinMux();/*ConfigStruct.Mode = SPI_MODE_TEST;ConfigStruct.ClkDiv = Chip_SPI_CalClkRateDivider(LPC_SPI, 100000);ConfigStruct.ClockMode = SPI_CLOCK_CPHA0_CPOL0;ConfigStruct.DataOrder = SPI_DATA_MSB_FIRST;ConfigStruct.SSELPol = SPI_SSEL_ACTIVE_LO;*/Chip_SPI_Init(LPC_SPI);Chip_SPI_ConfigureSPI(LPC_SPI, SPI_MODE_TEST | /* Enable master/Slave mode */SPI_CLOCK_CPHA0_CPOL0 | /* Set Clock polarity to 0 */SPI_CFG_MSB_FIRST_EN |/* Enable MSB first option */SPI_CFG_SPOL_LO); /* Chipselect is active low */DelayConfigStruct.FrameDelay = 0;DelayConfigStruct.PostDelay = 0;DelayConfigStruct.PreDelay = 0;DelayConfigStruct.TransferDelay = 0;Chip_SPI_DelayConfig(LPC_SPI, &DelayConfigStruct);Chip_SPI_Enable(LPC_SPI);XfSetup.Length = 1;XfSetup.pTx = (uint16_t*)0xFFFF;XfSetup.RxCnt = XfSetup.TxCnt = 0;XfSetup.DataSize = 8;XfSetup.pRx = NULL;Chip_SPI_WriteFrames_Blocking(LPC_SPI, &XfSetup);while (1){Chip_SPI_WriteFrames_Blocking(LPC_SPI, &XfSetup);}}

author: nctnico
author_rank: Super Contributor
timestamp: June 19, 2016, 09:38:53 am
content: I'd add some code to make a pin wiggle from the main loop. If that doesn't work then your code is not running. Is the reset pin high (inactive) and did you pull the bootloader entry pin high (see user manual section on ISP flash)?

author: dizgah
author_rank: Regular Contributor
timestamp: June 20, 2016, 04:03:57 am
content: I don't know where are codes that you mentioned,But mcu is running correctly every thing is OK(it execute codes) but this code is unable to drive spi pins like clock(i checked it by logic analyzer and there are no action )

author: laneboysrc
author_rank: Contributor
timestamp: June 20, 2016, 05:12:02 am
content: I am not familiar with LPCOPEN as I only use the LPC812 on register level.Usually when a peripheral does not work, its clock is not enabled.Something like:Chip_Clock_EnablePeriphClock(SYSCTL_CLOCK_SPI0);It may be done in the library when SPI is enabled, but better make sure.good luck debugging, Werner

author: dizgah
author_rank: Regular Contributor
timestamp: June 20, 2016, 12:35:43 pm
content: Thank for response,I dont have debugging ability on my board.can you please share us your spi initial section and send/receive in register based mode?

author: TheDirty
author_rank: Frequent Contributor
timestamp: June 20, 2016, 12:56:45 pm
content: LPC8xx SPI peripheral is very simple. Maybe a little too simple. Luckily I haven't had to do anything fancy with it.My own library has a little more in it, but doing a quick google search I found these that have the basics.https://github.com/dozencrows/i2c-ir/blob/master/src/common/spi.hhttps://github.com/laneboysrc/nrf24l01-rc/blob/master/lpc812-nrf24l01-receiver/firmware/spi.cEDIT: Neither of these assign the pins to the SPI functions. You need to assign the SPI functions using LPC_SWM->PINASSIGN3 and PINASSIGN4 to their pin numbers.Like:LPC_SWM->PINASSIGN3 = (NRF24_SCLK_PIN << 24) | (0xFF << 16) | (0xFF << 8) | (0xFF);LPC_SWM->PINASSIGN4 = (0xFF << 24) | (0xFF << 16) | (NRF24_MISO_PIN << 8) | (NRF24_MOSI_PIN);+ the slave select, which I don't use in my routines, because I need to control it separately.

author: laneboysrc
author_rank: Contributor
timestamp: June 21, 2016, 03:43:18 am
content: Quote from: dizgah on June 20, 2016, 12:35:43 pmSure!Somewhere during hardware initialization:Code:// Turn on peripheral clocks for SCTimer, IOCON, SPI0// (GPIO, SWM alrady enabled after reset)LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 8) | (1 << 18) | (1 << 11);Initialization: (note: this code drives a TLC5940 LED driver, which has two extra lines BLANK and GSCLK that are not related to SPI). Simply ignore themCode:// ****************************************************************************// SPI configuration:// Configuration: CPOL = 0, CPHA = 0,// We can send 6 bit frame lengths, so no need to pack light data!// TXRDY indicates when we can put the next data into txbuf// Use SSEL function to de-assert XLAT while sending new data// ****************************************************************************void init_lights(void){GPIO_BLANK = 1;GPIO_GSCLK = 0;GPIO_XLAT = 0;LPC_GPIO_PORT->DIR0 |= (1 << GPIO_BIT_GSCLK) |(1 << GPIO_BIT_SCK) |(1 << GPIO_BIT_XLAT) |(1 << GPIO_BIT_BLANK) |(1 << GPIO_BIT_SIN);// Use 2 MHz SPI clock. 16 bytes take about 50 us to transmit.LPC_SPI0->DIV = (__SYSTEM_CLOCK / 2000000) - 1;LPC_SPI0->CFG = (1 << 0) | // Enable SPI0(1 << 2) | // Master mode(0 << 3) | // LSB First mode disabled(0 << 4) | // CPHA = 0(0 << 5) | // CPOL = 0(0 << 8); // SPOL = 0LPC_SPI0->TXCTRL = (1 << 21) | // set EOF(1 << 22) | // RXIGNORE, otherwise SPI hangs until// we read the data register((6 - 1) << 24); // 6 bit frames// We use the SSEL function for XLAT: low during the transmission, high// during the idle periood.LPC_SWM->PINASSIGN3 = (GPIO_BIT_SCK << 24) | // SCK(0xff << 16) |(0xff << 8) |(0xff << 0);LPC_SWM->PINASSIGN4 = (0xff << 24) |(GPIO_BIT_XLAT << 16) | // XLAT (SSEL)(0xff << 8) |(GPIO_BIT_SIN << 0); // SIN (MOSI)}SPI transfer function: (Note: send only as my application does not require reading data back from the chip)Code:static void send_light_data_to_tlc5940(void){volatile int i;// Wait for MSTIDLE, should be a no-op since we are waiting after// the transfer.while (!(LPC_SPI0->STAT & (1 << 8)));for (i = 15; i >= 0; i--) {// Wait for TXRDYwhile (!(LPC_SPI0->STAT & (1 << 1)));LPC_SPI0->TXDAT = gamma_table.gamma_table[light_actual] >> 2;}// Force END OF TRANSFERLPC_SPI0->STAT = (1 << 7);// Wait for the transfer to finishwhile (!(LPC_SPI0->STAT & (1 << 8)));}The whole project is here:https://github.com/laneboysrc/rc-light-controller/tree/master/mk4-tlc5940-lpc812/firmwareFile main.c contains initialization, global.h all the IO defines, and lights.c the SPI codehope this helps, Werner

author: dizgah
author_rank: Regular Contributor
timestamp: June 22, 2016, 10:15:53 am
content: Thank you all,based on your advice's & lpc812 user manual i wrote this code:its used internal clock source,but when i trace clock pin with my logic analyzer there are no change on this pin but when i program lpcopen spi program to my chip , i can see clock pulses on this pin,whats wrong?Code:/*===============================================================================Name : SPI_LPC812.cAuthor : $(author)Version :Copyright : $(copyright)Description : main definition===============================================================================*/#include "chip.h"#include <stdio.h>#include <stdbool.h>#define misoPin 11#define mosiPin 12#define clkPin 5#define ssPin 1void spiInit(void){//---enabling clock to the spi peripheralLPC_SYSCON->SYSAHBCLKCTRL |= (1 << 11);//---deactivate reset state for the spi0 peripheralLPC_SYSCON->PRESETCTRL |= (0x1<<0);//---disabling fixed pinsLPC_SWM->PINENABLE0 = (1 << 0);//disable SWM_FIXED_ACMP_I1LPC_SWM->PINENABLE0 = (1 << 1);//disable SWM_FIXED_ACMP_I2LPC_SWM->PINENABLE0 = (1 << 2);//disable SWM_FIXED_SWDIOLPC_SWM->PINENABLE0 = (1 << 3);//disable SWM_FIXED_SWCLK//---assininng spi pins by SWMLPC_SWM->PINASSIGN = (clkPin << 24); //spi clock pinsLPC_SWM->PINASSIGN = (misoPin << 24) | //spi misoPin(mosiPin << 24) | // spi mosiPin(ssPin << 24); //spi ssPin//---configuring spi specificationLPC_SPI0->CFG = (1 << 0) | // Enable SPI0(1 << 2) | // Master mode(0 << 3) | // LSB First mode disabled(0 << 4) | // CPHA = 0(0 << 5) | // CPOL = 0(0 << 8); // SS = 0LPC_SPI0->TXCTRL = (1 << 20) | // set EOT(1 << 21) | // set EOF(1 << 22) | // RXIGNORE, otherwise SPI hangs until((8 - 1) << 24); // 8 bit framesLPC_SPI0->DIV = (12000000 / 2000000) - 1;}uint8_t spiTrns(uint8_t dataOut){uint8_t dataIn;// Wait for MSTIDLE, should be a no-op since we are waiting after// the transfer.while (!(LPC_SPI0->STAT & (1 << 8)));// Wait for TXRDYwhile (!(LPC_SPI0->STAT & (1 << 1)));LPC_SPI0->TXDAT = (uint8_t) dataOut;// Force END OF TRANSFERLPC_SPI0->STAT = (1 << 7);// Wait for the transfer to finishwhile (!(LPC_SPI0->STAT & (1 << 8)));dataIn = LPC_SPI0->RXDAT;// Wait for the transfer to finishwhile (!(LPC_SPI0->STAT & (1 << 8)));return dataIn;}int main(void){// Read clock settings and update SystemCoreClock variableSystemCoreClockUpdate();spiInit();while(1){spiTrns(0xff);}}Edit:know with changing clock to the other pin i can see colck pulses on logic but they are strange.http://pasteboard.co/1S6qCqX9.png]http://pasteboard.co/1S6qCqX9.png]http://pasteboard.co/1S6qCqX9.png

author: dannyf
author_rank: Super Contributor
timestamp: June 22, 2016, 11:00:52 am
content: Doesn't lpcopen give out examples? Lpcopen is a mess too.Btw, sending 0xff isn't a great way to debug.

author: TheDirty
author_rank: Frequent Contributor
timestamp: June 22, 2016, 12:29:38 pm
content: I haven't looked at it that well, I can do that later, but you are doing a lot of this stuff://---disabling fixed pinsLPC_SWM->PINENABLE0 = (1 << 0);//disable SWM_FIXED_ACMP_I1LPC_SWM->PINENABLE0 = (1 << 1);//disable SWM_FIXED_ACMP_I2LPC_SWM->PINENABLE0 = (1 << 2);//disable SWM_FIXED_SWDIOLPC_SWM->PINENABLE0 = (1 << 3);//disable SWM_FIXED_SWCLKYou are overwriting the value in LPC_SWM->PINENABLE0 every time you do an assign. Every line undoes what the line before it has done. You need to do bit manipulation if you want to set/clear specific bits, otherwise you are assigning a whole new value to this register every time you write to it.Again with this:LPC_SWM->PINASSIGN = (clkPin << 24); //spi clock pinsYou are setting the spi clock pin and assigning every other pin in this register to pin 0. 0xFF means unassigned and you need to set those. The example was in the code given by lane and me.LPC_SWM->PINASSIGN3 = (GPIO_BIT_SCK << 24) | // SCK(0xff << 16) |(0xff <<|(0xff << 0);

author: nctnico
author_rank: Super Contributor
timestamp: June 22, 2016, 12:55:18 pm
content: Quote from: dizgah on June 22, 2016, 10:15:53 amOn other LPC controllers there is also an SPI clock divider register which should be set to any other value than 0. Please read the LPC812 user manual for the SPI peripheral. The introduction has all the steps to setup clocks, power and reset. Check these so see if they are right.

author: dizgah
author_rank: Regular Contributor
timestamp: August 15, 2016, 04:58:09 am
content: HiI have a new stupid problem with this tiny monster and because it is related with this topic I don't create a new topic:---------------------Based on datasheet -page 17:GPIO registers are located on the ARM Cortex M0+ IO bus for fastest possiblesingle-cycle I/O timing, allowing GPIO toggling with rates of up to 15 MHz.And I used a tiny code (based on the LPCOPEN library )to test it's speed:Code:Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, 12);while(1){Chip_GPIO_SetPinState(LPC_GPIO_PORT, 0, 12, true);Chip_GPIO_SetPinState(LPC_GPIO_PORT, 0, 12, false);}When I trace this GPIO pin by logic analyzer,It's toggling around 250 KHZ which is far away from mentioned value in datasheet.I also used PLL to increase main clock and system clock for achieving better speed:Code:Chip_IRC_SetFreq(96000000, 24000000);but even for different values 250KHZ is the most frequency which I cant overtake.Decreasing PLL speed cause decrements on output frequency of GPIO and also I know I can achieve better speed with assembly code but 250KHZ is so far away from datasheet & It seems MCU are not able to overtake from this limit(there ara same substance for 60MHZ/30MHZ - 60MHZ/15MHZ and so) Also 250KHZ is maximum speed which pins in the SPI peripheral state can toggled.

author: dannyf
author_rank: Super Contributor
timestamp: August 15, 2016, 11:15:25 am
content: "far away from mentioned value in datasheet."Take a look at the disassembly and it will be clear to you. Basically, implementation of the two gpio functions plus associated overhead, and loop overhead.Try to find a single instruction for your task and try to unroll the loop.