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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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