cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F4 - Hanging on SPI Get Status

Rogers.Gary
Senior II
Posted on October 11, 2015 at 23:36

Hi,

I'm trying to get a Micron M25P128 flash device going on SPI1. below is the initialization, and then the send function.

At this point I am sending just a read ID opcode, but it is hanging at the next line after the one commented with **asterisks. Both MOSI / MISO pulled high with 10K, CS is set low (confirmed).

In addition, not using the ''NSS'' pin (PA4) - it's being used for something else, and not sure if it's relevant. I'm using PD6 for CS.

Can anyone please point out something that might be obviously wrong?

 

Thank for any help you can provide!

void SPI1_Configuration(void)

{

    SPI_InitTypeDef SPI_InitStruct;

    GPIO_InitTypeDef GPIO_InitStructure;    

    SPI_I2S_DeInit(SPI1);

    

    // enable GPIO D clock for PD6 - CS

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

    

      /* Configure the chip select pin to PD6 */

    GPIO_InitStructure.GPIO_Pin = MEM_CS;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;

    GPIO_Init(GPIOD, &GPIO_InitStructure);

    //set (PD6) CS high

    GPIO_SetPinHigh(GPIOD, MEM_CS);

    // enable peripheral clock - SPI Clock

    RCC_APB1PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

    // enable GPIO A clock for PA5/PA6/PA7 (SPI CLK/DATA)

    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin = MEM_SCK  | MEM_MOSI;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = MEM_MISO;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;

    GPIO_Init(GPIOA, &GPIO_InitStructure);

    //observe the ''GPIO_AF_SPI1'' denotes ALTERNATE MAPPING fucntion

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_SPI1); //connecting pin 5 of port A to the SPI1 peripheral

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource6, GPIO_AF_SPI1); //connecting pin 6 of port A to the SPI1 peripheral

    GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_SPI1); //connecting pin 7 of port A to the SPI1 peripheral

    /* configure SPI1 in Mode 0

     * CPOL = 0 --> clock is low when idle

     * CPHA = 0 --> data is sampled at the first edge

     */

    

    SPI_InitStruct.SPI_Direction = SPI_Direction_2Lines_FullDuplex; // set to full duplex mode, seperate MOSI and MISO lines

    //SPI_InitStruct.SPI_Direction = SPI_Direction_1Line_Tx; // set to TX only

    

    SPI_InitStruct.SPI_Mode = SPI_Mode_Master;     // transmit in master mode, NSS pin has to be always high

    SPI_InitStruct.SPI_DataSize = SPI_DataSize_8b; // one packet of data is 16 bits wide

    SPI_InitStruct.SPI_CPOL = SPI_CPOL_Low;        // clock is low when idle

    //SPI_InitStruct.SPI_CPOL = SPI_CPOL_High;

    SPI_InitStruct.SPI_CPHA = SPI_CPHA_1Edge;      // data sampled at first edge

    SPI_InitStruct.SPI_NSS = SPI_NSS_Soft; // set the NSS management to internal and pull internal NSS high

    SPI_InitStruct.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;

    SPI_InitStruct.SPI_FirstBit = SPI_FirstBit_MSB;// data is transmitted MSB first

    SPI_Init(SPI1, &SPI_InitStruct);

    

    SPI_Cmd(SPI1, ENABLE); // enable SPI1

 }

int8_t SPI1_send(uint8_t data)

{

        GPIO_SetPinLow(GPIOD, MEM_CS);

        //  *******code hangs at next line ********

        while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);

       //data in is opCode 0x9f

        SPI_I2S_SendData(SPI1, data);

      .......etc...etc...etc

}

#stm32f4 #spi
4 REPLIES 4
Posted on October 12, 2015 at 00:35

// enable peripheral clock - SPI Clock

    RCC_APB1PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);

APB1 != APB2

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
Posted on October 12, 2015 at 04:44

awesome clive1...thanks. as many times as you can look something like this over, it's amazing what you can miss.

it's no longer hanging, but then it's not returning any data either. I used the same Micron device on an LPC1768 and did not have any trouble sending in the identification opcode (0x9f) and it returned the device ID in the first 4 bytes: the first was a dummy byte, and the opcode was the OR of bytes,2 3 and 4. The LPC1768 SPI structure allowed you to use a pointer to a buffer and it would poll and transfer the right number of bytes according to the opcode.

I'm at a bit of a loss to understand the ST function - if I send an opcode that is to get back multiple bytes, how would they be read in? I tried multiple calls to:

dataRead = (uint8_t)SPI_I2S_ReceiveData(SPI1);

but the first returns 0, and it hangs up after that. I have read this link:

https://my.st.com/public/STe2ecommunities/mcu/Lists/cortex_mx_stm32/Flat.aspx?RootFolder=https%3a%2f%2fmy.st.com%2fpublic%2fSTe2ecommunities%2fmcu%2fLists%2fcortex_mx_stm32%2fSPI%20read%20problem&FolderCTID=0x01200200770978C69A1141439FE559EB459D7580009C4E14902C3CDE46A77F0FFD06506F5B&currentviews=272...

But still do not see what I need to send other than the opcode for device ID to get back and read multiple bytes.

Can you provide a link or some help to understand this? Searching the forum didn't get much other than that link.

Posted on October 12, 2015 at 04:54

You have to keep pushing bytes over the interface to clock back the responses. Reading the DR doesn't clock the bus, just reads the local register.

STM32F4xx_DSP_StdPeriph_Lib_V1.6.0\Project\STM32F4xx_StdPeriph_Examples\SPI\SPI_FLASH\spi_flash.c

/**
* @brief Sends a byte through the SPI interface and return the byte received
* from the SPI bus.
* @param byte: byte to send.
* @retval The value of the received byte.
*/
uint8_t sFLASH_SendByte(uint8_t byte)
{
/*!< Loop while DR register in not empty */
while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_TXE) == RESET);
/*!< Send byte through the SPI1 peripheral */
SPI_I2S_SendData(sFLASH_SPI, byte);
/*!< Wait to receive a byte */
while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_RXNE) == RESET);
/*!< Return the byte read from the SPI bus */
return SPI_I2S_ReceiveData(sFLASH_SPI);
}

/**
* @brief Reads FLASH identification.
* @param None
* @retval FLASH identification
*/
uint32_t sFLASH_ReadID(void)
{
uint32_t Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
/*!< Select the FLASH: Chip Select low */
sFLASH_CS_LOW();
/*!< Send ''RDID '' instruction */
sFLASH_SendByte(0x9F);
/*!< Read a byte from the FLASH */
Temp0 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
/*!< Read a byte from the FLASH */
Temp1 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
/*!< Read a byte from the FLASH */
Temp2 = sFLASH_SendByte(sFLASH_DUMMY_BYTE);
/*!< Deselect the FLASH: Chip Select high */
sFLASH_CS_HIGH();
Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
return Temp;
}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Rogers.Gary
Senior II
Posted on October 12, 2015 at 07:25

Great...appreciate your help and patience clive1

Next time I'll try LATE (Looking At The Examples)   8--)