设计说明
源码说明
相关模块 | 源码路径 |
PSRAM Driver | bsp/artinchip/drv_bare/psram |
HAL | bsp/artinchip/hal/xspi |
模块架构
ArtInChip 提供了 XSPI HAL 层,并且实现了对接 DRV_BARE 的驱动层。 由于 XSPI 传输需要使用 SYSCFG 和 CMU,因此 SYSCFG HAL 和 CMU HAL 是相关模块。
HAL 与 DRV
ArtInChip 的 PSRAM 驱动按照 HAL 层 + Driver 层的结构进行设计,其中 HAL 层为硬件抽象层, 提供系统无关的硬件驱动实现;在 HAL 层之上,可根据不同 RTOS 的驱动框架,实现对应的 PSRAM DRV 层进行对接。
XSPI HAL 的特点:
无状态
支持 XIP,AHB 模式
XSPI HAL 相关的设备操作都需要通过 Handle 的方式进行。 由于 HAL 其内部无状态,不会进行空间分配,因此 Handle 的空间需要外部申请并且传入, 由 HAL 层进行使用。
关键流程
在 bootloader 板级初始化过程中,会调用 aic_xspi_psram_init() 函数,对XSPI控制器、PSRAM设备初始化, 并开启XIP模式,系统可以通过PSRAM映射地址进行内存访问 0x40000000-0x5FFFFFFF
。
c
aic_xspi_psram_init(); // application\baremetal\bootloader\main.c
|-> hal_xspi_init(); // bsp\artinchip\drv_bare\psram\xspi_psram.c
|-> aic_xspi_psram_dev_init(); // bsp\artinchip\drv_bare\psram\xspi_psram.c
|-> hal_xspi_set_boudary(); // bsp\artinchip\drv_bare\psram\xspi_psram.c
|-> aic_xspi_psram_xip(); // bsp\artinchip\drv_bare\psram\xspi_psram.c
|-> hal_xspi_dll_training() // bsp\artinchip\drv_bare\psram\xspi_psram.c
|-> hal_xspi_set_parallel_mode(); // bsp\artinchip\drv_bare\psram\xspi_psram.c
1
2
3
4
5
6
7
2
3
4
5
6
7
数据结构
Driver层主要数据接口
c
struct aic_xspi
{
char \*name;
u32 idx;
u32 clk_id;
u32 clk_in_hz;
u32 dma_port_id;
u32 irq_num;
hal_xspi_handle handle;
bool inited;
};
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
小技巧
name
, idx
, clk_id
, clk_in_hz
属性需要有相应的值, 其中 clk_id 使
用 aic_clk_id.h
文件的宏定义, clk_in_hz 从配置文件中获取
HAL 层主要数据结构
c
struct hal_xspi_config {
u32 idx;
u32 clk_in_hz;
u32 clk_id;
u32 cs0_port;
u32 cs1_port;
bool bit_mode;
bool wire3_en;
bool lsb_en;
bool cs_auto;
u8 cs_polarity;
u8 cpol;
u8 cpha;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
c
struct hal_xspi_transfer {
u8 *tx_data;
u8 *rx_data;
u32 data_len;
};
1
2
3
4
5
2
3
4
5
c
struct hal_xspi_proto_cfg {
u8 mode;
u8 clk_mode;
u8 parallel_mode;
u8 wr_cmd_clk_mode;
u8 wr_cmd_lines;
u8 wr_cmd_val;
u8 rd_cmd_clk_mode;
u8 rd_cmd_lines;
u8 rd_cmd_val;
u8 addr_clk_mode;
u8 addr_lines;
u8 addr_width;
u8 wr_dummy;
u8 rd_dummy;
u8 wr_cnt_lines;
u32 wr_cnt;
u8 rd_cnt_lines;
u32 rd_cnt;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
c
struct hal*xspi_state {
u32 idx;
hal_xspi_async_cb cb;
void *cb*priv;
u32 status;
u32 clk_id;
u32 bus_hz;
u32 bus_width;
struct hal_xspi_dma_config dma_cfg;
void *dma*tx;
void *dma_rx;
u8 *async_tx; /* Used in Async Non-DMA mode */
u8 \_async*rx; /* Used in Async Non-DMA mode */
u32 async*tx_remain; /* Used in Async Non-DMA mode _/
u32 async_rx_remain; /_ Used in Async Non-DMA mode \*/
u32 work_mode;
u32 done_mask;
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
接口设计
Driver接口设计
aic_get_xspi_by_index
函数原型 | static struct aic_xspi \*aic_get_xspi_by_index(u32 idx) |
功能说明 | 获取具体XSPI控制设备 |
参数定义 | u32 idx XSPI 控制器编号,XSPI当前只有 0可选择。 |
返回值 | NULL: 失败 aic_xspi 实例: 成功 |
注意事项 | NULL: 失败 aic_xspi 实例: 成功 |
aic_xspi_psram_dev_reset
函数原型 | static u32 aic_xspi_psram_dev_reset(hal_xspi_handle \*handle) |
功能说明 | reset PSRAM 模块,当前只支持 APS3208K |
参数定义 | hal_xspi_handle *handle XSPI 控制器句柄, 经过hal_xspi_init初始化后可得到。 |
返回值 | 0: 操作完成 |
注意事项 |
aic_xspi_psram_dev_init
函数原型 | static u32 aic_xspi_psram_dev_init(hal_xspi_handle *handle) |
功能说明 | 初始化PSRAM设备 |
参数定义 | hal_xspi_handle *handle XSPI 控制器句柄, 经过hal_xspi_init初始化后可得到。 |
返回值 | 0: 操作完成 |
注意事项 |
aic_xspi_psram_read_id
函数原型 | static u32 aic_xspi_psram_read_id(hal_xspi_handle *handle) |
功能说明 | 读取PSRAM的ID |
参数定义 | hal_xspi_handle *handle XSPI 控制器句柄, 经过hal_xspi_init初始化后可得到。 |
返回值 | 0: 操作完成 |
注意事项 | 该接口只是读取一遍,没有实际作用,仅作为调试使用 |
aic_xspi_psram_xip
函数原型 | static u32 aic_xspi_psram_xip(hal_xspi_handle *handle, hal_xspi_proto_cfg_t proto) |
功能说明 | 读取PSRAM的ID |
参数定义 | hal_xspi_handle *handle XSPI 控制器句柄, 经过hal_xspi_init初始化后可得到。 hal_xspi_proto_cfg_t proto 关于XIP的相关配置 |
返回值 | 0: 操作完成 |
注意事项 |
aic_xspi_psram_icp_calc
函数原型 | u32 aic_xspi_psram_icp_calc(u32 clk_in_hz) |
功能说明 | 根据配置的clock,获取ICP时钟等级 |
参数定义 | u32 clk_in_hz 配置给XSPI的时钟值 |
返回值 | 0: AIC_XSPI_ICP_50_100M 1:AIC_XSPI_ICP_100_150M 2: AIC_XSPI_ICP_150_200M |
注意事项 | 返回结果一般作为aic_xspi_psram_training接口的reg_icp参数。 |
aic_xspi_psram_mem_test
函数原型 | static u8 aic_xspi_psram_mem_test(long address, u32 size) |
功能说明 | PSRAM的training使用的memtest |
参数定义 | long address training buffer的起始地址 u32 size training buffer的空间大小 |
返回值 | 0: AIC_XSPI_ICP_50_100M 1: AIC_XSPI_ICP_100_150M 2: AIC_XSPI_ICP_150_200M |
注意事项 | 返回结果一般作为aic_xspi_psram_training接口的reg_icp参数。 |
aic_xspi_psram_training
函数原型 | u32 aic_xspi_psram_training(hal_xspi_handle *h, u8 sel, u8 reg_icp, void *psram_buf, u32 len) |
功能说明 | PSRAM的training |
参数定义 | hal_xspi_handle *h XSPI 控制器 Handle u8 sel XSPI的CS选择,0, 1 u8 reg_icp XSPI的时钟范围选择,ICP__50_100M = 0x0, ICP_100_150M = 0x1, ICP_150_200M = 0x2, ICP_200_266M = 0x3. void *psram_buf psram的training地址,取psram的地址空间 u32 len 地址空间大小,建议256KB以上 |
返回值 | 0: 传输成功完成 1:传输失败 |
注意事项 | 需要判断是否traning成功 |
aic_xspi_psram_init
函数原型 | u32 aic_xspi_psram_init(void) |
功能说明 | 读取PSRAM的ID |
参数定义 | 无 |
返回值 | 0: 操作完成 |
注意事项 | training失败时,会打印 trainning failed, 并停止系统启动。 |
HAL接口设计
hal_xspi_init
函数原型 | int hal_xspi_init(hal_xspi_handle *h, struct hal_xspi_config *cfg) |
功能说明 | XSPI 控制器的初始化函数 |
参数定义 | hal_xspi_handle *h XSPI 控制器 Handle struct hal_xspi_config *cfg XSPI 控制器的初始化配置参数 |
返回值 | 0: 成功 其他: 失败 |
注意事项 | 初始化时,Handle 的空间由使用者负责分配和释放 |
hal_xspi_set_cmd_width
函数原型 | int hal_xspi_set_cmd_width(hal_xspi_handle *h, u8 ddr_sdr_mode, u8 lines) |
功能说明 | 设置CMD传输所使用的模式和总线位宽 |
参数定义 | hal_xspi_handle *h XSPI 控制器 Handle u8 ddr_sdr_mode cmd数据设置ddr,sdr模式 u8 lines cmd数据设置1/2/4/8线传输 |
返回值 | 0: 成功 其他: 失败 |
注意事项 |
hal_xspi_set_cmd
函数原型 | int hal_xspi_set_cmd(hal_xspi_handle *h, u8 ddr_sdr_mode, u8 cmd) |
功能说明 | 设置 CMD 的模式和opcode |
参数定义 | hal_xspi_handle *h XSPI 控制器 Handle u8 ddr_sdr_mode cmd数据设置ddr,sdr模式 u8 cmd 设置 CMD 的 opcode |
返回值 | 0: 成功 其他: 失败 |
注意事项 |
hal_xspi_set_addr_width
函数原型 | int hal_xspi_set_addr_width(hal_xspi_handle *h, u8 ddr_sdr_mode, u8 lines, u8 bw_3_4_bytes) |
功能说明 | 设置 addr 的模式,传输线数,地址宽度 |
参数定义 | hal_xspi_handle *h XSPI 控制器 Handle u8 ddr_sdr_mode ADDR数据设置ddr,sdr模式, 0x0是sdr, 0x01是ddr u8 lines ADDR数据设置1/2/4/8线传输, 可取值 0, 1, 2, 3 u8 bw_3_4_bytes ADDR数据的宽度,可取值 3、4 |
返回值 | 0: 成功 其他: 失败 |
注意事项 |
hal_xspi_set_addr
函数原型 | int hal_xspi_set_addr(hal_xspi_handle *h, u8 addr) |
功能说明 | 设置addr的opcode |
参数定义 | hal_xspi_handle *h XSPI 控制器 Handle u8 addr addr的opcode |
返回值 | 0: 成功 其他: 失败 |
注意事项 |
hal_xspi_set_dummy
函数原型 | int hal_xspi_set_dummy(hal_xspi_handle *h, u8 lines, u8 dummy) |
功能说明 | 配置read dummy |
参数定义 | hal_xspi_handle *h XSPI 控制器 Handle u8 lines 设置1/2/4/8线传输, 可取值 0, 1, 2, 3(可固定任意值) u8 dummy dummy个数 |
返回值 | 0: 成功 其他: 失败 |
注意事项 | line可以设置任意值,dummy不受传输线限制 |
hal_xspi_set_write_cnt
函数原型 | int hal_xspi_set_write_cnt(hal_xspi_handle *h, u8 ddr_sdr_mode, u8 lines, u32 count) |
功能说明 | 配置写data的个数 |
参数定义 | hal_xspi_handle *h XSPI 控制器 Handle u8 ddr_sdr_mode 写数据设置ddr,sdr模式, 0x0是sdr, 0x01是ddr u8 lines 设置1/2/4/8线传输, 可取值 0, 1, 2, 3 u32 count 设置写入data的个数,bytes为单位 |
返回值 | 0: 成功 其他: 失败 |
注意事项 | u8 lines需要根据实际配置,传入的lines和count硬件会控制输出的cycle |
hal_xspi_start_transfer
函数原型 | int hal_xspi_start_transfer(hal_xspi_handle *h) |
功能说明 | 开始传输使能 |
参数定义 | hal_xspi_handle *h XSPI 控制器 Handle |
返回值 | 0: 传输成功完成 |
注意事项 |
hal_xspi_xip_cfg
函数原型 | int hal_xspi_xip_cfg(hal_xspi_handle *h, hal_xspi_proto_cfg_t xip_proto_cfg) |
功能说明 | XSPI 的XIP配置,根据实际的psram设备协议写入XIP指令 |
参数定义 | hal_xspi_handle *h XSPI 控制器 Handle hal_xspi_proto_cfg_t xip_proto_cfg psram设备协议XIP指令 |
返回值 | 0: 设置完成 |
注意事项 |
hal_xspi_xip_enable
函数原型 | int hal_xspi_xip_enable( hal_xspi_handle *h) |
功能说明 | XSPI 的XIP使能 |
参数定义 | hal_xspi_handle *h XSPI 控制器 Handle |
返回值 | 0: 设置完成 |
注意事项 | 在hal_xspi_xip_cfg()后调用 |
hal_xspi_set_cs
函数原型 | int hal_xspi_set_cs(hal_xspi_handle *h, u8 sel) |
功能说明 | 数据传输配置,写入fifo。 |
参数定义 | hal_xspi_handle *h XSPI 控制器 Handle u8 sel XSPI的CS选择,0, 1 |
返回值 | 0: 设置完成 |
注意事项 |
hal_xspi_set_boudary
函数原型 | int hal_xspi_set_boudary(hal_xspi_handle *h, u8 by) |
功能说明 | 数据切割,根据具体psram配置 |
参数定义 | hal_xspi_handle *h XSPI 控制器 Handle u8 by 数据长度切割,可选xspi_2k = 0x0, xspi_1k = 0x1, |
返回值 | 0: 设置完成 |
注意事项 |
hal_xspi_set_parallel_mode
函数原型 | int hal_xspi_set_parallel_mode(hal_xspi_handle *h, u8 mode) |
功能说明 | 使用双/单片 PSRAM配置。 |
参数定义 | hal_xspi_handle *h XSPI 控制器 Handle u8 mode 单片或双片配置,可选single_mode = 0x0, parellel_mode = 0x1 |
返回值 | 0: 设置完成 |
注意事项 |
hal_xspi_set_dll_ctl
函数原型 | int hal_xspi_set_dll_ctl(hal_xspi_handle *h, u8 sel, u8 reg_icp, u8 phase_sel) |
功能说明 | int hal_xspi_set_dll_ctl(hal_xspi_handle *h, u8 sel, u8 reg_icp, u8 phase_sel) |
参数定义 | hal_xspi_handle *h XSPI 控制器 Handle u8 sel XSPI的CS选择,0, 1 u8 reg_icp 时钟频率等级,ICP_50_100M,ICP_100_150M, ICP_150_200M。 u8 phase_sel 相位等级配置(0x00-0x0f) |
返回值 | 0: 设置完成 |
注意事项 |
hal_xspi_set_phase_sel
函数原型 | int hal_xspi_set_phase_sel(hal_xspi_handle *h, u8 sel, u8 phase_sel) |
功能说明 | 时钟采样相位配置,需要传入相位值,一般在training过程尝试不同相位时配置。 |
参数定义 | hal_xspi_handle *h XSPI 控制器 Handle u8 sel XSPI的CS选择,0, 1 u8 phase_sel 相位等级配置(0x00-0x0f) |
返回值 | 0: 设置完成 |
注意事项 |