OpenOCD
flash/nand/tcl.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2007 by Dominic Rath <Dominic.Rath@gmx.de> *
5  * Copyright (C) 2002 Thomas Gleixner <tglx@linutronix.de> *
6  * Copyright (C) 2009 Zachary T Welch <zw@superlucidity.net> *
7  * *
8  * Partially based on drivers/mtd/nand_ids.c from Linux. *
9  ***************************************************************************/
10 
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif
14 
15 #include "core.h"
16 #include "imp.h"
17 #include "fileio.h"
18 #include <target/target.h>
19 
20 /* to be removed */
21 extern struct nand_device *nand_devices;
22 
23 COMMAND_HANDLER(handle_nand_list_command)
24 {
25  struct nand_device *p;
26  int i;
27 
28  if (!nand_devices) {
29  command_print(CMD, "no NAND flash devices configured");
30  return ERROR_OK;
31  }
32 
33  for (p = nand_devices, i = 0; p; p = p->next, i++) {
34  if (p->device)
35  command_print(CMD, "#%i: %s (%s) "
36  "pagesize: %i, buswidth: %i,\n\t"
37  "blocksize: %i, blocks: %i",
38  i, p->device->name, p->manufacturer->name,
39  p->page_size, p->bus_width,
40  p->erase_size, p->num_blocks);
41  else
42  command_print(CMD, "#%i: not probed", i);
43  }
44 
45  return ERROR_OK;
46 }
47 
48 COMMAND_HANDLER(handle_nand_info_command)
49 {
50  int i = 0;
51  int j = 0;
52  int first = -1;
53  int last = -1;
54 
55  switch (CMD_ARGC) {
56  default:
58  case 1:
59  first = 0;
60  last = INT32_MAX;
61  break;
62  case 2:
63  COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], i);
64  first = last = i;
65  i = 0;
66  break;
67  case 3:
68  COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], first);
69  COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], last);
70  break;
71  }
72 
73  struct nand_device *p;
74  int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
75  if (retval != ERROR_OK)
76  return retval;
77 
78  if (!p->device) {
79  command_print(CMD, "#%s: not probed", CMD_ARGV[0]);
80  return ERROR_OK;
81  }
82 
83  if (first >= p->num_blocks)
84  first = p->num_blocks - 1;
85 
86  if (last >= p->num_blocks)
87  last = p->num_blocks - 1;
88 
90  "#%i: %s (%s) pagesize: %i, buswidth: %i, erasesize: %i",
91  i++,
92  p->device->name,
93  p->manufacturer->name,
94  p->page_size,
95  p->bus_width,
96  p->erase_size);
97 
98  for (j = first; j <= last; j++) {
99  char *erase_state, *bad_state;
100 
101  if (p->blocks[j].is_erased == 0)
102  erase_state = "not erased";
103  else if (p->blocks[j].is_erased == 1)
104  erase_state = "erased";
105  else
106  erase_state = "erase state unknown";
107 
108  if (p->blocks[j].is_bad == 0)
109  bad_state = "";
110  else if (p->blocks[j].is_bad == 1)
111  bad_state = " (marked bad)";
112  else
113  bad_state = " (block condition unknown)";
114 
116  "\t#%i: 0x%8.8" PRIx32 " (%" PRIu32 "kB) %s%s",
117  j,
118  p->blocks[j].offset,
119  p->blocks[j].size / 1024,
120  erase_state,
121  bad_state);
122  }
123 
124  return ERROR_OK;
125 }
126 
127 COMMAND_HANDLER(handle_nand_probe_command)
128 {
129  if (CMD_ARGC != 1)
131 
132  struct nand_device *p;
133  int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
134  if (retval != ERROR_OK)
135  return retval;
136 
137  retval = nand_probe(p);
138  if (retval == ERROR_OK) {
139  command_print(CMD, "NAND flash device '%s (%s)' found",
140  p->device->name, p->manufacturer->name);
141  }
142 
143  return retval;
144 }
145 
146 COMMAND_HANDLER(handle_nand_erase_command)
147 {
148  if (CMD_ARGC != 1 && CMD_ARGC != 3)
150 
151  struct nand_device *p;
152  int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
153  if (retval != ERROR_OK)
154  return retval;
155 
156  unsigned long offset;
157  unsigned long length;
158 
159  /* erase specified part of the chip; or else everything */
160  if (CMD_ARGC == 3) {
161  unsigned long size = p->erase_size * p->num_blocks;
162 
164  if ((offset % p->erase_size) != 0 || offset >= size)
166 
168  if ((length == 0) || (length % p->erase_size) != 0
169  || (length + offset) > size)
171 
172  offset /= p->erase_size;
173  length /= p->erase_size;
174  } else {
175  offset = 0;
176  length = p->num_blocks;
177  }
178 
179  retval = nand_erase(p, offset, offset + length - 1);
180  if (retval == ERROR_OK) {
181  command_print(CMD, "erased blocks %lu to %lu "
182  "on NAND flash device #%s '%s'",
183  offset, offset + length - 1,
184  CMD_ARGV[0], p->device->name);
185  }
186 
187  return retval;
188 }
189 
190 COMMAND_HANDLER(handle_nand_check_bad_blocks_command)
191 {
192  int first = -1;
193  int last = -1;
194 
195  if ((CMD_ARGC < 1) || (CMD_ARGC > 3) || (CMD_ARGC == 2))
197 
198  struct nand_device *p;
199  int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
200  if (retval != ERROR_OK)
201  return retval;
202 
203  if (CMD_ARGC == 3) {
204  unsigned long offset;
205  unsigned long length;
206 
208  if (offset % p->erase_size)
210  offset /= p->erase_size;
211 
213  if (length % p->erase_size)
215 
216  length -= 1;
217  length /= p->erase_size;
218 
219  first = offset;
220  last = offset + length;
221  }
222 
223  retval = nand_build_bbt(p, first, last);
224  if (retval == ERROR_OK) {
225  command_print(CMD, "checked NAND flash device for bad blocks, "
226  "use \"nand info\" command to list blocks");
227  }
228 
229  return retval;
230 }
231 
232 COMMAND_HANDLER(handle_nand_write_command)
233 {
234  struct nand_device *nand = NULL;
235  struct nand_fileio_state s;
236  int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
237  &s, &nand, FILEIO_READ, false, true);
238  if (retval != ERROR_OK)
239  return retval;
240 
241  uint32_t total_bytes = s.size;
242  while (s.size > 0) {
243  int bytes_read = nand_fileio_read(nand, &s);
244  if (bytes_read <= 0) {
245  command_print(CMD, "error while reading file");
247  return ERROR_FAIL;
248  }
249  s.size -= bytes_read;
250 
251  retval = nand_write_page(nand, s.address / nand->page_size,
252  s.page, s.page_size, s.oob, s.oob_size);
253  if (retval != ERROR_OK) {
254  command_print(CMD, "failed writing file %s "
255  "to NAND flash %s at offset 0x%8.8" PRIx32,
256  CMD_ARGV[1], CMD_ARGV[0], s.address);
258  return retval;
259  }
260  s.address += s.page_size;
261  }
262 
263  if (nand_fileio_finish(&s) == ERROR_OK) {
264  command_print(CMD, "wrote file %s to NAND flash %s up to "
265  "offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
267  duration_kbps(&s.bench, total_bytes));
268  }
269  return ERROR_OK;
270 }
271 
272 COMMAND_HANDLER(handle_nand_verify_command)
273 {
274  struct nand_device *nand = NULL;
275  struct nand_fileio_state file;
276  int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
277  &file, &nand, FILEIO_READ, false, true);
278  if (retval != ERROR_OK)
279  return retval;
280 
281  struct nand_fileio_state dev;
282  nand_fileio_init(&dev);
283  dev.address = file.address;
284  dev.size = file.size;
285  dev.oob_format = file.oob_format;
286  retval = nand_fileio_start(CMD, nand, NULL, FILEIO_NONE, &dev);
287  if (retval != ERROR_OK)
288  return retval;
289 
290  while (file.size > 0) {
291  retval = nand_read_page(nand, dev.address / dev.page_size,
292  dev.page, dev.page_size, dev.oob, dev.oob_size);
293  if (retval != ERROR_OK) {
294  command_print(CMD, "reading NAND flash page failed");
295  nand_fileio_cleanup(&dev);
296  nand_fileio_cleanup(&file);
297  return retval;
298  }
299 
300  int bytes_read = nand_fileio_read(nand, &file);
301  if (bytes_read <= 0) {
302  command_print(CMD, "error while reading file");
303  nand_fileio_cleanup(&dev);
304  nand_fileio_cleanup(&file);
305  return ERROR_FAIL;
306  }
307 
308  if ((dev.page && memcmp(dev.page, file.page, dev.page_size)) ||
309  (dev.oob && memcmp(dev.oob, file.oob, dev.oob_size))) {
310  command_print(CMD, "NAND flash contents differ "
311  "at 0x%8.8" PRIx32, dev.address);
312  nand_fileio_cleanup(&dev);
313  nand_fileio_cleanup(&file);
314  return ERROR_FAIL;
315  }
316 
317  file.size -= bytes_read;
318  dev.address += nand->page_size;
319  }
320 
321  if (nand_fileio_finish(&file) == ERROR_OK) {
322  command_print(CMD, "verified file %s in NAND flash %s "
323  "up to offset 0x%8.8" PRIx32 " in %fs (%0.3f KiB/s)",
324  CMD_ARGV[1], CMD_ARGV[0], dev.address, duration_elapsed(&file.bench),
325  duration_kbps(&file.bench, dev.size));
326  }
327 
328  return nand_fileio_cleanup(&dev);
329 }
330 
331 COMMAND_HANDLER(handle_nand_dump_command)
332 {
333  size_t filesize;
334  struct nand_device *nand = NULL;
335  struct nand_fileio_state s;
336  int retval = CALL_COMMAND_HANDLER(nand_fileio_parse_args,
337  &s, &nand, FILEIO_WRITE, true, false);
338  if (retval != ERROR_OK)
339  return retval;
340 
341  while (s.size > 0) {
342  size_t size_written;
343  retval = nand_read_page(nand, s.address / nand->page_size,
344  s.page, s.page_size, s.oob, s.oob_size);
345  if (retval != ERROR_OK) {
346  command_print(CMD, "reading NAND flash page failed");
348  return retval;
349  }
350 
351  if (s.page)
352  fileio_write(s.fileio, s.page_size, s.page, &size_written);
353 
354  if (s.oob)
355  fileio_write(s.fileio, s.oob_size, s.oob, &size_written);
356 
357  s.size -= nand->page_size;
358  s.address += nand->page_size;
359  }
360 
361  retval = fileio_size(s.fileio, &filesize);
362  if (retval != ERROR_OK)
363  return retval;
364 
365  if (nand_fileio_finish(&s) == ERROR_OK) {
366  command_print(CMD, "dumped %zu bytes in %fs (%0.3f KiB/s)",
367  filesize, duration_elapsed(&s.bench),
368  duration_kbps(&s.bench, filesize));
369  }
370  return ERROR_OK;
371 }
372 
373 COMMAND_HANDLER(handle_nand_raw_access_command)
374 {
375  if ((CMD_ARGC < 1) || (CMD_ARGC > 2))
377 
378  struct nand_device *p;
379  int retval = CALL_COMMAND_HANDLER(nand_command_get_device, 0, &p);
380  if (retval != ERROR_OK)
381  return retval;
382 
383  if (!p->device) {
384  command_print(CMD, "#%s: not probed", CMD_ARGV[0]);
385  return ERROR_OK;
386  }
387 
388  if (CMD_ARGC == 2)
390 
391  const char *msg = p->use_raw ? "enabled" : "disabled";
392  command_print(CMD, "raw access is %s", msg);
393 
394  return ERROR_OK;
395 }
396 
397 static const struct command_registration nand_exec_command_handlers[] = {
398  {
399  .name = "list",
400  .handler = handle_nand_list_command,
401  .mode = COMMAND_EXEC,
402  .help = "list configured NAND flash devices",
403  .usage = "",
404  },
405  {
406  .name = "info",
407  .handler = handle_nand_info_command,
408  .mode = COMMAND_EXEC,
409  .usage = "[banknum | first_bank_num last_bank_num]",
410  .help = "print info about one or more NAND flash devices",
411  },
412  {
413  .name = "probe",
414  .handler = handle_nand_probe_command,
415  .mode = COMMAND_EXEC,
416  .usage = "bank_id",
417  .help = "identify NAND flash device",
418  },
419  {
420  .name = "check_bad_blocks",
421  .handler = handle_nand_check_bad_blocks_command,
422  .mode = COMMAND_EXEC,
423  .usage = "bank_id [offset length]",
424  .help = "check all or part of NAND flash device for bad blocks",
425  },
426  {
427  .name = "erase",
428  .handler = handle_nand_erase_command,
429  .mode = COMMAND_EXEC,
430  .usage = "bank_id [offset length]",
431  .help = "erase all or subset of blocks on NAND flash device",
432  },
433  {
434  .name = "dump",
435  .handler = handle_nand_dump_command,
436  .mode = COMMAND_EXEC,
437  .usage = "bank_id filename offset length "
438  "['oob_raw'|'oob_only']",
439  .help = "dump from NAND flash device",
440  },
441  {
442  .name = "verify",
443  .handler = handle_nand_verify_command,
444  .mode = COMMAND_EXEC,
445  .usage = "bank_id filename offset "
446  "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
447  .help = "verify NAND flash device",
448  },
449  {
450  .name = "write",
451  .handler = handle_nand_write_command,
452  .mode = COMMAND_EXEC,
453  .usage = "bank_id filename offset "
454  "['oob_raw'|'oob_only'|'oob_softecc'|'oob_softecc_kw']",
455  .help = "write to NAND flash device",
456  },
457  {
458  .name = "raw_access",
459  .handler = handle_nand_raw_access_command,
460  .mode = COMMAND_EXEC,
461  .usage = "bank_id ['enable'|'disable']",
462  .help = "raw access to NAND flash device",
463  },
465 };
466 
467 static int nand_init(struct command_context *cmd_ctx)
468 {
469  if (!nand_devices)
470  return ERROR_OK;
471 
472  return register_commands(cmd_ctx, "nand", nand_exec_command_handlers);
473 }
474 
475 COMMAND_HANDLER(handle_nand_init_command)
476 {
477  if (CMD_ARGC != 0)
479 
480  static bool nand_initialized;
481  if (nand_initialized) {
482  LOG_INFO("'nand init' has already been called");
483  return ERROR_OK;
484  }
485  nand_initialized = true;
486 
487  LOG_DEBUG("Initializing NAND devices...");
488  return nand_init(CMD_CTX);
489 }
490 
491 static int nand_list_walker(struct nand_flash_controller *c, void *x)
492 {
493  struct command_invocation *cmd = x;
494  command_print(cmd, " %s", c->name);
495  return ERROR_OK;
496 }
497 
498 COMMAND_HANDLER(handle_nand_list_drivers)
499 {
500  command_print(CMD, "Available NAND flash controller drivers:");
502 }
503 
504 static COMMAND_HELPER(create_nand_device, const char *bank_name,
505  struct nand_flash_controller *controller)
506 {
507  struct nand_device *c;
508  struct target *target;
509  int retval;
510 
511  if (CMD_ARGC < 2)
513  target = get_target(CMD_ARGV[1]);
514  if (!target) {
515  LOG_ERROR("invalid target %s", CMD_ARGV[1]);
517  }
518 
519  if (controller->commands) {
520  retval = register_commands(CMD_CTX, NULL, controller->commands);
521  if (retval != ERROR_OK)
522  return retval;
523  }
524  c = malloc(sizeof(struct nand_device));
525  if (!c) {
526  LOG_ERROR("End of memory");
527  return ERROR_FAIL;
528  }
529 
530  c->name = strdup(bank_name);
531  c->target = target;
532  c->controller = controller;
533  c->controller_priv = NULL;
534  c->manufacturer = NULL;
535  c->device = NULL;
536  c->bus_width = 0;
537  c->address_cycles = 0;
538  c->page_size = 0;
539  c->use_raw = false;
540  c->next = NULL;
541 
542  retval = CALL_COMMAND_HANDLER(controller->nand_device_command, c);
543  if (retval != ERROR_OK) {
544  LOG_ERROR("'%s' driver rejected nand flash. Usage: %s",
545  controller->name,
546  controller->usage);
547  free(c);
548  return retval;
549  }
550 
551  if (!controller->usage)
552  LOG_DEBUG("'%s' driver usage field missing", controller->name);
553 
554  nand_device_add(c);
555 
556  return ERROR_OK;
557 }
558 
559 COMMAND_HANDLER(handle_nand_device_command)
560 {
561  if (CMD_ARGC < 2)
563 
564  /* save name and increment (for compatibility) with drivers */
565  const char *bank_name = *CMD_ARGV++;
566  CMD_ARGC--;
567 
568  const char *driver_name = CMD_ARGV[0];
569  struct nand_flash_controller *controller;
570  controller = nand_driver_find_by_name(CMD_ARGV[0]);
571  if (!controller) {
572  LOG_ERROR("No valid NAND flash driver found (%s)", driver_name);
573  return CALL_COMMAND_HANDLER(handle_nand_list_drivers);
574  }
575  return CALL_COMMAND_HANDLER(create_nand_device, bank_name, controller);
576 }
577 
578 static const struct command_registration nand_config_command_handlers[] = {
579  {
580  .name = "device",
581  .handler = &handle_nand_device_command,
582  .mode = COMMAND_CONFIG,
583  .help = "defines a new NAND bank",
584  .usage = "bank_id driver target [driver_options ...]",
585  },
586  {
587  .name = "drivers",
588  .handler = &handle_nand_list_drivers,
589  .mode = COMMAND_ANY,
590  .help = "lists available NAND drivers",
591  .usage = ""
592  },
593  {
594  .name = "init",
595  .mode = COMMAND_CONFIG,
596  .handler = &handle_nand_init_command,
597  .help = "initialize NAND devices",
598  .usage = ""
599  },
601 };
602 
603 static const struct command_registration nand_command_handlers[] = {
604  {
605  .name = "nand",
606  .mode = COMMAND_ANY,
607  .help = "NAND flash command group",
608  .usage = "",
610  },
612 };
613 
615 {
616  return register_commands(cmd_ctx, NULL, nand_command_handlers);
617 }
void command_print(struct command_invocation *cmd, const char *format,...)
Definition: command.c:473
#define CMD
Use this macro to access the command being handled, rather than accessing the variable directly.
Definition: command.h:140
#define CALL_COMMAND_HANDLER(name, extra ...)
Use this to macro to call a command helper (or a nested handler).
Definition: command.h:117
#define CMD_ARGV
Use this macro to access the arguments for the command being handled, rather than accessing the varia...
Definition: command.h:155
#define ERROR_COMMAND_SYNTAX_ERROR
Definition: command.h:385
#define CMD_ARGC
Use this macro to access the number of arguments for the command being handled, rather than accessing...
Definition: command.h:150
#define COMMAND_PARSE_ENABLE(in, out)
parses an enable/disable command argument
Definition: command.h:507
#define COMMAND_PARSE_NUMBER(type, in, out)
parses the string in into out as a type, or prints a command error and passes the error code to the c...
Definition: command.h:425
#define CMD_CTX
Use this macro to access the context of the command being handled, rather than accessing the variable...
Definition: command.h:145
#define COMMAND_REGISTRATION_DONE
Use this as the last entry in an array of command_registration records.
Definition: command.h:247
#define ERROR_COMMAND_ARGUMENT_INVALID
Definition: command.h:387
static int register_commands(struct command_context *cmd_ctx, const char *cmd_prefix, const struct command_registration *cmds)
Register one or more commands in the specified context, as children of parent (or top-level commends,...
Definition: command.h:268
@ COMMAND_CONFIG
Definition: command.h:41
@ COMMAND_ANY
Definition: command.h:42
@ COMMAND_EXEC
Definition: command.h:40
uint8_t length
Definition: esp_usb_jtag.c:1
int nand_probe(struct nand_device *nand)
int nand_build_bbt(struct nand_device *nand, int first, int last)
int nand_erase(struct nand_device *nand, int first_block, int last_block)
int nand_write_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
int nand_read_page(struct nand_device *nand, uint32_t page, uint8_t *data, uint32_t data_size, uint8_t *oob, uint32_t oob_size)
void nand_device_add(struct nand_device *c)
int nand_driver_walk(nand_driver_walker_t f, void *x)
Walk the list of drivers, encapsulating the data structure type.
struct nand_flash_controller * nand_driver_find_by_name(const char *name)
Find a NAND flash controller by name.
int nand_fileio_cleanup(struct nand_fileio_state *state)
int nand_fileio_start(struct command_invocation *cmd, struct nand_device *nand, const char *filename, int filemode, struct nand_fileio_state *state)
void nand_fileio_init(struct nand_fileio_state *state)
int nand_fileio_read(struct nand_device *nand, struct nand_fileio_state *s)
int nand_fileio_finish(struct nand_fileio_state *state)
static COMMAND_HELPER(create_nand_device, const char *bank_name, struct nand_flash_controller *controller)
struct nand_device * nand_devices
COMMAND_HANDLER(handle_nand_list_command)
static int nand_init(struct command_context *cmd_ctx)
static const struct command_registration nand_exec_command_handlers[]
static int nand_list_walker(struct nand_flash_controller *c, void *x)
static const struct command_registration nand_config_command_handlers[]
static const struct command_registration nand_command_handlers[]
int nand_register_commands(struct command_context *cmd_ctx)
int fileio_write(struct fileio *fileio, size_t size, const void *buffer, size_t *size_written)
int fileio_size(struct fileio *fileio, size_t *size)
FIX!!!!
@ FILEIO_NONE
Definition: helper/fileio.h:27
@ FILEIO_WRITE
Definition: helper/fileio.h:29
@ FILEIO_READ
Definition: helper/fileio.h:28
#define ERROR_FAIL
Definition: log.h:161
#define LOG_ERROR(expr ...)
Definition: log.h:123
#define LOG_INFO(expr ...)
Definition: log.h:117
#define LOG_DEBUG(expr ...)
Definition: log.h:109
#define ERROR_OK
Definition: log.h:155
Upper level NOR flash interfaces.
struct target * target
Definition: rtt/rtt.c:26
size_t size
Size of the control block search area.
Definition: rtt/rtt.c:30
When run_command is called, a new instance will be created on the stack, filled with the proper value...
Definition: command.h:76
const char * name
Definition: command.h:229
int is_erased
True if the block has been erased.
Definition: nand/core.h:29
uint32_t offset
Offset to the block.
Definition: nand/core.h:23
int is_bad
True if the block is bad.
Definition: nand/core.h:32
uint32_t size
Size of the block.
Definition: nand/core.h:26
struct nand_flash_controller * controller
Definition: nand/core.h:50
void * controller_priv
Definition: nand/core.h:51
int page_size
Definition: nand/core.h:56
struct nand_device * next
Definition: nand/core.h:61
int num_blocks
Definition: nand/core.h:59
struct nand_block * blocks
Definition: nand/core.h:60
bool use_raw
Definition: nand/core.h:58
int address_cycles
Definition: nand/core.h:55
int bus_width
Definition: nand/core.h:54
int erase_size
Definition: nand/core.h:57
const char * name
Definition: nand/core.h:48
struct target * target
Definition: nand/core.h:49
struct nand_manufacturer * manufacturer
Definition: nand/core.h:52
struct nand_info * device
Definition: nand/core.h:53
struct duration bench
enum oob_formats oob_format
struct fileio * fileio
Interface for NAND flash controllers.
Definition: nand/driver.h:23
const char * usage
Usage of flash command registration.
Definition: nand/driver.h:28
const struct command_registration * commands
Definition: nand/driver.h:30
const char * name
Driver name that is used to select it from configuration files.
Definition: nand/driver.h:25
const char * name
Definition: nand/core.h:89
const char * name
Definition: nand/core.h:79
Definition: target.h:120
struct target * get_target(const char *id)
Definition: target.c:492
float duration_elapsed(const struct duration *duration)
Definition: time_support.c:83
float duration_kbps(const struct duration *duration, size_t count)
Definition: time_support.c:90
#define NULL
Definition: usb.h:16
uint8_t cmd
Definition: vdebug.c:1
uint8_t offset[4]
Definition: vdebug.c:9