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

Subversion Repositories neorv32

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

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
#ifdef __riscv_div
260
  // use div instructions
261
  i = (uint16_t)(clock / (2*baudrate));
262
#else
263
  // division via repeated subtraction
264 2 zero_gravi
  while (clock >= 2*baudrate) {
265
    clock -= 2*baudrate;
266
    i++;
267
  }
268 36 zero_gravi
#endif
269 2 zero_gravi
 
270 47 zero_gravi
  // find baud prescaler (12-bit wide))
271 2 zero_gravi
  while (i >= 0x0fff) {
272
    if ((p == 2) || (p == 4))
273
      i >>= 3;
274
    else
275
      i >>= 1;
276
    p++;
277
  }
278
 
279 47 zero_gravi
  uint32_t clk_prsc = (uint32_t)p;
280 64 zero_gravi
  clk_prsc = clk_prsc << UART_CTRL_PRSC0;
281 2 zero_gravi
 
282 47 zero_gravi
  uint32_t baud_prsc = (uint32_t)i;
283
  baud_prsc = baud_prsc - 1;
284 64 zero_gravi
  baud_prsc = baud_prsc << UART_CTRL_BAUD00;
285 2 zero_gravi
 
286
  uint32_t uart_en = 1;
287 64 zero_gravi
  uart_en = uart_en << UART_CTRL_EN;
288 2 zero_gravi
 
289 42 zero_gravi
  uint32_t parity_config = (uint32_t)(parity & 3);
290 64 zero_gravi
  parity_config = parity_config << UART_CTRL_PMODE0;
291 42 zero_gravi
 
292 51 zero_gravi
  uint32_t flow_control = (uint32_t)(flow_con & 3);
293 64 zero_gravi
  flow_control = flow_control << UART_CTRL_RTS_EN;
294 51 zero_gravi
 
295 50 zero_gravi
  /* Enable UART0 for SIM mode. */
296 42 zero_gravi
  /* USE THIS ONLY FOR SIMULATION! */
297 30 zero_gravi
#ifdef UART_SIM_MODE
298 50 zero_gravi
  #warning <UART_SIM_MODE> is obsolete (but still supported for compatibility). Please consider using the new flag <UART0_SIM_MODE>.
299
#endif
300
#if defined UART0_SIM_MODE || defined UART_SIM_MODE
301
  #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!
302 64 zero_gravi
  uint32_t sim_mode = 1 << UART_CTRL_SIM_MODE;
303 30 zero_gravi
#else
304
  uint32_t sim_mode = 0;
305
#endif
306
 
307 64 zero_gravi
  NEORV32_UART0.CTRL = clk_prsc | baud_prsc | uart_en | parity_config | sim_mode | flow_control;
308 2 zero_gravi
}
309
 
310
 
311
/**********************************************************************//**
312 50 zero_gravi
 * Disable UART0.
313 2 zero_gravi
 **************************************************************************/
314 50 zero_gravi
void neorv32_uart0_disable(void) {
315 2 zero_gravi
 
316 64 zero_gravi
  NEORV32_UART0.CTRL &= ~((uint32_t)(1 << UART_CTRL_EN));
317 2 zero_gravi
}
318
 
319
 
320
/**********************************************************************//**
321 61 zero_gravi
 * Enable UART0.
322
 **************************************************************************/
323
void neorv32_uart0_enable(void) {
324
 
325 64 zero_gravi
  NEORV32_UART0.CTRL = ((uint32_t)(1 << UART_CTRL_EN));
326 61 zero_gravi
}
327
 
328
 
329
/**********************************************************************//**
330 50 zero_gravi
 * Send single char via UART0.
331 2 zero_gravi
 *
332
 * @note This function is blocking.
333
 *
334
 * @param[in] c Char to be send.
335
 **************************************************************************/
