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

Subversion Repositories neorv32

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

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 zero_gravi
// #################################################################################################
2
// # << NEORV32: neorv32_uart.c - Universal Asynchronous Receiver/Transmitter (UART) HW Driver >>  #
3
// # ********************************************************************************************* #
4
// # BSD 3-Clause License                                                                          #
5
// #                                                                                               #
6 44 zero_gravi
// # Copyright (c) 2021, Stephan Nolting. All rights reserved.                                     #
7 2 zero_gravi
// #                                                                                               #
8
// # Redistribution and use in source and binary forms, with or without modification, are          #
9
// # permitted provided that the following conditions are met:                                     #
10
// #                                                                                               #
11
// # 1. Redistributions of source code must retain the above copyright notice, this list of        #
12
// #    conditions and the following disclaimer.                                                   #
13
// #                                                                                               #
14
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
15
// #    conditions and the following disclaimer in the documentation and/or other materials        #
16
// #    provided with the distribution.                                                            #
17
// #                                                                                               #
18
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
19
// #    endorse or promote products derived from this software without specific prior written      #
20
// #    permission.                                                                                #
21
// #                                                                                               #
22
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
23
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
24
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
25
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
26
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
27
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
28
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
29
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
30
// # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
31
// # ********************************************************************************************* #
32
// # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
33
// #################################################################################################
34
 
35
 
36
/**********************************************************************//**
37
 * @file neorv32_uart.c
38
 * @author Stephan Nolting
39 50 zero_gravi
 * @brief Universal asynchronous receiver/transmitter (UART0/UART1) HW driver source file.
40 2 zero_gravi
 *
41 50 zero_gravi
 * @warning UART0 (primary UART) is used as default user console interface for all NEORV32 software framework/library functions.
42
 *
43
 * @note These functions should only be used if the UART0/UART1 unit was synthesized (IO_UART0_EN = true / IO_UART1_EN = true).
44 2 zero_gravi
 **************************************************************************/
45
 
46
#include "neorv32.h"
47
#include "neorv32_uart.h"
48
#include <string.h>
49 61 zero_gravi
#include <stdarg.h>
50 2 zero_gravi
 
51
/// \cond
52
// Private functions
53 65 zero_gravi
static void __neorv32_uart_itoa(uint32_t x, char *res) __attribute__((unused)); // GCC: do not output a warning when this variable is unused
54
static void __neorv32_uart_tohex(uint32_t x, char *res) __attribute__((unused)); // GCC: do not output a warning when this variable is unused
55 2 zero_gravi
/// \endcond
56
 
57
 
58 50 zero_gravi
// #################################################################################################
59
// Primary UART (UART0)
60
// #################################################################################################
61
 
62
/**********************************************************************//**
63
 * Check if UART0 unit was synthesized.
64
 *
65
 * @return 0 if UART0 was not synthesized, 1 if UART0 is available.
66
 **************************************************************************/
67
int neorv32_uart0_available(void) {
68
 
69 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_IO_UART0)) {
70 2 zero_gravi
    return 1;
71
  }
72
  else {
73
    return 0;
74
  }
75
}
76
 
77
 
78
/**********************************************************************//**
79 50 zero_gravi
 * Enable and configure primary UART (UART0).
80 2 zero_gravi
 *
81 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!
82
 * @note To enable simulation mode add <USER_FLAGS+=-DUART0_SIM_MODE> when compiling.
83 30 zero_gravi
 *
84 47 zero_gravi
 * @warning The baud rate is computed using INTEGER operations (truncation errors might occur).
85
 *
86 2 zero_gravi
 * @param[in] baudrate Targeted BAUD rate (e.g. 9600).
87 51 zero_gravi
 * @param[in] parity Parity configuration (00=off, 10=even, 11=odd), see #NEORV32_UART_PARITY_enum.
88
 * @param[in] flow_con Hardware flow control configuration (00=off, 01=RTS, 10=CTS, 11=RTS/CTS), see #NEORV32_UART_FLOW_CONTROL_enum.
89 2 zero_gravi
 **************************************************************************/
