2021年10月09日

PIC32 ソフトウェアリセット

今回はPIC32MX270F256BをターゲットにMPLAB X v5.45+Harmony3+XC32 v2.50を使用して、PIC32マイコンのソフトウェアリセット(Soft Reset)を利用する方法について紹介します。

何かしらの異常が発生した場合に電源投入時の状態に初期化する際にソフトウェアリセットを利用します。Harmony3では予めコンポーネントが用意されているため、コンポーネントを追加するだけで簡単にソフトウェアリセットを利用することができます。ただ、名称が分かりづらく、RCONというコンポーネント名称になっているため、注意が必要です。

RCON1.jpg

RCONを追加した状態でコード生成をするとconfig/(ユーザ指定名)/peripheral/rcon/plib_rcon.h内にソフトウェアリセットの関数が定義されています。

条件に応じてRCON_SoftwareReset();を呼び出すだけでソフトウェアリセットを実行することができます。RCON_SoftwareReset()関数内では割込みの無効化、システムレジスタのアンロック、リセットという一連の必要な処理が既に定義されているため、自身でソフトウェアリセットを実装するよりも簡単に使用することができます。

異常が連続して起きた場合に変な挙動にならないようにソフトリセットの使い方には要注意ですが、コンポーネントを追加するだけで比較的簡単に実装することができました。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2021年10月02日

マルチゾーンToF測距センサVL53L5

今回はSTから販売されているマルチゾーンToF測距センサVL53L5について少し試食したので、その内容を紹介します。

今までもSTからToF測距センサVL53LXXシリーズが出ていましたが、VL53L5の特徴として最長4mまでの測距距離と最大64(8x8)の測距ゾーンを実現しています。デフォルト設定では4x4のマルチゾーンですが、設定変更で8x8のマルチゾーンに対応します。

VL53L5.jpg

VL53L5の評価ボード、VL53L5CX-SATELを使ってみました。従来のVL53LXの評価ボードとピン配列が異なっているため、注意が必要です。VL53L5CX-SATELは1列のピンになっています。少し戸惑った点としてVL53L5自体にないPWRENピンが評価ボードのピンにあり、評価ボード上のレギュレータの有効化ピンになっています。PWRENピンを3.3Vに接続して、AVDDからの5Vを3.3Vに落とすレギュレータを有効化します。

サンプルコードを実行したところ、デフォルト設定の4x4で取得できることが確認できました。ただ、従来のLVL53LXシリーズとの大きな違いとして、センサ自体がマイコンを搭載しているため、センサの初期化の際にセンサのファームウェアのロードが必要です。それに伴ってセンサドライバのコードサイズが非常に大きくなっています。手元にあったROMサイズ64kBのSTM32F303K8ではでは入らず、STM32F401REでサンプルコードを実行しました。

ビルドした際の出力を確認すると下記のようにサンプルコードだけで100kB近く使用していることが分かりました。

RAM: 1856 B 96 KB 1.89%
FLASH: 105800 B 512 KB 20.18%

VL53L5は最大64のマルチゾーン対応で非常に魅力的なセンサですが、それに合わせてセンサドライバが大きいということが分かりました。機能の制限や実装方法を工夫することで多少小さくできる余地はありますが、従来のセンサに比べて大きいということは変わりません。VL53L5を使用する場合はプログラムサイズが少なくとも128kB以上のマイコンを使用する必要がありそうです。
posted by Crescent at 00:00| Comment(0) | 電子部品 | このブログの読者になる | 更新情報をチェックする

2021年09月25日

PIC32マイコンEEPROMエミュレーション

今回はPIC32MX270F256BをターゲットにMPLAB X v5.45+Harmony3+XC32 v2.50を使用して、PIC32マイコンのフラッシュをEEPROMとしてユーザーデータを保存する方法について紹介します。


PICマイコンのシリーズによってはマイコン内にフラッシュ書き込み回路が内蔵されていないため、内蔵のフラッシュに単体で書き込むことができないものが多いです。一方、PIC32マイコンはフラッシュ書き込み回路が内蔵されているため、単体で書き込むことが可能です。この機能を活用することで外付けのEEPROMの代わりとして内蔵フラッシュに簡単な設定データや固定データ等を保存、読み込みすることができます。


なお、EEPROM同様にUSBメモリやSDカードのようにメモリ領域を分散して書き込む機能がないため、毎回同じメモリセルに書き込まれます。そのため、高頻度に書き換える用途ではフラッシュの該当するメモリセルのみ早期に寿命を迎える可能性があります。PIC32MXシリーズでは最低2万回の読み書きできる仕様ですが、RAMのような使い方をすると早期に寿命になり正常に読み書きできなくなります。設定データや固定データ等の書き換え回数が少ないデータ保存に使用するのが適切です。書き込みの回数に制約があるものの、読み込みは高頻度であっても問題はありません。

