Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 33 additions & 1 deletion src/rtos/freertos.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ struct freertos_params {
const struct rtos_register_stacking *stacking_info_cm3;
const struct rtos_register_stacking *stacking_info_cm4f;
const struct rtos_register_stacking *stacking_info_cm4f_fpu;
const struct rtos_register_stacking *stacking_info_cm33;
const struct rtos_register_stacking *stacking_info_cm33_fpu;
};

static const struct freertos_params freertos_params_list[] = {
Expand All @@ -55,6 +57,8 @@ static const struct freertos_params freertos_params_list[] = {
&rtos_standard_cortex_m3_stacking, /* stacking_info */
&rtos_standard_cortex_m4f_stacking,
&rtos_standard_cortex_m4f_fpu_stacking,
&rtos_standard_cortex_m33_stacking,
&rtos_standard_cortex_m33_fpu_stacking,
},
{
"hla_target", /* target_name */
Expand All @@ -69,6 +73,8 @@ static const struct freertos_params freertos_params_list[] = {
&rtos_standard_cortex_m3_stacking, /* stacking_info */
&rtos_standard_cortex_m4f_stacking,
&rtos_standard_cortex_m4f_fpu_stacking,
&rtos_standard_cortex_m33_stacking,
&rtos_standard_cortex_m33_fpu_stacking,
},
};

Expand Down Expand Up @@ -417,9 +423,35 @@ static int freertos_get_thread_reg_list(struct rtos *rtos, int64_t thread_id,
thread_id + param->thread_stack_offset,
stack_ptr);

struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target);

/* ARMv8-M FreeRTOS ports (Cortex-M33/M23, e.g. RP2350_ARM_NTZ) always push
* two extra software-saved words (PSPLIM, then EXC_RETURN) ahead of R4-R11,
* so both the EXC_RETURN position and all register offsets differ from the
* classic Cortex-M3/M4F layouts. The software-saved EXC_RETURN (at offset
* 0x04) is the authoritative indicator of whether the extended FPU frame
* was stacked, so use it directly here. Note we deliberately do NOT gate
* this on the armv7m FPU detection below (fp_feature / CPACR): that probe
* does not reliably report the FPU on ARMv8-M cores, and getting it wrong
* would silently misread every FPU-frame task with the basic layout. */
if (is_armv7m(armv7m_target) && armv7m_target->arm.arch == ARM_ARCH_V8M) {
uint32_t exc_return = 0;
retval = target_read_u32(rtos->target, stack_ptr + 0x04, &exc_return);
if (retval != ERROR_OK) {
LOG_ERROR("Error reading EXC_RETURN from FreeRTOS thread stack");
return retval;
}
/* EXC_RETURN bit 4 == 0 means the extended (FPU) frame is in use. */
const struct rtos_register_stacking *stacking;
if ((exc_return & 0x10) == 0)
stacking = param->stacking_info_cm33_fpu;
else
stacking = param->stacking_info_cm33;
return rtos_generic_stack_read(rtos->target, stacking, stack_ptr, reg_list, num_regs);
}

