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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [sw/] [example/] [demo_slink/] [main.c] - Blame information for rev 73

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 69 zero_gravi
// #################################################################################################
2
// # << NEORV32 - SLINK Demo Program >>                                                            #
3
// # ********************************************************************************************* #
4
// # BSD 3-Clause License                                                                          #
5
// #                                                                                               #
6 73 zero_gravi
// # Copyright (c) 2022, Stephan Nolting. All rights reserved.                                     #
7 69 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 demo_slink/main.c
38
 * @author Stephan Nolting
39
 * @brief SLINK demo program.
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 slink_configured; // 0 = not configured, 1 = blocking mode, 2 = non-blocking mode
57
uint32_t slink_irq_en;
58
uint32_t slink_irq_mode;
59
 
60
// Prototypes
61
void slink_read(void);
62
void slink_write(void);
63
void slink_status(void);
64
void slink_setup(void);
65
void slink_irq_enable(void);
66
void slink_irq_setup(void);
67
void slink_reset(void);
68
uint32_t hexstr_to_uint(char *buffer, uint8_t length);
69
void slink_rx_firq_handler(void);
70
void slink_tx_firq_handler(void);
71
 
72
 
73
 
74
/**********************************************************************//**
75
 * This program provides an interactive console to initiate SLINK transfers.
76
 *
77
 * @note This program requires the UART and the SLINK to be synthesized.
78
 *
79
 * @return Irrelevant.
80
 **************************************************************************/
81
int main() {
82
 
83
  char buffer[16];
84
  int length = 0;
85
 
86
 
87
  // capture all exceptions and give debug info via UART
88
  // this is not required, but keeps us safe
89
  neorv32_rte_setup();
90
 
91
  // init UART0 at default baud rate, no parity bits, ho hw flow control
92
  neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
93
 
94
 
95
  // check if UART0 unit is implemented at all
96
  if (neorv32_uart0_available() == 0) {
97
    return 1;
98
  }
99
 
100
  // intro
101
  neorv32_uart0_printf("\n<<< SLINK Access Test Program >>>\n\n");
102
 
103
  // check if SLINK is implemented at all
104
  if (neorv32_slink_available() == 0) {
105
    neorv32_uart0_printf("No SLINK implemented.");
106
    return 1;
107
  }
108
 
109
  // info
110
  neorv32_uart0_printf("This program allows to create SLINK transfers by hand.\n"
111
                       "Type 'help' to see the help menu.\n\n");
112
 
113
  // enable SLINK module
114
  neorv32_slink_enable();
115
  slink_configured = 0; // SLINK not configured yet
116
  slink_irq_en = 0; // interrupts disabled
117
  slink_irq_mode = 0;
118
 
119
 
120
  // configure SLINK interrupts
121
  int i;
122
  for (i=0; i<neorv32_slink_get_rx_num(); i++) {
123
    neorv32_slink_rx_irq_config(i, SLINK_IRQ_ENABLE, SLINK_IRQ_RX_NOT_EMPTY);
124
  }
125
  for (i=0; i<neorv32_slink_get_tx_num(); i++) {
126
    neorv32_slink_tx_irq_config(i, SLINK_IRQ_ENABLE, SLINK_IRQ_TX_NOT_FULL);
127
  }
128
 
129
  neorv32_rte_exception_install(SLINK_RX_RTE_ID, slink_rx_firq_handler);
130
  neorv32_rte_exception_install(SLINK_TX_RTE_ID, slink_tx_firq_handler);
131
  neorv32_cpu_eint(); // enable global interrupt flag
132
 
133
 
134
  // Main menu
135
  for (;;) {
136
    neorv32_uart0_printf("SLINK_ACCESS:> ");
137
    length = neorv32_uart0_scan(buffer, 15, 1);
138
    neorv32_uart0_printf("\n");
139
 
140
    if (!length) // nothing to be done
141
     continue;
142
 
143
    // decode input and execute command
144
    if (!strcmp(buffer, "help")) {
145
      neorv32_uart0_printf("Available commands:\n"
146
                          " help     - show this text\n"
147
                          " status   - show SLINK HW status\n"
148
                          " setup    - configure SLINK module\n"
149
                          " read     - read from SLINK channel\n"
150
                          " write    - write to SLINK channel\n"
151
                          " irq_mode - toggle SLINK IRQ mode\n"
152
                          " irq_en   - toggle SLINK IRQ enable\n"
153
                          " reset    - reset SLINK module\n"
154
                          "\n"
155
                          "Configure the SLINK module using 'setup'. Then transfer data using 'read' and 'write'.\n\n");
156
    }
157
    else if (!strcmp(buffer, "setup")) {
158
      slink_setup();
159
    }
160
    else if (!strcmp(buffer, "status")) {
161
      slink_status();
162
    }
163
    else if (!strcmp(buffer, "read")) {
164
      slink_read();
165
    }
166
    else if (!strcmp(buffer, "write")) {
167
      slink_write();
168
    }
169
    else if (!strcmp(buffer, "irq_en")) {
170
      slink_irq_enable();
171
    }
172
    else if (!strcmp(buffer, "irq_mode")) {
173
      slink_irq_setup();
174
    }
175
    else if (!strcmp(buffer, "reset")) {
176
      slink_reset();
177
    }
178
    else {
179
      neorv32_uart0_printf("Invalid command. Type 'help' to see all commands.\n");
180
    }
181
  }
182
 
183
  return 0;
184
}
185
 
