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 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 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 */ 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 */ 123 static rt_err_t sst25vfxx_flash_init(rt_device_t dev) 124 { 125 return RT_EOK; 126 } 127 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 157 static rt_err_t sst25vfxx_flash_close(rt_device_t dev) 158 { 159 return RT_EOK; 160 } 161 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 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 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 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