90 51 zero_gravi
void neorv32_uart0_setup(uint32_t baudrate, uint8_t parity, uint8_t flow_con) {
91 2 zero_gravi
 
92 64 zero_gravi
  NEORV32_UART0.CTRL = 0; // reset
93 2 zero_gravi
 
94 64 zero_gravi
  uint32_t clock = NEORV32_SYSINFO.CLK;
95 2 zero_gravi
  uint16_t i = 0; // BAUD rate divisor
96 36 zero_gravi
  uint8_t p = 0; // initial prsc = CLK/2
97
 
98
  // raw clock prescaler
99 66 zero_gravi
#ifndef make_bootloader
100 36 zero_gravi
  i = (uint16_t)(clock / (2*baudrate));
101
#else
102 66 zero_gravi
  // division via repeated subtraction (minimal size, only for bootloader)
103 2 zero_gravi
  while (clock >= 2*baudrate) {
104
    clock -= 2*baudrate;
105
    i++;
106
  }
107 36 zero_gravi
#endif
108 2 zero_gravi
 
109 47 zero_gravi
  // find baud prescaler (12-bit wide))
110 2 zero_gravi
  while (i >= 0x0fff) {
111
    if ((p == 2) || (p == 4))
112
      i >>= 3;
113
    else
114
      i >>= 1;
115
    p++;
116
  }
117
 
118 47 zero_gravi
  uint32_t clk_prsc = (uint32_t)p;
119 64 zero_gravi
  clk_prsc = clk_prsc << UART_CTRL_PRSC0;
120 2 zero_gravi
 
121 47 zero_gravi
  uint32_t baud_prsc = (uint32_t)i;
122
  baud_prsc = baud_prsc - 1;
123 64 zero_gravi
  baud_prsc = baud_prsc << UART_CTRL_BAUD00;
124 2 zero_gravi
 
125
  uint32_t uart_en = 1;
126 64 zero_gravi
  uart_en = uart_en << UART_CTRL_EN;
127 2 zero_gravi
 
128 42 zero_gravi
  uint32_t parity_config = (uint32_t)(parity & 3);
129 64 zero_gravi
  parity_config = parity_config << UART_CTRL_PMODE0;
130 42 zero_gravi
 
131 51 zero_gravi
  uint32_t flow_control = (uint32_t)(flow_con & 3);
132 64 zero_gravi
  flow_control = flow_control << UART_CTRL_RTS_EN;
133 51 zero_gravi
 
134 50 zero_gravi
  /* Enable UART0 for SIM mode. */
135 42 zero_gravi
  /* USE THIS ONLY FOR SIMULATION! */
136 30 zero_gravi
#ifdef UART_SIM_MODE
137 50 zero_gravi
  #warning <UART_SIM_MODE> is obsolete (but still supported for compatibility). Please consider using the new flag <UART0_SIM_MODE>.
138
#endif
139
#if defined UART0_SIM_MODE || defined UART_SIM_MODE
140
  #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!
141 64 zero_gravi
  uint32_t sim_mode = 1 << UART_CTRL_SIM_MODE;
142 30 zero_gravi
#else
143
  uint32_t sim_mode = 0;
144
#endif
145
 
146 64 zero_gravi
  NEORV32_UART0.CTRL = clk_prsc | baud_prsc | uart_en | parity_config | sim_mode | flow_control;
147 2 zero_gravi
}
148
 
149
 
150
/**********************************************************************//**
151 50 zero_gravi
 * Disable UART0.
152 2 zero_gravi
 **************************************************************************/
153 50 zero_gravi
void neorv32_uart0_disable(void) {
154 2 zero_gravi
 
155 64 zero_gravi
  NEORV32_UART0.CTRL &= ~((uint32_t)(1 << UART_CTRL_EN));
156 2 zero_gravi
}
157
 
158
 
159
/**********************************************************************//**
160 61 zero_gravi
 * Enable UART0.
161
 **************************************************************************/
162
void neorv32_uart0_enable(void) {
163
 
164 69 zero_gravi
  NEORV32_UART0.CTRL |= ((uint32_t)(1 << UART_CTRL_EN));
165 61 zero_gravi
}
166
 
167
 
168
/**********************************************************************//**
169 50 zero_gravi
 * Send single char via UART0.
170 2 zero_gravi
 *
171
 * @note This function is blocking.
172
 *
173
 * @param[in] c Char to be send.
174
 **************************************************************************/
175 50 zero_gravi
void neorv32_uart0_putc(char c) {
176 2 zero_gravi
 
177
  // wait for previous transfer to finish
178 65 zero_gravi
  while ((NEORV32_UART0.CTRL & (1<<UART_CTRL_TX_FULL)) != 0); // wait for space in TX FIFO
179 64 zero_gravi
  NEORV32_UART0.DATA = ((uint32_t)c) << UART_DATA_LSB;
180 2 zero_gravi
}
181
 
182
 
