Author Topic: LPC812 SPI initialling based on the LPCOPEN  (Read 5916 times)

0 Members and 1 Guest are viewing this topic.

Offline dizgahTopic starter

  • Regular Contributor
  • *
  • Posts: 61
  • Country: 00
LPC812 SPI initialling based on the LPCOPEN
« on: June 19, 2016, 03:43:12 am »
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: [Select]
#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() may
   already 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);


    }
}

Happiness can be found, even in the darkest of times, if one only remembers to turn on the light.
Albus Dumbledore
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26891
  • Country: nl
    • NCT Developments
Re: LPC812 SPI initialling based on the LPCOPEN
« Reply #1 on: June 19, 2016, 09:38:53 am »
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)?
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 
The following users thanked this post: dizgah

Offline dizgahTopic starter

  • Regular Contributor
  • *
  • Posts: 61
  • Country: 00
Re: LPC812 SPI initialling based on the LPCOPEN
« Reply #2 on: June 20, 2016, 04:03:57 am »
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 )
Happiness can be found, even in the darkest of times, if one only remembers to turn on the light.
Albus Dumbledore
 

Offline laneboysrc

  • Contributor
  • Posts: 28
  • Country: sg
    • LANE Boys RC - radio control related electronics
Re: LPC812 SPI initialling based on the LPCOPEN
« Reply #3 on: June 20, 2016, 05:12:02 am »
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
 
The following users thanked this post: dizgah

Offline dizgahTopic starter

  • Regular Contributor
  • *
  • Posts: 61
  • Country: 00
Re: LPC812 SPI initialling based on the LPCOPEN
« Reply #4 on: June 20, 2016, 12:35:43 pm »
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?
Happiness can be found, even in the darkest of times, if one only remembers to turn on the light.
Albus Dumbledore
 

Offline TheDirty

  • Frequent Contributor
  • **
  • Posts: 440
  • Country: ca
Re: LPC812 SPI initialling based on the LPCOPEN
« Reply #5 on: June 20, 2016, 12:56:45 pm »
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.h
https://github.com/laneboysrc/nrf24l01-rc/blob/master/lpc812-nrf24l01-receiver/firmware/spi.c

EDIT:  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.
« Last Edit: June 20, 2016, 01:08:17 pm by TheDirty »
Mark Higgins
 
The following users thanked this post: dizgah

Offline laneboysrc

  • Contributor
  • Posts: 28
  • Country: sg
    • LANE Boys RC - radio control related electronics
Re: LPC812 SPI initialling based on the LPCOPEN
« Reply #6 on: June 21, 2016, 03:43:18 am »
can you please share us your spi initial section and send/receive in register based mode?

Sure!

Somewhere during hardware initialization:
Code: [Select]
    // 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 them
Code: [Select]
// ****************************************************************************
// 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 = 0

    LPC_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: [Select]
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 TXRDY
        while (!(LPC_SPI0->STAT & (1 << 1)));

        LPC_SPI0->TXDAT = gamma_table.gamma_table[light_actual[i]] >> 2;
    }

    // Force END OF TRANSFER
    LPC_SPI0->STAT = (1 << 7);

    // Wait for the transfer to finish
    while (!(LPC_SPI0->STAT & (1 << 8)));

}


The whole project is here: https://github.com/laneboysrc/rc-light-controller/tree/master/mk4-tlc5940-lpc812/firmware
File main.c contains initialization, global.h all the IO defines, and lights.c the SPI code

hope this helps, Werner
 
The following users thanked this post: dizgah

Offline dizgahTopic starter

  • Regular Contributor
  • *
  • Posts: 61
  • Country: 00
