OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [lib/] [source/] [neorv32_uart.c] - Blame information for rev 66

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 zero_gravi
// #################################################################################################
2
// # << NEORV32: neorv32_uart.c - Universal Asynchronous Receiver/Transmitter (UART) HW Driver >>  #
3
// # ********************************************************************************************* #
4
// # BSD 3-Clause License                                                                          #
5
// #                                                                                               #
6 44 zero_gravi
// # Copyright (c) 2021, Stephan Nolting. All rights reserved.                                     #
7 2 zero_gravi
// #                                                                                               #
8
// # Redistribution and use in source and binary forms, with or without modification, are          #
9
// # permitted provided that the following conditions are met:                                     #
10
// #                                                                                               #
11
// # 1. Redistributions of source code must retain the above copyright notice, this list of        #
12
// #    conditions and the following disclaimer.                                                   #
13
// #                                                                                               #
14
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
15
// #    conditions and the following disclaimer in the documentation and/or other materials        #
16
// #    provided with the distribution.                                                            #
17
// #                                                                                               #
18
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
19
// #    endorse or promote products derived from this software without specific prior written      #
20
// #    permission.                                                                                #
21
// #                                                                                               #
22
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
23
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
24
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
25
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
26
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
27
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
28
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
29
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
30
// # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
31
// # ********************************************************************************************* #
32
// # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
33
// #################################################################################################
34
 
35
 
36
/**********************************************************************//**
37
 * @file neorv32_uart.c
38
 * @author Stephan Nolting
39 50 zero_gravi
 * @brief Universal asynchronous receiver/transmitter (UART0/UART1) HW driver source file.
40 2 zero_gravi
 *
41 50 zero_gravi
 * @warning UART0 (primary UART) is used as default user console interface for all NEORV32 software framework/library functions.
42
 *
43
 * @note These functions should only be used if the UART0/UART1 unit was synthesized (IO_UART0_EN = true / IO_UART1_EN = true).
44 2 zero_gravi
 **************************************************************************/
45
 
46
#include "neorv32.h"
47
#include "neorv32_uart.h"
48
#include <string.h>
49 61 zero_gravi
#include <stdarg.h>
50 2 zero_gravi
 
51
/// \cond
52
// Private functions
53 65 zero_gravi
static void __neorv32_uart_itoa(uint32_t x, char *res) __attribute__((unused)); // GCC: do not output a warning when this variable is unused
54
static void __neorv32_uart_tohex(uint32_t x, char *res) __attribute__((unused)); // GCC: do not output a warning when this variable is unused
55 2 zero_gravi
/// \endcond
56
 
57
 
58 50 zero_gravi
 
59
// #################################################################################################
60
// Compatibility wrappers mapping to UART0 (primary UART)
61
// #################################################################################################
62
 
63 2 zero_gravi
/**********************************************************************//**
64 50 zero_gravi
 * Check if UART0 unit was synthesized.
65 2 zero_gravi
 *
66 50 zero_gravi
 * @warning This functions maps to UART0 (primary UART).
67
 *
68
 * @return 0 if UART0 was not synthesized, 1 if UART0 is available.
69 2 zero_gravi
 **************************************************************************/
70 50 zero_gravi
int neorv32_uart_available(void) { return neorv32_uart0_available(); }
71 2 zero_gravi
 
72 50 zero_gravi
 
73
/**********************************************************************//**
74
 * Enable and configure primary UART (UART0).
75
 *
76
 * @warning This functions maps to UART0 (primary UART).
77
 *
78
 * @note The 'UART0_SIM_MODE' compiler flag will configure UART0 for simulation mode: all UART0 TX data will be redirected to simulation output. Use this for simulations only!
79
 * @note To enable simulation mode add <USER_FLAGS+=-DUART0_SIM_MODE> when compiling.
80
 *
81
 * @warning The baud rate is computed using INTEGER operations (truncation errors might occur).
82
 *
83
 * @param[in] baudrate Targeted BAUD rate (e.g. 9600).
84 51 zero_gravi
 * @param[in] parity Parity configuration (00=off, 10=even, 11=odd), see #NEORV32_UART_PARITY_enum.
85
 * @param[in] flow_con Hardware flow control configuration (00=off, 01=RTS, 10=CTS, 11=RTS/CTS), see #NEORV32_UART_FLOW_CONTROL_enum.
86 50 zero_gravi
 **************************************************************************/
87 51 zero_gravi
void neorv32_uart_setup(uint32_t baudrate, uint8_t parity, uint8_t flow_con) { neorv32_uart0_setup(baudrate, parity, flow_con); }
88 50 zero_gravi
 
89
 
90
/**********************************************************************//**
91
 * Disable UART0.
92
 * @warning This functions maps to UART0 (primary UART).
93
 **************************************************************************/
94
void neorv32_uart_disable(void) { neorv32_uart0_disable(); }
95
 
96
 
97
/**********************************************************************//**
98 61 zero_gravi
 * Enable UART0.
99
 * @warning This functions maps to UART0 (primary UART).
100
 **************************************************************************/
101
void neorv32_uart_enable(void) { neorv32_uart0_enable(); }
102
 
103
 
104
/**********************************************************************//**
105 50 zero_gravi
 * Send single char via UART0.
106
 *
107
 * @warning This functions maps to UART0 (primary UART).
108
 * @note This function is blocking.
109
 *
110
 * @param[in] c Char to be send.
111
 **************************************************************************/
112
void neorv32_uart_putc(char c) { neorv32_uart0_putc(c); }
113
 
