refactor code

This commit is contained in:
liamcottle
2024-07-14 19:10:40 +12:00
parent eda5dd4f0e
commit 163a91ea48
4 changed files with 322 additions and 269 deletions

View File

@@ -33,6 +33,12 @@
</button> </button>
</div> </div>
<div>
<button @click="detect" class="border px-2 bg-gray-100 hover:bg-gray-200 rounded">
Detect
</button>
</div>
</div> </div>
<script> <script>
@@ -46,36 +52,71 @@
}, },
methods: { methods: {
async connect() { async askForSerialPort() {
if(!navigator.serial){ if(!navigator.serial){
alert("Serial is not supported in this browser"); alert("Web Serial is not supported in this browser");
return; return null;
} }
// ask user to select device // ask user to select device
const serialPort = await navigator.serial.requestPort({ return await navigator.serial.requestPort({
filters: [], filters: [],
}); });
this.flasher = new Nrf52DfuFlasher(serialPort); },
async enterDfuMode() {
// await this.flasher.enterDfuMode(); // ask for serial port
const serialPort = await this.askForSerialPort();
return; if(!serialPort){
await serialPort.open({
baudRate: RNode.BAUD_RATE,
});
const rnode = RNode.fromSerialPort(serialPort);
if(!await rnode.detect()){
console.log("device is not an rnode");
return; return;
} }
// dump node info // enter dfu mode
const flasher = new Nrf52DfuFlasher(serialPort);
await flasher.enterDfuMode();
},
async flash() {
// ensure firmware file selected
const file = this.$refs["file"].files[0];
if(!file){
alert("Select a firmware file first");
return;
}
// ask for serial port
const serialPort = await this.askForSerialPort();
if(!serialPort){
return;
}
// flash file
const flasher = new Nrf52DfuFlasher(serialPort);
await flasher.flash(file);
},
async detect() {
// ask for serial port
const serialPort = await this.askForSerialPort();
if(!serialPort){
return;
}
// check if device is an rnode
const rnode = await RNode.fromSerialPort(serialPort);
const isRNode = await rnode.detect();
if(!isRNode){
alert("Selected device is not an RNode!");
return;
}
const firmwareVersion = await rnode.getFirmwareVersion();
alert("RNode has firmware v" + firmwareVersion);
console.log({ console.log({
firmware_version: await rnode.getFirmwareVersion(), firmware_version: await rnode.getFirmwareVersion(),
platform: await rnode.getPlatform(), platform: await rnode.getPlatform(),
@@ -96,104 +137,7 @@
rssi_stat: await rnode.getRssiStat(), rssi_stat: await rnode.getRssiStat(),
}); });
// console.log(response.map(x => x.toString(16).padStart(2, '0')).join('')); await rnode.close();
// rnode.device_probe()
// rnode.download_eeprom()
// if rnode.provisioned and rnode.signature_valid:
// This device is already installed and provisioned. No further action will
// if rnode.detected:
// The device seems to have an RNode firmware installed, but it was not provisioned correctly, or it is corrupt
// We are going to reinstall the correct firmware and provision it.
// else
// It looks like this is a fresh device with no RNode firmware.
// selected_product = ROM.PRODUCT_RAK4631
// selected_platform = None
// selected_model = None
// selected_mcu = ROM.MCU_NRF52
// print("\nWhat band is this RAK4631 for?\n")
// print("[1] 433 MHz")
// selected_model = ROM.MODEL_11
// selected_platform = ROM.PLATFORM_NRF52
// print("[2] 868 MHz")
// print("[3] 915 MHz")
// print("[4] 923 MHz")
// selected_model = ROM.MODEL_12
// selected_platform = ROM.PLATFORM_NRF52
// fw_filename = models[selected_model][4]
// if fw_filename == None:
// Sorry, no firmware for your board currently exists.
// args.key = True
// args.port = selected_port.device
// args.platform = selected_platform
// args.hwrev = 1
// mapped_model = selected_model
// mapped_product = selected_product
// args.update = False
// args.flash = True
// ensure_firmware_file(fw_filename)
// get or generate device signing key (rns identity is used)
// get or generate eeprom signing key (rsa private key is generated)
// get partition hash (sha256 of firmware file for rak)
// extract firmware zip folder
// get flasher call
// adafruit-nrfutil dfu serial --package fw_filename -p args.port -b 115200 -t 1200
// adafruit-nrfutil dfu serial --package ~/Downloads/rnode_firmware_rak4631.zip -p /dev/cu.usbmodem14401 -b 115200 -t 1200
// --package dfu filename
// -p comport
// -b baud rate
// -t Open port with specified baud then close it, before uploading
// https://github.com/adafruit/Adafruit_nRF52_nrfutil/blob/master/nordicsemi/__main__.py
// https://github.com/adafruit/Adafruit_nRF52_nrfutil/blob/master/nordicsemi/dfu/dfu_transport_serial.py#L49
// https://github.com/markqvist/Reticulum/discussions/471
},
async initFlasher() {
if(!navigator.serial){
alert("Web Serial is not supported in this browser");
return;
}
// ask user to select device
const serialPort = await navigator.serial.requestPort({
filters: [],
});
return new Nrf52DfuFlasher(serialPort);
},
async enterDfuMode() {
const flasher = await this.initFlasher();
await flasher.enterDfuMode();
},
async flash() {
// ensure firmware file selected
const file = this.$refs["file"].files[0];
if(!file){
alert("Select a firmware file first");
return;
}
// flash file
const flasher = await this.initFlasher();
await flasher.flash(file);
}, },
}, },

