0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

GD32开发实战指南(基础篇) 第20章 GD32的存储结构

嵌入式大杂烩 来源:嵌入式大杂烩 作者:嵌入式大杂烩 2023-06-03 09:12 次阅读

开发环境:

MDK:Keil 5.30

开发板:GD32F207I-EVAL

MCU:GD32F207IK

1 GD32存储结构的工作原理

1.1 Cortex-M内核的存储器映射

存储器映射是指把芯片中或芯片外的FLASH,RAM,外设,BOOTBLOCK等进行统一编址。即用地址来表示对象。这个地址绝大多数是由厂家规定好的,用户只能用而不能改。用户只能在挂外部RAM或FLASH的情况下可进行自定义。

如下图,是Cortex-M3存储器映射结构图。

1684499765582h595y8083z

Cortex-M3是32位的内核,因此其PC指针可以指向2^32=4G的地址空间,也就是0x0000_0000 - 0xFFFF_FFFF这一大块空间。根据图中描述,Cortex-M3内核将0x0000_0000 - 0xFFFF_FFFF这块4G大小的空间分成8大块:代码、SRAM、外设、外部RAM、外部设备、专用外设总线-内部、专用外设总线-外部、特定厂商等,因此使用该内核的设计者必须按照这个进行各自芯片的存储器结构设计。

1.2 GD32存储器结构

首先,我们对比一下Cortex-M3存储器结构和GD32存储器结构:

C:\\\\Users\\\\BruceOu\\\\Desktop\\\\11.jpg

图中可以很清晰的看到,GD32的存储器结构和Cortex-M3的很相似,不同的是,GD32加入了很多实际的东西,如:Flash、SRAM等。只有加入了这些东西,才能成为一个拥有实际意义的、可以工作的处理芯片-GD32。

GD32的存储器地址空间被划分为大小相等的8块区域,每块区域大小为512MB。

对GD32存储器知识的掌握,实际上就是对Flash和SRAM这两个区域知识的掌握。

2 FLASH读写数据

2.1 GD32的Flash

GD32的Flash,严格说,应该是Flash模块。该Flash模块包括:Flash主存储区(Main memory)、Flash信息区(Information block),以及Flash存储接口寄存器区(Flash memory interface)。三个组成部分分别在0x0000 0000 - 0xFFFF FFFF不同的区域,GD32F2的Flash结构如下表所示。

1684499766584ucx37erq24

【注】信息块存储了boot loader,不能被用户编程或擦除。

GD32的闪存模块由:主存储闪存块、信息块和选项字节块3部分组成。

主存储器 ,该部分用来存放代码和数据常数(如加const类型的数据)。对于主存储闪存容量不多于512KB的GD32F20x_CL,闪存页大小为2KB。对于主存储闪存容量不少于768KB的GD32F20x_CL,使用了两片闪存;前512KB容量在第一片闪存(bank0)中,后续的容量在第二片闪存(bank1)中。其中bank0的闪存页大小为2KB, bank1的闪存页大小为4KB。主存储闪存的每页都可以单独擦除。

__信息__块,是用来存储GD自带的启动程序,用于串口下载,当B0接3.3V,B1接GND时,运行的就这部分代码,用户选择字节,则一般用于配置保护等功能。

选项字节块 ,该部分用于控制闪存储器读取等,是整个闪存储器的控制机构。

对于主存储器和信息块的写入有内嵌的闪存编程管理;编程与擦除的高压由内部产生。

在执行闪存写操作时,任何对闪存的读操作都会锁定总线,在写完成后才能正确进行,在进行读取或擦除操作时,不能进行代码或者数据的读取操作。

下面对GD32的存储器进行总结。

C:\\\\Users\\\\ouxiaolong\\\\Desktop\\\\zaszddf.jpg

