首页 > 其他分享 >基于CH32V208开发板—FLASH读写、擦除

基于CH32V208开发板—FLASH读写、擦除

时间:2023-10-18 11:23:41浏览次数:38  
标签:FLASH ADDR Flash 开发板 CH32V208 擦除 PAGE 编程

-------------------------------------------------------------------------------------------------------------------------------------

在CH32V208系列芯片中,各个型号的参数如下图:

FLASH的大小包含零等待区和非零等待区,一共是480K。
1、内部实际存储代码的flash为慢速flash;
2、芯片复位后由硬件根据配置把慢速flash的代码拷贝到 用ram工艺做的快速flash区域,然后从快速flash里面运行;
3、芯片内部的慢速flash通常都比较大,并且支持运行代码,只是速度慢了点;
4、WCH官网的宣传FLASH大小实际上是针对快速FLASH.


在手册中查到,可以将快速FLASH/RAM配置为以下三种;需要在WCHISPTOOL工具中配置,也需要修改LD文件与之对应。

在 Link.ld中,也需要修改对应位置的参数

 

通过V208的EVT中,使用FLASH的例程对flash进行读写、擦除操作以及标准编程和快速编程的过程。编程过程中,只有半字和字编程,没有字节编程

当主频率超过100MHz时,在操作FLASH时需要注意:将HCLK除以2会导致与HCLK相关的外设时钟也被除以2。在使用过程中需要注意这一点。


在程序中,先进行标准编程flash测试,

#include "debug.h"

/* Global define */
typedef enum
{
    FAILED = 0,
    PASSED = !FAILED
} TestStatus;

#define PAGE_WRITE_START_ADDR  ((uint32_t)0x08008000) /* Start from 32K */  //Flash存储器的起始地址,这里表示从地址0x08008000(32K)开始写入数据
#define PAGE_WRITE_END_ADDR    ((uint32_t)0x08009000) /* End at 36K */  //Flash存储器的结束地址,这里表示写入数据的结束地址为0x08009000(36K)。
#define FLASH_PAGE_SIZE                   4096    //Flash存储器的页大小,这里表示每个页的大小为4096字节(4KB)。
#define FLASH_PAGES_TO_BE_PROTECTED FLASH_WRProt_Pages60to63    //需要保护的Flash页范围,这里表示保护页为从60到63页。

/* Fast Mode define */
#define FAST_FLASH_PROGRAM_START_ADDR  ((uint32_t)0x08008000)  //快速模式下编程的起始地址,这里表示快速编程模式的起始地址为0x08008000。(32K)
#define FAST_FLASH_PROGRAM_END_ADDR  ((uint32_t)0x08010000)    //快速模式下编程的结束地址,这里表示快速编程模式的结束地址为0x08010000。(64K)
#define FAST_FLASH_SIZE  (64*1024)      //快速模式下编程的Flash大小,这里表示快速编程模式的Flash大小为64KB。

/* Global Variable */
uint32_t EraseCounter = 0x0;  //擦除计数器,用于记录擦除的次数。初始值为0。
uint32_t Address = 0x0;       //Flash操作的地址变量,用于指定Flash中的地址。初始值为0。

uint16_t Data = 0x1234;        //编程数据,用于存储要编程到Flash的16位数据。初始值为0xAAAA。
uint32_t WRPR_Value = 0xFFFFFFFF;  ////写保护寄存器的值,用于配置Flash的写保护。初始值为0xFFFFFFFF
uint32_t ProtectedPages = 0x0;      //受保护的页数,用于记录被写保护的Flash页的数量。初始值为0。
uint32_t NbrOfPage;                  //页数,用于记录需要擦除的Flash页的数量。该值由根据计算得出。

volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;    //页数,用于记录需要擦除的Flash页的数量。该值由根据计算得出。
volatile TestStatus MemoryProgramStatus = PASSED;     //存储程序操作状态的变量,用于跟踪编程操作的结果。初始值为PASSED。
volatile TestStatus MemoryEraseStatus = PASSED;     //存储擦除操作状态的变量,用于跟踪擦除操作的结果。初始值为PASSED。
u32 buf[64];

uint16_t flashdata;

