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

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers USBMSD_AT45.cpp Source File

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 }