HOME

早速使ってみた

メモリーマップ  

<2008/11/27記>
 これがまた分からないんだよな。
 普通のCPUみたいに単純にアドレスバスだけでアクセスするんじゃないらしい。
 同じ番地のメモリーに、LバスだのIバスだのと何種類かのバスが繋がっていて、どのバスを使うかによってアクセス速度に差が出てくる。
 使うバスによってキャッシュされたりされなかったりもする。
 例えば内蔵のRAM(SH7710の場合はXYメモリーと言う)にアクセスするのにも何種類か方法がある。

<2008/11/6追記>
 XYメモリーは必ずLバス経由でアクセスすること。キャッシュの項を参照
 内蔵のXYメモリーは特別別扱いだったんだよ。それを知らないから悩んだじゃんか。

図1 X/Y メモリ論理アドレス HARD取説 P.223

 論理アドレスでアクセスする方法を「Lバス経由でのアクセス」と言うらしく、この場合はA500_7000番地を使う。物理アドレスでアクセスするときは、上位3ビットをマスクしてIバス経由でアクセスする・・つまり0500_7000番地でアクセスする。
 Lバス経由でのアクセス(A500_7000番地)とIバス経由でのアクセス(0500_7000番地)で何か違いがあるわけ?あるらしい。
 IバスはDMAなんかの時に周辺のI/Oが使うんで、競合が起きると調停の必要があるのだ。つまり速度低下するかもってこと。

 なら黙ってLバスでアクセスすればよろしい・・・かと思うと、LバスだとP2エリアなんでキャッシュが効かないじゃん。そうなんだよキャッシュが効かないんだよ。
 だからハードを設計するときに、P2領域にメモリーを割り付けるんじゃないよ。
 外付けメモリーはP0エリアにくっつけなきゃダメって事な。
 で、Lバス経由でアクセスする。

 例えば0C00_0000にRAMを載せたんなら、P0領域の論理アドレス0C00_0000でアクセスする。
 P2領域のAC00_0000からアクセスするとキャッシュが効かないよってことじゃ。
  *p=0x0c000000; *p=0xaa; // これはキャッシュが効くけど
  *p=0xac000000: *p=0xaa; // これはキャッシュが効かない

 んま、MMUを使わないなら黙ってP0で動けばいいのじゃってことみたいね。

取説抜粋 HARD取説 P224
 論理アドレス(Lバス)からのアクセスは、1 サイクルアクセスになります。
 物理アドレス(Iバス)からのアクセスは、複数サイクル必要となります。
 なお物理アドレスからアクセスする場合は、上位3ビットを0とする。

           図2 P0〜P4領域のアドレスとキャッシュ
   0000_0000








   8000_0000



   A000_0000




   C000_0000



   E000_0000


   FFFF_FFFF

     
     
     
     P0/U0



 

     P1    

 

     P2
  キャッシュ無効  
 

     P3
    
 

     P4
  キャッシュ無効  




←ここで動けばいいのだ。






←OSを載せるならここ。



←BOOT。内蔵I/Oや外部I/O。
XYメモリーもここ(特例でキャッシュ有効)。



←ここはMMUを使うときだけ。


←ここは一部の内蔵I/O。

 





外部メモリー

<2008/11/27記>
 CPUのアドレスバスの上位3ビット(A31,A30,A29)は、メモリーと接続されていない。
 つまり、A000_0000と0000_0000はメモリー側から見ると同じアドレスである。
 CPUはBOOT時にアドレスバスをA000_0000にするから、上位3ビットを無視した0000_0000番地にROMを接続しておけば、BOOTプログラムが起動する。
 だけどA000_0000からのアクセスだとP2領域なんでキャッシュが効かないから、さっさとP0領域の0000_0000へジャンプするだ(図4のRSTHandler)。
 で、前処理が終わったら次はC言語のプログラムエリア(図4のP)へジャンプ。

 ROMが0000_0000〜03FF_FFFF番地、SDRAMが0C00_0000〜0FFF_FFFF。
 こんな感じになるんかも・・

