]> begriffs open source - cmsis-freertos/blob - Demo/CORTEX_STM32F103_IAR/spi_flash.c
Update README.md - branch main is now the base branch
[cmsis-freertos] / Demo / CORTEX_STM32F103_IAR / spi_flash.c
1 /******************** (C) COPYRIGHT 2007 STMicroelectronics ********************
2 * File Name          : spi_flash.c
3 * Author             : MCD Application Team
4 * Date First Issued  : 02/05/2007
5 * Description        : This file provides a set of functions needed to manage the
6 *                      communication between SPI peripheral and SPI M25P64 FLASH.
7 ********************************************************************************
8 * History:
9 * 04/02/2007: V0.2
10 * 02/05/2007: V0.1
11 ********************************************************************************
12 * THE PRESENT SOFTWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
13 * WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME.
14 * AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
15 * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
16 * CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
17 * INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
18 *******************************************************************************/
19
20 /* Includes ------------------------------------------------------------------*/
21 #include "spi_flash.h"
22
23 /* Private typedef -----------------------------------------------------------*/
24 #define SPI_FLASH_PageSize 256
25
26 #define WRITE      0x02  /* Write to Memory instruction */
27 #define WRSR       0x01  /* Write Status Register instruction */ 
28 #define WREN       0x06  /* Write enable instruction */
29
30 #define READ       0x03  /* Read from Memory instruction */
31 #define RDSR       0x05  /* Read Status Register instruction  */
32 #define RDID       0x9F  /* Read identification */
33 #define SE         0xD8  /* Sector Erase instruction */
34 #define BE         0xC7  /* Bulk Erase instruction */
35
36 #define WIP_Flag   0x01  /* Write In Progress (WIP) flag */
37
38 #define Dummy_Byte 0xA5
39
40 /* Private define ------------------------------------------------------------*/
41 /* Private macro -------------------------------------------------------------*/
42 /* Private variables ---------------------------------------------------------*/
43 /* Private function prototypes -----------------------------------------------*/
44 /* Private functions ---------------------------------------------------------*/
45
46 /*******************************************************************************
47 * Function Name  : SPI_FLASH_Init
48 * Description    : Initializes the peripherals used by the SPI FLASH driver.
49 * Input          : None
50 * Output         : None
51 * Return         : None
52 *******************************************************************************/
53 void SPI_FLASH_Init(void)
54 {
55   SPI_InitTypeDef  SPI_InitStructure;
56   GPIO_InitTypeDef GPIO_InitStructure;
57    
58   /* Enable SPI1 and GPIOA clocks */
59   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1 | RCC_APB2Periph_GPIOA, ENABLE);
60   
61   /* Configure SPI1 pins: NSS, SCK, MISO and MOSI */
62   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;
63   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
64   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
65   GPIO_Init(GPIOA, &GPIO_InitStructure);
66
67   /* Configure PA.4 as Output push-pull, used as Flash Chip select */
68   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
69   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
70   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
71   GPIO_Init(GPIOA, &GPIO_InitStructure);
72
73   /* Deselect the FLASH: Chip Select high */
74   SPI_FLASH_ChipSelect(High);
75
76   /* SPI1 configuration */ 
77   SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
78   SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
79   SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
80   SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
81   SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
82   SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
83   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
84   SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
85   SPI_InitStructure.SPI_CRCPolynomial = 7;
86   SPI_Init(SPI1, &SPI_InitStructure);
87   
88   /* Enable SPI1  */
89   SPI_Cmd(SPI1, ENABLE);   
90 }
91
92 /*******************************************************************************
93 * Function Name  : SPI_FLASH_SectorErase
94 * Description    : Erases the specified FLASH sector.
95 * Input          : SectorAddr: address of the sector to erase.
96 * Output         : None
97 * Return         : None
98 *******************************************************************************/
99 void SPI_FLASH_SectorErase(u32 SectorAddr)
100 {
101   /* Send write enable instruction */
102   SPI_FLASH_WriteEnable();
103                         
104   /* Sector Erase */ 
105   /* Select the FLASH: Chip Select low */
106   SPI_FLASH_ChipSelect(Low);            
107   /* Send Sector Erase instruction  */
108   SPI_FLASH_SendByte(SE);
109   /* Send SectorAddr high nibble address byte */
110   SPI_FLASH_SendByte((SectorAddr & 0xFF0000) >> 16);
111   /* Send SectorAddr medium nibble address byte */
112   SPI_FLASH_SendByte((SectorAddr & 0xFF00) >> 8);
113   /* Send SectorAddr low nibble address byte */
114   SPI_FLASH_SendByte(SectorAddr & 0xFF);
115   /* Deselect the FLASH: Chip Select high */
116   SPI_FLASH_ChipSelect(High);   
117
118   /* Wait the end of Flash writing */
119   SPI_FLASH_WaitForWriteEnd();  
120 }
121
122 /*******************************************************************************
123 * Function Name  : SPI_FLASH_BulkErase
124 * Description    : Erases the entire FLASH.
125 * Input          : None
126 * Output         : None
127 * Return         : None
128 *******************************************************************************/
129 void SPI_FLASH_BulkErase(void)
130 {       
131   /* Send write enable instruction */
132   SPI_FLASH_WriteEnable();      
133         
134   /* Bulk Erase */ 
135   /* Select the FLASH: Chip Select low */
136   SPI_FLASH_ChipSelect(Low);            
137   /* Send Bulk Erase instruction  */
138   SPI_FLASH_SendByte(BE);
139   /* Deselect the FLASH: Chip Select high */
140   SPI_FLASH_ChipSelect(High);   
141                 
142   /* Wait the end of Flash writing */
143   SPI_FLASH_WaitForWriteEnd();          
144 }
145
146 /*******************************************************************************
147 * Function Name  : SPI_FLASH_PageWrite
148 * Description    : Writes more than one byte to the FLASH with a single WRITE
149 *                  cycle(Page WRITE sequence). The number of byte can't exceed
150 *                  the FLASH page size.
151 * Input          : - pBuffer : pointer to the buffer  containing the data to be 
152 *                    written to the FLASH.
153 *                  - WriteAddr : FLASH's internal address to write to.
154 *                  - NumByteToWrite : number of bytes to write to the FLASH,
155 *                    must be equal or less than "SPI_FLASH_PageSize" value. 
156 * Output         : None
157 * Return         : None
158 *******************************************************************************/
159 void SPI_FLASH_PageWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
160 {
161   /* Enable the write access to the FLASH */
162   SPI_FLASH_WriteEnable();              
163   
164   /* Select the FLASH: Chip Select low */
165   SPI_FLASH_ChipSelect(Low);       
166   /* Send "Write to Memory " instruction */    
167   SPI_FLASH_SendByte(WRITE);    
168   /* Send WriteAddr high nibble address byte to write to */
169   SPI_FLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
170   /* Send WriteAddr medium nibble address byte to write to */
171   SPI_FLASH_SendByte((WriteAddr & 0xFF00) >> 8);  
172   /* Send WriteAddr low nibble address byte to write to */
173   SPI_FLASH_SendByte(WriteAddr & 0xFF);             
174   
175   /* while there is data to be written on the FLASH */
176   while(NumByteToWrite--) 
177   {
178     /* Send the current byte */                 
179     SPI_FLASH_SendByte(*pBuffer);                      
180     /* Point on the next byte to be written */
181     pBuffer++; 
182   }             
183   
184   /* Deselect the FLASH: Chip Select high */
185   SPI_FLASH_ChipSelect(High);
186   
187   /* Wait the end of Flash writing */
188   SPI_FLASH_WaitForWriteEnd();  
189 }
190
191 /*******************************************************************************
192 * Function Name  : SPI_FLASH_BufferWrite
193 * Description    : Writes block of data to the FLASH. In this function, the
194 *                  number of WRITE cycles are reduced, using Page WRITE sequence.
195 * Input          : - pBuffer : pointer to the buffer  containing the data to be 
196 *                    written to the FLASH.
197 *                  - WriteAddr : FLASH's internal address to write to.
198 *                  - NumByteToWrite : number of bytes to write to the FLASH.
199 * Output         : None
200 * Return         : None
201 *******************************************************************************/
202 void SPI_FLASH_BufferWrite(u8* pBuffer, u32 WriteAddr, u16 NumByteToWrite)
203 {
204   u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0, temp = 0;
205
206   Addr = WriteAddr % SPI_FLASH_PageSize;
207   count = SPI_FLASH_PageSize - Addr;
208   NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;
209   NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;
210   
211   if(Addr == 0) /* WriteAddr is SPI_FLASH_PageSize aligned  */
212   {
213     if(NumOfPage == 0) /* NumByteToWrite < SPI_FLASH_PageSize */
214     {
215       SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
216     }
217     else /* NumByteToWrite > SPI_FLASH_PageSize */ 
218     {
219       while(NumOfPage--)
220       {
221         SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
222         WriteAddr +=  SPI_FLASH_PageSize;
223         pBuffer += SPI_FLASH_PageSize;  
224       }    
225      
226       SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);      
227    }
228   }
229   else /* WriteAddr is not SPI_FLASH_PageSize aligned  */
230   {
231     if(NumOfPage== 0) /* NumByteToWrite < SPI_FLASH_PageSize */
232     {
233       if(NumOfSingle > count) /* (NumByteToWrite + WriteAddr) > SPI_FLASH_PageSize */
234       {
235         temp = NumOfSingle - count;
236         
237         SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
238         WriteAddr +=  count;
239         pBuffer += count; 
240         
241         SPI_FLASH_PageWrite(pBuffer, WriteAddr, temp);          
242       }
243       else
244       {
245         SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumByteToWrite);
246       }
247     }
248     else /* NumByteToWrite > SPI_FLASH_PageSize */
249     {
250       NumByteToWrite -= count;
251       NumOfPage =  NumByteToWrite / SPI_FLASH_PageSize;
252       NumOfSingle = NumByteToWrite % SPI_FLASH_PageSize;        
253       
254       SPI_FLASH_PageWrite(pBuffer, WriteAddr, count);
255       WriteAddr +=  count;
256       pBuffer += count;  
257      
258       while(NumOfPage--)
259       {
260         SPI_FLASH_PageWrite(pBuffer, WriteAddr, SPI_FLASH_PageSize);
261         WriteAddr +=  SPI_FLASH_PageSize;
262         pBuffer += SPI_FLASH_PageSize;  
263       }
264       
265       if(NumOfSingle != 0)
266       {
267         SPI_FLASH_PageWrite(pBuffer, WriteAddr, NumOfSingle);
268       }
269     }
270   }             
271 }
272
273 /*******************************************************************************
274 * Function Name  : SPI_FLASH_BufferRead
275 * Description    : Reads a block of data from the FLASH.
276 * Input          : - pBuffer : pointer to the buffer that receives the data read 
277 *                    from the FLASH.
278 *                  - ReadAddr : FLASH's internal address to read from.
279 *                  - NumByteToRead : number of bytes to read from the FLASH.
280 * Output         : None
281 * Return         : None
282 *******************************************************************************/
283 void SPI_FLASH_BufferRead(u8* pBuffer, u32 ReadAddr, u16 NumByteToRead)
284 {
285   /* Select the FLASH: Chip Select low */
286   SPI_FLASH_ChipSelect(Low);       
287   
288   /* Send "Read from Memory " instruction */
289   SPI_FLASH_SendByte(READ);      
290   
291   /* Send ReadAddr high nibble address byte to read from */
292   SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
293   /* Send ReadAddr medium nibble address byte to read from */
294   SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);  
295   /* Send ReadAddr low nibble address byte to read from */
296   SPI_FLASH_SendByte(ReadAddr & 0xFF);     
297         
298   while(NumByteToRead--) /* while there is data to be read */
299   {
300     /* Read a byte from the FLASH */                    
301     *pBuffer = SPI_FLASH_SendByte(Dummy_Byte);   
302     /* Point to the next location where the byte read will be saved */
303     pBuffer++;
304   }     
305   
306   /* Deselect the FLASH: Chip Select high */
307   SPI_FLASH_ChipSelect(High);           
308 }
309
310 /*******************************************************************************
311 * Function Name  : SPI_FLASH_ReadID
312 * Description    : Reads FLASH identification.
313 * Input          : None
314 * Output         : None
315 * Return         : FLASH identification
316 *******************************************************************************/
317 u32 SPI_FLASH_ReadID(void)
318 {        
319   u32 Temp = 0, Temp0 = 0, Temp1 = 0, Temp2 = 0;
320
321   /* Select the FLASH: Chip Select low */
322   SPI_FLASH_ChipSelect(Low);       
323   
324   /* Send "RDID " instruction */
325   SPI_FLASH_SendByte(0x9F);
326
327   /* Read a byte from the FLASH */                      
328   Temp0 = SPI_FLASH_SendByte(Dummy_Byte);
329
330   /* Read a byte from the FLASH */                      
331   Temp1 = SPI_FLASH_SendByte(Dummy_Byte);
332
333   /* Read a byte from the FLASH */                      
334   Temp2 = SPI_FLASH_SendByte(Dummy_Byte);
335
336   /* Deselect the FLASH: Chip Select high */
337   SPI_FLASH_ChipSelect(High);
338          
339   Temp = (Temp0 << 16) | (Temp1 << 8) | Temp2;
340
341   return Temp;
342 }
343
344 /*******************************************************************************
345 * Function Name  : SPI_FLASH_StartReadSequence
346 * Description    : Initiates a read data byte (READ) sequence from the Flash.
347 *                  This is done by driving the /CS line low to select the device,
348 *                  then the READ instruction is transmitted followed by 3 bytes
349 *                  address. This function exit and keep the /CS line low, so the
350 *                  Flash still being selected. With this technique the whole
351 *                  content of the Flash is read with a single READ instruction.
352 * Input          : - ReadAddr : FLASH's internal address to read from.
353 * Output         : None
354 * Return         : None
355 *******************************************************************************/
356 void SPI_FLASH_StartReadSequence(u32 ReadAddr)
357 {
358   /* Select the FLASH: Chip Select low */
359   SPI_FLASH_ChipSelect(Low);       
360   
361   /* Send "Read from Memory " instruction */
362   SPI_FLASH_SendByte(READ);      
363
364 /* Send the 24-bit address of the address to read from -----------------------*/  
365   /* Send ReadAddr high nibble address byte */
366   SPI_FLASH_SendByte((ReadAddr & 0xFF0000) >> 16);
367   /* Send ReadAddr medium nibble address byte */
368   SPI_FLASH_SendByte((ReadAddr& 0xFF00) >> 8);  
369   /* Send ReadAddr low nibble address byte */
370   SPI_FLASH_SendByte(ReadAddr & 0xFF);  
371 }
372
373 /*******************************************************************************
374 * Function Name  : SPI_FLASH_ReadByte
375 * Description    : Reads a byte from the SPI Flash.
376 *                  This function must be used only if the Start_Read_Sequence
377 *                  function has been previously called.
378 * Input          : None
379 * Output         : None
380 * Return         : Byte Read from the SPI Flash.
381 *******************************************************************************/
382 u8 SPI_FLASH_ReadByte(void)
383 {
384   return (SPI_FLASH_SendByte(Dummy_Byte));
385 }
386
387 /*******************************************************************************
388 * Function Name  : SPI_FLASH_ChipSelect
389 * Description    : Selects or deselects the FLASH.
390 * Input          : State : level to be applied on the FLASH's ChipSelect pin.
391 * Output         : None
392 * Return         : None
393 *******************************************************************************/
394 void SPI_FLASH_ChipSelect(u8 State)
395 {
396   /* Set High or low the chip select line on PA.4 pin */
397   GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)State);
398 }
399
400 /*******************************************************************************
401 * Function Name  : SPI_FLASH_SendByte
402 * Description    : Sends a byte through the SPI interface and return the byte 
403 *                  received from the SPI bus.
404 * Input          : byte : byte to send.
405 * Output         : None
406 * Return         : The value of the received byte.
407 *******************************************************************************/
408 u8 SPI_FLASH_SendByte(u8 byte)
409 {
410   /* Loop while DR register in not emplty */
411   while(SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE) == RESET); 
412
413   /* Send byte through the SPI1 peripheral */   
414   SPI_SendData(SPI1, byte);     
415
416   /* Wait to receive a byte */
417   while(SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) == RESET);
418
419   /* Return the byte read from the SPI bus */  
420   return SPI_ReceiveData(SPI1); 
421 }
422
423 /*******************************************************************************
424 * Function Name  : SPI_FLASH_SendHalfWord
425 * Description    : Sends a Half Word through the SPI interface and return the  
426 *                  Half Word received from the SPI bus.
427 * Input          : Half Word : Half Word to send.
428 * Output         : None
429 * Return         : The value of the received Half Word.
430 *******************************************************************************/
431 u16 SPI_FLASH_SendHalfWord(u16 HalfWord)
432 {
433   /* Loop while DR register in not emplty */
434   while(SPI_GetFlagStatus(SPI1, SPI_FLAG_TXE) == RESET); 
435
436   /* Send Half Word through the SPI1 peripheral */      
437   SPI_SendData(SPI1, HalfWord); 
438
439   /* Wait to receive a Half Word */
440   while(SPI_GetFlagStatus(SPI1, SPI_FLAG_RXNE) == RESET);
441
442   /* Return the Half Word read from the SPI bus */  
443   return SPI_ReceiveData(SPI1); 
444 }
445
446 /*******************************************************************************
447 * Function Name  : SPI_FLASH_WriteEnable
448 * Description    : Enables the write access to the FLASH.
449 * Input          : None
450 * Output         : None
451 * Return         : None
452 *******************************************************************************/
453 void SPI_FLASH_WriteEnable(void)  
454 {
455   /* Select the FLASH: Chip Select low */
456   SPI_FLASH_ChipSelect(Low);    
457   
458   /* Send "Write Enable" instruction */
459   SPI_FLASH_SendByte(WREN);
460   
461   /* Deselect the FLASH: Chip Select high */
462   SPI_FLASH_ChipSelect(High);   
463 }
464
465 /*******************************************************************************
466 * Function Name  : SPI_FLASH_WaitForWriteEnd
467 * Description    : Polls the status of the Write In Progress (WIP) flag in the  
468 *                  FLASH's status  register  and  loop  until write  opertaion
469 *                  has completed.  
470 * Input          : None
471 * Output         : None
472 * Return         : None
473 *******************************************************************************/
474 void SPI_FLASH_WaitForWriteEnd(void) 
475 {
476   u8 FLASH_Status = 0;
477   
478   /* Select the FLASH: Chip Select low */
479   SPI_FLASH_ChipSelect(Low);
480         
481   /* Send "Read Status Register" instruction */
482   SPI_FLASH_SendByte(RDSR);
483   
484   /* Loop as long as the memory is busy with a write cycle */           
485   do
486   {     
487          
488     /* Send a dummy byte to generate the clock needed by the FLASH 
489     and put the value of the status register in FLASH_Status variable */
490     FLASH_Status = SPI_FLASH_SendByte(Dummy_Byte);  
491                                                                                                                                         
492   } while((FLASH_Status & WIP_Flag) == SET); /* Write in progress */  
493
494   /* Deselect the FLASH: Chip Select high */
495   SPI_FLASH_ChipSelect(High);           
496 }
497
498 /******************* (C) COPYRIGHT 2007 STMicroelectronics *****END OF FILE****/