2022年02月26日

PIC32MZEFシリーズのブートローダ機能

 PIC32MZ2048EFGマイコンのブートローダ機能を検討したため、今回はその際に戸惑った点等を備忘録として紹介します。ブートローダ機能を利用するとPICkit4やSNAP等の専用の書き込み治具がなくても、SDカードやUART等からファームウェアを容易に書き換えできるようになります。何かしらの製品に組み込んだ際にユーザ側でファームアップデートすることが想定される場合に便利です。今回は事前にブートローダを書き込んだPIC32MZマイコンにファームウェアの入ったSDカードを挿入すると自動的にファームウェアが書き込まれるブートローダを作成しました。Microchipから様々なブートローダのドキュメントが提供されていますが、いまいち全容を把握するのに苦労したため、ポイントを絞って紹介したいと思います。詳細は各ドキュメントを参照してください。


まずはブートローダ機能を開発する際のポイントを先に紹介します。

■ポイント
@ブートローダ用のプロジェクトとアプリケーションのプロジェクトは分けて作成する
 →リンカファイルが異なるため、ミスを減らすためにプロジェクトを分ける。また、アプリケーション用のプロジェクトでは通常のバイナリ(hex)ファイルの他にbinファイルを生成するスクリプトを追加することでブートローダ読み込み用のbinファイルを追加で生成させる。

Aリンカファイル作成方法
 →Harmony3+bootloaderで生成したプロジェクトでブートローダ用のリンカファイルbtl.ldはそのまま使用可能。一方、アプリケーション側のリンカファイルはp32MZ2048EFG100.ldを編集必須。また、Harmony3+bootloaderで生成したプロジェクトのリンカ設定はbtl.ldファイルでなく、p32MZ2048EFG100.ldファイルとなっているため、p32MZ2048EFG100.ldをプロジェクトから除外してブートローダ用のリンカファイルbtl.ldに置き換えること。

Bクロック設定やデバイスコンフィグは同じ設定にする
 →ブートローダとアプリケーションの切り替え動作が不安定になる。

Cブートローダ用のプロジェクトは最低限の機能に絞る
 →機能を盛り込むとブートローダファームがブートローダ領域に入らない。SDを読み込み専用に設定し、コンソールデバッグ機能は使用しない。

Dブートローダのファームは直接書き込み可能
 →MPLAB IDEからデバッガを介して書き込み可能。既定ではフラッシュ全削除後に書き込みされるため、通常は書き込み直後にブートローダが起動し、アプリケーションの書き込みモードに入る。

Eアプリケーションのファームは直接書き込まずにブートローダから書き込み
 →直接書き込むとフラッシュ全削除してアプリケーションだけが書き込まれる。ブートローダが消されてしまうため、アプリケーション領域に処理をジャンプさせることができず、アプリケーションが起動しない。

■ブートローダ機能のシーケンス
ブートローダ起動→トリガチェック→(書き換えモードの時)ファーム書き換え処理→ソフトリセット
                →(通常起動の時)アプリケーション起動処理→アプリケーション起動

■トリガ種類
ブートローダが起動後にファーム書き換えモードに入るか、通常のアプリケーション起動モードに入るかはIO状態やメモリ上の変数状態で切り替えることができます。

・a)IO状態トリガ
 PIC32マイコンをリセットさせて、起動時のIO状態を見て切り替えます
・b)メモリ上の変数状態トリガ
 アプリケーションが起動している状態でユーザ操作によってファーム書き換えモードにします。ファーム書き換えモードでは特定のメモリ領域に変数を書き込んで部分的なシステムリセット(特定のメモリ領域はリセットされない)をかけることでブートローダを再度起動させて、特定のメモリ領域の変数を見て書き換えモードに入るか、通常のアプリケーション起動モードに入るか切り替えます。




■ブートローダ側の開発流れ
1. MPLAB ] IDEのHarmony3にBootloaderパッケージを追加する。
 Tools→Embedded→MPLAB Harmoney3 Content Managerをクリック。bootloaderとbootloader_apps_sd〜にチェックを入れてパッケージを追加します。

bootloader1.jpg

bootloader2.jpg


