2021年04月10日

PIC32MX+Harmony3+MSD(USB Host)設定ポイント

ここ5年くらいはSTM32マイコンを中心に開発、展開していました。しかし、昨今の半導体供給不足で主要なSTM32マイコンが入手困難となっています。運よく在庫がある場合でも価格が上がっている場合が多々あります。STM32マイコンがこれまで通りに安定して入手可能になるには少なくとも半年(2021年末)、長くて数年(2022~23年以降)は要すると思われます。

このような状況を受けて、STM32マイコンの代替として今更ながら古巣のPICマイコンに少し戻ってきました。PICマイコンも半導体供給不足の影響を多少受けていますが、STM32マイコンほど長納期化していません。主にdsPIC33F、30Fを使用していた10年近く前に比べると自動コード生成ツール(Harmony Configurator)、内部可視化(Data Visualizer)等のツール群が充実してきています。

今回はPIC32MX250F128BをターゲットにMPLAB X v5.45+Harmony3を使用してUSBメモリへの書き込み(MSD:Mass Strage Device)を行いました。その際にポイントとなる設定について紹介します。なお、ターゲットへの書き込みはPickit3を使用しました。


全体の手順については既にMicrochipのgithubサイトに詳しく書かれているため、設定のポイントに絞って紹介します。
MPLAB Xには予め、MPLAB Harmony 3 Launcher(旧名称 MPLAB Harmony Configurator 3)をインストールしてあります。


@File System設定
Use File System Auto Mount Featureにチェックを入れます。また、Media TypeにSYS_FS_MEDIA_TYPE_MSDを選択します。この設定を忘れるとSYS_FS_EventHandlerSet関数やSYS_FS_MEDIA_MANAGER_EventHandlerSet関数が生成されず、app.cのサンプルプログラムのビルドで失敗します。


filesystem_setting.jpg


AHeap Size設定
こちらのMicrochipのgithubサイトでは500byte以上とありましたが、500byteでは動作しませんでした。1024byte程度が良さそうです。

system_heap_setting.jpg


BCrystal設定
PIC32MX2XXの場合はこちらのMicrochipのgithubサイトとは異なり、クロック設定箇所はシンプルです。一方でUSBを使用する場合は外付け発振子が必須となります。最終的に設定上部のUSB Clockが48000000Hz(48MHz)になっていればOKです。USB Clockが0Hzといった48MHz以外の場合は設定を見直す必要があります。

crystal_setting.jpg


以上の設定を終えた段階で、プロジェクトフォルダsrc内のapp.c、app.hを下記のサンプルコードに置き換えます。
Harmony3\usb_apps_host\apps\msd_basic\firmware\src

置き換え後、USBメモリをPIC32マイコンに接続し、ファームを書き込むとUSBメモリにサンプルファイルが保存されれば成功です。

result.jpg

今回のコード、プロジェクトファイルは
です。

STM32マイコンのCubeMXのようにMPLAB Harmonyによって最初のセットアップの敷居が下がっていることを実感できました。一方でMPLAB Harmonyの情報が少なく、バージョンによってUIや設定項目が異なるため、情報収集に苦労する面がありました。今後、CubeMXの様に洗練されたUIになることに期待です。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2021年04月03日

フォトカプラを使ったUART通信

電圧レベルが異なる場合やノイズ環境といった場合に安全に信号を伝える方法の1つとしてフォトカプラを使用することがあります。フォトカプラでON、OFFといった単純な信号のやりとりの場合はフォトカプラと適切な抵抗のみで信号のやり取りが可能です。一方でUARTやSPIといったある程度高速な信号をやり取りする場合、フォトカプラと抵抗のみでは安定した通信ができません。

下記はフォトカプラと抵抗のみを使用した場合のボーレート38400bpsのUART通信をフォトカプラの入力と出力のTXの電圧波形の比較です。赤がフォトカプラ入力電圧、黄色がフォトカプラ出力の電圧です。

uart.jpg

