Skip to content

Commit

Permalink
Merge pull request #26 from microbit-foundation/new-device
Browse files Browse the repository at this point in the history
Add support for MicroPython for the new micro:bit
  • Loading branch information
microbit-carlos authored Nov 24, 2020
2 parents cb2393c + c8d43bf commit 5361a6b
Show file tree
Hide file tree
Showing 20 changed files with 54,904 additions and 519 deletions.
2 changes: 1 addition & 1 deletion docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ nav_order: 1
# micro:bit Filesystem
{: .fs-9 }

<img alt="microbit-fs logo" src="img/microbit-fs-logo.png" style="max-height: 100px; float: left; padding-right: 16px;">
<img alt="microbit-fs logo" src="img/microbit-fs-logo.png" style="max-height: 125px; float: left; padding-right: 16px;">

Manipulate files in a micro:bit MicroPython Intel Hex file.
{: .fs-6 .fw-300 }
Expand Down
50 changes: 39 additions & 11 deletions docs/quick-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Initialise a File System instance with a MicroPython Intel Hex string and start
```js
// Create a new FileSystem instance passing the MicroPython Intel Hex string
var micropythonFs = new microbitFs.MicropythonFsHex(IntelHexStr);
// There are some options available in the constructor
micropythonFs = new microbitFs.MicropythonFsHex(IntelHexStr, { maxFsSize: 20 * 1024});

// Import files from a different MicroPython hex file with filesystem
var addedFilenames = micropythonFs.importFilesFromIntelHex(UploadedHexWithUserFiles);
Expand Down Expand Up @@ -45,7 +47,31 @@ var intelHexStrWithFs = micropythonFs.getIntelHex();
var intelHexBytesWithFs = micropythonFs.getIntelHexBytes();
```

Public interface can be found in the `src/fs-interface.ts` file.
Using multiple MicroPython Intel Hex files to generate a Universal Hex:

```js
// Create a new FileSystem instance passing the MicroPython Intel Hex string
var micropythonFs = new microbitFs.MicropythonFsHex([
{ hex: uPy1HexFile, boardId: 0x9900 },
{ hex: uPy2HexFile, boardId: 0x9903 },
]);;

// Import files from a different MicroPython Intel hex file with filesystem
var addedFilenames = micropythonFs.importFilesFromIntelHex(UploadedHexWithUserFiles);
addedFilenames = micropythonFs.importFilesFromIntelHex(UploadedHexWithUserFiles, {overwrite: false, formatFirst: false});

// Generate a new Intel hex string or Uint8Array with MicroPython and the files
var uPy1IntelHexStrWithFs = micropythonFs.getIntelHex(0x9900);
var uPy1IntelHexBytesWithFs = micropythonFs.getIntelHexBytes(0x9900);
var uPy2IntelHexStrWithFs = micropythonFs.getIntelHex(0x9903);
var uPy2IntelHexBytesWithFs = micropythonFs.getIntelHexBytes(0x9903);

// Generate a new Universal hex string with all MicroPython+files data
var universalHexStrWithFs = micropythonFs.getUniversalHex();
```

The `MicropythonFsHex` class public interface can be found in the
`src/fs-interface.ts` file.

