セクションの複数ページをまとめています。 印刷またはPDF形式で保存...

もとのページに戻る

2025-08-08 現在

RAMの割当

RAMの割当
    RAMの割当について記述しています。

    RAMの割当

    TWWLIET GOLD の SRAM 領域は以下のようになっています。

    BASETOP(末尾+1)SIZE
    SRAM110x0402_C0000x0403_000016KB
    SRAM100x0402_80000x0402_C00016KB
    SRAM90x0402_40000x0402_800016KB
    SRAM80x0402_00000x0402_400016KB
    SRAM70x0401_50000x0401_60004KB
    SRAM60x0401_40000x0401_50004KB
    SRAM50x0401_20000x0401_40008KB
    SRAM40x0401_00000x0401_20008KB
    SRAM30x0400_C0000x0401_000016KB
    SRAM20x0400_80000x0400_C00016KB
    SRAM10x0400_40000x0400_800016KB
    SRAM00x0400_00000x0400_400016KB

    TWENET ではメモリマップを以下のように定義しています。

    BASETOPサイズ用途RETバンク名
    アプリケーション利用0x0400_0000コンパイル時に決定~64KBMMACのリンク時に必要SRAM0..3
    ヒープ0x0401_5000
    (変更可)
    0x0401_5C003KBヒープ領域 (malloc, new)SRAM7
    未使用0x0402_00000x0402_C00048KB未使用領域SRAM8,9,10
    SRAM11
    未使用0x0402_C0000x0402_F00012KB未使用領域SRAM11
    スタック0x0402_F0000x0403_00004KBスタック領域SRAM11

    (BASE: 開始アドレス, TOP: 終了アドレス+1, RET: スリープ時のRAM保持)

    • アプリケーション利用領域は、コンパイル時に決まる静的なメモリ範囲です。末尾アドレスは(uint32)&_end_fw_retentionにて参照できます。スリープ時には末尾アドレスをもとに不要なバンクを保持しないように設定してます。
    • ヒープ領域は、 malloc()new 演算子で確保される領域です。一般論として領域補確保・解放を繰り返すと断片化が問題になり、これを意識してアプリケーションの実装を行います。規定ではメモリの割り当てをSRAMのバンク7としています。ただし、バンク7の末尾512バイトはマイコン半導体の仕様で、続く512バイトはTWENETにて予約しています。
      • この領域は App_User_Defs.ld (build ディレクトリ直下に配置する) にHEAP_START=0x04014000;  HEAP_SIZE = 8192 - BANK7_RESERVE; のように記述することで調整できます。
        • HEAP_STARTはヒープの開始アドレス、HEAP_SIZEは確保サイズです。代表的な組み合わせを挙げます。
          • 0x04014000, 8192-BANK7_RESERVE(7KB, BANK6-7)
          • 0x04012000,16384-BANK7_RESERVE(15KB, BANK5-7)
          • 0x04010000,24576-BANK7_RESERVE(23KB, BANK4-7)
          • 0x0,0 (最大限、つまり_end_fw_rententionから 0x04016000-BANK7_RESERVE までの領域をHEAPに設定する)
    • 未使用領域は、SRAM8,9,10 の各16KBです。
    • スタック領域は、SRAM11 の一番最後 (0x0403_0000)から 4096 バイトを規定として確保しています。
      • この領域はApp_User_Defs.ld (build ディレクトリ直下に配置する) に STACK_SIZE = 8192; のように記述すると、サイズを変更することができます。またSTACK_TOP = 0x04024000; のように、末尾アドレスを指定できます。
      • build ディレクトリに作成される mapファイルの _vStackTop __StackLimit を確認してください。
      • この領域はスリープ時に保持されません。

    スリープ時の保持領域の設定

    アプリケーション利用領域やヒープ領域は、TWENETライブラリ内でスリープ時に保持すべきSRAMバンクを適切に設定しています。アプリケーションの設計や実装によっては、保持されないバンクを保持状態にしたい場合もあります。TWENETcmptライブラリ中に定義されるグローバル変数 G_TWENET_POWER_DOWN_RETENTION_CONFIG_ADD() に、追加的に必要なバンクに対応するビットをセットしておきます。

    例えばバンク8,9の32KBを保持したい場合は、TWENET CライブラリのToCoNet_vSleep() や mwx ライブラリのthe_twelite.sleep()呼び出し前に以下を指定します。

    G_TWENET_POWER_DOWN_RETENTION_CONFIG_ADD() = PM_CFG_SRAM_BANK8_RET | PM_CFG_SRAM_BANK9_RET;

    ※ 保持するSRAM領域が増えると、その分スリープ電流が増加します。

    App_User_Defs.ld 設定例

    未指定時は HEAP は 0x0401_5000から0x0401_5FE0、STACKは 0x0402_F000から0x0403_0000 となります。以下に .../build/App_User_Defs.ld の設定例を記載します。

    • HEAPを _end_fw_retention から 0x0401_5FE0 まで最大限確保する。
    HEAP_START = 0;
    HEAP_SIZE = 0;
    
    • RAM6,7にHEAPを確保する (約8KB)。
    HEAP_START = 0x04014000;
    HEAP_SIZE = 8192 - BANK7_RESERVE;
    • HEAPを _end_fw_retention から 0x0401_5000 まで、STACKを0x0401_5000から0x0401_5FE0とする。(0x0402_0000から0x0403_0000のBANK8..11を未使用領域にする)
    HEAP_TOP = 0x04015000;
    HEAP_START = 0;
    HEAP_SIZE = 0;
    STACK_TOP = 0x04015fe0;
    STACK_SIZE = 4096-BANK7_RESERVE;
    

    注:HEAP_STARTHEAP_SIZEがともに0の場合 HEAP_TOP を設定できます。この場合 HEAP_TOP0x0402_0000以上の領域には設定できません。

    • HEAP領域に0x0402_0000から64KB確保しSTACK領域は0x04015fe0以下の領域に移動する。
    HEAP_START = 0x04020000;
    HEAP_SIZE = 0x10000;
    STACK_TOP = 0x04015fe0;
    STACK_SIZE = 4096-BANK7_RESERVE;

    OneTime_Heap.c,h

    TWENETutils には、メモリ破棄を行わず順番にメモリを確保するための One Time Heap を用意しています。未使用領域の利用を容易にするものです。

    #include <OneTimeHeap.h>
    OTHEAP_tsContext scOTHeap;
    
    void setup() {
        uint32 u32bytes;
        void *p;
    
        // 0x0402_0000 から 0x0402_4000 の 16KB 領域を利用する。
        OTHEAP_Init(&scOTHeap, 0x04020000, 0x04024000, NULL);
    
        Serial << crlf << "--- One Time HEAP ---";
        Serial << crlf << format("start %08x", (uint32)OTHEAP_pvGetRegionStart(&scOTHeap));
        Serial << crlf << format("top %08x", (uint32)OTHEAP_pvGetRegionTop(&scOTHeap));
    
        // 100バイト確保する
        u32bytes = 100;
        Serial << crlf;
        Serial << crlf << format("head %08x", (uint32)OTHEAP_pvGetHead(&scOTHeap));
        p = OTHEAP_pvAlloc(&scOTHeap, u32bytes, TRUE);
        		// p=0x0402_0004 (4バイトのヘッダの後が利用可能)
        Serial << crlf << format("alloc %dbytes [%08x->%08x)", u32bytes, (uint32)p, (uint32)p+u32bytes);
        if(p) Serial << crlf << format("next %08x", *(uint32*)((uint32)p - 4));
        		// ヘッダは次のブロックのアドレス (0x0402_0068)
    
        // 10バイト確保する (4バイト境界に配置されるため実際は12バイト)
        u32bytes = 10;
        Serial << crlf;
        Serial << crlf << format("head %08x", (uint32)OTHEAP_pvGetHead(&scOTHeap));
        p = OTHEAP_pvAlloc(&scOTHeap, u32bytes, TRUE);
        		// p=0x0402_006c
        Serial << crlf << format("alloc %dbytes [%08x->%08x)", u32bytes, (uint32)p, (uint32)p+u32bytes);
        if(p) Serial << crlf << format("next %08x", *(uint32*)((uint32)p - 4));
        		// ヘッダは次のブロックのアドレス (0x0402_0078)
    
        // 最後に確保されたブロックを開放する。解放されたブロックのアドレス(p=0x0402_006c)
        p = OTHEAP_pvFreeLastBlock(&scOTHeap);
    }