2017-01-03 12 views
0

は、私たちはSTM32F103リンカスクリプトを見てみましょう:リンクとメモリの問題に

/* Entry Point */ 
ENTRY(Reset_Handler) 

/* Highest address of the user mode stack */ 
_estack = 0x20005000; /* End of 20K RAM */ 

/* Generate a link error if heap and stack don't fit into RAM */ 
_Min_Heap_Size = 0;  /* Required amount of heap */ 
_Min_Stack_Size = 0x100; /* Required amount of stack */ 

/* Specify the memory areas */ 
MEMORY 
{ 
    FLASH (rx)  : ORIGIN = 0x08000000, LENGTH = 128K 
    RAM (xrw)  : ORIGIN = 0x20000000, LENGTH = 20K 
    MEMORY_B1 (rx) : ORIGIN = 0x60000000, LENGTH = 0K 
} 

/* Define output sections */ 
SECTIONS 
{ 
    /* The startup code goes first into FLASH */ 
    .isr_vector : 
    { 
    . = ALIGN(4); 
    KEEP(*(.isr_vector)) /* Startup code */ 
    . = ALIGN(4); 
    } >FLASH 

    /* The program code and other data goes into FLASH */ 
    .text : 
    { 
    . = ALIGN(4); 
    *(.text)   /* .text sections (code) */ 
    *(.text*)   /* .text* sections (code) */ 
    *(.rodata)   /* .rodata sections (constants, strings, etc.) */ 
    *(.rodata*)  /* .rodata* sections (constants, strings, etc.) */ 
    *(.glue_7)   /* Glue arm to thumb code */ 
    *(.glue_7t)  /* Glue thumb to arm code */ 

    KEEP (*(.init)) 
    KEEP (*(.fini)) 

    . = ALIGN(4); 
    _etext = .;  /* Define a global symbols at end of code */ 
    } >FLASH 


    .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH 
    .ARM : { 
    __exidx_start = .; 
     *(.ARM.exidx*) 
     __exidx_end = .; 
    } >FLASH 

    .ARM.attributes : { *(.ARM.attributes) } > FLASH 

    .preinit_array  : 
    { 
    PROVIDE_HIDDEN (__preinit_array_start = .); 
    KEEP (*(.preinit_array*)) 
    PROVIDE_HIDDEN (__preinit_array_end = .); 
    } >FLASH 
    .init_array : 
    { 
    PROVIDE_HIDDEN (__init_array_start = .); 
    KEEP (*(SORT(.init_array.*))) 
    KEEP (*(.init_array*)) 
    PROVIDE_HIDDEN (__init_array_end = .); 
    } >FLASH 
    .fini_array : 
    { 
    PROVIDE_HIDDEN (__fini_array_start = .); 
    KEEP (*(.fini_array*)) 
    KEEP (*(SORT(.fini_array.*))) 
    PROVIDE_HIDDEN (__fini_array_end = .); 
    } >FLASH 

    /* Used by the startup to initialize data */ 
    _sidata = .; 

    /* Initialized data sections goes into RAM, load LMA copy after code */ 
    .data : AT (_sidata) 
    { 
    . = ALIGN(4); 
    _sdata = .;  /* Create a global symbol at data start */ 
    *(.data)   /* .data sections */ 
    *(.data*)   /* .data* sections */ 

    . = ALIGN(4); 
    _edata = .;  /* Define a global symbol at data end */ 
    } >RAM 

    /* Uninitialized data section */ 
    . = ALIGN(4); 
    .bss : 
    { 
    /* This is used by the startup in order to initialize the .bss secion */ 
    _sbss = .;   /* Define a global symbol at BSS start */ 
    __bss_start__ = _sbss; 
    *(.bss) 
    *(.bss*) 
    *(COMMON) 

    . = ALIGN(4); 
    _ebss = .;   /* Define a global symbol at BSS end */ 
    __bss_end__ = _ebss; 
    } >RAM 

    PROVIDE (end = _ebss); 
    PROVIDE (_end = _ebss); 

    /* User_heap_stack section, used to check that there is enough RAM left */ 
    ._user_heap_stack : 
    { 
    . = ALIGN(4); 
    . = . + _Min_Heap_Size; 
    . = . + _Min_Stack_Size; 
    . = ALIGN(4); 
    } >RAM 

    /* MEMORY_bank1 section, code must be located here explicitly   */ 
    /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */ 
    .memory_b1_text : 
    { 
    *(.mb1text)  /* .mb1text sections (code) */ 
    *(.mb1text*)  /* .mb1text* sections (code) */ 
    *(.mb1rodata)  /* read-only data (constants) */ 
    *(.mb1rodata*) 
    } >MEMORY_B1 

    /* Remove information from the standard libraries */ 
    /DISCARD/ : 
    { 
    libc.a (*) 
    libm.a (*) 
    libgcc.a (*) 
    } 
} 

