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

Subversion Repositories neorv32

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

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
 
50
/// \cond
51
// Private functions
52
static void __neorv32_uart_itoa(uint32_t x, char *res) __attribute__((unused)); // GCC: do not ouput a warning when this variable is unused
53
static void __neorv32_uart_tohex(uint32_t x, char *res) __attribute__((unused)); // GCC: do not ouput a warning when this variable is unused
54
/// \endcond
55
 
56
 
57 50 zero_gravi
 
58
// #################################################################################################
59
// Compatibility wrappers mapping to UART0 (primary UART)
60
// #################################################################################################
61
 
62 2 zero_gravi
/**********************************************************************//**
63 50 zero_gravi
 * Check if UART0 unit was synthesized.
64 2 zero_gravi
 *
65 50 zero_gravi
 * @warning This functions maps to UART0 (primary UART).
66
 *
67
 * @return 0 if UART0 was not synthesized, 1 if UART0 is available.
68 2 zero_gravi
 **************************************************************************/
69 50 zero_gravi
int neorv32_uart_available(void) { return neorv32_uart0_available(); }
70 2 zero_gravi
 
71 50 zero_gravi
 
72
/**********************************************************************//**
73
 * Enable and configure primary UART (UART0).
74
 *
75
 * @warning This functions maps to UART0 (primary UART).
76
 *
77
 * @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!
78
 * @note To enable simulation mode add <USER_FLAGS+=-DUART0_SIM_MODE> when compiling.
79
 *
80
 * @warning The baud rate is computed using INTEGER operations (truncation errors might occur).
81
 *
82
 * @param[in] baudrate Targeted BAUD rate (e.g. 9600).
83
 * @param[in] parity Parity configuration (00=off, 10=even, 11=odd).
84
 **************************************************************************/
85
void neorv32_uart_setup(uint32_t baudrate, uint8_t parity) { neorv32_uart0_setup(baudrate, parity); }
86
 
87
 
88
/**********************************************************************//**
89
 * Disable UART0.
90
 * @warning This functions maps to UART0 (primary UART).
91
 **************************************************************************/
92
void neorv32_uart_disable(void) { neorv32_uart0_disable(); }
93
 
94
 
95
/**********************************************************************//**
96
 * Send single char via UART0.
97
 *
98
 * @warning This functions maps to UART0 (primary UART).
99
 * @note This function is blocking.
100
 *
101
 * @param[in] c Char to be send.
102
 **************************************************************************/
103
void neorv32_uart_putc(char c) { neorv32_uart0_putc(c); }
104
 
105
 
106
/**********************************************************************//**
107
 * Check if UART0 TX is busy.
108
 *
109
 * @warning This functions maps to UART0 (primary UART).
110
 * @note This function is blocking.
111
 *
112
 * @return 0 if idle, 1 if busy
113
 **************************************************************************/
114
int neorv32_uart_tx_busy(void) { return neorv32_uart0_tx_busy(); }
115
 
116
 
117
/**********************************************************************//**
118
 * Get char from UART0.
119
 *
120
 * @warning This functions maps to UART0 (primary UART).
121
 * @note This function is blocking and does not check for UART frame/parity errors.
122
 *
123
 * @return Received char.
124
 **************************************************************************/
125
char neorv32_uart_getc(void) { return neorv32_uart0_getc(); }
126
 
127
 
128
/**********************************************************************//**
129
 * Check if UART0 has received a char.
130
 *
131
 * @warning This functions maps to UART0 (primary UART).
132
 * @note This function is non-blocking.
133
 * @note Use neorv32_uart0_char_received_get(void) to get the char.
134
 *
135
 * @return =!0 when a char has been received.
136
 **************************************************************************/
137
int neorv32_uart_char_received(void) { return neorv32_uart0_char_received(); }
138
 
139
 
140
/**********************************************************************//**
141
 * Get char from UART0 (and check errors).
142
 *
143
 * @warning This functions maps to UART0 (primary UART).
144
 * @note This function is non-blocking and checks for frame and parity errors.
145
 *
146
 * @param[in,out] data Received char.
147
 * @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).
148
 **************************************************************************/
149
int neorv32_uart_getc_secure(char *data) { return neorv32_uart0_getc_secure(data); }
150
 
151
 