2. Harmoney3プロジェクトを作成し、Filesytemタイプのbootloaderを追加する。
 メディアタイプにSDカードを選択し、b)メモリ上の変数状態トリガを有効にするために16バイトの領域を確保する。また、ファイルシステムの設定は自動マウントを有効化して、読み込み専用に設定する。また、32GB以上のSDカードにも対応させる場合はexFatにチェックを入れる。また、クロック設定やデバイスコンフィグはアプリケーション側と共通の設定をします。

bootloader3.jpg

bootloader4.jpg

bootloader5.jpg


3. コード生成後にリンカファイルを設定する。
 Harmoney3プロジェクトでbootloaderを追加すると自動的にbtl.ldとp32MZ2048EFG100.ldの2つのリンカファイルがプロジェクトに追加される。ただ、ビルド設定ではp32MZ2048EFG100.ldが有効となるため、p32MZ2048EFG100.ldをプロジェクトから除外して、btl.ldだけにする。

bootloader7.jpg


4. ファイルシステムコード追記する。
 デフォルトではff.hのビルドに失敗するため、ff.hの38行目くらいに#define __STDC_VERSION__ 199902を定義する。

5. ブートローダコードを実装する。
 詳細はコードをアップロードしてありますのでそちらを参照してください。起動直後にブートローダ機能を実行するか、アプリケーションを起動させるかの切り替えがinitialization.cにあります。

■アプリケーション側の開発流れ
1. 通常通りにMPLAB ] IDEのHarmony3のプロジェクトを作成します。また、クロック設定やデバイスコンフィグはブートローダ側と共通の設定をします。また、リンカファイルを変更して独自のリンカファイルを使用するため、Harmony3のプロジェクトグラフ内のsystem→Device&Project Confguration→Toolchain selectionのAdd linker file to projectのチェックを外します。

bootloader9.jpg

2. リンカファイルp32MZ2048EFG100.ldを書き換えます。

・PROVIDE(_ebase_address = 0x9D000000);の下にPROVIDE(_ebase_vector_offsets = 0x1000);を追加。
・_RESET_ADDR = 0xBFC00000;を_RESET_ADDR = 0xBD000000;に変更。
・_BEV_EXCPT_ADDR = 0xBFC00380;と_DBG_EXCPT_ADDR = 0xBFC00480;を削除。
・_SIMPLE_TLB_REFILL_EXCPT_ADDR、_CACHE_ERR_EXCPT_ADDR 、_GEN_EXCPT_ADDR に_ebase_address を追加して下記のように書き換える。
_SIMPLE_TLB_REFILL_EXCPT_ADDR = _ebase_address + _ebase_vector_offsets + 0;
_CACHE_ERR_EXCPT_ADDR = _ebase_address + _ebase_vector_offsets + 0x100;
_GEN_EXCPT_ADDR = _ebase_address + _ebase_vector_offsets + 0x180;

・メモリ領域(MEMORY)の書き換えとconfig領域の削除
(変更)
kseg0_program_mem (rx) : ORIGIN = 0x9D001000, LENGTH = 0x200000 - 0x1000
kseg1_boot_mem : ORIGIN = 0xBD000000, LENGTH = 0x480
kseg1_boot_mem_4B0 : ORIGIN = 0xBD0004B0, LENGTH = 0x1000 - 0x04B0
(追記)
/* Reserve 16 Bytes to Store Bootloader Trigger Pattern */
kseg0_data_mem (w!x) : ORIGIN = 0x80000000 + 16, LENGTH = 0x80000 - 16
(削除)
アプリケーション側ではコンフィグを行わないため、config領域を削除します。
config_BFC0FF40からboot2lastpageまでを削除します。

・SECTION領域(SECTIONS)のconfig削除
.config_BFC0FF40から始まるSECTIONSを削除する。

・SECTION領域(SECTIONS)の例外処理を削除
ブートローダ側に含まれるため、下記の例外処理を削除する。
.bev_excpt _BEV_EXCPT_ADDR :
{
KEEP(*(.bev_handler))
} > kseg1_boot_mem

・割込みオフセットに_ebase_vector_offsetsを追記

