3

セクションに分割されたフラッシュメモリを備えたMCUがあります(いつものように)。リンカは、.struct_init、.struct_init_const、.struct_not_init セクションを、フラッシュ メモリ section20 に属するアドレスに配置します。リンカー スクリプトにハードコードされています。

次のテスト コードを検討してください: test.h

typedef struct
{
    int val1;
    int val2;
} mystruct_t;

test.cpp

#include "test.h"

// each variable is placed in dedicated section
// sections are placed in flash section20
// linker exports symbols with address of eaach section
__attribute__((section(".struct_init")))
mystruct_t struct_init = {
    .val1 = 1,.val2 = 2};

__attribute__((section(".struct_init_const")))
extern const mystruct_t struct_init_const = {
    .val1 = 1, .val2 = 2};

__attribute__((section(".struct_not_init")))
mystruct_t struct_not_init;

main.cpp

#include <stdint.h>

// This symbols exported by linker
// contains addresses of corresponding sections
extern uintptr_t LNK_STRUCT_INIT_ADDR;
extern uintptr_t LNK_STRUCT_INIT_CONST_ADDR;
extern uintptr_t LNK_STRUCT_NOT_INIT_ADDR;

// Pointers for indirect access to data
mystruct_t* struct_init_ptr = (mystruct_t*)LNK_STRUCT_INIT_ADDR;
const mystruct_t* struct_init_const_ptr = (const mystruct_t*)LNK_STRUCT_INIT_CONST_ADDR;
mystruct_t* struct_not_init_ptr = (mystruct_t*)LNK_STRUCT_NOT_INIT_ADDR;

// Extern variables declarations for DIRECT access data
extern mystruct_t struct_init;
extern const mystruct_t struct_init_const;
extern mystruct_t struct_not_init;

// This is some variables representing config values
// They can be more complex objects(classes) with internal state and logic..
int param1_direct;
int param1_init_const_direct;
int param1_not_init_direct;

int param1_indirect;
int param2_init_const_indirect;
int param1_not_init_indirect;

int main(void)
{
    // local variables init with direct access
    int param1_direct_local = struct_init.val1;
    int param1_init_const_direct_local = struct_init_const.val1;
    int param1_not_init_direct_local = struct_not_init.val1;

    // local variables init with indirect access
    int param1_indirect_local = struct_init_ptr->val1;
    int param2_init_const_indirect_local = struct_init_const_ptr->val1;
    int param1_not_init_indirect_local = struct_not_init_ptr->val1;

    //global variables init direct
    param1_direct = struct_init.val1;
    param1_init_const_direct = struct_init_const.val1;
    param1_not_init_direct = struct_not_init.val1;
    //global variables init indirect
    param1_indirect = struct_init_ptr->val1;
    param2_init_const_indirect = struct_init_const_ptr->val1;
    param1_not_init_indirect = struct_not_init_ptr->val1;

    while(1){
        // use all variables we init above
        // usage of variables may also occure in some functions or methods
        // directly or indirectly called from this loop
    }
}

param1_ 変数の初期化により、フラッシュからデータがフェッチされることを確認したいと思います。フラッシュセクション20のデータは、ブートローダーを使用して変更できるため(メインファームウェアが実行されていない瞬間)。

問題は、LTO(およびその他の最適化)がフラッシュからのフェッチを破棄し、初期化のためにリンク時に既知であるため、既知の値を単に置き換えることができるかということです。どのアプローチが良いですか?LTO が値を代用できる場合、初期化は避けるべきですか? volatile が役立つことはわかっていますが、この状況で本当に必要なのでしょうか?

コード例は、データへのアクセスと初期化のさまざまなアプローチを示しています。コンパイラは何も置き換えることができないため、not_init バージョンが最適なようです。しかし、いくつかのデフォルト パラメータを用意しておくことをお勧めします。そのため、使用できる場合は init バージョンを使用することをお勧めします。

どのようなアプローチを選択する必要がありますか?

現在、GCC 4.9.3 を使用していますが、これは C/C++ コンパイラに関する一般的な質問です。

4

1 に答える 1