2014-09-26 11:07 AM
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------------------------------------------------- #stm32f4 #spi2014-09-27 02:17 AM
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.2014-09-27 03:33 PM
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.2014-09-28 04:40 AM
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_SPI2void 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)2014-09-29 05:31 AM
I just tested this code on an independent hardware target and I am getting the same result.
2014-09-29 06:39 AM
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.2014-09-29 10:14 AM
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.