jtag: linuxgpiod: drop extra parenthesis
[openocd.git] / src / target / mem_ap.c
1 /*****************************************************************************
2 * Copyright (C) 2016 by Matthias Welwarsky <matthias.welwarsky@sysgo.com> *
3 * *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
8 * *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
13 ****************************************************************************/
14
15 #ifdef HAVE_CONFIG_H
16 #include "config.h"
17 #endif
18
19 #include "target.h"
20 #include "target_type.h"
21 #include "arm.h"
22 #include "arm_adi_v5.h"
23 #include "register.h"
24
25 #include <jtag/jtag.h>
26
27 struct mem_ap {
28 struct arm arm;
29 struct adiv5_ap *ap;
30 int ap_num;
31 };
32
33 static int mem_ap_target_create(struct target *target, Jim_Interp *interp)
34 {
35 struct mem_ap *mem_ap;
36 struct adiv5_private_config *pc;
37
38 pc = (struct adiv5_private_config *)target->private_config;
39 if (pc == NULL)
40 return ERROR_FAIL;
41
42 if (pc->ap_num == DP_APSEL_INVALID) {
43 LOG_ERROR("AP number not specified");
44 return ERROR_FAIL;
45 }
46
47 mem_ap = calloc(1, sizeof(struct mem_ap));
48 if (mem_ap == NULL) {
49 LOG_ERROR("Out of memory");
50 return ERROR_FAIL;
51 }
52
53 mem_ap->ap_num = pc->ap_num;
54 mem_ap->arm.common_magic = ARM_COMMON_MAGIC;
55 mem_ap->arm.dap = pc->dap;
56
57 target->arch_info = mem_ap;
58
59 if (!target->gdb_port_override)
60 target->gdb_port_override = strdup("disabled");
61
62 return ERROR_OK;
63 }
64
65 static int mem_ap_init_target(struct command_context *cmd_ctx, struct target *target)
66 {
67 LOG_DEBUG("%s", __func__);
68 target->state = TARGET_UNKNOWN;
69 target->debug_reason = DBG_REASON_UNDEFINED;
70 return ERROR_OK;
71 }
72
73 static void mem_ap_deinit_target(struct target *target)
74 {
75 LOG_DEBUG("%s", __func__);
76
77 free(target->private_config);
78 free(target->arch_info);
79 return;
80 }
81
82 static int mem_ap_arch_state(struct target *target)
83 {
84 LOG_DEBUG("%s", __func__);
85 return ERROR_OK;
86 }
87
88 static int mem_ap_poll(struct target *target)
89 {
90 if (target->state == TARGET_UNKNOWN) {
91 target->state = TARGET_RUNNING;
92 target->debug_reason = DBG_REASON_NOTHALTED;
93 }
94
95 return ERROR_OK;
96 }
97
98 static int mem_ap_halt(struct target *target)
99 {
100 LOG_DEBUG("%s", __func__);
101 target->state = TARGET_HALTED;
102 target->debug_reason = DBG_REASON_DBGRQ;
103 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
104 return ERROR_OK;
105 }
106
107 static int mem_ap_resume(struct target *target, int current, target_addr_t address,
108 int handle_breakpoints, int debug_execution)
109 {
110 LOG_DEBUG("%s", __func__);
111 target->state = TARGET_RUNNING;
112 target->debug_reason = DBG_REASON_NOTHALTED;
113 return ERROR_OK;
114 }
115
116 static int mem_ap_step(struct target *target, int current, target_addr_t address,
117 int handle_breakpoints)
118 {
119 LOG_DEBUG("%s", __func__);
120 target->state = TARGET_HALTED;
121 target->debug_reason = DBG_REASON_DBGRQ;
122 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
123 return ERROR_OK;
124 }
125
126 static int mem_ap_assert_reset(struct target *target)
127 {
128 target->state = TARGET_RESET;
129 target->debug_reason = DBG_REASON_UNDEFINED;
130
131 LOG_DEBUG("%s", __func__);
132 return ERROR_OK;
133 }
134
135 static int mem_ap_examine(struct target *target)
136 {
137 struct mem_ap *mem_ap = target->arch_info;
138
139 if (!target_was_examined(target)) {
140 mem_ap->ap = dap_ap(mem_ap->arm.dap, mem_ap->ap_num);
141 target_set_examined(target);
142 target->state = TARGET_UNKNOWN;
143 target->debug_reason = DBG_REASON_UNDEFINED;
144 return mem_ap_init(mem_ap->ap);
145 }
146
147 return ERROR_OK;
148 }
149
150 static int mem_ap_deassert_reset(struct target *target)
151 {
152 if (target->reset_halt) {
153 target->state = TARGET_HALTED;
154 target->debug_reason = DBG_REASON_DBGRQ;
155 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
156 } else {
157 target->state = TARGET_RUNNING;
158 target->debug_reason = DBG_REASON_NOTHALTED;
159 }
160
161 LOG_DEBUG("%s", __func__);
162 return ERROR_OK;
163 }
164
165 static int mem_ap_reg_get(struct reg *reg)
166 {
167 return ERROR_OK;
168 }
169
170 static int mem_ap_reg_set(struct reg *reg, uint8_t *buf)
171 {
172 return ERROR_OK;
173 }
174
175 static struct reg_arch_type mem_ap_reg_arch_type = {
176 .get = mem_ap_reg_get,
177 .set = mem_ap_reg_set,
178 };
179
180 const char *mem_ap_get_gdb_arch(struct target *target)
181 {
182 return "arm";
183 }
184
185 /*
186 * Dummy ARM register emulation:
187 * reg[0..15]: 32 bits, r0~r12, sp, lr, pc
188 * reg[16..23]: 96 bits, f0~f7
189 * reg[24]: 32 bits, fps
190 * reg[25]: 32 bits, cpsr
191 *
192 * Set 'exist' only to reg[0..15], so initial response to GDB is correct
193 */
194 #define NUM_REGS 26
195 #define MAX_REG_SIZE 96
196 #define REG_EXIST(n) ((n) < 16)
197 #define REG_SIZE(n) ((((n) >= 16) && ((n) < 24)) ? 96 : 32)
198
199 struct mem_ap_alloc_reg_list {
200 /* reg_list must be the first field */
201 struct reg *reg_list[NUM_REGS];
202 struct reg regs[NUM_REGS];
203 uint8_t regs_value[MAX_REG_SIZE / 8];
204 };
205
206 static int mem_ap_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
207 int *reg_list_size, enum target_register_class reg_class)
208 {
209 struct mem_ap_alloc_reg_list *mem_ap_alloc = calloc(1, sizeof(struct mem_ap_alloc_reg_list));
210 if (!mem_ap_alloc) {
211 LOG_ERROR("Out of memory");
212 return ERROR_FAIL;
213 }
214
215 *reg_list = mem_ap_alloc->reg_list;
216 *reg_list_size = NUM_REGS;
217 struct reg *regs = mem_ap_alloc->regs;
218
219 for (int i = 0; i < NUM_REGS; i++) {
220 regs[i].number = i;
221 regs[i].value = mem_ap_alloc->regs_value;
222 regs[i].size = REG_SIZE(i);
223 regs[i].exist = REG_EXIST(i);
224 regs[i].type = &mem_ap_reg_arch_type;
225 (*reg_list)[i] = &regs[i];
226 }
227
228 return ERROR_OK;
229 }
230
231 static int mem_ap_read_memory(struct target *target, target_addr_t address,
232 uint32_t size, uint32_t count, uint8_t *buffer)
233 {
234 struct mem_ap *mem_ap = target->arch_info;
235
236 LOG_DEBUG("Reading memory at physical address " TARGET_ADDR_FMT
237 "; size %" PRIu32 "; count %" PRIu32, address, size, count);
238
239 if (count == 0 || buffer == NULL)
240 return ERROR_COMMAND_SYNTAX_ERROR;
241
242 return mem_ap_read_buf(mem_ap->ap, buffer, size, count, address);
243 }
244
245 static int mem_ap_write_memory(struct target *target, target_addr_t address,
246 uint32_t size, uint32_t count,
247 const uint8_t *buffer)
248 {
249 struct mem_ap *mem_ap = target->arch_info;
250
251 LOG_DEBUG("Writing memory at physical address " TARGET_ADDR_FMT
252 "; size %" PRIu32 "; count %" PRIu32, address, size, count);
253
254 if (count == 0 || buffer == NULL)
255 return ERROR_COMMAND_SYNTAX_ERROR;
256
257 return mem_ap_write_buf(mem_ap->ap, buffer, size, count, address);
258 }
259
260 struct target_type mem_ap_target = {
261 .name = "mem_ap",
262
263 .target_create = mem_ap_target_create,
264 .init_target = mem_ap_init_target,
265 .deinit_target = mem_ap_deinit_target,
266 .examine = mem_ap_examine,
267 .target_jim_configure = adiv5_jim_configure,
268
269 .poll = mem_ap_poll,
270 .arch_state = mem_ap_arch_state,
271
272 .halt = mem_ap_halt,
273 .resume = mem_ap_resume,
274 .step = mem_ap_step,
275
276 .assert_reset = mem_ap_assert_reset,
277 .deassert_reset = mem_ap_deassert_reset,
278
279 .get_gdb_arch = mem_ap_get_gdb_arch,
280 .get_gdb_reg_list = mem_ap_get_gdb_reg_list,
281
282 .read_memory = mem_ap_read_memory,
283 .write_memory = mem_ap_write_memory,
284 };