また、内蔵フラッシュにデータを保存する注意点として内蔵フラッシュの空き領域であることを確認する必要があります。デフォルトではMedia Start Addressは0x9D020000以降に128kbの領域で設定されています。つまり、内蔵フラッシュの半分以降がEEPROMとして使用する領域として設定されています。この場合、プログラムメモリの使用率を内蔵フラッシュの半分以下にする必要があります。プログラムメモリを多く使用する場合や逆にNVMエリアを広くする場合はプログラムメモリと重複しないようにMedia Start Addressの設定に注意してください。

重複の有無はMPLAB Xのファームを書き込む際に表示されるコンソールから領域を確認できます。
The following memory area(s) will be programmed:
@program memory:
start address = 0x1d000000, end address = 0x1d0083ff

Aprogram memory:
start address = 0x1d03f000, end address = 0x1d03f7ff

上記の領域に0x80000000をオフセットされた領域が実際の領域です。
@0x9d000000, end address = 0x9d0083ff
A0x9d03f000, end address = 0x9d03f7ff

つまり、内蔵フラッシュを0x1F000以上書き込むとAの領域と重複することが分かります。今回のテストコードは0x0400(1024)サイズの書き込みのため、問題ないことが分かります。


Harmony3ではNVMコンポーネントとしてライブラリが準備されています。NVMコンポーネントだけでも読み書きできますが、MEMORYコンポーネントと合わせて使用することで他のメモリでも同じ関数で読み書きできるため、汎用性高く実装できます。今回はNVMコンポーネントとMEMORYコンポーネントを合わせて使用して内蔵フラッシュに対して読み書きしてみました。

Harmony3のプロジェクトグラフは下記の通りです。

eeprom_emu1.jpg

実装は下記の通りです。

app.c内に変数定義及び読み書き完了割込み関数を追加します。

#define BUFFER_SIZE 1024
uint8_t writeBuffer[BUFFER_SIZE];
uint8_t readBuffer[BUFFER_SIZE];
uint32_t blockStart = 0x0;
uint32_t nBlock = BUFFER_SIZE;
DRV_MEMORY_COMMAND_HANDLE commandHandle;
bool xfer_done = false;

void appTransferHandler
(
 DRV_MEMORY_EVENT event,
 DRV_MEMORY_COMMAND_HANDLE commandHandle,
 uintptr_t context
)
{
 switch(event)
 {
  case DRV_MEMORY_EVENT_COMMAND_COMPLETE:
  xfer_done = true;
  break;
  case DRV_MEMORY_EVENT_COMMAND_ERROR:
  break;
  default:
 break;
 }
}

app.c内のAPP_Tasks内に読み書きのテストコードを追加します。


 DRV_HANDLE memoryHandle;
 memoryHandle = DRV_MEMORY_Open(DRV_MEMORY_INDEX_0, DRV_IO_INTENT_READWRITE);
 if (DRV_HANDLE_INVALID == memoryHandle)
  {
   SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "Open ERR\r\n");
  }
  SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "Open OK\r\n");

  DRV_MEMORY_TransferHandlerSet(memoryHandle, appTransferHandler, (uintptr_t)NULL);
  SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "TransferHandlerSet OK\r\n");


  memset(writeBuffer,'\0',sizeof(writeBuffer));
  memset(readBuffer,'\0',sizeof(readBuffer));
  sprintf((char*)writeBuffer, "Hello!! ");
  SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "sprintf OK\r\n");


  //Write Data
  xfer_done = false;
  DRV_MEMORY_AsyncEraseWrite(memoryHandle, &commandHandle, writeBuffer, blockStart, nBlock);
  if(DRV_MEMORY_COMMAND_HANDLE_INVALID == commandHandle)
  {
   SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "AsyncWrite ERR\r\n");
  }
  while(!xfer_done)
  {
   DRV_MEMORY_Tasks(sysObj.drvMemory0);
  }
  SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "AsyncWrite Complited\r\n");

  //Read Data
  xfer_done = false;
  DRV_MEMORY_AsyncRead(memoryHandle, &commandHandle, readBuffer, blockStart, nBlock);
  if(DRV_MEMORY_COMMAND_HANDLE_INVALID == commandHandle)
  {
   SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "AsyncRead ERR\r\n");
  }
   while(!xfer_done)
   {
    DRV_MEMORY_Tasks(sysObj.drvMemory0);
   }
   SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "AsyncRead Complited\r\n");
   SYS_DEBUG_PRINT(SYS_ERROR_DEBUG, "W:%s\tR:%s\r\n",writeBuffer,readBuffer);


実際に実行した結果は下記の通りです。

