[研电赛技术支持] GD32ARM存储器

[复制链接]
51|0
磨砂 发表于 2026-2-4 13:23 | 显示全部楼层 |阅读模式
1.0 简介

86749698187188b7e9.png

ARM(Advanced RISC Machine)架构的存储器系统是其设计中的关键部分,它不仅影响着处理器的性能,还决定了系统的整体效率和功耗。以下是关于ARM存储器的一些基本概念和特性介绍:

2.0 芯片内部结构

8443669818711d387c.png

注:芯片的内部结构包含矩阵存储器,地址译码器,控制电路,每个控制电流都包含对应的功能

533146981870d65812.png

注:以上对应引脚的地址,给出特定的功能,这里的数据线有16根,也就是数据的位数是16位的那么:也可以称16根数据线,所以它的访问数据宽度为16位,2个字节,19根地址线一共可以表示0~111 1111 11111111 1111地址范围,2^19=2^9x1024=512K个16位数据宽度的存储单元,所以能访问512Kx16bits大小的空间:为了能够细粒度到访问16位宽度的高8位或低8位,又使用UB或LB线控制。

3.0 SRAM存储器的时序
读写时序的流程如下:

1.0 主机使用地址信号线发出要访问的存储器目标地址

2.0 控制片选信号CS1使能存储器芯片

3.0 若是要进行读操作,则控制读使能信号OE表示要读数据

4.0 若进行写操作则控制写使能信号WE表示要写数据

5.0 使用掩码信号LB与UB指示要访问目标地址的高、低字节部分

6.0 若是读取过程,存储器会通过数据线向主机输出目标数据

7.0 若是写入过程,主要使用数据线向存储器传输目标数据

4.0 SRAM芯片时序

36546698187048b8d5.png

936716981870065d95.png

5.0 EXMC 存储器映射
单片机通过地址来访问寄存器、RAM、FLASH,ARM寻址范围4GB,分为多个块:

48974698186fbb94ea.png

EXMC外设可以用来驱动外部扩展的存储器,包括SRAM、NOR FLASH以及NAND FLSAH类型的存储器,但不能驱动如DRAM这种动态的存储器。

EXMC地址区域又分成了4个Bank,每个Bank占256M字节空间,并分配了地址范围及适用驱动的存储器类型如NOR FLASH及SRAM存储器只能使用Bank1的地址来访问和驱动。

9492698186f6529b1.png

注:这里每个EXMC分为四个块,整个EXMC的总大小是1G,而分为四个区域每个区域的大小是256MB, 然后每个blank块分别用于存储不同外部存储器的数据。

在NOR及SRAM区域又分成了4个小块,每个小块有相应的控制引脚(EXMC NE[3:0])可以作为芯片片选信号如访问0x68000000-0x6BFFFFFF地址空间时,会访问到的Region2区域,相应的EXMC NE2信号线会输出低电平控制信号。

99242698186f1ca9eb.png

存储器映射EXMC对应引脚图:

52174698186edd68d3.png

注:一般情况下一个地址对应的大小就是一个字节,比如我们想往外部存储器写数据10,也就是往D0里面写数据10,这个时候通过系统总线HA0给一个地址,然后地址给EXMC存储器映射,也就是给到我们MCU对外引出的引脚,然后引脚在连接到对应的外部设备,然后将数据存储到外部设备中。

46483698186e8abdac.png

注:如果我们存储的数据不是8位的而是16位的会比较的难处理,因为系统总线默认是8位的,这个时候从外部过来就需要往左移动一位,相当于数MA0连接到HA1这个引脚,然后再使用掩码信号访问来解决是访问的高8位还是低8位。

60469698186e470985.png

6.0 EXMC控制SRAM时序

77228698186dfa986a.png

当要访问某个指向外部存储器地址时,EXMC会根据配置控制信号线产生时序访问存储器,上图
中是访问外部SRAM时的读时序。

该时序由一个存储器操作期由地址建立周期(ADDSET)、数据建立周期(DATAST)以及2个HCLK周期组成。在地址建立周期中,地址线发出要访问的地址,数据掩码信号线指示出要读取地址的高、低字节部分,片选信号使能存储器芯片;

