rt-thread-official/bsp/nv32f100x/lib/src/spi.c

330 lines
8.4 KiB
C

/******************************************************************************
* @brief providing APIs for configuring SPI module (SPI).
*
*******************************************************************************
*
* provide APIs for configuring SPI module (SPI).
******************************************************************************/
#include "common.h"
#include "spi.h"
/******************************************************************************
* Local variables
******************************************************************************/
SPI_CallbackType SPI_Callback[MAX_SPI_NO] = {(SPI_CallbackType)NULL};
/******************************************************************************
* Local function prototypes
******************************************************************************/
/******************************************************************************
* Local functions
*****************************************************************************/
/******************************************************************************
* Global functions
******************************************************************************/
/******************************************************************************
* define SPI APIs
*
*//*! @addtogroup spi_api_list
* @{
*******************************************************************************/
/*****************************************************************************//*!
*
* @brief initialize SPI as per params.
*
* @param[in] pSPI point to SPI module type.
* @param[in] pConfig point to configuration parameters.
*
* @return none.
*
* @ Pass/ Fail criteria: none.
*****************************************************************************/
void SPI_Init(SPI_Type *pSPI, SPI_ConfigType *pConfig)
{
#if defined(CPU_NV32M3)
/* sanity check */
ASSERT((pSPI == SPI0));
SIM->SCGC |= SIM_SCGC_SPI0_MASK;
#else
/* sanity check */
ASSERT((pSPI == SPI0) || (pSPI == SPI1));
/* enable SPI clock gating on */
if( pSPI == SPI0)
{
SIM->SCGC |= SIM_SCGC_SPI0_MASK;
}
else
{
SIM->SCGC |= SIM_SCGC_SPI1_MASK;
}
#endif
/* configure other control bits */
if( pConfig->sSettings.bIntEn)
{
SPI_IntEnable(pSPI);
#if defined(CPU_NV32M3)
NVIC_EnableIRQ(SPI0_IRQn);
#else
if( pSPI == SPI0 )
{
NVIC_EnableIRQ(SPI0_IRQn);
}
else
{
NVIC_EnableIRQ(SPI1_IRQn);
}
#endif
}
if( pConfig->sSettings.bTxIntEn)
{
SPI_TxIntEnable(pSPI);
#if defined(CPU_NV32M3)
NVIC_EnableIRQ(SPI0_IRQn);
#else
if( pSPI == SPI0 )
{
NVIC_EnableIRQ(SPI0_IRQn);
}
else
{
NVIC_EnableIRQ(SPI1_IRQn);
}
#endif
}
if( pConfig->sSettings.bMasterMode)
{
SPI_SetMasterMode(pSPI);
}
else
{
SPI_SetSlaveMode(pSPI);
}
if( pConfig->sSettings.bClkPolarityLow)
{
SPI_SetClockPol(pSPI,1);
}
if( pConfig->sSettings.bClkPhase1)
{
SPI_SetClockPhase(pSPI,1);
}else
{
SPI_SetClockPhase(pSPI,0);
}
if( pConfig->sSettings.bShiftLSBFirst)
{
SPI_SetLSBFirst(pSPI);
}
if( pConfig->sSettings.bMatchIntEn)
{
SPI_MatchIntEnable(pSPI);
}
if( pConfig->sSettings.bModeFaultEn)
{
SPI_ModfEnable(pSPI);
}
if( pConfig->sSettings.bMasterAutoDriveSS)
{
/* set both SSOE and MODFEN bits when auto drive slave SS is enabled */
SPI_SSOutputEnable(pSPI);
SPI_ModfEnable(pSPI);
}
if( pConfig->sSettings.bPinAsOuput)
{
SPI_BidirPinEnable(pSPI);
}
if( pConfig->sSettings.bBidirectionModeEn)
{
SPI_BidirOutEnable(pSPI);
}
if( pConfig->sSettings.bStopInWaitMode)
{
SPI_ClockStopEnable(pSPI);
}
if(pConfig->sSettings.bMasterMode)
{
SPI_SetBaudRate(pSPI,pConfig->u32BusClkHz,pConfig->u32BitRate);
}
/* enable SPI module */
if( pConfig->sSettings.bModuleEn)
{
SPI_Enable(pSPI);
}
}
/*****************************************************************************//*!
*
* @brief SPI set band rate.
*
* @param[in] pSPI point to SPI module type.
* @param[in] u32BusClock Bus clock.
* @param[in] u32Bps set spi's baudrate.
*
* @return none.
*
* @ Pass/ Fail criteria: none.
*****************************************************************************/
void SPI_SetBaudRate(SPI_Type *pSPI,uint32_t u32BusClock,uint32_t u32Bps)
{
uint32_t u32BitRateDivisor;
uint8_t u8Sppr;
uint8_t u8Spr;
uint8_t u8ReadFlag;
u32BitRateDivisor = u32BusClock/u32Bps; /* calculate bit rate divisor */
u8ReadFlag = 0;
/* find best fit SPPR and SPR */
for (u8Spr = 0; u8Spr <= 8; u8Spr++)
{
for(u8Sppr = 0; u8Sppr <= 7; u8Sppr++)
{
if((u32BitRateDivisor>>(u8Spr+1))<=(u8Sppr+1))
{
u8ReadFlag = 1;
break;
}
}
if(u8ReadFlag)
{
break;
}
}
if(u8Sppr >=8)
{
u8Sppr = 7;
}
if(u8Spr >8)
{
u8Spr = 8;
}
/* set bit rate */
pSPI->BR = SPI_BR_SPPR(u8Sppr) | SPI_BR_SPR(u8Spr);
}
/*****************************************************************************//*!
*
* @brief implement write data to SPI.
*
* @param[in] pSPI pointer to SPI module type.
* @param[in] pWrBuff -- write data buffer pointer.
* @param[in] uiLength -- read/write data length.
* @param[out] pRdBuff -- read data buffer pointer.
*
* @return if <0, means error, 0: success.
*
* @ Pass/ Fail criteria: none.
*****************************************************************************/
ResultType SPI_TransferWait(SPI_Type *pSPI, SPI_WidthType* pRdBuff, SPI_WidthType *pWrBuff,uint32 uiLength)
{
ResultType err = SPI_ERR_SUCCESS;
uint32_t i;
if(!uiLength)
{
return (err);
}
for(i = 0; i < uiLength; i++)
{
while(!SPI_IsSPTEF(pSPI));
SPI_WriteDataReg(pSPI,pWrBuff[i]);
while(!SPI_IsSPRF(pSPI));
pRdBuff[i] = SPI_ReadDataReg(pSPI);
}
return (err);
}
/*****************************************************************************//*!
*
* @brief Deinitialize SPI to the default state (reset value).
*
* @param[in] pSPI pointer to SPI module type.
*
* @return none.
*
* @ Pass/ Fail criteria: none.
*****************************************************************************/
void SPI_DeInit(SPI_Type *pSPI)
{
int16 i;
pSPI->C1 = SPI_C1_DEFAULT;
pSPI->C2 = SPI_C2_DEFAULT;
pSPI->BR = SPI_BR_DEFAULT;
pSPI->M = SPI_M_DEFAULT;
for(i = 0; i<100; i++); /* wait for some cycles for the ISR exit */
}
/*****************************************************************************//*!
*
* @brief set up SPI callback routines to be called by interrupt service routine.
*
* @param[in] pSPI pointer to SPI module type.
* @param[in] pfnCallback callback routine.
*
* @return none.
*
* @ Pass/ Fail criteria: none.
*****************************************************************************/
void SPI_SetCallback(SPI_Type *pSPI,SPI_CallbackType pfnCallback)
{
uint32_t u32Port = ((uint32_t)pSPI-(uint32_t)SPI0)>>12;
ASSERT(u32Port <2);
SPI_Callback[u32Port] = pfnCallback;
}
/*! @} End of spi_api_list */
/*****************************************************************************//*!
*
* @brief SPI0 interrupt service routine.
*
* @param none.
* @return none.
*
* @ Pass/ Fail criteria: none.
*****************************************************************************/
void SPI0_Isr(void)
{
if( SPI_Callback[0] )
{
SPI_Callback[0]();
}
}
#ifndef CPU_NV32M3
/*****************************************************************************//*!
*
* @brief SPI1 interrupt service routine.
*
* @param none.
* @return none.
*
* @ Pass/ Fail criteria: none
*****************************************************************************/
void SPI1_Isr(void)
{
if( SPI_Callback[1] )
{
SPI_Callback[1]();
}
}
#endif