152
/**********************************************************************//**
153
 * Get a received char from UART0.
154
 *
155
 * @warning This functions maps to UART0 (primary UART).
156
 * @note This function is non-blocking.
157
 * @note Should only be used in combination with neorv32_uart_char_received(void).
158
 *
159
 * @return Received char.
160
 **************************************************************************/
161
char neorv32_uart_char_received_get(void) { return neorv32_uart0_char_received_get(); }
162
 
163
 
164
/**********************************************************************//**
165
 * Print string (zero-terminated) via UART0. Print full line break "\r\n" for every '\n'.
166
 *
167
 * @warning This functions maps to UART0 (primary UART).
168
 * @note This function is blocking.
169
 *
170
 * @param[in] s Pointer to string.
171
 **************************************************************************/
172
void neorv32_uart_print(const char *s) { neorv32_uart0_print(s); }
173
 
174
 
175
/**********************************************************************//**
176
 * Custom version of 'printf' function using UART0.
177
 *
178
 * @warning This functions maps to UART0 (primary UART).
179
 * @note This function is blocking.
180
 *
181
 * @param[in] format Pointer to format string.
182
 *
183
 * <TABLE>
184
 * <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
185
 * <TR><TD>%c</TD><TD>Single char</TD></TR>
186
 * <TR><TD>%i</TD><TD>32-bit signed number, printed as decimal</TD></TR>
187
 * <TR><TD>%u</TD><TD>32-bit unsigned number, printed as decimal</TD></TR>
188
 * <TR><TD>%x</TD><TD>32-bit number, printed as 8-char hexadecimal</TD></TR>
189
 * </TABLE>
190
 **************************************************************************/
191
void neorv32_uart_printf(const char *format, ...) { neorv32_uart0_printf(format); }
192
 
193
 
194
/**********************************************************************//**
195
 * Simplified custom version of 'scanf' function for UART0.
196
 *
197
 * @warning This functions maps to UART0 (primary UART).
198
 * @note This function is blocking.
199
 *
200
 * @param[in,out] buffer Pointer to array of chars to store string.
201
 * @param[in] max_size Maximum number of chars to sample.
202
 * @param[in] echo Echo UART input when 1.
203
 * @return Number of chars read.
204
 **************************************************************************/
205
int neorv32_uart_scan(char *buffer, int max_size, int echo) { return neorv32_uart0_scan(buffer, max_size, echo); }
206
 
207
 
208
 
209
// #################################################################################################
210
// Primary UART (UART0)
211
// #################################################################################################
212
 
213
/**********************************************************************//**
214
 * Check if UART0 unit was synthesized.
215
 *
216
 * @return 0 if UART0 was not synthesized, 1 if UART0 is available.
217
 **************************************************************************/
218
int neorv32_uart0_available(void) {
219
 
220
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_IO_UART0)) {
221 2 zero_gravi
    return 1;
222
  }
223
  else {
224
    return 0;
225
  }
226
}
227
 
228
 
229
/**********************************************************************//**
230 50 zero_gravi
 * Enable and configure primary UART (UART0).
231 2 zero_gravi
 *
232 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!
233
 * @note To enable simulation mode add <USER_FLAGS+=-DUART0_SIM_MODE> when compiling.
234 30 zero_gravi
 *
235 47 zero_gravi
 * @warning The baud rate is computed using INTEGER operations (truncation errors might occur).
236
 *
237 2 zero_gravi
 * @param[in] baudrate Targeted BAUD rate (e.g. 9600).
238 50 zero_gravi
 * @param[in] parity Parity configuration (00=off, 10=even, 11=odd).
239 2 zero_gravi
 **************************************************************************/