114
 
115
/**********************************************************************//**
116
 * Check if UART0 TX is busy.
117
 *
118
 * @warning This functions maps to UART0 (primary UART).
119
 * @note This function is blocking.
120
 *
121
 * @return 0 if idle, 1 if busy
122
 **************************************************************************/
123
int neorv32_uart_tx_busy(void) { return neorv32_uart0_tx_busy(); }
124
 
125
 
126
/**********************************************************************//**
127
 * Get char from UART0.
128
 *
129
 * @warning This functions maps to UART0 (primary UART).
130
 * @note This function is blocking and does not check for UART frame/parity errors.
131
 *
132
 * @return Received char.
133
 **************************************************************************/
134
char neorv32_uart_getc(void) { return neorv32_uart0_getc(); }
135
 
136
 
137
/**********************************************************************//**
138
 * Check if UART0 has received a char.
139
 *
140
 * @warning This functions maps to UART0 (primary UART).
141
 * @note This function is non-blocking.
142
 * @note Use neorv32_uart0_char_received_get(void) to get the char.
143
 *
144
 * @return =!0 when a char has been received.
145
 **************************************************************************/
146
int neorv32_uart_char_received(void) { return neorv32_uart0_char_received(); }
147
 
148
 
149
/**********************************************************************//**
150
 * Get char from UART0 (and check errors).
151
 *
152
 * @warning This functions maps to UART0 (primary UART).
153
 * @note This function is non-blocking and checks for frame and parity errors.
154
 *
155
 * @param[in,out] data Received char.
156
 * @return Status code (0=nothing received, 1: char received without errors; -1: char received with frame error; -2: char received with parity error; -3 char received with frame & parity error).
157
 **************************************************************************/
158 51 zero_gravi
int neorv32_uart_getc_safe(char *data) { return neorv32_uart0_getc_safe(data); }
159 50 zero_gravi
 
160
 
161
/**********************************************************************//**
162
 * Get a received char from UART0.
163
 *
164
 * @warning This functions maps to UART0 (primary UART).
165
 * @note This function is non-blocking.
166
 * @note Should only be used in combination with neorv32_uart_char_received(void).
167
 *
168
 * @return Received char.
169
 **************************************************************************/
170
char neorv32_uart_char_received_get(void) { return neorv32_uart0_char_received_get(); }
171
 
172
 
173
/**********************************************************************//**
174
 * Print string (zero-terminated) via UART0. Print full line break "\r\n" for every '\n'.
175
 *
176
 * @warning This functions maps to UART0 (primary UART).
177
 * @note This function is blocking.
178
 *
179
 * @param[in] s Pointer to string.
180
 **************************************************************************/
181
void neorv32_uart_print(const char *s) { neorv32_uart0_print(s); }
182
 
183
 
184
/**********************************************************************//**
185
 * Custom version of 'printf' function using UART0.
186
 *
187
 * @warning This functions maps to UART0 (primary UART).
188
 * @note This function is blocking.
189
 *
190
 * @param[in] format Pointer to format string.
191
 *
192
 * <TABLE>
193
 * <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
194
 * <TR><TD>%c</TD><TD>Single char</TD></TR>
195
 * <TR><TD>%i</TD><TD>32-bit signed number, printed as decimal</TD></TR>
196
 * <TR><TD>%u</TD><TD>32-bit unsigned number, printed as decimal</TD></TR>
197
 * <TR><TD>%x</TD><TD>32-bit number, printed as 8-char hexadecimal</TD></TR>
198
 * </TABLE>
199
 **************************************************************************/
200
void neorv32_uart_printf(const char *format, ...) { neorv32_uart0_printf(format); }
201
 
202
 
203
/**********************************************************************//**
204
 * Simplified custom version of 'scanf' function for UART0.
205
 *
206
 * @warning This functions maps to UART0 (primary UART).
207
 * @note This function is blocking.
208
 *
209
 * @param[in,out] buffer Pointer to array of chars to store string.
210
 * @param[in] max_size Maximum number of chars to sample.
211
 * @param[in] echo Echo UART input when 1.
212
 * @return Number of chars read.
213
 **************************************************************************/
214
int neorv32_uart_scan(char *buffer, int max_size, int echo) { return neorv32_uart0_scan(buffer, max_size, echo); }
215
 
216
 
217
 
218
// #################################################################################################
219
// Primary UART (UART0)
220
// #################################################################################################
221
 
222
/**********************************************************************//**
223
 * Check if UART0 unit was synthesized.
224
 *
225
 * @return 0 if UART0 was not synthesized, 1 if UART0 is available.
226
 **************************************************************************/
227
int neorv32_uart0_available(void) {
228
 
229 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_IO_UART0)) {
230 2 zero_gravi
    return 1;
231
  }
232
  else {
233
    return 0;
234
  }
235
}
236
 
237
 
238
/**********************************************************************//**
239 50 zero_gravi
 * Enable and configure primary UART (UART0).
240 2 zero_gravi
 *
241 50 zero_gravi
 * @note The 'UART0_SIM_MODE' compiler flag will configure UART0 for simulation mode: all UART0 TX data will be redirected to simulation output. Use this for simulations only!
242
 * @note To enable simulation mode add <USER_FLAGS+=-DUART0_SIM_MODE> when compiling.
243 30 zero_gravi
 *
244 47 zero_gravi
 * @warning The baud rate is computed using INTEGER operations (truncation errors might occur).
245
 *
246 2 zero_gravi
 * @param[in] baudrate Targeted BAUD rate (e.g. 9600).
247 51 zero_gravi
 * @param[in] parity Parity configuration (00=off, 10=even, 11=odd), see #NEORV32_UART_PARITY_enum.
248
 * @param[in] flow_con Hardware flow control configuration (00=off, 01=RTS, 10=CTS, 11=RTS/CTS), see #NEORV32_UART_FLOW_CONTROL_enum.
249 2 zero_gravi
 **************************************************************************/