183
/**********************************************************************//**
184 65 zero_gravi
 * Check if UART0 TX is busy (transmitter busy or data left in TX buffer).
185 23 zero_gravi
 *
186
 * @note This function is blocking.
187
 *
188
 * @return 0 if idle, 1 if busy
189
 **************************************************************************/
190 50 zero_gravi
int neorv32_uart0_tx_busy(void) {
191 23 zero_gravi
 
192 65 zero_gravi
  uint32_t ctrl = NEORV32_UART0.CTRL;
193
 
194
  if (((ctrl & (1<<UART_CTRL_TX_BUSY)) != 0) ||  // TX engine busy
195
      ((ctrl & (1<<UART_CTRL_TX_EMPTY)) == 0)) { // TX buffer not empty
196 23 zero_gravi
    return 1;
197
  }
198
  return 0;
199
}
200
 
201
 
202
/**********************************************************************//**
203 50 zero_gravi
 * Get char from UART0.
204 2 zero_gravi
 *
205 42 zero_gravi
 * @note This function is blocking and does not check for UART frame/parity errors.
206 2 zero_gravi
 *
207
 * @return Received char.
208
 **************************************************************************/
209 50 zero_gravi
char neorv32_uart0_getc(void) {
210 2 zero_gravi
 
211
  uint32_t d = 0;
212
  while (1) {
213 64 zero_gravi
    d = NEORV32_UART0.DATA;
214 2 zero_gravi
    if ((d & (1<<UART_DATA_AVAIL)) != 0) { // char received?
215
      return (char)d;
216
    }
217
  }
218
}
219
 
220
 
221
/**********************************************************************//**
222 50 zero_gravi
 * Get char from UART0 (and check errors).
223 2 zero_gravi
 *
224 42 zero_gravi
 * @note This function is non-blocking and checks for frame and parity errors.
225
 *
226
 * @param[in,out] data Received char.
227 65 zero_gravi
 * @return Status code:
228
 *  0 = char received without errors
229
 * -1 = nothing received
230
 * -2 = char received with frame error
231
 * -3 = char received with parity error
232
 * -4 = char received with overrun error.
233 42 zero_gravi
 **************************************************************************/
234 51 zero_gravi
int neorv32_uart0_getc_safe(char *data) {
235 42 zero_gravi
 
236 64 zero_gravi
  uint32_t uart_rx = NEORV32_UART0.DATA;
237 42 zero_gravi
 
238 65 zero_gravi
  // get received byte (if there is any)
239
  *data = (char)uart_rx;
240 42 zero_gravi
 
241 65 zero_gravi
  // check if no data available at all
242
  if ((uart_rx & (1<<UART_DATA_AVAIL)) == 0) {
243
   return -1;
244
  }
245 42 zero_gravi
 
246 65 zero_gravi
  // check for frame error
247
  if (uart_rx & (1<<UART_DATA_FERR)) {
248
    return -2;
249
  }
250 42 zero_gravi
 
251 65 zero_gravi
  // check for parity error
252
  if (uart_rx & (1<<UART_DATA_PERR)) {
253
    return -3;
254
  }
255 42 zero_gravi
 
256 65 zero_gravi
  // check for overrun error
257
  if (uart_rx & (1<<UART_DATA_OVERR)) {
258
    return -4;
259
  }
260 42 zero_gravi
 
261 65 zero_gravi
  return 0; // all fine
262 42 zero_gravi
}
263
 
264
 
265
/**********************************************************************//**
266 50 zero_gravi
 * Check if UART0 has received a char.
267 42 zero_gravi
 *
268 2 zero_gravi
 * @note This function is non-blocking.
269 50 zero_gravi
 * @note Use neorv32_uart0_char_received_get(void) to get the char.
270 2 zero_gravi
 *
271
 * @return =!0 when a char has been received.
272
 **************************************************************************/
273 50 zero_gravi
int neorv32_uart0_char_received(void) {
274 2 zero_gravi
 
275 64 zero_gravi
  if ((NEORV32_UART0.DATA & (1<<UART_DATA_AVAIL)) != 0) {
276 2 zero_gravi
    return 1;
277
  }
278
  else {
279
    return 0;
280
  }
281
}
282
 
283
 
284
/**********************************************************************//**
285 50 zero_gravi
 * Get a received char from UART0.
286 2 zero_gravi
 *
287
 * @note This function is non-blocking.
288
 * @note Should only be used in combination with neorv32_uart_char_received(void).
289
 *
290
 * @return Received char.
291
 **************************************************************************/
292 50 zero_gravi
char neorv32_uart0_char_received_get(void) {
293 2 zero_gravi
 
294 64 zero_gravi
  return (char)NEORV32_UART0.DATA;
295 2 zero_gravi
}
296
 
297
 
298
/**********************************************************************//**
299 50 zero_gravi
 * Print string (zero-terminated) via UART0. Print full line break "\r\n" for every '\n'.
300 2 zero_gravi
 *
301
 * @note This function is blocking.
302
 *
303
 * @param[in] s Pointer to string.
304
 **************************************************************************/
305 50 zero_gravi
void neorv32_uart0_print(const char *s) {
306 2 zero_gravi
 
307
  char c = 0;
308
  while ((c = *s++)) {
309
    if (c == '\n') {
310 50 zero_gravi
      neorv32_uart0_putc('\r');
311 2 zero_gravi
    }
312 50 zero_gravi
    neorv32_uart0_putc(c);
313 2 zero_gravi
  }
314
}
315
 
316
 
317
/**********************************************************************//**
318 50 zero_gravi
 * Custom version of 'printf' function using UART0.
319 2 zero_gravi
 *
320 50 zero_gravi
 * @note This function is blocking.
321
 *
322
 * @param[in] format Pointer to format string.
323
 *
324
 * <TABLE>
325
 * <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
326
 * <TR><TD>%c</TD><TD>Single char</TD></TR>
327
 * <TR><TD>%i</TD><TD>32-bit signed number, printed as decimal</TD></TR>
328
 * <TR><TD>%u</TD><TD>32-bit unsigned number, printed as decimal</TD></TR>
329
 * <TR><TD>%x</TD><TD>32-bit number, printed as 8-char hexadecimal</TD></TR>
330
 * </TABLE>
331 2 zero_gravi
 **************************************************************************/
332 50 zero_gravi
void neorv32_uart0_printf(const char *format, ...) {
333 2 zero_gravi
 
334 50 zero_gravi
  char c, string_buf[11];
335
  int32_t n;
336 2 zero_gravi
 
337 50 zero_gravi
  va_list a;
338
  va_start(a, format);
339 2 zero_gravi
 
340 50 zero_gravi
  while ((c = *format++)) {
341
    if (c == '%') {
342
      c = *format++;
343
      switch (c) {
344
        case 's': // string
345
          neorv32_uart0_print(va_arg(a, char*));
346
          break;
347
        case 'c': // char
348
          neorv32_uart0_putc((char)va_arg(a, int));
349
          break;
350
        case 'i': // 32-bit signed
351
          n = (int32_t)va_arg(a, int32_t);
352
          if (n < 0) {
353
            n = -n;
354
            neorv32_uart0_putc('-');
355
          }
356
          __neorv32_uart_itoa((uint32_t)n, string_buf);
357
          neorv32_uart0_print(string_buf);
358
          break;
359
        case 'u': // 32-bit unsigned
360
          __neorv32_uart_itoa(va_arg(a, uint32_t), string_buf);
361
          neorv32_uart0_print(string_buf);
362
          break;
363
        case 'x': // 32-bit hexadecimal
364
          __neorv32_uart_tohex(va_arg(a, uint32_t), string_buf);
365
          neorv32_uart0_print(string_buf);
366
          break;
367 55 zero_gravi
        default: // unsupported format
368
          neorv32_uart0_putc('%');
369
          neorv32_uart0_putc(c);
370
          break;
371 50 zero_gravi
      }
372
    }
373
    else {
374
      if (c == '\n') {
375
        neorv32_uart0_putc('\r');
376
      }
377
      neorv32_uart0_putc(c);
378
    }
379 2 zero_gravi
  }
380 50 zero_gravi
  va_end(a);
381
}
382 2 zero_gravi
 
383 50 zero_gravi
 
384
/**********************************************************************//**
385
 * Simplified custom version of 'scanf' function for UART0.
386
 *
387
 * @note This function is blocking.
388
 *
389
 * @param[in,out] buffer Pointer to array of chars to store string.
390
 * @param[in] max_size Maximum number of chars to sample.
391
 * @param[in] echo Echo UART input when 1.
392
 * @return Number of chars read.
393
 **************************************************************************/
