]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/CORTEX_M7_SAMV71_Xplained_AtmelStudio/libchip_samv7/source/usart.c
Add SAMV7 (Cortex-M7) demo for Atmel Studio.
[freertos] / FreeRTOS / Demo / CORTEX_M7_SAMV71_Xplained_AtmelStudio / libchip_samv7 / source / usart.c
1 /* ----------------------------------------------------------------------------\r
2  *         SAM Software Package License \r
3  * ----------------------------------------------------------------------------\r
4  * Copyright (c) 2013, Atmel Corporation\r
5  *\r
6  * All rights reserved.\r
7  *\r
8  * Redistribution and use in source and binary forms, with or without\r
9  * modification, are permitted provided that the following conditions are met:\r
10  *\r
11  * - Redistributions of source code must retain the above copyright notice,\r
12  * this list of conditions and the disclaimer below.\r
13  *\r
14  * Atmel's name may not be used to endorse or promote products derived from\r
15  * this software without specific prior written permission.\r
16  *\r
17  * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR\r
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\r
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE\r
20  * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,\r
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT\r
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,\r
23  * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF\r
24  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING\r
25  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
26  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
27  * ----------------------------------------------------------------------------\r
28  */\r
29 \r
30 /**\r
31  * \file\r
32  *\r
33  * Implementation of USART (Universal Synchronous Asynchronous Receiver \r
34  * Transmitter) controller.\r
35  *\r
36  */\r
37 /*------------------------------------------------------------------------------\r
38  *         Headers\r
39  *-----------------------------------------------------------------------------*/\r
40 #include "chip.h"\r
41 \r
42 #include <assert.h>\r
43 #include <string.h>\r
44 \r
45 /*----------------------------------------------------------------------------\r
46  *        Local definitions\r
47  *----------------------------------------------------------------------------*/\r
48 \r
49 \r
50 /*------------------------------------------------------------------------------\r
51  *         Exported functions\r
52  *-----------------------------------------------------------------------------*/\r
53 \r
54 /**\r
55  * \brief Configures an USART baudrate.\r
56  *\r
57  *\r
58  *  \param pUsart  Pointer to the USART peripheral to configure.\r
59  *  \param baudrate  Baudrate at which the USART should operate (in Hz).\r
60  *  \param masterClock  Frequency of the system master clock (in Hz).\r
61  */\r
62 void USART_SetBaudrate(Usart *pUsart,\r
63                                         uint8_t OverSamp,\r
64                                         uint32_t baudrate,\r
65                                         uint32_t masterClock)\r
66 {\r
67         unsigned int CD, FP, BaudError, ActualBaudRate;\r
68         /* Configure baudrate*/  \r
69         BaudError = 10;\r
70         OverSamp = 0;\r
71 \r
72                 /*Asynchronous*/\r
73                 if ((pUsart->US_MR & US_MR_SYNC) == 0)\r
74                 {\r
75                         /* 7816 mode */\r
76                         if( ((pUsart->US_MR & US_MR_USART_MODE_IS07816_T_0) \r
77                                         == US_MR_USART_MODE_IS07816_T_0 )\r
78                                 || ((pUsart->US_MR & US_MR_USART_MODE_IS07816_T_1) \r
79                                         == US_MR_USART_MODE_IS07816_T_1 ))\r
80                         {\r
81                                 /* Define the baud rate divisor register */\r
82                                 /* CD  = MCK / SCK */\r
83                                 /* SCK = FIDI x BAUD = 372 x 9600 */\r
84                                 /* BOARD_MCK */\r
85                                 /* CD = MCK/(FIDI x BAUD) = 150000000 / (372x9600) = 42 */\r
86                                 CD = masterClock / (pUsart->US_FIDI * baudrate);\r
87                                 FP = 0;\r
88                         }\r
89                         else{\r
90                         while (BaudError > 5) {\r
91                                 CD = (masterClock / (baudrate * 8 *( 2 - OverSamp)));\r
92                                 FP = ((masterClock / (baudrate * ( 2 - OverSamp)) ) - CD * 8);\r
93                                 ActualBaudRate = (masterClock/(CD * 8 + FP)) / ( 2 - OverSamp);\r
94                                 BaudError = (100 - ((baudrate * 100 / ActualBaudRate)));\r
95 \r
96                                 if (BaudError > 5) \r
97                                 {\r
98                                         OverSamp++;\r
99                                         if(OverSamp >= 2) \r
100                                         {\r
101                                                 TRACE_ERROR("Canont set this baudrate \n\r");\r
102                                                                 break;\r
103                                         }\r
104                                 }\r
105                         }\r
106                         }\r
107                 }\r
108                 /*Synchronous SPI  */\r
109                 if((pUsart->US_MR & US_MR_USART_MODE_SPI_MASTER) \r
110                                 == US_MR_USART_MODE_SPI_MASTER\r
111                         || ((pUsart->US_MR & US_MR_SYNC) == US_MR_SYNC) )\r
112                 {\r
113                         if( (pUsart->US_MR & US_MR_USCLKS_Msk) == US_MR_USCLKS_MCK)\r
114                         {\r
115                                 CD = masterClock / baudrate;\r
116                                 FP = ((masterClock / baudrate) - CD);\r
117                         }\r
118                 }\r
119                 \r
120         pUsart->US_BRGR = ( US_BRGR_CD(CD) | US_BRGR_FP(FP));\r
121         \r
122         /* Configure OverSamp*/\r
123         pUsart->US_MR |= (OverSamp << 19);\r
124 }\r
125 \r
126 /**\r
127  * \brief Configures an USART peripheral with the specified parameters.\r
128  *\r
129  *\r
130  *  \param pUsart  Pointer to the USART peripheral to configure.\r
131  *  \param mode  Desired value for the USART mode register (see the datasheet).\r
132  *  \param baudrate  Baudrate at which the USART should operate (in Hz).\r
133  *  \param masterClock  Frequency of the system master clock (in Hz).\r
134  */\r
135 void USART_Configure(Usart *pUsart,\r
136                 uint32_t mode,\r
137                 uint32_t baudrate,\r
138                 uint32_t masterClock)\r
139 {\r
140 \r
141         /* Reset and disable receiver & transmitter*/\r
142         pUsart->US_CR = US_CR_RSTRX | US_CR_RSTTX\r
143                 | US_CR_RXDIS | US_CR_TXDIS | US_CR_RSTSTA;\r
144         pUsart->US_IDR = 0xFFFFFFFF;\r
145 \r
146         pUsart->US_MR = mode; \r
147         /* Configure baudrate*/  \r
148         USART_SetBaudrate(pUsart, 0, baudrate, masterClock);\r
149 \r
150         /* Enable receiver and transmitter */\r
151         pUsart->US_CR = US_CR_RXEN | US_CR_TXEN;\r
152 \r
153         /* Disable buffering for printf(). */\r
154 #if ( defined (__GNUC__) && !defined (__SAMBA__) )\r
155         setvbuf(stdout, (char *)NULL, _IONBF, 0);\r
156 #endif\r
157  \r
158 }\r
159 /**\r
160  * \brief Enables or disables the transmitter of an USART peripheral.\r
161  *\r
162  *\r
163  * \param pUsart  Pointer to an USART peripheral\r
164  * \param enabled  If true, the transmitter is enabled; otherwise it is\r
165  * disabled.\r
166  */\r
167 void USART_SetTransmitterEnabled(Usart *pUsart, uint8_t enabled)\r
168 {\r
169         if (enabled) {\r
170                 pUsart->US_CR = US_CR_TXEN;\r
171         } else {\r
172                 pUsart->US_CR = US_CR_TXDIS;\r
173         }\r
174 }\r
175 \r
176 /**\r
177  * \brief Disables the Receiver of an USART peripheral.\r
178  *\r
179  * \param pUsart  Pointer to an USART peripheral\r
180  */\r
181 void USART_DisableRx(Usart *pUsart)\r
182 {\r
183 \r
184   pUsart->US_CR = US_CR_RXDIS;\r
185 }\r
186 \r
187 /**\r
188  * \brief Disables the transmitter of an USART peripheral.\r
189  *\r
190  * \param pUsart  Pointer to an USART peripheral\r
191  */\r
192 void USART_DisableTx(Usart *pUsart)\r
193 {\r
194          pUsart->US_CR =  US_CR_TXDIS;\r
195 }\r
196 \r
197 /**\r
198  * \brief Enables the Receiver of an USART peripheral.\r
199  *\r
200  * \param pUsart  Pointer to an USART peripheral\r
201  */\r
202 void USART_EnableRx(Usart *pUsart)\r
203 {\r
204 \r
205   pUsart->US_CR = US_CR_RXEN;\r
206 }\r
207 \r
208 /**\r
209  * \brief Enables the transmitter of an USART peripheral\r
210  *\r
211  * \param pUsart  Pointer to an USART peripheral\r
212  */\r
213 void USART_EnableTx(Usart *pUsart)\r
214 {\r
215          pUsart->US_CR =  US_CR_TXEN;\r
216 }\r
217 /**\r
218  * \brief Resets or disables the Receiver of an USART peripheral.\r
219  *\r
220  *\r
221  * \param pUsart  Pointer to an USART peripheral\r
222  */\r
223 void USART_ResetRx(Usart *pUsart)\r
224 {\r
225 \r
226   pUsart->US_CR = US_CR_RSTRX | US_CR_RXDIS;\r
227 }\r
228 \r
229 /**\r
230  * \brief resets and disables the transmitter of an USART peripheral.\r
231  *\r
232  *\r
233  * \param pUsart  Pointer to an USART peripheral\r
234  */\r
235 void USART_ResetTx(Usart *pUsart)\r
236 {\r
237          pUsart->US_CR =  US_CR_RSTTX | US_CR_TXDIS;\r
238 }\r
239 /**\r
240  * \brief Enables or disables the receiver of an USART peripheral\r
241  *\r
242  *\r
243  * \param pUsart  Pointer to an USART peripheral\r
244  * \param enabled  If true, the receiver is enabled; otherwise it is disabled.\r
245  */\r
246 void USART_SetReceiverEnabled(Usart *pUsart, uint8_t enabled)\r
247 {\r
248         if (enabled) {\r
249                 pUsart->US_CR = US_CR_RXEN;\r
250         } else {\r
251                 pUsart->US_CR = US_CR_RXDIS;\r
252         }\r
253 }\r
254 \r
255 /**\r
256  * \brief Enables or disables the Request To Send (RTS) of an USART peripheral\r
257  *\r
258  *\r
259  * \param pUsart  Pointer to an USART peripheral\r
260  * \param enabled  If true, the RTS is enabled (0); otherwise it is disabled.\r
261  */\r
262 void USART_SetRTSEnabled( Usart *pUsart, uint8_t enabled)\r
263 {\r
264         if (enabled) {\r
265                 pUsart->US_CR = US_CR_RTSEN;\r
266         } else {\r
267                 pUsart->US_CR = US_CR_RTSDIS;\r
268         }\r
269 }\r
270 \r
271 /**\r
272  * \brief Sends one packet of data through the specified USART peripheral. This\r
273  * function operates synchronously, so it only returns when the data has been\r
274  * actually sent.\r
275  *\r
276  *\r
277  * \param pUsart  Pointer to an USART peripheral.\r
278  * \param data  Data to send including 9nth bit and sync field if necessary (in\r
279  *        the same format as the US_THR register in the datasheet).\r
280  * \param timeOut  Time out value (0 = no timeout).\r
281  */\r
282 void USART_Write( Usart *pUsart, uint16_t data, volatile uint32_t timeOut)\r
283 {\r
284         if (timeOut == 0) {\r
285                 while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0);\r
286         } else {\r
287                 while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0) {\r
288                         if (timeOut == 0) {\r
289                                 TRACE_ERROR("USART_Write: Timed out.\n\r");\r
290                                 return;\r
291                         }\r
292                         timeOut--;\r
293                 }\r
294         }\r
295         pUsart->US_THR = data;\r
296 }\r
297 \r
298 /**\r
299  * \brief  Reads and return a packet of data on the specified USART peripheral. \r
300  * This function operates asynchronously, so it waits until some data has been\r
301  * received.\r
302  *\r
303  * \param pUsart  Pointer to an USART peripheral.\r
304  * \param timeOut  Time out value (0 -> no timeout).\r
305  */\r
306 uint16_t USART_Read( Usart *pUsart, volatile uint32_t timeOut)\r
307 {\r
308         if (timeOut == 0) {\r
309                 while ((pUsart->US_CSR & US_CSR_RXRDY) == 0);\r
310         } else {\r
311                 while ((pUsart->US_CSR & US_CSR_RXRDY) == 0) {\r
312                         if (timeOut == 0) {\r
313                                 TRACE_ERROR( "USART_Read: Timed out.\n\r" ) ;\r
314                                 return 0;\r
315                         }\r
316                         timeOut--;\r
317                 }\r
318         }\r
319         return pUsart->US_RHR;\r
320 }\r
321 \r
322 /**\r
323  * \brief  Returns 1 if some data has been received and can be read from an \r
324  * USART; otherwise returns 0.\r
325  *\r
326  * \param pUsart  Pointer to an USART instance.\r
327  */\r
328 uint8_t USART_IsDataAvailable(Usart *pUsart)\r
329 {\r
330         if ((pUsart->US_CSR & US_CSR_RXRDY) != 0) {\r
331                 return 1;\r
332         } else {\r
333                 return 0;\r
334         }\r
335 }\r
336 \r
337 /**\r
338  * \brief  Sends one packet of data through the specified USART peripheral. This\r
339  * function operates synchronously, so it only returns when the data has been\r
340  * actually sent.\r
341  *\r
342  * \param pUsart  Pointer to an USART peripheral.\r
343  * \param c  Character to send\r
344  */\r
345 void USART_PutChar( Usart *pUsart, uint8_t c)\r
346 {\r
347         /* Wait for the transmitter to be ready*/\r
348         while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0);\r
349 \r
350         /* Send character*/\r
351         pUsart->US_THR = c;\r
352 \r
353         /* Wait for the transfer to complete*/\r
354         while ((pUsart->US_CSR & US_CSR_TXEMPTY) == 0);\r
355 }\r
356 \r
357 /**\r
358  * \brief   Return 1 if a character can be read in USART\r
359  * \param pUsart  Pointer to an USART peripheral.\r
360  */\r
361 uint32_t USART_IsRxReady(Usart *pUsart)\r
362 {\r
363         return (pUsart->US_CSR & US_CSR_RXRDY);\r
364 }\r
365 \r
366 /**\r
367  * \brief   Get present status\r
368  * \param pUsart  Pointer to an USART peripheral.\r
369  */\r
370 uint32_t USART_GetStatus(Usart *pUsart)\r
371 {\r
372         return pUsart->US_CSR;\r
373 }\r
374 \r
375 /**\r
376  * \brief   Enable interrupt\r
377  * \param pUsart  Pointer to an USART peripheral.\r
378  * \param mode  Interrupt mode.\r
379  */\r
380 void USART_EnableIt(Usart *pUsart,uint32_t mode)\r
381 {\r
382         pUsart->US_IER = mode;\r
383 }\r
384 \r
385 /**\r
386  * \brief   Disable interrupt\r
387  * \param pUsart  Pointer to an USART peripheral.\r
388  * \param mode  Interrupt mode.\r
389  */\r
390 void USART_DisableIt(Usart *pUsart,uint32_t mode)\r
391 {\r
392         pUsart->US_IDR = mode;\r
393 }\r
394 \r
395 /**\r
396  * \brief   Return interrupt mask\r
397  * \param pUsart  Pointer to an USART peripheral.\r
398  */\r
399 uint32_t USART_GetItMask(Usart *pUsart)\r
400 {\r
401         return pUsart->US_IMR;\r
402 }\r
403 \r
404 /**\r
405  * \brief  Reads and returns a character from the USART.\r
406  *\r
407  * \note This function is synchronous (i.e. uses polling).\r
408  * \param pUsart  Pointer to an USART peripheral.\r
409  * \return Character received.\r
410  */\r
411 uint8_t USART_GetChar(Usart *pUsart)\r
412 {\r
413         while ((pUsart->US_CSR & US_CSR_RXRDY) == 0);\r
414         return pUsart->US_RHR;\r
415 }\r
416 \r
417 /**\r
418  * \brief  Enable Rx Timeout for USART.\r
419  *\r
420  * \param pUsart  Pointer to an USART peripheral.\r
421  * \param Timeout  Timeout value\r
422  * \return None\r
423  */\r
424 void USART_EnableRecvTimeOut(Usart *pUsart, uint32_t Timeout)\r
425 {\r
426         if( Timeout <= MAX_RX_TIMEOUT ) {\r
427                 pUsart->US_RTOR = Timeout;\r
428         } else if( Timeout == 0) {\r
429                 TRACE_DEBUG("Timeout is disabled\n\r");\r
430         } else {\r
431                 TRACE_INFO_WP("\n\r");\r
432                 TRACE_FATAL("Timeout value is out of range\n\r");\r
433         }\r
434 }\r
435 \r
436 /**\r
437  * \brief  Enable Tx Timeout for USART.\r
438  *\r
439  * \param pUsart  Pointer to an USART peripheral.\r
440  * \param TimeGaurd  TimeGaurd value\r
441  * \return None\r
442  */\r
443 void USART_EnableTxTimeGaurd(Usart *pUsart, uint32_t TimeGaurd)\r
444 {\r
445         if( ( (pUsart->US_MR & US_MR_USART_MODE_LON ) && TimeGaurd <= 16777215) || \r
446                         ((pUsart->US_MR & US_MR_USART_MODE_LON ) && TimeGaurd <= 255) ) {\r
447           pUsart->US_TTGR = TimeGaurd;\r
448         } else {\r
449           TRACE_ERROR(" TimeGaurd Value is too big for mode");\r
450         }\r
451 }\r
452 /**\r
453  * \brief  Acknowledge Rx timeout and sets to Idle or periodic repetitive state.\r
454  *\r
455  * \param pUsart  Pointer to an USART peripheral.\r
456  * \param Periodic  If timeout is periodic or should wait for new char\r
457  * \return None\r
458  */\r
459 void USART_AcknowledgeRxTimeOut(Usart *pUsart, uint8_t Periodic)\r
460 {\r
461         if(Periodic) {\r
462                 pUsart->US_CR = US_CR_RETTO;     // Restart timeout timer\r
463         } else {\r
464                 // Puts USARt in Idle mode and waits for a char after timeout\r
465                 pUsart->US_CR = US_CR_STTTO; \r
466         }\r
467 }\r