/**************************************************************************//** | |
* @file scuart.c | |
* @version V3.00 | |
* @brief Smartcard UART mode (SCUART) driver source file | |
* | |
* @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved. | |
*****************************************************************************/ | |
#include "NuMicro.h" | |
static uint32_t SCUART_GetClock(SC_T *sc); | |
/** @addtogroup Standard_Driver Standard Driver | |
@{ | |
*/ | |
/** @addtogroup SCUART_Driver SCUART Driver | |
@{ | |
*/ | |
/** @addtogroup SCUART_EXPORTED_FUNCTIONS SCUART Exported Functions | |
@{ | |
*/ | |
/** | |
* @brief Disable smartcard interface | |
* | |
* @param sc The pointer of smartcard module. | |
* | |
* @return None | |
* | |
* @details The function is used to disable smartcard interface UART mode. | |
*/ | |
void SCUART_Close(SC_T* sc) | |
{ | |
sc->INTEN = 0UL; | |
sc->UARTCTL = 0UL; | |
sc->CTL = 0UL; | |
} | |
/** @cond HIDDEN_SYMBOLS */ | |
/** | |
* @brief Returns module clock of specified SC interface | |
* | |
* @param[in] sc The pointer of smartcard module. | |
* | |
* @return Module clock of specified SC interface. | |
*/ | |
static uint32_t SCUART_GetClock(SC_T *sc) | |
{ | |
uint32_t u32ClkSrc, u32Num, u32Clk = __HIRC, u32Div; | |
/* Get smartcard module clock source and divider */ | |
if((sc == SC0) || (sc == SC0_NS)) | |
{ | |
u32Num = 0UL; | |
u32ClkSrc = CLK_GetModuleClockSource(SC0_MODULE); | |
u32Div = CLK_GetModuleClockDivider(SC0_MODULE); | |
} | |
else if((sc == SC1) || (sc == SC1_NS)) | |
{ | |
u32Num = 1UL; | |
u32ClkSrc = CLK_GetModuleClockSource(SC1_MODULE); | |
u32Div = CLK_GetModuleClockDivider(SC1_MODULE); | |
} | |
else if((sc == SC2) || (sc == SC2_NS)) | |
{ | |
u32Num = 2UL; | |
u32ClkSrc = CLK_GetModuleClockSource(SC2_MODULE); | |
u32Div = CLK_GetModuleClockDivider(SC2_MODULE); | |
} | |
else | |
{ | |
u32Clk = 0UL; | |
} | |
if(u32Clk == 0UL) | |
{ | |
; /* Invalid sc port */ | |
} | |
else | |
{ | |
/* Get smartcard module clock */ | |
if(u32ClkSrc == 0UL) | |
{ | |
u32Clk = __HXT; | |
} | |
else if(u32ClkSrc == 1UL) | |
{ | |
u32Clk = CLK_GetPLLClockFreq(); | |
} | |
else if(u32ClkSrc == 2UL) | |
{ | |
if(u32Num == 1UL) | |
{ | |
u32Clk = CLK_GetPCLK1Freq(); | |
} | |
else | |
{ | |
u32Clk = CLK_GetPCLK0Freq(); | |
} | |
} | |
else | |
{ | |
u32Clk = __HIRC; | |
} | |
u32Clk /= (u32Div + 1UL); | |
} | |
return u32Clk; | |
} | |
/** @endcond HIDDEN_SYMBOLS */ | |
/** | |
* @brief Enable smartcard module UART mode and set baudrate | |
* | |
* @param[in] sc The pointer of smartcard module. | |
* @param[in] u32Baudrate Target baudrate of smartcard UART module. | |
* | |
* @return Actual baudrate of smartcard UART mode | |
* | |
* @details This function use to enable smartcard module UART mode and set baudrate. | |
* | |
* @note This function configures character width to 8 bits, 1 stop bit, and no parity. | |
* And can use \ref SCUART_SetLineConfig function to update these settings. | |
* The baudrate clock source comes from SC_CLK/SC_DIV, where SC_CLK is controlled | |
* by SCxSEL in CLKSEL3 register, SC_DIV is controlled by SCxDIV in CLKDIV1 | |
* register. Since the baudrate divider is 12-bit wide and must be larger than 4, | |
* (clock source / baudrate) must be larger or equal to 5 and smaller or equal to | |
* 4096. Otherwise this function cannot configure SCUART to work with target baudrate. | |
*/ | |
uint32_t SCUART_Open(SC_T* sc, uint32_t u32Baudrate) | |
{ | |
uint32_t u32Clk = SCUART_GetClock(sc), u32Div; | |
/* Calculate divider for target baudrate */ | |
u32Div = (u32Clk + (u32Baudrate >> 1) - 1UL) / u32Baudrate - 1UL; | |
sc->CTL = SC_CTL_SCEN_Msk | SC_CTL_NSB_Msk; /* Enable smartcard interface and stop bit = 1 */ | |
sc->UARTCTL = SCUART_CHAR_LEN_8 | SCUART_PARITY_NONE | SC_UARTCTL_UARTEN_Msk; /* Enable UART mode, disable parity and 8 bit per character */ | |
sc->ETUCTL = u32Div; | |
return(u32Clk / (u32Div + 1UL)); | |
} | |
/** | |
* @brief Read Rx data from Rx FIFO | |
* | |
* @param[in] sc The pointer of smartcard module. | |
* @param[in] pu8RxBuf The buffer to store receive the data. | |
* @param[in] u32ReadBytes Target number of characters to receive | |
* | |
* @return Actual character number reads to buffer | |
* | |
* @details The function is used to read data from Rx FIFO. | |
* | |
* @note This function does not block and return immediately if there's no data available. | |
*/ | |
uint32_t SCUART_Read(SC_T* sc, uint8_t pu8RxBuf[], uint32_t u32ReadBytes) | |
{ | |
uint32_t u32Count; | |
for(u32Count = 0UL; u32Count < u32ReadBytes; u32Count++) | |
{ | |
if(SCUART_GET_RX_EMPTY(sc)) /* no data available */ | |
{ | |
break; | |
} | |
pu8RxBuf[u32Count] = (uint8_t)SCUART_READ(sc); /* get data from FIFO */ | |
} | |
return u32Count; | |
} | |
/** | |
* @brief Configure smartcard UART mode line setting | |
* | |
* @param[in] sc The pointer of smartcard module. | |
* @param[in] u32Baudrate Target baudrate of smartcard UART mode. If this value is 0, SC UART baudrate will not change. | |
* @param[in] u32DataWidth The data length, could be: | |
* - \ref SCUART_CHAR_LEN_5 | |
* - \ref SCUART_CHAR_LEN_6 | |
* - \ref SCUART_CHAR_LEN_7 | |
* - \ref SCUART_CHAR_LEN_8 | |
* @param[in] u32Parity The parity setting, could be: | |
* - \ref SCUART_PARITY_NONE | |
* - \ref SCUART_PARITY_ODD | |
* - \ref SCUART_PARITY_EVEN | |
* @param[in] u32StopBits The stop bit length, could be: | |
* - \ref SCUART_STOP_BIT_1 | |
* - \ref SCUART_STOP_BIT_2 | |
* | |
* @return Actual baudrate of smartcard UART mode | |
* | |
* @details The baudrate clock source comes from SC_CLK/SC_DIV, where SC_CLK is controlled | |
* by SCxSEL in CLKSEL3 register, SC_DIV is controlled by SCxDIV in CLKDIV1 | |
* register. Since the baudrate divider is 12-bit wide and must be larger than 4, | |
* (clock source / baudrate) must be larger or equal to 5 and smaller or equal to | |
* 4096. Otherwise this function cannot configure SCUART to work with target baudrate. | |
*/ | |
uint32_t SCUART_SetLineConfig(SC_T* sc, uint32_t u32Baudrate, uint32_t u32DataWidth, uint32_t u32Parity, uint32_t u32StopBits) | |
{ | |
uint32_t u32Clk = SCUART_GetClock(sc), u32Div; | |
if(u32Baudrate == 0UL) | |
{ | |
/* Keep original baudrate setting */ | |
u32Div = sc->ETUCTL & SC_ETUCTL_ETURDIV_Msk; | |
} | |
else | |
{ | |
/* Calculate divider for target baudrate */ | |
u32Div = ((u32Clk + (u32Baudrate >> 1) - 1UL) / u32Baudrate) - 1UL; | |
sc->ETUCTL = u32Div; | |
} | |
sc->CTL = u32StopBits | SC_CTL_SCEN_Msk; /* Set stop bit */ | |
sc->UARTCTL = u32Parity | u32DataWidth | SC_UARTCTL_UARTEN_Msk; /* Set character width and parity */ | |
return (u32Clk / (u32Div + 1UL)); | |
} | |
/** | |
* @brief Set receive timeout count | |
* | |
* @param[in] sc The pointer of smartcard module. | |
* @param[in] u32TOC Rx time-out counter, using baudrate as counter unit. Valid range are 0~0x1FF, | |
* set this value to 0 will disable time-out counter. | |
* | |
* @return None | |
* | |
* @details The time-out counter resets and starts counting whenever the Rx buffer received a | |
* new data word. Once the counter decrease to 1 and no new data is received or CPU | |
* does not read any data from FIFO, a receiver time-out interrupt will be generated. | |
*/ | |
void SCUART_SetTimeoutCnt(SC_T* sc, uint32_t u32TOC) | |
{ | |
sc->RXTOUT = u32TOC; | |
} | |
/** | |
* @brief Write data into transmit FIFO to send data out | |
* | |
* @param[in] sc The pointer of smartcard module. | |
* @param[in] pu8TxBuf The buffer containing data to send to transmit FIFO. | |
* @param[in] u32WriteBytes Number of data to send. | |
* | |
* @return None | |
* | |
* @details This function is used to write data into Tx FIFO to send data out. | |
* | |
* @note This function blocks until all data write into FIFO. | |
*/ | |
void SCUART_Write(SC_T* sc, uint8_t pu8TxBuf[], uint32_t u32WriteBytes) | |
{ | |
uint32_t u32Count; | |
for(u32Count = 0UL; u32Count != u32WriteBytes; u32Count++) | |
{ | |
/* Wait 'til FIFO not full */ | |
while(SCUART_GET_TX_FULL(sc)) | |
{ | |
; | |
} | |
/* Write 1 byte to FIFO */ | |
sc->DAT = pu8TxBuf[u32Count]; /* Write 1 byte to FIFO */ | |
} | |
} | |
/*@}*/ /* end of group SCUART_EXPORTED_FUNCTIONS */ | |
/*@}*/ /* end of group SCUART_Driver */ | |
/*@}*/ /* end of group Standard_Driver */ | |
/*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/ |