汎用フォトカプラTPC817を使用し、フォトカプラの入力には直列に330Ω抵抗、フォトカプラの出力には120Ωでプルアップしています。フォトカプラのOFF状態でも1.6V程度出ており、ピークで3V出ています。波形も鈍っており、安定してUART通信できません。

フォトカプラの受光側のフォトトランジスタに流せるコレクタ電流は最大50mA程度です。実際は定格最大が50mA程度であって、発光側の光量によっては数mA以下となります。駆動できる電流が数mA程度の場合、フォトカプラのフォトトランジスタやマイコンの入力端子、ケーブル等の静電容量の影響によって波形が鈍ってしまいます。UARTやSPIといったある程度高速な信号をやり取りする場合はトランジスタやバッファIC等で電流を増幅して伝達することが必要となります。

uart_relay_with_tr.jpg

フォトカプラの出力部分をトランジスタC1815で増幅すると上記のように波形が鈍りを低減させることができました。

BOMコスト低減のためにトランジスタやバッファICを使用したくない場合は、ADuM1200ARZといった信号用デジタルアイソレータIC、大電流対応のフォトカプラTLP250等を使用することで追加回路なしで波形の鈍りを低減できます。なお、TLP250の動作電圧10V以上ですが、仕様範囲外の3.3Vでも動作します。


uart_photo_high_current.jpg

TLP250を用いたフォトカプラの入力と出力のTXの電圧波形の比較です。


uart_photo_fet.jpg

参考になりますが、こちらはフォトカプラの出力を手持ちのパワーMOSFet、IRLU3410PBFで増幅した波形です。信号の鈍りはないものの、MOSFetのゲートの静電容量の影響を受けて波形のON、OFFの長さが完全に変わっています。これでは正しく通信できません。フォトトランジスタの出力電流や増幅回路の静電容量を考えて設計することが重要だと分かります。


フォトカプラは単純な機構なので理想的に動くと勘違いしがちです。特に通信を絶縁する場合のアプリケーションでは波形を見ながら抵抗値や増幅回路等を決定することが重要です。
posted by Crescent at 00:00| Comment(0) | 電子部品 | このブログの読者になる | 更新情報をチェックする

2021年03月27日

Elasticsearchデータ修復

今回はelasticsearchのデータが破損してしまった場合(シングルノード)の修復方法について紹介します。簡易的なデータストレージとしてelasticsearchを使用する場合、クラスター化させずにシングルノードで使用する場合があります。データが冗長化されていないため、誤って電源断をしてしまった時やストレージに障害が発生した時にインデックスがred状態となってしまう場合があります。最悪のケースとしては.kibana_*等のElasticのシステム系インデックスがred状態になるとkibanaが起動できなくなり、開発consoleでコマンド操作といったkibanaの操作が一切できません。

重要なデータでない場合はred状態のindexを丸ごと削除するということが多いと思います。一方で重要でないが可能なら残っているデータを可能な限り復元、修復したいといった場合もあると思います。障害の種類によって修復方法が異なりますが、今回はtranslogの破損による障害の修復方法を紹介します。

translogの細かい説明はここではしませんが、負荷を分散させるためにインデックス内のデータを書き込む前にデータを一時保存するファイルです。translogの破損によってred状態となっている場合、一時保存された直近のデータは消える可能性があります。ただ、red状態で該当するインデックスのすべてのデータにアクセスできない、新規データ投入できない状態から回復したいという場合に有効です。

まずはブラウザやcurlコマンドで下記を実行し、red状態のノードを確認します。修復で使用するため、red状態となったインデックス名のUUIDも合わせて確認します。

続いて、ブラウザやcurlコマンドで下記を実行し、red状態の理由を確認します。

理由として表示された内容で下記の様にTranslog関連の障害が発生している場合は今回の方法で修復できます。unassigned_infoのdetailsにTranslogCorruptedExceptionと表示されており、translog関連の障害と分かります。TranslogCorruptedException以外にもtranslog整合性が合わないといった障害も同様に今回の方法で修復できます。

err_info.jpg