* Interrupt vector table with vector offsets */
.vectors _ebase_address + _ebase_vector_offsets + 0x200 :

・ブートローダ側に含まれるため、下記を削除する
/* The startup code is in the .reset.startup section.
* Keep this here for backwards compatibility with older
* C32 v1.xx releases.
*/
.startup ORIGIN(kseg0_boot_mem) :
{
KEEP(*(.startup))
} > kseg0_boot_mem

・ デバッグ例外処理とコンフィグはブートローダ側に含まれるため、除く処理を追加する。
/DISCARD/ : { *(.note.GNU-stack) *(.gnu_debuglink) *(.gnu.lto_*) *(.discard) }の下に下記を追加する。
/DISCARD/ : { *(._debug_exception) }
/DISCARD/ : { *(.config_*) }

最終的に書き換え前(書換前リンカファイル.ld)と書き換え後(書換後リンカファイル.ld)のファイルはこのようになります。

3. アプリケーション側で必要に応じて、ソフトウェア的にファーム書き換えモードにするコードを追加します。BTL_TRIGGER_PATTERN で定義された特殊な値をBTL_TRIGGER_RAM_START に書き込んでソフトリセットさせることでリセット後にブートローダが起動し、SDカードからファームを書き換える処理を走らせることができます。

#include "sys/kmem.h"

#define BTL_TRIGGER_RAM_START KVA0_TO_KVA1(0x80000000)
#define BTL_TRIGGER_PATTERN (0x5048434DUL)
#define DCACHE_CLEAN_BY_ADDR(start, sz)
static uint32_t *ramStart = (uint32_t *)BTL_TRIGGER_RAM_START;

SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "Bootloader Triggered!\r\n");
ramStart[0] = BTL_TRIGGER_PATTERN;
ramStart[1] = BTL_TRIGGER_PATTERN;
ramStart[2] = BTL_TRIGGER_PATTERN;
ramStart[3] = BTL_TRIGGER_PATTERN;
DCACHE_CLEAN_BY_ADDR(ramStart, 16);
APP_SystemReset();

