676 lines
17 KiB
C
676 lines
17 KiB
C
|
||
#undef LOG_TAG_CONST
|
||
#define LOG_TAG "[SPI]"
|
||
#define LOG_ERROR_ENABLE
|
||
//#define LOG_DEBUG_ENABLE
|
||
#include "system/debug.h"
|
||
#include "generic/gpio.h"
|
||
#include "asm/clock.h"
|
||
#include "asm/spi.h"
|
||
#include "update.h"
|
||
|
||
|
||
#define spi_enable(reg) ((reg)->CON |= BIT(0))
|
||
#define spi_disable(reg) ((reg)->CON &= ~BIT(0))
|
||
#define spi_role_slave(reg) ((reg)->CON |= BIT(1))
|
||
#define spi_role_master(reg) ((reg)->CON &= ~BIT(1))
|
||
#define spi_cs_en(reg) ((reg)->CON |= BIT(2))
|
||
#define spi_cs_dis(reg) ((reg)->CON &= ~BIT(2))
|
||
#define spi_bidir(reg) ((reg)->CON |= BIT(3))
|
||
#define spi_unidir(reg) ((reg)->CON &= ~BIT(3))
|
||
#define spi_smp_edge_rise(reg) ((reg)->CON &= ~BIT(4))
|
||
#define spi_smp_edge_fall(reg) ((reg)->CON |= BIT(4))
|
||
#define spi_ud_edge_rise(reg) ((reg)->CON &= ~BIT(5))
|
||
#define spi_ud_edge_fall(reg) ((reg)->CON |= BIT(5))
|
||
#define spi_clk_idle_h(reg) ((reg)->CON |= BIT(6))
|
||
#define spi_clk_idle_l(reg) ((reg)->CON &= ~BIT(6))
|
||
#define spi_cs_idle_h(reg) ((reg)->CON |= BIT(7))
|
||
#define spi_cs_idle_l(reg) ((reg)->CON &= ~BIT(7))
|
||
#define spi_data_width(reg, x) ((reg)->CON = (reg->CON&~(3<<10))|((x)<<10))
|
||
#define spi_dir_in(reg) ((reg)->CON |= BIT(12))
|
||
#define spi_dir_out(reg) ((reg)->CON &= ~BIT(12))
|
||
#define spi_ie_en(reg) ((reg)->CON |= BIT(13))
|
||
#define spi_ie_dis(reg) ((reg)->CON &= ~BIT(13))
|
||
#define spi_clr_pnd(reg) ((reg)->CON |= BIT(14))
|
||
#define spi_pnd(reg) ((reg)->CON & BIT(15))
|
||
|
||
#define spi_w_reg_con(reg, val) ((reg)->CON = (val))
|
||
#define spi_r_reg_con(reg) ((reg)->CON)
|
||
#define spi_w_reg_buf(reg, val) ((reg)->BUF = (val))
|
||
#define spi_r_reg_buf(reg) ((reg)->BUF)
|
||
#define spi_w_reg_baud(reg, baud) ((reg)->BAUD = (baud))
|
||
#define spi_r_reg_baud(reg) ((reg)->BAUD)
|
||
#define spi_w_reg_dma_addr(reg, addr) ((reg)->ADR = (addr))
|
||
#define spi_w_reg_dma_cnt(reg, cnt) ((reg)->CNT = (cnt))
|
||
|
||
|
||
#define SPI0_ENABLE 0 //是否使能SPI0,使能后需定义spi0_p_data
|
||
#define SPI1_ENABLE 1 //是否使能SPI1,使能后需定义spi1_p_data
|
||
#define SPI2_ENABLE 1 //是否使能SPI2,使能后需定义spi2_p_data
|
||
|
||
|
||
static const struct spi_io_mapping spi_io_map[SPI_MAX_HW_NUM] = {
|
||
//SPI0
|
||
{
|
||
.num = 1,
|
||
//port A
|
||
.io[0] = {
|
||
.cs_pin = IO_PORTD_03,
|
||
.di_pin = IO_PORTD_02,
|
||
.do_pin = IO_PORTD_01,
|
||
.clk_pin = IO_PORTD_00,
|
||
.d2_pin = IO_PORTB_04,
|
||
.d3_pin = IO_PORTC_04,
|
||
}
|
||
},
|
||
//SPI1
|
||
{
|
||
.num = 2,
|
||
//port A
|
||
.io[0] = {
|
||
.cs_pin = -1,
|
||
.di_pin = IO_PORTB_02,
|
||
.do_pin = IO_PORTB_01,
|
||
.clk_pin = IO_PORTB_00,
|
||
.d2_pin = -1,
|
||
.d3_pin = -1,
|
||
},
|
||
//port B
|
||
.io[1] = {
|
||
.cs_pin = -1,
|
||
.di_pin = IO_PORTC_03,
|
||
.do_pin = IO_PORTC_05,
|
||
.clk_pin = IO_PORTC_04,
|
||
.d2_pin = -1,
|
||
.d3_pin = -1,
|
||
}
|
||
},
|
||
//SPI2
|
||
{
|
||
.num = 2,
|
||
//port A
|
||
.io[0] = {
|
||
.cs_pin = -1,
|
||
.di_pin = IO_PORTB_05,
|
||
.do_pin = IO_PORTB_07,
|
||
.clk_pin = IO_PORTB_06,
|
||
.d2_pin = -1,
|
||
.d3_pin = -1,
|
||
},
|
||
//port B
|
||
.io[1] = {
|
||
.cs_pin = -1,
|
||
.di_pin = IO_PORTC_01,
|
||
.do_pin = IO_PORT_DM,
|
||
.clk_pin = IO_PORT_DP,
|
||
.d2_pin = -1,
|
||
.d3_pin = -1,
|
||
}
|
||
},
|
||
};
|
||
|
||
static JL_SPI_TypeDef *const spi_regs[SPI_MAX_HW_NUM] = {
|
||
JL_SPI0,
|
||
JL_SPI1,
|
||
JL_SPI2,
|
||
};
|
||
|
||
static u8 spi_get_info_id(spi_dev spi)
|
||
{
|
||
ASSERT(spi < SPI_MAX_HW_NUM);
|
||
return spi;
|
||
}
|
||
|
||
static u8 spi_get_info_port(spi_dev spi)
|
||
{
|
||
u8 port = (u8) - 1;
|
||
u8 id = spi_get_info_id(spi);
|
||
switch (id) {
|
||
#if SPI0_ENABLE
|
||
case SPI0:
|
||
port = spi0_p_data.port;
|
||
break;
|
||
#endif
|
||
#if SPI1_ENABLE
|
||
case SPI1:
|
||
port = spi1_p_data.port;
|
||
break;
|
||
#endif
|
||
#if SPI2_ENABLE
|
||
case SPI2:
|
||
port = spi2_p_data.port;
|
||
break;
|
||
#endif
|
||
default:
|
||
break;
|
||
}
|
||
ASSERT(port - 'A' < spi_io_map[id].num);
|
||
return port;
|
||
}
|
||
|
||
static u8 spi_get_info_mode(spi_dev spi)
|
||
{
|
||
u8 mode = (u8) - 1;
|
||
u8 id = spi_get_info_id(spi);
|
||
switch (id) {
|
||
#if SPI0_ENABLE
|
||
case SPI0:
|
||
mode = spi0_p_data.mode;
|
||
break;
|
||
#endif
|
||
#if SPI1_ENABLE
|
||
case SPI1:
|
||
mode = spi1_p_data.mode;
|
||
break;
|
||
#endif
|
||
#if SPI2_ENABLE
|
||
case SPI2:
|
||
mode = spi2_p_data.mode;
|
||
break;
|
||
#endif
|
||
default:
|
||
break;
|
||
}
|
||
return mode;
|
||
}
|
||
|
||
static u8 spi_get_info_role(spi_dev spi)
|
||
{
|
||
u8 role = (u8) - 1;
|
||
u8 id = spi_get_info_id(spi);
|
||
switch (id) {
|
||
#if SPI0_ENABLE
|
||
case SPI0:
|
||
role = spi0_p_data.role;
|
||
break;
|
||
#endif
|
||
#if SPI1_ENABLE
|
||
case SPI1:
|
||
role = spi1_p_data.role;
|
||
break;
|
||
#endif
|
||
#if SPI2_ENABLE
|
||
case SPI2:
|
||
role = spi2_p_data.role;
|
||
break;
|
||
#endif
|
||
default:
|
||
break;
|
||
}
|
||
return role;
|
||
}
|
||
|
||
static u32 spi_get_info_clock(spi_dev spi)
|
||
{
|
||
u32 clock = (u8) - 1;
|
||
u8 id = spi_get_info_id(spi);
|
||
switch (id) {
|
||
#if SPI0_ENABLE
|
||
case SPI0:
|
||
clock = spi0_p_data.clk;
|
||
break;
|
||
#endif
|
||
#if SPI1_ENABLE
|
||
case SPI1:
|
||
clock = spi1_p_data.clk;
|
||
break;
|
||
#endif
|
||
#if SPI2_ENABLE
|
||
case SPI2:
|
||
clock = spi2_p_data.clk;
|
||
break;
|
||
#endif
|
||
default:
|
||
break;
|
||
}
|
||
return clock;
|
||
}
|
||
|
||
static void spi0_iomc_config(spi_dev spi)
|
||
{
|
||
u8 port = spi_get_info_port(spi);
|
||
if (port == 'A') {
|
||
JL_IOMAP->CON0 &= ~BIT(2);
|
||
}
|
||
}
|
||
|
||
static void spi1_iomc_config(spi_dev spi)
|
||
{
|
||
u8 port = spi_get_info_port(spi);
|
||
if (port == 'A') {
|
||
JL_IOMAP->CON1 &= ~BIT(4);
|
||
} else if (port == 'B') {
|
||
JL_IOMAP->CON1 |= BIT(4);
|
||
}
|
||
}
|
||
|
||
static void spi2_iomc_config(spi_dev spi)
|
||
{
|
||
u8 port = spi_get_info_port(spi);
|
||
if (port == 'A') {
|
||
JL_IOMAP->CON1 &= ~BIT(16);
|
||
} else if (port == 'B') {
|
||
JL_IOMAP->CON1 |= BIT(16);
|
||
}
|
||
}
|
||
|
||
static void (*pSPI_IOMC_CONFIG[])(spi_dev spi) = {
|
||
spi0_iomc_config,
|
||
spi1_iomc_config,
|
||
spi2_iomc_config,
|
||
};
|
||
|
||
|
||
static void spi_io_port_init(u8 port, u8 dir)
|
||
{
|
||
if (port != (u8) - 1) {
|
||
if (dir == 1) {
|
||
gpio_set_direction(port, 1);
|
||
} else {
|
||
gpio_set_direction(port, 0);
|
||
}
|
||
gpio_set_die(port, 1);
|
||
gpio_set_pull_up(port, 0);
|
||
gpio_set_pull_down(port, 0);
|
||
}
|
||
}
|
||
|
||
static void spi_io_port_uninit(u8 port)
|
||
{
|
||
if (port != (u8) - 1) {
|
||
gpio_set_direction(port, 1);
|
||
gpio_set_die(port, 0);
|
||
gpio_set_pull_up(port, 0);
|
||
gpio_set_pull_down(port, 0);
|
||
}
|
||
}
|
||
|
||
/*
|
||
* @brief 设置波特率
|
||
* @parm spi spi句柄
|
||
* @parm baud 波特率
|
||
* @return 0 成功,< 0 失败
|
||
*/
|
||
int spi_set_baud(spi_dev spi, u32 baud)
|
||
{
|
||
//SPICK = sysclk / (SPIx_BAUD + 1)
|
||
//=> SPIx_BAUD = sysclk / SPICK - 1
|
||
u8 id = spi_get_info_id(spi);
|
||
u32 sysclk;
|
||
|
||
sysclk = clk_get("spi");
|
||
log_debug("spi clock source freq %lu", sysclk);
|
||
if (sysclk < baud) {
|
||
spi_w_reg_baud(spi_regs[id], 0);
|
||
return -EINVAL;
|
||
}
|
||
spi_w_reg_baud(spi_regs[id], sysclk / baud - 1);
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* @brief 获取波特率
|
||
* @parm spi spi句柄
|
||
* @return 波特率
|
||
*/
|
||
u32 spi_get_baud(spi_dev spi)
|
||
{
|
||
u8 id = spi_get_info_id(spi);
|
||
return spi_get_info_clock(spi);
|
||
}
|
||
|
||
static int __spi_wait_ok(spi_dev spi, u32 n)
|
||
{
|
||
u8 id = spi_get_info_id(spi);
|
||
u32 baud = spi_get_info_clock(spi);
|
||
baud = clk_get("spi") / baud - 1;
|
||
u32 retry = baud * (clk_get("sys") / clk_get("spi")) * 8 * n * 5; //500% spi baudate
|
||
|
||
while (!spi_pnd(spi_regs[id])) {
|
||
__asm__ volatile("nop");
|
||
if (--retry == 0) {
|
||
log_error("spi wait pnd timeout");
|
||
return -EFAULT;
|
||
}
|
||
}
|
||
spi_clr_pnd(spi_regs[id]);
|
||
return 0;
|
||
}
|
||
|
||
/*
|
||
* @brief 发送1个字节
|
||
* @parm spi spi句柄
|
||
* @parm byte 发送的字节
|
||
* @return 0 成功,< 0 失败
|
||
*/
|
||
int spi_send_byte(spi_dev spi, u8 byte)
|
||
{
|
||
u8 id = spi_get_info_id(spi);
|
||
|
||
spi_dir_out(spi_regs[id]);
|
||
spi_w_reg_buf(spi_regs[id], byte);
|
||
return __spi_wait_ok(spi, 1);
|
||
}
|
||
|
||
/*
|
||
* @brief 发送1个字节,不等待pnd,用于中断
|
||
* @parm spi spi句柄
|
||
* @parm byte 发送的字节
|
||
* @return null
|
||
*/
|
||
void spi_send_byte_for_isr(spi_dev spi, u8 byte)
|
||
{
|
||
u8 id = spi_get_info_id(spi);
|
||
|
||
spi_dir_out(spi_regs[id]);
|
||
spi_w_reg_buf(spi_regs[id], byte);
|
||
}
|
||
|
||
/*
|
||
* @brief 接收1个字节
|
||
* @parm spi spi句柄
|
||
* @parm err 返回错误信息,若err为非空指针,0 成功,< 0 失败,若为空指针,忽略
|
||
* @return 接收的字节
|
||
*/
|
||
u8 spi_recv_byte(spi_dev spi, int *err)
|
||
{
|
||
u8 id = spi_get_info_id(spi);
|
||
int ret;
|
||
|
||
spi_dir_in(spi_regs[id]);
|
||
spi_w_reg_buf(spi_regs[id], 0xff);
|
||
ret = __spi_wait_ok(spi, 1);
|
||
if (ret) {
|
||
err != NULL ? *err = ret : 0;
|
||
return 0;
|
||
}
|
||
err != NULL ? *err = 0 : 0;
|
||
return spi_r_reg_buf(spi_regs[id]);
|
||
}
|
||
|
||
|
||
/*
|
||
* @brief 接收1个字节,不等待pnd,用于中断
|
||
* @parm spi spi句柄
|
||
* @return 接收的字节
|
||
*/
|
||
u8 spi_recv_byte_for_isr(spi_dev spi)
|
||
{
|
||
u8 id = spi_get_info_id(spi);
|
||
|
||
spi_dir_in(spi_regs[id]);
|
||
return spi_r_reg_buf(spi_regs[id]);
|
||
}
|
||
|
||
/*
|
||
* @brief 发送并接收1个字节,在8个时钟内完成,仅使用于SPI_MODE_BIDIR_1BIT
|
||
* @parm spi spi句柄
|
||
* @parm byte 发送的字节
|
||
* @parm err 返回错误信息,若err为非空指针,0 成功,< 0 失败,若为空指针,忽略
|
||
* @return 接收的字节
|
||
*/
|
||
u8 spi_send_recv_byte(spi_dev spi, u8 byte, int *err)
|
||
{
|
||
u8 id = spi_get_info_id(spi);
|
||
int ret;
|
||
|
||
spi_w_reg_buf(spi_regs[id], byte);
|
||
ret = __spi_wait_ok(spi, 1);
|
||
if (ret) {
|
||
err != NULL ? *err = ret : 0;
|
||
return 0;
|
||
}
|
||
err != NULL ? *err = 0 : 0;
|
||
return spi_r_reg_buf(spi_regs[id]);
|
||
}
|
||
|
||
/*
|
||
* @brief 设置spi[单向/双向,位数]模式
|
||
* @parm spi spi句柄
|
||
* @parm mode 模式
|
||
* @return null
|
||
*/
|
||
void spi_set_bit_mode(spi_dev spi, int mode)
|
||
{
|
||
u8 id = spi_get_info_id(spi);
|
||
u8 port = spi_get_info_port(spi);
|
||
u8 role = spi_get_info_role(spi);
|
||
|
||
switch (mode) {
|
||
case SPI_MODE_BIDIR_1BIT:
|
||
spi_bidir(spi_regs[id]);
|
||
spi_data_width(spi_regs[id], 0);
|
||
break;
|
||
case SPI_MODE_UNIDIR_1BIT:
|
||
spi_unidir(spi_regs[id]);
|
||
spi_data_width(spi_regs[id], 0);
|
||
break;
|
||
case SPI_MODE_UNIDIR_2BIT:
|
||
/* ASSERT(id == 0, "spi%d not support SPI_MODE_UNIDIR_2BIT\n", id); */
|
||
spi_unidir(spi_regs[id]);
|
||
spi_data_width(spi_regs[id], 1);
|
||
break;
|
||
case SPI_MODE_UNIDIR_4BIT:
|
||
ASSERT(id == 0, "spi%d not support SPI_MODE_UNIDIR_4BIT\n", id);
|
||
spi_unidir(spi_regs[id]);
|
||
spi_data_width(spi_regs[id], 2);
|
||
break;
|
||
}
|
||
|
||
port -= 'A';
|
||
if (id == SPI2 && port + 'A' == 'B') {
|
||
JL_USB_IO->CON0 |= BIT(11); //IO MODE
|
||
spi_io_port_init(spi_io_map[id].io[port].di_pin, 1);
|
||
JL_USB_IO->CON0 &= ~BIT(2); //DP DIR OUT
|
||
JL_USB_IO->CON0 &= ~BIT(3); //DM DIR OUT
|
||
JL_USB_IO->CON0 |= BIT(9); //DP 1.2V digital input en
|
||
JL_USB_IO->CON0 |= BIT(10); //DM 1.2V digital input en
|
||
} else {
|
||
spi_io_port_init(spi_io_map[id].io[port].clk_pin,
|
||
role == SPI_ROLE_MASTER ? 0 : 1);
|
||
spi_io_port_init(spi_io_map[id].io[port].do_pin, 0);
|
||
if (mode == SPI_MODE_BIDIR_1BIT) {
|
||
spi_io_port_init(spi_io_map[id].io[port].di_pin, 1);
|
||
} else if (mode == SPI_MODE_UNIDIR_2BIT) {
|
||
spi_io_port_init(spi_io_map[id].io[port].di_pin, 0);
|
||
} else if (mode == SPI_MODE_UNIDIR_4BIT) {
|
||
spi_io_port_init(spi_io_map[id].io[port].di_pin, 0);
|
||
spi_io_port_init(spi_io_map[id].io[port].d2_pin, 0);
|
||
spi_io_port_init(spi_io_map[id].io[port].d3_pin, 0);
|
||
}
|
||
}
|
||
}
|
||
|
||
/*
|
||
* @brief 打开spi
|
||
* @parm spi spi句柄
|
||
* @return 0 成功,< 0 失败
|
||
*/
|
||
int spi_open(spi_dev spi)
|
||
{
|
||
int err;
|
||
u8 id = spi_get_info_id(spi);
|
||
u8 port = spi_get_info_port(spi);
|
||
u8 mode = spi_get_info_mode(spi);
|
||
u8 role = spi_get_info_role(spi);
|
||
u32 clock = spi_get_info_clock(spi);
|
||
|
||
pSPI_IOMC_CONFIG[id](spi);
|
||
|
||
spi_set_bit_mode(spi, mode);
|
||
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_rise(spi_regs[id]);
|
||
spi_ud_edge_fall(spi_regs[id]);
|
||
spi_cs_idle_h(spi_regs[id]);
|
||
spi_clk_idle_l(spi_regs[id]);
|
||
spi_clr_pnd(spi_regs[id]);
|
||
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]);
|
||
|
||
#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;
|
||
}
|
||
|
||
/*
|
||
* @brief spi dma接收
|
||
* @parm spi spi句柄
|
||
* @parm buf 接收缓冲区基地址
|
||
* @parm len 期望接收长度
|
||
* @return 实际接收长度,< 0表示失败
|
||
*/
|
||
int spi_dma_recv(spi_dev spi, void *buf, u32 len)
|
||
{
|
||
u8 id = spi_get_info_id(spi);
|
||
|
||
/* 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);
|
||
spi_w_reg_dma_cnt(spi_regs[id], len);
|
||
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)
|
||
{
|
||
u8 id = spi_get_info_id(spi);
|
||
|
||
/* 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)
|
||
{
|
||
u8 id = spi_get_info_id(spi);
|
||
|
||
/* ASSERT((u32)buf % 4 == 0, "spi dma addr need 4-aligned"); */
|
||
rw ? spi_dir_in(spi_regs[id]) : 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);
|
||
}
|
||
|
||
/*
|
||
* @brief 中断使能
|
||
* @parm spi spi句柄
|
||
* @parm en 1 使能,0 失能
|
||
* @return null
|
||
*/
|
||
void spi_set_ie(spi_dev spi, u8 en)
|
||
{
|
||
u8 id = spi_get_info_id(spi);
|
||
en ? spi_ie_en(spi_regs[id]) : spi_ie_dis(spi_regs[id]);
|
||
}
|
||
|
||
/*
|
||
* @brief 判断中断标志
|
||
* @parm spi spi句柄
|
||
* @return 0 / 1
|
||
*/
|
||
u8 spi_get_pending(spi_dev spi)
|
||
{
|
||
u8 id = spi_get_info_id(spi);
|
||
return spi_pnd(spi_regs[id]) ? 1 : 0;
|
||
}
|
||
|
||
/*
|
||
* @brief 清除中断标志
|
||
* @parm spi spi句柄
|
||
* @return null
|
||
*/
|
||
void spi_clear_pending(spi_dev spi)
|
||
{
|
||
u8 id = spi_get_info_id(spi);
|
||
spi_clr_pnd(spi_regs[id]);
|
||
}
|
||
|
||
/*
|
||
* @brief 关闭spi
|
||
* @parm spi spi句柄
|
||
* @return null
|
||
*/
|
||
void spi_close(spi_dev spi)
|
||
{
|
||
u8 id = spi_get_info_id(spi);
|
||
u8 port = spi_get_info_port(spi);
|
||
u8 mode = spi_get_info_mode(spi);
|
||
|
||
port -= 'A';
|
||
if (id == SPI2 && port + 'A' == 'B') {
|
||
spi_io_port_uninit(spi_io_map[id].io[port].di_pin);
|
||
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);
|
||
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]);
|
||
}
|
||
|
||
void spi_disable_for_ota()
|
||
{
|
||
for (int i = 0; i < 2; i++) {
|
||
spi_disable(spi_regs[i]);
|
||
}
|
||
}
|
||
|
||
REGISTER_UPDATE_TARGET(spi_update_target) = {
|
||
.name = "spi",
|
||
.driver_close = spi_disable_for_ota,
|
||
};
|