240 50 zero_gravi
void neorv32_uart0_setup(uint32_t baudrate, uint8_t parity) {
241 2 zero_gravi
 
242 50 zero_gravi
  UART0_CT = 0; // reset
243 2 zero_gravi
 
244 12 zero_gravi
  uint32_t clock = SYSINFO_CLK;
245 2 zero_gravi
  uint16_t i = 0; // BAUD rate divisor
246 36 zero_gravi
  uint8_t p = 0; // initial prsc = CLK/2
247
 
248
  // raw clock prescaler
249
#ifdef __riscv_div
250
  // use div instructions
251
  i = (uint16_t)(clock / (2*baudrate));
252
#else
253
  // division via repeated subtraction
254 2 zero_gravi
  while (clock >= 2*baudrate) {
255
    clock -= 2*baudrate;
256
    i++;
257
  }
258 36 zero_gravi
#endif
259 2 zero_gravi
 
260 47 zero_gravi
  // find baud prescaler (12-bit wide))
261 2 zero_gravi
  while (i >= 0x0fff) {
262
    if ((p == 2) || (p == 4))
263
      i >>= 3;
264
    else
265
      i >>= 1;
266
    p++;
267
  }
268
 
269 47 zero_gravi
  uint32_t clk_prsc = (uint32_t)p;
270
  clk_prsc = clk_prsc << UART_CT_PRSC0;
271 2 zero_gravi
 
272 47 zero_gravi
  uint32_t baud_prsc = (uint32_t)i;
273
  baud_prsc = baud_prsc - 1;
274
  baud_prsc = baud_prsc << UART_CT_BAUD00;
275 2 zero_gravi
 
276
  uint32_t uart_en = 1;
277
  uart_en = uart_en << UART_CT_EN;
278
 
279 42 zero_gravi
  uint32_t parity_config = (uint32_t)(parity & 3);
280
  parity_config = parity_config << UART_CT_PMODE0;
281
 
282 50 zero_gravi
  /* Enable UART0 for SIM mode. */
283 42 zero_gravi
  /* USE THIS ONLY FOR SIMULATION! */
284 30 zero_gravi
#ifdef UART_SIM_MODE
285 50 zero_gravi
  #warning <UART_SIM_MODE> is obsolete (but still supported for compatibility). Please consider using the new flag <UART0_SIM_MODE>.
286
#endif
287
#if defined UART0_SIM_MODE || defined UART_SIM_MODE
288
  #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!
289 30 zero_gravi
  uint32_t sim_mode = 1 << UART_CT_SIM_MODE;
290
#else
291
  uint32_t sim_mode = 0;
292
#endif
293
 
294 50 zero_gravi
  UART0_CT = clk_prsc | baud_prsc | uart_en | parity_config | sim_mode;
295 2 zero_gravi
}
296
 
297
 
298
/**********************************************************************//**
299 50 zero_gravi
 * Disable UART0.
300 2 zero_gravi
 **************************************************************************/
301 50 zero_gravi
void neorv32_uart0_disable(void) {
302 2 zero_gravi
 
303 50 zero_gravi
  UART0_CT &= ~((uint32_t)(1 << UART_CT_EN));
304 2 zero_gravi
}
305
 
306
 
307
/**********************************************************************//**
308 50 zero_gravi
 * Send single char via UART0.
309 2 zero_gravi
 *
310
 * @note This function is blocking.
311
 *
312
 * @param[in] c Char to be send.
313
 **************************************************************************/
314 50 zero_gravi
void neorv32_uart0_putc(char c) {
315 2 zero_gravi
 
316 50 zero_gravi
#if defined UART0_SIM_MODE || defined UART_SIM_MODE
317
  UART0_DATA = ((uint32_t)c) << UART_DATA_LSB;
318 3 zero_gravi
#else
319 2 zero_gravi
  // wait for previous transfer to finish
320 50 zero_gravi
  while ((UART0_CT & (1<<UART_CT_TX_BUSY)) != 0);
321
  UART0_DATA = ((uint32_t)c) << UART_DATA_LSB;
322 3 zero_gravi
#endif
323 2 zero_gravi
}
324
 
325
 
326
/**********************************************************************//**
327 50 zero_gravi
 * Check if UART0 TX is busy.
328 23 zero_gravi
 *
329
 * @note This function is blocking.
330
 *
331
 * @return 0 if idle, 1 if busy
332
 **************************************************************************/
333 50 zero_gravi
int neorv32_uart0_tx_busy(void) {
334 23 zero_gravi
 
335 50 zero_gravi
  if ((UART0_CT & (1<<UART_CT_TX_BUSY)) != 0) {
336 23 zero_gravi
    return 1;
337
  }
338
  return 0;
339
}
340
 
341
 
342
/**********************************************************************//**
343 50 zero_gravi
 * Get char from UART0.
344 2 zero_gravi
 *
345 42 zero_gravi
 * @note This function is blocking and does not check for UART frame/parity errors.
346 2 zero_gravi
 *
347
 * @return Received char.
348
 **************************************************************************/
349 50 zero_gravi
char neorv32_uart0_getc(void) {
350 2 zero_gravi
 
351
  uint32_t d = 0;
352
  while (1) {
353 50 zero_gravi
    d = UART0_DATA;
354 2 zero_gravi
    if ((d & (1<<UART_DATA_AVAIL)) != 0) { // char received?
355
      return (char)d;
356
    }
357
  }
358
}
359
 