250 51 zero_gravi
void neorv32_uart0_setup(uint32_t baudrate, uint8_t parity, uint8_t flow_con) {
251 2 zero_gravi
 
252 64 zero_gravi
  NEORV32_UART0.CTRL = 0; // reset
253 2 zero_gravi
 
254 64 zero_gravi
  uint32_t clock = NEORV32_SYSINFO.CLK;
255 2 zero_gravi
  uint16_t i = 0; // BAUD rate divisor
256 36 zero_gravi
  uint8_t p = 0; // initial prsc = CLK/2
257
 
258
  // raw clock prescaler
259 66 zero_gravi
#ifndef make_bootloader
260 36 zero_gravi
  i = (uint16_t)(clock / (2*baudrate));
261
#else
262 66 zero_gravi
  // division via repeated subtraction (minimal size, only for bootloader)
263 2 zero_gravi
  while (clock >= 2*baudrate) {
264
    clock -= 2*baudrate;
265
    i++;
266
  }
267 36 zero_gravi
#endif
268 2 zero_gravi
 
269 47 zero_gravi
  // find baud prescaler (12-bit wide))
270 2 zero_gravi
  while (i >= 0x0fff) {
271
    if ((p == 2) || (p == 4))
272
      i >>= 3;
273
    else
274
      i >>= 1;
275
    p++;
276
  }
277
 
278 47 zero_gravi
  uint32_t clk_prsc = (uint32_t)p;
279 64 zero_gravi
  clk_prsc = clk_prsc << UART_CTRL_PRSC0;
280 2 zero_gravi
 
281 47 zero_gravi
  uint32_t baud_prsc = (uint32_t)i;
282
  baud_prsc = baud_prsc - 1;
283 64 zero_gravi
  baud_prsc = baud_prsc << UART_CTRL_BAUD00;
284 2 zero_gravi
 
285
  uint32_t uart_en = 1;
286 64 zero_gravi
  uart_en = uart_en << UART_CTRL_EN;
287 2 zero_gravi
 
288 42 zero_gravi
  uint32_t parity_config = (uint32_t)(parity & 3);
289 64 zero_gravi
  parity_config = parity_config << UART_CTRL_PMODE0;
290 42 zero_gravi
 
291 51 zero_gravi
  uint32_t flow_control = (uint32_t)(flow_con & 3);
292 64 zero_gravi
  flow_control = flow_control << UART_CTRL_RTS_EN;
293 51 zero_gravi
 
294 50 zero_gravi
  /* Enable UART0 for SIM mode. */
295 42 zero_gravi
  /* USE THIS ONLY FOR SIMULATION! */
296 30 zero_gravi
#ifdef UART_SIM_MODE
297 50 zero_gravi
  #warning <UART_SIM_MODE> is obsolete (but still supported for compatibility). Please consider using the new flag <UART0_SIM_MODE>.
298
#endif
299
#if defined UART0_SIM_MODE || defined UART_SIM_MODE
300
  #warning UART0_SIM_MODE (primary UART) enabled! Sending all UART0.TX data to text.io simulation output instead of real UART0 transmitter. Use this for simulations only!
301 64 zero_gravi
  uint32_t sim_mode = 1 << UART_CTRL_SIM_MODE;
302 30 zero_gravi
#else
303
  uint32_t sim_mode = 0;
304
#endif
305
 
306 64 zero_gravi
  NEORV32_UART0.CTRL = clk_prsc | baud_prsc | uart_en | parity_config | sim_mode | flow_control;
307 2 zero_gravi
}
308
 
309
 
310
/**********************************************************************//**
311 50 zero_gravi
 * Disable UART0.
312 2 zero_gravi
 **************************************************************************/
313 50 zero_gravi
void neorv32_uart0_disable(void) {
314 2 zero_gravi
 
315 64 zero_gravi
  NEORV32_UART0.CTRL &= ~((uint32_t)(1 << UART_CTRL_EN));
316 2 zero_gravi
}
317
 
318
 
319
/**********************************************************************//**
320 61 zero_gravi
 * Enable UART0.
321
 **************************************************************************/
322
void neorv32_uart0_enable(void) {
323
 
324 64 zero_gravi
  NEORV32_UART0.CTRL = ((uint32_t)(1 << UART_CTRL_EN));
325 61 zero_gravi
}
326
 
327
 
328
/**********************************************************************//**
329 50 zero_gravi
 * Send single char via UART0.
330 2 zero_gravi
 *
331
 * @note This function is blocking.
332
 *
333
 * @param[in] c Char to be send.
334
 **************************************************************************/
335 50 zero_gravi
void neorv32_uart0_putc(char c) {
336 2 zero_gravi
 
337
  // wait for previous transfer to finish
338 65 zero_gravi
  while ((NEORV32_UART0.CTRL & (1<<UART_CTRL_TX_FULL)) != 0); // wait for space in TX FIFO
339 64 zero_gravi
  NEORV32_UART0.DATA = ((uint32_t)c) << UART_DATA_LSB;
340 2 zero_gravi
}
341
 