336 50 zero_gravi
void neorv32_uart0_putc(char c) {
337 2 zero_gravi
 
338
  // wait for previous transfer to finish
339 65 zero_gravi
  while ((NEORV32_UART0.CTRL & (1<<UART_CTRL_TX_FULL)) != 0); // wait for space in TX FIFO
340 64 zero_gravi
  NEORV32_UART0.DATA = ((uint32_t)c) << UART_DATA_LSB;
341 2 zero_gravi
}
342
 
343
 
344
/**********************************************************************//**
345 65 zero_gravi
 * Check if UART0 TX is busy (transmitter busy or data left in TX buffer).
346 23 zero_gravi
 *
347
 * @note This function is blocking.
348
 *
349
 * @return 0 if idle, 1 if busy
350
 **************************************************************************/
351 50 zero_gravi
int neorv32_uart0_tx_busy(void) {
352 23 zero_gravi
 
353 65 zero_gravi
  uint32_t ctrl = NEORV32_UART0.CTRL;
354
 
355
  if (((ctrl & (1<<UART_CTRL_TX_BUSY)) != 0) ||  // TX engine busy
356
      ((ctrl & (1<<UART_CTRL_TX_EMPTY)) == 0)) { // TX buffer not empty
357 23 zero_gravi
    return 1;
358
  }
359
  return 0;
360
}
361
 
362
 
363
/**********************************************************************//**
364 50 zero_gravi
 * Get char from UART0.
365 2 zero_gravi
 *
366 42 zero_gravi
 * @note This function is blocking and does not check for UART frame/parity errors.
367 2 zero_gravi
 *
368
 * @return Received char.
369
 **************************************************************************/
370 50 zero_gravi
char neorv32_uart0_getc(void) {
371 2 zero_gravi
 
372
  uint32_t d = 0;
373
  while (1) {
374 64 zero_gravi
    d = NEORV32_UART0.DATA;
375 2 zero_gravi
    if ((d & (1<<UART_DATA_AVAIL)) != 0) { // char received?
376
      return (char)d;
377
    }
378
  }
379
}
380
 
381
 
382
/**********************************************************************//**
383 50 zero_gravi
 * Get char from UART0 (and check errors).
384 2 zero_gravi
 *
385 42 zero_gravi
 * @note This function is non-blocking and checks for frame and parity errors.
386
 *
387
 * @param[in,out] data Received char.
388 65 zero_gravi
 * @return Status code:
389
 *  0 = char received without errors
390
 * -1 = nothing received
391
 * -2 = char received with frame error
392
 * -3 = char received with parity error
393
 * -4 = char received with overrun error.
394 42 zero_gravi
 **************************************************************************/
395 51 zero_gravi
int neorv32_uart0_getc_safe(char *data) {
396 42 zero_gravi
 
397 64 zero_gravi
  uint32_t uart_rx = NEORV32_UART0.DATA;
398 42 zero_gravi
 
399 65 zero_gravi
  // get received byte (if there is any)
400
  *data = (char)uart_rx;
401 42 zero_gravi
 
402 65 zero_gravi
  // check if no data available at all
403
  if ((uart_rx & (1<<UART_DATA_AVAIL)) == 0) {
404
   return -1;
405
  }
406 42 zero_gravi
 
407 65 zero_gravi
  // check for frame error
408
  if (uart_rx & (1<<UART_DATA_FERR)) {
409
    return -2;
410
  }
411 42 zero_gravi
 
412 65 zero_gravi
  // check for parity error
413
  if (uart_rx & (1<<UART_DATA_PERR)) {
414
    return -3;
415
  }
416 42 zero_gravi
 
417 65 zero_gravi
  // check for overrun error
418
  if (uart_rx & (1<<UART_DATA_OVERR)) {
419
    return -4;
420
  }
421 42 zero_gravi
 
422 65 zero_gravi
  return 0; // all fine
423 42 zero_gravi
}
424
 
425
 