186
 
187
/**********************************************************************//**
188
 * Show SLINK status
189
 **************************************************************************/
190
void slink_status(void) {
191
 
192
  neorv32_uart0_printf("Hardware configuration\n");
193
  neorv32_uart0_printf(" TX links: %u\n", neorv32_slink_get_rx_num());
194
  neorv32_uart0_printf(" RX links: %u\n", neorv32_slink_get_tx_num());
195
  neorv32_uart0_printf(" TX FIFO:  %u entries \n", neorv32_slink_get_rx_depth());
196
  neorv32_uart0_printf(" RX FIFO:  %u entries \n\n", neorv32_slink_get_tx_depth());
197
 
198
  neorv32_uart0_printf("SLINK status:\n");
199
  neorv32_uart0_printf(" Link status: 0x%x \n", NEORV32_SLINK.STATUS);
200
  neorv32_uart0_printf(" IRQ config.: 0x%x \n\n", NEORV32_SLINK.IRQ);
201
}
202
 
203
 
204
/**********************************************************************//**
205
 * Configure SLINK
206
 **************************************************************************/
207
void slink_setup(void) {
208
 
209
  char tmp_c;
210
 
211
  while (1) {
212
    neorv32_uart0_printf("Select SLINK access mode:\n"
213
                         " n: non-blocking access -> check SLINK status flags before access\n"
214
                         " b: blocking access     -> raise an exception on invalid access request\n"
215
                         "Select: ");
216
    tmp_c = neorv32_uart0_getc();
217
    neorv32_uart0_putc(tmp_c);
218
    if (tmp_c == 'n') {
219
      slink_configured = 2;
220
      break;
221
    }
222
    else if (tmp_c == 'b') {
223
      slink_configured = 1;
224
      break;
225
    }
226
    else {
227
     neorv32_uart0_printf("\nInvalid selection!\n");
228
    }
229
  }
230
 
231
  neorv32_uart0_printf("\n\n");
232
}
233
 
234
 
235
/**********************************************************************//**
236
 * Reset SLINK
237
 **************************************************************************/
238
void slink_reset(void) {
239
 
240
  int i;
241
 
242
  for (i=0; i<neorv32_slink_get_rx_num(); i++) {
243
    neorv32_slink_rx_irq_config(i, SLINK_IRQ_DISABLE, SLINK_IRQ_RX_NOT_EMPTY);
244
  }
245
  for (i=0; i<neorv32_slink_get_tx_num(); i++) {
246
    neorv32_slink_tx_irq_config(i, SLINK_IRQ_DISABLE, SLINK_IRQ_TX_NOT_FULL);
247
  }
248
 
249
  neorv32_slink_disable();
250
  neorv32_slink_enable();
251
 
252
  slink_configured = 0;
253
  slink_irq_en = 0;
254
  slink_irq_mode = 0;
255
 
256
  neorv32_uart0_printf("SLINK has been reset.\n\n");
257
}
258
 
