1-15 GD32ARM存储器

发布于:2024-12-18 ⋅ 阅读:(13) ⋅ 点赞:(0)

前言:


项目过程中对相关知识回顾,仅供学习参考......


目录

前言:

1.0 简介

2.0 芯片内部结构

3.0 SRAM存储器的时序

4.0 SRAM芯片时序

5.0 EXMC 存储器映射

6.0 EXMC控制SRAM时序

7.0 FLASH空间布局

8.0 RAM区域

9.0 程序实现

9.0.1原理图

9.0.2 宏定义外部存储器

9.0.3 RCU使能GPIO时钟

9.0.4 初始化地址总线

9.0.5 初始化数据总线

9.0.6 初始化控制总线

9.0.7 控制块函数

9.0.8 补充知识点

9.0.9 完整程序

后记:


1.0 简介


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


2.0 芯片内部结构


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


注:以上对应引脚的地址,给出特定的功能,这里的数据线有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芯片时序




5.0 EXMC 存储器映射

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

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


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

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


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


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

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


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


6.0 EXMC控制SRAM时序


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

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

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


写时序

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


7.0 FLASH空间布局


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


8.0 RAM区域


9.0 程序实现

9.0.1原理图

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

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


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的时钟

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


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


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

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


/**
 * @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初始化函数

/**
 * @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`。

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

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


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

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

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

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


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] = 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[i])
        {
            printf("0x%02X ", g_buffer[i]);
            printf("\n\nex sram测试故障,请排查!\n\n");
            return;
        }
        printf("0x%02X ", g_buffer[i]);
        if (15 == i % 16)
        {
            printf("\r\n");
        }
    }

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

编译程序输出如下结果:

下载:

实际输出:

后记:

仅供学习参考 ...


网站公告

今日签到

点亮在社区的每一天
去签到