はじめに
Lチカが動いたのでシリアルでHello world
してみる。
このハロワは失業と関係ない
今時の人たちはHello world
を「ハロワ」と略すらしい。
当時在籍した会社が潰れてハローワークにお世話になった経験がある筆者は、このワードからは悲壮感しか無い。
プロジェクトの作成
戯言はともかく、プロジェクトを作成する。
$ mkdir -p ~/pio/longan_hello $ cd ~/pio/longan_hello $ pio init -b sipeed-longan-nano
USART0のピン
Longan nanoで一番簡単に使用できそうなシリアルポートはUSART0で、 これらは基板に引き出されている。
Type-Cポートを左にした時に右側に見える「T0」と「R0」のシルクがあるピンがそれぞれ次のようになっている。
pin | 機能 |
---|---|
T0 | PA9/USART0_TX |
R0 | PA10/USART0_RX |
今回は出力だけなのでT0のみ使用する。
プログラムの作成
platformio.ini
Lチカではframeworkをarduino
としたが、今回はデフォルトのgd32vf103-sdk
を使用する。
ファームウェアの書き込みにDFUを使用するので、最終的には次のようになる。
[env:sipeed-longan-nano] platform = gd32v board = sipeed-longan-nano framework = gd32vf103-sdk upload_protocol = dfu
シリアル送信までの流れ
まず、Longan nanoのUSART0を使用できるようにする必要がある。
それには次のような処理が必要となる。
- GPIOAのクロック有効化
- USART0のクロック有効化
- PA9ピンのAlternative Function設定
- USART0の有効化
初期化処理は次のようにする。
// 1. GPIOAのクロック有効化 rcu_periph_clock_enable(RCU_GPIOA); // 2. USART0のクロック有効化 rcu_periph_clock_enable(RCU_USART0); // 3. PA9の設定 gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); // 4. USART0の有効化 usart_enable(USART0);
その後USART0の設定を行い、送信シーケンスに入る。
USARTの送信シーケンス
マニュアルからUSARTの送信シーケンスを抜粋する。
送信関数として実装するのはこの7〜10まで。
要約すると、次のようになる。
- TBEを待つ
- USART_DATAレジスタに送信データを書く
- データ数分1と2を繰り返す
- TC=1を待つ
図にはTCはcleared by software
とあるので、明示的にクリアする必要があるかもしれない。
それらを踏まえて次のようにする。
static void putc(unsigned char c) { // 1. TBEを待つ while (usart_flag_get(USART0, USART_FLAG_TBE) == RESET) ; // 2. USART_DATAレジスタにデータを書く usart_data_transmit(USART0, c); } static void puts(const char* s) { // 3. 送信データ数分1と2を繰り返す while (*s != '\0') { if (*s == '\n') putc('\r'); putc(*s++); } // 4. TC=1を待つ while (usart_flag_get(USART0, USART_FLAG_TC) == RESET) ; // おまけ TCをクリアする。 usart_flag_clear(USART0, USART_FLAG_TC); }
サンプルコードではTBE待ちとDATA書き込みが逆になっているが、とりあえずマニュアルにならった。
main.c
これらを踏まえて最終的なプログラムは次のようになる。
#include "gd32vf103.h" static void putc(unsigned char c) { while (usart_flag_get(USART0, USART_FLAG_TBE) == RESET) ; usart_data_transmit(USART0, c); } static void puts(const char* s) { while (*s != '\0') { if (*s == '\n') putc('\r'); putc(*s++); } while (usart_flag_get(USART0, USART_FLAG_TC) == RESET) ; usart_flag_clear(USART0, USART_FLAG_TC); } int main(int argc, char* argv[]) { rcu_periph_clock_enable(RCU_USART0); rcu_periph_clock_enable(RCU_GPIOA); gpio_init(GPIOA, GPIO_MODE_AF_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_9); usart_deinit(USART0); usart_enable(USART0); usart_baudrate_set(USART0, 115200); usart_transmit_config(USART0, USART_TRANSMIT_ENABLE); puts("Hello "); puts("World\n"); while (1); return 0; }
ビルドと書き込み
Longan nanoをDFUモードでPCと接続し、次のコマンドでファームウェアを書き込む。
$ pio run -t upload
ビルドが必要な場合は、ビルドした後にファームウェアを書き込む。
dfu-util: dfuse_download: libusb_control_transfer returned -1 *** [upload] Error 74
前回同様このエラーは無視する。
実行
USB-シリアル変換ケーブルでLongan nanoとPCを接続し、minicomなど端末を開く。
Longan nanoのリセットボタンを押して、次のように表示されれば成功。
minicom へようこそ 2.7.1 オプション: I18n コンパイルされた日時は: Aug 13 2017, 15:25:34. ポート /dev/ttyUSB0, 21:32:17 CTRL-@ Z を押すと、説明画面になります。 Hello World
ただ、Longan nanoのピン電圧は3.3Vで、筆者が普段使っている変換ケーブルが5Vのみの対応だったので、 出力が確認できずしばらくハマった。
ロジアナで出力を確認したりオシロで電圧を測ってみたりで原因はわかったが、こういう作業も組み込みの楽しみだと思う。
まとめ
最近ではHello world
のことを「ハロワ」という。
USART0を使う間にGPIOAとUSART0のクロック有効化が必要だが、それを忘れていてしばらくハマった。
ピン設定からUSART0設定は特に癖はない。
USART0のピン電圧は3.3V。
ということで、無事にHello worldができた。
今回は、gd32vf103-sdk
を使用したので、レジスタのアドレスなどは特に意識しなくてもプログラムできた。