2021年01月16日

QSPI通信を用いたSRAM読み書き

STM32マイコンのペリフェラル機能の1つ、QSPIがあります。今回はQSPIでNOR Flashではなく、SRAM(IS62WVS5128FB)を読み書きする方法を紹介します。データ削除等が必要なNOR FlashよりもSRAMは処理がシンプルで、読み書きのみです。

SPIは4つの信号線 (CS:Cable Select、SCK:Serial Clock、MISO:Master In Slave Out、MOSI:Master Out Slave In) で構成されています。一方、QSPIは6つの信号線(CS、SIO0、SIO1、SIO2、SIO3、SCK)で構成されています。SPIはMISO、MOSIの2本の通信バスに対して、QSPIはSIO0、SIO1、SIO2、SIO3の4本の通信バスに拡張されています。そのため、1クロックで送受信できるデータが2倍となり、より高速に通信できるようになっています。QSPIは主にNOR Flash、SRAM等のメモリ向けのインタフェースとして多く採用されています。

QSPI通信はSPI通信と互換があり、多くのQSPI対応デバイスは起動直後はSPIデバイスとして動作します。初期化や設定が完了してからQSPIモードに切り替えて高速に通信します。また、SPIのMISO、MOSIの2本のバスは通信方向が固定されていますが、QSPIは通信状態に応じて通信方向が変化します。通信状態をやり取りするためにSPIと異なり、インストラクションを送ってからアドレスやデータのやり取りを行います。多くの場合はインストラクション+アドレス+データの3つで構成されています。

STM32マイコンのHALライブラリでは、HAL_QSPI_Commandでインストラクション+アドレス+データ設定を行い、送信の場合のデータはHAL_QSPI_Transmitで送信し、受信の場合はHAL_QSPI_Receiveで受信します。

具体的にデータをメモリから読み込む場合は下記のような流れで設定します。
QSPI_CommandTypeDef sCommand;
HAL_StatusTypeDef res=0;
sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;//インストラクションのバス数 1~4
sCommand.Instruction = READ_CMD;//インストラクション
sCommand.AddressMode = QSPI_ADDRESS_1_LINE;//アドレスのバス数 1~4
sCommand.Address = address;//アドレス
sCommand.AddressSize = QSPI_ADDRESS_24_BITS;//アドレス長
sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;//オルタネイトバイト(拡張用、通常は未使用)
sCommand.DataMode = QSPI_DATA_1_LINE;//データのバス数 1~4
sCommand.DummyCycles = 0;//アドレスを設定してからデータの送受信までに待機が必要な場合に設定
sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;//DDRモード設定
sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;//DDRモード時遅延設定
sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;//コマンドモード
sCommand.NbData = read_length;//データ長さ
res+=HAL_QSPI_Command(&QSPIHandle, &sCommand, 0xFFF);//インストラクション+アドレス+データ設定
res+=HAL_QSPI_Receive(&QSPIHandle, read_data, 0xFFF);//受信処理

上記の例では一般的なインダイレクトモードの例を紹介しました。STM32マイコンのQSPIではインダイレクトモード、ステータスポーリングモード、メモリマップモードの3種類あります。

インダイレクトモード:インストラクション+アドレス+データで送受信する一般的処理モードです。
ステータスポーリングモード:メモリのフォーマット等、時間を要する処理の場合に処理の完了有無を定期的に自動で確認することができます。
メモリマップモード:アドレスで直接、データを読み込み可能なモードです。ポイントは読み込み専用で書き込み不可。フォントや画像といった固定のデータを読み出す場合に向いています。

SRAM(IS62WVS5128FB)はDDRモードに対応していませんが、DDRモードに対応しているメモリの場合、クロックの立上がりと立下りの両方でデータのやり取りができるため、さらに倍のデータをやり取りできます。今回は読み込みのみ紹介しましたが、SRAM(IS62WVS5128FB)とQSPIで読み書きする全体コードはこちらにアップしました。