私は、プログラムはいくつかのベクトルに格納されたアドレスを呼び出す必要があるので、もしISRベクターは、フラッシュに配置されていることがわかりますフラッシュメモリから読み込みます。

最初の質問:ハードウェアはどのようにRAMとフラッシュからの読み取りに違いはありませんか?そして、なぜ私はコードでフラッシュメモリに書き込むか、またはフラッシュメモリから読み出すために特別なレジスタが必要であり、そのアドレスから明示的に書き込むことも読み出すこともできないのですか?

第2の質問は、RAMよりもフラッシュから読み込むのがどれくらい遅いのですか?そして、私のコードでどのような機能が最も使われているのか分かっていれば、RAMセクションに移動させて実行を高速化することができますか?私はこのスクリプトの中でMEMORY_B1が特にこの目的のために作られたと信じています。

第3質問:MEMORY_B1に何かを配置するには、長さが0の場合はどうすればよいですか?

最後の質問:フラッシュメモリに追加のセクションを作成すると、単純な仮想メモリのアナログを作成できますか?私はこの質問への答えが最初のものに依存すると思います。

答えて

2
  1. 両方のメモリ(実際には他のもの)が共通アドレス空間にマップされているため、ハードウェアは気にしません。しかし、これはフラッシュメモリを簡単に書き込んでRAMとして扱うことを意味するわけではありません。これは、速度が遅く、メモリに急速に損傷を与える可能性があります(通常、書き込み耐性は100kサイクルです)。さらに、フルページ(いくつかのSTM32チップでは128   kBほどの大きさになる可能性があります)でしか消去できないため、RAMの代替として使用するのは問題になります。

  2. 速度の差はごくわずかです。 RAMは異なるバス(データ用)に接続されており、コード実行にはより遅い「相互接続」を使用する必要があるため、ARM Cortex-MマイクロコントローラのRAMからコードを実行するのは期待以上に遅くなります。

  3. できません。そこに何かを配置したい場合は、メモリのサイズを増やす必要があります(また、「通常のRAM」のサイズは小さくなります)。

  4. 一般的に、あなたはそれを行うことができますが、それは非常に遅くなると、すぐにフラッシュを損傷します。

0

1/2。はSTM32F1にありません。 100Mhz以上のコア速度でのみ、フラッシュプリフェッチとキャッシュミスが発生します。このチップでもキャッシュとプリフェッチがあります。 このコアでは、特別な場合にRAMにベクタテーブルを置くと、わずかな利益しか得られない可能性があります。

ただし、アクセスに適用されるハードウェアの制限は、の幅である可能性があります。しかし、このフラッシュはその影響を受けません。

3.はい、あなたは確かにすることができます。ファイルシステムを置くことができます。しかし、フラッシュを確実に書き込むことができる温度範囲は限られています。また、1つのフラッシュバンクしかないので、消去/フラッシュが成功するまで、すべてのアクティビティが停止します。コードがRAMから実行されている場合を除きます。 2つの追加の注意点は、フラッシュプログラミング/消去には数ミリ秒かかることがあることです。ページ消去にはそれぞれ2kBを考慮する必要がありますが、すべてのフラッシュコントローラで行う必要があります。

余分なRAMが必要な場合は、ボードにSPI FRAMを取り付けてください。