360
 
361
/**********************************************************************//**
362 50 zero_gravi
 * Get char from UART0 (and check errors).
363 2 zero_gravi
 *
364 42 zero_gravi
 * @note This function is non-blocking and checks for frame and parity errors.
365
 *
366
 * @param[in,out] data Received char.
367
 * @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).
368
 **************************************************************************/
369 50 zero_gravi
int neorv32_uart0_getc_secure(char *data) {
370 42 zero_gravi
 
371 50 zero_gravi
  uint32_t uart_rx = UART0_DATA;
372 42 zero_gravi
  if (uart_rx & (1<<UART_DATA_AVAIL)) { // char available at all?
373
 
374
    int status = 0;
375
 
376
    // check for frame error
377
    if (uart_rx & (1<<UART_DATA_FERR)) {
378
      status -= 1;
379
    }
380
 
381
    // check for parity error
382
    if (uart_rx & (1<<UART_DATA_PERR)) {
383
      status -= 2;
384
    }
385
 
386
    if (status == 0) {
387
      status = 1;
388
    }
389
 
390
    // get received byte
391
    *data =  (char)uart_rx;
392
 
393
    return status;
394
  }
395
  else {
396
    return 0;
397
  }
398
}
399
 
400
 
401
/**********************************************************************//**
402 50 zero_gravi
 * Check if UART0 has received a char.
403 42 zero_gravi
 *
404 2 zero_gravi
 * @note This function is non-blocking.
405 50 zero_gravi
 * @note Use neorv32_uart0_char_received_get(void) to get the char.
406 2 zero_gravi
 *
407
 * @return =!0 when a char has been received.
408
 **************************************************************************/
409 50 zero_gravi
int neorv32_uart0_char_received(void) {
410 2 zero_gravi
 
411 50 zero_gravi
  if ((UART0_DATA & (1<<UART_DATA_AVAIL)) != 0) {
412 2 zero_gravi
    return 1;
413
  }
414
  else {
415
    return 0;
416
  }
417
}
418
 
419
 
420
/**********************************************************************//**
421 50 zero_gravi
 * Get a received char from UART0.
422 2 zero_gravi
 *
423
 * @note This function is non-blocking.
424
 * @note Should only be used in combination with neorv32_uart_char_received(void).
425
 *
426
 * @return Received char.
427
 **************************************************************************/
428 50 zero_gravi
char neorv32_uart0_char_received_get(void) {
429 2 zero_gravi
 
430 50 zero_gravi
  return (char)UART0_DATA;
431 2 zero_gravi
}
432
 
433
 
434
/**********************************************************************//**
435 50 zero_gravi
 * Print string (zero-terminated) via UART0. Print full line break "\r\n" for every '\n'.
436 2 zero_gravi
 *
437
 * @note This function is blocking.
438
 *
439
 * @param[in] s Pointer to string.
440
 **************************************************************************/
441 50 zero_gravi
void neorv32_uart0_print(const char *s) {
442 2 zero_gravi
 
443
  char c = 0;
444
  while ((c = *s++)) {
445
    if (c == '\n') {
446 50 zero_gravi
      neorv32_uart0_putc('\r');
447 2 zero_gravi
    }
448 50 zero_gravi
    neorv32_uart0_putc(c);
449 2 zero_gravi
  }
450
}
451
 
452
 
453
/**********************************************************************//**
454 50 zero_gravi
 * Custom version of 'printf' function using UART0.
455 2 zero_gravi
 *
456 50 zero_gravi
 * @note This function is blocking.
457
 *
458
 * @param[in] format Pointer to format string.
459
 *
460
 * <TABLE>
461
 * <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
462
 * <TR><TD>%c</TD><TD>Single char</TD></TR>
463
 * <TR><TD>%i</TD><TD>32-bit signed number, printed as decimal</TD></TR>
464
 * <TR><TD>%u</TD><TD>32-bit unsigned number, printed as decimal</TD></TR>
465
 * <TR><TD>%x</TD><TD>32-bit number, printed as 8-char hexadecimal</TD></TR>
466
 * </TABLE>
467 2 zero_gravi
 **************************************************************************/