图中淡蓝色就是你需要知道的。

  • Peripherals:外设的存储器映射,对该区域操作,就是对相应的外设进行操作;
  • SRAM:运行时临时存放代码的地方;
  • Flash:存放代码的地方;
  • System Memory:GD32出厂时自带的你只能使用,不能写或擦除;
  • Option Bytes:可以按照用户的需要进行配置(如配置看门狗为硬件实现还是软件实现);

今后,你的编写代码、程序运行、寄存器设置、ICP、IAP都依靠这些东西。

2.2 FLASH读写实现

GD32F20x 系列产品的片上 Flash 起始地址时 0x0800 0000,最大容量可达 3072 KB。读操作为 0 等待,可支持字节、半字(16 bits)和字(32 bits)访问。 Flash 编程以半字(16 bits)或字(32bits)为单位。擦除可以以页(page)为单位,也可以进行全片擦除(information blocks 除外)。

Flash的寄存器有很多,当时GD的工程师已经封装好了,直接用就可以,我这里就不在贴出来了。

Flash操作很简单,我们将数据写入到Flash中,再将其读出来。主要有以下步骤:

1.Flash解锁操作

2.清除Flash标志

3.页擦除

4.读写操作

5.锁定

核心代码如下:

#define FLASH_ADR 0x0807F800

/**
  * @brief  flash test
  * @param  WriteAddr, InData
  * @retval OutData
  */
uint32_t flash_test(uint32_t WriteAddr, uint32_t InData)
{
    uint32_t OutData = 0;

    //解锁
    fmc_unlock();
    //清除标志位
    fmc_flag_clear(FMC_FLAG_BANK0_PGERR | FMC_FLAG_BANK0_WPERR | FMC_FLAG_BANK0_END | FMC_FLAG_BANK1_PGERR | FMC_FLAG_BANK1_WPERR | 
    FMC_FLAG_BANK1_END);
    //要擦出页的起始地址
    fmc_page_erase(WriteAddr);
    //写数据
    fmc_word_program(WriteAddr, InData);

    //锁定
    fmc_lock();

    OutData=(*(__IO uint32_t*)(WriteAddr));
    return OutData;
}

程序就不讲了,这里需要注意一个C语言的知识点。

OutData=(*(__IO uint32_t*)(WriteAddr));

这一句很多新手很懵逼,也就是从一个地址中读取数据,多看看指针相关的知识就好理解了。

主函数如下:

/*
    brief      main function
    param[in]  none
    param[out] none
    retval     none
*/
int main(void)
{
    uint32_t InData = 12345678;
    uint32_t OutData;

    // systick init
    sysTick_init();

    //usart init 115200 8-N-1
    com_init(COM1, 115200, 0, 1);

    // led1 init
    led_init(LED1);

    printf("InData = %d\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\r\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n",InData);

    // flash test
    OutData= flash_test(FLASH_ADR, InData);

    printf("OutData = %d\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\r\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n",OutData);

    if(OutData == InData)
    {
        printf("Flash test success !\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\r\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");
    }
    else
    {
        printf("Flash test fail !\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\r\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n");
    }
    while(1)
    {
        led_on(LED1);   // 亮
        delay_ms(1000);
        led_off(LED1);   // 灭 
        delay_ms(1000);
    }
}

2.3 实验结果

将程序边看一完成后下载到板子中,通过串口助手,按下板子的复位按键可以看到如下现象。

168449976724761wuxzkxp2

3 SRAM启动

3.1 GD32的启动模式

首先要回顾一下GD32的启动模式,因为启动模式决定了向量表的位置,GD32有三种启动模式:

1)主闪存存储器(Main Flash)启动:从GD32内置的Flash启动(0x0800 0000-0x0807 FFFF),一般我们使用JTAG或者SWD模式下载程序时,就是下载到这个里面,重启后也直接从这启动程序。以0x08000000 对应的内存为例,则该块内存既可以通过0x00000000 操作也可以通过0x08000000 操作,且都是操作的同一块内存。

