1 // SPDX-License-Identifier: GPL-2.0-or-later
3 /***************************************************************************
4 * Copyright (C) 2016-2023 by Andreas Fritiofson *
5 * andreas.fritiofson@gmail.com *
6 ***************************************************************************/
12 #include <helper/time_support.h>
13 #include <jtag/jtag.h>
14 #include "target/target.h"
15 #include "target/target_type.h"
17 #include "helper/log.h"
18 #include "helper/types.h"
19 #include "rtos_standard_stackings.h"
20 #include "target/armv7m.h"
21 #include "target/cortex_m.h"
23 #define ST_DEAD BIT(0) /* Task is waiting to be deleted */
24 #define ST_WAIT BIT(1) /* Task is blocked: */
25 #define ST_SEM BIT(2) /* on semaphore */
26 #define ST_MTX BIT(3) /* on mutex */
27 #define ST_SIG BIT(4) /* on signal */
28 #define ST_DLY BIT(5) /* on timer */
29 #define ST_FLAG BIT(6) /* on flag */
30 #define ST_FLAG_ALL BIT(7) /* on flag and flag mode is "ALL" */
31 #define ST_MBOX BIT(8) /* on mailbox */
32 #define ST_STP BIT(9) /* self stopped */
33 #define ST_SUSPEND BIT(10) /* Task is suspended */
34 #define ST_TT BIT(11) /* Time triggered task */
35 #define ST_TT_YIELD BIT(12) /* Time triggered task that yields */
36 #define ST_CREATE BIT(13) /* Task was created by task_create() */
38 struct rtkernel_params
{
39 const char *target_name
;
40 const struct rtos_register_stacking
*stacking_info_cm3
;
41 const struct rtos_register_stacking
*stacking_info_cm4f
;
42 const struct rtos_register_stacking
*stacking_info_cm4f_fpu
;
45 static const struct rtkernel_params rtkernel_params_list
[] = {
47 "cortex_m", /* target_name */
48 &rtos_standard_cortex_m3_stacking
, /* stacking_info */
49 &rtos_standard_cortex_m4f_stacking
,
50 &rtos_standard_cortex_m4f_fpu_stacking
,
53 "hla_target", /* target_name */
54 &rtos_standard_cortex_m3_stacking
, /* stacking_info */
55 &rtos_standard_cortex_m4f_stacking
,
56 &rtos_standard_cortex_m4f_fpu_stacking
,
60 enum rtkernel_symbol_values
{
62 sym___off_os_state2chain
= 1,
63 sym___off_os_state2current
= 2,
64 sym___off_task2chain
= 3,
65 sym___off_task2magic
= 4,
66 sym___off_task2stack
= 5,
67 sym___off_task2state
= 6,
68 sym___off_task2name
= 7,
69 sym___val_task_magic
= 8,
77 static const struct symbols rtkernel_symbol_list
[] = {
78 { "os_state", false },
79 { "__off_os_state2chain", false },
80 { "__off_os_state2current", false },
81 { "__off_task2chain", false },
82 { "__off_task2magic", false },
83 { "__off_task2stack", false },
84 { "__off_task2state", false },
85 { "__off_task2name", false },
86 { "__val_task_magic", false },
90 static void *realloc_preserve(void *ptr
, size_t old_size
, size_t new_size
)
92 void *new_ptr
= malloc(new_size
);
95 memcpy(new_ptr
, ptr
, MIN(old_size
, new_size
));
102 static int rtkernel_add_task(struct rtos
*rtos
, uint32_t task
, uint32_t current_task
)
105 int new_thread_count
= rtos
->thread_count
+ 1;
106 struct thread_detail
*new_thread_details
= realloc_preserve(rtos
->thread_details
,
107 rtos
->thread_count
* sizeof(struct thread_detail
),
108 new_thread_count
* sizeof(struct thread_detail
));
109 if (!new_thread_details
) {
110 LOG_ERROR("Error growing memory to %d threads", new_thread_count
);
113 rtos
->thread_details
= new_thread_details
;
114 struct thread_detail
*thread
= &new_thread_details
[rtos
->thread_count
];
116 *thread
= (struct thread_detail
){ .threadid
= task
, .exists
= true };
118 /* Read the task name */
120 retval
= target_read_u32(rtos
->target
, task
+ rtos
->symbols
[sym___off_task2name
].address
, &name
);
121 if (retval
!= ERROR_OK
) {
122 LOG_ERROR("Could not read task name pointer from target");
126 retval
= target_read_buffer(rtos
->target
, name
, sizeof(tmp_str
) - 1, tmp_str
);
127 if (retval
!= ERROR_OK
) {
128 LOG_ERROR("Error reading task name from target");
131 tmp_str
[sizeof(tmp_str
) - 1] = '\0';
132 LOG_DEBUG("task name at 0x%" PRIx32
", value \"%s\"", name
, tmp_str
);
134 if (tmp_str
[0] != '\0')
135 thread
->thread_name_str
= strdup((char *)tmp_str
);
137 thread
->thread_name_str
= strdup("No Name");
139 /* Read the task state */
141 retval
= target_read_u16(rtos
->target
, task
+ rtos
->symbols
[sym___off_task2state
].address
, &state
);
142 if (retval
!= ERROR_OK
) {
143 LOG_ERROR("Could not read task state from target");
147 LOG_DEBUG("task state 0x%" PRIx16
, state
);
149 char state_str
[64] = "";
151 strcat(state_str
, "TT|");
152 if (task
== current_task
) {
153 strcat(state_str
, "RUN");
155 if (state
& (ST_TT
| ST_TT_YIELD
))
156 strcat(state_str
, "YIELD");
157 else if (state
& ST_DEAD
)
158 strcat(state_str
, "DEAD");
159 else if (state
& ST_WAIT
)
160 strcat(state_str
, "WAIT");
161 else if (state
& ST_SUSPEND
)
162 strcat(state_str
, "SUSP");
164 strcat(state_str
, "READY");
167 strcat(state_str
, "|SEM");
169 strcat(state_str
, "|MTX");
171 strcat(state_str
, "|SIG");
173 strcat(state_str
, "|DLY");
174 if ((state
& ST_FLAG
) || (state
& ST_FLAG_ALL
))
175 strcat(state_str
, "|FLAG");
176 if (state
& ST_FLAG_ALL
)
177 strcat(state_str
, "_ALL");
179 strcat(state_str
, "|MBOX");
181 strcat(state_str
, "|STP");
183 thread
->extra_info_str
= strdup(state_str
);
185 rtos
->thread_count
= new_thread_count
;
186 if (task
== current_task
)
187 rtos
->current_thread
= task
;
191 static int rtkernel_verify_task(struct rtos
*rtos
, uint32_t task
)
195 retval
= target_read_u32(rtos
->target
, task
+ rtos
->symbols
[sym___off_task2magic
].address
, &magic
);
196 if (retval
!= ERROR_OK
) {
197 LOG_ERROR("Could not read task magic from target");
200 if (magic
!= rtos
->symbols
[sym___val_task_magic
].address
) {
201 LOG_ERROR("Invalid task found (magic=0x%" PRIx32
")", magic
);
207 static int rtkernel_update_threads(struct rtos
*rtos
)
209 /* wipe out previous thread details if any */
210 /* do this first because rtos layer does not check our retval */
211 rtos_free_threadlist(rtos
);
212 rtos
->current_thread
= 0;
214 if (!rtos
->symbols
) {
215 LOG_ERROR("No symbols for rt-kernel");
219 /* read the current task */
220 uint32_t current_task
;
221 int retval
= target_read_u32(rtos
->target
,
222 rtos
->symbols
[sym_os_state
].address
+ rtos
->symbols
[sym___off_os_state2current
].address
,
224 if (retval
!= ERROR_OK
) {
225 LOG_ERROR("Error reading current task");
228 LOG_DEBUG("current task is 0x%" PRIx32
, current_task
);
230 retval
= rtkernel_verify_task(rtos
, current_task
);
231 if (retval
!= ERROR_OK
) {
232 LOG_ERROR("Current task is invalid");
236 /* loop through kernel task list */
237 uint32_t chain
= rtos
->symbols
[sym_os_state
].address
+ rtos
->symbols
[sym___off_os_state2chain
].address
;
238 LOG_DEBUG("chain start at 0x%" PRIx32
, chain
);
240 uint32_t next
= chain
;
242 retval
= target_read_u32(rtos
->target
, next
, &next
);
243 if (retval
!= ERROR_OK
) {
244 LOG_ERROR("Could not read rt-kernel data structure from target");
247 LOG_DEBUG("next entry at 0x%" PRIx32
, next
);
249 LOG_DEBUG("end of chain detected");
252 uint32_t task
= next
- rtos
->symbols
[sym___off_task2chain
].address
;
253 LOG_DEBUG("found task at 0x%" PRIx32
, task
);
255 retval
= rtkernel_verify_task(rtos
, task
);
256 if (retval
!= ERROR_OK
) {
257 LOG_ERROR("Invalid task found");
261 retval
= rtkernel_add_task(rtos
, task
, current_task
);
262 if (retval
!= ERROR_OK
) {
263 LOG_ERROR("Could not add task to rtos system");
270 static int rtkernel_get_thread_reg_list(struct rtos
*rtos
, int64_t thread_id
,
271 struct rtos_reg
**reg_list
, int *num_regs
)
273 uint32_t stack_ptr
= 0;
281 if (!rtos
->rtos_specific_params
)
284 const struct rtkernel_params
*param
= rtos
->rtos_specific_params
;
286 /* Read the stack pointer */
287 int retval
= target_read_u32(rtos
->target
, thread_id
+ rtos
->symbols
[sym___off_task2stack
].address
, &stack_ptr
);
288 if (retval
!= ERROR_OK
) {
289 LOG_ERROR("Error reading stack pointer from rtkernel thread");
292 LOG_DEBUG("stack pointer at 0x%" PRIx64
", value 0x%" PRIx32
,
293 thread_id
+ rtos
->symbols
[sym___off_task2stack
].address
,
296 /* Adjust stack pointer to ignore non-standard BASEPRI register stacking */
299 /* Check for armv7m with *enabled* FPU, i.e. a Cortex M4F */
300 bool cm4_fpu_enabled
= false;
301 struct armv7m_common
*armv7m_target
= target_to_armv7m(rtos
->target
);
302 if (is_armv7m(armv7m_target
)) {
303 if (armv7m_target
->fp_feature
!= FP_NONE
) {
304 /* Found ARM v7m target which includes a FPU */
307 retval
= target_read_u32(rtos
->target
, FPU_CPACR
, &cpacr
);
308 if (retval
!= ERROR_OK
) {
309 LOG_ERROR("Could not read CPACR register to check FPU state");
313 /* Check if CP10 and CP11 are set to full access. */
314 if (cpacr
& 0x00F00000) {
315 /* Found target with enabled FPU */
316 cm4_fpu_enabled
= true;
321 if (!cm4_fpu_enabled
) {
322 LOG_DEBUG("cm3 stacking");
323 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info_cm3
, stack_ptr
, reg_list
, num_regs
);
326 /* Read the LR to decide between stacking with or without FPU */
328 retval
= target_read_u32(rtos
->target
, stack_ptr
+ 0x20, &lr_svc
);
329 if (retval
!= ERROR_OK
) {
330 LOG_OUTPUT("Error reading stack frame from rtkernel thread\r\n");
334 if ((lr_svc
& 0x10) == 0) {
335 LOG_DEBUG("cm4f_fpu stacking");
336 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info_cm4f_fpu
, stack_ptr
, reg_list
, num_regs
);
339 LOG_DEBUG("cm4f stacking");
340 return rtos_generic_stack_read(rtos
->target
, param
->stacking_info_cm4f
, stack_ptr
, reg_list
, num_regs
);
343 static int rtkernel_get_symbol_list_to_lookup(struct symbol_table_elem
*symbol_list
[])
345 *symbol_list
= calloc(ARRAY_SIZE(rtkernel_symbol_list
), sizeof(struct symbol_table_elem
));
349 for (size_t i
= 0; i
< ARRAY_SIZE(rtkernel_symbol_list
); i
++) {
350 (*symbol_list
)[i
].symbol_name
= rtkernel_symbol_list
[i
].name
;
351 (*symbol_list
)[i
].optional
= rtkernel_symbol_list
[i
].optional
;
357 static bool rtkernel_detect_rtos(struct target
*target
)
359 return (target
->rtos
->symbols
) &&
360 (target
->rtos
->symbols
[sym___off_os_state2chain
].address
!= 0);
363 static int rtkernel_create(struct target
*target
)
365 for (size_t i
= 0; i
< ARRAY_SIZE(rtkernel_params_list
); i
++) {
366 if (strcmp(rtkernel_params_list
[i
].target_name
, target
->type
->name
) == 0) {
367 target
->rtos
->rtos_specific_params
= (void *)&rtkernel_params_list
[i
];
372 LOG_ERROR("Could not find target in rt-kernel compatibility list");
376 const struct rtos_type rtkernel_rtos
= {
379 .detect_rtos
= rtkernel_detect_rtos
,
380 .create
= rtkernel_create
,
381 .update_threads
= rtkernel_update_threads
,
382 .get_thread_reg_list
= rtkernel_get_thread_reg_list
,
383 .get_symbol_list_to_lookup
= rtkernel_get_symbol_list_to_lookup
,
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)