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

Subversion Repositories neorv32

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

Go to most recent revision | 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
uint32_t hexstr_to_uint(char *buffer, uint8_t length);
64
void aux_print_hex_byte(uint8_t byte);
65
 
66
 
67
/**********************************************************************//**
68
 * This program provides an interactive console to communicate with SPI devices.
69
 *
70
 * @note This program requires the UART and the SPI to be synthesized.
71
 *
72
 * @return Irrelevant.
73
 **************************************************************************/
74
int main() {
75
 
76
  char buffer[8];
77
  int length = 0;
78
 
79
 
80
  // capture all exceptions and give debug info via UART
81
  // this is not required, but keeps us safe
82
  neorv32_rte_setup();
83
 
84
  // init UART0 at default baud rate, no parity bits, ho hw flow control
85
  neorv32_uart0_setup(BAUD_RATE, PARITY_NONE, FLOW_CONTROL_NONE);
86
 
87
 
88
  // check if UART0 unit is implemented at all
89
  if (neorv32_uart0_available() == 0) {
90
    return 1;
91
  }
92
 
93
  // intro
94
  neorv32_uart0_printf("\n<<< SPI Bus Explorer >>>\n\n");
95
 
96
  // check if SPI unit is implemented at all
97
  if (neorv32_spi_available() == 0) {
98
    neorv32_uart0_printf("No SPI unit implemented.");
99
    return 1;
100
  }
101
 
102
 
103
  // info
104
  neorv32_uart0_printf("This program allows to create SPI transfers by hand.\n"
105
                      "Type 'help' to see the help menu.\n\n");
106
 
107
  // disable and reset SPI module
108
  NEORV32_SPI.CTRL = 0;
109
  spi_configured = 0; // SPI not configured yet
110
  spi_size = 0;
111
 
112
 
113
  // Main menu
114
  for (;;) {
115
    neorv32_uart0_printf("SPI_EXPLORER:> ");
116
    length = neorv32_uart0_scan(buffer, 8, 1);
117
    neorv32_uart0_printf("\n");
118
 
119
    if (!length) // nothing to be done
120
     continue;
121
 
122
    // decode input and execute command
123
    if (!strcmp(buffer, "help")) {
124
      neorv32_uart0_printf("Available commands:\n"
125
                          " help   - show this text\n"
126
                          " setup  - configure SPI module\n"
127
                          " cs-en  - enable CS line (set low)\n"
128
                          " cs-dis - disable CS line (set high)\n"
129
                          " trans  - execute a transmission (write & read to/from SPI)\n"
130
                          "\n"
131
                          "Configure the SPI module using 'setup'. Enable a certain module using 'cs-en',\n"
132
                          "then transfer data using 'trans' and disable the module again using 'cs-dis'.\n\n");
133
    }
134
    else if (!strcmp(buffer, "setup")) {
135
      spi_setup();
136
    }
137
    else if (!strcmp(buffer, "cs-en")) {
138
      spi_cs(1);
139
    }
140
    else if (!strcmp(buffer, "cs-dis")) {
141
      spi_cs(0);
142
    }
143
    else if (!strcmp(buffer, "trans")) {
144
      spi_trans();
145
    }
146
    else {
147
      neorv32_uart0_printf("Invalid command. Type 'help' to see all commands.\n");
148
    }
149
  }
150
 
151
  return 0;
152
}
153
 
154
 
155
/**********************************************************************//**
156
 * Enable or disable chip-select line
157
 *
158
 * @param[in] type 0=disable, 1=enable
159
 **************************************************************************/
