aboutsummaryrefslogtreecommitdiff
path: root/src/rtos
diff options
context:
space:
mode:
Diffstat (limited to 'src/rtos')
-rw-r--r--src/rtos/Makefile.am10
-rw-r--r--src/rtos/chibios.c18
-rw-r--r--src/rtos/ecos.c (renamed from src/rtos/eCos.c)0
-rw-r--r--src/rtos/embkernel.c (renamed from src/rtos/embKernel.c)0
-rw-r--r--src/rtos/freertos.c (renamed from src/rtos/FreeRTOS.c)0
-rw-r--r--src/rtos/hwthread.c94
-rw-r--r--src/rtos/linux.c33
-rw-r--r--src/rtos/mqx.c5
-rw-r--r--src/rtos/nuttx.c54
-rw-r--r--src/rtos/rtos.c12
-rw-r--r--src/rtos/rtos_nuttx_stackings.c134
-rw-r--r--src/rtos/rtos_nuttx_stackings.h9
-rw-r--r--src/rtos/rtos_standard_stackings.c4
-rw-r--r--src/rtos/threadx.c (renamed from src/rtos/ThreadX.c)0
-rw-r--r--src/rtos/ucos_iii.c (renamed from src/rtos/uCOS-III.c)0
15 files changed, 192 insertions, 181 deletions
diff --git a/src/rtos/Makefile.am b/src/rtos/Makefile.am
index 0796910..5267fea 100644
--- a/src/rtos/Makefile.am
+++ b/src/rtos/Makefile.am
@@ -11,15 +11,15 @@ noinst_LTLIBRARIES += %D%/librtos.la
%D%/rtos_ucos_iii_stackings.c \
%D%/rtos_riot_stackings.c \
%D%/rtos_nuttx_stackings.c \
- %D%/FreeRTOS.c \
- %D%/ThreadX.c \
- %D%/eCos.c \
+ %D%/freertos.c \
+ %D%/threadx.c \
+ %D%/ecos.c \
%D%/linux.c \
%D%/chibios.c \
%D%/chromium-ec.c \
- %D%/embKernel.c \
+ %D%/embkernel.c \
%D%/mqx.c \
- %D%/uCOS-III.c \
+ %D%/ucos_iii.c \
%D%/nuttx.c \
%D%/rtkernel.c \
%D%/hwthread.c \
diff --git a/src/rtos/chibios.c b/src/rtos/chibios.c
index c1e4e84..af590c2 100644
--- a/src/rtos/chibios.c
+++ b/src/rtos/chibios.c
@@ -31,7 +31,7 @@ struct chibios_chdebug {
char ch_identifier[4]; /**< @brief Always set to "main". */
uint8_t ch_zero; /**< @brief Must be zero. */
uint8_t ch_size; /**< @brief Size of this structure. */
- uint16_t ch_version; /**< @brief Encoded ChibiOS/RT version. */
+ uint8_t ch_version[2]; /**< @brief Encoded ChibiOS/RT version. */
uint8_t ch_ptrsize; /**< @brief Size of a pointer. */
uint8_t ch_timesize; /**< @brief Size of a @p systime_t. */
uint8_t ch_threadsize; /**< @brief Size of a @p Thread struct. */
@@ -171,13 +171,7 @@ static int chibios_update_memory_signature(struct rtos *rtos)
" expected. Assuming compatibility...");
}
- /* Convert endianness of version field */
- const uint8_t *versiontarget = (const uint8_t *)
- &signature->ch_version;
- signature->ch_version = rtos->target->endianness == TARGET_LITTLE_ENDIAN ?
- le_to_h_u32(versiontarget) : be_to_h_u32(versiontarget);
-
- const uint16_t ch_version = signature->ch_version;
+ const uint16_t ch_version = target_buffer_get_u16(rtos->target, signature->ch_version);
LOG_INFO("Successfully loaded memory map of ChibiOS/RT target "
"running version %i.%i.%i", GET_CH_KERNEL_MAJOR(ch_version),
GET_CH_KERNEL_MINOR(ch_version), GET_CH_KERNEL_PATCH(ch_version));
@@ -427,9 +421,11 @@ static int chibios_update_threads(struct rtos *rtos)
else
state_desc = "Unknown";
- curr_thrd_details->extra_info_str = malloc(strlen(
- state_desc)+8);
- sprintf(curr_thrd_details->extra_info_str, "State: %s", state_desc);
+ curr_thrd_details->extra_info_str = alloc_printf("State: %s", state_desc);
+ if (!curr_thrd_details->extra_info_str) {
+ LOG_ERROR("Could not allocate space for thread state description");
+ return -1;
+ }
curr_thrd_details->exists = true;
diff --git a/src/rtos/eCos.c b/src/rtos/ecos.c
index 7048b00..7048b00 100644
--- a/src/rtos/eCos.c
+++ b/src/rtos/ecos.c
diff --git a/src/rtos/embKernel.c b/src/rtos/embkernel.c
index 7e6de79..7e6de79 100644
--- a/src/rtos/embKernel.c
+++ b/src/rtos/embkernel.c
diff --git a/src/rtos/FreeRTOS.c b/src/rtos/freertos.c
index 02409a5..02409a5 100644
--- a/src/rtos/FreeRTOS.c
+++ b/src/rtos/freertos.c
diff --git a/src/rtos/hwthread.c b/src/rtos/hwthread.c
index f256bc2..3e4a4ec 100644
--- a/src/rtos/hwthread.c
+++ b/src/rtos/hwthread.c
@@ -36,7 +36,18 @@ struct target *hwthread_swbp_target(struct rtos *rtos, target_addr_t address,
static inline threadid_t threadid_from_target(const struct target *target)
{
- return target->coreid + 1;
+ if (!target->smp)
+ return 1;
+
+ threadid_t threadid = 1;
+ struct target_list *head;
+ foreach_smp_target(head, target->smp_targets) {
+ if (target == head->target)
+ return threadid;
+ ++threadid;
+ }
+ assert(0 && "Target is not found in it's own SMP group!");
+ return -1;
}
const struct rtos_type hwthread_rtos = {
@@ -59,14 +70,13 @@ struct hwthread_params {
int dummy_param;
};
-static int hwthread_fill_thread(struct rtos *rtos, struct target *curr, int thread_num)
+static int hwthread_fill_thread(struct rtos *rtos, struct target *curr, int thread_num, threadid_t tid)
{
char tmp_str[HW_THREAD_NAME_STR_SIZE];
- threadid_t tid = threadid_from_target(curr);
memset(tmp_str, 0, HW_THREAD_NAME_STR_SIZE);
- /* thread-id is the core-id of this core inside the SMP group plus 1 */
+ /* thread-id is the index of this core inside the SMP group plus 1 */
rtos->thread_details[thread_num].threadid = tid;
/* create the thread name */
rtos->thread_details[thread_num].exists = true;
@@ -115,7 +125,7 @@ static int hwthread_update_threads(struct rtos *rtos)
if (current_threadid <= thread_list_size)
rtos->current_threadid = current_threadid;
else
- LOG_WARNING("SMP node change, disconnect GDB from core/thread %" PRId64,
+ LOG_TARGET_WARNING(target, "SMP node change, disconnect GDB from core/thread %" PRId64,
current_threadid);
/* create space for new thread details */
@@ -131,8 +141,7 @@ static int hwthread_update_threads(struct rtos *rtos)
continue;
threadid_t tid = threadid_from_target(curr);
-
- hwthread_fill_thread(rtos, curr, threads_found);
+ hwthread_fill_thread(rtos, curr, threads_found, tid);
/* find an interesting thread to set as current */
switch (current_reason) {
@@ -152,9 +161,8 @@ static int hwthread_update_threads(struct rtos *rtos)
if (curr->debug_reason == DBG_REASON_SINGLESTEP) {
current_reason = curr->debug_reason;
current_thread = tid;
- } else
- /* multiple breakpoints, prefer gdbs' threadid */
- if (curr->debug_reason == DBG_REASON_BREAKPOINT) {
+ } else if (curr->debug_reason == DBG_REASON_BREAKPOINT) {
+ /* multiple breakpoints, prefer gdbs' threadid */
if (tid == rtos->current_threadid)
current_thread = tid;
}
@@ -174,8 +182,7 @@ static int hwthread_update_threads(struct rtos *rtos)
curr->debug_reason == DBG_REASON_BREAKPOINT) {
current_reason = curr->debug_reason;
current_thread = tid;
- } else
- if (curr->debug_reason == DBG_REASON_DBGRQ) {
+ } else if (curr->debug_reason == DBG_REASON_DBGRQ) {
if (tid == rtos->current_threadid)
current_thread = tid;
}
@@ -189,8 +196,8 @@ static int hwthread_update_threads(struct rtos *rtos)
threads_found++;
}
} else {
- hwthread_fill_thread(rtos, target, threads_found);
- current_thread = threadid_from_target(target);
+ current_thread = 1;
+ hwthread_fill_thread(rtos, target, threads_found, current_thread);
threads_found++;
}
@@ -204,7 +211,8 @@ static int hwthread_update_threads(struct rtos *rtos)
else
rtos->current_thread = threadid_from_target(target);
- LOG_DEBUG("current_thread=%i, threads_found=%d", (int)rtos->current_thread, threads_found);
+ LOG_TARGET_DEBUG(target, "current_thread=%i, threads_found=%d",
+ (int)rtos->current_thread, threads_found);
return 0;
}
@@ -213,19 +221,17 @@ static int hwthread_smp_init(struct target *target)
return hwthread_update_threads(target->rtos);
}
-static struct target *hwthread_find_thread(struct target *target, int64_t thread_id)
+static struct target *hwthread_find_thread(struct target *target, threadid_t thread_id)
{
- /* Find the thread with that thread_id */
- if (!target)
- return NULL;
- if (target->smp) {
- struct target_list *head;
- foreach_smp_target(head, target->smp_targets) {
- if (thread_id == threadid_from_target(head->target))
- return head->target;
- }
- } else if (thread_id == threadid_from_target(target)) {
+ /* Find the thread with that thread_id (index in SMP group plus 1)*/
+ if (!(target && target->smp))
return target;
+ struct target_list *head;
+ threadid_t tid = 1;
+ foreach_smp_target(head, target->smp_targets) {
+ if (thread_id == tid)
+ return head->target;
+ ++tid;
}
return NULL;
}
@@ -254,7 +260,7 @@ static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
int j = 0;
for (int i = 0; i < reg_list_size; i++) {
- if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden)
+ if (!reg_list[i] || !reg_list[i]->exist || reg_list[i]->hidden)
continue;
j++;
}
@@ -267,12 +273,13 @@ static int hwthread_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
j = 0;
for (int i = 0; i < reg_list_size; i++) {
- if (!reg_list[i] || reg_list[i]->exist == false || reg_list[i]->hidden)
+ if (!reg_list[i] || !reg_list[i]->exist || reg_list[i]->hidden)
continue;
if (!reg_list[i]->valid) {
retval = reg_list[i]->type->get(reg_list[i]);
if (retval != ERROR_OK) {
- LOG_ERROR("Couldn't get register %s.", reg_list[i]->name);
+ LOG_TARGET_ERROR(curr, "Couldn't get register %s",
+ reg_list[i]->name);
free(reg_list);
free(*rtos_reg_list);
return retval;
@@ -299,19 +306,20 @@ static int hwthread_get_thread_reg_value(struct rtos *rtos, int64_t thread_id,
struct target *curr = hwthread_find_thread(target, thread_id);
if (!curr) {
- LOG_ERROR("Couldn't find RTOS thread for id %" PRId64 ".", thread_id);
+ LOG_TARGET_ERROR(target, "Couldn't find RTOS thread for id %" PRId64,
+ thread_id);
return ERROR_FAIL;
}
if (!target_was_examined(curr)) {
- LOG_ERROR("Target %d hasn't been examined yet.", curr->coreid);
+ LOG_TARGET_ERROR(curr, "Target hasn't been examined yet.");
return ERROR_FAIL;
}
struct reg *reg = register_get_by_number(curr->reg_cache, reg_num, true);
if (!reg) {
- LOG_ERROR("Couldn't find register %" PRIu32 " in thread %" PRId64 ".", reg_num,
- thread_id);
+ LOG_TARGET_ERROR(curr, "Couldn't find register %" PRIu32 " in thread %" PRId64,
+ reg_num, thread_id);
return ERROR_FAIL;
}
@@ -319,7 +327,7 @@ static int hwthread_get_thread_reg_value(struct rtos *rtos, int64_t thread_id,
return ERROR_FAIL;
*size = reg->size;
- unsigned bytes = DIV_ROUND_UP(reg->size, 8);
+ unsigned int bytes = DIV_ROUND_UP(reg->size, 8);
*value = malloc(bytes);
if (!*value) {
LOG_ERROR("Failed to allocate memory for %d-bit register.", reg->size);
@@ -377,24 +385,24 @@ static bool hwthread_detect_rtos(struct target *target)
static int hwthread_thread_packet(struct connection *connection, const char *packet, int packet_size)
{
- struct target *target = get_target_from_connection(connection);
-
- struct target *curr = NULL;
- int64_t current_threadid;
-
if (packet[0] == 'H' && packet[1] == 'g') {
+ int64_t current_threadid;
sscanf(packet, "Hg%16" SCNx64, &current_threadid);
+ struct target *target = get_target_from_connection(connection);
+
if (current_threadid > 0) {
+ struct target *curr = NULL;
if (hwthread_target_for_threadid(connection, current_threadid, &curr) != ERROR_OK) {
- LOG_ERROR("hwthread: cannot find thread id %"PRId64, current_threadid);
+ LOG_TARGET_ERROR(target, "hwthread: cannot find thread id %" PRId64,
+ current_threadid);
gdb_put_packet(connection, "E01", 3);
return ERROR_FAIL;
}
target->rtos->current_thread = current_threadid;
- } else
- if (current_threadid == 0 || current_threadid == -1)
+ } else if (current_threadid == 0 || current_threadid == -1) {
target->rtos->current_thread = threadid_from_target(target);
+ }
target->rtos->current_threadid = current_threadid;
@@ -407,7 +415,7 @@ static int hwthread_thread_packet(struct connection *connection, const char *pac
static int hwthread_create(struct target *target)
{
- LOG_INFO("Hardware thread awareness created");
+ LOG_TARGET_INFO(target, "Hardware thread awareness created");
target->rtos->rtos_specific_params = NULL;
target->rtos->current_thread = 0;
diff --git a/src/rtos/linux.c b/src/rtos/linux.c
index 7517ec7..5efdc9f 100644
--- a/src/rtos/linux.c
+++ b/src/rtos/linux.c
@@ -624,7 +624,7 @@ static struct threads *liste_add_task(struct threads *task_list, struct threads
{
t->next = NULL;
- if (!*last)
+ if (!*last) {
if (!task_list) {
task_list = t;
return task_list;
@@ -637,7 +637,8 @@ static struct threads *liste_add_task(struct threads *task_list, struct threads
temp->next = t;
*last = t;
return task_list;
- } else {
+ }
+ } else {
(*last)->next = t;
*last = t;
return task_list;
@@ -1039,6 +1040,10 @@ static int linux_gdb_thread_packet(struct target *target,
return ERROR_TARGET_FAILURE;
char *out_str = calloc(MAX_THREADS * 17 + 10, 1);
+ if (!out_str) {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
char *tmp_str = out_str;
tmp_str += sprintf(tmp_str, "m");
struct threads *temp = linux_os->thread_list;
@@ -1115,23 +1120,13 @@ static int linux_thread_extra_info(struct target *target,
while (temp) {
if (temp->threadid == threadid) {
- char *pid = " PID: ";
- char *pid_current = "*PID: ";
- char *name = "Name: ";
- int str_size = strlen(pid) + strlen(name);
- char *tmp_str = calloc(1, str_size + 50);
- char *tmp_str_ptr = tmp_str;
-
- /* discriminate current task */
- if (temp->status == 3)
- tmp_str_ptr += sprintf(tmp_str_ptr, "%s",
- pid_current);
- else
- tmp_str_ptr += sprintf(tmp_str_ptr, "%s", pid);
-
- tmp_str_ptr += sprintf(tmp_str_ptr, "%d, ", (int)temp->pid);
- sprintf(tmp_str_ptr, "%s", name);
- sprintf(tmp_str_ptr, "%s", temp->name);
+ char *tmp_str = alloc_printf("%cPID: %" PRIu32 ", Name: %s",
+ temp->status == 3 ? '*' : ' ',
+ temp->pid, temp->name);
+ if (!tmp_str) {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
char *hex_str = calloc(1, strlen(tmp_str) * 2 + 1);
size_t pkt_len = hexify(hex_str, (const uint8_t *)tmp_str,
strlen(tmp_str), strlen(tmp_str) * 2 + 1);
diff --git a/src/rtos/mqx.c b/src/rtos/mqx.c
index b4a1821..017fd2b 100644
--- a/src/rtos/mqx.c
+++ b/src/rtos/mqx.c
@@ -319,7 +319,7 @@ static int mqx_update_threads(
i < (uint32_t)rtos->thread_count;
i++
) {
- uint8_t task_name[MQX_THREAD_NAME_LENGTH + 1];
+ char task_name[MQX_THREAD_NAME_LENGTH + 1];
uint32_t task_addr = 0, task_template = 0, task_state = 0;
uint32_t task_name_addr = 0, task_id = 0, task_errno = 0;
uint32_t state_index = 0;
@@ -380,10 +380,9 @@ static int mqx_update_threads(
rtos->thread_details[i].threadid = task_id;
rtos->thread_details[i].exists = true;
/* set thread name */
- rtos->thread_details[i].thread_name_str = malloc(strlen((void *)task_name) + 1);
+ rtos->thread_details[i].thread_name_str = strdup(task_name);
if (!rtos->thread_details[i].thread_name_str)
return ERROR_FAIL;
- strcpy(rtos->thread_details[i].thread_name_str, (void *)task_name);
/* set thread extra info
* - task state
* - task address
diff --git a/src/rtos/nuttx.c b/src/rtos/nuttx.c
index 9100148..821e550 100644
--- a/src/rtos/nuttx.c
+++ b/src/rtos/nuttx.c
@@ -32,7 +32,6 @@
struct nuttx_params {
const char *target_name;
const struct rtos_register_stacking *stacking;
- const struct rtos_register_stacking *(*select_stackinfo)(struct target *target);
};
/*
@@ -56,19 +55,12 @@ struct symbols {
bool optional;
};
-/* Used to index the list of retrieved symbols. See nuttx_symbol_list for the order. */
-enum nuttx_symbol_vals {
- NX_SYM_READYTORUN = 0,
- NX_SYM_PIDHASH,
- NX_SYM_NPIDHASH,
- NX_SYM_TCB_INFO,
-};
-
static const struct symbols nuttx_symbol_list[] = {
{ "g_readytorun", false },
{ "g_pidhash", false },
{ "g_npidhash", false },
{ "g_tcbinfo", false },
+ { "g_reg_offs", false},
{ NULL, false }
};
@@ -86,18 +78,14 @@ static char *task_state_str[] = {
"STOPPED",
};
-static const struct rtos_register_stacking *cortexm_select_stackinfo(struct target *target);
-
static const struct nuttx_params nuttx_params_list[] = {
{
.target_name = "cortex_m",
- .stacking = NULL,
- .select_stackinfo = cortexm_select_stackinfo,
+ .stacking = &nuttx_stacking_cortex_m,
},
{
.target_name = "hla_target",
- .stacking = NULL,
- .select_stackinfo = cortexm_select_stackinfo,
+ .stacking = &nuttx_stacking_cortex_m,
},
{
.target_name = "esp32",
@@ -117,28 +105,6 @@ static const struct nuttx_params nuttx_params_list[] = {
},
};
-static bool cortexm_hasfpu(struct target *target)
-{
- uint32_t cpacr;
- struct armv7m_common *armv7m_target = target_to_armv7m(target);
-
- if (!is_armv7m(armv7m_target) || armv7m_target->fp_feature == FP_NONE)
- return false;
-
- int retval = target_read_u32(target, FPU_CPACR, &cpacr);
- if (retval != ERROR_OK) {
- LOG_ERROR("Could not read CPACR register to check FPU state");
- return false;
- }
-
- return cpacr & 0x00F00000;
-}
-
-static const struct rtos_register_stacking *cortexm_select_stackinfo(struct target *target)
-{
- return cortexm_hasfpu(target) ? &nuttx_stacking_cortex_m_fpu : &nuttx_stacking_cortex_m;
-}
-
static bool nuttx_detect_rtos(struct target *target)
{
if (target->rtos->symbols &&
@@ -371,29 +337,25 @@ static int nuttx_getreg_current_thread(struct rtos *rtos,
static int nuttx_getregs_fromstack(struct rtos *rtos, int64_t thread_id,
struct rtos_reg **reg_list, int *num_regs)
{
- uint16_t xcpreg_off;
+ uint16_t regs_off;
uint32_t regsaddr;
const struct nuttx_params *priv = rtos->rtos_specific_params;
const struct rtos_register_stacking *stacking = priv->stacking;
if (!stacking) {
- if (priv->select_stackinfo) {
- stacking = priv->select_stackinfo(rtos->target);
- } else {
- LOG_ERROR("Can't find a way to get stacking info");
- return ERROR_FAIL;
- }
+ LOG_ERROR("Can't find a way to get stacking info");
+ return ERROR_FAIL;
}
int ret = target_read_u16(rtos->target,
rtos->symbols[NX_SYM_TCB_INFO].address + offsetof(struct tcbinfo, regs_off),
- &xcpreg_off);
+ &regs_off);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to read registers' offset: ret = %d", ret);
return ERROR_FAIL;
}
- ret = target_read_u32(rtos->target, thread_id + xcpreg_off, &regsaddr);
+ ret = target_read_u32(rtos->target, thread_id + regs_off, &regsaddr);
if (ret != ERROR_OK) {
LOG_ERROR("Failed to read registers' address: ret = %d", ret);
return ERROR_FAIL;
diff --git a/src/rtos/rtos.c b/src/rtos/rtos.c
index b5e8e9a..e87e51c 100644
--- a/src/rtos/rtos.c
+++ b/src/rtos/rtos.c
@@ -109,7 +109,7 @@ int rtos_create(struct jim_getopt_info *goi, struct target *target)
Jim_Obj *res;
int e;
- if (!goi->isconfigure && goi->argc != 0) {
+ if (!goi->is_configure && goi->argc != 0) {
Jim_WrongNumArgs(goi->interp, goi->argc, goi->argv, "NO PARAMS");
return JIM_ERR;
}
@@ -317,7 +317,7 @@ int rtos_qsymbol(struct connection *connection, char const *packet, int packet_s
reply_len += 2 * strlen(next_suffix); /* hexify(..., next_suffix, ...) */
reply_len += 1; /* Terminating NUL */
if (reply_len > sizeof(reply)) {
- LOG_ERROR("ERROR: RTOS symbol '%s%s' name is too long for GDB!", next_sym->symbol_name, next_suffix);
+ LOG_ERROR("RTOS symbol '%s%s' name is too long for GDB", next_sym->symbol_name, next_suffix);
goto done;
}
@@ -370,6 +370,10 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa
str_size += strlen(detail->extra_info_str);
char *tmp_str = calloc(str_size + 9, sizeof(char));
+ if (!tmp_str) {
+ LOG_ERROR("Out of memory");
+ return ERROR_FAIL;
+ }
char *tmp_str_ptr = tmp_str;
if (detail->thread_name_str)
@@ -397,7 +401,7 @@ int rtos_thread_packet(struct connection *connection, char const *packet, int pa
return ERROR_OK;
} else if (strncmp(packet, "qSymbol", 7) == 0) {
if (rtos_qsymbol(connection, packet, packet_size) == 1) {
- if (target->rtos_auto_detect == true) {
+ if (target->rtos_auto_detect) {
target->rtos_auto_detect = false;
target->rtos->type->create(target);
}
@@ -635,7 +639,7 @@ int rtos_generic_stack_read(struct target *target,
int retval;
if (stack_ptr == 0) {
- LOG_ERROR("Error: null stack pointer in thread");
+ LOG_ERROR("null stack pointer in thread");
return -5;
}
/* Read the stack */
diff --git a/src/rtos/rtos_nuttx_stackings.c b/src/rtos/rtos_nuttx_stackings.c
index b70cccb..6faa56a 100644
--- a/src/rtos/rtos_nuttx_stackings.c
+++ b/src/rtos/rtos_nuttx_stackings.c
@@ -9,60 +9,100 @@
#include "rtos_nuttx_stackings.h"
#include "rtos_standard_stackings.h"
#include <target/riscv/riscv.h>
+#include <helper/bits.h>
-/* see arch/arm/include/armv7-m/irq_cmnvector.h */
+/* The cortex_m target uses nuttx_tcbinfo_stack_read which uses a symbol
+ * provided by Nuttx to read the registers from memory and place them directly
+ * in the order we need. This is because the register offsets change with
+ * different versions of Nuttx, FPU vs non-FPU and ARMv7 vs ARMv8.
+ * This allows a single function to work with many versions.
+ */
static const struct stack_register_offset nuttx_stack_offsets_cortex_m[] = {
- { ARMV7M_R0, 0x28, 32 }, /* r0 */
- { ARMV7M_R1, 0x2c, 32 }, /* r1 */
- { ARMV7M_R2, 0x30, 32 }, /* r2 */
- { ARMV7M_R3, 0x34, 32 }, /* r3 */
- { ARMV7M_R4, 0x08, 32 }, /* r4 */
- { ARMV7M_R5, 0x0c, 32 }, /* r5 */
- { ARMV7M_R6, 0x10, 32 }, /* r6 */
- { ARMV7M_R7, 0x14, 32 }, /* r7 */
- { ARMV7M_R8, 0x18, 32 }, /* r8 */
- { ARMV7M_R9, 0x1c, 32 }, /* r9 */
- { ARMV7M_R10, 0x20, 32 }, /* r10 */
- { ARMV7M_R11, 0x24, 32 }, /* r11 */
- { ARMV7M_R12, 0x38, 32 }, /* r12 */
- { ARMV7M_R13, 0, 32 }, /* sp */
- { ARMV7M_R14, 0x3c, 32 }, /* lr */
- { ARMV7M_PC, 0x40, 32 }, /* pc */
- { ARMV7M_XPSR, 0x44, 32 }, /* xPSR */
+ { ARMV7M_R0, 0, 32 }, /* r0 */
+ { ARMV7M_R1, 4, 32 }, /* r1 */
+ { ARMV7M_R2, 8, 32 }, /* r2 */
+ { ARMV7M_R3, 12, 32 }, /* r3 */
+ { ARMV7M_R4, 16, 32 }, /* r4 */
+ { ARMV7M_R5, 20, 32 }, /* r5 */
+ { ARMV7M_R6, 24, 32 }, /* r6 */
+ { ARMV7M_R7, 28, 32 }, /* r7 */
+ { ARMV7M_R8, 32, 32 }, /* r8 */
+ { ARMV7M_R9, 36, 32 }, /* r9 */
+ { ARMV7M_R10, 40, 32 }, /* r10 */
+ { ARMV7M_R11, 44, 32 }, /* r11 */
+ { ARMV7M_R12, 48, 32 }, /* r12 */
+ { ARMV7M_R13, 52, 32 }, /* sp */
+ { ARMV7M_R14, 56, 32 }, /* lr */
+ { ARMV7M_PC, 60, 32 }, /* pc */
+ { ARMV7M_XPSR, 64, 32 }, /* xPSR */
};
-const struct rtos_register_stacking nuttx_stacking_cortex_m = {
- .stack_registers_size = 0x48,
- .stack_growth_direction = -1,
- .num_output_registers = 17,
- .register_offsets = nuttx_stack_offsets_cortex_m,
-};
+/* The Nuttx stack frame for most architectures has some registers placed
+ * by hardware and some by software. The hardware register order and number does not change
+ * but the software registers may change with different versions of Nuttx.
+ * For example with ARMv7, nuttx-12.3.0 added a new register which changed all
+ * the offsets. We can either create separate offset tables for each version of Nuttx
+ * which will break again in the future, or read the offsets from the TCB info.
+ * Nuttx provides a symbol (g_reg_offs) which holds all the offsets for each stored register.
+ * This offset table is stored in GDB org.gnu.gdb.xxx feature order.
+ * The same order we need.
+ * Please refer:
+ * https://sourceware.org/gdb/current/onlinedocs/gdb/ARM-Features.html
+ * https://sourceware.org/gdb/current/onlinedocs/gdb/RISC_002dV-Features.html
+ */
+static int nuttx_cortex_m_tcbinfo_stack_read(struct target *target,
+ int64_t stack_ptr, const struct rtos_register_stacking *stacking,
+ uint8_t *stack_data)
+{
+ struct rtos *rtos = target->rtos;
+ target_addr_t xcpreg_off = rtos->symbols[NX_SYM_REG_OFFSETS].address;
-static const struct stack_register_offset nuttx_stack_offsets_cortex_m_fpu[] = {
- { ARMV7M_R0, 0x6c, 32 }, /* r0 */
- { ARMV7M_R1, 0x70, 32 }, /* r1 */
- { ARMV7M_R2, 0x74, 32 }, /* r2 */
- { ARMV7M_R3, 0x78, 32 }, /* r3 */
- { ARMV7M_R4, 0x08, 32 }, /* r4 */
- { ARMV7M_R5, 0x0c, 32 }, /* r5 */
- { ARMV7M_R6, 0x10, 32 }, /* r6 */
- { ARMV7M_R7, 0x14, 32 }, /* r7 */
- { ARMV7M_R8, 0x18, 32 }, /* r8 */
- { ARMV7M_R9, 0x1c, 32 }, /* r9 */
- { ARMV7M_R10, 0x20, 32 }, /* r10 */
- { ARMV7M_R11, 0x24, 32 }, /* r11 */
- { ARMV7M_R12, 0x7c, 32 }, /* r12 */
- { ARMV7M_R13, 0, 32 }, /* sp */
- { ARMV7M_R14, 0x80, 32 }, /* lr */
- { ARMV7M_PC, 0x84, 32 }, /* pc */
- { ARMV7M_XPSR, 0x88, 32 }, /* xPSR */
-};
+ for (int i = 0; i < stacking->num_output_registers; ++i) {
+ uint16_t stack_reg_offset;
+ int ret = target_read_u16(rtos->target, xcpreg_off + 2 * i, &stack_reg_offset);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("Failed to read stack_reg_offset: ret = %d", ret);
+ return ret;
+ }
+ if (stack_reg_offset != UINT16_MAX && stacking->register_offsets[i].offset >= 0) {
+ ret = target_read_buffer(target,
+ stack_ptr + stack_reg_offset,
+ stacking->register_offsets[i].width_bits / 8,
+ &stack_data[stacking->register_offsets[i].offset]);
+ if (ret != ERROR_OK) {
+ LOG_ERROR("Failed to read register: ret = %d", ret);
+ return ret;
+ }
+ }
+ }
+
+ /* Offset match nuttx_stack_offsets_cortex_m */
+ const int XPSR_OFFSET = 64;
+ const int SP_OFFSET = 52;
+ /* Nuttx stack frames (produced in exception_common) store the SP of the ISR minus
+ * the hardware stack frame size. This SP may include an additional 4 byte alignment
+ * depending in xPSR[9]. The Nuttx stack frame stores post alignment since the
+ * hardware will add/remove automatically on both enter/exit.
+ * We need to adjust the SP to get the real SP of the stack.
+ * See Arm Reference manual "Stack alignment on exception entry"
+ */
+ uint32_t xpsr = target_buffer_get_u32(target, &stack_data[XPSR_OFFSET]);
+ if (xpsr & BIT(9)) {
+ uint32_t sp = target_buffer_get_u32(target, &stack_data[SP_OFFSET]);
+ target_buffer_set_u32(target, &stack_data[SP_OFFSET], sp - 4 * stacking->stack_growth_direction);
+ }
-const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu = {
- .stack_registers_size = 0x8c,
+ return ERROR_OK;
+}
+
+const struct rtos_register_stacking nuttx_stacking_cortex_m = {
+ /* nuttx_tcbinfo_stack_read transforms the stack into just output registers */
+ .stack_registers_size = ARRAY_SIZE(nuttx_stack_offsets_cortex_m) * 4,
.stack_growth_direction = -1,
- .num_output_registers = 17,
- .register_offsets = nuttx_stack_offsets_cortex_m_fpu,
+ .num_output_registers = ARRAY_SIZE(nuttx_stack_offsets_cortex_m),
+ .read_stack = nuttx_cortex_m_tcbinfo_stack_read,
+ .calculate_process_stack = NULL, /* Stack alignment done in nuttx_cortex_m_tcbinfo_stack_read */
+ .register_offsets = nuttx_stack_offsets_cortex_m,
};
static const struct stack_register_offset nuttx_stack_offsets_riscv[] = {
diff --git a/src/rtos/rtos_nuttx_stackings.h b/src/rtos/rtos_nuttx_stackings.h
index 213a060..5d55e75 100644
--- a/src/rtos/rtos_nuttx_stackings.h
+++ b/src/rtos/rtos_nuttx_stackings.h
@@ -5,6 +5,15 @@
#include "rtos.h"
+/* Used to index the list of retrieved symbols. See nuttx_symbol_list for the order. */
+enum nuttx_symbol_vals {
+ NX_SYM_READYTORUN = 0,
+ NX_SYM_PIDHASH,
+ NX_SYM_NPIDHASH,
+ NX_SYM_TCB_INFO,
+ NX_SYM_REG_OFFSETS,
+};
+
extern const struct rtos_register_stacking nuttx_stacking_cortex_m;
extern const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu;
extern const struct rtos_register_stacking nuttx_riscv_stacking;
diff --git a/src/rtos/rtos_standard_stackings.c b/src/rtos/rtos_standard_stackings.c
index 0ca664f..360ae9b 100644
--- a/src/rtos/rtos_standard_stackings.c
+++ b/src/rtos/rtos_standard_stackings.c
@@ -327,9 +327,7 @@ target_addr_t rtos_cortex_m_stack_align(struct target *target,
new_stack_ptr = stack_ptr - stacking->stack_growth_direction *
stacking->stack_registers_size;
- xpsr = (target->endianness == TARGET_LITTLE_ENDIAN) ?
- le_to_h_u32(&stack_data[xpsr_offset]) :
- be_to_h_u32(&stack_data[xpsr_offset]);
+ xpsr = target_buffer_get_u32(target, &stack_data[xpsr_offset]);
if ((xpsr & ALIGN_NEEDED) != 0) {
LOG_DEBUG("XPSR(0x%08" PRIx32 ") indicated stack alignment was necessary\r\n",
xpsr);
diff --git a/src/rtos/ThreadX.c b/src/rtos/threadx.c
index 61c4926..61c4926 100644
--- a/src/rtos/ThreadX.c
+++ b/src/rtos/threadx.c
diff --git a/src/rtos/uCOS-III.c b/src/rtos/ucos_iii.c
index f19d06e..f19d06e 100644
--- a/src/rtos/uCOS-III.c
+++ b/src/rtos/ucos_iii.c