cf5aa54497423a6e4d785b09da568197638154ce
[fw/openocd] / 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_adi_v5.h"
22 #include "register.h"
23
24 #include <jtag/jtag.h>
25
26 #define MEM_AP_COMMON_MAGIC 0x4DE4DA50
27
28 struct mem_ap {
29         int common_magic;
30         struct adiv5_dap *dap;
31         struct adiv5_ap *ap;
32         uint64_t ap_num;
33 };
34
35 static int mem_ap_target_create(struct target *target, Jim_Interp *interp)
36 {
37         struct mem_ap *mem_ap;
38         struct adiv5_private_config *pc;
39
40         pc = (struct adiv5_private_config *)target->private_config;
41         if (!pc)
42                 return ERROR_FAIL;
43
44         if (pc->ap_num == DP_APSEL_INVALID) {
45                 LOG_ERROR("AP number not specified");
46                 return ERROR_FAIL;
47         }
48
49         mem_ap = calloc(1, sizeof(struct mem_ap));
50         if (!mem_ap) {
51                 LOG_ERROR("Out of memory");
52                 return ERROR_FAIL;
53         }
54
55         mem_ap->ap_num = pc->ap_num;
56         mem_ap->common_magic = MEM_AP_COMMON_MAGIC;
57         mem_ap->dap = pc->dap;
58
59         target->arch_info = mem_ap;
60
61         if (!target->gdb_port_override)
62                 target->gdb_port_override = strdup("disabled");
63
64         return ERROR_OK;
65 }
66
67 static int mem_ap_init_target(struct command_context *cmd_ctx, struct target *target)
68 {
69         LOG_DEBUG("%s", __func__);
70         target->state = TARGET_UNKNOWN;
71         target->debug_reason = DBG_REASON_UNDEFINED;
72         return ERROR_OK;
73 }
74
75 static void mem_ap_deinit_target(struct target *target)
76 {
77         struct mem_ap *mem_ap = target->arch_info;
78
79         LOG_DEBUG("%s", __func__);
80
81         if (mem_ap->ap)
82                 dap_put_ap(mem_ap->ap);
83
84         free(target->private_config);
85         free(target->arch_info);
86         return;
87 }
88
89 static int mem_ap_arch_state(struct target *target)
90 {
91         LOG_DEBUG("%s", __func__);
92         return ERROR_OK;
93 }
94
95 static int mem_ap_poll(struct target *target)
96 {
97         if (target->state == TARGET_UNKNOWN) {
98                 target->state = TARGET_RUNNING;
99                 target->debug_reason = DBG_REASON_NOTHALTED;
100         }
101
102         return ERROR_OK;
103 }
104
105 static int mem_ap_halt(struct target *target)
106 {
107         LOG_DEBUG("%s", __func__);
108         target->state = TARGET_HALTED;
109         target->debug_reason = DBG_REASON_DBGRQ;
110         target_call_event_callbacks(target, TARGET_EVENT_HALTED);
111         return ERROR_OK;
112 }
113
114 static int mem_ap_resume(struct target *target, int current, target_addr_t address,
115                 int handle_breakpoints, int debug_execution)
116 {
117         LOG_DEBUG("%s", __func__);
118         target->state = TARGET_RUNNING;
119         target->debug_reason = DBG_REASON_NOTHALTED;
120         return ERROR_OK;
121 }
122
123 static int mem_ap_step(struct target *target, int current, target_addr_t address,
124                                 int handle_breakpoints)
125 {
126         LOG_DEBUG("%s", __func__);
127         target->state = TARGET_HALTED;
128         target->debug_reason = DBG_REASON_DBGRQ;
129         target_call_event_callbacks(target, TARGET_EVENT_HALTED);
130         return ERROR_OK;
131 }
132
133 static int mem_ap_assert_reset(struct target *target)
134 {
135         target->state = TARGET_RESET;
136         target->debug_reason = DBG_REASON_UNDEFINED;
137
138         LOG_DEBUG("%s", __func__);
139         return ERROR_OK;
140 }
141
142 static int mem_ap_examine(struct target *target)
143 {
144         struct mem_ap *mem_ap = target->arch_info;
145
146         if (!target_was_examined(target)) {
147                 if (mem_ap->ap) {
148                         dap_put_ap(mem_ap->ap);
149                         mem_ap->ap = NULL;
150                 }
151
152                 mem_ap->ap = dap_get_ap(mem_ap->dap, mem_ap->ap_num);
153                 if (!mem_ap->ap) {
154                         LOG_ERROR("Cannot get AP");
155                         return ERROR_FAIL;
156                 }
157                 target_set_examined(target);
158                 target->state = TARGET_UNKNOWN;
159                 target->debug_reason = DBG_REASON_UNDEFINED;
160                 return mem_ap_init(mem_ap->ap);
161         }
162
163         return ERROR_OK;
164 }
165
166 static int mem_ap_deassert_reset(struct target *target)
167 {
168         if (target->reset_halt) {
169                 target->state = TARGET_HALTED;
170                 target->debug_reason = DBG_REASON_DBGRQ;
171                 target_call_event_callbacks(target, TARGET_EVENT_HALTED);
172         } else {
173                 target->state = TARGET_RUNNING;
174                 target->debug_reason = DBG_REASON_NOTHALTED;
175         }
176
177         LOG_DEBUG("%s", __func__);
178         return ERROR_OK;
179 }
180
181 static int mem_ap_reg_get(struct reg *reg)
182 {
183         return ERROR_OK;
184 }
185
186 static int mem_ap_reg_set(struct reg *reg, uint8_t *buf)
187 {
188         return ERROR_OK;
189 }
190
191 static struct reg_arch_type mem_ap_reg_arch_type = {
192         .get = mem_ap_reg_get,
193         .set = mem_ap_reg_set,
194 };
195
196 const char *mem_ap_get_gdb_arch(struct target *target)
197 {
198         return "arm";
199 }
200
201 /*
202  * Dummy ARM register emulation:
203  * reg[0..15]:  32 bits, r0~r12, sp, lr, pc
204  * reg[16..23]: 96 bits, f0~f7
205  * reg[24]:     32 bits, fps
206  * reg[25]:     32 bits, cpsr
207  *
208  * Set 'exist' only to reg[0..15], so initial response to GDB is correct
209  */
210 #define NUM_REGS     26
211 #define MAX_REG_SIZE 96
212 #define REG_EXIST(n) ((n) < 16)
213 #define REG_SIZE(n)  ((((n) >= 16) && ((n) < 24)) ? 96 : 32)
214
215 struct mem_ap_alloc_reg_list {
216         /* reg_list must be the first field */
217         struct reg *reg_list[NUM_REGS];
218         struct reg regs[NUM_REGS];
219         uint8_t regs_value[MAX_REG_SIZE / 8];
220 };
221
222 static int mem_ap_get_gdb_reg_list(struct target *target, struct reg **reg_list[],
223                                 int *reg_list_size, enum target_register_class reg_class)
224 {
225         struct mem_ap_alloc_reg_list *mem_ap_alloc = calloc(1, sizeof(struct mem_ap_alloc_reg_list));
226         if (!mem_ap_alloc) {
227                 LOG_ERROR("Out of memory");
228                 return ERROR_FAIL;
229         }
230
231         *reg_list = mem_ap_alloc->reg_list;
232         *reg_list_size = NUM_REGS;
233         struct reg *regs = mem_ap_alloc->regs;
234
235         for (int i = 0; i < NUM_REGS; i++) {
236                 regs[i].number = i;
237                 regs[i].value = mem_ap_alloc->regs_value;
238                 regs[i].size = REG_SIZE(i);
239                 regs[i].exist = REG_EXIST(i);
240                 regs[i].type = &mem_ap_reg_arch_type;
241                 (*reg_list)[i] = &regs[i];
242         }
243
244         return ERROR_OK;
245 }
246
247 static int mem_ap_read_memory(struct target *target, target_addr_t address,
248                                uint32_t size, uint32_t count, uint8_t *buffer)
249 {
250         struct mem_ap *mem_ap = target->arch_info;
251
252         LOG_DEBUG("Reading memory at physical address " TARGET_ADDR_FMT
253                   "; size %" PRIu32 "; count %" PRIu32, address, size, count);
254
255         if (count == 0 || !buffer)
256                 return ERROR_COMMAND_SYNTAX_ERROR;
257
258         return mem_ap_read_buf(mem_ap->ap, buffer, size, count, address);
259 }
260
261 static int mem_ap_write_memory(struct target *target, target_addr_t address,
262                                 uint32_t size, uint32_t count,
263                                 const uint8_t *buffer)
264 {
265         struct mem_ap *mem_ap = target->arch_info;
266
267         LOG_DEBUG("Writing memory at physical address " TARGET_ADDR_FMT
268                   "; size %" PRIu32 "; count %" PRIu32, address, size, count);
269
270         if (count == 0 || !buffer)
271                 return ERROR_COMMAND_SYNTAX_ERROR;
272
273         return mem_ap_write_buf(mem_ap->ap, buffer, size, count, address);
274 }
275
276 struct target_type mem_ap_target = {
277         .name = "mem_ap",
278
279         .target_create = mem_ap_target_create,
280         .init_target = mem_ap_init_target,
281         .deinit_target = mem_ap_deinit_target,
282         .examine = mem_ap_examine,
283         .target_jim_configure = adiv5_jim_configure,
284
285         .poll = mem_ap_poll,
286         .arch_state = mem_ap_arch_state,
287
288         .halt = mem_ap_halt,
289         .resume = mem_ap_resume,
290         .step = mem_ap_step,
291
292         .assert_reset = mem_ap_assert_reset,
293         .deassert_reset = mem_ap_deassert_reset,
294
295         .get_gdb_arch = mem_ap_get_gdb_arch,
296         .get_gdb_reg_list = mem_ap_get_gdb_reg_list,
297
298         .read_memory = mem_ap_read_memory,
299         .write_memory = mem_ap_write_memory,
300 };