160
void spi_cs(uint32_t type) {
161
 
162
  char terminal_buffer[2];
163
  uint8_t channel;
164
 
165
  if (type) {
166
    neorv32_uart0_printf("Select chip-select line to enable (set low) [0..7]: ");
167
  }
168
  else {
169
    neorv32_uart0_printf("Select chip-select line to disable (set high) [0..7]: ");
170
  }
171
 
172
  while (1) {
173
    neorv32_uart0_scan(terminal_buffer, 2, 1); // 1 hex char plus '\0'
174
    channel = (uint8_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
175
    if (channel > 7) {
176
      neorv32_uart0_printf("\nInvalid channel selection!\n");
177
      return;
178
    }
179
    else {
180
      neorv32_uart0_printf("\n");
181
      break;
182
    }
183
  }
184
 
185
  if (type) {
186
    neorv32_spi_cs_en(channel);
187
  }
188
  else {
189
    neorv32_spi_cs_dis(channel);
190
  }
191
}
192
 
193
 
194
/**********************************************************************//**
195
 * SPI data transfer
196
 **************************************************************************/
197
void spi_trans(void) {
198
 
199
  char terminal_buffer[9];
200
 
201
  if (spi_configured == 0) {
202
    neorv32_uart0_printf("SPI module not configured yet! Use 'setup' to configure SPI module.\n");
203
    return;
204
  }
205
 
206
  neorv32_uart0_printf("Enter TX data (%u hex chars): 0x", spi_size);
207
  neorv32_uart0_scan(terminal_buffer, spi_size*2+1, 1);
208
  uint32_t tx_data = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
209
 
210
  uint32_t rx_data = neorv32_spi_trans(tx_data);
211
 
212
  if (spi_size == 1) {
213
    neorv32_uart0_printf("\nTX data: 0x");
214
    aux_print_hex_byte((uint8_t)(tx_data));
215
    neorv32_uart0_printf("\nRX data: 0x");
216
    aux_print_hex_byte((uint8_t)(rx_data));
217
    neorv32_uart0_printf("\n");
218
  }
219
  else if (spi_size == 2) {
220
    neorv32_uart0_printf("\nTX data: 0x");
221
    aux_print_hex_byte((uint8_t)(tx_data >> 8));
222
    aux_print_hex_byte((uint8_t)(tx_data));
223
    neorv32_uart0_printf("\nRX data: 0x");
224
    aux_print_hex_byte((uint8_t)(rx_data >> 8));
225
    aux_print_hex_byte((uint8_t)(rx_data));
226
    neorv32_uart0_printf("\n");
227
  }
228
  else if (spi_size == 3) {
229
    neorv32_uart0_printf("\nTX data: 0x");
230
    aux_print_hex_byte((uint8_t)(tx_data >> 16));
231
    aux_print_hex_byte((uint8_t)(tx_data >> 8));
232
    aux_print_hex_byte((uint8_t)(tx_data));
233
    neorv32_uart0_printf("\nRX data: 0x");
234
    aux_print_hex_byte((uint8_t)(rx_data >> 16));
235
    aux_print_hex_byte((uint8_t)(rx_data >> 8));
236
    aux_print_hex_byte((uint8_t)(rx_data));
237
    neorv32_uart0_printf("\n");
238
  }
239
  else {
240
    neorv32_uart0_printf("\nTX data: 0x%x\n", tx_data);
241
    neorv32_uart0_printf("RX data: 0x%x\n", rx_data);
242
  }
243
}
244
 
245
 
246
/**********************************************************************//**
247
 * Configure SPI module
248
 **************************************************************************/
249
void spi_setup(void) {
250
 
251
  char terminal_buffer[9];
252
  uint8_t spi_prsc, clk_phase, clk_pol, data_size;
253
  uint32_t tmp;
254
 
255
  // ---- SPI clock ----
256
 
257
  while (1) {
258
  neorv32_uart0_printf("Select SPI clock prescaler (0..7): ");
259
  neorv32_uart0_scan(terminal_buffer, 2, 1);
260
  tmp = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
261
    if (tmp > 8) {
262
      neorv32_uart0_printf("\nInvalid selection!\n");
263
    }
264
    else {
265
      spi_prsc = (uint8_t)tmp;
266
      break;
267
    }
268
  }
269
 
270
  uint32_t div = 0;
271
  switch (spi_prsc) {
272
    case 0: div = 2 * 2; break;
273
    case 1: div = 2 * 4; break;
274
    case 2: div = 2 * 8; break;
275
    case 3: div = 2 * 64; break;
276
    case 4: div = 2 * 128; break;
277
    case 5: div = 2 * 1024; break;
278
    case 6: div = 2 * 2048; break;
279
    case 7: div = 2 * 4096; break;
280
    default: div = 0; break;
281
  }
282
  uint32_t clock = NEORV32_SYSINFO.CLK / div;
283
  neorv32_uart0_printf("\n+ New SPI clock speed = %u Hz\n", clock);
284
 
285
  // ---- SPI clock mode ----
286
 
287
  while (1) {
288
  neorv32_uart0_printf("Select SPI clock mode (0..3): ");
289
  neorv32_uart0_scan(terminal_buffer, 2, 1);
290
  tmp = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
291
    if (tmp > 4) {
292
      neorv32_uart0_printf("\nInvalid selection!\n");
293
    }
294
    else {
295
      clk_pol   = (uint8_t)((tmp >> 1) & 1);
296
      clk_phase = (uint8_t)(tmp & 1);
297
      break;
298
    }
299
  }
300
  neorv32_uart0_printf("\n+ New SPI clock mode = %u\n", tmp);
301
 
302
  // ---- SPI transfer data quantity ----
303
 
304
  while (1) {
305
  neorv32_uart0_printf("Select SPI data transfer size in bytes (1,2,3,4): ");
306
  neorv32_uart0_scan(terminal_buffer, 2, 1);
307
  tmp = (uint32_t)hexstr_to_uint(terminal_buffer, strlen(terminal_buffer));
308
    if ( (tmp < 1) || (tmp > 4)) {
309
      neorv32_uart0_printf("\nInvalid selection!\n");
310
    }
311
    else {
312
      data_size = (uint8_t)(tmp - 1);
313
      break;
314
    }
315
  }
316
  neorv32_uart0_printf("\n+ New SPI data size = %u-byte(s)\n\n", tmp);
317
 
318
  neorv32_spi_setup(spi_prsc, clk_phase, clk_pol, data_size);
319
  spi_configured = 1; // SPI is configured now
320
  spi_size = tmp;
321
}
322
 
323
 
324
/**********************************************************************//**
325
 * Helper function to convert N hex chars string into uint32_T
326
 *
327
 * @param[in,out] buffer Pointer to array of chars to convert into number.
328
 * @param[in,out] length Length of the conversion string.
329
 * @return Converted number.
330
 **************************************************************************/
331
uint32_t hexstr_to_uint(char *buffer, uint8_t length) {
332
 
333
  uint32_t res = 0, d = 0;
334
  char c = 0;
335
 
336
  while (length--) {
337
    c = *buffer++;
338
 
339
    if ((c >= '0') && (c <= '9'))
340
      d = (uint32_t)(c - '0');
341
    else if ((c >= 'a') && (c <= 'f'))
342
      d = (uint32_t)((c - 'a') + 10);
343
    else if ((c >= 'A') && (c <= 'F'))
344
      d = (uint32_t)((c - 'A') + 10);
345
    else
346
      d = 0;
347
 
348
    res = res + (d << (length*4));
349
  }
350
 
351
  return res;
352
}
353
 
354
 
355
/**********************************************************************//**
356
 * Print HEX byte.
357
 *
358
 * @param[in] byte Byte to be printed as 2-cahr hex value.
359
 **************************************************************************/
360
void aux_print_hex_byte(uint8_t byte) {
361
 
362
  static const char symbols[] = "0123456789abcdef";
363
 
364
  neorv32_uart0_putc(symbols[(byte >> 4) & 0x0f]);
365
  neorv32_uart0_putc(symbols[(byte >> 0) & 0x0f]);
366
}

powered by: WebSVN 2.1.0

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