/* Check for armv7m with *enabled* FPU, i.e. a Cortex-M4F */
int cm4_fpu_enabled = 0;
struct armv7m_common *armv7m_target = target_to_armv7m(rtos->target);
if (is_armv7m(armv7m_target)) {
if ((armv7m_target->fp_feature == FPV4_SP) || (armv7m_target->fp_feature == FPV5_SP) ||
(armv7m_target->fp_feature == FPV5_DP)) {
Expand Down
89 changes: 89 additions & 0 deletions src/rtos/rtos_standard_stackings.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,61 @@ static const struct stack_register_offset rtos_standard_cortex_m4f_fpu_stack_off
};


/*
* ARMv8-M (Cortex-M33/M23) FreeRTOS ports (e.g. RP2350_ARM_NTZ) push an extra
* software-saved frame that the classic Cortex-M3/M4F layouts do not:
*
* [low addr = saved pxTopOfStack]
* 0x00 PSPLIM
* 0x04 EXC_RETURN (software-saved LR)
* 0x08 R4 .. 0x24 R11
* (0x28 S16..S31, only when the task used the FPU - extended frame)
* <hardware exception frame: R0..R3, R12, LR, PC, xPSR (+ S0..S15, FPSCR)>
*
* Compared to rtos_standard_cortex_m4f*, every register is shifted by the two
* leading PSPLIM/EXC_RETURN words and R4-R11 follow EXC_RETURN rather than
* preceding it. Using the M4F tables here yields a garbage call stack.
*/
static const struct stack_register_offset rtos_standard_cortex_m33_stack_offsets[] = {
{ 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, -2, 32 }, /* sp */
{ ARMV7M_R14, 0x3c, 32 }, /* lr */
{ ARMV7M_PC, 0x40, 32 }, /* pc */
{ ARMV7M_XPSR, 0x44, 32 }, /* xPSR */
};

static const struct stack_register_offset rtos_standard_cortex_m33_fpu_stack_offsets[] = {
{ ARMV7M_R0, 0x68, 32 }, /* r0 */
{ ARMV7M_R1, 0x6c, 32 }, /* r1 */
{ ARMV7M_R2, 0x70, 32 }, /* r2 */
{ ARMV7M_R3, 0x74, 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, 0x78, 32 }, /* r12 */
{ ARMV7M_R13, -2, 32 }, /* sp */
{ ARMV7M_R14, 0x7c, 32 }, /* lr */
{ ARMV7M_PC, 0x80, 32 }, /* pc */
{ ARMV7M_XPSR, 0x84, 32 }, /* xPSR */
};

static const struct stack_register_offset rtos_standard_cortex_r4_stack_offsets[] = {
{ 0, 0x08, 32 }, /* r0 (a1) */
{ 1, 0x0c, 32 }, /* r1 (a2) */
Expand Down Expand Up @@ -196,6 +251,24 @@ static target_addr_t rtos_standard_cortex_m4f_fpu_stack_align(struct target *tar
stack_ptr, XPSR_OFFSET);
}

static target_addr_t rtos_standard_cortex_m33_stack_align(struct target *target,
const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
target_addr_t stack_ptr)
{
const int XPSR_OFFSET = 0x44;
return rtos_cortex_m_stack_align(target, stack_data, stacking,
stack_ptr, XPSR_OFFSET);
}

static target_addr_t rtos_standard_cortex_m33_fpu_stack_align(struct target *target,
const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
target_addr_t stack_ptr)
{
const int XPSR_OFFSET = 0x84;
return rtos_cortex_m_stack_align(target, stack_data, stacking,
stack_ptr, XPSR_OFFSET);
}


const struct rtos_register_stacking rtos_standard_cortex_m3_stacking = {
.stack_registers_size = 0x40,
Expand All @@ -221,6 +294,22 @@ const struct rtos_register_stacking rtos_standard_cortex_m4f_fpu_stacking = {
.register_offsets = rtos_standard_cortex_m4f_fpu_stack_offsets
};

const struct rtos_register_stacking rtos_standard_cortex_m33_stacking = {
.stack_registers_size = 0x48,
.stack_growth_direction = -1,
.num_output_registers = ARMV7M_NUM_CORE_REGS,
.calculate_process_stack = rtos_standard_cortex_m33_stack_align,
.register_offsets = rtos_standard_cortex_m33_stack_offsets
};

const struct rtos_register_stacking rtos_standard_cortex_m33_fpu_stacking = {
.stack_registers_size = 0xd0,
.stack_growth_direction = -1,
.num_output_registers = ARMV7M_NUM_CORE_REGS,
.calculate_process_stack = rtos_standard_cortex_m33_fpu_stack_align,
.register_offsets = rtos_standard_cortex_m33_fpu_stack_offsets
};

const struct rtos_register_stacking rtos_standard_cortex_r4_stacking = {
.stack_registers_size = 0x48,
.stack_growth_direction = -1,
Expand Down
2 changes: 2 additions & 0 deletions src/rtos/rtos_standard_stackings.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
extern const struct rtos_register_stacking rtos_standard_cortex_m3_stacking;
extern const struct rtos_register_stacking rtos_standard_cortex_m4f_stacking;
extern const struct rtos_register_stacking rtos_standard_cortex_m4f_fpu_stacking;
extern const struct rtos_register_stacking rtos_standard_cortex_m33_stacking;
extern const struct rtos_register_stacking rtos_standard_cortex_m33_fpu_stacking;
extern const struct rtos_register_stacking rtos_standard_cortex_r4_stacking;
target_addr_t rtos_generic_stack_align8(struct target *target,
const uint8_t *stack_data, const struct rtos_register_stacking *stacking,
Expand Down