259
 
260
/**********************************************************************//**
261
 * Toggle SLINK interrupt mode
262
 **************************************************************************/
263
void slink_irq_setup(void) {
264
 
265
  int i;
266
 
267
  if (slink_irq_mode == 0) {
268
    for (i=0; i<neorv32_slink_get_rx_num(); i++) {
269
      neorv32_slink_rx_irq_config(i, SLINK_IRQ_DISABLE, SLINK_IRQ_RX_NOT_EMPTY); // disable first to reset trigger logic
270
      neorv32_slink_rx_irq_config(i, SLINK_IRQ_ENABLE, SLINK_IRQ_RX_NOT_EMPTY);
271
    }
272
    for (i=0; i<neorv32_slink_get_tx_num(); i++) {
273
      neorv32_slink_tx_irq_config(i, SLINK_IRQ_DISABLE, SLINK_IRQ_TX_NOT_FULL);
274
      neorv32_slink_tx_irq_config(i, SLINK_IRQ_ENABLE, SLINK_IRQ_TX_NOT_FULL);
275
    }
276
    neorv32_uart0_printf("New SLINK IRQ mode: SLINK_IRQ_RX_NOT_EMPTY + SLINK_IRQ_TX_NOT_FULL\n\n");
277
  }
278
  else {
279
    for (i=0; i<neorv32_slink_get_rx_num(); i++) {
280
      neorv32_slink_rx_irq_config(i, SLINK_IRQ_DISABLE, SLINK_IRQ_RX_FIFO_HALF);
281
      neorv32_slink_rx_irq_config(i, SLINK_IRQ_ENABLE, SLINK_IRQ_RX_FIFO_HALF);
282
    }
283
    for (i=0; i<neorv32_slink_get_tx_num(); i++) {
284
      neorv32_slink_tx_irq_config(i, SLINK_IRQ_DISABLE, SLINK_IRQ_TX_FIFO_HALF);
285
      neorv32_slink_tx_irq_config(i, SLINK_IRQ_ENABLE, SLINK_IRQ_TX_FIFO_HALF);
286
    }
287
    neorv32_uart0_printf("New SLINK IRQ mode: SLINK_IRQ_RX_FIFO_HALF + SLINK_IRQ_TX_FIFO_HALF\n\n");
288
  }
289
  slink_irq_mode = ~slink_irq_mode;
290
}
291
 
292
 
293
/**********************************************************************//**
294
 * Toggle SLINK interrupt enable
295
 **************************************************************************/
296
void slink_irq_enable(void) {
297
 
298
  if (slink_irq_en == 0) {
299
    neorv32_cpu_irq_enable(SLINK_RX_FIRQ_ENABLE);
300
    neorv32_cpu_irq_enable(SLINK_TX_FIRQ_ENABLE);
301
    neorv32_uart0_printf("SLINK interrupts are now ENABLED.\n\n");
302
  }
303
  else {
304
    neorv32_cpu_irq_disable(SLINK_RX_FIRQ_ENABLE);
305
    neorv32_cpu_irq_disable(SLINK_TX_FIRQ_ENABLE);
306
    neorv32_uart0_printf("SLINK interrupts are now DISABLED.\n\n");
307
  }
308
  slink_irq_en = ~slink_irq_en;
309
}
310
 
311
 
312
/**********************************************************************//**
313
 * Read from SLINK channel
314
 **************************************************************************/
