]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_MPU_M23_Nuvoton_NuMaker_PFM_M2351_IAR_GCC/Nuvoton_Code/StdDriver/src/scuart.c
Add Cortex M23 GCC and IAR ports. Add demo projects for Nuvoton NuMaker-PFM-2351.
[freertos] / FreeRTOS / Demo / CORTEX_MPU_M23_Nuvoton_NuMaker_PFM_M2351_IAR_GCC / Nuvoton_Code / StdDriver / src / scuart.c
1 /**************************************************************************//**\r
2  * @file     scuart.c\r
3  * @version  V3.00\r
4  * @brief    Smartcard UART mode (SCUART) driver source file\r
5  *\r
6  * @copyright (C) 2016 Nuvoton Technology Corp. All rights reserved.\r
7 *****************************************************************************/\r
8 #include "NuMicro.h"\r
9 \r
10 static uint32_t SCUART_GetClock(SC_T *sc);\r
11 \r
12 /** @addtogroup Standard_Driver Standard Driver\r
13   @{\r
14 */\r
15 \r
16 /** @addtogroup SCUART_Driver SCUART Driver\r
17   @{\r
18 */\r
19 \r
20 /** @addtogroup SCUART_EXPORTED_FUNCTIONS SCUART Exported Functions\r
21   @{\r
22 */\r
23 \r
24 /**\r
25   * @brief      Disable smartcard interface\r
26   *\r
27   * @param      sc      The pointer of smartcard module.\r
28   *\r
29   * @return     None\r
30   *\r
31   * @details    The function is used to disable smartcard interface UART mode.\r
32   */\r
33 void SCUART_Close(SC_T* sc)\r
34 {\r
35     sc->INTEN = 0UL;\r
36     sc->UARTCTL = 0UL;\r
37     sc->CTL = 0UL;\r
38 }\r
39 \r
40 /** @cond HIDDEN_SYMBOLS */\r
41 /**\r
42   * @brief      Returns module clock of specified SC interface\r
43   *\r
44   * @param[in]  sc      The pointer of smartcard module.\r
45   *\r
46   * @return     Module clock of specified SC interface.\r
47   */\r
48 static uint32_t SCUART_GetClock(SC_T *sc)\r
49 {\r
50     uint32_t u32ClkSrc, u32Num, u32Clk = __HIRC, u32Div;\r
51 \r
52     /* Get smartcard module clock source and divider */\r
53     if((sc == SC0) || (sc == SC0_NS))\r
54     {\r
55         u32Num = 0UL;\r
56         u32ClkSrc = CLK_GetModuleClockSource(SC0_MODULE);\r
57         u32Div = CLK_GetModuleClockDivider(SC0_MODULE);\r
58     }\r
59     else if((sc == SC1) || (sc == SC1_NS))\r
60     {\r
61         u32Num = 1UL;\r
62         u32ClkSrc = CLK_GetModuleClockSource(SC1_MODULE);\r
63         u32Div = CLK_GetModuleClockDivider(SC1_MODULE);\r
64     }\r
65     else if((sc == SC2) || (sc == SC2_NS))\r
66     {\r
67         u32Num = 2UL;\r
68         u32ClkSrc = CLK_GetModuleClockSource(SC2_MODULE);\r
69         u32Div = CLK_GetModuleClockDivider(SC2_MODULE);\r
70     }\r
71     else\r
72     {\r
73         u32Clk = 0UL;\r
74     }\r
75 \r
76     if(u32Clk == 0UL)\r
77     {\r
78         ; /* Invalid sc port */\r
79     }\r
80     else\r
81     {\r
82         /* Get smartcard module clock */\r
83         if(u32ClkSrc == 0UL)\r
84         {\r
85             u32Clk = __HXT;\r
86         }\r
87         else if(u32ClkSrc == 1UL)\r
88         {\r
89             u32Clk = CLK_GetPLLClockFreq();\r
90         }\r
91         else if(u32ClkSrc == 2UL)\r
92         {\r
93             if(u32Num == 1UL)\r
94             {\r
95                 u32Clk = CLK_GetPCLK1Freq();\r
96             }\r
97             else\r
98             {\r
99                 u32Clk = CLK_GetPCLK0Freq();\r
100             }\r
101         }\r
102         else\r
103         {\r
104             u32Clk = __HIRC;\r
105         }\r
106 \r
107         u32Clk /= (u32Div + 1UL);\r
108     }\r
109 \r
110     return u32Clk;\r
111 }\r
112 /** @endcond HIDDEN_SYMBOLS */\r
113 \r
114 /**\r
115   * @brief      Enable smartcard module UART mode and set baudrate\r
116   *\r
117   * @param[in]  sc          The pointer of smartcard module.\r
118   * @param[in]  u32Baudrate Target baudrate of smartcard UART module.\r
119   *\r
120   * @return     Actual baudrate of smartcard UART mode\r
121   *\r
122   * @details    This function use to enable smartcard module UART mode and set baudrate.\r
123   *\r
124   * @note       This function configures character width to 8 bits, 1 stop bit, and no parity.\r
125   *             And can use \ref SCUART_SetLineConfig function to update these settings.\r
126   *             The baudrate clock source comes from SC_CLK/SC_DIV, where SC_CLK is controlled\r
127   *             by SCxSEL in CLKSEL3 register, SC_DIV is controlled by SCxDIV in CLKDIV1\r
128   *             register. Since the baudrate divider is 12-bit wide and must be larger than 4,\r
129   *             (clock source / baudrate) must be larger or equal to 5 and smaller or equal to\r
130   *             4096. Otherwise this function cannot configure SCUART to work with target baudrate.\r
131   */\r
132 uint32_t SCUART_Open(SC_T* sc, uint32_t u32Baudrate)\r
133 {\r
134     uint32_t u32Clk = SCUART_GetClock(sc), u32Div;\r
135 \r
136     /* Calculate divider for target baudrate */\r
137     u32Div = (u32Clk + (u32Baudrate >> 1) - 1UL) / u32Baudrate - 1UL;\r
138 \r
139     sc->CTL = SC_CTL_SCEN_Msk | SC_CTL_NSB_Msk;  /* Enable smartcard interface and stop bit = 1 */\r
140     sc->UARTCTL = SCUART_CHAR_LEN_8 | SCUART_PARITY_NONE | SC_UARTCTL_UARTEN_Msk; /* Enable UART mode, disable parity and 8 bit per character */\r
141     sc->ETUCTL = u32Div;\r
142 \r
143     return(u32Clk / (u32Div + 1UL));\r
144 }\r
145 \r
146 /**\r
147   * @brief      Read Rx data from Rx FIFO\r
148   *\r
149   * @param[in]  sc              The pointer of smartcard module.\r
150   * @param[in]  pu8RxBuf        The buffer to store receive the data.\r
151   * @param[in] u32ReadBytes     Target number of characters to receive\r
152   *\r
153   * @return     Actual character number reads to buffer\r
154   *\r
155   * @details    The function is used to read data from Rx FIFO.\r
156   *\r
157   * @note       This function does not block and return immediately if there's no data available.\r
158   */\r
159 uint32_t SCUART_Read(SC_T* sc, uint8_t pu8RxBuf[], uint32_t u32ReadBytes)\r
160 {\r
161     uint32_t u32Count;\r
162 \r
163     for(u32Count = 0UL; u32Count < u32ReadBytes; u32Count++)\r
164     {\r
165         if(SCUART_GET_RX_EMPTY(sc))   /* no data available */\r
166         {\r
167             break;\r
168         }\r
169         pu8RxBuf[u32Count] = (uint8_t)SCUART_READ(sc);    /* get data from FIFO */\r
170     }\r
171 \r
172     return u32Count;\r
173 }\r
174 \r
175 /**\r
176   * @brief      Configure smartcard UART mode line setting\r
177   *\r
178   * @param[in]  sc              The pointer of smartcard module.\r
179   * @param[in]  u32Baudrate     Target baudrate of smartcard UART mode. If this value is 0, SC UART baudrate will not change.\r
180   * @param[in]  u32DataWidth    The data length, could be:\r
181   *                                 - \ref SCUART_CHAR_LEN_5\r
182   *                                 - \ref SCUART_CHAR_LEN_6\r
183   *                                 - \ref SCUART_CHAR_LEN_7\r
184   *                                 - \ref SCUART_CHAR_LEN_8\r
185   * @param[in]  u32Parity       The parity setting, could be:\r
186   *                                 - \ref SCUART_PARITY_NONE\r
187   *                                 - \ref SCUART_PARITY_ODD\r
188   *                                  - \ref SCUART_PARITY_EVEN\r
189   * @param[in]  u32StopBits     The stop bit length, could be:\r
190   *                                 - \ref SCUART_STOP_BIT_1\r
191   *                                 - \ref SCUART_STOP_BIT_2\r
192   *\r
193   * @return     Actual baudrate of smartcard UART mode\r
194   *\r
195   * @details    The baudrate clock source comes from SC_CLK/SC_DIV, where SC_CLK is controlled\r
196   *             by SCxSEL in CLKSEL3 register, SC_DIV is controlled by SCxDIV in CLKDIV1\r
197   *             register. Since the baudrate divider is 12-bit wide and must be larger than 4,\r
198   *             (clock source / baudrate) must be larger or equal to 5 and smaller or equal to\r
199   *             4096. Otherwise this function cannot configure SCUART to work with target baudrate.\r
200   */\r
201 uint32_t SCUART_SetLineConfig(SC_T* sc, uint32_t u32Baudrate, uint32_t u32DataWidth, uint32_t u32Parity, uint32_t u32StopBits)\r
202 {\r
203     uint32_t u32Clk = SCUART_GetClock(sc), u32Div;\r
204 \r
205     if(u32Baudrate == 0UL)\r
206     {\r
207         /* Keep original baudrate setting */\r
208         u32Div = sc->ETUCTL & SC_ETUCTL_ETURDIV_Msk;\r
209     }\r
210     else\r
211     {\r
212         /* Calculate divider for target baudrate */\r
213         u32Div = ((u32Clk + (u32Baudrate >> 1) - 1UL) / u32Baudrate) - 1UL;\r
214         sc->ETUCTL = u32Div;\r
215     }\r
216 \r
217     sc->CTL = u32StopBits | SC_CTL_SCEN_Msk;  /* Set stop bit */\r
218     sc->UARTCTL = u32Parity | u32DataWidth | SC_UARTCTL_UARTEN_Msk;  /* Set character width and parity */\r
219 \r
220     return (u32Clk / (u32Div + 1UL));\r
221 }\r
222 \r
223 /**\r
224   * @brief      Set receive timeout count\r
225   *\r
226   * @param[in]  sc      The pointer of smartcard module.\r
227   * @param[in]  u32TOC  Rx time-out counter, using baudrate as counter unit. Valid range are 0~0x1FF,\r
228   *                     set this value to 0 will disable time-out counter.\r
229   *\r
230   * @return     None\r
231   *\r
232   * @details    The time-out counter resets and starts counting whenever the Rx buffer received a\r
233   *             new data word. Once the counter decrease to 1 and no new data is received or CPU\r
234   *             does not read any data from FIFO, a receiver time-out interrupt will be generated.\r
235   */\r
236 void SCUART_SetTimeoutCnt(SC_T* sc, uint32_t u32TOC)\r
237 {\r
238     sc->RXTOUT = u32TOC;\r
239 }\r
240 \r
241 /**\r
242   * @brief      Write data into transmit FIFO to send data out\r
243   *\r
244   * @param[in]  sc              The pointer of smartcard module.\r
245   * @param[in]  pu8TxBuf        The buffer containing data to send to transmit FIFO.\r
246   * @param[in]  u32WriteBytes   Number of data to send.\r
247   *\r
248   * @return     None\r
249   *\r
250   * @details    This function is used to write data into Tx FIFO to send data out.\r
251   *\r
252   * @note       This function blocks until all data write into FIFO.\r
253   */\r
254 void SCUART_Write(SC_T* sc, uint8_t pu8TxBuf[], uint32_t u32WriteBytes)\r
255 {\r
256     uint32_t u32Count;\r
257 \r
258     for(u32Count = 0UL; u32Count != u32WriteBytes; u32Count++)\r
259     {\r
260         /* Wait 'til FIFO not full */\r
261         while(SCUART_GET_TX_FULL(sc))\r
262         {\r
263             ;\r
264         }\r
265         /* Write 1 byte to FIFO */\r
266         sc->DAT = pu8TxBuf[u32Count];  /* Write 1 byte to FIFO */\r
267     }\r
268 }\r
269 \r
270 \r
271 /*@}*/ /* end of group SCUART_EXPORTED_FUNCTIONS */\r
272 \r
273 /*@}*/ /* end of group SCUART_Driver */\r
274 \r
275 /*@}*/ /* end of group Standard_Driver */\r
276 \r
277 /*** (C) COPYRIGHT 2016 Nuvoton Technology Corp. ***/\r