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.
Dependents: AT45_spi_flash_example AT45_spi_flash_example PLC1608-V1 RL0201-V1
Fork of AT45 by
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 Sat Jul 16 2022 13:04:03 by
1.7.2
