nao-milkの経験ブログ

25年間の半導体エンジニア経験で知り得た内容を記載したブログです。

組み込みソフトでレジスタにアクセス

f:id:nao-milk:20210317125456p:plain

FPGA内にCPUを配置した場合、CPUからLogic内のレジスタにアクセスする時のC言語記述についてです。

 

f:id:nao-milk:20210317013944p:plain

 

CPUからレジスタにリード/ライトする場合、C言語予約語volatile」が重要になります。

 

volatileは、C言語ソースをコンパイルする時の「最適化を抑止」します。

と、よく書かれていますが、最初はピンとこなかったです。

 

コンパイラの最適化とは、論理合成みたいなイメージだと思っています。

冗長なものは削除したり、処理の順番を変更したりします。

※極力プログラム量(.text領域)を小さくしようとします。

 

なので、論理回路エンジニア(HDL記述者)がC言語を使って組み込みソフトの設計をする場合、volatileを意識する必要があります。

レジスタにアクセスする場合以外に、for文を使ってWait関数を作る場合は必要になります。

 

CPUをNIOSにする場合

 レジスタリード/ライト用のマクロが準備されていますので、それを使用します。

 レジスタライト:マクロIOWR( ) や IOWR_?

 レジスタリード:マクロIORD( )や IORD_?

 を、それぞれ使用します。

 尚、このマクロを使用する場合、io.hをIncludeする必要があります。

 ※パスは、bsp/HAL/inc/io.h

  どのようなマクロなのかは、io.hをみてください。

 

 このマクロを使用することで、最適化時に別のアドレスになったり、

 削除されたりすることはありません。

 また、キャッシュもバイパスします。

 

CPUをMicroBlazeにする場合

 volatileを使って、レジスタへのアクセスは可能です。

 が、これではキャッシュの制御ができなため、MicroBlazeの場合も

 マクロが準備されています。

 レジスタライト:Xil_out?

 レジスタリード:Xil_in?

 尚、このマクロを使用する場合、xil_io.hをincludeする必要があります。

 

CPUをARMにする場合

 volatileを使ってレジスタにアクセスしてください。

 

volatileやマクロを使わずC言語ソース作った場合、

実機確認した時やCo-Simした時に レジスタへのアクセス無かったり、アクセスの順番が変わっていたりします。

※気付きにくいところなので、注意して記述してください。

 

余談)

 組み込みソフトを速く動作させたい場合は、

 ① 関数分け細分化させない。

  流用性と可読性は悪くなりますが、関数呼び出しのスタックへのアクセスが

  少なくなります。

  ※defineでマクロを作ったり、INLINEを使用する方法もあります。

 ② 関数への引数や戻り値は、グローバル変数にする。

   これも、スタックへのアクセスが少なくなります。