SH-2A 基板 (4)

SH-2A でキャッシュを有効にする設定自体は非常に簡単で、命令キャッシュなら CCR1 レジスタの ICE ビット、オペランド (データ) キャッシュなら OCE ビットを「1」にするだけです。
通常はキャッシュ内容を無効化するのと同時にキャッシュ動作を許可しますから、そのための設定も取り込んで、ビットごとの操作ではなく、レジスタ全体を一度に設定する形で示すと、

  CCNT.CCR1.LONG = 0x0909;

となります。
ただし、オペランド・キャッシュについては、invalidate ビットをセットしても自動では RAM への書き戻しは実行しない仕様になっています。 (もともと、命令キャッシュは読み込みだけで、書き込みはなし)
データシートの 8-13 ページにも、
「キャッシュと外部メモリ/大容量内蔵RAM とのコヒーレンシはソフトウェアで保証してください。」
と書かれており、何らかのソフトウェアのサポートが必要です。
どのようなプログラムを書けば良いのか分からなかったのですが、「SH-2A キャッシュ」のキーワードでググると、ルネサスの Web サイトの e-ラーニングのコースのベージがヒットし、そこでサンプルプログラムとして示されている関数を実装して、うまく動作させることができました。
ルネサスの Web サイト
  Renesas Electronics | ルネサス エレクトロニクス
のトップ・ページから、
「FAQ/サポート」 → 「半導体セミナー」 → 「e-ラーニング」 → 「SH-2A, SH-2A DUAL」
と進むと無料のクイックラーニングのページが開きます。 (FLASH プラグインが必要です)
左側の 5 個のボタンの一番下、「効率アップのワンポイントアドバイス」を押すと section5 の画面に切り換わり、キャッシュメモリ機能の使い方などの解説が始まります。
詳しいことは解説自体を見ていただくこととして、その中で示されているサンプルプログラムの記述に沿って「キャッシュ初期化関数」と「オペランドキャッシュの全てのパージ関数」を示すと

void Cache_Init( void )
{
    CCNT.CCR1.LONG = 0x0909;
    if (CCNT.CCR1.LONG) {} // dummy read
} // void Cache_Init()

void OCache_All_Purge( void )
{
    unsigned int entry;
    for (entry = 0; entry < 4*128*16; entry += 16) {
        *(unsigned int *)(0xF0800000 + entry) = 0; // A=0, U=V=0 (Purge)
    }
} // void OCache_All_Purge()

のようになります。
パージ関数は、4 ウェイ x 128 エントリの、合計 512 エントリにアクセスするため 512 回の繰り返しループとなっていますが、プログラム自体は簡単なものです。
これらの関数は、キャッシュ無効空間に配置して実行する必要があります。
C ソース中ではコンパイラの「#pragma section」指令によりセクション名を指定しておき、リンカで、そのセクション名に対応するアドレスをキャッシュ無効空間に割り付けるような設定にしておきます。
HEW の機能により新規作成したプロジェクトの構成では、パワー ON リセット・エントリ関数「PowerON_Reset_PC()」を含むファイルが「resetprg.c」という名前で生成され、「#pragma section ResetPRG」指令により「PResetPRG」というセクション名が付けられています。
これを利用して、上記の 2 関数を「resetprg.c」ファイルの中に追加し、PowerON_Reset_PC() 関数に変更を加え、最適化リンカの設定のセクション・カテゴリで、たとえば

0x3C000500 PResetPRG

のように指定しておきます。
「resetprg.c」の変更箇所は、たとえば次のようになります。

// --- (中略) ---

//#include "typedefine.h"  // --- (コメントアウト) ---
#include "iodefine.h"  // --- (追加) ---

// --- (中略) ---

#pragma section ResetPRG
#pragma entry PowerON_Reset_PC

// --- (ここから追加) --- 
void Cache_Init( void )
{
    CCNT.CCR1.LONG = 0x0909;
    if (CCNT.CCR1.LONG) {} // dummy read
} // void Cache_Init()

void OCache_All_Purge( void )
{
    unsigned int entry;
    for (entry = 0; entry < 4*128*16; entry += 16) {
        *(unsigned int *)(0xF0800000 + entry) = 0; // A=0, U=V=0 (Purge)
    }
} // void OCache_All_Purge()
// --- (ここまで追加) ---

void PowerON_Reset_PC(void)
{
// --- (中略) ---

    set_cr(SR_Init);
 
  OCache_All_Purge(); // --- (追加) ---
  Cache_Init();       // --- (追加) ---
    
    main();

// --- (中略) ---
}

// --- (中略) ---