394
int neorv32_uart0_scan(char *buffer, int max_size, int echo) {
395
 
396
  char c = 0;
397
  int length = 0;
398
 
399
  while (1) {
400
    c = neorv32_uart0_getc();
401
    if (c == '\b') { // BACKSPACE
402
      if (length != 0) {
403
        if (echo) {
404
          neorv32_uart0_print("\b \b"); // delete last char in console
405
        }
406
        buffer--;
407
        length--;
408
      }
409
    }
410
    else if (c == '\r') // carriage return
411 2 zero_gravi
      break;
412 50 zero_gravi
    else if ((c >= ' ') && (c <= '~') && (length < (max_size-1))) {
413
      if (echo) {
414
        neorv32_uart0_putc(c); // echo
415
      }
416
      *buffer++ = c;
417
      length++;
418
    }
419 2 zero_gravi
  }
420 50 zero_gravi
  *buffer = '\0'; // terminate string
421 2 zero_gravi
 
422 50 zero_gravi
  return length;
423
}
424 2 zero_gravi
 
425 50 zero_gravi
 
426
 
427
// #################################################################################################
428
// Secondary UART (UART1)
429
// #################################################################################################
430
 
431
/**********************************************************************//**
432
 * Check if UART1 unit was synthesized.
433
 *
434
 * @return 0 if UART1 was not synthesized, 1 if UART1 is available.
435
 **************************************************************************/
436
int neorv32_uart1_available(void) {
437
 
438 64 zero_gravi
  if (NEORV32_SYSINFO.SOC & (1 << SYSINFO_SOC_IO_UART1)) {
439 50 zero_gravi
    return 1;
440
  }
441
  else {
442
    return 0;
443
  }
444 2 zero_gravi
}
445
 
446
 
447
/**********************************************************************//**
448 50 zero_gravi
 * Enable and configure secondary UART (UART1).
449 2 zero_gravi
 *
450 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!
451
 * @note To enable simulation mode add <USER_FLAGS+=-DUART1_SIM_MODE> when compiling.
452
 *
453
 * @warning The baud rate is computed using INTEGER operations (truncation errors might occur).
454
 *
455
 * @param[in] baudrate Targeted BAUD rate (e.g. 9600).
456 51 zero_gravi
 * @param[in] parity Parity configuration (00=off, 10=even, 11=odd), see #NEORV32_UART_PARITY_enum.
457
 * @param[in] flow_con Hardware flow control configuration (00=off, 01=RTS, 10=CTS, 11=RTS/CTS), see #NEORV32_UART_FLOW_CONTROL_enum.
458 2 zero_gravi
 **************************************************************************/
459 51 zero_gravi
void neorv32_uart1_setup(uint32_t baudrate, uint8_t parity, uint8_t flow_con) {
460 2 zero_gravi
 
461 64 zero_gravi
  NEORV32_UART1.CTRL = 0; // reset
462 2 zero_gravi
 
463 64 zero_gravi
  uint32_t clock = NEORV32_SYSINFO.CLK;
464 50 zero_gravi
  uint16_t i = 0; // BAUD rate divisor
465
  uint8_t p = 0; // initial prsc = CLK/2
466
 
467
  // raw clock prescaler
468 66 zero_gravi
#ifdef make_bootloader
469 50 zero_gravi
  // use div instructions
470
  i = (uint16_t)(clock / (2*baudrate));
471
#else
472 66 zero_gravi
  // division via repeated subtraction (minimal size, only for bootloader)
473 50 zero_gravi
  while (clock >= 2*baudrate) {
474
    clock -= 2*baudrate;
475
    i++;
476 2 zero_gravi
  }
477 50 zero_gravi
#endif
478 2 zero_gravi
 
479 50 zero_gravi
  // find baud prescaler (12-bit wide))
480
  while (i >= 0x0fff) {
481
    if ((p == 2) || (p == 4))
482
      i >>= 3;
483
    else
484
      i >>= 1;
485
    p++;
486
  }
487
 
488
  uint32_t clk_prsc = (uint32_t)p;
489 64 zero_gravi
  clk_prsc = clk_prsc << UART_CTRL_PRSC0;
490 50 zero_gravi
 
491
  uint32_t baud_prsc = (uint32_t)i;
492
  baud_prsc = baud_prsc - 1;
493 64 zero_gravi
  baud_prsc = baud_prsc << UART_CTRL_BAUD00;
494 50 zero_gravi
 
495
  uint32_t uart_en = 1;
496 64 zero_gravi
  uart_en = uart_en << UART_CTRL_EN;
497 50 zero_gravi
 
498
  uint32_t parity_config = (uint32_t)(parity & 3);
499 64 zero_gravi
  parity_config = parity_config << UART_CTRL_PMODE0;
500 50 zero_gravi
 
501 51 zero_gravi
  uint32_t flow_control = (uint32_t)(flow_con & 3);
502 64 zero_gravi
  flow_control = flow_control << UART_CTRL_RTS_EN;
503 51 zero_gravi
 
504 50 zero_gravi
  /* Enable UART1 for SIM mode. */
505
  /* USE THIS ONLY FOR SIMULATION! */
506
#ifdef UART1_SIM_MODE
507
  #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!
508 64 zero_gravi
  uint32_t sim_mode = 1 << UART_CTRL_SIM_MODE;
509 50 zero_gravi
#else
510
  uint32_t sim_mode = 0;
511
#endif
512
 
513 64 zero_gravi
  NEORV32_UART1.CTRL = clk_prsc | baud_prsc | uart_en | parity_config | sim_mode | flow_control;
514 2 zero_gravi
}
515
 
