11 #ifdef ARDUINO_ARCH_STM32F1
12 #include "flash_stm32.h"
19 #ifdef ARDUINO_ARCH_STM32F1
21 #define FlashPageSize 0x400
22 #define FlashStartAddress 0x0801fc00 // Page127
23 #elif defined(MCU_STM32F103C8)
24 #define FlashPageSize 0x400
25 #define FlashStartAddress 0x0800fc00 // Page63
27 #error Unknown CPU type
31 uint8_t data[FlashPageSize];
33 void eeprom_read_block(
void* buf,
const void* addr,
size_t size) {
34 uintptr_t offset = (uintptr_t)addr;
35 if( offset + size <
sizeof(data) ) {
36 memcpy(buf,&data[offset],size);
39 void eeprom_write_block(
const void* buf,
void* addr,
size_t size) {
40 uintptr_t offset = (uintptr_t)addr;
41 if( offset + size <
sizeof(data) ) {
42 memcpy(&data[offset],buf,size);
51 inline void memcpy(
void* dest,
const void* src,
size_t size) {
52 uint8_t* d = (uint8_t*)dest;
53 const uint8_t* s = (
const uint8_t*)src;
54 for(
size_t i=0; i<size; ++i ) {
59 void eeprom_read_block(
void* buf,
const void* addr,
size_t size) {
60 uintptr_t offset = (uintptr_t)addr;
61 if( offset + size <
sizeof(data) ) {
62 memcpy(buf,&data[offset],size);
65 void eeprom_write_block(
const void* buf,
void* addr,
size_t size) {
66 uintptr_t offset = (uintptr_t)addr;
67 if( offset + size <
sizeof(data) ) {
68 memcpy(&data[offset],buf,size);
75 #ifdef ARDUINO_ARCH_STM32F1
77 uint16_t* towrite = (uint16_t*)data;
78 uint16_t *toread = (uint16_t*)(uintptr_t)FlashStartAddress;
79 for(
size_t i=0; i<
sizeof(data)/2; ++i ) {
80 *(towrite + i) = *(toread + i);
90 #ifdef ARDUINO_ARCH_STM32F1
98 #ifdef ARDUINO_ARCH_STM32F1
101 FLASH_ErasePage(FlashStartAddress);
102 uint16_t* toread = (uint16_t*)data;
103 for(
size_t i=0; i<
sizeof(data)/2; ++i ) {
104 FLASH_ProgramHalfWord(FlashStartAddress+i+i,*(toread+i));
110 uint8_t getByte (uint16_t addr) {
112 eeprom_read_block(&b,(
void*)(uintptr_t)addr,1);
116 bool setByte (uint16_t addr, uint8_t d) {
118 eeprom_write_block(&b,(
void*)(uintptr_t)addr,1);
122 bool setData (uint16_t addr,uint8_t* buf,uint16_t size) {
123 eeprom_write_block(buf,(
void*)(uintptr_t)addr,size);
127 bool getData (uint16_t addr,uint8_t* buf,uint16_t size) {
128 eeprom_read_block(buf,(
const void*)(uintptr_t)addr,size);
132 bool clearData (uint16_t addr, uint16_t size) {
133 for( uint16_t i=0; i<size; ++i) {
141 #if defined(TwoWire_h) || defined(_WIRE_H_) || defined(_TWOWIRE_H_) || defined(_WIREBASE_H_)
143 #ifndef BUFFER_LENGTH
144 #ifdef TWI_BUFFER_SIZE // MightyCore
145 #define BUFFER_LENGTH TWI_BUFFER_SIZE
146 #else // fall back to default value
147 #define BUFFER_LENGTH 32
153 template <u
int8 ID,u
int16_t PAGES,u
int8_t PAGESIZE>
159 Wire.beginTransmission(ID);
162 return Wire.endTransmission() == 0;
166 return PAGES * PAGESIZE;
171 uint8 getByte (uint16_t addr) {
173 Wire.beginTransmission(ID);
174 Wire.write(addr >> 8);
175 Wire.write(addr & 0xff);
176 if( Wire.endTransmission() == 0 ) {
177 Wire.requestFrom(ID,(uint8_t)1);
183 bool setByte (uint16_t addr, uint8 d) {
185 Wire.beginTransmission(ID);
186 Wire.write(addr >> 8);
187 Wire.write(addr & 0xff);
189 success = Wire.endTransmission() == 0;
191 if( success ==
true ) {
192 success = waitComplete();
197 uint16_t calcBlockSize(uint16_t addr, uint16_t size) {
198 uint16_t block = PAGESIZE - (addr % PAGESIZE);
200 block = (BUFFER_LENGTH - 2) < block ? BUFFER_LENGTH - 2 : block;
201 return (size < block) ? size : block;
205 bool setData (uint16_t addr,uint8* buf,uint16_t size) {
208 while( success ==
true && size > 0 ) {
209 uint16_t towrite = calcBlockSize(addr, size);
211 Wire.beginTransmission(ID);
212 Wire.write(addr >> 8);
213 Wire.write(addr & 0xff);
215 while( done < towrite ) {
219 success = Wire.endTransmission() == 0;
221 if( success ==
true ) {
222 success = waitComplete();
225 DPRINTLN(F(
"ERROR EEPROM WRITE"));
233 bool getData (uint16_t addr,uint8* buf,uint16_t size) {
235 while( success ==
true && size > 0 ) {
236 uint16_t toread = calcBlockSize(addr, size);
238 Wire.beginTransmission(ID);
239 Wire.write(addr >> 8);
240 Wire.write(addr & 0xff);
241 success = Wire.endTransmission() == 0;
242 if( success ==
true ) {
243 Wire.requestFrom(ID,(uint8_t)toread);
245 while( done < toread ) {
247 *buf++ = (uint8_t)Wire.read();
256 bool clearData (uint16_t addr, uint16_t size) {
259 while( success ==
true && size > 0 ) {
260 uint16_t towrite = calcBlockSize(addr, size);
262 Wire.beginTransmission(ID);
263 Wire.write(addr >> 8);
264 Wire.write(addr & 0xff);
266 while( done < towrite ) {
270 success = Wire.endTransmission() == 0;
272 if( success ==
true ) {
273 success = waitComplete();
276 DPRINTLN(F(
"ERROR EEPROM CLEAR"));
285 bool waitComplete () {
287 for (uint8_t i=25; i; --i) {
289 if( present() ==
true ) {
293 DPRINTLN(F(
"ERROR EEPROM WAIT"));
299 template <u
int8_t ID,u
int16_t PAGES,u
int8_t PAGESIZE>
301 uint8_t pagecache[PAGESIZE];
314 if( pageaddr != 0xffff && dirty ==
true ) {
316 Base::setData(pageaddr, pagecache, PAGESIZE);
321 uint8_t* fillcache(uint16_t addr) {
322 uint16_t paddr = addr & ~(PAGESIZE-1);
323 if( pageaddr != paddr ) {
327 Base::getData(pageaddr,pagecache,PAGESIZE);
340 uint8_t getByte (uint16_t addr) {
342 return pagecache[addr - pageaddr];
345 bool setByte (uint16_t addr, uint8_t d) {
347 pagecache[addr - pageaddr] = d;
352 bool getData (uint16_t addr,uint8_t* buf,uint16_t size) {
354 return Base::getData(addr, buf, size);
357 bool setData (uint16_t addr,uint8_t* buf,uint16_t size) {
359 return Base::setData(addr, buf, size);
362 bool clearData (uint16_t addr, uint16_t size) {
364 return Base::clearData(addr, size);
376 template <
class DRIVER=InternalEprom>
382 bool setup (uint16_t checksum=0) {
383 bool firststart =
false;
385 DRIVER::getData(0x0,(uint8_t*)&mem,4);
386 uint32_t magic = 0xCAFE0000 | checksum;
389 DPRINT(F(
"Init Storage: "));
392 DRIVER::setData(0x0,(uint8_t*)&magic,4);
398 bool setBits (uint16_t addr, uint8_t bits) {
399 DRIVER::setByte(addr,DRIVER::getByte(addr) | bits);
403 bool clearBits (uint16_t addr, uint8_t bits) {
404 DRIVER::setByte(addr,DRIVER::getByte(addr) & ~bits);
408 bool setData (uint16_t addr,uint8_t* buf,uint16_t size) {
409 return DRIVER::setData(addr,buf,size);
413 bool setData (uint16_t addr,
const T& obj) {
414 return DRIVER::setData(addr,(uint8_t*)&obj,
sizeof(T));
417 bool getData (uint16_t addr,uint8_t* buf,uint16_t size) {
418 return DRIVER::getData(addr,buf,size);
422 bool getData (uint16_t addr,T* obj) {
423 return DRIVER::getData(addr,(uint8_t*)obj,
sizeof(T));
426 bool clearData (uint16_t addr, uint16_t size) {
427 return DRIVER::clearData(addr,size);
435 void dump (uint16_t start, uint16_t num) {
436 for( uint16_t i=0; i<num; ++i, ++start ) {
437 DHEX(DRIVER::getByte(start));
445 #ifndef STORAGEDRIVER
446 #define STORAGEDRIVER InternalEprom
449 extern void* __gb_store;
459 static inline Storage& storage () {
460 return *((
Storage*)__gb_store);
463 #define STORAGE_CFG_START 0x04
469 uint8_t checksum ()
const {
471 for( uint8_t i=0; i<size-1; ++i ) {
478 setByte(size-1,checksum());
481 bool valid ()
const {
482 return getByte(size-1) == checksum();
486 storage().clearData(STORAGE_CFG_START, size);
489 uint8_t getSize ()
const {
493 uint8_t getByte (uint8_t offset)
const {
494 return storage().getByte(STORAGE_CFG_START+offset);
497 void setByte(uint8_t offset,uint8_t data) {
498 storage().setByte(STORAGE_CFG_START+offset,data);
510 uint16_t getAddress ()
const {
514 uint16_t getSize ()
const {
515 return storage().size() - getAddress();
519 storage().clearData(getAddress(),getSize());
522 uint8_t getByte (uint16_t offset)
const {
523 return storage().getByte(getAddress()+offset);
526 void setByte(uint16_t offset,uint8_t data) {
527 storage().setByte(getAddress()+offset,data);
530 void setData (uint16_t offset,uint8_t* buf,uint16_t size) {
531 storage().setData(getAddress()+offset,buf,size);
534 void getData (uint16_t offset,uint8_t* buf,uint16_t size) {
535 storage().getData(getAddress()+offset,buf,size);
539 void setData (uint16_t offset,
const T& obj) {
540 setData(offset,(uint8_t*)&obj,
sizeof(T));
544 void getData (uint16_t offset,T* obj) {
545 getData(offset,(uint8_t*)obj,
sizeof(T));