2013-03-29 03:57 PM
I am using the stm32l151RB microcontroller. It is running on an external clock source at 14.7456 MHz. I am communicating with a Micron M25P16 serial flash memory. This device states that it is compatible with CPOL/CPHA configurations of 0/0 and 1/1.
I am currently in the hardware validation phase writing simple blocks of code just to make sure the layout is correct. I was able to read the manufacturer id, memory type and memory capacity off of the device using a CPOL/CPHA set to 1/1. The problem is that when CPOL/CPHA are set to 0/0 I am unable to read the previously listed items. Originally I was getting nothing but zeroes, but I have since updated to the latest SPI library files that I could find on the website. I now get 0xFF when I attempt to read. Also strangely enough when hooked up to the scope, we don't see any data coming out of the controller on the MOSI line in the 0/0 configuration. Any help that can be provided would be greatly appreciated. Please let me know that additional information I can provide. Below you will find a snippet of the code that I am using detailing the SPI configuration. Pin Configurations void SPI_Flash_LowLevel_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_AHBPeriphClockCmd(FLASH_SPI_CS_GPIO_CLK | FLASH_SPI_MOSI_GPIO_CLK | FLASH_SPI_MISO_GPIO_CLK | FLASH_SPI_SCK_GPIO_CLK, ENABLE); RCC_APB2PeriphClockCmd(FLASH_SPI_CLK, ENABLE); GPIO_InitStructure.GPIO_Pin = FLASH_SPI_SCK_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_Init(FLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MISO_PIN; GPIO_Init(FLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = FLASH_SPI_MOSI_PIN; GPIO_Init(FLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure); /*MKM - TODO - Clean this up and put this pin configuration in the right place*/ GPIO_InitStructure.GPIO_Pin = FLASH_SPI_CS_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(FLASH_SPI_CS_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(FLASH_SPI_CS_GPIO_PORT, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz; GPIO_Init(FLASH_SPI_CS_GPIO_PORT, &GPIO_InitStructure); GPIO_PinAFConfig(FLASH_SPI_SCK_GPIO_PORT, FLASH_SPI_SCK_SOURCE, FLASH_SPI_SCK_AF); GPIO_PinAFConfig(FLASH_SPI_MISO_GPIO_PORT, FLASH_SPI_MISO_SOURCE, FLASH_SPI_MISO_AF); GPIO_PinAFConfig(FLASH_SPI_MOSI_GPIO_PORT, FLASH_SPI_MOSI_SOURCE, FLASH_SPI_MOSI_AF); SPI_Cmd(FLASH_SPI, ENABLE); } Usage unsigned int i,mfg,memtype,capacity,address; static portTASK_FUNCTION( vSPITask, pvParameters ) { /* The parameters are not used. */ ( void ) pvParameters; SPI_InitTypeDef SPI_InitStructure; SPI_InitTypeDef *ptr_SPI_InitStructure; ptr_SPI_InitStructure = &SPI_InitStructure; SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; SPI_InitStructure.SPI_Mode = SPI_Mode_Master; SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge; SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; SPI_InitStructure.SPI_CRCPolynomial = 7; SPI_Init(FLASH_SPI, &SPI_InitStructure); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); SPI_Init(FLASH_SPI, ptr_SPI_InitStructure); SPI_Cmd(FLASH_SPI, ENABLE); for(;;){ GPIO_ResetBits(GPIOA, GPIO_Pin_4); //Flash Chip Select //GPIO_ResetBits(GPIOA, GPIO_Pin_3); //FPGA Chip Select while(SPI_GetFlagStatus(FLASH_SPI, SPI_FLAG_TXE)==RESET){} SPI_SendData(FLASH_SPI,0x9F); //Read ID command while(SPI_I2S_GetFlagStatus(FLASH_SPI, SPI_I2S_FLAG_TXE)==RESET){} SPI_I2S_ReceiveData(FLASH_SPI); // Clear out any pending RX data SPI_I2S_SendData(FLASH_SPI,0x00); // Junk Byte while(SPI_GetFlagStatus(FLASH_SPI, SPI_FLAG_RXNE)==RESET){} mfg = SPI_ReceiveData(FLASH_SPI); // Manufactuer ID 0x20 while(SPI_GetFlagStatus(FLASH_SPI, SPI_FLAG_TXE)==RESET){} SPI_SendData(FLASH_SPI,0x00); // Junk Byte while(SPI_GetFlagStatus(FLASH_SPI, SPI_FLAG_RXNE)==RESET){} memtype = SPI_I2S_ReceiveData(FLASH_SPI); while(SPI_GetFlagStatus(FLASH_SPI, SPI_FLAG_TXE)==RESET){} SPI_SendData(FLASH_SPI,0x00); // Junk Byte while(SPI_GetFlagStatus(FLASH_SPI, SPI_FLAG_RXNE)==RESET){} capacity = SPI_ReceiveData(FLASH_SPI); GPIO_SetBits(GPIOA, GPIO_Pin_4); vTaskDelay( 2000/ portTICK_RATE_MS ); } } #spi #spi-cpha #spi-st32l151rb2015-07-08 05:58 AM
Jack thank you for this post. My driver with SPI mode 0 worked for quite some time :) but now I found a couple of devices that have some problems and I think edge sampling might be the problem.
If you are still active here on this forum I'd like to ask you, how did you handle the switch from mode 0 to mode 3. I asserted CS, sent command and address with mode 0, changed to mode 1 (waited until SPI is busy) and tried to read the data. Nothing useful comes out. Could you please comment on this? Thanx, Oversc0re2015-07-08 10:34 AM
If an SPI peripheral reads and writes on different clock edges then I switch the SPI port on the fly, depending on if I'm reading or writing to the port. Change the mode before asserting CS so any clock changes aren't seen by the peripheral.
Jack Peacock