315
void slink_read(void) {
316
 
317
  char terminal_buffer[9];
318
  uint32_t num_ch;
319
  uint32_t channel;
320
  uint32_t rxdata;
321
  int status = 1;
322
 
323
  if (slink_configured == 0) {
324
    neorv32_uart0_printf("SLINK module not configured yet! Use 'setup' to configure SLINK module.\n");
325
    return;
326
  }
327
 
328
  num_ch = (uint32_t)neorv32_slink_get_rx_num();
329
  if (num_ch == 0) {
330
    neorv32_uart0_printf("No SLINK RX channels implemented.\n");
331
    return;
332
  }
333
 
334
  // select channel
335
  while (1) {
336
    neorv32_uart0_printf("Enter RX channel ID (0..%u): ", num_ch-1);
337
    neorv32_uart0_scan(terminal_buffer, 2, 1); // 1 hex char plus '\0'
338
    channel = hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
339
    if ((channel < 0) || (channel > num_ch)) {
340
      neorv32_uart0_printf("\nInvalid channel selection!\n");
341
      continue;
342
    }
343
    else {
344
      break;
345
    }
346
  }
347
  channel &= 0x7;
348
 
349
  // actual read access
350
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
351
  neorv32_uart0_printf("\nReading from RX channel %u...\n", channel);
352
 
353
  if (slink_configured == 2) { // non-blocking access
354
    switch (channel) {
355
      case 0: status = neorv32_slink_rx0_nonblocking(&rxdata); break;
356
      case 1: status = neorv32_slink_rx1_nonblocking(&rxdata); break;
357
      case 2: status = neorv32_slink_rx2_nonblocking(&rxdata); break;
358
      case 3: status = neorv32_slink_rx3_nonblocking(&rxdata); break;
359
      case 4: status = neorv32_slink_rx4_nonblocking(&rxdata); break;
360
      case 5: status = neorv32_slink_rx5_nonblocking(&rxdata); break;
361
      case 6: status = neorv32_slink_rx6_nonblocking(&rxdata); break;
362
      case 7: status = neorv32_slink_rx7_nonblocking(&rxdata); break;
363
      default: status = 1; break;
364
    }
365
  }
366
  else { // blocking access
367
    status = 0;
368
    switch (channel) {
369
      case 0: neorv32_slink_rx0_blocking(&rxdata); break;
370
      case 1: neorv32_slink_rx1_blocking(&rxdata); break;
371
      case 2: neorv32_slink_rx2_blocking(&rxdata); break;
372
      case 3: neorv32_slink_rx3_blocking(&rxdata); break;
373
      case 4: neorv32_slink_rx4_blocking(&rxdata); break;
374
      case 5: neorv32_slink_rx5_blocking(&rxdata); break;
375
      case 6: neorv32_slink_rx6_blocking(&rxdata); break;
376
      case 7: neorv32_slink_rx7_blocking(&rxdata); break;
377
      default: status = 1; break;
378
    }
379
  }
380
 
381
  if ((status == 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_L_ACCESS)) {
382
    neorv32_uart0_printf("RX data: 0x%x\n\n", rxdata);
383
  }
384
  else {
385
    neorv32_uart0_printf("No data available.\n\n");
386
  }
387
}
388
 
389
 
390
/**********************************************************************//**
391
 * Write to SLINK channel
392
 **************************************************************************/