468 50 zero_gravi
void neorv32_uart0_printf(const char *format, ...) {
469 2 zero_gravi
 
470 50 zero_gravi
  char c, string_buf[11];
471
  int32_t n;
472 2 zero_gravi
 
473 50 zero_gravi
  va_list a;
474
  va_start(a, format);
475 2 zero_gravi
 
476 50 zero_gravi
  while ((c = *format++)) {
477
    if (c == '%') {
478
      c = *format++;
479
      switch (c) {
480
        case 's': // string
481
          neorv32_uart0_print(va_arg(a, char*));
482
          break;
483
        case 'c': // char
484
          neorv32_uart0_putc((char)va_arg(a, int));
485
          break;
486
        case 'i': // 32-bit signed
487
          n = (int32_t)va_arg(a, int32_t);
488
          if (n < 0) {
489
            n = -n;
490
            neorv32_uart0_putc('-');
491
          }
492
          __neorv32_uart_itoa((uint32_t)n, string_buf);
493
          neorv32_uart0_print(string_buf);
494
          break;
495
        case 'u': // 32-bit unsigned
496
          __neorv32_uart_itoa(va_arg(a, uint32_t), string_buf);
497
          neorv32_uart0_print(string_buf);
498
          break;
499
        case 'x': // 32-bit hexadecimal
500
          __neorv32_uart_tohex(va_arg(a, uint32_t), string_buf);
501
          neorv32_uart0_print(string_buf);
502
          break;
503
        default:
504
          return;
505
      }
506
    }
507
    else {
508
      if (c == '\n') {
509
        neorv32_uart0_putc('\r');
510
      }
511
      neorv32_uart0_putc(c);
512
    }
513 2 zero_gravi
  }
514 50 zero_gravi
  va_end(a);
515
}
516 2 zero_gravi
 
517 50 zero_gravi
 
518
/**********************************************************************//**
519
 * Simplified custom version of 'scanf' function for UART0.
520
 *
521
 * @note This function is blocking.
522
 *
523
 * @param[in,out] buffer Pointer to array of chars to store string.
524
 * @param[in] max_size Maximum number of chars to sample.
525
 * @param[in] echo Echo UART input when 1.
526
 * @return Number of chars read.
527
 **************************************************************************/
528
int neorv32_uart0_scan(char *buffer, int max_size, int echo) {
529
 
530
  char c = 0;
531
  int length = 0;
532
 
533
  while (1) {
534
    c = neorv32_uart0_getc();
535
    if (c == '\b') { // BACKSPACE
536
      if (length != 0) {
537
        if (echo) {
538
          neorv32_uart0_print("\b \b"); // delete last char in console
539
        }
540
        buffer--;
541
        length--;
542
      }
543
    }
544
    else if (c == '\r') // carriage return
545 2 zero_gravi
      break;
546 50 zero_gravi
    else if ((c >= ' ') && (c <= '~') && (length < (max_size-1))) {
547
      if (echo) {
548
        neorv32_uart0_putc(c); // echo
549
      }
550
      *buffer++ = c;
551
      length++;
552
    }
553 2 zero_gravi
  }
554 50 zero_gravi
  *buffer = '\0'; // terminate string
555 2 zero_gravi
 
556 50 zero_gravi
  return length;
557
}
558 2 zero_gravi
 
559 50 zero_gravi
 
560
 
561
// #################################################################################################
562
// Secondary UART (UART1)
563
// #################################################################################################
564
 
565
/**********************************************************************//**
566
 * Check if UART1 unit was synthesized.
567
 *
568
 * @return 0 if UART1 was not synthesized, 1 if UART1 is available.
569
 **************************************************************************/
570
int neorv32_uart1_available(void) {
571
 
572
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_IO_UART1)) {
573
    return 1;
574
  }
575
  else {
576
    return 0;
577
  }
578 2 zero_gravi
}
579
 
580
 
581
/**********************************************************************//**
582 50 zero_gravi
 * Enable and configure secondary UART (UART1).
583 2 zero_gravi
 *
584 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!
585
 * @note To enable simulation mode add <USER_FLAGS+=-DUART1_SIM_MODE> when compiling.
586
 *
587
 * @warning The baud rate is computed using INTEGER operations (truncation errors might occur).
588
 *
589
 * @param[in] baudrate Targeted BAUD rate (e.g. 9600).
590
 * @param[in] parity Parity configuration (00=off, 10=even, 11=odd).
591 2 zero_gravi
 **************************************************************************/