426
/**********************************************************************//**
427 50 zero_gravi
 * Check if UART0 has received a char.
428 42 zero_gravi
 *
429 2 zero_gravi
 * @note This function is non-blocking.
430 50 zero_gravi
 * @note Use neorv32_uart0_char_received_get(void) to get the char.
431 2 zero_gravi
 *
432
 * @return =!0 when a char has been received.
433
 **************************************************************************/
434 50 zero_gravi
int neorv32_uart0_char_received(void) {
435 2 zero_gravi
 
436 64 zero_gravi
  if ((NEORV32_UART0.DATA & (1<<UART_DATA_AVAIL)) != 0) {
437 2 zero_gravi
    return 1;
438
  }
439
  else {
440
    return 0;
441
  }
442
}
443
 
444
 
445
/**********************************************************************//**
446 50 zero_gravi
 * Get a received char from UART0.
447 2 zero_gravi
 *
448
 * @note This function is non-blocking.
449
 * @note Should only be used in combination with neorv32_uart_char_received(void).
450
 *
451
 * @return Received char.
452
 **************************************************************************/
453 50 zero_gravi
char neorv32_uart0_char_received_get(void) {
454 2 zero_gravi
 
455 64 zero_gravi
  return (char)NEORV32_UART0.DATA;
456 2 zero_gravi
}
457
 
458
 
459
/**********************************************************************//**
460 50 zero_gravi
 * Print string (zero-terminated) via UART0. Print full line break "\r\n" for every '\n'.
461 2 zero_gravi
 *
462
 * @note This function is blocking.
463
 *
464
 * @param[in] s Pointer to string.
465
 **************************************************************************/
466 50 zero_gravi
void neorv32_uart0_print(const char *s) {
467 2 zero_gravi
 
468
  char c = 0;
469
  while ((c = *s++)) {
470
    if (c == '\n') {
471 50 zero_gravi
      neorv32_uart0_putc('\r');
472 2 zero_gravi
    }
473 50 zero_gravi
    neorv32_uart0_putc(c);
474 2 zero_gravi
  }
475
}
476
 
477
 
478
/**********************************************************************//**
479 50 zero_gravi
 * Custom version of 'printf' function using UART0.
480 2 zero_gravi
 *
481 50 zero_gravi
 * @note This function is blocking.
482
 *
483
 * @param[in] format Pointer to format string.
484
 *
485
 * <TABLE>
486
 * <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
487
 * <TR><TD>%c</TD><TD>Single char</TD></TR>
488
 * <TR><TD>%i</TD><TD>32-bit signed number, printed as decimal</TD></TR>
489
 * <TR><TD>%u</TD><TD>32-bit unsigned number, printed as decimal</TD></TR>
490
 * <TR><TD>%x</TD><TD>32-bit number, printed as 8-char hexadecimal</TD></TR>
491
 * </TABLE>
492 2 zero_gravi
 **************************************************************************/
493 50 zero_gravi
void neorv32_uart0_printf(const char *format, ...) {
494 2 zero_gravi
 
495 50 zero_gravi
  char c, string_buf[11];
496
  int32_t n;
497 2 zero_gravi
 
498 50 zero_gravi
  va_list a;
499
  va_start(a, format);
500 2 zero_gravi
 
501 50 zero_gravi
  while ((c = *format++)) {
502
    if (c == '%') {
503
      c = *format++;
504
      switch (c) {
505
        case 's': // string
506
          neorv32_uart0_print(va_arg(a, char*));
507
          break;
508
        case 'c': // char
509
          neorv32_uart0_putc((char)va_arg(a, int));
510
          break;
511
        case 'i': // 32-bit signed
512
          n = (int32_t)va_arg(a, int32_t);
513
          if (n < 0) {
514
            n = -n;
515
            neorv32_uart0_putc('-');
516
          }
517
          __neorv32_uart_itoa((uint32_t)n, string_buf);
518
          neorv32_uart0_print(string_buf);
519
          break;
520
        case 'u': // 32-bit unsigned
521
          __neorv32_uart_itoa(va_arg(a, uint32_t), string_buf);
522
          neorv32_uart0_print(string_buf);
523
          break;
524
        case 'x': // 32-bit hexadecimal
525
          __neorv32_uart_tohex(va_arg(a, uint32_t), string_buf);
526
          neorv32_uart0_print(string_buf);
527
          break;
528 55 zero_gravi
        default: // unsupported format
529
          neorv32_uart0_putc('%');
530
          neorv32_uart0_putc(c);
531
          break;
532 50 zero_gravi
      }
533
    }
534
    else {
535
      if (c == '\n') {
536
        neorv32_uart0_putc('\r');
537
      }
538
      neorv32_uart0_putc(c);
539
    }
540 2 zero_gravi
  }
541 50 zero_gravi
  va_end(a);
542
}
543 2 zero_gravi
 
