I am trying to write to flash in a sketch so I can save some data that is being collected (I'm not worried about accidentally deleting the bootloader because I am writing the sketch via ICSP). I found an example of using avr/boot.h and wrote the test sketch included below (it just writes a few pages and then looks for the written data).
But the flash is not being written. When run only a single matching string, which I assume is the string in the compiled program. Are there fuse bits or something that need to be set to enable writing of flash from sketches?
I am seeing the "boot lock protection bits" in the 328p spec but I am having trouble figuring out the ramifications of the various settings (other then to change the size reserved for the bootloader). I have no bootloader since I am writing the sketch via ICSP... (note, please ignore the USB.print stuff in the sketch below; it is similar to Serial.print but goes to a usb chip over SPI instead of serial).
Cheers!
Andrew
#include <inttypes.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
#include <avr/boot.h>
#include <lightuino5.h>
// Pulled from boot.h example code:
void programFlash (uint32_t page, uint8_t *buf)
{
uint16_t i;
uint8_t sreg;
// Disable interrupts.
sreg = SREG;
cli();
eeprom_busy_wait ();
boot_page_erase (page);
boot_spm_busy_wait (); // Wait until the memory is erased.
for (i=0; i<SPM_PAGESIZE; i+=2)
{
// Set up little-endian word.
uint16_t w = *buf++;
w += (*buf++) << 8;
boot_page_fill (page + i, w);
}
boot_page_write (page); // Store buffer in flash page.
boot_spm_busy_wait(); // Wait until the memory is written.
// Reenable RWW-section again. We need this if we want to jump back
// to the application after bootloading.
boot_rww_enable ();
// Re-enable interrupts (if they were ever enabled).
SREG = sreg;
}
// Printf-style to the USB
void p(const char *fmt, ... )
{
char tmp[128]; // resulting string limited to 128 chars
va_list args;
va_start (args, fmt );
vsnprintf(tmp, 128, fmt, args);
va_end (args);
Usb.print(tmp);
}
void setup(void)
{
Usb.begin();
}
char c[128];
#define FLASH_PAGES 32768/SPM_PAGESIZE
void loop(void)
{
strcpy (c,"!ATHIS IS A TEST OF THE FLASH WRITE CAPABILITY");
int lastpage = FLASH_PAGES-1;
programFlash(32768UL-SPM_PAGESIZE,(uint8_t*)c);
c[1] = 'B';
programFlash(32768UL-(SPM_PAGESIZE*2),(uint8_t*)c);
c[1] = 'C';
programFlash(32768UL-2048,(uint8_t*)c);
delay(5000);
Usb.print("Flash write test\n");
p("Page size: %d\n", SPM_PAGESIZE);
// Now search for my written string:
for (unsigned long int i=0;i<32768;i++)
{
char c = pgm_read_byte(i);
if ((c>='A') && (c<='Z')) Usb.write(c); // Dump everything readable and caps
if (c=='!') // This may be my string's beginning
{
p("\nFound ! at: %lu\n", i);
}
}
Usb.print("Done!\n");
delay(20000);
while(1);
}