2009/01/29(木)[NiosII][組込] IOアクセスの注意事項など

[NiosII][組込] NiosII コアを/fにしてD-cacheを有効にする場合の注意

NiosIIシステムはメモリマップドI/Oなので,I/Oに関するキャッシュ制御はどのようになっているのか気にはなっていた.

コアのconfigurationでキャッシュレスとして遊んできていたので,特に問題は起きてこなかった.キャッシュ有りとしてソフトの動作が不安定になったので,そのときに参照した資料へのポインタと,ドライバを各ユーザ向けのメモを残しておく.

こんなもんにはまってたらいかんのだが...

(引用元)

Nios II Software Developer’s Handbook (NII5V2-8.0, n2sw_nii5v2.pdf)\9. Cache and Tightly-Coupled Memory\ Writing Device Drivers

(意訳)

デバイスドライバでは,データキャッシュは命令セットのldio/stioファミリを使うことでバイパスしなければなりません.\データキャッシュの無いNios IIコアでは,これらの命令の挙動は 対応するld/st命令と同じように振舞うので,親切です?(benign).

Cプログラマのために.\volatileのようにポインタを宣言し,そのvolatileポインタを使ってアクセスしても,データキャッシュをバイパスすることはできないことに注意ください.\volatileキーワードはポインタを使ったアクセスを,コンパイラ最適化から防ぐ(除外する)だけです.

で,HAL上でコードを書いているなら,このマクロを使ってくれ,とのこと.

ファイル:C:\altera\81\nios2eds\components\altera_nios2\HAL\inc\io.h

/* Dynamic bus access functions */
IORD_32DIRECT(BASE, OFFSET)
IORD_16DIRECT(BASE, OFFSET)
IORD_8DIRECT(BASE, OFFSET)
IOWR_32DIRECT(BASE, OFFSET, DATA)
IOWR_16DIRECT(BASE, OFFSET, DATA)
IOWR_8DIRECT(BASE, OFFSET, DATA)

これらは,offsetBYTEアドレスを記述します.NG箇所の,DATA FIFOへの吐き出しコードを記します.

#define IOWR_UJIYA_DAI_DATAFIFO(base,data)	IOWR_32DIRECT(base, ((3) * 4), (data))

"アドレス"が必要なので,ベースアドレスから3つ目のレジスタとなる,12バイト目をoffsetに渡しています.


/* Native bus access functions */
IORD(BASE, REGNUM)
IOWR(BASE, REGNUM, DATA)

これらは,REGNUMBYTEアドレスを記述します.\同ファイルに,以下の定義がなされています.バス幅を32bitにしていれば,REGNUM×4をオフセット指定したのと同じになりますね.

#define __IO_CALC_ADDRESS_NATIVE(BASE, REGNUM) \
  ((void *)(((alt_u8*)BASE) + ((REGNUM) * (SYSTEM_BUS_WIDTH/8))))

作成するモジュールを,バス幅固定を前提とするか,任意幅(8bit幅で抑えることになる?)で実装するかによって,使うマクロを分けたほうが良い感じがしますね.\明示的に幅を規定するほうが安心感はありますけれど.


[NiosII][組込] 追記

長船さんからコメントをいただいておりますが,資料をあさっているとイロイロと書いてありました(^^;


cache controlの下記関数でcache対象外にしてしまう方法もある.memcpyするときとか,DDRRAMをVRAMにするときなんかに使える模様.

volatile void* alt_remap_uncached (void* ptr, alt_u32 len);

# memcpyのIO空間版を作るのが早そうだけれど.


さらに追記.というか順序からいうとこっちが先だろう...

Nios II Processor Reference Handbook ("NII5V1-8.1", "n2cpu_nii5v1.pdf")\Chapter 2: Processor Architecture\Memory and I/O OrganizationCache Memory\Cache Bypass Methods

  • I/O Load and Store Instructions Method\The load and store I/O instructions such as ldio and stio bypass the data cache and

force an Avalon-MM data transfer to a specified address.

  • The Bit-31 Cache Bypass Method\The bit-31 cache bypass method on the data master port uses bit 31 of the address as a

tag that indicates whether the processor should transfer data to/from cache, or bypass it.\This is a convenience for software, which might need to cache certain addresses and bypass others. Software can pass addresses as parameters between functions, without having to specify any further information about whether the addressed data is cached or not.

MSBに1たてとけばおk... 和訳は日本語ドキュメント見るなり華麗にスルーするなりで(笑



おまけ

memcpy()はsrc,dstが(4byte)alignmentされていればlong単位での転送.\burstを狙って*src++ = *dst++を記述(C言語で書かれている.)ただし,逆アセ結果は"ldw/add/stw/add"がセットになっているだけのコード.

インストラクションセットを見ると,こうせざるをえないようですね.ARMみたいなヘンタイ命令体系だと,複数転送命令があるのになぁ.(AMBAがburstコマンドを持っているから,必要なんだろうけど.Niosのburstはcache fillだけでburst動作かな...メモリが対応して無いと項か薄いだろうけど)



[NiosII][組込] 最適化有効(release build)時に漢字フォントが化ける

適当にいじくってるコードの話をしても通じませんが,恥ずかしい事例をひとつ.

globalにおいた char配列が奇数アドレスにマッピングされたために,まずいことになった.一部のメンバを shortでアクセスするため,alignment違反で変な値を読み込んでいた.

gcc方言となるが,__attribute__修飾子を使って4byte境界に置いておいた.

∵システムのバス幅が32bitなので,long(32buit)までのアクセスしかありえない

  const char font_table_kanji[] __attribute__ ((aligned (4))) = {
  #include "./VMGOL16.inc"

参考サイト ttp://developer.apple.com/DOCUMENTATION/DeveloperTools/gcc-3.3/gcc/Variable-Attributes.htmlあぽーになってるけどgcc manualがあればなんでも良い...