Re: LPC812 SPI initialling based on the LPCOPEN
« Reply #7 on: June 22, 2016, 10:15:53 am »
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: [Select]
/*
===============================================================================
 Name        : SPI_LPC812.c
 Author      : $(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           1


void spiInit(void)
{
//---enabling clock to the spi peripheral
LPC_SYSCON->SYSAHBCLKCTRL |=  (1 << 11);

//---deactivate reset state for the spi0 peripheral
LPC_SYSCON->PRESETCTRL |= (0x1<<0);

//---disabling fixed pins
LPC_SWM->PINENABLE0 = (1 << 0);//disable SWM_FIXED_ACMP_I1
LPC_SWM->PINENABLE0 = (1 << 1);//disable SWM_FIXED_ACMP_I2
LPC_SWM->PINENABLE0 = (1 << 2);//disable SWM_FIXED_SWDIO
LPC_SWM->PINENABLE0 = (1 << 3);//disable SWM_FIXED_SWCLK

//---assininng spi pins by SWM

LPC_SWM->PINASSIGN[3] = (clkPin << 24);       //spi clock pins

LPC_SWM->PINASSIGN[4] = (misoPin << 24) |     //spi misoPin
                        (mosiPin << 24) |     // spi mosiPin
                        (ssPin << 24);        //spi ssPin

//---configuring spi specification
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);           // SS = 0

LPC_SPI0->TXCTRL =  (1 << 20) |      // set EOT
                    (1 << 21) |      // set EOF
                    (1 << 22) |      // RXIGNORE, otherwise SPI hangs until
                    ((8 - 1) << 24); // 8 bit frames

LPC_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 TXRDY
      while (!(LPC_SPI0->STAT & (1 << 1)));

      LPC_SPI0->TXDAT = (uint8_t) dataOut;

  // Force END OF TRANSFER
  LPC_SPI0->STAT = (1 << 7);

  // Wait for the transfer to finish
  while (!(LPC_SPI0->STAT & (1 << 8)));

  dataIn = LPC_SPI0->RXDAT;

  // Wait for the transfer to finish
  while (!(LPC_SPI0->STAT & (1 << 8)));

  return dataIn;
}

int main(void)
{
    // Read clock settings and update SystemCoreClock variable
    SystemCoreClockUpdate();

    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
« Last Edit: June 22, 2016, 12:07:24 pm by dizgah »
Happiness can be found, even in the darkest of times, if one only remembers to turn on the light.
Albus Dumbledore
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: LPC812 SPI initialling based on the LPCOPEN
« Reply #8 on: June 22, 2016, 11:00:52 am »
Doesn't lpcopen give out examples? Lpcopen is a mess too.

Btw, sending 0xff isn't a great way to debug.
================================
https://dannyelectronics.wordpress.com/
 

Offline TheDirty

  • Frequent Contributor
  • **
  • Posts: 440
  • Country: ca
Re: LPC812 SPI initialling based on the LPCOPEN
« Reply #9 on: June 22, 2016, 12:29:38 pm »
I haven't looked at it that well, I can do that later, but you are doing a lot of this stuff:
//---disabling fixed pins
LPC_SWM->PINENABLE0 = (1 << 0);//disable SWM_FIXED_ACMP_I1
LPC_SWM->PINENABLE0 = (1 << 1);//disable SWM_FIXED_ACMP_I2
LPC_SWM->PINENABLE0 = (1 << 2);//disable SWM_FIXED_SWDIO
LPC_SWM->PINENABLE0 = (1 << 3);//disable SWM_FIXED_SWCLK

You 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[3] = (clkPin << 24);       //spi clock pins

You 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 << 8) |
                          (0xff << 0);

Mark Higgins
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26891
  • Country: nl
    • NCT Developments
Re: LPC812 SPI initialling based on the LPCOPEN
« Reply #10 on: June 22, 2016, 12:55:18 pm »
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
On 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.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline dizgahTopic starter

  • Regular Contributor
  • *
  • Posts: 61
  • Country: 00
Re: LPC812 SPI initialling based on the LPCOPEN
« Reply #11 on: August 15, 2016, 04:58:09 am »
Hi
I 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 possible
    single-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: [Select]
      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: [Select]
    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.

Happiness can be found, even in the darkest of times, if one only remembers to turn on the light.
Albus Dumbledore
 

Offline dannyf

  • Super Contributor
  • ***
  • Posts: 8221
  • Country: 00
Re: LPC812 SPI initialling based on the LPCOPEN
« Reply #12 on: August 15, 2016, 11:15:25 am »
"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.
================================
https://dannyelectronics.wordpress.com/
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf