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

Subversion Repositories neorv32

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

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 55 zero_gravi
        default: // unsupported format
509
          neorv32_uart0_putc('%');
510
          neorv32_uart0_putc(c);
511
          break;
512 50 zero_gravi
      }
513
    }
514
    else {
515
      if (c == '\n') {
516
        neorv32_uart0_putc('\r');
517
      }
518
      neorv32_uart0_putc(c);
519
    }
520 2 zero_gravi
  }
521 50 zero_gravi
  va_end(a);
522
}
523 2 zero_gravi
 
524 50 zero_gravi
 
525
/**********************************************************************//**
526
 * Simplified custom version of 'scanf' function for UART0.
527
 *
528
 * @note This function is blocking.
529
 *
530
 * @param[in,out] buffer Pointer to array of chars to store string.
531
 * @param[in] max_size Maximum number of chars to sample.
532
 * @param[in] echo Echo UART input when 1.
533
 * @return Number of chars read.
534
 **************************************************************************/
535
int neorv32_uart0_scan(char *buffer, int max_size, int echo) {
536
 
537
  char c = 0;
538
  int length = 0;
539
 
540
  while (1) {
541
    c = neorv32_uart0_getc();
542
    if (c == '\b') { // BACKSPACE
543
      if (length != 0) {
544
        if (echo) {
545
          neorv32_uart0_print("\b \b"); // delete last char in console
546
        }
547
        buffer--;
548
        length--;
549
      }
550
    }
551
    else if (c == '\r') // carriage return
552 2 zero_gravi
      break;
553 50 zero_gravi
    else if ((c >= ' ') && (c <= '~') && (length < (max_size-1))) {
554
      if (echo) {
555
        neorv32_uart0_putc(c); // echo
556
      }
557
      *buffer++ = c;
558
      length++;
559
    }
560 2 zero_gravi
  }
561 50 zero_gravi
  *buffer = '\0'; // terminate string
562 2 zero_gravi
 
563 50 zero_gravi
  return length;
564
}
565 2 zero_gravi
 
566 50 zero_gravi
 
567
 
568
// #################################################################################################
569
// Secondary UART (UART1)
570
// #################################################################################################
571
 
572
/**********************************************************************//**
573
 * Check if UART1 unit was synthesized.
574
 *
575
 * @return 0 if UART1 was not synthesized, 1 if UART1 is available.
576
 **************************************************************************/
577
int neorv32_uart1_available(void) {
578
 
579
  if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_IO_UART1)) {
580
    return 1;
581
  }
582
  else {
583
    return 0;
584
  }
585 2 zero_gravi
}
586
 
587
 
588
/**********************************************************************//**
589 50 zero_gravi
 * Enable and configure secondary UART (UART1).
590 2 zero_gravi
 *
591 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!
592
 * @note To enable simulation mode add <USER_FLAGS+=-DUART1_SIM_MODE> when compiling.
593
 *
594
 * @warning The baud rate is computed using INTEGER operations (truncation errors might occur).
595
 *
596
 * @param[in] baudrate Targeted BAUD rate (e.g. 9600).
597 51 zero_gravi
 * @param[in] parity Parity configuration (00=off, 10=even, 11=odd), see #NEORV32_UART_PARITY_enum.
598
 * @param[in] flow_con Hardware flow control configuration (00=off, 01=RTS, 10=CTS, 11=RTS/CTS), see #NEORV32_UART_FLOW_CONTROL_enum.
599 2 zero_gravi
 **************************************************************************/
600 51 zero_gravi
void neorv32_uart1_setup(uint32_t baudrate, uint8_t parity, uint8_t flow_con) {
601 2 zero_gravi
 
602 50 zero_gravi
  UART1_CT = 0; // reset
603 2 zero_gravi
 
604 50 zero_gravi
  uint32_t clock = SYSINFO_CLK;
605
  uint16_t i = 0; // BAUD rate divisor
606
  uint8_t p = 0; // initial prsc = CLK/2
607
 
608
  // raw clock prescaler
609
#ifdef __riscv_div
610
  // use div instructions
611
  i = (uint16_t)(clock / (2*baudrate));
612
#else
613
  // division via repeated subtraction
614
  while (clock >= 2*baudrate) {
615
    clock -= 2*baudrate;
616
    i++;
617 2 zero_gravi
  }
618 50 zero_gravi
#endif
619 2 zero_gravi
 
620 50 zero_gravi
  // find baud prescaler (12-bit wide))
621
  while (i >= 0x0fff) {
622
    if ((p == 2) || (p == 4))
623
      i >>= 3;
624
    else
625
      i >>= 1;
626
    p++;
627
  }
628
 
629
  uint32_t clk_prsc = (uint32_t)p;
630
  clk_prsc = clk_prsc << UART_CT_PRSC0;
631
 
632
  uint32_t baud_prsc = (uint32_t)i;
633
  baud_prsc = baud_prsc - 1;
634
  baud_prsc = baud_prsc << UART_CT_BAUD00;
635
 
636
  uint32_t uart_en = 1;
637
  uart_en = uart_en << UART_CT_EN;
638
 
639
  uint32_t parity_config = (uint32_t)(parity & 3);
640
  parity_config = parity_config << UART_CT_PMODE0;
641
 
642 51 zero_gravi
  uint32_t flow_control = (uint32_t)(flow_con & 3);
643
  flow_control = flow_control << UART_CT_RTS_EN;
644
 
645 50 zero_gravi
  /* Enable UART1 for SIM mode. */
646
  /* USE THIS ONLY FOR SIMULATION! */
647
#ifdef UART1_SIM_MODE
648
  #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!
649
  uint32_t sim_mode = 1 << UART_CT_SIM_MODE;
650
#else
651
  uint32_t sim_mode = 0;
652
#endif
653
 
654 51 zero_gravi
  UART1_CT = clk_prsc | baud_prsc | uart_en | parity_config | sim_mode | flow_control;
655 2 zero_gravi
}
656
 
657
 
658
/**********************************************************************//**
659 50 zero_gravi
 * Disable UART1.
660
 **************************************************************************/
661
void neorv32_uart1_disable(void) {
662
 
663
  UART1_CT &= ~((uint32_t)(1 << UART_CT_EN));
664
}
665
 
666
 
667
/**********************************************************************//**
668
 * Send single char via UART1.
669 2 zero_gravi
 *
670
 * @note This function is blocking.
671
 *
672 50 zero_gravi
 * @param[in] c Char to be send.
673
 **************************************************************************/
674
void neorv32_uart1_putc(char c) {
675
 
676
#ifdef UART1_SIM_MODE
677
  UART1_DATA = ((uint32_t)c) << UART_DATA_LSB;
678
#else
679
  // wait for previous transfer to finish
680
  while ((UART1_CT & (1<<UART_CT_TX_BUSY)) != 0);
681
  UART1_DATA = ((uint32_t)c) << UART_DATA_LSB;
682
#endif
683
}
684
 
685
 
686
/**********************************************************************//**
687
 * Check if UART1 TX is busy.
688
 *
689
 * @note This function is blocking.
690
 *
691
 * @return 0 if idle, 1 if busy
692
 **************************************************************************/
693
int neorv32_uart1_tx_busy(void) {
694
 
695
  if ((UART1_CT & (1<<UART_CT_TX_BUSY)) != 0) {
696
    return 1;
697
  }
698
  return 0;
699
}
700
 
701
 
702
/**********************************************************************//**
703
 * Get char from UART1.
704
 *
705
 * @note This function is blocking and does not check for UART frame/parity errors.
706
 *
707
 * @return Received char.
708
 **************************************************************************/
709
char neorv32_uart1_getc(void) {
710
 
711
  uint32_t d = 0;
712
  while (1) {
713
    d = UART1_DATA;
714
    if ((d & (1<<UART_DATA_AVAIL)) != 0) { // char received?
715
      return (char)d;
716
    }
717
  }
718
}
719
 
720
 
721
/**********************************************************************//**
722
 * Get char from UART1 (and check errors).
723
 *
724
 * @note This function is non-blocking and checks for frame and parity errors.
725
 *
726
 * @param[in,out] data Received char.
727
 * @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).
728
 **************************************************************************/
729 51 zero_gravi
int neorv32_uart1_getc_safe(char *data) {
730 50 zero_gravi
 
731
  uint32_t uart_rx = UART1_DATA;
732
  if (uart_rx & (1<<UART_DATA_AVAIL)) { // char available at all?
733
 
734
    int status = 0;
735
 
736
    // check for frame error
737
    if (uart_rx & (1<<UART_DATA_FERR)) {
738
      status -= 1;
739
    }
740
 
741
    // check for parity error
742
    if (uart_rx & (1<<UART_DATA_PERR)) {
743
      status -= 2;
744
    }
745
 
746
    if (status == 0) {
747
      status = 1;
748
    }
749
 
750
    // get received byte
751
    *data =  (char)uart_rx;
752
 
753
    return status;
754
  }
755
  else {
756
    return 0;
757
  }
758
}
759
 
760
 
761
/**********************************************************************//**
762
 * Check if UART1 has received a char.
763
 *
764
 * @note This function is non-blocking.
765
 * @note Use neorv32_uart0_char_received_get(void) to get the char.
766
 *
767
 * @return =!0 when a char has been received.
768
 **************************************************************************/
769
int neorv32_uart1_char_received(void) {
770
 
771
  if ((UART1_DATA & (1<<UART_DATA_AVAIL)) != 0) {
772
    return 1;
773
  }
774
  else {
775
    return 0;
776
  }
777
}
778
 
779
 
780
/**********************************************************************//**
781
 * Get a received char from UART1.
782
 *
783
 * @note This function is non-blocking.
784
 * @note Should only be used in combination with neorv32_uart_char_received(void).
785
 *
786
 * @return Received char.
787
 **************************************************************************/
788
char neorv32_uart1_char_received_get(void) {
789
 
790
  return (char)UART1_DATA;
791
}
792
 
793
 
794
/**********************************************************************//**
795
 * Print string (zero-terminated) via UART1. Print full line break "\r\n" for every '\n'.
796
 *
797
 * @note This function is blocking.
798
 *
799
 * @param[in] s Pointer to string.
800
 **************************************************************************/
801
void neorv32_uart1_print(const char *s) {
802
 
803
  char c = 0;
804
  while ((c = *s++)) {
805
    if (c == '\n') {
806
      neorv32_uart1_putc('\r');
807
    }
808
    neorv32_uart1_putc(c);
809
  }
810
}
811
 
812
 
813
/**********************************************************************//**
814
 * Custom version of 'printf' function using UART1.
815
 *
816
 * @note This function is blocking.
817
 *
818 2 zero_gravi
 * @param[in] format Pointer to format string.
819
 *
820
 * <TABLE>
821
 * <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
822
 * <TR><TD>%c</TD><TD>Single char</TD></TR>
823
 * <TR><TD>%i</TD><TD>32-bit signed number, printed as decimal</TD></TR>
824
 * <TR><TD>%u</TD><TD>32-bit unsigned number, printed as decimal</TD></TR>
825
 * <TR><TD>%x</TD><TD>32-bit number, printed as 8-char hexadecimal</TD></TR>
826
 * </TABLE>
827
 **************************************************************************/
828 50 zero_gravi
void neorv32_uart1_printf(const char *format, ...) {
829 2 zero_gravi
 
830
  char c, string_buf[11];
831
  int32_t n;
832
 
833
  va_list a;
834
  va_start(a, format);
835
 
836
  while ((c = *format++)) {
837
    if (c == '%') {
838
      c = *format++;
839
      switch (c) {
840
        case 's': // string
841 50 zero_gravi
          neorv32_uart1_print(va_arg(a, char*));
842 2 zero_gravi
          break;
843
        case 'c': // char
844 50 zero_gravi
          neorv32_uart1_putc((char)va_arg(a, int));
845 2 zero_gravi
          break;
846
        case 'i': // 32-bit signed
847
          n = (int32_t)va_arg(a, int32_t);
848
          if (n < 0) {
849
            n = -n;
850 50 zero_gravi
            neorv32_uart1_putc('-');
851 2 zero_gravi
          }
852
          __neorv32_uart_itoa((uint32_t)n, string_buf);
853 50 zero_gravi
          neorv32_uart1_print(string_buf);
854 2 zero_gravi
          break;
855
        case 'u': // 32-bit unsigned
856
          __neorv32_uart_itoa(va_arg(a, uint32_t), string_buf);
857 50 zero_gravi
          neorv32_uart1_print(string_buf);
858 2 zero_gravi
          break;
859
        case 'x': // 32-bit hexadecimal
860
          __neorv32_uart_tohex(va_arg(a, uint32_t), string_buf);
861 50 zero_gravi
          neorv32_uart1_print(string_buf);
862 2 zero_gravi
          break;
863 55 zero_gravi
        default: // unsupported format
864
          neorv32_uart1_putc('%');
865
          neorv32_uart1_putc(c);
866
          break;
867 2 zero_gravi
      }
868
    }
869
    else {
870
      if (c == '\n') {
871 50 zero_gravi
        neorv32_uart1_putc('\r');
872 2 zero_gravi
      }
873 50 zero_gravi
      neorv32_uart1_putc(c);
874 2 zero_gravi
    }
875
  }
876
  va_end(a);
877
}
878
 
879
 
880
/**********************************************************************//**
881 50 zero_gravi
 * Simplified custom version of 'scanf' function for UART1.
882 2 zero_gravi
 *
883
 * @note This function is blocking.
884
 *
885
 * @param[in,out] buffer Pointer to array of chars to store string.
886
 * @param[in] max_size Maximum number of chars to sample.
887
 * @param[in] echo Echo UART input when 1.
888
 * @return Number of chars read.
889
 **************************************************************************/
890 50 zero_gravi
int neorv32_uart1_scan(char *buffer, int max_size, int echo) {
891 2 zero_gravi
 
892
  char c = 0;
893
  int length = 0;
894
 
895
  while (1) {
896 50 zero_gravi
    c = neorv32_uart1_getc();
897 2 zero_gravi
    if (c == '\b') { // BACKSPACE
898
      if (length != 0) {
899
        if (echo) {
900 50 zero_gravi
          neorv32_uart1_print("\b \b"); // delete last char in console
901 2 zero_gravi
        }
902
        buffer--;
903
        length--;
904
      }
905
    }
906
    else if (c == '\r') // carriage return
907
      break;
908
    else if ((c >= ' ') && (c <= '~') && (length < (max_size-1))) {
909
      if (echo) {
910 50 zero_gravi
        neorv32_uart1_putc(c); // echo
911 2 zero_gravi
      }
912
      *buffer++ = c;
913
      length++;
914
    }
915
  }
916
  *buffer = '\0'; // terminate string
917
 
918
  return length;
919
}
920
 
921 50 zero_gravi
 
922
 
923
// #################################################################################################
924
// Shared functions
925
// #################################################################################################
926
 
927
/**********************************************************************//**
928
 * Private function for 'neorv32_printf' to convert into decimal.
929
 *
930
 * @param[in] x Unsigned input number.
931
 * @param[in,out] res Pointer for storing the reuslting number string (11 chars).
932
 **************************************************************************/
933
static void __neorv32_uart_itoa(uint32_t x, char *res) {
934
 
935
  static const char numbers[] = "0123456789";
936
  char buffer1[11];
937
  uint16_t i, j;
938
 
939
  buffer1[10] = '\0';
940
  res[10] = '\0';
941
 
942
  // convert
943
  for (i=0; i<10; i++) {
944
    buffer1[i] = numbers[x%10];
945
    x /= 10;
946
  }
947
 
948
  // delete 'leading' zeros
949
  for (i=9; i!=0; i--) {
950
    if (buffer1[i] == '0')
951
      buffer1[i] = '\0';
952
    else
953
      break;
954
  }
955
 
956
  // reverse
957
  j = 0;
958
  do {
959
    if (buffer1[i] != '\0')
960
      res[j++] = buffer1[i];
961
  } while (i--);
962
 
963
  res[j] = '\0'; // terminate result string
964
}
965
 
966
 
967
/**********************************************************************//**
968
 * Private function for 'neorv32_printf' to convert into hexadecimal.
969
 *
970
 * @param[in] x Unsigned input number.
971 55 zero_gravi
 * @param[in,out] res Pointer for storing the resulting number string (9 chars).
972 50 zero_gravi
 **************************************************************************/
973
static void __neorv32_uart_tohex(uint32_t x, char *res) {
974
 
975
  static const char symbols[] = "0123456789abcdef";
976
 
977
  int i;
978 55 zero_gravi
  for (i=0; i<8; i++) { // nibble by nibble
979 50 zero_gravi
    uint32_t num_tmp = x >> (4*i);
980
    res[7-i] = (char)symbols[num_tmp & 0x0f];
981
  }
982
 
983
  res[8] = '\0'; // terminate result string
984
}

powered by: WebSVN 2.1.0

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