地址建立周期结束后读使能信号线发出读使能信号,接着存储器通过数据信号线把目标数据
传输给EXMC,EXMC再交给内核。

写时序

49148698186d88a8ac.png

写时序类似,区别是它的一个存储器操作周期仅由地址建立周期(ADDSET)和数据建立周期(DATAST)组成,且在数据建立周期期间写使能信号线发出写信号,接着EXMC将数据通过
数据线传输到存储器中。

7.0 FLASH空间布局

13594698186d33b911.png

最终烧写到单片机flash中的文件大小:Code+RO +RW,Program Size:Code=276 RO-data=992 RW-data=4Zl-data=1028。

8.0 RAM区域

75108698186ccdeea6.png

9.0 程序实现
9.0.1原理图

26802698186c774641.png

9.0.2 宏定义外部存储器
注:这个位置表示存储器的存储位置,表示哪一个外部存储器块,和存储器块中的哪一个位置

/**
* @brief  宏定义缓冲区
* @param  无参数
* @return 无返回值
* @author tao.Huang
*/
#define BANK0_REGON3_ADDR ((uint32_t)0x6C000000)    // bank0 regon3起始地址
#define EXMC_SRAM_BUFFER_SIZE (1 * 1024 * 1024)     // 外部SRAM缓冲区大小,1M字节
#define EXMC_SRAM_BEGIN_ADDR (BANK0_REGON3_ADDR)    // 存储器映射起始地址
#define EXMC_SRAM_END_ADDR (BANK0_REGON3_ADDR + EXMC_SRAM_BUFFER_SIZE - 1)  // 0x6c100000 - 1



76434698186be248c7.png

注:分为每一个块,然后每一个块占用的存储空间大小是256M

51289698186b947008.png

9.0.3 RCU使能GPIO时钟
    rcu_periph_clock_enable(RCU_GPIOD); // 使能GPIOD的时钟
    rcu_periph_clock_enable(RCU_GPIOE); // 使能GPIOE的时钟
    rcu_periph_clock_enable(RCU_GPIOF); // 使能GPIOF的时钟
    rcu_periph_clock_enable(RCU_GPIOG); // 使能GPIOG的时钟


注:下面的引脚表示的是端口对应的引脚定义图

82227698186b10d7e0.png

9.0.4 初始化地址总线
    /* 地址总线 */
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0);  // A0
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1);  // A1
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_2);  // A2
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_3);  // A3
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_4);  // A4
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_5);  // A5
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); // A6
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13); // A7
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_14); // A8
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_15); // A9
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0);  // A10
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1);  // A11
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_2);  // A12
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_3);  // A13
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_4);  // A14
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_5);  // A15
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_11); // A16
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); // A17
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13); // A18



41568698186a855b57.png

9.0.5 初始化数据总线
    /* 数据总线 */
        gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_14); //D0
        gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_15); //D1
        gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0 ); //D2
        gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1 ); //D3
        gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_7 ); //D4
        gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_8 ); //D5
        gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_9 ); //D6
        gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_10); //D7
        gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_11); //D8
        gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); //D9
        gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13); //D10
        gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_14); //D11
        gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_15); //D12
        gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_8 ); //D13
        gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_9 ); //D14
        gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_10); //D15



74735698186a11e8d3.png

9.0.6 初始化控制总线
    /* 控制信号 */
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_9);  // EXMC_NE1
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_4);  // EXMC_NOE
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_5);  // EXMC_NWE
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); // EXMC_NE3
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0);  // EXMC_NBL0
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1);  // EXMC_NBL1

210969818697ee2ca.png


