Nucleo STM32f411re 보드 내부 플래시 메모리 지우고 쓰고 읽기 포스팅을 정리하고자 한다.
STM32 CHIP 플래시 메모리 구조
- Main memory : 주요 플래시 메모리 공간으로 사용된다.
- System memory : CPU가 부팅할 때 사용하는 메모리 공간으로 Boot mode에 따라 사용 유무가 결정되는 공간으로 Main memory에 펌웨어 다운로드, Boot mode 중 펌웨어 업데이트, UART1을 통해 Flash loader 툴 사용이 가능함
- OTP(One Time Programmable) 공간 : 한번 쓸 수 있는 사용자 메모리 공간으로 사용(mac주소 등)
- Option bytes : Watchdog 설정, Read/Write 보호와 같은 시스템관련 설정을 담당하는 저장소
필독
1.쓰기작업을 하기 위해서는 메모리 잠금 상태를 풀어야 쓰기 작업이 가능하다.
2. 쓰기 작업 전에 반드시 지우기 작업을 먼저 해야 한다.
읽기
모든 32비트 데이터 읽기 작업은 플래시의 데이터에 접근할 수 있다.
강제로 주소를 32비트 정수 포인터로 변환한 다음 포인터가 가리키는 주소 값을 취하여 주소의 32비트 데이터를 얻는다.
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base address of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base address of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base address of Sector 2, 16 Kbytes */
#define FLASH_USER_START_ADDR ADDR_FLASH_SECTOR_0 /* Start @ of user Flash area */
//읽을 데이터 주소
uint32_t Address = FLASH_USER_START_ADDR
//데이터 읽기
uintt32_t *RxBuf = *(__IO uint32_t*)Address;
2. 지우기
플래시 메모리는 섹터 단위로 지우기 작업한다.
static FLASH_EraseInitTypeDef EraseInitStruct;
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS; //섹터 단위 지우기
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3; //전압 단위
EraseInitStruct.Sector = FirstSector;
EraseInitStruct.NbSectors = NbOfSectors;
if (HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)
{
/* Infinite loop */
while (1)
{
// error
}
}
3.쓰기
리셋 후 플래시 컨트롤러 레지스터(flash_cr)에 쓰기가 허용되지 않으면
전기적 이유로 플래시 메모리를 다른 동작으로부터 보호한다.
따라서 플래시 메모리 잠금을 해제 한 후 쓰기 작업을 진행할 수 있다.
HAL_FLASH_UnLock(); //메모리 잠금 해제
Address = FLASH_USER_START_ADDR;
while (Address < FLASH_USER_END_ADDR)
{
if (HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, DATA_32) == HAL_OK)
{
Address = Address + 4;
}
else
{
while (1)
{
//error
}
}
}
HAL_FLASH_Lock(); //메모리 잠금
예제
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
/* USER CODE END PTD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
#define ADDR_FLASH_SECTOR_0 ((uint32_t)0x08000000) /* Base address of Sector 0, 16 Kbytes */
#define ADDR_FLASH_SECTOR_1 ((uint32_t)0x08004000) /* Base address of Sector 1, 16 Kbytes */
#define ADDR_FLASH_SECTOR_2 ((uint32_t)0x08008000) /* Base address of Sector 2, 16 Kbytes */
#define ADDR_FLASH_SECTOR_3 ((uint32_t)0x0800C000) /* Base address of Sector 3, 16 Kbytes */
#define ADDR_FLASH_SECTOR_4 ((uint32_t)0x08010000) /* Base address of Sector 4, 64 Kbytes */
#define ADDR_FLASH_SECTOR_5 ((uint32_t)0x08020000) /* Base address of Sector 5, 128 Kbytes */
#define ADDR_FLASH_SECTOR_6 ((uint32_t)0x08040000) /* Base address of Sector 6, 128 Kbytes */
#define ADDR_FLASH_SECTOR_7 ((uint32_t)0x08060000) /* Base address of Sector 7, 128 Kbytes */
#define FLASH_USER_START_ADDR ADDR_FLASH_SECTOR_2 /* Start @ of user Flash area */
#define FLASH_USER_END_ADDR ADDR_FLASH_SECTOR_7 + GetSectorSize(ADDR_FLASH_SECTOR_7) -1 /* End @ of user Flash area : sector start address + sector size -1 */
#define DATA_32 ((uint32_t)0x12345678)
#define DATA2_32 ((uint32_t)0x87654321)
#define USER_DATA1 (FLASH_USER_START_ADDR)
#define USER_DATA2 (FLASH_USER_START_ADDR + 4)
#define USER_DATA3 (FLASH_USER_START_ADDR + 8)
#define USER_DATA4 (FLASH_USER_START_ADDR + 12)
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
/* USER CODE BEGIN PV */
uint32_t FirstSector = 0, NbOfSectors = 0;
uint32_t Address = 0, SECTORError = 0;
__IO uint32_t data32 = 0 , MemoryProgramStatus = 0;
static FLASH_EraseInitTypeDef EraseInitStruct;
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
static void MX_GPIO_Init(void);
static void MX_USART2_UART_Init(void);
static void MX_USART1_UART_Init(void);
/* USER CODE BEGIN PFP */
static uint32_t GetSector(uint32_t Address);
static uint32_t GetSectorSize(uint32_t Sector);
int __io_putchar(int ch){
HAL_UART_Transmit(&huart1, &ch, 1, 1000);
return ch;
}
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/**
* @brief The application entry point.
* @retval int
*/
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_USART2_UART_Init();
MX_USART1_UART_Init();
/* USER CODE BEGIN 2 */
HAL_FLASH_Unlock();
/* Erase the user Flash area
(area defined by FLASH_USER_START_ADDR and FLASH_USER_END_ADDR) ***********/
/* Get the 1st sector to erase */
FirstSector = GetSector(FLASH_USER_START_ADDR);
/* Get the number of sector to erase from 1st sector*/
NbOfSectors = GetSector(FLASH_USER_END_ADDR) - FirstSector + 1;
/* Fill EraseInit structure*/
EraseInitStruct.TypeErase = FLASH_TYPEERASE_SECTORS;
EraseInitStruct.VoltageRange = FLASH_VOLTAGE_RANGE_3;
EraseInitStruct.Sector = FirstSector;
EraseInitStruct.NbSectors = NbOfSectors;
if((HAL_FLASHEx_Erase(&EraseInitStruct, &SECTORError) != HAL_OK)){
printf("Write Error\r\n");
while (1)
{
}
}
if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, USER_DATA1, DATA_32) != HAL_OK)
{
while (1)
{
}
}
if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, USER_DATA2, DATA2_32) != HAL_OK)
{
printf("Write Error\r\n");
while (1)
{
}
}
if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, USER_DATA3, DATA_32) != HAL_OK)
{
printf("Write Error\r\n");
while (1)
{
}
}
if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, USER_DATA4, DATA2_32) != HAL_OK)
{
printf("Write Error\r\n");
while (1)
{
}
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
printf("1.Addr = %x , Data = %d\r\n", USER_DATA1, *(__IO uint32_t *)USER_DATA1);
printf("2.Addr = %x , Data = %d\r\n", USER_DATA2, *(__IO uint32_t *)USER_DATA2);
printf("3.Addr = %x , Data = %d\r\n", USER_DATA3, *(__IO uint32_t *)USER_DATA3);
printf("4.Addr = %x , Data = %d\r\n", USER_DATA4, *(__IO uint32_t *)USER_DATA4);
HAL_Delay(1000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE BEGIN 3 */
HAL_FLASH_Unlock();
/* USER CODE END 3 */
}
/* USER CODE BEGIN 4 */
static uint32_t GetSector(uint32_t Address)
{
uint32_t sector = 0;
if((Address < ADDR_FLASH_SECTOR_1) && (Address >= ADDR_FLASH_SECTOR_0))
{
sector = FLASH_SECTOR_0;
}
else if((Address < ADDR_FLASH_SECTOR_2) && (Address >= ADDR_FLASH_SECTOR_1))
{
sector = FLASH_SECTOR_1;
}
else if((Address < ADDR_FLASH_SECTOR_3) && (Address >= ADDR_FLASH_SECTOR_2))
{
sector = FLASH_SECTOR_2;
}
else if((Address < ADDR_FLASH_SECTOR_4) && (Address >= ADDR_FLASH_SECTOR_3))
{
sector = FLASH_SECTOR_3;
}
else if((Address < ADDR_FLASH_SECTOR_5) && (Address >= ADDR_FLASH_SECTOR_4))
{
sector = FLASH_SECTOR_4;
}
else if((Address < ADDR_FLASH_SECTOR_6) && (Address >= ADDR_FLASH_SECTOR_5))
{
sector = FLASH_SECTOR_5;
}
else if((Address < ADDR_FLASH_SECTOR_7) && (Address >= ADDR_FLASH_SECTOR_6))
{
sector = FLASH_SECTOR_6;
}
else /* (Address < FLASH_END_ADDR) && (Address >= ADDR_FLASH_SECTOR_7) */
{
sector = FLASH_SECTOR_7;
}
return sector;
}
/**
* @brief Gets sector Size
* @param None
* @retval The size of a given sector
*/
static uint32_t GetSectorSize(uint32_t Sector)
{
uint32_t sectorsize = 0x00;
if((Sector == FLASH_SECTOR_0) || (Sector == FLASH_SECTOR_1) || (Sector == FLASH_SECTOR_2) || (Sector == FLASH_SECTOR_3))
{
sectorsize = 16 * 1024;
}
else if(Sector == FLASH_SECTOR_4)
{
sectorsize = 64 * 1024;
}
else
{
sectorsize = 128 * 1024;
}
return sectorsize;
}
/* USER CODE END 4 */
참고
'Stm32 > 실제 구동(stm32cubeide)' 카테고리의 다른 글
ADC Multi Channel - Joy Stick (0) | 2024.07.10 |
---|---|
UART 실습[2] (0) | 2024.06.30 |
Timer Interrupt (0) | 2024.06.18 |
UART (Polling, Interrupt , DMA) [HAL-DRIVER 이용] (0) | 2024.05.08 |
[1]GPIO 입출력 레지스터 직접 제어 (0) | 2024.05.02 |