скрытое меню

вутренняя Flash STM32

Только что чтение стирание запись внутренней памяти контроллера работала из кода самой программы и опять перестала. Знакома ситуация?

Чтение памяти

Вроде все просто на первый взгляд :

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))) ].