[STM32] Preliminary use of reading and writing internal Flash

Based on stm32f103, used as a personal learning record

There is a FLASH memory inside the STM32 chip, which is mainly used to store codes. In emergency situations, the internal FLASH is often used to store key records;
Insert image description here

The composition of internal FLASH

STM32's internal FLASH contains 主存储器, 系统存储器and选项字节区域

The composition of FLASH inside large-capacity products (excerpted from "STM32F10x Flash Memory Programming Reference Manual"
Insert image description here

main memory

Generally, when we talk about STM32 internal FLASH, we refer to this main memory area, which is the space for storing user applications. The 256K FLASH and 512K FLASH in the chip model description refer to the size of this area.

The main memory is divided into 256 pages, each page is 2KB in size, totaling 512KB. The concept of paging is essentially the sectors of FLASH memory. Like other FLASH, before writing data, it must be erased by page (sector).

Chips with different capacities have different page numbers and page sizes in the main memory of Flash.

System storage area

The system storage area is an area that cannot be accessed by users. The startup code has been solidified when the chip leaves the factory. It is responsible for implementing ISP burning functions such as serial port, USB and CAN.

option byte

The option byte is used to configure FLASH's read and write protection, standby/stop reset, software/hardware watchdog and other functions. This part has a total of 16 bytes. It can be modified by modifying the option control register of FLASH.

Check the spatial distribution of keil projects and determine the free space

The internal FLASH itself stores program data. Unless a certain section of program code is intentionally deleted, the contents of the program space should generally not be modified. Therefore, before using the internal FLASH to store other data, you need to know which spaces have been written with program code, and the sectors storing program code should not be modified in any way.

Through .mapfiles, you can understand which areas the program is stored in.
Open method
After opening the map file, look at the last area of ​​the file and you can see a record starting with "Memory Map of the image".
Insert image description here
This section is the ROM memory distribution image of a certain project. In the STM32 chip, the content of the ROM area refers to the code stored in the internal FLASH.

1. Calculate the loading and execution space of program ROM

In the example
Load Region LR_ROM1: the loading space of the program: Base 0x800 0000, Size: 0x0000 17a8
Execution Region ER_IROM1: the execution space of the program: Base 0x0800 0000, Size: 0x0000 177c

When the chip is first powered on and running, it will load programs and data. For example, it will load from the program's storage area to the program's execution area, and also copy some initialized global variables from ROM to RAM space so that they can be modified when the program is running. The content of the variable. After loading is completed, the program starts executing from the execution area.

In the description of the map file above

The base address (Base) of the loading and execution space is both 0x08000000, which happens to be the first address of the STM32 internal FLASH. It is also the program storage space of the STM32 and is directly the execution space; their sizes (Size) are 0x000017a8 and 0x0000177c respectively. The
execution space The reason why the ROM is relatively small is because some RW-data type variables are copied to the RAM space;
copy RW to RAM

最大空间(Max):0x00080000, which is 512K bytes, the maximum internal FLASH space of this STM32.

Use the big one

When calculating the space occupied by the program, you need to use 加载区域的大小the calculation. In this example, the internal FLASH used by the application is the space area from 0x08000000 to (0x08000000+0x000017a8) address.

2. ROM space distribution table

After the overall description of the loading and execution space, there is a ROM detailed address distribution table, which lists the address Base Addr of each segment in the project (such as functions, constant data) and the occupied space Size. Insert image description here
TypeIt describes the type of the segment;
CODErepresents code;
DATArepresents data;
PADrepresents the padding area between segments, which is invalid content. The PAD area is often used to solve the problem of address alignment.
Insert image description here
Observe the last item in the table. Its base address is 0x0800175c and its size is 0x00000020. It can be seen that the highest address space it occupies is 0x0800177c, which is the same as the highest address 0x0000177c of the execution area, but they are higher than the highest address 0x80017a8 in the load area description. should be small, so we use the size of the loading area as the criterion.

So a total of less than 4k of space is used here, and it can be used for other functions starting from the third page.

General process of writing to internal FLASH

1. Unlock

Since the internal FLASH space mainly stores application programs, which are very critical data, in order to prevent misuse of these contents, the chip will lock the control register FLASH_CR by default after reset. At this time, the FLASH control register is not allowed to be set and cannot be modified. Content in FLASH.
Therefore, before writing data to FLASH, you need to unlock it first. The steps to unlock are as follows:
(1) Write KEY1 = 0x45670123 into the FPEC key register FLASH_KEYR
(2) Then write KEY2 = 0xCDEF89AB into the FPEC key register FLASH_KEYR

#define FLASH_KEY1 ((uint32_t)0x45670123)
#define FLASH_KEY2 ((uint32_t)0xCDEF89AB)

//对 FLASH 控制寄存器解锁,使能访问
void FLASH_Unlock(void)
 {
    
    
 if ((FLASH->CR & FLASH_CR_LOCK) != RESET) {
    
    
	 /* 写入确认验证码 */
	 FLASH->KEYR = FLASH_KEY1;
	 FLASH->KEYR = FLASH_KEY2;
 }}

By the way, how to lock flash

void FLASH_Lock(void)
{
    
    
	FLASH->CR |= FLASH_CR_LOCK;/* 设置 FLASH 寄存器的 LOCK 位 */
}

2. Page erase

Before writing new data, the storage area needs to be erased first. STM32 provides page (sector) erase instructions and entire FLASH erase (batch erase) instructions. The batch erase instructions are only for the main storage area.
Page erase process:
(1) Check the "Busy Register Bit BSY" in the FLASH_SR register to confirm that no Flash operation is currently performed; (
2) In the FLASH_CR register, set the "Activate Page Erase Register Bit PER" to 1 ;
(3) Use the FLASH_AR register to select the page to be erased;
(4) Set the "Start Erase Register Bit STRT" in the FLASH_CR register to 1 to start erasing;
(5) Wait for the BSY bit to be cleared, indicating that the erase Except completed.

/**
* @brief 擦除指定的页
* @param Page_Address: 要擦除的页地址.
* @retval FLASH Status:
可能的返回值: FLASH_BUSY, FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_ErasePage(uint32_t Page_Address)
{
    
    
	 FLASH_Status status = FLASH_COMPLETE;
	 /* 检查参数 */
	 assert_param(IS_FLASH_ADDRESS(Page_Address));
	 /*...此处省略 XL 超大容量芯片的控制部分*/
	 /* 等待上一次操作完成 */
	 status = FLASH_WaitForLastOperation(EraseTimeout);
	 
	 if (status == FLASH_COMPLETE) {
    
    
	 /* 若上次操作完成,则开始页擦除 */
	 FLASH->CR|= CR_PER_Set;
	 FLASH->AR = Page_Address;
	 FLASH->CR|= CR_STRT_Set;
	 
	 /* 等待操作完成 */
	 status = FLASH_WaitForLastOperation(EraseTimeout);
	 
	 /* 复位 PER 位 */
	 FLASH->CR &= CR_PER_Reset;
	 }
 	 return status; /* 返回擦除结果 */
}

