/** * @file spi.c * @author chipsea * @brief Contains all functions support for spi driver * @version 0.1 * @date 2020-11-30 * @copyright Copyright (c) 2020, CHIPSEA Co., Ltd. * @note */ #include "sdk_config.h" #include "rom_sym_def.h" #include "gpio.h" #include "error.h" #include #include "pwrmgr.h" #include "clock.h" #include "log.h" #include "spi.h" #include "dma.h" #include "jump_function.h" #define DMAC_USE 1 /** * @struct SpiBufCtl_t * @brief spi buffer information */ typedef struct { uint16_t bufOffset; uint16_t bufSize; uint8_t* buf; } SpiBufCtl_t; /** * @struct SpiCtl_t * @brief spi control information */ typedef struct { bool enable; spi_Cfg_t cfg; uint8_t busy; SpiBufCtl_t txBufCtl; SpiBufCtl_t rxBufCtl; //It's valid when role is master } SpiCtl_t; static SpiCtl_t spiCtl[2]; #define SPI_USE_TIMEOUT 1 #define SPI_OP_TIMEOUT 1000 //100ms for an Byte operation #if(SPI_USE_TIMEOUT == 1) #define SPI_INIT_TOUT(to) int to = hal_systick() #define SPI_CHECK_TOUT(to, timeout) {if(hal_ms_intv(to) > timeout){return ERR_TIMEOUT;}} #else #define SPI_INIT_TOUT(to) #define SPI_CHECK_TOUT(to, timeout) #endif static void HalSpiWriteFifo(AP_SSI_TypeDef* SPIx, uint8_t len, uint8_t* tx_rx_ptr) { uint8_t i=0; HAL_ENTER_CRITICAL_SECTION(); while(iDataReg = *(tx_rx_ptr+i); i++; } HAL_EXIT_CRITICAL_SECTION(); } void HalSpiIntEnable(SPI_INDEX_e index, uint32_t mask) { if(index == SPI0) { AP_SPI0->IMR = mask & 0x11; JUMP_FUNCTION(SPI0_IRQ_HANDLER) = (uint32_t)&HalSpi0IRQHandler; } else { AP_SPI1->IMR = mask & 0x11; JUMP_FUNCTION(SPI1_IRQ_HANDLER) = (uint32_t)&HalSpi1IRQHandler; } NVIC_EnableIRQ((IRQn_Type)(SPI0_IRQn + index)); NVIC_SetPriority((IRQn_Type)(SPI0_IRQn + index), IRQ_PRIO_HAL); } static void HalSpiIntDisable(SPI_INDEX_e index) { NVIC_DisableIRQ((IRQn_Type)(SPI0_IRQn + index)); if(index == SPI0) { AP_SPI0->IMR = 0x00; } else { AP_SPI1->IMR = 0x00; } } static void HalSpiMasterHandle(SPI_INDEX_e id, AP_SSI_TypeDef* SPIx) { volatile uint8_t spi_irs_status; spi_evt_t evt; uint8_t i, cnt; spi_irs_status = SPIx->ISR; if(spi_irs_status & TRANSMIT_FIFO_EMPTY) { cnt = 8 - SPIx->TXFLR; for(i = 0; i< cnt; i++) { if(spiCtl[id].txBufCtl.bufOffset >= spiCtl[id].txBufCtl.bufSize) { SPIx->IMR = 0x10; if(spiCtl[id].cfg.force_cs == true) { while(SPIx->SR & 0x01); HalGpioFmuxEnable(spiCtl[id].cfg.ssn_pin, Bit_ENABLE); } spiCtl[id].busy = false; evt.id = id; evt.evt = SPI_TX_COMPLETED; if(spiCtl[id].cfg.evt_handler) { spiCtl[id].cfg.evt_handler(&evt); } break; } if(spiCtl[id].txBufCtl.buf) { SPIx->DataReg = spiCtl[id].txBufCtl.buf[spiCtl[id].txBufCtl.bufOffset++]; } else { if(!(spi_irs_status & RECEIVE_FIFO_FULL)) { if(spiCtl[id].rxBufCtl.buf) { spiCtl[id].rxBufCtl.buf[spiCtl[id].rxBufCtl.bufOffset++] = SPIx->DataReg; } } spiCtl[id].txBufCtl.bufOffset++; SPIx->DataReg = 0; } } } if(spi_irs_status & RECEIVE_FIFO_FULL) { cnt = SPIx->RXFTLR + 1; for(i = 0; i< cnt; i++) { if(spiCtl[id].rxBufCtl.buf) { spiCtl[id].rxBufCtl.buf[spiCtl[id].rxBufCtl.bufOffset++] = SPIx->DataReg; } else { VOID (SPIx->DataReg & 0xff); } } if(spiCtl[id].rxBufCtl.bufOffset >= spiCtl[id].rxBufCtl.bufSize) { if(spiCtl[id].cfg.force_cs == true) HalGpioFmuxEnable(spiCtl[id].cfg.ssn_pin, Bit_ENABLE); spiCtl[id].busy = false; spiCtl[id].rxBufCtl.buf = NULL; spiCtl[id].rxBufCtl.bufOffset = 0; evt.id = id; evt.evt = SPI_RX_COMPLETED; hal_pwrmgr_unlock((MODULE_e)(MOD_SPI0 + id)); if(spiCtl[id].cfg.evt_handler) { spiCtl[id].cfg.evt_handler(&evt); } } if(spiCtl[id].txBufCtl.bufOffset >= spiCtl[id].txBufCtl.bufSize) { spiCtl[id].busy = false; evt.id = id; evt.evt = SPI_TX_COMPLETED; if(spiCtl[id].cfg.evt_handler) { spiCtl[id].cfg.evt_handler(&evt); } } } } static void HalSpiSlaveHandle(SPI_INDEX_e id, AP_SSI_TypeDef* SPIx) { volatile uint8_t spi_irs_status; spi_evt_t evt; uint16_t i, cnt; spi_irs_status = SPIx->ISR; if(spi_irs_status & TRANSMIT_FIFO_EMPTY) { cnt = 8 - SPIx->TXFLR; for(i = 0; i< cnt; i++) { if(spiCtl[id].txBufCtl.bufOffset >= spiCtl[id].txBufCtl.bufSize) { SPIx->DataReg = 0; SPIx->IMR = 0x10; break; } if(spiCtl[id].txBufCtl.buf && spiCtl[id].busy) { SPIx->DataReg = spiCtl[id].txBufCtl.buf[spiCtl[id].txBufCtl.bufOffset++]; } else { SPIx->DataReg = 0; } } } if(spi_irs_status & RECEIVE_FIFO_FULL) { volatile uint32_t garbage; cnt = SPIx->RXFLR; if(spiCtl[id].rxBufCtl.buf) { for(i = 0; i< cnt; i++) { if(spiCtl[id].rxBufCtl.bufSize > spiCtl[id].rxBufCtl.bufOffset) spiCtl[id].rxBufCtl.buf[spiCtl[id].rxBufCtl.bufOffset++] = SPIx->DataReg; else garbage = SPIx->DataReg; } } else if(!spiCtl[id].busy) { uint8_t rxbuf[16]; for(i = 0; i< cnt; i++) { *(rxbuf+i) = SPIx->DataReg; } evt.id = id; evt.evt = SPI_RX_DATA_S; evt.data = rxbuf; evt.len = cnt; spiCtl[id].cfg.evt_handler(&evt); } else { garbage = SPIx->DataReg; spiCtl[id].rxBufCtl.bufOffset += cnt; } if(spiCtl[id].busy && spiCtl[id].rxBufCtl.bufOffset >= spiCtl[id].txBufCtl.bufSize) { spiCtl[id].busy = false; spiCtl[id].txBufCtl.buf = NULL; spiCtl[id].txBufCtl.bufOffset = 0; spiCtl[id].rxBufCtl.bufOffset = 0; evt.id = id; evt.evt = SPI_TX_COMPLETED; spiCtl[id].cfg.evt_handler(&evt); } } } /************************************************************************************** @fn HalSpi0IRQHandler @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)) HalSpi0IRQHandler(void) { if(!spiCtl[0].enable) return; if(spiCtl[0].cfg.is_slave) HalSpiSlaveHandle(SPI0, AP_SPI0); else HalSpiMasterHandle(SPI0, AP_SPI0); } /************************************************************************************** @fn HalSpi1IRQHandler @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)) HalSpi1IRQHandler(void) { if(!spiCtl[1].enable) return; if(spiCtl[1].cfg.is_slave) HalSpiSlaveHandle(SPI1, AP_SPI1); else HalSpiMasterHandle(SPI1, AP_SPI1); } /************************************************************************************** @fn HalSpiPinInit @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 HalSpiPinInit(SPI_INDEX_e index, GpioPin_t sck_pin, GpioPin_t ssn_pin, GpioPin_t tx_pin, GpioPin_t rx_pin) { HalGpioFmuxConfig(sck_pin, (gpio_fmux_e)(FMUX_SPI_0_SCK+index*4)); HalGpioFmuxConfig(ssn_pin, (gpio_fmux_e)(FMUX_SPI_0_SSN+index*4)); HalGpioFmuxConfig(tx_pin, (gpio_fmux_e)(FMUX_SPI_0_TX+index*4)); HalGpioFmuxConfig(rx_pin, (gpio_fmux_e)(FMUX_SPI_0_RX+index*4)); } static void HalSpiPinDeinit(GpioPin_t sck_pin, GpioPin_t ssn_pin, GpioPin_t tx_pin, GpioPin_t rx_pin) { HalGpioFmuxEnable(sck_pin, Bit_DISABLE); HalGpioFmuxEnable(ssn_pin, Bit_DISABLE); HalGpioFmuxEnable(tx_pin, Bit_DISABLE); HalGpioFmuxEnable(rx_pin, Bit_DISABLE); } #if DMAC_USE static void HalConfigDmaSpiTx(AP_SSI_TypeDef* SPIx, uint8_t* tx_buf, uint16_t tx_len) { uint8_t index = 0; DMA_CH_CFG_t cfgc; if(SPIx == AP_SPI1) { index = 1; } SPIx->DMACR &= 0x01; cfgc.transf_size = tx_len; cfgc.sinc = DMA_INC_INC; if(spiCtl[index].cfg.spi_dfsmod == SPI_1BYTE) { cfgc.src_tr_width = DMA_WIDTH_BYTE; cfgc.dst_tr_width = DMA_WIDTH_BYTE; } else { cfgc.src_tr_width = DMA_WIDTH_HALFWORD; cfgc.dst_tr_width = DMA_WIDTH_HALFWORD; } cfgc.src_msize = DMA_BSIZE_1; cfgc.src_addr = (uint32_t)tx_buf; cfgc.dinc = DMA_INC_NCHG; cfgc.dst_msize = DMA_BSIZE_1; cfgc.dst_addr = (uint32_t)&(SPIx->DataReg); cfgc.enable_int = true; HalDMAConfigChannel(SPI_DMAC_CH, &cfgc); HalDMAStartChannel(SPI_DMAC_CH); SPIx->DMACR |= 0x02; SPIx->DMATDLR = 0; } static void HalConfigDmaSpiRx(AP_SSI_TypeDef* SPIx, uint8_t* rx_buf, uint16_t rx_len) { DMA_CH_CFG_t cfgc; SPIx->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)&(SPIx->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 = true; HalDMAConfigChannel(SPI_DMAC_CH, &cfgc); HalDMAStartChannel(SPI_DMAC_CH); SPIx->DMACR |= 0x01; SPIx->DMARDLR = 0; } #endif static ErrCode_t HalSpiXmitPolling(AP_SSI_TypeDef* SPIx, uint8_t* tx_buf, uint8_t* rx_buf, uint16_t len) { uint16_t tmp_len, i; uint16_t tx_size, rx_size; #if DMAC_USE SPI_INDEX_e index = SPI0; if(SPIx == AP_SPI1) { index = SPI1; } #endif tx_size = len; rx_size = len; SPI_INIT_TOUT(to); #if DMAC_USE if(rx_buf && spiCtl[index].cfg.dma_rx_enable) { HalConfigDmaSpiRx(SPIx, rx_buf, rx_size); } else if(tx_buf && spiCtl[index].cfg.dma_tx_enable) { HalConfigDmaSpiTx(SPIx, tx_buf, tx_size); } #endif while(1) { #if DMAC_USE if( (SPIx->SR&TX_FIFO_NOT_FULL) && (!(spiCtl[index].cfg.dma_tx_enable)) ) #else if(SPIx->SR & TX_FIFO_NOT_FULL && tx_size) #endif { tmp_len = 8-SPIx->TXFLR; if(tmp_len > tx_size) tmp_len = tx_size; for(i=0; iDataReg = (tx_buf!=NULL)?(*(tx_buf+len-tx_size+i)):0; } tx_size -= tmp_len; } #if DMAC_USE if( ((rx_buf == NULL) && ((tx_size == 0)||(tx_size && (spiCtl[index].cfg.dma_tx_enable)))) || ((rx_buf != NULL) && (tx_size == 0) && (spiCtl[index].cfg.dma_rx_enable)) ) break; else if( (rx_buf != NULL) && (!(spiCtl[index].cfg.dma_rx_enable)) ) #else if((rx_size == 0) && ((tx_size == 0))) break; else if(rx_size) #endif { if(SPIx->RXFLR) { tmp_len = SPIx->RXFLR; for(i = 0; i< tmp_len; i++) { *rx_buf++= SPIx->DataReg; } rx_size -= tmp_len; } if(rx_size == 0) break; } SPI_CHECK_TOUT(to, SPI_OP_TIMEOUT); } #if DMAC_USE if((spiCtl[index].cfg.dma_rx_enable) || (spiCtl[index].cfg.dma_tx_enable)) { HalDMAStatusControl(SPI_DMAC_CH); } #endif while(SPIx->SR & SPI_BUSY) { SPI_CHECK_TOUT(to, SPI_OP_TIMEOUT); } return ERR_NONE; } static ErrCode_t HalSpiDisable(SPI_INDEX_e index) { if(index >SPI1) { return ERR_NOT_SUPPORTED; } hal_clk_gate_disable((MODULE_e)(MOD_SPI0 + index)); HalSpiPinDeinit(spiCtl[index].cfg.sclk_pin, spiCtl[index].cfg.ssn_pin, spiCtl[index].cfg.MOSI, spiCtl[index].cfg.MISO); osal_memset(&spiCtl[index], 0, sizeof(spiCtl)); return ERR_NONE; } static void HalSpi0SleepHandler(void) { if(spiCtl[0].enable) { HalSpiDisable(SPI0); } } static void HalSpi1SleepHandler(void) { if(spiCtl[1].enable) { HalSpiDisable(SPI1); } } static void HalSpi0WakeupHandler(void) { NVIC_SetPriority((IRQn_Type)SPI0_IRQn, IRQ_PRIO_HAL); } static void HalSpi1WakeupHandler(void) { NVIC_SetPriority((IRQn_Type)SPI1_IRQn, IRQ_PRIO_HAL); } void HalSpiTmodSet(AP_SSI_TypeDef* SPIx, SPI_TMOD_e mod) { SPIx->SSIEN = 0; subWriteReg(&SPIx->CR0,9,8,mod); SPIx->SSIEN = 1; } void HalSpiDfsSet(SPI_INDEX_e index, SPI_DFS_e mod) { AP_SSI_TypeDef* SPIx = NULL; SPIx = (index == SPI0) ? AP_SPI0 : AP_SPI1; SPIx->SSIEN = 0; subWriteReg(&SPIx->CR0,3,0,mod); SPIx->SSIEN = 1; spiCtl[index].cfg.spi_dfsmod = mod; } void HalSpiNdfSet(AP_SSI_TypeDef* SPIx, uint16_t len) { SPIx->SSIEN = 0; SPIx->CR1 = len-1; SPIx->SSIEN = 1; } ErrCode_t HalSpiMasterTransfer(AP_SSI_TypeDef* SPIx, SPI_TMOD_e mod, uint8_t* tx_buf, uint8_t* rx_buf, uint16_t len) { int ret; SPI_INDEX_e index = SPI0; if(SPIx != AP_SPI0 && SPIx != AP_SPI1) { return ERR_NOT_SUPPORTED; } if(mod > SPI_RXD) { return ERR_IO_CONFILCT; } if(len == 0 || (tx_buf == NULL && rx_buf == NULL)) { return ERR_INVALID_DATA; } if(SPIx == AP_SPI1) { index = SPI1; } if(!spiCtl[index].enable) { return ERR_NOT_REGISTED; } if(spiCtl[index].busy) { return ERR_BUSY; } spiCtl[index].txBufCtl.buf = tx_buf; spiCtl[index].txBufCtl.bufOffset = 0; spiCtl[index].txBufCtl.bufSize = len; spiCtl[index].rxBufCtl.buf = rx_buf; spiCtl[index].rxBufCtl.bufOffset = 0; spiCtl[index].rxBufCtl.bufSize = len; HalSpiTmodSet(SPIx, mod); if(mod > SPI_TXD) //spi receive only or eeprom read,should set read data len(ndf) { HalSpiNdfSet(SPIx, len); } if(spiCtl[index].cfg.force_cs == true) { HalGpioFmuxEnable(spiCtl[index].cfg.ssn_pin,Bit_DISABLE); HalGpioSet(spiCtl[index].cfg.ssn_pin, Bit_DISABLE); HalGpioPinInit(spiCtl[index].cfg.ssn_pin, GPIO_OUTPUT); } if(spiCtl[index].cfg.int_mode == false) { ret = HalSpiXmitPolling(SPIx, tx_buf, rx_buf, len); if(spiCtl[index].cfg.force_cs == true) { HalGpioFmuxEnable(spiCtl[index].cfg.ssn_pin,Bit_ENABLE); } if(ret) { return ERR_TIMEOUT; } } else { HalSpiIntDisable(index); if(SPIx->SR & TX_FIFO_NOT_FULL) { uint8_t dummy[8] = {0}; hal_pwrmgr_lock((MODULE_e)(MOD_SPI0 + index)); spiCtl[index].txBufCtl.bufOffset = (len >= 8)?8:len; // Ssix->RXFTLR = _tx_len - 1; HalSpiWriteFifo(SPIx, spiCtl[index].txBufCtl.bufOffset, (tx_buf!=NULL)?tx_buf:dummy); } spiCtl[index].busy = true; HalSpiIntEnable(index, 0x11); } return ERR_NONE; } ErrCode_t HalSpiSlaveTxPrepare(AP_SSI_TypeDef* SPIx, uint8_t* tx_buf, uint16_t len) { SPI_INDEX_e index = SPI0; if(SPIx != AP_SPI0 && SPIx != AP_SPI1) { return ERR_NOT_SUPPORTED; } if(tx_buf == NULL || len ==0) { return ERR_INVALID_DATA; } if(SPIx == AP_SPI1) { index = SPI1; } spiCtl[index].txBufCtl.buf = tx_buf; spiCtl[index].txBufCtl.bufSize = len; spiCtl[index].txBufCtl.bufOffset = 0; spiCtl[index].rxBufCtl.buf = NULL; spiCtl[index].rxBufCtl.bufOffset = 0; if(SPIx->SR & 0x10) { SPIx->IMR |= BIT(0); return ERR_NONE; } if(len > 8 - SPIx->TXFLR) { len = 8 - SPIx->TXFLR; } for(uint8_t i=0; iDataReg = tx_buf[i]; } spiCtl[index].txBufCtl.bufOffset = len; SPIx->IMR |= BIT(0); spiCtl[index].busy = true; return ERR_NONE; } ErrCode_t HalSpiSetIntMode(SPI_INDEX_e index, bool en) { if(index > SPI1) { return ERR_DATA_SIZE; } spiCtl[index].cfg.int_mode = en; if(en) { HalSpiIntEnable(index, 0x10); } else { HalSpiIntDisable(index); } return ERR_NONE; } ErrCode_t HalSpiSetForceCs(SPI_INDEX_e index, bool en) { if(index > SPI1) { return ERR_NOT_SUPPORTED; } spiCtl[index].cfg.force_cs = en; return ERR_NONE; } bool HalSpiGetTransmitState(SPI_INDEX_e index) { AP_SSI_TypeDef* SPIx = NULL; SPIx = (index == SPI0) ? AP_SPI0 : AP_SPI1; return (SPIx->SR&SPI_BUSY)||spiCtl[index].busy; } ErrCode_t HalSpiMasterConfig(AP_SSI_TypeDef* SPIx, spi_Cfg_t *cfg) { uint16_t baud_temp; SPI_INDEX_e index = SPI0; int pclk = clk_get_pclk(); if(SPIx != AP_SPI0 && SPIx != AP_SPI1) { return ERR_NOT_SUPPORTED; } if(cfg->is_slave) { return ERR_IO_CONFILCT; } if(cfg->sclk_pin >=GPIO_NUM || cfg->sclk_pin == cfg->ssn_pin || cfg->sclk_pin == cfg->MOSI || cfg->sclk_pin == cfg->MISO) { return ERR_IO_CONFILCT; } if(cfg->ssn_pin>=GPIO_NUM || cfg->ssn_pin == cfg->MOSI || cfg->ssn_pin == cfg->MISO) { return ERR_IO_CONFILCT; } if(cfg->MOSI>=GPIO_NUM || cfg->MOSI == cfg->MISO) { return ERR_IO_CONFILCT; } // if(cfg->MISO>=GPIO_NUM) // { // return ERR_IO_CONFILCT; // } if(cfg->spi_tmod>SPI_RXD) { return ERR_NOT_SUPPORTED; } if(cfg->spi_scmod>SPI_MODE3) { return ERR_NOT_SUPPORTED; } if(cfg->spi_dfsmod < SPI_MINBYTE || cfg->spi_dfsmod > SPI_MAXBYTE) { return ERR_NOT_SUPPORTED; } if(SPIx == AP_SPI1) { index = SPI1; } osal_memcpy(&spiCtl[index].cfg, cfg, sizeof(spi_Cfg_t)); spiCtl[index].busy = false; spiCtl[index].enable = true; spiCtl[index].cfg.is_slave = false; hal_clk_gate_enable((MODULE_e)(MOD_SPI0+index)); HalSpiPinInit(index, cfg->sclk_pin, cfg->ssn_pin, cfg->MOSI, cfg->MISO); SPIx->SSIEN = 0; //DISABLE_SPI; SPI_MASTER_SELECT(index); SPIx->CR0= ((SPIx->CR0) & 0xfffffc30)|((unsigned int)(spiCtl[index].cfg.spi_dfsmod))|(cfg->spi_scmod<<6)|(cfg->spi_tmod<<8); baud_temp = (pclk + (cfg->baudrate>>1)) / cfg->baudrate; if(baud_temp<2) { baud_temp = 2; } else if(baud_temp>65534) { baud_temp =65534; } SPIx->BAUDR= baud_temp; // set clock(round) SPIx->TXFTLR=4; // set fifo threshold to triggle interrupt SPIx->RXFTLR=0; SPIx->IMR = 0x00; SPIx->SER=1; //enable slave device SPIx->SSIEN = 1; //ENABLE_SPI; if(cfg->int_mode) HalSpiIntEnable(index, 0x10); else HalSpiIntDisable(index); return ERR_NONE; } ErrCode_t HalSpiSlaveConfig(AP_SSI_TypeDef* SPIx, spi_Cfg_t *cfg) { SPI_INDEX_e index = SPI0; if(SPIx != AP_SPI0 && SPIx != AP_SPI1) { return ERR_NOT_SUPPORTED; } if(!cfg->is_slave) { return ERR_IO_CONFILCT; } if(cfg->sclk_pin >=GPIO_NUM || cfg->sclk_pin == cfg->ssn_pin || cfg->sclk_pin == cfg->MOSI || cfg->sclk_pin == cfg->MISO) { return ERR_IO_CONFILCT; } if(cfg->ssn_pin>=GPIO_NUM || cfg->ssn_pin == cfg->MOSI || cfg->ssn_pin == cfg->MISO) { return ERR_IO_CONFILCT; } if(cfg->MOSI>=GPIO_NUM || cfg->MOSI == cfg->MISO) { return ERR_IO_CONFILCT; } if(cfg->MISO>=GPIO_NUM) { return ERR_IO_CONFILCT; } if(cfg->spi_tmod>SPI_RXD) { return ERR_NOT_SUPPORTED; } if(cfg->spi_scmod>SPI_MODE3) { return ERR_NOT_SUPPORTED; } if(cfg->spi_dfsmod < SPI_MINBYTE || cfg->spi_dfsmod > SPI_MAXBYTE) { return ERR_NOT_SUPPORTED; } if(SPIx == AP_SPI1) { index = SPI1; } osal_memcpy(&spiCtl[index].cfg, cfg, sizeof(spi_Cfg_t)); spiCtl[index].busy = false; spiCtl[index].enable = true; spiCtl[index].cfg.is_slave = true; hal_clk_gate_enable((MODULE_e)(MOD_SPI0 + index)); if(spiCtl[index].cfg.int_mode) HalSpiIntEnable(index, 0x11); else HalSpiIntDisable(index); HalSpiPinInit(index, spiCtl[index].cfg.sclk_pin, spiCtl[index].cfg.ssn_pin, spiCtl[index].cfg.MISO, spiCtl[index].cfg.MOSI); SPIx->SSIEN = 0; //disable SPI SPI_SLAVE_SELECT(index); SPIx->CR0 = ((SPIx->CR0 & 0xfffffc30) | ((unsigned int)(spiCtl[index].cfg.spi_dfsmod)) | ((unsigned int)(spiCtl[index].cfg.spi_scmod) << 6) | ((unsigned int)SPI_TRXD << 8)) ; SPIx->TXFTLR = 4; SPIx->RXFTLR = 0; SPIx->SSIEN = 1; return ERR_NONE; } /************************************************************************************** @fn HalSpiDeinit @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 SUCCESS ERR_INVALID_PARAM **************************************************************************************/ ErrCode_t HalSpiDeinit(SPI_INDEX_e index) { if(index >SPI1) { return ERR_NOT_SUPPORTED; } HalSpiDisable(index); if(index == SPI0) { hal_pwrmgr_unregister(MOD_SPI0); } else if(index == SPI1) { hal_pwrmgr_unregister(MOD_SPI1); } return ERR_NONE; } /************************************************************************************** @fn HalSpiInit @brief it is used to init spi module. input parameters @param None output parameters @param None. @return None. **************************************************************************************/ ErrCode_t HalSpiInit(SPI_INDEX_e channel) { ErrCode_t ret = ERR_NONE; if(channel == SPI0) { ret = hal_pwrmgr_register(MOD_SPI0, HalSpi0SleepHandler, HalSpi0WakeupHandler); if(ret == ERR_NONE) osal_memset(&spiCtl[0], 0, sizeof(SpiCtl_t)); return ret; } else if(channel == SPI1) { ret = hal_pwrmgr_register(MOD_SPI1, HalSpi1SleepHandler, HalSpi1WakeupHandler); if(ret == ERR_NONE) osal_memset(&spiCtl[1], 0, sizeof(SpiCtl_t)); return ret; } return ERR_INVALID_PARAM; } #if DMAC_USE ErrCode_t HalSpiDmaSet(SPI_INDEX_e index, bool ten, bool ren) { if(index >SPI1) { return ERR_NOT_SUPPORTED; } spiCtl[index].cfg.dma_rx_enable = ren; spiCtl[index].cfg.dma_tx_enable = ten; return ERR_NONE; } #endif