516
 
517
/**********************************************************************//**
518 50 zero_gravi
 * Disable UART1.
519
 **************************************************************************/
520
void neorv32_uart1_disable(void) {
521
 
522 64 zero_gravi
  NEORV32_UART1.CTRL &= ~((uint32_t)(1 << UART_CTRL_EN));
523 50 zero_gravi
}
524
 
525
 
526
/**********************************************************************//**
527 61 zero_gravi
 * Enable UART1.
528
 **************************************************************************/
529
void neorv32_uart1_enable(void) {
530
 
531 64 zero_gravi
  NEORV32_UART1.CTRL |= ((uint32_t)(1 << UART_CTRL_EN));
532 61 zero_gravi
}
533
 
534
 
535
/**********************************************************************//**
536 50 zero_gravi
 * Send single char via UART1.
537 2 zero_gravi
 *
538
 * @note This function is blocking.
539
 *
540 50 zero_gravi
 * @param[in] c Char to be send.
541
 **************************************************************************/
542
void neorv32_uart1_putc(char c) {
543
 
544
  // wait for previous transfer to finish
545 65 zero_gravi
  while ((NEORV32_UART1.CTRL & (1<<UART_CTRL_TX_FULL)) != 0); // wait for space in TX FIFO
546 64 zero_gravi
  NEORV32_UART1.DATA = ((uint32_t)c) << UART_DATA_LSB;
547 50 zero_gravi
}
548
 
549
 
550
/**********************************************************************//**
551 65 zero_gravi
 * Check if UART1 TX is busy (transmitter busy or data left in TX buffer).
552 50 zero_gravi
 *
553
 * @note This function is blocking.
554
 *
555
 * @return 0 if idle, 1 if busy
556
 **************************************************************************/
557
int neorv32_uart1_tx_busy(void) {
558
 
559 65 zero_gravi
  uint32_t ctrl = NEORV32_UART1.CTRL;
560
 
561
  if (((ctrl & (1<<UART_CTRL_TX_BUSY)) != 0) ||  // TX engine busy
562
      ((ctrl & (1<<UART_CTRL_TX_EMPTY)) == 0)) { // TX buffer not empty
563 50 zero_gravi
    return 1;
564
  }
565
  return 0;
566
}
567
 
568
 
569
/**********************************************************************//**
570
 * Get char from UART1.
571
 *
572
 * @note This function is blocking and does not check for UART frame/parity errors.
573
 *
574
 * @return Received char.
575
 **************************************************************************/
576
char neorv32_uart1_getc(void) {
577
 
578
  uint32_t d = 0;
579
  while (1) {
580 64 zero_gravi
    d = NEORV32_UART1.DATA;
581 50 zero_gravi
    if ((d & (1<<UART_DATA_AVAIL)) != 0) { // char received?
582
      return (char)d;
583
    }
584
  }
585
}
586
 
587
 
588
/**********************************************************************//**
589
 * Get char from UART1 (and check errors).
590
 *
591
 * @note This function is non-blocking and checks for frame and parity errors.
592
 *
593
 * @param[in,out] data Received char.
594 65 zero_gravi
 * @return Status code:
595
 *  0 = char received without errors
596
 * -1 = nothing received
597
 * -2 = char received with frame error
598
 * -3 = char received with parity error
599
 * -4 = char received with overrun error.
600 50 zero_gravi
 **************************************************************************/
