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