Flash Memory Control by direct accessing memory address
2. Category
"STM32", "Firmware"
3. Key Concepts
"Flash Memory" STM32 flash memory can be read and write by directly accessing specific memory addresses.
First, the flash memory is unlocked using HAL_FLASH_Unlock(). To write data, the code uses HAL_FLASH_Program() to store data at a specified memory address. Remember that Flash memory cannot be written directly; it must first be erased before writing. To read, data is fetched by directly accessing the memory location using pointer dereferencing. To erase specific sectors of the flash, HAL_FLASHEx_Erase() is used. Finally, the flash memory is locked again using HAL_FLASH_Lock()to prevent accidental modifications.
In below code Flash operations are performed on sector 7, starting from the address 0x8060000.
3. Code Review
HAL_StatusTypeDef flash_write(uint32_t *data32, int size){
uint32_t *mem32 = data32;
/* Unlock to control */HAL_FLASH_Unlock();
uint32_t Address = FLASH_USER_START_ADDR;
printf("size: %d\n", size);
/* Writing data to flash memory */for (int i=0; i < size;)
{
if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, *mem32) == HAL_OK)
{
printf("mem32: %0x\n", *mem32);
mem32++;
Address = Address + 4;
i += 4;
}
else
{
uint32_t errorcode = HAL_FLASH_GetError();
return HAL_ERROR;
}
}
/* Lock flash control register */HAL_FLASH_Lock();
return HAL_OK;
}
This function writes data to flash memory in 32-bit chunks by using HAL_FLASH_Program() to store the data at specified addresses. It starts at the address defined by FLASH_USER_START_ADDR and writes data sequentially, incrementing the address by 4 bytes each time. After writing, it locks the flash memory control register using HAL_FLASH_Lock()to prevent further modifications.
This function reads data from flash memory in 32-bit chunks, starting at the address defined by FLASH_USER_START_ADDR. It continues reading until the specified size is covered, incrementing the address by 4 bytes for each 32-bit word. The data is stored in the provided pointer data32, and the function returns HAL_OK upon successful completion.
This function erases a specified sector of the flash memory by first unlocking the flash control registers using HAL_FLASH_Unlock(). It sets up the FLASH_EraseInitTypeDefstructure to specify the sector number and number of sectors to erase. The erasure is performed using HAL_FLASHEx_Erase(). If the erasure is successful, it locks the flash control register again with HAL_FLASH_Lock().
#define ADDR_FLASH_SECTOR7 ((uint32_t) 0x8060000)#define FLASH_USER_START_ADDR ((uint32_t) 0x8060000)#define USER_DATA_ADDRESS 0x8060004#define FLASH_USER_END_ADDR ((uint32_t) 0x807FFFF)#define FLASH_INIT_STATUS 0xFFFFFFFF // flash 초기 상태#define FLASH_NOT_INIT_STATUS 0xAAAAAAAA // flash 초기 상태가 아니다#define DATA_32 ((uint32_t) 0x00000001)uint32_t flash_read_value=0;
typedefstructstudent
{
uint32_t magic;
int num; // hakbunchar name[20]; // namedouble grade; // hakjum
} t_student;
voidflash_main(){
t_student *read_student;
flash_read_value = *(__IO uint32_t *) USER_DATA_ADDRESS;
if (flash_read_value == FLASH_INIT_STATUS) // 초기에 아무런 데이터도 존재 하지 않을 경우
{
flash_erase();
student.magic=0x55555555;
student.num=1101815;
strncpy((char *)&student.name,"Hong_Gil_Dong", strlen("Hong_Gil_Dong"));
student.grade=4.0;
printf("w magic: %08x\n", student.magic);
printf("w num: %08x\n", student.num);
printf("w name: %s\n", student.name);
printf("w grade: %lf\n", student.grade);
flash_write((uint32_t *) &student, sizeof(student));
}
else// 1번 이상 flash memory에 데이터를 write 한 경우
{
flash_read((uint32_t *) &student, sizeof(student));
printf("r magic: %08x\n", student.magic);
printf("r num: %08x\n", student.num);
printf("r name: %s\n", student.name);
printf("r grade: %lf\n", student.grade);
}
}
This code demonstrates reading and writing data to STM32 flash memory, using a structure t_student to store student information (magic number, student number, name, and grade).
If the program find out that flash memory is empty (flash_read_value == FLASH_INIT_STATUS) initialize the flash sector, sets magic values that indicates that the memory is not empty. (e.g., magic = 0x55555555), and writes them to flash using flash_write(). If it isn't empty(flash_read_value != FLASH_INIT_STATUS), the data is read back and printed. The magic number(first line of flash memory) helps distinguish between uninitialized and initialized memory, acting as a form of a "flag" for initialization.