342
 
343
/**********************************************************************//**
344 65 zero_gravi
 * Check if UART0 TX is busy (transmitter busy or data left in TX buffer).
345 23 zero_gravi
 *
346
 * @note This function is blocking.
347
 *
348
 * @return 0 if idle, 1 if busy
349
 **************************************************************************/
350 50 zero_gravi
int neorv32_uart0_tx_busy(void) {
351 23 zero_gravi
 
352 65 zero_gravi
  uint32_t ctrl = NEORV32_UART0.CTRL;
353
 
354
  if (((ctrl & (1<<UART_CTRL_TX_BUSY)) != 0) ||  // TX engine busy
355
      ((ctrl & (1<<UART_CTRL_TX_EMPTY)) == 0)) { // TX buffer not empty
356 23 zero_gravi
    return 1;
357
  }
358
  return 0;
359
}
360
 
361
 
362
/**********************************************************************//**
363 50 zero_gravi
 * Get char from UART0.
364 2 zero_gravi
 *
365 42 zero_gravi
 * @note This function is blocking and does not check for UART frame/parity errors.
366 2 zero_gravi
 *
367
 * @return Received char.
368
 **************************************************************************/
369 50 zero_gravi
char neorv32_uart0_getc(void) {
370 2 zero_gravi
 
371
  uint32_t d = 0;
372
  while (1) {
373 64 zero_gravi
    d = NEORV32_UART0.DATA;
374 2 zero_gravi
    if ((d & (1<<UART_DATA_AVAIL)) != 0) { // char received?
375
      return (char)d;
376
    }
377
  }
378
}
379
 
380
 
381
/**********************************************************************//**
382 50 zero_gravi
 * Get char from UART0 (and check errors).
383 2 zero_gravi
 *
384 42 zero_gravi
 * @note This function is non-blocking and checks for frame and parity errors.
385
 *
386
 * @param[in,out] data Received char.
387 65 zero_gravi
 * @return Status code:
388
 *  0 = char received without errors
389
 * -1 = nothing received
390
 * -2 = char received with frame error
391
 * -3 = char received with parity error
392
 * -4 = char received with overrun error.
393 42 zero_gravi
 **************************************************************************/
394 51 zero_gravi
int neorv32_uart0_getc_safe(char *data) {
395 42 zero_gravi
 
396 64 zero_gravi
  uint32_t uart_rx = NEORV32_UART0.DATA;
397 42 zero_gravi
 
398 65 zero_gravi
  // get received byte (if there is any)
399
  *data = (char)uart_rx;
400 42 zero_gravi
 
401 65 zero_gravi
  // check if no data available at all
402
  if ((uart_rx & (1<<UART_DATA_AVAIL)) == 0) {
403
   return -1;
404
  }
405 42 zero_gravi
 
406 65 zero_gravi
  // check for frame error
407
  if (uart_rx & (1<<UART_DATA_FERR)) {
408
    return -2;
409
  }
410 42 zero_gravi
 
411 65 zero_gravi
  // check for parity error
412
  if (uart_rx & (1<<UART_DATA_PERR)) {
413
    return -3;
414
  }
415 42 zero_gravi
 
416 65 zero_gravi
  // check for overrun error
417
  if (uart_rx & (1<<UART_DATA_OVERR)) {
418
    return -4;
419
  }
420 42 zero_gravi
 
421 65 zero_gravi
  return 0; // all fine
422 42 zero_gravi
}
423
 
424
 
425
/**********************************************************************//**
426 50 zero_gravi
 * Check if UART0 has received a char.
427 42 zero_gravi
 *
428 2 zero_gravi
 * @note This function is non-blocking.
429 50 zero_gravi
 * @note Use neorv32_uart0_char_received_get(void) to get the char.
430 2 zero_gravi
 *
431
 * @return =!0 when a char has been received.
432
 **************************************************************************/
433 50 zero_gravi
int neorv32_uart0_char_received(void) {
434 2 zero_gravi
 
435 64 zero_gravi
  if ((NEORV32_UART0.DATA & (1<<UART_DATA_AVAIL)) != 0) {
436 2 zero_gravi
    return 1;
437
  }
438
  else {
439
    return 0;
440
  }
441
}
442
 
443
 
444
/**********************************************************************//**
445 50 zero_gravi
 * Get a received char from UART0.
446 2 zero_gravi
 *
447
 * @note This function is non-blocking.
448
 * @note Should only be used in combination with neorv32_uart_char_received(void).
449
 *
450
 * @return Received char.
451
 **************************************************************************/
452 50 zero_gravi
char neorv32_uart0_char_received_get(void) {
453 2 zero_gravi
 
454 64 zero_gravi
  return (char)NEORV32_UART0.DATA;
455 2 zero_gravi
}
456
 
457
 
458
/**********************************************************************//**
459 50 zero_gravi
 * Print string (zero-terminated) via UART0. Print full line break "\r\n" for every '\n'.
460 2 zero_gravi
 *
461
 * @note This function is blocking.
462
 *
463
 * @param[in] s Pointer to string.
464
 **************************************************************************/
465 50 zero_gravi
void neorv32_uart0_print(const char *s) {
466 2 zero_gravi
 
467
  char c = 0;
468
  while ((c = *s++)) {
469
    if (c == '\n') {
470 50 zero_gravi
      neorv32_uart0_putc('\r');
471 2 zero_gravi
    }
472 50 zero_gravi
    neorv32_uart0_putc(c);
473 2 zero_gravi
  }
474
}
475
 
