USBMSD SD card Hello World for Mbed platforms

Dependencies:   mbed USBMSD_SD USBDevice

Committer:
samux
Date:
Fri Nov 11 15:22:53 2011 +0000
Revision:
2:27a7e7f8d399
we have 2MB with the sdcard!!

Who changed what in which revision?

UserRevisionLine numberNew contents of line
samux 2:27a7e7f8d399 1 #include "AT45.h"
samux 2:27a7e7f8d399 2 #include "mbed.h"
samux 2:27a7e7f8d399 3
samux 2:27a7e7f8d399 4 /* mbed Library - AT45
samux 2:27a7e7f8d399 5 * (c)2007, cstyles
samux 2:27a7e7f8d399 6 */
samux 2:27a7e7f8d399 7
samux 2:27a7e7f8d399 8
samux 2:27a7e7f8d399 9
samux 2:27a7e7f8d399 10 /*
samux 2:27a7e7f8d399 11 * Constructor
samux 2:27a7e7f8d399 12 */
samux 2:27a7e7f8d399 13
samux 2:27a7e7f8d399 14 AT45::AT45(PinName mosi, PinName miso, PinName clk, PinName ncs)
samux 2:27a7e7f8d399 15 : _spi(mosi, miso, clk), _ncs(ncs) {
samux 2:27a7e7f8d399 16
samux 2:27a7e7f8d399 17 _pages = -1; // number of pages
samux 2:27a7e7f8d399 18 _pagesize = -1; // size of pages 256/264, 512/528, 1024/1056
samux 2:27a7e7f8d399 19 _devicesize = -1; // In bytes
samux 2:27a7e7f8d399 20
samux 2:27a7e7f8d399 21 _buffer1address = -1; // page address in buffer 1
samux 2:27a7e7f8d399 22 _buffer2address = -1; // page address in buffer 2
samux 2:27a7e7f8d399 23 _lru = -1; // leas recently used buffer (for eviction)
samux 2:27a7e7f8d399 24
samux 2:27a7e7f8d399 25 _reset(); // Populate all this stuff
samux 2:27a7e7f8d399 26
samux 2:27a7e7f8d399 27 }
samux 2:27a7e7f8d399 28
samux 2:27a7e7f8d399 29
samux 2:27a7e7f8d399 30
samux 2:27a7e7f8d399 31
samux 2:27a7e7f8d399 32
samux 2:27a7e7f8d399 33 /*
samux 2:27a7e7f8d399 34 * This is the reset function of the constructor.
samux 2:27a7e7f8d399 35 * Interrogate the part and set up some variables.
samux 2:27a7e7f8d399 36 */
samux 2:27a7e7f8d399 37
samux 2:27a7e7f8d399 38 void AT45::_reset() {
samux 2:27a7e7f8d399 39 int _id = 0;
samux 2:27a7e7f8d399 40 int _status = 0;
samux 2:27a7e7f8d399 41
samux 2:27a7e7f8d399 42 _spi.format(8,0);
samux 2:27a7e7f8d399 43 _spi.frequency(5000000);
samux 2:27a7e7f8d399 44
samux 2:27a7e7f8d399 45 _id = id();
samux 2:27a7e7f8d399 46 _status = status();
samux 2:27a7e7f8d399 47
samux 2:27a7e7f8d399 48 if ( (_id & 0x1f) == 0x2) { // 1Mbit
samux 2:27a7e7f8d399 49 _devicesize = 131072; // size in bytes
samux 2:27a7e7f8d399 50 _pages = 512; // number of pages
samux 2:27a7e7f8d399 51 _blocks = 256; // Number of 512 byte blocks
samux 2:27a7e7f8d399 52 if (_status & 0x1) {
samux 2:27a7e7f8d399 53 _pagesize = 256;}
samux 2:27a7e7f8d399 54 else {
samux 2:27a7e7f8d399 55 _pagesize = 264;}
samux 2:27a7e7f8d399 56 }
samux 2:27a7e7f8d399 57
samux 2:27a7e7f8d399 58 else if ( (_id & 0x1f) == 0x3) { // 2M
samux 2:27a7e7f8d399 59 _devicesize = 262144; // Size in bytes
samux 2:27a7e7f8d399 60 _pages = 1024; // Number of pages
samux 2:27a7e7f8d399 61 _blocks = 512; // Number of 512 byte blocks
samux 2:27a7e7f8d399 62 if (_status & 0x1) {
samux 2:27a7e7f8d399 63 _pagesize = 256;}
samux 2:27a7e7f8d399 64 else {
samux 2:27a7e7f8d399 65 _pagesize = 264;}
samux 2:27a7e7f8d399 66 }
samux 2:27a7e7f8d399 67
samux 2:27a7e7f8d399 68 else if ( (_id & 0x1f) == 0x4) { // 4M
samux 2:27a7e7f8d399 69 _devicesize = 524288;
samux 2:27a7e7f8d399 70 _pages = 2048;
samux 2:27a7e7f8d399 71 _blocks = 1024; // Number of 512 byte blocks
samux 2:27a7e7f8d399 72 if (_status & 0x1) {
samux 2:27a7e7f8d399 73 _pagesize = 256;}
samux 2:27a7e7f8d399 74 else {
samux 2:27a7e7f8d399 75 _pagesize = 264;}
samux 2:27a7e7f8d399 76 }
samux 2:27a7e7f8d399 77
samux 2:27a7e7f8d399 78 else if ( (_id & 0x1f) == 0x5) { // 8M
samux 2:27a7e7f8d399 79 _devicesize = 1048576;
samux 2:27a7e7f8d399 80 _pages = 4096;
samux 2:27a7e7f8d399 81 _blocks = 2048; // Number of 512 byte blocks
samux 2:27a7e7f8d399 82 if (_status & 0x1) {
samux 2:27a7e7f8d399 83 _pagesize = 256;}
samux 2:27a7e7f8d399 84 else {
samux 2:27a7e7f8d399 85 _pagesize = 264;}
samux 2:27a7e7f8d399 86 }
samux 2:27a7e7f8d399 87
samux 2:27a7e7f8d399 88 else if ( (_id & 0x1f) == 0x6) { // 16M
samux 2:27a7e7f8d399 89 _devicesize = 2097152;
samux 2:27a7e7f8d399 90 _pages = 4096;
samux 2:27a7e7f8d399 91 _blocks = 4096; // Number of 512 byte blocks
samux 2:27a7e7f8d399 92 if (_status & 0x1) {
samux 2:27a7e7f8d399 93 _pagesize = 512;}
samux 2:27a7e7f8d399 94 else {
samux 2:27a7e7f8d399 95 _pagesize = 528;}
samux 2:27a7e7f8d399 96 }
samux 2:27a7e7f8d399 97
samux 2:27a7e7f8d399 98 else if ( (_id & 0x1f) == 0x7) { // 32M
samux 2:27a7e7f8d399 99 _devicesize = 4194304;
samux 2:27a7e7f8d399 100 _pages = 8192;
samux 2:27a7e7f8d399 101 _blocks = 8192; // Number of 512 byte blocks
samux 2:27a7e7f8d399 102 if (_status & 0x1) {
samux 2:27a7e7f8d399 103 _pagesize = 512;}
samux 2:27a7e7f8d399 104 else {
samux 2:27a7e7f8d399 105 _pagesize = 528;}
samux 2:27a7e7f8d399 106 }
samux 2:27a7e7f8d399 107
samux 2:27a7e7f8d399 108 else if ( (_id & 0x1f) == 0x8) { // 64M
samux 2:27a7e7f8d399 109 _devicesize = 8388608;
samux 2:27a7e7f8d399 110 _pages = 8192;
samux 2:27a7e7f8d399 111 _blocks = 16384;
samux 2:27a7e7f8d399 112 if (_status & 0x1) {
samux 2:27a7e7f8d399 113 _pagesize = 1024;}
samux 2:27a7e7f8d399 114 else {
samux 2:27a7e7f8d399 115 _pagesize = 1056;}
samux 2:27a7e7f8d399 116 }
samux 2:27a7e7f8d399 117
samux 2:27a7e7f8d399 118 else {
samux 2:27a7e7f8d399 119 _devicesize = -1;
samux 2:27a7e7f8d399 120 _pages = -1;
samux 2:27a7e7f8d399 121 _pagesize = -1;
samux 2:27a7e7f8d399 122 }
samux 2:27a7e7f8d399 123 }
samux 2:27a7e7f8d399 124
samux 2:27a7e7f8d399 125
samux 2:27a7e7f8d399 126
samux 2:27a7e7f8d399 127
samux 2:27a7e7f8d399 128
samux 2:27a7e7f8d399 129 /*
samux 2:27a7e7f8d399 130 * Select pulls nCS low, but also ensure SPI channel is formatted
samux 2:27a7e7f8d399 131 * This is so that another device sharing the same SPI pins
samux 2:27a7e7f8d399 132 * doenst leave it in an unknown state
samux 2:27a7e7f8d399 133 */
samux 2:27a7e7f8d399 134
samux 2:27a7e7f8d399 135 void AT45::_select() {
samux 2:27a7e7f8d399 136 // ensure that the SPI port is set up correctly still
samux 2:27a7e7f8d399 137 // This allows SPI channel sharing
samux 2:27a7e7f8d399 138 _spi.format(8,0);
samux 2:27a7e7f8d399 139 _spi.frequency(5000000);
samux 2:27a7e7f8d399 140 _ncs = 0;
samux 2:27a7e7f8d399 141 }
samux 2:27a7e7f8d399 142
samux 2:27a7e7f8d399 143
samux 2:27a7e7f8d399 144
samux 2:27a7e7f8d399 145
samux 2:27a7e7f8d399 146
samux 2:27a7e7f8d399 147 /*
samux 2:27a7e7f8d399 148 * Deselect simply returns nCS to high
samux 2:27a7e7f8d399 149 */
samux 2:27a7e7f8d399 150 void AT45::_deselect() {
samux 2:27a7e7f8d399 151 _ncs = 1;
samux 2:27a7e7f8d399 152 }
samux 2:27a7e7f8d399 153
samux 2:27a7e7f8d399 154
samux 2:27a7e7f8d399 155
samux 2:27a7e7f8d399 156
samux 2:27a7e7f8d399 157
samux 2:27a7e7f8d399 158 /*
samux 2:27a7e7f8d399 159 * Work out the page address
samux 2:27a7e7f8d399 160 * If we have a 2^N page size, it is just the top N bits
samux 2:27a7e7f8d399 161 * If we have non-2^N, we use the shifted address
samux 2:27a7e7f8d399 162 */
samux 2:27a7e7f8d399 163
samux 2:27a7e7f8d399 164 int AT45::_getpaddr(int address) {
samux 2:27a7e7f8d399 165
samux 2:27a7e7f8d399 166 int paddr;
samux 2:27a7e7f8d399 167
samux 2:27a7e7f8d399 168 if (_pagesize == 256) {
samux 2:27a7e7f8d399 169 paddr = address & 0xffffff00;}
samux 2:27a7e7f8d399 170 else if (_pagesize == 264) {
samux 2:27a7e7f8d399 171 paddr = (address << 1) & 0xfffffe00;}
samux 2:27a7e7f8d399 172 else if (_pagesize == 512) {
samux 2:27a7e7f8d399 173 paddr = address & 0xfffffe00;}
samux 2:27a7e7f8d399 174 else if (_pagesize == 528 ) {
samux 2:27a7e7f8d399 175 paddr = (address << 1) & 0xfffffc00;}
samux 2:27a7e7f8d399 176 else if (_pagesize == 1024) {
samux 2:27a7e7f8d399 177 paddr = address & 0xfffffc00;}
samux 2:27a7e7f8d399 178 else if (_pagesize == 1056 ) {
samux 2:27a7e7f8d399 179 paddr = (address << 1) & 0xfffff800;}
samux 2:27a7e7f8d399 180 else {
samux 2:27a7e7f8d399 181 paddr = 0xdeadbeef;}
samux 2:27a7e7f8d399 182
samux 2:27a7e7f8d399 183 return (paddr);
samux 2:27a7e7f8d399 184
samux 2:27a7e7f8d399 185 }
samux 2:27a7e7f8d399 186
samux 2:27a7e7f8d399 187
samux 2:27a7e7f8d399 188
samux 2:27a7e7f8d399 189
samux 2:27a7e7f8d399 190
samux 2:27a7e7f8d399 191 /*
samux 2:27a7e7f8d399 192 * Clean the buffer address. This is the 8/9/10 LSBs
samux 2:27a7e7f8d399 193 */
samux 2:27a7e7f8d399 194
samux 2:27a7e7f8d399 195 int AT45::_getbaddr(int address) {
samux 2:27a7e7f8d399 196
samux 2:27a7e7f8d399 197 int baddr;
samux 2:27a7e7f8d399 198
samux 2:27a7e7f8d399 199 if ((_pagesize == 256) || (_pagesize == 264 )) {
samux 2:27a7e7f8d399 200 baddr = address & 0xff;}
samux 2:27a7e7f8d399 201 else if ((_pagesize == 512) || (_pagesize == 528 )) {
samux 2:27a7e7f8d399 202 baddr = address & 0x1ff;}
samux 2:27a7e7f8d399 203 else if ((_pagesize == 1024) || (_pagesize == 1056 )) {
samux 2:27a7e7f8d399 204 baddr = address & 0x3ff;}
samux 2:27a7e7f8d399 205 else {
samux 2:27a7e7f8d399 206 baddr = 0xcafebabe;}
samux 2:27a7e7f8d399 207
samux 2:27a7e7f8d399 208 return (baddr);
samux 2:27a7e7f8d399 209 }
samux 2:27a7e7f8d399 210
samux 2:27a7e7f8d399 211
samux 2:27a7e7f8d399 212
samux 2:27a7e7f8d399 213
samux 2:27a7e7f8d399 214
samux 2:27a7e7f8d399 215 /*
samux 2:27a7e7f8d399 216 * Return the Id of the part
samux 2:27a7e7f8d399 217 */
samux 2:27a7e7f8d399 218
samux 2:27a7e7f8d399 219 int AT45::id() {
samux 2:27a7e7f8d399 220 int id = 0;
samux 2:27a7e7f8d399 221 _select();
samux 2:27a7e7f8d399 222 _spi.write(0x9f);
samux 2:27a7e7f8d399 223 id = (_spi.write(0x00) << 8);
samux 2:27a7e7f8d399 224 id |= _spi.write(0x00);
samux 2:27a7e7f8d399 225 _deselect();
samux 2:27a7e7f8d399 226 return id;
samux 2:27a7e7f8d399 227 }
samux 2:27a7e7f8d399 228
samux 2:27a7e7f8d399 229
samux 2:27a7e7f8d399 230
samux 2:27a7e7f8d399 231
samux 2:27a7e7f8d399 232
samux 2:27a7e7f8d399 233 /*
samux 2:27a7e7f8d399 234 * return the Status
samux 2:27a7e7f8d399 235 */
samux 2:27a7e7f8d399 236
samux 2:27a7e7f8d399 237 int AT45::status() {
samux 2:27a7e7f8d399 238 int status = 0;
samux 2:27a7e7f8d399 239 _select();
samux 2:27a7e7f8d399 240 _spi.write(0xd7);
samux 2:27a7e7f8d399 241 status = (_spi.write(0x00) << 8 );
samux 2:27a7e7f8d399 242 status |= _spi.write(0x00);
samux 2:27a7e7f8d399 243 _deselect();
samux 2:27a7e7f8d399 244 return status;
samux 2:27a7e7f8d399 245 }
samux 2:27a7e7f8d399 246
samux 2:27a7e7f8d399 247
samux 2:27a7e7f8d399 248
samux 2:27a7e7f8d399 249
samux 2:27a7e7f8d399 250
samux 2:27a7e7f8d399 251 /*
samux 2:27a7e7f8d399 252 * Erase the entire chip
samux 2:27a7e7f8d399 253 */
samux 2:27a7e7f8d399 254
samux 2:27a7e7f8d399 255 void AT45::erase() {
samux 2:27a7e7f8d399 256
samux 2:27a7e7f8d399 257 _pollbusy(); // make sure flash isnt already in busy.
samux 2:27a7e7f8d399 258
samux 2:27a7e7f8d399 259 // There are errata on this. For now, do itthe long way :-(
samux 2:27a7e7f8d399 260 _select();
samux 2:27a7e7f8d399 261 // 4 byte command sequence
samux 2:27a7e7f8d399 262 _spi.write(0xc7);
samux 2:27a7e7f8d399 263 _spi.write(0x94);
samux 2:27a7e7f8d399 264 _spi.write(0x80);
samux 2:27a7e7f8d399 265 _spi.write(0x9a);
samux 2:27a7e7f8d399 266 _deselect();
samux 2:27a7e7f8d399 267
samux 2:27a7e7f8d399 268 _pollbusy(); // Make erase a blocking function
samux 2:27a7e7f8d399 269
samux 2:27a7e7f8d399 270 }
samux 2:27a7e7f8d399 271
samux 2:27a7e7f8d399 272
samux 2:27a7e7f8d399 273
samux 2:27a7e7f8d399 274
samux 2:27a7e7f8d399 275
samux 2:27a7e7f8d399 276 /*
samux 2:27a7e7f8d399 277 * return the size of the part in bytes
samux 2:27a7e7f8d399 278 */
samux 2:27a7e7f8d399 279
samux 2:27a7e7f8d399 280 int AT45::size() {
samux 2:27a7e7f8d399 281 return _devicesize;
samux 2:27a7e7f8d399 282 }
samux 2:27a7e7f8d399 283
samux 2:27a7e7f8d399 284
samux 2:27a7e7f8d399 285
samux 2:27a7e7f8d399 286
samux 2:27a7e7f8d399 287
samux 2:27a7e7f8d399 288 /*
samux 2:27a7e7f8d399 289 * return the page size of the part in bytes
samux 2:27a7e7f8d399 290 */
samux 2:27a7e7f8d399 291
samux 2:27a7e7f8d399 292 int AT45::pagesize() {
samux 2:27a7e7f8d399 293 return _pagesize;
samux 2:27a7e7f8d399 294 }
samux 2:27a7e7f8d399 295
samux 2:27a7e7f8d399 296
samux 2:27a7e7f8d399 297
samux 2:27a7e7f8d399 298
samux 2:27a7e7f8d399 299
samux 2:27a7e7f8d399 300 /*
samux 2:27a7e7f8d399 301 * return the numbers of pages
samux 2:27a7e7f8d399 302 */
samux 2:27a7e7f8d399 303
samux 2:27a7e7f8d399 304 int AT45::pages() {
samux 2:27a7e7f8d399 305 return _pages;
samux 2:27a7e7f8d399 306 }
samux 2:27a7e7f8d399 307
samux 2:27a7e7f8d399 308
samux 2:27a7e7f8d399 309
samux 2:27a7e7f8d399 310
samux 2:27a7e7f8d399 311
samux 2:27a7e7f8d399 312 /*
samux 2:27a7e7f8d399 313 * Make sure the Flash isnt already doing something
samux 2:27a7e7f8d399 314 */
samux 2:27a7e7f8d399 315 void AT45::_pollbusy() {
samux 2:27a7e7f8d399 316 volatile int busy = 1;
samux 2:27a7e7f8d399 317 while (busy) {
samux 2:27a7e7f8d399 318 // if bit 7 is set, we can proceed
samux 2:27a7e7f8d399 319 if ( status() & 0x80 ) {
samux 2:27a7e7f8d399 320 busy = 0;}
samux 2:27a7e7f8d399 321 }
samux 2:27a7e7f8d399 322 }
samux 2:27a7e7f8d399 323
samux 2:27a7e7f8d399 324
samux 2:27a7e7f8d399 325
samux 2:27a7e7f8d399 326
samux 2:27a7e7f8d399 327
samux 2:27a7e7f8d399 328 /*
samux 2:27a7e7f8d399 329 * Make sure the Flash isnt already doing something
samux 2:27a7e7f8d399 330 */
samux 2:27a7e7f8d399 331
samux 2:27a7e7f8d399 332 void AT45::pollbusy() {
samux 2:27a7e7f8d399 333 _pollbusy();
samux 2:27a7e7f8d399 334 }
samux 2:27a7e7f8d399 335
samux 2:27a7e7f8d399 336
samux 2:27a7e7f8d399 337
samux 2:27a7e7f8d399 338
samux 2:27a7e7f8d399 339
samux 2:27a7e7f8d399 340 /*
samux 2:27a7e7f8d399 341 * This function returns the char
samux 2:27a7e7f8d399 342 */
samux 2:27a7e7f8d399 343
samux 2:27a7e7f8d399 344 char AT45::read(int address) {
samux 2:27a7e7f8d399 345 // return byte from address
samux 2:27a7e7f8d399 346 return (_memread( address ));
samux 2:27a7e7f8d399 347 }
samux 2:27a7e7f8d399 348
samux 2:27a7e7f8d399 349
samux 2:27a7e7f8d399 350
samux 2:27a7e7f8d399 351
samux 2:27a7e7f8d399 352
samux 2:27a7e7f8d399 353 /*
samux 2:27a7e7f8d399 354 * This function writes the char to the address supplied
samux 2:27a7e7f8d399 355 * Note : We pass the raw address to the underlying functions
samux 2:27a7e7f8d399 356 */
samux 2:27a7e7f8d399 357
samux 2:27a7e7f8d399 358 void AT45::write(int address, char data) {
samux 2:27a7e7f8d399 359
samux 2:27a7e7f8d399 360 _pollbusy();
samux 2:27a7e7f8d399 361 _flashread(1,address); // read the Flash page into SRAM buffer
samux 2:27a7e7f8d399 362 _pollbusy(); // wait for the read to complete
samux 2:27a7e7f8d399 363 _sramwrite(1,address,data); // Write new data into SRAM
samux 2:27a7e7f8d399 364 _pollbusy(); // Make sure flash isnt busy
samux 2:27a7e7f8d399 365 _flashwrite(1,address); // Write back to the page address
samux 2:27a7e7f8d399 366 }
samux 2:27a7e7f8d399 367
samux 2:27a7e7f8d399 368
samux 2:27a7e7f8d399 369
samux 2:27a7e7f8d399 370
samux 2:27a7e7f8d399 371
samux 2:27a7e7f8d399 372 /*
samux 2:27a7e7f8d399 373 * Read from an SRAM buffer
samux 2:27a7e7f8d399 374 * Note : We create buffer and page addresses in _sram and _flash
samux 2:27a7e7f8d399 375 */
samux 2:27a7e7f8d399 376
samux 2:27a7e7f8d399 377 int AT45::_sramread(int buffer, int address) {
samux 2:27a7e7f8d399 378
samux 2:27a7e7f8d399 379 int cmd = 0;
samux 2:27a7e7f8d399 380 int baddr = 0;
samux 2:27a7e7f8d399 381
samux 2:27a7e7f8d399 382 baddr = _getbaddr(address);
samux 2:27a7e7f8d399 383
samux 2:27a7e7f8d399 384 _select();
samux 2:27a7e7f8d399 385
samux 2:27a7e7f8d399 386 if(buffer == 1)
samux 2:27a7e7f8d399 387 {cmd = 0xd4;}
samux 2:27a7e7f8d399 388 else
samux 2:27a7e7f8d399 389 {cmd = 0xd6;}
samux 2:27a7e7f8d399 390
samux 2:27a7e7f8d399 391 _spi.write(cmd);
samux 2:27a7e7f8d399 392 _sendaddr (baddr);
samux 2:27a7e7f8d399 393 _spi.write (0x0); // dont care byte
samux 2:27a7e7f8d399 394 cmd = _spi.write (0x0);
samux 2:27a7e7f8d399 395
samux 2:27a7e7f8d399 396 _deselect();
samux 2:27a7e7f8d399 397
samux 2:27a7e7f8d399 398 return (cmd);
samux 2:27a7e7f8d399 399 }
samux 2:27a7e7f8d399 400
samux 2:27a7e7f8d399 401
samux 2:27a7e7f8d399 402
samux 2:27a7e7f8d399 403
samux 2:27a7e7f8d399 404
samux 2:27a7e7f8d399 405
samux 2:27a7e7f8d399 406 /*
samux 2:27a7e7f8d399 407 * Write to an SRAM buffer
samux 2:27a7e7f8d399 408 * Note : We create buffer and page addresses in _sram and _flash
samux 2:27a7e7f8d399 409 */
samux 2:27a7e7f8d399 410
samux 2:27a7e7f8d399 411 void AT45::_sramwrite(int buffer, int address, int data) {
samux 2:27a7e7f8d399 412
samux 2:27a7e7f8d399 413 int cmd = 0;
samux 2:27a7e7f8d399 414 int baddr = 0;
samux 2:27a7e7f8d399 415
samux 2:27a7e7f8d399 416 baddr = _getbaddr(address);
samux 2:27a7e7f8d399 417
samux 2:27a7e7f8d399 418 _pollbusy();
samux 2:27a7e7f8d399 419
samux 2:27a7e7f8d399 420 _select();
samux 2:27a7e7f8d399 421
samux 2:27a7e7f8d399 422 if (buffer == 1)
samux 2:27a7e7f8d399 423 {cmd = 0x84;}
samux 2:27a7e7f8d399 424 else
samux 2:27a7e7f8d399 425 {cmd = 0x87;}
samux 2:27a7e7f8d399 426
samux 2:27a7e7f8d399 427 _spi.write(cmd);
samux 2:27a7e7f8d399 428 _sendaddr (baddr);
samux 2:27a7e7f8d399 429 _spi.write (data);
samux 2:27a7e7f8d399 430
samux 2:27a7e7f8d399 431 _deselect();
samux 2:27a7e7f8d399 432 }
samux 2:27a7e7f8d399 433
samux 2:27a7e7f8d399 434
samux 2:27a7e7f8d399 435
samux 2:27a7e7f8d399 436
samux 2:27a7e7f8d399 437
samux 2:27a7e7f8d399 438 /*
samux 2:27a7e7f8d399 439 * Read from Flash memory into SRAM buffer
samux 2:27a7e7f8d399 440 */
samux 2:27a7e7f8d399 441
samux 2:27a7e7f8d399 442 void AT45::_flashread (int buffer, int address) {
samux 2:27a7e7f8d399 443
samux 2:27a7e7f8d399 444 int cmd = 0;
samux 2:27a7e7f8d399 445 int paddr = _getpaddr(address); // calculate page address
samux 2:27a7e7f8d399 446
samux 2:27a7e7f8d399 447 _pollbusy(); // Check flash is not busy
samux 2:27a7e7f8d399 448 _select();
samux 2:27a7e7f8d399 449
samux 2:27a7e7f8d399 450 if (buffer == 1)
samux 2:27a7e7f8d399 451 {cmd = 0x53;}
samux 2:27a7e7f8d399 452 else
samux 2:27a7e7f8d399 453 {cmd = 0x55;}
samux 2:27a7e7f8d399 454
samux 2:27a7e7f8d399 455 _spi.write (cmd);
samux 2:27a7e7f8d399 456 _sendaddr (paddr);
samux 2:27a7e7f8d399 457 _deselect();
samux 2:27a7e7f8d399 458
samux 2:27a7e7f8d399 459 }
samux 2:27a7e7f8d399 460
samux 2:27a7e7f8d399 461
samux 2:27a7e7f8d399 462
samux 2:27a7e7f8d399 463
samux 2:27a7e7f8d399 464
samux 2:27a7e7f8d399 465 /*
samux 2:27a7e7f8d399 466 * Write and SRAM buffer back to main memory
samux 2:27a7e7f8d399 467 */
samux 2:27a7e7f8d399 468
samux 2:27a7e7f8d399 469 void AT45::_flashwrite (int buffer, int address) {
samux 2:27a7e7f8d399 470
samux 2:27a7e7f8d399 471 int cmd = 0;
samux 2:27a7e7f8d399 472 int paddr = _getpaddr(address);
samux 2:27a7e7f8d399 473
samux 2:27a7e7f8d399 474 _pollbusy(); // Check flash is not busy
samux 2:27a7e7f8d399 475
samux 2:27a7e7f8d399 476 _select();
samux 2:27a7e7f8d399 477
samux 2:27a7e7f8d399 478 if (buffer == 1)
samux 2:27a7e7f8d399 479 {cmd = 0x83;}
samux 2:27a7e7f8d399 480 else
samux 2:27a7e7f8d399 481 {cmd = 0x86;}
samux 2:27a7e7f8d399 482
samux 2:27a7e7f8d399 483 _spi.write (cmd);
samux 2:27a7e7f8d399 484 _sendaddr (paddr);
samux 2:27a7e7f8d399 485 _deselect();
samux 2:27a7e7f8d399 486
samux 2:27a7e7f8d399 487 _pollbusy(); // Check flash is not busy
samux 2:27a7e7f8d399 488
samux 2:27a7e7f8d399 489 }
samux 2:27a7e7f8d399 490
samux 2:27a7e7f8d399 491
samux 2:27a7e7f8d399 492
samux 2:27a7e7f8d399 493
samux 2:27a7e7f8d399 494
samux 2:27a7e7f8d399 495 /*
samux 2:27a7e7f8d399 496 * Read directly from main memory
samux 2:27a7e7f8d399 497 */
samux 2:27a7e7f8d399 498
samux 2:27a7e7f8d399 499 int AT45::_memread (int address) {
samux 2:27a7e7f8d399 500
samux 2:27a7e7f8d399 501 int data = 0;
samux 2:27a7e7f8d399 502 int addr;
samux 2:27a7e7f8d399 503
samux 2:27a7e7f8d399 504 addr = _getpaddr(address) | _getbaddr(address);
samux 2:27a7e7f8d399 505
samux 2:27a7e7f8d399 506 _pollbusy();
samux 2:27a7e7f8d399 507
samux 2:27a7e7f8d399 508 _select();
samux 2:27a7e7f8d399 509
samux 2:27a7e7f8d399 510 _spi.write (0xd2); // Direct read command
samux 2:27a7e7f8d399 511 _sendaddr (addr);
samux 2:27a7e7f8d399 512
samux 2:27a7e7f8d399 513 // 4 dont care bytes
samux 2:27a7e7f8d399 514 _spi.write (0x00);
samux 2:27a7e7f8d399 515 _spi.write (0x00);
samux 2:27a7e7f8d399 516 _spi.write (0x00);
samux 2:27a7e7f8d399 517 _spi.write (0x00);
samux 2:27a7e7f8d399 518
samux 2:27a7e7f8d399 519 // this one clocks the data
samux 2:27a7e7f8d399 520 data = _spi.write (0x00);
samux 2:27a7e7f8d399 521 _deselect();
samux 2:27a7e7f8d399 522
samux 2:27a7e7f8d399 523 _pollbusy();
samux 2:27a7e7f8d399 524
samux 2:27a7e7f8d399 525 return data;
samux 2:27a7e7f8d399 526 }
samux 2:27a7e7f8d399 527
samux 2:27a7e7f8d399 528
samux 2:27a7e7f8d399 529
samux 2:27a7e7f8d399 530
samux 2:27a7e7f8d399 531
samux 2:27a7e7f8d399 532 /*
samux 2:27a7e7f8d399 533 * Sends the three lest significant bytes of the supplied address
samux 2:27a7e7f8d399 534 */
samux 2:27a7e7f8d399 535
samux 2:27a7e7f8d399 536 void AT45::_sendaddr (int address) {
samux 2:27a7e7f8d399 537 _spi.write(address >> 16);
samux 2:27a7e7f8d399 538 _spi.write(address >> 8);
samux 2:27a7e7f8d399 539 _spi.write(address);
samux 2:27a7e7f8d399 540 }
samux 2:27a7e7f8d399 541
samux 2:27a7e7f8d399 542
samux 2:27a7e7f8d399 543
samux 2:27a7e7f8d399 544
samux 2:27a7e7f8d399 545
samux 2:27a7e7f8d399 546 /*
samux 2:27a7e7f8d399 547 * Return the number of 512 byte blocks in this device
samux 2:27a7e7f8d399 548 */
samux 2:27a7e7f8d399 549
samux 2:27a7e7f8d399 550 int AT45::blocks(void) {
samux 2:27a7e7f8d399 551 return _blocks;
samux 2:27a7e7f8d399 552 }
samux 2:27a7e7f8d399 553
samux 2:27a7e7f8d399 554
samux 2:27a7e7f8d399 555
samux 2:27a7e7f8d399 556
samux 2:27a7e7f8d399 557
samux 2:27a7e7f8d399 558 /*
samux 2:27a7e7f8d399 559 * Read the numbered block into the data array supplied
samux 2:27a7e7f8d399 560 */
samux 2:27a7e7f8d399 561
samux 2:27a7e7f8d399 562 int AT45::blockread (char* data, int block) {
samux 2:27a7e7f8d399 563
samux 2:27a7e7f8d399 564 // For 256 byte pages, we read two pages
samux 2:27a7e7f8d399 565 if((_pagesize == 256) || (_pagesize == 264)) {
samux 2:27a7e7f8d399 566
samux 2:27a7e7f8d399 567 int address = block * 512; // This is the start address of the 512 byte block
samux 2:27a7e7f8d399 568
samux 2:27a7e7f8d399 569 _flashread(1,address); // read the first page of the block into SRAM buffer 1
samux 2:27a7e7f8d399 570 _pollbusy(); // Wait until First page has loaded into buffer 1
samux 2:27a7e7f8d399 571
samux 2:27a7e7f8d399 572 // I'll do this directly as we are reading back an entire buffer, and this can be done more optimally
samux 2:27a7e7f8d399 573 // than using _sramread
samux 2:27a7e7f8d399 574 _select();
samux 2:27a7e7f8d399 575 _spi.write(0xd4);
samux 2:27a7e7f8d399 576 _sendaddr (0x0);
samux 2:27a7e7f8d399 577 _spi.write (0x0); // dont care byte
samux 2:27a7e7f8d399 578
samux 2:27a7e7f8d399 579 for(int i=0;i<256;i++) {
samux 2:27a7e7f8d399 580 data[i] = _spi.write (0x0);
samux 2:27a7e7f8d399 581 }
samux 2:27a7e7f8d399 582 _deselect();
samux 2:27a7e7f8d399 583
samux 2:27a7e7f8d399 584 _flashread(1,address+256); // read the second page of the block into SRAM buffer 2
samux 2:27a7e7f8d399 585 _pollbusy(); // Wait until second page has loaded into buffer 2
samux 2:27a7e7f8d399 586
samux 2:27a7e7f8d399 587 // Now the second page is loaded, pull this out into the second half of the data buffer
samux 2:27a7e7f8d399 588 // I'll do this directly as we are reading back an entire buffer, and this can be done more optimally
samux 2:27a7e7f8d399 589 // than using _sramread
samux 2:27a7e7f8d399 590 _select();
samux 2:27a7e7f8d399 591 _spi.write(0xd4);
samux 2:27a7e7f8d399 592 _sendaddr (0x0);
samux 2:27a7e7f8d399 593 _spi.write (0x0); // dont care byte
samux 2:27a7e7f8d399 594
samux 2:27a7e7f8d399 595 for(int i=0;i<256;i++) {
samux 2:27a7e7f8d399 596 data[256+i] = _spi.write (0x0);
samux 2:27a7e7f8d399 597 }
samux 2:27a7e7f8d399 598 _deselect();
samux 2:27a7e7f8d399 599 return (0);
samux 2:27a7e7f8d399 600 }
samux 2:27a7e7f8d399 601
samux 2:27a7e7f8d399 602
samux 2:27a7e7f8d399 603 // For 512 byte pages, we read just the single page, transfer it
samux 2:27a7e7f8d399 604 else if((_pagesize == 512) || (_pagesize == 528)) {
samux 2:27a7e7f8d399 605
samux 2:27a7e7f8d399 606 int address = block * 512; // This is the start address of the 512 byte block
samux 2:27a7e7f8d399 607
samux 2:27a7e7f8d399 608 _pollbusy(); // Wait until First page has loaded into buffer 1
samux 2:27a7e7f8d399 609 _flashread(1,address); // read the first page of the block into SRAM buffer 1
samux 2:27a7e7f8d399 610 _pollbusy(); // Wait until First page has loaded into buffer 1
samux 2:27a7e7f8d399 611
samux 2:27a7e7f8d399 612 // Now the page has loaded, simply transfer it from the sram buffer to the data array
samux 2:27a7e7f8d399 613 // I'll do this directly as we are reading back an entire buffer, and this can be done more optimally
samux 2:27a7e7f8d399 614 // than using _sramread
samux 2:27a7e7f8d399 615 _select();
samux 2:27a7e7f8d399 616 _spi.write(0xd4);
samux 2:27a7e7f8d399 617 _sendaddr (0x0);
samux 2:27a7e7f8d399 618 _spi.write (0x0); // dont care byte
samux 2:27a7e7f8d399 619
samux 2:27a7e7f8d399 620 for(int i=0;i<512;i++) {
samux 2:27a7e7f8d399 621 data[i] = _spi.write (0x0);
samux 2:27a7e7f8d399 622 }
samux 2:27a7e7f8d399 623 _deselect();
samux 2:27a7e7f8d399 624 return (0);
samux 2:27a7e7f8d399 625 }
samux 2:27a7e7f8d399 626
samux 2:27a7e7f8d399 627
samux 2:27a7e7f8d399 628 // For 1024 byte pages, we read just a single page, transfer half of it
samux 2:27a7e7f8d399 629 else if((_pagesize == 1024) || (_pagesize == 1056)) {
samux 2:27a7e7f8d399 630 int address = _getpaddr(block * 512); // This is the start address of the 512 byte block
samux 2:27a7e7f8d399 631
samux 2:27a7e7f8d399 632 _pollbusy(); // Wait until First page has loaded into buffer 1
samux 2:27a7e7f8d399 633
samux 2:27a7e7f8d399 634 _flashread(1,address); // read the first page of the block into SRAM buffer 1
samux 2:27a7e7f8d399 635
samux 2:27a7e7f8d399 636 _pollbusy(); // Wait until First page has loaded into buffer 1
samux 2:27a7e7f8d399 637
samux 2:27a7e7f8d399 638 // Now the page has loaded, simply transfer it from the sram buffer to the data array
samux 2:27a7e7f8d399 639 // I'll do this directly as we are reading back an entire buffer, and this can be done more optimally
samux 2:27a7e7f8d399 640 // than using _sramread
samux 2:27a7e7f8d399 641
samux 2:27a7e7f8d399 642 _select();
samux 2:27a7e7f8d399 643 _spi.write(0xd4);
samux 2:27a7e7f8d399 644
samux 2:27a7e7f8d399 645 if (block %2) { // odd numbered block, read from adress 0x200
samux 2:27a7e7f8d399 646 _sendaddr (0x200);
samux 2:27a7e7f8d399 647 }
samux 2:27a7e7f8d399 648 else {// even numbered block, then we are reading from sram buffer 0x0
samux 2:27a7e7f8d399 649 _sendaddr (0x0);
samux 2:27a7e7f8d399 650 }
samux 2:27a7e7f8d399 651
samux 2:27a7e7f8d399 652
samux 2:27a7e7f8d399 653 _spi.write (0x0); // dont care byte
samux 2:27a7e7f8d399 654
samux 2:27a7e7f8d399 655 for(int i=0;i<512;i++) {
samux 2:27a7e7f8d399 656 data[i] = _spi.write (0x0);
samux 2:27a7e7f8d399 657 }
samux 2:27a7e7f8d399 658 _deselect();
samux 2:27a7e7f8d399 659 return (0);
samux 2:27a7e7f8d399 660 }
samux 2:27a7e7f8d399 661
samux 2:27a7e7f8d399 662 else {
samux 2:27a7e7f8d399 663 return (-1); // something isnt configured right
samux 2:27a7e7f8d399 664 }
samux 2:27a7e7f8d399 665 }
samux 2:27a7e7f8d399 666
samux 2:27a7e7f8d399 667
samux 2:27a7e7f8d399 668
samux 2:27a7e7f8d399 669
samux 2:27a7e7f8d399 670
samux 2:27a7e7f8d399 671 /*
samux 2:27a7e7f8d399 672 * Write the buffer to the numbered block
samux 2:27a7e7f8d399 673 */
samux 2:27a7e7f8d399 674
samux 2:27a7e7f8d399 675 int AT45::blockwrite(char* data, int block) {
samux 2:27a7e7f8d399 676
samux 2:27a7e7f8d399 677 // For 256 byte pages, we overwrite two pages
samux 2:27a7e7f8d399 678 if((_pagesize == 256) || (_pagesize == 264)) {
samux 2:27a7e7f8d399 679
samux 2:27a7e7f8d399 680 // fill the first buffer with the first half of the block
samux 2:27a7e7f8d399 681 // do this directly, for better performance
samux 2:27a7e7f8d399 682 _select();
samux 2:27a7e7f8d399 683 _spi.write(0x84); // writing to buffer #1
samux 2:27a7e7f8d399 684 _sendaddr (0); // we are writing to the entire buffer
samux 2:27a7e7f8d399 685
samux 2:27a7e7f8d399 686 for(int i=0;i<256;i++) {
samux 2:27a7e7f8d399 687 _spi.write (data[i]);
samux 2:27a7e7f8d399 688 }
samux 2:27a7e7f8d399 689 _deselect();
samux 2:27a7e7f8d399 690
samux 2:27a7e7f8d399 691 _flashwrite(1,(block*512));
samux 2:27a7e7f8d399 692
samux 2:27a7e7f8d399 693 // fill the buffer with the second half of the block
samux 2:27a7e7f8d399 694 // do this directly, for better performance
samux 2:27a7e7f8d399 695 _select();
samux 2:27a7e7f8d399 696 _spi.write(0x84); // writing to buffer #1
samux 2:27a7e7f8d399 697 _sendaddr (0); // we are writing to the entire buffer
samux 2:27a7e7f8d399 698
samux 2:27a7e7f8d399 699 for(int i=0;i<256;i++) {
samux 2:27a7e7f8d399 700 _spi.write (data[256+i]);
samux 2:27a7e7f8d399 701 }
samux 2:27a7e7f8d399 702 _deselect();
samux 2:27a7e7f8d399 703
samux 2:27a7e7f8d399 704 _flashwrite(1,((block*512)+256));
samux 2:27a7e7f8d399 705 }
samux 2:27a7e7f8d399 706
samux 2:27a7e7f8d399 707
samux 2:27a7e7f8d399 708 // For 512 byte pages, we overwrite a single page
samux 2:27a7e7f8d399 709 else if((_pagesize == 512) || (_pagesize == 528)) {
samux 2:27a7e7f8d399 710
samux 2:27a7e7f8d399 711 // fill the first buffer with the block data
samux 2:27a7e7f8d399 712 // do this directly, for better performance
samux 2:27a7e7f8d399 713 _select();
samux 2:27a7e7f8d399 714 _spi.write(0x84); // writing to buffer #1
samux 2:27a7e7f8d399 715 _sendaddr (0); // we are writing to the entire buffer
samux 2:27a7e7f8d399 716
samux 2:27a7e7f8d399 717 for(int i=0;i<512;i++) {
samux 2:27a7e7f8d399 718 _spi.write (data[i]);
samux 2:27a7e7f8d399 719 }
samux 2:27a7e7f8d399 720 _deselect();
samux 2:27a7e7f8d399 721
samux 2:27a7e7f8d399 722 _pollbusy(); // make sure the Flahs isnt busy
samux 2:27a7e7f8d399 723
samux 2:27a7e7f8d399 724 // issue command to write buffer 1 to the appropraite flash page
samux 2:27a7e7f8d399 725 _select();
samux 2:27a7e7f8d399 726 _spi.write (0x83);
samux 2:27a7e7f8d399 727 _sendaddr (_getpaddr(block * 512));
samux 2:27a7e7f8d399 728 _deselect();
samux 2:27a7e7f8d399 729 _pollbusy(); // make sure the Flahs isnt busy
samux 2:27a7e7f8d399 730 }
samux 2:27a7e7f8d399 731
samux 2:27a7e7f8d399 732
samux 2:27a7e7f8d399 733 // For 1024 byte pages, we do a read modify write
samux 2:27a7e7f8d399 734 // must make sure we overwrite the right half of the page!
samux 2:27a7e7f8d399 735 else if((_pagesize == 1024) || (_pagesize == 1056)) {
samux 2:27a7e7f8d399 736
samux 2:27a7e7f8d399 737 _pollbusy(); // make sure the flash isnt busy
samux 2:27a7e7f8d399 738
samux 2:27a7e7f8d399 739 int address = _getpaddr(block*512);
samux 2:27a7e7f8d399 740
samux 2:27a7e7f8d399 741 // Read the page into sram
samux 2:27a7e7f8d399 742 _flashread(1,address);
samux 2:27a7e7f8d399 743
samux 2:27a7e7f8d399 744 // wait for this operation to complete
samux 2:27a7e7f8d399 745 _pollbusy();
samux 2:27a7e7f8d399 746
samux 2:27a7e7f8d399 747 // Overwrite the appropriate half
samux 2:27a7e7f8d399 748 // do this directly, for better performance
samux 2:27a7e7f8d399 749 _select();
samux 2:27a7e7f8d399 750 _spi.write(0x84); // writing to buffer #1
samux 2:27a7e7f8d399 751
samux 2:27a7e7f8d399 752 if(block%2) { // this is an odd block number, overwrite second half of buffer
samux 2:27a7e7f8d399 753 _sendaddr (0x200); // we are writing to the entire buffer
samux 2:27a7e7f8d399 754 }
samux 2:27a7e7f8d399 755 else { // this is an even block, overwrite the first half
samux 2:27a7e7f8d399 756 _sendaddr (0x0); // we are writing to the entire buffer
samux 2:27a7e7f8d399 757 }
samux 2:27a7e7f8d399 758
samux 2:27a7e7f8d399 759 for(int i=0;i<512;i++) {
samux 2:27a7e7f8d399 760 _spi.write (data[i]);
samux 2:27a7e7f8d399 761 }
samux 2:27a7e7f8d399 762 _deselect();
samux 2:27a7e7f8d399 763
samux 2:27a7e7f8d399 764 // Write the page back
samux 2:27a7e7f8d399 765 _pollbusy();
samux 2:27a7e7f8d399 766 _flashwrite(1,address);
samux 2:27a7e7f8d399 767
samux 2:27a7e7f8d399 768 }
samux 2:27a7e7f8d399 769
samux 2:27a7e7f8d399 770
samux 2:27a7e7f8d399 771 // Something has gone wrong
samux 2:27a7e7f8d399 772 else {
samux 2:27a7e7f8d399 773 return (-1);
samux 2:27a7e7f8d399 774 }
samux 2:27a7e7f8d399 775
samux 2:27a7e7f8d399 776 return (0);
samux 2:27a7e7f8d399 777 }
samux 2:27a7e7f8d399 778
samux 2:27a7e7f8d399 779
samux 2:27a7e7f8d399 780 /*
samux 2:27a7e7f8d399 781 * Return the number of 512 byte blocks in this device
samux 2:27a7e7f8d399 782 */
samux 2:27a7e7f8d399 783 void blockerase (int block) {}
samux 2:27a7e7f8d399 784
samux 2:27a7e7f8d399 785
samux 2:27a7e7f8d399 786
samux 2:27a7e7f8d399 787 /*
samux 2:27a7e7f8d399 788 * returns the number of buffer to use
samux 2:27a7e7f8d399 789 * If page is already open, use it
samux 2:27a7e7f8d399 790 * If one of the buffers is unused, use it
samux 2:27a7e7f8d399 791 * else evict the least recently used.
samux 2:27a7e7f8d399 792
samux 2:27a7e7f8d399 793 */
samux 2:27a7e7f8d399 794 int _allocatebuffer (int address) {
samux 2:27a7e7f8d399 795
samux 2:27a7e7f8d399 796 int buf = 0;
samux 2:27a7e7f8d399 797 // is page already open in buffer 1?
samux 2:27a7e7f8d399 798 // is page already open in buffer 2
samux 2:27a7e7f8d399 799 // is buffer 1 unusued?
samux 2:27a7e7f8d399 800 // is buffer 2 unused
samux 2:27a7e7f8d399 801 // evict LRU
samux 2:27a7e7f8d399 802
samux 2:27a7e7f8d399 803 return (buf);
samux 2:27a7e7f8d399 804
samux 2:27a7e7f8d399 805 }
samux 2:27a7e7f8d399 806
samux 2:27a7e7f8d399 807
samux 2:27a7e7f8d399 808
samux 2:27a7e7f8d399 809 /*
samux 2:27a7e7f8d399 810 * write the buffer back to flash
samux 2:27a7e7f8d399 811 * set it as LRU
samux 2:27a7e7f8d399 812 * make _bufferNaddress = -1
samux 2:27a7e7f8d399 813 */
samux 2:27a7e7f8d399 814 void _flushbuffer (int buffer) {
samux 2:27a7e7f8d399 815
samux 2:27a7e7f8d399 816 // is page already open in buffer 1?
samux 2:27a7e7f8d399 817 // is page already open in buffer 2
samux 2:27a7e7f8d399 818 // is buffer 1 unusued?
samux 2:27a7e7f8d399 819 // is buffer 2 unused
samux 2:27a7e7f8d399 820 // evict LRU
samux 2:27a7e7f8d399 821
samux 2:27a7e7f8d399 822 }
samux 2:27a7e7f8d399 823
samux 2:27a7e7f8d399 824
samux 2:27a7e7f8d399 825
samux 2:27a7e7f8d399 826
samux 2:27a7e7f8d399 827
samux 2:27a7e7f8d399 828
samux 2:27a7e7f8d399 829