544 50 zero_gravi
 
545
/**********************************************************************//**
546
 * Simplified custom version of 'scanf' function for UART0.
547
 *
548
 * @note This function is blocking.
549
 *
550
 * @param[in,out] buffer Pointer to array of chars to store string.
551
 * @param[in] max_size Maximum number of chars to sample.
552
 * @param[in] echo Echo UART input when 1.
553
 * @return Number of chars read.
554
 **************************************************************************/
555
int neorv32_uart0_scan(char *buffer, int max_size, int echo) {
556
 
557
  char c = 0;
558
  int length = 0;
559
 
560
  while (1) {
561
    c = neorv32_uart0_getc();
562
    if (c == '\b') { // BACKSPACE
563
      if (length != 0) {
564
        if (echo) {
565
          neorv32_uart0_print("\b \b"); // delete last char in console
566
        }
567
        buffer--;
568
        length--;
569
      }
570
    }
571
    else if (c == '\r') // carriage return
572 2 zero_gravi
      break;
573 50 zero_gravi
    else if ((c >= ' ') && (c <= '~') && (length < (max_size-1))) {
574
      if (echo) {
575
        neorv32_uart0_putc(c); // echo
576
      }
577
      *buffer++ = c;
578
      length++;
579
    }
580 2 zero_gravi
  }
581 50 zero_gravi
  *buffer = '\0'; // terminate string
582 2 zero_gravi
 
583 50 zero_gravi
  return length;
584
}
585 2 zero_gravi
 
586 50 zero_gravi
 
587
 
588
// #################################################################################################
589
// Secondary UART (UART1)
590
// #################################################################################################
591
 
592
/**********************************************************************//**
593
 * Check if UART1 unit was synthesized.
594
 *
595
 * @return 0 if UART1 was not synthesized, 1 if UART1 is available.
596
 **************************************************************************/
597
int neorv32_uart1_available(void) {
598
 
599 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_IO_UART1)) {
600 50 zero_gravi
    return 1;
601
  }
602
  else {
603
    return 0;
604
  }
605 2 zero_gravi
}
606
 
607
 
608
/**********************************************************************//**
609 50 zero_gravi
 * Enable and configure secondary UART (UART1).
610 2 zero_gravi
 *
611 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!
612
 * @note To enable simulation mode add <USER_FLAGS+=-DUART1_SIM_MODE> when compiling.
613
 *
614
 * @warning The baud rate is computed using INTEGER operations (truncation errors might occur).
615
 *
616
 * @param[in] baudrate Targeted BAUD rate (e.g. 9600).
617 51 zero_gravi
 * @param[in] parity Parity configuration (00=off, 10=even, 11=odd), see #NEORV32_UART_PARITY_enum.
618
 * @param[in] flow_con Hardware flow control configuration (00=off, 01=RTS, 10=CTS, 11=RTS/CTS), see #NEORV32_UART_FLOW_CONTROL_enum.
619 2 zero_gravi
 **************************************************************************/