//标准编程
void Flash_Test()
{
    printf("FLASH Test\n");
 /*When the main frequency exceeds 100MHz, attention should be paid when 
  *operating FLASH: dividing HCLK by two will result in the related peripheral 
  *clock of HCLK being divided by two. Attention should be paid when using.   //在执行FLASH操作时,如果主频率超过100MHz,需要注意将主频分为二并将与HCLK相关的外设时钟也除以二的情况
  */
    RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV2;  //将主频分为二
    __disable_irq();
    USART_Printf_Init(115200);

    FLASH_Unlock();  //解锁FLASH

    //页面的起始地址 PAGE_WRITE_START_ADDR 和结束地址 PAGE_WRITE_END_ADDR
    //页面的大小 FLASH_PAGE_SIZE
    NbrOfPage = (PAGE_WRITE_END_ADDR - PAGE_WRITE_START_ADDR) / FLASH_PAGE_SIZE;  //计算需要擦除的页面数量,

    //忙标志位 FLASH_FLAG_BSY、
    //结束标志位 FLASH_FLAG_EOP 、
    //写保护错误标志位 FLASH_FLAG_WRPRTERR。
    FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP |FLASH_FLAG_WRPRTERR);  //清除FLASH的状态标志位

    //擦除Flash每一页数据
    for(EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
    {
      FLASHStatus = FLASH_ErasePage(PAGE_WRITE_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter));  //Erase 4KB  执行擦除操作

      if(FLASHStatus != FLASH_COMPLETE)  //判断是否擦除成功
      {
        printf("FLASH Erase Fail\r\n");  //失败
      }
      printf("FLASH Erase Suc\r\n");
    }
    Address = PAGE_WRITE_START_ADDR;   //初始化地址变量 Address 为页面的起始地址
    printf("Programing...\r\n");  //表示开始编程

    while((Address < PAGE_WRITE_END_ADDR) && (FLASHStatus == FLASH_COMPLETE))  //编程Flash
    {
      FLASHStatus = FLASH_ProgramHalfWord(Address, Data);  //使用FLASH_ProgramHalfWord()函数逐个编程半字(16位)数据到Flash中
      // 打印地址和数据
      printf("Addr: %08X, Data: %04X", Address, Data);
      Address = Address + 2;
    }

    Address = PAGE_WRITE_START_ADDR;  //写入数据起始地址

    printf("Program Cheking...\r\n");   //检查Flash 中的数据是否与原始数据相同
    while((Address < PAGE_WRITE_END_ADDR) && (MemoryProgramStatus != FAILED))
    {
      if((*(__IO uint16_t*) Address) != Data)   // Flash 内容转换为 uint16_t 类型的数据,并与 Data 进行比较
      {
        MemoryProgramStatus = FAILED;
      }
      Address += 2;
    }

    if(MemoryProgramStatus == FAILED)
    {
       printf("Memory Program FAIL!\r\n");
    }
    else
    {
       printf("Memory Program PASS!\r\n");
    }

     FLASH_Lock();  //锁定Flash:调用FLASH_Lock()函数锁定Flash,确保保护已编程的数据。

     RCC->CFGR0 &= ~(uint32_t)RCC_HPRE_DIV2;  //清除 RCC_CFGR0 寄存器中的 RCC_HPRE_DIV2 位,恢复主频为原来的频率。
     __enable_irq();   //使能中断
     USART_Printf_Init(115200);

}

通过从串口打印,查看地址下将数据写入

 

 

 

 在程序中,快速编程flash测试,

//快速擦除和编程 Flash 的函数
void Flash_Test_Fast(void)
{
    u16 i,j,flag;

    for(i=0; i<64; i++)
    {
        buf[i] = i;
    }

    printf("FLASH Fast Mode Test\n");

    RCC->CFGR0 |= (uint32_t)RCC_HPRE_DIV2; //配置时钟分频,将时钟频率分为原来的一半
    __disable_irq();  //禁用中断并初始化串口以便进行打印输出
    USART_Printf_Init(115200);

    FLASH_Unlock_Fast();   //快速解锁 Flash 存储器,

    FLASH_EraseBlock_32K_Fast(FAST_FLASH_PROGRAM_START_ADDR);  //快速擦除一个32K字节的块

    printf("Program 32KByte start\n");
    for(i=0; i<128; i++)
    {                                                                          //128*256=32768 = 32K
        FLASH_ProgramPage_Fast(FAST_FLASH_PROGRAM_START_ADDR + 256*i, buf);  //将数据缓冲区 buf 中的数据以256字节的页方式快速编程到Flash存储器中,每次编程一个256字节的页,循环执行128次,总共编程32K字节。
    }

    //检查已编程的数据是否正确
    for(i=0; i<128; i++)
    {
        for(j=0; j<64; j++)
        {
            if(*(u32*)(FAST_FLASH_PROGRAM_START_ADDR+256*i+4*j) != j)  //它会将内存中的值与循环变量 j 的值进行比较
            {
                flag = 0;
                break;
            }
            else
            {
                flag = 1;  //相同,标志位为1
            }
        }

    }

    if(flag)
    {
        printf("Program 32KByte suc\n");
    }
    else printf("Program fail\n");

    printf("Erase 256Byte...\n");
    FLASH_ErasePage_Fast(FAST_FLASH_PROGRAM_START_ADDR);  //快速擦除一个256字节的页

    printf("Read 4KByte...\n");
    for(i=0;i<1024; i++)
    {
      printf("%08x ",*(u32*)(FAST_FLASH_PROGRAM_START_ADDR+4*i));  //通过循环逐个读取4K字节页的内容并打印

    }
    printf("\n");

    printf("Erase 4KByte...\n");
    FLASH_ErasePage(FAST_FLASH_PROGRAM_START_ADDR);  //擦除一个4K字节的页

    printf("Read 8KByte...\n");
    for(i=0;i<2048; i++)
    {
      printf("%08x ",*(u32*)(FAST_FLASH_PROGRAM_START_ADDR+4*i));  //通过循环逐个读取8K字节页的内容并打印。

    }
    printf("\n");

    printf("Erase 32KByte...\n");
    FLASH_EraseBlock_32K_Fast(FAST_FLASH_PROGRAM_START_ADDR);  //快速擦除一个32K字节的块

    printf("Read 32KByte...\n");
    for(i=0;i<(1024*9); i++)
    {
      printf("%08x ",*(u32*)(FAST_FLASH_PROGRAM_START_ADDR+i*4));  //逐个读取32K字节块的内容并打印。

    }
    printf("\n");

    FLASH_Lock_Fast();
    RCC->CFGR0 &= ~(uint32_t)RCC_HPRE_DIV2;
    __enable_irq();
    USART_Printf_Init(115200);
}

 通过串口打印出数据,

 

 

 

