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"
38 struct arm_cti_object
{
45 static LIST_HEAD(all_cti
);
47 const char *arm_cti_name(struct arm_cti
*self
)
49 struct arm_cti_object
*obj
= container_of(self
, struct arm_cti_object
, cti
);
53 struct arm_cti
*cti_instance_by_jim_obj(Jim_Interp
*interp
, Jim_Obj
*o
)
55 struct arm_cti_object
*obj
= NULL
;
59 name
= Jim_GetString(o
, NULL
);
61 list_for_each_entry(obj
, &all_cti
, lh
) {
62 if (!strcmp(name
, obj
->name
)) {
73 static int arm_cti_mod_reg_bits(struct arm_cti
*self
, unsigned int reg
, uint32_t mask
, uint32_t value
)
78 int retval
= mem_ap_read_atomic_u32(self
->ap
, self
->base
+ reg
, &tmp
);
79 if (ERROR_OK
!= retval
)
88 return mem_ap_write_atomic_u32(self
->ap
, self
->base
+ reg
, tmp
);
91 int arm_cti_enable(struct arm_cti
*self
, bool enable
)
93 uint32_t val
= enable
? 1 : 0;
95 return mem_ap_write_atomic_u32(self
->ap
, self
->base
+ CTI_CTR
, val
);
98 int arm_cti_ack_events(struct arm_cti
*self
, uint32_t event
)
103 retval
= mem_ap_write_atomic_u32(self
->ap
, self
->base
+ CTI_INACK
, event
);
104 if (retval
== ERROR_OK
) {
105 int64_t then
= timeval_ms();
107 retval
= mem_ap_read_atomic_u32(self
->ap
, self
->base
+ CTI_TROUT_STATUS
, &tmp
);
108 if (retval
!= ERROR_OK
)
110 if ((tmp
& event
) == 0)
112 if (timeval_ms() > then
+ 1000) {
113 LOG_ERROR("timeout waiting for target");
114 retval
= ERROR_TARGET_TIMEOUT
;
123 int arm_cti_gate_channel(struct arm_cti
*self
, uint32_t channel
)
126 return ERROR_COMMAND_ARGUMENT_INVALID
;
128 return arm_cti_mod_reg_bits(self
, CTI_GATE
, CTI_CHNL(channel
), 0);
131 int arm_cti_ungate_channel(struct arm_cti
*self
, uint32_t channel
)
134 return ERROR_COMMAND_ARGUMENT_INVALID
;
136 return arm_cti_mod_reg_bits(self
, CTI_GATE
, CTI_CHNL(channel
), 0xFFFFFFFF);
139 int arm_cti_write_reg(struct arm_cti
*self
, unsigned int reg
, uint32_t value
)
141 return mem_ap_write_atomic_u32(self
->ap
, self
->base
+ reg
, value
);
144 int arm_cti_read_reg(struct arm_cti
*self
, unsigned int reg
, uint32_t *p_value
)
147 return ERROR_COMMAND_ARGUMENT_INVALID
;
149 return mem_ap_read_atomic_u32(self
->ap
, self
->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_object
*obj
, *tmp
;
230 list_for_each_entry_safe(obj
, tmp
, &all_cti
, lh
) {
238 COMMAND_HANDLER(handle_cti_dump
)
240 struct arm_cti_object
*obj
= CMD_DATA
;
241 struct arm_cti
*cti
= &obj
->cti
;
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(cti
->ap
,
246 cti
->base
+ cti_names
[i
].offset
, cti_names
[i
].p_val
);
248 if (retval
== ERROR_OK
)
249 retval
= dap_run(cti
->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_object
*obj
= CMD_DATA
;
264 struct arm_cti
*cti
= &obj
->cti
;
268 return ERROR_COMMAND_SYNTAX_ERROR
;
270 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], on_off
);
272 return arm_cti_enable(cti
, on_off
);
275 COMMAND_HANDLER(handle_cti_testmode
)
277 struct arm_cti_object
*obj
= CMD_DATA
;
278 struct arm_cti
*cti
= &obj
->cti
;
282 return ERROR_COMMAND_SYNTAX_ERROR
;
284 COMMAND_PARSE_ON_OFF(CMD_ARGV
[0], on_off
);
286 return arm_cti_write_reg(cti
, 0xf00, on_off
? 0x1 : 0x0);
289 COMMAND_HANDLER(handle_cti_write
)
291 struct arm_cti_object
*obj
= CMD_DATA
;
292 struct arm_cti
*cti
= &obj
->cti
;
297 return ERROR_COMMAND_SYNTAX_ERROR
;
299 offset
= cti_find_reg_offset(CMD_ARGV
[0]);
303 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[1], value
);
305 return arm_cti_write_reg(cti
, offset
, value
);
308 COMMAND_HANDLER(handle_cti_read
)
310 struct arm_cti_object
*obj
= CMD_DATA
;
311 struct arm_cti
*cti
= &obj
->cti
;
317 return ERROR_COMMAND_SYNTAX_ERROR
;
319 offset
= cti_find_reg_offset(CMD_ARGV
[0]);
323 retval
= arm_cti_read_reg(cti
, offset
, &value
);
324 if (retval
!= ERROR_OK
)
327 command_print(CMD
, "0x%08"PRIx32
, value
);
332 COMMAND_HANDLER(handle_cti_ack
)
334 struct arm_cti_object
*obj
= CMD_DATA
;
335 struct arm_cti
*cti
= &obj
->cti
;
339 return ERROR_COMMAND_SYNTAX_ERROR
;
341 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], event
);
343 int retval
= arm_cti_ack_events(cti
, 1 << event
);
346 if (retval
!= ERROR_OK
)
352 COMMAND_HANDLER(handle_cti_channel
)
354 struct arm_cti_object
*obj
= CMD_DATA
;
355 struct arm_cti
*cti
= &obj
->cti
;
356 int retval
= ERROR_OK
;
360 return ERROR_COMMAND_SYNTAX_ERROR
;
362 COMMAND_PARSE_NUMBER(u32
, CMD_ARGV
[0], ch_num
);
364 if (!strcmp(CMD_ARGV
[1], "gate"))
365 retval
= arm_cti_gate_channel(cti
, ch_num
);
366 else if (!strcmp(CMD_ARGV
[1], "ungate"))
367 retval
= arm_cti_ungate_channel(cti
, ch_num
);
368 else if (!strcmp(CMD_ARGV
[1], "pulse"))
369 retval
= arm_cti_pulse_channel(cti
, ch_num
);
370 else if (!strcmp(CMD_ARGV
[1], "set"))
371 retval
= arm_cti_set_channel(cti
, ch_num
);
372 else if (!strcmp(CMD_ARGV
[1], "clear"))
373 retval
= arm_cti_clear_channel(cti
, ch_num
);
375 command_print(CMD
, "Possible channel operations: gate|ungate|set|clear|pulse");
376 return ERROR_COMMAND_ARGUMENT_INVALID
;
379 if (retval
!= ERROR_OK
)
385 static const struct command_registration cti_instance_command_handlers
[] = {
388 .mode
= COMMAND_EXEC
,
389 .handler
= handle_cti_dump
,
390 .help
= "dump CTI registers",
395 .mode
= COMMAND_EXEC
,
396 .handler
= handle_cti_enable
,
397 .help
= "enable or disable the CTI",
398 .usage
= "'on'|'off'",
402 .mode
= COMMAND_EXEC
,
403 .handler
= handle_cti_testmode
,
404 .help
= "enable or disable integration test mode",
405 .usage
= "'on'|'off'",
409 .mode
= COMMAND_EXEC
,
410 .handler
= handle_cti_write
,
411 .help
= "write to a CTI register",
412 .usage
= "register_name value",
416 .mode
= COMMAND_EXEC
,
417 .handler
= handle_cti_read
,
418 .help
= "read a CTI register",
419 .usage
= "register_name",
423 .mode
= COMMAND_EXEC
,
424 .handler
= handle_cti_ack
,
425 .help
= "acknowledge a CTI event",
430 .mode
= COMMAND_EXEC
,
431 .handler
= handle_cti_channel
,
432 .help
= "do an operation on one CTI channel, possible operations: "
433 "gate, ungate, set, clear and pulse",
434 .usage
= "channel_number operation",
436 COMMAND_REGISTRATION_DONE
445 static const Jim_Nvp nvp_config_opts
[] = {
446 { .name
= "-dap", .value
= CFG_DAP
},
447 { .name
= "-ctibase", .value
= CFG_CTIBASE
},
448 { .name
= "-ap-num", .value
= CFG_AP_NUM
},
449 { .name
= NULL
, .value
= -1 }
452 static int cti_configure(Jim_GetOptInfo
*goi
, struct arm_cti_object
*cti
)
454 struct adiv5_dap
*dap
= NULL
;
459 /* parse config or cget options ... */
460 while (goi
->argc
> 0) {
461 Jim_SetEmptyResult(goi
->interp
);
463 e
= Jim_GetOpt_Nvp(goi
, nvp_config_opts
, &n
);
465 Jim_GetOpt_NvpUnknown(goi
, nvp_config_opts
, 0);
471 e
= Jim_GetOpt_Obj(goi
, &o_t
);
474 dap
= dap_instance_by_jim_obj(goi
->interp
, o_t
);
476 Jim_SetResultString(goi
->interp
, "-dap is invalid", -1);
483 e
= Jim_GetOpt_Wide(goi
, &w
);
486 cti
->cti
.base
= (uint32_t)w
;
491 e
= Jim_GetOpt_Wide(goi
, &w
);
494 if (w
< 0 || w
> DP_APSEL_MAX
) {
495 Jim_SetResultString(goi
->interp
, "-ap-num is invalid", -1);
498 cti
->ap_num
= (uint32_t)w
;
503 Jim_SetResultString(goi
->interp
, "-dap required when creating CTI", -1);
507 cti
->cti
.ap
= dap_ap(dap
, cti
->ap_num
);
512 static int cti_create(Jim_GetOptInfo
*goi
)
514 struct command_context
*cmd_ctx
;
515 static struct arm_cti_object
*cti
;
521 cmd_ctx
= current_command_context(goi
->interp
);
522 assert(cmd_ctx
!= NULL
);
525 Jim_WrongNumArgs(goi
->interp
, 1, goi
->argv
, "?name? ..options...");
529 Jim_GetOpt_Obj(goi
, &new_cmd
);
530 /* does this command exist? */
531 cmd
= Jim_GetCommand(goi
->interp
, new_cmd
, JIM_ERRMSG
);
533 cp
= Jim_GetString(new_cmd
, NULL
);
534 Jim_SetResultFormatted(goi
->interp
, "Command: %s Exists", cp
);
539 cti
= calloc(1, sizeof(struct arm_cti_object
));
543 e
= cti_configure(goi
, cti
);
549 cp
= Jim_GetString(new_cmd
, NULL
);
550 cti
->name
= strdup(cp
);
552 /* now - create the new cti name command */
553 const struct command_registration cti_subcommands
[] = {
555 .chain
= cti_instance_command_handlers
,
557 COMMAND_REGISTRATION_DONE
559 const struct command_registration cti_commands
[] = {
563 .help
= "cti instance command group",
565 .chain
= cti_subcommands
,
567 COMMAND_REGISTRATION_DONE
569 e
= register_commands(cmd_ctx
, NULL
, cti_commands
);
573 struct command
*c
= command_find_in_context(cmd_ctx
, cp
);
575 command_set_handler_data(c
, cti
);
577 list_add_tail(&cti
->lh
, &all_cti
);
579 return (ERROR_OK
== e
) ? JIM_OK
: JIM_ERR
;
582 static int jim_cti_create(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
585 Jim_GetOpt_Setup(&goi
, interp
, argc
- 1, argv
+ 1);
587 Jim_WrongNumArgs(goi
.interp
, goi
.argc
, goi
.argv
,
588 "<name> [<cti_options> ...]");
591 return cti_create(&goi
);
594 static int jim_cti_names(Jim_Interp
*interp
, int argc
, Jim_Obj
*const *argv
)
596 struct arm_cti_object
*obj
;
599 Jim_WrongNumArgs(interp
, 1, argv
, "Too many parameters");
602 Jim_SetResult(interp
, Jim_NewListObj(interp
, NULL
, 0));
603 list_for_each_entry(obj
, &all_cti
, lh
) {
604 Jim_ListAppendElement(interp
, Jim_GetResult(interp
),
605 Jim_NewStringObj(interp
, obj
->name
, -1));
611 static const struct command_registration cti_subcommand_handlers
[] = {
615 .jim_handler
= jim_cti_create
,
616 .usage
= "name '-chain-position' name [options ...]",
617 .help
= "Creates a new CTI object",
622 .jim_handler
= jim_cti_names
,
624 .help
= "Lists all registered CTI objects by name",
626 COMMAND_REGISTRATION_DONE
629 static const struct command_registration cti_command_handlers
[] = {
632 .mode
= COMMAND_CONFIG
,
633 .help
= "CTI commands",
634 .chain
= cti_subcommand_handlers
,
637 COMMAND_REGISTRATION_DONE
640 int cti_register_commands(struct command_context
*cmd_ctx
)
642 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)