4454|11

12

帖子

0

TA的资源

一粒金砂(中级)

楼主
 

复旦微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)
//FLASHx:外设地址
//address:操作的地址(页首地址)
//data:读回的数据存放地址
//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)
//页擦写函数
//FLASHx:外设地址
//address:操作的地址(页首地址)

ErrorStatus FL_FLASH_Program_Page(FLASH_Type* FLASHx, uint32_t pageNum, uint32_t *data)
//FLASHx:外设地址
//pageNum:扇区号
//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)
    {
        /* Key 序列*/
        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)//flash操作
	{
		if(uc_uart0_rev[2]==0x01)//读flash
		{
			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)//写flash
		{
			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);//接收中断标志可通过读取rxreg寄存器清除
		uc_uart0_num++;
		uc_uart0_revouttime=20;//200ms超时
		
	}
	
	//发送中断处理
	if((ENABLE == FL_UART_IsEnabledIT_TXShiftBuffEmpty(UART0))
		&&(SET == FL_UART_IsActiveFlag_TXShiftBuffEmpty(UART0)))
	{
		//发送中断标志可通过写txreg寄存器清除或txif写1清除
		//发送指定长度的数据
		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、串口发送函数

//uart0 串口发送函数
void uart0_send(void)
{
	uc_uart0_sendnum=1;
	FL_UART_ClearFlag_TXShiftBuffEmpty(UART0);//清除UART发送移位寄存器标志
	FL_UART_EnableIT_TXShiftBuffEmpty(UART0);//启用UART发送移位寄存器中断
	FL_UART_WriteTXBuff(UART0, uc_uart0_sendbuf[0]);
	DelayMs(50);//软件延时
	FL_UART_DisableIT_TXShiftBuffEmpty(UART0); //禁用UART发送移位寄存器中断
	FL_UART_EnableIT_RXBuffFull(UART0);//启用UART接收缓冲区中断
}

8、串口助手通信报文截图

 
 
 

最新回复

串口通信最后的图片,读数据返回和读数据一致?   详情 回复 发表于 2021-3-9 20:31

赞赏

1

查看全部赞赏

点赞(1) 关注
 
 

回复
举报

1942

帖子

2

TA的资源

版主

沙发
 

感谢分享!

 
 
 

回复

2万

帖子

341

TA的资源

版主

板凳
 

可以总结一下FM33LC046N存储Flash情况是什么样,有没有读取Flash内容时卡死

点评

FM33LC046N的flash资源的详细介绍在官方文档中可查询到,我只是验证了简单的flash读写操作;至于读取时会不会卡死这个问题,我暂时并没有发现过  详情 回复 发表于 2021-3-9 16:39
 
 
 

回复

7608

帖子

2

TA的资源

五彩晶圆(高级)

4
 

自己写这么多代码,这个评测做的很认真了!

点评

新的东西总能提起人的兴趣,开发板也一样  详情 回复 发表于 2021-3-9 16:47
个人签名

默认摸鱼,再摸鱼。2022、9、28

 
 
 

回复

6802

帖子

0

TA的资源

五彩晶圆(高级)

5
 

flash擦除之前需要key验证

点评

[attachimg]527326[/attachimg][attachimg]527327[/attachimg]文档介绍是需要先进行校验才能操作flash  详情 回复 发表于 2021-3-9 16:43
 
 
 

回复

2万

帖子

74

TA的资源

管理员

6
 

能得到FREE肯定不容易,楼主继续加油

加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身

点评

谢谢  详情 回复 发表于 2021-3-9 16:44
 
 
 

回复

12

帖子

0

TA的资源

一粒金砂(中级)

7
 
qwqwqw2088 发表于 2021-3-5 11:53 可以总结一下FM33LC046N存储Flash情况是什么样,有没有读取Flash内容时卡死

FM33LC046N的flash资源的详细介绍在官方文档中可查询到,我只是验证了简单的flash读写操作;至于读取时会不会卡死这个问题,我暂时并没有发现过

 
 
 

回复

12

帖子

0

TA的资源

一粒金砂(中级)

8
 
Jacktang 发表于 2021-3-8 20:27 flash擦除之前需要key验证

文档介绍是需要先进行校验才能操作flash

 
 
 

回复

12

帖子

0

TA的资源

一粒金砂(中级)

9
 
soso 发表于 2021-3-9 16:02 能得到FREE肯定不容易,楼主继续加油

谢谢

 
 
 

回复

12

帖子

0

TA的资源

一粒金砂(中级)

10
 
freebsder 发表于 2021-3-6 21:40 自己写这么多代码,这个评测做的很认真了!

新的东西总能提起人的兴趣,开发板也一样

 
 
 

回复

6802

帖子

0

TA的资源

五彩晶圆(高级)

11
 

串口通信最后的图片,读数据返回和读数据一致?

点评

是不同的,绿色是发送,蓝色是接收  详情 回复 发表于 2021-3-11 14:34
 
 
 

回复

12

帖子

0

TA的资源

一粒金砂(中级)

12
 
Jacktang 发表于 2021-3-9 20:31 串口通信最后的图片,读数据返回和读数据一致?

是不同的,绿色是发送,蓝色是接收

 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表