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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [example/] [demo_spi/] [main.c] - Blame information for rev 69

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 68 zero_gravi
// #################################################################################################
2
// # << NEORV32 - SPI Bus Explorer Demo Program >>                                                 #
3
// # ********************************************************************************************* #
4
// # BSD 3-Clause License                                                                          #
5
// #                                                                                               #
6
// # Copyright (c) 2021, Stephan Nolting. All rights reserved.                                     #
7
// #                                                                                               #
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 demo_spi/main.c
38
 * @author Stephan Nolting
39
 * @brief SPI bus explorer (execute SPI transactions by hand).
40
 **************************************************************************/
41
 
42
#include <neorv32.h>
43
#include <string.h>
44
 
45
 
46
/**********************************************************************//**
47
 * @name User configuration
48
 **************************************************************************/
49
/**@{*/
50
/** UART BAUD rate */
51
#define BAUD_RATE 19200
52
/**@}*/
53
 
54
 
55
// Global variables
56
uint32_t spi_configured;
57
uint32_t spi_size; // data quantity in bytes
58
 
59
// Prototypes
60
void spi_cs(uint32_t type);
61
void spi_trans(void);
62
void spi_setup(void);
63 69 zero_gravi
void flash_write(void);
64
void flash_read(void);
65 68 zero_gravi
uint32_t hexstr_to_uint(char *buffer, uint8_t length);
66
void aux_print_hex_byte(uint8_t byte);
67
 
68
 
69
/**********************************************************************//**
70 69 zero_gravi
 * SPI flash commands
71
 **************************************************************************/
72
enum SPI_FLASH_CMD {
73
  SPI_FLASH_CMD_WRITE    = 0x02, /**< Write data */
74
  SPI_FLASH_CMD_READ     = 0x03, /**< Read data */
75
  SPI_FLASH_CMD_READ_SR  = 0x05, /**< Get status register */
76
  SPI_FLASH_CMD_WREN     = 0x06  /**< Enable write access */
77
};
78
 
79
 
80
/**********************************************************************//**
81 68 zero_gravi
 * This program provides an interactive console to communicate with SPI devices.
82
 *
83
 * @note This program requires the UART and the SPI to be synthesized.
84
 *
85
 * @return Irrelevant.
86
 **************************************************************************/
87
int main() {
88
 
89 69 zero_gravi
  char buffer[16];
90 68 zero_gravi
  int length = 0;
91
 
92
 
93
  // capture all exceptions and give debug info via UART
94
  // this is not required, but keeps us safe
95
  neorv32_rte_setup();
96
 
97
  // init UART0 at default baud rate, no parity bits, ho hw flow control
98
  neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
99
 
100
 
101
  // check if UART0 unit is implemented at all
102
  if (neorv32_uart0_available() == 0) {
103
    return 1;
104
  }
105
 
106
  // intro
107
  neorv32_uart0_printf("\n<<< SPI Bus Explorer >>>\n\n");
108
 
109
  // check if SPI unit is implemented at all
110
  if (neorv32_spi_available() == 0) {
111
    neorv32_uart0_printf("No SPI unit implemented.");
112
    return 1;
113
  }
114
 
115
  // info
116
  neorv32_uart0_printf("This program allows to create SPI transfers by hand.\n"
117
                      "Type 'help' to see the help menu.\n\n");
118
 
119
  // disable and reset SPI module
120
  NEORV32_SPI.CTRL = 0;
121
  spi_configured = 0; // SPI not configured yet
122
  spi_size = 0;
123
 
124
 
125
  // Main menu
126
  for (;;) {
127
    neorv32_uart0_printf("SPI_EXPLORER:> ");
128 69 zero_gravi
    length = neorv32_uart0_scan(buffer, 15, 1);
129 68 zero_gravi
    neorv32_uart0_printf("\n");
130
 
131
    if (!length) // nothing to be done
132
     continue;
133
 
134
    // decode input and execute command
135
    if (!strcmp(buffer, "help")) {
136
      neorv32_uart0_printf("Available commands:\n"
137 69 zero_gravi
                          " help     - show this text\n"
138
                          " setup    - configure SPI module (clock speed and mode, data size)\n"
139
                          " cs-en    - enable CS line (set low)\n"
140
                          " cs-dis   - disable CS line (set high)\n"
141
                          " trans    - execute a transmission (write & read to/from SPI)\n"
142 68 zero_gravi
                          "\n"
143 69 zero_gravi
                          " flash-wr - write binary file to SPI flash\n"
144
                          " flash-rd - dump SPI flash\n"
145
                          "\n"
146 68 zero_gravi
                          "Configure the SPI module using 'setup'. Enable a certain module using 'cs-en',\n"
147 69 zero_gravi
                          "then transfer data using 'trans' and disable the module again using 'cs-dis'.\n"
148
                          "\n"
149
                          "Standard SPI flash and EEPROM memories can be programmed/read\n"
150
                          "via 'flash-wr' and 'flash-rd'.\n\n");
151 68 zero_gravi
    }
152
    else if (!strcmp(buffer, "setup")) {
153
      spi_setup();
154
    }
155
    else if (!strcmp(buffer, "cs-en")) {
156
      spi_cs(1);
157
    }
158
    else if (!strcmp(buffer, "cs-dis")) {
159
      spi_cs(0);
160
    }
161
    else if (!strcmp(buffer, "trans")) {
162
      spi_trans();
163
    }
164 69 zero_gravi
    else if (!strcmp(buffer, "flash-wr")) {
165
      flash_write();
166
    }
167
    else if (!strcmp(buffer, "flash-rd")) {
168
      flash_read();
169
    }
170 68 zero_gravi
    else {
171
      neorv32_uart0_printf("Invalid command. Type 'help' to see all commands.\n");
172
    }
173
  }
174
 
175
  return 0;
176
}
177
 
