Skip to content

Commit 5007a6a

Browse files
authored
feat(demo): CircuitPython demo (#121)
* Add CircuitPython filesystem functionality * Consolidate MicroPython and CircuitPython demo files * Update README with CircuitPython instructions
1 parent d8b369b commit 5007a6a

File tree

4 files changed

+72
-12
lines changed

4 files changed

+72
-12
lines changed

README.md

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ npm install
3737
npm run start:micropython
3838
```
3939

40-
and enjoy the MicroPython REPL! Quit the REPL with Ctrl+X. A different UF2 image can be loaded by supplying the `--image` option:
40+
and enjoy the MicroPython REPL! Quit the REPL with Ctrl+X. A different MicroPython UF2 image can be loaded by supplying the `--image` option:
4141

4242
```
4343
npm run start:micropython -- --image=my_image.uf2
@@ -53,7 +53,7 @@ For using the MicroPython demo code in tests, the `--expect-text` can come handy
5353

5454
#### Filesystem support
5555

56-
With MicroPython – and probably also CircuitPython – you can use the filesystem on the Pico. This becomes useful as more than one script file is used in your code. Just put a [LittleFS](https://github.com/littlefs-project/littlefs) formatted filesystem image called `littlefs.img` into the rp2040js root directory, and your `main.py` will be automatically started from there.
56+
With MicroPython, you can use the filesystem on the Pico. This becomes useful as more than one script file is used in your code. Just put a [LittleFS](https://github.com/littlefs-project/littlefs) formatted filesystem image called `littlefs.img` into the rp2040js root directory, and your `main.py` will be automatically started from there.
5757

5858
A simple way to create a suitable LittleFS image containing your script files is outlined in [create_littlefs_image.py](https://github.com/tomods/GrinderController/blob/358ad3e0f795d8cc0bdf4f21bb35f806871d433f/tools/create_littlefs_image.py).
5959
So, using [littlefs-python](https://pypi.org/project/littlefs-python/), you can do the following:
@@ -74,6 +74,39 @@ Other ways of creating LittleFS images can be found [here](https://github.com/wo
7474

7575
Currently, the filesystem is not writeable, as the SSI peripheral required for flash writing is not implemented yet. If you're interested in hacking, see the discussion in https://github.com/wokwi/rp2040js/issues/88 for a workaround.
7676

77+
### CircuitPython code
78+
79+
To run the CircuitPython demo, you can follow the directions above for MicroPython, except download [adafruit-circuitpython-raspberry_pi_pico-en_US-8.0.2.uf2](https://adafruit-circuit-python.s3.amazonaws.com/bin/raspberry_pi_pico/en_US/adafruit-circuitpython-raspberry_pi_pico-en_US-8.0.2.uf2) instead of the MicroPython UF2 file. Place it in the rp2040js root directory, then run:
80+
81+
```
82+
npm install
83+
npm run start:circuitpython
84+
```
85+
86+
and start the CircuitPython REPL! The rest of the experience is the same as the MicroPython demo (Ctrl+X to exit, using the `--image` and
87+
`--gdb` options, etc).
88+
89+
#### Filesystem support
90+
91+
For CircuitPython, you can create a FAT12 filesystem in Linux using the `truncate` and `mkfs.vfat` utilities:
92+
93+
```shell
94+
truncate fat12.img -s 1M # make the image file
95+
mkfs.vfat -F12 -S512 fat12.img # create the FAT12 filesystem
96+
```
97+
98+
You can then mount the filesystem image and add files to it:
99+
100+
```shell
101+
mkdir fat12 # create the mounting folder if needed
102+
sudo mount -o loop fat12.img fat12/ # mount the filesystem to the folder
103+
sudo cp code.py fat12/ # copy code.py to the filesystem
104+
sudo umount fat12/ # unmount the filesystem
105+
```
106+
107+
While CircuitPython does not typically use a writeable filesystem, note that this functionality is unavailable (see MicroPython filesystem
108+
support section for more details).
109+
77110
## Learn more
78111

79112
- [Live-coding stream playlist](https://www.youtube.com/playlist?list=PLLomdjsHtJTxT-vdJHwa3z62dFXZnzYBm)

demo/load-flash.ts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,29 @@ const MICROPYTHON_FS_FLASH_START = 0xa0000;
77
const MICROPYTHON_FS_BLOCKSIZE = 4096;
88
const MICROPYTHON_FS_BLOCKCOUNT = 352;
99

10-
export function loadMicropythonFlashImage(filename: string, rp2040: RP2040) {
10+
const CIRCUITPYTHON_FS_FLASH_START = 0x100000;
11+
const CIRCUITPYTHON_FS_BLOCKSIZE = 4096;
12+
const CIRCUITPYTHON_FS_BLOCKCOUNT = 512;
13+
14+
function loadFlashImage(filename: string, rp2040: RP2040, flashStart: number, blockSize: number) {
1115
const file = openSync(filename, 'r');
12-
const buffer = new Uint8Array(MICROPYTHON_FS_BLOCKSIZE);
13-
let flashAddress = MICROPYTHON_FS_FLASH_START;
16+
const buffer = new Uint8Array(blockSize);
17+
let flashAddress = flashStart;
1418
while (readSync(file, buffer) === buffer.length) {
1519
rp2040.flash.set(buffer, flashAddress);
1620
flashAddress += buffer.length;
1721
}
1822
closeSync(file);
1923
}
2024

25+
export function loadMicropythonFlashImage(filename: string, rp2040: RP2040) {
26+
loadFlashImage(filename, rp2040, MICROPYTHON_FS_FLASH_START, MICROPYTHON_FS_BLOCKSIZE);
27+
}
28+
29+
export function loadCircuitpythonFlashImage(filename: string, rp2040: RP2040) {
30+
loadFlashImage(filename, rp2040, CIRCUITPYTHON_FS_FLASH_START, CIRCUITPYTHON_FS_BLOCKSIZE);
31+
}
32+
2133
export function loadUF2(filename: string, rp2040: RP2040) {
2234
const file = openSync(filename, 'r');
2335
const buffer = new Uint8Array(512);

demo/micropython-run.ts

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import { GDBTCPServer } from '../src/gdb/gdb-tcp-server';
33
import { USBCDC } from '../src/usb/cdc';
44
import { ConsoleLogger, LogLevel } from '../src/utils/logging';
55
import { bootromB1 } from './bootrom';
6-
import { loadUF2, loadMicropythonFlashImage } from './load-flash';
6+
import { loadUF2, loadMicropythonFlashImage, loadCircuitpythonFlashImage } from './load-flash';
77
import fs from 'fs';
88
import minimist from 'minimist';
99

@@ -12,20 +12,30 @@ const args = minimist(process.argv.slice(2), {
1212
'image', // UF2 image to load; defaults to "rp2-pico-20210902-v1.17.uf2"
1313
'expect-text', // Text to expect on the serial console, process will exit with code 0 if found
1414
],
15-
boolean: 'gdb', // start GDB server on 3333
15+
boolean: [
16+
'gdb', // start GDB server on 3333
17+
'circuitpython', // use CircuitPython instead of MicroPython
18+
],
1619
});
1720
const expectText = args['expect-text'];
1821

1922
const mcu = new RP2040();
2023
mcu.loadBootrom(bootromB1);
2124
mcu.logger = new ConsoleLogger(LogLevel.Error);
2225

23-
const imageName = args.image ?? 'rp2-pico-20210902-v1.17.uf2';
26+
let imageName: string;
27+
if (!args.circuitpython) {
28+
imageName = args.image ?? 'rp2-pico-20210902-v1.17.uf2';
29+
} else {
30+
imageName = args.image ?? 'adafruit-circuitpython-raspberry_pi_pico-en_US-8.0.2.uf2';
31+
}
2432
console.log(`Loading uf2 image ${imageName}`);
2533
loadUF2(imageName, mcu);
2634

27-
if (fs.existsSync('littlefs.img')) {
35+
if (fs.existsSync('littlefs.img') && !args.circuitpython) {
2836
loadMicropythonFlashImage('littlefs.img', mcu);
37+
} else if (fs.existsSync('fat12.img') && args.circuitpython) {
38+
loadCircuitpythonFlashImage('fat12.img', mcu);
2939
// Instead of reading from file, it would also be possible to generate the LittleFS image on-the-fly here, e.g. using
3040
// https://github.com/wokwi/littlefs-wasm or https://github.com/littlefs-project/littlefs-js
3141
}
@@ -37,9 +47,13 @@ if (args.gdb) {
3747

3848
const cdc = new USBCDC(mcu.usbCtrl);
3949
cdc.onDeviceConnected = () => {
40-
// We send a newline so the user sees the MicroPython prompt
41-
cdc.sendSerialByte('\r'.charCodeAt(0));
42-
cdc.sendSerialByte('\n'.charCodeAt(0));
50+
if (!args.circuitpython) {
51+
// We send a newline so the user sees the MicroPython prompt
52+
cdc.sendSerialByte('\r'.charCodeAt(0));
53+
cdc.sendSerialByte('\n'.charCodeAt(0));
54+
} else {
55+
cdc.sendSerialByte(3);
56+
}
4357
};
4458

4559
let currentLine = '';

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"lint": "eslint . --ext .ts",
3535
"start": "ts-node demo/emulator-run.ts",
3636
"start:micropython": "ts-node demo/micropython-run.ts",
37+
"start:circuitpython": "ts-node demo/micropython-run.ts --circuitpython",
3738
"start:gdbdiff": "ts-node debug/gdbdiff.ts",
3839
"test": "jest"
3940
},

0 commit comments

Comments
 (0)