破損したtranslogファイル等を削除して新規に空のtranslogファイルを生成するために下記のコマンドを実行します。なお、ファイル操作を伴うため、elastcisearchを終了させた状態で実行します。また、破損ファイルを削除するため、必要に応じてdataフォルダのバックアップをしてください。インデックスに反映される前のtranslogにのみ記録された直近のデータは削除される場合があります。コマンドラインから下記のコマンドを実行します。

Elasticsearch7以降
bin/elasticsearch-shard remove-corrupted-data --index (インデックス名) --shard-id 0

Elasticsearch6以前
bin/elasticsearch-translog truncate -d (データフォルダ)/elasticsearch/data/nodes/0/indices/(UUID)/0/translog/

elasticsearch7以降の場合は下記のように表示され、translogの破損を発見した場合、修復の有無を聞いてきます。yキーを押して修復させます。

------------------------------------------------------------------------
WARNING: Elasticsearch MUST be stopped before running this tool.
-----------------------------------------------------------------------
Please make a complete backup of your index before using this tool.
-----------------------------------------------------------------------
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
No problems were detected with this index.
Took 0.025 sec total.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
>> Translog is corrupted at \data\nodes\0\indices\~\0\translog
-----------------------------------------------------------------------
Documents inside of translog files will be lost.
The following files will be DELETED at \0\translog
--> translog-2_.tlog
--> translog.ckp
WARNING: YOU MAY LOSE DATA.
-----------------------------------------------------------------------
Continue and remove corrupted data from the shard ?
Confirm [y/N] y
Checking existing translog files
Reading translog UUID information from Lucene commit from shard at
Translog UUID :
History UUID :
Removing existing translog files
Creating new empty checkpoint at \translog\translog.ckp]
Creating new empty translog at [translog\translog-1.tlog]
Marking index with the new history uuid :
Changing allocation id to
You should run the following command to allocate this shard:
POST /_cluster/reroute
{
 "commands" : [
  {
   "allocate_stale_primary" : {
    "index" : "(インデックス名)",
    "shard" : 0,
    "node" : "(UUID)",
    "accept_data_loss" : false
   }
  }
 ]
}
You must accept the possibility of data loss by changing the `accept_data_loss` parameter to `true`.
上記は一部を書き換えています。

上記のコマンドだけでは修復したインデックスはred状態のままです。続いて、elasticsearchを起動させ、下記のコマンドを実行して再割り当てを行います。先ほどの修復コマンドの最後に表示されているように、accept_data_lossをtrueにしてcurlコマンドで下記のように実行すると再割り当てが行われ、red状態から回復します。

curl -XPOST localhost:9200/_cluster/reroute --header "Content-Type: application/json" --data "{\"commands\":[{\"allocate_stale_primary\":{\"index\":\"(インデックス名)\",\"shard\" : 0,\"node\" : \"(UUID)\",\"accept_data_loss\" : true}}]}"


再度、下記のコマンドで再割り当てされたノードを確認します。red状態から回復していれば修復完了です。

今回はelasticsearchのtranslog破損時の修復方法について紹介しました。elasticsearch-shard remove-corrupted-dataコマンドはtranslogの破損以外にも対応できるようで他の障害でも使えそうです。

もし、正常な状態のバックアップデータ(スナップショット)がある場合、邪道な方法ではありますが、該当するインデックスのtranslogファイルを丸ごと置き換える方法もあります。http://localhost:9200/_cat/indices?vでインデックス名とUUIDの関係を調べ、dataフォルダ内の該当するUUIDフォルダを見つけます。その中にtranslogフォルダがあり、同じUUIDの正常なtranslogフォルダを丸ごと置き換えます。translog自体の破損は修復できますが、インデックスデータとの整合性が合わない可能性が出てきます。ただ、この方法の場合、コマンド操作が不要なため、ダメ元で修復したい場合は作業として非常に楽になります。なお、当然ではありますが異なるUUIDのtranslogフォルダを置き換えた場合は整合性が取れないため、red状態のままです。
posted by Crescent at 00:00| Comment(0) | ナレッジ | このブログの読者になる | 更新情報をチェックする

2021年03月20日

USBホストMAX3421変換基板

