1 /***************************************************************************
2 * Copyright (C) 2016 by Matthias Welwarsky *
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. *
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. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
18 ***************************************************************************/
26 #include "target/arm_adi_v5.h"
27 #include "target/arm_cti.h"
28 #include "target/target.h"
29 #include "helper/time_support.h"
30 #include "helper/list.h"
31 #include "helper/command.h"
36 struct adiv5_mem_ap_spot spot
;
39 static LIST_HEAD(all_cti
);
41 const char *arm_cti_name(struct arm_cti
*self
)
46 struct arm_cti
*cti_instance_by_jim_obj(Jim_Interp
*interp
, Jim_Obj
*o
)
48 struct arm_cti
*obj
= NULL
;
52 name
= Jim_GetString(o
, NULL
);
54 list_for_each_entry(obj
, &all_cti
, lh
) {
55 if (!strcmp(name
, obj
->name
)) {
66 static int arm_cti_mod_reg_bits(struct arm_cti
*self
, unsigned int reg
, uint32_t mask
, uint32_t value
)
68 struct adiv5_ap
*ap
= dap_ap(self
->spot
.dap
, self
->spot
.ap_num
);
72 int retval
= mem_ap_read_atomic_u32(ap
, self
->spot
.base
+ reg
, &tmp
);
73 if (ERROR_OK
!= retval
)
82 return mem_ap_write_atomic_u32(ap
, self
->spot
.base
+ reg
, tmp
);
85 int arm_cti_enable(struct arm_cti
*self
, bool enable
)
87 struct adiv5_ap
*ap
= dap_ap(self
->spot
.dap
, self
->spot
.ap_num
);
88 uint32_t val
= enable
? 1 : 0;
90 return mem_ap_write_atomic_u32(ap
, self
->spot
.base
+ CTI_CTR
, val
);
93 int arm_cti_ack_events(struct arm_cti
*self
, uint32_t event
)
95 struct adiv5_ap
*ap
= dap_ap(self
->spot
.dap
, self
->spot
.ap_num
);
99 retval
= mem_ap_write_atomic_u32(ap
, self
->spot
.base
+ CTI_INACK
, event
);
100 if (retval
== ERROR_OK
) {
101 int64_t then
= timeval_ms();
103 retval
= mem_ap_read_atomic_u32(ap
, self
->spot
.base
+ CTI_TROUT_STATUS
, &tmp
);
104 if (retval
!= ERROR_OK
)
106 if ((tmp
& event
) == 0)
108 if (timeval_ms() > then
+ 1000) {
109 LOG_ERROR("timeout waiting for target");
110 retval
= ERROR_TARGET_TIMEOUT
;
119 int arm_cti_gate_channel(struct arm_cti
*self
, uint32_t channel
)
122 return ERROR_COMMAND_ARGUMENT_INVALID
;
124 return arm_cti_mod_reg_bits(self
, CTI_GATE
, CTI_CHNL(channel
), 0);
127 int arm_cti_ungate_channel(struct arm_cti
*self
, uint32_t channel
)
130 return ERROR_COMMAND_ARGUMENT_INVALID
;
132 return arm_cti_mod_reg_bits(self
, CTI_GATE
, CTI_CHNL(channel
), 0xFFFFFFFF);
135 int arm_cti_write_reg(struct arm_cti
*self
, unsigned int reg
, uint32_t value
)
137 struct adiv5_ap
*ap
= dap_ap(self
->spot
.dap
, self
->spot
.ap_num
);
139 return mem_ap_write_atomic_u32(ap
, self
->spot
.base
+ reg
, value
);
142 int arm_cti_read_reg(struct arm_cti
*self
, unsigned int reg
, uint32_t *p_value
)
144 struct adiv5_ap
*ap
= dap_ap(self
->spot
.dap
, self
->spot
.ap_num
);
147 return ERROR_COMMAND_ARGUMENT_INVALID
;
149 return mem_ap_read_atomic_u32(ap
, self
->spot
.base
+ reg
, p_value
);
152 int arm_cti_pulse_channel(struct arm_cti
*self
, uint32_t channel
)
155 return ERROR_COMMAND_ARGUMENT_INVALID
;
157 return arm_cti_write_reg(self
, CTI_APPPULSE
, CTI_CHNL(channel
));
160 int arm_cti_set_channel(struct arm_cti
*self
, uint32_t channel
)
163 return ERROR_COMMAND_ARGUMENT_INVALID
;
165 return arm_cti_write_reg(self
, CTI_APPSET
, CTI_CHNL(channel
));
168 int arm_cti_clear_channel(struct arm_cti
*self
, uint32_t channel
)
171 return ERROR_COMMAND_ARGUMENT_INVALID
;
173 return arm_cti_write_reg(self
, CTI_APPCLEAR
, CTI_CHNL(channel
));
176 static uint32_t cti_regs
[28];
178 static const struct {
183 { CTI_CTR
, "CTR", &cti_regs
[0] },
184 { CTI_GATE
, "GATE", &cti_regs
[1] },
185 { CTI_INEN0
, "INEN0", &cti_regs
[2] },
186 { CTI_INEN1
, "INEN1", &cti_regs
[3] },
187 { CTI_INEN2
, "INEN2", &cti_regs
[4] },
188 { CTI_INEN3
, "INEN3", &cti_regs
[5] },
189 { CTI_INEN4
, "INEN4", &cti_regs
[6] },
190 { CTI_INEN5
, "INEN5", &cti_regs
[7] },
191 { CTI_INEN6
, "INEN6", &cti_regs
[8] },
192 { CTI_INEN7
, "INEN7", &cti_regs
[9] },
193 { CTI_INEN8
, "INEN8", &cti_regs
[10] },
194 { CTI_OUTEN0
, "OUTEN0", &cti_regs
[11] },
195 { CTI_OUTEN1
, "OUTEN1", &cti_regs
[12] },
196 { CTI_OUTEN2
, "OUTEN2", &cti_regs
[13] },
197 { CTI_OUTEN3
, "OUTEN3", &cti_regs
[14] },
198 { CTI_OUTEN4
, "OUTEN4", &cti_regs
[15] },
199 { CTI_OUTEN5
, "OUTEN5", &cti_regs
[16] },
200 { CTI_OUTEN6
, "OUTEN6", &cti_regs
[17] },
201 { CTI_OUTEN7
, "OUTEN7", &cti_regs
[18] },
202 { CTI_OUTEN8
, "OUTEN8", &cti_regs
[19] },
203 { CTI_TRIN_STATUS
, "TRIN", &cti_regs
[20] },
204 { CTI_TROUT_STATUS
, "TROUT", &cti_regs
[21] },
205 { CTI_CHIN_STATUS
, "CHIN", &cti_regs
[22] },
206 { CTI_CHOU_STATUS
, "CHOUT", &cti_regs
[23] },
207 { CTI_APPSET
, "APPSET", &cti_regs
[24] },
208 { CTI_APPCLEAR
, "APPCLR", &cti_regs
[25] },
209 { CTI_APPPULSE
, "APPPULSE", &cti_regs
[26] },
210 { CTI_INACK
, "INACK", &cti_regs
[27] },
213 static int cti_find_reg_offset(const char *name
)
217 for (i
= 0; i
< ARRAY_SIZE(cti_names
); i
++) {
218 if (!strcmp(name
, cti_names
[i
].label
))
219 return cti_names
[i
].offset
;
222 LOG_ERROR("unknown CTI register %s", name
);
226 int arm_cti_cleanup_all(void)
228 struct arm_cti
*obj
, *tmp
;
230 list_for_each_entry_safe(obj
, tmp
, &all_cti
, lh
) {
238 COMMAND_HANDLER(handle_cti_dump
)
240 struct arm_cti
*cti
= CMD_DATA
;
241 struct adiv5_ap
*ap
= dap_ap(cti
->spot
.dap
, cti
->spot
.ap_num
);
242 int retval
= ERROR_OK
;
244 for (int i
= 0; (retval
== ERROR_OK
) && (i
< (int)ARRAY_SIZE(cti_names
)); i
++)
245 retval
= mem_ap_read_u32(ap
,
246 cti
->spot
.base
+ cti_names
[i
].offset
, cti_names
[i
].p_val
);
248 if (retval
== ERROR_OK
)
249 retval
= dap_run(ap
->dap
);
251 if (retval
!= ERROR_OK
)
254 for (int i
= 0; i
< (int)ARRAY_SIZE(cti_names
); i
++)
255 command_print(CMD
, "%8.8s (0x%04"PRIx32
") 0x%08"PRIx32
,
256 cti_names
[i
].label
, cti_names
[i
].offset
, *cti_names
[i
].p_val
);
261 COMMAND_HANDLER(handle_cti_enable
)
263 struct arm_cti
*cti
= CMD_DATA
;
267 return ERROR_COMMAND_SYNTAX_ERROR
;
269 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], on_off
);
271 return arm_cti_enable(cti
, on_off
);
274 COMMAND_HANDLER(handle_cti_testmode
)
276 struct arm_cti
*cti
= CMD_DATA
;
280 return ERROR_COMMAND_SYNTAX_ERROR
;
282 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], on_off
);
284 return arm_cti_write_reg(cti
, 0xf00, on_off
? 0x1 : 0x0);
287 COMMAND_HANDLER(handle_cti_write
)
289 struct arm_cti
*cti
= CMD_DATA
;
294 return ERROR_COMMAND_SYNTAX_ERROR
;
296 offset
= cti_find_reg_offset(CMD_ARGV
[0]);
300 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], value
);
302 return arm_cti_write_reg(cti
, offset
, value
);
305 COMMAND_HANDLER(handle_cti_read
)
307 struct arm_cti
*cti
= CMD_DATA
;
313 return ERROR_COMMAND_SYNTAX_ERROR
;
315 offset
= cti_find_reg_offset(CMD_ARGV
[0]);
319 retval
= arm_cti_read_reg(cti
, offset
, &value
);
320 if (retval
!= ERROR_OK
)
323 command_print(CMD
, "0x%08"PRIx32
, value
);
328 COMMAND_HANDLER(handle_cti_ack
)
330 struct arm_cti
*cti
= CMD_DATA
;
334 return ERROR_COMMAND_SYNTAX_ERROR
;
336 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], event
);
338 int retval
= arm_cti_ack_events(cti
, 1 << event
);
341 if (retval
!= ERROR_OK
)
347 COMMAND_HANDLER(handle_cti_channel
)
349 struct arm_cti
*cti
= CMD_DATA
;
350 int retval
= ERROR_OK
;
354 return ERROR_COMMAND_SYNTAX_ERROR
;
356 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], ch_num
);
358 if (!strcmp(CMD_ARGV
[1], "gate"))
359 retval
= arm_cti_gate_channel(cti
, ch_num
);
360 else if (!strcmp(CMD_ARGV
[1], "ungate"))
361 retval
= arm_cti_ungate_channel(cti
, ch_num
);
362 else if (!strcmp(CMD_ARGV
[1], "pulse"))
363 retval
= arm_cti_pulse_channel(cti
, ch_num
);
364 else if (!strcmp(CMD_ARGV
[1], "set"))
365 retval
= arm_cti_set_channel(cti
, ch_num
);
366 else if (!strcmp(CMD_ARGV
[1], "clear"))
367 retval
= arm_cti_clear_channel(cti
, ch_num
);
369 command_print(CMD
, "Possible channel operations: gate|ungate|set|clear|pulse");
370 return ERROR_COMMAND_ARGUMENT_INVALID
;
373 if (retval
!= ERROR_OK
)
379 static const struct command_registration cti_instance_command_handlers
[] = {
382 .mode
= COMMAND_EXEC
,
383 .handler
= handle_cti_dump
,
384 .help
= "dump CTI registers",
389 .mode
= COMMAND_EXEC
,
390 .handler
= handle_cti_enable
,
391 .help
= "enable or disable the CTI",
392 .usage
= "'on'|'off'",
396 .mode
= COMMAND_EXEC
,
397 .handler
= handle_cti_testmode
,
398 .help
= "enable or disable integration test mode",
399 .usage
= "'on'|'off'",
403 .mode
= COMMAND_EXEC
,
404 .handler
= handle_cti_write
,
405 .help
= "write to a CTI register",
406 .usage
= "register_name value",
410 .mode
= COMMAND_EXEC
,
411 .handler
= handle_cti_read
,
412 .help
= "read a CTI register",
413 .usage
= "register_name",
417 .mode
= COMMAND_EXEC
,
418 .handler
= handle_cti_ack
,
419 .help
= "acknowledge a CTI event",
424 .mode
= COMMAND_EXEC
,
425 .handler
= handle_cti_channel
,
426 .help
= "do an operation on one CTI channel, possible operations: "
427 "gate, ungate, set, clear and pulse",
428 .usage
= "channel_number operation",
430 COMMAND_REGISTRATION_DONE
433 static int cti_configure(Jim_GetOptInfo
*goi
, struct arm_cti
*cti
)
435 /* parse config or cget options ... */
436 while (goi
->argc
> 0) {
437 int e
= adiv5_jim_mem_ap_spot_configure(&cti
->spot
, goi
);
442 if (!cti
->spot
.dap
) {
443 Jim_SetResultString(goi
->interp
, "-dap required when creating CTI", -1);
449 static int cti_create(Jim_GetOptInfo
*goi
)
451 struct command_context
*cmd_ctx
;
452 static struct arm_cti
*cti
;
458 cmd_ctx
= current_command_context(goi
->interp
);
459 assert(cmd_ctx
!= NULL
);
462 Jim_WrongNumArgs(goi
->interp
, 1, goi
->argv
, "?name? ..options...");
466 Jim_GetOpt_Obj(goi
, &new_cmd
);
467 /* does this command exist? */
468 cmd
= Jim_GetCommand(goi
->interp
, new_cmd
, JIM_ERRMSG
);
470 cp
= Jim_GetString(new_cmd
, NULL
);
471 Jim_SetResultFormatted(goi
->interp
, "Command: %s Exists", cp
);
476 cti
= calloc(1, sizeof(*cti
));
480 adiv5_mem_ap_spot_init(&cti
->spot
);
482 /* Do the rest as "configure" options */
483 goi
->isconfigure
= 1;
484 e
= cti_configure(goi
, cti
);
490 cp
= Jim_GetString(new_cmd
, NULL
);
491 cti
->name
= strdup(cp
);
493 /* now - create the new cti name command */
494 const struct command_registration cti_subcommands
[] = {
496 .chain
= cti_instance_command_handlers
,
498 COMMAND_REGISTRATION_DONE
500 const struct command_registration cti_commands
[] = {
504 .help
= "cti instance command group",
506 .chain
= cti_subcommands
,
508 COMMAND_REGISTRATION_DONE
510 e
= register_commands(cmd_ctx
, NULL
, cti_commands
);
514 struct command
*c
= command_find_in_context(cmd_ctx
, cp
);
516 command_set_handler_data(c
, cti
);
518 list_add_tail(&cti
->lh
, &all_cti
);
520 return (ERROR_OK
== e
) ? JIM_OK
: JIM_ERR
;
523 static int jim_cti_create(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
526 Jim_GetOpt_Setup(&goi
, interp
, argc
- 1, argv
+ 1);
528 Jim_WrongNumArgs(goi
.interp
, goi
.argc
, goi
.argv
,
529 "<name> [<cti_options> ...]");
532 return cti_create(&goi
);
535 static int jim_cti_names(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
540 Jim_WrongNumArgs(interp
, 1, argv
, "Too many parameters");
543 Jim_SetResult(interp
, Jim_NewListObj(interp
, NULL
, 0));
544 list_for_each_entry(obj
, &all_cti
, lh
) {
545 Jim_ListAppendElement(interp
, Jim_GetResult(interp
),
546 Jim_NewStringObj(interp
, obj
->name
, -1));
552 static const struct command_registration cti_subcommand_handlers
[] = {
556 .jim_handler
= jim_cti_create
,
557 .usage
= "name '-chain-position' name [options ...]",
558 .help
= "Creates a new CTI object",
563 .jim_handler
= jim_cti_names
,
565 .help
= "Lists all registered CTI objects by name",
567 COMMAND_REGISTRATION_DONE
570 static const struct command_registration cti_command_handlers
[] = {
573 .mode
= COMMAND_CONFIG
,
574 .help
= "CTI commands",
575 .chain
= cti_subcommand_handlers
,
578 COMMAND_REGISTRATION_DONE
581 int cti_register_commands(struct command_context
*cmd_ctx
)
583 return register_commands(cmd_ctx
, NULL
, cti_command_handlers
);
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)