592 50 zero_gravi
void neorv32_uart1_setup(uint32_t baudrate, uint8_t parity) {
593 2 zero_gravi
 
594 50 zero_gravi
  UART1_CT = 0; // reset
595 2 zero_gravi
 
596 50 zero_gravi
  uint32_t clock = SYSINFO_CLK;
597
  uint16_t i = 0; // BAUD rate divisor
598
  uint8_t p = 0; // initial prsc = CLK/2
599
 
600
  // raw clock prescaler
601
#ifdef __riscv_div
602
  // use div instructions
603
  i = (uint16_t)(clock / (2*baudrate));
604
#else
605
  // division via repeated subtraction
606
  while (clock >= 2*baudrate) {
607
    clock -= 2*baudrate;
608
    i++;
609 2 zero_gravi
  }
610 50 zero_gravi
#endif
611 2 zero_gravi
 
612 50 zero_gravi
  // find baud prescaler (12-bit wide))
613
  while (i >= 0x0fff) {
614
    if ((p == 2) || (p == 4))
615
      i >>= 3;
616
    else
617
      i >>= 1;
618
    p++;
619
  }
620
 
621
  uint32_t clk_prsc = (uint32_t)p;
622
  clk_prsc = clk_prsc << UART_CT_PRSC0;
623
 
624
  uint32_t baud_prsc = (uint32_t)i;
625
  baud_prsc = baud_prsc - 1;
626
  baud_prsc = baud_prsc << UART_CT_BAUD00;
627
 
628
  uint32_t uart_en = 1;
629
  uart_en = uart_en << UART_CT_EN;
630
 
631
  uint32_t parity_config = (uint32_t)(parity & 3);
632
  parity_config = parity_config << UART_CT_PMODE0;
633
 
634
  /* Enable UART1 for SIM mode. */
635
  /* USE THIS ONLY FOR SIMULATION! */
636
#ifdef UART1_SIM_MODE
637
  #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!
638
  uint32_t sim_mode = 1 << UART_CT_SIM_MODE;
639
#else
640
  uint32_t sim_mode = 0;
641
#endif
642
 
643
  UART1_CT = clk_prsc | baud_prsc | uart_en | parity_config | sim_mode;
644 2 zero_gravi
}
645
 
646
 
647
/**********************************************************************//**
648 50 zero_gravi
 * Disable UART1.
649
 **************************************************************************/
650
void neorv32_uart1_disable(void) {
651
 
652
  UART1_CT &= ~((uint32_t)(1 << UART_CT_EN));
653
}
654
 
655
 
656
/**********************************************************************//**
657
 * Send single char via UART1.
658 2 zero_gravi
 *
659
 * @note This function is blocking.
660
 *
661 50 zero_gravi
 * @param[in] c Char to be send.
662
 **************************************************************************/
663
void neorv32_uart1_putc(char c) {
664
 
665
#ifdef UART1_SIM_MODE
666
  UART1_DATA = ((uint32_t)c) << UART_DATA_LSB;
667
#else
668
  // wait for previous transfer to finish
669
  while ((UART1_CT & (1<<UART_CT_TX_BUSY)) != 0);
670
  UART1_DATA = ((uint32_t)c) << UART_DATA_LSB;
671
#endif
672
}
673
 
674
 
675
/**********************************************************************//**
676
 * Check if UART1 TX is busy.
677
 *
678
 * @note This function is blocking.
679
 *
680
 * @return 0 if idle, 1 if busy
681
 **************************************************************************/
682
int neorv32_uart1_tx_busy(void) {
683
 
684
  if ((UART1_CT & (1<<UART_CT_TX_BUSY)) != 0) {
685
    return 1;
686
  }
687
  return 0;
688
}
689
 
690
 
691
/**********************************************************************//**
692
 * Get char from UART1.
693
 *
694
 * @note This function is blocking and does not check for UART frame/parity errors.
695
 *
696
 * @return Received char.
697
 **************************************************************************/
698
char neorv32_uart1_getc(void) {
699
 
700
  uint32_t d = 0;
701
  while (1) {
702
    d = UART1_DATA;
703
    if ((d & (1<<UART_DATA_AVAIL)) != 0) { // char received?
704
      return (char)d;
705
    }
706
  }
707
}
708
 
709
 
710
/**********************************************************************//**
711
 * Get char from UART1 (and check errors).
712
 *
713
 * @note This function is non-blocking and checks for frame and parity errors.
714
 *
715
 * @param[in,out] data Received char.
716
 * @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).
717
 **************************************************************************/
