Led と Delay の抽象化
これから、LEDルーレットアプリケーションを実装するために使用する、2つの高水準の抽象化を紹介します。
補助クレート aux5 は、init という初期化関数を公開しています。この関数を呼び出すと、タプルにまとめられた2つの値、Delay 値と LedArray 値が返されます。
Delay は、指定したミリ秒数の間プログラムをブロックするために使用できます。
LedArray は、8個の Led からなる配列です。各 Led は F3 ボード上の1つのLEDを表し、2つのメソッド on と off を公開しています。これらを使うと、それぞれLEDをオンまたはオフにできます。
では、スターターコードを次のように変更して、この2つの抽象化を試してみましょう。
#![deny(unsafe_code)]
#![no_main]
#![no_std]
use aux5::{entry, Delay, DelayMs, LedArray, OutputSwitch};
#[entry]
fn main() -> ! {
let (mut delay, mut leds): (Delay, LedArray) = aux5::init();
let half_period = 500_u16;
loop {
leds[0].on().ok();
delay.delay_ms(half_period);
leds[0].off().ok();
delay.delay_ms(half_period);
}
}
ではビルドします:
cargo build
NOTE: GDB セッションを開始する 前に プログラムを再ビルドするのを忘れてしまうことがあります。この見落としは、非常に混乱しやすいデバッグセッションにつながる可能性があります。この問題を避けるために、
cargo buildの代わりにcargo runを実行するだけでかまいません。cargo runコマンドはビルドを行い、さらに デバッグセッションも開始するため、プログラムの再コンパイルを忘れずに済みます。
では、新しいプログラムで前の節と同じように実行し、フラッシュ手順を繰り返しましょう。cargo run は自分で入力してみてください。これもすぐに楽になります。:)
NOTE: 別のターミナルで
openocd(デバッガー)を起動するのを忘れないでください。
そうしないとtarget remote :3333は動作しません!
$ cargo run
Finished dev [unoptimized + debuginfo] target(s) in 0.01s
Running `arm-none-eabi-gdb -q ~/embedded-discovery/target/thumbv7em-none-eabihf/debug/led-roulette`
Reading symbols from ~/embedded-discovery/target/thumbv7em-none-eabihf/debug/led-roulette...
(gdb) target remote :3333
Remote debugging using :3333
led_roulette::__cortex_m_rt_main_trampoline () at ~/embedded-discovery/src/05-led-roulette/src/main.rs:7
7 #[entry]
(gdb) load
Loading section .vector_table, size 0x194 lma 0x8000000
Loading section .text, size 0x52c0 lma 0x8000194
Loading section .rodata, size 0xb50 lma 0x8005454
Start address 0x08000194, load size 24484
Transfer rate: 21 KB/sec, 6121 bytes/write.
(gdb) break main
Breakpoint 1 at 0x8000202: file ~/embedded-discovery/src/05-led-roulette/src/main.rs, line 7.
Note: automatically using hardware breakpoints for read-only addresses.
(gdb) continue
Continuing.
Breakpoint 1, led_roulette::__cortex_m_rt_main_trampoline ()
at ~/embedded-discovery/src/05-led-roulette/src/main.rs:7
7 #[entry]
(gdb) step
led_roulette::__cortex_m_rt_main () at ~/embedded-discovery/src/05-led-roulette/src/main.rs:9
9 let (mut delay, mut leds): (Delay, LedArray) = aux5::init();
(gdb)
OK。コードをステップ実行していきましょう。今回は step ではなく next コマンドを使います。違いは、next コマンドは関数呼び出しの中に入るのではなく、それを 飛び越えて ステップ実行することです。
(gdb) next
11 let half_period = 500_u16;
(gdb) next
13 loop {
(gdb) next
14 leds[0].on().ok();
(gdb) next
15 delay.delay_ms(half_period);
leds[0].on().ok() 文を実行した後、北を向いた赤色LEDが点灯するはずです。
そのままプログラムをステップオーバーしていきましょう。
(gdb) next
17 leds[0].off().ok();
(gdb) next
18 delay.delay_ms(half_period);
delay_ms の呼び出しはプログラムを0.5秒間ブロックしますが、next コマンド自体の実行にも少し時間がかかるため、気づかないかもしれません。ただし、leds[0].off() 文をステップオーバーした後には、赤色LEDが消灯するはずです。
このプログラムが何をするかは、もう想像できるでしょう。continue コマンドを使って、中断せずに実行させてみましょう。
(gdb) continue
Continuing.
では、もっと面白いことをしてみましょう。GDB を使って、プログラムの挙動を変更します。
まず、Ctrl+C を押して無限ループを止めましょう。おそらく Led::on、Led::off、delay_ms のどこかで停止します。
^C
Program received signal SIGINT, Interrupt.
0x08003434 in core::ptr::read_volatile<u32> (src=0xe000e010)
at ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:1053
私の場合、プログラムは read_volatile 関数の中で実行を停止しました。GDB の出力には、そのことに関する興味深い情報が表示されています: core::ptr::read_volatile (src=0xe000e010)。これは、その関数が core クレート由来であり、引数 src = 0xe000e010 を伴って呼び出されたことを意味します。
補足すると、関数の引数をより明示的に表示するには info args コマンドを使います。
(gdb) info args
src = 0xe000e010
プログラムがどこで停止していても、backtrace コマンド(短縮形は bt)の出力を見れば、そこに至るまでの経路をいつでも確認できます。
(gdb) backtrace
#0 0x08003434 in core::ptr::read_volatile<u32> (src=0xe000e010)
at ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:1053
#1 0x08002d66 in vcell::VolatileCell<u32>::get<u32> (self=0xe000e010) at ~/.cargo/registry/src/github.com-1ecc6299db9ec823/vcell-0.1.3/src/lib.rs:33
#2 volatile_register::RW<u32>::read<u32> (self=0xe000e010) at ~/.cargo/registry/src/github.com-1ecc6299db9ec823/volatile-register-0.2.0/src/lib.rs:75
#3 cortex_m::peripheral::SYST::has_wrapped (self=0x20009fa4)
at ~/.cargo/registry/src/github.com-1ecc6299db9ec823/cortex-m-0.6.4/src/peripheral/syst.rs:136
#4 0x08003004 in stm32f3xx_hal::delay::{{impl}}::delay_us (self=0x20009fa4, us=500000)
at ~/.cargo/registry/src/github.com-1ecc6299db9ec823/stm32f3xx-hal-0.5.0/src/delay.rs:58
#5 0x08002f3e in stm32f3xx_hal::delay::{{impl}}::delay_ms (self=0x20009fa4, ms=500)
at ~/.cargo/registry/src/github.com-1ecc6299db9ec823/stm32f3xx-hal-0.5.0/src/delay.rs:32
#6 0x08002f80 in stm32f3xx_hal::delay::{{impl}}::delay_ms (self=0x20009fa4, ms=500)
at ~/.cargo/registry/src/github.com-1ecc6299db9ec823/stm32f3xx-hal-0.5.0/src/delay.rs:38
#7 0x0800024c in led_roulette::__cortex_m_rt_main () at src/05-led-roulette/src/main.rs:15
#8 0x08000206 in led_roulette::__cortex_m_rt_main_trampoline () at src/05-led-roulette/src/main.rs:7
backtrace は、現在の関数から main までの関数呼び出しのトレースを表示します。
本題に戻りましょう。やりたいことを行うには、まず main 関数に戻る必要があります。それには finish コマンドを使えます。このコマンドはプログラムの実行を再開し、現在の関数からプログラムが戻った直後に再び停止します。これを数回呼び出す必要があります。
(gdb) finish
Run till exit from #0 0x08003434 in core::ptr::read_volatile
(..)
(gdb) finish Run till exit from #0 0x08002f3e in stm32f3xx_hal::delay::{{impl}}::delay_ms (self=0x20009fa4, ms=500) at ~/.cargo/registry/src/github.com-1ecc6299db9ec823/stm32f3xx-hal-0.5.0/src/delay.rs:32 0x08002f80 in stm32f3xx_hal::delay::{{impl}}::delay_ms (self=0x20009fa4, ms=500) at ~/.cargo/registry/src/github.com-1ecc6299db9ec823/stm32f3xx-hal-0.5.0/src/delay.rs:38 38 self.delay_ms(u32(ms));
(gdb) finish Run till exit from #0 0x08002f80 in stm32f3xx_hal::delay::{{impl}}::delay_ms (self=0x20009fa4, ms=500) at ~/.cargo/registry/src/github.com-1ecc6299db9ec823/stm32f3xx-hal-0.5.0/src/delay.rs:38 0x0800024c in led_roulette::__cortex_m_rt_main () at src/05-led-roulette/src/main.rs:15 15 delay.delay_ms(half_period);
`main` に戻ってきました。ここにはローカル変数 `half_period` があります。
(gdb) print half_period $3 = 500
では、`set` コマンドを使ってこの変数を変更してみましょう。
(gdb) set half_period = 100
(gdb) print half_period $5 = 100
`continue` コマンドを使ってプログラムを再びそのまま実行させると、LED が今度はずっと速く
点滅するのが **見えるかもしれません** が、おそらく点滅速度は変わっていません。**何が起きたのでしょうか?**
`Ctrl+C` でプログラムを停止し、その後 `main:14` にブレークポイントを設定しましょう。
``` console
(gdb) continue
Continuing.
^C
Program received signal SIGINT, Interrupt.
core::cell::UnsafeCell<u32>::get<u32> (self=0x20009fa4)
at ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/cell.rs:1711
1711 pub const fn get(&self) -> *mut T {
次に、main.rs:14 にブレークポイントを設定して、continue を実行します。
(gdb) break main.rs:14
Breakpoint 2 at 0x8000236: file src/05-led-roulette/src/main.rs, line 14.
(gdb) continue
Continuing.
Breakpoint 2, led_roulette::__cortex_m_rt_main () at src/05-led-roulette/src/main.rs:14
14 leds[0].on().ok();
次に、可能であれば端末ウィンドウを縦約 80 行、横約 170 文字になるように開いてください。
注: そこまで大きく端末を開けなくても問題ありません。その場合は
--Type <RET> for more, q to quit, c to continue without paging--と表示されるので、(gdb)プロンプトが見えるまで return を入力してください。その後、端末ウィンドウを スクロールして結果を確認してください。
(gdb) disassemble /m
Dump of assembler code for function _ZN12led_roulette18__cortex_m_rt_main17h51e7c3daad2af251E:
8 fn main() -> ! {
0x08000208 <+0>: push {r7, lr}
0x0800020a <+2>: mov r7, sp
0x0800020c <+4>: sub sp, #64 ; 0x40
0x0800020e <+6>: add r0, sp, #32
9 let (mut delay, mut leds): (Delay, LedArray) = aux5::init();
0x08000210 <+8>: bl 0x8000302 <aux5::init>
0x08000214 <+12>: b.n 0x8000216 <led_roulette::__cortex_m_rt_main+14>
0x08000216 <+14>: add r0, sp, #32
0x08000218 <+16>: add r1, sp, #4
0x0800021a <+18>: ldmia.w r0, {r2, r3, r4, r12, lr}
0x0800021e <+22>: stmia.w r1, {r2, r3, r4, r12, lr}
0x08000222 <+26>: ldr r0, [sp, #52] ; 0x34
0x08000224 <+28>: ldr r1, [sp, #56] ; 0x38
0x08000226 <+30>: str r1, [sp, #28]
0x08000228 <+32>: str r0, [sp, #24]
0x0800022a <+34>: mov.w r0, #500 ; 0x1f4
10
11 let half_period = 500_u16;
0x0800022e <+38>: strh.w r0, [r7, #-2]
12
13 loop {
0x08000232 <+42>: b.n 0x8000234 <led_roulette::__cortex_m_rt_main+44>
0x08000234 <+44>: add r0, sp, #24
0x08000268 <+96>: b.n 0x8000234 <led_roulette::__cortex_m_rt_main+44>
14 leds[0].on().ok();
=> 0x08000236 <+46>: bl 0x80001ec <switch_hal::output::{{impl}}::on<stm32f3xx_hal::gpio::gpioe::PEx<stm32f3xx_hal::gpio::Output<stm32f3xx_hal::gpio::PushPull>>>>
0x0800023a <+50>: b.n 0x800023c <led_roulette::__cortex_m_rt_main+52>
0x0800023c <+52>: bl 0x8000594 <core::result::Result<(), core::convert::Infallible>::ok<(),core::convert::Infallible>>
0x08000240 <+56>: b.n 0x8000242 <led_roulette::__cortex_m_rt_main+58>
0x08000242 <+58>: add r0, sp, #4
0x08000244 <+60>: mov.w r1, #500 ; 0x1f4
15 delay.delay_ms(half_period);
0x08000248 <+64>: bl 0x8002f5c <stm32f3xx_hal::delay::{{impl}}::delay_ms>
0x0800024c <+68>: b.n 0x800024e <led_roulette::__cortex_m_rt_main+70>
0x0800024e <+70>: add r0, sp, #24
16
17 leds[0].off().ok();
0x08000250 <+72>: bl 0x800081a <switch_hal::output::{{impl}}::off<stm32f3xx_hal::gpio::gpioe::PEx<stm32f3xx_hal::gpio::Output<stm32f3xx_hal::gpio::PushPull>>>>
0x08000254 <+76>: b.n 0x8000256 <led_roulette::__cortex_m_rt_main+78>
0x08000256 <+78>: bl 0x8000594 <core::result::Result<(), core::convert::Infallible>::ok<(),core::convert::Infallible>>
0x0800025a <+82>: b.n 0x800025c <led_roulette::__cortex_m_rt_main+84>
0x0800025c <+84>: add r0, sp, #4
0x0800025e <+86>: mov.w r1, #500 ; 0x1f4
18 delay.delay_ms(half_period);
0x08000262 <+90>: bl 0x8002f5c <stm32f3xx_hal::delay::{{impl}}::delay_ms>
0x08000266 <+94>: b.n 0x8000268 <led_roulette::__cortex_m_rt_main+96>
End of assembler dump.
上のダンプで遅延が変わらなかった理由は、コンパイラが half_period は変化しないと
認識し、その結果 delay.delay_ms(half_period); が呼ばれている 2 か所で
mov.w r1, #500 が見えているためです。つまり、half_period の値を変更しても
何も起こりません。
0x08000244 <+60>: mov.w r1, #500 ; 0x1f4
15 delay.delay_ms(half_period);
0x08000248 <+64>: bl 0x8002f5c <stm32f3xx_hal::delay::{{impl}}::delay_ms>
(..)
0x0800025e <+86>: mov.w r1, #500 ; 0x1f4
18 delay.delay_ms(half_period);
0x08000262 <+90>: bl 0x8002f5c <stm32f3xx_hal::delay::{{impl}}::delay_ms>
この問題に対する 1 つの解決策は、以下に示すように half_period を Volatile でラップすることです。
#![deny(unsafe_code)]
#![no_main]
#![no_std]
use volatile::Volatile;
use aux5::{Delay, DelayMs, LedArray, OutputSwitch, entry};
#[entry]
fn main() -> ! {
let (mut delay, mut leds): (Delay, LedArray) = aux5::init();
let mut half_period = 500_u16;
let v_half_period = Volatile::new(&mut half_period);
loop {
leds[0].on().ok();
delay.delay_ms(v_half_period.read());
leds[0].off().ok();
delay.delay_ms(v_half_period.read());
}
}
Cargo.toml の [dependencies] セクションに volatile = "0.4.3" を追加してください。
[dependencies]
aux5 = { path = "auxiliary" }
volatile = "0.4.3"
上記のコードで Volatile を使うと、half_period を変更できるようになり、
さまざまな値を試せるようになります。以下にコマンドの一覧を示し、その後で
説明します。# xxxx は説明のためのものです。
$ cargo run --target thumbv7em-none-eabihf # プログラムをコンパイルして gdb に読み込む
(gdb) target remote :3333 # PC から STM32F3DISCOVERY ボードに接続する
(gdb) load # プログラムを書き込む
(gdb) break main.rs:16 # ループの先頭にブレークポイント 1 を設定する
(gdb) continue # 続行。main.rs:16 で停止する
(gdb) disable 1 # ブレークポイント 1 を無効にする
(gdb) set print asm-demangle on # asm-demangle を有効にする
(gdb) disassemble /m # main 関数を逆アセンブルする
(gdb) continue # LED が 1/2 秒点灯し、その後 1/2 秒消灯する
^C # Ctrl+C で停止する
(gdb) enable 1 # ブレークポイント 1 を有効にする
(gdb) continue # 続行。main.rs:16 で停止する
(gdb) print half_period # half_period を表示する。結果は 500
(gdb) set half_period = 2000 # half_period を 2000ms に設定する
(gdb) print half_period # half_period を表示する。結果は 2000
(gdb) disable 1 # ブレークポイント 1 を無効にする
(gdb) continue # LED が 2 秒点灯し、その後 2 秒消灯する
^C # Ctrl+C で停止する
(gdb) quit # gdb を終了する
重要な変更点はソースコードの 13、17、20 行目にあり、これは
逆アセンブル結果で確認できます。13 行目では v_half_period を作成し、その後
17 行目と 20 行目でその値を read() しています。これは、set half_period = 2000
を実行すると、LED が 2 秒間点灯し、その後 2 秒間消灯するようになることを意味します。
$ cargo run --target thumbv7em-none-eabihf
Compiling led-roulette v0.2.0 (~/embedded-discovery/src/05-led-roulette)
Finished dev [unoptimized + debuginfo] target(s) in 0.18s
Running `arm-none-eabi-gdb -q ~/embedded-discovery/target/thumbv7em-none-eabihf/debug/led-roulette`
Reading symbols from ~/embedded-discovery/target/thumbv7em-none-eabihf/debug/led-roulette...
(gdb) target remote :3333
Remote debugging using :3333
led_roulette::__cortex_m_rt_main () at src/05-led-roulette/src/main.rs:16
16 leds[0].on().ok();
(gdb) load
Loading section .vector_table, size 0x194 lma 0x8000000
Loading section .text, size 0x5258 lma 0x8000194
Loading section .rodata, size 0xbd8 lma 0x80053ec
Start address 0x08000194, load size 24516
Transfer rate: 21 KB/sec, 6129 bytes/write.
(gdb) break main.rs:16
Breakpoint 1 at 0x8000246: file src/05-led-roulette/src/main.rs, line 16.
Note: automatically using hardware breakpoints for read-only addresses.
(gdb) continue
Continuing.
Breakpoint 1, led_roulette::__cortex_m_rt_main () at src/05-led-roulette/src/main.rs:16
16 leds[0].on().ok();
(gdb) disable 1
(gdb) set print asm-demangle on
(gdb) disassemble /m
Dump of assembler code for function _ZN12led_roulette18__cortex_m_rt_main17he1f2bc7990b13731E:
9 fn main() -> ! {
0x0800020e <+0>: push {r7, lr}
0x08000210 <+2>: mov r7, sp
0x08000212 <+4>: sub sp, #72 ; 0x48
0x08000214 <+6>: add r0, sp, #36 ; 0x24
10 let (mut delay, mut leds): (Delay, LedArray) = aux5::init();
0x08000216 <+8>: bl 0x800036a <aux5::init>
0x0800021a <+12>: b.n 0x800021c <led_roulette::__cortex_m_rt_main+14>
0x0800021c <+14>: add r0, sp, #36 ; 0x24
0x0800021e <+16>: add r1, sp, #8
0x08000220 <+18>: ldmia.w r0, {r2, r3, r4, r12, lr}
0x08000224 <+22>: stmia.w r1, {r2, r3, r4, r12, lr}
0x08000228 <+26>: ldr r0, [sp, #56] ; 0x38
0x0800022a <+28>: ldr r1, [sp, #60] ; 0x3c
0x0800022c <+30>: str r1, [sp, #32]
0x0800022e <+32>: str r0, [sp, #28]
0x08000230 <+34>: mov.w r0, #500 ; 0x1f4
11
12 let mut half_period = 500_u16;
0x08000234 <+38>: strh.w r0, [r7, #-6]
0x08000238 <+42>: subs r0, r7, #6
13 let v_half_period = Volatile::new(&mut half_period);
0x0800023a <+44>: bl 0x800033e <volatile::Volatile<&mut u16, volatile::access::ReadWrite>::new<&mut u16>>
0x0800023e <+48>: str r0, [sp, #68] ; 0x44
0x08000240 <+50>: b.n 0x8000242 <led_roulette::__cortex_m_rt_main+52>
14
15 loop {
0x08000242 <+52>: b.n 0x8000244 <led_roulette::__cortex_m_rt_main+54>
0x08000244 <+54>: add r0, sp, #28
0x08000288 <+122>: b.n 0x8000244 <led_roulette::__cortex_m_rt_main+54>
16 leds[0].on().ok();
=> 0x08000246 <+56>: bl 0x800032c <switch_hal::output::{{impl}}::on<stm32f3xx_hal::gpio::gpioe::PEx<stm32f3xx_hal::gpio::Output<stm32f3xx_hal::gpio::PushPull>>>>
0x0800024a <+60>: b.n 0x800024c <led_roulette::__cortex_m_rt_main+62>
0x0800024c <+62>: bl 0x80005fc <core::result::Result<(), core::convert::Infallible>::ok<(),core::convert::Infallible>>
0x08000250 <+66>: b.n 0x8000252 <led_roulette::__cortex_m_rt_main+68>
0x08000252 <+68>: add r0, sp, #68 ; 0x44
17 delay.delay_ms(v_half_period.read());
0x08000254 <+70>: bl 0x800034a <volatile::Volatile<&mut u16, volatile::access::ReadWrite>::read<&mut u16,u16,volatile::access::ReadWrite>>
0x08000258 <+74>: str r0, [sp, #4]
0x0800025a <+76>: b.n 0x800025c <led_roulette::__cortex_m_rt_main+78>
0x0800025c <+78>: add r0, sp, #8
0x0800025e <+80>: ldr r1, [sp, #4]
0x08000260 <+82>: bl 0x8002fc4 <stm32f3xx_hal::delay::{{impl}}::delay_ms>
0x08000264 <+86>: b.n 0x8000266 <led_roulette::__cortex_m_rt_main+88>
0x08000266 <+88>: add r0, sp, #28
18
19 leds[0].off().ok();
0x08000268 <+90>: bl 0x8000882 <switch_hal::output::{{impl}}::off<stm32f3xx_hal::gpio::gpioe::PEx<stm32f3xx_hal::gpio::Output<stm32f3xx_hal::gpio::PushPull>>>>
0x0800026c <+94>: b.n 0x800026e <led_roulette::__cortex_m_rt_main+96>
0x0800026e <+96>: bl 0x80005fc <core::result::Result<(), core::convert::Infallible>::ok<(),core::convert::Infallible>>
0x08000272 <+100>: b.n 0x8000274 <led_roulette::__cortex_m_rt_main+102>
0x08000274 <+102>: add r0, sp, #68 ; 0x44
20 delay.delay_ms(v_half_period.read());
0x08000276 <+104>: bl 0x800034a <volatile::Volatile<&mut u16, volatile::access::ReadWrite>::read<&mut u16,u16,volatile::access::ReadWrite>>
0x0800027a <+108>: str r0, [sp, #0]
0x0800027c <+110>: b.n 0x800027e <led_roulette::__cortex_m_rt_main+112>
0x0800027e <+112>: add r0, sp, #8
0x08000280 <+114>: ldr r1, [sp, #0]
0x08000282 <+116>: bl 0x8002fc4 <stm32f3xx_hal::delay::{{impl}}::delay_ms>
0x08000286 <+120>: b.n 0x8000288 <led_roulette::__cortex_m_rt_main+122>
End of assembler dump.
(gdb) continue
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x080037b2 in core::cell::UnsafeCell<u32>::get<u32> (self=0x20009fa0) at ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/cell.rs:1716
1716 }
(gdb) enable 1
(gdb) continue
Continuing.
Breakpoint 1, led_roulette::__cortex_m_rt_main () at src/05-led-roulette/src/main.rs:16
16 leds[0].on().ok();
(gdb) print half_period
$2 = 500
(gdb) disable 1
(gdb) continue
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x08003498 in core::ptr::read_volatile<u32> (src=0xe000e010) at ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:1052
1052 unsafe { intrinsics::volatile_load(src) }
(gdb) enable 1
(gdb) continue
Continuing.
Breakpoint 1, led_roulette::__cortex_m_rt_main () at src/05-led-roulette/src/main.rs:16
16 leds[0].on().ok();
(gdb) print half_period
$3 = 500
(gdb) set half_period = 2000
(gdb) print half_period
$4 = 2000
(gdb) disable 1
(gdb) continue
Continuing.
^C
Program received signal SIGINT, Interrupt.
0x0800348e in core::ptr::read_volatile<u32> (src=0xe000e010) at ~/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ptr/mod.rs:1046
1046 pub unsafe fn read_volatile<T>(src: *const T) -> T {
(gdb) q
Detaching from program: ~/embedded-discovery/target/thumbv7em-none-eabihf/debug/led-roulette, Remote target
Ending remote debugging.
[Inferior 1 (Remote target) detached]
質問です!half_period の値を下げ始めると何が起こりますか?half_period が
いくつになると、LED の点滅が見えなくなりますか?
では、今度はあなたがプログラムを書く番です。