ちょっとTea Time!? PICO(RP2040)を思い出してみる(備忘録) 2024.2.15
Raspberry Pi PICOなるものが出て、飛びついたものの、
いまだにPICばかりつかっています。というのも、PICでできることが
PICOで出来ないとソフト移植もままならないので、そこが完全に
確認できていなかったからです。まずはPICOでも出来るでしょうが、
課題はやり方を知らないということです。
そこで、ここでは備忘録として、PICOの使い方についてすこし調べてみました。
<過去の記事>
ちょっとTea Time !? Raspberry Pi のPICOを動かしてみる。 2021.8.5
ちょっとTea Time!? PICOの開発環境を揃える(備忘録) 2022.7.10
ちょっとTea Time!? 秋月のRP2040マイコンボードを動かしてみる! 2023.3.1
こちらも備忘録がわりに貼り付けておきました。
1.インターバルタイマ割り込みは止められるの?
インターバルタイマー割り込みはタクトスイッチやエンコーダの接点を定期的に調べるために
1ms間隔で必ずといっていいほど使っているのですが、赤外線リモコンの受信ONを確認すれば、
そこからは割り込みを停止して、赤外線受信に専念するようにしています。というのも、赤外線の
リモコンコードは少なくとも数10msありますので、再帰的に割り込みがかかるとややこしいからです。
PICOでは disable_interrupts(INT_TIMER0) enable_interrupts(INT_TIMER0) で
タイマー割り込みの停止、再開の関数がありました。
PICOではどうすればいいのだろう?
ということで、あれこれ調べると、 ありました。
まずは、割り込みの種類で番号は割り当てられています。
そして、割り込みの停止、再開は
irq_set_enabled(割り込み種類の番号,0:停止 1:再開)
という関数で行えるようです。
サンプルプログラムで100usでタイマー割り込みをかけますが、
割り込みルーチンの中で、50usの処理と割り込みを止めて200usほどの処理を行うような
ことをしてみました。
GPIOの出力を観察すると、100us毎の割り込みですが、250us毎の
処理になっており割り込みが停止していることがわかりました。
なお、割り込みから復帰すると、すでにタイマー割り込みのトリガが
かかっている状態になっている様子なので、直ぐに再度割り込み処理が行われるようです。
// サンプルプログラム |
上:GPIO0、下:GPIO1 |
2.FLASHの書き込み速度は?
PICで設定値を記録・読み出しするときはEEPROMを使います。
関数は
write_eeprom(int16 adrs, int data)
read_eeprom(int16 adrs)
です。write関数は1バイトあたり概ね数msかかりますが、PICOの場合はどうだろう?
PICOではeepromの代わりにflashメモリーを使いますが、書き込みの前に
消去をする必要があります。そして消去の単位が4096byteと、書き込みの単位が
256byteと大きいです。どのくらいの時間がかかるのかな?
あまり時間がかかるようだと、どこかにバッファーをもたせて、適当な
タイミングでまとめて書くようなことをしなければなりません。
一度調べておきましょう。
まずはflashメモリをつかうために、CMakeLists.txt を一部編集(追記)します。
下記のように1024Byte分の領域を仮定して、書き込む時間を測定してみました。
書き込みにかかっているときのGPIOをONにしてオシロで時間を計測です。
で、結果は1024Byteの書き込みで35msほどかかりました。
こりゃ、PICとおなじようにEEPROMのように扱うためには、ちょっとした
サブルーチンをつくる必要がありそうです。
#include <stdio.h> #include "pico/stdlib.h" #include "hardware/pio.h" #include "hardware/interp.h" #include "hardware/timer.h" #include "hardware/watchdog.h" #include "hardware/clocks.h" #include "hardware/flash.h" #define GPIO_00 (0) #define FLASH_TARGET_OFFSET (0x1f0000) uint8_t write_data[1024]; void main( void ) { gpio_init( GPIO_00 ); gpio_set_dir( GPIO_00, GPIO_OUT ); while( true ) { gpio_put(GPIO_00,1); flash_range_erase(FLASH_TARGET_OFFSET, FLASH_SECTOR_SIZE); flash_range_program(FLASH_TARGET_OFFSET, write_data, FLASH_PAGE_SIZE * 4); gpio_put(GPIO_00,0); busy_wait_us_32(1000); } } |
(つづく?)