476
 
477
/**********************************************************************//**
478 50 zero_gravi
 * Custom version of 'printf' function using UART0.
479 2 zero_gravi
 *
480 50 zero_gravi
 * @note This function is blocking.
481
 *
482
 * @param[in] format Pointer to format string.
483
 *
484
 * <TABLE>
485
 * <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
486
 * <TR><TD>%c</TD><TD>Single char</TD></TR>
487
 * <TR><TD>%i</TD><TD>32-bit signed number, printed as decimal</TD></TR>
488
 * <TR><TD>%u</TD><TD>32-bit unsigned number, printed as decimal</TD></TR>
489
 * <TR><TD>%x</TD><TD>32-bit number, printed as 8-char hexadecimal</TD></TR>
490
 * </TABLE>
491 2 zero_gravi
 **************************************************************************/
492 50 zero_gravi
void neorv32_uart0_printf(const char *format, ...) {
493 2 zero_gravi
 
494 50 zero_gravi
  char c, string_buf[11];
495
  int32_t n;
496 2 zero_gravi
 
497 50 zero_gravi
  va_list a;
498
  va_start(a, format);
499 2 zero_gravi
 
500 50 zero_gravi
  while ((c = *format++)) {
501
    if (c == '%') {
502
      c = *format++;
503
      switch (c) {
504
        case 's': // string
505
          neorv32_uart0_print(va_arg(a, char*));
506
          break;
507
        case 'c': // char
508
          neorv32_uart0_putc((char)va_arg(a, int));
509
          break;
510
        case 'i': // 32-bit signed
511
          n = (int32_t)va_arg(a, int32_t);
512
          if (n < 0) {
513
            n = -n;
514
            neorv32_uart0_putc('-');
515
          }
516
          __neorv32_uart_itoa((uint32_t)n, string_buf);
517
          neorv32_uart0_print(string_buf);
518
          break;
519
        case 'u': // 32-bit unsigned
520
          __neorv32_uart_itoa(va_arg(a, uint32_t), string_buf);
521
          neorv32_uart0_print(string_buf);
522
          break;
523
        case 'x': // 32-bit hexadecimal
524
          __neorv32_uart_tohex(va_arg(a, uint32_t), string_buf);
525
          neorv32_uart0_print(string_buf);
526
          break;
527 55 zero_gravi
        default: // unsupported format
528
          neorv32_uart0_putc('%');
529
          neorv32_uart0_putc(c);
530
          break;
531 50 zero_gravi
      }
532
    }
533
    else {
534
      if (c == '\n') {
535
        neorv32_uart0_putc('\r');
536
      }
537
      neorv32_uart0_putc(c);
538
    }
539 2 zero_gravi
  }
540 50 zero_gravi
  va_end(a);
541
}
542 2 zero_gravi
 
543 50 zero_gravi
 
544
/**********************************************************************//**
545
 * Simplified custom version of 'scanf' function for UART0.
546
 *
547
 * @note This function is blocking.
548
 *
549
 * @param[in,out] buffer Pointer to array of chars to store string.
550
 * @param[in] max_size Maximum number of chars to sample.
551
 * @param[in] echo Echo UART input when 1.
552
 * @return Number of chars read.
553
 **************************************************************************/
554
int neorv32_uart0_scan(char *buffer, int max_size, int echo) {
555
 
556
  char c = 0;
557
  int length = 0;
558
 
559
  while (1) {
560
    c = neorv32_uart0_getc();
561
    if (c == '\b') { // BACKSPACE
562
      if (length != 0) {
563
        if (echo) {
564
          neorv32_uart0_print("\b \b"); // delete last char in console
565
        }
566
        buffer--;
567
        length--;
568
      }
569
    }
570
    else if (c == '\r') // carriage return
571 2 zero_gravi
      break;
572 50 zero_gravi
    else if ((c >= ' ') && (c <= '~') && (length < (max_size-1))) {
573
      if (echo) {
574
        neorv32_uart0_putc(c); // echo
575
      }
576
      *buffer++ = c;
577
      length++;
578
    }
579 2 zero_gravi
  }
580 50 zero_gravi
  *buffer = '\0'; // terminate string
581 2 zero_gravi
 
582 50 zero_gravi
  return length;
583
}
584 2 zero_gravi
 
585 50 zero_gravi
 
586
 
587
// #################################################################################################
588
// Secondary UART (UART1)
589
// #################################################################################################
590
 
591
/**********************************************************************//**
592
 * Check if UART1 unit was synthesized.
593
 *
594
 * @return 0 if UART1 was not synthesized, 1 if UART1 is available.
595
 **************************************************************************/
596
int neorv32_uart1_available(void) {
597
 
598 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_IO_UART1)) {
599 50 zero_gravi
    return 1;
600
  }
601
  else {
602
    return 0;
603
  }
604 2 zero_gravi
}
605
 
606
 
607
/**********************************************************************//**
608 50 zero_gravi
 * Enable and configure secondary UART (UART1).
609 2 zero_gravi
 *
610 50 zero_gravi
 * @note The 'UART1_SIM_MODE' compiler flag will configure UART1 for simulation mode: all UART1 TX data will be redirected to simulation output. Use this for simulations only!
611
 * @note To enable simulation mode add <USER_FLAGS+=-DUART1_SIM_MODE> when compiling.
612
 *
613
 * @warning The baud rate is computed using INTEGER operations (truncation errors might occur).
614
 *
615
 * @param[in] baudrate Targeted BAUD rate (e.g. 9600).
616 51 zero_gravi
 * @param[in] parity Parity configuration (00=off, 10=even, 11=odd), see #NEORV32_UART_PARITY_enum.
617
 * @param[in] flow_con Hardware flow control configuration (00=off, 01=RTS, 10=CTS, 11=RTS/CTS), see #NEORV32_UART_FLOW_CONTROL_enum.
618 2 zero_gravi
 **************************************************************************/
