USBMSD device (USB Flashdisk) library using AT45DBxx serial flash storage chip. Works with 2, 4, 8, 16, 32 and 64 Mbit chips within AT45DBxx series.
Dependents: USBMSD_AT45_HelloWorld
USBMSD_AT45.cpp
00001 /* Copyright (c) <2012> <llumpu>, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00005 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00006 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00007 * furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 00019 /* 00020 * Inspired by Steen Joergensen (stjo2809) and Chris Styles AT45 libraries 00021 */ 00022 00023 #include "mbed.h" 00024 #include "USBMSD_AT45.h" 00025 00026 00027 00028 #define IS_PAGE_BINARY 0x01 00029 #define IS_FLASH_READY 0x80 00030 00031 #define TWO_MBIT 0x03 00032 #define FOUR_MBIT 0x04 00033 #define EIGHT_MBIT 0x05 00034 #define SIXTEEN_MBIT 0x06 00035 #define THIRTYTWO_MBIT 0x07 00036 #define SIXTYFOUR_MBIT 0x08 00037 00038 DigitalOut read_act_led(LED1); // LED indicating data are being read from storage chip 00039 DigitalOut write_act_led(LED2); // LED indicating data are being written to storage chip 00040 00041 //Serial _pc(USBTX, USBRX); 00042 00043 00044 /************************************** Constructor **************************************/ 00045 00046 00047 USBMSD_AT45::USBMSD_AT45(PinName mosi, PinName miso, PinName sclk, PinName ncs, int transport_block_size) : 00048 _spi(mosi, miso, sclk), _ncs(ncs), _transport_block_size (transport_block_size) 00049 { 00050 //_pc.baud(921600); 00051 _spi.format(8,3); 00052 _spi.frequency(24000000); 00053 00054 write_act_led = 0; 00055 read_act_led = 0; 00056 00057 _init_status = 1; // memory chip is not ready, disk_initialize() will be called in connect() 00058 00059 connect(); 00060 } 00061 00062 00063 /************************************ Public methods ************************************/ 00064 00065 00066 // This method is called when disk_status returns 0x01 (not initialized) 00067 00068 int USBMSD_AT45::disk_initialize() 00069 { 00070 _initialize(); // Determine storage chip parameters 00071 00072 write_act_led = 1; 00073 read_act_led = 1; 00074 00075 _init_status = 0; // Set status to 0x00 (initialized) 00076 00077 return _init_status; 00078 } 00079 00080 // Returns size of storage chip in bytes 00081 00082 int USBMSD_AT45::disk_size() 00083 { 00084 return _flash_size; 00085 } 00086 00087 // Returns count of sectors of storage chip 00088 00089 int USBMSD_AT45::disk_sectors() 00090 { 00091 return (_flash_size / _transport_block_size); 00092 } 00093 00094 // Returns status of storage chip - 0x00 ready, 0x01 not initialized (disk_initialize is then called) 00095 00096 int USBMSD_AT45::disk_status() 00097 { 00098 //_pc.printf("d_status \n\r "); 00099 return _init_status; 00100 } 00101 00102 // Reads block of data from storage chip. Size of block is set in constructor. 00103 00104 int USBMSD_AT45::disk_read(char* data, int block) 00105 { 00106 read_act_led = 0; 00107 00108 //_pc.printf("r 0x%2d ", block); 00109 //_pc.printf(" \n\r"); 00110 00111 int address = block * _transport_block_size; // Start address of block 00112 int count = (_transport_block_size / _flash_buffer_size); 00113 int transport_address = 0; 00114 00115 // If block transported over USB is bigger than size of AT45 SRAM buffer. 00116 // We read all parts of block one by one to SRAM 1 and SRAM 2 and then transfer them to host at once. 00117 00118 if(_transport_block_size > _flash_buffer_size) { 00119 00120 // We load data to first SRAM buffer and then to second SRAM buffer 00121 // We do this again if block transported over USB is more than 2 x bigger than SRAM buffer is 00122 00123 for(int i=0; i<(count / 2); i++) { 00124 00125 00126 _busy(); // Check if we can proceed 00127 _flashread(1, address); // Read first part of block into SRAM 1 buffer 00128 00129 _busy(); // Check if we can proceed 00130 _ncs = 0; // Chip select 00131 _spi.write(0xd4); // Read data from SRAM 1 buffer 00132 _sendaddr (0x0); // Start address of block in SRAM buffer : 0 - We read entire buffer 00133 _spi.write (0x0); // Don't care byte 00134 00135 for(int i = 0; i < _flash_buffer_size; i++) { 00136 data[transport_address + i] = _spi.write (0x0); 00137 } 00138 _ncs = 1; // Chip deselect 00139 00140 transport_address = (transport_address + _flash_buffer_size); 00141 address = (address + _flash_buffer_size); 00142 00143 _busy(); // Check if we can proceed 00144 _flashread(2,address); // Read first part of block into SRAM 2 buffer 00145 00146 _busy(); // Check if we can proceed 00147 _ncs = 0; // Chip select 00148 _spi.write(0xd6); // Read data from SRAM 2 buffer 00149 _sendaddr (0x0); // Start address of block in SRAM buffer : 0 - We read entire buffer 00150 _spi.write (0x0); // Don't care byte 00151 00152 for(int i = 0; i < _flash_buffer_size; i++) { 00153 data[transport_address + i] = _spi.write (0x0); 00154 } 00155 _ncs = 1; // Chip deselect 00156 00157 transport_address = (transport_address + _flash_buffer_size); 00158 address = (address + _flash_buffer_size); 00159 } 00160 00161 } 00162 00163 00164 // If block transported over USB equals size of AT45 SRAM buffer. 00165 // We read whole block into SRAM 1 buffer and then transport it to host. 00166 00167 else if(_transport_block_size == _flash_buffer_size) { 00168 00169 _busy(); // Check if we can proceed 00170 _flashread(1, address); // Read whole block into SRAM 1 buffer 00171 00172 _busy(); // Check if we can proceed 00173 _ncs = 0; // Chip select 00174 _spi.write(0xd4); // Read data from SRAM 1 buffer 00175 _sendaddr (0x0); // Start address of block in SRAM buffer : 0 - We read entire buffer 00176 _spi.write (0x0); // Don't care byte 00177 00178 for(int i = 0; i < _flash_buffer_size; i++) { 00179 data[transport_address + i] = _spi.write (0x0); 00180 } 00181 _ncs = 1; // Chip deselect 00182 00183 00184 } 00185 00186 // If block transported over USB is smaller than size of AT45 SRAM buffer. 00187 // We read whole page into SRAM 1 and then transfer only desired part of SRAM buffer. 00188 00189 else if(_transport_block_size < _flash_buffer_size) { 00190 00191 _busy(); // Check if we can proceed 00192 _flashread(1, address); // Read whole memory page into SRAM 1 buffer 00193 00194 _busy(); // Check if we can proceed 00195 _ncs = 0; // Chip select 00196 _spi.write(0xd4); // Read data from SRAM 1 buffer 00197 _sendaddr (0x0); // Start address of block in SRAM buffer : 0 - We read entire buffer 00198 _spi.write (0x0); // dont care byte 00199 00200 for(int i = 0; i < _transport_block_size; i++) { 00201 data[transport_address + i] = _spi.write (0x0); 00202 } 00203 _ncs = 1; // Chip deselect 00204 00205 00206 } 00207 00208 read_act_led = 1; 00209 return (0); 00210 00211 } 00212 00213 00214 // Writes block of data to storage chip. Size of block is set in constructor 00215 00216 int USBMSD_AT45::disk_write(const char* data, int block) 00217 { 00218 write_act_led = 0; 00219 00220 //_pc.printf("w 0x%2d ", block); 00221 //_pc.printf(" \n\r"); 00222 00223 int address = block * _transport_block_size; // This is the start address of the block 00224 int count = (_transport_block_size / _flash_buffer_size); 00225 int transport_address = 0; 00226 00227 // If block transported over USB is bigger than size of AT45 SRAM buffer. 00228 // We write all parts of block one by one to SRAM 1 and SRAM 2 and then we write them to flash. 00229 00230 if(_transport_block_size >_flash_buffer_size) { 00231 00232 // But if memory page size (and SRAM buffer size) is not binary 00233 // Before each write, we must read desired block from flash to SRAM buffer first 00234 // then write data from host to same SRAM buffer. After this we store whole 00235 // SRAM buffer back to flash. This slows down writing speed but must be done because 00236 // SRAM buffer size is bigger than (part of) data we want to write and it would corrupt 00237 // previously stored data if not done. 00238 00239 if(_page_size > _flash_buffer_size) { 00240 00241 for(int i=0; i<(count / 2); i++) { 00242 00243 _busy(); // Check if we can proceed 00244 _flashread(1, address); // Read first part of block into SRAM 1 buffer 00245 00246 _busy(); // Check if we can proceed 00247 _ncs = 0; // Chip select 00248 _spi.write(0x84); // Write data to SRAM 1 buffer 00249 _sendaddr (0); // Start address of block written to SRAM buffer : 0 - We write buffer from start 00250 00251 for(int i = 0; i < _flash_buffer_size; i++) { 00252 _spi.write (data[transport_address + i]); 00253 } 00254 _ncs = 1; // Chip deselect 00255 00256 _flashwrite(1, address); // Write first part of block from SRAM 1 buffer to flash 00257 00258 transport_address = (transport_address + _flash_buffer_size); 00259 address = (address + _flash_buffer_size); 00260 00261 00262 _busy(); // Check if we can proceed 00263 _flashread(2, address); // Read next part of block into SRAM 2 buffer 00264 00265 _busy(); // Check if we can proceed 00266 _ncs = 0; // Chip select 00267 _spi.write(0x87); // Write data to SRAM 2 buffer 00268 _sendaddr (0); // Start address of block written to SRAM buffer : 0 - We write buffer from start 00269 00270 for(int i = 0; i < _flash_buffer_size; i++) { 00271 _spi.write (data[transport_address + i]); 00272 } 00273 _ncs = 1; // Chip deselect 00274 00275 _flashwrite(2, address); // Write next part of block from SRAM 2 buffer to flash 00276 00277 transport_address = (transport_address + _flash_buffer_size); 00278 address = (address + _flash_buffer_size); 00279 00280 } 00281 00282 00283 } 00284 00285 00286 // Else if memory page size (and SRAM buffer size) is binary 00287 // We write all parts of block one by one to SRAM 1 and SRAM 2 and then store them to flash 00288 00289 else { 00290 00291 for(int i=0; i<(count / 2); i++) { 00292 00293 _ncs = 0; // Chip select 00294 _spi.write(0x84); // Write data to SRAM 1 buffer 00295 _sendaddr (0); // Start address of block written to SRAM buffer : 0 - We write buffer from start 00296 00297 for(int i = 0; i < _flash_buffer_size; i++) { 00298 _spi.write (data[transport_address + i]); 00299 } 00300 _ncs = 1; // Chip deselect 00301 00302 _flashwrite(1, address); // Write first part of block from SRAM 1 buffer to flash 00303 00304 transport_address = (transport_address + _flash_buffer_size); 00305 address = (address + _flash_buffer_size); 00306 00307 _ncs = 0; // Chip select 00308 _spi.write(0x87); // Write data to SRAM 2 buffer 00309 _sendaddr (0); // Start address of block written to SRAM buffer : 0 - We write buffer from start 00310 00311 for(int i = 0; i < _flash_buffer_size; i++) { 00312 _spi.write (data[transport_address + i]); 00313 } 00314 _ncs = 1; // Chip deselect 00315 00316 _flashwrite(2, address); // Write next part of block from SRAM 2 buffer to flash 00317 00318 transport_address = (transport_address + _flash_buffer_size); 00319 address = (address + _flash_buffer_size); 00320 00321 } 00322 } 00323 00324 } 00325 00326 // If block transported over USB equals size of AT45 SRAM buffer. 00327 // We write whole block into SRAM 1 buffer and then we write SRAM 1 buffer to flash. 00328 00329 else if(_transport_block_size == _flash_buffer_size) { 00330 00331 // But if memory page size (and SRAM buffer size) is not binary 00332 // Before each write, we must read desired block from flash to SRAM buffer first 00333 // then write data from host to same SRAM buffer. After this we store whole 00334 // SRAM buffer back to flash. This slows down writing speed but must be done because 00335 // SRAM buffer size is bigger than (part of) data we want to write and it would corrupt 00336 // previously stored data if not done. 00337 00338 if(_page_size > _flash_buffer_size) { 00339 _busy(); // Check if we can proceed 00340 _flashread(1, address); // Read block into SRAM 1 buffer 00341 00342 _busy(); // Check if we can proceed 00343 _ncs = 0; // Chip select 00344 _spi.write(0x84); // Write data to SRAM 1 buffer 00345 _sendaddr (0); // Start address of block written to SRAM buffer : 0 - We write buffer from start 00346 00347 for(int i = 0; i < _flash_buffer_size; i++) { 00348 _spi.write (data[transport_address + i]); 00349 } 00350 _ncs = 1; // Chip deselect 00351 00352 _flashwrite(1, address); // Write block from SRAM 1 buffer to flash 00353 00354 00355 } 00356 00357 // Else if memory page size (and SRAM buffer size) is binary 00358 // We write whole block of data to SRAM 1 buffer and then store it to flash 00359 00360 else { 00361 00362 _ncs = 0; // Chip select 00363 _spi.write(0x84); // Write data to SRAM 1 buffer 00364 _sendaddr (0); // Start address of block written to SRAM buffer : 0 - We write buffer from start 00365 00366 for(int i = 0; i < _flash_buffer_size; i++) { 00367 _spi.write (data[transport_address + i]); 00368 } 00369 _ncs = 1; // Chip deselect 00370 00371 _flashwrite(1, address); // Write block from SRAM 1 buffer to flash 00372 } 00373 00374 } 00375 00376 // If block transported over USB is smaller than size of AT45 SRAM buffer 00377 // We always have to read block being written because we store whole SRAM buffer which is bigger 00378 // than block we want write and if not done, data in previously stored blocks will be corrupted. 00379 00380 // Before each write, we must read desired block from flash to SRAM buffer first 00381 // then write data from host to same SRAM buffer. After this we store whole 00382 // SRAM buffer back to flash. This slows down writing speed but must be done because 00383 // SRAM buffer size is bigger than (part of) data we want to write and it would corrupt 00384 // previously stored data if not done. 00385 00386 else if(_transport_block_size < _flash_buffer_size) { 00387 00388 _busy(); // Check if we can proceed 00389 _flashread(1, address); // Read block into SRAM 1 buffer 00390 00391 _busy(); // Check if we can proceed 00392 _ncs = 0; // Chip select 00393 _spi.write(0x84); // Write data to SRAM 1 buffer 00394 _sendaddr (0); // Start address of block written to SRAM buffer : 0 - We write buffer from start 00395 00396 for(int i = 0; i < _transport_block_size; i++) { 00397 _spi.write (data[transport_address + i]); 00398 } 00399 _ncs = 1; // Chip deselect 00400 00401 _flashwrite(1, address); // Write block from SRAM 1 buffer to flash 00402 00403 }// if block smaller ends 00404 00405 00406 00407 write_act_led = 1; 00408 return (0); 00409 00410 } 00411 00412 00413 00414 /************************************ Protected methods ************************************/ 00415 00416 // Determine storage chip parameters 00417 00418 void USBMSD_AT45::_initialize() 00419 { 00420 _busy(); // Must be here? - Check status of storage chip 00421 00422 _ncs = 0; // Chip select 00423 00424 _spi.write(0x9f); // Read Manufacturer ID & Device ID 00425 00426 int ManufacturerID = (_spi.write(0x00)); 00427 int DeviceID_0 = (_spi.write(0x00)); 00428 int DeviceID_1 = (_spi.write(0x00)); 00429 int ExtendedID_length = (_spi.write(0x00)); 00430 00431 _ncs = 1; // Chip deselect 00432 00433 00434 int DensityCode = (DeviceID_0 & 0x1f); // Determine density of storage chip in Mbits 00435 00436 00437 _ncs = 0; // Chip select 00438 00439 _spi.write(0xd7); // Read status of storage chip and determine if memory page size is binary 00440 00441 int PageIsBinary = ((_spi.write(0x00)) & IS_PAGE_BINARY); // Check if bit 0 is set to 1 00442 00443 _ncs = 1; // Chip deselect 00444 00445 //_pc.printf("M %x \n\r", ManufacturerID); 00446 //_pc.printf("D0 %x \n\r", DeviceID_0); 00447 //_pc.printf("D1 %x \n\r", DeviceID_1); 00448 //_pc.printf("E %x \n\r", ExtendedID_length); 00449 00450 00451 if (DensityCode == TWO_MBIT) { // 2Mbits 00452 00453 if (PageIsBinary) { 00454 00455 _flash_size = 262144; 00456 _flash_buffer_size = 256; 00457 _page_size = 256; 00458 00459 } else { 00460 00461 _flash_size = 270336; 00462 _flash_buffer_size = 256; 00463 _page_size = 264; 00464 00465 } 00466 } else if (DensityCode == FOUR_MBIT) { // 4Mbits 00467 00468 if (PageIsBinary) { 00469 00470 _flash_size = 524288; 00471 _flash_buffer_size = 256; 00472 _page_size = 256; 00473 00474 } else { 00475 00476 _flash_size = 540672; 00477 _flash_buffer_size = 256; 00478 _page_size = 264; 00479 00480 } 00481 } else if (DensityCode == EIGHT_MBIT) { // 8Mbits 00482 00483 if (PageIsBinary) { 00484 00485 _flash_size = 1048576; 00486 _flash_buffer_size = 256; 00487 _page_size = 256; 00488 00489 } else { 00490 00491 _flash_size = 1081344; 00492 _flash_buffer_size = 256; 00493 _page_size = 264; 00494 00495 } 00496 } else if (DensityCode == SIXTEEN_MBIT) { // 16Mbits 00497 00498 if (PageIsBinary) { 00499 00500 _flash_size = 2097152; 00501 _flash_buffer_size = 512; 00502 _page_size = 512; 00503 00504 } else { 00505 00506 _flash_size = 2162688; 00507 _flash_buffer_size = 512; 00508 _page_size = 528; 00509 00510 } 00511 } else if (DensityCode == THIRTYTWO_MBIT) { // 32Mbits 00512 00513 if (PageIsBinary) { 00514 00515 _flash_size = 4194304; 00516 _flash_buffer_size = 512; 00517 _page_size = 512; 00518 00519 } else { 00520 00521 _flash_size = 4325376; 00522 _flash_buffer_size = 512; 00523 _page_size = 528; 00524 00525 } 00526 } else if (DensityCode == SIXTYFOUR_MBIT) { // 64Mbits 00527 00528 if (PageIsBinary) { 00529 00530 _flash_size = 8388608; 00531 _flash_buffer_size = 1024; 00532 _page_size = 1024; 00533 00534 } else { 00535 00536 _flash_size = 8650752; 00537 _flash_buffer_size = 1024; 00538 _page_size = 1056; 00539 00540 } 00541 } else { 00542 00543 _flash_size = -1; 00544 _flash_buffer_size = -1; 00545 _page_size = -1; 00546 00547 } 00548 } 00549 00550 00551 00552 void USBMSD_AT45::_busy() 00553 { 00554 //_pc.printf("BUSY? \n\r"); 00555 00556 volatile int IsBusy = 1; 00557 while (IsBusy) { 00558 _ncs = 0; // Chip select 00559 00560 _spi.write(0xd7); // Read status register of storage chip 00561 00562 int IsReady = ((_spi.write(0x00)) & IS_FLASH_READY); // If bit 7 is set we can proceed 00563 00564 _ncs = 1; // Chip deselect 00565 00566 if (IsReady) { 00567 IsBusy = 0; 00568 00569 00570 00571 } 00572 } 00573 } 00574 00575 00576 00577 // Write and SRAM buffer to main memory 00578 void USBMSD_AT45::_flashwrite (int buffer, int address) 00579 { 00580 00581 int cmd = 0; 00582 int paddr = _getpaddr(address); // Calculate address 00583 00584 _ncs = 0; // Chip select 00585 00586 if (buffer == 1) { 00587 cmd = 0x83; // Write SRAM 1 buffer to flash 00588 } else { 00589 cmd = 0x86; // Write SRAM 2 buffer to flash 00590 } 00591 00592 _spi.write (cmd); 00593 _sendaddr (paddr); 00594 _ncs = 1; // Chip deselect 00595 00596 } 00597 00598 // Read from Flash memory into SRAM buffer 00599 00600 void USBMSD_AT45::_flashread (int buffer, int address) 00601 { 00602 00603 int cmd = 0; 00604 int paddr = _getpaddr(address); // Calculate address 00605 00606 _ncs = 0; // Chip select 00607 00608 if (buffer == 1) { 00609 cmd = 0x53; // Read from flash to SRAM 1 buffer 00610 } else { 00611 cmd = 0x55; // Read from flash to SRAM 2 buffer 00612 } 00613 00614 _spi.write (cmd); 00615 _sendaddr (paddr); 00616 _ncs = 1; // Chip deselect 00617 00618 } 00619 00620 00621 00622 // Work out the page address 00623 // If we have a 2^N page size, it is just the top N bits 00624 // If we have non-2^N, we use the shifted address 00625 00626 int USBMSD_AT45::_getpaddr(int address) 00627 { 00628 00629 int paddr; 00630 00631 if (_page_size == 256) { 00632 paddr = address & 0xffffff00; 00633 } else if (_page_size == 264) { 00634 paddr = (address << 1) & 0xfffffe00; 00635 } else if (_page_size == 512) { 00636 paddr = address & 0xfffffe00; 00637 } else if (_page_size == 528 ) { 00638 paddr = (address << 1) & 0xfffffc00; 00639 } else if (_page_size == 1024) { 00640 paddr = address & 0xfffffc00; 00641 } else if (_page_size == 1056 ) { 00642 paddr = (address << 1) & 0xfffff800; 00643 } else { 00644 paddr = -1; 00645 } 00646 00647 return (paddr); 00648 } 00649 00650 00651 00652 // Sends the three least significant bytes of the supplied address 00653 00654 void USBMSD_AT45::_sendaddr (int address) 00655 { 00656 _spi.write(address >> 16); 00657 _spi.write(address >> 8); 00658 _spi.write(address); 00659 }
Generated on Fri Jul 15 2022 12:07:27 by
![doxygen](doxygen.png)