620 51 zero_gravi
void neorv32_uart1_setup(uint32_t baudrate, uint8_t parity, uint8_t flow_con) {
621 2 zero_gravi
 
622 64 zero_gravi
  NEORV32_UART1.CTRL = 0; // reset
623 2 zero_gravi
 
624 64 zero_gravi
  uint32_t clock = NEORV32_SYSINFO.CLK;
625 50 zero_gravi
  uint16_t i = 0; // BAUD rate divisor
626
  uint8_t p = 0; // initial prsc = CLK/2
627
 
628
  // raw clock prescaler
629
#ifdef __riscv_div
630
  // use div instructions
631
  i = (uint16_t)(clock / (2*baudrate));
632
#else
633
  // division via repeated subtraction
634
  while (clock >= 2*baudrate) {
635
    clock -= 2*baudrate;
636
    i++;
637 2 zero_gravi
  }
638 50 zero_gravi
#endif
639 2 zero_gravi
 
640 50 zero_gravi
  // find baud prescaler (12-bit wide))
641
  while (i >= 0x0fff) {
642
    if ((p == 2) || (p == 4))
643
      i >>= 3;
644
    else
645
      i >>= 1;
646
    p++;
647
  }
648
 
649
  uint32_t clk_prsc = (uint32_t)p;
650 64 zero_gravi
  clk_prsc = clk_prsc << UART_CTRL_PRSC0;
651 50 zero_gravi
 
652
  uint32_t baud_prsc = (uint32_t)i;
653
  baud_prsc = baud_prsc - 1;
654 64 zero_gravi
  baud_prsc = baud_prsc << UART_CTRL_BAUD00;
655 50 zero_gravi
 
656
  uint32_t uart_en = 1;
657 64 zero_gravi
  uart_en = uart_en << UART_CTRL_EN;
658 50 zero_gravi
 
659
  uint32_t parity_config = (uint32_t)(parity & 3);
660 64 zero_gravi
  parity_config = parity_config << UART_CTRL_PMODE0;
661 50 zero_gravi
 
662 51 zero_gravi
  uint32_t flow_control = (uint32_t)(flow_con & 3);
663 64 zero_gravi
  flow_control = flow_control << UART_CTRL_RTS_EN;
664 51 zero_gravi
 
665 50 zero_gravi
  /* Enable UART1 for SIM mode. */
666
  /* USE THIS ONLY FOR SIMULATION! */
667
#ifdef UART1_SIM_MODE
668
  #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!
669 64 zero_gravi
  uint32_t sim_mode = 1 << UART_CTRL_SIM_MODE;
670 50 zero_gravi
#else
671
  uint32_t sim_mode = 0;
672
#endif
673
 
674 64 zero_gravi
  NEORV32_UART1.CTRL = clk_prsc | baud_prsc | uart_en | parity_config | sim_mode | flow_control;
675 2 zero_gravi
}
676
 
677
 
678
/**********************************************************************//**
679 50 zero_gravi
 * Disable UART1.
680
 **************************************************************************/
681
void neorv32_uart1_disable(void) {
682
 
683 64 zero_gravi
  NEORV32_UART1.CTRL &= ~((uint32_t)(1 << UART_CTRL_EN));
684 50 zero_gravi
}
685
 
686
 
687
/**********************************************************************//**
688 61 zero_gravi
 * Enable UART1.
689
 **************************************************************************/
690
void neorv32_uart1_enable(void) {
691
 
692 64 zero_gravi
  NEORV32_UART1.CTRL |= ((uint32_t)(1 << UART_CTRL_EN));
693 61 zero_gravi
}
694
 
695
 
696
/**********************************************************************//**
697 50 zero_gravi
 * Send single char via UART1.
698 2 zero_gravi
 *
699
 * @note This function is blocking.
700
 *
701 50 zero_gravi
 * @param[in] c Char to be send.
702
 **************************************************************************/
