A: Write_N_4Byte_flash(FLASH_APP1_ADDR,(uint32_t*)(valid_data+8),len);
B:Write_N_4Byte_flash(FLASH_APP1_ADDR,(uint32_t*)(valid_data+6),len);
A語句存在寫入flash時讀取valid_data數據失敗
B語句則可以正常的讀寫valid_data中數據的數據內容
不知道照成上述問題的原因,本人估計是內存對齊的問題
代碼展示:
uint8_t __NeetErease(uint32_t start_addr ,uint32_t len)
{
//該函數len必須是4的倍數 即 len%4==0
volatile uint32_t i=0;
for(;i<len;i++)
{
if(Read_4Byte_flash(start_addr)!=0xffffffff)
{
break;
}
start_addr+=4;
}
return i==len ? 0:1;
}
uint8_t _Erease_Flash(uint32_t base_addr)
{
uint8_t flag=0;
FLASH_EraseInitTypeDef hflash;
//擦除頁
hflash.TypeErase=FLASH_TYPEERASE_PAGES; //擦除類型
hflash.Banks = FLASH_BANK_1;
hflash.PageAddress = base_addr;//頁基地址
hflash.NbPages = 1;//需要擦除的頁數
uint32_t error=0;
if(HAL_FLASHEx_Erase(&hflash,&error)==HAL_OK)
{
flag=1;
}
return flag;
}
uint8_t Write_One_Page_Data(volatile uint32_t base_addr,volatile uint32_t page_offst,volatile uint32_t *ppdata,volatile uint32_t erease_size)
{
volatile uint8_t flag=0;
volatile uint16_t i=0;
volatile uint16_t cnt;
volatile uint32_t cur_addr=0;
//static uint8_t add=0;
//add++;
//HAL_FLASH_Unlock();
if(__NeetErease(base_addr,erease_size))
{
memset((void*)flash_data,0,STM32_FLASH_PAGE_SIZE);
for(i=0;i<page_offst ;i++)
{
cur_addr = base_addr + i*4;
flash_data[i]=Read_4Byte_flash(cur_addr);
}
_Erease_Flash(base_addr);
//寫入數據
i=page_offst;
cnt = erease_size+page_offst;
for(;i<cnt;i++)
{
flash_data[i]=*ppdata;
//flash_data[i]=i+add;
ppdata++;
}
for(i=0;i<erease_size+page_offst;i++)
{
cur_addr = base_addr+i*4;
if(cur_addr%4==0&& cur_addr >STM32_FLASH_BASE)
{
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,cur_addr,flash_data[i]);
}
}
}
else //不需要擦除就從偏移開始
{
for(i=page_offst;i<erease_size+page_offst;i++)
{
cur_addr = base_addr+i*4;
if(cur_addr%4==0&& cur_addr >STM32_FLASH_BASE)
{
HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD,cur_addr,*ppdata);
ppdata++;
}
}
}
//HAL_FLASH_Lock();
return 1;
}
/*
本函數操作的整型數據 4個字節;flash是以一個字節爲一個地址的
addr 起始地址
data 數據開始地址
surplus 整型數據長度1len=4Byte ;最大爲 STM32_FLASH_PAGE_SIZE/4;
*/
uint8_t Write_N_4Byte_flash(uint32_t addr,uint32_t *data,uint32_t len)
{
volatile uint32_t start_page=0; //起始頁
volatile uint32_t page_size=0; //需要操作頁的大小
volatile uint32_t _offset=0; //頁操作頁碼的起始地址
volatile uint32_t page_offset=0; //頁偏移
volatile uint32_t erease_size=0; //本次操作頁可以使用的剩餘大小
volatile uint32_t base_addr=0; //本次操作頁的基地址
volatile uint32_t surplus=0;
start_page=((uint32_t)addr-STM32_FLASH_BASE)/STM32_FLASH_PAGE_SIZE;
_offset = (((uint32_t)addr-STM32_FLASH_BASE)%STM32_FLASH_PAGE_SIZE)/4;
if(PAGE_INT_SIZE-_offset>=len)
{
page_size=1;
surplus=0;
}
else
{
page_size=1;
surplus = len-(PAGE_INT_SIZE-_offset);
page_size +=surplus/PAGE_INT_SIZE + surplus%PAGE_INT_SIZE>0?1:0;
}
surplus=len;
for(page_offset=0;page_offset<page_size;page_offset++)
{
if(page_offset==0)
{
erease_size =(PAGE_INT_SIZE-_offset)<surplus ? (PAGE_INT_SIZE-_offset):surplus;
base_addr = STM32_FLASH_BASE + start_page*STM32_FLASH_PAGE_SIZE;
surplus = len-erease_size;
}
else
{
_offset=0;
erease_size =surplus>PAGE_INT_SIZE ? PAGE_INT_SIZE:surplus;
base_addr = STM32_FLASH_BASE + (start_page+page_offset)*STM32_FLASH_PAGE_SIZE;
surplus = surplus-erease_size;
}
Write_One_Page_Data(base_addr,_offset,data,erease_size);
data+=erease_size;
//_offset=0;
}
return 1;
}
補充說明,問題產生原因:
上圖中給指針賦值就會出問題,程序就會跑到HardFault_Handler()裏
0x20000a1和0x20000a0 都不是4的倍數
根據map文件的內容可以看見每個變量都是4的倍數的地址,STM32內存4字節對齊