スイッチサイエンスが2022年6月に発表した「Raspberry Pi Pico W」を販売開始すると発表しました。価格は1,210円だそうです。技適取得のため発表からずいぶん時間が開きましたが、ようやく発売できるようになったようです。
現在は入手困難な様子ですが手に入ったらちょっといじってみたいと思います。
現在は入手困難な様子ですが手に入ったらちょっといじってみたいと思います。
https://datasheets.raspberrypi.com/picow/connecting-to-the-internet-with-pico-w.pdf
どうやらこれがネットワーク機能に関するドキュメントらしい。
アプリケーションノートっていうかSDKの差分マニュアルって感じ。
SDKのインストールの説明の所で"cyw43-driver"と"lwip"をチェックアウトしないとネットワーク機能は使えないと説明されている。
lwIP は組み込み向けのオープンソース TCP/IPプロトコルスタック。
後はCによるサンプルの説明と独自のプロジェクトの作成方法とMicroPythonでの使用方法が説明されていました。
CコードでlwIPのAPIを触る部分は全然説明が無く、これ以上の情報はlwIPのサイト(https://savannah.nongnu.org/projects/lwip/)かpico_wのサンプルコード(https://github.com/raspberrypi/pico-examples/tree/picow/pico_w)を見ろと書いてある。
サンプルコードはこんな感じ
・access_point
・blink
・freertos
・iperf
・ntp_client
・python_test_tcp
・tcp_client
・tcp_server
・wifi_scan
割とローレベルな物しかない印象…
Raspberry Pi PicoにInfineon CYW43439無線チップを追加搭載して2.4 GHzの無線LAN機能(802.11n)が使えるようになりました!
接続はSPI接続だそうで、CからもMicroPythonからも使えアクセスポイントとしても動作すると書かれています、サンプルコードはWEBサーバーとして動作するようなものだとか。
基本的にピンコンパチっぽいですがアンテナのせいかSWDとかデバッグ用端子は位置が変わってしまっています。ちなみにUSBコネクタはmicroです、どうせならType-Cにして欲しかったところです。
現在はまだ技適が取れてみたいで、技適が取れ次第発売予定となっていました。
発売したら入手していじってみたいと思います。
PICOのドキュメントを見てたら、いつの間にかアップデートしていることに気が付いた。
ヒストリーによると以下の通り
1.4 07/Apr/2021
• Minor corrections
• Added errata E10
• Note about how to update the C SDK from Github
• To accompany the V1.1.2 release of the C SDK
1.4.1 13/Apr/2021
• Minor corrections
• Clarified that all source code in the documentation is under the
3-Clause BSD license.
どうやらC SDKがV1.1.0からV1.1.2にアップデートしたようだが具体的なところはよくわかりません。Windowsでのデバッグ周りがもう少し簡単にならないかなと思う今日この頃。
たぶんディスプレイのベンダーによるものと思われるサンプルコードを元に書きましたが、CSをSPIの機能ではなく単純なGPIOとして動作させている以外は特に何も設定せずに素直に動いてくれました。
だがしかし!0.96インチだと文字が小さい・・・
もう一回り大きくしたいところだけどフォントを自作するのはめんどくさいなぁと思う今日この頃。
最近、Visual Studio Codeを積極的に使おうと努力しているのですがなかなか手に馴染みません。なんかヒントはないかなとGoogleで検索してみようかと「vs code 」と入力したところで検索候補に「日本語化」と出てきたので、そのまま検索してみたところトップに設定方法がそのまま表示されました。
Visual Studio Codeの日本語化設定
1. Visual Studio Codeを開く
2. メニューから[View]-[Command Palette]を選択
3. [Configure Display Language]を選択
4. [Install Additional Laugage]を選択サイドバーに拡張言語パックが表示されます。
簡単だけど、自分では絶対探し出せない自信がある。とりあえず日本語で表示できるようになりました。
日本語といえばソースコードのコメントが化ける場合があって文字コードの設定を合わせないとと思っていたのですが、実は自動認識の機能がありました、そしてなぜかデフォルトはオフ。どうかしています。
ファイル>基本設定>設定からfiles.autoGuessEncodingと入力しcheckをつけます。
Picoはこのクラスのマイコンにしては潤沢なメモリーを搭載しているのであまりメモリーマップを気にせずにここまで来ましたが、MSCでフラッシュアクセスなんかの活用を考えるとメモリーの使用状況の把握は必須なのでこの機会にメモリマップの表を作成しました。
Picoメモリーマップ | |||
| アドレス | サイズ | 用途 | 備考 |
| 0x00000000 | 0x4000 | ROM | ブートコードなど |
| 0x10000000 | 0x1000000 | Flash | XIPによりメモリーイメージに展開されている |
| 0x14000000 | XIP Registers | ||
| 0x15000000 | 0x4000 | XIP Cache | XIP Cacheを無効にしたらSRAMとして使用可能 |
| 0x20000000 | 0x40000 | SRAM | 4個のSRAM Bankをストライピングしている |
| 0x20040000 | 0x1000 | SRAM | |
| 0x20041000 | 0x1000 | SRAM | |
| 0x21000000 | 0x10000 | SRAM Bank 0 | |
| 0x21010000 | 0x10000 | SRAM Bank 1 | |
| 0x21020000 | 0x10000 | SRAM Bank 2 | |
| 0x21030000 | 0x10000 | SRAM Bank 3 |
コロナ騒ぎのニュースの中で換気の目安としてCO2センサーを使うという話しを聞きます。調べてみると部品としてもCO2センサーは数種類出回っているようなのでアマゾンで一番安いのを試しに買ってみました。

Seeedで基板を作る時にPicoをうけ Seeedで基板を作る時にPicoを売っているのを見つけて注文していたのですがようやく送られてきました。
MSCのサンプルアプリは8KByteのRAMドライブを使用していますがこのRAMドライブをフラッシュに置き換えていわゆるUSBメモリー的な動作をするようにしてみました。
まずはRAMドライブが512Byte/セクターになっているのでこれをフラッシュの消去単位である4KByte/セクターに変更します。ブロック数も256ブロックにして合計1MByteのドライブになるようにします。
合わせてBPBの内容をこのサイズに合わせます。
BPBの表記はリトルエンディアンなのでセクターサイズ(BPB_BytePerSec)4096=0x1000が0x00,0x10となり、セクターサイズが8倍になったのでルートエントリー(BPB_RootEntCnt)が0x10から0x80(128個)、トータルセクターサイズ(BPB_TotSec16)は256=0x100なので0x00,0x01となります。
管理情報を予め書いておかないとアクセスできないので未フォーマットの場合(BPBのシグネイチャーが書かれていないことで判断)管理情報をフラッシュに書き込みます。
後は肝心の読み書きAPIのwrite10,read10をフラッシュの読み書きに置き換えます。
ReadはRP2040のeXecute In Place(XIP)の仕組みのおかげでダイレクトにメモリにマッピングされているように見えますので単純にメモリーコピーで読めます。問題なのは書き込みの方でフラッシュに書き込みを行うとキャッシュのコヒーレンシーの問題が出てしまいキャッシュをクリアする必要があるのですが、このキャッシュの管理がコードを実行しているXIPと共通なのでコードの実行に支障が出て書き込み時にストールしてしまうことがあります。データシートを見ると何か回避策がありそうな感じですが。一般的なセオリーであるフラッシュ書き込み時には別のメモリー(RAM)でコードを実行するという方法で回避します。調べてみると実に簡単にRAM上で実行できました。
CMakeLists.txtに以下の1行を足すだけです。
これで1MByteのUSBメモリーになりました。
Pico側でもこのファイルを読み書きできるように実装すればPCとのデータ共有が楽になるのでアプリケーションの幅が広がるかなと思います。
マルチコア用の仕組みはこれだけではなくコアの間にSIO(Single-cycle IO block)というブロックがありこの中にFIFO 0 to 1、FIFO 1 to 0というコア間でデータ転送する仕組みとHardware Spinlockというリソースの排他制御の仕組みなどがあります。
SIO(Single-cycle IO block)に含まれる機能
・CPUID
・GPIO Control
・Hardware Spinlock
・Inter-processor FIFO (Mailboxes)
・Integer Divider
・Interpolator
先日見つけた Tiny USB のサンプルコードは送信しかしていなかったので受信はどうするのかなと色々見てたのですが特にドキュメントも用意されていない様子。まぁこれぐらいのことはソースコードを読んで理解しろということなのかもしれません。
とりあえずサンプルコードで送信している関数tudi_midi_write24()をgrepしてみるとこれはmidi_device.hというヘッダーファイルにインライン関数として定義されていました。
同列に用意されているAPIは以下の通り。
3バイトメッセージの送信関数はあるのに2バイトメッセージの送信関数は無いんだなという中途半端感はありますが、問題はそこではなく受信関数でした。この中で受信に関係ありそうなのはtud_midi_read()とtud_midi_read_flush()。ソースコードを確認してみたところtud_midi_available()も受信用APIでした。
static inline uint32_t tud_midi_available(void);
受信FIFOにあるデータ数を返す。
static inline uint32_t tud_midi_read(void* buffer, uint32_t bufsize);
受信FIFOにあるデータを指定されたバッファにコピーする。
static inline void tud_midi_read_flush(void);
受信FIFOをクリアする。
ということらしいのでtud_midi_available()でデータを受信しているか確認してデータがあればtud_midi_read()で読み込むというのが正しそうです。
実際のコードにするとこんな感じ
試しにMIDI-OXからノートメッセージを送信してみるとコンソールに正しく表示されました。この関数をメインループの中からポーリングしても良いですがtud_midi_rx_cb()というコールバックの仕組みも用意されているのでこちらから呼ぶのがスマートですね。
RTOSが使えるようになったらここでタスクを起床してMIDI処理をさせる流れです。
秋月で自作基板用の部品を見繕っていたらPimoroniのPico RGB Keypadを見つけ、「これはMIDIコントローラーに良いかも!」と一緒に注文してしまいました。
それが届いたので早速組み立て。といっても半田付けするようなところはなくキーパッドのシリコンパッドをネジ止めするだけです。そして公式のGitリポジトリからサンプルコードを落として、コンパイル、焼きこみ、・・・何も起こらない。
サンプルのソースコードを見るとLEDは薄く点灯してパッドを押すとLEDの色が変化する感じのようです。とりあえず良くわからないのでサンプルコードでUSB-シリアルを使えるように変更してprintfデバッグしてみたところ、どうやらスイッチは正しく読めているがLEDが全く反応しない。PICOのSPI端子の所をオシロで見てもそれなりに動いてそうです。
Pimoroni公式に何か情報ないかと見て回ったのですが、この基板の回路図すらおいてない。まぁ動いてしまえば大したことやってる基板じゃないからサンプルコードだけあれば十分なんだろうけどね。楽しみにしていた分がっかりでした。
3/14に発注した基板が今日届きました!13日後ということで2週間かからずに手に入るのはなかなか良いのではないかと思います。ほとんどが輸送にかかっている時間なので輸送にお金をかければもっと早くなるんじゃないかと思います。
ピンヘッダーも付けたのでブレッドボードと組み合わせるもよし、ユニバーサル基板部分も設けているので開発基板としてはそれなりに使えそうです。
だがしかし、肝心のPicoが1枚しかないのでPicoprobeを使った開発がまだできないのが残念。現在追加の発注をしているので届くまではprintfデバッグで頑張ります!
Raspberry Pi PicoはRaspberry Pi財団が独自に開発したARM Cortex M0+デュアルコアのRP2040というマイコンが搭載されています。スマホに慣れた人にはデュアルコアなんて当たり前に見えるかもしれませんがARMのM系マイコンのプログラミングをしたことのある人には「え?どうなってんの?」と思わずにはいられないと思います。一般的にはメインメモリへのアクセスの競合を抑えるためにコアにキャッシュを持つのがマルチコアの常套手段だと思うのですがRP2040はM0+コアですからキャッシュなんてありません。RP2040のデータシートを見てみるとどうやらAHB-Lite crossbarというバスと6個に分割されているSRAMに仕組みがありました。AHB-Lite crossbarはクロスバーというだけあり単純なバスではなくSplitterとArbiterの組み合わせにより最大同時4転送できるようになっており分割されたSRAMを個別に割り当てることにより独立動作することが可能になっているようです。
RP2040の主な機能
• Dual Cortex M0+ processor cores, up to 133 MHz
• 264 kB of embedded SRAM in 6 banks
• 6 dedicated IO for SPI Flash (supporting XIP)
• 30 multifunction GPIO
• Dedicated hardware for commonly used peripherals
• Programmable IO for extended peripheral support
• 4 channel ADC with internal temperature sensor, 0.5 MSa/s, 12-bit conversion
• USB 1.1 Host/Device
まじめにTinyUSBのドキュメントを読み込むのは大変なのでUSB-MIDIのサンプルコードが無いかなと探していたところpico-sdk/lib/tinyusbにサンプルが含まれているという記事を見つけて、「そうかpico-exampleじゃなくてpico-sdkの方か!」と早速そのフォルダを見てみるとなんとカラでした。
WEBから見るGitリポジトリにはファイルが色々あるのでどうやら落とせてないだけみたい。Gitには詳しくないので色々調べてみたところ、Raspberry Pi Picoに直接関係が無いような部分はsubmoduleで管理しておりドキュメントで書かれているコマンドでは落ちてこないそうです。
ドキュメントに書かれているSDKを落とすコマンド
>git clone -b master https://github.com/raspberrypi/pico-sdk.git
こうするとsubmoduleも全部落としてくれる
>git clone --recursive https://github.com/raspberrypi/pico-sdk.git
私のように既に落としてしまっている場合はpico-sdkフォルダ上から
>git submodule update --init --recursive
とすると全部落としてくれます。
ちなみにUSB-MIDIのサンプルはここにありました。
pico-sdk\lib\tinyusb\examples\device\midi_test
スイッチをマジメに読むにはチャタリングの除去をする必要がありますが、タイマー割り込みを設定するほどのことではないのでサンプルコードにちょうど良い物がないかなと探してみたらTiny USBのコードの中でboard_millis()という関数で起動からの積算時間をミリ秒単位で取得していました。ソースコードを見てみるとTiny USBとして抽象化するためにラッピングしているだけのようなので、直接SDKのAPIを呼ぶようにします。
APIとしては to_ms_since_boot(get_absolute_time()) こんな感じでget_absolute_time()でマイクロ秒単位の時間を単純に/1000しているだけのようです。
実際のコードはほぼサンプルコードと同じにして経過時間が達していなければリターンするコードとなっています。
プロジェクトを手動で作る方法を延々と説明した後で、GUIでプロジェクトを作成するツールが紹介されてます。初心者にはこちらを先に教えてもらった方がうれしいのではないだろうか?
さっそくGitから落とします。
> git clone https://github.com/raspberrypi/pico-project-generator.git
フォルダに移動して実行します
> cd pico-project-generator
> pico_project.py --gui

基板を発送したとメールが来たので、中身の方を少しづつ作っていく事にします。
まずはLチカでGPIO出力はやってみているのでブレッドボード上にSWを実装してGPIO入力を確認します。
写真の通りGPIO10とGND間にタクトスイッチを実装します。
通常スイッチ入力の場合、抵抗でプルアップしますがRP2040は各ポートに内蔵プルアップ/プルダウンの機能があるのでそれを有効にします。SDKにgpio_puull_upというAPIが用意されているのでそれを使ってプルアップ抵抗を有効にします。
実行部分は簡単に押されてGPIOがローレベルになったらそのままLEDのGPIOもローレベルにしてLEDを消灯するというものです。
現状Picoがなかなか入手できないので2枚使ってのSWDデバッグが出来ないのでついでにprintfデバッグをするためのシリアル出力を確認しておきます。
CMakeLists.txtに下記の行を入れます。
pico_enable_stdio_usb(test 1)
標準入出力のヘッダーファイルstdio.hをインクルードします。
main関数の冒頭で初期化します。
puts関数で出力します。
非常に簡単です、ちなみにCMakeLists.txtの行を入れ替えるだけでUART出力に入れ替えられるようです。SDKさまさまです、とても良くできてると思います。
サンプルコードを直接変更するのも何なので「Getting started with Raspberry Pi Pico」の「Chapter 7. Creating your own Project」の感じで新規プロジェクトを作成します。
ドキュメントではLinux環境で説明されているのでWindows用に読み替えていきます。
pico-examples/
pico-sdk/
test/
ここにtestフォルダを作成してソースコード(test.c)とCMakeLists.txt、pico_sdk_import.cmakeをコピーします。
CMakeLists.txtの中身はこんな感じ
cmake_minimum_required(VERSION 3.12)
include(pico_sdk_import.cmake)
project(test_project)
pico_sdk_init()
add_executable(test
test.c
)
pico_enable_stdio_usb(test 1)
pico_add_extra_outputs(test)
target_link_libraries(test pico_stdlib)
pico_sdk_import.cmakeは pico-sdk/external/pico_sdk_import.cmake にあります。
testフォルダ内にbuildフォルダを作成してそこから下記のようにmakeを実行します。
cmake -G "NMake Makefiles" ..
nmake
これでtest.uf2まで作成できます。
ちなみにファイルを追加する場合はCMakeLists.txtにファイル名を追加します。
add_executable(test
test.c
add_file.c
)