AnsweredAssumed Answered

STM32 SPI Flash Problems

Question asked by hughes.lloyd on Nov 11, 2014
Latest reply on Nov 12, 2014 by karpavicius.linas
Hi,

I have a custom board with an STM32F205RE MCU linked to a AT25SF041 flash memory via SPI1. Our board means we are using SPI1 with the following setup:
SCK - PB3
MISO - PB4
MOSI - PA7
NCS - PA15

I have the SPI setup and can read the manufacturer information from the device perfectly. However, when I try read memory I end up with an additional byte (0x00) being read as the first byte, when I am expecting 0xFF. This problem goes away when I step through the code line by line. Which leads me to think it is a timing issue. 

Furthermore, I cannot get the Write Enable bit to be set in the status register. Even after sending the 0x06 command, the bit is not set. I know it is not the memory as I have tried 3 chips, of which 1 was a compatible chip from a different manufacturer (Spansion).

Below is my code for setting up and reading/writing the flash. I would really appreciate any feedback, as I suspect this is a configuration issue.

spi.h
01.#ifndef __SPI_FLASH_H
02.#define __SPI_FLASH_H
03. 
04.#include "stm32f2xx_flash.h"
05.#include "stm32f2xx_spi.h"
06.#include "stm32f2xx_gpio.h"
07.#include "stm32f2xx_rcc.h"
08. 
09.#define WRITE_ENABLE    0x06
10.#define WRITE_DISABLE   0x04
11.#define CHIP_ERASE      0xC7
12.#define BLOCK_ERASE_4   0x20
13.#define BLOCK_ERASE_32  0x52
14.#define BLOCK_ERASE_64  0xD8
15.#define DEEP_POWER_DOWN 0xB9
16.#define RESUME_DPD      0xAB
17.#define READ_ARRAY      0x0B
18.#define WRITE_PAGE      0x02
19.#define READ_DEV_ID     0x9F
20.#define READ_STATUS_1   0x05
21. 
22.typedef enum {
23.    BLOCK_ERASE_S  = BLOCK_ERASE_4,
24.    BLOCK_ERASE_M = BLOCK_ERASE_32,
25.    BLOCK_ERASE_L = BLOCK_ERASE_64,
26.    BLOCK_ERASE_F = CHIP_ERASE,
27.} SPI_FLASH_ERASE_TYPE;
28. 
29.void spi_flash_start( void );
30.void spi_flash_stop( void );
31.void spi_flash_powerdown( void );
32. 
33.void write_page(uint32_t address,const uint8_t *data, uint16_t len);
34.void write_spi_flash(uint32_t address,const uint8_t *data, uint16_t len);
35.void read_spi_flash(uint32_t address, uint8_t *data, uint16_t len);
36.void erase_spi_flash(SPI_FLASH_ERASE_TYPE opcode, uint32_t address);
37.void wait_for_last_spi_operation( void );
38. 
39.#endif