4. プロジェクト設定でbinファイルを生成するコードを追加します。
アプリケーション側のビルド後にhexファイルからbinファイルを生成します。
${MP_CC_DIR}/xc32-objcopy -I ihex -O binary ${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.hex ${DISTDIR}/${PROJECTNAME}.${IMAGE_TYPE}.bin

bootloader8.jpg


これでブートローダ機能の設定および実装は完了です。先にブートローダ側のファームをPIC32マイコンに書き込んで、アプリケーション側のbinファイルをimage.binにファイル名を書き換えてSDカードに入れるとファームが書き換えられ、アプリケーションが実行されます。プロジェクトファイルおよび全体のコードはこちら(code.zip)です。

なお、パッケージを追加するとC:\Users\(ユーザ名)\Harmony3\bootloader_apps_sdcard\apps\sdcard_bootloader内にブートローダ側のbootloaderとアプリケーション側のtest_appがサンプルコードが追加されます。ただ、サンプルプログラム(PIC32MZDA)とREADMEだけでは情報少なく苦労したため、試行錯誤しながら何とか動かすことができました。SDカード以外にもUARTやフラッシュメモリ等からも書き換えできますが、専用ソフトが不要でユーザ側のOS環境に依らず負担が少ないSDカードからの書き換えが汎用性が高く良いと思いました。また、アプリケーション側のリンカファイルを書き換えるとそのままでは簡単にデバッグやブートローダ無の単体動作できないため、元のリンカファイルも残しておいて、読み込むリンカファイルを切り替えるとよいと思います(Lodableに追加する別のデバッグ方法もありますが...)。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2022年02月12日

Rust + Eclipse IDE + GDB

今回はWindows環境でEclipse IDEを使用したRust開発環境の構築方法について紹介します。一般的にはVSCodeを使う流れですが、時代錯誤感はありますが、組込系でも慣れたEclipse IDEで構築しました。

Rust版Eclipse IDEは発展途上or見放された?ようでEclipseの2020-12が最新で以降はRust版が提供されていないようです。そのため、MacやLinux環境では比較的うまく動くようですが、Windows環境ではなかなかすんなり動かないようです。既知の問題点として対処方法含めて紹介されていますが、それだけでは分かりずらい点もあったため、環境構築方法を改めて紹介します。


@Rustインストール
既にRust環境が入っている場合は飛ばしてください。コマンドライン等からcargo --versionと打ってバージョン情報の正しい応答があればインストール済&パスOKです。必要に応じて公式サイトからインストールしてください。

AEclipseインストール
残念ながら2020-12が最新で以降はRust版が提供されていないようです。こちらのページの中央右にあるWindows x86_64をクリックしてダウンロードします。なお、右端のボタンは最新版統合インストトーラのため、Rust版ではありませんので間違えないように注意。直リンクはこちらです。Eclipseはzipを解凍するのみでインストール不要です。適当な場所に解凍したフォルダを置きます。

BGDBインストール
コマンドライン等からgdb --versionと打ってバージョン情報の正しい応答があればGDBインストール済です。「gdbは、内部コマンドまたは外部コマンド、操作可能なプログラムまたはバッチ ファイルとして認識されていません。」と表示される場合はインストールされていないorパスが通っていません。既にCygwin等がインストールされている場合、GDBが入っていればパスを通します。何もインストールされていない場合は最低限としてGDBだけの TDM-GCC Compilerをこちらからダウンロード、インストールします。インストールはzipを解凍し、Cドライブ直下かユーザーディレクトリ直下等にフォルダを配置し、gdb.exeがあるフォルダに対して環境変数のPATHにパスを追加します。

例: C:\Users\(ユーザ名)\gdb\bin

環境変数にパスを追加した後、再度開き直したコマンドライン等からgdb --versionと打ってバージョン情報の正しい応答があればOKです。

Cツールチェーンインストール
コマンドラインから下記の2つのコマンドを順番に打ち込んでツールチェーンをインストールします。

rustup toolchain install stable-x86_64-pc-windows-gnu
rustup default stable-x86_64-pc-windows-gnu


Dコマンドファイル追加
Windows環境ではrust-gdb.exeがそのままでは使用できないため、下記のフォルダにrust-gdb.cmdというファイルを生成し、こちらのサイトに記載されたスクリプトをメモ帳等で書き込みます。念のため、既にスクリプト書き込み済みのrust-gdb.cmdのファイルを圧縮してアップロード(rust-gdb.zip)してあります。

C:\Users\(ユーザ名)\.cargo\bin

Eプロジェクト追加
Eclipse IDEのZipファイルを解凍したフォルダ内のeclipse.exeをクリックし、起動させます。プロジェクトのワークスペースは適当なディレクトリを指定します。File→New→ProjectからRust→Cargo Projectをクリックし、プロジェクト名を入力し、Finishボタンでプロジェクトを作成します。その他の設定はデフォルトでOKです。

rust2.jpg

Fデバッグ設定変更
このままではGDBデバッグ機能が利用できないため、デバッグ設定を変更します。Run→Debug ConfigurationからDebuggerタブをクリックし、GDB debuggerにrust-gdbの代わりに先ほど作成、格納したC:\Users\(ユーザ名)\.cargo\bin\rust-gdb.cmdを指定します。また、Environmentタブをクリックし、Addをクリックして適当な名前と値を入れます。面倒な場合は下記のようにHOGE、hogeと入れます。デフォルトの空白だとエラーになるため、その対処のため、何かしらの文字列を指定します。特に意味はないため、空白以外の文字列であれば構いません。

rust3.jpg

rust4.jpg


Gデバッグ
これで設定完了です。Run→Debugから今まで通りにデバッグできます。

rust5.jpg

Rustでもこれまでと同じようにGDBでデバッグできるようになりました。時代錯誤感はありますが、プラグインやアドオンで重くなりがちなVSCodeよりも各プロジェクトで独立した開発環境を構築できるEclipse IDEの方が個人的に好んでいます。最新版とまでは言わなくとも継続してRust版のEclipseを開発して頂きたいと思いました。
posted by Crescent at 00:00| Comment(0) | ナレッジ | このブログの読者になる | 更新情報をチェックする

2022年01月29日

PIC32MXとPIC32MZのUSB HOST

今回はPIC32MXとPIC32MZでUSB HOST機能の両者の仕様差について紹介します。PIC32MXで動いていたコードがPIC32MZで若干、仕様が異なるためにそのままでは動きませんでした。若干の仕様差について注意すべき点を紹介します。

■PIC32MZはUSB2.0 High Speed対応(480MHz)
 組込系のマイコンの多くはUSB 2.0 Host対応を謳っていても8割、9割はFull Speed対応(12MHz)です。PIC32MXもFull Speed対応(12MHz)です。一部のマイコン、例えばSTM32F7ではFull SpeedとHigh Speedに対応していますが、High Speedの場合、High Speedの信号を処理するためのUSB PHYを内蔵していません(一部内蔵したモデルもあるようです)。そのため、USB3300といったUSB PHYのICを外付けすることが必要です。High Speedの480MHz信号をそのままでは処理しきれないため、USB PHYでパラレル信号に変換してクロックを落としてマイコンに接続することが一般的です。

 一方、PIC32MZは驚くことにHigh Speed対応USB PHYをマイコンに内蔵しています。つまり、High Speedの480MHz信号をマイコンからUSBコネクタに直結可能です。ただし、480MHzの信号を扱うことになるため、基板の配線には特に注意が必要です。480MHzとなると普通のSPIやI2Cのような適当な信号配線では全く動きません。目安としてマイコンとUSBコネクタまでの配線長は最大75mm程度、30mm以下が理想でD+とD-の配線差は最大2.5mm、直角でなく、45度に曲げるといったUSB2.0に準拠するため、細心の注意を払って配線する必要があります。kicadの等長配線、差動ペアの配線方法は以前に紹介した通りです。Full Speedと同じような感覚でいつものように適当に配線してしまい、まったくUSBを認識できませんでした。仕方なくパターンを切って外付けで差動ペアを配線したところ、正常に認識することができました。

PIC32MZ1.jpg

即席で作った基板では当然ながらHigh Speedの480MHzに耐えられず、写真のように配線パターンを切ってからポリウレタン銅線のツイストペアケーブルでジャンパさせると正常に通信できました。

■PIC32MZはVBUS電圧レベルを厳密に監視
 PIC32MXのVBUSピンはONかOFFかを見ているだけだったため、適当に3.3Vを入れておけばUSB機能を利用することができました。一方、PIC32MZのVBUSピンは内部にコンパレータを内蔵しており、厳密にVBUS電圧レベルを監視しています。PIC32MXと同じ感覚で3.3Vを入れたところ、DRV_USBHS_Tasks内のDRV_USBHS_TASK_STATE_RUNNINGの途中で停止してしまいました。PLIB_USBHS_VBUSLevelGetで電圧レベルを取得しており、VBUSに5Vを入れると正常に状態遷移することができました。VBUSピンはPIC32MX、PIC32MZ含めて最大5.5Vまで印加可能なため、正しくはUSB電源に接続すべきピンです。マイコンのピンを外部電源系にそのまま接続するのは過電圧保護やESD対策等を考えると気が引けるため、3.3Vを接続していました。PIC32MZではそれが通用しないことが分かりました。


PIC32MZ2.jpg

ポリウレタン銅線でVBUSピンの電源を3.3Vから5Vにジャンパさせると正常に状態遷移することが確認できた。


■その他
 High Speedの場合、Full Speedに比べてよりデバイスの消費電力が上がる傾向があります。電源配線幅、場合によってはコンデンサ等で安定したUSB電源をデバイスに供給できるように注意が必要です。USBデバイスを認識するものの、その後、デバイスの処理を開始するとUSBデバイスがリセットする現象に遭遇しました。オシロで確認するとデバイス処理開始直後に急激な電圧低下が生じていることが分かり、1つ目の写真にもある通り、電解コンデンサで電源を補強するとUSBデバイスがリセットされずに安定してデバイスの処理をすることが確認できました。


 PIC32MZは他のPIC32マイコンと比べると割高な印象がありますが、USB PHY内蔵と考えると、外付けよりもBOMコストを抑えて省配線でHigh Speedに対応できるため、むしろ他のマイコンよりも安いと言えます。今後、USBの他にPIC32MZのEthernet機能等も実験して紹介したいと思います。なお、Ethernet機能についてはPIC32MZでも残念ながら外付けでEthernet PHYのICが必須です。
posted by Crescent at 00:00| Comment(0) | 電子部品 | このブログの読者になる | 更新情報をチェックする

2022年01月08日

STM32 EvoPrimer

今年もよろしくお願いします。

正月明けの先日、秋月電子通商の八潮店にお邪魔しました。八潮店は店舗が秋葉原店よりも広く、混雑していないのでおススメです。さらにおススメなのは10~20年前の秋葉原店のようなジャンク部品が八潮店では販売されています。入口入って左側のジャンクコーナーでは通販やWebサイトに載っていない部品がたくさん格安で売られています。

今回、お邪魔して購入したものはSTM32 EvoPrimerジャンク品です。STM32F103V*シリーズが搭載されたSTM32 EvoPrimerのベースボード(定価1万前後)が300円、ターゲットボード(定価3~4千円前後)が200円で販売されていました。ベースボードに搭載されているリチウム充電池が完全に放電しているようでジャンクとして大量に販売されていました。10年以上前の開発ボードでNucleoボードやDiscoveryボードが販売される前の製品のため、情報等が限られていますが、まだ回路図等は部分的に確認できるようです。


p1.jpg


p2.jpg

ベースボードとターゲットボードを接続してUSB電源を供給するとデモプログラムが動作しました。


p3.jpg

ST7732ドライバ搭載の160x128のパラレル接続LCDが搭載されているようです。


p4.jpg

ベースボードはSTM32F103VE、タッチパネル付きLCD、スピーカ、microSDスロット、加速度センサ、リチウム充電池、充電回路等が搭載されていました。

p5.jpg

偶然?にも電池は完全に消耗しておらず、3.4V程度電圧がありました。

p6.jpg

ターゲットボードは数種類販売されており、ROM容量が一番大きなSTM32F103VGを購入してみました。10年以上前の製品に搭載されたSTM32F103シリーズのため、初期レビジョン固有のエラッタ等があるかもしれませんが、部品取りや簡単な実験用として非常にお買い得だと思いました。


p7.jpg

他にも鉛フリーのクリームハンダ等もあり、ジャンクならではのお買い得品が多数ありました。なお、ジャンクコーナーは在庫の入れ替わりが激しく、在庫管理された正規在庫品ではないため、店舗へ在庫有無の確認等はお控え頂き、直接、八潮店でご確認ください。プラ箱に大量に入っていたため、数週間程度は引き続き販売されていると思われます。

ぜひ、秋葉原店だけでなく、八潮店で買い物するのも如何でしょうか?
posted by Crescent at 00:00| Comment(0) | 部品 | このブログの読者になる | 更新情報をチェックする

2021年12月25日

Marketplace Maker Awards 2021受賞

先日、12月23日、技研ベースにて、スイッチサイエンスマーケットプレイス Maker Awards 2021 が開催されました。スイッチサイエンスマーケットプレイス Maker Awards 2021は今年の締めくくりとして、スイッチサイエンスマーケットプレイス (委託販売)に出品されている900以上の商品の中から、今年最も優れた作品・メイカーを表彰するイベントです。

光栄なことにCrescentは2021年、スイッチサイエンスマーケットプレイス (委託販売)の個人部門で売上1位として個人賞を受賞することができました。更に売上がたくさんある方々がおられると思っていたため、連絡をいただいた際には非常に驚きました。

mpa.jpg

スイッチサイエンスマーケットプレイスという場を提供して頂いたスイッチサイエンス様に感謝申し上げるとともに、今後ともよいプロダクトを開発、提供できるよう励んでいきたいと思います。なお、当日の様子はスイッチサイエンスのYoutubeチャンネルにアーカイブされています。
posted by Crescent at 00:00| Comment(0) | イベント | このブログの読者になる | 更新情報をチェックする