Skip to content

Commit

Permalink
Core dump analysis improvements
Browse files Browse the repository at this point in the history
 * ARM
   * Provide MSP and PSP
   * Provide FreeRTOS task info
   * Profide target specification XML (extra regs and FPU / no FPU Cortex cores)
 * ESP32
   * Use uxTaskGetSystemState instead of uxTaskGetTaskHandles
 * General cleanup and refactoring

CL: Core dump analysis improvements

PUBLISHED_FROM=3297ffb2e6069a3a6a598367273bc2183063cf1e
  • Loading branch information
Deomid Ryabkov authored and cesantabot committed Apr 10, 2019
1 parent 8fab526 commit 054cc35
Show file tree
Hide file tree
Showing 5 changed files with 142 additions and 1 deletion.
2 changes: 1 addition & 1 deletion include/FreeRTOSConfigCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@

#define configUSE_MALLOC_FAILED_HOOK 0
#define configUSE_TICKLESS_IDLE 0
#define configUSE_TRACE_FACILITY 0
#define configUSE_TRACE_FACILITY 1
#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1
#define configAPPLICATION_ALLOCATED_HEAP 0
#define configUSE_TASK_NOTIFICATIONS 1
Expand Down
8 changes: 8 additions & 0 deletions include/mgos_freertos.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <stdbool.h>

#include "FreeRTOS.h"
#include "queue.h"
#include "task.h"

#include "mgos_init.h"

Expand All @@ -19,6 +21,12 @@ void mgos_freertos_run_mgos_task(bool start_scheduler);

extern enum mgos_init_result mgos_freertos_pre_init(void);

void mgos_freertos_core_dump(void);

// This function extracts registers from the task's stack frame
// and populates GDB stack frame.
size_t mgos_freertos_extract_regs(StackType_t *sp, void *buf, size_t buf_size);

#ifdef __cplusplus
}
#endif
69 changes: 69 additions & 0 deletions src/cmsis/mgos_arm_regs.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
/*
* Copyright (c) 2014-2018 Cesanta Software Limited
* All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the ""License"");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an ""AS IS"" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include <string.h>

#include "arm_exc.h"
#include "mgos_freertos.h"

// This uses the same logic as xPortPendSVHandler does when switching tasks.
size_t mgos_freertos_extract_regs(StackType_t *sp, void *buf, size_t buf_size) {
struct arm_gdb_reg_file *rf = (struct arm_gdb_reg_file *) buf;
if (buf_size < sizeof(*rf)) return 0;
// ldmia r0!, {r4-r11, r14}
rf->r[4] = *sp++;
rf->r[5] = *sp++;
rf->r[6] = *sp++;
rf->r[7] = *sp++;
rf->r[8] = *sp++;
rf->r[9] = *sp++;
rf->r[10] = *sp++;
rf->r[11] = *sp++;
uint32_t exc_lr = *sp++;
#if __FPU_PRESENT
// Is the task using the FPU context? If so, pop the high vfp registers too.
bool fpu_used = (exc_lr & 0x10) == 0;
if (fpu_used) {
// vldmiaeq r0!, {s16-s31}
memcpy((void *) &rf->d[8], sp, 16 * 4);
sp += 16;
}
#endif
// After this we have standard exception frame.
rf->r[0] = *sp++;
rf->r[1] = *sp++;
rf->r[2] = *sp++;
rf->r[3] = *sp++;
rf->r[12] = *sp++;
rf->lr = *sp++;
rf->pc = *sp++;
rf->xpsr = *sp++;
#if __FPU_PRESENT
if (fpu_used) {
memcpy((void *) &rf->d[0], sp, 16 * 4); // s0 - s15
sp += 16;
rf->fpscr = *sp++;
sp++; // reserved
}
#else
(void) exc_lr;
#endif
rf->sp = (uint32_t) sp;
rf->psp = (uint32_t) sp;
// msp? do we need it?
return sizeof(*rf);
}
2 changes: 2 additions & 0 deletions src/mgos_freertos.c
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,8 @@ void mgos_freertos_run_mgos_task(bool start_scheduler) {

mgos_app_preinit();

mgos_cd_register_section_writer(mgos_freertos_core_dump);

s_mgos_mux = xSemaphoreCreateRecursiveMutex();
s_mg_poll_timer = xTimerCreate("mg_poll", 10, pdFALSE /* reload */, 0,
mgos_mg_poll_timer_cb);
Expand Down
62 changes: 62 additions & 0 deletions src/mgos_freertos_core_dump.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright (c) 2014-2019 Cesanta Software Limited
* All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the ""License"");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an ""AS IS"" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "mgos_freertos.h"

#include "common/platform.h"

#include "mgos_core_dump.h"
#include "mgos_utils.h"

// TODO(rojer): Multi-processor support.

extern TaskHandle_t pxCurrentTCB;

void mgos_freertos_core_dump(void) {
uint32_t unused_runtime;
TaskStatus_t tss[16];
mgos_cd_puts(",\r\n\"freertos\":{\"tasks\":[");
UBaseType_t n = uxTaskGetSystemState(tss, ARRAY_SIZE(tss), &unused_runtime);
for (UBaseType_t i = 0; i < n; i++) {
const TaskStatus_t *ts = &tss[i];
if (i > 0) mgos_cd_puts(",");
// Topt of stack pointer is the first member of the task structure.
StackType_t *pxTopOfStack = *((StackType_t **) ts->xHandle);
mgos_cd_puts("\r\n");
mgos_cd_printf(
"{\"h\":%lu,\"n\":\"%s\",\"st\":%lu,"
"\"cpri\":%lu,\"bpri\":%lu,\"sb\":%lu,\"sp\":%lu",
(unsigned long) ts->xHandle, ts->pcTaskName,
(unsigned long) ts->eCurrentState,
(unsigned long) ts->uxCurrentPriority,
(unsigned long) ts->uxBasePriority, (unsigned long) ts->pxStackBase,
(unsigned long) pxTopOfStack);
if (ts->xHandle != pxCurrentTCB) {
uint32_t buf[128]; // Surely this will be enough.
memset(buf, 0, sizeof(buf));
size_t regs_size =
mgos_freertos_extract_regs(pxTopOfStack, &buf, sizeof(buf));
if (regs_size > 0) {
mgos_cd_write_section("regs", buf, regs_size);
}
} else {
// For running task current backtrace will be used.
}
mgos_cd_puts("}");
}
mgos_cd_printf("\r\n],\"cur\":%lu}", (unsigned long) pxCurrentTCB);
}

0 comments on commit 054cc35

Please sign in to comment.