Skip to content

Instantly share code, notes, and snippets.

@ashtonchase
Created June 9, 2019 15:10
Show Gist options
  • Save ashtonchase/f7edffaea896db81a17e7811e939c3c4 to your computer and use it in GitHub Desktop.
Save ashtonchase/f7edffaea896db81a17e7811e939c3c4 to your computer and use it in GitHub Desktop.
FreeRTOS Kernel Aware Debug GDB helper file for Cortex A9
/*
* ca9_debug_gdb_helper.c
*
* Created on: 17.05.2013
* Author: Artem Pisarenko
*
* Helper file for ARM Cortex-M3 port of FreeRTOS.
* Used in conjunction with .gdbinit-FreeRTOS-helpers script.
*
* Add following replacement macro in FreeRTOSConfig.h:
* #define xPortPendSVHandler xPortPendSVHandler_native // any valid c identifier name
*
* Replaced xPortPendSVHandler handles command invocations from gdb via dbgXXX variables
* and performs context switch.
*
* Revised on: 09.JUNE.2019
* Author: Ashton Johnson
*
* Revised to target Cortex-A9.
* Updated psr to cpsr
*/
#include "FreeRTOS.h"
#ifdef xPortPendSVHandler
#define DBG_STRINGIFY_THIS_(arg) #arg
#define DBG_STRINGIFY_THIS(arg) DBG_STRINGIFY_THIS_(arg)
/* Switch control variable:
* 0 - no hook installed (normal execution),
* 1 - hook installation performed,
* 2 - following hooked switches
*/
int volatile dbgPendSVHookState = 2;
/* Requested target task handle variable */
void * volatile dbgPendingTaskHandle;
const int volatile dbgFreeRTOSConfig_suspend_value = INCLUDE_vTaskSuspend;
const int volatile dbgFreeRTOSConfig_delete_value = INCLUDE_vTaskDelete;
void __attribute__ ((naked)) xPortPendSVHandler_jumper( void ) {
__asm volatile("b " DBG_STRINGIFY_THIS(xPortPendSVHandler));
}
#undef xPortPendSVHandler
void __attribute__ ((naked)) xPortPendSVHandler( void ) {
/* Double-right-shifted (tabbed) lines are those from native (port provided) xPortPendSVHandler */
__asm volatile
(
" ldr r1, _dbgPendSVHookState \n" /* Check hook installed */
" ldr r0, [r1] \n"
" cmp r0, #0 \n"
" beq xPortPendSVHandler_jumper \n" /* if no hook installed then jump to native handler, else proceed... */
" cmp r0, #1 \n" /* check whether hook triggered for the first time... */
" bne dbg_switch_to_pending_task \n" /* if not so, then jump to switching right now, otherwise current task context must be saved first... */
" mov r0, #2 \n" /* mark hook after triggered for the first time */
" str r0, [r1] \n"
" mrs r0, cpsr \n"
" \n"
" ldr r3, pxCurrentTCBConst \n" /* Get the location of the current TCB. */
" ldr r2, [r3] \n"
" \n"
" stmdb r0!, {r4-r11} \n" /* Save the remaining registers. */
" str r0, [r2] \n" /* Save the new top of stack into the first member of the TCB. */
" \n"
#if 0
" stmdb sp!, {r3, r14} \n"
" mov r0, %0 \n"
" msr basepri, r0 \n"
" bl vTaskSwitchContext \n"
" mov r0, #0 \n"
" msr basepri, r0 \n"
" ldmia sp!, {r3, r14} \n"
#else
"dbg_switch_to_pending_task: \n"
" ldr r3, _dbgPendingTaskHandle \n" /* --> Load task handle going to switch to <-- */
#endif
" \n" /* Restore the context. */
" ldr r1, [r3] \n"
" ldr r0, [r1] \n" /* The first item in the TCB is the task top of stack. */
" ldmia r0!, {r4-r11} \n" /* Pop the registers. */
" msr cpsr, r0 \n"
#if 1
" bkpt \n" /* <-- here debugger stops and steps out to target task context */
#endif
" bx r14 \n"
" \n"
" .align 2 \n"
"pxCurrentTCBConst: .word pxCurrentTCB \n"
"_dbgPendSVHookState: .word dbgPendSVHookState \n"
"_dbgPendingTaskHandle: .word dbgPendingTaskHandle \n"
".word dbgFreeRTOSConfig_suspend_value \n" /* force keep these symbols from cutting away by garbage collector */
".word dbgFreeRTOSConfig_delete_value \n"
::"i"(configMAX_API_CALL_INTERRUPT_PRIORITY)
);
}
#endif /* xPortPendSVHandler */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment