1 /*
2 * Copyright (c) 2006-2018, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2011-12-16 aozima the first version
9 */
10
11 #include <stdint.h>
12 #include "spi_flash_sst25vfxx.h"
13
14 #define FLASH_DEBUG
15
16 #ifdef FLASH_DEBUG
17 #define FLASH_TRACE rt_kprintf
18 #else
19 #define FLASH_TRACE(...)
20 #endif /* #ifdef FLASH_DEBUG */
21
22 /* JEDEC Manufacturer’s ID */
23 #define MF_ID (0xBF)
24 /* JEDEC Device ID : Memory Type */
25 #define MT_ID (0x25)
26 /* JEDEC Device ID: Memory Capacity */
27 #define MC_ID_SST25VF020B (0x8C) /* 2Mbit */
28 #define MC_ID_SST25VF040B (0x8D) /* 4Mbit */
29 #define MC_ID_SST25VF080B (0x8E) /* 8Mbit */
30 #define MC_ID_SST25VF016B (0x41) /* 16Mbit */
31 #define MC_ID_SST25VF032B (0x4A) /* 32Mbit */
32 #define MC_ID_SST25VF064C (0x4B) /* 64Mbit */
33
34 /* command list */
35 #define CMD_RDSR (0x05)
36 #define CMD_WRSR (0x01)
37 #define CMD_EWSR (0x50)
38 #define CMD_WRDI (0x04)
39 #define CMD_WREN (0x06)
40 #define CMD_READ (0x03)
41 #define CMD_FAST_READ (0x0B)
42 #define CMD_BP (0x02)
43 #define CMD_AAIP (0xAD)
44 #define CMD_ERASE_4K (0x20)
45 #define CMD_ERASE_32K (0x52)
46 #define CMD_ERASE_64K (0xD8)
47 #define CMD_ERASE_full (0xC7)
48 #define CMD_JEDEC_ID (0x9F)
49 #define CMD_EBSY (0x70)
50 #define CMD_DBSY (0x80)
51
52 #define DUMMY (0xFF)
53
54 static struct spi_flash_sst25vfxx spi_flash_sst25vfxx;
55
sst25vfxx_read_status(struct spi_flash_sst25vfxx * spi_flash)56 static uint8_t sst25vfxx_read_status(struct spi_flash_sst25vfxx * spi_flash)
57 {
58 return rt_spi_sendrecv8(spi_flash->rt_spi_device, CMD_RDSR);
59 }
60
sst25vfxx_wait_busy(struct spi_flash_sst25vfxx * spi_flash)61 static void sst25vfxx_wait_busy(struct spi_flash_sst25vfxx * spi_flash)
62 {
63 while( sst25vfxx_read_status(spi_flash) & (0x01));
64 }
65
66 /** \brief write N page on [page]
67 *
68 * \param page uint32_t unit : byte (4096 * N,1 page = 4096byte)
69 * \param buffer const uint8_t*
70 * \param size uint32_t unit : byte ( 4096*N )
71 * \return uint32_t
72 *
73 */
sst25vfxx_page_write(struct spi_flash_sst25vfxx * spi_flash,uint32_t page,const uint8_t * buffer,uint32_t size)74 static uint32_t sst25vfxx_page_write(struct spi_flash_sst25vfxx * spi_flash, uint32_t page, const uint8_t * buffer, uint32_t size)
75 {
76 uint32_t index;
77 uint32_t need_wirte = size;
78 uint8_t send_buffer[6];
79
80 page &= ~0xFFF; // page size = 4096byte
81
82 send_buffer[0] = CMD_WREN;
83 rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
84
85 send_buffer[0] = CMD_ERASE_4K;
86 send_buffer[1] = (page >> 16);
87 send_buffer[2] = (page >> 8);
88 send_buffer[3] = (page);
89 rt_spi_send(spi_flash->rt_spi_device, send_buffer, 4);
90
91 sst25vfxx_wait_busy(spi_flash); // wait erase done.
92
93 send_buffer[0] = CMD_WREN;
94 rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
95
96 send_buffer[0] = CMD_AAIP;
97 send_buffer[1] = (uint8_t)(page >> 16);
98 send_buffer[2] = (uint8_t)(page >> 8);
99 send_buffer[3] = (uint8_t)(page);
100 send_buffer[4] = *buffer++;
101 send_buffer[5] = *buffer++;
102 need_wirte -= 2;
103 rt_spi_send(spi_flash->rt_spi_device, send_buffer, 6);
104
105 sst25vfxx_wait_busy(spi_flash);
106
107 for(index=0; index < need_wirte/2; index++)
108 {
109 send_buffer[0] = CMD_AAIP;
110 send_buffer[1] = *buffer++;
111 send_buffer[2] = *buffer++;
112 rt_spi_send(spi_flash->rt_spi_device, send_buffer, 3);
113 sst25vfxx_wait_busy(spi_flash);
114 }
115
116 send_buffer[0] = CMD_WRDI;
117 rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
118
119 return size;
120 }
121
122 /* RT-Thread device interface */
sst25vfxx_flash_init(rt_device_t dev)123 static rt_err_t sst25vfxx_flash_init(rt_device_t dev)
124 {
125 return RT_EOK;
126 }
127
sst25vfxx_flash_open(rt_device_t dev,rt_uint16_t oflag)128 static rt_err_t sst25vfxx_flash_open(rt_device_t dev, rt_uint16_t oflag)
129 {
130 rt_err_t result;
131 uint8_t send_buffer[2];
132 struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev;
133
134 /* lock spi flash */
135 result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER);
136 if(result != RT_EOK)
137 {
138 return result;
139 }
140
141 send_buffer[0] = CMD_DBSY;
142 rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
143
144 send_buffer[0] = CMD_EWSR;
145 rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
146
147 send_buffer[0] = CMD_WRSR;
148 send_buffer[1] = 0;
149 rt_spi_send(spi_flash->rt_spi_device, send_buffer, 2);
150
151 /* release lock */
152 rt_mutex_release(&(spi_flash->lock));
153
154 return RT_EOK;
155 }
156
sst25vfxx_flash_close(rt_device_t dev)157 static rt_err_t sst25vfxx_flash_close(rt_device_t dev)
158 {
159 return RT_EOK;
160 }
161
sst25vfxx_flash_control(rt_device_t dev,int cmd,void * args)162 static rt_err_t sst25vfxx_flash_control(rt_device_t dev, int cmd, void *args)
163 {
164 struct spi_flash_sst25vfxx * spi_flash;
165
166 spi_flash = (struct spi_flash_sst25vfxx *)dev;
167
168 RT_ASSERT(dev != RT_NULL);
169
170 if (cmd == RT_DEVICE_CTRL_BLK_GETGEOME)
171 {
172 struct rt_device_blk_geometry *geometry;
173
174 geometry = (struct rt_device_blk_geometry *)args;
175 if (geometry == RT_NULL) return -RT_ERROR;
176
177 geometry->bytes_per_sector = spi_flash->geometry.bytes_per_sector;
178 geometry->sector_count = spi_flash->geometry.sector_count;
179 geometry->block_size = spi_flash->geometry.block_size;
180 }
181
182 return RT_EOK;
183 }
184
sst25vfxx_flash_read(rt_device_t dev,rt_off_t pos,void * buffer,rt_size_t size)185 static rt_size_t sst25vfxx_flash_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
186 {
187 rt_err_t result;
188 uint8_t send_buffer[4];
189 struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev;
190 uint32_t offset = pos * spi_flash->geometry.bytes_per_sector;
191
192 /* lock spi flash */
193 result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER);
194 if(result != RT_EOK)
195 {
196 return 0;
197 }
198
199 send_buffer[0] = CMD_WRDI;
200 rt_spi_send(spi_flash->rt_spi_device, send_buffer, 1);
201
202 send_buffer[0] = CMD_READ;
203 send_buffer[1] = (uint8_t)(offset>>16);
204 send_buffer[2] = (uint8_t)(offset>>8);
205 send_buffer[3] = (uint8_t)(offset);
206 rt_spi_send_then_recv(spi_flash->rt_spi_device, send_buffer, 4, buffer, size * spi_flash->geometry.bytes_per_sector);
207
208 /* release lock */
209 rt_mutex_release(&(spi_flash->lock));
210
211 return size;
212 }
213
sst25vfxx_flash_write(rt_device_t dev,rt_off_t pos,const void * buffer,rt_size_t size)214 static rt_size_t sst25vfxx_flash_write(rt_device_t dev, rt_off_t pos, const void* buffer, rt_size_t size)
215 {
216 uint32_t i;
217 rt_err_t result;
218 const uint8_t * write_buffer = buffer;
219 struct spi_flash_sst25vfxx * spi_flash = (struct spi_flash_sst25vfxx *)dev;
220
221 /* lock spi flash */
222 result = rt_mutex_take(&(spi_flash->lock), RT_WAITING_FOREVER);
223 if(result != RT_EOK)
224 {
225 return 0;
226 }
227
228 for(i=0; i<size; i++)
229 {
230 sst25vfxx_page_write(spi_flash,
231 (pos + i) * spi_flash->geometry.bytes_per_sector,
232 write_buffer,
233 spi_flash->geometry.bytes_per_sector);
234 write_buffer += spi_flash->geometry.bytes_per_sector;
235 }
236
237 /* release lock */
238 rt_mutex_release(&(spi_flash->lock));
239
240 return size;
241 }
242
243 #ifdef RT_USING_DEVICE_OPS
244 const static struct rt_device_ops sst25vfxx_device_ops =
245 {
246 sst25vfxx_flash_init,
247 sst25vfxx_flash_open,
248 sst25vfxx_flash_close,
249 sst25vfxx_flash_read,
250 sst25vfxx_flash_write,
251 sst25vfxx_flash_control
252 };
253 #endif
254
sst25vfxx_init(const char * flash_device_name,const char * spi_device_name)255 rt_err_t sst25vfxx_init(const char * flash_device_name, const char * spi_device_name)
256 {
257 struct rt_spi_device * rt_spi_device;
258 struct spi_flash_sst25vfxx * spi_flash = &spi_flash_sst25vfxx;
259
260 rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name);
261 if(rt_spi_device == RT_NULL)
262 {
263 FLASH_TRACE("spi device %s not found!\r\n", spi_device_name);
264 return -RT_ENOSYS;
265 }
266 spi_flash->rt_spi_device = rt_spi_device;
267
268 /* config spi */
269 {
270 struct rt_spi_configuration cfg;
271 cfg.data_width = 8;
272 cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0 and Mode 3 */
273 cfg.max_hz = 50000000; /* 50M */
274 rt_spi_configure(spi_flash->rt_spi_device, &cfg);
275 }
276
277 /* init flash */
278 {
279 rt_uint8_t cmd;
280 rt_uint8_t id_recv[3];
281
282 cmd = CMD_WRDI;
283 rt_spi_send(spi_flash->rt_spi_device, &cmd, 1);
284
285 /* read flash id */
286 cmd = CMD_JEDEC_ID;
287 rt_spi_send_then_recv(spi_flash->rt_spi_device, &cmd, 1, id_recv, 3);
288
289 if(id_recv[0] != MF_ID || id_recv[1] != MT_ID)
290 {
291 FLASH_TRACE("Manufacturer’s ID or Memory Type error!\r\n");
292 FLASH_TRACE("JEDEC Read-ID Data : %02X %02X %02X\r\n", id_recv[0], id_recv[1], id_recv[2]);
293 return -RT_ENOSYS;
294 }
295
296 spi_flash->geometry.bytes_per_sector = 4096;
297 spi_flash->geometry.block_size = 4096; /* block erase: 4k */
298
299 if(id_recv[2] == MC_ID_SST25VF020B)
300 {
301 FLASH_TRACE("SST25VF020B detection\r\n");
302 spi_flash->geometry.sector_count = 64;
303 }
304 else if(id_recv[2] == MC_ID_SST25VF040B)
305 {
306 FLASH_TRACE("SST25VF040B detection\r\n");
307 spi_flash->geometry.sector_count = 128;
308 }
309 else if(id_recv[2] == MC_ID_SST25VF080B)
310 {
311 FLASH_TRACE("SST25VF080B detection\r\n");
312 spi_flash->geometry.sector_count = 256;
313 }
314 else if(id_recv[2] == MC_ID_SST25VF016B)
315 {
316 FLASH_TRACE("SST25VF016B detection\r\n");
317 spi_flash->geometry.sector_count = 512;
318 }
319 else if(id_recv[2] == MC_ID_SST25VF032B)
320 {
321 FLASH_TRACE("SST25VF032B detection\r\n");
322 spi_flash->geometry.sector_count = 1024;
323 }
324 else if(id_recv[2] == MC_ID_SST25VF064C)
325 {
326 FLASH_TRACE("SST25VF064C detection\r\n");
327 spi_flash->geometry.sector_count = 2048;
328 }
329 else
330 {
331 FLASH_TRACE("Memory Capacity error!\r\n");
332 return -RT_ENOSYS;
333 }
334 }
335
336 /* initialize mutex lock */
337 rt_mutex_init(&spi_flash->lock, flash_device_name, RT_IPC_FLAG_PRIO);
338
339 /* register device */
340 spi_flash->flash_device.type = RT_Device_Class_Block;
341 #ifdef RT_USING_DEVICE_OPS
342 spi_flash->flash_device.ops = &sst25vfxx_device_ops;
343 #else
344 spi_flash->flash_device.init = sst25vfxx_flash_init;
345 spi_flash->flash_device.open = sst25vfxx_flash_open;
346 spi_flash->flash_device.close = sst25vfxx_flash_close;
347 spi_flash->flash_device.read = sst25vfxx_flash_read;
348 spi_flash->flash_device.write = sst25vfxx_flash_write;
349 spi_flash->flash_device.control = sst25vfxx_flash_control;
350 #endif
351 /* no private */
352 spi_flash->flash_device.user_data = RT_NULL;
353
354 rt_device_register(&spi_flash->flash_device, flash_device_name,
355 RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
356
357 return RT_EOK;
358 }
359