OpenOCD
mqx.c
Go to the documentation of this file.
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 
3 /***************************************************************************
4  * Copyright (C) 2014 by Marian Cingel *
5  * cingel.marian@gmail.com *
6  ***************************************************************************/
7 
8 #ifdef HAVE_CONFIG_H
9 #include "config.h"
10 #endif
11 
12 #include <stdint.h>
13 #include <helper/time_support.h>
14 #include <jtag/jtag.h>
15 #include "target/target.h"
16 #include "target/target_type.h"
17 #include "rtos.h"
18 #include "helper/log.h"
19 #include "helper/types.h"
20 #include "rtos_mqx_stackings.h"
21 
22 /* constants */
23 #define MQX_THREAD_NAME_LENGTH (255)
24 #define MQX_KERNEL_OFFSET_TDLIST (0x0108)
25 #define MQX_KERNEL_OFFSET_SYSTEM_TASK (0x0050)
26 #define MQX_KERNEL_OFFSET_ACTIVE_TASK (0x001C)
27 #define MQX_KERNEL_OFFSET_CAPABILITY (0x0000)
28 #define MQX_QUEUE_OFFSET_SIZE (0x0008)
29 #define MQX_TASK_OFFSET_STATE (0x0008)
30 #define MQX_TASK_OFFSET_ID (0x000c)
31 #define MQX_TASK_OFFSET_TEMPLATE (0x0068)
32 #define MQX_TASK_OFFSET_STACK (0x0014)
33 #define MQX_TASK_OFFSET_TDLIST (0x006C)
34 #define MQX_TASK_OFFSET_NEXT (0x0000)
35 #define MQX_TASK_TEMPLATE_OFFSET_NAME (0x0010)
36 #define MQX_TASK_OFFSET_ERROR_CODE (0x005C)
37 #define MQX_TASK_STATE_MASK (0xFFF)
38 
39 /* types */
43 };
44 
45 enum mqx_arch {
47 };
48 
49 struct mqx_params {
50  const char *target_name;
51  const enum mqx_arch target_arch;
53 };
54 
55 struct mqx_state {
56  uint32_t state;
57  char *name;
58 };
59 
60 /* local data */
61 static const struct mqx_state mqx_states[] = {
62  { 0x0002, "READY" },
63  { 0x0003, "BLOCKED" },
64  { 0x0005, "RCV_SPECIFIC_BLOCKED" },
65  { 0x0007, "RCV_ANY_BLOCKED" },
66  { 0x0009, "DYING" },
67  { 0x000B, "UNHANDLED_INT_BLOCKED" },
68  { 0x000D, "SEND_BLOCKED" },
69  { 0x000F, "BREAKPOINT_BLOCKED" },
70  { 0x0211, "IO_BLOCKED" },
71  { 0x0021, "SEM_BLOCKED" },
72  { 0x0223, "MUTEX_BLOCKED" },
73  { 0x0025, "EVENT_BLOCKED" },
74  { 0x0229, "TASK_QUEUE_BLOCKED" },
75  { 0x042B, "LWSEM_BLOCKED" },
76  { 0x042D, "LWEVENT_BLOCKED" },
77 };
78 
79 static const char * const mqx_symbol_list[] = {
80  "_mqx_kernel_data",
81  "MQX_init_struct",
82  NULL
83 };
84 
85 static const struct mqx_params mqx_params_list[] = {
87 };
88 
89 /*
90  * Perform simple address check to avoid bus fault.
91  */
93  struct rtos *rtos,
94  uint32_t address
95 )
96 {
97  enum mqx_arch arch_type = ((struct mqx_params *)rtos->rtos_specific_params)->target_arch;
98  const char *targetname = ((struct mqx_params *)rtos->rtos_specific_params)->target_name;
99 
100  /* Cortex-M address range */
101  if (arch_type == mqx_arch_cortexm) {
102  if (
103  /* code and sram area */
104  (address && address <= 0x3FFFFFFFu) ||
105  /* external ram area*/
106  (address >= 0x6000000u && address <= 0x9FFFFFFFu)
107  ) {
108  return ERROR_OK;
109  }
110  return ERROR_FAIL;
111  }
112  LOG_ERROR("MQX RTOS - unknown architecture %s", targetname);
113  return ERROR_FAIL;
114 }
115 
116 /*
117  * Wrapper of 'target_read_buffer' fn.
118  * Include address check.
119  */
121  struct target *target,
122  uint32_t address,
123  uint32_t size,
124  uint8_t *buffer
125 )
126 {
127  int status = mqx_valid_address_check(target->rtos, address);
128  if (status != ERROR_OK) {
129  LOG_WARNING("MQX RTOS - target address 0x%" PRIx32 " is not allowed to read", address);
130  return status;
131  }
133  if (status != ERROR_OK) {
134  LOG_ERROR("MQX RTOS - reading target address 0x%" PRIx32" failed", address);
135  return status;
136  }
137  return ERROR_OK;
138 }
139 
140 /*
141  * Get symbol address if present
142  */
143 static int mqx_get_symbol(
144  struct rtos *rtos,
145  enum mqx_symbols symbol,
146  void *result
147 )
148 {
149  /* TODO: additional check ?? */
150  (*(int *)result) = (uint32_t)rtos->symbols[symbol].address;
151  return ERROR_OK;
152 }
153 
154 /*
155  * Get value of struct member by passing
156  * member offset, width and name (debug purpose)
157  */
158 static int mqx_get_member(
159  struct rtos *rtos,
160  const uint32_t base_address,
161  int32_t member_offset,
162  int32_t member_width,
163  const char *member_name,
164  void *result
165 )
166 {
167  int status = ERROR_FAIL;
169  rtos->target, base_address + member_offset, member_width, result
170  );
171  if (status != ERROR_OK)
172  LOG_WARNING("MQX RTOS - cannot read \"%s\" at address 0x%" PRIx32,
173  member_name, (uint32_t)(base_address + member_offset));
174  return status;
175 }
176 
177 /*
178  * Check whether scheduler started
179  */
181  struct rtos *rtos
182 )
183 {
184  uint32_t kernel_data_symbol = 0;
185  uint32_t kernel_data_addr = 0;
186  uint32_t system_td_addr = 0;
187  uint32_t active_td_addr = 0;
188  uint32_t capability_value = 0;
189 
190  /* get '_mqx_kernel_data' symbol */
191  if (mqx_get_symbol(rtos, MQX_VAL_MQX_KERNEL_DATA, &kernel_data_symbol) != ERROR_OK)
192  return ERROR_FAIL;
193 
194  /* get '_mqx_kernel_data' */
195  if (mqx_get_member(rtos, kernel_data_symbol, 0, 4,
196  "_mqx_kernel_data", &kernel_data_addr) != ERROR_OK)
197  return ERROR_FAIL;
198 
199  /* return if '_mqx_kernel_data' is NULL or default 0xFFFFFFFF */
200  if (kernel_data_addr == 0 || kernel_data_addr == (uint32_t)(-1))
201  return ERROR_FAIL;
202  /* get kernel_data->ADDRESSING_CAPABILITY */
203  if (mqx_get_member(rtos, kernel_data_addr, MQX_KERNEL_OFFSET_CAPABILITY, 4,
204  "kernel_data->ADDRESSING_CAPABILITY", (void *)&capability_value) != ERROR_OK)
205  return ERROR_FAIL;
206 
207  /* check first member, the '_mqx_kernel_data->ADDRESSING_CAPABILITY'.
208  it suppose to be set to value 8 */
209  if (capability_value != 8) {
210  LOG_WARNING("MQX RTOS - value of '_mqx_kernel_data->ADDRESSING_CAPABILITY' contains invalid value");
211  return ERROR_FAIL;
212  }
213  /* get active ptr */
214  if (mqx_get_member(rtos, kernel_data_addr, MQX_KERNEL_OFFSET_ACTIVE_TASK, 4,
215  "kernel_data->ACTIVE_PTR", (void *)&active_td_addr) != ERROR_OK)
216  return ERROR_FAIL;
217 
218  /* active task is system task, scheduler has not not run yet */
219  system_td_addr = kernel_data_addr + MQX_KERNEL_OFFSET_SYSTEM_TASK;
220  if (active_td_addr == system_td_addr) {
221  LOG_WARNING("MQX RTOS - scheduler does not run");
222  return ERROR_FAIL;
223  }
224  return ERROR_OK;
225 }
226 
227 /*
228  * API function, return true if MQX is present
229  */
230 static bool mqx_detect_rtos(
231  struct target *target
232 )
233 {
234  if (
235  (target->rtos->symbols) &&
237  ) {
238  return true;
239  }
240  return false;
241 }
242 
243 /*
244  * API function, pass MQX extra info to context data
245  */
246 static int mqx_create(
247  struct target *target
248 )
249 {
250  /* check target name against supported architectures */
251  for (unsigned int i = 0; i < ARRAY_SIZE(mqx_params_list); i++) {
252  if (strcmp(mqx_params_list[i].target_name, target->type->name) == 0) {
254  /* LOG_DEBUG("MQX RTOS - valid architecture: %s", target->type->name); */
255  return 0;
256  }
257  }
258  LOG_ERROR("MQX RTOS - could not find target \"%s\" in MQX compatibility list", target->type->name);
259  return -1;
260 }
261 
262 /*
263  * API function, update list of threads
264  */
266  struct rtos *rtos
267 )
268 {
269  uint32_t task_queue_addr = 0;
270  uint32_t kernel_data_addr = 0;
271  uint16_t task_queue_size = 0;
272  uint32_t active_td_addr = 0;
273 
275  return -3;
276 
277  if (!rtos->symbols)
278  return -4;
279 
280  /* clear old data */
282  /* check scheduler */
284  return ERROR_FAIL;
285  /* get kernel_data symbol */
286  if (mqx_get_symbol(rtos, MQX_VAL_MQX_KERNEL_DATA, &kernel_data_addr) != ERROR_OK)
287  return ERROR_FAIL;
288 
289  /* read kernel_data */
290  if (mqx_get_member(rtos, kernel_data_addr, 0, 4,
291  "_mqx_kernel_data", &kernel_data_addr) != ERROR_OK)
292  return ERROR_FAIL;
293 
294  /* get task queue address */
295  task_queue_addr = kernel_data_addr + MQX_KERNEL_OFFSET_TDLIST;
296  /* get task queue size */
297  if (mqx_get_member(rtos, task_queue_addr, MQX_QUEUE_OFFSET_SIZE, 2,
298  "kernel_data->TD_LIST.SIZE", &task_queue_size) != ERROR_OK)
299  return ERROR_FAIL;
300 
301  /* get active ptr */
302  if (mqx_get_member(rtos, kernel_data_addr, MQX_KERNEL_OFFSET_ACTIVE_TASK, 4,
303  "kernel_data->ACTIVE_PTR", (void *)&active_td_addr) != ERROR_OK)
304  return ERROR_FAIL;
305 
306  /* setup threads info */
307  rtos->thread_count = task_queue_size;
308  rtos->current_thread = 0;
309  rtos->thread_details = calloc(rtos->thread_count, sizeof(struct thread_detail));
310  if (!rtos->thread_details)
311  return ERROR_FAIL;
312 
313  /* loop over each task and setup thread details,
314  the current_taskpool_addr is set to queue head
315  NOTE: debugging functions task create/destroy
316  might cause to show invalid data.
317  */
318  for (
319  uint32_t i = 0, taskpool_addr = task_queue_addr;
320  i < (uint32_t)rtos->thread_count;
321  i++
322  ) {
323  uint8_t task_name[MQX_THREAD_NAME_LENGTH + 1];
324  uint32_t task_addr = 0, task_template = 0, task_state = 0;
325  uint32_t task_name_addr = 0, task_id = 0, task_errno = 0;
326  uint32_t state_index = 0;
327  uint32_t extra_info_length = 0;
328  char *state_name = "Unknown";
329 
330  /* set current taskpool address */
331  if (mqx_get_member(rtos, taskpool_addr, MQX_TASK_OFFSET_NEXT, 4,
332  "td_struct_ptr->NEXT", &taskpool_addr) != ERROR_OK)
333  return ERROR_FAIL;
334 
335  /* get task address from taskpool */
336  task_addr = taskpool_addr - MQX_TASK_OFFSET_TDLIST;
337  /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR' */
338  if (mqx_get_member(rtos, task_addr, MQX_TASK_OFFSET_TEMPLATE, 4,
339  "td_struct_ptr->TEMPLATE_LIST_PTR", &task_template) != ERROR_OK)
340  return ERROR_FAIL;
341 
342  /* get address of 'td_struct_ptr->TEMPLATE_LIST_PTR->NAME' */
343  if (mqx_get_member(rtos, task_template, MQX_TASK_TEMPLATE_OFFSET_NAME, 4,
344  "td_struct_ptr->TEMPLATE_LIST_PTR->NAME", &task_name_addr) != ERROR_OK)
345  return ERROR_FAIL;
346 
347  /* get value of 'td_struct->TEMPLATE_LIST_PTR->NAME' */
348  if (mqx_get_member(rtos, task_name_addr, 0, MQX_THREAD_NAME_LENGTH,
349  "*td_struct_ptr->TEMPLATE_LIST_PTR->NAME", task_name) != ERROR_OK)
350  return ERROR_FAIL;
351 
352  /* always terminate last character by force,
353  otherwise openocd might fail if task_name
354  has corrupted data */
355  task_name[MQX_THREAD_NAME_LENGTH] = '\0';
356  /* get value of 'td_struct_ptr->TASK_ID' */
357  if (mqx_get_member(rtos, task_addr, MQX_TASK_OFFSET_ID, 4,
358  "td_struct_ptr->TASK_ID", &task_id) != ERROR_OK)
359  return ERROR_FAIL;
360 
361  /* get task errno */
363  "td_struct_ptr->TASK_ERROR_CODE", &task_errno) != ERROR_OK)
364  return ERROR_FAIL;
365 
366  /* get value of 'td_struct_ptr->STATE' */
367  if (mqx_get_member(rtos, task_addr, MQX_TASK_OFFSET_STATE, 4,
368  "td_struct_ptr->STATE", &task_state) != ERROR_OK)
369  return ERROR_FAIL;
370 
371  task_state &= MQX_TASK_STATE_MASK;
372  /* and search for defined state */
373  for (state_index = 0; state_index < ARRAY_SIZE(mqx_states); state_index++) {
374  if (mqx_states[state_index].state == task_state) {
375  state_name = mqx_states[state_index].name;
376  break;
377  }
378  }
379 
380  /* setup thread details struct */
381  rtos->thread_details[i].threadid = task_id;
382  rtos->thread_details[i].exists = true;
383  /* set thread name */
384  rtos->thread_details[i].thread_name_str = malloc(strlen((void *)task_name) + 1);
386  return ERROR_FAIL;
387  strcpy(rtos->thread_details[i].thread_name_str, (void *)task_name);
388  /* set thread extra info
389  * - task state
390  * - task address
391  * - task errno
392  * calculate length as:
393  * state length + address length + errno length + formatter length
394  */
395  extra_info_length += strlen((void *)state_name) + 7 + 13 + 8 + 15 + 8;
396  rtos->thread_details[i].extra_info_str = malloc(extra_info_length + 1);
398  return ERROR_FAIL;
399  snprintf(rtos->thread_details[i].extra_info_str, extra_info_length,
400  "State: %s, Address: 0x%" PRIx32 ", Error Code: %" PRIu32,
401  state_name, task_addr, task_errno
402  );
403  /* set active thread */
404  if (active_td_addr == task_addr)
405  rtos->current_thread = task_id;
406  }
407  return ERROR_OK;
408 }
409 
410 /*
411  * API function, get info of selected thread
412  */
414  struct rtos *rtos,
415  int64_t thread_id,
416  struct rtos_reg **reg_list,
417  int *num_regs
418 )
419 {
420  int64_t stack_ptr = 0;
421  uint32_t my_task_addr = 0;
422  uint32_t task_queue_addr = 0;
423  uint32_t task_queue_size = 0;
424  uint32_t kernel_data_addr = 0;
425 
426  if (thread_id == 0) {
427  LOG_ERROR("MQX RTOS - invalid threadid: 0x%X", (int)thread_id);
428  return ERROR_FAIL;
429  }
431  return ERROR_FAIL;
432  /* get kernel_data symbol */
433  if (mqx_get_symbol(rtos, MQX_VAL_MQX_KERNEL_DATA, &kernel_data_addr) != ERROR_OK)
434  return ERROR_FAIL;
435 
436  /* read kernel_data */
437  if (mqx_get_member(rtos, kernel_data_addr, 0, 4,
438  "_mqx_kernel_data", &kernel_data_addr) != ERROR_OK)
439  return ERROR_FAIL;
440 
441  /* get task queue address */
442  task_queue_addr = kernel_data_addr + MQX_KERNEL_OFFSET_TDLIST;
443  /* get task queue size */
444  if (mqx_get_member(rtos, task_queue_addr, MQX_QUEUE_OFFSET_SIZE, 2,
445  "kernel_data->TD_LIST.SIZE", &task_queue_size) != ERROR_OK)
446  return ERROR_FAIL;
447 
448  /* search for taskid */
449  for (
450  uint32_t i = 0, taskpool_addr = task_queue_addr;
451  i < (uint32_t)rtos->thread_count;
452  i++
453  ) {
454  uint32_t tmp_address = 0, task_addr = 0;
455  uint32_t task_id = 0;
456  /* set current taskpool address */
457  tmp_address = taskpool_addr;
458  if (mqx_get_member(rtos, tmp_address, MQX_TASK_OFFSET_NEXT, 4,
459  "td_struct_ptr->NEXT", &taskpool_addr) != ERROR_OK)
460  return ERROR_FAIL;
461 
462  /* get task address from taskpool */
463  task_addr = taskpool_addr - MQX_TASK_OFFSET_TDLIST;
464  /* get value of td_struct->TASK_ID */
465  if (mqx_get_member(rtos, task_addr, MQX_TASK_OFFSET_ID, 4,
466  "td_struct_ptr->TASK_ID", &task_id) != ERROR_OK)
467  return ERROR_FAIL;
468 
469  /* found taskid, break */
470  if (task_id == thread_id) {
471  my_task_addr = task_addr;
472  break;
473  }
474  }
475  if (!my_task_addr) {
476  LOG_ERROR("MQX_RTOS - threadid %" PRId64 " does not match any task", thread_id);
477  return ERROR_FAIL;
478  }
479  /* get task stack head address */
480  if (mqx_get_member(rtos, my_task_addr, MQX_TASK_OFFSET_STACK, 4,
481  "task->STACK_PTR", &stack_ptr) != ERROR_OK)
482  return ERROR_FAIL;
483 
485  rtos->target, ((struct mqx_params *)rtos->rtos_specific_params)->stacking_info, stack_ptr, reg_list, num_regs
486  );
487 }
488 
489 /* API function, export list of required symbols */
490 static int mqx_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
491 {
492  *symbol_list = calloc(ARRAY_SIZE(mqx_symbol_list), sizeof(struct symbol_table_elem));
493  if (!*symbol_list)
494  return ERROR_FAIL;
495  /* export required symbols */
496  for (int i = 0; i < (int)(ARRAY_SIZE(mqx_symbol_list)); i++)
497  (*symbol_list)[i].symbol_name = mqx_symbol_list[i];
498  return ERROR_OK;
499 }
500 
501 struct rtos_type mqx_rtos = {
502  .name = "mqx",
503  .detect_rtos = mqx_detect_rtos,
504  .create = mqx_create,
505  .update_threads = mqx_update_threads,
506  .get_thread_reg_list = mqx_get_thread_reg_list,
507  .get_symbol_list_to_lookup = mqx_get_symbol_list_to_lookup,
508 };
The JTAG interface can be implemented with a software or hardware fifo.
#define LOG_WARNING(expr ...)
Definition: log.h:120
#define ERROR_FAIL
Definition: log.h:161
#define LOG_ERROR(expr ...)
Definition: log.h:123
#define ERROR_OK
Definition: log.h:155
static int mqx_target_read_buffer(struct target *target, uint32_t address, uint32_t size, uint8_t *buffer)
Definition: mqx.c:120
#define MQX_KERNEL_OFFSET_SYSTEM_TASK
Definition: mqx.c:25
#define MQX_TASK_OFFSET_STATE
Definition: mqx.c:29
static int mqx_get_thread_reg_list(struct rtos *rtos, int64_t thread_id, struct rtos_reg **reg_list, int *num_regs)
Definition: mqx.c:413
#define MQX_TASK_OFFSET_ERROR_CODE
Definition: mqx.c:36
#define MQX_KERNEL_OFFSET_CAPABILITY
Definition: mqx.c:27
#define MQX_TASK_OFFSET_NEXT
Definition: mqx.c:34
#define MQX_THREAD_NAME_LENGTH
Definition: mqx.c:23
static int mqx_is_scheduler_running(struct rtos *rtos)
Definition: mqx.c:180
static int mqx_get_symbol_list_to_lookup(struct symbol_table_elem *symbol_list[])
Definition: mqx.c:490
static int mqx_get_symbol(struct rtos *rtos, enum mqx_symbols symbol, void *result)
Definition: mqx.c:143
#define MQX_TASK_TEMPLATE_OFFSET_NAME
Definition: mqx.c:35
static const struct mqx_params mqx_params_list[]
Definition: mqx.c:85
#define MQX_TASK_OFFSET_ID
Definition: mqx.c:30
mqx_symbols
Definition: mqx.c:40
@ MQX_VAL_MQX_INIT_STRUCT
Definition: mqx.c:42
@ MQX_VAL_MQX_KERNEL_DATA
Definition: mqx.c:41
static int mqx_get_member(struct rtos *rtos, const uint32_t base_address, int32_t member_offset, int32_t member_width, const char *member_name, void *result)
Definition: mqx.c:158
#define MQX_TASK_OFFSET_TEMPLATE
Definition: mqx.c:31
#define MQX_TASK_STATE_MASK
Definition: mqx.c:37
static int mqx_valid_address_check(struct rtos *rtos, uint32_t address)
Definition: mqx.c:92
static const struct mqx_state mqx_states[]
Definition: mqx.c:61
static int mqx_update_threads(struct rtos *rtos)
Definition: mqx.c:265
static int mqx_create(struct target *target)
Definition: mqx.c:246
#define MQX_KERNEL_OFFSET_TDLIST
Definition: mqx.c:24
static const char *const mqx_symbol_list[]
Definition: mqx.c:79
struct rtos_type mqx_rtos
Definition: mqx.c:501
#define MQX_TASK_OFFSET_STACK
Definition: mqx.c:32
mqx_arch
Definition: mqx.c:45
@ mqx_arch_cortexm
Definition: mqx.c:46
#define MQX_TASK_OFFSET_TDLIST
Definition: mqx.c:33
#define MQX_KERNEL_OFFSET_ACTIVE_TASK
Definition: mqx.c:26
static bool mqx_detect_rtos(struct target *target)
Definition: mqx.c:230
#define MQX_QUEUE_OFFSET_SIZE
Definition: mqx.c:28
int rtos_generic_stack_read(struct target *target, const struct rtos_register_stacking *stacking, int64_t stack_ptr, struct rtos_reg **reg_list, int *num_regs)
Definition: rtos.c:617
void rtos_free_threadlist(struct rtos *rtos)
Definition: rtos.c:707
const struct rtos_register_stacking rtos_mqx_arm_v7m_stacking
size_t size
Size of the control block search area.
Definition: rtt/rtt.c:30
Definition: mqx.c:49
const struct rtos_register_stacking * stacking_info
Definition: mqx.c:52
enum mqx_arch target_arch
Definition: mqx.c:51
const char * target_name
Definition: mqx.c:50
Definition: mqx.c:55
char * name
Definition: mqx.c:57
uint32_t state
Definition: mqx.c:56
Definition: rtos.h:53
Definition: rtos.h:59
const char * name
Definition: rtos.h:60
Definition: rtos.h:36
int thread_count
Definition: rtos.h:47
struct thread_detail * thread_details
Definition: rtos.h:46
struct symbol_table_elem * symbols
Definition: rtos.h:39
struct target * target
Definition: rtos.h:40
void * rtos_specific_params
Definition: rtos.h:50
threadid_t current_thread
Definition: rtos.h:45
Table should be terminated by an element with NULL in symbol_name.
Definition: rtos.h:23
symbol_address_t address
Definition: rtos.h:25
const char * name
Name of this type of target.
Definition: target_type.h:31
Definition: target.h:120
struct rtos * rtos
Definition: target.h:188
struct target_type * type
Definition: target.h:121
char * extra_info_str
Definition: rtos.h:33
char * thread_name_str
Definition: rtos.h:32
bool exists
Definition: rtos.h:31
threadid_t threadid
Definition: rtos.h:30
int target_read_buffer(struct target *target, target_addr_t address, uint32_t size, uint8_t *buffer)
Definition: target.c:2473
static const char * target_name(struct target *target)
Returns the instance-specific name of the specified target.
Definition: target.h:234
#define ARRAY_SIZE(x)
Compute the number of elements of a variable length array.
Definition: types.h:57
#define NULL
Definition: usb.h:16
uint8_t status[4]
Definition: vdebug.c:17
uint8_t state[4]
Definition: vdebug.c:21