330 lines
8.4 KiB
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
|
|
|
|
|