Edit online

设计说明

12 Nov 2024
Read time: 12 minute(s)

源码说明

1.
相关模块 源码路径
PSRAM Driver bsp/artinchip/drv_bare/psram
HAL bsp/artinchip/hal/xspi

模块架构


../../../../_images/luban-lite-XSPI-PSRAM-arch.drawio.png

1. Luban-Lite XSPI PSRAM 框图

ArtInChip 提供了 XSPI HAL 层,并且实现了对接 DRV_BARE 的驱动层。 由于 XSPI 传输需要使用 SYSCFG 和 CMU,因此 SYSCFG HAL 和 CMU HAL 是相关模块。

HAL 与 DRV

ArtInChip 的 PSRAM 驱动按照 HAL 层 + Driver 层的结构进行设计,其中 HAL 层为硬件抽象层, 提供系统无关的硬件驱动实现;在 HAL 层之上,可根据不同 RTOS 的驱动框架,实现对应的 PSRAM DRV 层进行对接。


../../../../_images/luban-lite-hal-drv.drawio.png

2. HAL and DRV

XSPI HAL 的特点:

  1. 无状态

  2. 支持 XIP,AHB 模式

XSPI HAL 相关的设备操作都需要通过 Handle 的方式进行。 由于 HAL 其内部无状态,不会进行空间分配,因此 Handle 的空间需要外部申请并且传入, 由 HAL 层进行使用。

关键流程设计

在 bootloader 板级初始化过程中,会调用 aic_xspi_psram_init() 函数,对 XSPI 控制器、PSRAM 设备初始化, 并开启 XIP 模式,系统可以通过 PSRAM 映射地址进行内存访问 0x40000000-0x5FFFFFFF
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

数据结构设计

Driver 层主要数据接口
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;
};
提示:

name,idx,clk_id,clk_in_hz 属性需要有相应的值, 其中 clk_id 使用 aic_clk_id.h 文件的宏定义, clk_in_hz 从配置文件中获取

HAL 层主要数据结构
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;
};
struct hal_xspi_transfer {
    u8 *tx_data;
    u8 *rx_data;
    u32 data_len;
};
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;

};
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;
};

接口设计

Driver 接口设计
2. 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 实例: 成功
注意事项 -
3. 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: 操作完成
注意事项 -
4. 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: 操作完成
注意事项 -
5. 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: 操作完成
注意事项 该接口只是读取一遍,没有实际作用,仅作为调试使用
6. 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: 操作完成
注意事项 -
7. 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 参数。
8. 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: 成功完成
1:失败
注意事项 需要判断是否成功
9. 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 成功
10. aic_xspi_psram_init
函数原型 u32 aic_xspi_psram_init(void)
功能说明 读取 PSRAM 的 ID
参数定义
返回值
0: 操作完成
注意事项 training 失败时,会打印 trainning failed, 并停止系统启动。
HAL 接口设计
11. 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 的空间由使用者负责分配和释放
12. 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: 成功
其他: 失败
注意事项 -
13. 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: 成功
其他: 失败
注意事项 -
14. 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: 成功
其他: 失败
注意事项 -
15. 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: 成功
其他: 失败
注意事项 -
16. 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 不受传输线限制
17. 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
18. hal_xspi_set_read_cnt
函数原型 int hal_xspi_set_read_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
19. hal_xspi_start_transfer
函数原型 int hal_xspi_start_transfer(hal_xspi_handle *h)
功能说明 开始传输使能
参数定义
hal_xspi_handle *h
XSPI 控制器 Handle
返回值
0: 成功
其他: 失败
注意事项 -
20. hal_xspi_transfer_cpu_sync
函数原型 int hal_xspi_transfer_cpu_sync(hal_xspi_handle *h, struct hal_xspi_transfer *t)
功能说明 数据传输配置,写入 fifo。
参数定义
hal_xspi_handle *h
XSPI 控制器 Handle
struct hal_xspi_transfer *t
数据结构体
返回值
0: 传输成功完成
注意事项 -
21. 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: 设置完成
注意事项 -
22. 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()后调用
23. 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: 设置完成
注意事项 -
24. 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: 设置完成
注意事项 -
25. 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: 设置完成
注意事项 -
26. hal_xspi_set_dll_ctl
函数原型 int hal_xspi_set_dll_ctl(hal_xspi_handle *h, u8 sel, u8 reg_icp, u8 phase_sel)
功能说明 时钟采样相位和时钟频率等级配置,需要传入与时钟频率等级和相位值,一般在 training 得到稳定相位时传入。
参数定义
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: 设置完成
注意事项 -
27. 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: 设置完成
注意事项 -