• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
3  *
4  * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
5  * You may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at:
7  *
8  *        http://www.st.com/software_license_agreement_liberty_v2
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include "spi.h"
18 #include "w25qxx.h"
19 #include "stm32f4xx_conf.h"
20 #include "prt_task.h"
21 
22 #define BUFFER_SIZE     4096
23 
24 u16 W25X_TYPE = W25Q128;
25 
W25qxxInit(void)26 void W25qxxInit(void)
27 {
28     GPIO_InitTypeDef  gpioInitStruct;
29 
30     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);
31     RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
32 
33     gpioInitStruct.GPIO_PuPd = GPIO_PuPd_UP;
34     gpioInitStruct.GPIO_Pin = GPIO_Pin_14;
35     gpioInitStruct.GPIO_Speed = GPIO_Speed_100MHz;
36     gpioInitStruct.GPIO_Mode = GPIO_Mode_OUT;
37     gpioInitStruct.GPIO_OType = GPIO_OType_PP;
38     GPIO_Init(GPIOB, &gpioInitStruct);
39 
40     gpioInitStruct.GPIO_Pin = GPIO_Pin_7;
41     GPIO_Init(GPIOG, &gpioInitStruct);
42 
43     GPIO_SetBits(GPIOG,GPIO_Pin_7);
44     W25X_CS = 1; /* 1, register status */
45     Spi1Init();
46     Spi1SetSpeed(SPI_BaudRatePrescaler_4);
47     W25X_TYPE = W25qxxReadID();
48 }
49 
W25qxxReadSR(void)50 u8 W25qxxReadSR(void)
51 {
52     u8 byte = 0;
53     W25X_CS = 0; /* 0, register status */
54     Spi1ReadWriteByte(W25X_READSTATUSREG);
55     byte = Spi1ReadWriteByte(0Xff);
56     W25X_CS = 1; /* 1, register status */
57     return byte;
58 }
59 
W25qxxWriteSR(u8 sr)60 void W25qxxWriteSR(u8 sr)
61 {
62     W25X_CS = 0; /* 0, register status */
63     Spi1ReadWriteByte(W25X_WRITESTATUSREG);
64     Spi1ReadWriteByte(sr);
65     W25X_CS = 1; /* 1, register status */
66 }
67 
W25qxxWriteEnable(void)68 void W25qxxWriteEnable(void)
69 {
70     W25X_CS = 0; /* 0, register status */
71     Spi1ReadWriteByte(W25X_WRITEENABLE);
72     W25X_CS = 1; /* 1, register status */
73 }
74 
W25qxxWriteDisable(void)75 void W25qxxWriteDisable(void)
76 {
77     W25X_CS = 0; /* 0, register status */
78     Spi1ReadWriteByte(W25X_WRITEDISABLE);
79     W25X_CS = 1; /* 1, register status */
80 }
81 
W25qxxReadID(void)82 u16 W25qxxReadID(void)
83 {
84     u16 tmp = 0;
85     W25X_CS = 0; /* 0, register status */
86     Spi1ReadWriteByte(0x90);
87     Spi1ReadWriteByte(0x00);
88     Spi1ReadWriteByte(0x00);
89     Spi1ReadWriteByte(0x00);
90     tmp |= Spi1ReadWriteByte(0xFF) << 8;
91     tmp |= Spi1ReadWriteByte(0xFF);
92     W25X_CS = 1; /* 1, register status */
93     return tmp;
94 }
95 
W25qxxRead(u8 * pBuffer,u32 readAddr,u16 NumByteToRead)96 void W25qxxRead(u8 *pBuffer, u32 readAddr, u16 NumByteToRead)
97 {
98     W25X_CS = 0; /* 0, register status */
99     Spi1ReadWriteByte(W25X_READDATA);
100     Spi1ReadWriteByte((u8)((readAddr) >> 16));
101     Spi1ReadWriteByte((u8)((readAddr) >> 8));
102     Spi1ReadWriteByte((u8)readAddr);
103     for(u16 i = 0; i < NumByteToRead; i++) {
104         pBuffer[i] = Spi1ReadWriteByte(0XFF);
105     }
106     W25X_CS = 1; /* 1, register status */
107 }
108 
W25qxxWritePage(u8 * pBuffer,u32 writeAddr,u16 numByteToWrite)109 void W25qxxWritePage(u8 *pBuffer, u32 writeAddr, u16 numByteToWrite)
110 {
111     W25qxxWriteEnable();
112     W25X_CS = 0; /* 0, register status */
113     Spi1ReadWriteByte(W25X_PAGEPROGRAM);
114     Spi1ReadWriteByte((u8)((writeAddr) >> 16));
115     Spi1ReadWriteByte((u8)((writeAddr) >> 8));
116     Spi1ReadWriteByte((u8)writeAddr);
117     for(u16 i = 0; i < numByteToWrite; i++) {
118         Spi1ReadWriteByte(pBuffer[i]);
119     }
120     W25X_CS = 1; /* 1, register status */
121     W25qxxWaitBusy();
122 }
123 
W25qxxWriteNoCheck(u8 * pBuffer,u32 writeAddr,u16 numByteToWrite)124 void W25qxxWriteNoCheck(u8 *pBuffer, u32 writeAddr, u16 numByteToWrite)
125 {
126     u16 pageRemain;
127     pageRemain = 256 - writeAddr % 256;
128     if (numByteToWrite <= pageRemain) {
129         pageRemain = numByteToWrite;
130     }
131     while(1) {
132         W25qxxWritePage(pBuffer, writeAddr, pageRemain);
133         if(numByteToWrite == pageRemain) {
134             break;
135         } else {
136             pBuffer += pageRemain;
137             writeAddr += pageRemain;
138             numByteToWrite -= pageRemain;
139             if (numByteToWrite > 256) {
140                 pageRemain = 256;
141             }else {
142                 pageRemain = numByteToWrite;
143             }
144         }
145     }
146 }
147 
148 u8 w25qxxBuffer[BUFFER_SIZE];
W25qxxWrite(u8 * pBuffer,u32 writeAddr,u16 numByteToWrite)149 void W25qxxWrite(u8 *pBuffer, u32 writeAddr, u16 numByteToWrite)
150 {
151     u16 i;
152     u32 secPos;
153     u16 secOff;
154     u16 secRemain;
155     u8 *w25qxxBuf = w25qxxBuffer;
156 
157     secPos = writeAddr / BUFFER_SIZE;
158     secOff = writeAddr % BUFFER_SIZE;
159     secRemain = BUFFER_SIZE - secOff;
160 
161     if(numByteToWrite <= secRemain) {
162         secRemain = numByteToWrite;
163     }
164     while(1) {
165         W25qxxRead(w25qxxBuf, secPos * BUFFER_SIZE, BUFFER_SIZE);
166         for(i = 0; i < secRemain; i++) {
167             if(w25qxxBuf[secOff + i] != 0XFF) {
168                 break;
169             }
170         }
171         if( i < secRemain) {
172             W25qxxEraseSector(secPos);
173             for(i = 0; i < secRemain; i++) {
174                 w25qxxBuf[i + secOff] = pBuffer[i];
175             }
176             W25qxxWriteNoCheck(w25qxxBuf, secPos * BUFFER_SIZE, BUFFER_SIZE);
177         } else {
178             W25qxxWriteNoCheck(pBuffer, writeAddr, secRemain);
179         }
180         if(numByteToWrite==secRemain) {
181             break;
182         } else {
183             secPos++;
184             secOff = 0;
185             pBuffer += secRemain;
186             writeAddr += secRemain;
187             numByteToWrite -= secRemain;
188             if(numByteToWrite > BUFFER_SIZE) {
189                 secRemain = BUFFER_SIZE;
190             } else {
191                 secRemain = numByteToWrite;
192             }
193         }
194     }
195 }
196 
W25qxxEraseChip(void)197 void W25qxxEraseChip(void)
198 {
199     W25qxxWriteEnable();
200     W25qxxWaitBusy();
201     W25X_CS = 0; /* 0, register status */
202     Spi1ReadWriteByte(W25X_CHIPERASE);
203     W25X_CS = 1; /* 1, register status */
204     W25qxxWaitBusy();
205 }
206 
W25qxxEraseSector(u32 dstAddr)207 void W25qxxEraseSector(u32 dstAddr)
208 {
209     printf("fe:%x\r\n", dstAddr);
210     dstAddr *= BUFFER_SIZE;
211     W25qxxWriteEnable();
212     W25qxxWaitBusy();
213     W25X_CS = 0; /* 0, register status */
214     Spi1ReadWriteByte(W25X_SECTORERASE);
215     Spi1ReadWriteByte((u8)((dstAddr) >> 16));
216     Spi1ReadWriteByte((u8)((dstAddr) >> 8));
217     Spi1ReadWriteByte((u8)dstAddr);
218     W25X_CS = 1; /* 1, register status */
219     W25qxxWaitBusy();
220 }
221 
W25qxxWaitBusy(void)222 void W25qxxWaitBusy(void)
223 {
224     while ((W25qxxReadSR() & 0x01) == 0x01);
225 }
226 
W25qxxPowerDown(void)227 void W25qxxPowerDown(void)
228 {
229     W25X_CS = 0; /* 0, register status */
230     Spi1ReadWriteByte(W25X_POWERDOWN);
231     W25X_CS = 1; /* 1, register status */
232     PRT_TaskDelay(3); /* 3, number of delayed ticks */
233 }
234 
W25qxxWakeup(void)235 void W25qxxWakeup(void)
236 {
237     W25X_CS = 0; /* 0, register status */
238     Spi1ReadWriteByte(W25X_RELEASEPOWERDOWN);
239     W25X_CS = 1; /* 1, register status */
240     PRT_TaskDelay(3); /* 3, number of delayed ticks */
241 }
242