blob: 88c916617e06c1809e8d3bc639ba991a792be1df [file] [log] [blame]
Kévin Redon93717e42018-07-08 13:26:15 +02001/* ----------------------------------------------------------------------------
2 * ATMEL Microcontroller Software Support
3 * ----------------------------------------------------------------------------
4 * Copyright (c) 2009, Atmel Corporation
5 *
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
10 *
11 * - Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the disclaimer below.
13 *
14 * Atmel's name may not be used to endorse or promote products derived from
15 * this software without specific prior written permission.
16 *
17 * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
20 * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
23 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
24 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
25 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 * ----------------------------------------------------------------------------
28 */
29
30/**
31 * \file
32 *
33 * Implements UART console.
34 *
35 */
36
37/*----------------------------------------------------------------------------
38 * Headers
39 *----------------------------------------------------------------------------*/
40
41#include "board.h"
42
43#include <stdio.h>
44#include <stdint.h>
45
46#include "ringbuffer.h"
47
48/*----------------------------------------------------------------------------
49 * Definitions
50 *----------------------------------------------------------------------------*/
51
52/*----------------------------------------------------------------------------
53 * Variables
54 *----------------------------------------------------------------------------*/
55
56/** Is Console Initialized. */
57static uint8_t _ucIsConsoleInitialized=0;
58/** Ring buffer to queue data to be sent */
59static ringbuf uart_tx_buffer;
60
61/**
62 * \brief Configures an USART peripheral with the specified parameters.
63 *
64 * \param baudrate Baudrate at which the USART should operate (in Hz).
65 * \param masterClock Frequency of the system master clock (in Hz).
66 */
67extern void UART_Configure( uint32_t baudrate, uint32_t masterClock)
68{
69 const Pin pPins[] = CONSOLE_PINS;
70 Uart *pUart = CONSOLE_UART;
71
72 /* Configure PIO */
73 PIO_Configure(pPins, PIO_LISTSIZE(pPins));
74
75 /* Configure PMC */
76 PMC->PMC_PCER0 = 1 << CONSOLE_ID;
77
78 /* Reset and disable receiver & transmitter */
79 pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX
80 | UART_CR_RXDIS | UART_CR_TXDIS;
81
82 /* Configure mode */
83 pUart->UART_MR = UART_MR_PAR_NO;
84
85 /* Configure baudrate */
86 /* Asynchronous, no oversampling */
87 pUart->UART_BRGR = (masterClock / baudrate) / 16;
88
89 /* Disable PDC channel */
90 pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
91
92 /* Reset transmit ring buffer */
93 rbuf_reset(&uart_tx_buffer);
94
95 /* Enable TX interrupts */
96 pUart->UART_IER = UART_IER_TXRDY;
97 NVIC_EnableIRQ(CONSOLE_IRQ);
98
99 /* Enable receiver and transmitter */
100 pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
101
102 /* Remember the configuration is complete */
103 _ucIsConsoleInitialized=1 ;
104}
105
106/**
107 * \brief Disables the USART peripheral and related IRQ
108 */
109void UART_Exit(void)
110{
111 if (!_ucIsConsoleInitialized) {
112 return;
113 }
114
115 Uart *pUart = CONSOLE_UART;
116 pUart->UART_IDR = UART_IDR_TXRDY;
117 pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS | UART_CR_RSTSTA;
118 PMC->PMC_PCDR0 = 1 << CONSOLE_ID;
119 NVIC_DisableIRQ(CONSOLE_IRQ);
120}
121
122/** Interrupt Service routine to transmit queued data */
123void CONSOLE_ISR(void)
124{
125 Uart *uart = CONSOLE_UART;
126 if (uart->UART_SR & UART_SR_TXRDY) {
127 if (!rbuf_is_empty(&uart_tx_buffer)) {
128 uart->UART_THR = rbuf_read(&uart_tx_buffer);
129 } else {
130 uart->UART_IDR = UART_IER_TXRDY;
131 }
132 }
133}
134
135/**
136 * \brief Outputs a character on the UART line.
137 *
138 * \note This function is synchronous (i.e. uses polling).
139 * \param c Character to send.
140 */
141extern void UART_PutChar( uint8_t c )
142{
143 Uart *pUart = CONSOLE_UART ;
144
145 /* Initialize console is not already done */
146 if ( !_ucIsConsoleInitialized )
147 {
148 UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
149 }
150
151 /* Only store input if buffer is not full, else drop it */
152 if (!rbuf_is_full(&uart_tx_buffer)) {
153 rbuf_write(&uart_tx_buffer, c);
154 if (!(pUart->UART_IMR & UART_IMR_TXRDY)) {
155 pUart->UART_IER = UART_IER_TXRDY;
156 CONSOLE_ISR();
157 }
158 }
159}
160
161/**
162 * \brief Input a character from the UART line.
163 *
164 * \note This function is synchronous
165 * \return character received.
166 */
167extern uint32_t UART_GetChar( void )
168{
169 Uart *pUart = CONSOLE_UART ;
170
171 if ( !_ucIsConsoleInitialized )
172 {
173 UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
174 }
175
176 while ( (pUart->UART_SR & UART_SR_RXRDY) == 0 )
177 WDT_Restart(WDT);
178
179 return pUart->UART_RHR ;
180}
181
182/**
183 * \brief Check if there is Input from UART line.
184 *
185 * \return true if there is Input.
186 */
187extern uint32_t UART_IsRxReady( void )
188{
189 Uart *pUart = CONSOLE_UART;
190
191 if ( !_ucIsConsoleInitialized )
192 {
193 UART_Configure( CONSOLE_BAUDRATE, BOARD_MCK ) ;
194 }
195
196 return (pUart->UART_SR & UART_SR_RXRDY) > 0 ;
197}
198
199/**
200 * Displays the content of the given frame on the UART0.
201 *
202 * \param pucFrame Pointer to the frame to dump.
203 * \param dwSize Buffer size in bytes.
204 */
205extern void UART_DumpFrame( uint8_t* pucFrame, uint32_t dwSize )
206{
207 uint32_t dw ;
208
209 for ( dw=0 ; dw < dwSize ; dw++ )
210 {
211 printf( "%02X ", pucFrame[dw] ) ;
212 }
213
214 printf( "\n\r" ) ;
215}
216
217/**
218 * Displays the content of the given buffer on the UART0.
219 *
220 * \param pucBuffer Pointer to the buffer to dump.
221 * \param dwSize Buffer size in bytes.
222 * \param dwAddress Start address to display
223 */
224extern void UART_DumpMemory( uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress )
225{
226 uint32_t i ;
227 uint32_t j ;
228 uint32_t dwLastLineStart ;
229 uint8_t* pucTmp ;
230
231 for ( i=0 ; i < (dwSize / 16) ; i++ )
232 {
233 printf( "0x%08X: ", (unsigned int)(dwAddress + (i*16)) ) ;
234 pucTmp = (uint8_t*)&pucBuffer[i*16] ;
235
236 for ( j=0 ; j < 4 ; j++ )
237 {
238 printf( "%02X%02X%02X%02X ", pucTmp[0], pucTmp[1], pucTmp[2], pucTmp[3] ) ;
239 pucTmp += 4 ;
240 }
241
242 pucTmp=(uint8_t*)&pucBuffer[i*16] ;
243
244 for ( j=0 ; j < 16 ; j++ )
245 {
246 UART_PutChar( *pucTmp++ ) ;
247 }
248
249 printf( "\n\r" ) ;
250 }
251
252 if ( (dwSize%16) != 0 )
253 {
254 dwLastLineStart=dwSize - (dwSize%16) ;
255
256 printf( "0x%08X: ", (unsigned int)(dwAddress + dwLastLineStart) ) ;
257 for ( j=dwLastLineStart ; j < dwLastLineStart+16 ; j++ )
258 {
259 if ( (j!=dwLastLineStart) && (j%4 == 0) )
260 {
261 printf( " " ) ;
262 }
263
264 if ( j < dwSize )
265 {
266 printf( "%02X", pucBuffer[j] ) ;
267 }
268 else
269 {
270 printf(" ") ;
271 }
272 }
273
274 printf( " " ) ;
275 for ( j=dwLastLineStart ; j < dwSize ; j++ )
276 {
277 UART_PutChar( pucBuffer[j] ) ;
278 }
279
280 printf( "\n\r" ) ;
281 }
282}
283
284/**
285 * Reads an integer
286 *
287 * \param pdwValue Pointer to the uint32_t variable to contain the input value.
288 */
289extern uint32_t UART_GetInteger( uint32_t* pdwValue )
290{
291 uint8_t ucKey ;
292 uint8_t ucNbNb=0 ;
293 uint32_t dwValue=0 ;
294
295 while ( 1 )
296 {
297 ucKey=UART_GetChar() ;
298 UART_PutChar( ucKey ) ;
299
300 if ( ucKey >= '0' && ucKey <= '9' )
301 {
302 dwValue = (dwValue * 10) + (ucKey - '0');
303 ucNbNb++ ;
304 }
305 else
306 {
307 if ( ucKey == 0x0D || ucKey == ' ' )
308 {
309 if ( ucNbNb == 0 )
310 {
311 printf( "\n\rWrite a number and press ENTER or SPACE!\n\r" ) ;
312 return 0 ;
313 }
314 else
315 {
316 printf( "\n\r" ) ;
317 *pdwValue=dwValue ;
318
319 return 1 ;
320 }
321 }
322 else
323 {
324 printf( "\n\r'%c' not a number!\n\r", ucKey ) ;
325
326 return 0 ;
327 }
328 }
329 WDT_Restart(WDT);
330 }
331}
332
333/**
334 * Reads an integer and check the value
335 *
336 * \param pdwValue Pointer to the uint32_t variable to contain the input value.
337 * \param dwMin Minimum value
338 * \param dwMax Maximum value
339 */
340extern uint32_t UART_GetIntegerMinMax( uint32_t* pdwValue, uint32_t dwMin, uint32_t dwMax )
341{
342 uint32_t dwValue=0 ;
343
344 if ( UART_GetInteger( &dwValue ) == 0 )
345 {
346 return 0 ;
347 }
348
349 if ( dwValue < dwMin || dwValue > dwMax )
350 {
351 printf( "\n\rThe number have to be between %d and %d\n\r", (int)dwMin, (int)dwMax ) ;
352
353 return 0 ;
354 }
355
356 printf( "\n\r" ) ;
357
358 *pdwValue = dwValue ;
359
360 return 1 ;
361}
362
363/**
364 * Reads an hexadecimal number
365 *
366 * \param pdwValue Pointer to the uint32_t variable to contain the input value.
367 */
368extern uint32_t UART_GetHexa32( uint32_t* pdwValue )
369{
370 uint8_t ucKey ;
371 uint32_t dw = 0 ;
372 uint32_t dwValue = 0 ;
373
374 for ( dw=0 ; dw < 8 ; dw++ )
375 {
376 ucKey = UART_GetChar() ;
377 UART_PutChar( ucKey ) ;
378
379 if ( ucKey >= '0' && ucKey <= '9' )
380 {
381 dwValue = (dwValue * 16) + (ucKey - '0') ;
382 }
383 else
384 {
385 if ( ucKey >= 'A' && ucKey <= 'F' )
386 {
387 dwValue = (dwValue * 16) + (ucKey - 'A' + 10) ;
388 }
389 else
390 {
391 if ( ucKey >= 'a' && ucKey <= 'f' )
392 {
393 dwValue = (dwValue * 16) + (ucKey - 'a' + 10) ;
394 }
395 else
396 {
397 printf( "\n\rIt is not a hexa character!\n\r" ) ;
398
399 return 0 ;
400 }
401 }
402 }
403 }
404
405 printf("\n\r" ) ;
406 *pdwValue = dwValue ;
407
408 return 1 ;
409}
410
411#if defined __ICCARM__ /* IAR Ewarm 5.41+ */
412/**
413 * \brief Outputs a character on the UART.
414 *
415 * \param c Character to output.
416 *
417 * \return The character that was output.
418 */
419extern WEAK signed int putchar( signed int c )
420{
421 UART_PutChar( c ) ;
422
423 return c ;
424}
425#endif // defined __ICCARM__
426