Fudan Micro FM33LC046N Review + FLASH Storage
[Copy link]
1. Overview
1. FLASH capacity 64K * 32 = 256K
Page---page(512B)
Sector--sector(2K)
2. Support page erase, sector erase, full erase (only supports SWD program download mode)
3. Flash memory
Size: 256k
Range: 0x00000000 -- 0x00040000
The size of a Flash sector is 512 bytes, and every 16 sectors form an 8K-byte block.
Flash contains 4 information sectors, 2 LDT sectors, 1 redundant sector, and 1 DCT sector. DCT and LDT are sectors reserved by the chip manufacturer and are not open to users. Information is the user configuration sector, which is used to store user configuration information.
The option sector is isolated from the main Flash area in terms of address.
2. Flash erase method
3. Software Implementation Steps
1. Based on serial communication, send data to MCU through the serial port to operate read/write flash
2. Command judgment
Instruction code: flash operation is fixed at 0x01;
Operation code: 0x01--read, 0x04--write
The above commands are all sent in HEX data format
Example:
(1) Write data
68 01 04 02 12 34 16 //Write two bytes of data to the flash. The data is 0x12 and 0x34.
No return. You can check it by reading the data.
(2) Read data
[2021-03-02 13:36:37:313] 68 01 01 01 05 16 (6 bytes) //Read 5 bytes of data from the flash
[2021-03-02 13:36:37:518] 68 01 81 05 11 22 33 44 55 16 (10 bytes) //The data read is: 11 22 33 44 55
3. Flash read function
ErrorStatus FL_FLASH_Read_Dma(FLASH_Type* FLASHx, uint32_t address, uint32_t *data, uint16_t length)
ErrorStatus FL_FLASH_Read_Dma(FLASH_Type* FLASHx, uint32_t address, uint32_t *data, uint16_t length)
{
ErrorStatus ret;
uint32_t Timeout;
FL_DMA_InitTypeDef initStruct={0};
assert_param(IS_FLASH_ALL_INSTANCE(FLASHx));
assert_param(IS_FL_FLASH_MAX_ADDR(address));
if(address & (FL_FLASH_SECTOR_SIZE_BYTE / 2 - 1))
{
return FAIL;
}
initStruct.circMode = DISABLE;
initStruct.direction = FL_DMA_DIR_FLASH_TO_RAM;
initStruct.memoryAddressIncMode = FL_DMA_CH7_MEMORY_INC_MODE_INCREASE;
initStruct.flashAddressIncMode = FL_DMA_CH7_FLASH_INC_MODE_INCREASE;
initStruct.priority = FL_DMA_PRIORITY_HIGH;
initStruct.periphAddress = address >> 2;
FL_DMA_Init(DMA, &initStruct, FL_DMA_CHANNEL_7);
FL_DMA_WriteFlashAddress(DMA, address >> 2);
FL_DMA_WriteMemoryAddress(DMA, (uint32_t)data >> 2, FL_DMA_CHANNEL_7);
FL_DMA_WriteTransmissionSize(DMA, length - 1, FL_DMA_CHANNEL_7);
FL_DMA_ClearFlag_TransferComplete(DMA, FL_DMA_CHANNEL_7);
FL_DMA_EnableChannel(DMA, FL_DMA_CHANNEL_7);
FL_DMA_Enable(DMA);
Timeout = 0;
while (1)
{
Timeout++;
if(Timeout > FL_FLASH_ERASE_TIMEOUT)
{
ret = FAIL;
break;
}
if (FL_DMA_IsActiveFlag_TransferComplete(DMA, FL_DMA_CHANNEL_7) == SET)
{
ret = PASS;
break;
}
}
return ret;
}
4. Flash write function
ErrorStatus FL_FLASH_PageErase(FLASH_Type* FLASHx, uint32_t address)
ErrorStatus FL_FLASH_Program_Page(FLASH_Type* FLASHx, uint32_t pageNum, uint32_t *data)
ErrorStatus FL_FLASH_Program_Page(FLASH_Type* FLASHx, uint32_t pageNum, uint32_t *data)
{
uint32_t count;
uint32_t primask;
uint32_t address;
uint32_t timeout;
ErrorStatus ret;
assert_param(IS_FLASH_ALL_INSTANCE(FLASHx));
assert_param(IS_FL_FLASH_MAX_PAGE((uint32_t)pageNum));
address = pageNum*FL_FLASH_PAGE_SIZE_BYTE;
if(address & (FL_FLASH_PAGE_SIZE_BYTE-1))
{
return FAIL;
}
FL_RCC_EnableGroup2BusClock(FL_RCC_GROUP2_BUSCLK_FLASH);
FL_RCC_EnableGroup2OperationClock(FL_RCC_GROUP2_OPCLK_FLASH);
FL_FLASH_EnableProgram(FLASHx);
if(FL_FLASH_GetFlashLockStatus(FLASHx) != FL_FLASH_KEY_STATUS_PROGRAM)
{
primask = __get_PRIMASK();
__disable_irq();
FL_FLASH_UnlockFlash(FLASHx,FL_FLASH_PROGRAM_KEY1);
FL_FLASH_UnlockFlash(FLASHx,FL_FLASH_PROGRAM_KEY2);
__set_PRIMASK(primask);
}
for (count = 0; count < FL_FLASH_PAGE_SIZE_BYTE; count += 4)
{
timeout = 0;
FL_FLASH_EnableProgram(FLASHx);
*((uint32_t*)address) = *(data++);
address += 4;
while(1)
{
timeout++;
if((timeout > FL_FLASH_ERASE_TIMEOUT)\
||(FL_FLASH_IsActiveFlag_ClockError(FLASHx))\
||(FL_FLASH_IsActiveFlag_KeyError(FLASHx))\
||(FL_FLASH_IsActiveFlag_AuthenticationError(FLASHx)))
{
ret = FAIL;
break;
}
if(FL_FLASH_IsActiveFlag_ProgramComplete(FLASHx))
{
FL_FLASH_ClearFlag_ProgramComplete(FLASHx);
ret = PASS;
break;
}
}
}
FL_FLASH_LockFlash(FLASHx);
FL_RCC_DisableGroup2OperationClock(FL_RCC_GROUP2_OPCLK_FLASH);
return ret;
}
5. Serial communication test
if(uc_uart0_revok==1)
{
uc_uart0_revok=0;
if(uc_uart0_rev[1]==0x01)
{
if(uc_uart0_rev[2]==0x01)
{
FL_FLASH_Read_Dma(FLASH,0x00004000,(uint32_t * )DataTowrite,512);
uc_uart0_sendbuf[0]=0x68;
uc_uart0_sendbuf[1]=0x01;
uc_uart0_sendbuf[2]=0x81;
uc_uart0_sendbuf[3]=uc_uart0_rev[4];
for(i1=0;i1<uc_uart0_rev[4];i1++)
{
uc_uart0_sendbuf[4+i1]=DataTowrite[i1];
}
uc_uart0_sendbuf[4+uc_uart0_rev[4]]=0x16;
uc_uart0_sendlight=5+uc_uart0_rev[4];
uart0_send();
}
else if(uc_uart0_rev[2]==0x04)
{
memset(DataTowrite,0,512);
for(i1=0;i1<uc_uart0_rev[3];i1++)
{
DataTowrite[i1]=uc_uart0_rev[4+i1];
}
FL_FLASH_PageErase(FLASH, 0x00004000);
FL_FLASH_Program_Page(FLASH,32,DataTowrite);
}
}
}
6. Serial port interrupt service function
void UART0_IRQHandler(void)
{
uint8_t tmp08;
if((ENABLE == FL_UART_IsEnabledIT_RXBuffFull(UART0))
&&(SET == FL_UART_IsActiveFlag_RXBuffFull(UART0)))
{
uc_uart0_rev[uc_uart0_num]=FL_UART_ReadRXBuff(UART0);
uc_uart0_num++;
uc_uart0_revouttime=20;
}
if((ENABLE == FL_UART_IsEnabledIT_TXShiftBuffEmpty(UART0))
&&(SET == FL_UART_IsActiveFlag_TXShiftBuffEmpty(UART0)))
{
if(uc_uart0_sendnum<uc_uart0_sendlight)
{
FL_UART_WriteTXBuff(UART0, uc_uart0_sendbuf[uc_uart0_sendnum]);
uc_uart0_sendnum++;
}
else
{
uc_uart0_sendnum=0;
uc_uart0_sendlight=0;
}
FL_UART_ClearFlag_TXShiftBuffEmpty(UART0);
}
}
7. Serial port sending function
void uart0_send(void)
{
uc_uart0_sendnum=1;
FL_UART_ClearFlag_TXShiftBuffEmpty(UART0);
FL_UART_EnableIT_TXShiftBuffEmpty(UART0);
FL_UART_WriteTXBuff(UART0, uc_uart0_sendbuf[0]);
DelayMs(50);
FL_UART_DisableIT_TXShiftBuffEmpty(UART0);
FL_UART_EnableIT_RXBuffFull(UART0);
}
8. Screenshot of the communication message of the serial port assistant
|