/*****************************************\
* Flash-Speicher mit wahlfreiem Zugriff *
\*****************************************/
#ifndef _FLASH_RW_H_
#define _FLASH_RW_H_
/* Für ATtiny85: Die SELFPRGEN-Fuse muss gebrannt (=0) sein!
* ATtiny haben keinen Bootloader-Bereich! (Genauer: RWW-Sektion.)
* Daher blockiert das Flash-Schreiben immer die CPU.
*
* Eignet sich durchaus für eine Art Mini-Massenspeicher im AVR.
* Denn der Flash ist viel schneller beim Schreiben als der EEPROM.
* Bedenke, auch die Lunte in der Hand zu haben, den Kode zu überschreiben.
* Oder aber gezielt selbstmodifizierenden Kode zu schreiben.
*
* Beim Startup muss GPIOR0 Bit 6 gelöscht werden!!
* (Dies ist das Dirty-Flag.)
* Bei allen Routinen wird sei() vorausgesetzt.
* Die Routinen sind (erwartungsgemäß?) nicht multithread-sicher.
*/
#include <avr/pgmspace.h>
/* Der Zugriff erfolgt solange über einen (nur einen!) Hilfspuffer im RAM,
* bis ein anderer Sektor gelesen werden muss.
* Somit kann man kleine Datenportionen schreiben,
* ohne den Flash zu stark zu verbrauchen
* Besonders bei sequenziellem Zugriff.
┌───────┐
│Sektor3│ RAM
└───────┘
┌───────┬───────┬───────┬───────┬───────┬────\
│Sektor0│Sektor1│Sektor2│XXXXXXX│Sektor4│Sekt/ Flash
└───────┴───────┴───────┴───────┴───────┴────\
FlashPtr↑
* Man darf aber kein memcpy_P u.a. auf den infrage
* kommenden Flash-Bereich benutzen!
* Sondern muss flash_read() verwenden, es klammert den gerade ungültigen
* Flash-Bereich aus und liest aus dem Hilfspuffer.
* Oder man stellt mit flash_flush() sicher, dass der Flash ausgeschrieben ist.
*
* flash_write() kümmert sich automatisch um Pufferaktualisierungen
* und kann daher für einige Millisekunden blockieren.
* Es wird nichts unternommen, wenn sich nichts ändert!
* Alle Arten von Überlappungen und Grenzübergängen sind erlaubt.
*
* flash_flush() „leert“ den Puffer (wenn gefüllt, sonst passiert nichts),
* und blockiert in diesem Fall immer für ca. 7 ms.
*/
void flash_read(void *dst, PGM_VOID_P src, size_t len);
void flash_write(PGM_VOID_P dst, const void *src, size_t len);
void flash_flush(void);
/* Die lange Unterbrechungszeit verschlechtert die Impulslängenmessung.
* Da ohnehin kein Hardware-Capture zur Verfügung steht,
* sollte Timer1 den Wert von T0NT korrigieren,
* damit wenigstens die Differenzen stimmen.
* Daher wird von flash_write() bei Bedarf extern_flash_flush() aufgerufen.
* Jene Prozedur muss zumindest flash_flush() aufrufen.
*/
void extern_flash_flush(void);
/* Eine Aktualisierungsroutine für den EEPROM:
* Kann man immer wieder (gelegentlich) aufrufen,
* um persistende Daten, die als Kopie im RAM stehen,
* automatisch rückschreiben zu lassen.
* Etwa für USB-HID-Feature-Reports, die Einstellungen vornehmen.
* (Damit schafft man sich so etwas wie ein Stück ferroelektrischen RAM,
* der ordentlich adressierbar ist und schnell beim Schreiben ist.)
* Liefert die Stelle in <src>, die gerade gebrannt wird.
* NULL wenn alles gleich ist ODER gerade gebrannt wird.
* Diese Routine blockiert nicht, im Gegensatz zu eeprom_write_block().
*/
void*eeprom_update(void*dst, const void*src, size_t len);
#endif//_FLASH_RW_H_
Detected encoding: UTF-8 | 0
|