/
FlashStringLoader.js
95 lines (88 loc) · 4.11 KB
/
FlashStringLoader.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
* FlashString.js - Flash memory manager for JavaScript strings
* Thorsten von Eicken 2016
* MIT License
*
* Stores strings indexed by name in flash, one string per flash page. This is targeted at the
* esp8266 where each flash page is 4KB. This means that each string consumes 4KB and its length
* is limited to 4KB minus the length of the name minus 4 bytes.
* Load the FlashString module using `FS=require('FlashString')`, then write a string using
* `FS.save(name, str)` and restore it using `str = FS.load(name)`. Writing a string with the
* same name again overwrites the earlier one. To delete a string use `FS.erase(name)` and to
* delete all use `FS.eraseAll()`.
* When "restoring" a string the load() function returns a memoryArea, i.e. a string that
* points directly into the bytes in flash, so only a couple of JSvars are used to hold the
* name of the javascript string variable. However, if you change the flash location the string
* will change too...
* Esp8266 modules with 512KB flash are not currently supported (too little free flash). Esp8266
* with 1MB flash can store 5 flash strings and esp8266 with more flash can store 9 strings.
* The primary intended purpose of the FlashString module is to save javascript modules to flash
* and execute them from flash. For this purpose, use the save() function to write each module
* indexed by its name to flash. Then at boot time, load all the flash modules using the
* FlashLoader's loadAll function, which is under 500 bytes in size. The FlashString module
* itself uses approx 1KB minified but is not needed to load all modules at boot.
*/
var FL = require("Flash");
var FR = FL.getFree()[2]; // 3rd area has biggest chunk under 1MB
var FA = [FL.getFree()[0].addr,FL.getFree()[1].addr]; // use first 2 pages
var FB = FR.addr; // start of flash save area (0xf7000)
var FS = 0x1000; // esp8266 flash page size
var FN = 2+FR.length / FS; // number of flash pages
var FO = 0x40200000; // offset from flash address to its memory-mapped location
// find flash page for a string by name, returns the flash page address.
// If the name is not found and free==1 it returns a free flash page addr, else it returns 0
function findName(name, free) {
// console.log("looking for ",name, free);
// iterate through flash pages to see whether there's a match
var f = 0;
for (var i=0; i<FN; i++) {
var addr ;
if(i<2) addr = FA[i];
else addr= FB+(i-2)*FS;
// console.log("Checking", i, addr.toString(16));
// read index at start of page with name length and code text length
var ix = FL.read(4, addr);
var nameLen = ix[0];
// var codeLen = ix[1]<<4;
// see whether page is unused
// console.log("ix[3] ",String.fromCharCode(ix[3]) ,'\xA5' );
// console.log("(ix[3] != '\xA5) : ' ",(String.fromCharCode(ix[3]) !== '\xA5'));
if (String.fromCharCode(ix[3]) !== '\xA5') {
// console.log(" free at", addr.toString(16));
f = addr;
continue;
}
// see whether the name length differs
if (nameLen !== name.length) continue;
// read the name
var fName = FL.read(nameLen, addr+4);
if (fName == name) {
// console.log(" found at", addr.toString(16));
return addr;
}
}
return free ? f : 0;
}
// load() retrieves a string by name or null if not found. The retrieved string is kept in
// flash, i.e., it's a string created by E.memoryArea.
exports.load = function(name) {
// copy string into a Uint8Array rounded up to a multiple of 4 in length
function s2a(str) {
while (str.length & 3) str += " ";
return E.toUint8Array(str);
}
// copy the module name into a Uint8Array rounded up to a multiple of 4 in length
var nameArr = s2a(name);
// iterate through flash pages to see whether there's a match
var addr = findName(nameArr, 0);
if (!addr) return null;
// read length
var ix = FL.read(4, addr);
// address and length of code
var codeAddr = addr+4+(ix[0]);
var codeLen = (ix[1]<<8) + ix[2];
// return memory area
// console.log(" memoryArea", codeAddr.toString(16), codeLen);
// console.log(" ix", ix[0], ix[1], ix[2]);
return E.memoryArea(FO+codeAddr, codeLen);
};