2)系统存储器(System Memory)启动:从系统存储器启动(0x1FFFF000 - 0x1FFF F7FF),这种模式启动的程序功能是由厂家设置的。一般来说,我们选用这种启动模式时,是为了从串口下载程序,因为在厂家提供的ISP程序中,提供了串口下载程序的固件,可以通过这个ISP程序将用户程序下载到系统的Flash中。以0x1FFFFFF0对应的内存为例,则该块内存既可以通过0x00000000 操作也可以通过0x1FFFFFF0操作,且都是操作的同一块内存。

3)片上SRAM启动:从内置SRAM启动(0x2000 0000-0x3FFFFFFF),既然是SRAM,自然也就没有程序存储的能力了,这个模式一般用于程序调试。SRAM 只能通过0x20000000进行操作,与上述两者不同。从SRAM 启动时,需要在应用程序初始化代码中重新设置向量表的位置。

用户可以通过设置BOOT0和BOOT1的引脚电平状态,来选择复位后的启动模式。如下图所示:

16844997675999ih3hfv9z9

启动模式只决定程序烧录的位置 ,加载完程序之后会有一个重映射(映射到0x00000000地址位置);真正产生复位信号的时候,CPU还是从开始位置执行。

值得注意的是GD32上电复位以后,代码区都是从0x00000000开始的,三种启动模式只是将各自存储空间的地址映射到0x00000000中。

3.2 GD32的SRAM

不同类型的Cortex-M单片机的SRAM大小是不一样的,但是他们的起始地址都是0x2000 0000,终止地址都是0x2000 0000+其固定的容量大小。

SRAM的理解比较简单,其作用是用来存取各种动态的输入输出数据、中间计算结果以及与外部存储器交换的数据和暂存数据。设备断电后,SRAM中存储的数据就会丢失。

GD32F20x 系列产品的片上 SRAM 起始地址是 0x2000 0000,最大容量可达 384KB,可支持字节、半字(16bits)和字(32bits)访问。 片上 SRAM 被分为 SRAM0、 SRAM1 和 SRAM2 等三个模块,且每个模块都有一个与 AHB 总线矩阵连接的专用接口,这意味着它们可以被同时访问。

模块 容量 地址范围
SRAM1 112KB 0x2000 0000 ~
0x2001 BFFF
SRAM2 16KB 0x2001 C000 ~
0x2001 FFFF
SRAM3 256KB 0x2002 0000 ~
0x2005 FFFF

3.3 片上SRAM启动实现

在使用片上SRAM调试之前,需要了解为何要使用片上SARM来启动程序,因此GD32的片上Flash的擦写次数有限,若超过最大擦除次数则会损坏内部Flash,因此在平时的程序调试阶段,最好使用SRAM启动。

总的来说,SRAM启动程序有如下用途:

1.调试阶段,需要频繁更新程序,可以SRAM启动,加快调试,减少flash擦写损耗

2.程序SWD/JTAG接口已经配置为普通端口,程序启动后无法程序更新,可在SRAM中启动后,再更新flash程序

3.程序已经开启了读保护,可在SRAM启动后,进行读保护关闭

片上SRAM启动实现的方法很简单,这里以GDF207+Keil5举例,实现方法如下:

1.修改内存分配

修改了内存分配,也就是修改分散加载文件xxx.sct文件。

16844997678613pbroii5be

修改后再次生成工程,分散文件也会修改。

1684499768136mcxb3il87a

下面谈谈SRAM参数的分配,首先确定MCU的RAM大小,笔者使用的MCU是GD32F207,因此SRAM大小是256KB,然后还需要根据程序的编译大小来分配SRAM空间。

1684499768519imq0kzsipv

如果想方便点可以直接看MAP文件。

16844997687846pfdozcr9u

FLASH和RAM的大小分别如下:

Flash = Code + RO Data + RW Data = 3.88KB(3968)

