Today I would like to share with you STM32F103C8T6 to read and write internal flash. Regarding the 103 series of single-chip microcomputers, you can refer to the option manual to check the flash capacity.
1. Chip FLASH capacity classification:
The flash size of the chip introduced today is 64K, and some people on the Internet say that it can support up to 128K, but the official explanation is that the first 64K is guaranteed, and the latter cannot be guaranteed, so those who want to use it need careful.
Now that we know the flash size of the chip, let's see how the flash is divided. Through the chip data manual, we can see that the STM32F103C8T6 mentioned today is a medium-capacity device.
Since it is a medium-capacity device, let's take a look at the flash division. There is a paragraph in the STM32 flash programming manual: According to different capacities, the memory is organized into:
32 1K bytes/page (small capacity) 128 1K bytes/page (medium capacity) 256 2K bytes/page (large capacity)
How to understand this passage is to tell us that devices with small capacity (memory is 6K and 32K) are composed of 1K bytes per page.
Medium-capacity devices (64K and 128K memory) devices are composed of 1K bytes per page. Large-capacity devices (256K, 384K, and 512K memory) devices are composed of 2K bytes per page.
For example: The storage capacity of a chip is 64K. What is this 64K? It is 64*1024 BYTE. A BYTE is composed of 8 bits 0 or 1, (for example, 0000 1111 These 8 binary arrays become a byte, using decimal Let’s say 15)
To summarize: 64K flash can store 64*1024 bytes of data.
Let's continue to talk about how to divide the 64K data. The storage is stored in units of pages. A page with a capacity of 1K means that a page can store 1024 bytes.
How many pages are there in total?
The answer is: 64 pages, let’s see if the official says so.
This is indeed said in the flash programming manual, so we just said that 64 pages are correct
2. Reading and writing steps:
Above we know how the chips are classified, below we will focus on how the chips read and write.
For internal flash, we refer to the HAL library or the standard library and directly call the library packaged by ST for programming. Here I use the standard library. If you are interested, you can check the HAL library.
Do some friends ask what is the standard library and what is the HAL library?
Here to explain to you, these two libraries are ST companies, directly encapsulate the registers into functions, so that you can directly call a certain function, you can complete the configuration of various registers. Use, because the name and function of each function are different, you can refer to the comment of the function before calling. There are even usages of each function in the standard library of F0 and F4. I don’t know why it is used in the library of F1. Step removed.
Let's continue, the library functions for reading and writing are divided into:
/*------------ Functions used for all STM32F10x devices -----*/void FLASH_SetLatency(uint32_t FLASH_Latency);void FLASH_HalfCycleAccessCmd(uint32_t FLASH_HalfCycleAccess);void FLASH_PrefetchBufferCmd(uint32_t FLASH_PrefetchBuffer);void FLASH_Unlock(void);void FLASH_Lock(void);
FLASH_Status FLASH_ErasePage(uint32_t Page_Address);FLASH_Status FLASH_EraseAllPages(void);
FLASH_Status FLASH_EraseOptionBytes(void);FLASH_Status FLASH_ProgramWord(uint32_t Address, uint32_t Data);FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data);FLASH_Status FLASH_ProgramOptionByteData(uint32_t Address, uint8_t Data);FLASH_Status FLASH_EnableWriteProtection(uint32_t FLASH_Pages);FLASH_Status FLASH_ReadOutProtection(FunctionalState NewState);
FLASH_Status FLASH_UserOptionByteConfig(uint16_t OB_IWDG, uint16_t OB_STOP, uint16_t OB_STDBY);uint32_t FLASH_GetUserOptionByte(void);uint32_t FLASH_GetWriteProtectionOptionByte(void);
FlagStatus FLASH_GetReadOutProtectionStatus(void);FlagStatus FLASH_GetPrefetchBufferStatus(void);void FLASH_ITConfig(uint32_t FLASH_IT, FunctionalState NewState);FlagStatus FLASH_GetFlagStatus(uint32_t FLASH_FLAG);void FLASH_ClearFlag(uint32_t FLASH_FLAG);FLASH_Status FLASH_GetStatus(void);
FLASH_Status FLASH_WaitForLastOperation(uint32_t Timeout);
/*------------ New function used for all STM32F10x devices -----*/void FLASH_UnlockBank1(void);void FLASH_LockBank1(void);FLASH_Status FLASH_EraseAllBank1Pages(void);FLASH_Status FLASH_GetBank1Status(void);FLASH_Status FLASH_WaitForLastBank1Operation(uint32_t Timeout);
I won’t go into details one by one here, let’s just talk about the commonly used ones.
1. Unlock void FLASH_Unlock(void);
2. Lock void FLASH_Lock(void);
3. Page erase FLASH_Status FLASH_ErasePage (uint32_t Page_Address);
4. Write half word to FLASH_Status FLASH_ProgramHalfWord (uint32_t Address, uint16_t Data);
The above 4 functions are the most commonly used.
Let's talk about the steps of data writing:
The first step: unlock.
Step 2: Determine whether the written data has been erased, that is, whether 0xFFFF is stored in the written address. Here is an important point to say, why is it necessary to judge whether it is 0xFFFF instead of judging whether it is 0xFF? Because every time we write data, we have to write a half word, that is, two bytes of data, and the written address can only be an integer multiple of 2, not an odd number. Please pay attention here.
Step 3: Write data STM32F103C8T6 can only write data in half-word mode. The data before writing must be 0XFFFF. Because FLASH data is written, only 0 can be written, not 1, which is why we want Make sure that the data before writing is the cause of the erasure.
Step 4: Lock up.
Step 5: Verify that the writing is correct.
In fact, the fifth step can be omitted. Let's take a look at the official writing process:
Well, it's actually the same. Let me share it with you (99% reference punctual atom routines).
//Write without checking //WriteAddr: start address //pBuffer: data pointer //NumToWrite: half word (16 bits) void STMFLASH_Write_NoCheck(u32 WriteAddr, u16 *pBuffer, u16 NumToWrite) {u16 i; for( i=0;i《NumToWrite;i++) {FLASH_ProgramHalfWord(WriteAddr, pBuffer); WriteAddr+=2;//Add 2.}}
//Write data of the specified length from the specified address//WriteAddr: starting address (this address must be a multiple of 2!!) //pBuffer: data pointer //NumToWrite: half word (16 bits) number (just to The number of 16-bit data written.) u16 STMFLASH_BUF [STM_SECTOR_SIZE/2];//Up to 2K bytes void STMFLASH_Write (u32 WriteAddr, u16 *pBuffer, u16 NumToWrite) {u32 secpos; //Sector address u16 secoff ; //Offset address in the sector (16-bit word calculation) u16 secremain; //Remaining address in the sector (16-bit word calculation) u16 i; u32 offaddr; //Remove the address after 0X08000000 if (WriteAddr《STM32_FLASH_BASE| |(WriteAddr"=(STM32_FLASH_BASE+1024*STM32_FLASH_SIZE))) return;//Illegal address FLASH_Unlock();
//Unlock offaddr=WriteAddr-STM32_FLASH_BASE; //The actual offset address. secpos=offaddr/STM_SECTOR_SIZE;
//Sector address 0~127 for STM32F103RBT6 secoff=(offaddr%STM_SECTOR_SIZE)/2;
//The offset within the sector (2 bytes are the basic unit.) secremain=STM_SECTOR_SIZE/2-secoff; //The size of the remaining space in the sector if (NumToWrite《=secremain) {secremain=NumToWrite;//Not greater than The sector range} while(1) {STMFLASH_Read(((secpos*STM_SECTOR_SIZE)+STM32_FLASH_BASE), STMFLASH_BUF, STM_SECTOR_SIZE/2);//Read the content of the entire sector for(i=0;i《secremain;i++) //Check data// for (i=0;i《(STM_SECTOR_SIZE/2);i++)//Check data{ if (STMFLASH_BUF[secoff+i]!=0XFFFF) break;//Need to erase// if (STMFLASH_BUF!=0XFFFF) break;//Need to erase} FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
if(i《secremain)//Need to erase// if(i》(STM_SECTOR_SIZE/2))//Need to erase {FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR); FLASH_ErasePage(secpos*STM_SECTOR_/FLASH_SIZE+STM32; Except this sector for (i=0;i《secremain;i++)//copy {STMFLASH_BUF [i+secoff]=pBuffer;} STMFLASH_Write_NoCheck(secpos*STM_SECTOR_SIZE+STM32_FLASH_BASE, STMFLASH_BUF, STM_SECTOR_SIZE/2);//write the entire Sector}else STMFLASH_Write_NoCheck(WriteAddr, pBuffer, secremain);
//Write the erased ones, directly write into the remaining section of the sector. if (NumToWrite==secremain) break;//The writing is over else//The writing is not finished{ secpos++; //Increase the sector address by 1 secoff=0; //The offset position is 0 pBuffer+=secremain; //Pointer Offset WriteAddr+=(secremain*2); //Write address offset NumToWrite-=secremain; //Decrease the number of bytes (16 bits) if (NumToWrite" (STM_SECTOR_SIZE/2)) {secremain=STM_SECTOR_SIZE/2;// The next sector still cannot be written} else {secremain=NumToWrite;//The next sector can be written}}} FLASH_Lock();//Lock}
Finally, we call the STMFLASH_Write() function to write data. Are there any friends who don’t understand? Let me explain the writing process to you.
This STMFLASH_Write() function means that given a write address, data and number of writes, then start writing data according to the given address, pay attention to the red font.
How do you write data?
The first is to sort out the page address to be written and how many pages need to be written, what is the starting address for each page to be written, and then start writing page by page, when it comes to cross-page writing, the second page Write in the address, and just continue to write the number.
Another important point is that I modified the library function:
/** * [url=home.php?mod=space&uid=247401]@brief[/url] Programs a half word at a specified address. * [url=home.php?mod=space&uid=536309]@NOTE[/url] This function can be used for all STM32F10x devices. * @param Address: specifies the address to be programmed. * @param Data: specifies the data to be programmed. * @retval FLASH Status: The returned value can be: FLASH_ERROR_PG, * FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT. */FLASH_Status FLASH_ProgramHalfWord(uint32_t Address, uint16_t Data){ FLASH_ClearFlag(FLASH_FLAG_EOP | FLASH_FLAG_PGERR | FLASH_FLAG_WRPRTERR);
FLASH_Status status = FLASH_COMPLETE; /* Check the parameters */ assert_param(IS_FLASH_ADDRESS(Address));#ifdef STM32F10X_XL /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(ProgramTimeout);
if(Address 《 FLASH_BANK1_END_ADDRESS) { if(status == FLASH_COMPLETE) { /* if the previous operation is completed, proceed to program the new data */ FLASH-》CR |= CR_PG_Set; *(__IO uint16_t*)Address = Data; /* Wait for last operation to be completed */ status = FLASH_WaitForLastBank1Operation(ProgramTimeout);
/* Disable the PG Bit */ FLASH-》CR &= CR_PG_Reset; } } else { if(status == FLASH_COMPLETE) { /* if the previous operation is completed, proceed to program the new data */ FLASH-》CR2 |= CR_PG_Set; *(__IO uint16_t*)Address = Data; /* Wait for last operation to be completed */ status = FLASH_WaitForLastBank2Operation(ProgramTimeout);
/* Disable the PG Bit */ FLASH-》CR2 &= CR_PG_Reset; } }#else /* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(ProgramTimeout); if(status == FLASH_COMPLETE) { /* if the previous operation is completed, proceed to program the new data */ FLASH-》CR |= CR_PG_Set; *(__IO uint16_t*)Address = Data;
/* Wait for last operation to be completed */ status = FLASH_WaitForLastOperation(ProgramTimeout); /* Disable the PG Bit */ FLASH-》CR &= CR_PG_Reset; } #endif /* STM32F10X_XL */ /* Return the Program Status */ return status;}
Can you see it? It is the red font part, adding a clear all abnormal state before each writing. Why add this?
Because, if the address of the data you write is not erased, if you write it, it will cause an abnormal state to occur, and this abnormal state must be manually cleared, if you do not clear the abnormal state, and continue to write data , Then any data you write later will report an error, and you will not be able to write it in, so I added an exception status clear here. If the data written earlier is reported wrong, it will not affect my subsequent data writing.
Here everyone clears up why.
We will write data, so let's talk about reading data. In fact, reading data here is much easier than external flash reading. We read the address directly, and what is returned is the data stored in the address. Is it very simple?
Look at the following function:
//Read the half word of the specified address (16-bit data) //faddr: read address (this address must be a multiple of 2!!) //Return value: corresponding data.u16 STMFLASH_ReadHalfWord(u32 faddr){ return *(vu16 *) faddr; }//Read the data of the specified length from the specified address //ReadAddr: start address //pBuffer: data pointer //NumToWrite: half word (16 bits) void STMFLASH_Read (u32 ReadAddr, u16 *pBuffer , U16 NumToRead) {u16 i; for(i=0;i《NumToRead;i++) {pBuffer=STMFLASH_ReadHalfWord(ReadAddr);//Read 2 bytes. ReadAddr+=2;//offset by 2 bytes. }}
Are you very happy? Reading and writing data is as simple as that.
Comments
participate in discussions
Please login ? to participate in the comments
New customer Start here.