178
 
179
/**********************************************************************//**
180
 * Enable or disable chip-select line
181
 *
182
 * @param[in] type 0=disable, 1=enable
183
 **************************************************************************/
184
void spi_cs(uint32_t type) {
185
 
186
  char terminal_buffer[2];
187
  uint8_t channel;
188
 
189
  if (type) {
190
    neorv32_uart0_printf("Select chip-select line to enable (set low) [0..7]: ");
191
  }
192
  else {
193
    neorv32_uart0_printf("Select chip-select line to disable (set high) [0..7]: ");
194
  }
195
 
196
  while (1) {
197
    neorv32_uart0_scan(terminal_buffer, 2, 1); // 1 hex char plus '\0'
198
    channel = (uint8_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
199
    if (channel > 7) {
200
      neorv32_uart0_printf("\nInvalid channel selection!\n");
201
      return;
202
    }
203
    else {
204
      neorv32_uart0_printf("\n");
205
      break;
206
    }
207
  }
208
 
209
  if (type) {
210
    neorv32_spi_cs_en(channel);
211
  }
212
  else {
213
    neorv32_spi_cs_dis(channel);
214
  }
215
}
216
 
217
 
218
/**********************************************************************//**
219
 * SPI data transfer
220
 **************************************************************************/
221
void spi_trans(void) {
222
 
223
  char terminal_buffer[9];
224
 
225
  if (spi_configured == 0) {
226
    neorv32_uart0_printf("SPI module not configured yet! Use 'setup' to configure SPI module.\n");
227
    return;
228
  }
229
 
230 69 zero_gravi
  neorv32_uart0_printf("Enter TX data (%u hex chars): 0x", spi_size*2);
231 68 zero_gravi
  neorv32_uart0_scan(terminal_buffer, spi_size*2+1, 1);
232
  uint32_t tx_data = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
233
 
234
  uint32_t rx_data = neorv32_spi_trans(tx_data);
235
 
236
  if (spi_size == 1) {
237
    neorv32_uart0_printf("\nTX data: 0x");
238
    aux_print_hex_byte((uint8_t)(tx_data));
239
    neorv32_uart0_printf("\nRX data: 0x");
240
    aux_print_hex_byte((uint8_t)(rx_data));
241
    neorv32_uart0_printf("\n");
242
  }
243
  else if (spi_size == 2) {
244
    neorv32_uart0_printf("\nTX data: 0x");
245
    aux_print_hex_byte((uint8_t)(tx_data >> 8));
246
    aux_print_hex_byte((uint8_t)(tx_data));
247
    neorv32_uart0_printf("\nRX data: 0x");
248
    aux_print_hex_byte((uint8_t)(rx_data >> 8));
249
    aux_print_hex_byte((uint8_t)(rx_data));
250
    neorv32_uart0_printf("\n");
251
  }
252
  else if (spi_size == 3) {
253
    neorv32_uart0_printf("\nTX data: 0x");
254
    aux_print_hex_byte((uint8_t)(tx_data >> 16));
255
    aux_print_hex_byte((uint8_t)(tx_data >> 8));
256
    aux_print_hex_byte((uint8_t)(tx_data));
257
    neorv32_uart0_printf("\nRX data: 0x");
258
    aux_print_hex_byte((uint8_t)(rx_data >> 16));
259
    aux_print_hex_byte((uint8_t)(rx_data >> 8));
260
    aux_print_hex_byte((uint8_t)(rx_data));
261
    neorv32_uart0_printf("\n");
262
  }
263
  else {
264
    neorv32_uart0_printf("\nTX data: 0x%x\n", tx_data);
265
    neorv32_uart0_printf("RX data: 0x%x\n", rx_data);
266
  }
267
}
268
 
269
 
270
/**********************************************************************//**
271
 * Configure SPI module
272
 **************************************************************************/
273
void spi_setup(void) {
274
 
275
  char terminal_buffer[9];
276
  uint8_t spi_prsc, clk_phase, clk_pol, data_size;
277
  uint32_t tmp;
278
 
279
  // ---- SPI clock ----
280
 
281
  while (1) {
282
  neorv32_uart0_printf("Select SPI clock prescaler (0..7): ");
283
  neorv32_uart0_scan(terminal_buffer, 2, 1);
284
  tmp = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
285
    if (tmp > 8) {
286
      neorv32_uart0_printf("\nInvalid selection!\n");
287
    }
288
    else {
289
      spi_prsc = (uint8_t)tmp;
290
      break;
291
    }
292
  }
293
 
294
  uint32_t div = 0;
295
  switch (spi_prsc) {
296
    case 0: div = 2 * 2; break;
297
    case 1: div = 2 * 4; break;
298
    case 2: div = 2 * 8; break;
299
    case 3: div = 2 * 64; break;
300
    case 4: div = 2 * 128; break;
301
    case 5: div = 2 * 1024; break;
302
    case 6: div = 2 * 2048; break;
303
    case 7: div = 2 * 4096; break;
304
    default: div = 0; break;
305
  }
306
  uint32_t clock = NEORV32_SYSINFO.CLK / div;
307
  neorv32_uart0_printf("\n+ New SPI clock speed = %u Hz\n", clock);
308
 
309
  // ---- SPI clock mode ----
310
 
311
  while (1) {
312
  neorv32_uart0_printf("Select SPI clock mode (0..3): ");
313
  neorv32_uart0_scan(terminal_buffer, 2, 1);
314
  tmp = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
315
    if (tmp > 4) {
316
      neorv32_uart0_printf("\nInvalid selection!\n");
317
    }
318
    else {
319
      clk_pol   = (uint8_t)((tmp >> 1) & 1);
320
      clk_phase = (uint8_t)(tmp & 1);
321
      break;
322
    }
323
  }
324
  neorv32_uart0_printf("\n+ New SPI clock mode = %u\n", tmp);
325
 
326
  // ---- SPI transfer data quantity ----
327
 
328
  while (1) {
329
  neorv32_uart0_printf("Select SPI data transfer size in bytes (1,2,3,4): ");
330
  neorv32_uart0_scan(terminal_buffer, 2, 1);
331
  tmp = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
332
    if ( (tmp < 1) || (tmp > 4)) {
333
      neorv32_uart0_printf("\nInvalid selection!\n");
334
    }
335
    else {
336
      data_size = (uint8_t)(tmp - 1);
337
      break;
338
    }
339
  }
340
  neorv32_uart0_printf("\n+ New SPI data size = %u-byte(s)\n\n", tmp);
341
 
342
  neorv32_spi_setup(spi_prsc, clk_phase, clk_pol, data_size);
343
  spi_configured = 1; // SPI is configured now
344
  spi_size = tmp;
345
}
346
 
347
 
348
/**********************************************************************//**
349 69 zero_gravi
 * Read (dump) flash
350
 **************************************************************************/
351
void flash_read(void) {
352
 
353
  char terminal_buffer[9];
354
  uint32_t tmp, addr, channel, num_addr_bytes;
355
 
356
  if (spi_configured == 0) {
357
    neorv32_uart0_printf("SPI module not configured yet! Use 'setup' to configure SPI module.\n");
358
    return;
359
  }
360
 
361
  // configure 8-bit SPI mode
362
  tmp = NEORV32_SPI.CTRL;
363
  tmp &= ~(0x03 << SPI_CTRL_SIZE0);
364
  NEORV32_SPI.CTRL = tmp;
365
  neorv32_uart0_printf("Warning! SPI size configuration has been overridden!\n");
366
 
367
  // how many address bytes?
368
  while (1) {
369
    neorv32_uart0_printf("Enter number of address bytes (2,3): ");
370
    neorv32_uart0_scan(terminal_buffer, 2, 1); // 1 hex char plus '\0'
371
    num_addr_bytes = hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
372
    if ((num_addr_bytes < 2) || (num_addr_bytes > 3)) {
373
      neorv32_uart0_printf("\nInvalid channel selection!\n");
374
      continue;
375
    }
376
    else {
377
      break;
378
    }
379
  }
380
 
381
  // chip-select
382
  while (1) {
383
    neorv32_uart0_printf("\nSelect flash chip-select line [0..7]: ");
384
    neorv32_uart0_scan(terminal_buffer, 2, 1); // 1 hex char plus '\0'
385
    channel = hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
386
    if (channel > 7) {
387
      neorv32_uart0_printf("\nInvalid channel selection!\n");
388
      continue;
389
    }
390
    else {
391
      break;
392
    }
393
  }
394
 
395
  // base address
396
  neorv32_uart0_printf("\nEnter base address (8 hex chars): 0x");
397
  neorv32_uart0_scan(terminal_buffer, 9, 1);
398
  addr = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
399
 
400
  neorv32_uart0_printf("\nPress any key to start. Press any key to stop reading.\n");
401
  while(neorv32_uart0_char_received() == 0);
402
 
403
  while(1) {
404
    if (neorv32_uart0_char_received()) { // abort when key pressed
405
      break;
406
    }
407
 
408
    if ((addr & 0x1f) == 0) {
409
      neorv32_uart0_printf("\n%x: ", addr);
410
    }
411
 
412
    // read byte
413
    neorv32_spi_cs_en((uint8_t)channel);
414
    neorv32_spi_trans(SPI_FLASH_CMD_READ);
415
    if (num_addr_bytes == 3) {
416
      neorv32_spi_trans(addr >> 16);
417
    }
418
    neorv32_spi_trans(addr >> 8);
419
    neorv32_spi_trans(addr >> 0);
420
    tmp = neorv32_spi_trans(0);
421
    neorv32_spi_cs_dis((uint8_t)channel);
422
 
423
    aux_print_hex_byte((uint8_t)tmp);
424
    neorv32_uart0_putc(' ');
425
 
426
    addr++;
427
  }
428
 
429
  neorv32_uart0_printf("\n");
430
  spi_configured = 0;
431
}
432
 
433
 
434
/**********************************************************************//**
435
 * Write flash
436
 **************************************************************************/
437
void flash_write(void) {
438
 
439
  neorv32_uart0_printf("work-in-progress\n");
440
  return;
441
 
442
  char terminal_buffer[9], rx_data;
443
  uint32_t tmp, addr, channel, num_data_bytes, num_addr_bytes;
444
  int res;
445
 
446
  if (spi_configured == 0) {
447
    neorv32_uart0_printf("SPI module not configured yet! Use 'setup' to configure SPI module.\n");
448
    return;
449
  }
450
 
451
  // configure 8-bit SPI mode
452
  tmp = NEORV32_SPI.CTRL;
453
  tmp &= ~(0x03 << SPI_CTRL_SIZE0);
454
  NEORV32_SPI.CTRL = tmp;
455
  neorv32_uart0_printf("Warning! SPI size configuration has been overridden!\n");
456
 
457
  // how many address bytes?
458
  while (1) {
459
    neorv32_uart0_printf("Enter number of address bytes (2,3): ");
460
    neorv32_uart0_scan(terminal_buffer, 2, 1); // 1 hex char plus '\0'
461
    num_addr_bytes = hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
462
    if ((num_addr_bytes < 2) || (num_addr_bytes > 3)) {
463
      neorv32_uart0_printf("\nInvalid channel selection!\n");
464
      continue;
465
    }
466
    else {
467
      break;
468
    }
469
  }
470
 
471
  // how many bytes?
472
  neorv32_uart0_printf("\nEnter total number of bytes to write (%u hex chars): ", num_addr_bytes*2);
473
  neorv32_uart0_scan(terminal_buffer, num_addr_bytes*2+1, 1); // 1 hex char plus '\0'
474
  num_data_bytes = hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
475
 
476
  // chip-select
477
  while (1) {
478
    neorv32_uart0_printf("\nSelect flash chip-select line [0..7]: ");
479
    neorv32_uart0_scan(terminal_buffer, 2, 1); // 1 hex char plus '\0'
480
    channel = hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
481
    if (channel > 7) {
482
      neorv32_uart0_printf("\nInvalid channel selection!\n");
483
      continue;
484
    }
485
    else {
486
      break;
487
    }
488
  }
489
 
490
  // base address
491
  neorv32_uart0_printf("\nEnter base address (8 hex chars): 0x");
492
  neorv32_uart0_scan(terminal_buffer, 9, 1);
493
  addr = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
494
 
495
  // start!
496
  neorv32_uart0_printf("\nSend raw data via UART (%u bytes)...\n", num_data_bytes);
497
  while (neorv32_uart0_tx_busy());
498
 
499
  // clear UART0 FIFOs
500
  neorv32_uart0_disable();
501
  neorv32_uart0_enable();
502
 
503
  while (num_data_bytes) {
504
 
505
    // write enable
506
    neorv32_spi_cs_en((uint8_t)channel);
507
    neorv32_spi_trans(SPI_FLASH_CMD_WREN);
508
    neorv32_spi_cs_dis((uint8_t)channel);
509
 
510
    // get new UART data
511
    while(1) {
512
      res = neorv32_uart0_getc_safe(&rx_data);
513
      if (res == -1) {
514
        continue;
515
      }
516
      if (res == 0) {
517
        break;
518
      }
519
      else {
520
        neorv32_uart0_printf("UART transmission error (%i)!\n", res);
521
        return;
522
      }
523
    }
524
 
525
    // write byte
526
    neorv32_spi_cs_en((uint8_t)channel);
527
    neorv32_spi_trans(SPI_FLASH_CMD_WRITE);
528
    if (num_addr_bytes == 3) {
529
      neorv32_spi_trans(addr >> 16);
530
    }
531
    neorv32_spi_trans(addr >> 8);
532
    neorv32_spi_trans(addr >> 0);
533
    neorv32_spi_trans((uint32_t)rx_data);
534
    neorv32_spi_cs_dis((uint8_t)channel);
535
 
536
    // check status register
537
    while (1) {
538
      neorv32_spi_cs_en((uint8_t)channel);
539
      neorv32_spi_trans(SPI_FLASH_CMD_READ_SR);
540
      tmp = neorv32_spi_trans(0);
541
      neorv32_spi_cs_dis((uint8_t)channel);
542
      if ((tmp & 0x01) == 0) { // write-in-progress flag cleared?
543
        break;
544
      }
545
    }
546
 
547
    addr++;
548
    num_data_bytes--;
549
  }
550
 
551
  neorv32_uart0_printf("\n");
552
  spi_configured = 0;
553
}
554
 
555
 
556
/**********************************************************************//**
557 68 zero_gravi
 * Helper function to convert N hex chars string into uint32_T
558
 *
559
 * @param[in,out] buffer Pointer to array of chars to convert into number.
560
 * @param[in,out] length Length of the conversion string.
561
 * @return Converted number.
562
 **************************************************************************/
563
uint32_t hexstr_to_uint(char *buffer, uint8_t length) {
564
 
565
  uint32_t res = 0, d = 0;
566
  char c = 0;
567
 
568
  while (length--) {
569
    c = *buffer++;
570
 
571
    if ((c >= '0') && (c <= '9'))
572
      d = (uint32_t)(c - '0');
573
    else if ((c >= 'a') && (c <= 'f'))
574
      d = (uint32_t)((c - 'a') + 10);
575
    else if ((c >= 'A') && (c <= 'F'))
576
      d = (uint32_t)((c - 'A') + 10);
577
    else
578
      d = 0;
579
 
580
    res = res + (d << (length*4));
581
  }
582
 
583
  return res;
584
}
585
 
586
 
587
/**********************************************************************//**
588
 * Print HEX byte.
589
 *
590
 * @param[in] byte Byte to be printed as 2-cahr hex value.
591
 **************************************************************************/
592
void aux_print_hex_byte(uint8_t byte) {
593
 
594
  static const char symbols[] = "0123456789abcdef";
595
 
596
  neorv32_uart0_putc(symbols[(byte >> 4) & 0x0f]);
597
  neorv32_uart0_putc(symbols[(byte >> 0) & 0x0f]);
598
}

powered by: WebSVN 2.1.0

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