Edit online

设计说明

3 Mar 2025
Read time: 12 minute(s)

源码说明

1.

相关模块

源码路径

PSRAM Driver

bsp/artinchip/drv_bare/psram

HAL

bsp/artinchip/hal/xspi

模块架构


luban-lite-XSPI-PSRAM-arch

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 层进行对接。


luban-lite-hal-drv

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: 设置完成

注意事项

-