复旦微FM33LC046N评测+FLASH存储
[复制链接]
一、概述
1、FLASH容量64K * 32=256K
页---page(512B)
扇区--sector(2K)
2、支持页擦除,扇区擦除,全擦(仅支持SWD程序下载模式)
3、flash内存
大小:256k
范围:0x00000000 -- 0x00040000
Flash 扇区(Sector)大小为 512 字节,每 16 个扇区组成一个 8K 字节的块(Block)。
Flash 包含 4 个 information 扇区, 2 个 LDT 扇区, 1 个冗余扇区, 1 个DCT 扇区。其中 DCT 和 LDT为芯片原厂保留扇区,不对用户开放。Information 为用户配置扇区,用于保存用户配置信息。所有
option 扇区在地址上与 Flash 主区域互相隔离。
二、flash擦除方法
三、软件实现步骤
1、在串口通信的基础上,通过串口发送数据到MCU,操作读/写flash
2、命令判断
指令码:flash操作固定0x01;
操作码:0x01--读, 0x04--写
以上命令均以HEX数据格式发送
范例:
(1)写数据
68 01 04 02 12 34 16 //向flash中写两个字节的数据,数据为0x12, 0x34
无返回,可通过读取数据来进行检验
(2)读数据
[2021-03-02 13:36:37:313] 68 01 01 01 05 16 (6 bytes) //从flash中读取5个字节的数据
[2021-03-02 13:36:37:518] 68 01 81 05 11 22 33 44 55 16 (10 bytes)//读到的数据为:11 22 33 44 55
3、flash读函数
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写函数
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、串口通信测试
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、串口中断服务函数
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、串口发送函数
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、串口助手通信报文截图
|