SPI Flash Library for AT45

Dependents:   AT45_spi_flash_example AT45_spi_flash_example PLC1608-V1 RL0201-V1

Fork of AT45 by Steen Jørgensen

Committer:
maclobdell
Date:
Tue Nov 14 14:53:37 2017 +0000
Revision:
1:f8e562ae5cc3
Parent:
0:2e9d45485414
Make SPI object passed by reference to comply w/ Mbed OS 5.6.x which specifies that SPI objects are non-copyable.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
stjo2809 0:2e9d45485414 1 /* mbed AT45 Library, for driving the Atmel AT45 series Dataflash with Serial Interface (SPI)
stjo2809 0:2e9d45485414 2 * Copyright (c) 2012, Created by Steen Joergensen (stjo2809) inspired by Chris Styles AT45 library
stjo2809 0:2e9d45485414 3 *
stjo2809 0:2e9d45485414 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
stjo2809 0:2e9d45485414 5 * of this software and associated documentation files (the "Software"), to deal
stjo2809 0:2e9d45485414 6 * in the Software without restriction, including without limitation the rights
stjo2809 0:2e9d45485414 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
stjo2809 0:2e9d45485414 8 * copies of the Software, and to permit persons to whom the Software is
stjo2809 0:2e9d45485414 9 * furnished to do so, subject to the following conditions:
stjo2809 0:2e9d45485414 10 *
stjo2809 0:2e9d45485414 11 * The above copyright notice and this permission notice shall be included in
stjo2809 0:2e9d45485414 12 * all copies or substantial portions of the Software.
stjo2809 0:2e9d45485414 13 *
stjo2809 0:2e9d45485414 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
stjo2809 0:2e9d45485414 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
stjo2809 0:2e9d45485414 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
stjo2809 0:2e9d45485414 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
stjo2809 0:2e9d45485414 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
stjo2809 0:2e9d45485414 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
stjo2809 0:2e9d45485414 20 * THE SOFTWARE.
stjo2809 0:2e9d45485414 21 */
stjo2809 0:2e9d45485414 22
stjo2809 0:2e9d45485414 23 #include "mbed.h"
stjo2809 0:2e9d45485414 24 #include "AT45.h"
stjo2809 0:2e9d45485414 25
stjo2809 0:2e9d45485414 26 //=============================================================================
stjo2809 0:2e9d45485414 27 // Public functions
stjo2809 0:2e9d45485414 28 //=============================================================================
stjo2809 0:2e9d45485414 29
maclobdell 1:f8e562ae5cc3 30 AT45::AT45(SPI *spi, PinName ncs) : _spi(spi), _ncs(ncs)
stjo2809 0:2e9d45485414 31 {
stjo2809 0:2e9d45485414 32
stjo2809 0:2e9d45485414 33 _pages = -1; // number of pages
stjo2809 0:2e9d45485414 34 _pagesize = -1; // size of pages 256/264, 512/528, 1024/1056
stjo2809 0:2e9d45485414 35 _devicesize = -1; // In bytes
stjo2809 0:2e9d45485414 36 _deep_down = true; // variable for deep power down function (awake ?)
stjo2809 0:2e9d45485414 37 _deep_down_onoff = false; // variable for deep power down function (On/Off)
stjo2809 0:2e9d45485414 38
stjo2809 0:2e9d45485414 39 _initialize(); // Populate all this stuff
stjo2809 0:2e9d45485414 40
stjo2809 0:2e9d45485414 41 }
stjo2809 0:2e9d45485414 42
stjo2809 0:2e9d45485414 43 // This function returns the char
stjo2809 0:2e9d45485414 44 char AT45::read_byte(int address)
stjo2809 0:2e9d45485414 45 {
stjo2809 0:2e9d45485414 46 // return byte from address
stjo2809 0:2e9d45485414 47 return (_memread( address ));
stjo2809 0:2e9d45485414 48 }
stjo2809 0:2e9d45485414 49
stjo2809 0:2e9d45485414 50 int AT45::read_page(char* data, int page)
stjo2809 0:2e9d45485414 51 {
stjo2809 0:2e9d45485414 52 int address = -1;
stjo2809 0:2e9d45485414 53
stjo2809 0:2e9d45485414 54 if(_pagesize == 256)
stjo2809 0:2e9d45485414 55 {
stjo2809 0:2e9d45485414 56 address = page * 256;
stjo2809 0:2e9d45485414 57 }
stjo2809 0:2e9d45485414 58 else if(_pagesize == 264)
stjo2809 0:2e9d45485414 59 {
stjo2809 0:2e9d45485414 60 address = page * 512;
stjo2809 0:2e9d45485414 61 }
stjo2809 0:2e9d45485414 62 else if(_pagesize == 512)
stjo2809 0:2e9d45485414 63 {
stjo2809 0:2e9d45485414 64 address = page * 512;
stjo2809 0:2e9d45485414 65 }
stjo2809 0:2e9d45485414 66 else if(_pagesize == 528)
stjo2809 0:2e9d45485414 67 {
stjo2809 0:2e9d45485414 68 address = page * 1024;
stjo2809 0:2e9d45485414 69 }
stjo2809 0:2e9d45485414 70 else if(_pagesize == 1024)
stjo2809 0:2e9d45485414 71 {
stjo2809 0:2e9d45485414 72 address = page * 1024;
stjo2809 0:2e9d45485414 73 }
stjo2809 0:2e9d45485414 74 else if(_pagesize == 1056)
stjo2809 0:2e9d45485414 75 {
stjo2809 0:2e9d45485414 76 address = page * 2048;
stjo2809 0:2e9d45485414 77 }
stjo2809 0:2e9d45485414 78 else
stjo2809 0:2e9d45485414 79 {
stjo2809 0:2e9d45485414 80 return (-1); // something isnt configured right
stjo2809 0:2e9d45485414 81 }
stjo2809 0:2e9d45485414 82
stjo2809 0:2e9d45485414 83 _busy();
stjo2809 0:2e9d45485414 84 _flashread(1,address); // read the first page of the block into SRAM buffer 1
stjo2809 0:2e9d45485414 85 _busy(); // Wait until First page has loaded into buffer 1
stjo2809 0:2e9d45485414 86
stjo2809 0:2e9d45485414 87 // this is done directly as we are reading back an entire buffer, and this can be done more optimally than using _sramread
stjo2809 0:2e9d45485414 88 _select();
maclobdell 1:f8e562ae5cc3 89 _spi->write(0xd4);
stjo2809 0:2e9d45485414 90 _sendaddr (0x0);
maclobdell 1:f8e562ae5cc3 91 _spi->write (0x0); // dont care byte
stjo2809 0:2e9d45485414 92
stjo2809 0:2e9d45485414 93 for(int i=0; i<_pagesize ;i++)
stjo2809 0:2e9d45485414 94 {
maclobdell 1:f8e562ae5cc3 95 data[i] = _spi->write (0x0);
stjo2809 0:2e9d45485414 96 }
stjo2809 0:2e9d45485414 97 _deselect();
stjo2809 0:2e9d45485414 98
stjo2809 0:2e9d45485414 99 return (0);
stjo2809 0:2e9d45485414 100 }
stjo2809 0:2e9d45485414 101 int AT45::read_block(char *data, int block) // under construction F&#65533;R CHECK AF MIC OG LERCHE
stjo2809 0:2e9d45485414 102 {
stjo2809 0:2e9d45485414 103 char temp_data[_pagesize];
stjo2809 0:2e9d45485414 104 int page_start;
stjo2809 0:2e9d45485414 105
stjo2809 0:2e9d45485414 106 if (block < _blocks || block == 0) {
stjo2809 0:2e9d45485414 107 page_start = block * 8;
stjo2809 0:2e9d45485414 108
stjo2809 0:2e9d45485414 109 for (int i=0; i<8; i++) {
stjo2809 0:2e9d45485414 110 read_page(temp_data, page_start);
stjo2809 0:2e9d45485414 111 //printf("%d Read round, Data is: %d\r\n",i,*temp_data);
stjo2809 0:2e9d45485414 112 page_start = page_start + 1;
stjo2809 0:2e9d45485414 113 for (int z=0; z<_pagesize ; z++) {
stjo2809 0:2e9d45485414 114 data[z+(_pagesize*i)] = temp_data[z];
stjo2809 0:2e9d45485414 115 }
stjo2809 0:2e9d45485414 116 }
stjo2809 0:2e9d45485414 117 } else {
stjo2809 0:2e9d45485414 118 //do nothing
stjo2809 0:2e9d45485414 119 }
stjo2809 0:2e9d45485414 120 //printf("Read done, Data is: %d\r\n",*data);
stjo2809 0:2e9d45485414 121 return (0);
stjo2809 0:2e9d45485414 122 }
stjo2809 0:2e9d45485414 123
stjo2809 0:2e9d45485414 124 int AT45::read_block(char *data[], int block) // under construction F&#65533; CHECK AF MIC OG LERCHE
stjo2809 0:2e9d45485414 125 {
stjo2809 0:2e9d45485414 126 char temp_data[_pagesize];
stjo2809 0:2e9d45485414 127 int page_start;
stjo2809 0:2e9d45485414 128
stjo2809 0:2e9d45485414 129 if(block < _blocks || block == 0)
stjo2809 0:2e9d45485414 130 {
stjo2809 0:2e9d45485414 131 page_start = block * 8;
stjo2809 0:2e9d45485414 132
stjo2809 0:2e9d45485414 133 for(int i=0; i<8 ;i++) // 8 pages in a block
stjo2809 0:2e9d45485414 134 {
stjo2809 0:2e9d45485414 135 read_page(temp_data, page_start);
stjo2809 0:2e9d45485414 136 page_start = page_start + 1;
stjo2809 0:2e9d45485414 137 for(int z=0; z<_pagesize ;z++)
stjo2809 0:2e9d45485414 138 {
stjo2809 0:2e9d45485414 139 data[i][z] = temp_data[z];
stjo2809 0:2e9d45485414 140 }
stjo2809 0:2e9d45485414 141 }
stjo2809 0:2e9d45485414 142 }
stjo2809 0:2e9d45485414 143 else
stjo2809 0:2e9d45485414 144 {
stjo2809 0:2e9d45485414 145 //do nothing
stjo2809 0:2e9d45485414 146 }
stjo2809 0:2e9d45485414 147
stjo2809 0:2e9d45485414 148 return (0);
stjo2809 0:2e9d45485414 149 }
stjo2809 0:2e9d45485414 150
stjo2809 0:2e9d45485414 151 // This function writes the char to the address supplied
stjo2809 0:2e9d45485414 152 // Note : We pass the raw address to the underlying functions
stjo2809 0:2e9d45485414 153 void AT45::write_byte(int address, char data)
stjo2809 0:2e9d45485414 154 {
stjo2809 0:2e9d45485414 155 _busy();
stjo2809 0:2e9d45485414 156 _flashread(1,address); // read the Flash page into SRAM buffer
stjo2809 0:2e9d45485414 157 _busy(); // wait for the read to complete
stjo2809 0:2e9d45485414 158 _sramwrite(1,address,data); // Write new data into SRAM
stjo2809 0:2e9d45485414 159 _busy(); // Make sure flash isnt busy
stjo2809 0:2e9d45485414 160 _flashwrite(1,address); // Write back to the page address
stjo2809 0:2e9d45485414 161 }
stjo2809 0:2e9d45485414 162
stjo2809 0:2e9d45485414 163 int AT45::write_page(char* data, int page)
stjo2809 0:2e9d45485414 164 {
stjo2809 0:2e9d45485414 165 int address = -1;
stjo2809 0:2e9d45485414 166
stjo2809 0:2e9d45485414 167 if(_pagesize == 256)
stjo2809 0:2e9d45485414 168 {
stjo2809 0:2e9d45485414 169 address = page * 256;
stjo2809 0:2e9d45485414 170 }
stjo2809 0:2e9d45485414 171 else if(_pagesize == 264)
stjo2809 0:2e9d45485414 172 {
stjo2809 0:2e9d45485414 173 address = page * 512;
stjo2809 0:2e9d45485414 174 }
stjo2809 0:2e9d45485414 175 else if(_pagesize == 512)
stjo2809 0:2e9d45485414 176 {
stjo2809 0:2e9d45485414 177 address = page * 512;
stjo2809 0:2e9d45485414 178 }
stjo2809 0:2e9d45485414 179 else if(_pagesize == 528)
stjo2809 0:2e9d45485414 180 {
stjo2809 0:2e9d45485414 181 address = page * 1024;
stjo2809 0:2e9d45485414 182 }
stjo2809 0:2e9d45485414 183 else if(_pagesize == 1024)
stjo2809 0:2e9d45485414 184 {
stjo2809 0:2e9d45485414 185 address = page * 1024;
stjo2809 0:2e9d45485414 186 }
stjo2809 0:2e9d45485414 187 else if(_pagesize == 1056)
stjo2809 0:2e9d45485414 188 {
stjo2809 0:2e9d45485414 189 address = page * 2048;
stjo2809 0:2e9d45485414 190 }
stjo2809 0:2e9d45485414 191 else
stjo2809 0:2e9d45485414 192 {
stjo2809 0:2e9d45485414 193 return (-1); // something isnt configured right
stjo2809 0:2e9d45485414 194 }
stjo2809 0:2e9d45485414 195
stjo2809 0:2e9d45485414 196 _select();
maclobdell 1:f8e562ae5cc3 197 _spi->write(0x84); // writing to buffer #1
stjo2809 0:2e9d45485414 198 _sendaddr (0); // we are writing to the entire buffer
stjo2809 0:2e9d45485414 199
stjo2809 0:2e9d45485414 200 for(int i=0; i<_pagesize ;i++)
stjo2809 0:2e9d45485414 201 {
maclobdell 1:f8e562ae5cc3 202 _spi->write (data[i]);
stjo2809 0:2e9d45485414 203 }
stjo2809 0:2e9d45485414 204 _deselect();
stjo2809 0:2e9d45485414 205
stjo2809 0:2e9d45485414 206 _busy(); // make sure the Flahs isnt busy
stjo2809 0:2e9d45485414 207
stjo2809 0:2e9d45485414 208 // issue command to write buffer 1 to the appropraite flash page
stjo2809 0:2e9d45485414 209 _select();
maclobdell 1:f8e562ae5cc3 210 _spi->write (0x83);
stjo2809 0:2e9d45485414 211 _sendaddr (_getpaddr(address));
stjo2809 0:2e9d45485414 212 _deselect();
stjo2809 0:2e9d45485414 213
stjo2809 0:2e9d45485414 214 return (0);
stjo2809 0:2e9d45485414 215 }
stjo2809 0:2e9d45485414 216 int AT45::write_block(char *data, int block) // under construction F&#65533;R CHECK AF MIC OG LERCHE
stjo2809 0:2e9d45485414 217 {
stjo2809 0:2e9d45485414 218
stjo2809 0:2e9d45485414 219 int page_start;
stjo2809 0:2e9d45485414 220 char page_arr[_pagesize];
stjo2809 0:2e9d45485414 221
stjo2809 0:2e9d45485414 222 if (block < _blocks || block == 0)
stjo2809 0:2e9d45485414 223 {
stjo2809 0:2e9d45485414 224 page_start = block * 8;
stjo2809 0:2e9d45485414 225
stjo2809 0:2e9d45485414 226 for (int i=0; i<8 ; i++)
stjo2809 0:2e9d45485414 227 {
stjo2809 0:2e9d45485414 228 // Copy data from *data at 0 to 511 _ 512 - 1023, and so on every round.
stjo2809 0:2e9d45485414 229 memcpy(page_arr, &data[_pagesize*i], _pagesize);
stjo2809 0:2e9d45485414 230
stjo2809 0:2e9d45485414 231 write_page(page_arr, page_start);
stjo2809 0:2e9d45485414 232 page_start = page_start + 1;
stjo2809 0:2e9d45485414 233 }
stjo2809 0:2e9d45485414 234 } else {
stjo2809 0:2e9d45485414 235 //do nothing
stjo2809 0:2e9d45485414 236 }
stjo2809 0:2e9d45485414 237
stjo2809 0:2e9d45485414 238 return (0);
stjo2809 0:2e9d45485414 239 }
stjo2809 0:2e9d45485414 240 int AT45::write_block(char *data[], int block) // under construction F&#65533; CHECK AF MIC OG LERCHE
stjo2809 0:2e9d45485414 241 {
stjo2809 0:2e9d45485414 242 char temp_data[_pagesize];
stjo2809 0:2e9d45485414 243 int page_start;
stjo2809 0:2e9d45485414 244
stjo2809 0:2e9d45485414 245 if(block < _blocks || block == 0)
stjo2809 0:2e9d45485414 246 {
stjo2809 0:2e9d45485414 247 page_start = block * 8;
stjo2809 0:2e9d45485414 248
stjo2809 0:2e9d45485414 249 for(int i=0; i<8 ;i++)
stjo2809 0:2e9d45485414 250 {
stjo2809 0:2e9d45485414 251 for(int z=0; z<_pagesize ;z++)
stjo2809 0:2e9d45485414 252 {
stjo2809 0:2e9d45485414 253 temp_data[z] = data[i][z];
stjo2809 0:2e9d45485414 254 }
stjo2809 0:2e9d45485414 255 write_page(temp_data, page_start);
stjo2809 0:2e9d45485414 256 page_start = page_start + 1;
stjo2809 0:2e9d45485414 257 }
stjo2809 0:2e9d45485414 258 }
stjo2809 0:2e9d45485414 259 else
stjo2809 0:2e9d45485414 260 {
stjo2809 0:2e9d45485414 261 //do nothing
stjo2809 0:2e9d45485414 262 }
stjo2809 0:2e9d45485414 263
stjo2809 0:2e9d45485414 264 return (0);
stjo2809 0:2e9d45485414 265 }
stjo2809 0:2e9d45485414 266
stjo2809 0:2e9d45485414 267 int AT45::FAT_read(char* data, int page)
stjo2809 0:2e9d45485414 268 {
stjo2809 0:2e9d45485414 269 // For 256 byte pages, we read two pages
stjo2809 0:2e9d45485414 270 if((_pagesize == 256) || (_pagesize == 264))
stjo2809 0:2e9d45485414 271 {
stjo2809 0:2e9d45485414 272 int address = page * 512; // This is the start address of the 512 byte block
stjo2809 0:2e9d45485414 273
stjo2809 0:2e9d45485414 274 _flashread(1,address); // read the first page of the block into SRAM buffer 1
stjo2809 0:2e9d45485414 275 _busy(); // Wait until First page has loaded into buffer 1
stjo2809 0:2e9d45485414 276
stjo2809 0:2e9d45485414 277 // this is done directly as we are reading back an entire buffer, and this can be done more optimally than using _sramread
stjo2809 0:2e9d45485414 278 _select();
maclobdell 1:f8e562ae5cc3 279 _spi->write(0xd4);
stjo2809 0:2e9d45485414 280 _sendaddr (0x0);
maclobdell 1:f8e562ae5cc3 281 _spi->write (0x0); // dont care byte
stjo2809 0:2e9d45485414 282
stjo2809 0:2e9d45485414 283 for(int i=0;i<256;i++)
stjo2809 0:2e9d45485414 284 {
maclobdell 1:f8e562ae5cc3 285 data[i] = _spi->write (0x0);
stjo2809 0:2e9d45485414 286 }
stjo2809 0:2e9d45485414 287 _deselect();
stjo2809 0:2e9d45485414 288
stjo2809 0:2e9d45485414 289 _flashread(1,address+256); // read the second page of the block into SRAM buffer 2
stjo2809 0:2e9d45485414 290 _busy(); // Wait until second page has loaded into buffer 2
stjo2809 0:2e9d45485414 291
stjo2809 0:2e9d45485414 292 // Now the second page is loaded, pull this out into the second half of the data buffer
stjo2809 0:2e9d45485414 293 // this is done directly as we are reading back an entire buffer, and this can be done more optimally than using _sramread
stjo2809 0:2e9d45485414 294 _select();
maclobdell 1:f8e562ae5cc3 295 _spi->write(0xd4);
stjo2809 0:2e9d45485414 296 _sendaddr (0x0);
maclobdell 1:f8e562ae5cc3 297 _spi->write (0x0); // dont care byte
stjo2809 0:2e9d45485414 298
stjo2809 0:2e9d45485414 299 for(int i=0;i<256;i++)
stjo2809 0:2e9d45485414 300 {
maclobdell 1:f8e562ae5cc3 301 data[256+i] = _spi->write (0x0);
stjo2809 0:2e9d45485414 302 }
stjo2809 0:2e9d45485414 303 _deselect();
stjo2809 0:2e9d45485414 304 return (0);
stjo2809 0:2e9d45485414 305 }
stjo2809 0:2e9d45485414 306
stjo2809 0:2e9d45485414 307 // For 512 byte pages, we read just the single page, transfer it
stjo2809 0:2e9d45485414 308 else if((_pagesize == 512) || (_pagesize == 528))
stjo2809 0:2e9d45485414 309 {
stjo2809 0:2e9d45485414 310 int address = page * 512; // This is the start address of the 512 byte block
stjo2809 0:2e9d45485414 311
stjo2809 0:2e9d45485414 312 _busy(); // Wait until First page has loaded into buffer 1
stjo2809 0:2e9d45485414 313 _flashread(1,address); // read the first page of the block into SRAM buffer 1
stjo2809 0:2e9d45485414 314 _busy(); // Wait until First page has loaded into buffer 1
stjo2809 0:2e9d45485414 315
stjo2809 0:2e9d45485414 316 // Now the page has loaded, simply transfer it from the sram buffer to the data array
stjo2809 0:2e9d45485414 317 // this is done directly as we are reading back an entire buffer, and this can be done more optimally than using _sramread
stjo2809 0:2e9d45485414 318 _select();
maclobdell 1:f8e562ae5cc3 319 _spi->write(0xd4);
stjo2809 0:2e9d45485414 320 _sendaddr (0x0);
maclobdell 1:f8e562ae5cc3 321 _spi->write (0x0); // dont care byte
stjo2809 0:2e9d45485414 322
stjo2809 0:2e9d45485414 323 for(int i=0;i<512;i++)
stjo2809 0:2e9d45485414 324 {
maclobdell 1:f8e562ae5cc3 325 data[i] = _spi->write (0x0);
stjo2809 0:2e9d45485414 326 }
stjo2809 0:2e9d45485414 327 _deselect();
stjo2809 0:2e9d45485414 328 return (0);
stjo2809 0:2e9d45485414 329 }
stjo2809 0:2e9d45485414 330
stjo2809 0:2e9d45485414 331 // For 1024 byte pages, we read just a single page, transfer half of it
stjo2809 0:2e9d45485414 332 else if((_pagesize == 1024) || (_pagesize == 1056))
stjo2809 0:2e9d45485414 333 {
stjo2809 0:2e9d45485414 334 int address = _getpaddr(page * 512); // This is the start address of the 512 byte block
stjo2809 0:2e9d45485414 335
stjo2809 0:2e9d45485414 336 _busy(); // Wait until First page has loaded into buffer 1
stjo2809 0:2e9d45485414 337
stjo2809 0:2e9d45485414 338 _flashread(1,address); // read the first page of the block into SRAM buffer 1
stjo2809 0:2e9d45485414 339
stjo2809 0:2e9d45485414 340 _busy(); // Wait until First page has loaded into buffer 1
stjo2809 0:2e9d45485414 341
stjo2809 0:2e9d45485414 342 // Now the page has loaded, simply transfer it from the sram buffer to the data array
stjo2809 0:2e9d45485414 343 // this is done directly as we are reading back an entire buffer, and this can be done more optimally than using _sramread
stjo2809 0:2e9d45485414 344
stjo2809 0:2e9d45485414 345 _select();
maclobdell 1:f8e562ae5cc3 346 _spi->write(0xd4);
stjo2809 0:2e9d45485414 347
stjo2809 0:2e9d45485414 348 if (page %2) // odd numbered block, read from adress 0x200
stjo2809 0:2e9d45485414 349 {
stjo2809 0:2e9d45485414 350 _sendaddr (0x200);
stjo2809 0:2e9d45485414 351 }
stjo2809 0:2e9d45485414 352 else // even numbered block, then we are reading from sram buffer 0x0
stjo2809 0:2e9d45485414 353 {
stjo2809 0:2e9d45485414 354 _sendaddr (0x0);
stjo2809 0:2e9d45485414 355 }
stjo2809 0:2e9d45485414 356
maclobdell 1:f8e562ae5cc3 357 _spi->write (0x0); // dont care byte
stjo2809 0:2e9d45485414 358
stjo2809 0:2e9d45485414 359 for(int i=0;i<512;i++)
stjo2809 0:2e9d45485414 360 {
maclobdell 1:f8e562ae5cc3 361 data[i] = _spi->write (0x0);
stjo2809 0:2e9d45485414 362 }
stjo2809 0:2e9d45485414 363 _deselect();
stjo2809 0:2e9d45485414 364 return (0);
stjo2809 0:2e9d45485414 365 }
stjo2809 0:2e9d45485414 366 else
stjo2809 0:2e9d45485414 367 {
stjo2809 0:2e9d45485414 368 return (-1); // something isnt configured right
stjo2809 0:2e9d45485414 369 }
stjo2809 0:2e9d45485414 370 }
stjo2809 0:2e9d45485414 371
stjo2809 0:2e9d45485414 372 int AT45::FAT_write(char* data, int page)
stjo2809 0:2e9d45485414 373 {
stjo2809 0:2e9d45485414 374 // For 256 byte pages, we overwrite two pages
stjo2809 0:2e9d45485414 375 if((_pagesize == 256) || (_pagesize == 264))
stjo2809 0:2e9d45485414 376 {
stjo2809 0:2e9d45485414 377
stjo2809 0:2e9d45485414 378 // fill the first buffer with the first half of the block
stjo2809 0:2e9d45485414 379 // do this directly, for better performance
stjo2809 0:2e9d45485414 380 _select();
maclobdell 1:f8e562ae5cc3 381 _spi->write(0x84); // writing to buffer #1
stjo2809 0:2e9d45485414 382 _sendaddr (0); // we are writing to the entire buffer
stjo2809 0:2e9d45485414 383
stjo2809 0:2e9d45485414 384 for(int i=0;i<256;i++) {
maclobdell 1:f8e562ae5cc3 385 _spi->write (data[i]);
stjo2809 0:2e9d45485414 386 }
stjo2809 0:2e9d45485414 387 _deselect();
stjo2809 0:2e9d45485414 388
stjo2809 0:2e9d45485414 389 _flashwrite(1,(page*512));
stjo2809 0:2e9d45485414 390
stjo2809 0:2e9d45485414 391 // fill the buffer with the second half of the block
stjo2809 0:2e9d45485414 392 // do this directly, for better performance
stjo2809 0:2e9d45485414 393 _select();
maclobdell 1:f8e562ae5cc3 394 _spi->write(0x84); // writing to buffer #1
stjo2809 0:2e9d45485414 395 _sendaddr (0); // we are writing to the entire buffer
stjo2809 0:2e9d45485414 396
stjo2809 0:2e9d45485414 397 for(int i=0;i<256;i++) {
maclobdell 1:f8e562ae5cc3 398 _spi->write (data[256+i]);
stjo2809 0:2e9d45485414 399 }
stjo2809 0:2e9d45485414 400 _deselect();
stjo2809 0:2e9d45485414 401
stjo2809 0:2e9d45485414 402 _flashwrite(1,((page*512)+256));
stjo2809 0:2e9d45485414 403 }
stjo2809 0:2e9d45485414 404
stjo2809 0:2e9d45485414 405 // For 512 byte pages, we overwrite a single page
stjo2809 0:2e9d45485414 406 else if((_pagesize == 512) || (_pagesize == 528))
stjo2809 0:2e9d45485414 407 {
stjo2809 0:2e9d45485414 408
stjo2809 0:2e9d45485414 409 // fill the first buffer with the block data
stjo2809 0:2e9d45485414 410 // do this directly, for better performance
stjo2809 0:2e9d45485414 411 _select();
maclobdell 1:f8e562ae5cc3 412 _spi->write(0x84); // writing to buffer #1
stjo2809 0:2e9d45485414 413 _sendaddr (0); // we are writing to the entire buffer
stjo2809 0:2e9d45485414 414
stjo2809 0:2e9d45485414 415 for(int i=0;i<512;i++) {
maclobdell 1:f8e562ae5cc3 416 _spi->write (data[i]);
stjo2809 0:2e9d45485414 417 }
stjo2809 0:2e9d45485414 418 _deselect();
stjo2809 0:2e9d45485414 419
stjo2809 0:2e9d45485414 420 _busy(); // make sure the Flahs isnt busy
stjo2809 0:2e9d45485414 421
stjo2809 0:2e9d45485414 422 // issue command to write buffer 1 to the appropraite flash page
stjo2809 0:2e9d45485414 423 _select();
maclobdell 1:f8e562ae5cc3 424 _spi->write (0x83);
stjo2809 0:2e9d45485414 425 _sendaddr (_getpaddr(page * 512));
stjo2809 0:2e9d45485414 426 _deselect();
stjo2809 0:2e9d45485414 427 }
stjo2809 0:2e9d45485414 428
stjo2809 0:2e9d45485414 429 // For 1024 byte pages, we do a read modify write
stjo2809 0:2e9d45485414 430 // must make sure we overwrite the right half of the page!
stjo2809 0:2e9d45485414 431 else if((_pagesize == 1024) || (_pagesize == 1056))
stjo2809 0:2e9d45485414 432 {
stjo2809 0:2e9d45485414 433
stjo2809 0:2e9d45485414 434 _busy(); // make sure the flash isnt busy
stjo2809 0:2e9d45485414 435
stjo2809 0:2e9d45485414 436 int address = _getpaddr(page*512);
stjo2809 0:2e9d45485414 437
stjo2809 0:2e9d45485414 438 // Read the page into sram
stjo2809 0:2e9d45485414 439 _flashread(1,address);
stjo2809 0:2e9d45485414 440
stjo2809 0:2e9d45485414 441 // wait for this operation to complete
stjo2809 0:2e9d45485414 442 _busy();
stjo2809 0:2e9d45485414 443
stjo2809 0:2e9d45485414 444 // Overwrite the appropriate half
stjo2809 0:2e9d45485414 445 // do this directly, for better performance
stjo2809 0:2e9d45485414 446 _select();
maclobdell 1:f8e562ae5cc3 447 _spi->write(0x84); // writing to buffer #1
stjo2809 0:2e9d45485414 448
stjo2809 0:2e9d45485414 449 if(page%2) // this is an odd block number, overwrite second half of buffer
stjo2809 0:2e9d45485414 450 {
stjo2809 0:2e9d45485414 451 _sendaddr (0x200); // we are writing to the entire buffer
stjo2809 0:2e9d45485414 452 }
stjo2809 0:2e9d45485414 453 else // this is an even block, overwrite the first half
stjo2809 0:2e9d45485414 454 {
stjo2809 0:2e9d45485414 455 _sendaddr (0x0); // we are writing to the entire buffer
stjo2809 0:2e9d45485414 456 }
stjo2809 0:2e9d45485414 457
stjo2809 0:2e9d45485414 458 for(int i=0;i<512;i++)
stjo2809 0:2e9d45485414 459 {
maclobdell 1:f8e562ae5cc3 460 _spi->write (data[i]);
stjo2809 0:2e9d45485414 461 }
stjo2809 0:2e9d45485414 462 _deselect();
stjo2809 0:2e9d45485414 463
stjo2809 0:2e9d45485414 464 // Write the page back
stjo2809 0:2e9d45485414 465 _busy();
stjo2809 0:2e9d45485414 466 _flashwrite(1,address);
stjo2809 0:2e9d45485414 467 }
stjo2809 0:2e9d45485414 468
stjo2809 0:2e9d45485414 469 // Something has gone wrong
stjo2809 0:2e9d45485414 470 else
stjo2809 0:2e9d45485414 471 {
stjo2809 0:2e9d45485414 472 return (-1);
stjo2809 0:2e9d45485414 473 }
stjo2809 0:2e9d45485414 474
stjo2809 0:2e9d45485414 475 return (0);
stjo2809 0:2e9d45485414 476 }
stjo2809 0:2e9d45485414 477
stjo2809 0:2e9d45485414 478 // Erase the entire chip
stjo2809 0:2e9d45485414 479 void AT45::chip_erase()
stjo2809 0:2e9d45485414 480 {
stjo2809 0:2e9d45485414 481 _busy(); // make sure flash isnt already in busy.
stjo2809 0:2e9d45485414 482
stjo2809 0:2e9d45485414 483 _select();
stjo2809 0:2e9d45485414 484 // 4 byte command sequence
maclobdell 1:f8e562ae5cc3 485 _spi->write(0xc7);
maclobdell 1:f8e562ae5cc3 486 _spi->write(0x94);
maclobdell 1:f8e562ae5cc3 487 _spi->write(0x80);
maclobdell 1:f8e562ae5cc3 488 _spi->write(0x9a);
stjo2809 0:2e9d45485414 489 _deselect();
stjo2809 0:2e9d45485414 490
stjo2809 0:2e9d45485414 491 _busy(); // Make erase a blocking function
stjo2809 0:2e9d45485414 492 }
stjo2809 0:2e9d45485414 493
stjo2809 0:2e9d45485414 494 // Erase one block
stjo2809 0:2e9d45485414 495 void AT45::block_erase(int block)
stjo2809 0:2e9d45485414 496 {
stjo2809 0:2e9d45485414 497 int address = -1;
stjo2809 0:2e9d45485414 498
stjo2809 0:2e9d45485414 499 // Calculate page addresses
stjo2809 0:2e9d45485414 500 if(block < _blocks || block == 0)
stjo2809 0:2e9d45485414 501 {
stjo2809 0:2e9d45485414 502 if(_pagesize == 256)
stjo2809 0:2e9d45485414 503 {
stjo2809 0:2e9d45485414 504 address = block * 2048;
stjo2809 0:2e9d45485414 505 }
stjo2809 0:2e9d45485414 506 else if(_pagesize == 264)
stjo2809 0:2e9d45485414 507 {
stjo2809 0:2e9d45485414 508 address = block * 4096;
stjo2809 0:2e9d45485414 509 }
stjo2809 0:2e9d45485414 510 else if(_pagesize == 512)
stjo2809 0:2e9d45485414 511 {
stjo2809 0:2e9d45485414 512 address = block * 4096;
stjo2809 0:2e9d45485414 513 }
stjo2809 0:2e9d45485414 514 else if(_pagesize == 528)
stjo2809 0:2e9d45485414 515 {
stjo2809 0:2e9d45485414 516 address = block * 8192;
stjo2809 0:2e9d45485414 517 }
stjo2809 0:2e9d45485414 518 else if(_pagesize == 1024)
stjo2809 0:2e9d45485414 519 {
stjo2809 0:2e9d45485414 520 address = block * 8192;
stjo2809 0:2e9d45485414 521 }
stjo2809 0:2e9d45485414 522 else if(_pagesize == 1056)
stjo2809 0:2e9d45485414 523 {
stjo2809 0:2e9d45485414 524 address = block * 16384;
stjo2809 0:2e9d45485414 525 }
stjo2809 0:2e9d45485414 526
stjo2809 0:2e9d45485414 527 _busy();
stjo2809 0:2e9d45485414 528 _select();
maclobdell 1:f8e562ae5cc3 529 _spi->write(0x50);
stjo2809 0:2e9d45485414 530 _sendaddr (address);
stjo2809 0:2e9d45485414 531 _deselect();
stjo2809 0:2e9d45485414 532 _busy();
stjo2809 0:2e9d45485414 533 }
stjo2809 0:2e9d45485414 534 else
stjo2809 0:2e9d45485414 535 {
stjo2809 0:2e9d45485414 536 //do nothing
stjo2809 0:2e9d45485414 537 }
stjo2809 0:2e9d45485414 538 }
stjo2809 0:2e9d45485414 539
stjo2809 0:2e9d45485414 540 // Erase one page
stjo2809 0:2e9d45485414 541 void AT45::page_erase(int page)
stjo2809 0:2e9d45485414 542 {
stjo2809 0:2e9d45485414 543 int address = -1;
stjo2809 0:2e9d45485414 544
stjo2809 0:2e9d45485414 545 // Calculate page addresses
stjo2809 0:2e9d45485414 546 if(page < _pages || page == 0)
stjo2809 0:2e9d45485414 547 {
stjo2809 0:2e9d45485414 548 if(_pagesize == 256)
stjo2809 0:2e9d45485414 549 {
stjo2809 0:2e9d45485414 550 address = page * 256;
stjo2809 0:2e9d45485414 551 }
stjo2809 0:2e9d45485414 552 else if(_pagesize == 264)
stjo2809 0:2e9d45485414 553 {
stjo2809 0:2e9d45485414 554 address = page * 512;
stjo2809 0:2e9d45485414 555 }
stjo2809 0:2e9d45485414 556 else if(_pagesize == 512)
stjo2809 0:2e9d45485414 557 {
stjo2809 0:2e9d45485414 558 address = page * 512;
stjo2809 0:2e9d45485414 559 }
stjo2809 0:2e9d45485414 560 else if(_pagesize == 528)
stjo2809 0:2e9d45485414 561 {
stjo2809 0:2e9d45485414 562 address = page * 1024;
stjo2809 0:2e9d45485414 563 }
stjo2809 0:2e9d45485414 564 else if(_pagesize == 1024)
stjo2809 0:2e9d45485414 565 {
stjo2809 0:2e9d45485414 566 address = page * 1024;
stjo2809 0:2e9d45485414 567 }
stjo2809 0:2e9d45485414 568 else if(_pagesize == 1056)
stjo2809 0:2e9d45485414 569 {
stjo2809 0:2e9d45485414 570 address = page * 2048;
stjo2809 0:2e9d45485414 571 }
stjo2809 0:2e9d45485414 572
stjo2809 0:2e9d45485414 573 _busy();
stjo2809 0:2e9d45485414 574 _select();
maclobdell 1:f8e562ae5cc3 575 _spi->write(0x81);
stjo2809 0:2e9d45485414 576 _sendaddr (address);
stjo2809 0:2e9d45485414 577 _deselect();
stjo2809 0:2e9d45485414 578 _busy();
stjo2809 0:2e9d45485414 579 }
stjo2809 0:2e9d45485414 580 else
stjo2809 0:2e9d45485414 581 {
stjo2809 0:2e9d45485414 582 //do nothing
stjo2809 0:2e9d45485414 583 }
stjo2809 0:2e9d45485414 584 }
stjo2809 0:2e9d45485414 585
stjo2809 0:2e9d45485414 586 // return the size of the part in bytes
stjo2809 0:2e9d45485414 587 int AT45::device_size()
stjo2809 0:2e9d45485414 588 {
stjo2809 0:2e9d45485414 589 return _devicesize;
stjo2809 0:2e9d45485414 590 }
stjo2809 0:2e9d45485414 591
stjo2809 0:2e9d45485414 592 // return the numbers of pages
stjo2809 0:2e9d45485414 593 int AT45::pages()
stjo2809 0:2e9d45485414 594 {
stjo2809 0:2e9d45485414 595 return _pages;
stjo2809 0:2e9d45485414 596 }
stjo2809 0:2e9d45485414 597
stjo2809 0:2e9d45485414 598 // return the page size of the part in bytes
stjo2809 0:2e9d45485414 599 int AT45::pagesize()
stjo2809 0:2e9d45485414 600 {
stjo2809 0:2e9d45485414 601 return _pagesize;
stjo2809 0:2e9d45485414 602 }
stjo2809 0:2e9d45485414 603
stjo2809 0:2e9d45485414 604 // A one-time programmable configuration
stjo2809 0:2e9d45485414 605 void AT45::set_pageszie_to_binary()
stjo2809 0:2e9d45485414 606 {
stjo2809 0:2e9d45485414 607 _busy(); // make sure flash isnt already in busy.
stjo2809 0:2e9d45485414 608
stjo2809 0:2e9d45485414 609 _select();
stjo2809 0:2e9d45485414 610 // 4 byte command sequence
maclobdell 1:f8e562ae5cc3 611 _spi->write(0x3d);
maclobdell 1:f8e562ae5cc3 612 _spi->write(0x2a);
maclobdell 1:f8e562ae5cc3 613 _spi->write(0x80);
maclobdell 1:f8e562ae5cc3 614 _spi->write(0xa6);
stjo2809 0:2e9d45485414 615 _deselect();
stjo2809 0:2e9d45485414 616
stjo2809 0:2e9d45485414 617 _busy(); // Make erase a blocking function
stjo2809 0:2e9d45485414 618 }
stjo2809 0:2e9d45485414 619
stjo2809 0:2e9d45485414 620 // Return the number of blocks in this device in accordance with the datasheet
stjo2809 0:2e9d45485414 621 int AT45::blocks()
stjo2809 0:2e9d45485414 622 {
stjo2809 0:2e9d45485414 623 return _blocks;
stjo2809 0:2e9d45485414 624 }
stjo2809 0:2e9d45485414 625
stjo2809 0:2e9d45485414 626 // Return the Id of the part
stjo2809 0:2e9d45485414 627 int AT45::id()
stjo2809 0:2e9d45485414 628 {
stjo2809 0:2e9d45485414 629 int id = 0;
stjo2809 0:2e9d45485414 630 _select();
maclobdell 1:f8e562ae5cc3 631 _spi->write(0x9f);
maclobdell 1:f8e562ae5cc3 632 id = (_spi->write(0x00) << 8);
maclobdell 1:f8e562ae5cc3 633 id |= _spi->write(0x00);
stjo2809 0:2e9d45485414 634 _deselect();
stjo2809 0:2e9d45485414 635 return id;
stjo2809 0:2e9d45485414 636 }
stjo2809 0:2e9d45485414 637
stjo2809 0:2e9d45485414 638 // return the Status
stjo2809 0:2e9d45485414 639 int AT45::status()
stjo2809 0:2e9d45485414 640 {
stjo2809 0:2e9d45485414 641 int status = 0;
stjo2809 0:2e9d45485414 642 _select();
maclobdell 1:f8e562ae5cc3 643 _spi->write(0xd7);
maclobdell 1:f8e562ae5cc3 644 status = (_spi->write(0x00));
stjo2809 0:2e9d45485414 645 _deselect();
stjo2809 0:2e9d45485414 646 return status;
stjo2809 0:2e9d45485414 647 }
stjo2809 0:2e9d45485414 648
stjo2809 0:2e9d45485414 649 // Make sure the Flash isnt already doing something
stjo2809 0:2e9d45485414 650 void AT45::busy()
stjo2809 0:2e9d45485414 651 {
stjo2809 0:2e9d45485414 652 _busy();
stjo2809 0:2e9d45485414 653 }
stjo2809 0:2e9d45485414 654
stjo2809 0:2e9d45485414 655 void AT45::deep_power_down(bool _deep_down_onoff)
stjo2809 0:2e9d45485414 656 {
stjo2809 0:2e9d45485414 657 if(_deep_down_onoff == false) // Wake up from deep power down
stjo2809 0:2e9d45485414 658 {
stjo2809 0:2e9d45485414 659 _select();
maclobdell 1:f8e562ae5cc3 660 _spi->write(0xab);
stjo2809 0:2e9d45485414 661 _deselect();
stjo2809 0:2e9d45485414 662 _deep_down = true;
stjo2809 0:2e9d45485414 663 // remenber to want 35uS before using the device.
stjo2809 0:2e9d45485414 664 }
stjo2809 0:2e9d45485414 665 else if(_deep_down_onoff == true) // Go to deep power down
stjo2809 0:2e9d45485414 666 {
stjo2809 0:2e9d45485414 667 _busy();
stjo2809 0:2e9d45485414 668 _select();
maclobdell 1:f8e562ae5cc3 669 _spi->write(0xb9);
stjo2809 0:2e9d45485414 670 _deselect();
stjo2809 0:2e9d45485414 671 _deep_down = false;
stjo2809 0:2e9d45485414 672 }
stjo2809 0:2e9d45485414 673 else
stjo2809 0:2e9d45485414 674 {
stjo2809 0:2e9d45485414 675 //do nothing
stjo2809 0:2e9d45485414 676 }
stjo2809 0:2e9d45485414 677 }
stjo2809 0:2e9d45485414 678
stjo2809 0:2e9d45485414 679 bool AT45::is_it_awake()
stjo2809 0:2e9d45485414 680 {
stjo2809 0:2e9d45485414 681 return _deep_down;
stjo2809 0:2e9d45485414 682 }
stjo2809 0:2e9d45485414 683
stjo2809 0:2e9d45485414 684 //=============================================================================
stjo2809 0:2e9d45485414 685 // Private functions
stjo2809 0:2e9d45485414 686 //=============================================================================
stjo2809 0:2e9d45485414 687
stjo2809 0:2e9d45485414 688 void AT45::_initialize()
stjo2809 0:2e9d45485414 689 {
stjo2809 0:2e9d45485414 690 int _id = 0;
stjo2809 0:2e9d45485414 691 int _status = 0;
stjo2809 0:2e9d45485414 692
stjo2809 0:2e9d45485414 693 _id = id();
stjo2809 0:2e9d45485414 694 _status = status();
stjo2809 0:2e9d45485414 695
stjo2809 0:2e9d45485414 696 if ((_id & 0x1f) == 0x3) // 2Mbits
stjo2809 0:2e9d45485414 697 {
stjo2809 0:2e9d45485414 698 _devicesize = 262144; // Size in bytes
stjo2809 0:2e9d45485414 699 _pages = 1024; // Number of pages
stjo2809 0:2e9d45485414 700 _blocks = 128; // Number of blocks
stjo2809 0:2e9d45485414 701 if (_status & 0x1)
stjo2809 0:2e9d45485414 702 {
stjo2809 0:2e9d45485414 703 _pagesize = 256;
stjo2809 0:2e9d45485414 704 }
stjo2809 0:2e9d45485414 705 else
stjo2809 0:2e9d45485414 706 {
stjo2809 0:2e9d45485414 707 _pagesize = 264;
stjo2809 0:2e9d45485414 708 }
stjo2809 0:2e9d45485414 709 }
stjo2809 0:2e9d45485414 710 else if ( (_id & 0x1f) == 0x4) // 4Mbits
stjo2809 0:2e9d45485414 711 {
stjo2809 0:2e9d45485414 712 _devicesize = 524288;
stjo2809 0:2e9d45485414 713 _pages = 2048;
stjo2809 0:2e9d45485414 714 _blocks = 256;
stjo2809 0:2e9d45485414 715 if (_status & 0x1)
stjo2809 0:2e9d45485414 716 {
stjo2809 0:2e9d45485414 717 _pagesize = 256;
stjo2809 0:2e9d45485414 718 }
stjo2809 0:2e9d45485414 719 else
stjo2809 0:2e9d45485414 720 {
stjo2809 0:2e9d45485414 721 _pagesize = 264;
stjo2809 0:2e9d45485414 722 }
stjo2809 0:2e9d45485414 723 }
stjo2809 0:2e9d45485414 724 else if ( (_id & 0x1f) == 0x5) // 8Mbits
stjo2809 0:2e9d45485414 725 {
stjo2809 0:2e9d45485414 726 _devicesize = 1048576;
stjo2809 0:2e9d45485414 727 _pages = 4096;
stjo2809 0:2e9d45485414 728 _blocks = 512;
stjo2809 0:2e9d45485414 729 if (_status & 0x1)
stjo2809 0:2e9d45485414 730 {
stjo2809 0:2e9d45485414 731 _pagesize = 256;
stjo2809 0:2e9d45485414 732 }
stjo2809 0:2e9d45485414 733 else
stjo2809 0:2e9d45485414 734 {
stjo2809 0:2e9d45485414 735 _pagesize = 264;
stjo2809 0:2e9d45485414 736 }
stjo2809 0:2e9d45485414 737 }
stjo2809 0:2e9d45485414 738 else if ( (_id & 0x1f) == 0x6) // 16Mbits
stjo2809 0:2e9d45485414 739 {
stjo2809 0:2e9d45485414 740 _devicesize = 2097152;
stjo2809 0:2e9d45485414 741 _pages = 4096;
stjo2809 0:2e9d45485414 742 _blocks = 512;
stjo2809 0:2e9d45485414 743 if (_status & 0x1)
stjo2809 0:2e9d45485414 744 {
stjo2809 0:2e9d45485414 745 _pagesize = 512;
stjo2809 0:2e9d45485414 746 }
stjo2809 0:2e9d45485414 747 else
stjo2809 0:2e9d45485414 748 {
stjo2809 0:2e9d45485414 749 _pagesize = 528;
stjo2809 0:2e9d45485414 750 }
stjo2809 0:2e9d45485414 751 }
stjo2809 0:2e9d45485414 752 else if ( (_id & 0x1f) == 0x7) // 32Mbits
stjo2809 0:2e9d45485414 753 {
stjo2809 0:2e9d45485414 754 _devicesize = 4194304;
stjo2809 0:2e9d45485414 755 _pages = 8192;
stjo2809 0:2e9d45485414 756 _blocks = 1024;
stjo2809 0:2e9d45485414 757 if (_status & 0x1)
stjo2809 0:2e9d45485414 758 {
stjo2809 0:2e9d45485414 759 _pagesize = 512;
stjo2809 0:2e9d45485414 760 }
stjo2809 0:2e9d45485414 761 else
stjo2809 0:2e9d45485414 762 {
stjo2809 0:2e9d45485414 763 _pagesize = 528;
stjo2809 0:2e9d45485414 764 }
stjo2809 0:2e9d45485414 765 }
stjo2809 0:2e9d45485414 766 else if ( (_id & 0x1f) == 0x8) // 64Mbits
stjo2809 0:2e9d45485414 767 {
stjo2809 0:2e9d45485414 768 _devicesize = 8388608;
stjo2809 0:2e9d45485414 769 _pages = 8192;
stjo2809 0:2e9d45485414 770 _blocks = 1024;
stjo2809 0:2e9d45485414 771 if (_status & 0x1)
stjo2809 0:2e9d45485414 772 {
stjo2809 0:2e9d45485414 773 _pagesize = 1024;
stjo2809 0:2e9d45485414 774 }
stjo2809 0:2e9d45485414 775 else
stjo2809 0:2e9d45485414 776 {
stjo2809 0:2e9d45485414 777 _pagesize = 1056;
stjo2809 0:2e9d45485414 778 }
stjo2809 0:2e9d45485414 779 }
stjo2809 0:2e9d45485414 780 else
stjo2809 0:2e9d45485414 781 {
stjo2809 0:2e9d45485414 782 _devicesize = -1;
stjo2809 0:2e9d45485414 783 _pages = -1;
stjo2809 0:2e9d45485414 784 _pagesize = -1;
stjo2809 0:2e9d45485414 785 _blocks = -1;
stjo2809 0:2e9d45485414 786 }
stjo2809 0:2e9d45485414 787 }
stjo2809 0:2e9d45485414 788
stjo2809 0:2e9d45485414 789 void AT45::_select()
stjo2809 0:2e9d45485414 790 {
stjo2809 0:2e9d45485414 791 _ncs = 0;
stjo2809 0:2e9d45485414 792 }
stjo2809 0:2e9d45485414 793
stjo2809 0:2e9d45485414 794 void AT45::_deselect()
stjo2809 0:2e9d45485414 795 {
stjo2809 0:2e9d45485414 796 _ncs = 1;
stjo2809 0:2e9d45485414 797 }
stjo2809 0:2e9d45485414 798
stjo2809 0:2e9d45485414 799 void AT45::_busy() {
stjo2809 0:2e9d45485414 800 volatile int iambusy = 1;
stjo2809 0:2e9d45485414 801 while (iambusy) {
stjo2809 0:2e9d45485414 802 // if bit 7 is set, we can proceed
stjo2809 0:2e9d45485414 803 if ( status() & 0x80 ) {
stjo2809 0:2e9d45485414 804 iambusy = 0;}
stjo2809 0:2e9d45485414 805 }
stjo2809 0:2e9d45485414 806 }
stjo2809 0:2e9d45485414 807
stjo2809 0:2e9d45485414 808 // Write to an SRAM buffer
stjo2809 0:2e9d45485414 809 // Note : We create buffer and page addresses in _sram and _flash
stjo2809 0:2e9d45485414 810 void AT45::_sramwrite(int buffer, int address, int data)
stjo2809 0:2e9d45485414 811 {
stjo2809 0:2e9d45485414 812
stjo2809 0:2e9d45485414 813 int cmd = 0;
stjo2809 0:2e9d45485414 814 int baddr = 0;
stjo2809 0:2e9d45485414 815
stjo2809 0:2e9d45485414 816 baddr = _getbaddr(address);
stjo2809 0:2e9d45485414 817
stjo2809 0:2e9d45485414 818 _busy();
stjo2809 0:2e9d45485414 819
stjo2809 0:2e9d45485414 820 _select();
stjo2809 0:2e9d45485414 821
stjo2809 0:2e9d45485414 822 if (buffer == 1)
stjo2809 0:2e9d45485414 823 {cmd = 0x84;}
stjo2809 0:2e9d45485414 824 else
stjo2809 0:2e9d45485414 825 {cmd = 0x87;}
stjo2809 0:2e9d45485414 826
maclobdell 1:f8e562ae5cc3 827 _spi->write(cmd);
stjo2809 0:2e9d45485414 828 _sendaddr (baddr);
maclobdell 1:f8e562ae5cc3 829 _spi->write (data);
stjo2809 0:2e9d45485414 830
stjo2809 0:2e9d45485414 831 _deselect();
stjo2809 0:2e9d45485414 832 }
stjo2809 0:2e9d45485414 833
stjo2809 0:2e9d45485414 834 // Read from an SRAM buffer
stjo2809 0:2e9d45485414 835 // Note : We create buffer and page addresses in _sram and _flash
stjo2809 0:2e9d45485414 836 int AT45::_sramread(int buffer, int address)
stjo2809 0:2e9d45485414 837 {
stjo2809 0:2e9d45485414 838
stjo2809 0:2e9d45485414 839 int cmd = 0;
stjo2809 0:2e9d45485414 840 int baddr = 0;
stjo2809 0:2e9d45485414 841 int bufdata = 0;
stjo2809 0:2e9d45485414 842
stjo2809 0:2e9d45485414 843 baddr = _getbaddr(address);
stjo2809 0:2e9d45485414 844
stjo2809 0:2e9d45485414 845 _select();
stjo2809 0:2e9d45485414 846
stjo2809 0:2e9d45485414 847 if(buffer == 1)
stjo2809 0:2e9d45485414 848 {cmd = 0xd4;}
stjo2809 0:2e9d45485414 849 else
stjo2809 0:2e9d45485414 850 {cmd = 0xd6;}
stjo2809 0:2e9d45485414 851
maclobdell 1:f8e562ae5cc3 852 _spi->write(cmd);
stjo2809 0:2e9d45485414 853 _sendaddr (baddr);
maclobdell 1:f8e562ae5cc3 854 _spi->write (0x0); // dont care byte
maclobdell 1:f8e562ae5cc3 855 bufdata = _spi->write (0x0);
stjo2809 0:2e9d45485414 856
stjo2809 0:2e9d45485414 857 _deselect();
stjo2809 0:2e9d45485414 858
stjo2809 0:2e9d45485414 859 return (bufdata);
stjo2809 0:2e9d45485414 860 }
stjo2809 0:2e9d45485414 861
stjo2809 0:2e9d45485414 862 // Write and SRAM buffer to main memory
stjo2809 0:2e9d45485414 863 void AT45::_flashwrite (int buffer, int address)
stjo2809 0:2e9d45485414 864 {
stjo2809 0:2e9d45485414 865
stjo2809 0:2e9d45485414 866 int cmd = 0;
stjo2809 0:2e9d45485414 867 int paddr = _getpaddr(address);
stjo2809 0:2e9d45485414 868
stjo2809 0:2e9d45485414 869 _busy(); // Check flash is not busy
stjo2809 0:2e9d45485414 870
stjo2809 0:2e9d45485414 871 _select();
stjo2809 0:2e9d45485414 872
stjo2809 0:2e9d45485414 873 if (buffer == 1)
stjo2809 0:2e9d45485414 874 {cmd = 0x83;}
stjo2809 0:2e9d45485414 875 else
stjo2809 0:2e9d45485414 876 {cmd = 0x86;}
stjo2809 0:2e9d45485414 877
maclobdell 1:f8e562ae5cc3 878 _spi->write (cmd);
stjo2809 0:2e9d45485414 879 _sendaddr (paddr);
stjo2809 0:2e9d45485414 880 _deselect();
stjo2809 0:2e9d45485414 881
stjo2809 0:2e9d45485414 882 _busy(); // Check flash is not busy
stjo2809 0:2e9d45485414 883 }
stjo2809 0:2e9d45485414 884
stjo2809 0:2e9d45485414 885 // Read from Flash memory into SRAM buffer
stjo2809 0:2e9d45485414 886 void AT45::_flashread (int buffer, int address)
stjo2809 0:2e9d45485414 887 {
stjo2809 0:2e9d45485414 888
stjo2809 0:2e9d45485414 889 int cmd = 0;
stjo2809 0:2e9d45485414 890 int paddr = _getpaddr(address); // calculate page address
stjo2809 0:2e9d45485414 891
stjo2809 0:2e9d45485414 892 _busy(); // Check flash is not busy
stjo2809 0:2e9d45485414 893 _select();
stjo2809 0:2e9d45485414 894
stjo2809 0:2e9d45485414 895 if (buffer == 1)
stjo2809 0:2e9d45485414 896 {cmd = 0x53;}
stjo2809 0:2e9d45485414 897 else
stjo2809 0:2e9d45485414 898 {cmd = 0x55;}
stjo2809 0:2e9d45485414 899
maclobdell 1:f8e562ae5cc3 900 _spi->write (cmd);
stjo2809 0:2e9d45485414 901 _sendaddr (paddr);
stjo2809 0:2e9d45485414 902 _deselect();
stjo2809 0:2e9d45485414 903 }
stjo2809 0:2e9d45485414 904
stjo2809 0:2e9d45485414 905 // Read directly from main memory
stjo2809 0:2e9d45485414 906 int AT45::_memread (int address)
stjo2809 0:2e9d45485414 907 {
stjo2809 0:2e9d45485414 908
stjo2809 0:2e9d45485414 909 int data = 0;
stjo2809 0:2e9d45485414 910 int addr;
stjo2809 0:2e9d45485414 911
stjo2809 0:2e9d45485414 912 addr = _getpaddr(address) | _getbaddr(address);
stjo2809 0:2e9d45485414 913
stjo2809 0:2e9d45485414 914 _busy();
stjo2809 0:2e9d45485414 915
stjo2809 0:2e9d45485414 916 _select();
stjo2809 0:2e9d45485414 917
maclobdell 1:f8e562ae5cc3 918 _spi->write (0xd2); // Direct read command
stjo2809 0:2e9d45485414 919 _sendaddr (addr);
stjo2809 0:2e9d45485414 920
stjo2809 0:2e9d45485414 921 // 4 dont care bytes
maclobdell 1:f8e562ae5cc3 922 _spi->write (0x00);
maclobdell 1:f8e562ae5cc3 923 _spi->write (0x00);
maclobdell 1:f8e562ae5cc3 924 _spi->write (0x00);
maclobdell 1:f8e562ae5cc3 925 _spi->write (0x00);
stjo2809 0:2e9d45485414 926
stjo2809 0:2e9d45485414 927 // this one clocks the data
maclobdell 1:f8e562ae5cc3 928 data = _spi->write (0x00);
stjo2809 0:2e9d45485414 929 _deselect();
stjo2809 0:2e9d45485414 930
stjo2809 0:2e9d45485414 931 _busy();
stjo2809 0:2e9d45485414 932
stjo2809 0:2e9d45485414 933 return data;
stjo2809 0:2e9d45485414 934 }
stjo2809 0:2e9d45485414 935
stjo2809 0:2e9d45485414 936 // Work out the page address
stjo2809 0:2e9d45485414 937 // If we have a 2^N page size, it is just the top N bits
stjo2809 0:2e9d45485414 938 // If we have non-2^N, we use the shifted address
stjo2809 0:2e9d45485414 939 int AT45::_getpaddr(int address)
stjo2809 0:2e9d45485414 940 {
stjo2809 0:2e9d45485414 941
stjo2809 0:2e9d45485414 942 int paddr;
stjo2809 0:2e9d45485414 943
stjo2809 0:2e9d45485414 944 if (_pagesize == 256) {
stjo2809 0:2e9d45485414 945 paddr = address & 0xffffff00;}
stjo2809 0:2e9d45485414 946 else if (_pagesize == 264) {
stjo2809 0:2e9d45485414 947 paddr = (address << 1) & 0xfffffe00;}
stjo2809 0:2e9d45485414 948 else if (_pagesize == 512) {
stjo2809 0:2e9d45485414 949 paddr = address & 0xfffffe00;}
stjo2809 0:2e9d45485414 950 else if (_pagesize == 528 ) {
stjo2809 0:2e9d45485414 951 paddr = (address << 1) & 0xfffffc00;}
stjo2809 0:2e9d45485414 952 else if (_pagesize == 1024) {
stjo2809 0:2e9d45485414 953 paddr = address & 0xfffffc00;}
stjo2809 0:2e9d45485414 954 else if (_pagesize == 1056 ) {
stjo2809 0:2e9d45485414 955 paddr = (address << 1) & 0xfffff800;}
stjo2809 0:2e9d45485414 956 else {
stjo2809 0:2e9d45485414 957 paddr = -1;}
stjo2809 0:2e9d45485414 958
stjo2809 0:2e9d45485414 959 return (paddr);
stjo2809 0:2e9d45485414 960 }
stjo2809 0:2e9d45485414 961
stjo2809 0:2e9d45485414 962 // Clean the buffer address. This is the 8/9/10 LSBs
stjo2809 0:2e9d45485414 963 int AT45::_getbaddr(int address)
stjo2809 0:2e9d45485414 964 {
stjo2809 0:2e9d45485414 965
stjo2809 0:2e9d45485414 966 int baddr;
stjo2809 0:2e9d45485414 967
stjo2809 0:2e9d45485414 968 if ((_pagesize == 256) || (_pagesize == 264 )) {
stjo2809 0:2e9d45485414 969 baddr = address & 0xff;}
stjo2809 0:2e9d45485414 970 else if ((_pagesize == 512) || (_pagesize == 528 )) {
stjo2809 0:2e9d45485414 971 baddr = address & 0x1ff;}
stjo2809 0:2e9d45485414 972 else if ((_pagesize == 1024) || (_pagesize == 1056 )) {
stjo2809 0:2e9d45485414 973 baddr = address & 0x3ff;}
stjo2809 0:2e9d45485414 974 else {
stjo2809 0:2e9d45485414 975 baddr = -1;}
stjo2809 0:2e9d45485414 976
stjo2809 0:2e9d45485414 977 return (baddr);
stjo2809 0:2e9d45485414 978 }
stjo2809 0:2e9d45485414 979
stjo2809 0:2e9d45485414 980 // Sends the three lest significant bytes of the supplied address
stjo2809 0:2e9d45485414 981 void AT45::_sendaddr (int address)
stjo2809 0:2e9d45485414 982 {
maclobdell 1:f8e562ae5cc3 983 _spi->write(address >> 16);
maclobdell 1:f8e562ae5cc3 984 _spi->write(address >> 8);
maclobdell 1:f8e562ae5cc3 985 _spi->write(address);
stjo2809 0:2e9d45485414 986 }