Skip to content

Commit ea51f98

Browse files
upy-fs-builder: Add function to send several files at once to write to fs.
This will be much faster than the correct method to send individual files. This is because individual files convert the Intel Hex string to a memory map and then back to a string for each file.
1 parent 7583f22 commit ea51f98

File tree

4 files changed

+82
-36
lines changed

4 files changed

+82
-36
lines changed

src/__tests__/micropython-fs-builder.spec.ts

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,10 @@ import * as fs from 'fs';
22

33
import MemoryMap from 'nrf-intel-hex';
44

5-
import { bytesToStr, strToBytes } from '../common';
5+
import { strToBytes } from '../common';
66
import {
77
addIntelHexFile,
8+
addIntelHexFiles,
89
getIntelHexFiles,
910
testResetFileSystem,
1011
} from '../micropython-fs-builder';
@@ -146,16 +147,11 @@ describe('Writing files to the filesystem.', () => {
146147
const shortData = shortMap.get(0x3c900);
147148

148149
testResetFileSystem();
149-
let fwWithFsOther = addIntelHexFile(
150-
uPyHexFile,
151-
files[0].fileName,
152-
strToBytes(files[0].fileStr)
153-
);
154-
fwWithFsOther = addIntelHexFile(
155-
fwWithFsOther,
156-
files[1].fileName,
157-
strToBytes(files[1].fileStr)
158-
);
150+
const filesObj: { [filename: string]: Uint8Array } = {};
151+
filesObj[files[0].fileName] = strToBytes(files[0].fileStr);
152+
filesObj[files[1].fileName] = strToBytes(files[1].fileStr);
153+
154+
const fwWithFsOther = addIntelHexFiles(uPyHexFile, filesObj);
159155
// fs.writeFileSync('./ignore/output2.hex', fwWithFsOther);
160156

161157
const opMap = MemoryMap.fromHex(fwWithFsOther);

src/__tests__/micropython-fs-hex.spec.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import * as fsBuilder from '../micropython-fs-builder';
66
import { MicropythonFsHex } from '../micropython-fs-hex';
77

88
// Mock Spy
9-
const addIntelHexFileSpy = jest.spyOn(fsBuilder, 'addIntelHexFile');
9+
const addIntelHexFilesSpy = jest.spyOn(fsBuilder, 'addIntelHexFiles');
1010

1111
// MicroPython hex file for testing
1212
const uPyHexFile = fs.readFileSync('./src/__tests__/upy-v1.0.1.hex', 'utf8');
@@ -327,7 +327,7 @@ describe('Test other.', () => {
327327

328328
describe('Test hex generation.', () => {
329329
beforeEach(() => {
330-
addIntelHexFileSpy.mockReset();
330+
addIntelHexFilesSpy.mockReset();
331331
});
332332

333333
it('getIntelHex called with constructor hex string.', () => {
@@ -336,8 +336,8 @@ describe('Test hex generation.', () => {
336336

337337
const returnedIntelHex = microbitFs.getIntelHex();
338338

339-
expect(addIntelHexFileSpy.mock.calls.length).toEqual(1);
340-
expect(addIntelHexFileSpy.mock.calls[0][0]).toBe(uPyHexFile);
339+
expect(addIntelHexFilesSpy.mock.calls.length).toEqual(1);
340+
expect(addIntelHexFilesSpy.mock.calls[0][0]).toBe(uPyHexFile);
341341
});
342342

343343
it('getIntelHex called with argument hex string.', () => {
@@ -347,8 +347,8 @@ describe('Test hex generation.', () => {
347347

348348
const returnedIntelHex = microbitFs.getIntelHex(falseHex);
349349

350-
expect(addIntelHexFileSpy.mock.calls.length).toEqual(1);
351-
expect(addIntelHexFileSpy.mock.calls[0][0]).toBe(falseHex);
350+
expect(addIntelHexFilesSpy.mock.calls.length).toEqual(1);
351+
expect(addIntelHexFilesSpy.mock.calls[0][0]).toBe(falseHex);
352352
});
353353
});
354354

@@ -384,7 +384,7 @@ describe('Test importing files from hex.', () => {
384384
};
385385

386386
beforeEach(() => {
387-
addIntelHexFileSpy.mockReset();
387+
addIntelHexFilesSpy.mockReset();
388388
});
389389

390390
const createHexStrWithFiles = (): string => {
@@ -449,8 +449,8 @@ describe('Test importing files from hex.', () => {
449449
micropythonFs.importFilesFromIntelHex(hexStrWithFiles);
450450
const returnedIntelHex = micropythonFs.getIntelHex();
451451

452-
expect(addIntelHexFileSpy.mock.calls.length).toEqual(3);
453-
expect(addIntelHexFileSpy.mock.calls[0][0]).toBe(uPyHexFile);
452+
expect(addIntelHexFilesSpy.mock.calls.length).toEqual(1);
453+
expect(addIntelHexFilesSpy.mock.calls[0][0]).toBe(uPyHexFile);
454454
});
455455

456456
it('Constructor hex file with files to import thorws an error.', () => {

src/micropython-fs-builder.ts

Lines changed: 58 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -273,28 +273,26 @@ class FsFile {
273273
}
274274

275275
/**
276-
* Adds a byte array as a file in the MicroPython filesystem.
276+
* Adds a byte array as a file to a MicroPython Memory Map.
277277
*
278278
* @throws {Error} When the invalid file name is given.
279279
* @throws {Error} When the the file doesn't have any data.
280280
* @throws {Error} When there are issues calculating the file system boundaries.
281281
* @throws {Error} When there is no space left for the file.
282282
*
283-
* @param intelHex - MicroPython Intel Hex string.
283+
* @param intelHexMap - Memory map for the MicroPython Intel Hex.
284284
* @param filename - Name for the file.
285285
* @param data - Byte array for the file data.
286-
* @returns MicroPython Intel Hex string with the file in the filesystem.
286+
* @returns MicroPython Memory map with the file in the filesystem.
287287
*/
288-
function addIntelHexFile(
289-
intelHex: string,
288+
function addMemMapFile(
289+
intelHexMap: MemoryMap,
290290
filename: string,
291291
data: Uint8Array
292-
): string {
292+
): MemoryMap {
293293
if (!filename) throw new Error('File has to have a file name.');
294294
if (!data.length) throw new Error(`File ${filename} has to contain data.`);
295295

296-
const intelHexClean = cleanseOldHexFormat(intelHex);
297-
const intelHexMap: MemoryMap = MemoryMap.fromHex(intelHexClean);
298296
const freeChunks = getFreeChunks(intelHexMap);
299297
if (freeChunks.length === 0) {
300298
throw new Error('There is no storage space left.');
@@ -305,6 +303,57 @@ function addIntelHexFile(
305303
const fileFsBytes = fsFile.getFsBytes(freeChunks);
306304
intelHexMap.set(chunksStartAddress, fileFsBytes);
307305
setPersistentPage(intelHexMap);
306+
return intelHexMap;
307+
}
308+
309+
/**
310+
* Adds a byte array as a file in the MicroPython filesystem.
311+
*
312+
* @throws {Error} When the invalid file name is given.
313+
* @throws {Error} When the the file doesn't have any data.
314+
* @throws {Error} When there are issues calculating the file system boundaries.
315+
* @throws {Error} When there is no space left for the file.
316+
*
317+
* @param intelHex - MicroPython Intel Hex string.
318+
* @param filename - Name for the file.
319+
* @param data - Byte array for the file data.
320+
* @returns MicroPython Intel Hex string with the file in the filesystem.
321+
*/
322+
function addIntelHexFile(
323+
intelHex: string,
324+
filename: string,
325+
data: Uint8Array
326+
): string {
327+
// filename and data checked in addMemMapFile
328+
const intelHexClean = cleanseOldHexFormat(intelHex);
329+
let intelHexMap: MemoryMap = MemoryMap.fromHex(intelHexClean);
330+
intelHexMap = addMemMapFile(intelHexMap, filename, data);
331+
return intelHexMap.asHexString() + '\n';
332+
}
333+
334+
/**
335+
* Adds a hash table of filenames and byte arrays as files to the MicroPython
336+
* filesystem.
337+
*
338+
* @throws {Error} When the an invalid file name is given.
339+
* @throws {Error} When the a file doesn't have any data.
340+
* @throws {Error} When there are issues calculating the file system boundaries.
341+
* @throws {Error} When there is no space left for a file.
342+
*
343+
* @param intelHex - MicroPython Intel Hex string.
344+
* @param files - Hash table with filenames as the key and byte arrays as the
345+
* value.
346+
* @returns MicroPython Intel Hex string with the file in the filesystem.
347+
*/
348+
function addIntelHexFiles(
349+
intelHex: string,
350+
files: { [filename: string]: Uint8Array }
351+
): string {
352+
const intelHexClean = cleanseOldHexFormat(intelHex);
353+
let intelHexMap: MemoryMap = MemoryMap.fromHex(intelHexClean);
354+
Object.keys(files).forEach((filename) => {
355+
intelHexMap = addMemMapFile(intelHexMap, filename, files[filename]);
356+
});
308357
return intelHexMap.asHexString() + '\n';
309358
}
310359

@@ -408,4 +457,4 @@ function getIntelHexFiles(
408457
return files;
409458
}
410459

411-
export { addIntelHexFile, getIntelHexFiles };
460+
export { addIntelHexFile, addIntelHexFiles, getIntelHexFiles };

src/micropython-fs-hex.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/** Manage files in a MicroPython hex file. */
22
import { FsInterface } from './fs-interface';
3-
import { addIntelHexFile, getIntelHexFiles } from './micropython-fs-builder';
3+
import { addIntelHexFiles, getIntelHexFiles } from './micropython-fs-builder';
44
import { SimpleFile } from './simple-file';
55

66
export class MicropythonFsHex implements FsInterface {
@@ -204,19 +204,20 @@ export class MicropythonFsHex implements FsInterface {
204204
* Generate a new copy of the MicroPython Intel Hex with the filesystem
205205
* included.
206206
*
207-
* @throws {Error} When the file doesn't have any data.
207+
* @throws {Error} When a file doesn't have any data.
208208
* @throws {Error} When there are issues calculating file system boundaries.
209-
* @throws {Error} When there is no space left for the file.
209+
* @throws {Error} When there is no space left for a file.
210210
*
211211
* @param intelHex - Optionally provide a different Intel Hex to include the
212212
* filesystem into.
213-
* @returns A new Intel Hex string with the filesystem included.
213+
* @returns A new string with MicroPython and the filesystem included.
214214
*/
215215
getIntelHex(intelHex?: string): string {
216-
let finalHex = intelHex || this._intelHex;
216+
const finalHex = intelHex || this._intelHex;
217+
const files: { [filename: string]: Uint8Array } = {};
217218
Object.values(this._files).forEach((file) => {
218-
finalHex = addIntelHexFile(finalHex, file.filename, file.getBytes());
219+
files[file.filename] = file.getBytes();
219220
});
220-
return finalHex;
221+
return addIntelHexFiles(finalHex, files);
221222
}
222223
}

0 commit comments

Comments
 (0)