601 51 zero_gravi
int neorv32_uart1_getc_safe(char *data) {
602 50 zero_gravi
 
603 64 zero_gravi
  uint32_t uart_rx = NEORV32_UART1.DATA;
604 50 zero_gravi
 
605 65 zero_gravi
  // get received byte (if there is any)
606
  *data = (char)uart_rx;
607 50 zero_gravi
 
608 65 zero_gravi
  // check if no data available at all
609
  if ((uart_rx & (1<<UART_DATA_AVAIL)) == 0) {
610
   return -1;
611
  }
612 50 zero_gravi
 
613 65 zero_gravi
  // check for frame error
614
  if (uart_rx & (1<<UART_DATA_FERR)) {
615
    return -2;
616
  }
617 50 zero_gravi
 
618 65 zero_gravi
  // check for parity error
619
  if (uart_rx & (1<<UART_DATA_PERR)) {
620
    return -3;
621
  }
622 50 zero_gravi
 
623 65 zero_gravi
  // check for overrun error
624
  if (uart_rx & (1<<UART_DATA_OVERR)) {
625
    return -4;
626
  }
627 50 zero_gravi
 
628 65 zero_gravi
  return 0; // all fine
629 50 zero_gravi
}
630
 
631
 
632
/**********************************************************************//**
633
 * Check if UART1 has received a char.
634
 *
635
 * @note This function is non-blocking.
636
 * @note Use neorv32_uart0_char_received_get(void) to get the char.
637
 *
638
 * @return =!0 when a char has been received.
639
 **************************************************************************/
640
int neorv32_uart1_char_received(void) {
641
 
642 64 zero_gravi
  if ((NEORV32_UART1.DATA & (1<<UART_DATA_AVAIL)) != 0) {
643 50 zero_gravi
    return 1;
644
  }
645
  else {
646
    return 0;
647
  }
648
}
649
 
650
 
651
/**********************************************************************//**
652
 * Get a received char from UART1.
653
 *
654
 * @note This function is non-blocking.
655
 * @note Should only be used in combination with neorv32_uart_char_received(void).
656
 *
657
 * @return Received char.
658
 **************************************************************************/
659
char neorv32_uart1_char_received_get(void) {
660
 
661 64 zero_gravi
  return (char)NEORV32_UART1.DATA;
662 50 zero_gravi
}
663
 
664
 
665
/**********************************************************************//**
666
 * Print string (zero-terminated) via UART1. Print full line break "\r\n" for every '\n'.
667
 *
668
 * @note This function is blocking.
669
 *
670
 * @param[in] s Pointer to string.
671
 **************************************************************************/
672
void neorv32_uart1_print(const char *s) {
673
 
674
  char c = 0;
675
  while ((c = *s++)) {
676
    if (c == '\n') {
677
      neorv32_uart1_putc('\r');
678
    }
679
    neorv32_uart1_putc(c);
680
  }
681
}
682
 
683
 
684
/**********************************************************************//**
685
 * Custom version of 'printf' function using UART1.
686
 *
687
 * @note This function is blocking.
688
 *
689 2 zero_gravi
 * @param[in] format Pointer to format string.
690
 *
691
 * <TABLE>
692
 * <TR><TD>%s</TD><TD>String (array of chars, zero-terminated)</TD></TR>
693
 * <TR><TD>%c</TD><TD>Single char</TD></TR>
694
 * <TR><TD>%i</TD><TD>32-bit signed number, printed as decimal</TD></TR>
695
 * <TR><TD>%u</TD><TD>32-bit unsigned number, printed as decimal</TD></TR>
696
 * <TR><TD>%x</TD><TD>32-bit number, printed as 8-char hexadecimal</TD></TR>
697
 * </TABLE>
698
 **************************************************************************/
699 50 zero_gravi
void neorv32_uart1_printf(const char *format, ...) {
700 2 zero_gravi
 
701
  char c, string_buf[11];
702
  int32_t n;
703
 
704
  va_list a;
705
  va_start(a, format);
706
 
707
  while ((c = *format++)) {
708
    if (c == '%') {
709
      c = *format++;
710
      switch (c) {
711
        case 's': // string
712 50 zero_gravi
          neorv32_uart1_print(va_arg(a, char*));
713 2 zero_gravi
          break;
714
        case 'c': // char
715 50 zero_gravi
          neorv32_uart1_putc((char)va_arg(a, int));
716 2 zero_gravi
          break;
717
        case 'i': // 32-bit signed
718
          n = (int32_t)va_arg(a, int32_t);
719
          if (n < 0) {
720
            n = -n;
721 50 zero_gravi
            neorv32_uart1_putc('-');
722 2 zero_gravi
          }
723
          __neorv32_uart_itoa((uint32_t)n, string_buf);
724 50 zero_gravi
          neorv32_uart1_print(string_buf);
725 2 zero_gravi
          break;
726
        case 'u': // 32-bit unsigned
727
          __neorv32_uart_itoa(va_arg(a, uint32_t), string_buf);
728 50 zero_gravi
          neorv32_uart1_print(string_buf);
729 2 zero_gravi
          break;
730
        case 'x': // 32-bit hexadecimal
731
          __neorv32_uart_tohex(va_arg(a, uint32_t), string_buf);
732 50 zero_gravi
          neorv32_uart1_print(string_buf);
733 2 zero_gravi
          break;
734 55 zero_gravi
        default: // unsupported format
735
          neorv32_uart1_putc('%');
736
          neorv32_uart1_putc(c);
737
          break;
738 2 zero_gravi
      }
739
    }
740
    else {
741
      if (c == '\n') {
742 50 zero_gravi
        neorv32_uart1_putc('\r');
743 2 zero_gravi
      }
744 50 zero_gravi
      neorv32_uart1_putc(c);
745 2 zero_gravi
    }
746
  }
747
  va_end(a);
748
}
749
 
