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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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