とりあえず実機が手に入ったので定番のLチカでもしてみようと思います。といってもサンプルコードですでに用意されているのでそれを焼きこむだけです。
何も焼きこんでいない状態のPicoはUSBケーブルを刺すだけでブートモードになるようでドライブが現れますのでサンプルで用意されていたblink.uf2をドラッグアンドドロップで書き込みます。そうすると自動的にドライブが切断されてLEDがチカチカし始めました。非常にあっさりです。
ここでどれぐらいの速度でGPIOポートを操作できるのか確認しようとsleep関数をコメントアウトしてみました。
int main() {
const uint LED_PIN = 25;
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
while (true) {
gpio_put(LED_PIN, 1);
// sleep_ms(250);
gpio_put(LED_PIN, 0);
// sleep_ms(250);
}
}
想定では少し暗くLEDが点灯するはずですが、消灯のままです。最適化でコードが無くなっちゃってるのかと思いアセンブラ出力ファイルblink.disを開いてみるとmain関数はこんな感じでコードが無くなっている感じはありません。
sleepあり
1000030c <main>:
1000030c: b570 push {r4, r5, r6, lr}
1000030e: 2019 movs r0, #25
10000310: f000 f82a bl 10000368 <gpio_init>
10000314: 23d0 movs r3, #208 ; 0xd0
10000316: 061b lsls r3, r3, #24
10000318: 2280 movs r2, #128 ; 0x80
1000031a: 0492 lsls r2, r2, #18
1000031c: 625a str r2, [r3, #36] ; 0x24
1000031e: 24d0 movs r4, #208 ; 0xd0
10000320: 0624 lsls r4, r4, #24
10000322: 2580 movs r5, #128 ; 0x80
10000324: 04ad lsls r5, r5, #18
10000326: 6165 str r5, [r4, #20]
10000328: 20fa movs r0, #250 ; 0xfa
1000032a: f000 fcb1 bl 10000c90 <sleep_ms>
1000032e: 61a5 str r5, [r4, #24]
10000330: 20fa movs r0, #250 ; 0xfa
10000332: f000 fcad bl 10000c90 <sleep_ms>
10000336: e7f2 b.n 1000031e <main+0x12>
sleepなし
1000030c <main>:
1000030c: b510 push {r4, lr}
1000030e: 2019 movs r0, #25
10000310: f000 f824 bl 1000035c <gpio_init>
10000314: 23d0 movs r3, #208 ; 0xd0
10000316: 061b lsls r3, r3, #24
10000318: 2280 movs r2, #128 ; 0x80
1000031a: 0492 lsls r2, r2, #18
1000031c: 625a str r2, [r3, #36] ; 0x24
1000031e: 23d0 movs r3, #208 ; 0xd0
10000320: 061b lsls r3, r3, #24
10000322: 2280 movs r2, #128 ; 0x80
10000324: 0492 lsls r2, r2, #18
10000326: 615a str r2, [r3, #20]
10000328: 619a str r2, [r3, #24]
1000032a: e7f8 b.n 1000031e <main+0x12>
赤字の部分がGPIOへのセットとリセットですが1命令で並んでいるのでペリフェラルへアクセスするタイミングでは同タイミングになってしまい無かったことになっているか100MHzのオシロスコープでは見えないようなパルスになっているのかもしれません。
試しに0と1の順番を変えてみるとLEDは点灯しっぱなしになりました。
while (true) {
gpio_put(LED_PIN, 0);
// sleep_ms(250);
gpio_put(LED_PIN, 1);
// sleep_ms(250);
}
しょうがないのでレジスタアクセスを無駄に1個増やしてみたところ、無事パルスが出るようになりました。
int main() {
const uint LED_PIN = 25;
const uint GPIO_PIN = 22;
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
gpio_init(GPIO_PIN);
gpio_set_dir(GPIO_PIN, GPIO_OUT);
while (true) {
gpio_put(LED_PIN, 0);
// sleep_ms(250);
gpio_put(GPIO_PIN, 1);
gpio_put(LED_PIN, 1);
// sleep_ms(250);
}
}
1000030c <main>:
1000030c: b510 push {r4, lr}
1000030e: 2019 movs r0, #25
10000310: f000 f82e bl 10000370 <gpio_init>
10000314: 24d0 movs r4, #208 ; 0xd0
10000316: 0624 lsls r4, r4, #24
10000318: 2380 movs r3, #128 ; 0x80
1000031a: 049b lsls r3, r3, #18
1000031c: 6263 str r3, [r4, #36] ; 0x24
1000031e: 2016 movs r0, #22
10000320: f000 f826 bl 10000370 <gpio_init>
10000324: 2380 movs r3, #128 ; 0x80
10000326: 03db lsls r3, r3, #15
10000328: 6263 str r3, [r4, #36] ; 0x24
1000032a: 23d0 movs r3, #208 ; 0xd0
1000032c: 061b lsls r3, r3, #24
1000032e: 2280 movs r2, #128 ; 0x80
10000330: 0492 lsls r2, r2, #18
10000332: 619a str r2, [r3, #24]
10000334: 2180 movs r1, #128 ; 0x80
10000336: 03c9 lsls r1, r1, #15
10000338: 6159 str r1, [r3, #20]
1000033a: 615a str r2, [r3, #20]
1000033c: e7f5 b.n 1000032a <main+0x1e>
0x1000032aからのループなのでちょうど10ステップ、このループが12MHzぐらいで回っているので、I/Oアクセスでもそれほどスピードが落ちていない感じです。