eeprom_emu2.jpg


今回は動作テストとして非同期関数を同期関数のように実装しました。注意点として、読み書き完了後の割込み関数appTransferHandlerはDRV_MEMORY_Tasksを実行しないと呼び出されません。main.cのSYS_Tasks内でDRV_MEMORY_Tasksが自動的に追加されているため、非同期として使用する場合には問題ありませんが、ブロックさせて同期関数のように使用する場合はDRV_MEMORY_Tasksを呼び出してメモリ処理を別途実行する必要があります。

今回のプロジェクトファイル一式はこちらにアップ(PIC32MX_EEPROM.zip)しています。Harmony3を使用することでSTM32マイコン同様に簡単に内蔵フラッシュにユーザーデータを読み書きできることが分かりました。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2021年09月18日

USBカメラ接続

今回は昨年から試行錯誤しながら取り組んでいるプロジェクトを少し紹介します。組込系でカメラ機能を利用する場合、昨今ではOpenMVやM5Camera、ESP32-Cam等を利用することが多いと思いますが、いまいち継続的な入手性や汎用性に欠けます。


そこで汎用的なUSBカメラから取り込むことで汎用性高く実装することを検討しています。ただ、USBカメラはUVC(USB Video Class)という規格があるものの、非常に帯域を要するため、組込系では処理がギリギリです。また、USBカメラの機種やメーカによっても細かい挙動が異なるため、なかなか苦戦中です。

まだ動作に改善の余地がありますが、LCDに表示させてみました。


uvc1.jpeg


uvc2.jpeg

もともとはSTM32マイコンで実装予定でしたが、Isochronous転送が安定しないことと、、昨今の半導体不足で入手困難であるため、断念しました。FTDIのVinculum2ではRTOSのオーバーヘッドが無視できず、SPIの転送速度が遅すぎて断念しました。現状はPIC32マイコンで実装しています。

紆余曲折あって、苦戦していますが、もう少しファームの作りこみや動作確認を継続して、検討中のプロジェクトに組込たいと思います。
posted by Crescent at 00:00| Comment(0) | 電子工作 | このブログの読者になる | 更新情報をチェックする

2021年09月11日

I2C Bus Accelarator検証

以前に紹介したGrove等で使用されるI2Cを延長する方法について、実際に少し検証してみました。

一般的にI2Cはマイコン周辺の機器との通信を想定しているため、数メートルといった距離の通信を想定していません。Grove規格ではハブやケーブルを接続して、数mまでケーブルを延長すると波形が鈍って通信エラーが多発します。このような場合にI2CバスバッファICで差動信号に変換して、延長先で再度、差動信号をI2Cに変換する方法があります。数10m以上延長する場合に非常に有効な方法ですが、数m程度の延長で変換アダプタを使用するのは少し大がかりです。その際に便利な部品、バスアクセラレータLTC4311を紹介します。


バスアクセラレータLTC4311は、400pFのI2C仕様を上回るバス負荷条件で
データ伝送速度と信頼性を向上させるアクティブ・プルアップです。

• I2Cバス立ち上がり遷移時間を改善
• I2Cバス上に複数のデバイスを接続する場合にデータの完全性を保証
• 広い電源電圧範囲:1.6V〜5.5V
• “L”状態のノイズマージンを改善
• 最大400kHz動作

簡単に言えば、配線が長くなってクロックや信号が鈍ってしまうところをHigh、Lowをバシッと決めてくれるデバイスです。

通信ケーブル1m、波形の鈍りが分かりやすいように意図的に大きなプルアップ抵抗20kΩを接続し、HS3001温度湿度センサをI2Cデバイスとして使用した場合の波形を比べてみました。


LTC4311_3.jpg
100kHzクロックでLTC4311未使用の場合です。赤線がデータ、黄線がクロックです。1mなので通信できますが、立ち上がりが少し鈍っています。

LTC4311_4.jpg
100kHzクロックでLTC4311使用の場合です。赤線がデータ、黄線がクロックです。I2CバスラインにLTC4311を挿入するだけで立ち上がりの鈍りが解消されています。

ケーブルが長い場合やケーブルの種類によっては通常、波形の鈍りが大きくなり、正常に0と1を送信できなくなり、通信エラーが多発します。アクティブ・プルアップによって波形の鈍りを解消することでより長いケーブルでの伝送ができるようになります。今回は検証していませんが、I2C駆動電流を大きく流せないようなデバイスやマイコンの場合に波形が鈍って通信できない場合にも有効だと思います。

部品単体では効果を確認できたため、I2Cバスアクセラレータ基板の設計をしてみたいと思います。
posted by Crescent at 00:00| Comment(0) | 電子部品 | このブログの読者になる | 更新情報をチェックする