rpremote 0.6.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 +6 -0
- data/README.ja.md +3 -1
- data/README.md +3 -1
- data/RELEASING.md +2 -2
- data/THIRD_PARTY_NOTICES.md +1 -1
- data/lib/rpremote/build_command.rb +3 -3
- data/lib/rpremote/builder.rb +14 -8
- 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 -54
- 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/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/version.rb +1 -1
- data/patches/picoruby-4.0.4-pwm-sleep-clock.patch +27 -0
- data/sig/rpremote.rbs +11 -4
- metadata +11 -1
|
@@ -9,78 +9,106 @@ module Rpremote
|
|
|
9
9
|
SHELL_READY_TIMEOUT = 2.0
|
|
10
10
|
RETRY_INTERVAL = 0.25
|
|
11
11
|
|
|
12
|
+
Context = Data.define(:options, :output, :error, :services, :target_options, :firmware_path)
|
|
13
|
+
|
|
12
14
|
class Error < Rpremote::Error; end
|
|
13
15
|
|
|
14
|
-
# rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
15
16
|
def self.run(args, defaults:, output: $stdout, error: $stderr, services: {})
|
|
16
17
|
options = parse_options(args, defaults)
|
|
17
18
|
raise ArgumentError, "usage: rpremote deploy PATH [options]" unless args.length == 1
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
library, remote_library, source = project_files(project)
|
|
20
|
+
library, remote_library, source = project_files(File.expand_path(args.first))
|
|
21
21
|
Language.validate!(options[:language])
|
|
22
|
+
context = deployment_context(options, output, error, services)
|
|
23
|
+
build_firmware(context)
|
|
24
|
+
result = flash_firmware(context)
|
|
25
|
+
connect_to_shell(context, result)
|
|
26
|
+
push_library(context, result, library, remote_library)
|
|
27
|
+
run_source(context, result, source)
|
|
28
|
+
rescue Errno::ENOENT => e
|
|
29
|
+
raise ArgumentError, e.message
|
|
30
|
+
end
|
|
22
31
|
|
|
23
|
-
|
|
24
|
-
serial = services.fetch(:serial, Serial)
|
|
25
|
-
device = services.fetch(:device, Device)
|
|
26
|
-
runner = services.fetch(:runner, Runner)
|
|
32
|
+
def self.deployment_context(options, output, error, services)
|
|
27
33
|
target_options = options.slice(:language, :language_version, :board, :cache_dir, :firmware)
|
|
28
34
|
firmware_path = Target.new(**target_options).firmware_path(root: Dir.pwd)
|
|
35
|
+
Context.new(options:, output:, error:, services:, target_options:, firmware_path:)
|
|
36
|
+
end
|
|
37
|
+
private_class_method :deployment_context
|
|
38
|
+
|
|
39
|
+
def self.build_firmware(context)
|
|
40
|
+
return unless context.options[:build]
|
|
41
|
+
|
|
42
|
+
builder = context.services.fetch(:builder) { Builder.new }
|
|
43
|
+
context.output.puts("deploy build: #{context.firmware_path}")
|
|
44
|
+
builder.build(
|
|
45
|
+
**context.target_options,
|
|
46
|
+
mrbgems_lock: context.options[:mrbgems_lock],
|
|
47
|
+
output: context.output,
|
|
48
|
+
error: context.error
|
|
49
|
+
)
|
|
50
|
+
end
|
|
51
|
+
private_class_method :build_firmware
|
|
29
52
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
**target_options,
|
|
35
|
-
mrbgems: options[:mrbgems],
|
|
36
|
-
output: output,
|
|
37
|
-
error: error
|
|
38
|
-
)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
flash_service = flasher.new(timeout: options[:timeout])
|
|
42
|
-
bootsel_mount = resolve_bootsel_mount(options, flash_service, output, services)
|
|
43
|
-
|
|
53
|
+
def self.flash_firmware(context)
|
|
54
|
+
options = context.options
|
|
55
|
+
flash_service = context.services.fetch(:flasher, Flasher).new(timeout: options[:timeout])
|
|
56
|
+
bootsel_mount = resolve_bootsel_mount(options, flash_service, context.output, context.services)
|
|
44
57
|
mount = options[:mount] || "an automatically detected RP2350 BOOTSEL volume"
|
|
45
|
-
output.puts(
|
|
46
|
-
|
|
47
|
-
firmware_path,
|
|
48
|
-
mount: bootsel_mount,
|
|
49
|
-
port: options[:port]
|
|
58
|
+
context.output.puts(
|
|
59
|
+
"deploy flash: #{context.firmware_path} to #{mount}; this replaces persistent board firmware"
|
|
50
60
|
)
|
|
61
|
+
flash_service.flash(context.firmware_path, mount: bootsel_mount, port: options[:port])
|
|
62
|
+
end
|
|
63
|
+
private_class_method :flash_firmware
|
|
51
64
|
|
|
52
|
-
|
|
53
|
-
|
|
65
|
+
def self.connect_to_shell(context, result)
|
|
66
|
+
options = context.options
|
|
67
|
+
context.output.puts("deploy connect: waiting for R2P2 Shell on #{result.port}")
|
|
54
68
|
wait_for_shell(
|
|
55
|
-
port: result.port, baud: options[:baud], timeout: options[:timeout],
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
69
|
+
port: result.port, baud: options[:baud], timeout: options[:timeout],
|
|
70
|
+
serial: context.services.fetch(:serial, Serial),
|
|
71
|
+
shell: context.services.fetch(:shell, Shell),
|
|
72
|
+
sleeper: context.services.fetch(:sleeper) { ->(seconds) { sleep(seconds) } },
|
|
73
|
+
clock: context.services.fetch(:clock) { -> { Process.clock_gettime(Process::CLOCK_MONOTONIC) } }
|
|
59
74
|
)
|
|
60
|
-
output.puts("deploy connect: ready on #{result.port}")
|
|
75
|
+
context.output.puts("deploy connect: ready on #{result.port}")
|
|
76
|
+
end
|
|
77
|
+
private_class_method :connect_to_shell
|
|
61
78
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
end
|
|
67
|
-
recursive_copy.call(library, ":#{remote_library}", connection_options)
|
|
68
|
-
else
|
|
69
|
-
output.puts("deploy push: skipped; directory not found: #{library}")
|
|
79
|
+
def self.push_library(context, result, library, remote_library)
|
|
80
|
+
unless File.directory?(library)
|
|
81
|
+
context.output.puts("deploy push: skipped; directory not found: #{library}")
|
|
82
|
+
return
|
|
70
83
|
end
|
|
71
84
|
|
|
72
|
-
output.puts("deploy
|
|
73
|
-
|
|
85
|
+
context.output.puts("deploy push: #{library} -> :#{remote_library}")
|
|
86
|
+
recursive_copy = context.services.fetch(:recursive_copy) do
|
|
87
|
+
RecursiveCopy.new(
|
|
88
|
+
output: context.output,
|
|
89
|
+
serial: context.services.fetch(:serial, Serial),
|
|
90
|
+
device: context.services.fetch(:device, Device)
|
|
91
|
+
)
|
|
92
|
+
end
|
|
93
|
+
connection_options = context.options.except(:build).merge(port: result.port)
|
|
94
|
+
recursive_copy.call(library, ":#{remote_library}", connection_options)
|
|
95
|
+
end
|
|
96
|
+
private_class_method :push_library
|
|
97
|
+
|
|
98
|
+
def self.run_source(context, result, source)
|
|
99
|
+
options = context.options
|
|
100
|
+
context.output.puts("deploy run: #{source} on #{result.port}")
|
|
101
|
+
source_data = prepend_mrbgem_requires(File.binread(source), options[:mrbgems_lock])
|
|
102
|
+
serial = context.services.fetch(:serial, Serial)
|
|
103
|
+
runner = context.services.fetch(:runner, Runner)
|
|
74
104
|
run_output = serial.open(result.port, baud: options[:baud]) do |port|
|
|
75
105
|
runner.new(port, timeout: options[:timeout]).run(
|
|
76
|
-
source_data, output: output, cleanup: false, remote_path: Runner::DEPLOY_REMOTE_PATH
|
|
106
|
+
source_data, output: context.output, cleanup: false, remote_path: Runner::DEPLOY_REMOTE_PATH
|
|
77
107
|
)
|
|
78
108
|
end
|
|
79
|
-
output.puts("deploy run: completed; output bytes: #{run_output.to_s.bytesize}")
|
|
80
|
-
rescue Errno::ENOENT => e
|
|
81
|
-
raise ArgumentError, e.message
|
|
109
|
+
context.output.puts("deploy run: completed; output bytes: #{run_output.to_s.bytesize}")
|
|
82
110
|
end
|
|
83
|
-
|
|
111
|
+
private_class_method :run_source
|
|
84
112
|
|
|
85
113
|
def self.project_files(project)
|
|
86
114
|
raise ArgumentError, "project directory not found: #{project}" unless File.directory?(project)
|
|
@@ -94,10 +122,13 @@ module Rpremote
|
|
|
94
122
|
end
|
|
95
123
|
private_class_method :project_files
|
|
96
124
|
|
|
97
|
-
def self.prepend_mrbgem_requires(source,
|
|
98
|
-
return source if
|
|
125
|
+
def self.prepend_mrbgem_requires(source, lock_file)
|
|
126
|
+
return source if lock_file == false
|
|
127
|
+
|
|
128
|
+
path = lock_file || Mrbgems::DEFAULT_LOCK_PATH
|
|
129
|
+
raise ArgumentError, "mrbgems lock file does not exist: #{path}" if lock_file && !File.file?(path)
|
|
99
130
|
|
|
100
|
-
Mrbgems.new(
|
|
131
|
+
Mrbgems.new(lock_path: path, cwd: Dir.pwd).prepend_requires(source)
|
|
101
132
|
end
|
|
102
133
|
private_class_method :prepend_mrbgem_requires
|
|
103
134
|
|
|
@@ -157,7 +188,7 @@ module Rpremote
|
|
|
157
188
|
board: defaults.fetch(:board, Target::DEFAULT_BOARD),
|
|
158
189
|
cache_dir: defaults.fetch(:cache, Target::DEFAULT_CACHE_DIR),
|
|
159
190
|
firmware: defaults[:firmware],
|
|
160
|
-
|
|
191
|
+
mrbgems_lock: defaults[:mrbgems_lock],
|
|
161
192
|
mount: defaults[:mount],
|
|
162
193
|
port: defaults[:port],
|
|
163
194
|
baud: defaults.fetch(:baud, Serial::BAUD_RATE),
|
|
@@ -175,8 +206,8 @@ module Rpremote
|
|
|
175
206
|
parser.on("--board BOARD") { |value| options[:board] = value }
|
|
176
207
|
parser.on("--cache DIR") { |value| options[:cache_dir] = value }
|
|
177
208
|
parser.on("--firmware FILE") { |value| options[:firmware] = value }
|
|
178
|
-
parser.on("--
|
|
179
|
-
parser.on("--no-mrbgems") { options[:
|
|
209
|
+
parser.on("--lockfile FILE") { |value| options[:mrbgems_lock] = value }
|
|
210
|
+
parser.on("--no-mrbgems") { options[:mrbgems_lock] = false }
|
|
180
211
|
parser.on("--mount DIR") { |value| options[:mount] = value }
|
|
181
212
|
parser.on("--port PORT") { |value| options[:port] = value }
|
|
182
213
|
parser.on("--baud RATE", Integer) { |value| options[:baud] = value }
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rpremote
|
|
4
|
+
module Help
|
|
5
|
+
def self.dfu_text(subcommand)
|
|
6
|
+
return dfu_app_text if subcommand == "app"
|
|
7
|
+
return dfu_compile_text if subcommand == "compile"
|
|
8
|
+
return dfu_status_text if subcommand == "status"
|
|
9
|
+
return dfu_remove_text if subcommand == "remove"
|
|
10
|
+
|
|
11
|
+
<<~HELP
|
|
12
|
+
Usage: #{COMMAND_USAGE.fetch(:dfu_app)}
|
|
13
|
+
#{COMMAND_USAGE.fetch(:dfu_compile)}
|
|
14
|
+
#{COMMAND_USAGE.fetch(:dfu_status)}
|
|
15
|
+
#{COMMAND_USAGE.fetch(:dfu_remove)}
|
|
16
|
+
|
|
17
|
+
Stages and inspects PicoModem DFU applications. Run `rpremote dfu SUBCOMMAND --help` for details.
|
|
18
|
+
HELP
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.dfu_app_text
|
|
22
|
+
<<~HELP
|
|
23
|
+
Usage: #{COMMAND_USAGE.fetch(:dfu_app)}
|
|
24
|
+
|
|
25
|
+
Transfers a Ruby source or matching RITE bytecode application to the inactive DFU slot. The next R2P2 restart tries it.
|
|
26
|
+
Options default to the configured or automatically selected CDC 0 port, 115200 baud, and 20 seconds.
|
|
27
|
+
The transfer changes the staged boot application; use `rpremote reset` to restart and require DFU.confirm after a successful boot.
|
|
28
|
+
HELP
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.dfu_compile_text
|
|
32
|
+
<<~HELP
|
|
33
|
+
Usage: #{COMMAND_USAGE.fetch(:dfu_compile)}
|
|
34
|
+
|
|
35
|
+
Compiles Ruby source to bytecode that matches the selected PicoRuby version. The output defaults beside FILE.
|
|
36
|
+
It requires prepared PicoRuby source and does not connect to a board.
|
|
37
|
+
HELP
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.dfu_status_text
|
|
41
|
+
<<~HELP
|
|
42
|
+
Usage: #{COMMAND_USAGE.fetch(:dfu_status)}
|
|
43
|
+
|
|
44
|
+
Prints the active and candidate DFU A/B slots. Defaults are the configured or automatically selected CDC 0 port,
|
|
45
|
+
115200 baud, and 20 seconds. This command reads board state without changing it.
|
|
46
|
+
HELP
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def self.dfu_remove_text
|
|
50
|
+
<<~HELP
|
|
51
|
+
Usage: #{COMMAND_USAGE.fetch(:dfu_remove)}
|
|
52
|
+
|
|
53
|
+
Permanently removes the Ruby source and bytecode applications from both DFU A/B slots and resets their metadata.
|
|
54
|
+
Run `rpremote reset` afterward to stop the application already running in RAM. It does not remove /home/app.rb,
|
|
55
|
+
/home/app.mrb, other files, embedded mrbgems, or R2P2 firmware.
|
|
56
|
+
HELP
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rpremote
|
|
4
|
+
module Help
|
|
5
|
+
def self.fs_text(subcommand)
|
|
6
|
+
return fs_subcommand_text(subcommand) if %w[cp push cat ls rm mkdir].include?(subcommand)
|
|
7
|
+
|
|
8
|
+
<<~HELP
|
|
9
|
+
Usage: #{COMMAND_USAGE.fetch(:fs_cp)}
|
|
10
|
+
#{COMMAND_USAGE.fetch(:fs_push)}
|
|
11
|
+
#{COMMAND_USAGE.fetch(:fs_cat)}
|
|
12
|
+
#{COMMAND_USAGE.fetch(:fs_ls)}
|
|
13
|
+
#{COMMAND_USAGE.fetch(:fs_rm)}
|
|
14
|
+
#{COMMAND_USAGE.fetch(:fs_mkdir)}
|
|
15
|
+
|
|
16
|
+
Uses :/REMOTE/PATH for R2P2 paths. Run `rpremote fs SUBCOMMAND --help` for details.
|
|
17
|
+
HELP
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.fs_subcommand_text(subcommand)
|
|
21
|
+
usage = COMMAND_USAGE.fetch(:"fs_#{subcommand}")
|
|
22
|
+
effect = case subcommand
|
|
23
|
+
when "rm" then "Deletes the remote path permanently."
|
|
24
|
+
when "mkdir" then "Creates a remote directory."
|
|
25
|
+
when "cp" then "Transfers one file, or recursively uploads a local directory with --recursive."
|
|
26
|
+
when "push" then "Creates missing remote directories and recursively uploads a local directory."
|
|
27
|
+
else "Reads remote files."
|
|
28
|
+
end
|
|
29
|
+
<<~HELP
|
|
30
|
+
Usage: #{usage}
|
|
31
|
+
|
|
32
|
+
#{effect} Defaults are the automatic CDC 0 port, 115200 baud, and 20 seconds.
|
|
33
|
+
HELP
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rpremote
|
|
4
|
+
module Help
|
|
5
|
+
def self.setup_text
|
|
6
|
+
<<~HELP
|
|
7
|
+
Usage: #{COMMAND_USAGE.fetch(:setup)}
|
|
8
|
+
|
|
9
|
+
Creates config/setting.json when it does not exist, then downloads and prepares PicoRuby source and the official Raspberry Pi nuke_universal.uf2 firmware.
|
|
10
|
+
Options: --language LANGUAGE (picoruby), --language-version VERSION (latest), --cache DIR (firmware), --force.
|
|
11
|
+
This changes the project configuration and source cache but does not connect to a board.
|
|
12
|
+
HELP
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.build_text
|
|
16
|
+
<<~HELP
|
|
17
|
+
Usage: #{COMMAND_USAGE.fetch(:build)}
|
|
18
|
+
|
|
19
|
+
Builds a custom UF2 for the selected target. It writes generated files under build/ and the selected firmware path.
|
|
20
|
+
Options: --language LANGUAGE, --language-version VERSION, --board BOARD (pico2), --cache DIR (firmware),
|
|
21
|
+
--firmware FILE, --lockfile FILE, --no-mrbgems. A project Mrbgems.lock file is used automatically by default.
|
|
22
|
+
HELP
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def self.build_clean_text
|
|
26
|
+
<<~HELP
|
|
27
|
+
Usage: #{COMMAND_USAGE.fetch(:build_clean)}
|
|
28
|
+
|
|
29
|
+
Removes only the project's generated build/ directory. It does not remove firmware/, Mrbgems, or Mrbgems.lock.
|
|
30
|
+
HELP
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.deploy_text
|
|
34
|
+
<<~HELP
|
|
35
|
+
Usage: #{COMMAND_USAGE.fetch(:deploy)}
|
|
36
|
+
|
|
37
|
+
Enters BOOTSEL when needed, flashes the existing selected UF2, and waits for the R2P2 Shell to become ready.
|
|
38
|
+
With --build, builds the selected custom UF2 before entering BOOTSEL and flashing it.
|
|
39
|
+
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.
|
|
40
|
+
The stages run in order and stop at the first failure. Flashing replaces persistent board firmware.
|
|
41
|
+
deploy requires current PicoRuby 4.x firmware.
|
|
42
|
+
Options combine build, BOOTSEL, flash, library-copy, and run settings. The first install of firmware with automatic BOOTSEL still requires holding BOOTSEL.
|
|
43
|
+
HELP
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.bootsel_text
|
|
47
|
+
<<~HELP
|
|
48
|
+
Usage: #{COMMAND_USAGE.fetch(:bootsel)}
|
|
49
|
+
|
|
50
|
+
Asks the running R2P2 firmware to restart as an RP2350 BOOTSEL USB volume, then waits for that volume to appear.
|
|
51
|
+
By default it does not write firmware. This requires firmware built by a current rpremote; use physical BOOTSEL once to install it first.
|
|
52
|
+
--reset-flash-memory copies the official Raspberry Pi nuke_universal.uf2 in BOOTSEL mode and erases all external flash memory.
|
|
53
|
+
After resetting flash memory, wait for BOOTSEL to reappear and run `rpremote flash` to install R2P2 again.
|
|
54
|
+
HELP
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def self.mrbgems_text(subcommand)
|
|
58
|
+
action = subcommand || "check|list|lock|update"
|
|
59
|
+
<<~HELP
|
|
60
|
+
Usage: #{COMMAND_USAGE.fetch(:mrbgems).sub("SUBCOMMAND", action)}
|
|
61
|
+
|
|
62
|
+
Checks or lists build dependencies, writes a reproducible lock file, or updates locked GitHub commits.
|
|
63
|
+
`lock --with production --without test` includes common and production gems. Exclusions take precedence.
|
|
64
|
+
`update` resolves new commits using the same group options.
|
|
65
|
+
HELP
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def self.flash_text
|
|
69
|
+
<<~HELP
|
|
70
|
+
Usage: #{COMMAND_USAGE.fetch(:flash)}
|
|
71
|
+
|
|
72
|
+
Copies the selected UF2 to an RP2350 BOOTSEL volume and waits for R2P2 to reconnect. It replaces persistent board firmware.
|
|
73
|
+
Defaults select pico2, firmware/picoruby-latest-pico2.uf2, an automatic BOOTSEL mount and CDC 0 port, and 20 seconds.
|
|
74
|
+
HELP
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def self.config_text(subcommand)
|
|
78
|
+
unless subcommand == "show"
|
|
79
|
+
return "Usage: #{COMMAND_USAGE.fetch(:config_show)}\n\nUse `rpremote config show --help` for the supported overrides.\n"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
<<~HELP
|
|
83
|
+
Usage: #{COMMAND_USAGE.fetch(:config_show)}
|
|
84
|
+
|
|
85
|
+
Prints the configuration file, defaults, and command-line overrides after resolution. It does not connect to a board or change state.
|
|
86
|
+
HELP
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rpremote
|
|
4
|
+
module Help
|
|
5
|
+
def self.ports_text
|
|
6
|
+
"Usage: #{COMMAND_USAGE.fetch(:ports)}\n\nPrints each detected R2P2 CDC 0 serial path, one per line. It does not connect to a board.\n"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.run_text
|
|
10
|
+
<<~HELP
|
|
11
|
+
Usage: #{COMMAND_USAGE.fetch(:run)}
|
|
12
|
+
|
|
13
|
+
Uploads FILE to R2P2, or main.rb when FILE is a directory, relays output, then removes the temporary remote file. Defaults are the automatic CDC 0 port,
|
|
14
|
+
115200 baud, a 20-second idle timeout, and picoruby. Output from the running program resets the idle timeout.
|
|
15
|
+
It exits nonzero when compatible R2P2 firmware reports a Ruby exception.
|
|
16
|
+
--reset-on-timeout resets R2P2 after the run times out and the serial connection has closed.
|
|
17
|
+
HELP
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.exec_text
|
|
21
|
+
<<~HELP
|
|
22
|
+
Usage: #{COMMAND_USAGE.fetch(:exec)}
|
|
23
|
+
|
|
24
|
+
Runs short Ruby CODE through a temporary remote file, then removes it. Defaults are the automatic CDC 0 port,
|
|
25
|
+
115200 baud, a 20-second idle timeout, and picoruby. Output from the running program resets the idle timeout.
|
|
26
|
+
It exits nonzero when compatible R2P2 firmware reports a Ruby exception.
|
|
27
|
+
HELP
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.monitor_text
|
|
31
|
+
<<~HELP
|
|
32
|
+
Usage: #{COMMAND_USAGE.fetch(:monitor)}
|
|
33
|
+
|
|
34
|
+
Opens a serial monitor for the selected CDC 0 port. Defaults are 115200 baud and 20 seconds; exit with Ctrl-].
|
|
35
|
+
HELP
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.repl_text
|
|
39
|
+
<<~HELP
|
|
40
|
+
Usage: #{COMMAND_USAGE.fetch(:repl)}
|
|
41
|
+
|
|
42
|
+
Opens PicoIRB on the selected CDC 0 port. Defaults are 115200 baud and 20 seconds; exit with Ctrl-].
|
|
43
|
+
HELP
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def self.reset_text
|
|
47
|
+
<<~HELP
|
|
48
|
+
Usage: #{COMMAND_USAGE.fetch(:reset)}
|
|
49
|
+
|
|
50
|
+
Reboots R2P2 and waits for reconnection. Defaults are the automatic CDC 0 port, 115200 baud, and 20 seconds.
|
|
51
|
+
HELP
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rpremote
|
|
4
|
+
module Help
|
|
5
|
+
TEXT = <<~HELP.freeze
|
|
6
|
+
rpremote - R2P2 remote control for Raspberry Pi Pico 2
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
#{COMMAND_USAGE.fetch(:setup)}
|
|
10
|
+
#{COMMAND_USAGE.fetch(:build)}
|
|
11
|
+
#{COMMAND_USAGE.fetch(:build_clean)}
|
|
12
|
+
#{COMMAND_USAGE.fetch(:bootsel)}
|
|
13
|
+
#{COMMAND_USAGE.fetch(:deploy)}
|
|
14
|
+
#{COMMAND_USAGE.fetch(:dfu_app)}
|
|
15
|
+
#{COMMAND_USAGE.fetch(:dfu_compile)}
|
|
16
|
+
#{COMMAND_USAGE.fetch(:dfu_status)}
|
|
17
|
+
#{COMMAND_USAGE.fetch(:dfu_remove)}
|
|
18
|
+
#{COMMAND_USAGE.fetch(:mrbgems).sub("SUBCOMMAND", "check|list|lock|update")}
|
|
19
|
+
#{COMMAND_USAGE.fetch(:flash)}
|
|
20
|
+
#{COMMAND_USAGE.fetch(:config_show)}
|
|
21
|
+
#{COMMAND_USAGE.fetch(:ports)}
|
|
22
|
+
#{COMMAND_USAGE.fetch(:run)}
|
|
23
|
+
#{COMMAND_USAGE.fetch(:monitor)}
|
|
24
|
+
#{COMMAND_USAGE.fetch(:repl)}
|
|
25
|
+
#{COMMAND_USAGE.fetch(:exec)}
|
|
26
|
+
#{COMMAND_USAGE.fetch(:reset)}
|
|
27
|
+
#{COMMAND_USAGE.fetch(:fs_cp)}
|
|
28
|
+
#{COMMAND_USAGE.fetch(:fs_push)}
|
|
29
|
+
#{COMMAND_USAGE.fetch(:fs_cat)}
|
|
30
|
+
#{COMMAND_USAGE.fetch(:fs_ls)}
|
|
31
|
+
#{COMMAND_USAGE.fetch(:fs_rm)}
|
|
32
|
+
#{COMMAND_USAGE.fetch(:fs_mkdir)}
|
|
33
|
+
|
|
34
|
+
`rpremote build clean` removes only the project's generated `build/` directory.
|
|
35
|
+
|
|
36
|
+
Configuration:
|
|
37
|
+
config/setting.json default project options
|
|
38
|
+
|
|
39
|
+
Options:
|
|
40
|
+
--force download the PicoRuby source again during setup
|
|
41
|
+
--build build the selected firmware before deploy flashes it
|
|
42
|
+
--language-version VERSION
|
|
43
|
+
use a PicoRuby tag or latest (default: latest)
|
|
44
|
+
--cache DIR use another project cache directory
|
|
45
|
+
--lockfile FILE use an explicit Mrbgems.lock for build, deploy, run, or exec
|
|
46
|
+
--no-mrbgems do not build or automatically require locked mrbgems
|
|
47
|
+
--with GROUPS lock common mrbgems and the comma-separated groups
|
|
48
|
+
--without GROUPS exclude the comma-separated groups from the lock
|
|
49
|
+
--board BOARD
|
|
50
|
+
select pico2 or pico2_w (default: pico2)
|
|
51
|
+
--firmware FILE build to, or deploy or flash from, this UF2 path
|
|
52
|
+
--language LANGUAGE
|
|
53
|
+
select the remote language (default: picoruby)
|
|
54
|
+
--config FILE use another configuration file
|
|
55
|
+
--mount DIR use an explicit RP2350 BOOTSEL drive
|
|
56
|
+
--port PORT use an explicit R2P2 CDC 0 device
|
|
57
|
+
--baud RATE serial baud rate (default: 115200)
|
|
58
|
+
--timeout SEC timeout in seconds (default: 20)
|
|
59
|
+
-h, --help show this help
|
|
60
|
+
-V, --version show the version
|
|
61
|
+
HELP
|
|
62
|
+
end
|
|
63
|
+
end
|