Driver for SST 64Mbit flash (8Mbyte) model 25VF064C including higher level methods for rewrite and buffered read/write to help optimize I/O. Can also work with other 25 series flash and eeprom devices, requiring minor revisions for their capabilities.

Dependencies:   SPIDebug

Committer:
davervw
Date:
Tue Apr 10 07:17:51 2012 +0000
Revision:
0:332d4b991d16
Child:
2:33d8a5ea4a80
initial revision, tested

Who changed what in which revision?

UserRevisionLine numberNew contents of line
davervw 0:332d4b991d16 1 ///////////////////////////////////////////////////////////////////////////////
davervw 0:332d4b991d16 2 // SST25VF064C.cpp - EEPROM driver
davervw 0:332d4b991d16 3 //
davervw 0:332d4b991d16 4 // COPYRIGHT (c) 2012 by David Van Wagner
davervw 0:332d4b991d16 5 //
davervw 0:332d4b991d16 6 // dave@vanwagner.org
davervw 0:332d4b991d16 7 // http://techwithdave.blogspot.com
davervw 0:332d4b991d16 8 //
davervw 0:332d4b991d16 9 // License: Creative Commons Attribution-ShareAlike 3.0 Unported License
davervw 0:332d4b991d16 10 // http://creativecommons.org/licenses/by-sa/3.0/
davervw 0:332d4b991d16 11 ///////////////////////////////////////////////////////////////////////////////
davervw 0:332d4b991d16 12
davervw 0:332d4b991d16 13 #include "SST25VF064C.h"
davervw 0:332d4b991d16 14 //#include <assert.h>
davervw 0:332d4b991d16 15
davervw 0:332d4b991d16 16 SST25VF064C::uint8 SST25VF064C::SID_buffer[SID_LEN];
davervw 0:332d4b991d16 17 SST25VF064C::uint8 SST25VF064C::sector_buffer[SECTOR_LEN];
davervw 0:332d4b991d16 18 SST25VF064C::int32 SST25VF064C::buffered_addr;
davervw 0:332d4b991d16 19 bool SST25VF064C::buffered_erased;
davervw 0:332d4b991d16 20
davervw 0:332d4b991d16 21 SST25VF064C::SST25VF064C(PinName mosi, PinName miso, PinName sclk, PinName cs, int frequency)
davervw 0:332d4b991d16 22 {
davervw 0:332d4b991d16 23 #ifdef SPIDEBUG
davervw 0:332d4b991d16 24 this->cs = new CSDebug(cs);
davervw 0:332d4b991d16 25 #else
davervw 0:332d4b991d16 26 this->cs = new DigitalOut(cs);
davervw 0:332d4b991d16 27 #endif
davervw 0:332d4b991d16 28 this->cs->write(true);
davervw 0:332d4b991d16 29 this->frequency = frequency;
davervw 0:332d4b991d16 30 #ifdef SPIDEBUG
davervw 0:332d4b991d16 31 spi = new SPIDebug(mosi, miso, sclk);
davervw 0:332d4b991d16 32 #else
davervw 0:332d4b991d16 33 spi = new SPI(mosi, miso, sclk);
davervw 0:332d4b991d16 34 #endif
davervw 0:332d4b991d16 35 spi->format(8, 0);
davervw 0:332d4b991d16 36 spi->frequency(frequency);
davervw 0:332d4b991d16 37 buffered_addr = -1;
davervw 0:332d4b991d16 38 buffered_erased = false;
davervw 0:332d4b991d16 39 //assert(Id() == 0x4bbf);
davervw 0:332d4b991d16 40 //assert(JEDECId() == 0xbf254b);
davervw 0:332d4b991d16 41 }
davervw 0:332d4b991d16 42
davervw 0:332d4b991d16 43 SST25VF064C::~SST25VF064C()
davervw 0:332d4b991d16 44 {
davervw 0:332d4b991d16 45 delete spi;
davervw 0:332d4b991d16 46 delete cs;
davervw 0:332d4b991d16 47 }
davervw 0:332d4b991d16 48
davervw 0:332d4b991d16 49 SST25VF064C::uint16 SST25VF064C::Id()
davervw 0:332d4b991d16 50 {
davervw 0:332d4b991d16 51 cs->write(0);
davervw 0:332d4b991d16 52 spi->write(0xab);
davervw 0:332d4b991d16 53 spi->write(0);
davervw 0:332d4b991d16 54 spi->write(0);
davervw 0:332d4b991d16 55 spi->write(0);
davervw 0:332d4b991d16 56 unsigned id = (spi->write(0) << 8) | spi->write(0);
davervw 0:332d4b991d16 57 cs->write(1);
davervw 0:332d4b991d16 58 return id;
davervw 0:332d4b991d16 59 }
davervw 0:332d4b991d16 60
davervw 0:332d4b991d16 61 SST25VF064C::uint32 SST25VF064C::JEDECId()
davervw 0:332d4b991d16 62 {
davervw 0:332d4b991d16 63 cs->write(0);
davervw 0:332d4b991d16 64 spi->write(0x9f);
davervw 0:332d4b991d16 65 unsigned id = (spi->write(0) << 16) | (spi->write(0) << 8) | spi->write(0);
davervw 0:332d4b991d16 66 cs->write(1);
davervw 0:332d4b991d16 67 return id;
davervw 0:332d4b991d16 68 }
davervw 0:332d4b991d16 69
davervw 0:332d4b991d16 70 SST25VF064C::uint8* SST25VF064C::SID()
davervw 0:332d4b991d16 71 {
davervw 0:332d4b991d16 72 cs->write(0);
davervw 0:332d4b991d16 73 spi->write(0x88);
davervw 0:332d4b991d16 74 spi->write(0); // address
davervw 0:332d4b991d16 75 spi->write(0); // dummy
davervw 0:332d4b991d16 76 for (int i=0; i<SID_LEN; ++i)
davervw 0:332d4b991d16 77 SID_buffer[i] = spi->write(0);
davervw 0:332d4b991d16 78 cs->write(1);
davervw 0:332d4b991d16 79 return SID_buffer;
davervw 0:332d4b991d16 80 }
davervw 0:332d4b991d16 81
davervw 0:332d4b991d16 82 // Read Status Register
davervw 0:332d4b991d16 83 // bit 0 BUSY 1=Write in progress
davervw 0:332d4b991d16 84 // bit 1 WEL 1=Write Enabled
davervw 0:332d4b991d16 85 // bit 2 BP0 block write protection
davervw 0:332d4b991d16 86 // bit 3 BP1 block write protection
davervw 0:332d4b991d16 87 // bit 4 BP2 block write protection
davervw 0:332d4b991d16 88 // bit 5 BP3 block write protection
davervw 0:332d4b991d16 89 // bit 6 SEC 1=Security ID space locked
davervw 0:332d4b991d16 90 // bit 7 BPL 1=BP0..BP3 are read-only, 0=r/w
davervw 0:332d4b991d16 91 SST25VF064C::uint8 SST25VF064C::RDSR()
davervw 0:332d4b991d16 92 {
davervw 0:332d4b991d16 93 cs->write(0);
davervw 0:332d4b991d16 94 spi->write(0x05);
davervw 0:332d4b991d16 95 uint8 status = spi->write(0);
davervw 0:332d4b991d16 96 cs->write(1);
davervw 0:332d4b991d16 97 return status;
davervw 0:332d4b991d16 98 }
davervw 0:332d4b991d16 99
davervw 0:332d4b991d16 100 // Enable Write Status Register
davervw 0:332d4b991d16 101 void SST25VF064C::EWSR()
davervw 0:332d4b991d16 102 {
davervw 0:332d4b991d16 103 cs->write(0);
davervw 0:332d4b991d16 104 spi->write(0x50);
davervw 0:332d4b991d16 105 cs->write(1);
davervw 0:332d4b991d16 106 }
davervw 0:332d4b991d16 107
davervw 0:332d4b991d16 108 // Write Status Register
davervw 0:332d4b991d16 109 void SST25VF064C::WRSR(SST25VF064C::uint8 status)
davervw 0:332d4b991d16 110 {
davervw 0:332d4b991d16 111 cs->write(0);
davervw 0:332d4b991d16 112 spi->write(0x01);
davervw 0:332d4b991d16 113 spi->write(status);
davervw 0:332d4b991d16 114 cs->write(1);
davervw 0:332d4b991d16 115 }
davervw 0:332d4b991d16 116
davervw 0:332d4b991d16 117 // Write Enable
davervw 0:332d4b991d16 118 void SST25VF064C::WREN()
davervw 0:332d4b991d16 119 {
davervw 0:332d4b991d16 120 cs->write(0);
davervw 0:332d4b991d16 121 spi->write(0x06);
davervw 0:332d4b991d16 122 cs->write(1);
davervw 0:332d4b991d16 123 }
davervw 0:332d4b991d16 124
davervw 0:332d4b991d16 125 // Write Disable
davervw 0:332d4b991d16 126 void SST25VF064C::WRDI()
davervw 0:332d4b991d16 127 {
davervw 0:332d4b991d16 128 cs->write(0);
davervw 0:332d4b991d16 129 spi->write(0x04);
davervw 0:332d4b991d16 130 cs->write(1);
davervw 0:332d4b991d16 131 }
davervw 0:332d4b991d16 132
davervw 0:332d4b991d16 133 bool SST25VF064C::BUSY()
davervw 0:332d4b991d16 134 {
davervw 0:332d4b991d16 135 return (RDSR() & 0x01) != 0;
davervw 0:332d4b991d16 136 }
davervw 0:332d4b991d16 137
davervw 0:332d4b991d16 138 bool SST25VF064C::WEL()
davervw 0:332d4b991d16 139 {
davervw 0:332d4b991d16 140 return (RDSR() & 0x02) != 0;
davervw 0:332d4b991d16 141 }
davervw 0:332d4b991d16 142
davervw 0:332d4b991d16 143 SST25VF064C::uint8 SST25VF064C::BP()
davervw 0:332d4b991d16 144 {
davervw 0:332d4b991d16 145 return (RDSR() >> 2) & 0xF;
davervw 0:332d4b991d16 146 }
davervw 0:332d4b991d16 147
davervw 0:332d4b991d16 148 bool SST25VF064C::SEC()
davervw 0:332d4b991d16 149 {
davervw 0:332d4b991d16 150 return (RDSR() & 0x40) != 0;
davervw 0:332d4b991d16 151 }
davervw 0:332d4b991d16 152
davervw 0:332d4b991d16 153 bool SST25VF064C::BPL()
davervw 0:332d4b991d16 154 {
davervw 0:332d4b991d16 155 return (RDSR() & 0x80) != 0;
davervw 0:332d4b991d16 156 }
davervw 0:332d4b991d16 157
davervw 0:332d4b991d16 158 void SST25VF064C::wait_while_busy()
davervw 0:332d4b991d16 159 {
davervw 0:332d4b991d16 160 while (BUSY())
davervw 0:332d4b991d16 161 ;
davervw 0:332d4b991d16 162 }
davervw 0:332d4b991d16 163
davervw 0:332d4b991d16 164 SST25VF064C::uint8 SST25VF064C::read(SST25VF064C::int32 addr)
davervw 0:332d4b991d16 165 {
davervw 0:332d4b991d16 166 cs->write(0);
davervw 0:332d4b991d16 167 spi->write(0x03);
davervw 0:332d4b991d16 168 spi->write((addr >> 16) & 0xff);
davervw 0:332d4b991d16 169 spi->write((addr >> 8) & 0xff);
davervw 0:332d4b991d16 170 spi->write(addr & 0xff);
davervw 0:332d4b991d16 171 uint8 data = spi->write(0);
davervw 0:332d4b991d16 172 cs->write(1);
davervw 0:332d4b991d16 173 return data;
davervw 0:332d4b991d16 174 }
davervw 0:332d4b991d16 175
davervw 0:332d4b991d16 176 bool SST25VF064C::read(SST25VF064C::int32 addr, SST25VF064C::uint8* dst, SST25VF064C::int32 len)
davervw 0:332d4b991d16 177 {
davervw 0:332d4b991d16 178 if (addr < 0 || addr >= MAX_ADDR || dst == 0 || len < 1 || addr+len > MAX_ADDR)
davervw 0:332d4b991d16 179 return false;
davervw 0:332d4b991d16 180
davervw 0:332d4b991d16 181 cs->write(0);
davervw 0:332d4b991d16 182 spi->write(0x03);
davervw 0:332d4b991d16 183 spi->write((addr >> 16) & 0xff);
davervw 0:332d4b991d16 184 spi->write((addr >> 8) & 0xff);
davervw 0:332d4b991d16 185 spi->write(addr & 0xff);
davervw 0:332d4b991d16 186 for (int32 i=0; i<len; ++i)
davervw 0:332d4b991d16 187 dst[i] = spi->write(0);
davervw 0:332d4b991d16 188 cs->write(1);
davervw 0:332d4b991d16 189
davervw 0:332d4b991d16 190 return true;
davervw 0:332d4b991d16 191 }
davervw 0:332d4b991d16 192
davervw 0:332d4b991d16 193 void SST25VF064C::hsread(SST25VF064C::int32 addr, SST25VF064C::uint8* dst, SST25VF064C::int32 len, int frequency)
davervw 0:332d4b991d16 194 {
davervw 0:332d4b991d16 195 int save_frequency = this->frequency;
davervw 0:332d4b991d16 196 spi->frequency(frequency);
davervw 0:332d4b991d16 197 cs->write(0);
davervw 0:332d4b991d16 198 spi->write(0x0B);
davervw 0:332d4b991d16 199 spi->write((addr >> 16) & 0xff);
davervw 0:332d4b991d16 200 spi->write((addr >> 8) & 0xff);
davervw 0:332d4b991d16 201 spi->write(addr & 0xff);
davervw 0:332d4b991d16 202 spi->write(0); // dummy
davervw 0:332d4b991d16 203 for (int32 i=0; i<len; ++i)
davervw 0:332d4b991d16 204 dst[i] = spi->write(0);
davervw 0:332d4b991d16 205 cs->write(1);
davervw 0:332d4b991d16 206 spi->frequency(save_frequency);
davervw 0:332d4b991d16 207 }
davervw 0:332d4b991d16 208
davervw 0:332d4b991d16 209 void SST25VF064C::sector_erase_4k(SST25VF064C::int32 addr)
davervw 0:332d4b991d16 210 {
davervw 0:332d4b991d16 211 cs->write(0);
davervw 0:332d4b991d16 212 spi->write(0x20);
davervw 0:332d4b991d16 213 spi->write((uint8)(addr >> 16));
davervw 0:332d4b991d16 214 spi->write((uint8)(addr >> 8));
davervw 0:332d4b991d16 215 spi->write((uint8)addr);
davervw 0:332d4b991d16 216 cs->write(1);
davervw 0:332d4b991d16 217 wait_while_busy();
davervw 0:332d4b991d16 218 }
davervw 0:332d4b991d16 219
davervw 0:332d4b991d16 220 void SST25VF064C::block_erase_32k(SST25VF064C::int32 addr)
davervw 0:332d4b991d16 221 {
davervw 0:332d4b991d16 222 cs->write(0);
davervw 0:332d4b991d16 223 spi->write(0x52);
davervw 0:332d4b991d16 224 spi->write((uint8)(addr >> 16));
davervw 0:332d4b991d16 225 spi->write((uint8)(addr >> 8));
davervw 0:332d4b991d16 226 spi->write((uint8)addr);
davervw 0:332d4b991d16 227 cs->write(1);
davervw 0:332d4b991d16 228 wait_while_busy();
davervw 0:332d4b991d16 229 }
davervw 0:332d4b991d16 230
davervw 0:332d4b991d16 231 void SST25VF064C::block_erase_64k(SST25VF064C::int32 addr)
davervw 0:332d4b991d16 232 {
davervw 0:332d4b991d16 233 cs->write(0);
davervw 0:332d4b991d16 234 spi->write(0xd8);
davervw 0:332d4b991d16 235 spi->write((uint8)(addr >> 16));
davervw 0:332d4b991d16 236 spi->write((uint8)(addr >> 8));
davervw 0:332d4b991d16 237 spi->write((uint8)addr);
davervw 0:332d4b991d16 238 cs->write(1);
davervw 0:332d4b991d16 239 wait_while_busy();
davervw 0:332d4b991d16 240 }
davervw 0:332d4b991d16 241
davervw 0:332d4b991d16 242 void SST25VF064C::chip_erase()
davervw 0:332d4b991d16 243 {
davervw 0:332d4b991d16 244 cs->write(0);
davervw 0:332d4b991d16 245 spi->write(0x60);
davervw 0:332d4b991d16 246 cs->write(1);
davervw 0:332d4b991d16 247 wait_while_busy();
davervw 0:332d4b991d16 248 }
davervw 0:332d4b991d16 249
davervw 0:332d4b991d16 250 bool SST25VF064C::page_program(SST25VF064C::int32 addr, SST25VF064C::uint8* write_buffer, short len)
davervw 0:332d4b991d16 251 {
davervw 0:332d4b991d16 252 // no point in writing FF as an empty sector already has those
davervw 0:332d4b991d16 253 // (and if not empty, write won't succeed)
davervw 0:332d4b991d16 254 bool skipped = false;
davervw 0:332d4b991d16 255 while (len > 0 && *write_buffer == 0xFF)
davervw 0:332d4b991d16 256 {
davervw 0:332d4b991d16 257 ++write_buffer;
davervw 0:332d4b991d16 258 --len;
davervw 0:332d4b991d16 259 ++addr;
davervw 0:332d4b991d16 260 skipped = true;
davervw 0:332d4b991d16 261 }
davervw 0:332d4b991d16 262 if (len == 0 && skipped)
davervw 0:332d4b991d16 263 return true; // special case when succeeds when nothing to do
davervw 0:332d4b991d16 264
davervw 0:332d4b991d16 265 if (len < 1 || len > 256)
davervw 0:332d4b991d16 266 return false;
davervw 0:332d4b991d16 267
davervw 0:332d4b991d16 268 // write enable
davervw 0:332d4b991d16 269 WREN();
davervw 0:332d4b991d16 270
davervw 0:332d4b991d16 271 cs->write(0);
davervw 0:332d4b991d16 272 spi->write(0x02);
davervw 0:332d4b991d16 273 spi->write((uint8)(addr >> 16));
davervw 0:332d4b991d16 274 spi->write((uint8)(addr >> 8));
davervw 0:332d4b991d16 275 spi->write((uint8)addr);
davervw 0:332d4b991d16 276 for (short i=0; i<len; ++i)
davervw 0:332d4b991d16 277 spi->write(write_buffer[i]);
davervw 0:332d4b991d16 278 cs->write(1);
davervw 0:332d4b991d16 279 wait_while_busy();
davervw 0:332d4b991d16 280
davervw 0:332d4b991d16 281 return true;
davervw 0:332d4b991d16 282 }
davervw 0:332d4b991d16 283
davervw 0:332d4b991d16 284 bool SST25VF064C::write(SST25VF064C::int32 addr, SST25VF064C::uint8* write_buffer, SST25VF064C::int32 len)
davervw 0:332d4b991d16 285 {
davervw 0:332d4b991d16 286 if (len < 0 || addr < 0 || addr > MAX_ADDR || (addr+len > MAX_ADDR) || (addr+len < 0))
davervw 0:332d4b991d16 287 return false;
davervw 0:332d4b991d16 288
davervw 0:332d4b991d16 289 if (len == 0)
davervw 0:332d4b991d16 290 return true; // done!
davervw 0:332d4b991d16 291
davervw 0:332d4b991d16 292 // calculate first page size based on address and length
davervw 0:332d4b991d16 293 int32 page_len = PAGE_LEN-(addr & (PAGE_LEN-1)); // remaining space in page
davervw 0:332d4b991d16 294
davervw 0:332d4b991d16 295 while (len > 0)
davervw 0:332d4b991d16 296 {
davervw 0:332d4b991d16 297 if (page_len > len)
davervw 0:332d4b991d16 298 page_len = len;
davervw 0:332d4b991d16 299
davervw 0:332d4b991d16 300 page_program(addr, write_buffer, page_len);
davervw 0:332d4b991d16 301
davervw 0:332d4b991d16 302 addr += page_len;
davervw 0:332d4b991d16 303 write_buffer += page_len;
davervw 0:332d4b991d16 304 len -= page_len;
davervw 0:332d4b991d16 305 page_len = PAGE_LEN;
davervw 0:332d4b991d16 306 }
davervw 0:332d4b991d16 307
davervw 0:332d4b991d16 308 return true;
davervw 0:332d4b991d16 309 }
davervw 0:332d4b991d16 310
davervw 0:332d4b991d16 311 bool SST25VF064C::rewrite(SST25VF064C::int32 addr, SST25VF064C::uint8* write_buffer, SST25VF064C::int32 len)
davervw 0:332d4b991d16 312 {
davervw 0:332d4b991d16 313 // validate parameters
davervw 0:332d4b991d16 314 if (len < 0 || addr < 0 || addr > MAX_ADDR || (addr+len > MAX_ADDR) || (addr+len < 0))
davervw 0:332d4b991d16 315 return false;
davervw 0:332d4b991d16 316
davervw 0:332d4b991d16 317 // are we done before we've started?
davervw 0:332d4b991d16 318 if (len == 0)
davervw 0:332d4b991d16 319 return true; // done!
davervw 0:332d4b991d16 320
davervw 0:332d4b991d16 321 // calculate first sector size based on address and length
davervw 0:332d4b991d16 322 int32 sector_len = SECTOR_LEN-(addr & (SECTOR_LEN-1)); // remaining space in sector
davervw 0:332d4b991d16 323
davervw 0:332d4b991d16 324 while (len > 0)
davervw 0:332d4b991d16 325 {
davervw 0:332d4b991d16 326 // adjust if buffer than sector size
davervw 0:332d4b991d16 327 if (sector_len > len)
davervw 0:332d4b991d16 328 sector_len = len;
davervw 0:332d4b991d16 329
davervw 0:332d4b991d16 330 // read existing data into entire sector buffer
davervw 0:332d4b991d16 331 read(addr & (MAX_ADDR ^ (SECTOR_LEN-1)), sector_buffer, SECTOR_LEN);
davervw 0:332d4b991d16 332
davervw 0:332d4b991d16 333 // overwrite with requested data at proper offset
davervw 0:332d4b991d16 334 memcpy(sector_buffer + (addr & (SECTOR_LEN-1)), write_buffer, sector_len);
davervw 0:332d4b991d16 335
davervw 0:332d4b991d16 336 // reset to beginning of sector
davervw 0:332d4b991d16 337 addr = addr ^ (addr & (SECTOR_LEN-1));
davervw 0:332d4b991d16 338
davervw 0:332d4b991d16 339 // erase sector
davervw 0:332d4b991d16 340 WREN();
davervw 0:332d4b991d16 341 sector_erase_4k(addr);
davervw 0:332d4b991d16 342
davervw 0:332d4b991d16 343 // rewrite the sector
davervw 0:332d4b991d16 344 uint8 *p = sector_buffer;
davervw 0:332d4b991d16 345 int sectors_in_page = SECTOR_LEN/PAGE_LEN;
davervw 0:332d4b991d16 346 for (int i=0; i<sectors_in_page; ++i)
davervw 0:332d4b991d16 347 {
davervw 0:332d4b991d16 348 page_program(addr, p, PAGE_LEN);
davervw 0:332d4b991d16 349 addr += PAGE_LEN;
davervw 0:332d4b991d16 350 p += PAGE_LEN;
davervw 0:332d4b991d16 351 }
davervw 0:332d4b991d16 352
davervw 0:332d4b991d16 353 // adjust where we are, what left to do
davervw 0:332d4b991d16 354 write_buffer += sector_len;
davervw 0:332d4b991d16 355 len -= sector_len;
davervw 0:332d4b991d16 356 sector_len = SECTOR_LEN;
davervw 0:332d4b991d16 357 }
davervw 0:332d4b991d16 358
davervw 0:332d4b991d16 359 wait_while_busy();
davervw 0:332d4b991d16 360
davervw 0:332d4b991d16 361 return true;
davervw 0:332d4b991d16 362 }
davervw 0:332d4b991d16 363
davervw 0:332d4b991d16 364 bool SST25VF064C::buffered_write(SST25VF064C::uint8 data)
davervw 0:332d4b991d16 365 {
davervw 0:332d4b991d16 366 int32& addr = buffered_addr;
davervw 0:332d4b991d16 367
davervw 0:332d4b991d16 368 if (addr < 0 || addr > MAX_ADDR)
davervw 0:332d4b991d16 369 return false;
davervw 0:332d4b991d16 370
davervw 0:332d4b991d16 371 bool result = true;
davervw 0:332d4b991d16 372
davervw 0:332d4b991d16 373 // if at sector boundary
davervw 0:332d4b991d16 374 if ((addr & (SECTOR_LEN-1)) == 0 || !buffered_erased)
davervw 0:332d4b991d16 375 {
davervw 0:332d4b991d16 376 WREN();
davervw 0:332d4b991d16 377 sector_erase_4k(addr ^ (addr & (SECTOR_LEN-1)));
davervw 0:332d4b991d16 378 buffered_erased = true;
davervw 0:332d4b991d16 379 }
davervw 0:332d4b991d16 380
davervw 0:332d4b991d16 381 sector_buffer[addr & (SECTOR_LEN-1)] = data;
davervw 0:332d4b991d16 382
davervw 0:332d4b991d16 383 ++addr;
davervw 0:332d4b991d16 384
davervw 0:332d4b991d16 385 // if at sector boundary
davervw 0:332d4b991d16 386 if ((addr & (SECTOR_LEN-1)) == 0)
davervw 0:332d4b991d16 387 {
davervw 0:332d4b991d16 388 // write sector
davervw 0:332d4b991d16 389 result = write(addr-SECTOR_LEN, sector_buffer, SECTOR_LEN);
davervw 0:332d4b991d16 390 buffered_erased = false;
davervw 0:332d4b991d16 391
davervw 0:332d4b991d16 392 // read more
davervw 0:332d4b991d16 393 if (addr != MAX_ADDR)
davervw 0:332d4b991d16 394 result = result && read(addr, sector_buffer, SECTOR_LEN);
davervw 0:332d4b991d16 395 }
davervw 0:332d4b991d16 396
davervw 0:332d4b991d16 397 return result;
davervw 0:332d4b991d16 398 }
davervw 0:332d4b991d16 399
davervw 0:332d4b991d16 400 bool SST25VF064C::buffered_write(SST25VF064C::uint8* src, int len)
davervw 0:332d4b991d16 401 {
davervw 0:332d4b991d16 402 bool result = true;
davervw 0:332d4b991d16 403
davervw 0:332d4b991d16 404 while (result && len > 0)
davervw 0:332d4b991d16 405 {
davervw 0:332d4b991d16 406 result = buffered_write(*src);
davervw 0:332d4b991d16 407 --len;
davervw 0:332d4b991d16 408 ++src;
davervw 0:332d4b991d16 409 }
davervw 0:332d4b991d16 410
davervw 0:332d4b991d16 411 return result;
davervw 0:332d4b991d16 412 }
davervw 0:332d4b991d16 413
davervw 0:332d4b991d16 414 SST25VF064C::uint8 SST25VF064C::buffered_read()
davervw 0:332d4b991d16 415 {
davervw 0:332d4b991d16 416 int32& addr = buffered_addr;
davervw 0:332d4b991d16 417 if (addr < 0 || addr >= MAX_ADDR)
davervw 0:332d4b991d16 418 {
davervw 0:332d4b991d16 419 addr = -1;
davervw 0:332d4b991d16 420 return 0xff;
davervw 0:332d4b991d16 421 }
davervw 0:332d4b991d16 422 uint8 data = sector_buffer[addr & (SECTOR_LEN-1)];
davervw 0:332d4b991d16 423 ++addr;
davervw 0:332d4b991d16 424 if ((addr & (SECTOR_LEN-1)) == 0)
davervw 0:332d4b991d16 425 {
davervw 0:332d4b991d16 426 if (buffered_erased)
davervw 0:332d4b991d16 427 {
davervw 0:332d4b991d16 428 write(addr-SECTOR_LEN, sector_buffer, SECTOR_LEN);
davervw 0:332d4b991d16 429 buffered_erased = false;
davervw 0:332d4b991d16 430 }
davervw 0:332d4b991d16 431 if (addr == MAX_ADDR)
davervw 0:332d4b991d16 432 addr = -1;
davervw 0:332d4b991d16 433 else
davervw 0:332d4b991d16 434 read(addr, sector_buffer, SECTOR_LEN);
davervw 0:332d4b991d16 435 }
davervw 0:332d4b991d16 436 return data;
davervw 0:332d4b991d16 437 }
davervw 0:332d4b991d16 438
davervw 0:332d4b991d16 439 bool SST25VF064C::buffered_read(SST25VF064C::uint8* dest, int len)
davervw 0:332d4b991d16 440 {
davervw 0:332d4b991d16 441 while (len > 0)
davervw 0:332d4b991d16 442 {
davervw 0:332d4b991d16 443 if (buffered_addr < 0 || buffered_addr >= MAX_ADDR)
davervw 0:332d4b991d16 444 return false;
davervw 0:332d4b991d16 445
davervw 0:332d4b991d16 446 *dest = buffered_read();
davervw 0:332d4b991d16 447 --len;
davervw 0:332d4b991d16 448 ++dest;
davervw 0:332d4b991d16 449 }
davervw 0:332d4b991d16 450
davervw 0:332d4b991d16 451 return true;
davervw 0:332d4b991d16 452 }
davervw 0:332d4b991d16 453
davervw 0:332d4b991d16 454 void SST25VF064C::buffered_seek(SST25VF064C::int32 addr)
davervw 0:332d4b991d16 455 {
davervw 0:332d4b991d16 456 if (buffered_erased)
davervw 0:332d4b991d16 457 write(buffered_addr ^ (buffered_addr & (SECTOR_LEN-1)), sector_buffer, SECTOR_LEN);
davervw 0:332d4b991d16 458 if (addr < 0 || addr >= MAX_ADDR)
davervw 0:332d4b991d16 459 {
davervw 0:332d4b991d16 460 buffered_addr = -1;
davervw 0:332d4b991d16 461 buffered_erased = false;
davervw 0:332d4b991d16 462 }
davervw 0:332d4b991d16 463 else
davervw 0:332d4b991d16 464 {
davervw 0:332d4b991d16 465 read(addr ^ (addr & (SECTOR_LEN-1)), sector_buffer, SECTOR_LEN);
davervw 0:332d4b991d16 466 buffered_addr = addr;
davervw 0:332d4b991d16 467 buffered_erased = false;
davervw 0:332d4b991d16 468 }
davervw 0:332d4b991d16 469 }
davervw 0:332d4b991d16 470
davervw 0:332d4b991d16 471 void SST25VF064C::buffered_sync()
davervw 0:332d4b991d16 472 {
davervw 0:332d4b991d16 473 int32& addr = buffered_addr;
davervw 0:332d4b991d16 474
davervw 0:332d4b991d16 475 if (buffered_erased)
davervw 0:332d4b991d16 476 {
davervw 0:332d4b991d16 477 write(addr ^ (addr & (SECTOR_LEN-1)), sector_buffer, SECTOR_LEN);
davervw 0:332d4b991d16 478 buffered_erased = false;
davervw 0:332d4b991d16 479 }
davervw 0:332d4b991d16 480 }