750
 
751
/**********************************************************************//**
752 50 zero_gravi
 * Simplified custom version of 'scanf' function for UART1.
753 2 zero_gravi
 *
754
 * @note This function is blocking.
755
 *
756
 * @param[in,out] buffer Pointer to array of chars to store string.
757
 * @param[in] max_size Maximum number of chars to sample.
758
 * @param[in] echo Echo UART input when 1.
759
 * @return Number of chars read.
760
 **************************************************************************/
761 50 zero_gravi
int neorv32_uart1_scan(char *buffer, int max_size, int echo) {
762 2 zero_gravi
 
763
  char c = 0;
764
  int length = 0;
765
 
766
  while (1) {
767 50 zero_gravi
    c = neorv32_uart1_getc();
768 2 zero_gravi
    if (c == '\b') { // BACKSPACE
769
      if (length != 0) {
770
        if (echo) {
771 50 zero_gravi
          neorv32_uart1_print("\b \b"); // delete last char in console
772 2 zero_gravi
        }
773
        buffer--;
774
        length--;
775
      }
776
    }
777
    else if (c == '\r') // carriage return
778
      break;
779
    else if ((c >= ' ') && (c <= '~') && (length < (max_size-1))) {
780
      if (echo) {
781 50 zero_gravi
        neorv32_uart1_putc(c); // echo
782 2 zero_gravi
      }
783
      *buffer++ = c;
784
      length++;
785
    }
786
  }
787
  *buffer = '\0'; // terminate string
788
 
789
  return length;
790
}
791
 
792 50 zero_gravi
 
793
 
794
// #################################################################################################
795
// Shared functions
796
// #################################################################################################
797
 
798
/**********************************************************************//**
799
 * Private function for 'neorv32_printf' to convert into decimal.
800
 *
801
 * @param[in] x Unsigned input number.
802
 * @param[in,out] res Pointer for storing the reuslting number string (11 chars).
803
 **************************************************************************/
804
static void __neorv32_uart_itoa(uint32_t x, char *res) {
805
 
806
  static const char numbers[] = "0123456789";
807
  char buffer1[11];
808
  uint16_t i, j;
809
 
810
  buffer1[10] = '\0';
811
  res[10] = '\0';
812
 
813
  // convert
814
  for (i=0; i<10; i++) {
815
    buffer1[i] = numbers[x%10];
816
    x /= 10;
817
  }
818
 
819
  // delete 'leading' zeros
820
  for (i=9; i!=0; i--) {
821
    if (buffer1[i] == '0')
822
      buffer1[i] = '\0';
823
    else
824
      break;
825
  }
826
 
827
  // reverse
828
  j = 0;
829
  do {
830
    if (buffer1[i] != '\0')
831
      res[j++] = buffer1[i];
832
  } while (i--);
833
 
834
  res[j] = '\0'; // terminate result string
835
}
836
 
837
 
838
/**********************************************************************//**
839
 * Private function for 'neorv32_printf' to convert into hexadecimal.
840
 *
841
 * @param[in] x Unsigned input number.
842 55 zero_gravi
 * @param[in,out] res Pointer for storing the resulting number string (9 chars).
843 50 zero_gravi
 **************************************************************************/
844
static void __neorv32_uart_tohex(uint32_t x, char *res) {
845
 
846
  static const char symbols[] = "0123456789abcdef";
847
 
848
  int i;
849 55 zero_gravi
  for (i=0; i<8; i++) { // nibble by nibble
850 50 zero_gravi
    uint32_t num_tmp = x >> (4*i);
851
    res[7-i] = (char)symbols[num_tmp & 0x0f];
852
  }
853
 
854
  res[8] = '\0'; // terminate result string
855
}

powered by: WebSVN 2.1.0

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