Bangle.js2: Add second Storage area in internal flash for fast access, memory-mapped files

This commit is contained in:
Gordon Williams 2021-10-19 15:42:33 +01:00
parent a94b26f973
commit f3fb29f692
5 changed files with 161 additions and 60 deletions

View File

@ -46,6 +46,7 @@
Graphics: drawString(..., true) for vector fonts now clears the background
nRF52: swap getSerial bytes around so device ID string matches nrfjprog
Bangle.js2: bootloader can now flash firmware from a file in Storage
Bangle.js2: Add second Storage area in internal flash for fast access, memory-mapped files
2v10 : Bangle.js: Improved HRM calculations - swapped autocorrelation for bandpass filter
Bangle.js: Significantly improved step counting algorithm using bandpass filter (fix #1846)

View File

@ -90,14 +90,13 @@ chip = {
'adc' : 1,
'dac' : 0,
'saved_code' : {
# 'address' : ((246 - 10) * 4096), # Bootloader takes pages 248-255, FS takes 246-247
# 'page_size' : 4096,
# 'pages' : 10,
# 'flash_available' : 1024 - ((38 + 8 + 2 + 10)*4) # Softdevice uses 0x26=38 pages of flash, bootloader 8, FS 2, code 10. Each page is 4 kb.
'address' : 0x60000000, # put this in external spiflash (see below)
'page_size' : 4096,
'pages' : 2048, # Entire 8MB of external flash
'flash_available' : 1024 - ((38 + 8 + 2)*4) # Softdevice uses 31 pages of flash, bootloader 8, FS 2, code 10. Each page is 4 kb.
'address' : ((246 - 20) * 4096), # Bootloader takes pages 248-255, FS takes 246-247
'page_size' : 4096,
'pages' : 20,
'flash_available' : 1024 - ((38 + 8 + 2 + 20)*4), # Softdevice uses 0x26=38 pages of flash, bootloader 8, FS 2, code 20. Each page is 4 kb.
'address2' : 0x60000000, # put this in external spiflash (see below)
'pages2' : 2048, # Entire 8MB of external flash
},
};

View File

@ -104,11 +104,15 @@ else: # NOT LINUX
# F4 has different page sizes in different places
total_flash = board.chip["flash"]*1024
flash_saved_code2_pages = 0
if "saved_code" in board.chip:
flash_saved_code_start = board.chip["saved_code"]["address"]
flash_page_size = board.chip["saved_code"]["page_size"]
flash_saved_code_pages = board.chip["saved_code"]["pages"]
flash_available_for_code = board.chip["saved_code"]["flash_available"]*1024
flash_saved_code2_start = board.chip["saved_code"]["address2"]
flash_saved_code2_pages = board.chip["saved_code"]["pages2"]
else:
flash_saved_code_start = "(FLASH_START + FLASH_TOTAL - FLASH_SAVED_CODE_LENGTH)"
flash_available_for_code = total_flash - (flash_saved_code_pages*flash_page_size)
@ -300,6 +304,10 @@ else:
codeOut("#define FLASH_SAVED_CODE_START "+str(flash_saved_code_start))
codeOut("#define FLASH_SAVED_CODE_LENGTH "+str(int(flash_page_size*flash_saved_code_pages)))
if flash_saved_code2_pages:
codeOut("// Extra flash pages in external flash")
codeOut("#define FLASH_SAVED_CODE2_START "+str(flash_saved_code2_start))
codeOut("#define FLASH_SAVED_CODE2_LENGTH "+str(int(flash_page_size*flash_saved_code2_pages)))
codeOut("");
codeOut("#define CLOCK_SPEED_MHZ "+str(board.chip["speed"]))

View File

@ -24,6 +24,14 @@
#define JSF_START_ADDRESS FLASH_SAVED_CODE_START
#define JSF_END_ADDRESS (FLASH_SAVED_CODE_START+FLASH_SAVED_CODE_LENGTH)
#ifdef FLASH_SAVED_CODE2_START // if there's a second bank of flash to use..
#define JSF_BANK2_START_ADDRESS FLASH_SAVED_CODE2_START
#define JSF_BANK2_END_ADDRESS (FLASH_SAVED_CODE2_START+FLASH_SAVED_CODE2_LENGTH)
#define JSF_DEFAULT_START_ADDRESS JSF_BANK2_START_ADDRESS
#else
#define JSF_DEFAULT_START_ADDRESS JSF_START_ADDRESS
#endif
#ifdef USE_HEATSHRINK
#include "compress_heatshrink.h"
#define COMPRESS heatshrink_encode
@ -85,14 +93,24 @@ JsfFileFlags jsfGetFileFlags(JsfFileHeader *header) {
return (JsfFileFlags)((uint32_t)header->size >> 24);
}
/// Return the flags for this file based on the header
static uint32_t jsfGetBankEndAddress(uint32_t addr) {
#ifdef JSF_BANK2_START_ADDRESS
if (addr>=JSF_BANK2_START_ADDRESS && addr<=JSF_BANK2_END_ADDRESS)
return JSF_BANK2_END_ADDRESS;
#endif
return JSF_END_ADDRESS;
}
/** Load a file header from flash, return true if it is valid.
* If readFullName==false, only the first 4 bytes of the name are loaded */
static bool jsfGetFileHeader(uint32_t addr, JsfFileHeader *header, bool readFullName) {
assert(header);
if (!addr) return false;
jshFlashRead(header, addr, readFullName ? sizeof(JsfFileHeader) : 8/* size + name.firstChars */);
uint32_t endAddress = addr + (uint32_t)sizeof(JsfFileHeader) + jsfGetFileSize(header);
return (header->size != JSF_WORD_UNSET) &&
(addr+(uint32_t)sizeof(JsfFileHeader)+jsfGetFileSize(header) <= JSF_END_ADDRESS);
(endAddress <= jsfGetBankEndAddress(addr));
}
/// Is an area of flash completely erased?
@ -129,12 +147,14 @@ static bool jsfIsEqual(uint32_t addr, const unsigned char *data, uint32_t len) {
return true;
}
/// Erase the entire contents of the memory store
/// Erase the entire contents of the memory store. Return true on success
static bool jsfEraseFrom(uint32_t startAddr) {
uint32_t endAddr = jsfGetBankEndAddress(startAddr);
uint32_t addr, len;
if (!jshFlashGetPage(startAddr, &addr, &len))
return false;
while (addr<JSF_END_ADDRESS && !jspIsInterrupted()) {
while (addr<endAddr && !jspIsInterrupted()) {
if (!jsfIsErased(addr,len))
jshFlashErasePage(addr);
if (!jshFlashGetPage(addr+len, &addr, &len))
@ -148,6 +168,9 @@ static bool jsfEraseFrom(uint32_t startAddr) {
/// Erase the entire contents of the memory store
bool jsfEraseAll() {
jsDebug(DBG_INFO,"EraseAll\n");
#ifdef JSF_BANK2_START_ADDRESS
if (!jsfEraseFrom(JSF_BANK2_START_ADDRESS)) return false;
#endif
return jsfEraseFrom(JSF_START_ADDRESS);
}
@ -174,8 +197,11 @@ static uint32_t jsfGetAddressOfNextPage(uint32_t addr) {
uint32_t pageAddr,pageLen;
if (!jshFlashGetPage(addr, &pageAddr, &pageLen))
return 0;
uint32_t endAddr = jsfGetBankEndAddress(addr);
addr = pageAddr+pageLen;
if (addr>=JSF_END_ADDRESS) return 0; // no pages in range
if (addr>=endAddr) {
return 0; // no pages in range
}
return addr;
}
@ -185,12 +211,13 @@ static uint32_t jsfGetSpaceLeftInPage(uint32_t addr) {
uint32_t pageAddr,pageLen;
if (!jshFlashGetPage(addr, &pageAddr, &pageLen))
return 0;
uint32_t endAddr = jsfGetBankEndAddress(addr);
uint32_t nextPageStart = pageAddr+pageLen;
// if the next page is empty, assume it's empty until the end of flash
JsfFileHeader header;
if (nextPageStart<JSF_END_ADDRESS &&
if (nextPageStart<endAddr &&
!jsfGetFileHeader(nextPageStart, &header, false)) {
nextPageStart = JSF_END_ADDRESS;
nextPageStart = endAddr;
}
return nextPageStart - addr;
}
@ -215,7 +242,7 @@ static bool jsfGetNextFileHeader(uint32_t *addr, JsfFileHeader *header, jsfGetNe
newAddr = jsfAlignAddress(newAddr);
// sanity check for bad data
if (newAddr<oldAddr) return 0; // corrupt!
if (newAddr+sizeof(JsfFileHeader)>JSF_END_ADDRESS) return 0; // not enough space
if (newAddr+sizeof(JsfFileHeader) > jsfGetBankEndAddress(oldAddr)) return 0; // not enough space
*addr = newAddr;
bool valid = jsfGetFileHeader(newAddr, header, !(type&GNFH_READ_ONLY_FILENAME_START));
if ((type&GNFH_GET_ALL) && !valid) {
@ -246,8 +273,8 @@ static uint32_t jsfGetAddressOfNextStartPage(uint32_t addr) {
// Get the amount of space free in this page (or all pages). addr=0 uses start page
uint32_t jsfGetFreeSpace(uint32_t addr, bool allPages) {
if (!addr) addr=JSF_START_ADDRESS;
uint32_t pageEndAddr = JSF_END_ADDRESS;
if (!addr) addr=JSF_DEFAULT_START_ADDRESS;
uint32_t pageEndAddr = jsfGetBankEndAddress(addr);
if (!allPages) {
uint32_t pageAddr,pageLen;
if (!jshFlashGetPage(addr, &pageAddr, &pageLen))
@ -292,8 +319,9 @@ static void memcpy_circular(char *dst, uint32_t *dstIndex, uint32_t dstSize, cha
}
static void jsfCompactWriteBuffer(uint32_t *writeAddress, uint32_t readAddress, char *swapBuffer, uint32_t swapBufferSize, uint32_t *swapBufferUsed, uint32_t *swapBufferTail) {
uint32_t endAddr = jsfGetBankEndAddress(*writeAddress);
uint32_t nextFlashPage = jsfGetAddressOfNextPage(*writeAddress);
if (nextFlashPage==0) nextFlashPage=JSF_END_ADDRESS;
if (nextFlashPage==0) nextFlashPage=endAddr;
// write any data between swapBufferTail and the end of the buffer
while (*swapBufferUsed) {
uint32_t s = *swapBufferUsed;
@ -315,7 +343,7 @@ static void jsfCompactWriteBuffer(uint32_t *writeAddress, uint32_t readAddress,
jshFlashWrite(&swapBuffer[*swapBufferTail], *writeAddress, s);
*writeAddress += s;
nextFlashPage = jsfGetAddressOfNextPage(*writeAddress);
if (nextFlashPage==0) nextFlashPage=JSF_END_ADDRESS;
if (nextFlashPage==0) nextFlashPage=endAddr;
*swapBufferTail = (*swapBufferTail+s) % swapBufferSize;
*swapBufferUsed -= s;
}
@ -337,7 +365,7 @@ static bool jsfCompactInternal(uint32_t startAddress, char *swapBuffer, uint32_t
if (header.name.firstChars != 0) { // if not replaced
jsDebug(DBG_INFO,"compact> copying file at 0x%08x\n", addr);
// Rewrite file position for any JsVars that used this file *if* the file changed position
int newAddress = writeAddress+swapBufferUsed;
uint32_t newAddress = writeAddress+swapBufferUsed;
if (addr != newAddress)
jsvUpdateMemoryAddress(addr, sizeof(JsfFileHeader) + jsfGetFileSize(&header), newAddress);
// Copy the file into the circular buffer, one bit at a time.
@ -373,7 +401,7 @@ static bool jsfCompactInternal(uint32_t startAddress, char *swapBuffer, uint32_t
} while (jsfGetNextFileHeader(&addr, &header, GNFH_GET_ALL));
jsDebug(DBG_INFO,"compact> finished reading...\n");
// try and write the remaining
jsfCompactWriteBuffer(&writeAddress, JSF_END_ADDRESS, swapBuffer, swapBufferSize, &swapBufferUsed, &swapBufferTail);
jsfCompactWriteBuffer(&writeAddress, jsfGetBankEndAddress(writeAddress), swapBuffer, swapBufferSize, &swapBufferUsed, &swapBufferTail);
// Finished - erase remaining
jsDebug(DBG_INFO,"compact> almost there - erase remaining pages\n");
writeAddress = jsfGetAddressOfNextPage(writeAddress-1);
@ -383,18 +411,17 @@ static bool jsfCompactInternal(uint32_t startAddress, char *swapBuffer, uint32_t
}
#endif
// Try and compact saved data so it'll fit in Flash again
bool jsfCompact() {
bool jsfBankCompact(uint32_t startAddress) {
#ifndef SAVE_ON_FLASH
jsDebug(DBG_INFO,"Compacting\n");
uint32_t pageAddr,pageSize;
if (!jshFlashGetPage(JSF_START_ADDRESS, &pageAddr, &pageSize))
if (!jshFlashGetPage(startAddress, &pageAddr, &pageSize))
return 0;
uint32_t maxRequired = pageSize + (uint32_t)sizeof(JsfFileHeader);
// TODO: We could skip forward pages if we think they are already fully compacted?
uint32_t uncompacted = 0;
uint32_t allocated = jsfGetAllocatedSpace(JSF_START_ADDRESS, true, &uncompacted);
uint32_t allocated = jsfGetAllocatedSpace(startAddress, true, &uncompacted);
if (!uncompacted) {
jsDebug(DBG_INFO,"Already fully compacted\n");
return true;
@ -405,14 +432,14 @@ bool jsfCompact() {
if (swapBufferSize+256 < jsuGetFreeStack()) {
jsDebug(DBG_INFO,"Enough stack for %d byte buffer\n", swapBufferSize);
char *swapBuffer = alloca(swapBufferSize);
return jsfCompactInternal(JSF_START_ADDRESS, swapBuffer, swapBufferSize);
return jsfCompactInternal(startAddress, swapBuffer, swapBufferSize);
} else {
jsDebug(DBG_INFO,"Not enough stack for (%d bytes)\n", swapBufferSize);
JsVar *buf = jsvNewFlatStringOfLength(swapBufferSize);
if (buf) {
jsDebug(DBG_INFO,"Allocated data in JsVars\n");
char *swapBuffer = jsvGetFlatStringPointer(buf);
bool r = jsfCompactInternal(JSF_START_ADDRESS, swapBuffer, swapBufferSize);
bool r = jsfCompactInternal(startAddress, swapBuffer, swapBufferSize);
jsvUnLock(buf);
return r;
}
@ -431,16 +458,35 @@ bool jsfCompact() {
return false;
}
// Try and compact saved data so it'll fit in Flash again
bool jsfCompact() {
bool compacted = jsfBankCompact(JSF_START_ADDRESS);
#ifdef JSF_BANK2_START_ADDRESS
compacted |= jsfBankCompact(JSF_BANK2_START_ADDRESS);
#endif
return compacted;
}
/// Create a new 'file' in the memory store - DOES NOT remove existing files with same name. Return the address of data start, or 0 on error
static uint32_t jsfCreateFile(JsfFileName name, uint32_t size, JsfFileFlags flags, JsfFileHeader *returnedHeader) {
jsDebug(DBG_INFO,"CreateFile (%d bytes)\n", size);
uint32_t bankStartAddress = JSF_DEFAULT_START_ADDRESS;
if (name.c[1]==':') { // if a 'drive' is specified like "C:foobar.js"
char drive = name.c[0];
memmove(name.c, name.c+2, sizeof(name)-2); // shift back
#ifdef JSF_BANK2_START_ADDRESS
if (drive=='C')
bankStartAddress = JSF_START_ADDRESS;
#endif
}
uint32_t requiredSize = jsfAlignAddress(size)+(uint32_t)sizeof(JsfFileHeader);
bool compacted = false;
uint32_t addr = 0;
JsfFileHeader header;
uint32_t freeAddr = 0;
while (!freeAddr) {
addr = JSF_START_ADDRESS;
addr = bankStartAddress;
freeAddr = 0;
// Find a hole that's big enough for our file
do {
@ -462,7 +508,7 @@ static uint32_t jsfCreateFile(JsfFileName name, uint32_t size, JsfFileFlags flag
jsDebug(DBG_INFO,"CreateFile - Compact failed\n");
return 0;
}
addr = JSF_START_ADDRESS; // addr->startAddr = restart
addr = bankStartAddress; // addr->startAddr = restart
} else {
jsDebug(DBG_INFO,"CreateFile - Not enough space\n");
return 0;
@ -493,9 +539,8 @@ static uint32_t jsfCreateFile(JsfFileName name, uint32_t size, JsfFileFlags flag
return addr+(uint32_t)sizeof(JsfFileHeader);
}
/// Find a 'file' in the memory store. Return the address of data start (and header if returnedHeader!=0). Returns 0 if not found
uint32_t jsfFindFile(JsfFileName name, JsfFileHeader *returnedHeader) {
uint32_t addr = JSF_START_ADDRESS;
static uint32_t jsfBankFindFile(uint32_t bankAddress, uint32_t bankEndAddress, JsfFileName name, JsfFileHeader *returnedHeader) {
uint32_t addr = bankAddress;
JsfFileHeader header;
memset(&header,0,sizeof(JsfFileHeader));
if (jsfGetFileHeader(addr, &header, false)) do {
@ -505,7 +550,7 @@ uint32_t jsfFindFile(JsfFileName name, JsfFileHeader *returnedHeader) {
jsfGetFileHeader(addr, &header, true);
if (memcmp(header.name.c, name.c, sizeof(name.c))==0) {
uint32_t endOfFile = addr + (uint32_t)sizeof(JsfFileHeader) + jsfGetFileSize(&header);
if (endOfFile<addr || endOfFile>JSF_END_ADDRESS)
if (endOfFile<addr || endOfFile>bankEndAddress)
return 0; // corrupt - file too long
if (returnedHeader)
*returnedHeader = header;
@ -516,13 +561,20 @@ uint32_t jsfFindFile(JsfFileName name, JsfFileHeader *returnedHeader) {
return 0;
}
/// Find a 'file' in the memory store. Return the address of data start (and header if returnedHeader!=0). Returns 0 if not found
uint32_t jsfFindFile(JsfFileName name, JsfFileHeader *returnedHeader) {
uint32_t a = jsfBankFindFile(JSF_START_ADDRESS, JSF_END_ADDRESS, name, returnedHeader);
if (a) return a;
#ifdef JSF_BANK2_START_ADDRESS
a = jsfBankFindFile(JSF_BANK2_START_ADDRESS, JSF_BANK2_END_ADDRESS, name, returnedHeader);
#endif
return a;
}
/// Output debug info for files stored in flash storage
void jsfDebugFiles() {
uint32_t addr = JSF_START_ADDRESS;
static void jsfBankDebugFiles(uint32_t addr) {
uint32_t pageAddr = 0, pageLen = 0, pageEndAddr = 0;
jsiConsolePrintf("DEBUG FILES %d live\n", jsfGetAllocatedSpace(addr,true,0));
jsiConsolePrintf("DEBUG FILES (0x%08x) %d live\n", addr, jsfGetAllocatedSpace(addr,true,0));
JsfFileHeader header;
memset(&header,0,sizeof(JsfFileHeader));
@ -554,16 +606,17 @@ void jsfDebugFiles() {
} while (jsfGetNextFileHeader(&addr, &header, GNFH_GET_ALL));
}
/** Return false if the current storage is not valid
* or is corrupt somehow. Basically that means if
* jsfGet[Next]FileHeader returns false but the header isn't all FF
*
* If fullTest is true, all of storage is scanned.
* For instance the first page may be blank but other pages
* may contain info (which is invalid)...
*/
bool jsfIsStorageValid(JsfStorageTestType testType) {
uint32_t addr = JSF_START_ADDRESS;
/// Output debug info for files stored in flash storage
void jsfDebugFiles() {
jsfBankDebugFiles(JSF_START_ADDRESS);
#ifdef JSF_BANK2_START_ADDRESS
jsfBankDebugFiles(JSF_BANK2_START_ADDRESS);
#endif
}
static bool jsfIsBankStorageValid(uint32_t startAddr, JsfStorageTestType testType) {
uint32_t addr = startAddr;
uint32_t endAddr = jsfGetBankEndAddress(addr);
uint32_t oldAddr = addr;
JsfFileHeader header;
unsigned char *headerPtr = (unsigned char *)&header;
@ -577,8 +630,8 @@ bool jsfIsStorageValid(JsfStorageTestType testType) {
// Work out roughly where the start is
uint32_t newAddr = jsfAlignAddress(oldAddr + jsfGetFileSize(&header) + (uint32_t)sizeof(JsfFileHeader));
if (newAddr<oldAddr) return false; // definitely corrupt!
if (newAddr <= JSF_END_ADDRESS &&
newAddr+sizeof(JsfFileHeader)>JSF_END_ADDRESS) return true; // not enough space - this is fine
if (newAddr <= endAddr &&
newAddr+sizeof(JsfFileHeader)>endAddr) return true; // not enough space - this is fine
}
}
bool allFF = true;
@ -586,15 +639,32 @@ bool jsfIsStorageValid(JsfStorageTestType testType) {
if (headerPtr[i]!=0xFF) allFF=false;
if (allFF && ((addr && testType==JSFSTT_ALL) || // FULL: always search the remaining area
(addr==JSF_START_ADDRESS && testType==JSFSTT_NORMAL))) { // NORMAL: if no files, only search everything if storage is empty
return jsfIsErased(addr, JSF_END_ADDRESS-addr);
(addr==startAddr && testType==JSFSTT_NORMAL))) { // NORMAL: if no files, only search everything if storage is empty
return jsfIsErased(addr, endAddr-addr);
}
return allFF;
}
/** Return false if the current storage is not valid
* or is corrupt somehow. Basically that means if
* jsfGet[Next]FileHeader returns false but the header isn't all FF
*
* If fullTest is true, all of storage is scanned.
* For instance the first page may be blank but other pages
* may contain info (which is invalid)...
*/
bool jsfIsStorageValid(JsfStorageTestType testType) {
if (!jsfIsBankStorageValid(JSF_START_ADDRESS, testType))
return false;
#ifdef JSF_BANK2_START_ADDRESS
if (!jsfIsBankStorageValid(JSF_BANK2_START_ADDRESS, testType))
return false;
#endif
return true;
}
/** Return true if there is nothing at all in Storage (first header on first page is all 0xFF) */
bool jsfIsStorageEmpty() {
uint32_t addr = JSF_START_ADDRESS;
bool jsfIsBankStorageEmpty(uint32_t addr) {
JsfFileHeader header;
unsigned char *headerPtr = (unsigned char *)&header;
jsfGetFileHeader(addr, &header, true);
@ -604,6 +674,17 @@ bool jsfIsStorageEmpty() {
return allFF;
}
/** Return true if there is nothing at all in Storage (first header on first page is all 0xFF) */
bool jsfIsStorageEmpty() {
if (!jsfIsBankStorageEmpty(JSF_START_ADDRESS))
return false;
#ifdef JSF_BANK2_START_ADDRESS
if (!jsfIsBankStorageEmpty(JSF_BANK2_START_ADDRESS))
return false;
#endif
return true;
}
JsVar *jsfReadFile(JsfFileName name, int offset, int length) {
JsfFileHeader header;
uint32_t addr = jsfFindFile(name, &header);
@ -706,11 +787,7 @@ bool jsfWriteFile(JsfFileName name, JsVar *data, JsfFileFlags flags, JsVarInt of
* If containing!=0, file flags must contain one of the 'containing' argument's bits.
* Flags can't contain any bits in the 'notContaining' argument
*/
JsVar *jsfListFiles(JsVar *regex, JsfFileFlags containing, JsfFileFlags notContaining) {
JsVar *files = jsvNewEmptyArray();
if (!files) return 0;
uint32_t addr = JSF_START_ADDRESS;
static void jsfBankListFiles(JsVar *files, uint32_t addr, JsVar *regex, JsfFileFlags containing, JsfFileFlags notContaining) {
JsfFileHeader header;
memset(&header,0,sizeof(JsfFileHeader));
if (jsfGetFileHeader(addr, &header, true)) do {
@ -739,6 +816,20 @@ JsVar *jsfListFiles(JsVar *regex, JsfFileFlags containing, JsfFileFlags notConta
else jsvUnLock(v);
}
} while (jsfGetNextFileHeader(&addr, &header, GNFH_GET_ALL));
}
/** Return all files in flash as a JsVar array of names. If regex is supplied, it is used to filter the filenames using String.match(regexp)
* If containing!=0, file flags must contain one of the 'containing' argument's bits.
* Flags can't contain any bits in the 'notContaining' argument
*/
JsVar *jsfListFiles(JsVar *regex, JsfFileFlags containing, JsfFileFlags notContaining) {
JsVar *files = jsvNewEmptyArray();
if (!files) return 0;
jsfBankListFiles(files, JSF_START_ADDRESS, regex, containing, notContaining);
#ifdef JSF_BANK2_START_ADDRESS
jsfBankListFiles(files, JSF_BANK2_START_ADDRESS, regex, containing, notContaining);
#endif
return files;
}
@ -828,10 +919,11 @@ void jsfSaveToFlash() {
while (jsiFreeMoreMemory());
jspSoftKill();
jsvSoftKill();
compressedSize = 4 + COMPRESS(varPtr, varSize, NULL, NULL);
savedCodeAddr = jsfCreateFile(name, compressedSize, JSFF_COMPRESSED, NULL);
}
if (!savedCodeAddr) {
if (jsfGetAllocatedSpace(JSF_START_ADDRESS, true, 0))
if (jsfGetAllocatedSpace(JSF_DEFAULT_START_ADDRESS, true, 0))
jsiConsolePrint("Not enough free space to save. Try require('Storage').eraseAll()\n");
else
jsiConsolePrint("Code is too big to save to Flash.\n");

View File

@ -482,7 +482,8 @@ void jsiSoftInit(bool hasBeenReset) {
jsfResetStorage();
} else {
#ifdef BANGLEJS
jsiConsolePrintf("Storage Ok.\n");
if (fullTest)
jsiConsolePrintf("Storage Ok.\n");
#endif
}
#endif