USBホストICの比較検証のためにMAX3421E変換基板をAliexpressから購入してみました。以前に紹介したVinclumシリーズとの違いはどちら側に処理の中心を置くかの思想が違います。MAX3421はSPIスレーブICでUSBプロトコル変換に特化しており、動作の処理を命令するマイコンが別に必要となります。一方、VinclumシリーズはVinclum自体がプログラム可能なマイコンになっているため、用途によってはVinclum単体で動作させることが可能です。プロジェクトの目的によって使い分ける必要があります。部品コストとしてはVinculumは500円前後、MAX3421Eは1000円前後とVinculumの方が低コストです。

今回購入したAliexpressのMAX3421E変換基板は使う上で2点注意点が必要です。

@VBUS
基板上のVBUSは通常、USB電源として5Vを供給しますが、基板上で3.3VとVBUSが接続されているため、そのまま5Vを接続すると3.3Vラインにも5Vが供給されてしまいます。基板上のパターンを切って3.3Vラインと5Vラインを分離する必要があります。最初、誤ってそのまま5Vを供給してしまい、3.3V系の電圧がおかしいことに気づいて判明しました。今回は偶然?にもMAX3421E他、デバイスは壊れませんでしたが、注意が必要です。

max3421_1.jpg

ASPIシルク
基板上のシルクに間違いがあり、そのままマイコンと接続しても通信できません。基板上のMAX3421のICの足と基板上のピンをテスターで確認すると、基板上のCLKとMOSIが入れ替わっていることが分かりました。正しく配線することでMAX3421のレビジョンを正しく取得できるようになりました。


基板上のCLK→MOSIが正しい
基板上のMOSI→CLKが正しい
max3421_2.jpg


今後はVinculumとMAX3421を使いこなして、それぞれの特徴をまとめてみたいと思います。
posted by Crescent at 00:00| Comment(0) | 電子部品 | このブログの読者になる | 更新情報をチェックする

2021年03月13日

VinculumU SPIパフォーマンス

以前にFTDIのVinculumUを紹介しました。VinculumUはUSBホスト機能を備えたマイコンで最大2つのUSBポートを使用することができます。開発環境のVinculum II Toolchainを使用することで書き込むプログラムによって様々な機能のUSBホストを実現することが可能です。

今回はVinculumU を用いてSPIマスタのパフォーマンスを評価してみました。最終的にはUSBから取得したデータをVinculumU のSPIマスタを介して外付けメモリに転送することを検討しています。検討に際して想定よりもパフォーマンスが出ないことが分かったため、設定による違いをまとめてみました。

前提条件としてvos_initではVOS_Q=10、VOS_TICK=1、NUMBER_OF_DEVICES=4、VOS_48MHZ_CLOCK_FREQUENCY、VOS_IOCTL_SPI_MASTER_SET_DATA_DELAY=0で実験しています。また、CSとCLKを測定して1回のSPI通信サイクルを確認しました。

まず、DMAを無効化した状態で8byteのデータをSPIマスタから書き込む操作を行いました。

vos_dev_write(hSPI_MASTER, wcmd, 4, &num);
vos_dev_read(hSPI_MASTER, dummy, 4, &num);
vos_dev_write(hSPI_MASTER, data, 4, &num);
vos_dev_read(hSPI_MASTER, dummy, 4, &num);

■DMA未使用
VOS_IOCTL_COMMON_DISABLE_DMA、クロック3MHz

1_No_DMA_3MHz_8byte.png

黄色がCLK、赤がCSです。CSが0の期間は約820usecとなりました。1byte毎に分かれて送出されていることが分かります。また、各byte毎に50usec程度の間をおいてから次のbyteが送出されています。また、4byteの書き込み後、次の4byteを書き込むまでに200usec以上要していることが分かりました。

■DMA使用 DMA_ACQUIRE_AS_REQUIREDモード、クロック3MHz
DMA転送を有効にしてDMAモードをDMA_ACQUIRE_AS_REQUIREDで同様に書き込みを行いました。

2_DMA_AS_3MHz_8byte.png

