我有一個結構陣列,需要在編譯時(無 memset)初始化為 0xFF。該陣列將作為程式的一部分在已擦除閃存上寫入。通過將其設定為 0xFF,它會在編程后保持擦除,應用程式可以將其用作持久存盤。我找到了兩種方法,一種是丑陋的,一種是解決方法。我想知道是否還有另一種我還沒有找到的語法方式。丑陋的方法是使用嵌套初始化程式設定結構的每個欄位。但是,它容易出錯并且有點難看。我的解決方法是將結構分配為位元組陣列,然后使用結構型別的指標來訪問資料。線性位元組陣列更容易初始化為非零值。
為了幫助其他人做同樣的事情,我包括了使用的 gcc 屬性和聯結器腳本部分。
示例結構:
struct BlData_t {
uint8_t version[3];
uint8_t reserved;
uint8_t markers[128];
struct AppData_t {
uint8_t version[3];
uint8_t reserved;
uint32_t crc;
} appInfo[512] __attribute__(( packed ));
} __attribute__(( packed ));
使用我知道的最佳方式初始化為 0xFF:
// Allocate the space as an array of bytes
// because it's a simpler syntax to
// initialize to 0xFF.
__attribute__(( section(".bootloader_data") ))
uint8_t bootloaderDataArray[sizeof(struct BlData_t)] = {
[0 ... sizeof(struct BlData_t) - 1] = 0xFF
};
// Use a correctly typed pointer set to the
// array of bytes for actual usage
struct BlData_t *bootloaderData = (struct BlData_t *)&bootloaderDataArray;
除了鏈接描述檔案:
.bootloader_data (NOLOAD):
{
FILL(0xFF); /* Doesn't matter because (NOLOAD) */
. = ALIGN(512); /* start on a 512B page boundary */
KEEP (*(.bootloader_data)) /* .bootloader_data sections */
KEEP (*(.bootloader_data*)) /* .bootloader_data* sections */
. = ALIGN(512); /* end on a 512B boundary to support
runtime erasure, if possible */
} >FLASH
更新:
- 事實證明我問錯了問題。我不知道
(NOLOAD)聯結器部分屬性告訴程式加載器不要將此部分刻錄到閃存中。我接受了這個答案,以幫助其他人認識到我的錯誤,也可能是他們的錯誤。通過甚至不對該部分進行編程,我根本不必擔心初始化。 - 我贊成這些
union答案,因為它們似乎是我提出的問題的一個很好的解決方案。
uj5u.com熱心網友回復:
執行此操作的明智方法是在鏈接描述檔案中找到命令,告訴它首先不要接觸該記憶體。因為你為什么要擦除它只是為了再次填充 0xFF?這只會導致不必要的閃光磨損。
類似這樣的東西:
.bootloader_data (NOLOAD) :
{
. = ALIGN(512);
*(.bootloader_data *)
} >FLASH
uj5u.com熱心網友回復:
我會使用union你的結構和正確大小的陣列,然后初始化陣列成員。
union {
struct BlData_t data;
uint8_t bytes[sizeof(struct BlData_t)];
} data_with_ff = {
.bytes = {
[0 ... sizeof(struct BlData_t) - 1] = 0xff
}
};
然后,您可以訪問您的結構data_with_ff.data,如果您愿意,可以定義一個指標或宏以方便使用。
試試神器
(讀者應注意,...指定初始化程式中的海合會我認為這很好。如果使用沒有它的編譯器,除了.bytes = { 0xff, 0xff, 0xff ... }實際正確的0xffs 數之外,我不知道其他選項;您可能希望使用腳本生成它。)
uj5u.com熱心網友回復:
如果您確實需要在純標準 C 中進行此初始化,則可以將內部結構包裝在匿名聯合 (C11) 中,然后使用宏技巧初始化該結構:
struct BlData_t {
uint8_t version[3];
uint8_t reserved;
uint8_t markers[128];
union {
struct AppData_t {
uint8_t version[3];
uint8_t reserved;
uint32_t crc;
} appInfo[512];
uint8_t raw [512];
};
};
#define INIT_VAL 0xFF, // note the comma
#define INIT_1 INIT_VAL
#define INIT_2 INIT_1 INIT_1
#define INIT_5 INIT_2 INIT_2 INIT_1
#define INIT_10 INIT_5 INIT_5
/* ... you get the idea */
#define INIT_512 INIT_500 INIT_10 INIT_2
const struct BlData_t bld = { .raw = {INIT_512} };
此方法也可以在整個結構的基礎上應用,例如,如果您想要初始化一個結構陣列,其中所有專案在編譯時設定為相同的值。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/456461.html