619 51 zero_gravi
void neorv32_uart1_setup(uint32_t baudrate, uint8_t parity, uint8_t flow_con) {
620 2 zero_gravi
 
621 64 zero_gravi
  NEORV32_UART1.CTRL = 0; // reset
622 2 zero_gravi
 
623 64 zero_gravi
  uint32_t clock = NEORV32_SYSINFO.CLK;
624 50 zero_gravi
  uint16_t i = 0; // BAUD rate divisor
625
  uint8_t p = 0; // initial prsc = CLK/2
626
 
627
  // raw clock prescaler
628 66 zero_gravi
#ifdef make_bootloader
629 50 zero_gravi
  // use div instructions
630
  i = (uint16_t)(clock / (2*baudrate));
631
#else
632 66 zero_gravi
  // division via repeated subtraction (minimal size, only for bootloader)
633 50 zero_gravi
  while (clock >= 2*baudrate) {
634
    clock -= 2*baudrate;
635
    i++;
636 2 zero_gravi
  }
637 50 zero_gravi
#endif
638 2 zero_gravi
 
639 50 zero_gravi
  // find baud prescaler (12-bit wide))
640
  while (i >= 0x0fff) {
641
    if ((p == 2) || (p == 4))
642
      i >>= 3;
643
    else
644
      i >>= 1;
645
    p++;
646
  }
647
 
648
  uint32_t clk_prsc = (uint32_t)p;
649 64 zero_gravi
  clk_prsc = clk_prsc << UART_CTRL_PRSC0;
650 50 zero_gravi
 
651
  uint32_t baud_prsc = (uint32_t)i;
652
  baud_prsc = baud_prsc - 1;
653 64 zero_gravi
  baud_prsc = baud_prsc << UART_CTRL_BAUD00;
654 50 zero_gravi
 
655
  uint32_t uart_en = 1;
656 64 zero_gravi
  uart_en = uart_en << UART_CTRL_EN;
657 50 zero_gravi
 
658
  uint32_t parity_config = (uint32_t)(parity & 3);
659 64 zero_gravi
  parity_config = parity_config << UART_CTRL_PMODE0;
660 50 zero_gravi
 
661 51 zero_gravi
  uint32_t flow_control = (uint32_t)(flow_con & 3);
662 64 zero_gravi
  flow_control = flow_control << UART_CTRL_RTS_EN;
663 51 zero_gravi
 
664 50 zero_gravi
  /* Enable UART1 for SIM mode. */
665
  /* USE THIS ONLY FOR SIMULATION! */
666
#ifdef UART1_SIM_MODE
667
  #warning UART1_SIM_MODE (secondary UART) enabled! Sending all UART1.TX data to text.io simulation output instead of real UART1 transmitter. Use this for simulations only!
668 64 zero_gravi
  uint32_t sim_mode = 1 << UART_CTRL_SIM_MODE;
669 50 zero_gravi
#else
670
  uint32_t sim_mode = 0;
671
#endif
672
 
673 64 zero_gravi
  NEORV32_UART1.CTRL = clk_prsc | baud_prsc | uart_en | parity_config | sim_mode | flow_control;
674 2 zero_gravi
}
675
 
676
 
677
/**********************************************************************//**
678 50 zero_gravi
 * Disable UART1.
679
 **************************************************************************/
680
void neorv32_uart1_disable(void) {
681
 
682 64 zero_gravi
  NEORV32_UART1.CTRL &= ~((uint32_t)(1 << UART_CTRL_EN));
683 50 zero_gravi
}
684
 
685
 
686
/**********************************************************************//**
687 61 zero_gravi
 * Enable UART1.
688
 **************************************************************************/
689
void neorv32_uart1_enable(void) {
690
 
691 64 zero_gravi
  NEORV32_UART1.CTRL |= ((uint32_t)(1 << UART_CTRL_EN));
692 61 zero_gravi
}
693
 
694
 
695
/**********************************************************************//**
696 50 zero_gravi
 * Send single char via UART1.
697 2 zero_gravi
 *
698
 * @note This function is blocking.
699
 *
700 50 zero_gravi
 * @param[in] c Char to be send.
701
 **************************************************************************/
702
void neorv32_uart1_putc(char c) {
703
 
704
  // wait for previous transfer to finish
705 65 zero_gravi
  while ((NEORV32_UART1.CTRL & (1<<UART_CTRL_TX_FULL)) != 0); // wait for space in TX FIFO
706 64 zero_gravi
  NEORV32_UART1.DATA = ((uint32_t)c) << UART_DATA_LSB;
707 50 zero_gravi
}
708
 
709
 
710
/**********************************************************************//**
711 65 zero_gravi
 * Check if UART1 TX is busy (transmitter busy or data left in TX buffer).
712 50 zero_gravi
 *
713
 * @note This function is blocking.
714
 *
715
 * @return 0 if idle, 1 if busy
716
 **************************************************************************/