最近のSTM32L5等ではQSPIの代わりにOctalSPIが搭載されています。OctalSPIはバスが8本となりさらに高速に通信することが可能です。残念ながらQSPIのメモリマップモードは読み込み専用ですが、OctalSPIのメモリマップモードはFMCやFSMCのメモリマップモード同様に読み書き可能です。OctalSPIも今後紹介したいと思います。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2021年01月09日

C言語FFTライブラリ

今回はC言語ベースのFFTライブラリについて紹介します。音や画像などを処理する場合に欠かせない処理としてFFTがあります。1次元の場合はFFT処理で時間毎の信号を周波数ごとの信号に変換できます。1からFFT処理を実装するよりも多くの場合はライブラリを活用すると思います。今回は代表的なFFTライブラリを紹介したいと思います。

・ライセンス
 GPL、商用ライセンス

・メリット
 多次元対応
 CPUの拡張命令によってより高速な処理が可能
 マルチスレッド対応

・デメリット
 GPLライセンス
 専用ライブラリを組み込む必要がある
 fotranコンパイラが必要
 malloc使用
 →組み込み系には向かない

・ライセンス
 修正 BSD

・メリット
 BSDライセンス
 FFTWと互換インタフェース
 多次元対応
 fotranコンパイラ不要

・デメリット
 全てのFFTW関数と互換があるわけではない
 コード構成が複雑
 malloc使用
 →組み込み系には向かない

・ラインセンス
 フリーソフトウェア

・メリット
 コード構成がシンプルで移植が容易
 CPUの拡張命令未使用で移植性が高い
 マルチスレッド対応
 malloc使用/未使用選択可能
 組み込み系にも移植可能

・デメリット
 CPUの拡張命令未使用で速度は期待できない

・ライセンス
  Apache2.0

・メリット
 ARM DSPを活用した高速処理

・デメリット
 ARMDSP搭載マイコンのみ使用可能
 ARMDSP専用で移植性が低い
 サイズ最大4096点

PCアプリケーションで使用する場合はFFTSSやFFTSGがお勧めです。組み込み系の場合はFFTSGがお勧めです。

STM32マイコンでFPU搭載の場合、FFTSGとCMSIS-DSPライブラリで同じ処理点数で速度差はほとんどありませんでした。DSPを使用するCMSIS-DSPライブラリの方がハードウェア演算を利用するため、若干速くなります。

ただ、最適化されたFFTとFPUによってFFTSGも高速に処理できるため、あまり差がなくなっています。一方、CMSIS-DSPライブラリは最大4096点と用意されている関数の点数に制約があります。また、事前にVisualStudio等のコンソールアプリケーションとして単体テストしてからマイコンに移植するといった用途も考えるとFFTSGの一択となります。FFTSGのソースコードはdoubleとなっているため、STM32マイコン等に移植する際にはソースコード内のdoubleを丸ごとfloatに置換させるとFPUで高速に処理できるようになります。なお、FFTSGはサイズ最大4096点の制約がないものの、4096点以上の場合に膨大なRAMメモリが必要となります。高性能マイコンや外部RAM搭載マイコンが必要となります。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2021年01月02日

mbedからSW4STM32インポート時のエラー対策

あけましておめでとうございます。2021年も組み込み系を中心として情報発信や開発を行っていきたいと思います。

今回は今回はよくあるmbedからのインポート時に生じるエラーの対処方法について紹介します。mbedの機能としてオフライン開発環境のプロジェクトファイルとしてエクスポートできる機能があります。ただ、プロジェクトによってはmbedからエクスポートしたプロジェクトをSW4STM32等にインポートするとエラーでビルドできない場合があります。エラー内容に応じて下記の対策を行います。

■mbed namespace undefined mbedエラー
プロジェクト内にC言語のcファイルがある場合に発生します。mbedはC++言語のため、ファイルを強制的にcppファイルに拡張子を書き換えることで対処することができます。多くの場合、コード自体を書き換える必要はありません。