/**
* @brief  外部存储器映射GPIO初始化
* @param  void
* @return 无返回值
* @author tao.Huang
*/
static void Config_Exmc_Gpio(void)
{
    rcu_periph_clock_enable(RCU_GPIOD); // 使能GPIOD的时钟
    rcu_periph_clock_enable(RCU_GPIOE); // 使能GPIOE的时钟
    rcu_periph_clock_enable(RCU_GPIOF); // 使能GPIOF的时钟
    rcu_periph_clock_enable(RCU_GPIOG); // 使能GPIOG的时钟

    /* 地址总线 */
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0);  // A0
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1);  // A1
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_2);  // A2
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_3);  // A3
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_4);  // A4
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_5);  // A5
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); // A6
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13); // A7
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_14); // A8
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_15); // A9
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0);  // A10
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1);  // A11
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_2);  // A12
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_3);  // A13
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_4);  // A14
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_5);  // A15
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_11); // A16
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); // A17
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13); // A18

    /* 数据总线 */
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_14); // D0
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_15); // D1
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0);  // D2
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1);  // D3
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_7);  // D4
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_8);  // D5
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_9);  // D6
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_10); // D7
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_11); // D8
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); // D9
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13); // D10
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_14); // D11
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_15); // D12
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_8);  // D13
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_9);  // D14
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_10); // D15

    /* 控制信号 */
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_9);  // EXMC_NE1
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_4);  // EXMC_NOE
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_5);  // EXMC_NWE
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); // EXMC_NE3
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0);  // EXMC_NBL0
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1);  // EXMC_NBL1
}



9.0.7 控制块函数
注:以下的是程序的原码,结构体定义中包含的参数,值有使能或者是失能

/* EXMC NOR/SRAM timing initialize struct */
typedef struct
{
    uint32_t asyn_access_mode;                                          /*!< asynchronous access mode */
    uint32_t syn_data_latency;                                          /*!< configure the data latency */
    uint32_t syn_clk_division;                                          /*!< configure the clock divide ratio */
    uint32_t bus_latency;                                               /*!< configure the bus latency */
    uint32_t asyn_data_setuptime;                                       /*!< configure the data setup time,asynchronous access mode valid */
    uint32_t asyn_address_holdtime;                                     /*!< configure the address hold time,asynchronous access mode valid */
    uint32_t asyn_address_setuptime;                                    /*!< configure the data setup time,asynchronous access mode valid */
}exmc_norsram_timing_parameter_struct;
------------------|----------------|----------------

/* EXMC NOR/SRAM initialize struct */
typedef struct
{
    uint32_t norsram_region;                                            /*!< select the region of EXMC NOR/SRAM bank */
    uint32_t write_mode;                                                /*!< the write mode, synchronous mode or asynchronous mode */
    uint32_t extended_mode;                                             /*!< enable or disable the extended mode */
    uint32_t asyn_wait;                                                 /*!< enable or disable the asynchronous wait function */
    uint32_t nwait_signal;                                              /*!< enable or disable the NWAIT signal while in synchronous bust mode */
    uint32_t memory_write;                                              /*!< enable or disable the write operation */
    uint32_t nwait_config;                                              /*!< NWAIT signal configuration */
    uint32_t wrap_burst_mode;                                           /*!< enable or disable the wrap burst mode */
    uint32_t nwait_polarity;                                            /*!< specifies the polarity of NWAIT signal from memory */
    uint32_t burst_mode;                                                /*!< enable or disable the burst mode */
    uint32_t databus_width;                                             /*!< specifies the databus width of external memory */
    uint32_t memory_type;                                               /*!< specifies the type of external memory */
    uint32_t address_data_mux;                                          /*!< specifies whether the data bus and address bus are multiplexed */
    exmc_norsram_timing_parameter_struct* read_write_timing;            /*!< timing parameters for read and write if the extended mode is not used or the timing
                                                                             parameters for read if the extended mode is used */
    exmc_norsram_timing_parameter_struct* write_timing;                 /*!< timing parameters for write when the extended mode is used */
}exmc_norsram_parameter_struct;



