1200 lines
35 KiB
C
1200 lines
35 KiB
C
/*******************************************************************************
|
|
@file spi.c
|
|
@brief Contains all functions support for spi driver
|
|
@version 0.0
|
|
@date 18. Oct. 2017
|
|
@author qing.han
|
|
|
|
SDK_LICENSE
|
|
|
|
*******************************************************************************/
|
|
#include "rom_sym_def.h"
|
|
#include "bus_dev.h"
|
|
#include "spi.h"
|
|
#include "gpio.h"
|
|
#include "error.h"
|
|
#include <string.h>
|
|
#include "pwrmgr.h"
|
|
#include "clock.h"
|
|
#include "log.h"
|
|
#include "jump_function.h"
|
|
|
|
#if DMAC_USE
|
|
#include "dma.h"
|
|
#endif
|
|
|
|
typedef struct _spi_Context
|
|
{
|
|
spi_Cfg_t cfg;
|
|
hal_spi_t* spi_info;
|
|
bool is_slave_mode;
|
|
spi_xmit_t transmit;
|
|
} spi_Ctx_t;
|
|
|
|
static spi_Ctx_t m_spiCtx[2];
|
|
|
|
#define SPI_HDL_VALIDATE(hdl) {if((hdl == NULL) || (hdl->spi_index > 1))\
|
|
return PPlus_ERR_INVALID_PARAM;\
|
|
if((hdl != m_spiCtx[0].spi_info) && (hdl != m_spiCtx[1].spi_info))\
|
|
return PPlus_ERR_NOT_REGISTED;}
|
|
|
|
|
|
////////////////// SPI /////////////////////////////////////////
|
|
static void hal_spi_write_fifo(AP_SSI_TypeDef* Ssix,uint8_t len,uint8_t* tx_rx_ptr)
|
|
{
|
|
uint8_t i=0;
|
|
SPI_INDEX_e spi_index = (Ssix == AP_SPI0) ? SPI0 : SPI1;
|
|
HAL_ENTER_CRITICAL_SECTION();
|
|
|
|
while(i<len)
|
|
{
|
|
if (m_spiCtx[spi_index].cfg.spi_dfsmod <= SPI_1BYTE)
|
|
{
|
|
Ssix->DataReg = *(tx_rx_ptr+i);
|
|
}
|
|
else
|
|
{
|
|
Ssix->DataReg = *((uint16_t*)tx_rx_ptr+i);
|
|
}
|
|
|
|
i++;
|
|
}
|
|
|
|
HAL_EXIT_CRITICAL_SECTION();
|
|
}
|
|
|
|
|
|
void spi_int_enable(hal_spi_t* spi_ptr, uint32_t mask)
|
|
{
|
|
AP_SSI_TypeDef* Ssix = NULL;
|
|
Ssix = (spi_ptr->spi_index == SPI0) ? AP_SPI0 : AP_SPI1;
|
|
Ssix->IMR = mask & 0x11;
|
|
|
|
if(Ssix == AP_SPI0)
|
|
{
|
|
JUMP_FUNCTION(SPI0_IRQ_HANDLER) = (uint32_t)&hal_SPI0_IRQHandler;
|
|
}
|
|
else
|
|
{
|
|
JUMP_FUNCTION(SPI1_IRQ_HANDLER) = (uint32_t)&hal_SPI1_IRQHandler;
|
|
}
|
|
|
|
NVIC_EnableIRQ((IRQn_Type)(SPI0_IRQn + spi_ptr->spi_index));
|
|
NVIC_SetPriority((IRQn_Type)(SPI0_IRQn + spi_ptr->spi_index), IRQ_PRIO_HAL);
|
|
}
|
|
|
|
static void spi_int_disable(hal_spi_t* spi_ptr)
|
|
{
|
|
AP_SSI_TypeDef* Ssix = NULL;
|
|
Ssix = (spi_ptr->spi_index == SPI0) ? AP_SPI0 : AP_SPI1;
|
|
NVIC_DisableIRQ((IRQn_Type)(SPI0_IRQn + spi_ptr->spi_index));
|
|
Ssix->IMR = 0x00;
|
|
}
|
|
|
|
static void spi_int_handle(uint8_t id, spi_Ctx_t* pctx, AP_SSI_TypeDef* Ssix)
|
|
{
|
|
volatile uint8_t spi_irs_status;
|
|
spi_evt_t evt;
|
|
uint8_t i, cnt;
|
|
spi_xmit_t* trans_ptr;
|
|
trans_ptr = &pctx->transmit;
|
|
spi_irs_status = Ssix->ISR;
|
|
|
|
if(spi_irs_status & TRANSMIT_FIFO_EMPTY)
|
|
{
|
|
cnt = 8 - Ssix->TXFLR;
|
|
|
|
for(i = 0; i< cnt; i++)
|
|
{
|
|
if(trans_ptr->tx_buf)
|
|
{
|
|
Ssix->DataReg = trans_ptr->tx_buf[trans_ptr->tx_offset ++];
|
|
}
|
|
else
|
|
{
|
|
trans_ptr->tx_offset++;
|
|
Ssix->DataReg = 0;
|
|
}
|
|
|
|
if(trans_ptr->tx_offset == trans_ptr->xmit_len)
|
|
{
|
|
Ssix->IMR = 0x10;
|
|
m_spiCtx[pctx->spi_info->spi_index].transmit.busy = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(spi_irs_status & RECEIVE_FIFO_FULL)
|
|
{
|
|
cnt = Ssix->RXFTLR;
|
|
|
|
for(i = 0; i< cnt; i++)
|
|
{
|
|
trans_ptr->rx_buf[trans_ptr->rx_offset++] = Ssix->DataReg;
|
|
}
|
|
|
|
if(trans_ptr->rx_offset == trans_ptr->xmit_len)
|
|
{
|
|
if(pctx->cfg.force_cs == true)
|
|
hal_gpio_fmux(pctx->cfg.ssn_pin, Bit_ENABLE);
|
|
|
|
trans_ptr->busy = false;
|
|
trans_ptr->rx_buf = NULL;
|
|
trans_ptr->rx_offset = 0;
|
|
evt.id = id;
|
|
evt.evt = SPI_RX_COMPLETED;
|
|
hal_pwrmgr_unlock((MODULE_e)(MOD_SPI0 + id));
|
|
pctx->cfg.evt_handler(&evt);
|
|
evt.evt = SPI_TX_COMPLETED;
|
|
pctx->cfg.evt_handler(&evt);
|
|
}
|
|
}
|
|
}
|
|
|
|
static void spis_int_handle(uint8_t id, spi_Ctx_t* pctx, AP_SSI_TypeDef* Ssix)
|
|
{
|
|
volatile uint8_t spi_irs_status;
|
|
spi_xmit_t* trans_ptr;
|
|
spi_evt_t evt;
|
|
uint16_t i, cnt;
|
|
trans_ptr = &(pctx->transmit);
|
|
spi_irs_status = Ssix->ISR;
|
|
|
|
if(spi_irs_status & TRANSMIT_FIFO_EMPTY)
|
|
{
|
|
cnt = 8 - Ssix->TXFLR;
|
|
|
|
for(i = 0; i< cnt; i++)
|
|
{
|
|
if(trans_ptr->tx_offset == trans_ptr->xmit_len)
|
|
{
|
|
Ssix->IMR = 0x10;
|
|
break;
|
|
}
|
|
|
|
if(trans_ptr->tx_buf)
|
|
{
|
|
Ssix->DataReg = trans_ptr->tx_buf[trans_ptr->tx_offset ++];
|
|
}
|
|
else
|
|
{
|
|
trans_ptr->tx_offset ++;
|
|
Ssix->DataReg = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(spi_irs_status & RECEIVE_FIFO_FULL)
|
|
{
|
|
volatile uint32_t garbage;
|
|
cnt = Ssix->RXFLR;
|
|
|
|
if(trans_ptr->rx_buf)
|
|
{
|
|
for(i = 0; i< cnt; i++)
|
|
{
|
|
if(trans_ptr->xmit_len > trans_ptr->rx_offset)
|
|
trans_ptr->rx_buf[trans_ptr->rx_offset++] = Ssix->DataReg;
|
|
else
|
|
garbage = Ssix->DataReg;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
uint8_t rxbuf[16];
|
|
|
|
if(trans_ptr->busy)
|
|
trans_ptr->rx_offset += cnt;
|
|
|
|
for(i = 0; i< cnt; i++)
|
|
{
|
|
*(rxbuf+i) = Ssix->DataReg;
|
|
}
|
|
|
|
evt.id = id;
|
|
evt.evt = SPI_RX_DATA_S;
|
|
evt.data = rxbuf;
|
|
evt.len = cnt;
|
|
pctx->cfg.evt_handler(&evt);
|
|
}
|
|
|
|
if(trans_ptr->busy && trans_ptr->rx_offset >= trans_ptr->xmit_len)
|
|
{
|
|
memset(trans_ptr, 0, sizeof(spi_xmit_t));
|
|
evt.id = id;
|
|
evt.evt = SPI_RX_COMPLETED;
|
|
evt.data = NULL;
|
|
evt.len = cnt;
|
|
pctx->cfg.evt_handler(&evt);
|
|
evt.evt = SPI_TX_COMPLETED;
|
|
pctx->cfg.evt_handler(&evt);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**************************************************************************************
|
|
@fn hal_SPI0_IRQHandler
|
|
|
|
@brief This function process for spi0 interrupt,when use int please consummate its callbackfunction
|
|
|
|
input parameters
|
|
|
|
@param None.
|
|
|
|
output parameters
|
|
|
|
@param None.
|
|
|
|
@return None.
|
|
**************************************************************************************/
|
|
void __attribute__((used)) hal_SPI0_IRQHandler(void)
|
|
{
|
|
spi_Ctx_t* pctx = &m_spiCtx[0];
|
|
|
|
if(pctx->spi_info == NULL)
|
|
return;
|
|
|
|
if(pctx->is_slave_mode)
|
|
spis_int_handle(0, pctx, AP_SPI0);
|
|
else
|
|
spi_int_handle(0, pctx, AP_SPI0);
|
|
}
|
|
|
|
/**************************************************************************************
|
|
@fn hal_SPI1_IRQHandler
|
|
|
|
@brief This function process for spi1 interrupt,when use int please consummate its callbackfunction
|
|
|
|
input parameters
|
|
|
|
@param None.
|
|
|
|
output parameters
|
|
|
|
@param None.
|
|
|
|
@return None.
|
|
**************************************************************************************/
|
|
void __attribute__((used)) hal_SPI1_IRQHandler(void)
|
|
{
|
|
spi_Ctx_t* pctx = &m_spiCtx[1];
|
|
|
|
if(pctx->spi_info == NULL)
|
|
return;
|
|
|
|
if(pctx->is_slave_mode)
|
|
spis_int_handle(1, pctx, AP_SPI1);
|
|
else
|
|
spi_int_handle(1, pctx, AP_SPI1);
|
|
}
|
|
|
|
/**************************************************************************************
|
|
@fn hal_spi_pin_init
|
|
|
|
@brief This function process for spi pin initial(4 lines);You can use two spi,spi0 and spi1,should programe by USE_AP_SPIX
|
|
|
|
input parameters
|
|
|
|
@param GPIO_Pin_e sck_pin: define sclk pin
|
|
GPIO_Pin_e ssn_pin: define ssn pin
|
|
GPIO_Pin_e tx_pin: define transmit pin;when use as master,it's mosi pin;corresponding,use as slave,it's miso
|
|
GPIO_Pin_e rx_pin: define receive pin;when use as master,it's miso pin;corresponding,use as slave,it's mosi
|
|
|
|
output parameters
|
|
|
|
@param None.
|
|
|
|
@return None.
|
|
**************************************************************************************/
|
|
static void hal_spi_pin_init(hal_spi_t* spi_ptr,GPIO_Pin_e sck_pin,GPIO_Pin_e ssn_pin,GPIO_Pin_e tx_pin,GPIO_Pin_e rx_pin)
|
|
{
|
|
if(spi_ptr->spi_index == SPI0)
|
|
{
|
|
hal_gpio_fmux_set(sck_pin, FMUX_SPI_0_SCK);
|
|
hal_gpio_fmux_set(ssn_pin, FMUX_SPI_0_SSN);
|
|
hal_gpio_fmux_set(tx_pin, FMUX_SPI_0_TX);
|
|
hal_gpio_fmux_set(rx_pin, FMUX_SPI_0_RX);
|
|
}
|
|
else if(spi_ptr->spi_index == SPI1)
|
|
{
|
|
hal_gpio_fmux_set(sck_pin, FMUX_SPI_1_SCK);
|
|
hal_gpio_fmux_set(ssn_pin, FMUX_SPI_1_SSN);
|
|
hal_gpio_fmux_set(tx_pin, FMUX_SPI_1_TX);
|
|
hal_gpio_fmux_set(rx_pin, FMUX_SPI_1_RX);
|
|
}
|
|
}
|
|
|
|
static void hal_spi_pin_deinit(GPIO_Pin_e sck_pin,GPIO_Pin_e ssn_pin,GPIO_Pin_e tx_pin,GPIO_Pin_e rx_pin)
|
|
{
|
|
hal_gpio_fmux(sck_pin, Bit_DISABLE);
|
|
hal_gpio_fmux(ssn_pin, Bit_DISABLE);
|
|
hal_gpio_fmux(tx_pin, Bit_DISABLE);
|
|
hal_gpio_fmux(rx_pin, Bit_DISABLE);
|
|
}
|
|
|
|
/**************************************************************************************
|
|
@fn hal_spi_master_init
|
|
|
|
@brief This function process for spi master initial
|
|
|
|
input parameters
|
|
|
|
@param uint32_t baud: baudrate select
|
|
SPI_SCMOD_e scmod: Serial Clock Polarity and Phase select; SPI_MODE0, //SCPOL=0,SCPH=0(default)
|
|
SPI_MODE1, //SCPOL=0,SCPH=1
|
|
SPI_MODE2, //SCPOL=1,SCPH=0
|
|
SPI_MODE3, //SCPOL=1,SCPH=1
|
|
SPI_TMOD_e tmod: Transfer Mode SPI_TRXD, //Transmit & Receive(default)
|
|
SPI_TXD, //Transmit Only
|
|
SPI_RXD, //Receive Only
|
|
SPI_EEPROM, //EEPROM Read
|
|
|
|
output parameters
|
|
|
|
@param None.
|
|
|
|
@return None.
|
|
**************************************************************************************/
|
|
static void hal_spi_master_init(hal_spi_t* spi_ptr,uint32_t baud,SPI_SCMOD_e scmod,SPI_TMOD_e tmod)
|
|
{
|
|
uint8_t shift = 0;
|
|
AP_SSI_TypeDef* Ssix = NULL;
|
|
AP_COM_TypeDef* apcom = AP_COM;
|
|
uint16_t baud_temp;
|
|
int pclk = clk_get_pclk();
|
|
|
|
if(spi_ptr->spi_index == SPI1)
|
|
{
|
|
shift = 1;
|
|
}
|
|
|
|
Ssix = (spi_ptr->spi_index == SPI0) ? AP_SPI0 : AP_SPI1;
|
|
Ssix->SSIEN = 0; //DISABLE_SPI;
|
|
apcom->PERI_MASTER_SELECT |= (BIT(shift)|BIT(shift+4));
|
|
Ssix->CR0= ((Ssix->CR0) & 0xfffffc3f)|(scmod<<6)|(tmod<<8);
|
|
baud_temp = (pclk + (baud>>1)) / baud;
|
|
|
|
if(baud_temp<2)
|
|
{
|
|
baud_temp = 2;
|
|
}
|
|
else if(baud_temp>65534)
|
|
{
|
|
baud_temp =65534;
|
|
}
|
|
|
|
Ssix->BAUDR= baud_temp; // set clock(round)
|
|
Ssix->TXFTLR=4; // set fifo threshold to triggle interrupt
|
|
Ssix->RXFTLR=1;
|
|
Ssix->IMR = 0x00;
|
|
Ssix->SER=1; //enable slave device
|
|
Ssix->SSIEN = 1; //ENABLE_SPI;
|
|
}
|
|
|
|
/**************************************************************************************
|
|
@fn hal_spi_slave_init
|
|
|
|
@brief This function process for spi slave initial
|
|
|
|
input parameters
|
|
|
|
@param uint32_t baud: baudrate select
|
|
SPI_SCMOD_e scmod: Serial Clock Polarity and Phase select; SPI_MODE0, //SCPOL=0,SCPH=0(default)
|
|
SPI_MODE1, //SCPOL=0,SCPH=1
|
|
SPI_MODE2, //SCPOL=1,SCPH=0
|
|
SPI_MODE3, //SCPOL=1,SCPH=1
|
|
SPI_TMOD_e tmod: Transfer Mode SPI_TRXD, //Transmit & Receive(default)
|
|
SPI_TXD, //Transmit Only
|
|
SPI_RXD, //Receive Only
|
|
SPI_EEPROM, //EEPROM Read
|
|
|
|
output parameters
|
|
|
|
@param None.
|
|
|
|
@return None.
|
|
**************************************************************************************/
|
|
/*static*/ void hal_spi_slave_init(hal_spi_t* spi_ptr,uint32_t baud,SPI_SCMOD_e scmod,SPI_TMOD_e tmod)
|
|
{
|
|
uint8_t shift = 0;
|
|
AP_SSI_TypeDef* Ssix = NULL;
|
|
AP_COM_TypeDef* apcom = AP_COM;
|
|
uint16_t baud_temp;
|
|
int pclk = clk_get_pclk();
|
|
|
|
if(spi_ptr->spi_index == SPI1)
|
|
{
|
|
shift = 1;
|
|
}
|
|
|
|
Ssix = (spi_ptr->spi_index == SPI0) ? AP_SPI0 : AP_SPI1;
|
|
Ssix->SSIEN = 0; //DISABLE_SPI;
|
|
apcom->PERI_MASTER_SELECT &= ~(BIT(shift));
|
|
Ssix->CR0= ((Ssix->CR0) & 0xfffffc3f)|(scmod<<6)|(tmod<<8)|0x400;
|
|
baud_temp = (pclk + (baud>>1)) / baud;
|
|
|
|
if(baud_temp<2)
|
|
{
|
|
baud_temp = 2;
|
|
}
|
|
else if(baud_temp>65534)
|
|
{
|
|
baud_temp =65534;
|
|
}
|
|
|
|
Ssix->BAUDR= baud_temp; // set clock(round)
|
|
Ssix->TXFTLR=4; // set fifo threshold to triggle interrupt
|
|
Ssix->RXFTLR=1; //threshold is 1
|
|
Ssix->IMR=0x11; //enable tx and rx
|
|
// Ssix->SER=1; //enable slave device
|
|
Ssix->SSIEN = 1; //ENABLE_SPI;
|
|
}
|
|
#if DMAC_USE
|
|
static void config_dma_channel4spitx(hal_spi_t* spi_ptr,uint8_t* tx_buf,uint16_t tx_len)
|
|
{
|
|
DMA_CH_CFG_t cfgc;
|
|
AP_SSI_TypeDef* Ssix = NULL;
|
|
Ssix = (spi_ptr->spi_index == SPI0) ? AP_SPI0 : AP_SPI1;
|
|
Ssix->DMACR &= 0x01;
|
|
spi_Ctx_t* pctx;
|
|
pctx = &m_spiCtx[spi_ptr->spi_index];
|
|
cfgc.sinc = DMA_INC_INC;
|
|
|
|
if(pctx->cfg.spi_dfsmod <= SPI_1BYTE)
|
|
{
|
|
hal_spi_dfs_set(spi_ptr,SPI_1BYTE);
|
|
cfgc.transf_size = tx_len;
|
|
cfgc.src_tr_width = DMA_WIDTH_BYTE;
|
|
cfgc.dst_tr_width = DMA_WIDTH_BYTE;
|
|
cfgc.src_addr = (uint32_t)tx_buf;
|
|
}
|
|
else
|
|
{
|
|
uint16_t* size16_tx_buf = (uint16_t*)tx_buf;
|
|
hal_spi_dfs_set(spi_ptr,SPI_2BYTE);
|
|
cfgc.transf_size = tx_len/2;
|
|
cfgc.src_tr_width = DMA_WIDTH_HALFWORD;
|
|
cfgc.dst_tr_width = DMA_WIDTH_HALFWORD;
|
|
cfgc.src_addr = (uint32_t)size16_tx_buf;
|
|
}
|
|
|
|
cfgc.src_msize = DMA_BSIZE_1;
|
|
cfgc.dinc = DMA_INC_NCHG;
|
|
cfgc.dst_msize = DMA_BSIZE_1;
|
|
cfgc.dst_addr = (uint32_t)&(Ssix->DataReg);
|
|
cfgc.enable_int = false;
|
|
hal_dma_config_channel(DMA_CH_0,&cfgc);
|
|
hal_dma_start_channel(DMA_CH_0);
|
|
Ssix->DMACR |= 0x02;
|
|
Ssix->DMATDLR = 0;
|
|
}
|
|
|
|
static void config_dma_channel4spirx(hal_spi_t* spi_ptr,uint8_t* rx_buf,uint16_t rx_len)
|
|
{
|
|
DMA_CH_CFG_t cfgc;
|
|
AP_SSI_TypeDef* Ssix = NULL;
|
|
Ssix = (spi_ptr->spi_index == SPI0) ? AP_SPI0 : AP_SPI1;
|
|
Ssix->DMACR &= 0x02;
|
|
cfgc.transf_size = rx_len;
|
|
cfgc.sinc = DMA_INC_NCHG;
|
|
cfgc.src_tr_width = DMA_WIDTH_BYTE;
|
|
cfgc.src_msize = DMA_BSIZE_1;
|
|
cfgc.src_addr = (uint32_t)&(Ssix->DataReg);
|
|
cfgc.dinc = DMA_INC_INC;
|
|
cfgc.dst_tr_width = DMA_WIDTH_BYTE;
|
|
cfgc.dst_msize = DMA_BSIZE_1;
|
|
cfgc.dst_addr = (uint32_t)rx_buf;
|
|
cfgc.enable_int = false;
|
|
hal_dma_config_channel(DMA_CH_0,&cfgc);
|
|
hal_dma_start_channel(DMA_CH_0);
|
|
Ssix->DMACR |= 0x01;
|
|
Ssix->DMARDLR = 0;
|
|
}
|
|
#endif
|
|
|
|
static int hal_spi_xmit_polling
|
|
(
|
|
hal_spi_t* spi_ptr,
|
|
uint8_t* tx_buf,
|
|
uint8_t* rx_buf,
|
|
uint16_t tx_len,
|
|
uint16_t rx_len
|
|
)
|
|
{
|
|
uint32_t rx_size = rx_len, tx_size = tx_len;
|
|
uint32_t tmp_len,i,tmp_tx_buf_len = 0;
|
|
AP_SSI_TypeDef* Ssix = NULL;
|
|
#if DMAC_USE
|
|
spi_Ctx_t* pctx;
|
|
pctx = &m_spiCtx[spi_ptr->spi_index];
|
|
#endif
|
|
Ssix = (spi_ptr->spi_index == SPI0) ? AP_SPI0 : AP_SPI1;
|
|
SPI_INIT_TOUT(to);
|
|
#if DMAC_USE
|
|
|
|
if(rx_len && pctx->cfg.dma_rx_enable)
|
|
{
|
|
config_dma_channel4spirx(spi_ptr,rx_buf,rx_len);
|
|
}
|
|
else if(tx_len && pctx->cfg.dma_tx_enable)
|
|
{
|
|
config_dma_channel4spitx(spi_ptr,tx_buf,tx_len);
|
|
}
|
|
|
|
#endif
|
|
|
|
while(1)
|
|
{
|
|
if(Ssix->SR & TX_FIFO_NOT_FULL && tx_size
|
|
#if DMAC_USE
|
|
&& !(pctx->cfg.dma_tx_enable)
|
|
#endif
|
|
)
|
|
//#if DMAC_USE
|
|
// if(Ssix->SR & TX_FIFO_NOT_FULL && tx_size && !(pctx->cfg.dma_tx_enable))
|
|
//#else
|
|
// if(Ssix->SR & TX_FIFO_NOT_FULL && tx_size)
|
|
//#endif
|
|
{
|
|
tmp_len = 8-Ssix->TXFLR;
|
|
|
|
if(tmp_len > tx_size)
|
|
tmp_len = tx_size;
|
|
|
|
if(tx_buf)
|
|
{
|
|
//support divider 2
|
|
if (m_spiCtx[spi_ptr->spi_index].cfg.spi_dfsmod <= SPI_1BYTE)
|
|
{
|
|
switch (tmp_len)
|
|
{
|
|
case 1:
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len);
|
|
tmp_tx_buf_len += 1;
|
|
break;
|
|
|
|
case 2:
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+1);
|
|
tmp_tx_buf_len += 2;
|
|
break;
|
|
|
|
case 3:
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+1);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+2);
|
|
tmp_tx_buf_len += 3;
|
|
break;
|
|
|
|
case 4:
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+1);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+2);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+3);
|
|
tmp_tx_buf_len += 4;
|
|
break;
|
|
|
|
case 5:
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+1);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+2);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+3);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+4);
|
|
tmp_tx_buf_len += 5;
|
|
break;
|
|
|
|
case 6:
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+1);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+2);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+3);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+4);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+5);
|
|
tmp_tx_buf_len += 6;
|
|
break;
|
|
|
|
case 7:
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+1);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+2);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+3);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+4);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+5);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+6);
|
|
tmp_tx_buf_len += 7;
|
|
break;
|
|
|
|
case 8:
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+1);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+2);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+3);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+4);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+5);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+6);
|
|
Ssix->DataReg = *(tx_buf+tmp_tx_buf_len+7);
|
|
tmp_tx_buf_len += 8;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (tmp_len)
|
|
{
|
|
case 1:
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len);
|
|
tmp_tx_buf_len += 1;
|
|
break;
|
|
|
|
case 2:
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+1);
|
|
tmp_tx_buf_len += 2;
|
|
break;
|
|
|
|
case 3:
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+1);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+2);
|
|
tmp_tx_buf_len += 3;
|
|
break;
|
|
|
|
case 4:
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+1);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+2);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+3);
|
|
tmp_tx_buf_len += 4;
|
|
break;
|
|
|
|
case 5:
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+1);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+2);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+3);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+4);
|
|
tmp_tx_buf_len += 5;
|
|
break;
|
|
|
|
case 6:
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+1);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+2);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+3);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+4);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+5);
|
|
tmp_tx_buf_len += 6;
|
|
break;
|
|
|
|
case 7:
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+1);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+2);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+3);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+4);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+5);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+6);
|
|
tmp_tx_buf_len += 7;
|
|
break;
|
|
|
|
case 8:
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+1);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+2);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+3);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+4);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+5);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+6);
|
|
Ssix->DataReg = *((uint16_t*)tx_buf+tmp_tx_buf_len+7);
|
|
tmp_tx_buf_len += 8;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for(i = 0; i< tmp_len; i++)
|
|
{
|
|
Ssix->DataReg = 0;
|
|
}
|
|
}
|
|
|
|
tx_size -= tmp_len;
|
|
}
|
|
|
|
#if DMAC_USE
|
|
|
|
if(((rx_len == 0) && ((tx_size == 0)||(tx_size && (pctx->cfg.dma_tx_enable)))) ||
|
|
(rx_len && (tx_size == 0) && (pctx->cfg.dma_rx_enable)))
|
|
break;
|
|
else if(rx_len && !(pctx->cfg.dma_rx_enable))
|
|
#else
|
|
if((rx_len == 0) && ((tx_size == 0)))
|
|
break;
|
|
else if(rx_len)
|
|
#endif
|
|
{
|
|
if(Ssix->RXFLR)
|
|
{
|
|
tmp_len = Ssix->RXFLR;
|
|
|
|
for(i = 0; i< tmp_len; i++)
|
|
{
|
|
*rx_buf++= Ssix->DataReg;
|
|
}
|
|
|
|
rx_size -= tmp_len;
|
|
}
|
|
|
|
if(rx_size == 0)
|
|
break;
|
|
}
|
|
|
|
SPI_CHECK_TOUT(to, SPI_OP_TIMEOUT, "hal_spi_xmit_polling TO\n");
|
|
}
|
|
|
|
#if DMAC_USE
|
|
|
|
if((pctx->cfg.dma_rx_enable) || (pctx->cfg.dma_tx_enable))
|
|
hal_dma_status_control(DMA_CH_0);
|
|
|
|
#endif
|
|
|
|
while(Ssix->SR & SPI_BUSY)
|
|
{
|
|
SPI_CHECK_TOUT(to, SPI_OP_TIMEOUT, "hal_spi_xmit_polling TO\n");
|
|
}
|
|
|
|
return PPlus_SUCCESS;
|
|
}
|
|
|
|
static void spi0_sleep_handler(void)
|
|
{
|
|
if(m_spiCtx[0].spi_info != NULL)
|
|
hal_spi_bus_deinit(m_spiCtx[0].spi_info);
|
|
}
|
|
|
|
static void spi1_sleep_handler(void)
|
|
{
|
|
if(m_spiCtx[1].spi_info != NULL)
|
|
hal_spi_bus_deinit(m_spiCtx[1].spi_info);
|
|
}
|
|
|
|
static void spi0_wakeup_handler(void)
|
|
{
|
|
NVIC_SetPriority((IRQn_Type)SPI0_IRQn, IRQ_PRIO_HAL);
|
|
}
|
|
|
|
static void spi1_wakeup_handler(void)
|
|
{
|
|
NVIC_SetPriority((IRQn_Type)SPI1_IRQn, IRQ_PRIO_HAL);
|
|
}
|
|
|
|
void hal_spi_tmod_set(hal_spi_t* spi_ptr,SPI_TMOD_e mod)
|
|
{
|
|
AP_SSI_TypeDef* Ssix = NULL;
|
|
Ssix = (spi_ptr->spi_index == SPI0) ? AP_SPI0 : AP_SPI1;
|
|
Ssix->SSIEN = 0;
|
|
subWriteReg(&Ssix->CR0,9,8,mod);
|
|
Ssix->SSIEN = 1;
|
|
}
|
|
|
|
void hal_spi_dfs_set(hal_spi_t* spi_ptr,SPI_DFS_e mod)
|
|
{
|
|
AP_SSI_TypeDef* Ssix = NULL;
|
|
spi_Ctx_t* pctx;
|
|
Ssix = (spi_ptr->spi_index == SPI0) ? AP_SPI0 : AP_SPI1;
|
|
pctx = &m_spiCtx[spi_ptr->spi_index];
|
|
Ssix->SSIEN = 0;
|
|
subWriteReg(&Ssix->CR0,3,0,mod);
|
|
Ssix->SSIEN = 1;
|
|
pctx->cfg.spi_dfsmod = mod;
|
|
}
|
|
|
|
|
|
|
|
static void hal_spi_ndf_set(hal_spi_t* spi_ptr,uint16_t len)
|
|
{
|
|
AP_SSI_TypeDef* Ssix = NULL;
|
|
|
|
if(len == 0)
|
|
return;
|
|
|
|
Ssix = (spi_ptr->spi_index == SPI0) ? AP_SPI0 : AP_SPI1;
|
|
Ssix->SSIEN = 0;
|
|
Ssix->CR1 = len-1;
|
|
Ssix->SSIEN = 1;
|
|
}
|
|
|
|
int hal_spi_transmit
|
|
(
|
|
hal_spi_t* spi_ptr,
|
|
SPI_TMOD_e mod,
|
|
uint8_t* tx_buf,
|
|
uint8_t* rx_buf,
|
|
uint16_t tx_len,
|
|
uint16_t rx_len
|
|
)
|
|
{
|
|
int ret;
|
|
spi_Ctx_t* pctx;
|
|
AP_SSI_TypeDef* Ssix = NULL;
|
|
spi_xmit_t* trans_ptr;
|
|
SPI_HDL_VALIDATE(spi_ptr);
|
|
pctx = &m_spiCtx[spi_ptr->spi_index];
|
|
trans_ptr = &(pctx->transmit);
|
|
|
|
if(((tx_len == 0)&&(rx_len == 0))||(mod > SPI_EEPROM)||(tx_buf == NULL))
|
|
return PPlus_ERR_INVALID_PARAM;
|
|
|
|
if(pctx->transmit.busy == true)
|
|
return PPlus_ERR_BUSY;
|
|
|
|
#if DMAC_USE
|
|
|
|
if((pctx->cfg.dma_rx_enable && (rx_len==0)) ||
|
|
(pctx->cfg.dma_tx_enable && (tx_len==0)))
|
|
{
|
|
return PPlus_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
#endif
|
|
Ssix = (spi_ptr->spi_index == SPI0) ? AP_SPI0 : AP_SPI1;
|
|
hal_spi_tmod_set(spi_ptr,mod);
|
|
|
|
if(mod > SPI_TXD) //spi receive only or eeprom read,should set read data len(ndf)
|
|
{
|
|
hal_spi_ndf_set(spi_ptr,rx_len);
|
|
}
|
|
|
|
if(pctx->cfg.force_cs == true /*&& pctx->is_slave_mode == FALSE*/)
|
|
{
|
|
hal_gpio_fmux(pctx->cfg.ssn_pin,Bit_DISABLE);
|
|
hal_gpio_write(pctx->cfg.ssn_pin,0);
|
|
}
|
|
|
|
if(pctx->cfg.int_mode == false)
|
|
{
|
|
ret = hal_spi_xmit_polling(spi_ptr,tx_buf, rx_buf, tx_len,rx_len);
|
|
|
|
if(pctx->cfg.force_cs == true && pctx->is_slave_mode == FALSE)
|
|
hal_gpio_fmux(pctx->cfg.ssn_pin,Bit_ENABLE);
|
|
|
|
if(ret)
|
|
return PPlus_ERR_TIMEOUT;
|
|
}
|
|
else
|
|
{
|
|
spi_int_disable(spi_ptr);
|
|
|
|
if(trans_ptr->buf_len < tx_len)
|
|
return PPlus_ERR_NO_MEM;
|
|
|
|
if(tx_buf)
|
|
{
|
|
if(!trans_ptr->tx_buf)
|
|
return PPlus_ERR_NO_MEM;
|
|
}
|
|
|
|
trans_ptr->tx_offset = 0;
|
|
memcpy(trans_ptr->tx_buf,tx_buf,tx_len);
|
|
|
|
if(Ssix->SR & TX_FIFO_NOT_FULL)
|
|
{
|
|
uint16_t _tx_len;
|
|
uint8_t dummy[8];
|
|
|
|
if(rx_buf)
|
|
{
|
|
trans_ptr->rx_buf = rx_buf;
|
|
}
|
|
|
|
hal_pwrmgr_lock((MODULE_e)(MOD_SPI0 + spi_ptr->spi_index));
|
|
_tx_len = (tx_len >= 8)?8:tx_len;
|
|
|
|
if(trans_ptr->tx_buf)
|
|
{
|
|
trans_ptr->tx_offset += _tx_len;
|
|
hal_spi_write_fifo(Ssix,_tx_len,tx_buf);
|
|
}
|
|
else
|
|
{
|
|
hal_spi_write_fifo(Ssix,_tx_len,dummy);
|
|
}
|
|
|
|
trans_ptr->xmit_len = tx_len;
|
|
}
|
|
|
|
pctx->transmit.busy = true;
|
|
spi_int_enable(spi_ptr, 0x11);
|
|
}
|
|
|
|
return PPlus_SUCCESS;
|
|
}
|
|
|
|
int hal_spi_set_tx_buffer(hal_spi_t* spi_ptr,uint8_t* tx_buf,uint16_t len)
|
|
{
|
|
SPI_HDL_VALIDATE(spi_ptr);
|
|
|
|
if((tx_buf == NULL) || (len == 0))
|
|
return PPlus_ERR_INVALID_PARAM;
|
|
|
|
m_spiCtx[spi_ptr->spi_index].transmit.tx_buf = tx_buf;//used when tx int
|
|
m_spiCtx[spi_ptr->spi_index].transmit.buf_len = len;
|
|
return PPlus_SUCCESS;
|
|
}
|
|
|
|
int hal_spi_set_int_mode(hal_spi_t* spi_ptr,bool en)
|
|
{
|
|
SPI_HDL_VALIDATE(spi_ptr);
|
|
m_spiCtx[spi_ptr->spi_index].cfg.int_mode = en;
|
|
|
|
if(en)
|
|
{
|
|
m_spiCtx[spi_ptr->spi_index].cfg.int_mode = true;
|
|
spi_int_enable(spi_ptr, 0x10);
|
|
}
|
|
else
|
|
{
|
|
m_spiCtx[spi_ptr->spi_index].cfg.int_mode = false;
|
|
spi_int_disable(spi_ptr);
|
|
}
|
|
|
|
return PPlus_SUCCESS;
|
|
}
|
|
|
|
int hal_spi_set_force_cs(hal_spi_t* spi_ptr,bool en)
|
|
{
|
|
SPI_HDL_VALIDATE(spi_ptr);
|
|
m_spiCtx[spi_ptr->spi_index].cfg.force_cs = en;
|
|
return PPlus_SUCCESS;
|
|
}
|
|
|
|
bool hal_spi_get_transmit_bus_state(hal_spi_t* spi_ptr)
|
|
{
|
|
return m_spiCtx[spi_ptr->spi_index].transmit.busy;
|
|
}
|
|
|
|
|
|
int hal_spi_TxComplete(hal_spi_t* spi_ptr)
|
|
{
|
|
AP_SSI_TypeDef* Ssix = NULL;
|
|
SPI_HDL_VALIDATE(spi_ptr);
|
|
Ssix = (spi_ptr->spi_index == SPI0) ? AP_SPI0 : AP_SPI1;
|
|
SPI_INIT_TOUT(to);
|
|
|
|
while(Ssix->SR & SPI_BUSY)
|
|
{
|
|
SPI_CHECK_TOUT(to, SPI_OP_TIMEOUT, "hal_spi_TxComplete TO\n");
|
|
}
|
|
|
|
return PPlus_SUCCESS;
|
|
}
|
|
|
|
int hal_spi_send_byte(hal_spi_t* spi_ptr,uint8_t data)
|
|
{
|
|
AP_SSI_TypeDef* Ssix = NULL;
|
|
SPI_HDL_VALIDATE(spi_ptr);
|
|
Ssix = (spi_ptr->spi_index == SPI0) ? AP_SPI0 : AP_SPI1;
|
|
|
|
if(Ssix->SR & TX_FIFO_NOT_FULL)
|
|
{
|
|
Ssix->DataReg = data & 0xff;
|
|
SPI_INIT_TOUT(to);
|
|
|
|
while(Ssix->SR & SPI_BUSY)
|
|
{
|
|
SPI_CHECK_TOUT(to, SPI_OP_TIMEOUT,"hal_spi_send_byte TO\n");
|
|
}
|
|
}
|
|
|
|
return PPlus_SUCCESS;
|
|
}
|
|
|
|
|
|
int hal_spi_bus_init(hal_spi_t* spi_ptr,spi_Cfg_t cfg)
|
|
{
|
|
spi_Ctx_t* pctx = NULL;
|
|
|
|
if((spi_ptr == NULL) || (spi_ptr->spi_index > 1))
|
|
return PPlus_ERR_INVALID_PARAM;
|
|
|
|
pctx = &m_spiCtx[spi_ptr->spi_index];
|
|
|
|
if(pctx->spi_info != NULL)
|
|
return PPlus_ERR_BUSY;
|
|
|
|
hal_clk_gate_enable((MODULE_e)(MOD_SPI0 + spi_ptr->spi_index));
|
|
hal_spi_pin_init(spi_ptr,cfg.sclk_pin,cfg.ssn_pin,cfg.MOSI,cfg.MISO);
|
|
hal_spi_master_init(spi_ptr,cfg.baudrate, cfg.spi_scmod, cfg.spi_tmod);
|
|
hal_spi_dfs_set(spi_ptr,cfg.spi_dfsmod);
|
|
pctx->cfg = cfg;
|
|
pctx->transmit.busy = false;
|
|
pctx->spi_info = spi_ptr;
|
|
|
|
if(cfg.int_mode)
|
|
spi_int_enable(spi_ptr, 0x10);
|
|
else
|
|
spi_int_disable(spi_ptr);
|
|
|
|
pctx->is_slave_mode = false;
|
|
return PPlus_SUCCESS;
|
|
}
|
|
|
|
int hal_spis_clear_rx(hal_spi_t* spi_ptr)
|
|
{
|
|
AP_SSI_TypeDef* Ssix = NULL;
|
|
volatile uint8_t rx;
|
|
SPI_HDL_VALIDATE(spi_ptr);
|
|
Ssix = (spi_ptr->spi_index == SPI0) ? AP_SPI0 : AP_SPI1;
|
|
|
|
while(Ssix->RXFLR)
|
|
{
|
|
rx = Ssix->DataReg;
|
|
}
|
|
|
|
return (int)rx;
|
|
}
|
|
|
|
uint32_t hal_spis_rx_len(hal_spi_t* spi_ptr)
|
|
{
|
|
AP_SSI_TypeDef* Ssix = NULL;
|
|
Ssix = (spi_ptr->spi_index == SPI0) ? AP_SPI0 : AP_SPI1;
|
|
return Ssix->RXFLR;
|
|
}
|
|
|
|
int hal_spis_read_rxn(hal_spi_t* spi_ptr, uint8_t* pbuf, uint16_t len)
|
|
{
|
|
AP_SSI_TypeDef* Ssix = NULL;
|
|
Ssix = (spi_ptr->spi_index == SPI0) ? AP_SPI0 : AP_SPI1;
|
|
|
|
while(len)
|
|
{
|
|
*pbuf = Ssix->DataReg;
|
|
pbuf ++;
|
|
len --;
|
|
}
|
|
|
|
return PPlus_SUCCESS;
|
|
}
|
|
|
|
int hal_spis_bus_init(hal_spi_t* spi_ptr,spi_Cfg_t cfg)
|
|
{
|
|
spi_Ctx_t* pctx = NULL;
|
|
|
|
if((spi_ptr == NULL) || (spi_ptr->spi_index > 1))
|
|
return PPlus_ERR_INVALID_PARAM;
|
|
|
|
pctx = &m_spiCtx[spi_ptr->spi_index];
|
|
|
|
if(pctx->spi_info != NULL)
|
|
return PPlus_ERR_BUSY;
|
|
|
|
hal_clk_gate_enable((MODULE_e)(MOD_SPI0 + spi_ptr->spi_index));
|
|
hal_spi_pin_init(spi_ptr,cfg.sclk_pin,cfg.ssn_pin,cfg.MOSI,cfg.MISO);
|
|
hal_spi_slave_init(spi_ptr,cfg.baudrate, cfg.spi_scmod, cfg.spi_tmod);
|
|
pctx->cfg = cfg;
|
|
memset(&(pctx->transmit), 0, sizeof(spi_xmit_t));
|
|
pctx->spi_info = spi_ptr;
|
|
pctx->is_slave_mode = true;
|
|
|
|
if(cfg.int_mode)
|
|
spi_int_enable(spi_ptr, 0x10);
|
|
else
|
|
spi_int_disable(spi_ptr);
|
|
|
|
return PPlus_SUCCESS;
|
|
}
|
|
|
|
/**************************************************************************************
|
|
@fn hal_spi_deinit
|
|
|
|
@brief This function will deinit the spi you select.
|
|
|
|
input parameters
|
|
|
|
@param hal_spi_t* spi_ptr: spi module handle.
|
|
|
|
|
|
output parameters
|
|
|
|
@param None.
|
|
|
|
@return
|
|
PPlus_SUCCESS
|
|
PPlus_ERR_INVALID_PARAM
|
|
**************************************************************************************/
|
|
int hal_spi_bus_deinit(hal_spi_t* spi_ptr)
|
|
{
|
|
SPI_HDL_VALIDATE(spi_ptr);
|
|
hal_clk_gate_disable((MODULE_e)(MOD_SPI0 + spi_ptr->spi_index));
|
|
//spi_int_disable(spi_ptr);
|
|
hal_spi_pin_deinit(m_spiCtx[spi_ptr->spi_index].cfg.sclk_pin,m_spiCtx[spi_ptr->spi_index].cfg.ssn_pin,m_spiCtx[spi_ptr->spi_index].cfg.MOSI,m_spiCtx[spi_ptr->spi_index].cfg.MISO);
|
|
memset(&m_spiCtx,0,2*sizeof(spi_Ctx_t));
|
|
return PPlus_SUCCESS;
|
|
}
|
|
|
|
|
|
|
|
/**************************************************************************************
|
|
@fn hal_spi_init
|
|
|
|
@brief it is used to init spi module.
|
|
|
|
input parameters
|
|
@param None
|
|
|
|
output parameters
|
|
@param None.
|
|
|
|
@return None.
|
|
**************************************************************************************/
|
|
int hal_spi_init(SPI_INDEX_e channel)
|
|
{
|
|
int ret = 0;
|
|
|
|
if(channel == SPI0)
|
|
{
|
|
ret = hal_pwrmgr_register(MOD_SPI0,spi0_sleep_handler, spi0_wakeup_handler);
|
|
|
|
if(ret == PPlus_SUCCESS)
|
|
memset(&m_spiCtx[0],0,sizeof(spi_Ctx_t));
|
|
|
|
return ret;
|
|
}
|
|
else if(channel == SPI1)
|
|
{
|
|
ret = hal_pwrmgr_register(MOD_SPI1,spi1_sleep_handler, spi1_wakeup_handler);
|
|
|
|
if(ret == PPlus_SUCCESS)
|
|
memset(&m_spiCtx[1],0,sizeof(spi_Ctx_t));
|
|
|
|
return ret;
|
|
}
|
|
|
|
return PPlus_ERR_INVALID_PARAM;
|
|
}
|
|
|
|
#if DMAC_USE
|
|
int hal_spi_dma_set(hal_spi_t* spi_ptr,bool ten,bool ren)
|
|
{
|
|
spi_Ctx_t* pctx = NULL;
|
|
|
|
if((spi_ptr == NULL) || (spi_ptr->spi_index > 1))
|
|
return PPlus_ERR_INVALID_PARAM;
|
|
|
|
pctx = &m_spiCtx[spi_ptr->spi_index];
|
|
pctx->cfg.dma_rx_enable = ren;
|
|
pctx->cfg.dma_tx_enable = ten;
|
|
return PPlus_SUCCESS;
|
|
}
|
|
#endif
|
|
|
|
|