2021-09-19

CH32F103 FLASH的使用

最近使用CH32F103来替代STM32F103,遇到的flash问题来简单记一下。
程序使用STM32的没有修改直接烧入,能启动,能运行,内部flash写入失败,查看官方文档,标准模式太慢,基本不大行,可以使用快速模式,按照官方例程修改失败,查看文档,按照标准流程进行了修改,成功。

这是官方文档描述:
24.4.6 主存储器快速编程
快速编程按页(128 字节)进行编程。系统内置了 128 字节缓存区,将要待编程的数据线保存到
缓存区后执行一次编程操作,效率更高。
1)检查 FLASH_CTLR 寄存器 LOCK 位,如果为 1,需要执行“解除闪存锁”操作。
2)检查 FLASH_STATR 寄存器的 BSY 位,以确认没有其他正在进行的编程操作。
3)检查 FLASH_CTLR 寄存器 FLOCK 位,如果为 1,需要执行“快速编程模式解锁”操作。
CH32x103 应用手册 272 http://wch.cn
4)设置 FLASH_CTLR 寄存器的 FTPG 位,开启快速编程模式功能。
5)设置 FLASH_CTLR 寄存器的 BUFRST 位,执行清除内部 128 字节缓存区操作。
6)等待 BYS 位变为‘0’或 FLASH_STATR 寄存器的 EOP 位为‘1’表示清除结束,将 EOP 位清 0。
7)向指定地址开始连续写入 16 字节数据(4 字节/次操作,写的地址每次偏移量为 4),然后设置
FLASH_CTLR 寄存器的 BUFLOAD 位,执行加载到缓存区。
8)等待 BYS 位变为‘0’或 FLASH_STATR 寄存器的 EOP 位为‘1’表示加载结束,将 EOP 位清 0。
9)重复步骤 7-8 共 8 次,将 128 字节数据都加载到缓存区(主要 8 轮操作地址要连续)。
10)向 FLASH_ADDR 寄存器写入快速编程页的首地址。
11)设置 FLASH_CTLR 寄存器的 STAT 位为‘1’,启动一次快速页编程动作。
12)等待 BYS 位变为‘0’或 FLASH_STATR 寄存器的 EOP 位为‘1’表示编程结束,将 EOP 位清 0。
13)查询 FLASH_STATR 寄存器看是否有错误,或者读编程地址数据校验。
14)继续快速页编程可以重复 5-13 步骤,结束编程将 FTPG 位清 0。
24.4.7 主存储器快速擦除
快速擦除也按页(128 字节)进行擦除。
1)检查 FLASH_CTLR 寄存器 LOCK 位,如果为 1,需要执行“解除闪存锁”操作。
2)检查 FLASH_STATR 寄存器的 BSY 位,以确认没有其他正在进行的编程操作。
3)检查 FLASH_CTLR 寄存器 FLOCK 位,如果为 1,需要执行“快速编程模式解锁”操作。
4)设置 FLASH_CTLR 寄存器的 FTER 位,开启快速擦除模式功能。
5)向 FLASH_ADDR 寄存器写入快速擦除页的首地址。
6)设置 FLASH_CTLR 寄存器的 STAT 位为‘1’,启动一次快速页擦除动作。
7)等待 BYS 位变为‘0’或 FLASH_STATR 寄存器的 EOP 位为‘1’表示擦除结束,将 EOP 位清 0。
8)查询 FLASH_STATR 寄存器看是否有错误,或者读擦除页地址数据校验。
9)继续快速页擦除可以重复 5-8 步骤,结束擦除将 FTER 位清 0。

这是修改的代码

