SPI接口打开函数说明:
/*
* @brief 打开spi
* @parm spi spi句柄
* @return 0 成功,< 0 失败
*/
int spi_open(spi_dev spi)//打开spi
{
int err;
u8 id = spi_get_info_id(spi);//获取SPI的ID
u8 port = spi_get_info_port(spi);//获取port
u8 mode = spi_get_info_mode(spi);//获取mode
u8 role = spi_get_info_role(spi);//获取role
u32 clock = spi_get_info_clock(spi);//获取时钟
pSPI_IOMC_CONFIGid;//配置IO映射
spi_set_bit_mode(spi, mode);//设置bit模式
spi_cs_dis(spi_regs[id]);//禁止片选
if (role == SPI_ROLE_MASTER) {//如果是主机
spi_role_master(spi_regs[id]);//配置为主机
} else if (role == SPI_ROLE_SLAVE) {//如果是从机
spi_role_slave(spi_regs[id]);//配置为从机
}
spi_smp_edge_fall(spi_regs[id]);//在 SPICK 的下降沿采样数据
spi_ud_edge_fall(spi_regs[id]);//在 SPICK 的下降沿更新数据
spi_cs_idle_h(spi_regs[id]);// SPICS 空闲时为 1 电平
spi_clk_idle_l(spi_regs[id]);//SPICK 空闲时为 0 电平
spi_clr_pnd(spi_regs[id]);//写入‘1’将清除 PND 中断请求标志
if ((err = spi_set_baud(spi, clock))) {//配置波特率
log_error(“invalid spi baudrate”);
/* return 0; */
}
spi_w_reg_buf(spi_regs[id], 0);//设定spi初始化后DO口默认电平为低
spi_enable(spi_regs[id]);//使能SPI
#if 0//调试打印信息
printf(“spi%d port = ‘%c’\n”, id, port);
printf(“spi%d clk = %d\n”, id, clock);
printf(“spi%d mode = %d\n”, id, mode);
printf(“spi%d role = %d\n”, id, role);
printf(“spi%d di_pin = %d\n”, id, spi_io_map[id].io[port - ‘A’].di_pin);
printf(“spi%d clk_pin = %d\n”, id, spi_io_map[id].io[port - ‘A’].clk_pin);
printf(“spi%d do_pin = %d\n”, id, spi_io_map[id].io[port - ‘A’].do_pin);
printf(“spi%d d2_pin = %d\n”, id, spi_io_map[id].io[port - ‘A’].d2_pin);
printf(“spi%d d3_pin = %d\n”, id, spi_io_map[id].io[port - ‘A’].d3_pin);
printf(“spi%d CON = %04x\n”, id, spi_r_reg_con(spi_regs[id]));
printf(“spi%d IOMC1 = %08x\n”, id, JL_IOMAP->CON1);
#endif
return 0;
}
SPI接口的关闭:
/*
* @brief 关闭spi
* @parm spi spi句柄
* @return null
*/
void spi_close(spi_dev spi)//关闭spi
{
u8 id = spi_get_info_id(spi);//获取ID
u8 port = spi_get_info_port(spi);//获取port
u8 mode = spi_get_info_mode(spi);//获取模式
port -= ‘A’;
if (id == SPI2 && port + ‘A’ == ‘B’) {//如果是SPI2的B组
spi_io_port_uninit(spi_io_map[id].io[port].di_pin);//复位DP和DM引脚配置
JL_USB_IO->CON0 |= BIT(2); //DP DIR IN
JL_USB_IO->CON0 |= BIT(3); //DM DIR IN
JL_USB_IO->CON0 &= ~BIT(9); //DP 1.2V digital input dis
JL_USB_IO->CON0 &= ~BIT(10); //DM 1.2V digital input dis
} else {
spi_io_port_uninit(spi_io_map[id].io[port].clk_pin);//CLK、DO、DI引脚复位
spi_io_port_uninit(spi_io_map[id].io[port].do_pin);
if (mode == SPI_MODE_BIDIR_1BIT) {
spi_io_port_uninit(spi_io_map[id].io[port].di_pin);
} else if (mode == SPI_MODE_UNIDIR_2BIT) {
spi_io_port_uninit(spi_io_map[id].io[port].di_pin);
} else if (mode == SPI_MODE_UNIDIR_4BIT) {
spi_io_port_uninit(spi_io_map[id].io[port].di_pin);
spi_io_port_uninit(spi_io_map[id].io[port].d2_pin);
spi_io_port_uninit(spi_io_map[id].io[port].d3_pin);
}
}
spi_disable(spi_regs[id]);//禁能SPI
}
以下SPI DMA相关函数配置:
/*
* @brief spi dma接收
* @parm spi spi句柄
* @parm buf 接收缓冲区基地址
* @parm len 期望接收长度
* @return 实际接收长度,< 0表示失败
*/
int spi_dma_recv(spi_dev spi, void *buf, u32 len)//spi dma接收
{
u8 id = spi_get_info_id(spi);//获取ID
/* ASSERT((u32)buf % 4 == 0, “spi dma addr need 4-aligned”); */
spi_dir_in(spi_regs[id]);//配置为接收数据
spi_w_reg_dma_addr(spi_regs[id], (u32)buf);//配置DMA地址
spi_w_reg_dma_cnt(spi_regs[id], len);//配置DMA接收数量
asm(“csync”);
if (__spi_wait_ok(spi, len)) {
return -EFAULT;
}
return len;
}
/*
* @brief spi dma发送
* @parm spi spi句柄
* @parm buf 发送缓冲区基地址
* @parm len 期望发送长度
* @return 实际发送长度,< 0表示失败
*/
int spi_dma_send(spi_dev spi, const void *buf, u32 len)//spi dma发送
{
u8 id = spi_get_info_id(spi);//获取ID
/* ASSERT((u32)buf % 4 == 0, “spi dma addr need 4-aligned”); */
spi_dir_out(spi_regs[id]);//配置为输出方向
spi_w_reg_dma_addr(spi_regs[id], (u32)buf);//写入地址
spi_w_reg_dma_cnt(spi_regs[id], len);//写入长度
asm(“csync”);
if (__spi_wait_ok(spi, len)) {//等待发送完成
return -EFAULT;
}
return len;
}
/*
* @brief spi 配置dma,不等待pnd,用于中断
* @parm spi spi句柄
* @parm buf 缓冲区基地址
* @parm len 期望长度
* @parm rw 1 接收 / 0 发送
* @return null
*/
void spi_dma_set_addr_for_isr(spi_dev spi, void *buf, u32 len, u8 rw)//spi 配置dma,不等待pnd,用于中断
{
u8 id = spi_get_info_id(spi);//获取ID
/* ASSERT((u32)buf % 4 == 0, “spi dma addr need 4-aligned”); */
rw ? spi_dir_in(spi_regs[id]) : spi_dir_out(spi_regs[id]);//根据rw标志,配置输出或输入
spi_w_reg_dma_addr(spi_regs[id], (u32)buf);//写地址
spi_w_reg_dma_cnt(spi_regs[id], len);//写长度
}