組み込みソフトでレジスタにアクセス
FPGA内にCPUを配置した場合、CPUからLogic内のレジスタにアクセスする時のC言語記述についてです。
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を使用する方法もあります。
② 関数への引数や戻り値は、グローバル変数にする。
これも、スタックへのアクセスが少なくなります。