図3 外部メモリーのデコードイメージ





セクション指定

<2008/11/27記>
 取り敢えず適当にセクションを設定してコンパイルしてみた。
 B、R、Sセクションだけど、このCPUボードには物理アドレス0C00_0000に2MのSDRAMが載っている・・つまり0C00_0000〜0FFF_FFFFまで・・で、前述の通り間違ってAC00_0000(P2領域)でセクション指定しちゃうと変数のキャッシュが効かなくなっちゃうよ。必ずP0領域のアドレス0C00_0000でセクション指定してちょうだい。
 なおA500_7000はXYメモリーの指定なり(このアドレスはP2領域だけどXYメモリーは特別扱いでキャッシュが効くのだ キャッシュの項を参照)。

図4 リンカのセクション設定でセクション名を実アドレスに割り付ける。

 外付けのフラッシュROMは0000_0000番地に接続されており、プログラムコードはここに書き込まれる。
 外付けの低速なSDRAMは0C00_0000に接続されており、変数(B,R)やスタック(S)はこのSDRAM上に置かれる。
 内蔵の高速なXYメモリーはA500_7000とA501_7000に接続されており、#pragma sectionで指定することでここに変数が置かれる。
 なおセクション名BX,BY,$XB,$YB等は自動的に生成される。DSP取説 P90

 1 BXとBYはFFT演算使用時に#pragama section X/Yを使ったので現れてる。

 2 $XBと$YBは以下のように変数宣言すると現れる。
  int __X x1; // Xメモリー上に変数x1を置く
  int __Y y1; // Yメモリー上に変数y1を置く

 なお、セクション設定はインポートとエクスポート可能であるぞな。




セクション名の規則

<2008/11/27記>
 基本のセクションの命名規則はこんな感じ。
 ちょいこんがらがるのがD,R,B辺りかな。
 んま、ここは難しいことはない。

     図5 セクション名一覧

 ここにも説明有り。
 図4も見てね。

  1. PResetPRG
    HEWのウイザードが生成した起動ルーチンのセクション。
     
  2. P
    プログラムセクション。
     
  3. C
    定数(const)セクション。
     
  4. D、R、B
    Dはデータ領域のコピー元のセクション(ROM)。
    コピー先はR(RAM)で、main実行前にDをコピーしておくこと。
    Bはグローバル変数エリアで、mainが走る前にゼロで初期化しておくのが礼儀ってモンですわ。
    main実行前の変数の初期化処理は「resetprg.c」の中の「_INITSCT()」と言う関数で行われるんだけど、初期化の為のセクション指定なんかは dbsct.c で指定してるんで、この辺を自分で変更したいときはいじれるよ。詳細は導入ガイド P25
     
  5. S
    スタック領域のセクション。
    Call Walkerやシミュレータを使って正確なスタックサイズを調べて、stacksct.hの定義を修正して使う・・ま、今時はメモリーはたっぷりだろうから、大きめにしとけば間違いないって。
     
  6. C$DSEC、C$BSEC
    変数領域の初期化時にHEW独自の組み込み関数が使用する変数領域のセクション名で、dbsct.cの中でセクション定義を見る事が出来る。
    自分で独自のセクションも作れるよ。
     
      int x1; // この変数は普通にBセクションに生成される。
      #pragma section MOO // 適当なセクション名を作り・・
      int x2; // これでBMOOセクションが生成される
      int x3=0; // これでDMOO  ”
      void proc(void){} // これでPMOO  ”
      #pragma section // 何も書かなければ元のセクションに戻るんで・・
      int c; // この変数は元のBセクションに生成される。

 なおセクション名だけ書いてリンカでアドレスを設定しない場合は、直前のセクションに続いて配置される。リンク時にウォーニングが出るけどね。

HOME