703
void neorv32_uart1_putc(char c) {
704
 
705
  // wait for previous transfer to finish
706 65 zero_gravi
  while ((NEORV32_UART1.CTRL & (1<<UART_CTRL_TX_FULL)) != 0); // wait for space in TX FIFO
707 64 zero_gravi
  NEORV32_UART1.DATA = ((uint32_t)c) << UART_DATA_LSB;
708 50 zero_gravi
}
709
 
710
 
711
/**********************************************************************//**
712 65 zero_gravi
 * Check if UART1 TX is busy (transmitter busy or data left in TX buffer).
713 50 zero_gravi
 *
714
 * @note This function is blocking.
715
 *
716
 * @return 0 if idle, 1 if busy
717
 **************************************************************************/
718
int neorv32_uart1_tx_busy(void) {
719
 
720 65 zero_gravi
  uint32_t ctrl = NEORV32_UART1.CTRL;
721
 
722
  if (((ctrl & (1<<UART_CTRL_TX_BUSY)) != 0) ||  // TX engine busy
723
      ((ctrl & (1<<UART_CTRL_TX_EMPTY)) == 0)) { // TX buffer not empty
724 50 zero_gravi
    return 1;
725
  }
726
  return 0;
727
}
728
 
729
 
730
/**********************************************************************//**
731
 * Get char from UART1.
732
 *
733
 * @note This function is blocking and does not check for UART frame/parity errors.
734
 *
735
 * @return Received char.
736
 **************************************************************************/
737
char neorv32_uart1_getc(void) {
738
 
739
  uint32_t d = 0;
740
  while (1) {
741 64 zero_gravi
    d = NEORV32_UART1.DATA;
742 50 zero_gravi
    if ((d & (1<<UART_DATA_AVAIL)) != 0) { // char received?
743
      return (char)d;
744
    }
745
  }
746
}
747
 
748
 
749
/**********************************************************************//**
750
 * Get char from UART1 (and check errors).
751
 *
752
 * @note This function is non-blocking and checks for frame and parity errors.
753
 *
754
 * @param[in,out] data Received char.
755 65 zero_gravi
 * @return Status code:
756
 *  0 = char received without errors
757
 * -1 = nothing received
758
 * -2 = char received with frame error
759
 * -3 = char received with parity error
760
 * -4 = char received with overrun error.
761 50 zero_gravi
 **************************************************************************/
762 51 zero_gravi
int neorv32_uart1_getc_safe(char *data) {
763 50 zero_gravi
 
764 64 zero_gravi
  uint32_t uart_rx = NEORV32_UART1.DATA;
765 50 zero_gravi
 
766 65 zero_gravi
  // get received byte (if there is any)
767
  *data = (char)uart_rx;
768 50 zero_gravi
 
769 65 zero_gravi
  // check if no data available at all
770
  if ((uart_rx & (1<<UART_DATA_AVAIL)) == 0) {
771
   return -1;
772
  }
773 50 zero_gravi
 
774 65 zero_gravi
  // check for frame error
775
  if (uart_rx & (1<<UART_DATA_FERR)) {
776
    return -2;
777
  }
778 50 zero_gravi
 
779 65 zero_gravi
  // check for parity error
780
  if (uart_rx & (1<<UART_DATA_PERR)) {
781
    return -3;
782
  }
783 50 zero_gravi
 
784 65 zero_gravi
  // check for overrun error
785
  if (uart_rx & (1<<UART_DATA_OVERR)) {
786
    return -4;
787
  }
788 50 zero_gravi
 
789 65 zero_gravi
  return 0; // all fine
790 50 zero_gravi
}
791
 
792
 
793
/**********************************************************************//**
794
 * Check if UART1 has received a char.
795
 *
796
 * @note This function is non-blocking.
797
 * @note Use neorv32_uart0_char_received_get(void) to get the char.
798
 *
799
 * @return =!0 when a char has been received.
800
 **************************************************************************/
801
int neorv32_uart1_char_received(void) {
802
 
803 64 zero_gravi
  if ((NEORV32_UART1.DATA & (1<<UART_DATA_AVAIL)) != 0) {
804 50 zero_gravi
    return 1;
805
  }
806
  else {
807
    return 0;
808
  }
809
}
810
 