View File

@@ -1,5 +1,5 @@
/** /**
* A web based nRF52 flasher based on: * A Web Serial based nRF52 flasher written by liam@liamcottle.com based on dfu_transport.serial.py
* https://github.com/adafruit/Adafruit_nRF52_nrfutil/blob/master/nordicsemi/dfu/dfu_transport_serial.py * https://github.com/adafruit/Adafruit_nRF52_nrfutil/blob/master/nordicsemi/dfu/dfu_transport_serial.py
*/ */
class Nrf52DfuFlasher { class Nrf52DfuFlasher {
@@ -10,7 +10,7 @@ class Nrf52DfuFlasher {
FLASH_BAUD = 115200; FLASH_BAUD = 115200;
HexType_APPLICATION = 4; HEX_TYPE_APPLICATION = 4;
DFU_INIT_PACKET = 1; DFU_INIT_PACKET = 1;
DFU_START_PACKET = 3; DFU_START_PACKET = 3;
@@ -31,15 +31,30 @@ class Nrf52DfuFlasher {
constructor(serialPort) { constructor(serialPort) {
this.serialPort = serialPort; this.serialPort = serialPort;
this.sequence_number = 0; this.sequenceNumber = 0;
this.sd_size = 0; this.sd_size = 0;
this.total_size = 0; this.total_size = 0;
} }
async send_packet(data) { /**
* Waits for the provided milliseconds, and then resolves.
* @param millis
* @returns {Promise<void>}
*/
async sleepMillis(millis) {
await new Promise((resolve) => {
setTimeout(resolve, millis);
});
}
/**
* Writes the provided data to the Serial Port.
* @param data
* @returns {Promise<void>}
*/
async sendPacket(data) {
const writer = this.serialPort.writable.getWriter(); const writer = this.serialPort.writable.getWriter();
try { try {
console.log("writing", data);
await writer.write(new Uint8Array(data)); await writer.write(new Uint8Array(data));
} finally { } finally {
writer.releaseLock(); writer.releaseLock();
@@ -47,7 +62,7 @@ class Nrf52DfuFlasher {
} }
/** /**
* Puts an nRF52 board into DFU mode by quickly opening and closing a serial port * Puts an nRF52 board into DFU mode by quickly opening and closing a serial port.
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
async enterDfuMode() { async enterDfuMode() {
@@ -58,20 +73,21 @@ class Nrf52DfuFlasher {
}); });
// wait SERIAL_PORT_OPEN_WAIT_TIME before closing port // wait SERIAL_PORT_OPEN_WAIT_TIME before closing port
await new Promise((resolve, reject) => { await this.sleepMillis(this.SERIAL_PORT_OPEN_WAIT_TIME * 1000);
setTimeout(resolve, this.SERIAL_PORT_OPEN_WAIT_TIME * 1000);
});
// close port // close port
await this.serialPort.close(); await this.serialPort.close();
// wait TOUCH_RESET_WAIT_TIME for device to enter into DFU mode // wait TOUCH_RESET_WAIT_TIME for device to enter into DFU mode
await new Promise((resolve, reject) => { await this.sleepMillis(this.TOUCH_RESET_WAIT_TIME * 1000);
setTimeout(resolve, this.TOUCH_RESET_WAIT_TIME * 1000);
});
} }
/**
* Flashes the provided firmware zip.
* @param firmwareZipBlob
* @returns {Promise<void>}
*/
async flash(firmwareZipBlob) { async flash(firmwareZipBlob) {
// read zip file // read zip file
@@ -81,6 +97,9 @@ class Nrf52DfuFlasher {
// find manifest file // find manifest file
const manifestFile = zipEntries.find((zipEntry) => zipEntry.filename === "manifest.json"); const manifestFile = zipEntries.find((zipEntry) => zipEntry.filename === "manifest.json");
if(!manifestFile){
throw "manifest.json not found in firmware file!";
}
// read manifest file as text // read manifest file as text
const text = await manifestFile.getData(new window.zip.TextWriter()); const text = await manifestFile.getData(new window.zip.TextWriter());
@@ -89,29 +108,33 @@ class Nrf52DfuFlasher {
const json = JSON.parse(text); const json = JSON.parse(text);
const manifest = json.manifest; const manifest = json.manifest;
console.log(manifest); // todo softdevice_bootloader
// if self.manifest.softdevice_bootloader: // if self.manifest.softdevice_bootloader:
// self._dfu_send_image(HexType.SD_BL, self.manifest.softdevice_bootloader) // self._dfu_send_image(HexType.SD_BL, self.manifest.softdevice_bootloader)
//
// todo softdevice
// if self.manifest.softdevice: // if self.manifest.softdevice:
// self._dfu_send_image(HexType.SOFTDEVICE, self.manifest.softdevice) // self._dfu_send_image(HexType.SOFTDEVICE, self.manifest.softdevice)
//
// todo bootloader
// if self.manifest.bootloader: // if self.manifest.bootloader:
// self._dfu_send_image(HexType.BOOTLOADER, self.manifest.bootloader) // self._dfu_send_image(HexType.BOOTLOADER, self.manifest.bootloader)
// flash application image // flash application image
if(manifest.application){ if(manifest.application){
await this.dfuSendImage(this.HexType_APPLICATION, zipEntries, manifest.application); await this.dfuSendImage(this.HEX_TYPE_APPLICATION, zipEntries, manifest.application);
} }
} }
async dfuSendImage(program_mode, zipEntries, firmware_manifest) { /**
* Sends the firmware image to the device in DFU mode.
if(!firmware_manifest){ * @param programMode
throw "firmware_manifest must be provided."; * @param zipEntries
} * @param firmwareManifest
* @returns {Promise<void>}
*/
async dfuSendImage(programMode, zipEntries, firmwareManifest) {
// open port // open port
await this.serialPort.open({ await this.serialPort.open({
@@ -119,49 +142,39 @@ class Nrf52DfuFlasher {
}); });
// wait SERIAL_PORT_OPEN_WAIT_TIME // wait SERIAL_PORT_OPEN_WAIT_TIME
await new Promise((resolve, reject) => { await this.sleepMillis(this.SERIAL_PORT_OPEN_WAIT_TIME * 1000);
setTimeout(resolve, this.SERIAL_PORT_OPEN_WAIT_TIME * 1000);
});
var softdevice_size = 0 // file sizes
var bootloader_size = 0 var softdeviceSize = 0
var application_size = 0 var bootloaderSize = 0
var applicationSize = 0
// read bin file (firmware) // read bin file (firmware)
const binFile = zipEntries.find((zipEntry) => zipEntry.filename === firmware_manifest.bin_file); const binFile = zipEntries.find((zipEntry) => zipEntry.filename === firmwareManifest.bin_file);
const firmware = await binFile.getData(new window.zip.Uint8ArrayWriter()); const firmware = await binFile.getData(new window.zip.Uint8ArrayWriter());
console.log(firmware);
// read dat file (init packet) // read dat file (init packet)
const datFile = zipEntries.find((zipEntry) => zipEntry.filename === firmware_manifest.dat_file); const datFile = zipEntries.find((zipEntry) => zipEntry.filename === firmwareManifest.dat_file);
const init_packet = await datFile.getData(new window.zip.Uint8ArrayWriter()); const init_packet = await datFile.getData(new window.zip.Uint8ArrayWriter());
console.log(init_packet);
// only support flashing application for now // only support flashing application for now
if(program_mode !== this.HexType_APPLICATION){ if(programMode !== this.HEX_TYPE_APPLICATION){
throw "not implemented"; throw "not implemented";
} }
if(program_mode === this.HexType_APPLICATION){ // determine application size
application_size = firmware.length; if(programMode === this.HEX_TYPE_APPLICATION){
console.log("app size", application_size); applicationSize = firmware.length;
} }
// todo test this works...
console.log("Sending DFU start packet"); console.log("Sending DFU start packet");
await this.send_start_dfu(program_mode, softdevice_size, bootloader_size, application_size); await this.sendStartDfu(programMode, softdeviceSize, bootloaderSize, applicationSize);
console.log("Sending DFU init packet"); console.log("Sending DFU init packet");
await this.send_init_packet(init_packet); await this.sendInitPacket(init_packet);
console.log("Sending firmware file") console.log("Sending firmware file")
await this.send_firmware(firmware); await this.sendFirmware(firmware);
// console.log("Sending validate firmware")
// await this.send_validate_firmware();
//
// console.log("Sending activate firmware")
// await this.send_activate_firmware();
// close port // close port
console.log("Closing Port"); console.log("Closing Port");
@@ -174,20 +187,19 @@ class Nrf52DfuFlasher {
} }
// confirmed working /**
* Calculates CRC16 on the provided binaryData
* @param {Uint8Array} binaryData - Array with data to run CRC16 calculation on
* @param {number} crc - CRC value to start calculation with
* @return {number} - Calculated CRC value of binaryData
*/
calcCrc16(binaryData, crc = 0xffff) { calcCrc16(binaryData, crc = 0xffff) {
/**
* Calculates CRC16 on binaryData if(!(binaryData instanceof Uint8Array)){
*
* @param {Uint8Array} binaryData - Array with data to run CRC16 calculation on
* @param {number} crc - CRC value to start calculation with
* @return {number} - Calculated CRC value of binaryData
*/
if (!(binaryData instanceof Uint8Array)) {
throw new Error("calcCrc16 requires Uint8Array input"); throw new Error("calcCrc16 requires Uint8Array input");
} }
for (let b of binaryData) { for(let b of binaryData){
crc = (crc >> 8 & 0x00FF) | (crc << 8 & 0xFF00); crc = (crc >> 8 & 0x00FF) | (crc << 8 & 0xFF00);
crc ^= b; crc ^= b;
crc ^= (crc & 0x00FF) >> 4; crc ^= (crc & 0x00FF) >> 4;
@@ -196,26 +208,25 @@ class Nrf52DfuFlasher {
} }
return crc & 0xFFFF; return crc & 0xFFFF;
} }
// confirmed working /**
* Encode esc characters in a SLIP package.
* Replace 0xC0 with 0xDBDC and 0xDB with 0xDBDD.
* @param dataIn
* @returns {*[]}
*/
slipEncodeEscChars(dataIn) { slipEncodeEscChars(dataIn) {
/**
* Encode esc characters in a SLIP package.
*
* Replace 0xC0 with 0xDBDC and 0xDB with 0xDBDD.
*
* @param {string} dataIn - String to encode
* @return {string} - String with encoded packet
*/
let result = []; let result = [];
for (let i = 0; i < dataIn.length; i++) { for(let i = 0; i < dataIn.length; i++){
let char = dataIn[i]; let char = dataIn[i];
if (char === 0xC0) { if(char === 0xC0){
result.push(0xDB); result.push(0xDB);
result.push(0xDC); result.push(0xDC);
} else if (char === 0xDB) { } else if(char === 0xDB) {
result.push(0xDB); result.push(0xDB);
result.push(0xDD); result.push(0xDD);
} else { } else {
@@ -223,125 +234,157 @@ class Nrf52DfuFlasher {
} }
} }
// return String.fromCharCode(...result);
return result; return result;
} }
// seems to be working as expected, was hard to test /**
frameToHciPacket(frame) { * Creates an HCI packet from the provided frame data.
* https://github.com/adafruit/Adafruit_nRF52_nrfutil/blob/master/nordicsemi/dfu/dfu_transport_serial.py#L332
* @param frame
* @returns {*[]}
*/
createHciPacketFromFrame(frame) {
this.sequence_number = (this.sequence_number + 1) % 8; // increase sequence number, but roll over at 8
this.sequenceNumber = (this.sequenceNumber + 1) % 8;
const slip_bytes = this.slipPartsToFourBytes( // create slip header
this.sequence_number, const slipHeaderBytes = this.createSlipHeader(
this.sequenceNumber,
this.DATA_INTEGRITY_CHECK_PRESENT, this.DATA_INTEGRITY_CHECK_PRESENT,
this.RELIABLE_PACKET, this.RELIABLE_PACKET,
this.HCI_PACKET_TYPE, this.HCI_PACKET_TYPE,
frame.length, frame.length,
); );
let tempData = [ // create packet data
...slip_bytes, let data = [
...slipHeaderBytes,
...frame, ...frame,
]; ];
// Add escape characters // add crc of data
const crc = this.calcCrc16(new Uint8Array(tempData), 0xffff); const crc = this.calcCrc16(new Uint8Array(data), 0xffff);
tempData.push(crc & 0xFF) data.push(crc & 0xFF);
tempData.push((crc & 0xFF00) >> 8) data.push((crc & 0xFF00) >> 8);
// add escape characters
return [ return [
0xc0, 0xc0,
...this.slipEncodeEscChars(tempData), ...this.slipEncodeEscChars(data),
0xc0, 0xc0,
]; ];
} }
get_erase_wait_time() { /**
// timeout is not least than 0.5 seconds * Calculate how long we should wait for erasing data.
* @returns {number}
*/
getEraseWaitTime() {
// always wait at least 0.5 seconds
return Math.max(0.5, ((this.total_size / this.FLASH_PAGE_SIZE) + 1) * this.FLASH_PAGE_ERASE_TIME); return Math.max(0.5, ((this.total_size / this.FLASH_PAGE_SIZE) + 1) * this.FLASH_PAGE_ERASE_TIME);
} }
// frame seems to be fine /**
async send_start_dfu(mode, softdevice_size = 0, bootloader_size = 0, app_size = 0){ * Constructs the image size packet sent in the DFU Start packet.
* @param softdeviceSize
* @param bootloaderSize
* @param appSize
* @returns {number[]}
*/
createImageSizePacket(softdeviceSize = 0, bootloaderSize = 0, appSize = 0) {
return [
...this.int32ToBytes(softdeviceSize),
...this.int32ToBytes(bootloaderSize),
...this.int32ToBytes(appSize),
];
}
/**
* Sends the DFU Start packet to the device.
* @param mode
* @param softdevice_size
* @param bootloader_size
* @param app_size
* @returns {Promise<void>}
*/
async sendStartDfu(mode, softdevice_size = 0, bootloader_size = 0, app_size = 0){
// create frame
const frame = [ const frame = [
...this.toBytesInt32(this.DFU_START_PACKET), ...this.int32ToBytes(this.DFU_START_PACKET),
...this.toBytesInt32(mode), ...this.int32ToBytes(mode),
...this.create_image_size_packet(softdevice_size, bootloader_size, app_size), ...this.createImageSizePacket(softdevice_size, bootloader_size, app_size),
]; ];
await this.send_packet(this.frameToHciPacket(frame)); // send hci packet
await this.sendPacket(this.createHciPacketFromFrame(frame));
// remember file sizes for calculating erase wait time
this.sd_size = softdevice_size; this.sd_size = softdevice_size;
this.total_size = softdevice_size + bootloader_size + app_size; this.total_size = softdevice_size + bootloader_size + app_size;
await new Promise((resolve, reject) => { // wait for initial erase
setTimeout(resolve, this.get_erase_wait_time() * 1000); await this.sleepMillis(this.getEraseWaitTime() * 1000);
});
} }
async send_init_packet(init_packet){ /**
* Sends the DFU Init packet to the device.
* @param initPacket
* @returns {Promise<void>}
*/
async sendInitPacket(initPacket){
// create frame
const frame = [ const frame = [
...this.toBytesInt32(this.DFU_INIT_PACKET), ...this.int32ToBytes(this.DFU_INIT_PACKET),
...init_packet, ...initPacket,
...this.toBytesInt16(0x0000), // Padding required ...this.int16ToBytes(0x0000), // padding required
]; ];
await this.send_packet(this.frameToHciPacket(frame)); // send hci packet
await this.sendPacket(this.createHciPacketFromFrame(frame));
} }
async send_firmware(firmware) { /**
* Sends the firmware file to the device in multiple chunks.
* @param firmware
* @returns {Promise<void>}
*/
async sendFirmware(firmware) {
const frames = []; const packets = [];
// seems to be chunking properly // chunk firmware into separate packets
for(let i = 0; i < firmware.length; i += this.DFU_PACKET_MAX_SIZE){ for(let i = 0; i < firmware.length; i += this.DFU_PACKET_MAX_SIZE){
frames.push(this.frameToHciPacket([ packets.push(this.createHciPacketFromFrame([
...this.toBytesInt32(this.DFU_DATA_PACKET), ...this.int32ToBytes(this.DFU_DATA_PACKET),
...firmware.slice(i, i + this.DFU_PACKET_MAX_SIZE), ...firmware.slice(i, i + this.DFU_PACKET_MAX_SIZE),
])); ]));
} }
// todo rename to packet? // send each packet one after the other
for(var i = 0; i < frames.length; i++){ for(var i = 0; i < packets.length; i++){
const frame = frames[i]; // send packet
await this.sendPacket(packets[i]);
await this.send_packet(frame); // wait a bit to allow device to write before sending next packet
await this.sleepMillis(this.FLASH_PAGE_WRITE_TIME * 1000);
// wait a bit to allow device to write before sending next frame
await new Promise((resolve, reject) => {
setTimeout(resolve, this.FLASH_PAGE_WRITE_TIME * 1000);
});
} }
// Wait for last page to write // finished sending firmware, send DFU Stop Data packet
await new Promise((resolve, reject) => { await this.sendPacket(this.createHciPacketFromFrame([
setTimeout(resolve, this.FLASH_PAGE_WRITE_TIME * 1000); ...this.int32ToBytes(this.DFU_STOP_DATA_PACKET),
});
// Send data stop packet
await this.send_packet(this.frameToHciPacket([
...this.toBytesInt32(this.DFU_STOP_DATA_PACKET),
])); ]));
} }
async send_validate_firmware() {
// no op for usb
}
async send_activate_firmware() {
// no op for usb
}
/** /**
* Creates a SLIP header. * Creates a SLIP header.
* *
@@ -355,8 +398,7 @@ class Nrf52DfuFlasher {
* @param {number} pktLen - Packet length * @param {number} pktLen - Packet length
* @return {Uint8Array} - SLIP header * @return {Uint8Array} - SLIP header
*/ */
// confirmed working createSlipHeader(seq, dip, rp, pktType, pktLen) {
slipPartsToFourBytes(seq, dip, rp, pktType, pktLen) {
let ints = [0, 0, 0, 0]; let ints = [0, 0, 0, 0];
ints[0] = seq | (((seq + 1) % 8) << 3) | (dip << 6) | (rp << 7); ints[0] = seq | (((seq + 1) % 8) << 3) | (dip << 6) | (rp << 7);
ints[1] = pktType | ((pktLen & 0x000F) << 4); ints[1] = pktType | ((pktLen & 0x000F) << 4);
@@ -365,17 +407,12 @@ class Nrf52DfuFlasher {
return new Uint8Array(ints); return new Uint8Array(ints);
} }
// confirmed working /**
create_image_size_packet(softdevice_size = 0, bootloader_size = 0, app_size = 0) { * Converts the provided int32 to 4 bytes.
return [ * @param num
...this.toBytesInt32(softdevice_size), * @returns {number[]}
...this.toBytesInt32(bootloader_size), */
...this.toBytesInt32(app_size), int32ToBytes(num){
];
}
// confirmed working
toBytesInt32(num){
return [ return [
(num & 0x000000ff), (num & 0x000000ff),
(num & 0x0000ff00) >> 8, (num & 0x0000ff00) >> 8,
@@ -384,10 +421,14 @@ class Nrf52DfuFlasher {
]; ];
} }
// confirmed working /**
toBytesInt16(num){ * Converts the provided int16 to 2 bytes.
* @param num
* @returns {number[]}
*/
int16ToBytes(num){
return [ return [
num & 0x00FF, (num & 0x00FF),
(num & 0xFF00) >> 8, (num & 0xFF00) >> 8,
]; ];
} }

View File

@@ -1,7 +1,5 @@
class RNode { class RNode {
static BAUD_RATE = 115200;
KISS_FEND = 0xC0; KISS_FEND = 0xC0;
KISS_FESC = 0xDB; KISS_FESC = 0xDB;
KISS_TFEND = 0xDC; KISS_TFEND = 0xDC;
@@ -60,16 +58,25 @@ class RNode {
HASH_TYPE_TARGET_FIRMWARE = 0x01; HASH_TYPE_TARGET_FIRMWARE = 0x01;
HASH_TYPE_FIRMWARE = 0x02; HASH_TYPE_FIRMWARE = 0x02;
constructor() { constructor(serialPort) {
this.readable = null; this.serialPort = serialPort;
this.writable = null; this.readable = serialPort.readable;
this.writable = serialPort.writable;
} }
static fromSerialPort(port) { static async fromSerialPort(serialPort) {
const rnode = new RNode();
rnode.readable = port.readable; // open port
rnode.writable = port.writable; await serialPort.open({
return rnode; baudRate: 115200,
});
return new RNode(serialPort);
}
async close() {
await this.serialPort.close();
} }
async write(bytes) { async write(bytes) {

61
todo.txt Normal file
View File

@@ -0,0 +1,61 @@
rnode.device_probe()
rnode.download_eeprom()
if rnode.provisioned and rnode.signature_valid:
This device is already installed and provisioned. No further action will
if rnode.detected:
The device seems to have an RNode firmware installed, but it was not provisioned correctly, or it is corrupt
We are going to reinstall the correct firmware and provision it.
else
It looks like this is a fresh device with no RNode firmware.
selected_product = ROM.PRODUCT_RAK4631
selected_platform = None
selected_model = None
selected_mcu = ROM.MCU_NRF52
print("\nWhat band is this RAK4631 for?\n")
print("[1] 433 MHz")
selected_model = ROM.MODEL_11
selected_platform = ROM.PLATFORM_NRF52
print("[2] 868 MHz")
print("[3] 915 MHz")
print("[4] 923 MHz")
selected_model = ROM.MODEL_12
selected_platform = ROM.PLATFORM_NRF52
fw_filename = models[selected_model][4]
if fw_filename == None:
Sorry, no firmware for your board currently exists.
args.key = True
args.port = selected_port.device
args.platform = selected_platform
args.hwrev = 1
mapped_model = selected_model
mapped_product = selected_product
args.update = False
args.flash = True
ensure_firmware_file(fw_filename)
get or generate device signing key (rns identity is used)
get or generate eeprom signing key (rsa private key is generated)
get partition hash (sha256 of firmware file for rak)
extract firmware zip folder
get flasher call
adafruit-nrfutil dfu serial --package fw_filename -p args.port -b 115200 -t 1200
adafruit-nrfutil dfu serial --package ~/Downloads/rnode_firmware_rak4631.zip -p /dev/cu.usbmodem14401 -b 115200 -t 1200
--package dfu filename
-p comport
-b baud rate
-t Open port with specified baud then close it, before uploading
https://github.com/adafruit/Adafruit_nRF52_nrfutil/blob/master/nordicsemi/__main__.py
https://github.com/adafruit/Adafruit_nRF52_nrfutil/blob/master/nordicsemi/dfu/dfu_transport_serial.py#L49
https://github.com/markqvist/Reticulum/discussions/471