查看: 1844|回复: 0
收起左侧

第八十九章:CH32V103应用教程——FLASH编程

[复制链接]

  离线 

  • TA的每日心情
    慵懒
    2021-7-23 17:16
  • 签到天数: 17 天

    [LV.4]

    发表于 2021-5-1 16:54:37 | 显示全部楼层 |阅读模式

    有人预言,RISC-V或将是继Intel和Arm之后的第三大主流处理器体系。欢迎访问全球首家只专注于RISC-V单片机行业应用的中文网站

    您需要 登录 才可以下载或查看,没有帐号?立即注册

    x
    本帖最后由 草帽王子 于 2021-9-10 18:24 编辑

    本章主要使用CH32V103进行FLASH的擦/读/写,以及快速编程。


    1、FLASH简介及相关函数介绍

    关于CH2V103的FLSAH,其支持2种编程/擦除方式,具体如下:
    • 标准编程:此方式是默认编程方式(兼容方式)。这种模式下CPU以单次2字节方式执行编程,单次1K字节执行擦除及整片擦除操作。
    • 快速编程:此方式采用页操作方式(推荐)。经过特定序列解锁后,执行单次128字节的编程及128字节擦除。

    关于FLASH编程,本次所用库函数中具体函数如下:
    (1)FLASH_Unlock函数:此函数主要用于解锁闪存程序擦除控制器。
    (2)FLASH_GetWriteProtectionOptionByte函数:此函数主要用于返回闪存写保护选项字节寄存器值。
    (3)FLASH_ClearFlag函数:此函数主要用于清除闪存的挂起标志。
    (4)FLASH_ErasePage函数:此函数主要用于擦除指定的闪存页。
    (5)FLASH_ProgramHalfWord函数:此函数主要用于在指定的地址编写半个字的程序。
    (6)FLASH_Lock函数:此函数主要用于锁定闪存程序擦除控制器。
    (7)FLASH_Unlock_Fast函数:此函数主要用于解锁快速程序擦除模式。
    (8)FLASH_ErasePage_Fast函数:此函数主要用于擦除指定的闪存页(1页=128字节)。
    (9)FLASH_BufReset函数:此函数主要用于闪存缓冲复位。
    (10)FLASH_BufLoad函数:此函数主要用于闪存缓冲区加载(128位)。
    (11)FLASH_ProgramPage_Fast函数:此函数主要用于编程指定的闪存页(1页=128字节)。
    (12)FLASH_Lock_Fast函数:此函数主要用于锁定快速程序擦除模式。

    以上就是本次程序中所要用到的函数,关于ch32v10x_flash.c文件中的其他函数,感兴趣可对照注释以及函数内容进行了解。关于FLASH操作流程,可参考CH32V103应用手册。


    2、硬件设计

    本章教程主要FLASH编程操作,无需进行硬件设计。


    3、软件设计

    FLASH编程操作具体程序如下:
    flash.h文件
    1. #ifndef  __FLASH_H
    2. #define  __FLASH_H

    3. #include "ch32v10x_conf.h"

    4. /* Global define */
    5. typedef enum
    6. {
    7.     FAILED = 0,
    8.     PASSED = !FAILED
    9. } TestStatus;

    10. #define  PAGE_WRITE_START_ADDR       ((uint32_t)0x0800F000) /* Start from 60K */
    11. //#define  PAGE_WRITE_START_ADDR       ((uint32_t)0x0800E000) /* Start from 56K */

    12. #define  PAGE_WRITE_END_ADDR         ((uint32_t)0x08010000) /* End at 63K */
    13. //#define  PAGE_WRITE_END_ADDR         ((uint32_t)0x0800F000) /* End at 59K */

    14. #define  FLASH_PAGE_SIZE             1024

    15. //#define  FLASH_PAGES_TO_BE_PROTECTED FLASH_WRProt_Pages60to63
    16. #define  FLASH_PAGES_TO_BE_PROTECTED FLASH_WRProt_Pages56to59

    17. void Flash_Test(void);
    18. void Flash_Test_Fast(void);


    19. #endif
    复制代码
    flash.h文件主要进行相关定义和函数声明;
    flash.c文件
    1. #include "flash.h"

    2. /* Global Variable */
    3. uint32_t EraseCounter = 0x0, Address = 0x0;
    4. uint16_t Data = 0xAAAA;
    5. uint32_t WRPR_Value = 0xFFFFFFFF, ProtectedPages = 0x0;
    6. uint32_t NbrOfPage;
    7. volatile FLASH_Status FLASHStatus = FLASH_COMPLETE;

    8. volatile TestStatus MemoryProgramStatus = PASSED;
    9. volatile TestStatus MemoryEraseStatus = PASSED;

    10. /*******************************************************************************
    11. * Function Name  : Flash_Test
    12. * Description    : Flash Program Test.
    13. * Input          : None
    14. * Return         : None
    15. *******************************************************************************/
    16. void Flash_Test(void)
    17. {

    18.   //系统复位后,闪存控制器(FPEC)和 FLASH_CTLR 寄存器是被锁定的,不可访问。通过写入序列到 FLASH_KEYR 寄存器可解锁闪存控制器模块。
    19.   //解锁序列:
    20.   //1)向 FLASH_KEYR 寄存器写入 KEY1 = 0x45670123(第 1 步必须是 KEY1);
    21.   //2)向 FLASH_KEYR 寄存器写入 KEY2 = 0xCDEF89AB(第 2 步必须是 KEY2)。
    22.   //解锁闪存器
    23.   FLASH_Unlock();
    24.   
    25.   //读取写保护寄存器的值  1:写保护失效  0:写保护有效
    26.   //每个比特位代表 4K 字节(32 页)存储写保护状态
    27.   //WPR在系统复位后从用户选择字区域加载
    28.   WRPR_Value = FLASH_GetWriteProtectionOptionByte();
    29.   printf("WRPR_Value = %x\n",WRPR_Value);

    30.   //PAGE_WRITE_START_ADDR:写入的起始地址     PAGE_WRITE_END_ADDR:结束地址     FLASH_PAGE_SIZE:一页大小,1024字节     NbrOfPage:记录要擦除的页数
    31.   NbrOfPage = (PAGE_WRITE_END_ADDR - PAGE_WRITE_START_ADDR) / FLASH_PAGE_SIZE;


    32.   if ( (WRPR_Value & FLASH_PAGES_TO_BE_PROTECTED) != 0x00)
    33.   {
    34.     //FLASH_FLAG_BSY:指示忙状态  1:表示闪存操作正在进行;0:操作结束或发生错误
    35.     //FLASH_FLAG_EOP:指示操作结束,写1清零
    36.     //FLASH_FLAG_PGERR:指示编程错误,写1清零
    37.     //FLASH_FLAG_WRPRTERR:只是写保护错误,写1清零
    38.     //清除挂起标志
    39.     FLASH_ClearFlag(FLASH_FLAG_BSY | FLASH_FLAG_EOP|FLASH_FLAG_PGERR |FLASH_FLAG_WRPRTERR);

    40.     //EraseCounter:擦除计数     NbrOfPage:记录要擦除的页数
    41.     for(EraseCounter = 0; (EraseCounter < NbrOfPage) && (FLASHStatus == FLASH_COMPLETE); EraseCounter++)
    42.     {
    43.       //FLASH Status: The returned value can be: FLASH_BUSY, FLASH_ERROR_PG,FLASH_ERROR_WRP, FLASH_COMPLETE or FLASH_TIMEOUT.
    44.       //FLASH_ErasePage:擦除指定的闪存页,此函数包含应用手册介绍主存储器标准擦除操作的2、3、4步
    45.       FLASHStatus = FLASH_ErasePage(PAGE_WRITE_START_ADDR + (FLASH_PAGE_SIZE * EraseCounter));

    46.       //FLASH_COMPLETE:FLASH擦除完成标志
    47.       if(FLASHStatus != FLASH_COMPLETE)
    48.       {
    49.         printf("FLASH Erase ERR at Page%d\r\n",EraseCounter+60);
    50.       }

    51.       printf("FLASH Erase Page%d...\r\n",EraseCounter+60);
    52.     }

    53.     //Address:写入地址     PAGE_WRITE_START_ADDR:写入的起始地址
    54.     Address = PAGE_WRITE_START_ADDR;

    55.     printf("Erase Cheking...\r\n");
    56.     while((Address < PAGE_WRITE_END_ADDR) && (MemoryEraseStatus != FAILED))
    57.     {
    58.       if((*(__IO uint16_t*) Address) != 0xFFFF)
    59.       {
    60.         MemoryEraseStatus = FAILED;
    61.        }
    62.         Address += 2;
    63.     }
    64.     if(MemoryEraseStatus == FAILED)
    65.     {
    66.       printf("Erase Flash FAIL!\r\n");
    67.       printf("\r\n");
    68.     }
    69.     else
    70.     {
    71.       printf("Erase Flash PASS!\r\n");
    72.       printf("\r\n");
    73.     }


    74.     Address = PAGE_WRITE_START_ADDR;
    75.     printf("Programing...\r\n");
    76.     while((Address < PAGE_WRITE_END_ADDR) && (FLASHStatus == FLASH_COMPLETE))
    77.     {
    78.       FLASHStatus = FLASH_ProgramHalfWord(Address, Data);
    79.       Address = Address + 2;
    80.       //printf("Write address:%08x\r\n",Address);
    81.     }

    82.     Address = PAGE_WRITE_START_ADDR;
    83.     printf("Program Cheking...\r\n");
    84.     while((Address < PAGE_WRITE_END_ADDR) && (MemoryProgramStatus != FAILED))
    85.     {
    86.       if((*(__IO uint16_t*) Address) != Data)
    87.       {
    88.         MemoryProgramStatus = FAILED;
    89.        }
    90.         Address += 2;
    91.      }
    92.      if(MemoryProgramStatus == FAILED)
    93.      {
    94.        printf("Memory Program FAIL!\r\n");
    95.        printf("\r\n");
    96.      }
    97.      else
    98.      {
    99.        printf("Memory Program PASS!\r\n");
    100.        printf("\r\n");
    101.      }

    102.    }
    103.    else
    104.    {
    105.      MemoryProgramStatus = FAILED;
    106.      printf("Error to program the flash : The desired pages are write protected\r\n");
    107.    }

    108.    FLASH_Lock();

    109. }

    110. /*******************************************************************************
    111. * Function Name  : Flash_Test_Fast
    112. * Description    : Flash Fast Program Test.(128Byte±à³Ì)
    113. * Input          : None
    114. * Return         : None
    115. *******************************************************************************/
    116. void Flash_Test_Fast(void)
    117. {
    118.     u8 i, Verity_Flag=0;
    119.     u32 buf[32];

    120.     for(i=0; i<32; i++)
    121.     {
    122.         buf[i] = i;
    123.     }

    124.     //快速变成模式解锁
    125.     FLASH_Unlock_Fast();

    126.     //擦除指定的闪存页
    127.     FLASH_ErasePage_Fast(0x0800E000);

    128.     printf("128Byte Page Erase Sucess\r\n");

    129.     //闪存缓冲复位
    130.     FLASH_BufReset();

    131.     //闪存缓冲区加载(128位)。
    132.     FLASH_BufLoad(0x0800E000, buf[0], buf[1], buf[2], buf[3]);
    133.     FLASH_BufLoad(0x0800E000 + 0x10, buf[4], buf[5], buf[6], buf[7]);
    134.     FLASH_BufLoad(0x0800E000 + 0x20, buf[8], buf[9], buf[10], buf[11]);
    135.     FLASH_BufLoad(0x0800E000 + 0x30, buf[12], buf[13], buf[14], buf[15]);
    136.     FLASH_BufLoad(0x0800E000 + 0x40, buf[16], buf[17], buf[18], buf[19]);
    137.     FLASH_BufLoad(0x0800E000 + 0x50, buf[20], buf[21], buf[22], buf[23]);
    138.     FLASH_BufLoad(0x0800E000 + 0x60, buf[24], buf[25], buf[26], buf[27]);
    139.     FLASH_BufLoad(0x0800E000 + 0x70, buf[28], buf[29], buf[30], buf[31]);

    140.     //编程指定的闪存页(1页=128字节)。
    141.     FLASH_ProgramPage_Fast(0x0800E000);

    142.     printf("128Byte Page Program Sucess\r\n");

    143.     FLASH_Lock_Fast();

    144.     for(i=0; i<32; i++)
    145.     {
    146.         if(buf[i] == *(u32*)(0x0800E000 + 4*i))
    147.         {
    148.             Verity_Flag = 0;
    149.         }
    150.         else
    151.         {
    152.             Verity_Flag = 1;
    153.             break;
    154.         }
    155.     }

    156.     if(Verity_Flag) printf("128Byte Page Verity Fail\r\n");
    157.     else printf("128Byte Page Verity Sucess\r\n");
    158. }
    复制代码
    flash.c文件主要包括。关于几个函数的具体介绍,在程序中都有详细注释,在此不再赘述。
    main.c文件
    1. /********************************** (C) COPYRIGHT *******************************
    2. * File Name          : main.c
    3. * Author             : WCH
    4. * Version            : V1.0.0
    5. * Date               : 2020/04/30
    6. * Description        : Main program body.
    7. *******************************************************************************/

    8. #include "debug.h"
    9. #include "flash.h"


    10. /* Global typedef */

    11. /* Global define */

    12. /* Global Variable */


    13. /*******************************************************************************
    14. * Function Name  : main
    15. * Description    : Main program.
    16. * Input          : None
    17. * Return         : None
    18. *******************************************************************************/
    19. int main(void)
    20. {
    21.     NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    22.     Delay_Init();
    23.     USART_Printf_Init(115200);
    24.     printf("SystemClk:%d\r\n",SystemCoreClock);
    25.     printf("Flash Program Test\r\n");

    26.     Flash_Test();
    27.     Flash_Test_Fast();

    28.     while(1)
    29.     {
    30.         ;
    31.     }
    32. }
    复制代码
    main.c文件主要进行函数初始化。


    4、下载验证

    将编译好的程序下载到开发版并复位,串口打印显示如下:
    CH32V CH573单片机芯片-第八十九章:CH32V103应用教程——FLASH编程risc-v单片机中文社区(1)
    88、Flash编程.rar
    CH32V CH573单片机芯片-第八十九章:CH32V103应用教程——FLASH编程risc-v单片机中文社区(2) 88、Flash编程.rar (480.76 KB, 下载次数: 19)
    链接:https://pan.baidu.com/s/1Ck4QHSruSouG1ypLMxkkBw
    提取码:tkle
    复制这段内容后打开百度网盘手机App,操作更方便哦







    上一篇:第八十八章:CH32V103应用教程——步进电机驱动
    下一篇:第九十章:CH32V103应用教程——ADC-DMA-TIM3触发ADC转换
    RISCV作者优文
    全球首家只专注于RISC-V单片机行业应用的中文网站
    回复

    使用道具 举报

    高级模式
    B Color Image Link Quote Code Smilies

    本版积分规则

    关闭

    RISC-V单片机中文网上一条 /2 下一条



    版权及免责声明|RISC-V单片机中文网 |网站地图

    GMT+8, 2024-4-24 05:12 , Processed in 0.530313 second(s), 48 queries .

    快速回复 返回顶部 返回列表