/**
* @brief  外部存储器映射控制
* @param  void
* @return 无返回值
* @author tao.Huang
*/
static void Config_Bank0_Region3(void)
{
    exmc_norsram_parameter_struct sramInitStruct;
    exmc_norsram_timing_parameter_struct sramTimingInitStruct;
    exmc_norsram_struct_para_init(&sramInitStruct);

    // 外部读写时序
    sramTimingInitStruct.asyn_access_mode = EXMC_ACCESS_MODE_A; //模式A,异步访问SRAM
    sramTimingInitStruct.asyn_address_setuptime = 0;            // 异步访问地址建立时间
    sramTimingInitStruct.asyn_address_holdtime  = 0;            // 异步访问地址保持时间
    sramTimingInitStruct.asyn_data_setuptime    = 0;            // 异步访问数据建立时间
    sramTimingInitStruct.bus_latency                         = 0;            // 异步/同步访问总线延迟时间
    sramTimingInitStruct.syn_clk_division = 0;                  // 同步访问时钟分频系数(从HCLK中分频)
    sramTimingInitStruct.syn_data_latency = 0;                  // 同步访问中获得第1个数据所需要的等待延迟

    /* Region3配置 */
    sramInitStruct.norsram_region = EXMC_BANK0_NORSRAM_REGION3; // Region3
    sramInitStruct.address_data_mux = DISABLE;                  // 禁用地址、数据总线多路复用
    sramInitStruct.memory_type = EXMC_MEMORY_TYPE_SRAM;         // 储存器类型为SRAM
    sramInitStruct.databus_width = EXMC_NOR_DATABUS_WIDTH_16B;  // 数据宽度16位
    sramInitStruct.burst_mode = DISABLE;                        // 禁用突发访问
    sramInitStruct.nwait_config = EXMC_NWAIT_CONFIG_BEFORE;     // 等待输入配置
    sramInitStruct.nwait_polarity = EXMC_NWAIT_POLARITY_LOW;    // 等待输入信号低电平有效
    sramInitStruct.wrap_burst_mode = DISABLE;                   // 禁用包突发访问
    sramInitStruct.asyn_wait = DISABLE;                         // 禁用异步等待
    sramInitStruct.extended_mode = DISABLE;                     // 禁用扩展模式
    sramInitStruct.memory_write = ENABLE;                       // 使能写入外部存储器
    sramInitStruct.nwait_signal = DISABLE;                      // 禁用等待输入信号
    sramInitStruct.write_mode = EXMC_ASYN_WRITE;                // 写入模式为异步写入
    sramInitStruct.read_write_timing = &sramTimingInitStruct;   // 读写时序配置

    /* 初始化Region3 */
    exmc_norsram_init(&sramInitStruct);

    /* 使能Region3 */
    exmc_norsram_enable(EXMC_BANK0_NORSRAM_REGION3);
}



注:以上是外部存储器映射控制代码程序

9.0.8 SRAM初始化函数

1745469818670061e9.png

/**
* @brief  SRAM初始化函数
* @param  void
* @return 无返回值
* @author tao.Huang
*/
void ExSramDrvInit(void)
{
    Config_Exmc_Gpio();
    Config_Bank0_Region3();
}



9.0.8 补充知识点
格式 `0x%02X` 是一种常见的格式化字符串,用于在编程语言中将数值(通常是整数)转换为十六进制表示形式。具体来说:

- **`0x`**:这是十六进制数的前缀,表明后面跟随的是一个以16为基数的数字。这个前缀是C语言及其衍生语言(如C++、Java等)中约定俗成的表示方法。

- **`%02X`**:这部分是格式说明符,用来告诉编译器或解释器如何格式化输出:
  - **`%`**:表示接下来是一个格式化的指令。
  - **`02`**:指定了最小宽度为2个字符。如果转换后的值不足两位,则用前导零填充,确保输出总是两个字符宽。
  - **`X`**:表示将整数转换为大写的十六进制表示。如果是小写的 `x`,则会使用小写字母a-f来表示10到15的值;而大写的 `X` 则会使用A-F。

### 示例

假设你有一个整数值 `15`,当你使用 `printf("0x%02X", 15);` 或者类似的语句时,它将会输出 `0x0F`。同样地,对于整数值 `255`,使用相同的格式化字符串将会输出 `0xFF`。

这种格式化方式常用于调试信息输出、日志记录或者需要明确展示数值的二进制或十六进制表示的情况下,尤其是在嵌入式系统开发、驱动程序编写或其他低级编程任务中。

如果你有具体的编程语言或上下文,请提供更多信息,这样我可以给出更针对性的帮助。

187426981865c7bb83.png

注:全局变量初始化后的位置是放在flash中的,一个是RW区域一个是RO区域,这些数据初始化时是保存在flash的内存空间中的,当程序运行起来后这些数据是保存在内存当中的data段中

32122698186565bc7f.png

这个阶段是在.S汇编启动文件中完成的,先是调用Systeminit文件然后再调用main函数