717
int neorv32_uart1_tx_busy(void) {
718
 
719 65 zero_gravi
  uint32_t ctrl = NEORV32_UART1.CTRL;
720
 
721
  if (((ctrl & (1<<UART_CTRL_TX_BUSY)) != 0) ||  // TX engine busy
722
      ((ctrl & (1<<UART_CTRL_TX_EMPTY)) == 0)) { // TX buffer not empty
723 50 zero_gravi
    return 1;
724
  }
725
  return 0;
726
}
727
 
728
 
729
/**********************************************************************//**
730
 * Get char from UART1.
731
 *
732
 * @note This function is blocking and does not check for UART frame/parity errors.
733
 *
734
 * @return Received char.
735
 **************************************************************************/
736
char neorv32_uart1_getc(void) {
737
 
738
  uint32_t d = 0;
739
  while (1) {
740 64 zero_gravi
    d = NEORV32_UART1.DATA;
741 50 zero_gravi
    if ((d & (1<<UART_DATA_AVAIL)) != 0) { // char received?
742
      return (char)d;
743
    }
744
  }
745
}
746
 
747
 
748
/**********************************************************************//**
749
 * Get char from UART1 (and check errors).
750
 *
751
 * @note This function is non-blocking and checks for frame and parity errors.
752
 *
753
 * @param[in,out] data Received char.
754 65 zero_gravi
 * @return Status code:
755
 *  0 = char received without errors
756
 * -1 = nothing received
757
 * -2 = char received with frame error
758
 * -3 = char received with parity error
759
 * -4 = char received with overrun error.
760 50 zero_gravi
 **************************************************************************/
761 51 zero_gravi
int neorv32_uart1_getc_safe(char *data) {
762 50 zero_gravi
 
763 64 zero_gravi
  uint32_t uart_rx = NEORV32_UART1.DATA;
764 50 zero_gravi
 
765 65 zero_gravi
  // get received byte (if there is any)
766
  *data = (char)uart_rx;
767 50 zero_gravi
 
768 65 zero_gravi
  // check if no data available at all
769
  if ((uart_rx & (1<<UART_DATA_AVAIL)) == 0) {
770
   return -1;
771
  }
772 50 zero_gravi
 
773 65 zero_gravi
  // check for frame error
774
  if (uart_rx & (1<<UART_DATA_FERR)) {
775
    return -2;
776
  }
777 50 zero_gravi
 
778 65 zero_gravi
  // check for parity error
779
  if (uart_rx & (1<<UART_DATA_PERR)) {
780
    return -3;
781
  }
782 50 zero_gravi
 
783 65 zero_gravi
  // check for overrun error
784
  if (uart_rx & (1<<UART_DATA_OVERR)) {
785
    return -4;
786
  }
787 50 zero_gravi
 
788 65 zero_gravi
  return 0; // all fine
789 50 zero_gravi
}
790
 
791
 
792
/**********************************************************************//**
793
 * Check if UART1 has received a char.
794
 *
795
 * @note This function is non-blocking.
796
 * @note Use neorv32_uart0_char_received_get(void) to get the char.
797
 *
798
 * @return =!0 when a char has been received.
799
 **************************************************************************/
800
int neorv32_uart1_char_received(void) {
801
 
802 64 zero_gravi
  if ((NEORV32_UART1.DATA & (1<<UART_DATA_AVAIL)) != 0) {
803 50 zero_gravi
    return 1;
804
  }
805
  else {
806
    return 0;
807
  }
808
}
809
 
810
 
811
/**********************************************************************//**
812
 * Get a received char from UART1.
813
 *
814
 * @note This function is non-blocking.
815
 * @note Should only be used in combination with neorv32_uart_char_received(void).
816
 *
817
 * @return Received char.
818
 **************************************************************************/
819
char neorv32_uart1_char_received_get(void) {
820
 
821 64 zero_gravi
  return (char)NEORV32_UART1.DATA;
822 50 zero_gravi
}
823
 
824
 
825
/**********************************************************************//**
826
 * Print string (zero-terminated) via UART1. Print full line break "\r\n" for every '\n'.
827
 *
828
 * @note This function is blocking.
829
 *
830
 * @param[in] s Pointer to string.
831
 **************************************************************************/
832
void neorv32_uart1_print(const char *s) {
833
 
834
  char c = 0;
835
  while ((c = *s++)) {
836
    if (c == '\n') {
837
      neorv32_uart1_putc('\r');
838
    }
839
    neorv32_uart1_putc(c);
840
  }
841
}
842
 
843
 
844
/**********************************************************************//**
845
 * Custom version of 'printf' function using UART1.
846
 *
847
 * @note This function is blocking.
848
 *
849 2 zero_gravi
 * @param[in] format Pointer to format string.
850
 *
851
 * <TABLE>
852
 * <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
853
 * <TR><TD>%c</TD><TD>Single char</TD></TR>
854
 * <TR><TD>%i</TD><TD>32-bit signed number, printed as decimal</TD></TR>
855
 * <TR><TD>%u</TD><TD>32-bit unsigned number, printed as decimal</TD></TR>
856
 * <TR><TD>%x</TD><TD>32-bit number, printed as 8-char hexadecimal</TD></TR>
857
 * </TABLE>
858
 **************************************************************************/