393
void slink_write(void) {
394
 
395
  char terminal_buffer[9];
396
  uint32_t num_ch;
397
  uint32_t channel;
398
  uint32_t txdata;
399
  int status = 1;
400
 
401
  if (slink_configured == 0) {
402
    neorv32_uart0_printf("SLINK module not configured yet! Use 'setup' to configure SLINK module.\n");
403
    return;
404
  }
405
 
406
  num_ch = (uint32_t)neorv32_slink_get_tx_num();
407
  if (num_ch == 0) {
408
    neorv32_uart0_printf("No SLINK TX channels implemented.\n");
409
    return;
410
  }
411
 
412
  // select channel
413
  while (1) {
414
    neorv32_uart0_printf("Enter TX channel ID (0..%u): ", num_ch-1);
415
    neorv32_uart0_scan(terminal_buffer, 2, 1); // 1 hex char plus '\0'
416
    channel = hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
417
    if ((channel < 0) || (channel > num_ch)) {
418
      neorv32_uart0_printf("\nInvalid channel selection!\n");
419
      continue;
420
    }
421
    else {
422
      break;
423
    }
424
  }
425
  channel &= 0x7;
426
 
427
  // get TX data
428
  neorv32_uart0_printf("\nEnter TX data (8 hex chars): 0x");
429
  neorv32_uart0_scan(terminal_buffer, 9, 1); // 8 hex char plus '\0'
430
  txdata = hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
431
 
432
  // actual write access
433
  neorv32_cpu_csr_write(CSR_MCAUSE, 0);
434
  neorv32_uart0_printf("\nWriting '0x%x' to TX channel %u...\n", txdata, channel);
435
 
436
  if (slink_configured == 2) { // non-blocking access
437
    switch (channel) {
438
      case 0: status = neorv32_slink_tx0_nonblocking(txdata); break;
439
      case 1: status = neorv32_slink_tx1_nonblocking(txdata); break;
440
      case 2: status = neorv32_slink_tx2_nonblocking(txdata); break;
441
      case 3: status = neorv32_slink_tx3_nonblocking(txdata); break;
442
      case 4: status = neorv32_slink_tx4_nonblocking(txdata); break;
443
      case 5: status = neorv32_slink_tx5_nonblocking(txdata); break;
444
      case 6: status = neorv32_slink_tx6_nonblocking(txdata); break;
445
      case 7: status = neorv32_slink_tx7_nonblocking(txdata); break;
446
      default: status = 1; break;
447
    }
448
  }
449
  else { // blocking access
450
    status = 0;
451
    switch (channel) {
452
      case 0: neorv32_slink_tx0_blocking(txdata); break;
453
      case 1: neorv32_slink_tx1_blocking(txdata); break;
454
      case 2: neorv32_slink_tx2_blocking(txdata); break;
455
      case 3: neorv32_slink_tx3_blocking(txdata); break;
456
      case 4: neorv32_slink_tx4_blocking(txdata); break;
457
      case 5: neorv32_slink_tx5_blocking(txdata); break;
458
      case 6: neorv32_slink_tx6_blocking(txdata); break;
459
      case 7: neorv32_slink_tx7_blocking(txdata); break;
460
      default: status = 1; break;
461
    }
462
  }
463
 
464
  if ((status == 0) && (neorv32_cpu_csr_read(CSR_MCAUSE) != TRAP_CODE_S_ACCESS)) {
465
    neorv32_uart0_printf("Write successful.\n\n");
466
  }
467
  else {
468
    neorv32_uart0_printf("Write failed.\n\n", status);
469
  }
470
}
471
 
472
 
473
/**********************************************************************//**
474
 * SLINK RX FIRQ handler
475
 **************************************************************************/
476
void slink_rx_firq_handler(void) {
477
 
478 73 zero_gravi
  neorv32_cpu_csr_write(CSR_MIP, ~(1 << SLINK_RX_FIRQ_PENDING)); // ACK interrupt
479 69 zero_gravi
  neorv32_uart0_printf("\n<SLINK_RX_IRQ>\n");
480
}
481
 
482
 
483
/**********************************************************************//**
484
 * SLINK TX FIRQ handler
485
 **************************************************************************/
486
void slink_tx_firq_handler(void) {
487
 
488 73 zero_gravi
  neorv32_cpu_csr_write(CSR_MIP, ~(1 << SLINK_TX_FIRQ_PENDING)); // ACK interrupt
489 69 zero_gravi
  neorv32_uart0_printf("\n<SLINK_TX_IRQ>\n");
490
}
491
 
492
 
493
/**********************************************************************//**
494
 * Helper function to convert N hex chars string into uint32_T
495
 *
496
 * @param[in,out] buffer Pointer to array of chars to convert into number.
497
 * @param[in,out] length Length of the conversion string.
498
 * @return Converted number.
499
 **************************************************************************/
500
uint32_t hexstr_to_uint(char *buffer, uint8_t length) {
501
 
502
  uint32_t res = 0, d = 0;
503
  char c = 0;
504
 
505
  while (length--) {
506
    c = *buffer++;
507
 
508
    if ((c >= '0') && (c <= '9'))
509
      d = (uint32_t)(c - '0');
510
    else if ((c >= 'a') && (c <= 'f'))
511
      d = (uint32_t)((c - 'a') + 10);
512
    else if ((c >= 'A') && (c <= 'F'))
513
      d = (uint32_t)((c - 'A') + 10);
514
    else
515
      d = 0;
516
 
517
    res = res + (d << (length*4));
518
  }
519
 
520
  return res;
521
}
522
 

powered by: WebSVN 2.1.0

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