77969698186523d1fa.png

所以执行的顺序如下所示:

978436981864e04d59.png

将SRAM硬件初始化放到_main之前,放到SystemInit.c接口函数中调用

289666981864615df6.png

9.0.9 完整程序
头文件

#ifndef _EXSRAM_DRV_H_
#define _EXSRAM_DRV_H_

#include <stdint.h>
#include <stdlib.h>

void ExSramDrvInit(void);
void ExSramDrvTest(void);

#endif


-------------------|-----------------|-----------

#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdbool.h>
#include "gd32f30x.h"

/**
* @brief  宏定义缓冲区
* @param  无参数
* @return 无返回值
* @author tao.Huang
*/
#define BANK0_REGON3_ADDR ((uint32_t)0x6C000000)                           // bank0 regon3起始地址
#define EXMC_SRAM_BUFFER_SIZE (1 * 1024 * 1024)                            // 外部SRAM缓冲区大小,1M字节
#define EXMC_SRAM_BEGIN_ADDR (BANK0_REGON3_ADDR)                           // 存储器映射起始地址
#define EXMC_SRAM_END_ADDR (BANK0_REGON3_ADDR + EXMC_SRAM_BUFFER_SIZE - 1) // 0x6c100000 - 1

/**
* @brief  外部存储器映射GPIO初始化
* @param  void
* @return 无返回值
* @author tao.Huang
*/
static void Config_Exmc_Gpio(void)
{
    rcu_periph_clock_enable(RCU_GPIOD); // 使能GPIOD的时钟
    rcu_periph_clock_enable(RCU_GPIOE); // 使能GPIOE的时钟
    rcu_periph_clock_enable(RCU_GPIOF); // 使能GPIOF的时钟
    rcu_periph_clock_enable(RCU_GPIOG); // 使能GPIOG的时钟

        rcu_periph_clock_enable(RCU_EXMC);        // 使能EXMC时钟
       
    /* 地址总线 */
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0);  // A0
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1);  // A1
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_2);  // A2
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_3);  // A3
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_4);  // A4
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_5);  // A5
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); // A6
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13); // A7
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_14); // A8
    gpio_init(GPIOF, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_15); // A9
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0);  // A10
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1);  // A11
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_2);  // A12
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_3);  // A13
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_4);  // A14
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_5);  // A15
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_11); // A16
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); // A17
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13); // A18

    /* 数据总线 */
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_14); // D0
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_15); // D1
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0);  // D2
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1);  // D3
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_7);  // D4
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_8);  // D5
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_9);  // D6
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_10); // D7
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_11); // D8
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); // D9
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_13); // D10
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_14); // D11
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_15); // D12
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_8);  // D13
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_9);  // D14
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_10); // D15

    /* 控制信号 */
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_9);  // EXMC_NE1
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_4);  // EXMC_NOE
    gpio_init(GPIOD, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_5);  // EXMC_NWE
    gpio_init(GPIOG, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_12); // EXMC_NE3
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_0);  // EXMC_NBL0
    gpio_init(GPIOE, GPIO_MODE_AF_PP, GPIO_OSPEED_MAX, GPIO_PIN_1);  // EXMC_NBL1
}