811
 
812
/**********************************************************************//**
813
 * Get a received char from UART1.
814
 *
815
 * @note This function is non-blocking.
816
 * @note Should only be used in combination with neorv32_uart_char_received(void).
817
 *
818
 * @return Received char.
819
 **************************************************************************/
820
char neorv32_uart1_char_received_get(void) {
821
 
822 64 zero_gravi
  return (char)NEORV32_UART1.DATA;
823 50 zero_gravi
}
824
 
825
 
826
/**********************************************************************//**
827
 * Print string (zero-terminated) via UART1. Print full line break "\r\n" for every '\n'.
828
 *
829
 * @note This function is blocking.
830
 *
831
 * @param[in] s Pointer to string.
832
 **************************************************************************/
833
void neorv32_uart1_print(const char *s) {
834
 
835
  char c = 0;
836
  while ((c = *s++)) {
837
    if (c == '\n') {
838
      neorv32_uart1_putc('\r');
839
    }
840
    neorv32_uart1_putc(c);
841
  }
842
}
843
 
844
 
845
/**********************************************************************//**
846
 * Custom version of 'printf' function using UART1.
847
 *
848
 * @note This function is blocking.
849
 *
850 2 zero_gravi
 * @param[in] format Pointer to format string.
851
 *
852
 * <TABLE>
853
 * <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
854
 * <TR><TD>%c</TD><TD>Single char</TD></TR>
855
 * <TR><TD>%i</TD><TD>32-bit signed number, printed as decimal</TD></TR>
856
 * <TR><TD>%u</TD><TD>32-bit unsigned number, printed as decimal</TD></TR>
857
 * <TR><TD>%x</TD><TD>32-bit number, printed as 8-char hexadecimal</TD></TR>
858
 * </TABLE>
859
 **************************************************************************/
860 50 zero_gravi
void neorv32_uart1_printf(const char *format, ...) {
861 2 zero_gravi
 
862
  char c, string_buf[11];
863
  int32_t n;
864
 
865
  va_list a;
866
  va_start(a, format);
867
 
868
  while ((c = *format++)) {
869
    if (c == '%') {
870
      c = *format++;
871
      switch (c) {
872
        case 's': // string
873 50 zero_gravi
          neorv32_uart1_print(va_arg(a, char*));
874 2 zero_gravi
          break;
875
        case 'c': // char
876 50 zero_gravi
          neorv32_uart1_putc((char)va_arg(a, int));
877 2 zero_gravi
          break;
878
        case 'i': // 32-bit signed
879
          n = (int32_t)va_arg(a, int32_t);
880
          if (n < 0) {
881
            n = -n;
882 50 zero_gravi
            neorv32_uart1_putc('-');
883 2 zero_gravi
          }
884
          __neorv32_uart_itoa((uint32_t)n, string_buf);
885 50 zero_gravi
          neorv32_uart1_print(string_buf);
886 2 zero_gravi
          break;
887
        case 'u': // 32-bit unsigned
888
          __neorv32_uart_itoa(va_arg(a, uint32_t), string_buf);
889 50 zero_gravi
          neorv32_uart1_print(string_buf);
890 2 zero_gravi
          break;
891
        case 'x': // 32-bit hexadecimal
892
          __neorv32_uart_tohex(va_arg(a, uint32_t), string_buf);
893 50 zero_gravi
          neorv32_uart1_print(string_buf);
894 2 zero_gravi
          break;
895 55 zero_gravi
        default: // unsupported format
896
          neorv32_uart1_putc('%');
897
          neorv32_uart1_putc(c);
898
          break;
899 2 zero_gravi
      }
900
    }
901
    else {
902
      if (c == '\n') {
903 50 zero_gravi
        neorv32_uart1_putc('\r');
904 2 zero_gravi
      }
905 50 zero_gravi
      neorv32_uart1_putc(c);
906 2 zero_gravi
    }
907
  }
908
  va_end(a);
909
}
910
 