Linking to existing account procedure

If you already have an account and want to add another login method you MUST first sign in with your existing account and then change URL to read https://review.openocd.org/login/?link to get to this page again but this time it'll work for linking. Thank you.

SSH host keys fingerprints

1024 SHA256:YKx8b7u5ZWdcbp7/4AeXNaqElP49m6QrwfXaqQGJAOk gerrit-code-review@openocd.zylin.com (DSA)
384 SHA256:jHIbSQa4REvwCFG4cq5LBlBLxmxSqelQPem/EXIrxjk gerrit-code-review@openocd.org (ECDSA)
521 SHA256:UAOPYkU9Fjtcao0Ul/Rrlnj/OsQvt+pgdYSZ4jOYdgs gerrit-code-review@openocd.org (ECDSA)
256 SHA256:A13M5QlnozFOvTllybRZH6vm7iSt0XLxbA48yfc2yfY gerrit-code-review@openocd.org (ECDSA)
256 SHA256:spYMBqEYoAOtK7yZBrcwE8ZpYt6b68Cfh9yEVetvbXg gerrit-code-review@openocd.org (ED25519)
+--[ED25519 256]--+
|=..              |
|+o..   .         |
|*.o   . .        |
|+B . . .         |
|Bo. = o S        |
|Oo.+ + =         |
|oB=.* = . o      |
| =+=.+   + E     |
|. .=o   . o      |
+----[SHA256]-----+
2048 SHA256:0Onrb7/PHjpo6iVZ7xQX2riKN83FJ3KGU0TvI0TaFG4 gerrit-code-review@openocd.zylin.com (RSA)