### Append and extract Python code from known flash location
To add and remove the Python code using the old format:
Expand All @@ -57,16 +83,18 @@ if (microbitFs.isAppendedScriptPresent(finalHexStr)) {
}
```

### Read UICR data
### Read Device Memory Info data

```js
var uicrData = getIntelHexUicrData(IntelHexStr);
console.log('Flash Page Size:' + uicrData.flashPageSize);
console.log('Flash Size:' + uicrData.flashSize);
console.log('Runtime Start Page:' + uicrData.runtimeStartPage);
console.log('Runtime Start Address:' + uicrData.runtimeStartAddress);
console.log('Runtime End Used:' + uicrData.runtimeEndUsed);
console.log('Runtime End Address:' + uicrData.runtimeEndAddress);
console.log('Version Address:' + uicrData.versionAddress);
console.log('Version: ' + uicrData.version);
var deviceMemInfoData = getIntelHexDeviceMemInfo(IntelHexStr);
console.log('Flash Page Size:' + deviceMemInfoData.flashPageSize);
console.log('Flash Size:' + deviceMemInfoData.flashSize);
console.log('Flash Start Address:' + deviceMemInfoData.flashStartAddress);
console.log('Flash End Address:' + deviceMemInfoData.flashEndAddress);
console.log('Runtime Start Address:' + deviceMemInfoData.runtimeStartAddress);
console.log('Runtime End Address:' + deviceMemInfoData.runtimeEndAddress);
console.log('Filesystem Start Address:' + deviceMemInfoData.fsStartAddress);
console.log('Filesystem End Address:' + deviceMemInfoData.fsEndAddress);
console.log('MicroPython Version:' + deviceMemInfoData.uPyVersion);
console.log('Device Version: ' + deviceMemInfoData.deviceVersion);
```
9 changes: 7 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"tslib": ">=1.9.0"
},
"dependencies": {
"@microbit/microbit-universal-hex": "0.2.1",
"nrf-intel-hex": "1.3.0",
"text-encoder-lite": "2.0.0"
},
Expand Down
112 changes: 103 additions & 9 deletions src/__tests__/common.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,15 @@
* (c) 2019 Micro:bit Educational Foundation and the microbit-fs contributors.
* SPDX-License-Identifier: MIT
*/
import { bytesToStr, strToBytes } from '../common';
import {
bytesToStr,
strToBytes,
concatUint8Array,
areUint8ArraysEqual,
} from '../common';

describe(`strToBytes`, () => {
it(`works with 1 byte characters`, () => {
describe('strToBytes', () => {
it('works with 1 byte characters', () => {
const testString = 'test';
const testCodes = [116, 101, 115, 116];

Expand All @@ -15,7 +20,8 @@ describe(`strToBytes`, () => {
expect(tester.next().value).toEqual(code);
}
});
it(`works with 2 byte characters`, () => {

it('works with 2 byte characters', () => {
const testString = 'Ση';
const testCodes = [206, 163, 206, 183];

Expand All @@ -25,7 +31,8 @@ describe(`strToBytes`, () => {
expect(tester.next().value).toEqual(code);
}
});
it(`works with 3 byte characters`, () => {

it('works with 3 byte characters', () => {
const testString = '世';
const testCodes = [228, 184, 150];

Expand All @@ -37,20 +44,107 @@ describe(`strToBytes`, () => {
});
});

describe(`bytesToStr`, () => {
it(`works with 1 byte characters`, () => {
describe('bytesToStr', () => {
it('works with 1 byte characters', () => {
const testCodes: Uint8Array = new Uint8Array([116, 101, 115, 116]);

expect(bytesToStr(testCodes)).toEqual('test');
});
it(`works with 2 byte characters`, () => {

it('works with 2 byte characters', () => {
const testCodes: Uint8Array = new Uint8Array([206, 163, 206, 183]);

expect(bytesToStr(testCodes)).toEqual('Ση');
});
it(`works with 3 byte characters`, () => {

it('works with 3 byte characters', () => {
const testCodes: Uint8Array = new Uint8Array([228, 184, 150]);

expect(bytesToStr(testCodes)).toEqual('世');
});
});

describe('concatUint8Array', () => {
it('concatenates correctly', () => {
const firstArray = [116, 101, 115, 116];
const secondArray = [234, 56, 45, 98];
const first: Uint8Array = new Uint8Array(firstArray);
const second: Uint8Array = new Uint8Array(secondArray);

const result1 = concatUint8Array(first, first);
const result2 = concatUint8Array(second, second);
const result3 = concatUint8Array(first, second);

expect(result1).toEqual(new Uint8Array(firstArray.concat(firstArray)));
expect(result2).toEqual(new Uint8Array(secondArray.concat(secondArray)));
expect(result3).toEqual(new Uint8Array(firstArray.concat(secondArray)));
});

it('concatenates correctly empty arrays', () => {
const first: Uint8Array = new Uint8Array([]);
const second: Uint8Array = new Uint8Array([]);

const result = concatUint8Array(first, second);

expect(result).toEqual(new Uint8Array([]));
});

it('concatenates arrays of different length', () => {
const firstArray = [116, 101, 115, 116];
const secondArray = [234, 56, 45, 98, 0];
const first: Uint8Array = new Uint8Array(firstArray);
const second: Uint8Array = new Uint8Array(secondArray);

const result1 = concatUint8Array(first, second);
const result2 = concatUint8Array(second, first);

expect(result1).toEqual(new Uint8Array(firstArray.concat(secondArray)));
expect(result2).toEqual(new Uint8Array(secondArray.concat(firstArray)));
});
});

describe('areUint8ArraysEqual', () => {
it('compares correctly equal arrays', () => {
const first: Uint8Array = new Uint8Array([116, 101, 115, 116]);
const second: Uint8Array = new Uint8Array([116, 101, 115, 116]);

const result1 = areUint8ArraysEqual(first, first);
const result2 = areUint8ArraysEqual(second, second);
const result3 = areUint8ArraysEqual(first, second);

expect(result1).toBeTruthy();
expect(result2).toBeTruthy();
expect(result3).toBeTruthy();
});

it('compares correctly empty arrays', () => {
const first: Uint8Array = new Uint8Array([]);
const second: Uint8Array = new Uint8Array([]);

const result = areUint8ArraysEqual(first, second);

expect(result).toBeTruthy();
});

it('compares arrays of different length', () => {
const first: Uint8Array = new Uint8Array([5, 12, 46]);
const second: Uint8Array = new Uint8Array([5, 12, 46, 0]);

const result1 = areUint8ArraysEqual(first, second);
const result2 = areUint8ArraysEqual(second, first);

expect(result1).toBeFalsy();
expect(result2).toBeFalsy();
});

it('compares different arrays', () => {
const first: Uint8Array = new Uint8Array([1, 2, 3]);
const second: Uint8Array = new Uint8Array([4, 5, 6]);

const result1 = areUint8ArraysEqual(first, second);
const result2 = areUint8ArraysEqual(second, first);

expect(result1).toBeFalsy();
expect(result2).toBeFalsy();
});
});
43 changes: 43 additions & 0 deletions src/__tests__/flash-regions.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* (c) 2019 Micro:bit Educational Foundation and the microbit-fs contributors.
* SPDX-License-Identifier: MIT
*/
import * as fs from 'fs';

import * as flashRegions from '../flash-regions';

describe('Read MicroPython UICR data.', () => {
const uPyHexFile = fs.readFileSync(
'./src/__tests__/upy-v2-beta-region.hex',
'utf8'
);

it('Read MicroPython v2-beta-region hex file flash regions table', () => {
const expectedPageSize = 4096;
const expectedFlashSize = 512 * 1024;
const MicroPythonLastByteUsed = 0x61f24;
const expectedRuntimeEndPage = Math.ceil(
MicroPythonLastByteUsed / expectedPageSize
);
const expectedFsStartAddress = 0x6d000;
const expectedFsEndAddress = 0x73000;
const expectedUpyVersion =
'micro:bit v2.0.99+b260810 on 2020-11-17; ' +
'MicroPython b260810 on 2020-11-17';

const result = flashRegions.getIntelHexFlashRegionsData(uPyHexFile);

expect(result.flashPageSize).toEqual(expectedPageSize);
expect(result.flashSize).toEqual(expectedFlashSize);
expect(result.flashStartAddress).toEqual(0);
expect(result.flashEndAddress).toEqual(expectedFlashSize);
expect(result.runtimeStartAddress).toEqual(0);
expect(result.runtimeEndAddress).toEqual(
expectedRuntimeEndPage * expectedPageSize
);
expect(result.fsStartAddress).toEqual(expectedFsStartAddress);
expect(result.fsEndAddress).toEqual(expectedFsEndAddress);
expect(result.uPyVersion).toEqual(expectedUpyVersion);
expect(result.deviceVersion).toEqual(2);
});
});
Loading

0 comments on commit 5361a6b

Please sign in to comment.