cancel
Showing results for 
Search instead for 
Did you mean: 

SPI CPHA not setting correctly

dibs
Associate II
Posted on September 26, 2014 at 20:07

I am seeing some strange behavior in my SPI port.

I expect that it will be set up as CPOL = 0, CPHA = 0 and for the bus to output 0xA5.

What I see is that not only is MOSI transitioning on the wrong edges, but the data appears shifted.

I have inserted my code and a scope capture of the output. Red is CS, Yellow is CLK, and Green is MOSI.

Any ideas as to what is going on here?

-------------------------------------------Code-------------------------------------------------

    GPIO_InitTypeDef GPIO_InitStructure;

    SPI_InitTypeDef  SPI_InitStructure;

    // Enable GPIO clk

    RCC_AHB1PeriphClockCmd(EEPROM_MOSI_AHB1Periph_GPIOx, ENABLE);

    RCC_AHB1PeriphClockCmd(EEPROM_MISO_AHB1Periph_GPIOx, ENABLE);

    RCC_AHB1PeriphClockCmd(EEPROM_SCLK_AHB1Periph_GPIOx, ENABLE);

    RCC_AHB1PeriphClockCmd(EEPROM_CS_AHB1Periph_GPIOx,   ENABLE);

    // Connect Pins to AF

    GPIO_PinAFConfig(EEPROM_SCLK_GPIOx, EEPROM_SCLK_SOURCE, EEPROM_AF);

    GPIO_PinAFConfig(EEPROM_MOSI_GPIOx, EEPROM_MOSI_SOURCE, EEPROM_AF);

    GPIO_PinAFConfig(EEPROM_MISO_GPIOx, EEPROM_MISO_SOURCE, EEPROM_AF);

    // Pin Configuration

    GPIO_StructInit(&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;

    GPIO_InitStructure.GPIO_Pin   = EEPROM_SCLK_PIN_x;

    GPIO_Init(EEPROM_SCLK_GPIOx, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;

    GPIO_InitStructure.GPIO_Pin   = EEPROM_MOSI_PIN_x;

    GPIO_Init(EEPROM_MOSI_GPIOx, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   = EEPROM_MISO_PIN_x;

    GPIO_Init(EEPROM_MISO_GPIOx, &GPIO_InitStructure);

    GPIO_SetBits(EEPROM_CS_GPIOx, EEPROM_CS_PIN_x);

    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;

    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;

    GPIO_InitStructure.GPIO_Pin   = EEPROM_CS_PIN_x;

    GPIO_Init(EEPROM_CS_GPIOx, &GPIO_InitStructure);

    // Init SPI peripheral

    // Enable SPI clk

    EEPROM_CLK_INIT(EEPROM_CLK, ENABLE);

    SPI_I2S_DeInit(EEPROM_SPIx);

    SPI_StructInit(&SPI_InitStructure);

    SPI_InitStructure.SPI_Direction         = SPI_Direction_2Lines_FullDuplex;

    SPI_InitStructure.SPI_Mode              = SPI_Mode_Master;

    SPI_InitStructure.SPI_DataSize          = SPI_DataSize_8b;

    // CPHA = 0 CPOL = 0

    SPI_InitStructure.SPI_CPOL              = SPI_CPOL_Low;

    SPI_InitStructure.SPI_CPHA              = SPI_CPHA_1Edge;

    SPI_InitStructure.SPI_NSS               = SPI_NSS_Soft;

    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;

    SPI_InitStructure.SPI_FirstBit          = SPI_FirstBit_MSB;

    SPI_Init(EEPROM_SPIx,&SPI_InitStructure);

    // Set so that the SPI Master does not think someone is trying to take over the bus (Sets SSI bit)

    SPI_NSSInternalSoftwareConfig(EEPROM_SPIx,SPI_NSSInternalSoft_Set);

    eeprom_csd();

    SPI_Cmd(EEPROM_SPIx,ENABLE);

    SPI_I2S_SendData(EEPROM_SPIx,0xA5);

-------------------------------------------Code-------------------------------------------------

0690X00000605AUQAY.png

#stm32f4 #spi
6 REPLIES 6
stm322399
Senior
Posted on September 27, 2014 at 11:17

I must admit this trace bugs me, software looks good, and this shift shall not happen.

Is this possible for you to post a single file that compiles and produces the error for us to reproduce.

Also tell us which device you are using, and a few words about your HW target.

Last, do not configure GPIO for 50MHz where 25 MHz is good enough, this will reduce the overshoot on electrical signals.

dibs
Associate II
Posted on September 28, 2014 at 00:33

The target is an STM32F407. I will put together a file this weekend that will be able to compile on any Chinesium breakout board (or your favorite ST dev-kit), and I will post it on this thread.

At first I thought that the CPHA signal was incorrect, but on closer inspection, it really looks like the data is shifted backwards in time by a half clock cycle. I am not sure how this is possible. 

dibs
Associate II
Posted on September 28, 2014 at 13:40

Here is a file that can compile. It is using v_1_0_2 of the st stdperiph libraries. I will scope it out myself later today and see if I get the same thing.

File:

// Defines ----------------------------------------------------------------

#include ''stm32f4xx.h''

#include ''stm32f4xx_spi.h''

#include ''stm32f4xx_gpio.h''

#include ''stm32f4xx_rcc.h''

// Defines ----------------------------------------------------------------

#define MOSI_AHB1Periph_GPIOx     RCC_AHB1Periph_GPIOB

#define MOSI_GPIOx                GPIOB

#define MOSI_SOURCE               GPIO_PinSource15

#define MOSI_PIN_x                GPIO_Pin_15

#define MISO_AHB1Periph_GPIOx     RCC_AHB1Periph_GPIOB

#define MISO_GPIOx                GPIOB

#define MISO_SOURCE               GPIO_PinSource14

#define MISO_PIN_x                GPIO_Pin_14

#define SCLK_AHB1Periph_GPIOx     RCC_AHB1Periph_GPIOI

#define SCLK_GPIOx                GPIOI

#define SCLK_SOURCE               GPIO_PinSource1

#define SCLK_PIN_x                GPIO_Pin_1

#define CS_AHB1Periph_GPIOx       RCC_AHB1Periph_GPIOB

#define CS_GPIOx                  GPIOB

#define CS_SOURCE                 GPIO_PinSource12

#define CS_PIN_x                  GPIO_Pin_12

#define SPIx                      SPI2

#define CLK                       RCC_APB1Periph_SPI2

#define CLK_INIT                  RCC_APB1PeriphClockCmd

#define IRQn                      SPI2_IRQn

#define ISRHANDLER                SPI2_ISRHandler

#define AF                        GPIO_AF_SPI2

void init_spi(void);

int main (void) {

    init_spi();

}

void init_spi(void) {

    GPIO_InitTypeDef GPIO_InitStructure;

    SPI_InitTypeDef  SPI_InitStructure;

    // Enable GPIO clk

    RCC_AHB1PeriphClockCmd(MOSI_AHB1Periph_GPIOx, ENABLE);

    RCC_AHB1PeriphClockCmd(MISO_AHB1Periph_GPIOx, ENABLE);

    RCC_AHB1PeriphClockCmd(SCLK_AHB1Periph_GPIOx, ENABLE);

    RCC_AHB1PeriphClockCmd(CS_AHB1Periph_GPIOx,   ENABLE);

    // Connect Pins to AF

    GPIO_PinAFConfig(SCLK_GPIOx, SCLK_SOURCE, AF);

    GPIO_PinAFConfig(MOSI_GPIOx, MOSI_SOURCE, AF);

    GPIO_PinAFConfig(MISO_GPIOx, MISO_SOURCE, AF);

    // Pin Configuration

    GPIO_StructInit(&GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;

    GPIO_InitStructure.GPIO_Pin   = SCLK_PIN_x;

    GPIO_Init(SCLK_GPIOx, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;

    GPIO_InitStructure.GPIO_Pin   = MOSI_PIN_x;

    GPIO_Init(MOSI_GPIOx, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin   = MISO_PIN_x;

    GPIO_Init(MISO_GPIOx, &GPIO_InitStructure);

    GPIO_SetBits(CS_GPIOx, CS_PIN_x);

    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;

    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_NOPULL;

    GPIO_InitStructure.GPIO_Pin   = CS_PIN_x;

    GPIO_Init(CS_GPIOx, &GPIO_InitStructure);

    // Init SPI peripheral

    // Enable SPI clk

    CLK_INIT(CLK, ENABLE);

    SPI_I2S_DeInit(SPIx);

    SPI_StructInit(&SPI_InitStructure);

    SPI_InitStructure.SPI_Direction         = SPI_Direction_2Lines_FullDuplex;

    SPI_InitStructure.SPI_Mode              = SPI_Mode_Master;

    SPI_InitStructure.SPI_DataSize          = SPI_DataSize_8b;

    // CPHA = 0 CPOL = 0

    SPI_InitStructure.SPI_CPOL              = SPI_CPOL_Low;

    SPI_InitStructure.SPI_CPHA              = SPI_CPHA_1Edge;

    SPI_InitStructure.SPI_NSS               = SPI_NSS_Soft;

    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;

    SPI_InitStructure.SPI_FirstBit          = SPI_FirstBit_MSB;

    SPI_Init(SPIx,&SPI_InitStructure);

    // Set so that the SPI Master does not think someone is trying to take over the bus (Sets SSI bit)

    SPI_NSSInternalSoftwareConfig(SPIx,SPI_NSSInternalSoft_Set);

    GPIO_ResetBits(CS_GPIOx, CS_PIN_x);

    SPI_Cmd(SPIx,ENABLE);

    SPI_I2S_SendData(SPIx,0xA5);

} // end - void init_spi(void)

dibs
Associate II
Posted on September 29, 2014 at 14:31

I just tested this code on an independent hardware target and I am getting the same result.

stm322399
Senior
Posted on September 29, 2014 at 15:39

I have no F407 to test, but it works as expected on F429 disco (swapping CLK from I1 to D3, and MOSI from B15 to C3).

Sorry I can't help more.

dibs
Associate II
Posted on September 29, 2014 at 19:14

I found the problem, my scope had almost exactly a half clock cycle skew on the probe input for the clock. I am not sure how it ended up being so close, but I found it when I started varying the SPI baud rate and found that MOSI did not appear to be edge triggered....

A little embarrassing, but sometimes it is the measurement hardware and not the code.