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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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