SPI 驱动
结构体
定义 SPI 模式
typedef enum {
SPI_IO_SINGLE = 0x00,
SPI_IO_DUAL_RX,
SPI_IO_QUAD_RX,
SPI_IO_QUAD_IO,
} spi_io_mode_t;
定义 SPI 时钟寄存器
typedef struct spi_clk_reg {
uint32_t ccu_base;
uint32_t spi_clk_reg_offest;
uint32_t spi_bgr_reg_offset;
} spi_clk_reg_t;
定义 SPI 描述,包括基地址,控制器号,GPIO配置
typedef struct {
uint32_t base;
uint8_t id;
spi_clk_reg_t clk_reg;
uint32_t clk_rate;
gpio_mux_t gpio_cs;
gpio_mux_t gpio_sck;
gpio_mux_t gpio_miso;
gpio_mux_t gpio_mosi;
gpio_mux_t gpio_wp;
gpio_mux_t gpio_hold;
} sunxi_spi_t;
API 接口
sunxi_spi_init
int sunxi_spi_init(sunxi_spi_t *spi);
初始化具有指定配置的Sunxi SPI控制器。
spi
:指向Sunxi SPI控制器结构的指针。- 返回值:如果成功,则返回0;如果失败,则返回错误代码。
sunxi_spi_disable
void sunxi_spi_disable(sunxi_spi_t *spi);
禁用Sunxi SPI控制器。
spi
:指向Sunxi SPI控制器结构的指针。
sunxi_spi_transfer
int sunxi_spi_transfer(sunxi_spi_t *spi, spi_io_mode_t mode, void *txbuf, uint32_t txlen, void *rxbuf, uint32_t rxlen);
使用Sunxi SPI控制器执行SPI传输。
spi
:指向Sunxi SPI控制器结构的指针。mode
:传输时要使用的SPI IO模式(例如,SPI_IO_MODE_SINGLE,SPI_IO_MODE_DUAL,SPI_IO_MODE_QUAD)。txbuf
:指向要传输的数据的缓冲区的指针。txlen
:要传输的数据的长度(以字节为单位)。rxbuf
:用于存储接收到的数据的缓冲区的指针。rxlen
:要接收的数据的长度(以字节为单位)。- 返回值:如果成功,则返回0;如果失败,则返回错误代码。
使用示例
首先定义 SPI 使用的设备
sunxi_spi_t sunxi_spi0 = {
.base = SUNXI_SPI0_BASE,
.id = 0,
.clk_rate = 75 * 1000 * 1000,
.gpio_cs = {GPIO_PIN(GPIO_PORTC, 1), GPIO_PERIPH_MUX4},
.gpio_sck = {GPIO_PIN(GPIO_PORTC, 0), GPIO_PERIPH_MUX4},
.gpio_mosi = {GPIO_PIN(GPIO_PORTC, 2), GPIO_PERIPH_MUX4},
.gpio_miso = {GPIO_PIN(GPIO_PORTC, 3), GPIO_PERIPH_MUX4},
.gpio_wp = {GPIO_PIN(GPIO_PORTC, 4), GPIO_PERIPH_MUX4},
.gpio_hold = {GPIO_PIN(GPIO_PORTC, 5), GPIO_PERIPH_MUX4},
};
然后初始化 SPI
if (sunxi_spi_init(&sunxi_spi0_lcd) != 0) {
printk_error("SPI: init failed\n");
}
然后发送数据
if (sunxi_spi_transfer(&sunxi_spi0_lcd, SPI_IO_SINGLE, tx, 1, 0, 0) < 0)
printk_error("SPI: SPI Xfer error!\n");
如果是特殊域的SPI设备,可以定义其时钟地址,例如这里的在 CPUS 域中的 SPI 控制器
sunxi_spi_t sunxi_spi0_lcd = {
.base = SUNXI_R_SPI_BASE,
.clk_reg = {
.ccu_base = SUNXI_R_PRCM_BASE,
.spi_clk_reg_offest = SUNXI_S_SPI_CLK_REG,
.spi_bgr_reg_offset = SUNXI_S_SPI_BGR_REG,
},
.id = 0,
.clk_rate = 75 * 1000 * 1000,
.gpio_cs = {GPIO_PIN(GPIO_PORTL, 10), GPIO_PERIPH_MUX6},
.gpio_sck = {GPIO_PIN(GPIO_PORTL, 11), GPIO_PERIPH_MUX6},
.gpio_mosi = {GPIO_PIN(GPIO_PORTL, 12), GPIO_PERIPH_MUX6},
};