cancel
Showing results for 
Search instead for 
Did you mean: 

SPI reading data from external flash?

reckan
Associate II
Posted on April 18, 2011 at 15:29

SPI reading data from external flash?

#spi
18 REPLIES 18
jpeacock23
Associate II
Posted on May 17, 2011 at 14:31

SPI requires that the master generate the clock signal when transmitting OR receiving.  You need to transmit a dummy byte to generate the clocks for each incoming byte.

  Jack Peacock

Posted on May 17, 2011 at 14:31

SPI_I2S_ReceiveData merely reads the internal register of the STM32 of the data received during the last SPI_I2S_SendData. ie as you send data across the SPI bus to the slave, the master clocks back in the data the slave is sending.

Try looking at the ST library (2.0.1) example code bundled with the IAR/KEIL evals.

\ST\STM32F10xFWLib\Examples\SPI\M25P64_FLASH

/*******************************************************************************

* Function Name  : SPI_FLASH_ReadByte

* Description    : Reads a byte from the SPI Flash.

*                  This function must be used only if the Start_Read_Sequence

*                  function has been previously called.

* Input          : None

* Output         : None

* Return         : Byte Read from the SPI Flash.

*******************************************************************************/

u8 SPI_FLASH_ReadByte(void)

{

  return (SPI_FLASH_SendByte(Dummy_Byte));

}

/*******************************************************************************

* Function Name  : SPI_FLASH_SendByte

* Description    : Sends a byte through the SPI interface and return the byte

*                  received from the SPI bus.

* Input          : byte : byte to send.

* Output         : None

* Return         : The value of the received byte.

*******************************************************************************/

u8 SPI_FLASH_SendByte(u8 byte)

{

  /* Loop while DR register in not emplty */

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

  /* Send byte through the SPI1 peripheral */

  SPI_I2S_SendData(SPI1, byte);

  /* Wait to receive a byte */

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

  /* Return the byte read from the SPI bus */

  return SPI_I2S_ReceiveData(SPI1);

}

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
ColdWeather
Senior
Posted on May 17, 2011 at 14:31

''SPI_I2S_ReceiveData'' just returns the current value of the data register of the SPI peripheral (''return SPIx->DR'') and does not encapsulate the complete data transaction as anyone would expect from the library function :).

As peacock.jack wrote, the SPI nature is mostly full duplex bidirectional: the receiption takes place while sending the data or in other words, to receive the data ''write'' transaction should be initiated like below (pseudocode):

WAIT_FOR_TXE;

SPI_I2S_SendData(SPI1, value);

if (read_transaction) {

    WAIT_FOR_RXNE;

    value = SPI_I2S_ReceiveData(SPI1)

}

reckan
Associate II
Posted on May 17, 2011 at 14:31

Ok, so i get that i need to send to be able to receive. What im trying to do as a first thing (im pretty new at this which you maybe have noticed by now so please have patience) is to read the manufacturer id and device id from the flash memory. I read in the flash memory data sheet that i could send 0x90 followed by 0x000000 to the memory, and get back 0xEF followed by 0x14 which would be the id's. If i can't receive it with the SPI_I2S_ReceiveData function, how do i set it up? I just want to get this into a variable. Im doing this as a first step just to see that im really communicating with my external flash memory.

This is the code i have so far:

==========================

////////// INCLUDES ///////////

#include ''stddef.h''

#include ''stm32f10x.h''

#include ''stm32f10x_gpio.h''

#include <stm32f10x_spi.h>

#include ''string.h''

////////////// DEFINE ////////////////

#define SPI_COMMS           SPI1

#define PORT_SPI_COMMS      GPIOA

#define PIN_SPI_COMMS_NCS   GPIO_Pin_4

#define PIN_SPI_COMMS_SCK   GPIO_Pin_5

#define PIN_SPI_COMMS_MISO  GPIO_Pin_6

#define PIN_SPI_COMMS_MOSI  GPIO_Pin_7

//////////// FUNCTIONS ////////////

void RCC_Configuration(void);

void GPIO_Configuration(void);

void SPI_Configuration(void);

void NVIC_Configuration(void);

///////////// MAIN ////////////////////

int main(void)