718
int neorv32_uart1_getc_secure(char *data) {
719
 
720
  uint32_t uart_rx = UART1_DATA;
721
  if (uart_rx & (1<<UART_DATA_AVAIL)) { // char available at all?
722
 
723
    int status = 0;
724
 
725
    // check for frame error
726
    if (uart_rx & (1<<UART_DATA_FERR)) {
727
      status -= 1;
728
    }
729
 
730
    // check for parity error
731
    if (uart_rx & (1<<UART_DATA_PERR)) {
732
      status -= 2;
733
    }
734
 
735
    if (status == 0) {
736
      status = 1;
737
    }
738
 
739
    // get received byte
740
    *data =  (char)uart_rx;
741
 
742
    return status;
743
  }
744
  else {
745
    return 0;
746
  }
747
}
748
 
749
 
750
/**********************************************************************//**
751
 * Check if UART1 has received a char.
752
 *
753
 * @note This function is non-blocking.
754
 * @note Use neorv32_uart0_char_received_get(void) to get the char.
755
 *
756
 * @return =!0 when a char has been received.
757
 **************************************************************************/
758
int neorv32_uart1_char_received(void) {
759
 
760
  if ((UART1_DATA & (1<<UART_DATA_AVAIL)) != 0) {
761
    return 1;
762
  }
763
  else {
764
    return 0;
765
  }
766
}
767
 
768
 
769
/**********************************************************************//**
770
 * Get a received char from UART1.
771
 *
772
 * @note This function is non-blocking.
773
 * @note Should only be used in combination with neorv32_uart_char_received(void).
774
 *
775
 * @return Received char.
776
 **************************************************************************/
777
char neorv32_uart1_char_received_get(void) {
778
 
779
  return (char)UART1_DATA;
780
}
781
 
782
 
783
/**********************************************************************//**
784
 * Print string (zero-terminated) via UART1. Print full line break "\r\n" for every '\n'.
785
 *
786
 * @note This function is blocking.
787
 *
788
 * @param[in] s Pointer to string.
789
 **************************************************************************/
790
void neorv32_uart1_print(const char *s) {
791
 
792
  char c = 0;
793
  while ((c = *s++)) {
794
    if (c == '\n') {
795
      neorv32_uart1_putc('\r');
796
    }
797
    neorv32_uart1_putc(c);
798
  }
799
}
800
 
801
 
802
/**********************************************************************//**
803
 * Custom version of 'printf' function using UART1.
804
 *
805
 * @note This function is blocking.
806
 *
807 2 zero_gravi
 * @param[in] format Pointer to format string.
808
 *
809
 * <TABLE>
810
 * <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
811
 * <TR><TD>%c</TD><TD>Single char</TD></TR>
812
 * <TR><TD>%i</TD><TD>32-bit signed number, printed as decimal</TD></TR>
813
 * <TR><TD>%u</TD><TD>32-bit unsigned number, printed as decimal</TD></TR>
814
 * <TR><TD>%x</TD><TD>32-bit number, printed as 8-char hexadecimal</TD></TR>
815
 * </TABLE>
816
 **************************************************************************/
817 50 zero_gravi
void neorv32_uart1_printf(const char *format, ...) {
818 2 zero_gravi
 
819
  char c, string_buf[11];
820
  int32_t n;
821
 
822
  va_list a;
823
  va_start(a, format);
824
 
825
  while ((c = *format++)) {
826
    if (c == '%') {
827
      c = *format++;
828
      switch (c) {
829
        case 's': // string
830 50 zero_gravi
          neorv32_uart1_print(va_arg(a, char*));
831 2 zero_gravi
          break;
832
        case 'c': // char
833 50 zero_gravi
          neorv32_uart1_putc((char)va_arg(a, int));
834 2 zero_gravi
          break;
835
        case 'i': // 32-bit signed
836
          n = (int32_t)va_arg(a, int32_t);
837
          if (n < 0) {
838
            n = -n;
839 50 zero_gravi
            neorv32_uart1_putc('-');
840 2 zero_gravi
          }
841
          __neorv32_uart_itoa((uint32_t)n, string_buf);
842 50 zero_gravi
          neorv32_uart1_print(string_buf);
843 2 zero_gravi
          break;
844
        case 'u': // 32-bit unsigned
845
          __neorv32_uart_itoa(va_arg(a, uint32_t), string_buf);
846 50 zero_gravi
          neorv32_uart1_print(string_buf);
847 2 zero_gravi
          break;
848
        case 'x': // 32-bit hexadecimal
849
          __neorv32_uart_tohex(va_arg(a, uint32_t), string_buf);
850 50 zero_gravi
          neorv32_uart1_print(string_buf);
851 2 zero_gravi
          break;
852
        default:
853
          return;
854
      }
855
    }
856
    else {
857
      if (c == '\n') {
858 50 zero_gravi
        neorv32_uart1_putc('\r');
859 2 zero_gravi
      }
860 50 zero_gravi
      neorv32_uart1_putc(c);
861 2 zero_gravi
    }
862
  }
863
  va_end(a);
864
}
865
 
