diff --git a/inc/drivers/MicroBitFlash.h b/inc/drivers/MicroBitFlash.h index 5153508..c53cbcf 100644 --- a/inc/drivers/MicroBitFlash.h +++ b/inc/drivers/MicroBitFlash.h @@ -3,15 +3,8 @@ #include -#define DEFAULT_SCRATCH_ADDR 0x3B000 #define PAGE_SIZE 1024 -typedef enum flash_mode_t -{ - WR_WRITE, - WR_MEMSET -} flash_mode; - class MicroBitFlash { private: @@ -28,30 +21,6 @@ class MicroBitFlash */ void flash_burn(uint32_t* page_address, uint32_t* buffer, int len); - /** - * Write to address in flash, implementing either flash_write (copy - * data from buffer), or flash_memset (set all bytes in flash to - * provided constant. - * - * Function ensures that data is written correctly: - * - erase page if necessary (using need_erase) - * - preserve non-target flash by copying to scratch page. - * - * flash_write_mem assumes that the provided scratch page is already clean, - * i.e. all bytes = 0xFF. The page is erased after use, all bytes reset to - * 0xFF. - * - * @param address in flash to write to - * @param from_buffer address to write data from - * @param write_byte if writing the same byte to add addressed bytes - * @param len number of bytes to write to/copy to - * @param m mode to use this function, memset/memcpy. - * @param scratch_addr scratch page address (must be page-aligned) - * @return non-zero on success, zero on error. - */ - int flash_write_mem(uint8_t* address, uint8_t* from_buffer, - uint8_t write_byte, int len, flash_mode m, - uint8_t* scratch_addr); /** * Check if an erase is required to write to a region in flash memory. @@ -92,42 +61,6 @@ class MicroBitFlash int flash_write(void* address, void* buffer, int length, void* scratch_addr = NULL); - /** - * Set bytes in [address, address+length] to byte. - * Neither address nor buffer need be word-aligned. - * @param address to write to - * @param byte byte to burn to flash - * @param length number of bytes to write to. - * @param scratch_addr if specified, scratch page to use. Use default - * otherwise. - * @return non-zero on success, zero on error. - * - * Example: - * @code - * MicroBitFlash flash(); - * flash.flash_memset((uint8_t*)0x38000, 0x66, 12); //12 bytes to 0x66. - * @endcode - */ - int flash_memset(uint8_t* address, uint8_t byte, int length, - uint8_t* scratch_addr = NULL); - - /** - * Erase bytes in memory, from set address. - * @param address to erase bytes from (needn't be word-aligned. - * @param length number of bytes to erase (set to 0xFF). - * @param scratch_addr if specified, scratch page to use. Use default - * otherwise. - * @return non-zero on success, zero on error. - * - * Example: - * @code - * MicroBitFlash flash(); - * flash.flash_erase((uint8_t*)0x38000, 10240); //erase a flash page. - * @endcode - */ - int flash_erase_mem(uint8_t* address, int length, - uint8_t* scratch_addr = NULL); - /** * Erase an entire page. * @param page_address address of first word of page. diff --git a/source/drivers/MicroBitFlash.cpp b/source/drivers/MicroBitFlash.cpp index 3e4ea00..a17966f 100644 --- a/source/drivers/MicroBitFlash.cpp +++ b/source/drivers/MicroBitFlash.cpp @@ -1,5 +1,6 @@ #include "MicroBitConfig.h" #include "MicroBitFlash.h" +#include "ErrorNo.h" #include "mbed.h" // NVIC #define MIN(a,b) ((a)<(b)?(a):(b)) @@ -84,58 +85,48 @@ void MicroBitFlash::flash_burn(uint32_t* addr, uint32_t* buffer, int size) } /** - * Write to address in flash, implementing either flash_write (copy - * data from buffer), or flash_memset (set all bytes in flash to - * provided constant. - * - * Function ensures that data is written correctly: - * - erase page if necessary (using need_erase) - * - preserve non-target flash by copying to scratch page. - * - * flash_write_mem assumes that the provided scratch page is already clean, - * i.e. all bytes = 0xFF. The page is erased after use, all bytes reset to - * 0xFF. + * Writes the given number of bytes to the address in flash specified. + * Neither address nor buffer need be word-aligned. + * @param address location in flash to write to. + * @param buffer location in memory to write from. + * @length number of bytes to burn + * @param scratch_addr if specified, scratch page to use. Use default + * otherwise. + * @return non-zero on sucess, zero on error. * - * @param address in flash to write to - * @param from_buffer address to write data from - * @param write_byte if writing the same byte to add addressed bytes - * @param len number of bytes to write to/copy to - * @param m mode to use this function, memset/memcpy.$a - * @param scratch_addr scratch page address (must be page-aligned) - * @return non-zero on success, zero on error. + * Example: + * @code + * MicroBitFlash flash(); + * uint32_t word = 0x01; + * flash.flash_write((uint8_t*)0x38000, &word, sizeof(word)) + * @endcode */ -int MicroBitFlash::flash_write_mem(uint8_t* address, uint8_t* from_buffer, - uint8_t write_byte, int length, flash_mode m, uint8_t* scratch_addr) +int MicroBitFlash::flash_write(void* address, void* from_buffer, + int length, void* scratch_addr) { - // Check that scratch_addr is aligned on a page boundary. + // Ensure that scratch_addr is aligned on a page boundary. if((uint32_t)scratch_addr & 0x3FF) - { - return 0; - } + return MICROBIT_INVALID_PARAMETER; - // page number. + // Locate the hardware FLASH page used by this operation. int page = (uint32_t)address / PAGE_SIZE; - - //page address. uint32_t* pgAddr = (uint32_t*)(page * PAGE_SIZE); // offset to write from within page. int offset = (uint32_t)address % PAGE_SIZE; - // uBit.serial.printf("flash_write to 0x%x, from 0x%x, length: 0x%x\n", - // address, from_buffer, length); - // uBit.serial.printf(" - offset = %d, pgAddr = 0x%x, page = %d\n", - // offset, pgAddr, page); - uint8_t* writeFrom = (uint8_t*)pgAddr; int start = WORD_ADDR(offset); int end = WORD_ADDR((offset+length+4)); - int erase = need_erase(from_buffer, address, length); + int erase = need_erase((uint8_t *)from_buffer, (uint8_t *)address, length); // Preserve the data by writing to the scratch page. if(erase) { + if (!scratch_addr) + return MICROBIT_INVALID_PARAMETER; + this->flash_burn((uint32_t*)scratch_addr, pgAddr, PAGE_SIZE/4); this->erase_page(pgAddr); writeFrom = (uint8_t*)scratch_addr; @@ -151,16 +142,8 @@ int MicroBitFlash::flash_write_mem(uint8_t* address, uint8_t* from_buffer, if(i >= offset && i < (offset + length)) { - if(m == WR_WRITE) - { - // Write from buffer. - writeWord |= (from_buffer[i-offset] << ((byteOffset)*8)); - } - else if(m == WR_MEMSET) - { - // Write constant. - writeWord |= ((uint32_t)write_byte << (byteOffset*8)); - } + // Write from buffer. + writeWord |= (((uint8_t *)from_buffer)[i-offset] << ((byteOffset)*8)); } else { @@ -174,98 +157,6 @@ int MicroBitFlash::flash_write_mem(uint8_t* address, uint8_t* from_buffer, } } - return 1; -} - -/** - * Writes the given number of bytes to the address in flash specified. - * Neither address nor buffer need be word-aligned. - * @param address location in flash to write to. - * @param buffer location in memory to write from. - * @length number of bytes to burn - * @param scratch_addr if specified, scratch page to use. Use default - * otherwise. - * @return non-zero on sucess, zero on error. - * - * Example: - * @code - * MicroBitFlash flash(); - * uint32_t word = 0x01; - * flash.flash_write((uint8_t*)0x38000, &word, sizeof(word)) - * @endcode - */ -int MicroBitFlash::flash_write(void* address, void* from_buffer, - int length, void* scratch_addr) -{ - if(scratch_addr == NULL) - { - return this->flash_write_mem((uint8_t *)address, (uint8_t *)from_buffer, 0, length, - WR_WRITE,(uint8_t*)DEFAULT_SCRATCH_ADDR); - } - else - { - return this->flash_write_mem((uint8_t *)address, (uint8_t *)from_buffer, 0, length, - WR_WRITE, (uint8_t *)scratch_addr); - } -} - -/** - * Set bytes in [address, address+length] to byte. - * Neither address nor buffer need be word-aligned. - * @param address to write to - * @param byte byte to burn to flash - * @param length number of bytes to write to. - * @param scratch_addr if specified, scratch page to use. Use default - * otherwise. - * @return non-zero on success, zero on error. - * - * Example: - * @code - * MicroBitFlash flash(); - * flash.flash_memset((uint8_t*)0x38000, 0x66, 12); //12 bytes to 0x66. - * @endcode - */ -int MicroBitFlash::flash_memset(uint8_t* address, uint8_t write_byte, - int length, uint8_t* scratch_addr) -{ - if(scratch_addr == NULL) - { - return this->flash_write_mem(address, NULL, write_byte, length, - WR_MEMSET,(uint8_t*)DEFAULT_SCRATCH_ADDR); - } - else - { - return this->flash_write_mem(address, NULL, write_byte, length, - WR_MEMSET, scratch_addr); - } -} - -/** - * Erase bytes in memory, from set address. - * @param address to erase bytes from (needn't be word-aligned. - * @param length number of bytes to erase (set to 0xFF). - * @param scratch_addr if specified, scratch page to use. Use default - * otherwise. - * @return non-zero on success, zero on error. - * - * Example: - * @code - * MicroBitFlash flash(); - * flash.flash_erase((uint8_t*)0x38000, 10240); //erase a flash page. - * @endcode - */ -int MicroBitFlash::flash_erase_mem(uint8_t* address, int length, - uint8_t* scratch_addr) -{ - if(scratch_addr == NULL) - { - return this->flash_write_mem(address, NULL, 0xFF, length, - WR_MEMSET,(uint8_t*)DEFAULT_SCRATCH_ADDR); - } - else - { - return this->flash_write_mem(address, NULL, 0xff, length, - WR_MEMSET, scratch_addr); - } + return MICROBIT_OK; }