■nano.specs: attempt to rename spec 'link' to already defined spec 'nano_link' エラー
プロジェクトのプロパティからC/C++Build設定のSettings、Tool Settings、MCU GCC Linkerの設定で、-specs=nosys.specs -specs=nano.specを削除します。

linkersetting.jpg

また、プロジェクトフォルダ直下にmakefile.targetファイル内に2か所(debugとrelease)ある
-specs=nosys.specs -specs=nano.specを同様に削除します。

■Undefined reference to `_getpid', to `_kill', and others エラー
暫定対策ではありますが、main.cppファイル内に下記の2行を追加することでエラーを回避させます。
extern "C" int _getpid(void){return 1;}
extern "C" void _kill(int pid){while(1);}

以上のような対策でよくあるmbedからのインポート時のエラーに対処できます。他のエラーに遭遇した場合にはまた追記していきたいと思います。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2020年12月12日

STM32 UARTパリティ設定 注意点

STM32マイコンのUARTでパリティを使用する際の注意点について紹介します。通信相手によってはパリティビットを使用する場合があります。STM32マイコンのUARTにもパリティ設定項目があり、パリティなし、偶数パリティ、奇数パリティに対応しています。ただ、パリティを使用する際に注意点があり、注意点に気づかずに設定すると意図したデータが送受信されません。

パリティを使用する際の注意点として、パリティビットを含めたデータ長を設定する点です。具体的には8bitの送受信データでパリティビット有効にした場合はデータ長は9bitとして設定します。8bitのままの場合、パリティビットを含めて8bitとなり、送受信のデータ長は7bitとして扱われ、0x00~0x7Fまでのデータしか送受信されません。

parity.jpg

STM32CubeMXの設定項目をよく見ると「including Parity」と記載があり、パリティビットを含めたデータ長を設定することが分かりますが、あまり考えずに設定すると見落としがちです。特にCubeMXから生成した後にコード上で変更すると設定項目の注意書きにも気づかないため、特に注意が必要です。

posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2020年11月21日

STM32 USB CDC応用

以前、STM32 USB CDC注意点について紹介しました。今回はUSBの接続有無確認やCOMポートのオープンといった確認する方法を応用編として紹介します。

■USB接続有無確認方法
ステートを確認することでPC等のホスト側とのUSB接続有無を確認することができます。STM32 HALライブラリのUSB CDC以外でも利用できます。USBデバイスのハンドルのdev_stateから確認できます。dev_state が USBD_STATE_CONFIGURED の場合はUSBがPCと接続されている状態です。例えば下記のような使い方ができます。

if(hUsbDeviceFS.dev_state == USBD_STATE_CONFIGURED)
{
   //USBが接続されている場合
}
else
{
  //USBが接続されていない場合
}

■COMポートオープン有無
CDCの場合、USB接続の有無だけでなく、COMポートのオープン有無を確認したい場合が多々あると思います。通信で確認する他に間接的ではありますが、CDC_GET_LINE_CODINGの呼び出しイベントから確認できます。電源ON後のUSB認識時とCOMポートオープン時にそれぞれ2回から3回、CDC_GET_LINE_CODINGのイベントが発生します。このイベント発生をカウントすることでCOMポートのオープンを確認することが可能です。

usbd_cdc_if.cファイル内のCDC_Control_FS関数のCDC_GET_LINE_CODING条件を下記の様に書き換えます。必要に応じて下記の様にカウンタとフラグを設定して確認できるようにします。

case CDC_GET_LINE_CODING:
{
  USBD_SetupReqTypedef * req = (USBD_SetupReqTypedef *)pbuf;
  if((req->wValue & 0x0001) != 0) //ドライバによっては不要
  {
    comOpenCount++;
    if(comOpenCount>3)IsComPortOpen=true;
  }
}


STM32マイコンのUSB関連のHALライブラリについても、最低限の機能は実装されているため、少しコードを追加することで応用することが可能です。他にも便利な機能等あれば、また紹介したいと思います。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする