前言:
项目过程中对相关知识回顾,仅供学习参考......
目录
[1.0 简介](#1.0 简介)
[2.0 芯片内部结构](#2.0 芯片内部结构)
[3.0 SRAM存储器的时序](#3.0 SRAM存储器的时序)
[4.0 SRAM芯片时序](#4.0 SRAM芯片时序)
[5.0 EXMC 存储器映射](#5.0 EXMC 存储器映射)
[6.0 EXMC控制SRAM时序](#6.0 EXMC控制SRAM时序)
[7.0 FLASH空间布局](#7.0 FLASH空间布局)
[8.0 RAM区域](#8.0 RAM区域)
[9.0 程序实现](#9.0 程序实现)
[9.0.2 宏定义外部存储器](#9.0.2 宏定义外部存储器)
[9.0.3 RCU使能GPIO时钟](#9.0.3 RCU使能GPIO时钟)
[9.0.4 初始化地址总线](#9.0.4 初始化地址总线)
[9.0.5 初始化数据总线](#9.0.5 初始化数据总线)
[9.0.6 初始化控制总线](#9.0.6 初始化控制总线)
[9.0.7 控制块函数](#9.0.7 控制块函数)
[9.0.8 补充知识点](#9.0.8 补充知识点)
[9.0.9 完整程序](#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 宏定义外部存储器
注:这个位置表示存储器的存储位置,表示哪一个外部存储器块,和存储器块中的哪一个位置
cpp
/**
* @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时钟
cpp
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 初始化地址总线
cpp
/* 地址总线 */
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 初始化数据总线
cpp
/* 数据总线 */
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 初始化控制总线
cpp
/* 控制信号 */
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
cpp
/**
* @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 控制块函数
注:以下的是程序的原码,结构体定义中包含的参数,值有使能或者是失能
cpp
/* 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;
cpp
/**
* @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初始化函数
cpp
/**
* @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 完整程序
cpp
头文件
#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");
}
编译程序输出如下结果:
下载:
实际输出:
后记:
仅供学习参考 ...