/**
* @brief  外部存储器映射控制
* @param  void
* @return 无返回值
* @author tao.Huang
*/
static void Config_Bank0_Region3(void)
{
    exmc_norsram_parameter_struct sramInitStruct;
    exmc_norsram_timing_parameter_struct sramTimingInitStruct;
    exmc_norsram_struct_para_init(&sramInitStruct);

    // 外部读写时序
    sramTimingInitStruct.asyn_access_mode = EXMC_ACCESS_MODE_A; // 模式A,异步访问SRAM
    sramTimingInitStruct.asyn_address_setuptime = 0;            // 异步访问地址建立时间
    sramTimingInitStruct.asyn_address_holdtime = 0;             // 异步访问地址保持时间
    sramTimingInitStruct.asyn_data_setuptime = 0;               // 异步访问数据建立时间
    sramTimingInitStruct.bus_latency = 0;                       // 异步/同步访问总线延迟时间
    sramTimingInitStruct.syn_clk_division = 0;                  // 同步访问时钟分频系数(从HCLK中分频)
    sramTimingInitStruct.syn_data_latency = 0;                  // 同步访问中获得第1个数据所需要的等待延迟

    /* Region3配置 */
    sramInitStruct.norsram_region = EXMC_BANK0_NORSRAM_REGION3; // Region3
    sramInitStruct.address_data_mux = DISABLE;                  // 禁用地址、数据总线多路复用
    sramInitStruct.memory_type = EXMC_MEMORY_TYPE_SRAM;         // 储存器类型为SRAM
    sramInitStruct.databus_width = EXMC_NOR_DATABUS_WIDTH_16B;  // 数据宽度16位
    sramInitStruct.burst_mode = DISABLE;                        // 禁用突发访问
    sramInitStruct.nwait_config = EXMC_NWAIT_CONFIG_BEFORE;     // 等待输入配置
    sramInitStruct.nwait_polarity = EXMC_NWAIT_POLARITY_LOW;    // 等待输入信号低电平有效
    sramInitStruct.wrap_burst_mode = DISABLE;                   // 禁用包突发访问
    sramInitStruct.asyn_wait = DISABLE;                         // 禁用异步等待
    sramInitStruct.extended_mode = DISABLE;                     // 禁用扩展模式
    sramInitStruct.memory_write = ENABLE;                       // 使能写入外部存储器
    sramInitStruct.nwait_signal = DISABLE;                      // 禁用等待输入信号
    sramInitStruct.write_mode = EXMC_ASYN_WRITE;                // 写入模式为异步写入
    sramInitStruct.read_write_timing = &sramTimingInitStruct;   // 读写时序配置

    /* 初始化Region3 */
    exmc_norsram_init(&sramInitStruct);

    /* 使能Region3 */
    exmc_norsram_enable(EXMC_BANK0_NORSRAM_REGION3);
}

/**
* @brief  SRAM初始化函数
* @param  void
* @return 无返回值
* @author tao.Huang
*/
void ExSramDrvInit(void)
{
    Config_Exmc_Gpio();
    Config_Bank0_Region3();
}

/**
* @brief  宏定义存储空间
* @param  MULL
* @return 无返回值
* @author tao.Huang
*/
#define BUFFER_SIZE 6
// static uint8_t g_buffer[BUFFER_SIZE] __attribute__((at(EX_SRAM_BEGIN_ADDR)));
// static uint8_t g_buffer[BUFFER_SIZE];
static uint8_t g_buffer[BUFFER_SIZE] = {
    0,
    1,
    2,
    3,
    4,
    5,
};

/**
* @brief  测试函数
* @param  MULL
* @return 无返回值
* @author tao.Huang
*/
void ExSramDrvTest(void)
{
    printf("********************************\n");
    printf("********外部SRAM测试开始********\n");
    printf("********************************\n");

    //        printf("ex sram writing...\r\n");
    //        for (uint16_t i = 0; i < BUFFER_SIZE; i++)
    //        {
    //        g_buffer = i;
    //        printf("0x%02X ", i);
    //        if (15 == i % 16)
    //                {
    //            printf("\r\n");
    //        }
    //    }

    printf("ex sram reading...\r\n");
    for (uint16_t i = 0; i < BUFFER_SIZE; i++)
    {
        if (i != g_buffer)
        {
            printf("0x%02X ", g_buffer);
            printf("\n\nex sram测试故障,请排查!\n\n");
            return;
        }
        printf("0x%02X ", g_buffer);
        if (15 == i % 16)
        {
            printf("\r\n");
        }
    }

    printf("********************************\n");
    printf("********外部SRAM测试结束********\n");
    printf("********************************\n");
}


编译程序输出如下结果:

2468169818624b56b9.png

下载:

1707469818621ba8be.png

实际输出:

16516981861c83d14.png

38403698186167bb48.png

————————————————
版权声明:本文为CSDN博主「_沧浪之水_」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_45973003/article/details/144530609

87600698185ea6e683.png
15614698185f357ac5.png
您需要登录后才可以回帖 登录 | 注册

本版积分规则

157

主题

4499

帖子

3

粉丝
快速回复 在线客服 返回列表 返回顶部
0