859 50 zero_gravi
void neorv32_uart1_printf(const char *format, ...) {
860 2 zero_gravi
 
861
  char c, string_buf[11];
862
  int32_t n;
863
 
864
  va_list a;
865
  va_start(a, format);
866
 
867
  while ((c = *format++)) {
868
    if (c == '%') {
869
      c = *format++;
870
      switch (c) {
871
        case 's': // string
872 50 zero_gravi
          neorv32_uart1_print(va_arg(a, char*));
873 2 zero_gravi
          break;
874
        case 'c': // char
875 50 zero_gravi
          neorv32_uart1_putc((char)va_arg(a, int));
876 2 zero_gravi
          break;
877
        case 'i': // 32-bit signed
878
          n = (int32_t)va_arg(a, int32_t);
879
          if (n < 0) {
880
            n = -n;
881 50 zero_gravi
            neorv32_uart1_putc('-');
882 2 zero_gravi
          }
883
          __neorv32_uart_itoa((uint32_t)n, string_buf);
884 50 zero_gravi
          neorv32_uart1_print(string_buf);
885 2 zero_gravi
          break;
886
        case 'u': // 32-bit unsigned
887
          __neorv32_uart_itoa(va_arg(a, uint32_t), string_buf);
888 50 zero_gravi
          neorv32_uart1_print(string_buf);
889 2 zero_gravi
          break;
890
        case 'x': // 32-bit hexadecimal
891
          __neorv32_uart_tohex(va_arg(a, uint32_t), string_buf);
892 50 zero_gravi
          neorv32_uart1_print(string_buf);
893 2 zero_gravi
          break;
894 55 zero_gravi
        default: // unsupported format
895
          neorv32_uart1_putc('%');
896
          neorv32_uart1_putc(c);
897
          break;
898 2 zero_gravi
      }
899
    }
900
    else {
901
      if (c == '\n') {
902 50 zero_gravi
        neorv32_uart1_putc('\r');
903 2 zero_gravi
      }
904 50 zero_gravi
      neorv32_uart1_putc(c);
905 2 zero_gravi
    }
906
  }
907
  va_end(a);
908
}
909
 
910
 
911
/**********************************************************************//**
912 50 zero_gravi
 * Simplified custom version of 'scanf' function for UART1.
913 2 zero_gravi
 *
914
 * @note This function is blocking.
915
 *
916
 * @param[in,out] buffer Pointer to array of chars to store string.
917
 * @param[in] max_size Maximum number of chars to sample.
918
 * @param[in] echo Echo UART input when 1.
919
 * @return Number of chars read.
920
 **************************************************************************/
921 50 zero_gravi
int neorv32_uart1_scan(char *buffer, int max_size, int echo) {
922 2 zero_gravi
 
923
  char c = 0;
924
  int length = 0;
925
 
926
  while (1) {
927 50 zero_gravi
    c = neorv32_uart1_getc();
928 2 zero_gravi
    if (c == '\b') { // BACKSPACE
929
      if (length != 0) {
930
        if (echo) {
931 50 zero_gravi
          neorv32_uart1_print("\b \b"); // delete last char in console
932 2 zero_gravi
        }
933
        buffer--;
934
        length--;
935
      }
936
    }
937
    else if (c == '\r') // carriage return
938
      break;
939
    else if ((c >= ' ') && (c <= '~') && (length < (max_size-1))) {
940
      if (echo) {
941 50 zero_gravi
        neorv32_uart1_putc(c); // echo
942 2 zero_gravi
      }
943
      *buffer++ = c;
944
      length++;
945
    }
946
  }
947
  *buffer = '\0'; // terminate string
948
 
949
  return length;
950
}
951
 
952 50 zero_gravi
 
953
 
954
// #################################################################################################
955
// Shared functions
956
// #################################################################################################
957
 
958
/**********************************************************************//**
959
 * Private function for 'neorv32_printf' to convert into decimal.
960
 *
961
 * @param[in] x Unsigned input number.
962
 * @param[in,out] res Pointer for storing the reuslting number string (11 chars).
963
 **************************************************************************/
964
static void __neorv32_uart_itoa(uint32_t x, char *res) {
965
 
966
  static const char numbers[] = "0123456789";
967
  char buffer1[11];
968
  uint16_t i, j;
969
 
970
  buffer1[10] = '\0';
971
  res[10] = '\0';
972
 
973
  // convert
974
  for (i=0; i<10; i++) {
975
    buffer1[i] = numbers[x%10];
976
    x /= 10;
977
  }
978
 
979
  // delete 'leading' zeros
980
  for (i=9; i!=0; i--) {
981
    if (buffer1[i] == '0')
982
      buffer1[i] = '\0';
983
    else
984
      break;
985
  }
986
 
987
  // reverse
988
  j = 0;
989
  do {
990
    if (buffer1[i] != '\0')
991
      res[j++] = buffer1[i];
992
  } while (i--);
993
 
994
  res[j] = '\0'; // terminate result string
995
}
996
 
997
 
998
/**********************************************************************//**
999
 * Private function for 'neorv32_printf' to convert into hexadecimal.
1000
 *
1001
 * @param[in] x Unsigned input number.
1002 55 zero_gravi
 * @param[in,out] res Pointer for storing the resulting number string (9 chars).
1003 50 zero_gravi
 **************************************************************************/
1004
static void __neorv32_uart_tohex(uint32_t x, char *res) {
1005
 
1006
  static const char symbols[] = "0123456789abcdef";
1007
 
1008
  int i;
1009 55 zero_gravi
  for (i=0; i<8; i++) { // nibble by nibble
1010 50 zero_gravi
    uint32_t num_tmp = x >> (4*i);
1011
    res[7-i] = (char)symbols[num_tmp & 0x0f];
1012
  }
1013
 
1014
  res[8] = '\0'; // terminate result string
1015
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.