//G0B0 flash大小 0x08000000-0x0807FFFF 512K(0400 1K)//2k 1頁
//初始化標記數據地址 放最前面 脫機燒寫器可擦除掉
#define CONST_INITMARKDATA_ADDRESS (0x0807D000UL) //2k 1頁
//射頻數據地址
#define CONST_FREQDATA_ADDRESS (0x0807F000UL) //2k 1頁
//本振數據地址
#define CONST_BWLODATA_ADDRESS (0x0807F800UL)//用戶數據標記
#define CONST_USERDATA_ACTIVECOOKIE (0xFEDCCDEF)
========================================================================
__align(8) static uint8_t flashWriteBuf[2048];
__align(8)
: 用于指定存儲在內存中的變量的對齊方式為 8 字節。對齊的目的是為了優化內存訪問,確保變量在內存中的地址是某個值的倍數(這里是 8 字節)。這通常對于某些硬件和特定的數據結構是必要的。static
: 用于指示該變量的存儲持續時間為整個程序的執行期間。在這里,flashWriteBuf
是一個靜態變量,它在程序的整個執行期間都存在,并且其生命周期延伸到整個程序的運行時間。
這行代碼定義了一個靜態的、對齊為 8 字節的、包含 2048 個無符號8位整數的數組 flashWriteBuf
。
=========================================================================
為什么要使用 __align(8),以及對齊方式在內存中的表現是什么樣的?
在C語言中,對齊方式是指變量在內存中的存儲起始位置相對于地址的偏移量。
對齊的主要目的是優化內存訪問速度,特別是對于一些體系結構或硬件,它們可能要求某些數據類型的變量從特定地址開始。
-
訪問速度: 在某些架構中,對齊的數據訪問速度更快。例如,某些處理器可能要求訪問 4 字節整數從4字節對齊的地址開始,否則可能會引發性能損失或錯誤。
-
緩存行: 許多處理器以緩存行為單位加載數據到緩存中。如果變量的首地址是緩存行對齊的,那么對該變量的訪問可能會更加高效。
-
硬件限制: 某些硬件要求特定數據類型從特定對齊方式的地址開始。如果不滿足這些要求,可能會導致硬件異常或性能下降。
在具體的應用場景中,選擇對齊方式通常是為了優化性能或者滿足硬件的要求。然而,過度的對齊可能會導致內存空間的浪費。在實際開發中,對齊的選擇需要根據具體的硬件和性能需求進行權衡。
=========================================================================
1. 實現邏輯:
uint8_t* coreFlashAcquireWriteBuffer(void)
{return flashWriteBuf;
}
該函數返回一個 uint8_t
類型的指針。函數體內只有一條語句,即返回名為 flashWriteBuf
的靜態數組的首地址。
主要目的是獲取可用于寫入的緩沖區。由于返回的是指向 uint8_t
的指針,可以將這個指針用于寫入字節數據。
2. 主要目的和適用場景:
這段代碼的主要目的是提供一個接口,允許外部模塊或函數獲取一個可用于寫入的緩沖區。
這種模式常見于需要進行數據寫入或者數據緩沖的情境,例如將數據寫入到 Flash 存儲器中。
適用場景可能包括需要向 Flash 存儲器寫入數據的任務。通過調用 coreFlashAcquireWriteBuffer
函數,程序可以獲取一個緩沖區,然后將待寫入的數據寫入該緩沖區。
這種設計允許程序靈活地控制數據的寫入,同時提供了一種有效的機制來管理數據的寫入操作。
====================================================================
1. 實現邏輯:
static uint32_t getPage(uint32_t addr)
{uint32_t page = 0;/* Bank 1 */page = (addr - FLASH_BASE) / FLASH_PAGE_SIZE;return page;
}
? 這段代碼定義了一個靜態函數 getPage
,接受一個 uint32_t
類型的地址參數,計算并返回與該地址相關的頁面號(page number)。在這個實現中,頁面號被計算為地址相對于基地址 FLASH_BASE
的偏移量除以頁面大小 FLASH_PAGE_SIZE
。
2. 主要目的和適用場景:
? 主要目的是根據給定的地址計算出相應的頁面號。
? 在嵌入式系統中,Flash存儲器通常分為多個頁面,每個頁面存儲一定量的數據。
? 獲取地址對應的頁面號可以用于確定數據在Flash中的位置。
? 適用場景可能包括在程序中管理Flash存儲器的情況,比如需要存儲和檢索數據到Flash中的特定頁面。通過調用 getPage
函數,程序可以獲得給定地址所在的頁面號,然后使用這個頁面號進行相應的操作,例如擦除或寫入數據。
總體而言,這個函數是一個用于獲取地址對應頁面號的工具函數,可以用于在嵌入式系統中管理Flash存儲器中的數據。
========================================================================
1. 實現邏輯:
int32_t coreFlashWrite(void* dstAddr, const void* srcAddr, const uint32_t size)
{//...(變量定義和初始化)//初始化FLASH_EraseInitTypeDefFLASH_EraseInitTypeDef eraseInitStruct = {0x00};int32_t ret = ERR_FLASHOP_OK; // 返回值//判斷入參正確if (!srcAddr || !dstAddr || 0 == size){return ERR_FLASHOP_PARAM_INVAL;}if (0 != ((uint32_t)srcAddr & 0x00000007)){return ERR_FLASHOP_SRCADDR_UNALIGN;}if (0 != ((uint32_t)dstAddr & 0x00000007)){return ERR_FLASHOP_DSTADDR_UNALIGN;}//獲取要擦除的第一頁firstPage = getPage((uint32_t)dstAddr);//獲取要從第一頁擦除的頁數nbOfPages = size / FLASH_PAGE_SIZE + (size % FLASH_PAGE_SIZE ? 1 : 0);eraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES;eraseInitStruct.Page = firstPage; // 擦除起始頁eraseInitStruct.NbPages = nbOfPages; // 擦除頁數HAL_FLASH_Unlock(); // Flash解鎖__disable_irq(); // 擦除前需要關閉中斷if (HAL_FLASHEx_Erase(&eraseInitStruct, &pageError) != HAL_OK){__enable_irq();ret = -ERR_FLASHOP_FAIL_ERASE;goto exit;}__enable_irq();//開始寫入FlashflashAddress = (uint32_t)dstAddr;nWriteAll = size;while (nHasWrite < nWriteAll){// 以64位為單位寫入數據srcDW = *(uint64_t*)((uint32_t)srcAddr + nHasWrite);if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flashAddress, srcDW) == HAL_OK){flashAddress += 8;nHasWrite += 8;}else{ret = ERR_FLASHOP_FAIL_PROG;goto exit;}}exit:HAL_FLASH_Lock(); // Flash加鎖return ret;
}
2. 主要目的和適用場景:
? 這段代碼的主要目的是實現Flash存儲器的寫入操作。該函數接受目標地址 dstAddr
、源地址 srcAddr
和寫入大小 size
作為參數,首先擦除目標地址所在的Flash頁面,然后將數據從源地址寫入到目標地址。
? 適用場景可能涉及到需要在嵌入式系統中進行Flash存儲器的寫入操作,例如在固件更新或配置保存等場景。
3. 使用的關鍵字和修飾符:
static
: 該函數沒有使用static
關鍵字,因此在其他文件中可以訪問。uint32_t
,void
,const
: 這些是數據類型,用于聲明參數和變量的類型。FLASH_EraseInitTypeDef
: 這是一個結構體類型,用于配置Flash擦除的初始化參數。HAL_FLASH_Unlock()
,HAL_FLASH_Lock()
: 這些是由HAL(Hardware Abstraction Layer)提供的函數,用于解鎖和鎖定Flash。
總體而言,這是一個用于在嵌入式系統中進行Flash存儲器寫入的函數,包括擦除和寫入兩個步驟。============================================================================
1. 實現邏輯:
bool initMarkDataIsActive(void)
{const volatile initMarkDataFlash_t* rawPtr = (const volatile initMarkDataFlash_t*)CONST_INITMARKDATA_ADDRESS;return (rawPtr->active == CONST_USERDATA_ACTIVECOOKIE);
}
這段代碼定義了一個函數 initMarkDataIsActive
,該函數返回一個布爾值。函數內部首先聲明了一個指向 initMarkDataFlash_t
結構體類型的 volatile
常量指針 rawPtr
,然后將其初始化為指向一個特定地址 CONST_INITMARKDATA_ADDRESS
。
函數最后通過比較 rawPtr->active
和 CONST_USERDATA_ACTIVECOOKIE
的值來確定初始化標記數據是否處于激活狀態。
2. 主要目的和適用場景:
? 主要目的是檢查初始化標記數據是否處于激活狀態。在嵌入式系統中,可能會有一些標記數據用于指示系統的初始化狀態,這個函數就是用于檢查這些標記數據是否處于激活狀態。
? 適用場景可能包括在系統啟動時檢查某些初始化數據,以確保系統處于已初始化的狀態。
3. 使用的關鍵字和修飾符:
const
,volatile
: 這些關鍵字用于修飾指針rawPtr
,指明該指針指向的數據是常量且易變的,這通常用于防止編譯器進行一些優化,確保每次訪問都會從內存中讀取最新的值。
總體而言,這個函數用于檢查初始化標記數據是否處于激活狀態,返回一個布爾值表示檢查結果。
=========================================================================
1. 實現邏輯:
void initMarkDataReadFlash(void)
{const volatile initMarkDataFlash_t *rawPtr = (const volatile initMarkDataFlash_t*)CONST_INITMARKDATA_ADDRESS;if (initMarkDataIsActive()){memcpy(&initMarkDataFlash, (void*)rawPtr, sizeof(initMarkDataFlash_t));}
}
函數內部首先聲明了一個指向 initMarkDataFlash_t
結構體類型的 volatile
常量指針 rawPtr
,然后將其初始化為指向一個特定地址 CONST_INITMARKDATA_ADDRESS
。
接著,通過調用 initMarkDataIsActive
函數檢查初始化標記數據是否處于激活狀態。如果激活,那么通過 memcpy
函數將 Flash 中的數據復制到一個全局變量 initMarkDataFlash
中。
2. 主要目的和適用場景:
? 主要目的是在系統啟動時從 Flash 中讀取初始化標記數據。在嵌入式系統中,初始化標記數據可能包含一些配置信息或者系統狀態,該函數的目的是將這些數據讀取到內存中,以便系統可以使用這些數據進行初始化。
? 適用場景可能包括在系統啟動時加載先前保存的配置或狀態信息,以確保系統處于正確的狀態。
總體而言,這個函數用于從 Flash 中讀取初始化標記數據,如果數據處于激活狀態,則將其復制到全局變量中。
=======================================================================
1. 實現邏輯:
int32_t initMarkDataSyncFlash(void)
{int32_t ret = 0;//用戶數據寫入ret = coreFlashWrite((void*)CONST_INITMARKDATA_ADDRESS, (void*)&initMarkDataFlash, sizeof(initMarkDataFlash_t));return ret;
}
函數內部首先聲明了一個整數變量 ret
,用于存儲函數執行的結果。
接著,通過調用 coreFlashWrite
函數將全局變量 initMarkDataFlash
中的數據寫入到 Flash 中的指定地址 CONST_INITMARKDATA_ADDRESS
。
最后,函數返回執行的結果。
2. 主要目的和適用場景:
? 主要目的是將全局變量 initMarkDataFlash
中的數據同步到 Flash 中的指定地址。在嵌入式系統中,這可能用于將配置或狀態信息保存到 Flash 中,以便在系統重新啟動時恢復狀態。
? 適用場景可能包括在系統運行時修改了一些配置或狀態信息,希望將這些更改保存到持久性存儲中。
總體而言,這個函數用于將全局變量中的數據寫入到 Flash 中的指定地址,返回一個表示執行結果的整數值。