Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
AT45.cpp
00001 /* mbed AT45 Library, for driving the Atmel AT45 series Dataflash with Serial Interface (SPI) 00002 * Copyright (c) 2012, Created by Steen Joergensen (stjo2809) inspired by Chris Styles AT45 library 00003 * 00004 * Permission is hereby granted, free of charge, to any person obtaining a copy 00005 * of this software and associated documentation files (the "Software"), to deal 00006 * in the Software without restriction, including without limitation the rights 00007 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00008 * copies of the Software, and to permit persons to whom the Software is 00009 * furnished to do so, subject to the following conditions: 00010 * 00011 * The above copyright notice and this permission notice shall be included in 00012 * all copies or substantial portions of the Software. 00013 * 00014 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00015 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00016 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00017 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00018 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00019 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00020 * THE SOFTWARE. 00021 */ 00022 00023 #include "mbed.h" 00024 #include "AT45.h" 00025 00026 //============================================================================= 00027 // Public functions 00028 //============================================================================= 00029 00030 AT45::AT45(SPI& spi, PinName ncs) : _spi(spi), _ncs(ncs) 00031 { 00032 00033 _pages = -1; // number of pages 00034 _pagesize = -1; // size of pages 256/264, 512/528, 1024/1056 00035 _devicesize = -1; // In bytes 00036 _deep_down = true; // variable for deep power down function (awake ?) 00037 _deep_down_onoff = false; // variable for deep power down function (On/Off) 00038 00039 _initialize(); // Populate all this stuff 00040 00041 } 00042 00043 // This function returns the char 00044 char AT45::read_byte(int address) 00045 { 00046 // return byte from address 00047 return (_memread( address )); 00048 } 00049 00050 int AT45::read_page(char* data, int page) 00051 { 00052 int address = -1; 00053 00054 if(_pagesize == 256) 00055 { 00056 address = page * 256; 00057 } 00058 else if(_pagesize == 264) 00059 { 00060 address = page * 512; 00061 } 00062 else if(_pagesize == 512) 00063 { 00064 address = page * 512; 00065 } 00066 else if(_pagesize == 528) 00067 { 00068 address = page * 1024; 00069 } 00070 else if(_pagesize == 1024) 00071 { 00072 address = page * 1024; 00073 } 00074 else if(_pagesize == 1056) 00075 { 00076 address = page * 2048; 00077 } 00078 else 00079 { 00080 return (-1); // something isnt configured right 00081 } 00082 00083 _busy(); 00084 _flashread(1,address); // read the first page of the block into SRAM buffer 1 00085 _busy(); // Wait until First page has loaded into buffer 1 00086 00087 // this is done directly as we are reading back an entire buffer, and this can be done more optimally than using _sramread 00088 _select(); 00089 _spi.write(0xd4); 00090 _sendaddr (0x0); 00091 _spi.write (0x0); // dont care byte 00092 00093 for(int i=0; i<_pagesize ;i++) 00094 { 00095 data[i] = _spi.write (0x0); 00096 } 00097 _deselect(); 00098 00099 return (0); 00100 } 00101 int AT45::read_block(char *data, int block) // under construction F�R CHECK AF MIC OG LERCHE 00102 { 00103 char temp_data[_pagesize]; 00104 int page_start; 00105 00106 if (block < _blocks || block == 0) { 00107 page_start = block * 8; 00108 00109 for (int i=0; i<8; i++) { 00110 read_page(temp_data, page_start); 00111 //printf("%d Read round, Data is: %d\r\n",i,*temp_data); 00112 page_start = page_start + 1; 00113 for (int z=0; z<_pagesize ; z++) { 00114 data[z+(_pagesize*i)] = temp_data[z]; 00115 } 00116 } 00117 } else { 00118 //do nothing 00119 } 00120 //printf("Read done, Data is: %d\r\n",*data); 00121 return (0); 00122 } 00123 00124 int AT45::read_block(char *data[], int block) // under construction F� CHECK AF MIC OG LERCHE 00125 { 00126 char temp_data[_pagesize]; 00127 int page_start; 00128 00129 if(block < _blocks || block == 0) 00130 { 00131 page_start = block * 8; 00132 00133 for(int i=0; i<8 ;i++) // 8 pages in a block 00134 { 00135 read_page(temp_data, page_start); 00136 page_start = page_start + 1; 00137 for(int z=0; z<_pagesize ;z++) 00138 { 00139 data[i][z] = temp_data[z]; 00140 } 00141 } 00142 } 00143 else 00144 { 00145 //do nothing 00146 } 00147 00148 return (0); 00149 } 00150 00151 // This function writes the char to the address supplied 00152 // Note : We pass the raw address to the underlying functions 00153 void AT45::write_byte(int address, char data) 00154 { 00155 _busy(); 00156 _flashread(1,address); // read the Flash page into SRAM buffer 00157 _busy(); // wait for the read to complete 00158 _sramwrite(1,address,data); // Write new data into SRAM 00159 _busy(); // Make sure flash isnt busy 00160 _flashwrite(1,address); // Write back to the page address 00161 } 00162 00163 int AT45::write_page(char* data, int page) 00164 { 00165 int address = -1; 00166 00167 if(_pagesize == 256) 00168 { 00169 address = page * 256; 00170 } 00171 else if(_pagesize == 264) 00172 { 00173 address = page * 512; 00174 } 00175 else if(_pagesize == 512) 00176 { 00177 address = page * 512; 00178 } 00179 else if(_pagesize == 528) 00180 { 00181 address = page * 1024; 00182 } 00183 else if(_pagesize == 1024) 00184 { 00185 address = page * 1024; 00186 } 00187 else if(_pagesize == 1056) 00188 { 00189 address = page * 2048; 00190 } 00191 else 00192 { 00193 return (-1); // something isnt configured right 00194 } 00195 00196 _select(); 00197 _spi.write(0x84); // writing to buffer #1 00198 _sendaddr (0); // we are writing to the entire buffer 00199 00200 for(int i=0; i<_pagesize ;i++) 00201 { 00202 _spi.write (data[i]); 00203 } 00204 _deselect(); 00205 00206 _busy(); // make sure the Flahs isnt busy 00207 00208 // issue command to write buffer 1 to the appropraite flash page 00209 _select(); 00210 _spi.write (0x83); 00211 _sendaddr (_getpaddr(address)); 00212 _deselect(); 00213 00214 return (0); 00215 } 00216 int AT45::write_block(char *data, int block) // under construction F�R CHECK AF MIC OG LERCHE 00217 { 00218 00219 int page_start; 00220 char page_arr[_pagesize]; 00221 00222 if (block < _blocks || block == 0) 00223 { 00224 page_start = block * 8; 00225 00226 for (int i=0; i<8 ; i++) 00227 { 00228 // Copy data from *data at 0 to 511 _ 512 - 1023, and so on every round. 00229 memcpy(page_arr, &data[_pagesize*i], _pagesize); 00230 00231 write_page(page_arr, page_start); 00232 page_start = page_start + 1; 00233 } 00234 } else { 00235 //do nothing 00236 } 00237 00238 return (0); 00239 } 00240 int AT45::write_block(char *data[], int block) // under construction F� CHECK AF MIC OG LERCHE 00241 { 00242 char temp_data[_pagesize]; 00243 int page_start; 00244 00245 if(block < _blocks || block == 0) 00246 { 00247 page_start = block * 8; 00248 00249 for(int i=0; i<8 ;i++) 00250 { 00251 for(int z=0; z<_pagesize ;z++) 00252 { 00253 temp_data[z] = data[i][z]; 00254 } 00255 write_page(temp_data, page_start); 00256 page_start = page_start + 1; 00257 } 00258 } 00259 else 00260 { 00261 //do nothing 00262 } 00263 00264 return (0); 00265 } 00266 00267 int AT45::FAT_read(char* data, int page) 00268 { 00269 // For 256 byte pages, we read two pages 00270 if((_pagesize == 256) || (_pagesize == 264)) 00271 { 00272 int address = page * 512; // This is the start address of the 512 byte block 00273 00274 _flashread(1,address); // read the first page of the block into SRAM buffer 1 00275 _busy(); // Wait until First page has loaded into buffer 1 00276 00277 // this is done directly as we are reading back an entire buffer, and this can be done more optimally than using _sramread 00278 _select(); 00279 _spi.write(0xd4); 00280 _sendaddr (0x0); 00281 _spi.write (0x0); // dont care byte 00282 00283 for(int i=0;i<256;i++) 00284 { 00285 data[i] = _spi.write (0x0); 00286 } 00287 _deselect(); 00288 00289 _flashread(1,address+256); // read the second page of the block into SRAM buffer 2 00290 _busy(); // Wait until second page has loaded into buffer 2 00291 00292 // Now the second page is loaded, pull this out into the second half of the data buffer 00293 // this is done directly as we are reading back an entire buffer, and this can be done more optimally than using _sramread 00294 _select(); 00295 _spi.write(0xd4); 00296 _sendaddr (0x0); 00297 _spi.write (0x0); // dont care byte 00298 00299 for(int i=0;i<256;i++) 00300 { 00301 data[256+i] = _spi.write (0x0); 00302 } 00303 _deselect(); 00304 return (0); 00305 } 00306 00307 // For 512 byte pages, we read just the single page, transfer it 00308 else if((_pagesize == 512) || (_pagesize == 528)) 00309 { 00310 int address = page * 512; // This is the start address of the 512 byte block 00311 00312 _busy(); // Wait until First page has loaded into buffer 1 00313 _flashread(1,address); // read the first page of the block into SRAM buffer 1 00314 _busy(); // Wait until First page has loaded into buffer 1 00315 00316 // Now the page has loaded, simply transfer it from the sram buffer to the data array 00317 // this is done directly as we are reading back an entire buffer, and this can be done more optimally than using _sramread 00318 _select(); 00319 _spi.write(0xd4); 00320 _sendaddr (0x0); 00321 _spi.write (0x0); // dont care byte 00322 00323 for(int i=0;i<512;i++) 00324 { 00325 data[i] = _spi.write (0x0); 00326 } 00327 _deselect(); 00328 return (0); 00329 } 00330 00331 // For 1024 byte pages, we read just a single page, transfer half of it 00332 else if((_pagesize == 1024) || (_pagesize == 1056)) 00333 { 00334 int address = _getpaddr(page * 512); // This is the start address of the 512 byte block 00335 00336 _busy(); // Wait until First page has loaded into buffer 1 00337 00338 _flashread(1,address); // read the first page of the block into SRAM buffer 1 00339 00340 _busy(); // Wait until First page has loaded into buffer 1 00341 00342 // Now the page has loaded, simply transfer it from the sram buffer to the data array 00343 // this is done directly as we are reading back an entire buffer, and this can be done more optimally than using _sramread 00344 00345 _select(); 00346 _spi.write(0xd4); 00347 00348 if (page %2) // odd numbered block, read from adress 0x200 00349 { 00350 _sendaddr (0x200); 00351 } 00352 else // even numbered block, then we are reading from sram buffer 0x0 00353 { 00354 _sendaddr (0x0); 00355 } 00356 00357 _spi.write (0x0); // dont care byte 00358 00359 for(int i=0;i<512;i++) 00360 { 00361 data[i] = _spi.write (0x0); 00362 } 00363 _deselect(); 00364 return (0); 00365 } 00366 else 00367 { 00368 return (-1); // something isnt configured right 00369 } 00370 } 00371 00372 int AT45::FAT_write(char* data, int page) 00373 { 00374 // For 256 byte pages, we overwrite two pages 00375 if((_pagesize == 256) || (_pagesize == 264)) 00376 { 00377 00378 // fill the first buffer with the first half of the block 00379 // do this directly, for better performance 00380 _select(); 00381 _spi.write(0x84); // writing to buffer #1 00382 _sendaddr (0); // we are writing to the entire buffer 00383 00384 for(int i=0;i<256;i++) { 00385 _spi.write (data[i]); 00386 } 00387 _deselect(); 00388 00389 _flashwrite(1,(page*512)); 00390 00391 // fill the buffer with the second half of the block 00392 // do this directly, for better performance 00393 _select(); 00394 _spi.write(0x84); // writing to buffer #1 00395 _sendaddr (0); // we are writing to the entire buffer 00396 00397 for(int i=0;i<256;i++) { 00398 _spi.write (data[256+i]); 00399 } 00400 _deselect(); 00401 00402 _flashwrite(1,((page*512)+256)); 00403 } 00404 00405 // For 512 byte pages, we overwrite a single page 00406 else if((_pagesize == 512) || (_pagesize == 528)) 00407 { 00408 00409 // fill the first buffer with the block data 00410 // do this directly, for better performance 00411 _select(); 00412 _spi.write(0x84); // writing to buffer #1 00413 _sendaddr (0); // we are writing to the entire buffer 00414 00415 for(int i=0;i<512;i++) { 00416 _spi.write (data[i]); 00417 } 00418 _deselect(); 00419 00420 _busy(); // make sure the Flahs isnt busy 00421 00422 // issue command to write buffer 1 to the appropraite flash page 00423 _select(); 00424 _spi.write (0x83); 00425 _sendaddr (_getpaddr(page * 512)); 00426 _deselect(); 00427 } 00428 00429 // For 1024 byte pages, we do a read modify write 00430 // must make sure we overwrite the right half of the page! 00431 else if((_pagesize == 1024) || (_pagesize == 1056)) 00432 { 00433 00434 _busy(); // make sure the flash isnt busy 00435 00436 int address = _getpaddr(page*512); 00437 00438 // Read the page into sram 00439 _flashread(1,address); 00440 00441 // wait for this operation to complete 00442 _busy(); 00443 00444 // Overwrite the appropriate half 00445 // do this directly, for better performance 00446 _select(); 00447 _spi.write(0x84); // writing to buffer #1 00448 00449 if(page%2) // this is an odd block number, overwrite second half of buffer 00450 { 00451 _sendaddr (0x200); // we are writing to the entire buffer 00452 } 00453 else // this is an even block, overwrite the first half 00454 { 00455 _sendaddr (0x0); // we are writing to the entire buffer 00456 } 00457 00458 for(int i=0;i<512;i++) 00459 { 00460 _spi.write (data[i]); 00461 } 00462 _deselect(); 00463 00464 // Write the page back 00465 _busy(); 00466 _flashwrite(1,address); 00467 } 00468 00469 // Something has gone wrong 00470 else 00471 { 00472 return (-1); 00473 } 00474 00475 return (0); 00476 } 00477 00478 // Erase the entire chip 00479 void AT45::chip_erase() 00480 { 00481 _busy(); // make sure flash isnt already in busy. 00482 00483 _select(); 00484 // 4 byte command sequence 00485 _spi.write(0xc7); 00486 _spi.write(0x94); 00487 _spi.write(0x80); 00488 _spi.write(0x9a); 00489 _deselect(); 00490 00491 _busy(); // Make erase a blocking function 00492 } 00493 00494 // Erase one block 00495 void AT45::block_erase(int block) 00496 { 00497 int address = -1; 00498 00499 // Calculate page addresses 00500 if(block < _blocks || block == 0) 00501 { 00502 if(_pagesize == 256) 00503 { 00504 address = block * 2048; 00505 } 00506 else if(_pagesize == 264) 00507 { 00508 address = block * 4096; 00509 } 00510 else if(_pagesize == 512) 00511 { 00512 address = block * 4096; 00513 } 00514 else if(_pagesize == 528) 00515 { 00516 address = block * 8192; 00517 } 00518 else if(_pagesize == 1024) 00519 { 00520 address = block * 8192; 00521 } 00522 else if(_pagesize == 1056) 00523 { 00524 address = block * 16384; 00525 } 00526 00527 _busy(); 00528 _select(); 00529 _spi.write(0x50); 00530 _sendaddr (address); 00531 _deselect(); 00532 _busy(); 00533 } 00534 else 00535 { 00536 //do nothing 00537 } 00538 } 00539 00540 // Erase one page 00541 void AT45::page_erase(int page) 00542 { 00543 int address = -1; 00544 00545 // Calculate page addresses 00546 if(page < _pages || page == 0) 00547 { 00548 if(_pagesize == 256) 00549 { 00550 address = page * 256; 00551 } 00552 else if(_pagesize == 264) 00553 { 00554 address = page * 512; 00555 } 00556 else if(_pagesize == 512) 00557 { 00558 address = page * 512; 00559 } 00560 else if(_pagesize == 528) 00561 { 00562 address = page * 1024; 00563 } 00564 else if(_pagesize == 1024) 00565 { 00566 address = page * 1024; 00567 } 00568 else if(_pagesize == 1056) 00569 { 00570 address = page * 2048; 00571 } 00572 00573 _busy(); 00574 _select(); 00575 _spi.write(0x81); 00576 _sendaddr (address); 00577 _deselect(); 00578 _busy(); 00579 } 00580 else 00581 { 00582 //do nothing 00583 } 00584 } 00585 00586 // return the size of the part in bytes 00587 int AT45::device_size() 00588 { 00589 return _devicesize; 00590 } 00591 00592 // return the numbers of pages 00593 int AT45::pages() 00594 { 00595 return _pages; 00596 } 00597 00598 // return the page size of the part in bytes 00599 int AT45::pagesize() 00600 { 00601 return _pagesize; 00602 } 00603 00604 // A one-time programmable configuration 00605 void AT45::set_pageszie_to_binary() 00606 { 00607 _busy(); // make sure flash isnt already in busy. 00608 00609 _select(); 00610 // 4 byte command sequence 00611 _spi.write(0x3d); 00612 _spi.write(0x2a); 00613 _spi.write(0x80); 00614 _spi.write(0xa6); 00615 _deselect(); 00616 00617 _busy(); // Make erase a blocking function 00618 } 00619 00620 // Return the number of blocks in this device in accordance with the datasheet 00621 int AT45::blocks() 00622 { 00623 return _blocks; 00624 } 00625 00626 // Return the Id of the part 00627 int AT45::id() 00628 { 00629 int id = 0; 00630 _select(); 00631 _spi.write(0x9f); 00632 id = (_spi.write(0x00) << 8); 00633 id |= _spi.write(0x00); 00634 _deselect(); 00635 return id; 00636 } 00637 00638 // return the Status 00639 int AT45::status() 00640 { 00641 int status = 0; 00642 _select(); 00643 _spi.write(0xd7); 00644 status = (_spi.write(0x00)); 00645 _deselect(); 00646 return status; 00647 } 00648 00649 // Make sure the Flash isnt already doing something 00650 void AT45::busy() 00651 { 00652 _busy(); 00653 } 00654 00655 void AT45::deep_power_down(bool _deep_down_onoff) 00656 { 00657 if(_deep_down_onoff == false) // Wake up from deep power down 00658 { 00659 _select(); 00660 _spi.write(0xab); 00661 _deselect(); 00662 _deep_down = true; 00663 // remenber to want 35uS before using the device. 00664 } 00665 else if(_deep_down_onoff == true) // Go to deep power down 00666 { 00667 _busy(); 00668 _select(); 00669 _spi.write(0xb9); 00670 _deselect(); 00671 _deep_down = false; 00672 } 00673 else 00674 { 00675 //do nothing 00676 } 00677 } 00678 00679 bool AT45::is_it_awake() 00680 { 00681 return _deep_down; 00682 } 00683 00684 //============================================================================= 00685 // Private functions 00686 //============================================================================= 00687 00688 void AT45::_initialize() 00689 { 00690 int _id = 0; 00691 int _status = 0; 00692 00693 _id = id(); 00694 _status = status(); 00695 00696 if ((_id & 0x1f) == 0x3) // 2Mbits 00697 { 00698 _devicesize = 262144; // Size in bytes 00699 _pages = 1024; // Number of pages 00700 _blocks = 128; // Number of blocks 00701 if (_status & 0x1) 00702 { 00703 _pagesize = 256; 00704 } 00705 else 00706 { 00707 _pagesize = 264; 00708 } 00709 } 00710 else if ( (_id & 0x1f) == 0x4) // 4Mbits 00711 { 00712 _devicesize = 524288; 00713 _pages = 2048; 00714 _blocks = 256; 00715 if (_status & 0x1) 00716 { 00717 _pagesize = 256; 00718 } 00719 else 00720 { 00721 _pagesize = 264; 00722 } 00723 } 00724 else if ( (_id & 0x1f) == 0x5) // 8Mbits 00725 { 00726 _devicesize = 1048576; 00727 _pages = 4096; 00728 _blocks = 512; 00729 if (_status & 0x1) 00730 { 00731 _pagesize = 256; 00732 } 00733 else 00734 { 00735 _pagesize = 264; 00736 } 00737 } 00738 else if ( (_id & 0x1f) == 0x6) // 16Mbits 00739 { 00740 _devicesize = 2097152; 00741 _pages = 4096; 00742 _blocks = 512; 00743 if (_status & 0x1) 00744 { 00745 _pagesize = 512; 00746 } 00747 else 00748 { 00749 _pagesize = 528; 00750 } 00751 } 00752 else if ( (_id & 0x1f) == 0x7) // 32Mbits 00753 { 00754 _devicesize = 4194304; 00755 _pages = 8192; 00756 _blocks = 1024; 00757 if (_status & 0x1) 00758 { 00759 _pagesize = 512; 00760 } 00761 else 00762 { 00763 _pagesize = 528; 00764 } 00765 } 00766 else if ( (_id & 0x1f) == 0x8) // 64Mbits 00767 { 00768 _devicesize = 8388608; 00769 _pages = 8192; 00770 _blocks = 1024; 00771 if (_status & 0x1) 00772 { 00773 _pagesize = 1024; 00774 } 00775 else 00776 { 00777 _pagesize = 1056; 00778 } 00779 } 00780 else 00781 { 00782 _devicesize = -1; 00783 _pages = -1; 00784 _pagesize = -1; 00785 _blocks = -1; 00786 } 00787 } 00788 00789 void AT45::_select() 00790 { 00791 _ncs = 0; 00792 } 00793 00794 void AT45::_deselect() 00795 { 00796 _ncs = 1; 00797 } 00798 00799 void AT45::_busy() { 00800 volatile int iambusy = 1; 00801 while (iambusy) { 00802 // if bit 7 is set, we can proceed 00803 if ( status() & 0x80 ) { 00804 iambusy = 0;} 00805 } 00806 } 00807 00808 // Write to an SRAM buffer 00809 // Note : We create buffer and page addresses in _sram and _flash 00810 void AT45::_sramwrite(int buffer, int address, int data) 00811 { 00812 00813 int cmd = 0; 00814 int baddr = 0; 00815 00816 baddr = _getbaddr(address); 00817 00818 _busy(); 00819 00820 _select(); 00821 00822 if (buffer == 1) 00823 {cmd = 0x84;} 00824 else 00825 {cmd = 0x87;} 00826 00827 _spi.write(cmd); 00828 _sendaddr (baddr); 00829 _spi.write (data); 00830 00831 _deselect(); 00832 } 00833 00834 // Read from an SRAM buffer 00835 // Note : We create buffer and page addresses in _sram and _flash 00836 int AT45::_sramread(int buffer, int address) 00837 { 00838 00839 int cmd = 0; 00840 int baddr = 0; 00841 int bufdata = 0; 00842 00843 baddr = _getbaddr(address); 00844 00845 _select(); 00846 00847 if(buffer == 1) 00848 {cmd = 0xd4;} 00849 else 00850 {cmd = 0xd6;} 00851 00852 _spi.write(cmd); 00853 _sendaddr (baddr); 00854 _spi.write (0x0); // dont care byte 00855 bufdata = _spi.write (0x0); 00856 00857 _deselect(); 00858 00859 return (bufdata); 00860 } 00861 00862 // Write and SRAM buffer to main memory 00863 void AT45::_flashwrite (int buffer, int address) 00864 { 00865 00866 int cmd = 0; 00867 int paddr = _getpaddr(address); 00868 00869 _busy(); // Check flash is not busy 00870 00871 _select(); 00872 00873 if (buffer == 1) 00874 {cmd = 0x83;} 00875 else 00876 {cmd = 0x86;} 00877 00878 _spi.write (cmd); 00879 _sendaddr (paddr); 00880 _deselect(); 00881 00882 _busy(); // Check flash is not busy 00883 } 00884 00885 // Read from Flash memory into SRAM buffer 00886 void AT45::_flashread (int buffer, int address) 00887 { 00888 00889 int cmd = 0; 00890 int paddr = _getpaddr(address); // calculate page address 00891 00892 _busy(); // Check flash is not busy 00893 _select(); 00894 00895 if (buffer == 1) 00896 {cmd = 0x53;} 00897 else 00898 {cmd = 0x55;} 00899 00900 _spi.write (cmd); 00901 _sendaddr (paddr); 00902 _deselect(); 00903 } 00904 00905 // Read directly from main memory 00906 int AT45::_memread (int address) 00907 { 00908 00909 int data = 0; 00910 int addr; 00911 00912 addr = _getpaddr(address) | _getbaddr(address); 00913 00914 _busy(); 00915 00916 _select(); 00917 00918 _spi.write (0xd2); // Direct read command 00919 _sendaddr (addr); 00920 00921 // 4 dont care bytes 00922 _spi.write (0x00); 00923 _spi.write (0x00); 00924 _spi.write (0x00); 00925 _spi.write (0x00); 00926 00927 // this one clocks the data 00928 data = _spi.write (0x00); 00929 _deselect(); 00930 00931 _busy(); 00932 00933 return data; 00934 } 00935 00936 // Work out the page address 00937 // If we have a 2^N page size, it is just the top N bits 00938 // If we have non-2^N, we use the shifted address 00939 int AT45::_getpaddr(int address) 00940 { 00941 00942 int paddr; 00943 00944 if (_pagesize == 256) { 00945 paddr = address & 0xffffff00;} 00946 else if (_pagesize == 264) { 00947 paddr = (address << 1) & 0xfffffe00;} 00948 else if (_pagesize == 512) { 00949 paddr = address & 0xfffffe00;} 00950 else if (_pagesize == 528 ) { 00951 paddr = (address << 1) & 0xfffffc00;} 00952 else if (_pagesize == 1024) { 00953 paddr = address & 0xfffffc00;} 00954 else if (_pagesize == 1056 ) { 00955 paddr = (address << 1) & 0xfffff800;} 00956 else { 00957 paddr = -1;} 00958 00959 return (paddr); 00960 } 00961 00962 // Clean the buffer address. This is the 8/9/10 LSBs 00963 int AT45::_getbaddr(int address) 00964 { 00965 00966 int baddr; 00967 00968 if ((_pagesize == 256) || (_pagesize == 264 )) { 00969 baddr = address & 0xff;} 00970 else if ((_pagesize == 512) || (_pagesize == 528 )) { 00971 baddr = address & 0x1ff;} 00972 else if ((_pagesize == 1024) || (_pagesize == 1056 )) { 00973 baddr = address & 0x3ff;} 00974 else { 00975 baddr = -1;} 00976 00977 return (baddr); 00978 } 00979 00980 // Sends the three lest significant bytes of the supplied address 00981 void AT45::_sendaddr (int address) 00982 { 00983 _spi.write(address >> 16); 00984 _spi.write(address >> 8); 00985 _spi.write(address); 00986 }
Generated on Wed Jul 13 2022 11:21:47 by
1.7.2