Espruino/scripts/build_js_hardware.js

142 lines
4.0 KiB
JavaScript

#!/bin/node
/* This builds a js file containing the addresses of a chip's peripherals and
the values of the bits in each register. Can be used for quickly building
ways to access the underlying hardware from JS */
var INPUTFILE = "targetlibs/stm32f1/lib/stm32f10x.h";
var definitions = {"STM32F10X_XL":true};
//var INPUTFILE = "targetlibs/stm32f4/lib/stm32f4xx.h";
//var definitions = {"STM32F401xx":true};
var fs = require('fs');
var structContents = undefined;
var structSize = 0;
var typeSizes = {
"uint32_t" : 4,
"uint16_t" : 2,
"uint8_t" : 1,
"CAN_FIFOMailBox_TypeDef" : NaN,
"CAN_TxMailBox_TypeDef" : NaN,
"CAN_FilterRegister_TypeDef" : NaN,
};
var ifDefs = [];
var structs = {};
fs.readFileSync(INPUTFILE).toString().replace(/(\/\*[^\n*]*)\r\n(.*\*\/)/g,"$1$2").split("\n").forEach(function(oline) {
//console.log(JSON.stringify(oline));
var line = oline.trim();
if (line=="") return;
if (line.indexOf("#ifndef ")==0) {
ifDefs.push(!(line.substr(8).trim() in definitions));
return;
} else if (line.indexOf("#ifdef ")==0) {
ifDefs.push((line.substr(7).trim() in definitions));
return;
} else if (line.indexOf("#if ")==0) {
console.warn("Uh-oh, we have a #if - assuming it is true:"+line);
ifDefs.push(true);
return;
} else if (line.indexOf("#else")==0) {
ifDefs[ifDefs.length-1] = !ifDefs[ifDefs.length-1];
return;
} else if (line.indexOf("#endif")==0) {
ifDefs.pop();
return;
}
for (var i in ifDefs)
if (!ifDefs[i]) return;
if (line.indexOf("#error ")==0) {
console.warn(line);
}
if (line.indexOf("#define")==0) {
line = line.substr(7).trim();
var i = line.indexOf(" ");
var dkey = line.substr(0,i);
var dval = line.substr(i).trim();
if (dval.indexOf("/*")>=0) dval = dval.substr(0,dval.indexOf("/*")).trim();
definitions[dkey] = dval.replace(/\(uint32_t[ ]*\)/,"");
} else if (line=="typedef struct") {
structContents = {};
structSize = 0;
} else if (line[0]=="{") {
} else if (line[0]=="}") {
if (line.indexOf("_TypeDef;")>=0) {
var name = line.substring(line.lastIndexOf(" ")+1,line.indexOf("_TypeDef;"));
structs[name] = structContents;
}
structContents = undefined;
} else if (structContents) {
if (line.substr(0,2)!="/*") {
if (line.substr(0,2)=="__") line=line.substr(line.indexOf(" ")+1);
var type = line.substr(0,line.indexOf(" "));
line = line.substr(line.indexOf(" ")+1).trim();
var name = line.substr(0,line.indexOf(";"));
line = line.substr(line.indexOf(";")+1).trim();
if (!(type in typeSizes)) throw new Error("Unknown type "+type+" in "+JSON.stringify(oline));
var size = typeSizes[type];
if (name.indexOf("[")>=0) {
var c = name.substring(name.indexOf("[")+1, name.indexOf("]"));
size *= c;
}
structContents[name] = { offset : structSize, size : size };
structSize += size;
}
}
});
//console.log(structs)
// find base addresses
var bases = {};
for (var def in definitions) {
if (def.substr(-5)=="_BASE") {
var v = definitions[def].
replace(/(\()([A-Z])/,"$1 $2").
replace(/([A-Z])(\))/,"$1 $2").
split(" ");
v = v.map(function(tk) {
if (tk in bases) return bases[tk];
return tk;
});
bases[def] = eval(v.join(""));
}
}
var peripherals = ["RCC","DMA"];
function out(s) {
console.log(s);
}
peripherals.forEach(function(periph) {
var base = bases[periph+"_BASE"];
var data = { a : {}, f : {} };
for (var key in structs[periph]) {
if (key.substr(0,8)=="RESERVED") continue;
// address
data.a[key] = base+structs[periph][key].offset;
// flags
var pref = periph+"_"+key+"_";
for (var d in definitions) {
if (d.substr(0,pref.length)==pref) {
if (!data.f[key]) data.f[key] = {};
try {
data.f[key][d.substr(pref.length)] = eval(definitions[d]);
} catch (e) {}
}
}
}
// output
out("var "+periph+" = "+JSON.stringify(data,null,2)+";");
});