911
 
912
/**********************************************************************//**
913 50 zero_gravi
 * Simplified custom version of 'scanf' function for UART1.
914 2 zero_gravi
 *
915
 * @note This function is blocking.
916
 *
917
 * @param[in,out] buffer Pointer to array of chars to store string.
918
 * @param[in] max_size Maximum number of chars to sample.
919
 * @param[in] echo Echo UART input when 1.
920
 * @return Number of chars read.
921
 **************************************************************************/
922 50 zero_gravi
int neorv32_uart1_scan(char *buffer, int max_size, int echo) {
923 2 zero_gravi
 
924
  char c = 0;
925
  int length = 0;
926
 
927
  while (1) {
928 50 zero_gravi
    c = neorv32_uart1_getc();
929 2 zero_gravi
    if (c == '\b') { // BACKSPACE
930
      if (length != 0) {
931
        if (echo) {
932 50 zero_gravi
          neorv32_uart1_print("\b \b"); // delete last char in console
933 2 zero_gravi
        }
934
        buffer--;
935
        length--;
936
      }
937
    }
938
    else if (c == '\r') // carriage return
939
      break;
940
    else if ((c >= ' ') && (c <= '~') && (length < (max_size-1))) {
941
      if (echo) {
942 50 zero_gravi
        neorv32_uart1_putc(c); // echo
943 2 zero_gravi
      }
944
      *buffer++ = c;
945
      length++;
946
    }
947
  }
948
  *buffer = '\0'; // terminate string
949
 
950
  return length;
951
}
952
 
953 50 zero_gravi
 
954
 
955
// #################################################################################################
956
// Shared functions
957
// #################################################################################################
958
 
959
/**********************************************************************//**
960
 * Private function for 'neorv32_printf' to convert into decimal.
961
 *
962
 * @param[in] x Unsigned input number.
963
 * @param[in,out] res Pointer for storing the reuslting number string (11 chars).
964
 **************************************************************************/
965
static void __neorv32_uart_itoa(uint32_t x, char *res) {
966
 
967
  static const char numbers[] = "0123456789";
968
  char buffer1[11];
969
  uint16_t i, j;
970
 
971
  buffer1[10] = '\0';
972
  res[10] = '\0';
973
 
974
  // convert
975
  for (i=0; i<10; i++) {
976
    buffer1[i] = numbers[x%10];
977
    x /= 10;
978
  }
979
 
980
  // delete 'leading' zeros
981
  for (i=9; i!=0; i--) {
982
    if (buffer1[i] == '0')
983
      buffer1[i] = '\0';
984
    else
985
      break;
986
  }
987
 
988
  // reverse
989
  j = 0;
990
  do {
991
    if (buffer1[i] != '\0')
992
      res[j++] = buffer1[i];
993
  } while (i--);
994
 
995
  res[j] = '\0'; // terminate result string
996
}
997
 
998
 
999
/**********************************************************************//**
1000
 * Private function for 'neorv32_printf' to convert into hexadecimal.
1001
 *
1002
 * @param[in] x Unsigned input number.
1003 55 zero_gravi
 * @param[in,out] res Pointer for storing the resulting number string (9 chars).
1004 50 zero_gravi
 **************************************************************************/
1005
static void __neorv32_uart_tohex(uint32_t x, char *res) {
1006
 
1007
  static const char symbols[] = "0123456789abcdef";
1008
 
1009
  int i;
1010 55 zero_gravi
  for (i=0; i<8; i++) { // nibble by nibble
1011 50 zero_gravi
    uint32_t num_tmp = x >> (4*i);
1012
    res[7-i] = (char)symbols[num_tmp & 0x0f];
1013
  }
1014
 
1015
  res[8] = '\0'; // terminate result string
1016
}

powered by: WebSVN 2.1.0

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