rpremote 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -0
- data/README.ja.md +30 -46
- data/README.md +30 -47
- data/RELEASING.md +2 -2
- data/THIRD_PARTY_NOTICES.md +1 -1
- data/lib/rpremote/bootsel_command.rb +8 -6
- data/lib/rpremote/build_command.rb +3 -3
- data/lib/rpremote/builder.rb +15 -9
- data/lib/rpremote/cli/filesystem_commands.rb +105 -0
- data/lib/rpremote/cli.rb +20 -105
- data/lib/rpremote/config.rb +6 -5
- data/lib/rpremote/config_show.rb +13 -5
- data/lib/rpremote/deploy_command.rb +85 -55
- data/lib/rpremote/help/dfu_commands.rb +59 -0
- data/lib/rpremote/help/filesystem_commands.rb +36 -0
- data/lib/rpremote/help/project_commands.rb +89 -0
- data/lib/rpremote/help/remote_commands.rb +54 -0
- data/lib/rpremote/help/root_text.rb +63 -0
- data/lib/rpremote/help.rb +27 -300
- data/lib/rpremote/language_source.rb +19 -2
- data/lib/rpremote/mrbgems/definition.rb +116 -0
- data/lib/rpremote/mrbgems/file_writer.rb +26 -0
- data/lib/rpremote/mrbgems/lockfile.rb +131 -0
- data/lib/rpremote/mrbgems.rb +95 -155
- data/lib/rpremote/mrbgems_command.rb +19 -4
- data/lib/rpremote/picoruby_compiler.rb +28 -0
- data/lib/rpremote/picoruby_source_patch.rb +0 -4
- data/lib/rpremote/target.rb +1 -1
- data/lib/rpremote/terminal.rb +0 -2
- data/lib/rpremote/version.rb +1 -1
- data/lib/rpremote.rb +1 -0
- data/patches/picoruby-4.0.4-pwm-sleep-clock.patch +27 -0
- data/sig/rpremote.rbs +20 -4
- data/tasks/firmware_build.rb +10 -2
- metadata +12 -3
- data/patches/picoruby-3.4.5-bootsel.patch +0 -71
- data/patches/picoruby-4.0.3-bootsel.patch +0 -71
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 69cb11c8175c8864e4ae4a11108fb37e1ac08bab49b0b61ade2331f550b7d4b6
|
|
4
|
+
data.tar.gz: 7e32c77e20cda016f4b95ad5e60a5ccabf8a5d8aa1570ce8bcf3fd642b700b9d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f690408489ed84040dd492d4872747ec0a523d17bafc76603c885722c5aaca43a3a5f0d74584ca81f0ec5e7b4758bf0477a17f2877af045c81756894962fd5a8
|
|
7
|
+
data.tar.gz: bd1046210f3d48e00604328f72531455f236bd3e348b2bded6495b2681bf383367413ed2083b1469090d24ce10ab37ce85605454efa867e01c88a351807595aa
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,19 @@ Notable changes to the `rpremote` RubyGem will be documented in this file. Repos
|
|
|
4
4
|
|
|
5
5
|
## Unreleased
|
|
6
6
|
|
|
7
|
+
## 0.7.0 - 2026-10-04
|
|
8
|
+
|
|
9
|
+
- Add Bundler-style `group` blocks and `gem ..., group:` to `Mrbgems`; `mrbgems lock|update --with/--without` now selects the locked firmware contents, with exclusions taking precedence, and build/runtime commands consume `Mrbgems.lock` without selecting groups again.
|
|
10
|
+
- Make `Mrbgems.lock` version 2 a self-contained build input, add path checksum verification, and replace build/runtime `--mrbgems` and `--groups` options with `--lockfile`.
|
|
11
|
+
- Keep active RP2040/RP2350 PWM slices clocked during scheduler sleep on PicoRuby 4.0.4, and restore clock gating after the final slice stops.
|
|
12
|
+
|
|
13
|
+
## 0.6.0 - 2026-09-20
|
|
14
|
+
|
|
15
|
+
- Change the default PicoRuby version to `latest`, backed by the current `master` branch, while retaining `--language-version` for selecting a release tag.
|
|
16
|
+
- Replace the patched R2P2 `bootsel` executable with a temporary PicoModem script that calls `Machine.enter_bootsel` from the embedded `picoruby-bootsel` mrbgem.
|
|
17
|
+
- Support both the legacy `build/host/bin/mrbc` layout and the PicoRuby 4.0.4 `build/mrbc/default/bin/mrbc` layout when building custom firmware.
|
|
18
|
+
- Expand the human-readable executable specifications and validate bilingual documentation structure, links, command coverage, and safety warnings.
|
|
19
|
+
|
|
7
20
|
## 0.5.0 - 2026-09-12
|
|
8
21
|
|
|
9
22
|
- Make `deploy PATH` flash the existing UF2 by default, and add `deploy PATH --build` for the previous build-and-deploy workflow.
|
data/README.ja.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# rpremote
|
|
1
|
+
# rpremote
|
|
2
2
|
|
|
3
3
|
[English](README.md)
|
|
4
4
|
|
|
@@ -26,7 +26,7 @@ gem install rpremote
|
|
|
26
26
|
```sh
|
|
27
27
|
rpremote setup
|
|
28
28
|
rpremote build
|
|
29
|
-
rpremote flash
|
|
29
|
+
rpremote flash
|
|
30
30
|
rpremote run main.rb
|
|
31
31
|
```
|
|
32
32
|
|
|
@@ -39,7 +39,7 @@ rpremote deploy path/to/project
|
|
|
39
39
|
rpremote deploy path/to/project --build
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
既定では`firmware/picoruby-
|
|
42
|
+
既定では`firmware/picoruby-latest/`にソースを準備し、`firmware/picoruby-latest-pico2.uf2`を生成します。対象ボードを明示する必要がある場合は、`rpremote ports`でR2P2のCDC 0ポートを確認してください。
|
|
43
43
|
|
|
44
44
|
## mrbgemを追加する
|
|
45
45
|
|
|
@@ -59,68 +59,52 @@ rpremote mrbgems lock
|
|
|
59
59
|
rpremote build
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
`Mrbgems.lock
|
|
62
|
+
`Mrbgems.lock`は`build`で使うmrbgemを確定します。ビルドは`Mrbgems`を評価せず、GitHub branchも解決せずにlockを読みます。新しいコミットを解決するのは`rpremote mrbgems update`です。
|
|
63
|
+
|
|
64
|
+
構成ごとのgemは`group :development do ... end`または`gem ..., group: :development`で整理できます。`rpremote mrbgems lock --with production --without test`はグループ外の共通gemとproduction gemをlockへ記録します。除外指定が優先され、`build`、`deploy`、`run`、`exec`はそのlockだけを使います。
|
|
63
65
|
|
|
64
66
|
ファームウェアへ組み込む一方で、すべての`run`、`exec`、`deploy`に先行ロードしないgemには`auto_require: false`を指定できます。アプリケーション側から必要なgemを明示的に`require`してください。
|
|
65
67
|
|
|
66
68
|
## 対象を選択する
|
|
67
69
|
|
|
68
70
|
```sh
|
|
69
|
-
rpremote setup
|
|
70
|
-
rpremote build
|
|
71
|
-
rpremote flash
|
|
71
|
+
rpremote setup
|
|
72
|
+
rpremote build
|
|
73
|
+
rpremote flash
|
|
72
74
|
```
|
|
73
75
|
|
|
74
76
|
コマンドラインオプションは`config/setting.json`より優先されます。現在実装されているのはPicoRubyです。将来のMicroPythonと追加Picoボード対応に備え、`language`と`board`はインターフェースに残しています。
|
|
75
77
|
|
|
76
|
-
##
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
| `rpremote deploy PATH` | 既存ファームウェアを書き込み、存在する場合は`PATH/lib/NAME`を`:/lib/NAME`へコピーしてから`PATH/main.rb`を一時実行します。ハードウェア出力は次のコマンドまで維持されます。 |
|
|
85
|
-
| `rpremote deploy PATH --build` | ファームウェアをビルドして書き込んだ後、同じコピーと一時実行を行います。 |
|
|
86
|
-
| `rpremote dfu app FILE` | PicoModem DFUでRubyまたは版を照合したバイトコードのアプリを更新します。 |
|
|
87
|
-
| `rpremote dfu compile FILE` | DFU用にPicoRuby版と一致する`.mrb`を生成します。 |
|
|
88
|
-
| `rpremote dfu status` | DFUのアクティブおよび起動候補スロットを表示します。 |
|
|
89
|
-
| `rpremote dfu remove` | DFU起動アプリを両スロットから削除します。実行中のアプリを停止するには別途リセットします。 |
|
|
90
|
-
| `rpremote mrbgems …` | mrbgemを検査、表示、固定、更新します。 |
|
|
91
|
-
| `rpremote flash` | 選択したUF2をBOOTSEL経由で書き込みます。 |
|
|
92
|
-
| `rpremote bootsel --reset-flash-memory` | BOOTSELへ移行し、Pico 2の外部フラッシュメモリ全体を消去します。 |
|
|
93
|
-
| `rpremote config show` | 設定ファイルとコマンドラインオプションを反映した実効設定を表示します。 |
|
|
94
|
-
| `rpremote ports` | R2P2シリアルポートを表示します。 |
|
|
95
|
-
| `rpremote run FILE` | Rubyファイルを転送して実行します。ディレクトリ指定時は`main.rb`を実行し、出力をリアルタイム表示します。タイムアウトは無出力の継続時間として扱い、Ruby例外時は非0で終了します。`--reset-on-timeout`を指定すると実行タイムアウト後にR2P2をリセットします。 |
|
|
96
|
-
| `rpremote exec CODE` | 短いRubyコードを実行します。Ruby例外時は非0で終了します。 |
|
|
97
|
-
| `rpremote monitor` / `repl` | 対話型シリアルセッションを開きます。 |
|
|
98
|
-
| `rpremote reset` | R2P2を再起動して再接続まで待ちます。 |
|
|
99
|
-
| `rpremote fs cp/push/cat/ls/rm/mkdir` | R2P2ファイルシステムを操作します。 |
|
|
100
|
-
|
|
101
|
-
コマンド一覧は`rpremote --help`で確認できます。コマンド固有の構文、既定値、影響は`rpremote <command> --help`で確認できます。
|
|
78
|
+
## 作業を選ぶ
|
|
79
|
+
|
|
80
|
+
- `setup`でプロジェクトを準備し、`config show`で実効設定を確認します。最初のファームウェア導入には`build`と`flash`を使います。
|
|
81
|
+
- プロジェクト開発では`deploy PATH`を使います。選択したファームウェアを書き込み、存在する場合は`PATH/lib/NAME`をコピーして`PATH/main.rb`を実行します。先にファームウェアを再ビルドする場合は`--build`を付けます。
|
|
82
|
+
- Rubyを一時実行する場合は`run`または`exec`、対話型シリアル接続には`monitor`または`repl`を使います。`monitor`と`repl`は`Ctrl-]`で終了します。
|
|
83
|
+
- R2P2上へファイルを保持する場合は`fs`、再起動後も実行するA/B起動アプリには`dfu`を使います。
|
|
84
|
+
|
|
85
|
+
完全なコマンド一覧は`rpremote --help`で確認します。現在の構文、既定値、処理順、影響についてはコマンドヘルプが実行可能なリファレンスです。
|
|
102
86
|
|
|
103
87
|
```sh
|
|
104
|
-
rpremote
|
|
88
|
+
rpremote deploy --help
|
|
105
89
|
rpremote dfu app --help
|
|
90
|
+
rpremote fs cp --help
|
|
106
91
|
```
|
|
107
92
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
`run`と`exec`の例外終了コードには、Ruby例外ステータスに対応したR2P2ファームウェアが必要です。[GitHubリポジトリ](https://github.com/ogom/rpremote)のPicoRubyソースから`rpremote build`で生成したUF2が対応しています。
|
|
111
|
-
|
|
112
|
-
## 操作モデル
|
|
93
|
+
### 安全上の境界
|
|
113
94
|
|
|
114
|
-
- `
|
|
115
|
-
- `
|
|
116
|
-
- `
|
|
117
|
-
- `
|
|
118
|
-
- `dfu remove`はDFUのA/B両アプリスロットを完全に空にします。RAM上ですでに動作しているアプリは`rpremote reset`を実行するまで継続するため、起動アプリのログを混ぜずに`rpremote run`を使う場合は両方のコマンドを実行します。その他の`/home`ファイルとR2P2ファームウェアは削除しません。
|
|
119
|
-
- リモートパスには`:/REMOTE/PATH`を使います。`fs cp`はローカルパスとリモートパスの間で転送します。`fs push LOCAL_DIR :/REMOTE_DIR`は`fs cp --recursive`の別名で、不足しているリモートディレクトリを作成し、ローカルディレクトリの内容を一括転送します。リモートにだけ存在するファイルは削除しません。`fs rm`は指定したリモートパスを完全に削除します。
|
|
95
|
+
- `flash`は永続的なR2P2ファームウェアを置き換えます。`bootsel --reset-flash-memory`はPico 2の外部フラッシュ全体を消去するため、実行後にR2P2を再度書き込む必要があります。
|
|
96
|
+
- `dfu remove`はDFUのA/B両アプリスロットを完全に空にします。RAM上ですでに動作しているアプリを停止するには、別途リセットします。
|
|
97
|
+
- `fs rm`は指定したリモートパスを完全に削除します。再帰転送ではボード上だけに存在するファイルを削除しません。
|
|
98
|
+
- `run`と`exec`は一時リモートファイルを削除します。Ruby例外時の非0終了には対応するR2P2ファームウェアが必要で、このリポジトリからビルドしたUF2は対応しています。
|
|
120
99
|
|
|
121
100
|
## ドキュメントとサンプル
|
|
122
101
|
|
|
123
|
-
[
|
|
102
|
+
- [作業に応じてコマンドを選ぶ](https://github.com/ogom/rpremote/blob/main/docs/command.ja.md)
|
|
103
|
+
- [プロジェクトを設定する](https://github.com/ogom/rpremote/blob/main/docs/config.ja.md)
|
|
104
|
+
- [カスタムファームウェアをビルドする](https://github.com/ogom/rpremote/blob/main/docs/firmware.ja.md)
|
|
105
|
+
- [MrbgemsとMrbgems.lockを管理する](https://github.com/ogom/rpremote/blob/main/docs/mrbgems.ja.md)
|
|
106
|
+
- [PicoModem DFUで起動アプリを更新する](https://github.com/ogom/rpremote/blob/main/docs/dfu.ja.md)
|
|
107
|
+
- [電子工作サンプルを見る](https://github.com/ogom/rpremote/tree/main/examples)
|
|
124
108
|
|
|
125
109
|
## 関連プロジェクト
|
|
126
110
|
|
data/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# rpremote
|
|
1
|
+
# rpremote
|
|
2
2
|
|
|
3
3
|
[日本語](README.ja.md)
|
|
4
4
|
|
|
@@ -26,7 +26,7 @@ Run these commands in a project directory:
|
|
|
26
26
|
```sh
|
|
27
27
|
rpremote setup
|
|
28
28
|
rpremote build
|
|
29
|
-
rpremote flash
|
|
29
|
+
rpremote flash
|
|
30
30
|
rpremote run main.rb
|
|
31
31
|
```
|
|
32
32
|
|
|
@@ -39,7 +39,7 @@ rpremote deploy path/to/project
|
|
|
39
39
|
rpremote deploy path/to/project --build
|
|
40
40
|
```
|
|
41
41
|
|
|
42
|
-
The defaults prepare `firmware/picoruby-
|
|
42
|
+
The defaults prepare `firmware/picoruby-latest/` and create `firmware/picoruby-latest-pico2.uf2`. Use `rpremote ports` to locate the R2P2 CDC 0 port when a board must be selected explicitly.
|
|
43
43
|
|
|
44
44
|
## Add mrbgems
|
|
45
45
|
|
|
@@ -59,69 +59,52 @@ rpremote mrbgems lock
|
|
|
59
59
|
rpremote build
|
|
60
60
|
```
|
|
61
61
|
|
|
62
|
-
`Mrbgems.lock` pins
|
|
62
|
+
`Mrbgems.lock` pins the exact mrbgems used by `build`. Builds read the lock without evaluating `Mrbgems` or resolving GitHub branches; `rpremote mrbgems update` deliberately resolves new commits.
|
|
63
|
+
|
|
64
|
+
Use `group :development do ... end` blocks or `gem ..., group: :development` to organize variant-specific gems. `rpremote mrbgems lock --with production --without test` writes common and production gems to the lock; exclusions take precedence, and `build`, `deploy`, `run`, and `exec` then use exactly that lock.
|
|
63
65
|
|
|
64
66
|
Set `auto_require: false` for a gem that should remain embedded in firmware without being loaded before every `run`, `exec`, or `deploy`. Require that gem explicitly from the application when needed.
|
|
65
67
|
|
|
66
68
|
## Select a target
|
|
67
69
|
|
|
68
70
|
```sh
|
|
69
|
-
rpremote setup
|
|
70
|
-
rpremote build
|
|
71
|
-
rpremote flash
|
|
71
|
+
rpremote setup
|
|
72
|
+
rpremote build
|
|
73
|
+
rpremote flash
|
|
72
74
|
```
|
|
73
75
|
|
|
74
76
|
Command-line options override `config/setting.json`. PicoRuby is implemented today; `language` and `board` are retained for planned MicroPython and additional Pico board support.
|
|
75
77
|
|
|
76
|
-
##
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
| `rpremote deploy PATH` | Flash existing firmware, copy `PATH/lib/NAME` to `:/lib/NAME` when present, then temporarily run `PATH/main.rb` while preserving its hardware output until the next command. |
|
|
85
|
-
| `rpremote deploy PATH --build` | Build and flash firmware, then perform the same copy and temporary run workflow. |
|
|
86
|
-
| `rpremote dfu app FILE` | Stage a Ruby or version-checked bytecode app through PicoModem DFU. |
|
|
87
|
-
| `rpremote dfu compile FILE` | Compile `.rb` to matching PicoRuby bytecode for DFU. |
|
|
88
|
-
| `rpremote dfu status` | Show the active and candidate DFU slots. |
|
|
89
|
-
| `rpremote dfu remove` | Remove both DFU boot applications; reset separately to stop one already running. |
|
|
90
|
-
| `rpremote mrbgems …` | Check, list, lock, or update mrbgems. |
|
|
91
|
-
| `rpremote flash` | Flash the selected UF2 through BOOTSEL. |
|
|
92
|
-
| `rpremote bootsel --reset-flash-memory` | Enter BOOTSEL and erase all Pico 2 external flash memory. |
|
|
93
|
-
| `rpremote config show` | Show the effective configuration after file and command-line options are resolved. |
|
|
94
|
-
| `rpremote ports` | List detected R2P2 serial ports. |
|
|
95
|
-
| `rpremote run FILE` | Upload and run a Ruby file, or `main.rb` when FILE is a directory, with real-time output; exit nonzero on a Ruby exception. The timeout measures idle time without output. Use `--reset-on-timeout` to reset R2P2 after a run timeout. |
|
|
96
|
-
| `rpremote exec CODE` | Run short Ruby code and exit nonzero on a Ruby exception. |
|
|
97
|
-
| `rpremote monitor` / `repl` | Open an interactive serial session. |
|
|
98
|
-
| `rpremote reset` | Reboot R2P2 and wait for reconnection. |
|
|
99
|
-
| `rpremote fs cp/push/cat/ls/rm/mkdir` | Operate on the R2P2 filesystem. |
|
|
100
|
-
|
|
101
|
-
Run `rpremote --help` for the complete command list. Run `rpremote <command> --help` for command-specific syntax, defaults, and effects.
|
|
78
|
+
## Choose a workflow
|
|
79
|
+
|
|
80
|
+
- Prepare a project with `setup`, inspect resolved settings with `config show`, then use `build` and `flash` for the first firmware installation.
|
|
81
|
+
- Use `deploy PATH` during project development. It flashes the selected firmware, copies `PATH/lib/NAME` when present, and runs `PATH/main.rb`; add `--build` when the firmware must be rebuilt first.
|
|
82
|
+
- Use `run` or `exec` for temporary Ruby execution, and `monitor` or `repl` for an interactive serial session. `monitor` and `repl` exit with `Ctrl-]`.
|
|
83
|
+
- Use `fs` commands for persistent R2P2 files, and use `dfu` commands when an A/B boot application must survive a restart.
|
|
84
|
+
|
|
85
|
+
Run `rpremote --help` for the complete command list. Command help is the executable reference for current syntax, defaults, processing order, and effects.
|
|
102
86
|
|
|
103
87
|
```sh
|
|
104
|
-
rpremote
|
|
88
|
+
rpremote deploy --help
|
|
105
89
|
rpremote dfu app --help
|
|
90
|
+
rpremote fs cp --help
|
|
106
91
|
```
|
|
107
92
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
Ruby-exception exit statuses for `run` and `exec` require R2P2 firmware with Ruby exception status support.
|
|
111
|
-
UF2 files built with `rpremote build` from the [GitHub repository](https://github.com/ogom/rpremote) include that support.
|
|
112
|
-
|
|
113
|
-
## Operation model
|
|
93
|
+
### Safety boundaries
|
|
114
94
|
|
|
115
|
-
- `
|
|
116
|
-
- `
|
|
117
|
-
- `
|
|
118
|
-
- `
|
|
119
|
-
- `dfu remove` permanently clears both DFU A/B application slots. The application already loaded in RAM continues until you run `rpremote reset`; use both commands before `rpremote run` when boot-app output would be unwanted. It does not remove other `/home` files or R2P2 firmware.
|
|
120
|
-
- Remote paths use `:/REMOTE/PATH`. `fs cp` transfers between one local and one remote path. `fs push LOCAL_DIR :/REMOTE_DIR` is an alias of `fs cp --recursive`; it creates missing remote directories and uploads the local directory contents. It does not delete remote files. `fs rm` permanently deletes the selected remote path.
|
|
95
|
+
- `flash` replaces persistent R2P2 firmware. `bootsel --reset-flash-memory` erases all Pico 2 external flash and requires R2P2 to be flashed again.
|
|
96
|
+
- `dfu remove` permanently clears both DFU A/B application slots. Reset separately to stop an application already running in RAM.
|
|
97
|
+
- `fs rm` permanently deletes the selected remote path. Recursive uploads do not delete files that exist only on the board.
|
|
98
|
+
- `run` and `exec` remove their temporary remote file. Their nonzero Ruby-exception status requires compatible R2P2 firmware; UF2 files built from this repository include that support.
|
|
121
99
|
|
|
122
100
|
## Documentation and examples
|
|
123
101
|
|
|
124
|
-
|
|
102
|
+
- [Choose commands by workflow](https://github.com/ogom/rpremote/blob/main/docs/command.md)
|
|
103
|
+
- [Configure a project](https://github.com/ogom/rpremote/blob/main/docs/config.md)
|
|
104
|
+
- [Build custom firmware](https://github.com/ogom/rpremote/blob/main/docs/firmware.md)
|
|
105
|
+
- [Manage Mrbgems and Mrbgems.lock](https://github.com/ogom/rpremote/blob/main/docs/mrbgems.md)
|
|
106
|
+
- [Update a boot application with PicoModem DFU](https://github.com/ogom/rpremote/blob/main/docs/dfu.md)
|
|
107
|
+
- [Browse electronic-craft examples](https://github.com/ogom/rpremote/tree/main/examples)
|
|
125
108
|
|
|
126
109
|
## Related projects
|
|
127
110
|
|
data/RELEASING.md
CHANGED
|
@@ -49,7 +49,7 @@ bundle exec rake release
|
|
|
49
49
|
After the tag exists on GitHub, create a GitHub Release and attach the exact gem that passed validation. `--verify-tag` prevents GitHub CLI from silently creating a tag at another commit:
|
|
50
50
|
|
|
51
51
|
```sh
|
|
52
|
-
gh release create v0.
|
|
52
|
+
gh release create v0.7.0 rpremote-0.7.0.gem --verify-tag --generate-notes
|
|
53
53
|
```
|
|
54
54
|
|
|
55
|
-
Replace `0.
|
|
55
|
+
Replace `0.7.0` in both places for later versions. Finally, install from RubyGems.org in a fresh environment and run `rpremote --version`.
|
data/THIRD_PARTY_NOTICES.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Third-Party Notices
|
|
2
2
|
|
|
3
|
-
`rpremote` does not bundle R2P2 firmware. The `setup` command downloads
|
|
3
|
+
`rpremote` does not bundle R2P2 firmware. The `setup` command downloads and prepares the selected PicoRuby/R2P2 source archive from the PicoRuby project.
|
|
4
4
|
|
|
5
5
|
`setup` also downloads Raspberry Pi's `nuke_universal.uf2` from the official Pico SDK prebuilts release. It is used only by `rpremote bootsel --reset-flash-memory` to erase external flash memory.
|
|
6
6
|
|
|
@@ -7,6 +7,8 @@ module Rpremote
|
|
|
7
7
|
SHELL_READY_TIMEOUT = 2.0
|
|
8
8
|
RETRY_INTERVAL = 0.25
|
|
9
9
|
RESET_FLASH_FIRMWARE = File.join("firmware", "nuke_universal.uf2").freeze
|
|
10
|
+
REMOTE_SCRIPT_PATH = "/home/.rpremote-bootsel.rb"
|
|
11
|
+
REMOTE_SCRIPT = "require \"bootsel\"\nMachine.enter_bootsel\n".b.freeze
|
|
10
12
|
|
|
11
13
|
class Error < Rpremote::Error; end
|
|
12
14
|
|
|
@@ -47,7 +49,8 @@ module Rpremote
|
|
|
47
49
|
|
|
48
50
|
request_bootsel(
|
|
49
51
|
port: port, baud: baud, deadline: deadline, output: output,
|
|
50
|
-
serial: serial, device: device, shell: shell,
|
|
52
|
+
serial: serial, device: device, shell: shell, modem: services.fetch(:modem) { PicoModem },
|
|
53
|
+
sleeper: sleeper, clock: clock
|
|
51
54
|
)
|
|
52
55
|
|
|
53
56
|
remaining = deadline - clock.call
|
|
@@ -66,6 +69,7 @@ module Rpremote
|
|
|
66
69
|
serial = context.fetch(:serial)
|
|
67
70
|
device = context.fetch(:device)
|
|
68
71
|
shell = context.fetch(:shell)
|
|
72
|
+
modem = context.fetch(:modem) { PicoModem }
|
|
69
73
|
sleeper = context.fetch(:sleeper)
|
|
70
74
|
clock = context.fetch(:clock)
|
|
71
75
|
announced = false
|
|
@@ -84,11 +88,9 @@ module Rpremote
|
|
|
84
88
|
|
|
85
89
|
remote_shell = shell.new(connection, timeout: [remaining, SHELL_READY_TIMEOUT].min)
|
|
86
90
|
remote_shell.synchronize!
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
remote_shell.send_command("bootsel")
|
|
91
|
+
modem.new(connection, timeout: remaining).upload(REMOTE_SCRIPT_PATH, REMOTE_SCRIPT)
|
|
92
|
+
remote_shell.synchronize!
|
|
93
|
+
remote_shell.send_command("./#{File.basename(REMOTE_SCRIPT_PATH)}")
|
|
92
94
|
requested = true
|
|
93
95
|
end
|
|
94
96
|
break if requested
|
|
@@ -19,7 +19,7 @@ module Rpremote
|
|
|
19
19
|
board: Target::DEFAULT_BOARD,
|
|
20
20
|
cache_dir: defaults.fetch(:cache, Target::DEFAULT_CACHE_DIR),
|
|
21
21
|
firmware: defaults[:firmware],
|
|
22
|
-
|
|
22
|
+
mrbgems_lock: defaults[:mrbgems_lock]
|
|
23
23
|
}.merge(defaults.except(:cache))
|
|
24
24
|
OptionParser.new do |parser|
|
|
25
25
|
parser.on("--language LANGUAGE") { |value| options[:language] = value }
|
|
@@ -27,8 +27,8 @@ module Rpremote
|
|
|
27
27
|
parser.on("--board BOARD") { |value| options[:board] = value }
|
|
28
28
|
parser.on("--firmware FILE") { |value| options[:firmware] = value }
|
|
29
29
|
parser.on("--cache DIR") { |value| options[:cache_dir] = value }
|
|
30
|
-
parser.on("--
|
|
31
|
-
parser.on("--no-mrbgems") { options[:
|
|
30
|
+
parser.on("--lockfile FILE") { |value| options[:mrbgems_lock] = value }
|
|
31
|
+
parser.on("--no-mrbgems") { options[:mrbgems_lock] = false }
|
|
32
32
|
end.parse!(args)
|
|
33
33
|
raise ArgumentError, "build does not accept arguments" unless args.empty?
|
|
34
34
|
|
data/lib/rpremote/builder.rb
CHANGED
|
@@ -71,12 +71,12 @@ module Rpremote
|
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def add_mrbgems_environment!(environment, options, source_dir, output)
|
|
74
|
-
|
|
75
|
-
return unless
|
|
74
|
+
lock_file = mrbgems_lock(options[:mrbgems_lock])
|
|
75
|
+
return unless lock_file
|
|
76
76
|
|
|
77
|
-
manager = mrbgems_class.new(
|
|
77
|
+
manager = mrbgems_class.new(lock_path: lock_file, cwd: root)
|
|
78
78
|
config_language = mrbgems_config_language(
|
|
79
|
-
manager.
|
|
79
|
+
manager.locked_vm, options.fetch(:language), options.fetch(:language_version)
|
|
80
80
|
)
|
|
81
81
|
config_name = "r2p2-#{config_language}-#{options.fetch(:board)}"
|
|
82
82
|
base_config = File.join(source_dir, "build_config", "#{config_name}.rb")
|
|
@@ -90,25 +90,31 @@ module Rpremote
|
|
|
90
90
|
environment["RPREMOTE_CONFIG_NAME"] = config_name
|
|
91
91
|
environment["RPREMOTE_MRUBY_CONFIG"] = overlay.path
|
|
92
92
|
environment["RPREMOTE_MRBGEMS_FINGERPRINT"] = overlay.fingerprint
|
|
93
|
-
output.puts("using Mrbgems: #{manager.path}")
|
|
94
93
|
output.puts("using Mrbgems.lock: #{manager.lock_path}")
|
|
95
94
|
end
|
|
96
95
|
|
|
97
96
|
def mrbgems_config_language(vm_name, language, version)
|
|
98
97
|
return language unless vm_name
|
|
99
98
|
|
|
100
|
-
modern = Gem::Version.new(version) >= Gem::Version.new("4.0.0")
|
|
99
|
+
modern = version == "latest" || Gem::Version.new(version) >= Gem::Version.new("4.0.0")
|
|
101
100
|
return modern ? "femtoruby" : "picoruby" if vm_name == :mrubyc
|
|
102
101
|
|
|
103
102
|
modern ? "picoruby" : "microruby"
|
|
104
103
|
end
|
|
105
104
|
|
|
106
|
-
def
|
|
105
|
+
def mrbgems_lock(option)
|
|
107
106
|
return if option == false
|
|
108
107
|
|
|
109
|
-
candidate = File.expand_path(option || Mrbgems::
|
|
108
|
+
candidate = File.expand_path(option || Mrbgems::DEFAULT_LOCK_PATH, root)
|
|
110
109
|
return candidate if File.file?(candidate)
|
|
111
|
-
raise Error, "mrbgems
|
|
110
|
+
raise Error, "mrbgems lock file does not exist: #{candidate}" if option
|
|
111
|
+
|
|
112
|
+
definition = File.join(root, Mrbgems::DEFAULT_PATH)
|
|
113
|
+
if File.file?(definition)
|
|
114
|
+
raise Error,
|
|
115
|
+
"Mrbgems.lock does not exist: #{candidate}; " \
|
|
116
|
+
"run `rpremote mrbgems lock` before building"
|
|
117
|
+
end
|
|
112
118
|
|
|
113
119
|
nil
|
|
114
120
|
end
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rpremote
|
|
4
|
+
class CLI
|
|
5
|
+
module FilesystemCommands
|
|
6
|
+
private
|
|
7
|
+
|
|
8
|
+
def fs(args)
|
|
9
|
+
subcommand = args.shift
|
|
10
|
+
recursive = subcommand == "cp" && (args.delete("--recursive") || args.delete("-r"))
|
|
11
|
+
options = parse_connection_options(args)
|
|
12
|
+
case subcommand
|
|
13
|
+
when "cp"
|
|
14
|
+
copy(args, options, recursive: recursive)
|
|
15
|
+
when "push"
|
|
16
|
+
copy(args, options, recursive: true, command: "push")
|
|
17
|
+
when "cat"
|
|
18
|
+
cat(args, options)
|
|
19
|
+
when "ls", "rm", "mkdir"
|
|
20
|
+
filesystem_shell_command(subcommand, args, options)
|
|
21
|
+
else
|
|
22
|
+
raise ArgumentError, "unknown fs command: #{subcommand || "(none)"}"
|
|
23
|
+
end
|
|
24
|
+
rescue Shell::TimeoutError => e
|
|
25
|
+
raise Shell::TimeoutError, "filesystem connection failed: #{e.message}"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def copy(args, options, recursive: false, command: "cp")
|
|
29
|
+
usage = command == "push" ? "rpremote fs push LOCAL_DIR :/REMOTE_DIR" : "rpremote fs cp SOURCE DESTINATION"
|
|
30
|
+
raise ArgumentError, "usage: #{usage} [options]" unless args.length == 2
|
|
31
|
+
|
|
32
|
+
source, destination = args
|
|
33
|
+
source_remote = RemotePath.remote?(source)
|
|
34
|
+
destination_remote = RemotePath.remote?(destination)
|
|
35
|
+
raise ArgumentError, "exactly one cp path must be remote (prefix remote paths with :)" if source_remote == destination_remote
|
|
36
|
+
return RecursiveCopy.new(output: stdout, serial: serial, device: device).call(source, destination, options) if recursive
|
|
37
|
+
|
|
38
|
+
ensure_filesystem_connection!(options)
|
|
39
|
+
if source_remote
|
|
40
|
+
data = with_modem(options) { |modem| modem.download(RemotePath.unwrap(source)) }
|
|
41
|
+
File.binwrite(local_destination(destination, source), data)
|
|
42
|
+
stdout.puts("downloaded #{data.bytesize} bytes: #{source} -> #{destination}")
|
|
43
|
+
else
|
|
44
|
+
data = File.binread(source)
|
|
45
|
+
with_modem(options) { |modem| modem.upload(RemotePath.unwrap(destination), data) }
|
|
46
|
+
stdout.puts("uploaded #{data.bytesize} bytes: #{source} -> #{destination}")
|
|
47
|
+
end
|
|
48
|
+
rescue Errno::ENOENT => e
|
|
49
|
+
raise ArgumentError, e.message
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def cat(args, options)
|
|
53
|
+
raise ArgumentError, "usage: rpremote fs cat :/REMOTE/PATH [options]" unless args.length == 1
|
|
54
|
+
raise ArgumentError, "cat path must be remote (prefix it with :)" unless RemotePath.remote?(args.first)
|
|
55
|
+
|
|
56
|
+
stdout.write(with_modem(options) { |modem| modem.download(RemotePath.unwrap(args.first)) })
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def filesystem_shell_command(command, args, options)
|
|
60
|
+
usage = "usage: rpremote fs #{command} :/REMOTE/PATH [options]"
|
|
61
|
+
raise ArgumentError, usage unless args.length == 1
|
|
62
|
+
|
|
63
|
+
path = RemotePath.validate(args.first)
|
|
64
|
+
stdout.puts("deleting remote path permanently: #{path}") if command == "rm"
|
|
65
|
+
output = with_shell(options) do |shell|
|
|
66
|
+
shell.execute("#{command} #{Shell.quote_argument(path)}")
|
|
67
|
+
end
|
|
68
|
+
ensure_filesystem_success!(command, output)
|
|
69
|
+
stdout.write(output)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def ensure_filesystem_success!(command, output)
|
|
73
|
+
failed = command == "ls" ? output.start_with?("ls:") : !output.empty?
|
|
74
|
+
raise Shell::CommandError, output.strip if failed
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def ensure_filesystem_connection!(options)
|
|
78
|
+
output = with_shell(options) { |shell| shell.execute("ls '/'") }
|
|
79
|
+
ensure_filesystem_success!("ls", output)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def with_modem(options)
|
|
83
|
+
port_path = device.main_port(options[:port])
|
|
84
|
+
serial.open(port_path, baud: options[:baud]) do |port|
|
|
85
|
+
yield PicoModem.new(port, timeout: options[:timeout])
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def with_shell(options)
|
|
90
|
+
port_path = device.main_port(options[:port])
|
|
91
|
+
serial.open(port_path, baud: options[:baud]) do |port|
|
|
92
|
+
shell = Shell.new(port, timeout: options[:timeout])
|
|
93
|
+
shell.synchronize!
|
|
94
|
+
yield shell
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def local_destination(destination, source)
|
|
99
|
+
return destination unless File.directory?(destination)
|
|
100
|
+
|
|
101
|
+
File.join(destination, File.basename(RemotePath.unwrap(source)))
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|