RAM = RW-data + ZI-data=8.07KB(8264)

因此笔者这里分配空间如下:

IROM1地址为0x2000 0000, 大小是0x10000=65536=64kB

IRAM1地址为0x2000 3000, 大小是0x20000=131072=128kB

当然啦,SRAM空间分配需要根据自己的 MCU来决定。

2.修改debug配置

新建RAM.ini文件,配置如下:

/*----------------------------------------------------------------------------
 * Name:    RAM.ini
 * Purpose: RAM Debug Initialization File
 * Note(s):
 *----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
  Setup()  configure PC & SP for RAM Debug
 *----------------------------------------------------------------------------*/
FUNC void Setup (void) {
  SP = _RDWORD(0x20000000);          // Setup Stack Pointer
  PC = _RDWORD(0x20000004);          // Setup Program Counter
  _WDWORD(0xE000ED08, 0x20000000);   // Setup Vector Table Offset Register
}

FUNC void OnResetExec (void)  {      // executes upon software RESET
  Setup();                           // Setup for Running
}

load %L incremental

Setup();                             // Setup for Running

g, main

然后加载进来。

168449976904471crcriy6z

RAM.ini文件主要是初始化SP和PC指针。Cortex-M3复位时会从0x00000000和0x00000004的相对位置取出MSP初值以及将复位向量地址赋给PC,在SRAM中的绝对位置就是0x20000000和0x20000004。GD32F207需要手动配置。

C:\\\\Users\\\\BruceOu\\\\Desktop\\\\1.png

3.修改下载配置

需要把程序下载到SRAM,修改相应的下载地址。

1684499769605bhv2p1ahoz

4.修改中断向量表指针

由启动文件可知,程序启动首先执行Reset_Handler函数,SRAM启动硬件强制将PC指针赋值为0x200001E0,PC指针加1开始执行启动文件,故Reset_Handler函数的运行地址需为0x200001E1才行,否则程序就会跑飞。

因此需要在中断向量表的末尾添加SPACE 0x96。

1684499769910zngknxcfmo

同时在在main函数中添加设置中断向量表以及系统初化函数。

nvic_vector_table_set(NVIC_VECTTAB_RAM,0x00);

SystemInit();

5.修改启动模式

这里选择SRAM启动,因此BOOT0->1 BOOT1->1。

最后编译下载程序,然后就可以运行程序了。

1684499770201dea23o8tko

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • FlaSh
    +关注

    关注

    10

    文章

    1645

    浏览量

    148931
  • 存储器
    +关注

    关注

    38

    文章

    7538

    浏览量

    164523
  • RAM
    RAM
    +关注

    关注

    8

    文章

    1369

    浏览量

    115139
  • Cortex-M
    +关注

    关注

    2

    文章

    229

    浏览量

    29874
  • GD32
    +关注

    关注

    7

    文章

    416

    浏览量

    24549