{

    uint16_t data1=0, data2=0;

    //NVIC_Configuration();

    RCC_Configuration();

    GPIO_Configuration();

    SPI_Configuration();

    //memory ChipSelect must set high and thn low after powerup

    GPIO_SetBits(GPIOA, GPIO_Pin_4);//Chip select set high

    GPIO_ResetBits(GPIOA, GPIO_Pin_4);//Chip select set low

    for(;;){

        //Chip select set low

        GPIO_ResetBits(GPIOA, GPIO_Pin_4);

        //find out manufacturer id and device id

        SPI_I2S_SendData(SPI1,0x09); //10010000 = hex 90

        while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){}

        SPI_I2S_SendData(SPI1,0x00);

        while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){}

        SPI_I2S_SendData(SPI1,0x00);

        while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){}

        SPI_I2S_SendData(SPI1,0x00);

        while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE)==RESET){}

        SPI_I2S_SendData(SPI1,0x00);

        while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE)==RESET){}

        data1 = SPI_I2S_ReceiveData(SPI1);

        SPI_I2S_SendData(SPI1,0x00);

        //Chip select set high

        GPIO_SetBits(GPIOA, GPIO_Pin_4);

    }

}

/* SPI1-CONFIGURATION*/

void SPI_Configuration(void)

{

    SPI_InitTypeDef SPI_InitStructure;

    /* SPI_MASTER configuration -------------------------------------------------*/

      SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;

      SPI_InitStructure.SPI_Mode = SPI_Mode_Master;

      SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;

      SPI_InitStructure.SPI_CPOL = SPI_CPOL_High; //low

      SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;

      SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;

      SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4; // 4 = 5Mhz

      SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB; //MSB

      SPI_InitStructure.SPI_CRCPolynomial = 7;

      SPI_Init(SPI_COMMS, &SPI_InitStructure);

    /* Enable SPI_MASTER TXE interrupt */

      SPI_I2S_ITConfig(SPI_COMMS, SPI_I2S_IT_TXE, ENABLE);

    /* Enable SPI_MASTER */

      SPI_Cmd(SPI_COMMS, ENABLE);

}

/*NVIC-CONFIGURATION*/

void NVIC_Configuration(void)

{

    NVIC_InitTypeDef NVIC_InitStructure;

    /* 0 bits for pre-emption priority, 4 bits for subpriority */

    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);

    /* Configure and enable SPI_MASTER interrupt --------------------------------*/

    NVIC_InitStructure.NVIC_IRQChannel = SPI1_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

}

/*GPIO-CONFIGURATION*/

void GPIO_Configuration(void)

{

    GPIO_InitTypeDef GPIO_InitStructure;

    /* Configure SPI_MASTER pins: SCK, MISO and MOSI */

    GPIO_InitStructure.GPIO_Pin = PIN_SPI_COMMS_SCK | PIN_SPI_COMMS_MISO | PIN_SPI_COMMS_MOSI;

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //alternate function pushpull

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //2, 10, 50

    GPIO_Init(PORT_SPI_COMMS, &GPIO_InitStructure); //port A

    /* Configure SPI_MASTER pin: NCS */

    GPIO_InitStructure.GPIO_Pin = PIN_SPI_COMMS_NCS;

     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //out pushpull

     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //2, 10, 50

     GPIO_Init(GPIOA, &GPIO_InitStructure); //port A

}

/*RCC-CONFIGURATION*/

void RCC_Configuration(void)

{

    /* Enable GPIO clock */

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO | RCC_APB2Periph_SPI1, ENABLE);

}

==========================================

I have also set the chip select as a normal gpio because i couldn't make it work in any other way. The chip select pin must be brought low during sending and reading from the memory.

I guess the code i have right now is pretty messed up but but ive tried to send some bytes while reading but failed. At least i dont see anything being clocked out from the memory...

Thanks again for your help! Appreciate it a lot!

ColdWeather
Senior
Posted on May 17, 2011 at 14:31

        //find out manufacturer id and device id

        SPI_I2S_SendData(SPI1,0x09); //10010000 = hex 90

Watch! - your comment is hex 90, but you send 0x09 !

reckan
Associate II
Posted on May 17, 2011 at 14:31

Hey,

Thanks for observing that, but its actually something i chose because it got sent in the wrong way otherwise? 0x90 got sent like 00001001 instead of 10010000. Maybe its not the correct way to handle this problem but for me it was a simple solution =).

But something else is clearly wrong since i dont get any signals on the MISO.

John F.
Senior
Posted on May 17, 2011 at 14:31

The function expects a uint16_t argument.

void  SPI_I2S_SendData (SPI_TypeDef *SPIx, uint16_t Data)

reckan
Associate II
Posted on May 17, 2011 at 14:31

Ah! Didn't seem to help though but thanks! One step closer to solving the problem!

Posted on May 17, 2011 at 14:31

      SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;

      SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB; //MSB

 

Are you sure 8 bit MSB wouldn't be more appropriate? What part are you using, I don't see it specified in the thread.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..