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

Subversion Repositories neorv32

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

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

powered by: WebSVN 2.1.0

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