Только что чтение стирание запись внутренней памяти контроллера работала из кода самой программы и опять перестала. Знакома ситуация?
Чтение памяти
Вроде все просто на первый взгляд :
volatile uint32_t *innerFlashAddr = 0x8010000;
uint32_t uu = *(__IO uint32_t*) (innerFlashAddr);
printf("%0.8X : %0.8X \n", innerFlashAddr , uu);
//08010000 : FFFFFFFF
volatile не дает компилятору оптимизировать код , смещая переменную куда-то... Это полезная для нас полезная инструкция.
static говорит , что функцию размещать в SRAM , а не во FLASH, тоже может пригодится.
allign говорит компоновщику выравнивать объект памяти (переменную, массив, функцию) на адрес кратный (2,4,8 ... )
__disable_irq(); __enable_irq (); - запрещает/разрешает прерывания , тоже может пригодится.
Если вылетает HardWare_Fault просто смотрите какой адрес вы читаете / пишете . Это очень частая ошибка , когда глаз замыливается.
Берем USB_DFU пример от st.com И ОБРАЩАЕМ ВНИМАНИЕ ,что все функции из которых идет работа с FLASH памятью контроллера помечены static и размещаются они в SRAM памяти , а не во FLASH.
Стирание сектора контроллера STM32F205VG перед записью
Важно разблокировать сначала FLASH память HAL_FLASH_Unlock. А потом в конце естественно заблокировать HAL_FLASH_Lock(). Если стирание не пройдет результат вернется !=HAL_OK .
static HAL_StatusTypeDef eraseSector(uint32_t sector)
{
HAL_FLASH_Unlock();
FLASH_EraseInitTypeDef EraseInitStruct= {0};
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;//TYPEERASE_PAGES;//;
EraseInitStruct.Sector = sector; //FLASH_SECTOR_4;
EraseInitStruct.NbSectors = 1;
EraseInitStruct.Banks = FLASH_BANK_1;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
uint32_t SectorError=0;
HAL_StatusTypeDef res = HAL_OK;
res= HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);
//res= HAL_FLASHEx_Erase_IT(&EraseInitStruct);
if(res !=HAL_OK)
{
printf("HAL_FLASHEx_Erase != HAL_OK=%d SectorError=%x\n",res,SectorError);
printf("HAL_FLASH_Lock = %d\n",HAL_FLASH_Lock());
return;
}
else
printf("HAL_FLASHEx_Erase OK %d\n",sector);
HAL_FLASH_Lock();
return res;
}
Запись в память
Лучше внимательно изучить пример от STM DFU. И делаем также :
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
if(HAL_FLASH_Unlock() == HAL_OK ) //& HAL_FLASH_OB_Unlock() == HAL_OK)
{
for(volatile uint32_t ii=0; ii < len; ii += 4)
{
volatile uint32_t dest = pDestFlashAddress + ii;
volatile uint32_t src = pSrcSRAM + ii;
res = HAL_FLASH_Program( FLASH_TYPEPROGRAM_WORD, (uint32_t) (dest), *(uint32_t*)(src));
if( res != HAL_OK)
{
printf("HAL_FLASH_Program != HAL_OK=%d\n",res);
printf("HAL_FLASH_GetError()=%x\n",HAL_FLASH_GetError());
printf("dest=%0.8p *dest=%0.8x\n",(uint32_t)dest, *(uint32_t*)(dest));
printf("src=%0.8p *src=%0.8x \n\n" , (uint32_t) src , *(uint32_t*)src);
goto lock;
}
if(*(uint32_t *)(src ) != *(uint32_t*)(dest))
{
printf("ERROR HAL_FLASH_Program ERROR %x != %x \n",*(uint32_t *)(src ),*(uint32_t*)(dest));
printf("dest=%0.8x *dest=%0.8x\n",(uint32_t)dest, *(uint32_t*)(dest));
printf("src=%0.8X *src=%0.8x \n\n" , (uint32_t) src , *(uint32_t*)src);
goto lock;
}
//printf("%0.8X : dest=%0.8x %0.8X : src=%0.8x \n",(uint32_t)dest, *(uint32_t*)(dest),(uint32_t)src,*(uint32_t *)(src ));
}
}
else
printf(" writeBytesToInnerFlashHAL_FLASH_Unlock != HAL_OK=%d\n",res);
lock:
res = HAL_FLASH_Lock();
Это точно рабочий код.
Адрес записи pDestFlashAddress обязательно надо выравнивать на 4 [ __attribute__((aligned(4))) ].