866
 
867
/**********************************************************************//**
868 50 zero_gravi
 * Simplified custom version of 'scanf' function for UART1.
869 2 zero_gravi
 *
870
 * @note This function is blocking.
871
 *
872
 * @param[in,out] buffer Pointer to array of chars to store string.
873
 * @param[in] max_size Maximum number of chars to sample.
874
 * @param[in] echo Echo UART input when 1.
875
 * @return Number of chars read.
876
 **************************************************************************/
877 50 zero_gravi
int neorv32_uart1_scan(char *buffer, int max_size, int echo) {
878 2 zero_gravi
 
879
  char c = 0;
880
  int length = 0;
881
 
882
  while (1) {
883 50 zero_gravi
    c = neorv32_uart1_getc();
884 2 zero_gravi
    if (c == '\b') { // BACKSPACE
885
      if (length != 0) {
886
        if (echo) {
887 50 zero_gravi
          neorv32_uart1_print("\b \b"); // delete last char in console
888 2 zero_gravi
        }
889
        buffer--;
890
        length--;
891
      }
892
    }
893
    else if (c == '\r') // carriage return
894
      break;
895
    else if ((c >= ' ') && (c <= '~') && (length < (max_size-1))) {
896
      if (echo) {
897 50 zero_gravi
        neorv32_uart1_putc(c); // echo
898 2 zero_gravi
      }
899
      *buffer++ = c;
900
      length++;
901
    }
902
  }
903
  *buffer = '\0'; // terminate string
904
 
905
  return length;
906
}
907
 
908 50 zero_gravi
 
909
 
910
// #################################################################################################
911
// Shared functions
912
// #################################################################################################
913
 
914
/**********************************************************************//**
915
 * Private function for 'neorv32_printf' to convert into decimal.
916
 *
917
 * @param[in] x Unsigned input number.
918
 * @param[in,out] res Pointer for storing the reuslting number string (11 chars).
919
 **************************************************************************/
920
static void __neorv32_uart_itoa(uint32_t x, char *res) {
921
 
922
  static const char numbers[] = "0123456789";
923
  char buffer1[11];
924
  uint16_t i, j;
925
 
926
  buffer1[10] = '\0';
927
  res[10] = '\0';
928
 
929
  // convert
930
  for (i=0; i<10; i++) {
931
    buffer1[i] = numbers[x%10];
932
    x /= 10;
933
  }
934
 
935
  // delete 'leading' zeros
936
  for (i=9; i!=0; i--) {
937
    if (buffer1[i] == '0')
938
      buffer1[i] = '\0';
939
    else
940
      break;
941
  }
942
 
943
  // reverse
944
  j = 0;
945
  do {
946
    if (buffer1[i] != '\0')
947
      res[j++] = buffer1[i];
948
  } while (i--);
949
 
950
  res[j] = '\0'; // terminate result string
951
}
952
 
953
 
954
/**********************************************************************//**
955
 * Private function for 'neorv32_printf' to convert into hexadecimal.
956
 *
957
 * @param[in] x Unsigned input number.
958
 * @param[in,out] res Pointer for storing the reuslting number string (9 chars).
959
 **************************************************************************/
960
static void __neorv32_uart_tohex(uint32_t x, char *res) {
961
 
962
  static const char symbols[] = "0123456789abcdef";
963
 
964
  int i;
965
  for (i=0; i<8; i++) { // nibble by bibble
966
    uint32_t num_tmp = x >> (4*i);
967
    res[7-i] = (char)symbols[num_tmp & 0x0f];
968
  }
969
 
970
  res[8] = '\0'; // terminate result string
971
}

powered by: WebSVN 2.1.0

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