前回からの続きです。
このテーマを最初からご覧になる場合はこちらからどうぞ。
「Simplicity Studio」でプログラミング
インストールしたSilicon Labs社のマイコンようの統合開発環境「Simplicity Studio」で、テストプログラムを動かしてみましょう。
前回は、そのテストプログラムのためのプロジェクトを作りました。
その過程で、ターゲットボードで使用するハードウェアの設定と、それに使用するソフトウェア・コンポーネント(ドライバみたいなものですね!)を紐づけました。
これでコーディング作業に取り掛かる準備は万端です!
閉じてしまった方は「Simplicity Studio」を立ち上げましょう。
起動したら画面左上の「Project Explorer」タブに注目!
ここに前回作成した「empty」プロジェクトが表示されています。
プロジェクトに属しているファイルの一覧が表示されていない場合は「empty」という表示の先頭にある「V」マークをクリックして中身を展開しましょう。
さて、ある程度自動生成されているソースコードを見ていく訳ですが、今回使うのはC言語なので、一番最初に実行される関数は、多分「main()」。
なので、これが実装されているのは「main.c」かな?
…というわけで、ファイルの一覧から「main.c」をダブルクリックして、ソースコードを見てみましょう。
ソースコードを見てみると、やはりありましたよ「main()」。
コメントから推測するに、ユーザーのアプリケーションを実装するための関数は「app_init()」と「app_process_action()」のようですね。
まず「app_init()」は、ターゲットの起動時に一回だけ実行するべき処理を記述…。
その後、whileループの中にある「app_process_action()」に、アプリケーションの処理を記述すれば良さそうですね。
- ...
- int main(void)
- {
- // Silicon Labsデバイス、システム、サービス、プロトコル スタックを初期化します。
- // カーネルが存在する場合、この呼び出しによって処理タスクが作成されることに
- // 注意してください。
- sl_system_init();
- // アプリケーションを初期化します。たとえば、カーネルが存在する場合は、
- // 周期タイマーまたはタスクを作成します。
- app_init();
- #if defined(SL_CATALOG_KERNEL_PRESENT)
- // カーネルを起動します。app_init() で作成されたタスクが実行を開始します。
- sl_system_kernel_start();
- #else // SL_CATALOG_KERNEL_PRESENT
- while (1) {
- // この呼び出しを削除しないでください: Silicon Labsコンポーネント・プロセス・アクション・ルーチンは、
- // スーパー ループから呼び出す必要があります。
- sl_system_process_action();
- // アプリケーション・プロセス.
- app_process_action();
- #if defined(SL_CATALOG_POWER_MANAGER_PRESENT)
- // システムが許可する場合は、CPU をスリープ状態にします。
- sl_power_manager_sleep();
- #endif
- }
- #endif // SL_CATALOG_KERNEL_PRESENT
- }
では「app_init()」や「app_process_action()」は一体何処に存在するのか?
この「Simplicity Studio」も元となっているのは「Eclipse」ですので、同様の操作でソースコードから別のソースコードにある関数へジャンプできます。
すなわち、キーボードの「Ctrl」キーを押しながら、ジャンプしたい関数の記述にマウスカーソルを重ねれば、リンク可能状態となり、それをクリックすることで実際の関数の記述位置へジャンプすることができます。
ジャンプの結果「app_init()」と「app_process_action()」は共に「main.c」と同じディレクトリにある「app.c」であることが分かりました。
この「app.c」に、自分のプログラムを書いていけば良さそうです。
LEDとプッシュボタンとシリアル通信を使用した簡単なサンプルプログラムかぁ…。
こんなふうに作ってみました。
以下、実装した「app.c」のソースコードです。
- /***************************************************************************//**
- * @file
- * @brief Top level application functions
- *******************************************************************************
- * # License
- * <b>Copyright 2020 Silicon Laboratories Inc. www.silabs.com</b>
- *******************************************************************************
- *
- * The licensor of this software is Silicon Laboratories Inc. Your use of this
- * software is governed by the terms of Silicon Labs Master Software License
- * Agreement (MSLA) available at
- * www.silabs.com/about-us/legal/master-software-license-agreement. This
- * software is distributed to you in Source Code format and is governed by the
- * sections of the MSLA applicable to Source Code.
- *
- ******************************************************************************/
- #include "pin_config.h"
- /*
- * これ以降は「autogen」ディレクトリ以下に生成されたコンポーネントのヘッダファイル
- * コンポーネント、ドライバの関数を使用するために必要
- */
- #include "sl_simple_led_instances.h"
- #include "sl_simple_button_instances.h"
- #include "sl_uartdrv_instances.h"
- /***************************************************************************//**
- * Initialize application.
- ******************************************************************************/
- void app_init(void)
- {
- /*
- * VCOM_ENABLEピンをHighにして仮想シリアルポートを有効化
- */
- GPIO_PinOutSet(VCOM_ENABLE_PORT, VCOM_ENABLE_PIN);
- }
- /***************************************************************************//**
- * App ticking function.
- ******************************************************************************/
- void app_process_action(void)
- {
- sl_button_state_t s;
- static sl_button_state_t st0 = 0;
- static sl_button_state_t st1 = 0;
- /*
- * プッシュボタン0(PB0)の処理
- */
- s = sl_button_btn0.get_state(&sl_button_btn0);
- if (st0 != s) {
- // 以前の状態から変化があった場合
- st0 = s;
- if (st0) { // 押されている
- // LED0を点灯
- sl_simple_led_turn_on(sl_led_led0.context);
- // PB0が押されたメッセージを送信
- UARTDRV_TransmitB(sl_uartdrv_usart_vcom_handle, (uint8_t*)"PB0 Pushed!\r\n", 13);
- } else { // 放されている
- // LED0を消灯
- sl_simple_led_turn_off(sl_led_led0.context);
- // PB0が放されたメッセージを送信
- UARTDRV_TransmitB(sl_uartdrv_usart_vcom_handle, (uint8_t*)"PB0 Released!\r\n", 15);
- }
- }
- /*
- * プッシュボタン1(PB1)の処理
- */
- s = sl_button_btn1.get_state(&sl_button_btn1);
- if (st1 != s) {
- // 以前の状態から変化があった場合
- st1 = s;
- if (st1) { // 押されている
- // LED1を点灯
- sl_simple_led_turn_on(sl_led_led1.context);
- // PB1が押されたメッセージを送信
- UARTDRV_TransmitB(sl_uartdrv_usart_vcom_handle, (uint8_t*)"PB1 Pushed!\r\n", 13);
- } else { // 放されている
- // LED1を消灯
- sl_simple_led_turn_off(sl_led_led1.context);
- // PB1が放されたメッセージを送信
- UARTDRV_TransmitB(sl_uartdrv_usart_vcom_handle, (uint8_t*)"PB1 Released!\r\n", 15);
- }
- }
- }
このプログラムの内容は、プッシュボタン(0と1)を押したり放されたりするとLED(0と1)が点灯し、シリアル通信で各々の場合にメッセージが送信されるといった内容になります。
気をつけなければならないのは「app_init()」関数の内容です。
USBを経由した仮想シリアルポートを使用する場合は「VCOM_ENABLE」という信号線をHighにしなければなりません。
前回出てきた以下の回路図を思い出してください。
今回の場合、ターゲット起動時に一回だけ処理しなければならない処理、すなわち「app_init()」関数に記述するべき内容は、これだけです。
実行は、ターゲットをパソコンとUSBで接続し、編集した「app.c」を必ず保存してから「Simplicity Studio」左上の虫マークをクリックします。
これだけで、ビルド作業が開始され、デバッガが起動するはずです。
なにかワチャワチャ作業が始まりますが、やがて以下のように「sl_system_init()」関数の行で実行がストップします。
デフォルトの設定では、いきなりプログラムを開始するのではなくて、最初の行でデバッグが一時停止(ブレーク)するようになっているようです。
ここから「Resume」という操作を行えば、プログラムは再開されますが、せっかくなのでブレークポイントの仕掛け方も確認しておきましょう。
試しに、今回色々実装した「app_process_action()」関数で一時停止(ブレーク)するようにしてみます。
それには「app_process_action()」の行の先頭の部分、行番号の左側をダブルクリックします。
青い丸が表示されると、この行にブレークポイントが仕掛けられたことを意味します。
(解除は、同じくダブルクリックで青い丸を消せば可能です。)
ブレークポイントを仕掛けたら「Simplicity Studio」左上の「▶」マークをクリックします。
これで「Resume」という操作を行ったことになり、プログラムが再開されます。
しかし、すぐに「app_process_action()」の行まで処理が進み、以下のように再度一時停止(ブレーク)となります。
これで、ブレークポイントが正しく動作していることが確認できました。
尚、この行はwhileループの中にあります。
このままだと毎回止まってしまうので、必ずブレークポイントを解除しましょう!
解除してから、再度「▶」マークをクリックしてプログラムを再開させましょう。
今、ターゲット上では、今回作成したプログラムが動作しているはずです。
LEDの点灯は目視で分かりますが、シリアル通信の受信内容を見るためには「TeraTerm」などのターミナルソフトが必要です。
インストールしていない方は、このページ(TOPPERS/ASPのビルドからデバッグまで~サンプルプロジェクトのデバッグ)の「TeraTermの導入」の項目を参考にしてください。
もちろん、シリアル通信のターミナルであれば、他のものもお使いいただけます。
ボーレートは「9600」です。
では、動きを見てみましょう!
プッシュボタン0(BTN0)を押すと、LED0が点灯し…
…その瞬間に、ターミナルには「PB0 Pushed!」という表示が出力されます。
プッシュボタン0(BTN0)を放すと、LED0が消灯し…
…その瞬間に、ターミナルには「PB0 Released!」という表示が出力されます。
プッシュボタン1(BTN1)とLED1の組み合わせも同様の動きになっています。
どうやら、正しくプログラミングできているみたいです!
プログラムを停止するには「Simplicity Studio」左上の「■」マークをクリックします。
現在「Simplicity Studio」は「Debug」モードになっています。
プログラムの編集など、通常モードに戻すためには「Simplicity Studio」右上の「Simplicity IDE」ボタンをクリックし「Debug」から切り替えます。
再度デバッグを開始する際には、自動的に「Debug」モードに切り替わります。
Silicon Labs社の統合開発環境「Simplicity Studio」、若干クセはあるものの思った以上に使いやすい印象です。
マイコンのピンの機能をGUIで設定できて、その設定のソースコードへのエクスポート、デバイスドライバやコンポーネントの生成、更には雛形のプロジェクトまで吐き出してくれるとは…便利な時代となりましたね。
(マイコンのデータシートを隅から隅まで舐め回すように読み耽り、シリアル通信のドライバすら実装に一苦労していた時代は何だったのか…!?)
その点、STマイクロエレクトロニクス社の「STM32CubeIDE」や、ルネサスエレクトロニクス社の「e2 Studio」などと比較しても、通常の開発レベルでは遜色のない出来だと思います。
Silicon Labs社のマイコンは、各種無線に特化している魅力的なラインナップが揃ってます。
でも評価ボードは非常にいたって高価で、マイコンの小売販売はしていないため、ホビー用途には使えないのが残念です。
秋葉原あたりで買える安価で手軽な評価ボード、どこかが作ってくれないかなぁ…。
<終わり>