SAL_QSPI ( Sofetware Abstraction Layer - QSPI )
-
这是一个极为通用的软件抽象 4 线 spi 模拟驱动,移植到不同平台只需要实现两个函数
-
仓库链接:https://gitee.com/wattercutter/sal_qspi
用法
在工程中加入 ./include/_sal_qspi_mod.h
和 ./src/_sal_qspi_mod.c
, 调用方法见 ./demo/test_main.c
#include "_sal_qspi_mod.h"
void delay_us(unsigned int us_){
// porting
};
void set_pin(unsigned int pin_, unsigned int val_){
// porting
};
int main()
{
sal_qspi_info_t devx = {
.cs_num_ = 1,
.clk_pin_ = 2,
.cs_pins_ = {3,4,5,6,7,8,9,10,},
.dat_pins_ = {11,12,13,14}
};
// registering delay & set_pin function, reset 1 cs pin, reset dat pins
sal_qspi_init(
(sal_qspi_info_t*)&devx,
(unsigned long long)1,
// _STAUS_HIGH_LEVEL,
// _STAUS_HIGH_LEVEL,
delay_us,
set_pin
);
while(1){
// write [64]-bits data [0x12345678abcdef] to selected chip [(unsigned long long)0], info contained in [devx]
sal_qspi_wdat_64bit(
(sal_qspi_info_t*)&devx,
(unsigned long long)0,
(unsigned long long)0x12345678abcdef,
(unsigned long long)64
);
}
}
逐块说明一下:
1
#include "_sal_qspi_mod.h"
这是驱动的头文件,调用驱动的程序需要 #include
这个文件
2
void delay_us(unsigned int us_){
// porting
};
void set_pin(unsigned int pin_, unsigned int val_){
// porting
};
这是要在初始化时传入的两个函数,
- delay_us:以 1us 为基数进行延时,传参 us_ 表示延时 us_ 个微妙
- set_pin:把指定引脚
pin_
的输出设置为val_
这两个函数用于适配不同的硬件平台,比如使用不同的处理器就需要用对应的库/驱动实现这两个接口,供给 sal_qspi 的驱动去调用,这样就不需要修改驱动本身了。
这实际上是 sal_qspi 通过函数指针实现了方法的注册,减少了使用者阅读驱动源码的负担。
3
sal_qspi_info_t devx = {
.cs_num_ = 1,
.clk_pin_ = 2,
.cs_pins_ = {3,4,5,6,7,8,9,10,},
.dat_pins_ = {11,12,13,14}
};
这是准备 sal_sqpi 的基本信息,用到的结构体的原型如下:
typedef struct sal_qspi_info_{
unsigned int cs_num_;
unsigned int cs_pins_[SAL_QSPI_CS_MAX_NUM];
unsigned int clk_pin_;
unsigned int dat_pins_[4];
}sal_qspi_info_t;
- cs_num_ 指的是片选信号的数量
- cs_pins_[SAL_QSPI_CS_MAX_NUM] 指的是各个片选信号对应的 gpio 引脚号
- clk_pin_ 指的是时钟信号对应的 gpio 引脚号
- dat_pins[4] 指的是 4 个数据信号线对应的 gpio 引脚号
这样我们就知道上面的代码描述的 qspi 基本信息就是:有 1 个 片选,对应的引脚号是 3,时钟信号对应的引脚号是 2,4 个数据线对应的引脚号分别是 11、12、13、14
4
// registering delay & set_pin function, reset 1 cs pin, reset dat pins
sal_qspi_init(
(sal_qspi_info_t*)&devx,
(unsigned long long)1,
delay_us,
set_pin
);
这里是把前面实现的延时函数、gpio 操作函数两个接口函数注册到我们要初始化的 sal_qspi 设备信息中。用到的函数原型如下:
void
sal_qspi_init(
sal_qspi_info_t* sal_qspi_dev_,
unsigned long long cs_num,
void(*delay_us_)(unsigned int us_),
void(*set_pin_val_)(unsigned int pin_, unsigned int val_)
); // register delay call back function, reset gpio pin output
注意后两个参数是函数指针,一个是 void(*)(unsigned int)
类型的,另一个是 void(*)(unsigned int, unsigned int)
类型的。
5
发送数据的函数原型如下:
void
sal_qspi_wdat_64bit(
sal_qspi_info_t* sal_qspi_dev_,
unsigned long long csn_,
unsigned long long dat_,
unsigned long long bits_num_
);
发送数据的位宽 bits_num_
范围为 1-64 bits,需要是 4 的整数倍,不同位宽的发送时序如下:
bits_num_==24
bits_num_==8
例程
- 路径:./demo/test_main.c
- 包含路径:./include/
- 源文件:./src/*.c
移植说明
参考 …/demo/test_main.c,仅需实现以下两个函数(函数名任意)并作为参数在初始化时传入
void delay_us(unsigned int us_){
// porting
};
void set_pin(unsigned int pin_, unsigned int val_){
// porting
};
函数说明如下:
- delay_us:以 1us 为基数进行延时,传参 us_ 表示延时 us_ 个微妙
- set_pin:把指定引脚(pin_)的输出设置为 _val
约束
- 初始化不包含对应引脚的复用配置,请在 sal_qspi 初始化前完成相应配置