3. Write data

After erasing, data can be written. The process of writing data is not just to use pointers to assign values ​​to addresses. Before assigning values, a series of registers need to be configured. The steps are as follows: (1) Check the BSY bit in FLASH_SR to
confirm No other internal Flash operations are currently performed;
(2) Set the "Activate Programming Register Bit PG" in the FLASH_CR register to 1;
(3) Perform data write operations to the specified FLASH memory address, which can only be performed in 16-bit format at a time writing method;
(4) Waiting for the BSY bit to be cleared, indicating that the writing is completed.

/**
* @brief 向指定的地址写入一个字的数据(32 位)
* @param Address: 要写入的地址
* @param Data: 要写入的数据
* @retval FLASH Status:
可能的返回值: FLASH_ERROR_PG,
* FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
*/
FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data)
 {
    
    
 FLASH_Status status = FLASH_COMPLETE;
 __IO uint32_t tmp = 0;
 
 /* 检查参数 */
 assert_param(IS_FLASH_ADDRESS(Address));
 /*...此处省略 XL 超大容量芯片的控制部分*/
 /* Wait for last operation to be completed */
 status = FLASH_WaitForLastOperation(ProgramTimeout);
 
 if (status == FLASH_COMPLETE) {
    
    
 /* 若上次操作完成,则开始页入低 16 位的数据(输入参数的第 1 部分) */
 FLASH->CR |= CR_PG_Set;
 
 *(__IO uint16_t*)Address = (uint16_t)Data;
 /* 等待上一次操作完成 */
 status = FLASH_WaitForLastOperation(ProgramTimeout);
 
 if (status == FLASH_COMPLETE) {
    
    
 /* 若上次操作完成,则开始页入高 16 位的数据(输入参数的第 2 部分) */
 tmp = Address + 2;
 
 *(__IO uint16_t*) tmp = Data >> 16;
 
 /* 等待操作完成 */
 status = FLASH_WaitForLastOperation(ProgramTimeout);
 
 /* 复位 PG 位 */
 FLASH->CR &= CR_PG_Reset;
 } else {
    
    
 /* 复位 PG 位 */
 FLASH->CR &= CR_PG_Reset;
 }

	}
 return status; /* 返回写入结果 */
 }

Guess you like

Origin blog.csdn.net/apythonlearner/article/details/133294285