spi.c
001.#include "spi_flash.h"
002. 
003.#define DEVICE_SIZE     524288 //512KB
004.#define SECTOR_SIZE     4096 //4KB erase sectors
005.#define SECTOR_COUNT    (DEVICE_SIZE/SECTOR_SIZE)
006.#define PAGE_SIZE       256  //256 byte pages
007.#define PAGE_COUNT      (DEVICE_SIZE/PAGE_SIZE) //Number of 256B pages
008. 
009.#define ADDRESS_MASK    0x00FFFFFF // 3 byte addresses
010.#define BUSY_MASK       0x01
011. 
012.#define MIN(X,Y)        (X < Y ? X : Y)
013. 
014.#define FLASH_SPI       SPI1
015.#define FLASH_AF        GPIO_AF_SPI1
016.#define FLASH_SPI_APB   RCC_APB2Periph_SPI1
017.#define DUMMY_BYTE      0x00
018. 
019.#define SCK_Pin         GPIO_Pin_3
020.#define SCK_Port        GPIOB
021.#define SCK_Clk         RCC_AHB1Periph_GPIOB
022.#define SCK_PinSource   GPIO_PinSource3
023. 
024.#define MISO_Pin        GPIO_Pin_4
025.#define MISO_Port       GPIOB
026.#define MISO_Clk        RCC_AHB1Periph_GPIOB
027.#define MISO_PinSource  GPIO_PinSource4
028. 
029.#define MOSI_Pin        GPIO_Pin_7
030.#define MOSI_Port       GPIOA
031.#define MOSI_Clk        RCC_AHB1Periph_GPIOA
032.#define MOSI_PinSource  GPIO_PinSource7
033. 
034.#define NCS_Pin         GPIO_Pin_15
035.#define NCS_Port        GPIOA
036.#define NCS_Clk         RCC_AHB1Periph_GPIOA
037.#define NCS_PinSource   GPIO_PinSource15
038. 
039.#define ASSERT_NCS     GPIO_ResetBits(NCS_Port, NCS_Pin)
040.#define DEASSERT_NCS   GPIO_SetBits(NCS_Port, NCS_Pin)
041. 
042.#define BSY(x) ((x) & 0x01)
043.#define WREN(x) ((x) & 0x02)
044. 
045.void spi_gpio_config( void );
046.void spi_config( void );
047.void wait_for_TX( void );
048.void wait_for_RX( void );
049.uint8_t check_device_ID( uint8_t Manu_ID, uint8_t Dev_ID, uint8_t Dev_ID2 );
050.void send_opcode_and_address(uint8_t opcode, uint32_t address);
051.void send_opcode(uint8_t opcode);
052.uint8_t check_spi_status(uint8_t mask, uint8_t b_wait);
053.uint8_t SPI_Send_Receive(uint8_t data);
054.  
055.void spi_gpio_config(void)
056.{  
057.    GPIO_InitTypeDef GPIO_InitStructure;
058.     
059.    // Initialise the Clock
060.    RCC_AHB1PeriphClockCmd(SCK_Clk | MISO_Clk | MOSI_Clk | NCS_Clk, ENABLE);
061.    RCC_APB2PeriphClockCmd(FLASH_SPI_APB, ENABLE);
062.     
063.    // Configure the GPIO pins to use the correct Alternate Function
064.    GPIO_StructInit(&GPIO_InitStructure);
065.     
066.    /* Configure SPI_MASTER pins: NCS */
067.    GPIO_InitStructure.GPIO_Pin = NCS_Pin;
068.    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
069.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //2, 10, 50, 100
070.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
071.    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
072.    GPIO_Init(NCS_Port, &GPIO_InitStructure);
073.    ASSERT_NCS;
074.     
075.     /* Configure SPI_MASTER pins: SCK */
076.    GPIO_InitStructure.GPIO_Pin = SCK_Pin;
077.    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
078.    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
079.    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
080.    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
081.    GPIO_Init(SCK_Port, &GPIO_InitStructure);
082.     
083.    /* Configure SPI_MASTER pins: MOSI */
084.    GPIO_InitStructure.GPIO_Pin = MOSI_Pin;
085.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
086.    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
087.    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
088.    GPIO_Init(MOSI_Port, &GPIO_InitStructure);
089.     
090.    /* Configure SPI_MASTER pins: MISO */
091.    GPIO_InitStructure.GPIO_Pin = MISO_Pin;
092.    GPIO_Init(MISO_Port, &GPIO_InitStructure); //port A
093.     
094.        // Set the alternate function
095.    //GPIO_PinAFConfig(NCS_Port, NCS_PinSource, FLASH_AF);
096.    GPIO_PinAFConfig(SCK_Port, SCK_PinSource, FLASH_AF);
097.    GPIO_PinAFConfig(MOSI_Port, MOSI_PinSource, FLASH_AF);
098.    GPIO_PinAFConfig(MISO_Port, MISO_PinSource, FLASH_AF);
099.     
100.}
101. 
102.void spi_config( void )
103.{
104.    SPI_InitTypeDef SPI_InitStructure;
105.     
106.    SPI_DeInit(FLASH_SPI);
107. 
108.    SPI_StructInit(&SPI_InitStructure);
109.     
110.    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
111.    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
112.    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
113.    SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;//0
114.    SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;//0
115.    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
116.    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
117.    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
118.    SPI_InitStructure.SPI_CRCPolynomial = 7;
119.     
120.    SPI_Init(FLASH_SPI, &SPI_InitStructure);
121. 
122.    SPI_Cmd(FLASH_SPI, ENABLE);
123.}
124. 
125.void spi_flash_start( void )
126.{
127.    spi_gpio_config();
128.    spi_config();
129.     
130.    // Confirm the flash is operational by reading the manufacturer ID
131.    assert_param( check_device_ID(0x1F, 0x84, 0x01) );
132.}
133. 
134.void delay(int n){
135.    int i,l;
136.    for(i=0; i<n; i++){
137.        for(l=0; l<n; l++){}
138.    }
139.}
140. 
141.uint8_t check_device_ID( uint8_t Manu_ID, uint8_t Dev_ID, uint8_t Dev_ID2 )
142.{
143.    uint16_t mfg = 0, memtype = 0, capacity = 0;
144.     
145.    ASSERT_NCS;
146.    delay(10);
147.     
148.    SPI_Send_Receive(READ_DEV_ID);
149.     
150.    mfg = SPI_Send_Receive(DUMMY_BYTE); // Manufactuer ID
151.    memtype = SPI_Send_Receive(DUMMY_BYTE); // Manufactuer ID
152.    capacity = SPI_Send_Receive(DUMMY_BYTE); // Manufactuer ID
153.     
154.    delay(10);
155.    DEASSERT_NCS;
156.     
157.    return (mfg == Manu_ID) && (memtype == Dev_ID) && (capacity == Dev_ID2);
158.}
159. 
160.void wait_for_TX( void )
161.{
162.    // Wait until the TX buffer is empty
163.    while(SPI_I2S_GetFlagStatus(FLASH_SPI, SPI_I2S_FLAG_TXE) == RESET){}
164.}
165. 
166.void wait_for_RX( void )
167.{
168.    // Wait until there is data in the receive buffer
169.    while(SPI_I2S_GetFlagStatus(FLASH_SPI, SPI_I2S_FLAG_RXNE) == RESET){}
170.}
171. 
172. 
173.uint8_t SPI_Send_Receive(uint8_t data)
174.{
175.    wait_for_TX();
176.    SPI_I2S_SendData(FLASH_SPI, data);
177.    wait_for_RX();
178.    return SPI_I2S_ReceiveData(FLASH_SPI);
179.}
180. 
181.void send_opcode(uint8_t opcode)
182.{
183.    ASSERT_NCS;
184.    SPI_I2S_SendData(FLASH_SPI, (uint8_t) opcode); // Send opcode and start of address
185.    wait_for_TX();
186.    DEASSERT_NCS;
187.}
188. 
189.void send_opcode_and_address(uint8_t opcode, uint32_t address)
190.{
191.    address &= ADDRESS_MASK;
192.     
193.    SPI_I2S_SendData(FLASH_SPI, (uint8_t) opcode); // Send opcode and start of address
194.    wait_for_TX();
195.    SPI_I2S_SendData(FLASH_SPI, (uint8_t) (address >> 16)); // Send opcode and start of address
196.    wait_for_TX();
197.    SPI_I2S_SendData(FLASH_SPI, (uint8_t) (address >> 8)); // Send opcode and start of address
198.    wait_for_TX();
199.    SPI_I2S_SendData(FLASH_SPI, (uint8_t) address); // Send opcode and start of address
200.    wait_for_TX();
201.}
202. 
203.// This function assumes 256Byte aligned addresses when writing pages
204.void write_spi_flash(uint32_t address,const uint8_t *data, uint16_t len)
205.{
206.    uint32_t i, pos, byte_cnt;
207.    int32_t page_cnt;
208.     
209.    page_cnt = len;
210.    pos = 0;
211.     
212.    // As we can only write a maximum of 256bytes at a time we need to perform multiple writes for larger data blocks   
213.    while (page_cnt > 0) {
214.        byte_cnt = MIN(page_cnt,PAGE_SIZE);
215.        write_page(address + pos, data + pos, byte_cnt);
216.         
217.        pos += PAGE_SIZE;
218.        page_cnt -= PAGE_SIZE;
219.    }
220.     
221.}
222. 
223.void write_page(uint32_t address,const uint8_t *data, uint16_t len)
224.{
225.        uint32_t i;
226.        send_opcode(WRITE_ENABLE);
227.        wait_for_last_spi_operation();   
228.     
229.        if (check_spi_status(0x02, 0) == 0x02) {
230.         
231.            ASSERT_NCS;
232.             
233.            send_opcode_and_address(WRITE_PAGE, address);
234.             
235.            // Determine if we are writing a full page or only a section of a page
236.            for (i = 0; i < len; i++) {
237.                SPI_I2S_SendData(FLASH_SPI, (uint8_t) data[i]);
238.                wait_for_TX();
239.            }
240.             
241.            DEASSERT_NCS;
242.        }
243. 
244.        send_opcode(WRITE_DISABLE);
245.        wait_for_last_spi_operation();
246.}
247. 
248.void read_spi_flash(uint32_t address, uint8_t *data, uint16_t len)
249.{
250.    uint32_t i;
251.     
252.    ASSERT_NCS;
253.     
254.    send_opcode_and_address(READ_ARRAY, address);
255.     
256.    SPI_I2S_SendData(FLASH_SPI, DUMMY_BYTE); // The 0x0B opcode requires 1 dummy byte before transmitting
257.    wait_for_RX();
258.     
259.    // Clear out any pending RX data
260.    SPI_I2S_ReceiveData(FLASH_SPI);
261.     
262.    for (i = 0; i < len; i++) {
263.        SPI_I2S_SendData(FLASH_SPI, DUMMY_BYTE); // Junk Byte
264.        wait_for_RX();
265.        data[i] = (uint8_t) SPI_I2S_ReceiveData(FLASH_SPI);
266.    }
267.     
268.    delay(10);
269.    DEASSERT_NCS;
270.}
271. 
272.void erase_spi_flash(SPI_FLASH_ERASE_TYPE opcode, uint32_t address)
273.{
274.    SPI_Send_Receive(WRITE_ENABLE);
275.     
276.    if (check_spi_status(0x02, 0) == 0x02) {
277.        ASSERT_NCS;
278.         
279.        if (opcode == BLOCK_ERASE_F) {
280.            send_opcode(opcode);
281.        } else {
282.            send_opcode_and_address(opcode, address);
283.        }
284.         
285.        DEASSERT_NCS;
286.    }
287.     
288.    send_opcode(WRITE_DISABLE);
289.}
290. 
291.uint8_t check_spi_status(uint8_t mask, uint8_t b_wait)
292.{
293.    uint8_t busy = 1;
294.     
295.    ASSERT_NCS;
296.     
297.    SPI_Send_Receive(READ_STATUS_1);
298.//     SPI_I2S_SendData(FLASH_SPI, READ_STATUS_1);
299.//     wait_for_TX();
300.//    
301.//     //Get any rubbish
302.//     SPI_I2S_ReceiveData(FLASH_SPI);
303.     
304.    do {
305.        busy = SPI_Send_Receive(DUMMY_BYTE);
306.        busy &= mask;
307.    }while (busy && b_wait);
308.     
309.    DEASSERT_NCS;
310.     
311.    return busy;
312.}
313. 
314.void wait_for_last_spi_operation()
315.{
316.    check_spi_status(BUSY_MASK, 1);
317.}

I have also used an oscilloscope to monitor the lines, and it appears that the setting of the NCS at the end of a command is badly timed, as the NCS goes back to '1' half way through the last byte of data coming in.

Any assistance will be greatly appreciated.

Thanks

Outcomes