rpremote 0.3.0 → 0.5.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 +14 -4
- data/README.ja.md +7 -3
- data/README.md +7 -3
- data/RELEASING.md +6 -5
- data/lib/rpremote/cli.rb +8 -0
- data/lib/rpremote/deploy_command.rb +15 -11
- data/lib/rpremote/help.rb +4 -2
- data/lib/rpremote/mrbgems.rb +37 -17
- data/lib/rpremote/picoruby_source_patch.rb +3 -1
- data/lib/rpremote/version.rb +1 -1
- data/patches/picoruby-4.0.3-pwm-sleep-clock.patch +22 -0
- data/sig/rpremote.rbs +2 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4eb2ee018d6af469de77f435dd2a7d7021ae6e017d078655d5a7ca06e0735ac7
|
|
4
|
+
data.tar.gz: 547f6b9d2c98deab27f1a67b9b37bd375a2c0bbfbb55e7f1a1faca156de67ada
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c732178d037299500ee01e6a9ba0dfbe3836372e543be0db1a2e156586043f153a8fdf45f47d435390996b9a840e399a3140c65e3159d16ca9302018308003a4
|
|
7
|
+
data.tar.gz: fcca0bbaf3d04fd352fcd9ec00dbf08217c77dd23f2228cdfb17940d094d0c815d4bef14320d24641abb30a8dd6cdd8ce32858146bb3866f6e45f03d3f1f0089
|
data/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Notable changes to the `rpremote` RubyGem will be documented in this file. Repository-level examples, local mrbgems, and support files are documented in the [repository changelog](../../CHANGELOG.md).
|
|
4
|
+
|
|
5
|
+
## Unreleased
|
|
6
|
+
|
|
7
|
+
## 0.5.0 - 2026-09-12
|
|
8
|
+
|
|
9
|
+
- Make `deploy PATH` flash the existing UF2 by default, and add `deploy PATH --build` for the previous build-and-deploy workflow.
|
|
10
|
+
- Keep the RP2350 PWM clock running during scheduler sleep after PWM initialization, preventing buzzer and other PWM output from pausing between scheduler ticks on PicoRuby 4.0.3.
|
|
11
|
+
- Add `auto_require: false` to `Mrbgems` entries so a gem can remain embedded in firmware without being prepended to every `run`, `exec`, and `deploy` source.
|
|
12
|
+
|
|
13
|
+
## 0.4.0 - 2026-08-31
|
|
14
|
+
|
|
15
|
+
- Check R2P2 filesystem connectivity before non-recursive `fs cp` transfers, and report Shell synchronization timeouts as filesystem connection failures.
|
|
4
16
|
|
|
5
17
|
## 0.3.0 - 2026-08-28
|
|
6
18
|
|
|
@@ -15,13 +27,11 @@ All notable changes to this project will be documented in this file.
|
|
|
15
27
|
- Read mrbgem `require_name` values from `Mrbgems.lock` and automatically prepend the corresponding `require` calls to `run`, `exec`, and `deploy`; allow `Mrbgems` entries to specify `require:` explicitly.
|
|
16
28
|
- Change `flash` to accept an explicit UF2 only through `--firmware FILE`; positional UF2 arguments are no longer supported.
|
|
17
29
|
- Improve RP2350 BOOTSEL flashing on macOS by accepting the expected `ENXIO` volume-detach race after a successful copy.
|
|
18
|
-
- Add PicoRuby mrbgem examples for BMI270, HC-SR04 temperature, MAX30102, MPU6050, and WS2812 SPI, plus oximeter and Processing project examples.
|
|
19
30
|
|
|
20
31
|
## 0.2.0 - 2026-08-26
|
|
21
32
|
|
|
22
33
|
- Make `run` and `exec` exit nonzero when compatible R2P2 firmware reports a Ruby exception, while preserving real-time program output.
|
|
23
34
|
- Increase the default command timeout from 10 to 20 seconds.
|
|
24
|
-
- Add a bilingual education example for practical PicoModem DFU application updates, startup confirmation, and A/B-slot rollback.
|
|
25
35
|
|
|
26
36
|
## 0.1.0 - 2026-08-24
|
|
27
37
|
|
|
@@ -31,7 +41,7 @@ All notable changes to this project will be documented in this file.
|
|
|
31
41
|
- Add PicoModem DFU staging, status, compatible bytecode compilation, and A/B-slot rollback support for Ruby and `.mrb` applications.
|
|
32
42
|
- Add binary-safe file transfer and remote filesystem commands, plus `run`, `exec`, `monitor`, `repl`, and reset with reconnect waiting.
|
|
33
43
|
- Add macOS R2P2 serial-port detection for Raspberry Pi Pico 2 and Pico 2 W.
|
|
34
|
-
- Add bilingual
|
|
44
|
+
- Add bilingual package, configuration, firmware, mrbgem, and DFU documentation.
|
|
35
45
|
- Add RBS signatures, automated tests, macOS CI, and release validation with isolated gem installation and CLI smoke testing.
|
|
36
46
|
|
|
37
47
|
### Limitations
|
data/README.ja.md
CHANGED
|
@@ -32,10 +32,11 @@ rpremote run main.rb
|
|
|
32
32
|
|
|
33
33
|
`setup`はRaspberry Pi公式のリセット用`nuke_universal.uf2`も`firmware/`へダウンロードします。
|
|
34
34
|
|
|
35
|
-
再利用するRubyコードを`lib/NAME`へ置くプロジェクトでは、`deploy
|
|
35
|
+
再利用するRubyコードを`lib/NAME`へ置くプロジェクトでは、`deploy`が既存ファームウェアを書き込み、そのディレクトリをR2P2へコピーしてからエントリーファイルを一時実行します。`--build`を付けると、同じ処理の前にファームウェアをビルドします。
|
|
36
36
|
|
|
37
37
|
```sh
|
|
38
38
|
rpremote deploy path/to/project
|
|
39
|
+
rpremote deploy path/to/project --build
|
|
39
40
|
```
|
|
40
41
|
|
|
41
42
|
既定では`firmware/picoruby-4.0.3/`にソースを準備し、`firmware/picoruby-4.0.3-pico2.uf2`を生成します。対象ボードを明示する必要がある場合は、`rpremote ports`でR2P2のCDC 0ポートを確認してください。
|
|
@@ -60,6 +61,8 @@ rpremote build
|
|
|
60
61
|
|
|
61
62
|
`Mrbgems.lock`はGitHubのコミットとローカルgemの内容ハッシュを固定します。`build`は既存のlockを再利用し、`rpremote mrbgems update`だけが新しいコミットを解決します。
|
|
62
63
|
|
|
64
|
+
ファームウェアへ組み込む一方で、すべての`run`、`exec`、`deploy`に先行ロードしないgemには`auto_require: false`を指定できます。アプリケーション側から必要なgemを明示的に`require`してください。
|
|
65
|
+
|
|
63
66
|
## 対象を選択する
|
|
64
67
|
|
|
65
68
|
```sh
|
|
@@ -78,7 +81,8 @@ rpremote flash --language picoruby --language-version 3.4.2 --board pico2 --moun
|
|
|
78
81
|
| `rpremote build` | mrbgemを含むカスタムUF2をビルドします。 |
|
|
79
82
|
| `rpremote build clean` | 中間ビルドファイルを削除します。 |
|
|
80
83
|
| `rpremote bootsel` | 実行中のR2P2へBOOTSEL移行を要求し、USBボリュームの出現を待ちます。 |
|
|
81
|
-
| `rpremote deploy PATH` |
|
|
84
|
+
| `rpremote deploy PATH` | 既存ファームウェアを書き込み、存在する場合は`PATH/lib/NAME`を`:/lib/NAME`へコピーしてから`PATH/main.rb`を一時実行します。ハードウェア出力は次のコマンドまで維持されます。 |
|
|
85
|
+
| `rpremote deploy PATH --build` | ファームウェアをビルドして書き込んだ後、同じコピーと一時実行を行います。 |
|
|
82
86
|
| `rpremote dfu app FILE` | PicoModem DFUでRubyまたは版を照合したバイトコードのアプリを更新します。 |
|
|
83
87
|
| `rpremote dfu compile FILE` | DFU用にPicoRuby版と一致する`.mrb`を生成します。 |
|
|
84
88
|
| `rpremote dfu status` | DFUのアクティブおよび起動候補スロットを表示します。 |
|
|
@@ -108,7 +112,7 @@ rpremote dfu app --help
|
|
|
108
112
|
## 操作モデル
|
|
109
113
|
|
|
110
114
|
- `run`と`exec`はRubyコードを一時的に転送・実行して出力を表示し、一時リモートファイルを削除します。対応するR2P2ファームウェアがRuby例外を報告した場合は、非0で終了します。
|
|
111
|
-
- `deploy PATH
|
|
115
|
+
- `deploy PATH`はBOOTSELへ移行して既存の選択済みファームウェアを書き込んだ後、R2P2 Shellの起動完了を待ちます。存在する場合は`PATH/lib/NAME`を`:/lib/NAME`へコピーし、実行直前に読み込んだ`PATH/main.rb`を一時実行します。`deploy PATH --build`は同じ処理の前にファームウェアをビルドします。Shellジョブを保持するため、ハードウェア出力は次のコマンドまで維持されます。正常終了と出力バイト数を表示し、R2P2のRuby例外はコマンド失敗として扱います。ライブラリディレクトリがない場合、コピー処理はスキップします。PicoRuby 4系のファームウェアが必要です。
|
|
112
116
|
- `flash`はUF2をRP2350 BOOTSELボリュームへコピーし、永続的なR2P2ファームウェアを置き換えます。
|
|
113
117
|
- `dfu app`はRubyソースまたは対応するバイトコードのアプリを非アクティブDFUスロットへ登録します。R2P2を再起動して試行し、正常に起動したアプリは`DFU.confirm`を呼び出します。
|
|
114
118
|
- `dfu remove`はDFUのA/B両アプリスロットを完全に空にします。RAM上ですでに動作しているアプリは`rpremote reset`を実行するまで継続するため、起動アプリのログを混ぜずに`rpremote run`を使う場合は両方のコマンドを実行します。その他の`/home`ファイルとR2P2ファームウェアは削除しません。
|
data/README.md
CHANGED
|
@@ -32,10 +32,11 @@ rpremote run main.rb
|
|
|
32
32
|
|
|
33
33
|
`setup` also downloads the official Raspberry Pi `nuke_universal.uf2` reset firmware into `firmware/`.
|
|
34
34
|
|
|
35
|
-
For a project that stores reusable Ruby code in `lib/NAME`, `deploy`
|
|
35
|
+
For a project that stores reusable Ruby code in `lib/NAME`, `deploy` flashes the existing firmware, copies that directory to R2P2, and then temporarily runs its entry file. Add `--build` to build the firmware first:
|
|
36
36
|
|
|
37
37
|
```sh
|
|
38
38
|
rpremote deploy path/to/project
|
|
39
|
+
rpremote deploy path/to/project --build
|
|
39
40
|
```
|
|
40
41
|
|
|
41
42
|
The defaults prepare `firmware/picoruby-4.0.3/` and create `firmware/picoruby-4.0.3-pico2.uf2`. Use `rpremote ports` to locate the R2P2 CDC 0 port when a board must be selected explicitly.
|
|
@@ -60,6 +61,8 @@ rpremote build
|
|
|
60
61
|
|
|
61
62
|
`Mrbgems.lock` pins GitHub commits and hashes local gem contents. Existing locks are reused by `build`; `rpremote mrbgems update` deliberately resolves new commits.
|
|
62
63
|
|
|
64
|
+
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
|
+
|
|
63
66
|
## Select a target
|
|
64
67
|
|
|
65
68
|
```sh
|
|
@@ -78,7 +81,8 @@ Command-line options override `config/setting.json`. PicoRuby is implemented tod
|
|
|
78
81
|
| `rpremote build` | Build a custom UF2 with project mrbgems. |
|
|
79
82
|
| `rpremote build clean` | Remove intermediate build files. |
|
|
80
83
|
| `rpremote bootsel` | Ask the running R2P2 firmware to enter BOOTSEL and wait for its USB volume. |
|
|
81
|
-
| `rpremote deploy PATH` |
|
|
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. |
|
|
82
86
|
| `rpremote dfu app FILE` | Stage a Ruby or version-checked bytecode app through PicoModem DFU. |
|
|
83
87
|
| `rpremote dfu compile FILE` | Compile `.rb` to matching PicoRuby bytecode for DFU. |
|
|
84
88
|
| `rpremote dfu status` | Show the active and candidate DFU slots. |
|
|
@@ -109,7 +113,7 @@ UF2 files built with `rpremote build` from the [GitHub repository](https://githu
|
|
|
109
113
|
## Operation model
|
|
110
114
|
|
|
111
115
|
- `run` and `exec` upload Ruby code temporarily, relay output, then remove the temporary remote file. A Ruby exception reported by compatible R2P2 firmware makes the command exit nonzero.
|
|
112
|
-
- `deploy PATH`
|
|
116
|
+
- `deploy PATH` enters BOOTSEL, flashes the existing selected firmware, waits until the R2P2 Shell is ready, copies `PATH/lib/NAME` to `:/lib/NAME` when present, then temporarily runs the current contents of `PATH/main.rb`. `deploy PATH --build` builds that firmware before the same workflow. The Shell job is retained so hardware output remains active until the next command. It reports successful completion and the output byte count; an R2P2 Ruby exception remains a command failure. If the library directory is absent, the copy step is skipped. It requires PicoRuby 4.x firmware.
|
|
113
117
|
- `flash` copies a UF2 to the RP2350 BOOTSEL volume and replaces persistent R2P2 firmware.
|
|
114
118
|
- `dfu app` stages a Ruby source or matching bytecode app in the inactive DFU slot. Restart R2P2 to try it; a successful app must call `DFU.confirm`.
|
|
115
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.
|
data/RELEASING.md
CHANGED
|
@@ -5,9 +5,10 @@ This checklist prepares and publishes one immutable gem version. Run every comma
|
|
|
5
5
|
## 1. Prepare the version
|
|
6
6
|
|
|
7
7
|
1. Update `Rpremote::VERSION` in `lib/rpremote/version.rb`.
|
|
8
|
-
2.
|
|
9
|
-
3.
|
|
10
|
-
4.
|
|
8
|
+
2. Replace `Unreleased` in the package `CHANGELOG.md` with the same version and release date, then add a new empty `Unreleased` section.
|
|
9
|
+
3. If repository-level examples, local mrbgems, or support files changed, finalize the corresponding `Unreleased` section in `../../CHANGELOG.md` with the same release version and date, then add a new empty `Unreleased` section.
|
|
10
|
+
4. Commit all intended files and verify that `git status --short` is empty.
|
|
11
|
+
5. Run the non-publishing release check:
|
|
11
12
|
|
|
12
13
|
```sh
|
|
13
14
|
bundle exec rake release:check
|
|
@@ -48,7 +49,7 @@ bundle exec rake release
|
|
|
48
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:
|
|
49
50
|
|
|
50
51
|
```sh
|
|
51
|
-
gh release create v0.
|
|
52
|
+
gh release create v0.5.0 rpremote-0.5.0.gem --verify-tag --generate-notes
|
|
52
53
|
```
|
|
53
54
|
|
|
54
|
-
Replace `0.
|
|
55
|
+
Replace `0.5.0` in both places for later versions. Finally, install from RubyGems.org in a fresh environment and run `rpremote --version`.
|
data/lib/rpremote/cli.rb
CHANGED
|
@@ -152,6 +152,8 @@ module Rpremote
|
|
|
152
152
|
else
|
|
153
153
|
raise ArgumentError, "unknown fs command: #{subcommand || "(none)"}"
|
|
154
154
|
end
|
|
155
|
+
rescue Shell::TimeoutError => e
|
|
156
|
+
raise Shell::TimeoutError, "filesystem connection failed: #{e.message}"
|
|
155
157
|
end
|
|
156
158
|
|
|
157
159
|
def run_file(args)
|
|
@@ -255,6 +257,7 @@ module Rpremote
|
|
|
255
257
|
raise ArgumentError, "exactly one cp path must be remote (prefix remote paths with :)" if source_remote == destination_remote
|
|
256
258
|
return RecursiveCopy.new(output: stdout, serial: serial, device: device).call(source, destination, options) if recursive
|
|
257
259
|
|
|
260
|
+
ensure_filesystem_connection!(options)
|
|
258
261
|
if source_remote
|
|
259
262
|
data = with_modem(options) { |modem| modem.download(RemotePath.unwrap(source)) }
|
|
260
263
|
File.binwrite(local_destination(destination, source), data)
|
|
@@ -293,6 +296,11 @@ module Rpremote
|
|
|
293
296
|
raise Shell::CommandError, output.strip if failed
|
|
294
297
|
end
|
|
295
298
|
|
|
299
|
+
def ensure_filesystem_connection!(options)
|
|
300
|
+
output = with_shell(options) { |shell| shell.execute("ls '/'") }
|
|
301
|
+
ensure_filesystem_success!("ls", output)
|
|
302
|
+
end
|
|
303
|
+
|
|
296
304
|
def with_modem(options)
|
|
297
305
|
port_path = device.main_port(options[:port])
|
|
298
306
|
serial.open(port_path, baud: options[:baud]) do |port|
|
|
@@ -11,7 +11,7 @@ module Rpremote
|
|
|
11
11
|
|
|
12
12
|
class Error < Rpremote::Error; end
|
|
13
13
|
|
|
14
|
-
# The command intentionally keeps the
|
|
14
|
+
# The command intentionally keeps the deployment stages visible in execution order.
|
|
15
15
|
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
16
16
|
def self.run(args, defaults:, output: $stdout, error: $stderr, services: {})
|
|
17
17
|
options = parse_options(args, defaults)
|
|
@@ -21,7 +21,6 @@ module Rpremote
|
|
|
21
21
|
library, remote_library, source = project_files(project)
|
|
22
22
|
Language.validate!(options[:language])
|
|
23
23
|
|
|
24
|
-
builder = services.fetch(:builder) { Builder.new }
|
|
25
24
|
flasher = services.fetch(:flasher, Flasher)
|
|
26
25
|
serial = services.fetch(:serial, Serial)
|
|
27
26
|
device = services.fetch(:device, Device)
|
|
@@ -29,13 +28,16 @@ module Rpremote
|
|
|
29
28
|
target_options = options.slice(:language, :language_version, :board, :cache_dir, :firmware)
|
|
30
29
|
firmware_path = Target.new(**target_options).firmware_path(root: Dir.pwd)
|
|
31
30
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
if options[:build]
|
|
32
|
+
builder = services.fetch(:builder) { Builder.new }
|
|
33
|
+
output.puts("deploy build: #{firmware_path}")
|
|
34
|
+
builder.build(
|
|
35
|
+
**target_options,
|
|
36
|
+
mrbgems: options[:mrbgems],
|
|
37
|
+
output: output,
|
|
38
|
+
error: error
|
|
39
|
+
)
|
|
40
|
+
end
|
|
39
41
|
|
|
40
42
|
flash_service = flasher.new(timeout: options[:timeout])
|
|
41
43
|
bootsel_mount = resolve_bootsel_mount(options, flash_service, output, services)
|
|
@@ -48,7 +50,7 @@ module Rpremote
|
|
|
48
50
|
port: options[:port]
|
|
49
51
|
)
|
|
50
52
|
|
|
51
|
-
connection_options = options.merge(port: result.port)
|
|
53
|
+
connection_options = options.except(:build).merge(port: result.port)
|
|
52
54
|
output.puts("deploy connect: waiting for R2P2 Shell on #{result.port}")
|
|
53
55
|
wait_for_shell(
|
|
54
56
|
port: result.port, baud: options[:baud], timeout: options[:timeout], serial: serial,
|
|
@@ -160,13 +162,15 @@ module Rpremote
|
|
|
160
162
|
mount: defaults[:mount],
|
|
161
163
|
port: defaults[:port],
|
|
162
164
|
baud: defaults.fetch(:baud, Serial::BAUD_RATE),
|
|
163
|
-
timeout: defaults.fetch(:timeout, Flasher::DEFAULT_TIMEOUT)
|
|
165
|
+
timeout: defaults.fetch(:timeout, Flasher::DEFAULT_TIMEOUT),
|
|
166
|
+
build: false
|
|
164
167
|
}
|
|
165
168
|
end
|
|
166
169
|
private_class_method :default_options
|
|
167
170
|
|
|
168
171
|
def self.option_parser(options)
|
|
169
172
|
OptionParser.new do |parser|
|
|
173
|
+
parser.on("--build") { options[:build] = true }
|
|
170
174
|
parser.on("--language LANGUAGE") { |value| options[:language] = value }
|
|
171
175
|
parser.on("--language-version VERSION") { |value| options[:language_version] = value }
|
|
172
176
|
parser.on("--board BOARD") { |value| options[:board] = value }
|
data/lib/rpremote/help.rb
CHANGED
|
@@ -10,7 +10,7 @@ module Rpremote
|
|
|
10
10
|
"[--firmware FILE] [--cache DIR] [--mrbgems FILE|--no-mrbgems]",
|
|
11
11
|
build_clean: "rpremote build clean",
|
|
12
12
|
bootsel: "rpremote bootsel [--reset-flash-memory] [--mount DIR] [--port PORT] [--baud RATE] [--timeout SEC]",
|
|
13
|
-
deploy: "rpremote deploy PATH [--language LANGUAGE] [--language-version VERSION] [--board BOARD] " \
|
|
13
|
+
deploy: "rpremote deploy PATH [--build] [--language LANGUAGE] [--language-version VERSION] [--board BOARD] " \
|
|
14
14
|
"[--firmware FILE] [--cache DIR] [--mrbgems FILE|--no-mrbgems] [--mount DIR] " \
|
|
15
15
|
"[--port PORT] [--baud RATE] [--timeout SEC]",
|
|
16
16
|
dfu_app: "rpremote dfu app FILE [--type ruby|rite] [--port PORT] [--baud RATE] [--timeout SEC]",
|
|
@@ -73,6 +73,7 @@ module Rpremote
|
|
|
73
73
|
|
|
74
74
|
Options:
|
|
75
75
|
--force download the PicoRuby source again during setup
|
|
76
|
+
--build build the selected firmware before deploy flashes it
|
|
76
77
|
--language-version VERSION
|
|
77
78
|
use R2P2/PicoRuby 4.0.3 or 3.4.2 (default: 4.0.3)
|
|
78
79
|
--cache DIR use another project cache directory
|
|
@@ -152,7 +153,8 @@ module Rpremote
|
|
|
152
153
|
<<~HELP
|
|
153
154
|
Usage: #{COMMAND_USAGE.fetch(:deploy)}
|
|
154
155
|
|
|
155
|
-
|
|
156
|
+
Enters BOOTSEL when needed, flashes the existing selected UF2, and waits for the R2P2 Shell to become ready.
|
|
157
|
+
With --build, builds the selected custom UF2 before entering BOOTSEL and flashing it.
|
|
156
158
|
If PATH/lib/NAME exists, it copies it to :/lib/NAME, where NAME is the final component of PATH. It then runs PATH/main.rb and preserves its Shell job, so hardware output remains active until the next command.
|
|
157
159
|
The stages run in order and stop at the first failure. Flashing replaces persistent board firmware.
|
|
158
160
|
deploy requires PicoRuby 4.x firmware (currently 4.0.3).
|
data/lib/rpremote/mrbgems.rb
CHANGED
|
@@ -14,7 +14,7 @@ module Rpremote
|
|
|
14
14
|
COMMIT_PATTERN = /\A[0-9a-f]{40,64}\z/i
|
|
15
15
|
VMS = %i[mruby mrubyc].freeze
|
|
16
16
|
|
|
17
|
-
Dependency = Data.define(:type, :source, :branch, :commit, :path, :require_name)
|
|
17
|
+
Dependency = Data.define(:type, :source, :branch, :commit, :path, :require_name, :auto_require)
|
|
18
18
|
Overlay = Data.define(:path, :fingerprint)
|
|
19
19
|
|
|
20
20
|
class Error < Rpremote::Error; end
|
|
@@ -72,7 +72,9 @@ module Rpremote
|
|
|
72
72
|
lock_data = read_lock(required: false)
|
|
73
73
|
return [] unless lock_data
|
|
74
74
|
|
|
75
|
-
lock_data.fetch("gems").filter_map
|
|
75
|
+
lock_data.fetch("gems").filter_map do |gem|
|
|
76
|
+
gem["require_name"] if gem.fetch("auto_require", true)
|
|
77
|
+
end.uniq
|
|
76
78
|
end
|
|
77
79
|
|
|
78
80
|
def prepend_requires(source)
|
|
@@ -122,14 +124,19 @@ module Rpremote
|
|
|
122
124
|
commit = dependency.commit || previous_commit(previous, dependency) || resolver.call(
|
|
123
125
|
dependency.source, dependency.branch
|
|
124
126
|
)
|
|
125
|
-
{ "type" => "github", "source" => dependency.source,
|
|
126
|
-
|
|
127
|
-
|
|
127
|
+
entry = { "type" => "github", "source" => dependency.source,
|
|
128
|
+
"branch" => dependency.branch, "commit" => validate_commit!(commit),
|
|
129
|
+
"require_name" => dependency.require_name }.compact
|
|
128
130
|
else
|
|
129
|
-
{ "type" => "path", "source" => dependency.source,
|
|
130
|
-
|
|
131
|
-
|
|
131
|
+
entry = { "type" => "path", "source" => dependency.source,
|
|
132
|
+
"sha256" => digest_directory(dependency.path),
|
|
133
|
+
"require_name" => dependency.require_name || local_require_name(dependency.path) }.compact
|
|
132
134
|
end
|
|
135
|
+
unless dependency.auto_require
|
|
136
|
+
entry.delete("require_name")
|
|
137
|
+
entry["auto_require"] = false
|
|
138
|
+
end
|
|
139
|
+
entry
|
|
133
140
|
end
|
|
134
141
|
|
|
135
142
|
def previous_commit(lock_data, dependency)
|
|
@@ -200,18 +207,24 @@ module Rpremote
|
|
|
200
207
|
|
|
201
208
|
def valid_github_lock?(entry)
|
|
202
209
|
GITHUB_PATTERN.match?(entry["source"].to_s) && !entry["branch"].to_s.empty? &&
|
|
203
|
-
COMMIT_PATTERN.match?(entry["commit"].to_s) && valid_require_name?(entry["require_name"])
|
|
210
|
+
COMMIT_PATTERN.match?(entry["commit"].to_s) && valid_require_name?(entry["require_name"]) &&
|
|
211
|
+
valid_auto_require?(entry)
|
|
204
212
|
end
|
|
205
213
|
|
|
206
214
|
def valid_path_lock?(entry)
|
|
207
215
|
entry["type"] == "path" && !entry["source"].to_s.empty? &&
|
|
208
|
-
/\A[0-9a-f]{64}\z/.match?(entry["sha256"].to_s) && valid_require_name?(entry["require_name"])
|
|
216
|
+
/\A[0-9a-f]{64}\z/.match?(entry["sha256"].to_s) && valid_require_name?(entry["require_name"]) &&
|
|
217
|
+
valid_auto_require?(entry)
|
|
209
218
|
end
|
|
210
219
|
|
|
211
220
|
def valid_require_name?(name)
|
|
212
221
|
name.nil? || (name.is_a?(String) && !name.empty? && !name.match?(/[\x00-\x1f\x7f]/))
|
|
213
222
|
end
|
|
214
223
|
|
|
224
|
+
def valid_auto_require?(entry)
|
|
225
|
+
!entry.key?("auto_require") || entry["auto_require"] == true || entry["auto_require"] == false
|
|
226
|
+
end
|
|
227
|
+
|
|
215
228
|
def local_require_name(directory)
|
|
216
229
|
source = File.read(File.join(directory, "mrbgem.rake"))
|
|
217
230
|
match = source.match(/^\s*spec\.require_name\s*=\s*["']([^"']+)["']\s*$/)
|
|
@@ -226,6 +239,8 @@ module Rpremote
|
|
|
226
239
|
|
|
227
240
|
def overlay_source(base_config, target, locked_entries)
|
|
228
241
|
lines = [
|
|
242
|
+
"# frozen_string_literal: true",
|
|
243
|
+
"",
|
|
229
244
|
"# Generated by rpremote. Do not edit.",
|
|
230
245
|
"load #{File.expand_path(base_config).inspect}",
|
|
231
246
|
"conf = MRuby.targets.fetch(#{target.inspect})"
|
|
@@ -272,17 +287,20 @@ module Rpremote
|
|
|
272
287
|
@vm_name = value
|
|
273
288
|
end
|
|
274
289
|
|
|
275
|
-
def gem(github: nil, path: nil, branch: "main", commit: nil, require: nil)
|
|
290
|
+
def gem(github: nil, path: nil, branch: "main", commit: nil, require: nil, auto_require: true)
|
|
276
291
|
sources = [github, path].compact
|
|
277
292
|
raise DefinitionError, "gem requires exactly one of github or path" unless sources.length == 1
|
|
278
293
|
unless require.nil? || (require.is_a?(String) && !require.empty? && !require.match?(/[\x00-\x1f\x7f]/))
|
|
279
294
|
raise DefinitionError, "invalid mrbgem require name: #{require.inspect}"
|
|
280
295
|
end
|
|
281
296
|
|
|
297
|
+
valid_auto_require = [true, false].include?(auto_require)
|
|
298
|
+
raise DefinitionError, "mrbgem auto_require must be true or false: #{auto_require.inspect}" unless valid_auto_require
|
|
299
|
+
|
|
282
300
|
dependency = if github
|
|
283
|
-
github_dependency(github, branch, commit, require)
|
|
301
|
+
github_dependency(github, branch, commit, require, auto_require)
|
|
284
302
|
else
|
|
285
|
-
path_dependency(path, branch, commit, require)
|
|
303
|
+
path_dependency(path, branch, commit, require, auto_require)
|
|
286
304
|
end
|
|
287
305
|
key = [dependency.type, dependency.source]
|
|
288
306
|
raise DefinitionError, "duplicate mrbgem: #{dependency.source}" if dependencies.any? do |item|
|
|
@@ -296,21 +314,23 @@ module Rpremote
|
|
|
296
314
|
|
|
297
315
|
attr_reader :directory
|
|
298
316
|
|
|
299
|
-
def github_dependency(source, branch, commit, require_name)
|
|
317
|
+
def github_dependency(source, branch, commit, require_name, auto_require)
|
|
300
318
|
raise DefinitionError, "invalid GitHub mrbgem: #{source.inspect}" unless GITHUB_PATTERN.match?(source.to_s)
|
|
301
319
|
raise DefinitionError, "GitHub mrbgem branch must not be empty" if branch.to_s.empty?
|
|
302
320
|
raise DefinitionError, "invalid Git commit: #{commit.inspect}" if commit && !COMMIT_PATTERN.match?(commit.to_s)
|
|
303
321
|
|
|
304
322
|
Dependency.new(type: :github, source: source, branch: branch,
|
|
305
|
-
commit: commit&.downcase, path: nil, require_name: require_name
|
|
323
|
+
commit: commit&.downcase, path: nil, require_name: require_name,
|
|
324
|
+
auto_require: auto_require)
|
|
306
325
|
end
|
|
307
326
|
|
|
308
|
-
def path_dependency(source, branch, commit, require_name)
|
|
327
|
+
def path_dependency(source, branch, commit, require_name, auto_require)
|
|
309
328
|
raise DefinitionError, "local mrbgem path must not be empty" if source.to_s.empty?
|
|
310
329
|
raise DefinitionError, "local mrbgem does not accept branch or commit" if branch != "main" || commit
|
|
311
330
|
|
|
312
331
|
Dependency.new(type: :path, source: source, branch: nil, commit: nil,
|
|
313
|
-
path: File.expand_path(source, directory), require_name: require_name
|
|
332
|
+
path: File.expand_path(source, directory), require_name: require_name,
|
|
333
|
+
auto_require: auto_require)
|
|
314
334
|
end
|
|
315
335
|
end
|
|
316
336
|
end
|
|
@@ -4,6 +4,7 @@ module Rpremote
|
|
|
4
4
|
class PicoRubySourcePatch
|
|
5
5
|
JOB_PATH = "mrbgems/picoruby-shell/mrblib/job.rb"
|
|
6
6
|
BOOTSEL_PATH = "mrbgems/picoruby-machine/include/machine.h"
|
|
7
|
+
PWM_PATH = "mrbgems/picoruby-pwm/ports/rp2040/pwm.c"
|
|
7
8
|
PATCH_ALIASES = { "3.4.2" => "3.4.5" }.freeze
|
|
8
9
|
|
|
9
10
|
class Error < Rpremote::Error; end
|
|
@@ -35,7 +36,8 @@ module Rpremote
|
|
|
35
36
|
def patches(patch_version)
|
|
36
37
|
definitions = {
|
|
37
38
|
"ruby-exception-status" => JOB_PATH,
|
|
38
|
-
"bootsel" => BOOTSEL_PATH
|
|
39
|
+
"bootsel" => BOOTSEL_PATH,
|
|
40
|
+
"pwm-sleep-clock" => PWM_PATH
|
|
39
41
|
}
|
|
40
42
|
definitions.map do |name, prerequisite|
|
|
41
43
|
[File.expand_path("../../patches/picoruby-#{patch_version}-#{name}.patch", __dir__), prerequisite]
|
data/lib/rpremote/version.rb
CHANGED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
diff --git a/mrbgems/picoruby-pwm/ports/rp2040/pwm.c b/mrbgems/picoruby-pwm/ports/rp2040/pwm.c
|
|
2
|
+
--- a/mrbgems/picoruby-pwm/ports/rp2040/pwm.c
|
|
3
|
+
+++ b/mrbgems/picoruby-pwm/ports/rp2040/pwm.c
|
|
4
|
+
@@ -1,5 +1,6 @@
|
|
5
|
+
#include "pico/stdlib.h"
|
|
6
|
+
#include "hardware/pwm.h"
|
|
7
|
+
+#include "hardware/structs/clocks.h"
|
|
8
|
+
|
|
9
|
+
#include "../../include/pwm.h"
|
|
10
|
+
|
|
11
|
+
@@ -9,6 +10,11 @@
|
|
12
|
+
void
|
|
13
|
+
PWM_init(uint32_t pin)
|
|
14
|
+
{
|
|
15
|
+
+ /* The scheduler enters WFI while sleep_ms waits. Keep autonomous PWM
|
|
16
|
+
+ * output clocked between scheduler ticks after a PWM pin is initialized. */
|
|
17
|
+
+ hw_set_bits(&clocks_hw->sleep_en0,
|
|
18
|
+
+ CLOCKS_SLEEP_EN0_CLK_SYS_PWM_BITS);
|
|
19
|
+
+
|
|
20
|
+
gpio_set_function(pin, GPIO_FUNC_PWM);
|
|
21
|
+
uint slice_num = pwm_gpio_to_slice_num(pin);
|
|
22
|
+
pwm_set_clkdiv(slice_num, CLK_DIV);
|
data/sig/rpremote.rbs
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rpremote
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.5.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- ogom
|
|
@@ -60,6 +60,7 @@ files:
|
|
|
60
60
|
- patches/picoruby-3.4.5-bootsel.patch
|
|
61
61
|
- patches/picoruby-3.4.5-ruby-exception-status.patch
|
|
62
62
|
- patches/picoruby-4.0.3-bootsel.patch
|
|
63
|
+
- patches/picoruby-4.0.3-pwm-sleep-clock.patch
|
|
63
64
|
- patches/picoruby-4.0.3-ruby-exception-status.patch
|
|
64
65
|
- sig/rpremote.rbs
|
|
65
66
|
- tasks/firmware_build.rb
|