标签:FLASH,ADDR,Flash,开发板,CH32V208,擦除,PAGE,编程
From: https://www.cnblogs.com/ZYL-FS/p/17771597.html

相关文章

  • 星嵌OMAPL138+国产FPGA工业开发板 中科亿海微 EQ6HL45系列FPGA 替代spartan-6
    1XQ138F-EVM评估板简介基于TIOMAP-L138(定点/浮点DSPC674x+ARM9)+FPGA处理器的开发板;OMAP-L138是TI德州仪器的TMS320C6748+ARM926EJ-S异构双核处理器,主频456MHz,高达3648MIPS和2746MFLOPS的运算能力;FPGA采用中科亿海微eHiChip6家族EQ6HL45系列芯片,或XilinxSpartan-6系列芯......
  • ROM,FLASH和RAM的区别?
     转载自:ROM,FLASH和RAM的区别-Choris的文章-知乎https://zhuanlan.zhihu.com/p/38339306存储器的种类:ROM、RAM、FLASH-NewLook的文章-知乎https://zhuanlan.zhihu.com/p/640008073 本文非博主所写,博主结合自己的理解对原文做了删改已标明转载作者及出处,仅供学......
  • 关于Cortex-M3报错解决方法总结:Flash Download failed错误
    事情原因:在一次使用ST-LINKv2下载程序时,突然出现Error:FlashDownloadFailed-"Cortex-M3”这个错误,显示没有错误,没有警告。芯片型号接线都没有问题。当时就很摸不着头脑,然后上网查看了一下。原来是因为STM32F103C8T6有64kFlash和20kRAM,tm他们不属于高容量的Flash。所以我改了......
  • Flash8.0下载安装教程
    1、下载地址:https://www.jb51.net/softs/555686.html?pc2、在下载好之后然后双击Flash-chs.exe:出现这个弹窗界面:点击下一步;3、选择我接受协议和条款然后点击下一步;4、自定义存储位置,选择是否创建快捷方式然后直接下一步:点击安装:安装完成之后,出现这样一个弹窗界面......
  • FlashDuty Changelog 2023-09-21 | 自定义字段和开发者中心
    FlashDuty:一站式告警响应平台,前往此地址免费体验!自定义字段FlashDuty已支持接入大部分常见的告警系统,我们将推送内容中的大部分信息放到了Lables进行展示。尽管如此,我们用户还是会有一些扩展或定制性的需求,比如人工标记一个故障是否为误报。因此我们提供了自定义字段功能,......
  • [Unraid 系列 v6.10+] 4 UNRAID Flash 备份目录记录
    说明UNRAID/boot一般为以下目录:root@unraid:/boot#tree-L1.├──EFI├──config├──logs├──syslinux└──......其中./EFI、./logs、syslinux为系统文件夹,一般不涉及用户数据。./config为具体用户数据配置文件。DockerCompose自建STACK......
  • 【FTP】FlashFXP 530 Non-anonymous ... 连接失败(连接已被客户端关闭)
    参考的这个图: ......
  • 【WCH蓝牙系列芯片】-基于CH582开发板—从机主动使能通知(notify)
    -------------------------------------------------------------------------------------------------------------------------------------在EVT例程BLE-UART蓝牙透传功能中,通过串口发送数据至蓝牙时,每次需要开启notify,才能接受新的数据。当串口向蓝牙发送数据后,再打开notif......
  • MTK8183/MT8183安卓4G核心板_联发科安卓手机开发板主板方案定制
    MediaTek MT8183整合先进功能和AI的主流Chromebook平台MTK8183又称为MediaTekKompanio500,是一款支持强大功能的Chromebook平台,结合多种高功能硬件于单一高效能芯片。支持连接选项包括Wi-Fi、蓝芽和GNSS,外围设备可选择连接USB3(5Gbps)和SDIO,以协助品牌厂商能以各种效能水......
  • 迅为RK3588开发板添加 RIL 驱动程序库
    将Quectel提供的相应RIL库文件放入Android系统的以下路径。作者拷贝到了源码的android_build/device/fsl/imx8m/evk_8mm/lib目录下,如下图所示:然后将apns-conf.xml拷贝到android_build/device/fsl/imx8m/evk_8mm/下,如下图所示:B站搜索-北京迅为RK3588开发板,公众Hao关注:......