セクションに分割されたフラッシュメモリを備えた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++ コンパイラに関する一般的な質問です。