ソースを参照

new file: Install_SDK_onto_WSL/INSTALL.md

Satoshi Yoneda 2 週間 前
コミット
f959ec0e78

+ 105 - 0
Install_SDK_onto_WSL/INSTALL.md

@@ -0,0 +1,105 @@
+# WSL2にPico C SDK環境をインストールする
+
+Windows 11自体やSDKのアップデートにより、Windows上でPico C SDKによるデバッグが頻繁に利用できなくなったり、壊れる現象が発生しています。もっとも良い解決方法は、開発環境にLinuxかmacOSを利用することですが、手元に自由に利用できるLinuxやMacがないという方も多いでしょう。
+
+次善の策として、Windows上の仮想Linux環境であるWSL2にPico C SDKをインストールして利用する方法があります。若干の手間は発生しますが、VSCodeのWSL拡張機能を利用することでWindowsから透過的に開発環境を利用でき、なおかつ仮想とはいえLinux環境下であるためWindowsネイティブよりは安定してPico C SDKを利用することが可能です。Windows上でPico C SDKが動作しなくなった、あるいはインストールできなかった方は以下の手順を参考に、WSL2にインストールしてください。
+
+## WSL2をWindowsにインストールする
+
+WSL2のインストール方法はMicrosoft公式を始め、さまざまなサイトに解説があるので、それを参考にすればいいでしょう。インストールプロセス自体は簡単です。コマンドプロンプトかPower Shellを管理権限で開き、次のコマンドを実行してWindowsを再起動します。
+
+```console
+>wsl --install [Enter]
+```
+
+ディストリビューションはWindows Storeからインストールするのが簡単です。Windows Storeを起動して、インストールしたいディストリビューション名を検索してインストールしてください。ディストリビューションは自分が利用したいものがあればそれで構いませんが、ここではUbuntu 22.04 LTS以降を前提にしていきます。
+
+![Windows StoreでUbuntuを検索した例。22.04 LTS以降をインストールします](image/INSTALL/1764217917063.png)
+
+![入手をクリックしてインストール](image/INSTALL/1764217966770.png)
+
+ディストリビューションのインストールが終わったら、端末を開いて初期ユーザー名とパスワードを登録し、Linuxのシェルが利用できる状態にしてください。
+
+![端末を使えるようにする](image/INSTALL/1764218113004.png)
+
+端末が使えるようになったら、aptを使って次のパッケージをインストールしておいてください。Pico C SDKを利用するために必要になります。
+
+```console
+sudo apt install libhidapi-dev gdb-multiarch  libftdi1-dev libusb-1.0-0-dev usbutils build-essential [Enter]
+```
+
+## usbipd-winのインストール
+
+WSL2はMicrosoftの仮想化技術Hyper-Vを用いて、WSL2専用の仮想マシン下でLinuxを動作させています。Hyper-V仮想マシンに、ホストOS側のUSBデバイスを割り当てる[usbipd-win](https://github.com/dorssel/usbipd-win)というツールがオープンソースで開発されています。
+
+WSL2上のPico C SDKを利用してデバッグを行うには、WSL2環境下でCMSIS-DAPを利用しなければならないので、そのためにusbipd-winを利用します。[公式サイトのReleaseページ](https://github.com/dorssel/usbipd-win/releases)から最新バージョンのインストーラー(MSIパッケージ形式)ダウンロードしてください。MSIパッケージをダブルクリックしてWindowsにインストールします。
+
+PCにCMSIS-DAP(PicoprobeかRaspberry Pi Debug Probe)を接続しておいてください。usbipd-winをインストール後、Power Shellまたはコマンドプロンプトを**管理権限で**開きます。まず、`usbipd list`を実行して現在のUSBデバイスのリストを得ます。
+
+![Windowsが認識しているUSBデバイスのリストを得る](image/INSTALL/1764220124728.png)
+
+このようにCMSIS-DAP v2がリストに含まれているはずです。usbipdは、BUSIDかVID:PIDのいずれかでデバイスをHyper-V仮想マシン下に割り当てることができます。どちらでもいいですが、おすすめはVID:PIDです。VID:PIDで割り当てておくと、接続するUSBポートを変えてもusbipdの共有対象デバイスが維持されるからです。この例であれば2e8a:000cをコピーしておきます。
+
+そのうえで、次のコマンドを実行しusbipdの共有対象デバイスに2e8a:000cを登録します。
+
+```console
+usbipd bind --hardware-id 2e8a:000c [Enter]
+```
+
+改めてリストを取ると、次のようにSTATEがSharedに変わっているはずです。
+
+![usbipdの共有対象にCMSIS-DAPが追加された](image/INSTALL/1764220815816.png)
+
+このようにSharedに設定したデバイスは、次のコマンドでWSL2仮想マシンに接続できます。
+
+```console
+usbipd attach --wsl --hardware-id 2e8a:000c [Enter]
+usbipd: info: Device with hardware-id '2e8a:000c' found at busid '9-2'.
+usbipd: info: Using WSL distribution 'Ubuntu' to attach; the device will be available in all WSL 2 distributions.
+usbipd: info: Detected networking mode 'nat'.
+usbipd: info: Using IP address 172.30.112.1 to reach the host.
+```
+
+この例のようにエラーなくattachできたなら、Linuxの端末側で`lsusb`コマンドを実行してみてください。
+
+```console
+$ lsusb [Enter]
+Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
+Bus 001 Device 003: ID 2e8a:000c Raspberry Pi Debugprobe on Pico (CMSIS-DAP)
+Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
+```
+
+このように仮想マシン下のLinux側に接続されているはずです。なお、仮想マシンに接続したUSBデバイスは、ホストOSであるWindows上では利用できなくなります。ホストOS側でCMSIS-DAPを利用したいときは、Power Shellまたはコマンドプロンプトで次のコマンドを実行しdetachします。
+
+```console
+usbipd detach --hardware-id 2e8a:000c [Enter]
+```
+
+同じようにunbindを実行すれば共有デバイスからも外せますが、今後もWSL2環境側でCMSIS-DAPを使うのであればunbindは必要ありません。いったんbindしたデバイスは、USBポートから取り外したり、Windowsを再起動しても共有デバイスリストに残り続けます。
+
+ただし、attachの操作はWSL2起動後に毎回必要になります。少々面倒ですが、Pico C SDKを利用する前にPower Shellもしくはコマンドプロンプトを開いてコマンドを実行するだけでので、大した手間でもないでしょう。
+
+## VSCodeにWSL拡張とPico拡張をインストール
+
+Windows上でVSCodeを起動し、拡張機能「WSL」を検索してインストールしてください。提供元がMicrosoftになっていることを必ず確認します。
+
+![Microsoft純正のWSL拡張機能をインストールする](image/INSTALL/1764222939769.png)
+
+インストール後、VSCodeウィンドウ左下にあるリモート接続アイコンをクリックします。接続先を聞いてくるので、「WSLへの接続」を選択します。
+
+![WSLへの接続を選択](image/INSTALL/1764223120049.png)
+
+初回接続時にはWSL2のLinux側でVSCodeサーバーの設定が行われるので少し時間がかかりますが、しばらくするとWS2に接続した状態に切り替わります。左下のアイコンが`WSL:ディストリビューション名`に切り替わるので、それを確認してください。
+
+![WSL2に接続した状態](image/INSTALL/1764223279680.png)
+
+正常にWSL2に接続できたら、拡張機能アイコンをクリックしてPico拡張を検索します。次のように``WSL:ディストリビューション名にインストール``というインストールボタンが表示されるはずなので、クリックしてWSL側にPico拡張をインストールしましょう。
+
+![WSL2にPico拡張をインストールする](image/INSTALL/1764223420014.png)
+
+あとは、Windows側にインストールした場合とほとんど同じようにPico C SDKによる開発が行えます。注意すべきなのは、次の点です。
+
+* VSCode起動後に必ずWSLに接続し接続状態を確認する
+* デバッグを行う前に、CMSIS-DAPがWSLにattachされていることを確認する。attachされていないときはPower Shellまたはコマンドプロンプト上でusbipdコマンドを使ってattachする
+* プロジェクトディレクトリはWSL2の仮想ストレージ下に作成する(/mnt/ドライブレター/以下を使えばWindows側のストレージにもプロジェクトを作成できますが、WSL2はWindowsストレージへのアクセスが極端に遅いので、あまりおすすめできません)
+* シリアル端末にはデバイスノード`/dev/ttyACM0`を利用する

BIN
Install_SDK_onto_WSL/image/INSTALL/1764217917063.png


BIN
Install_SDK_onto_WSL/image/INSTALL/1764217966770.png


BIN
Install_SDK_onto_WSL/image/INSTALL/1764218113004.png


BIN
Install_SDK_onto_WSL/image/INSTALL/1764220124728.png


BIN
Install_SDK_onto_WSL/image/INSTALL/1764220815816.png


BIN
Install_SDK_onto_WSL/image/INSTALL/1764221250926.png


BIN
Install_SDK_onto_WSL/image/INSTALL/1764222939769.png


BIN
Install_SDK_onto_WSL/image/INSTALL/1764223120049.png


BIN
Install_SDK_onto_WSL/image/INSTALL/1764223279680.png


BIN
Install_SDK_onto_WSL/image/INSTALL/1764223420014.png


+ 15 - 16
jpfont_2_lcd/jpfont_2_lcd.cpp

@@ -146,21 +146,13 @@ int dma_ch = -1;                         // DMAチャンネル
 dma_channel_config dma_conf;             // DMA設定
 volatile bool dma_in_prgress = false;    // DMA転送中フラグ
 
-// ワンショットタイマー遅延呼び出し用
-int64_t schedule_deferred_call(alarm_id_t id, void *user_data)
-{
-    // DMA転送中フラグを落とす
-    dma_in_prgress = false;
-    return 0;
-}
 
 // DMA割り込み
 void dma_irq_handler()
 {
     dma_channel_acknowledge_irq0(dma_ch);
-    // 遅延を入れないと死ぬ
-    // ワンショットタイマーで20マイクロ秒後にフラグを落とす
-    add_alarm_in_us(20, schedule_deferred_call, NULL, true);
+    // DMA転送中のフラグを落とす
+    dma_in_prgress = false;
 }
 
 uint8_t *string_line_buffer[2];             // 1行バッファ
@@ -196,6 +188,11 @@ void draw_font_in_buffer(font_gryph_t *gryph, int x, int y)
 // 文字列描画用DMA設定関数
 void configure_dma_channel(void)
 {
+    // DMA用のダブルバッファを確保しておく
+    size_t line_buffer_size = TFT_WIDTH * pfn->get_max_font_height() * TFT_BYTES_PER_PIXEL;
+    string_line_buffer[0] = (uint8_t *)malloc(line_buffer_size);
+    string_line_buffer[1] = (uint8_t *)malloc(line_buffer_size);
+
     dma_ch = dma_claim_unused_channel(true);
     dma_conf = dma_channel_get_default_config(dma_ch);
     channel_config_set_transfer_data_size(&dma_conf, DMA_SIZE_16);
@@ -239,7 +236,12 @@ void render_string(const char *str, int x, int y)
         return;
 
     // 前のDMAを待つ
-    while(dma_in_prgress);
+    while(dma_in_prgress) {
+        // SSPのTX FIFOが空になるまで待つ
+        while(!(spi_get_hw(SPI_PORT)->sr & 1));
+        // 少し間を空けないと死ぬ
+        sleep_us(20);
+    }
 
     // SST77xxコマンド発行
     uint8_t cmd_param[4] = {0,0,0,0};
@@ -252,7 +254,7 @@ void render_string(const char *str, int x, int y)
     sst7735_send_cmd(SSTCMD_RASET);     // Row Address Set
     sst7735_send_data8(cmd_param, 4);
     sst7735_send_cmd(SSTCMD_RAMWR);     // RAM RW mode
-    sleep_us(50);
+    sleep_us(20);
 
     gpio_put(TFT_DC, TFT_DATA);
     spi_set_format (SPI_PORT, 16, SPI_CPOL_1 , SPI_CPHA_1,SPI_MSB_FIRST );
@@ -306,13 +308,10 @@ int main()
     // フォントが正しく読み込めたかチェック
     if (pfn->isValid()) {
         printf("Font loaded successfully.\n");
-        
-        size_t line_buffer_size = TFT_WIDTH * pfn->get_max_font_height() * TFT_BYTES_PER_PIXEL;
-        string_line_buffer[0] = (uint8_t *)malloc(line_buffer_size);
-        string_line_buffer[1] = (uint8_t *)malloc(line_buffer_size);
 
         // render_string()を使用する前にかならずconfigure_dma_channel()を呼ぶこと
         configure_dma_channel();
+        
         int x = 0, y = 0;
         while (true) {
             back_color = TFT_COLOR_BLACK;

+ 5 - 5
jpfont_test/README.md

@@ -2,13 +2,13 @@
 
 書籍に掲載する予定でしたが、時間切れで掲載できなかったコードです。これは日本語フォントファイルである[Pinot Font(PFN)フォーマット](https://zenn.dev/nom/articles/20211016-micropython-code-to-display-utf8-kanji)のフォントを使って日本語文字描画を行うためのライブラリpfnfont.h/pfnfont.cppと、そのテスト用コードで構成されています。
 
-[Pinot Font(PFN)フォーマット](https://zenn.dev/nom/articles/20211016-micropython-code-to-display-utf8-kanji)についてはリンク先に説明がありますが、フォントグリフをUTF-32コードポイント並びに変換した日本語ビットマップフォントです。従来の日本語フォントは文字コードにJISなどが使われていて扱いが少々厄介ですが、PFNフォントは現在主流のUTF-8環境で簡単かつ高速に扱うことができ、Picoシリーズで日本語を表示させるのに便利です。ご本家はMicroPython向けですが、C++でPFNフォントを扱うライブラリを作成しました。
+[Pinot Font(PFN)フォーマット](https://zenn.dev/nom/articles/20211016-micropython-code-to-display-utf8-kanji)についてはリンク先に説明がありますが、フォントグリフをUnicodeコードポイント並びに変換した日本語ビットマップフォントです。従来の日本語フォントは文字コードにJISなどが使われていて扱いが少々厄介ですが、PFNフォントは現在主流のUTF-8環境で簡単かつ高速に扱うことができ、Picoシリーズで日本語を表示させるのに便利です。ご本家はMicroPython向けですが、C++でPFNフォントを扱うライブラリを作成しました。
 
 Picoでデバッグ実行すると、次のようにコンソールに「Picoで日本語表示」という文字列がアスキーアートで表示されます。
 
 ![1755325635472](image/README/1755325635472.png)
 
-PFNFontクラスを使うには、何らかの方法でメモリに読み込んだPFNフォントと、コールバック関数が必要です。このサンプルでは`.incbin`を使って14ドットフォントをメモリ中に置いています。
+PFNFontクラスを使うには、何らかの方法でメモリに読み込んだPFNフォントと、コールバック関数が必要です。このサンプルでは `.incbin`を使って14ドットフォントをメモリ中に置いています。
 
 コールバック関数は3つの引数を取り、渡された1文字のフォントグリフを描画する関数を作成します。描画する先は通常はLCDやOLEDになるでしょう。
 
@@ -16,7 +16,7 @@ PFNFontクラスを使うには、何らかの方法でメモリに読み込ん
 void your_callback(font_gryph_t font, int x, int y);
 ```
 
-フォントのビットマップは`font_gryph_t font`に次のように格納されています。
+フォントのビットマップは `font_gryph_t font`に次のように格納されています。
 
 ```c
 typedef struct __attribute__((packed)) {
@@ -26,13 +26,13 @@ typedef struct __attribute__((packed)) {
 } font_gryph_t;
 ```
 
-`x`および`y`は必要に応じて利用するディスプレイ上でのフォントの描画座標が格納されています。
+`x`および `y`は必要に応じて利用するディスプレイ上でのフォントの描画座標が格納されています。
 
 ```c
 PFNFont *pfn = new PFNFont(フォントデータの先頭アドレス, フォントデータのサイズ, コールバック関数);
 ```
 
-次のように`draw_string()`を呼ぶと1文字ごとに(ここまでの例なら)`your_callback()`が呼ばれます。`your_callback()`を利用したい表示デバイスに合わせて記述すれば、どんなディスプレイにも日本語が表示できます。
+次のように `draw_string()`を呼ぶと1文字ごとに(ここまでの例なら)`your_callback()`が呼ばれます。`your_callback()`を利用したい表示デバイスに合わせて記述すれば、どんなディスプレイにも日本語が表示できます。
 
 ```c
 pfn->draw_string("Picoで日本語表示!", 0, 0);