void FLASH_ErasePage_Fast(uint32_t Page_Address)
{
	if(IS_FLASH_ADDRESS(Page_Address))
	{
    while(FLASH->CR & CR_LOCK_Set)
      FLASH_Unlock_Fast();
    while(FLASH->SR & SR_BSY);
		FLASH->CR |= CR_PAGE_ER;
		FLASH->AR = Page_Address;
		FLASH->CR |= CR_STRT_Set;	
		while(FLASH->SR & SR_BSY);
		FLASH->CR &= ~CR_PAGE_ER;		
		
		*(__IO uint32_t*)0x40022034 = *(__IO uint32_t*)(Page_Address ^ 0x00000100);
	}
}
void FLASH_ProgramPage_Fast(uint32_t Page_Address)
{
	if(IS_FLASH_ADDRESS(Page_Address))
	{
    while(FLASH->CR & CR_LOCK_Set)
      FLASH_Unlock_Fast();
    while(FLASH->SR & SR_BSY);
    while(FLASH->CR & CR_LOCK_FK)
      FLASH_Unlock_Fast();

		FLASH->CR |= CR_PAGE_PG;
		FLASH->AR = Page_Address;
		FLASH->CR |= CR_STRT_Set;	
		while(FLASH->SR & SR_BSY);
		FLASH->CR &= ~CR_PAGE_PG;	
	
		*(__IO uint32_t*)0x40022034 = *(__IO uint32_t*)(Page_Address ^ 0x00000100);	
	}
}

批量写入程序

int FlashWrite(uint32_t offsetAdd, uint8_t *buf, uint32_t iNbrToWrite)
{
    /* Unlock the Flash Bank1 Program Erase controller */
    uint32_t secpos, iAddress = _start_addr + offsetAdd;
    uint32_t iNumByteToWrite = iNbrToWrite;
    uint16_t secoff;
    uint16_t secremain;
    uint16_t i = 0;
    // 定义缓冲区,保存读出的页数据

    static uint8_t tmp[128];
    u32 *buffer;

    if ((_start_addr == 0) || (iAddress >= _end_addr))
    {
        
        return 0;
    }
    secremain = 128 ;       //空间大小
    if(iNumByteToWrite <= secremain) secremain = iNumByteToWrite; 
    FLASH_Unlock_Fast();

    while( 1 )
    {
        ebox_flashRead(iAddress, tmp, 128);   //读出整个扇区

            FLASH_ErasePage_Fast(iAddress);
            for(i = 0; i < 128; i++) //复制
            {
                tmp[i] = buf[i];
            }
            buffer = (u32 *)tmp;
            FLASH_BufReset();
            FLASH_BufLoad(iAddress, buffer[0], buffer[1], buffer[2], buffer[3]);
            FLASH_BufLoad(iAddress + 0x10, buffer[4], buffer[5], buffer[6], buffer[7]);
            FLASH_BufLoad(iAddress + 0x20, buffer[8], buffer[9], buffer[10], buffer[11]);
            FLASH_BufLoad(iAddress + 0x30, buffer[12], buffer[13], buffer[14], buffer[15]);
            FLASH_BufLoad(iAddress + 0x40, buffer[16], buffer[17], buffer[18], buffer[19]);
            FLASH_BufLoad(iAddress + 0x50, buffer[20], buffer[21], buffer[22], buffer[23]);
            FLASH_BufLoad(iAddress + 0x60, buffer[24], buffer[25], buffer[26], buffer[27]);
            FLASH_BufLoad(iAddress + 0x70, buffer[28], buffer[29], buffer[30], buffer[31]);	
            FLASH_ProgramPage_Fast(iAddress);

        if(iNumByteToWrite == secremain)  //写入结束了
        {
            break;
        }
        else     //不够写入,移到下一个扇区
        {
            secpos += 128;
            if (secpos >= _end_addr)
            {
                return -1;
            }
            buf += secremain;  //指针偏移
            iAddress += secremain;//写地址偏移
            iNumByteToWrite -= secremain;  //字节数递减
            if(iNumByteToWrite > 128) secremain = 128; //下一个扇区还是写不完
            else secremain = iNumByteToWrite;  //下一个扇区可以写完了
        }
    }  
  
   FLASH_Lock_Fast();	
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值