收藏 人收藏

    相关推荐

    GD32开发实战指南(基础) 14 内部温度传感器

    GD32 有一个内部的温度传感器,可以用来测量 CPU 及周围的温度(TA)。该温度传感器在内部和 ADCx_IN16 输入通道相连接,此通道把传感器输出的电压转换成数字值。温度传感器模拟输入
    的头像 发表于 05-17 08:58 5590次阅读
    <b class='flag-5'>GD32</b><b class='flag-5'>开发</b><b class='flag-5'>实战</b><b class='flag-5'>指南</b>(基础<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>14<b class='flag-5'>章</b> 内部温度传感器

    GD32开发实战指南(基础) 16 RTC

    开发环境: MDK:Keil 5.30 开发板:GD32F207I-EVAL MCU:GD32F207IK 1 RTC工作原理 1.1 RTC简介
    的头像 发表于 05-18 22:14 7386次阅读
    <b class='flag-5'>GD32</b><b class='flag-5'>开发</b><b class='flag-5'>实战</b><b class='flag-5'>指南</b>(基础<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>16<b class='flag-5'>章</b> RTC

    GD32和STM32有哪些不同的地方

    一、前言GD32是国内开发的一款单片机,据说开发的人员是来自ST公司的,GD32也是以STM32作为模板做出来的。所以GD32和STM32有
    发表于 08-09 07:03

    什么是GD32

    一、前言什么GD32GD32是国内开发的一款单片机,据说开发的人员是来自ST公司的,GD32也是以STM32作为模板做出来的。所以
    发表于 08-12 07:46

    GD32 MCU原理及固件库开发指南》+读后感

    2介绍GD32 MCU快速入门与开发平台搭建的方法,包括对软硬件开发平台、调试工具、GD32
    发表于 06-06 21:52

    GD32和STM32的区别

    一、前言GD32是国内开发的一款单片机,据说开发的人员是来自ST公司的,GD32也是以STM32作为模板做出来的。所以GD32和STM32有
    发表于 11-18 20:51 47次下载
    <b class='flag-5'>GD32</b>和STM32的区别

    GD32移植到STM32开发平台

    GD32移植到STM32开发平台
    发表于 12-02 14:51 28次下载
    <b class='flag-5'>GD32</b>移植到STM32<b class='flag-5'>开发</b>平台

    GD32选型手册

    GD32选型手册
    发表于 06-17 14:49 68次下载

    STM32、GD32、ESP32的区别

    GD32 是国产单片机,据说开发人员来自ST公司,GD32 也是以 STM32 作为模板做出来的。所以 GD32 和 STM32 有很多地方都是一样的,不过
    的头像 发表于 04-12 09:51 3180次阅读

    GD32开发实战指南(基础) 19 程序加密

    GD32通过读取芯片唯一ID号来实现程序的保护,防止被抄袭。96位的产品唯一身份标识所提供的参考号码对任意一个GD32微控制器
    的头像 发表于 05-20 09:10 4298次阅读
    <b class='flag-5'>GD32</b><b class='flag-5'>开发</b><b class='flag-5'>实战</b><b class='flag-5'>指南</b>(基础<b class='flag-5'>篇</b>) <b class='flag-5'>第</b>19<b class='flag-5'>章</b> 程序加密

    GD32和AT32哪个好?

    GD32和AT32哪个好? GD32和AT32是两种不同的微控制器型号,它们都是国内开发的芯片。GD32系列由国内芯片制造商GigaDevice Semiconductor
    的头像 发表于 08-16 11:32 2720次阅读

    GD32与STM32兼容吗?

    GD32与STM32兼容吗? GD32与STM32是两个不同的微控制器系列,是由两个不同的公司设计和生产的。GD32系列是由国内的长沙国芯微电子设计和生产的,而STM32系列则是由欧洲
    的头像 发表于 08-16 11:32 3066次阅读

    STM32与GD32横向对比区别

    GD32 是国产单片机,据说开发人员来自ST公司,GD32 也是以 STM32 作为模板做出来的。所以 GD32 和 STM32 有很多地方都是一样的
    的头像 发表于 09-13 11:47 3779次阅读
    STM32与<b class='flag-5'>GD32</b>横向对比区别

    GD32如何替换STM32?

    GD32如何替换STM32?
    的头像 发表于 09-18 10:58 2383次阅读
    <b class='flag-5'>GD32</b>如何替换STM32?

    GD32 MCU入门教程】GD32 MCU GPIO 结构与使用注意事项

    本文是专门为基于GD32 MCU开发的工程设计人员提供,主要介绍了GPIO的功能配置、内部结构以及在不同场景使用时的注意事项,旨在帮助GD32 MCU
    的头像 发表于 09-07 10:34 990次阅读
    【<b class='flag-5'>GD32</b> MCU入门教程】<b class='flag-5'>GD32</b> MCU GPIO <b class='flag-5'>结构</b>与使用注意事项