DMAを有効にすると1byte毎でなく、4byteまとめて送出されてるようになりました。CSが0の期間は約750usecとなりました。


■DMA使用DMA_ACQUIRE_AND_RETAINモード、クロック3MHz
DMAモードをDMA_ACQUIRE_AND_RETAINで同様に書き込みを行いました。

3_DMA_AND_3MHz_8byte.png

DMA_ACQUIRE_AND_RETAINモードでは4byteと次の4byteとの間隔が短くなり、CSが0の期間は約500usecとなりました。

■DMA使用 DMA_ACQUIRE_AS_REQUIREDモード、クロック20MHz
SPI通信のクロックを上げてDMA_ACQUIRE_AS_REQUIREDモードで同様に書き込みを行いました。

4_DMA_AS_20MHz_8byte.png

クロックを上げると4byteと次の4byteとの間隔が短くなり、CSが0の期間は約380usecとなりました。

■DMA使用 DMA_ACQUIRE_AS_REQUIREDモード、クロック20MHz、まとめて書き込み

4Byteを2回書き込みでなく、8byteを1回の書き込みに変更してみました。
vos_dev_write(hSPI_MASTER, data, 8, &num);
vos_dev_read(hSPI_MASTER, dummy, 8, &num);

5_DMA_AS_20MHz_8byteOnce.png

CSが0の期間は約200usecとなりました。

■DMA使用 DMA_ACQUIRE_AS_REQUIREDモード、クロック20MHz、まとめて書き込み、Writeのみ
VinculumUのSPIマスタは書き込み関数と読み込み関数がそれぞれ分かれています。通常は書き込み関数と読み込み関数の2つを使用してSPI通信の読み書きをします。書き込みのみの場合はvos_dev_write関数のみで構いませんが、読み込みの場合はvos_dev_write関数を実行してからvos_dev_read関数で値を読み込む必要があります。今回はメモリ書き込みのみを想定した場合、厳密には読み込み処理は不要です。書き込み関数のみにして同様に測定しました。

vos_dev_write(hSPI_MASTER, data, 8, &num);
//vos_dev_read(hSPI_MASTER, dummy, 8, &num);

6_DMA_AS_20MHz_8byteOnceWriteOnly.png

CSが0の期間は約100usecとなりました。

■結果まとめ
以上の結果からSPI通信を短時間で実行するためにはDMA転送の有効化、DMA_ACQUIRE_AS_REQUIREDよりもDMA_ACQUIRE_AND_RETAIN、クロックを高速にすることが重要であることが分かりました。また、vos_dev_write関数、vos_dev_read関数を細切れに呼び出すよりも分けずにまとめて呼び出すことが同様に短時間化に重要だと分かりました。

VinculumUは独自RTOSで実装されており、各処理の切り替え、関数呼び出しのオーバーヘッドが大きいようです。最後の結果でもCSが下がってからクロックが出るまで約40usec要しています。同様にクロックがで終わってからCSが上がるまでに約50usec要しています。VOS_Q、VOS_TICKの値を様々に変更してタイムスライスを小さくしても劇的な変化はありませんでした。VinculumU のSPIマスタは関数呼び出しのオーバーヘッドが非常に大きいことを考慮する必要があることが分かりました。

なお、今回の結果とは別に書き込みのみで書き込みデータを増やしてCSが0の区間を測定すると下記のような結果になりました。

書き込みデータ8byte192byte384byte512byte640byte800byte944byte
処理時間100usec200usec260usec310usec350usec410usec460usec

CS変化前後の処理オーバーヘッドの時間は変わらず、データ数の増加に合わせて処理時間が長くなる結果となりました。

これらのことからVinculumU のSPIマスタは高速な読み書き用途としてあまり向いていないことが分かりました。実装する際は関数呼び出しのオーバーヘッドを考慮してコーディングする必要があると分かりました。特にUSBのIsochronous転送の場合、最短1msecごとにデータが転送されます。少なくとも1msecより短い時間で1回の転送データを書き込む必要があり、SPI通信の処理速度が求められます。今後はIsochronous転送でどれくらいのデータ処理ができるか検討したいと思います。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする