forked from nuttx/nuttx-update
arch: move stack and task dump to common code
Signed-off-by: zhangyuan21 <zhangyuan21@xiaomi.com>
This commit is contained in:
parent
739aca095a
commit
453a1a7332
117 changed files with 2447 additions and 4630 deletions
|
@ -43,33 +43,6 @@
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
#if 0 /* Was useful in solving some startup problems */
|
||||
static inline void arm_registerdump(struct tcb_s *tcb)
|
||||
{
|
||||
int regndx;
|
||||
|
||||
_info("CPU%d:\n", up_cpu_index());
|
||||
|
||||
/* Dump the startup registers */
|
||||
|
||||
for (regndx = REG_R0; regndx <= REG_R15; regndx += 8)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)&tcb->xcp.regs[regndx];
|
||||
_info("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
regndx, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
|
||||
_info("CPSR: %08x\n", tcb->xcp.regs[REG_CPSR]);
|
||||
}
|
||||
#else
|
||||
# define arm_registerdump(tcb)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -108,7 +81,9 @@ int arm_start_handler(int irq, void *context, void *arg)
|
|||
|
||||
/* Dump registers so that we can see what is going to happen on return */
|
||||
|
||||
arm_registerdump(tcb);
|
||||
#if 0
|
||||
arm_registerdump(tcb->xcp.regs);
|
||||
#endif
|
||||
|
||||
/* Then switch contexts. This instantiates the exception context of the
|
||||
* tcb at the head of the assigned task list. In this case, this should
|
||||
|
|
|
@ -26,7 +26,7 @@ CMN_CSRCS += arm_initialize.c arm_lowputs.c
|
|||
CMN_CSRCS += arm_modifyreg16.c arm_modifyreg32.c
|
||||
CMN_CSRCS += arm_modifyreg8.c arm_nputs.c
|
||||
CMN_CSRCS += arm_releasestack.c arm_saveusercontext.c
|
||||
CMN_CSRCS += arm_stackframe.c
|
||||
CMN_CSRCS += arm_stackframe.c arm_registerdump.c arm_getintstack.c
|
||||
CMN_CSRCS += arm_vfork.c arm_switchcontext.c arm_usestack.c
|
||||
|
||||
ifneq ($(CONFIG_ALARM_ARCH),y)
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include <stdint.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/tls.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/board.h>
|
||||
|
||||
|
@ -37,8 +36,6 @@
|
|||
#include "sched/sched.h"
|
||||
#include "arm_internal.h"
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
@ -46,300 +43,18 @@
|
|||
static uint8_t s_last_regs[XCPTCONTEXT_SIZE];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_stackdump
|
||||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
static void arm_stackdump(uint32_t sp, uint32_t stack_top)
|
||||
{
|
||||
uint32_t stack;
|
||||
|
||||
for (stack = sp & ~0x1f; stack < (stack_top & ~0x1f); stack += 32)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)stack;
|
||||
_alert("%08" PRIx32 ": %08" PRIx32 " %08" PRIx32 " %08" PRIx32
|
||||
" %08" PRIx32 " %08" PRIx32 " %08" PRIx32 " %08" PRIx32
|
||||
" %08" PRIx32 "\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
static void arm_registerdump(volatile uint32_t *regs)
|
||||
{
|
||||
/* Dump the interrupt registers */
|
||||
|
||||
_alert("R0: %08" PRIx32 " R1: %08" PRIx32
|
||||
" R2: %08" PRIx32 " R3: %08" PRIx32 "\n",
|
||||
regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3]);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
_alert("R4: %08" PRIx32 " R5: %08" PRIx32
|
||||
" R6: %08" PRIx32 " FP: %08" PRIx32 "\n",
|
||||
regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]);
|
||||
_alert("R8: %08" PRIx32 " SB: %08" PRIx32
|
||||
" SL: %08" PRIx32 " R11: %08" PRIx32 "\n",
|
||||
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11]);
|
||||
#else
|
||||
_alert("R4: %08" PRIx32 " R5: %08" PRIx32
|
||||
" R6: %08" PRIx32 " R7: %08" PRIx32 "\n",
|
||||
regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]);
|
||||
_alert("R8: %08" PRIx32 " SB: %08" PRIx32
|
||||
" SL: %08" PRIx32 " FP: %08" PRIx32 "\n",
|
||||
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11]);
|
||||
#endif
|
||||
_alert("IP: %08" PRIx32 " SP: %08" PRIx32
|
||||
" LR: %08" PRIx32 " PC: %08" PRIx32 "\n",
|
||||
regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
|
||||
|
||||
#if defined(REG_BASEPRI)
|
||||
_alert("xPSR: %08" PRIx32 " BASEPRI: %08" PRIx32
|
||||
" CONTROL: %08" PRIx32 "\n",
|
||||
regs[REG_XPSR], regs[REG_BASEPRI], getcontrol());
|
||||
#elif defined(REG_PRIMASK)
|
||||
_alert("xPSR: %08" PRIx32 " PRIMASK: %08" PRIx32
|
||||
" CONTROL: %08" PRIx32 "\n",
|
||||
regs[REG_XPSR], regs[REG_PRIMASK], getcontrol());
|
||||
#elif defined(REG_CPSR)
|
||||
_alert("CPSR: %08" PRIx32 "\n", regs[REG_CPSR]);
|
||||
#endif
|
||||
|
||||
#ifdef REG_EXC_RETURN
|
||||
_alert("EXC_RETURN: %08" PRIx32 "\n", regs[REG_EXC_RETURN]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_dump_task
|
||||
****************************************************************************/
|
||||
|
||||
static void arm_dump_task(struct tcb_s *tcb, void *arg)
|
||||
{
|
||||
char args[64] = "";
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
uint32_t stack_filled = 0;
|
||||
uint32_t stack_used;
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CPULOAD
|
||||
struct cpuload_s cpuload;
|
||||
uint32_t fracpart;
|
||||
uint32_t intpart;
|
||||
uint32_t tmp;
|
||||
|
||||
clock_cpuload(tcb->pid, &cpuload);
|
||||
|
||||
if (cpuload.total > 0)
|
||||
{
|
||||
tmp = (1000 * cpuload.active) / cpuload.total;
|
||||
intpart = tmp / 10;
|
||||
fracpart = tmp - 10 * intpart;
|
||||
}
|
||||
else
|
||||
{
|
||||
intpart = 0;
|
||||
fracpart = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
stack_used = up_check_tcbstack(tcb);
|
||||
if (tcb->adj_stack_size > 0 && stack_used > 0)
|
||||
{
|
||||
/* Use fixed-point math with one decimal place */
|
||||
|
||||
stack_filled = 10 * 100 * stack_used / tcb->adj_stack_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISABLE_PTHREAD
|
||||
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD)
|
||||
{
|
||||
struct pthread_tcb_s *ptcb = (struct pthread_tcb_s *)tcb;
|
||||
|
||||
snprintf(args, sizeof(args), " %p", ptcb->arg);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
char **argv = tcb->group->tg_info->argv + 1;
|
||||
size_t npos = 0;
|
||||
|
||||
while (*argv != NULL && npos < sizeof(args))
|
||||
{
|
||||
npos += snprintf(args + npos, sizeof(args) - npos, " %s", *argv++);
|
||||
}
|
||||
}
|
||||
|
||||
/* Dump interesting properties of this task */
|
||||
|
||||
_alert(" %4d %4d"
|
||||
#ifdef CONFIG_SMP
|
||||
" %4d"
|
||||
#endif
|
||||
" %7lu"
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
" %7lu %3" PRId32 ".%1" PRId32 "%%%c"
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CPULOAD
|
||||
" %3" PRId32 ".%01" PRId32 "%%"
|
||||
#endif
|
||||
" %s%s\n"
|
||||
, tcb->pid, tcb->sched_priority
|
||||
#ifdef CONFIG_SMP
|
||||
, tcb->cpu
|
||||
#endif
|
||||
, (unsigned long)tcb->adj_stack_size
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
, (unsigned long)up_check_tcbstack(tcb)
|
||||
, stack_filled / 10, stack_filled % 10
|
||||
, (stack_filled >= 10 * 80 ? '!' : ' ')
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CPULOAD
|
||||
, intpart, fracpart
|
||||
#endif
|
||||
#if CONFIG_TASK_NAME_SIZE > 0
|
||||
, tcb->name
|
||||
#else
|
||||
, "<noname>"
|
||||
#endif
|
||||
, args
|
||||
);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_dump_backtrace
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SCHED_BACKTRACE
|
||||
static void arm_dump_backtrace(struct tcb_s *tcb, void *arg)
|
||||
{
|
||||
/* Show back trace */
|
||||
|
||||
sched_dumpstack(tcb->pid);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_showtasks
|
||||
****************************************************************************/
|
||||
|
||||
static void arm_showtasks(void)
|
||||
{
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 7
|
||||
# ifdef CONFIG_STACK_COLORATION
|
||||
uint32_t stack_used = up_check_intstack();
|
||||
uint32_t stack_filled = 0;
|
||||
|
||||
if ((CONFIG_ARCH_INTERRUPTSTACK & ~7) > 0 && stack_used > 0)
|
||||
{
|
||||
/* Use fixed-point math with one decimal place */
|
||||
|
||||
stack_filled = 10 * 100 *
|
||||
stack_used / (CONFIG_ARCH_INTERRUPTSTACK & ~7);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Dump interesting properties of each task in the crash environment */
|
||||
|
||||
_alert(" PID PRI"
|
||||
#ifdef CONFIG_SMP
|
||||
" CPU"
|
||||
#endif
|
||||
" STACK"
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
" USED FILLED "
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CPULOAD
|
||||
" CPU"
|
||||
#endif
|
||||
" COMMAND\n");
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 7
|
||||
_alert(" ---- ----"
|
||||
# ifdef CONFIG_SMP
|
||||
" ----"
|
||||
# endif
|
||||
" %7u"
|
||||
# ifdef CONFIG_STACK_COLORATION
|
||||
" %7" PRId32 " %3" PRId32 ".%1" PRId32 "%%%c"
|
||||
# endif
|
||||
# ifdef CONFIG_SCHED_CPULOAD
|
||||
" ----"
|
||||
# endif
|
||||
" irq\n"
|
||||
, (CONFIG_ARCH_INTERRUPTSTACK & ~7)
|
||||
# ifdef CONFIG_STACK_COLORATION
|
||||
, stack_used
|
||||
, stack_filled / 10, stack_filled % 10,
|
||||
(stack_filled >= 10 * 80 ? '!' : ' ')
|
||||
# endif
|
||||
);
|
||||
#endif
|
||||
|
||||
nxsched_foreach(arm_dump_task, NULL);
|
||||
#ifdef CONFIG_SCHED_BACKTRACE
|
||||
nxsched_foreach(arm_dump_backtrace, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_dump_stack
|
||||
****************************************************************************/
|
||||
|
||||
static void arm_dump_stack(const char *tag, uint32_t sp,
|
||||
uint32_t base, uint32_t size, bool force)
|
||||
{
|
||||
uint32_t top = base + size;
|
||||
|
||||
_alert("%s Stack:\n", tag);
|
||||
_alert("sp: %08" PRIx32 "\n", sp);
|
||||
_alert(" base: %08" PRIx32 "\n", base);
|
||||
_alert(" size: %08" PRIx32 "\n", size);
|
||||
|
||||
if (sp >= base && sp < top)
|
||||
{
|
||||
arm_stackdump(sp, top);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: %s Stack pointer is not within the stack\n", tag);
|
||||
if (force)
|
||||
{
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
uint32_t remain;
|
||||
|
||||
remain = size - arm_stack_check((void *)(uintptr_t)base, size);
|
||||
base += remain;
|
||||
size -= remain;
|
||||
#endif
|
||||
|
||||
#if CONFIG_ARCH_STACKDUMP_MAX_LENGTH > 0
|
||||
if (size > CONFIG_ARCH_STACKDUMP_MAX_LENGTH)
|
||||
{
|
||||
size = CONFIG_ARCH_STACKDUMP_MAX_LENGTH;
|
||||
}
|
||||
#endif
|
||||
|
||||
arm_stackdump(base, base + size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
static void arm_dumpstate(void)
|
||||
void up_assert(void)
|
||||
{
|
||||
struct tcb_s *rtcb = running_task();
|
||||
uint32_t sp = up_getsp();
|
||||
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
|
||||
/* Update the xcp context */
|
||||
|
||||
|
@ -353,78 +68,7 @@ static void arm_dumpstate(void)
|
|||
rtcb->xcp.regs = (uint32_t *)s_last_regs;
|
||||
}
|
||||
|
||||
/* Show back trace */
|
||||
|
||||
#ifdef CONFIG_SCHED_BACKTRACE
|
||||
sched_dumpstack(rtcb->pid);
|
||||
#endif
|
||||
|
||||
/* Dump the registers */
|
||||
/* Dump the interrupt registers */
|
||||
|
||||
arm_registerdump(rtcb->xcp.regs);
|
||||
|
||||
/* Dump the irq stack */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 7
|
||||
arm_dump_stack("IRQ", sp,
|
||||
# ifdef CONFIG_SMP
|
||||
(uint32_t)arm_intstack_alloc(),
|
||||
# else
|
||||
(uint32_t)g_intstackalloc,
|
||||
# endif
|
||||
(CONFIG_ARCH_INTERRUPTSTACK & ~7),
|
||||
!!CURRENT_REGS);
|
||||
|
||||
if (CURRENT_REGS)
|
||||
{
|
||||
sp = CURRENT_REGS[REG_R13];
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Dump the user stack */
|
||||
|
||||
arm_dump_stack("User", sp,
|
||||
(uint32_t)rtcb->stack_base_ptr,
|
||||
(uint32_t)rtcb->adj_stack_size,
|
||||
#ifdef CONFIG_ARCH_KERNEL_STACK
|
||||
false
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
);
|
||||
|
||||
#ifdef CONFIG_ARCH_KERNEL_STACK
|
||||
arm_dump_stack("Kernel", sp,
|
||||
(uint32_t)rtcb->xcp.kstack,
|
||||
CONFIG_ARCH_KERNEL_STACKSIZE,
|
||||
false);
|
||||
#endif
|
||||
|
||||
/* Dump the state of all tasks (if available) */
|
||||
|
||||
arm_showtasks();
|
||||
|
||||
#ifdef CONFIG_ARCH_USBDUMP
|
||||
/* Dump USB trace data */
|
||||
|
||||
usbtrace_enumerate(assert_tracecallback, NULL);
|
||||
#endif
|
||||
}
|
||||
#endif /* CONFIG_ARCH_STACKDUMP */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
void up_assert(const char *filename, int lineno)
|
||||
{
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
arm_dumpstate();
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -242,13 +242,8 @@ ssize_t up_check_stack_remain(void)
|
|||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
size_t up_check_intstack(void)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
return arm_stack_check((void *)arm_intstack_alloc(),
|
||||
return arm_stack_check((void *)up_get_intstackbase(),
|
||||
STACK_ALIGN_DOWN(CONFIG_ARCH_INTERRUPTSTACK));
|
||||
#else
|
||||
return arm_stack_check(g_intstackalloc,
|
||||
STACK_ALIGN_DOWN(CONFIG_ARCH_INTERRUPTSTACK));
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t up_check_intstack_remain(void)
|
||||
|
|
49
arch/arm/src/common/arm_getintstack.c
Normal file
49
arch/arm/src/common/arm_getintstack.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/common/arm_getintstack.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_intstackbase
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uintptr_t up_get_intstackbase(void)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
return arm_intstack_alloc();
|
||||
#else
|
||||
return (uintptr_t)g_intstackalloc;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
|
@ -480,6 +480,8 @@ size_t arm_stack_check(void *stackbase, size_t nbytes);
|
|||
void arm_stack_color(void *stackbase, size_t nbytes);
|
||||
#endif
|
||||
|
||||
void arm_registerdump(volatile uint32_t *regs);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
98
arch/arm/src/common/arm_registerdump.c
Normal file
98
arch/arm/src/common/arm_registerdump.c
Normal file
|
@ -0,0 +1,98 @@
|
|||
/****************************************************************************
|
||||
* arch/arm/src/common/arm_registerdump.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "arm_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
return CURRENT_REGS[REG_SP];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
void arm_registerdump(volatile uint32_t *regs)
|
||||
{
|
||||
/* Dump the interrupt registers */
|
||||
|
||||
_alert("R0: %08" PRIx32 " R1: %08" PRIx32
|
||||
" R2: %08" PRIx32 " R3: %08" PRIx32 "\n",
|
||||
regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3]);
|
||||
#ifdef CONFIG_ARM_THUMB
|
||||
_alert("R4: %08" PRIx32 " R5: %08" PRIx32
|
||||
" R6: %08" PRIx32 " FP: %08" PRIx32 "\n",
|
||||
regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]);
|
||||
_alert("R8: %08" PRIx32 " SB: %08" PRIx32
|
||||
" SL: %08" PRIx32 " R11: %08" PRIx32 "\n",
|
||||
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11]);
|
||||
#else
|
||||
_alert("R4: %08" PRIx32 " R5: %08" PRIx32
|
||||
" R6: %08" PRIx32 " R7: %08" PRIx32 "\n",
|
||||
regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]);
|
||||
_alert("R8: %08" PRIx32 " SB: %08" PRIx32
|
||||
" SL: %08" PRIx32 " FP: %08" PRIx32 "\n",
|
||||
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11]);
|
||||
#endif
|
||||
_alert("IP: %08" PRIx32 " SP: %08" PRIx32
|
||||
" LR: %08" PRIx32 " PC: %08" PRIx32 "\n",
|
||||
regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
|
||||
|
||||
#if defined(REG_BASEPRI)
|
||||
_alert("xPSR: %08" PRIx32 " BASEPRI: %08" PRIx32
|
||||
" CONTROL: %08" PRIx32 "\n",
|
||||
regs[REG_XPSR], regs[REG_BASEPRI], getcontrol());
|
||||
#elif defined(REG_PRIMASK)
|
||||
_alert("xPSR: %08" PRIx32 " PRIMASK: %08" PRIx32
|
||||
" CONTROL: %08" PRIx32 "\n",
|
||||
regs[REG_XPSR], regs[REG_PRIMASK], getcontrol());
|
||||
#elif defined(REG_CPSR)
|
||||
_alert("CPSR: %08" PRIx32 "\n", regs[REG_CPSR]);
|
||||
#endif
|
||||
|
||||
#ifdef REG_EXC_RETURN
|
||||
_alert("EXC_RETURN: %08" PRIx32 "\n", regs[REG_EXC_RETURN]);
|
||||
#endif
|
||||
}
|
|
@ -238,7 +238,7 @@ static int bt_hci_send(struct bt_driver_s *btdev,
|
|||
static void sdc_fault_handler(const char *file, const uint32_t line)
|
||||
{
|
||||
_alert("SoftDevice Controller Fault\n");
|
||||
up_assert(file, line);
|
||||
_assert(file, line);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -248,7 +248,7 @@ static void sdc_fault_handler(const char *file, const uint32_t line)
|
|||
static void mpsl_assert_handler(const char *const file, const uint32_t line)
|
||||
{
|
||||
_alert("MPSL assertion failed\n");
|
||||
up_assert(file, line);
|
||||
_assert(file, line);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
|
|
@ -48,6 +48,7 @@ CMN_CSRCS += arm64_createstack.c arm64_releasestack.c arm64_stackframe.c arm64_u
|
|||
CMN_CSRCS += arm64_task_sched.c arm64_exit.c arm64_vfork.c arm64_switchcontext.c
|
||||
CMN_CSRCS += arm64_assert.c arm64_schedulesigaction.c arm64_backtrace.c
|
||||
CMN_CSRCS += arm64_sigdeliver.c arm64_systemreset.c
|
||||
CMN_CSRCS += arm64_getintstack.c arm64_registerdump.c
|
||||
|
||||
# Common C source files ( hardware BSP )
|
||||
CMN_CSRCS += arm64_mmu.c arm64_arch_timer.c arm64_cache.c
|
||||
|
|
|
@ -39,384 +39,14 @@
|
|||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_registerdump
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
static void arm64_registerdump(struct regs_context * regs)
|
||||
{
|
||||
_alert("stack = %p\n", regs);
|
||||
_alert("x0: 0x%-16"PRIx64" x1: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X0], regs->regs[REG_X1]);
|
||||
_alert("x2: 0x%-16"PRIx64" x3: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X2], regs->regs[REG_X3]);
|
||||
_alert("x4: 0x%-16"PRIx64" x5: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X4], regs->regs[REG_X5]);
|
||||
_alert("x6: 0x%-16"PRIx64" x7: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X6], regs->regs[REG_X7]);
|
||||
_alert("x8: 0x%-16"PRIx64" x9: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X8], regs->regs[REG_X9]);
|
||||
_alert("x10: 0x%-16"PRIx64" x11: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X10], regs->regs[REG_X11]);
|
||||
_alert("x12: 0x%-16"PRIx64" x13: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X12], regs->regs[REG_X13]);
|
||||
_alert("x14: 0x%-16"PRIx64" x15: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X14], regs->regs[REG_X15]);
|
||||
_alert("x16: 0x%-16"PRIx64" x17: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X16], regs->regs[REG_X17]);
|
||||
_alert("x18: 0x%-16"PRIx64" x19: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X18], regs->regs[REG_X19]);
|
||||
_alert("x20: 0x%-16"PRIx64" x21: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X20], regs->regs[REG_X21]);
|
||||
_alert("x22: 0x%-16"PRIx64" x23: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X22], regs->regs[REG_X23]);
|
||||
_alert("x24: 0x%-16"PRIx64" x25: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X24], regs->regs[REG_X25]);
|
||||
_alert("x26: 0x%-16"PRIx64" x27: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X26], regs->regs[REG_X27]);
|
||||
_alert("x28: 0x%-16"PRIx64" x29: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X28], regs->regs[REG_X29]);
|
||||
_alert("x30: 0x%-16"PRIx64"\n", regs->regs[REG_X30]);
|
||||
|
||||
_alert("\n");
|
||||
_alert("STATUS Registers:\n");
|
||||
_alert("SPSR: 0x%-16"PRIx64"\n", regs->spsr);
|
||||
_alert("ELR: 0x%-16"PRIx64"\n", regs->elr);
|
||||
_alert("SP_EL0: 0x%-16"PRIx64"\n", regs->sp_el0);
|
||||
_alert("SP_ELX: 0x%-16"PRIx64"\n", regs->sp_elx);
|
||||
_alert("TPIDR_EL0: 0x%-16"PRIx64"\n", regs->tpidr_el0);
|
||||
_alert("TPIDR_EL1: 0x%-16"PRIx64"\n", regs->tpidr_el1);
|
||||
_alert("EXE_DEPTH: 0x%-16"PRIx64"\n", regs->exe_depth);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_stackdump
|
||||
****************************************************************************/
|
||||
|
||||
static void arm64_stackdump(uint64_t sp, uint64_t stack_top)
|
||||
{
|
||||
uint64_t stack;
|
||||
|
||||
for (stack = sp & ~0x1f; stack < (stack_top & ~0x1f); stack += 64)
|
||||
{
|
||||
uint64_t *ptr = (uint64_t *)stack;
|
||||
_alert("%08" PRIx64 ": %08" PRIx64 " %08" PRIx64 " %08" PRIx64
|
||||
" %08" PRIx64 " %08" PRIx64 " %08" PRIx64 " %08" PRIx64
|
||||
" %08" PRIx64 "\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_dump_task
|
||||
****************************************************************************/
|
||||
|
||||
static void arm64_dump_task(struct tcb_s *tcb, void *arg)
|
||||
{
|
||||
char args[64] = "";
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
uint64_t stack_filled = 0;
|
||||
uint64_t stack_used;
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CPULOAD
|
||||
struct cpuload_s cpuload;
|
||||
uint64_t fracpart;
|
||||
uint64_t intpart;
|
||||
uint64_t tmp;
|
||||
|
||||
clock_cpuload(tcb->pid, &cpuload);
|
||||
|
||||
if (cpuload.total > 0)
|
||||
{
|
||||
tmp = (1000 * cpuload.active) / cpuload.total;
|
||||
intpart = tmp / 10;
|
||||
fracpart = tmp - 10 * intpart;
|
||||
}
|
||||
else
|
||||
{
|
||||
intpart = 0;
|
||||
fracpart = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
stack_used = up_check_tcbstack(tcb);
|
||||
if (tcb->adj_stack_size > 0 && stack_used > 0)
|
||||
{
|
||||
/* Use fixed-point math with one decimal place */
|
||||
|
||||
stack_filled = 10 * 100 * stack_used / tcb->adj_stack_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISABLE_PTHREAD
|
||||
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD)
|
||||
{
|
||||
struct pthread_tcb_s *ptcb = (struct pthread_tcb_s *)tcb;
|
||||
|
||||
snprintf(args, sizeof(args), "%p ", ptcb->arg);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
char **argv = tcb->group->tg_info->argv + 1;
|
||||
size_t npos = 0;
|
||||
|
||||
while (*argv != NULL && npos < sizeof(args))
|
||||
{
|
||||
npos += snprintf(args + npos, sizeof(args) - npos, " %s", *argv++);
|
||||
}
|
||||
}
|
||||
|
||||
/* Dump interesting properties of this task */
|
||||
|
||||
_alert(" %4d %4d"
|
||||
#ifdef CONFIG_SMP
|
||||
" %4d"
|
||||
#endif
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
" %7lu"
|
||||
#endif
|
||||
" %7lu"
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
" %3" PRId64 ".%1" PRId64 "%%%c"
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CPULOAD
|
||||
" %3" PRId64 ".%01" PRId64 "%%"
|
||||
#endif
|
||||
#if CONFIG_TASK_NAME_SIZE > 0
|
||||
" %s %s\n",
|
||||
#else
|
||||
" %s\n",
|
||||
#endif
|
||||
tcb->pid, tcb->sched_priority,
|
||||
#ifdef CONFIG_SMP
|
||||
tcb->cpu,
|
||||
#endif
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
(unsigned long)up_check_tcbstack(tcb),
|
||||
#endif
|
||||
(unsigned long)tcb->adj_stack_size
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
, stack_filled / 10, stack_filled % 10,
|
||||
(stack_filled >= 10 * 80 ? '!' : ' ')
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CPULOAD
|
||||
, intpart, fracpart
|
||||
#endif
|
||||
#if CONFIG_TASK_NAME_SIZE > 0
|
||||
, tcb->name
|
||||
#else
|
||||
, "<noname>"
|
||||
#endif
|
||||
, args
|
||||
);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_dump_backtrace
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SCHED_BACKTRACE
|
||||
static void arm64_dump_backtrace(struct tcb_s *tcb, void *arg)
|
||||
{
|
||||
/* Show back trace */
|
||||
|
||||
sched_dumpstack(tcb->pid);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_showtasks
|
||||
****************************************************************************/
|
||||
|
||||
static void arm64_showtasks(void)
|
||||
{
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||
# ifdef CONFIG_STACK_COLORATION
|
||||
uint64_t stack_used = up_check_intstack();
|
||||
uint64_t stack_filled = 0;
|
||||
|
||||
if ((CONFIG_ARCH_INTERRUPTSTACK & ~15) > 0 && stack_used > 0)
|
||||
{
|
||||
/* Use fixed-point math with one decimal place */
|
||||
|
||||
stack_filled = 10 * 100 *
|
||||
stack_used / (CONFIG_ARCH_INTERRUPTSTACK & ~15);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Dump interesting properties of each task in the crash environment */
|
||||
|
||||
_alert(" PID PRI"
|
||||
#ifdef CONFIG_SMP
|
||||
" CPU"
|
||||
#endif
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
" USED"
|
||||
#endif
|
||||
" STACK"
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
" FILLED "
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CPULOAD
|
||||
" CPU"
|
||||
#endif
|
||||
" COMMAND\n");
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 7
|
||||
_alert(" ---- ----"
|
||||
# ifdef CONFIG_SMP
|
||||
" ----"
|
||||
# endif
|
||||
# ifdef CONFIG_STACK_COLORATION
|
||||
" %7lu"
|
||||
# endif
|
||||
" %7lu"
|
||||
# ifdef CONFIG_STACK_COLORATION
|
||||
" %3" PRId64 ".%1" PRId64 "%%%c"
|
||||
# endif
|
||||
# ifdef CONFIG_SCHED_CPULOAD
|
||||
" ----"
|
||||
# endif
|
||||
# if CONFIG_TASK_NAME_SIZE > 0
|
||||
" irq"
|
||||
# endif
|
||||
"\n"
|
||||
# ifdef CONFIG_STACK_COLORATION
|
||||
, (unsigned long)stack_used
|
||||
# endif
|
||||
, (unsigned long)(CONFIG_ARCH_INTERRUPTSTACK & ~15)
|
||||
# ifdef CONFIG_STACK_COLORATION
|
||||
, stack_filled / 10, stack_filled % 10,
|
||||
(stack_filled >= 10 * 80 ? '!' : ' ')
|
||||
# endif
|
||||
);
|
||||
#endif
|
||||
|
||||
nxsched_foreach(arm64_dump_task, NULL);
|
||||
#ifdef CONFIG_SCHED_BACKTRACE
|
||||
nxsched_foreach(arm64_dump_backtrace, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm_dump_stack
|
||||
****************************************************************************/
|
||||
|
||||
static void arm64_dump_stack(const char *tag, uint64_t sp,
|
||||
uint64_t base, uint64_t size, bool force)
|
||||
{
|
||||
uint64_t top = base + size;
|
||||
|
||||
_alert("%s Stack:\n", tag);
|
||||
_alert("sp: %08" PRIx64 "\n", sp);
|
||||
_alert(" base: %08" PRIx64 "\n", base);
|
||||
_alert(" size: %08" PRIx64 "\n", size);
|
||||
|
||||
if (sp >= base && sp < top)
|
||||
{
|
||||
arm64_stackdump(sp, top);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: %s Stack pointer is not within the stack\n", tag);
|
||||
|
||||
if (force)
|
||||
{
|
||||
arm64_stackdump(base, top);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm64_dumpstate_assert (for assert)
|
||||
****************************************************************************/
|
||||
|
||||
static void arm64_dumpstate_assert(void)
|
||||
{
|
||||
struct tcb_s *rtcb = (struct tcb_s *)arch_get_current_tcb();
|
||||
uint64_t sp = up_getsp();
|
||||
|
||||
/* Show back trace */
|
||||
|
||||
#ifdef CONFIG_SCHED_BACKTRACE
|
||||
sched_dumpstack(rtcb->pid);
|
||||
#endif
|
||||
|
||||
/* Update the xcp context */
|
||||
|
||||
if (CURRENT_REGS)
|
||||
{
|
||||
/* in interrupt */
|
||||
|
||||
rtcb->xcp.regs = (uint64_t *)CURRENT_REGS;
|
||||
}
|
||||
else
|
||||
{
|
||||
up_saveusercontext(rtcb->xcp.regs);
|
||||
}
|
||||
|
||||
/* Dump the registers */
|
||||
|
||||
arm64_registerdump((struct regs_context *)rtcb->xcp.regs);
|
||||
|
||||
/* Dump the irq stack */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 7
|
||||
arm64_dump_stack("IRQ", sp,
|
||||
# ifdef CONFIG_SMP
|
||||
(uint64_t)arm64_intstack_alloc(),
|
||||
# else
|
||||
(uint64_t)&g_interrupt_stack,
|
||||
# endif
|
||||
(CONFIG_ARCH_INTERRUPTSTACK & ~15),
|
||||
!!CURRENT_REGS);
|
||||
|
||||
if (CURRENT_REGS)
|
||||
{
|
||||
sp = CURRENT_REGS[REG_X13];
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Dump the user stack */
|
||||
|
||||
arm64_dump_stack("User", sp,
|
||||
(uint64_t)rtcb->stack_base_ptr,
|
||||
(uint64_t)rtcb->adj_stack_size,
|
||||
#ifdef CONFIG_ARCH_KERNEL_STACK
|
||||
false
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
);
|
||||
|
||||
#ifdef CONFIG_ARCH_KERNEL_STACK
|
||||
arm64_dump_stack("Kernel", sp,
|
||||
(uint64_t)rtcb->xcp.kstack,
|
||||
CONFIG_ARCH_KERNEL_STACKSIZE,
|
||||
false);
|
||||
#endif
|
||||
|
||||
/* Dump the state of all tasks (if available) */
|
||||
|
||||
arm64_showtasks();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_STACKDUMP */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm64_dump_fatal
|
||||
****************************************************************************/
|
||||
|
||||
void arm64_dump_fatal(struct regs_context * regs)
|
||||
void arm64_dump_fatal(struct regs_context *regs)
|
||||
{
|
||||
#ifdef CONFIG_SCHED_BACKTRACE
|
||||
struct tcb_s *rtcb = (struct tcb_s *)regs->tpidr_el1;
|
||||
|
@ -444,17 +74,28 @@ void up_mdelay(unsigned int milliseconds)
|
|||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
void up_assert(const char *filename, int lineno)
|
||||
void up_assert(void)
|
||||
{
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
arm64_dumpstate_assert();
|
||||
#endif
|
||||
struct tcb_s *rtcb = (struct tcb_s *)arch_get_current_tcb();
|
||||
|
||||
/* Update the xcp context */
|
||||
|
||||
if (CURRENT_REGS)
|
||||
{
|
||||
/* in interrupt */
|
||||
|
||||
rtcb->xcp.regs = (uint64_t *)CURRENT_REGS;
|
||||
}
|
||||
else
|
||||
{
|
||||
up_saveusercontext(rtcb->xcp.regs);
|
||||
}
|
||||
|
||||
/* Dump the registers */
|
||||
|
||||
arm64_registerdump((struct regs_context *)rtcb->xcp.regs);
|
||||
}
|
||||
|
|
|
@ -219,13 +219,8 @@ ssize_t up_check_stack_remain(void)
|
|||
#if CONFIG_ARCH_INTERRUPTSTACK > 7
|
||||
size_t up_check_intstack(void)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
return arm64_stack_check((void *)arm64_intstack_alloc(),
|
||||
return arm64_stack_check((void *)up_get_intstackbase(),
|
||||
STACK_ALIGN_DOWN(CONFIG_ARCH_INTERRUPTSTACK));
|
||||
#else
|
||||
return arm64_stack_check((void *)&g_interrupt_stack,
|
||||
STACK_ALIGN_DOWN(CONFIG_ARCH_INTERRUPTSTACK));
|
||||
#endif
|
||||
}
|
||||
|
||||
size_t up_check_intstack_remain(void)
|
||||
|
|
48
arch/arm64/src/common/arm64_getintstack.c
Normal file
48
arch/arm64/src/common/arm64_getintstack.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/common/arm64_getintstack.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "arm64_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_intstackbase
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 7
|
||||
uintptr_t up_get_intstackbase(void)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
return arm64_intstack_alloc();
|
||||
#else
|
||||
return (uintptr_t)g_interrupt_stack;
|
||||
#endif
|
||||
}
|
||||
#endif
|
|
@ -347,6 +347,8 @@ size_t arm64_stack_check(void *stackbase, size_t nbytes);
|
|||
void arm64_stack_color(void *stackbase, size_t nbytes);
|
||||
#endif
|
||||
|
||||
void arm64_registerdump(struct regs_context * regs);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
103
arch/arm64/src/common/arm64_registerdump.c
Normal file
103
arch/arm64/src/common/arm64_registerdump.c
Normal file
|
@ -0,0 +1,103 @@
|
|||
/****************************************************************************
|
||||
* arch/arm64/src/common/arm64_registerdump.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "arm64_arch.h"
|
||||
#include "arm64_internal.h"
|
||||
#include "chip.h"
|
||||
|
||||
#ifdef CONFIG_ARCH_FPU
|
||||
#include "arm64_fpu.h"
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
return CURRENT_REGS[REG_X13];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: arm64_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
void arm64_registerdump(struct regs_context * regs)
|
||||
{
|
||||
_alert("stack = %p\n", regs);
|
||||
_alert("x0: 0x%-16"PRIx64" x1: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X0], regs->regs[REG_X1]);
|
||||
_alert("x2: 0x%-16"PRIx64" x3: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X2], regs->regs[REG_X3]);
|
||||
_alert("x4: 0x%-16"PRIx64" x5: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X4], regs->regs[REG_X5]);
|
||||
_alert("x6: 0x%-16"PRIx64" x7: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X6], regs->regs[REG_X7]);
|
||||
_alert("x8: 0x%-16"PRIx64" x9: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X8], regs->regs[REG_X9]);
|
||||
_alert("x10: 0x%-16"PRIx64" x11: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X10], regs->regs[REG_X11]);
|
||||
_alert("x12: 0x%-16"PRIx64" x13: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X12], regs->regs[REG_X13]);
|
||||
_alert("x14: 0x%-16"PRIx64" x15: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X14], regs->regs[REG_X15]);
|
||||
_alert("x16: 0x%-16"PRIx64" x17: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X16], regs->regs[REG_X17]);
|
||||
_alert("x18: 0x%-16"PRIx64" x19: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X18], regs->regs[REG_X19]);
|
||||
_alert("x20: 0x%-16"PRIx64" x21: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X20], regs->regs[REG_X21]);
|
||||
_alert("x22: 0x%-16"PRIx64" x23: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X22], regs->regs[REG_X23]);
|
||||
_alert("x24: 0x%-16"PRIx64" x25: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X24], regs->regs[REG_X25]);
|
||||
_alert("x26: 0x%-16"PRIx64" x27: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X26], regs->regs[REG_X27]);
|
||||
_alert("x28: 0x%-16"PRIx64" x29: 0x%"PRIx64"\n",
|
||||
regs->regs[REG_X28], regs->regs[REG_X29]);
|
||||
_alert("x30: 0x%-16"PRIx64"\n", regs->regs[REG_X30]);
|
||||
|
||||
_alert("\n");
|
||||
_alert("STATUS Registers:\n");
|
||||
_alert("SPSR: 0x%-16"PRIx64"\n", regs->spsr);
|
||||
_alert("ELR: 0x%-16"PRIx64"\n", regs->elr);
|
||||
_alert("SP_EL0: 0x%-16"PRIx64"\n", regs->sp_el0);
|
||||
_alert("SP_ELX: 0x%-16"PRIx64"\n", regs->sp_elx);
|
||||
_alert("TPIDR_EL0: 0x%-16"PRIx64"\n", regs->tpidr_el0);
|
||||
_alert("TPIDR_EL1: 0x%-16"PRIx64"\n", regs->tpidr_el1);
|
||||
_alert("EXE_DEPTH: 0x%-16"PRIx64"\n", regs->exe_depth);
|
||||
}
|
|
@ -31,12 +31,7 @@ CMN_CSRCS += avr_initialize.c avr_initialstate.c
|
|||
CMN_CSRCS += avr_modifyreg8.c avr_modifyreg16.c avr_modifyreg32.c avr_releasestack.c
|
||||
CMN_CSRCS += avr_schedulesigaction.c avr_sigdeliver.c avr_stackframe.c
|
||||
CMN_CSRCS += avr_switchcontext.c avr_usestack.c avr_doirq.c avr_nputs.c
|
||||
|
||||
# Configuration-dependent common files
|
||||
|
||||
ifeq ($(CONFIG_ARCH_STACKDUMP),y)
|
||||
CMN_CSRCS += avr_dumpstate.c
|
||||
endif
|
||||
CMN_CSRCS += avr_registerdump.c avr_getintstack.c
|
||||
|
||||
# Required AT32UC3 files
|
||||
|
||||
|
|
|
@ -32,13 +32,10 @@ CMN_CSRCS += avr_mdelay.c avr_modifyreg8.c avr_modifyreg16.c avr_modifyreg32.c
|
|||
CMN_CSRCS += avr_nputs.c avr_releasestack.c
|
||||
CMN_CSRCS += avr_schedulesigaction.c avr_sigdeliver.c
|
||||
CMN_CSRCS += avr_stackframe.c avr_udelay.c avr_switchcontext.c avr_usestack.c
|
||||
CMN_CSRCS += avr_registerdump.c avr_getintstack.c
|
||||
|
||||
# Configuration-dependent common files
|
||||
|
||||
ifeq ($(CONFIG_ARCH_STACKDUMP),y)
|
||||
CMN_CSRCS += avr_dumpstate.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_AVR_SPI),y)
|
||||
CMN_CSRCS += avr_spi.c
|
||||
endif
|
||||
|
|
|
@ -32,13 +32,10 @@ CMN_CSRCS += avr_mdelay.c avr_modifyreg8.c avr_modifyreg16.c avr_modifyreg32.c
|
|||
CMN_CSRCS += avr_nputs.c avr_releasestack.c
|
||||
CMN_CSRCS += avr_schedulesigaction.c avr_sigdeliver.c
|
||||
CMN_CSRCS += avr_stackframe.c avr_udelay.c avr_switchcontext.c avr_usestack.c
|
||||
CMN_CSRCS += avr_registerdump.c avr_getintstack.c
|
||||
|
||||
# Configuration-dependent common files
|
||||
|
||||
ifeq ($(CONFIG_ARCH_STACKDUMP),y)
|
||||
CMN_CSRCS += avr_dumpstate.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_AVR_SPI),y)
|
||||
CMN_CSRCS += avr_spi.c
|
||||
endif
|
||||
|
|
|
@ -1,220 +0,0 @@
|
|||
/****************************************************************************
|
||||
* arch/avr/src/avr/avr_dumpstate.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/syslog/syslog.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "avr_internal.h"
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: avr_stackdump
|
||||
****************************************************************************/
|
||||
|
||||
static void avr_stackdump(uint16_t sp, uint16_t stack_top)
|
||||
{
|
||||
uint16_t stack;
|
||||
|
||||
/* Flush any buffered SYSLOG data to avoid overwrite */
|
||||
|
||||
syslog_flush();
|
||||
|
||||
for (stack = sp & ~0x7; stack < (stack_top & ~0x7); stack += 8)
|
||||
{
|
||||
uint8_t *ptr = (uint8_t *)stack;
|
||||
_alert("%04x: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: avr_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
static inline void avr_registerdump(void)
|
||||
{
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (g_current_regs)
|
||||
{
|
||||
_alert("R%02d: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
0,
|
||||
g_current_regs[REG_R0], g_current_regs[REG_R1],
|
||||
g_current_regs[REG_R2], g_current_regs[REG_R3],
|
||||
g_current_regs[REG_R4], g_current_regs[REG_R5],
|
||||
g_current_regs[REG_R6], g_current_regs[REG_R7]);
|
||||
|
||||
_alert("R%02d: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
8,
|
||||
g_current_regs[REG_R8], g_current_regs[REG_R9],
|
||||
g_current_regs[REG_R10], g_current_regs[REG_R11],
|
||||
g_current_regs[REG_R12], g_current_regs[REG_R13],
|
||||
g_current_regs[REG_R14], g_current_regs[REG_R15]);
|
||||
|
||||
_alert("R%02d: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
16,
|
||||
g_current_regs[REG_R16], g_current_regs[REG_R17],
|
||||
g_current_regs[REG_R18], g_current_regs[REG_R19],
|
||||
g_current_regs[REG_R20], g_current_regs[REG_R21],
|
||||
g_current_regs[REG_R22], g_current_regs[REG_R23]);
|
||||
|
||||
_alert("R%02d: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
24,
|
||||
g_current_regs[REG_R24], g_current_regs[REG_R25],
|
||||
g_current_regs[REG_R26], g_current_regs[REG_R27],
|
||||
g_current_regs[REG_R28], g_current_regs[REG_R29],
|
||||
g_current_regs[REG_R30], g_current_regs[REG_R31]);
|
||||
|
||||
#if !defined(REG_PC2)
|
||||
_alert("PC: %02x%02x SP: %02x%02x SREG: %02x\n",
|
||||
g_current_regs[REG_PC0], g_current_regs[REG_PC1],
|
||||
g_current_regs[REG_SPH], g_current_regs[REG_SPL],
|
||||
g_current_regs[REG_SREG]);
|
||||
#else
|
||||
_alert("PC: %02x%02x%02x SP: %02x%02x SREG: %02x\n",
|
||||
g_current_regs[REG_PC0], g_current_regs[REG_PC1],
|
||||
g_current_regs[REG_PC2], g_current_regs[REG_SPH],
|
||||
g_current_regs[REG_SPL], g_current_regs[REG_SREG]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: _up_assert
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: avr_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
void avr_dumpstate(void)
|
||||
{
|
||||
FAR struct tcb_s *rtcb = running_task();
|
||||
uint16_t sp = up_getsp();
|
||||
uint16_t ustackbase;
|
||||
uint16_t ustacksize;
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 0
|
||||
uint16_t istackbase;
|
||||
uint16_t istacksize;
|
||||
#endif
|
||||
|
||||
/* Dump the registers (if available) */
|
||||
|
||||
avr_registerdump();
|
||||
|
||||
/* Get the limits on the user stack memory */
|
||||
|
||||
ustackbase = (uint16_t)rtcb->stack_base_ptr;
|
||||
ustacksize = (uint16_t)rtcb->adj_stack_size;
|
||||
|
||||
/* Get the limits on the interrupt stack memory */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 0
|
||||
istackbase = (uint16_t)g_intstackalloc;
|
||||
istacksize = CONFIG_ARCH_INTERRUPTSTACK;
|
||||
|
||||
/* Show interrupt stack info */
|
||||
|
||||
_alert("sp: %04x\n", sp);
|
||||
_alert("IRQ stack:\n");
|
||||
_alert(" base: %04x\n", istackbase);
|
||||
_alert(" size: %04x\n", istacksize);
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
_alert(" used: %08x\n", up_check_intstack());
|
||||
#endif
|
||||
|
||||
/* Does the current stack pointer lie within the interrupt
|
||||
* stack?
|
||||
*/
|
||||
|
||||
if (sp >= istackbase && sp < istackbase + istacksize)
|
||||
{
|
||||
/* Yes.. dump the interrupt stack */
|
||||
|
||||
avr_stackdump(sp, istackbase + istacksize);
|
||||
}
|
||||
else if (g_current_regs)
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within the interrupt stack\n");
|
||||
avr_stackdump(istackbase, istackbase + istacksize);
|
||||
}
|
||||
|
||||
/* Extract the user stack pointer if we are in an interrupt handler.
|
||||
* If we are not in an interrupt handler. Then sp is the user stack
|
||||
* pointer (and the above range check should have failed).
|
||||
*/
|
||||
|
||||
if (g_current_regs)
|
||||
{
|
||||
sp = g_current_regs[REG_R13];
|
||||
_alert("sp: %04x\n", sp);
|
||||
}
|
||||
|
||||
_alert("User stack:\n");
|
||||
_alert(" base: %04x\n", ustackbase);
|
||||
_alert(" size: %04x\n", ustacksize);
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
_alert(" used: %08x\n", up_check_tcbstack(rtcb));
|
||||
#endif
|
||||
#else
|
||||
_alert("sp: %04x\n", sp);
|
||||
_alert("stack base: %04x\n", ustackbase);
|
||||
_alert("stack size: %04x\n", ustacksize);
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
_alert("stack used: %08x\n", up_check_tcbstack(rtcb));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Dump the user stack if the stack pointer lies within the allocated user
|
||||
* stack memory.
|
||||
*/
|
||||
|
||||
if (sp >= ustackbase && sp < ustackbase + ustacksize)
|
||||
{
|
||||
avr_stackdump(sp, ustackbase + ustacksize);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within allocated stack\n");
|
||||
avr_stackdump(ustackbase, ustackbase + ustacksize);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_STACKDUMP */
|
101
arch/avr/src/avr/avr_registerdump.c
Normal file
101
arch/avr/src/avr/avr_registerdump.c
Normal file
|
@ -0,0 +1,101 @@
|
|||
/****************************************************************************
|
||||
* arch/avr/src/avr/avr_registerdump.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "avr_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
return g_current_regs[REG_R13];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: avr_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
void avr_registerdump(volatile uint8_t *regs)
|
||||
{
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (regs)
|
||||
{
|
||||
_alert("R%02d: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
0,
|
||||
regs[REG_R0], regs[REG_R1],
|
||||
regs[REG_R2], regs[REG_R3],
|
||||
regs[REG_R4], regs[REG_R5],
|
||||
regs[REG_R6], regs[REG_R7]);
|
||||
|
||||
_alert("R%02d: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
8,
|
||||
regs[REG_R8], regs[REG_R9],
|
||||
regs[REG_R10], regs[REG_R11],
|
||||
regs[REG_R12], regs[REG_R13],
|
||||
regs[REG_R14], regs[REG_R15]);
|
||||
|
||||
_alert("R%02d: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
16,
|
||||
regs[REG_R16], regs[REG_R17],
|
||||
regs[REG_R18], regs[REG_R19],
|
||||
regs[REG_R20], regs[REG_R21],
|
||||
regs[REG_R22], regs[REG_R23]);
|
||||
|
||||
_alert("R%02d: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
24,
|
||||
regs[REG_R24], regs[REG_R25],
|
||||
regs[REG_R26], regs[REG_R27],
|
||||
regs[REG_R28], regs[REG_R29],
|
||||
regs[REG_R30], regs[REG_R31]);
|
||||
|
||||
#if !defined(REG_PC2)
|
||||
_alert("PC: %02x%02x SP: %02x%02x SREG: %02x\n",
|
||||
regs[REG_PC0], regs[REG_PC1],
|
||||
regs[REG_SPH], regs[REG_SPL],
|
||||
regs[REG_SREG]);
|
||||
#else
|
||||
_alert("PC: %02x%02x%02x SP: %02x%02x SREG: %02x\n",
|
||||
regs[REG_PC0], regs[REG_PC1],
|
||||
regs[REG_PC2], regs[REG_SPH],
|
||||
regs[REG_SPL], regs[REG_SREG]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
@ -1,191 +0,0 @@
|
|||
/****************************************************************************
|
||||
* arch/avr/src/avr32/avr_dumpstate.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/syslog/syslog.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "avr_internal.h"
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: avr_stackdump
|
||||
****************************************************************************/
|
||||
|
||||
static void avr_stackdump(uint32_t sp, uint32_t stack_top)
|
||||
{
|
||||
uint32_t stack;
|
||||
|
||||
/* Flush any buffered SYSLOG data to avoid overwrite */
|
||||
|
||||
syslog_flush();
|
||||
|
||||
for (stack = sp & ~0x1f; stack < (stack_top & ~0x1f); stack += 32)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)stack;
|
||||
_alert("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: avr_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
static inline void avr_registerdump(void)
|
||||
{
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (g_current_regs)
|
||||
{
|
||||
_alert("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
0,
|
||||
g_current_regs[REG_R0], g_current_regs[REG_R1],
|
||||
g_current_regs[REG_R2], g_current_regs[REG_R3],
|
||||
g_current_regs[REG_R4], g_current_regs[REG_R5],
|
||||
g_current_regs[REG_R6], g_current_regs[REG_R7]);
|
||||
|
||||
_alert("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
8,
|
||||
g_current_regs[REG_R8], g_current_regs[REG_R9],
|
||||
g_current_regs[REG_R10], g_current_regs[REG_R11],
|
||||
g_current_regs[REG_R12], g_current_regs[REG_R13],
|
||||
g_current_regs[REG_R14], g_current_regs[REG_R15]);
|
||||
|
||||
_alert("SR: %08x\n", g_current_regs[REG_SR]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: avr_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
void avr_dumpstate(void)
|
||||
{
|
||||
FAR struct tcb_s *rtcb = running_task();
|
||||
uint32_t sp = up_getsp();
|
||||
uint32_t ustackbase;
|
||||
uint32_t ustacksize;
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uint32_t istackbase;
|
||||
uint32_t istacksize;
|
||||
#endif
|
||||
|
||||
/* Dump the registers (if available) */
|
||||
|
||||
avr_registerdump();
|
||||
|
||||
/* Get the limits on the user stack memory */
|
||||
|
||||
ustackbase = (uint32_t)rtcb->stack_base_ptr;
|
||||
ustacksize = (uint32_t)rtcb->adj_stack_size;
|
||||
|
||||
/* Get the limits on the interrupt stack memory */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
istackbase = (uint32_t)g_intstackalloc;
|
||||
istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3);
|
||||
|
||||
/* Show interrupt stack info */
|
||||
|
||||
_alert("sp: %08x\n", sp);
|
||||
_alert("IRQ stack:\n");
|
||||
_alert(" base: %08x\n", istackbase);
|
||||
_alert(" size: %08x\n", istacksize);
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
_alert(" used: %08x\n", up_check_intstack());
|
||||
#endif
|
||||
|
||||
/* Does the current stack pointer lie within the interrupt
|
||||
* stack?
|
||||
*/
|
||||
|
||||
if (sp >= istackbase && sp < istackbase + istacksize)
|
||||
{
|
||||
/* Yes.. dump the interrupt stack */
|
||||
|
||||
avr_stackdump(sp, istackbase + istacksize);
|
||||
}
|
||||
else if (g_current_regs)
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within the interrupt stack\n");
|
||||
avr_stackdump(istackbase, istackbase + istacksize);
|
||||
}
|
||||
|
||||
/* Extract the user stack pointer if we are in an interrupt handler.
|
||||
* If we are not in an interrupt handler. Then sp is the user stack
|
||||
* pointer (and the above range check should have failed).
|
||||
*/
|
||||
|
||||
if (g_current_regs)
|
||||
{
|
||||
sp = g_current_regs[REG_R13];
|
||||
_alert("sp: %08x\n", sp);
|
||||
}
|
||||
|
||||
_alert("User stack:\n");
|
||||
_alert(" base: %08x\n", ustackbase);
|
||||
_alert(" size: %08x\n", ustacksize);
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
_alert(" used: %08x\n", up_check_tcbstack(rtcb));
|
||||
#endif
|
||||
#else
|
||||
_alert("sp: %08x\n", sp);
|
||||
_alert("stack base: %08x\n", ustackbase);
|
||||
_alert("stack size: %08x\n", ustacksize);
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
_alert("stack used: %08x\n", up_check_tcbstack(rtcb));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Dump the user stack if the stack pointer lies within the allocated user
|
||||
* stack memory.
|
||||
*/
|
||||
|
||||
if (sp >= ustackbase && sp < ustackbase + ustacksize)
|
||||
{
|
||||
avr_stackdump(sp, ustackbase + ustacksize);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within allocated stack\n");
|
||||
avr_stackdump(ustackbase, ustackbase + ustacksize);
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/z80/src/common/z80_stackdump.c
|
||||
* arch/avr/src/avr32/avr_registerdump.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -25,59 +25,53 @@
|
|||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "z80_internal.h"
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
#include "avr_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: z80_stackdump
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
void z80_stackdump(void)
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
FAR struct tcb_s *rtcb = running_task();
|
||||
uintptr_t sp = up_getsp();
|
||||
uintptr_t stack_base = (uintptr_t)rtcb->stack_base_ptr;
|
||||
uintptr_t stack_size = (uintptr_t)rtcb->adj_stack_size;
|
||||
uintptr_t stack;
|
||||
uintptr_t stack_top;
|
||||
return g_current_regs[REG_R13];
|
||||
}
|
||||
|
||||
_alert("stack_base: %06x\n", stack_base);
|
||||
_alert("stack_size: %06x\n", stack_size);
|
||||
_alert("sp: %06x\n", sp);
|
||||
/****************************************************************************
|
||||
* Name: avr_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
if (sp >= stack_base && sp < stack_base + stack_size)
|
||||
void avr_registerdump(volatile uint32_t *regs)
|
||||
{
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (regs)
|
||||
{
|
||||
stack = sp;
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within allocated stack\n");
|
||||
stack = stack_base;
|
||||
}
|
||||
_alert("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
0,
|
||||
regs[REG_R0], regs[REG_R1],
|
||||
regs[REG_R2], regs[REG_R3],
|
||||
regs[REG_R4], regs[REG_R5],
|
||||
regs[REG_R6], regs[REG_R7]);
|
||||
|
||||
stack_top = stack_base + stack_size;
|
||||
_alert("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
8,
|
||||
regs[REG_R8], regs[REG_R9],
|
||||
regs[REG_R10], regs[REG_R11],
|
||||
regs[REG_R12], regs[REG_R13],
|
||||
regs[REG_R14], regs[REG_R15]);
|
||||
|
||||
/* Flush any buffered SYSLOG data to avoid overwrite */
|
||||
|
||||
syslog_flush();
|
||||
|
||||
for (stack = stack & ~(8 * sizeof(chipreg_t) - 1);
|
||||
stack < (stack_top & ~(8 * sizeof(chipreg_t) - 1));
|
||||
stack += 8 * sizeof(chipreg_t))
|
||||
{
|
||||
FAR chipreg_t *ptr = (FAR chipreg_t *)stack;
|
||||
_alert("%06x: %06x %06x %06x %06x %06x %06x %06x %06x\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
_alert("SR: %08x\n", regs[REG_SR]);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_STACKDUMP */
|
|
@ -37,8 +37,8 @@
|
|||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
void up_assert(const char *filename, int lineno)
|
||||
void up_assert(void)
|
||||
{
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
avr_dumpstate();
|
||||
avr_registerdump(g_current_regs);
|
||||
}
|
||||
|
|
44
arch/avr/src/common/avr_getintstack.c
Normal file
44
arch/avr/src/common/avr_getintstack.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/****************************************************************************
|
||||
* arch/avr/src/common/avr_getintstack.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "avr_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_intstackbase
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uintptr_t up_get_intstackbase(void)
|
||||
{
|
||||
return (uintptr_t)g_intstackalloc;
|
||||
}
|
||||
#endif
|
|
@ -119,7 +119,11 @@ void weak_function avr_dma_initialize(void);
|
|||
void avr_sigdeliver(void);
|
||||
void avr_lowputc(char ch);
|
||||
void avr_lowputs(const char *str);
|
||||
void avr_dumpstate(void);
|
||||
#ifdef CONFIG_ARCH_FAMILY_AVR32
|
||||
void avr_registerdump(volatile uint32_t *regs);
|
||||
#else
|
||||
void avr_registerdump(volatile uint8_t *regs);
|
||||
#endif
|
||||
|
||||
/* Defined in common/avr_allocateheap.c or chip/xxx_allocateheap.c */
|
||||
|
||||
|
|
|
@ -35,80 +35,19 @@
|
|||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static uint32_t s_last_regs[XCPTCONTEXT_REGS];
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_stackdump
|
||||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static void up_stackdump(uint32_t sp, uint32_t stack_base)
|
||||
{
|
||||
uint32_t stack;
|
||||
|
||||
for (stack = sp; stack < stack_base; stack += 8 * sizeof(uint32_t))
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)stack;
|
||||
_alert("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define up_stackdump(sp, stack_base)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_taskdump
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
static void up_taskdump(struct tcb_s *tcb, void *arg)
|
||||
{
|
||||
/* Dump interesting properties of this task */
|
||||
|
||||
#if CONFIG_TASK_NAME_SIZE > 0
|
||||
_alert("%s: PID=%d Stack Used=%lu of %lu\n",
|
||||
tcb->name, tcb->pid, up_check_tcbstack(tcb),
|
||||
tcb->adj_stack_size);
|
||||
#else
|
||||
_alert("PID: %d Stack Used=%lu of %lu\n",
|
||||
tcb->pid, up_check_tcbstack(tcb),
|
||||
tcb->adj_stack_size);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_showtasks
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
static inline void up_showtasks(void)
|
||||
{
|
||||
/* Dump interesting properties of each task in the crash environment */
|
||||
|
||||
sched_foreach(up_taskdump, NULL);
|
||||
}
|
||||
#else
|
||||
# define up_showtasks()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static inline void up_registerdump(void)
|
||||
void up_assert(void)
|
||||
{
|
||||
volatile uint32_t *regs = CURRENT_REGS;
|
||||
int rx;
|
||||
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
|
@ -120,130 +59,5 @@ static inline void up_registerdump(void)
|
|||
regs = s_last_regs;
|
||||
}
|
||||
|
||||
/* Dump the interrupt registers */
|
||||
|
||||
for (rx = 0; rx < XCPTCONTEXT_REGS; rx += 8)
|
||||
{
|
||||
_alert("R%03d: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
rx, regs[rx], regs[rx + 1], regs[rx + 2], regs[rx + 3],
|
||||
regs[rx + 4], regs[rx + 5], regs[rx + 6], regs[rx + 7]);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define up_registerdump()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static void up_dumpstate(void)
|
||||
{
|
||||
struct tcb_s *rtcb = running_task();
|
||||
uint32_t sp = up_getsp();
|
||||
uint32_t ustackbase;
|
||||
uint32_t ustacksize;
|
||||
uint32_t istackbase;
|
||||
uint32_t istacksize;
|
||||
|
||||
/* Dump the registers (if available) */
|
||||
|
||||
up_registerdump();
|
||||
|
||||
/* Get the limits on the user stack memory */
|
||||
|
||||
ustackbase = (uint32_t)rtcb->stack_base_ptr;
|
||||
ustacksize = rtcb->adj_stack_size;
|
||||
|
||||
/* Get the limits on the interrupt stack memory */
|
||||
|
||||
istackbase = (uint32_t)g_intstackbase;
|
||||
istacksize = g_intstackbase - g_intstackalloc;
|
||||
|
||||
/* Show interrupt stack info */
|
||||
|
||||
_alert("sp: %08x\n", sp);
|
||||
_alert("IRQ stack:\n");
|
||||
_alert(" base: %08x\n", istackbase);
|
||||
_alert(" size: %08x\n", istacksize);
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
_alert(" used: %08x\n", up_check_intstack());
|
||||
#endif
|
||||
|
||||
/* Does the current stack pointer lie within the interrupt
|
||||
* stack?
|
||||
*/
|
||||
|
||||
if (sp <= istackbase && sp > istackbase - istacksize)
|
||||
{
|
||||
/* Yes.. dump the interrupt stack */
|
||||
|
||||
up_stackdump(sp, istackbase);
|
||||
}
|
||||
else if (CURRENT_REGS)
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within the interrupt stack\n");
|
||||
up_stackdump(istackbase - istacksize, istackbase);
|
||||
}
|
||||
|
||||
/* Extract the user stack pointer if we are in an interrupt handler.
|
||||
* If we are not in an interrupt handler. Then sp is the user stack
|
||||
* pointer (and the above range check should have failed).
|
||||
*/
|
||||
|
||||
if (CURRENT_REGS)
|
||||
{
|
||||
sp = (uint32_t)CURRENT_REGS;
|
||||
}
|
||||
|
||||
/* Show user stack info */
|
||||
|
||||
_alert("sp: %08x\n", sp);
|
||||
_alert("User stack:\n");
|
||||
_alert(" base: %08x\n", ustackbase);
|
||||
_alert(" size: %08x\n", ustacksize);
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
_alert(" used: %08x\n", up_check_tcbstack(rtcb));
|
||||
#endif
|
||||
|
||||
/* Dump the user stack if the stack pointer lies within the allocated user
|
||||
* stack memory.
|
||||
*/
|
||||
|
||||
if (sp > ustackbase || sp <= ustackbase - ustacksize)
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within the allocated stack\n");
|
||||
up_stackdump(ustackbase - ustacksize, ustackbase);
|
||||
}
|
||||
else
|
||||
{
|
||||
up_stackdump(sp, ustackbase);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Show the CPU number */
|
||||
|
||||
_alert("CPU%d:\n", up_cpu_index());
|
||||
#endif
|
||||
|
||||
/* Dump the state of all tasks (if available) */
|
||||
|
||||
up_showtasks();
|
||||
}
|
||||
#else
|
||||
# define up_dumpstate()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
void up_assert(const uint8_t *filename, int lineno)
|
||||
{
|
||||
up_dumpstate();
|
||||
ceva_registerdump(regs);
|
||||
}
|
||||
|
|
44
arch/ceva/src/common/ceva_getintstack.c
Normal file
44
arch/ceva/src/common/ceva_getintstack.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/****************************************************************************
|
||||
* arch/ceva/src/common/ceva_getintstack.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ceva_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_intstackbase
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uintptr_t up_get_intstackbase(void)
|
||||
{
|
||||
return (uintptr_t)g_intstackalloc;
|
||||
}
|
||||
#endif
|
|
@ -305,6 +305,8 @@ size_t ceva_stack_check(uintptr_t alloc, size_t size);
|
|||
void ceva_stack_color(void *stackbase, size_t nbytes);
|
||||
#endif
|
||||
|
||||
void ceva_registerdump(volatile uint32_t *regs);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
63
arch/ceva/src/common/ceva_registerdump.c
Normal file
63
arch/ceva/src/common/ceva_registerdump.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
/****************************************************************************
|
||||
* arch/ceva/src/common/ceva_registerdump.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "ceva_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
return CURRENT_REGS[REG_SP];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: ceva_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
void ceva_registerdump(volatile uint32_t *regs)
|
||||
{
|
||||
int rx;
|
||||
|
||||
/* Dump the interrupt registers */
|
||||
|
||||
for (rx = 0; rx < XCPTCONTEXT_REGS; rx += 8)
|
||||
{
|
||||
_alert("R%03d: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
rx, regs[rx], regs[rx + 1], regs[rx + 2], regs[rx + 3],
|
||||
regs[rx + 4], regs[rx + 5], regs[rx + 6], regs[rx + 7]);
|
||||
}
|
||||
}
|
44
arch/hc/src/common/hc_getintstack.c
Normal file
44
arch/hc/src/common/hc_getintstack.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/****************************************************************************
|
||||
* arch/hc/src/common/hc_getintstack.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "hc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_intstackbase
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uintptr_t up_get_intstackbase(void)
|
||||
{
|
||||
return (uintptr_t)g_intstackalloc;
|
||||
}
|
||||
#endif
|
|
@ -195,6 +195,8 @@ void hc_usbuninitialize(void);
|
|||
# define hc_usbuninitialize()
|
||||
#endif
|
||||
|
||||
void hc_registerdump(volatile uint8_t *regs);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __ARCH_HC_SRC_COMMON_UP_INTERNAL_H */
|
||||
|
|
|
@ -23,12 +23,12 @@ HEAD_ASRC = m9s12_vectors.S
|
|||
CMN_CSRCS = hc_allocateheap.c hc_copystate.c hc_createstack.c
|
||||
CMN_CSRCS += hc_doirq.c hc_exit.c hc_idle.c hc_initialize.c
|
||||
CMN_CSRCS += hc_mdelay.c hc_modifyreg16.c hc_modifyreg32.c hc_modifyreg8.c
|
||||
CMN_CSRCS += hc_nputs.c hc_releasestack.c
|
||||
CMN_CSRCS += hc_nputs.c hc_releasestack.c hc_getintstack.c
|
||||
CMN_CSRCS += hc_stackframe.c hc_udelay.c hc_switchcontext.c hc_usestack.c
|
||||
|
||||
CHIP_ASRCS = m9s12_start.S m9s12_lowputc.S m9s12_saveusercontext.S
|
||||
CHIP_CSRCS = m9s12_assert.c m9s12_gpio.c m9s12_gpioirq.c m9s12_initialstate.c
|
||||
CHIP_CSRCS += m9s12_irq.c m9s12_serial.c
|
||||
CHIP_CSRCS += m9s12_irq.c m9s12_serial.c m9s12_registerdump.c
|
||||
|
||||
ifneq ($(CONFIG_SCHED_TICKLESS),y)
|
||||
CHIP_CSRCS += m9s12_timerisr.c
|
||||
|
|
|
@ -40,42 +40,22 @@
|
|||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static uint8_t s_last_regs[XCPTCONTEXT_REGS];
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: hc_stackdump
|
||||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static void hc_stackdump(uint16_t sp, uint16_t stack_top)
|
||||
{
|
||||
uint16_t stack;
|
||||
|
||||
for (stack = sp & ~0x7; stack < (stack_top & ~0x7); stack += 8)
|
||||
{
|
||||
uint8_t *ptr = (uint8_t *)stack;
|
||||
_alert("%04x: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: hc_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static inline void hc_registerdump(void)
|
||||
void up_assert(void)
|
||||
{
|
||||
volatile uint8_t *regs = g_current_regs;
|
||||
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (regs == NULL)
|
||||
|
@ -86,132 +66,5 @@ static inline void hc_registerdump(void)
|
|||
regs = s_last_regs;
|
||||
}
|
||||
|
||||
_alert("A:%02x B:%02x X:%02x%02x Y:%02x%02x PC:%02x%02x CCR:%02x\n",
|
||||
regs[REG_A], regs[REG_B], regs[REG_XH], regs[REG_XL],
|
||||
regs[REG_YH], regs[REG_YL], regs[REG_PCH], regs[REG_PCL],
|
||||
regs[REG_CCR]);
|
||||
_alert("SP:%02x%02x FRAME:%02x%02x TMP:%02x%02x Z:%02x%02x XY:%02x\n",
|
||||
regs[REG_SPH], regs[REG_SPL], regs[REG_FRAMEH], regs[REG_FRAMEL],
|
||||
regs[REG_TMPL], regs[REG_TMPH], regs[REG_ZL], regs[REG_ZH],
|
||||
regs[REG_XY], regs[REG_XY + 1]);
|
||||
|
||||
#if CONFIG_HCS12_MSOFTREGS > 2
|
||||
# error "Need to save more registers"
|
||||
#elif CONFIG_HCS12_MSOFTREGS == 2
|
||||
_alert("SOFTREGS: %02x%02x :%02x%02x\n",
|
||||
regs[REG_SOFTREG1], regs[REG_SOFTREG1 + 1],
|
||||
regs[REG_SOFTREG2], regs[REG_SOFTREG2 + 1]);
|
||||
#elif CONFIG_HCS12_MSOFTREGS == 1
|
||||
_alert("SOFTREGS: %02x%02x\n",
|
||||
regs[REG_SOFTREG1], regs[REG_SOFTREG1 + 1]);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_HCS12_NONBANKED
|
||||
_alert("PPAGE: %02x\n", regs[REG_PPAGE]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static void up_dumpstate(void)
|
||||
{
|
||||
FAR struct tcb_s *rtcb = running_task();
|
||||
uint16_t sp = up_getsp();
|
||||
uint16_t ustackbase;
|
||||
uint16_t ustacksize;
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uint16_t istackbase;
|
||||
uint16_t istacksize;
|
||||
#endif
|
||||
|
||||
/* Dump the registers (if available) */
|
||||
|
||||
hc_registerdump();
|
||||
|
||||
/* Get the limits on the user stack memory */
|
||||
|
||||
ustackbase = (uint16_t)rtcb->stack_base_ptr;
|
||||
ustacksize = (uint16_t)rtcb->adj_stack_size;
|
||||
|
||||
/* Get the limits on the interrupt stack memory */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
istackbase = (uint16_t)g_intstackalloc;
|
||||
istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3);
|
||||
|
||||
/* Show interrupt stack info */
|
||||
|
||||
_alert("sp: %04x\n", sp);
|
||||
_alert("IRQ stack:\n");
|
||||
_alert(" base: %04x\n", istackbase);
|
||||
_alert(" size: %04x\n", istacksize);
|
||||
|
||||
/* Does the current stack pointer lie within the interrupt
|
||||
* stack?
|
||||
*/
|
||||
|
||||
if (sp >= istackbase && sp < istackbase + istacksize)
|
||||
{
|
||||
/* Yes.. dump the interrupt stack */
|
||||
|
||||
hc_stackdump(sp, istackbase + istacksize);
|
||||
|
||||
/* Extract the user stack pointer which should lie
|
||||
* at the base of the interrupt stack.
|
||||
*/
|
||||
|
||||
sp = g_intstacktop;
|
||||
_alert("sp: %04x\n", sp);
|
||||
}
|
||||
else if (g_current_regs)
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within the interrupt stack\n");
|
||||
hc_stackdump(istackbase, istackbase + istacksize);
|
||||
}
|
||||
|
||||
/* Show user stack info */
|
||||
|
||||
_alert("User stack:\n");
|
||||
_alert(" base: %04x\n", ustackbase);
|
||||
_alert(" size: %04x\n", ustacksize);
|
||||
#else
|
||||
_alert("sp: %04x\n", sp);
|
||||
_alert("stack base: %04x\n", ustackbase);
|
||||
_alert("stack size: %04x\n", ustacksize);
|
||||
#endif
|
||||
|
||||
/* Dump the user stack if the stack pointer lies within the allocated user
|
||||
* stack memory.
|
||||
*/
|
||||
|
||||
if (sp >= ustackbase && sp < ustackbase + ustacksize)
|
||||
{
|
||||
hc_stackdump(sp, ustackbase + ustacksize);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within allocated stack\n");
|
||||
hc_stackdump(ustackbase, ustackbase + ustacksize);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define up_dumpstate()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
void up_assert(const char *filename, int lineno)
|
||||
{
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
up_dumpstate();
|
||||
hc_registerdump(regs);
|
||||
}
|
||||
|
|
78
arch/hc/src/m9s12/m9s12_registerdump.c
Normal file
78
arch/hc/src/m9s12/m9s12_registerdump.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
/****************************************************************************
|
||||
* arch/hc/src/m9s12/m9s12_registerdump.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "hc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
uint8_t *ptr = (uint8_t *)g_current_regs;
|
||||
return (uintptr_t)(ptr[REG_SPH] << 8 | ptr[REG_SPL]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: hc_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
void hc_registerdump(volatile uint8_t *regs)
|
||||
{
|
||||
_alert("A:%02x B:%02x X:%02x%02x Y:%02x%02x PC:%02x%02x CCR:%02x\n",
|
||||
regs[REG_A], regs[REG_B], regs[REG_XH], regs[REG_XL],
|
||||
regs[REG_YH], regs[REG_YL], regs[REG_PCH], regs[REG_PCL],
|
||||
regs[REG_CCR]);
|
||||
_alert("SP:%02x%02x FRAME:%02x%02x TMP:%02x%02x Z:%02x%02x XY:%02x\n",
|
||||
regs[REG_SPH], regs[REG_SPL], regs[REG_FRAMEH], regs[REG_FRAMEL],
|
||||
regs[REG_TMPL], regs[REG_TMPH], regs[REG_ZL], regs[REG_ZH],
|
||||
regs[REG_XY], regs[REG_XY + 1]);
|
||||
|
||||
#if CONFIG_HCS12_MSOFTREGS > 2
|
||||
# error "Need to save more registers"
|
||||
#elif CONFIG_HCS12_MSOFTREGS == 2
|
||||
_alert("SOFTREGS: %02x%02x :%02x%02x\n",
|
||||
regs[REG_SOFTREG1], regs[REG_SOFTREG1 + 1],
|
||||
regs[REG_SOFTREG2], regs[REG_SOFTREG2 + 1]);
|
||||
#elif CONFIG_HCS12_MSOFTREGS == 1
|
||||
_alert("SOFTREGS: %02x%02x\n",
|
||||
regs[REG_SOFTREG1], regs[REG_SOFTREG1 + 1]);
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_HCS12_NONBANKED
|
||||
_alert("PPAGE: %02x\n", regs[REG_PPAGE]);
|
||||
#endif
|
||||
}
|
44
arch/mips/src/common/mips_getintstack.c
Normal file
44
arch/mips/src/common/mips_getintstack.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/****************************************************************************
|
||||
* arch/mips/src/common/mips_getintstack.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mips_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_intstackbase
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uintptr_t up_get_intstackbase(void)
|
||||
{
|
||||
return (uintptr_t)g_intstackalloc;
|
||||
}
|
||||
#endif
|
|
@ -178,11 +178,7 @@ void mips_lowputs(const char *str);
|
|||
|
||||
/* Debug */
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
void mips_dumpstate(void);
|
||||
#else
|
||||
# define mips_dumpstate()
|
||||
#endif
|
||||
void mips_registerdump(volatile uint32_t *regs);
|
||||
|
||||
/* Common MIPS32 functions defined in arch/mips/src/MIPS32 */
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
void up_assert(const char *filename, int lineno)
|
||||
void up_assert(void)
|
||||
{
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
mips_dumpstate();
|
||||
mips_registerdump(CURRENT_REGS);
|
||||
}
|
||||
|
|
|
@ -1,211 +0,0 @@
|
|||
/****************************************************************************
|
||||
* arch/mips/src/mips32/mips_dumpstate.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/syslog/syslog.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "mips_internal.h"
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mips_stackdump
|
||||
****************************************************************************/
|
||||
|
||||
static void mips_stackdump(uint32_t sp, uint32_t stack_top)
|
||||
{
|
||||
uint32_t stack;
|
||||
|
||||
/* Flush any buffered SYSLOG data to avoid overwrite */
|
||||
|
||||
syslog_flush();
|
||||
|
||||
for (stack = sp & ~0x1f; stack < (stack_top & ~0x1f); stack += 32)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)stack;
|
||||
_alert("%08" PRIx32 ": %08" PRIx32 " %08" PRIx32
|
||||
" %08" PRIx32 " %08" PRIx32 " %08" PRIx32
|
||||
" %08" PRIx32 " %08" PRIx32 " %08" PRIx32 "\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mips_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
static inline void mips_registerdump(void)
|
||||
{
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (CURRENT_REGS)
|
||||
{
|
||||
_alert("MFLO:%08" PRIx32 " MFHI:%08" PRIx32
|
||||
" EPC:%08" PRIx32 " STATUS:%08" PRIx32 "\n",
|
||||
CURRENT_REGS[REG_MFLO], CURRENT_REGS[REG_MFHI],
|
||||
CURRENT_REGS[REG_EPC], CURRENT_REGS[REG_STATUS]);
|
||||
_alert("AT:%08" PRIx32 " V0:%08" PRIx32 " V1:%08" PRIx32
|
||||
" A0:%08" PRIx32 " A1:%08" PRIx32 " A2:%08" PRIx32
|
||||
" A3:%08" PRIx32 "\n",
|
||||
CURRENT_REGS[REG_AT], CURRENT_REGS[REG_V0],
|
||||
CURRENT_REGS[REG_V1], CURRENT_REGS[REG_A0],
|
||||
CURRENT_REGS[REG_A1], CURRENT_REGS[REG_A2],
|
||||
CURRENT_REGS[REG_A3]);
|
||||
_alert("T0:%08" PRIx32 " T1:%08" PRIx32 " T2:%08" PRIx32
|
||||
" T3:%08" PRIx32 " T4:%08" PRIx32 " T5:%08" PRIx32
|
||||
" T6:%08" PRIx32 " T7:%08" PRIx32 "\n",
|
||||
CURRENT_REGS[REG_T0], CURRENT_REGS[REG_T1],
|
||||
CURRENT_REGS[REG_T2], CURRENT_REGS[REG_T3],
|
||||
CURRENT_REGS[REG_T4], CURRENT_REGS[REG_T5],
|
||||
CURRENT_REGS[REG_T6], CURRENT_REGS[REG_T7]);
|
||||
_alert("S0:%08" PRIx32 " S1:%08" PRIx32 " S2:%08" PRIx32
|
||||
" S3:%08" PRIx32 " S4:%08" PRIx32 " S5:%08" PRIx32
|
||||
" S6:%08" PRIx32 " S7:%08" PRIx32 "\n",
|
||||
CURRENT_REGS[REG_S0], CURRENT_REGS[REG_S1],
|
||||
CURRENT_REGS[REG_S2], CURRENT_REGS[REG_S3],
|
||||
CURRENT_REGS[REG_S4], CURRENT_REGS[REG_S5],
|
||||
CURRENT_REGS[REG_S6], CURRENT_REGS[REG_S7]);
|
||||
#ifdef MIPS32_SAVE_GP
|
||||
_alert("T8:%08" PRIx32 " T9:%08" PRIx32 " GP:%08" PRIx32
|
||||
" SP:%08" PRIx32 " FP:%08" PRIx32 " RA:%08" PRIx32 "\n",
|
||||
CURRENT_REGS[REG_T8], CURRENT_REGS[REG_T9],
|
||||
CURRENT_REGS[REG_GP], CURRENT_REGS[REG_SP],
|
||||
CURRENT_REGS[REG_FP], CURRENT_REGS[REG_RA]);
|
||||
#else
|
||||
_alert("T8:%08" PRIx32 " T9:%08" PRIx32 " SP:%08" PRIx32
|
||||
" FP:%08" PRIx32 " RA:%08" PRIx32 "\n",
|
||||
CURRENT_REGS[REG_T8], CURRENT_REGS[REG_T9],
|
||||
CURRENT_REGS[REG_SP], CURRENT_REGS[REG_FP],
|
||||
CURRENT_REGS[REG_RA]);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mips_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
void mips_dumpstate(void)
|
||||
{
|
||||
struct tcb_s *rtcb = running_task();
|
||||
uint32_t sp = up_getsp();
|
||||
uint32_t ustackbase;
|
||||
uint32_t ustacksize;
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uint32_t istackbase;
|
||||
uint32_t istacksize;
|
||||
#endif
|
||||
|
||||
/* Dump the registers (if available) */
|
||||
|
||||
mips_registerdump();
|
||||
|
||||
/* Get the limits on the user stack memory */
|
||||
|
||||
ustackbase = (uint32_t)rtcb->stack_base_ptr;
|
||||
ustacksize = (uint32_t)rtcb->adj_stack_size;
|
||||
|
||||
/* Get the limits on the interrupt stack memory */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
istackbase = (uint32_t)g_intstackalloc;
|
||||
istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3);
|
||||
|
||||
/* Show interrupt stack info */
|
||||
|
||||
_alert("sp: %08" PRIx32 "\n", sp);
|
||||
_alert("IRQ stack:\n");
|
||||
_alert(" base: %08" PRIx32 "\n", istackbase);
|
||||
_alert(" size: %08" PRIx32 "\n", istacksize);
|
||||
|
||||
/* Does the current stack pointer lie within the interrupt
|
||||
* stack?
|
||||
*/
|
||||
|
||||
if (sp >= istackbase && sp < istackbase + istacksize)
|
||||
{
|
||||
/* Yes.. dump the interrupt stack */
|
||||
|
||||
mips_stackdump(sp, istackbase + istacksize);
|
||||
|
||||
/* Extract the user stack pointer which should lie
|
||||
* at the base of the interrupt stack.
|
||||
*/
|
||||
|
||||
sp = g_intstacktop;
|
||||
_alert("sp: %08" PRIx32 "\n", sp);
|
||||
}
|
||||
else if (CURRENT_REGS)
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within the interrupt stack\n");
|
||||
mips_stackdump(istackbase, istackbase + istacksize);
|
||||
}
|
||||
|
||||
/* Show user stack info */
|
||||
|
||||
_alert("User stack:\n");
|
||||
_alert(" base: %08" PRIx32 "\n", ustackbase);
|
||||
_alert(" size: %08" PRIx32 "\n", ustacksize);
|
||||
#else
|
||||
_alert("sp: %08" PRIx32 "\n", sp);
|
||||
_alert("stack base: %08" PRIx32 "\n", ustackbase);
|
||||
_alert("stack size: %08" PRIx32 "\n", ustacksize);
|
||||
#endif
|
||||
|
||||
/* Dump the user stack if the stack pointer lies within the allocated user
|
||||
* stack memory.
|
||||
*/
|
||||
|
||||
if (sp >= ustackbase && sp < ustackbase + ustacksize)
|
||||
{
|
||||
mips_stackdump(sp, ustackbase + ustacksize);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within allocated stack\n");
|
||||
mips_stackdump(ustackbase, ustackbase + ustacksize);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_STACKDUMP */
|
99
arch/mips/src/mips32/mips_registerdump.c
Normal file
99
arch/mips/src/mips32/mips_registerdump.c
Normal file
|
@ -0,0 +1,99 @@
|
|||
/****************************************************************************
|
||||
* arch/mips/src/mips32/mips_registerdump.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "mips_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
return CURRENT_REGS[REG_SP];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mips_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
void mips_registerdump(volatile uint32_t *regs)
|
||||
{
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (regs)
|
||||
{
|
||||
_alert("MFLO:%08" PRIx32 " MFHI:%08" PRIx32
|
||||
" EPC:%08" PRIx32 " STATUS:%08" PRIx32 "\n",
|
||||
regs[REG_MFLO], regs[REG_MFHI],
|
||||
regs[REG_EPC], regs[REG_STATUS]);
|
||||
_alert("AT:%08" PRIx32 " V0:%08" PRIx32 " V1:%08" PRIx32
|
||||
" A0:%08" PRIx32 " A1:%08" PRIx32 " A2:%08" PRIx32
|
||||
" A3:%08" PRIx32 "\n",
|
||||
regs[REG_AT], regs[REG_V0],
|
||||
regs[REG_V1], regs[REG_A0],
|
||||
regs[REG_A1], regs[REG_A2],
|
||||
regs[REG_A3]);
|
||||
_alert("T0:%08" PRIx32 " T1:%08" PRIx32 " T2:%08" PRIx32
|
||||
" T3:%08" PRIx32 " T4:%08" PRIx32 " T5:%08" PRIx32
|
||||
" T6:%08" PRIx32 " T7:%08" PRIx32 "\n",
|
||||
regs[REG_T0], regs[REG_T1],
|
||||
regs[REG_T2], regs[REG_T3],
|
||||
regs[REG_T4], regs[REG_T5],
|
||||
regs[REG_T6], regs[REG_T7]);
|
||||
_alert("S0:%08" PRIx32 " S1:%08" PRIx32 " S2:%08" PRIx32
|
||||
" S3:%08" PRIx32 " S4:%08" PRIx32 " S5:%08" PRIx32
|
||||
" S6:%08" PRIx32 " S7:%08" PRIx32 "\n",
|
||||
regs[REG_S0], regs[REG_S1],
|
||||
regs[REG_S2], regs[REG_S3],
|
||||
regs[REG_S4], regs[REG_S5],
|
||||
regs[REG_S6], regs[REG_S7]);
|
||||
#ifdef MIPS32_SAVE_GP
|
||||
_alert("T8:%08" PRIx32 " T9:%08" PRIx32 " GP:%08" PRIx32
|
||||
" SP:%08" PRIx32 " FP:%08" PRIx32 " RA:%08" PRIx32 "\n",
|
||||
regs[REG_T8], regs[REG_T9],
|
||||
regs[REG_GP], regs[REG_SP],
|
||||
regs[REG_FP], regs[REG_RA]);
|
||||
#else
|
||||
_alert("T8:%08" PRIx32 " T9:%08" PRIx32 " SP:%08" PRIx32
|
||||
" FP:%08" PRIx32 " RA:%08" PRIx32 "\n",
|
||||
regs[REG_T8], regs[REG_T9],
|
||||
regs[REG_SP], regs[REG_FP],
|
||||
regs[REG_RA]);
|
||||
#endif
|
||||
}
|
||||
}
|
|
@ -43,38 +43,6 @@
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mips_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_SYSCALL_INFO
|
||||
static void mips_registerdump(const uint32_t *regs)
|
||||
{
|
||||
svcinfo("MFLO:%08x MFHI:%08x EPC:%08x STATUS:%08x\n",
|
||||
regs[REG_MFLO], regs[REG_MFHI], regs[REG_EPC], regs[REG_STATUS]);
|
||||
svcinfo("AT:%08x V0:%08x V1:%08x A0:%08x A1:%08x A2:%08x A3:%08x\n",
|
||||
regs[REG_AT], regs[REG_V0], regs[REG_V1], regs[REG_A0],
|
||||
regs[REG_A1], regs[REG_A2], regs[REG_A3]);
|
||||
svcinfo("T0:%08x T1:%08x T2:%08x T3:%08x "
|
||||
"T4:%08x T5:%08x T6:%08x T7:%08x\n",
|
||||
regs[REG_T0], regs[REG_T1], regs[REG_T2], regs[REG_T3],
|
||||
regs[REG_T4], regs[REG_T5], regs[REG_T6], regs[REG_T7]);
|
||||
svcinfo("S0:%08x S1:%08x S2:%08x S3:%08x "
|
||||
"S4:%08x S5:%08x S6:%08x S7:%08x\n",
|
||||
regs[REG_S0], regs[REG_S1], regs[REG_S2], regs[REG_S3],
|
||||
regs[REG_S4], regs[REG_S5], regs[REG_S6], regs[REG_S7]);
|
||||
#ifdef MIPS32_SAVE_GP
|
||||
svcinfo("T8:%08x T9:%08x GP:%08x SP:%08x FP:%08x RA:%08x\n",
|
||||
regs[REG_T8], regs[REG_T9], regs[REG_GP], regs[REG_SP],
|
||||
regs[REG_FP], regs[REG_RA]);
|
||||
#else
|
||||
svcinfo("T8:%08x T9:%08x SP:%08x FP:%08x RA:%08x\n",
|
||||
regs[REG_T8], regs[REG_T9], regs[REG_SP], regs[REG_FP],
|
||||
regs[REG_RA]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dispatch_syscall
|
||||
*
|
||||
|
@ -288,7 +256,7 @@ int mips_swint0(int irq, void *context, void *arg)
|
|||
if (regs != CURRENT_REGS)
|
||||
{
|
||||
svcinfo("SWInt Return: Context switch!\n");
|
||||
mips_registerdump((const uint32_t *)CURRENT_REGS);
|
||||
mips_registerdump(CURRENT_REGS);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -33,6 +33,7 @@ CMN_CSRCS += mips_nputs.c mips_releasestack.c
|
|||
CMN_CSRCS += mips_schedulesigaction.c mips_sigdeliver.c
|
||||
CMN_CSRCS += mips_stackframe.c mips_swint0.c mips_udelay.c mips_switchcontext.c
|
||||
CMN_CSRCS += mips_usestack.c mips_vfork.c
|
||||
CMN_CSRCS += mips_registerdump.c mips_getintstack.c
|
||||
|
||||
# Configuration dependent common files
|
||||
|
||||
|
@ -50,10 +51,6 @@ CMN_CSRCS += mips_etherstub.c
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_STACKDUMP),y)
|
||||
CMN_CSRCS += mips_dumpstate.c
|
||||
endif
|
||||
|
||||
# Required PIC32MX files
|
||||
|
||||
CHIP_CSRCS = pic32mx_irq.c pic32mx_decodeirq.c pic32mx_exception.c
|
||||
|
|
|
@ -33,6 +33,7 @@ CMN_CSRCS += mips_nputs.c mips_releasestack.c
|
|||
CMN_CSRCS += mips_schedulesigaction.c mips_sigdeliver.c
|
||||
CMN_CSRCS += mips_stackframe.c mips_swint0.c mips_udelay.c mips_switchcontext.c
|
||||
CMN_CSRCS += mips_usestack.c mips_vfork.c
|
||||
CMN_CSRCS += mips_registerdump.c mips_getintstack.c
|
||||
|
||||
# Configuration dependent common files
|
||||
|
||||
|
@ -50,10 +51,6 @@ CMN_CSRCS += mips_etherstub.c
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_STACKDUMP),y)
|
||||
CMN_CSRCS += mips_dumpstate.c
|
||||
endif
|
||||
|
||||
# Required PIC32MZ files
|
||||
|
||||
CHIP_CSRCS = pic32mz_lowinit.c pic32mz_exception.c pic32mz_decodeirq.c
|
||||
|
|
|
@ -29,7 +29,7 @@ CHIP_ASRCS = lm32_syscall.S
|
|||
|
||||
CHIP_CSRCS = lm32_allocateheap.c lm32_assert.c
|
||||
CHIP_CSRCS += lm32_copystate.c lm32_createstack.c lm32_decodeirq.c
|
||||
CHIP_CSRCS += lm32_doirq.c lm32_dumpstate.c lm32_exit.c lm32_idle.c
|
||||
CHIP_CSRCS += lm32_doirq.c lm32_registerdump.c lm32_exit.c lm32_idle.c
|
||||
CHIP_CSRCS += lm32_initialstate.c lm32_irq.c
|
||||
CHIP_CSRCS += lm32_releasestack.c lm32_stackframe.c lm32_swint.c
|
||||
CHIP_CSRCS += lm32_switchcontext.c
|
||||
|
|
|
@ -128,7 +128,7 @@ void lm32_flush_icache(void);
|
|||
|
||||
/* Debug ********************************************************************/
|
||||
|
||||
void lm32_dumpstate(void);
|
||||
void lm32_registerdump(volatile uint32_t *regs);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ARCH_MISOC_SRC_LM32_LM32_H */
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
void up_assert(const char *filename, int lineno)
|
||||
void up_assert(void)
|
||||
{
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
lm32_dumpstate();
|
||||
lm32_registerdump(g_current_regs);
|
||||
}
|
||||
|
|
|
@ -1,197 +0,0 @@
|
|||
/****************************************************************************
|
||||
* arch/misoc/src/lm32/lm32_dumpstate.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/syslog/syslog.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "lm32.h"
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lm32_stackdump
|
||||
****************************************************************************/
|
||||
|
||||
static void lm32_stackdump(uint32_t sp, uint32_t stack_top)
|
||||
{
|
||||
uint32_t stack;
|
||||
|
||||
/* Flush any buffered SYSLOG data to avoid overwrite */
|
||||
|
||||
syslog_flush();
|
||||
|
||||
for (stack = sp & ~0x1f; stack < (stack_top & ~0x1f); stack += 32)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)stack;
|
||||
_alert("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lm32_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
static inline void lm32_registerdump(void)
|
||||
{
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (g_current_regs)
|
||||
{
|
||||
_alert("EPC:%08x\n",
|
||||
g_current_regs[REG_EPC]);
|
||||
_alert(" X0:%08x A0:%08x A1:%08x A2:%08x "
|
||||
" A3:%08x A4:%08x A5:%08x A6:%08x\n",
|
||||
g_current_regs[REG_X0_NDX], g_current_regs[REG_X1_NDX],
|
||||
g_current_regs[REG_X2_NDX], g_current_regs[REG_X3_NDX],
|
||||
g_current_regs[REG_X4_NDX], g_current_regs[REG_X5_NDX],
|
||||
g_current_regs[REG_X6_NDX], g_current_regs[REG_X7_NDX]);
|
||||
_alert(" A7:%08x X9:%08x X10:%08x X11:%08x "
|
||||
"X12:%08x X13:%08x X14:%08x X15:%08x\n",
|
||||
g_current_regs[REG_X8_NDX], g_current_regs[REG_X9_NDX],
|
||||
g_current_regs[REG_X10_NDX], g_current_regs[REG_X11_NDX],
|
||||
g_current_regs[REG_X12_NDX], g_current_regs[REG_X13_NDX],
|
||||
g_current_regs[REG_X14_NDX], g_current_regs[REG_X15_NDX]);
|
||||
_alert("X16:%08x X17:%08x X18:%08x X19:%08x "
|
||||
"X20:%08x X21:%08x X22:%08x X23:%08x\n",
|
||||
g_current_regs[REG_X16_NDX], g_current_regs[REG_X17_NDX],
|
||||
g_current_regs[REG_X18_NDX], g_current_regs[REG_X19_NDX],
|
||||
g_current_regs[REG_X20_NDX], g_current_regs[REG_X21_NDX],
|
||||
g_current_regs[REG_X22_NDX], g_current_regs[REG_X23_NDX]);
|
||||
_alert("X24:%08x X25:%08x GP:%08x FP:%08x "
|
||||
" SP:%08x RA:%08x EA:%08x BA:%08x\n",
|
||||
g_current_regs[REG_X24_NDX], g_current_regs[REG_X25_NDX],
|
||||
g_current_regs[REG_X26_NDX], g_current_regs[REG_X27_NDX],
|
||||
g_current_regs[REG_X28_NDX], g_current_regs[REG_X29_NDX],
|
||||
g_current_regs[REG_X30_NDX], g_current_regs[REG_X31_NDX]);
|
||||
_alert(" IE:%08x\n", g_current_regs[REG_X32_NDX]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lm32_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
void lm32_dumpstate(void)
|
||||
{
|
||||
struct tcb_s *rtcb = running_task();
|
||||
uint32_t sp = up_getsp();
|
||||
uint32_t ustackbase;
|
||||
uint32_t ustacksize;
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uint32_t istackbase;
|
||||
uint32_t istacksize;
|
||||
#endif
|
||||
|
||||
/* Dump the registers (if available) */
|
||||
|
||||
lm32_registerdump();
|
||||
|
||||
/* Get the limits on the user stack memory */
|
||||
|
||||
ustackbase = (uint32_t)rtcb->stack_base_ptr;
|
||||
ustacksize = (uint32_t)rtcb->adj_stack_size;
|
||||
|
||||
/* Get the limits on the interrupt stack memory */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
istackbase = (uint32_t)g_intstackalloc;
|
||||
istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3);
|
||||
|
||||
/* Show interrupt stack info */
|
||||
|
||||
_alert("sp: %08x\n", sp);
|
||||
_alert("IRQ stack:\n");
|
||||
_alert(" base: %08x\n", istackbase);
|
||||
_alert(" size: %08x\n", istacksize);
|
||||
|
||||
/* Does the current stack pointer lie within the interrupt
|
||||
* stack?
|
||||
*/
|
||||
|
||||
if (sp >= istackbase && sp < istackbase + istacksize)
|
||||
{
|
||||
/* Yes.. dump the interrupt stack */
|
||||
|
||||
lm32_stackdump(sp, istackbase + istacksize);
|
||||
|
||||
/* Extract the user stack pointer which should lie
|
||||
* at the base of the interrupt stack.
|
||||
*/
|
||||
|
||||
sp = g_intstacktop;
|
||||
_alert("sp: %08x\n", sp);
|
||||
}
|
||||
else if (g_current_regs)
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within the interrupt stack\n");
|
||||
lm32_stackdump(istackbase, istackbase + istacksize);
|
||||
}
|
||||
|
||||
/* Show user stack info */
|
||||
|
||||
_alert("User stack:\n");
|
||||
_alert(" base: %08x\n", ustackbase);
|
||||
_alert(" size: %08x\n", ustacksize);
|
||||
#else
|
||||
_alert("sp: %08x\n", sp);
|
||||
_alert("stack base: %08x\n", ustackbase);
|
||||
_alert("stack size: %08x\n", ustacksize);
|
||||
#endif
|
||||
|
||||
/* Dump the user stack if the stack pointer lies within the allocated user
|
||||
* stack memory.
|
||||
*/
|
||||
|
||||
if (sp >= ustackbase && sp < ustackbase + ustacksize)
|
||||
{
|
||||
lm32_stackdump(sp, ustackbase + ustacksize);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within allocated stack\n");
|
||||
lm32_stackdump(ustackbase, ustackbase + ustacksize);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_STACKDUMP */
|
88
arch/misoc/src/lm32/lm32_registerdump.c
Normal file
88
arch/misoc/src/lm32/lm32_registerdump.c
Normal file
|
@ -0,0 +1,88 @@
|
|||
/****************************************************************************
|
||||
* arch/misoc/src/lm32/lm32_registerdump.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "lm32.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
return g_current_regs[REG_SP];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lm32_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
void lm32_registerdump(volatile uint32_t *regs)
|
||||
{
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (regs)
|
||||
{
|
||||
_alert("EPC:%08x\n",
|
||||
regs[REG_EPC]);
|
||||
_alert(" X0:%08x A0:%08x A1:%08x A2:%08x "
|
||||
" A3:%08x A4:%08x A5:%08x A6:%08x\n",
|
||||
regs[REG_X0_NDX], regs[REG_X1_NDX],
|
||||
regs[REG_X2_NDX], regs[REG_X3_NDX],
|
||||
regs[REG_X4_NDX], regs[REG_X5_NDX],
|
||||
regs[REG_X6_NDX], regs[REG_X7_NDX]);
|
||||
_alert(" A7:%08x X9:%08x X10:%08x X11:%08x "
|
||||
"X12:%08x X13:%08x X14:%08x X15:%08x\n",
|
||||
regs[REG_X8_NDX], regs[REG_X9_NDX],
|
||||
regs[REG_X10_NDX], regs[REG_X11_NDX],
|
||||
regs[REG_X12_NDX], regs[REG_X13_NDX],
|
||||
regs[REG_X14_NDX], regs[REG_X15_NDX]);
|
||||
_alert("X16:%08x X17:%08x X18:%08x X19:%08x "
|
||||
"X20:%08x X21:%08x X22:%08x X23:%08x\n",
|
||||
regs[REG_X16_NDX], regs[REG_X17_NDX],
|
||||
regs[REG_X18_NDX], regs[REG_X19_NDX],
|
||||
regs[REG_X20_NDX], regs[REG_X21_NDX],
|
||||
regs[REG_X22_NDX], regs[REG_X23_NDX]);
|
||||
_alert("X24:%08x X25:%08x GP:%08x FP:%08x "
|
||||
" SP:%08x RA:%08x EA:%08x BA:%08x\n",
|
||||
regs[REG_X24_NDX], regs[REG_X25_NDX],
|
||||
regs[REG_X26_NDX], regs[REG_X27_NDX],
|
||||
regs[REG_X28_NDX], regs[REG_X29_NDX],
|
||||
regs[REG_X30_NDX], regs[REG_X31_NDX]);
|
||||
_alert(" IE:%08x\n", regs[REG_X32_NDX]);
|
||||
}
|
||||
}
|
||||
|
|
@ -40,41 +40,6 @@
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: lm32_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_SYSCALL_INFO
|
||||
static void lm32_registerdump(const uint32_t *regs)
|
||||
{
|
||||
#if 0
|
||||
svcinfo("EPC:%08x\n",
|
||||
regs[REG_EPC]);
|
||||
svcinfo("A0:%08x A1:%08x A2:%08x A3:%08x "
|
||||
"A4:%08x A5:%08x A6:%08x A7:%08x\n",
|
||||
regs[REG_A0], regs[REG_A1], regs[REG_A2], regs[REG_A3],
|
||||
regs[REG_A4], regs[REG_A5], regs[REG_A6], regs[REG_A7]);
|
||||
svcinfo("T0:%08x T1:%08x T2:%08x T3:%08x T4:%08x T5:%08x T6:%08x\n",
|
||||
regs[REG_T0], regs[REG_T1], regs[REG_T2], regs[REG_T3],
|
||||
regs[REG_T4], regs[REG_T5], regs[REG_T6]);
|
||||
svcinfo("S0:%08x S1:%08x S2:%08x S3:%08x "
|
||||
"S4:%08x S5:%08x S6:%08x S7:%08x\n",
|
||||
regs[REG_S0], regs[REG_S1], regs[REG_S2], regs[REG_S3],
|
||||
regs[REG_S4], regs[REG_S5], regs[REG_S6], regs[REG_S7]);
|
||||
svcinfo("S8:%08x S9:%08x S10:%08x S11:%08x\n",
|
||||
regs[REG_S8], regs[REG_S9], regs[REG_S10], regs[REG_S11]);
|
||||
#ifdef LM3232_SAVE_GP
|
||||
svcinfo("GP:%08x SP:%08x FP:%08x TP:%08x RA:%08x\n",
|
||||
regs[REG_GP], regs[REG_SP], regs[REG_FP], regs[REG_TP],
|
||||
regs[REG_RA]);
|
||||
#else
|
||||
svcinfo("SP:%08x FP:%08x TP:%08x RA:%08x\n",
|
||||
regs[REG_SP], regs[REG_FP], regs[REG_TP], regs[REG_RA]);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dispatch_syscall
|
||||
*
|
||||
|
@ -289,7 +254,7 @@ int lm32_swint(int irq, void *context, void *arg)
|
|||
if (regs != g_current_regs)
|
||||
{
|
||||
svcinfo("SWInt Return: Context switch!\n");
|
||||
lm32_registerdump((const uint32_t *)g_current_regs);
|
||||
lm32_registerdump(g_current_regs);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -29,7 +29,7 @@ CHIP_ASRCS = minerva_syscall.S
|
|||
|
||||
CHIP_CSRCS = minerva_allocateheap.c minerva_assert.c
|
||||
CHIP_CSRCS += minerva_copystate.c minerva_createstack.c minerva_decodeirq.c
|
||||
CHIP_CSRCS += minerva_doirq.c minerva_dumpstate.c minerva_exit.c minerva_idle.c
|
||||
CHIP_CSRCS += minerva_doirq.c minerva_registerdump.c minerva_exit.c minerva_idle.c
|
||||
CHIP_CSRCS += minerva_initialstate.c minerva_irq.c
|
||||
CHIP_CSRCS += minerva_releasestack.c minerva_stackframe.c minerva_swint.c
|
||||
CHIP_CSRCS += minerva_switchcontext.c
|
||||
|
|
|
@ -127,7 +127,7 @@ void minerva_flush_icache(void);
|
|||
|
||||
/* Debug ********************************************************************/
|
||||
|
||||
void minerva_dumpstate(void);
|
||||
void mineva_registerdump(volatile uint32_t *regs);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* __ARCH_MISOC_SRC_MINERVA_MINERVA_H */
|
||||
|
|
|
@ -38,8 +38,8 @@
|
|||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
void up_assert(const char *filename, int lineno)
|
||||
void up_assert(void)
|
||||
{
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
minerva_dumpstate();
|
||||
mineva_registerdump(g_current_regs);
|
||||
}
|
||||
|
|
|
@ -1,199 +0,0 @@
|
|||
/****************************************************************************
|
||||
* arch/misoc/src/minerva/minerva_dumpstate.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/syslog/syslog.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "minerva.h"
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mineva_stackdump
|
||||
****************************************************************************/
|
||||
|
||||
static void mineva_stackdump(uint32_t sp, uint32_t stack_top)
|
||||
{
|
||||
uint32_t stack;
|
||||
|
||||
/* Flush any buffered SYSLOG data to avoid overwrite */
|
||||
|
||||
syslog_flush();
|
||||
|
||||
for (stack = sp & ~0x1f; stack < (stack_top & ~0x1f); stack += 32)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)stack;
|
||||
_alert("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mineva_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
static inline void mineva_registerdump(void)
|
||||
{
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (g_current_regs)
|
||||
{
|
||||
_alert("EPC:%08x\n", g_current_regs[REG_CSR_MEPC]);
|
||||
_alert(" X0:%08x A0:%08x A1:%08x A2:%08x "
|
||||
" A3:%08x A4:%08x A5:%08x A6:%08x\n",
|
||||
g_current_regs[REG_X0_NDX], g_current_regs[REG_X1_NDX],
|
||||
g_current_regs[REG_X2_NDX], g_current_regs[REG_X3_NDX],
|
||||
g_current_regs[REG_X4_NDX], g_current_regs[REG_X5_NDX],
|
||||
g_current_regs[REG_X6_NDX], g_current_regs[REG_X7_NDX]);
|
||||
_alert(" A7:%08x X9:%08x X10:%08x X11:%08x "
|
||||
"X12:%08x X13:%08x X14:%08x X15:%08x\n",
|
||||
g_current_regs[REG_X8_NDX], g_current_regs[REG_X9_NDX],
|
||||
g_current_regs[REG_X10_NDX], g_current_regs[REG_X11_NDX],
|
||||
g_current_regs[REG_X12_NDX], g_current_regs[REG_X13_NDX],
|
||||
g_current_regs[REG_X14_NDX], g_current_regs[REG_X15_NDX]);
|
||||
_alert("X16:%08x X17:%08x X18:%08x X19:%08x"
|
||||
"X20:%08x X21:%08x X22:%08x X23:%08x\n",
|
||||
g_current_regs[REG_X16_NDX], g_current_regs[REG_X17_NDX],
|
||||
g_current_regs[REG_X18_NDX], g_current_regs[REG_X19_NDX],
|
||||
g_current_regs[REG_X20_NDX], g_current_regs[REG_X21_NDX],
|
||||
g_current_regs[REG_X22_NDX], g_current_regs[REG_X23_NDX]);
|
||||
_alert("X24:%08x X25:%08x GP:%08x FP:%08x "
|
||||
" SP:%08x RA:%08x EA:%08x BA:%08x\n",
|
||||
g_current_regs[REG_X24_NDX], g_current_regs[REG_X25_NDX],
|
||||
g_current_regs[REG_X26_NDX], g_current_regs[REG_X27_NDX],
|
||||
g_current_regs[REG_X28_NDX], g_current_regs[REG_X29_NDX],
|
||||
g_current_regs[REG_X30_NDX], g_current_regs[REG_X31_NDX]);
|
||||
_alert(" IE:%08x\n", g_current_regs[REG_CSR_MSTATUS]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: minerva_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
void minerva_dumpstate(void)
|
||||
{
|
||||
struct tcb_s *rtcb = running_task();
|
||||
uint32_t sp = up_getsp();
|
||||
uint32_t ustackbase;
|
||||
uint32_t ustacksize;
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uint32_t istackbase;
|
||||
uint32_t istacksize;
|
||||
#endif
|
||||
|
||||
/* Dump the registers (if available) */
|
||||
|
||||
mineva_registerdump();
|
||||
|
||||
/* Get the limits on the user stack memory NOTE: You cannot use the PID to
|
||||
* determine if this is an IDLE task. In the SMP case, there may be
|
||||
* multiple IDLE tasks with different PIDs. The only consistent way to
|
||||
* test for the IDLE task is to check it is at the end of the list (flink
|
||||
* == NULL)
|
||||
*/
|
||||
|
||||
ustackbase = (uint32_t) rtcb->stack_base_ptr;
|
||||
ustacksize = (uint32_t) rtcb->adj_stack_size;
|
||||
|
||||
/* Get the limits on the interrupt stack memory */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
istackbase = (uint32_t)g_intstackalloc;
|
||||
istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3);
|
||||
|
||||
/* Show interrupt stack info */
|
||||
|
||||
_alert("sp: %08x\n", sp);
|
||||
_alert("IRQ stack:\n");
|
||||
_alert(" base: %08x\n", istackbase);
|
||||
_alert(" size: %08x\n", istacksize);
|
||||
|
||||
/* Does the current stack pointer lie within the interrupt stack? */
|
||||
|
||||
if (sp >= istackbase && sp < istackbase + istacksize)
|
||||
{
|
||||
/* Yes.. dump the interrupt stack */
|
||||
|
||||
mineva_stackdump(sp, istackbase + istacksize);
|
||||
|
||||
/* Extract the user stack pointer which should lie at the base of the
|
||||
* interrupt stack.
|
||||
*/
|
||||
|
||||
sp = g_intstacktop;
|
||||
_alert("sp: %08x\n", sp);
|
||||
}
|
||||
else if (g_current_regs)
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within the interrupt stack\n");
|
||||
mineva_stackdump(istackbase, istackbase + istacksize);
|
||||
}
|
||||
|
||||
/* Show user stack info */
|
||||
|
||||
_alert("User stack:\n");
|
||||
_alert(" base: %08x\n", ustackbase);
|
||||
_alert(" size: %08x\n", ustacksize);
|
||||
#else
|
||||
_alert("sp: %08x\n", sp);
|
||||
_alert("stack base: %08x\n", ustackbase);
|
||||
_alert("stack size: %08x\n", ustacksize);
|
||||
#endif
|
||||
|
||||
/* Dump the user stack if the stack pointer lies within the allocated user
|
||||
* stack memory.
|
||||
*/
|
||||
|
||||
if (sp >= ustackbase && sp < ustackbase + ustacksize)
|
||||
{
|
||||
mineva_stackdump(sp, ustackbase + ustacksize);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within allocated stack\n");
|
||||
mineva_stackdump(ustackbase, ustackbase + ustacksize);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_STACKDUMP */
|
87
arch/misoc/src/minerva/minerva_registerdump.c
Normal file
87
arch/misoc/src/minerva/minerva_registerdump.c
Normal file
|
@ -0,0 +1,87 @@
|
|||
/****************************************************************************
|
||||
* arch/misoc/src/minerva/minerva_registerdump.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "minerva.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
return g_current_regs[REG_X2];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: mineva_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
void mineva_registerdump(volatile uint32_t *regs)
|
||||
{
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (regs)
|
||||
{
|
||||
_alert("EPC:%08x\n", regs[REG_CSR_MEPC]);
|
||||
_alert(" X0:%08x A0:%08x A1:%08x A2:%08x "
|
||||
" A3:%08x A4:%08x A5:%08x A6:%08x\n",
|
||||
regs[REG_X0_NDX], regs[REG_X1_NDX],
|
||||
regs[REG_X2_NDX], regs[REG_X3_NDX],
|
||||
regs[REG_X4_NDX], regs[REG_X5_NDX],
|
||||
regs[REG_X6_NDX], regs[REG_X7_NDX]);
|
||||
_alert(" A7:%08x X9:%08x X10:%08x X11:%08x "
|
||||
"X12:%08x X13:%08x X14:%08x X15:%08x\n",
|
||||
regs[REG_X8_NDX], regs[REG_X9_NDX],
|
||||
regs[REG_X10_NDX], regs[REG_X11_NDX],
|
||||
regs[REG_X12_NDX], regs[REG_X13_NDX],
|
||||
regs[REG_X14_NDX], regs[REG_X15_NDX]);
|
||||
_alert("X16:%08x X17:%08x X18:%08x X19:%08x"
|
||||
"X20:%08x X21:%08x X22:%08x X23:%08x\n",
|
||||
regs[REG_X16_NDX], regs[REG_X17_NDX],
|
||||
regs[REG_X18_NDX], regs[REG_X19_NDX],
|
||||
regs[REG_X20_NDX], regs[REG_X21_NDX],
|
||||
regs[REG_X22_NDX], regs[REG_X23_NDX]);
|
||||
_alert("X24:%08x X25:%08x GP:%08x FP:%08x "
|
||||
" SP:%08x RA:%08x EA:%08x BA:%08x\n",
|
||||
regs[REG_X24_NDX], regs[REG_X25_NDX],
|
||||
regs[REG_X26_NDX], regs[REG_X27_NDX],
|
||||
regs[REG_X28_NDX], regs[REG_X29_NDX],
|
||||
regs[REG_X30_NDX], regs[REG_X31_NDX]);
|
||||
_alert(" IE:%08x\n", regs[REG_CSR_MSTATUS]);
|
||||
}
|
||||
}
|
||||
|
|
@ -40,41 +40,6 @@
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: minerva_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_SYSCALL_INFO
|
||||
static void minerva_registerdump(const uint32_t * regs)
|
||||
{
|
||||
#if 0
|
||||
svcinfo("EPC:%08x\n", regs[REG_CSR_MEPC]);
|
||||
svcinfo("A0:%08x A1:%08x A2:%08x A3:%08x "
|
||||
"A4:%08x A5:%08x A6:%08x A7:%08x\n",
|
||||
regs[REG_A0], regs[REG_A1], regs[REG_A2], regs[REG_A3],
|
||||
regs[REG_A4], regs[REG_A5], regs[REG_A6], regs[REG_A7]);
|
||||
svcinfo("T0:%08x T1:%08x T2:%08x T3:%08x "
|
||||
"T4:%08x T5:%08x T6:%08x\n",
|
||||
regs[REG_T0], regs[REG_T1], regs[REG_T2], regs[REG_T3],
|
||||
regs[REG_T4], regs[REG_T5], regs[REG_T6]);
|
||||
svcinfo("S0:%08x S1:%08x S2:%08x S3:%08x "
|
||||
"S4:%08x S5:%08x S6:%08x S7:%08x\n",
|
||||
regs[REG_S0], regs[REG_S1], regs[REG_S2], regs[REG_S3],
|
||||
regs[REG_S4], regs[REG_S5], regs[REG_S6], regs[REG_S7]);
|
||||
svcinfo("S8:%08x S9:%08x S10:%08x S11:%08x\n",
|
||||
regs[REG_S8], regs[REG_S9], regs[REG_S10], regs[REG_S11]);
|
||||
#ifdef MINERVA32_SAVE_GP
|
||||
svcinfo("GP:%08x SP:%08x FP:%08x TP:%08x RA:%08x\n",
|
||||
regs[REG_GP], regs[REG_SP], regs[REG_FP], regs[REG_TP],
|
||||
regs[REG_RA]);
|
||||
#else
|
||||
svcinfo("SP:%08x FP:%08x TP:%08x RA:%08x\n",
|
||||
regs[REG_SP], regs[REG_FP], regs[REG_TP], regs[REG_RA]);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dispatch_syscall
|
||||
*
|
||||
|
@ -265,7 +230,7 @@ int minerva_swint(int irq, void *context, void *arg)
|
|||
if (regs != g_current_regs)
|
||||
{
|
||||
svcinfo("SWInt Return: Context switch!\n");
|
||||
minerva_registerdump((const uint32_t *)g_current_regs);
|
||||
minerva_registerdump(g_current_regs);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -40,78 +40,22 @@
|
|||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static uint32_t s_last_regs[XCPTCONTEXT_REGS];
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: or1k_stackdump
|
||||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static void or1k_stackdump(uint32_t sp, uint32_t stack_top)
|
||||
{
|
||||
uint32_t stack;
|
||||
|
||||
for (stack = sp & ~0x1f; stack < (stack_top & ~0x1f); stack += 32)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)stack;
|
||||
_alert("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_taskdump
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
static void up_taskdump(struct tcb_s *tcb, void *arg)
|
||||
{
|
||||
/* Dump interesting properties of this task */
|
||||
|
||||
#if CONFIG_TASK_NAME_SIZE > 0
|
||||
_alert("%s: PID=%d Stack Used=%lu of %lu\n",
|
||||
tcb->name, tcb->pid, (unsigned long)up_check_tcbstack(tcb),
|
||||
(unsigned long)tcb->adj_stack_size);
|
||||
#else
|
||||
_alert("PID: %d Stack Used=%lu of %lu\n",
|
||||
tcb->pid, (unsigned long)up_check_tcbstack(tcb),
|
||||
(unsigned long)tcb->adj_stack_size);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_showtasks
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
static inline void up_showtasks(void)
|
||||
{
|
||||
/* Dump interesting properties of each task in the crash environment */
|
||||
|
||||
nxsched_foreach(up_taskdump, NULL);
|
||||
}
|
||||
#else
|
||||
# define up_showtasks()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: or1k_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static inline void or1k_registerdump(void)
|
||||
void up_assert(void)
|
||||
{
|
||||
volatile uint32_t *regs = CURRENT_REGS;
|
||||
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (regs == NULL)
|
||||
|
@ -122,139 +66,5 @@ static inline void or1k_registerdump(void)
|
|||
regs = s_last_regs;
|
||||
}
|
||||
|
||||
/* Dump the interrupt registers */
|
||||
|
||||
_alert("R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3],
|
||||
regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]);
|
||||
_alert("R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11],
|
||||
regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
_alert("xPSR: %08x PRIMASK: %08x EXEC_RETURN: %08x\n",
|
||||
regs[REG_XPSR], regs[REG_PRIMASK], regs[REG_EXC_RETURN]);
|
||||
#else
|
||||
_alert("xPSR: %08x PRIMASK: %08x\n",
|
||||
regs[REG_XPSR], regs[REG_PRIMASK]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static void up_dumpstate(void)
|
||||
{
|
||||
struct tcb_s *rtcb = running_task();
|
||||
uint32_t sp = up_getsp();
|
||||
uint32_t ustackbase;
|
||||
uint32_t ustacksize;
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uint32_t istackbase;
|
||||
uint32_t istacksize;
|
||||
#endif
|
||||
|
||||
/* Dump the registers (if available) */
|
||||
|
||||
or1k_registerdump();
|
||||
|
||||
/* Get the limits on the user stack memory */
|
||||
|
||||
ustackbase = (uint32_t)rtcb->stack_base_ptr;
|
||||
ustacksize = (uint32_t)rtcb->adj_stack_size;
|
||||
|
||||
/* Get the limits on the interrupt stack memory */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
istackbase = (uint32_t)g_intstackalloc;
|
||||
istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3);
|
||||
|
||||
/* Show interrupt stack info */
|
||||
|
||||
_alert("sp: %08x\n", sp);
|
||||
_alert("IRQ stack:\n");
|
||||
_alert(" base: %08x\n", istackbase);
|
||||
_alert(" size: %08x\n", istacksize);
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
_alert(" used: %08x\n", up_check_intstack());
|
||||
#endif
|
||||
|
||||
/* Does the current stack pointer lie within the interrupt
|
||||
* stack?
|
||||
*/
|
||||
|
||||
if (sp >= istackbase && sp < istackbase + istacksize)
|
||||
{
|
||||
/* Yes.. dump the interrupt stack */
|
||||
|
||||
or1k_stackdump(sp, istackbase + istacksize);
|
||||
}
|
||||
else if (CURRENT_REGS)
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within the interrupt stack\n");
|
||||
or1k_stackdump(istackbase, istackbase + istacksize);
|
||||
}
|
||||
|
||||
/* Extract the user stack pointer if we are in an interrupt handler.
|
||||
* If we are not in an interrupt handler. Then sp is the user stack
|
||||
* pointer (and the above range check should have failed).
|
||||
*/
|
||||
|
||||
if (CURRENT_REGS)
|
||||
{
|
||||
sp = CURRENT_REGS[REG_R13];
|
||||
_alert("sp: %08x\n", sp);
|
||||
}
|
||||
|
||||
_alert("User stack:\n");
|
||||
_alert(" base: %08x\n", ustackbase);
|
||||
_alert(" size: %08x\n", ustacksize);
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
_alert(" used: %08x\n", up_check_tcbstack(rtcb));
|
||||
#endif
|
||||
#else
|
||||
_alert("sp: %08x\n", sp);
|
||||
_alert("stack base: %08x\n", ustackbase);
|
||||
_alert("stack size: %08x\n", ustacksize);
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
_alert("stack used: %08x\n", up_check_tcbstack(rtcb));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Dump the user stack if the stack pointer lies within the allocated user
|
||||
* stack memory.
|
||||
*/
|
||||
|
||||
if (sp >= ustackbase && sp < ustackbase + ustacksize)
|
||||
{
|
||||
or1k_stackdump(sp, ustackbase + ustacksize);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within allocated stack\n");
|
||||
or1k_stackdump(ustackbase, ustackbase + ustacksize);
|
||||
}
|
||||
|
||||
/* Dump the state of all tasks (if available) */
|
||||
|
||||
up_showtasks();
|
||||
}
|
||||
#else
|
||||
# define up_dumpstate()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
void up_assert(const char *filename, int lineno)
|
||||
{
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
up_dumpstate();
|
||||
or1k_registerdump(regs);
|
||||
}
|
||||
|
|
44
arch/or1k/src/common/or1k_getintstack.c
Normal file
44
arch/or1k/src/common/or1k_getintstack.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/****************************************************************************
|
||||
* arch/or1k/src/common/or1k_getintstack.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "or1k_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_intstackbase
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uintptr_t up_get_intstackbase(void)
|
||||
{
|
||||
return (uintptr_t)g_intstackalloc;
|
||||
}
|
||||
#endif
|
|
@ -323,6 +323,8 @@ size_t or1k_stack_check(uintptr_t alloc, size_t size);
|
|||
void or1k_stack_color(void *stackbase, size_t nbytes);
|
||||
#endif
|
||||
|
||||
void or1k_registerdump(volatile uint32_t *regs);
|
||||
|
||||
#undef EXTERN
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
69
arch/or1k/src/common/or1k_registerdump.c
Normal file
69
arch/or1k/src/common/or1k_registerdump.c
Normal file
|
@ -0,0 +1,69 @@
|
|||
/****************************************************************************
|
||||
* arch/or1k/src/common/or1k_registerdump.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "or1k_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
return CURRENT_REGS[REG_R13];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: or1k_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
void or1k_registerdump(volatile uint32_t *regs)
|
||||
{
|
||||
/* Dump the interrupt registers */
|
||||
|
||||
_alert("R0: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3],
|
||||
regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]);
|
||||
_alert("R8: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11],
|
||||
regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
|
||||
#ifdef CONFIG_BUILD_PROTECTED
|
||||
_alert("xPSR: %08x PRIMASK: %08x EXEC_RETURN: %08x\n",
|
||||
regs[REG_XPSR], regs[REG_PRIMASK], regs[REG_EXC_RETURN]);
|
||||
#else
|
||||
_alert("xPSR: %08x PRIMASK: %08x\n",
|
||||
regs[REG_XPSR], regs[REG_PRIMASK]);
|
||||
#endif
|
||||
}
|
|
@ -32,6 +32,8 @@ CMN_CSRCS = or1k_initialize.c \
|
|||
or1k_switchcontext.c \
|
||||
or1k_schedulesigaction.c \
|
||||
or1k_copyfullstate.c \
|
||||
or1k_registerdump.c \
|
||||
or1k_getintstack.c \
|
||||
or1k_assert.c \
|
||||
or1k_exit.c \
|
||||
or1k_udelay.c \
|
||||
|
|
|
@ -25,10 +25,18 @@
|
|||
#include <nuttx/config.h>
|
||||
|
||||
#include <nuttx/board.h>
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "renesas_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t s_last_regs[XCPTCONTEXT_REGS];
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -37,8 +45,21 @@
|
|||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
void up_assert(const char *filename, int lineno)
|
||||
void up_assert(void)
|
||||
{
|
||||
volatile uint32_t *regs = g_current_regs;
|
||||
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
renesas_dumpstate();
|
||||
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (regs == NULL)
|
||||
{
|
||||
/* No.. capture user registers by hand */
|
||||
|
||||
up_saveusercontext(s_last_regs);
|
||||
regs = s_last_regs;
|
||||
}
|
||||
|
||||
renesas_registerdump(regs);
|
||||
}
|
||||
|
|
44
arch/renesas/src/common/renesas_getintstack.c
Normal file
44
arch/renesas/src/common/renesas_getintstack.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/****************************************************************************
|
||||
* arch/renesas/src/common/renesas_getintstack.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "renesas_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_intstackbase
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uintptr_t up_get_intstackbase(void)
|
||||
{
|
||||
return (uintptr_t)g_intstackalloc;
|
||||
}
|
||||
#endif
|
|
@ -118,6 +118,15 @@ typedef void (*up_vector_t)(void);
|
|||
extern uint32_t g_idle_topstack;
|
||||
#endif
|
||||
|
||||
/* Address of the saved user stack pointer */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
# if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
extern uint8_t g_intstackalloc[];
|
||||
extern uint8_t g_intstacktop[];
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Inline Functions
|
||||
****************************************************************************/
|
||||
|
@ -193,11 +202,7 @@ void renesas_usbuninitialize(void);
|
|||
|
||||
/* Defined in chip-specific logic */
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
void renesas_dumpstate(void);
|
||||
#else
|
||||
# define renesas_dumpstate()
|
||||
#endif
|
||||
void renesas_registerdump(volatile uint32_t *regs);
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
#endif /* ___ARCH_RENESAS_SRC_COMMON_UP_INTERNAL_H */
|
||||
|
|
|
@ -22,13 +22,14 @@ HEAD_ASRC = m16c_head.S
|
|||
|
||||
CMN_CSRCS = renesas_allocateheap.c renesas_assert.c
|
||||
CMN_CSRCS += renesas_createstack.c renesas_doirq.c renesas_exit.c renesas_idle.c renesas_initialize.c
|
||||
CMN_CSRCS += renesas_lowputs.c renesas_mdelay.c renesas_nputs.c renesas_releasestack.c
|
||||
CMN_CSRCS += renesas_lowputs.c renesas_mdelay.c renesas_nputs.c
|
||||
CMN_CSRCS += renesas_releasestack.c renesas_getintstack.c
|
||||
CMN_CSRCS += renesas_stackframe.c renesas_udelay.c renesas_switchcontext.c renesas_usestack.c
|
||||
|
||||
CHIP_ASRCS = m16c_vectors.S
|
||||
CHIP_CSRCS = m16c_initialstate.c m16c_copystate.c m16c_lowputc.c m16c_irq.c
|
||||
CHIP_CSRCS += m16c_schedulesigaction.c m16c_sigdeliver.c
|
||||
CHIP_CSRCS += m16c_serial.c m16c_dumpstate.c
|
||||
CHIP_CSRCS += m16c_serial.c m16c_registerdump.c
|
||||
|
||||
ifneq ($(CONFIG_SCHED_TICKLESS),y)
|
||||
CHIP_CSRCS += m16c_timerisr.c
|
||||
|
|
|
@ -253,15 +253,6 @@ extern uint32_t g_enronly; /* Start of relocated read-only data in FLASH *
|
|||
#endif
|
||||
extern uint32_t g_svarvect; /* Start of variable vectors */
|
||||
|
||||
/* Address of the saved user stack pointer */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
# if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
extern uint8_t g_intstackalloc[];
|
||||
extern uint8_t g_intstacktop[];
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif /* __ARCH_RENESAS_SRC_M16C_CHIP_H */
|
||||
|
|
|
@ -1,215 +0,0 @@
|
|||
/****************************************************************************
|
||||
* arch/renesas/src/m16c/m16c_dumpstate.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/syslog/syslog.h>
|
||||
|
||||
#include "renesas_internal.h"
|
||||
#include "sched/sched.h"
|
||||
#include "chip.h"
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static uint8_t s_last_regs[XCPTCONTEXT_REGS];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: m16c_getusersp
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
static inline uint16_t m16c_getusersp(void)
|
||||
{
|
||||
uint8_t *ptr = (uint8_t *) g_current_regs;
|
||||
return (uint16_t)ptr[REG_SP] << 8 | ptr[REG_SP + 1];
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: m16c_stackdump
|
||||
****************************************************************************/
|
||||
|
||||
static void m16c_stackdump(uint16_t sp, uint16_t stack_top)
|
||||
{
|
||||
uint16_t stack;
|
||||
|
||||
/* Flush any buffered SYSLOG data to avoid overwrite */
|
||||
|
||||
syslog_flush();
|
||||
|
||||
for (stack = sp & ~0x7; stack < (stack_top & ~0x7); stack += 8)
|
||||
{
|
||||
uint8_t *ptr = (uint8_t *)stack;
|
||||
_alert("%04x: %02x %02x %02x %02x %02x %02x %02x %02x\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: m16c_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
static inline void m16c_registerdump(void)
|
||||
{
|
||||
volatile uint8_t *ptr = (uint8_t *)g_current_regs;
|
||||
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (ptr == NULL)
|
||||
{
|
||||
/* No.. capture user registers by hand */
|
||||
|
||||
up_saveusercontext((uint32_t *)s_last_regs);
|
||||
ptr = s_last_regs;
|
||||
}
|
||||
|
||||
/* Dump the interrupt registers */
|
||||
|
||||
_alert("PC: %02x%02x%02x FLG: %02x00%02x FB: %02x%02x SB: %02x%02x "
|
||||
"SP: %02x%02x\n",
|
||||
ptr[REG_FLGPCHI] & 0xff, ptr[REG_PC], ptr[REG_PC + 1],
|
||||
ptr[REG_FLGPCHI] >> 8, ptr[REG_FLG],
|
||||
ptr[REG_FB], ptr[REG_FB + 1],
|
||||
ptr[REG_SB], ptr[REG_SB + 1],
|
||||
ptr[REG_SP], ptr[REG_SP + 1]);
|
||||
|
||||
_alert("R0: %02x%02x R1: %02x%02x R2: %02x%02x A0: %02x%02x "
|
||||
"A1: %02x%02x\n",
|
||||
ptr[REG_R0], ptr[REG_R0 + 1], ptr[REG_R1], ptr[REG_R1 + 1],
|
||||
ptr[REG_R2], ptr[REG_R2 + 1], ptr[REG_R3], ptr[REG_R3 + 1],
|
||||
ptr[REG_A0], ptr[REG_A0 + 1], ptr[REG_A1], ptr[REG_A1 + 1]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: renesas_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
void renesas_dumpstate(void)
|
||||
{
|
||||
struct tcb_s *rtcb = running_task();
|
||||
uint16_t sp = up_getsp();
|
||||
uint16_t ustackbase;
|
||||
uint16_t ustacksize;
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uint16_t istackbase;
|
||||
uint16_t istacksize;
|
||||
#endif
|
||||
|
||||
/* Dump the registers (if available) */
|
||||
|
||||
m16c_registerdump();
|
||||
|
||||
/* Get the limits on the user stack memory */
|
||||
|
||||
ustackbase = (uint16_t)rtcb->stack_base_ptr;
|
||||
ustacksize = (uint16_t)rtcb->adj_stack_size;
|
||||
|
||||
/* Get the limits on the interrupt stack memory.
|
||||
* The near RAM memory map is as follows:
|
||||
*
|
||||
* 0x00400 - DATA Size: Determined by linker
|
||||
* BSS Size: Determined by linker
|
||||
* Interrupt stack Size: CONFIG_ARCH_INTERRUPTSTACK
|
||||
* Idle stack Size: CONFIG_IDLETHREAD_STACKSIZE
|
||||
* Heap Size: Everything remaining
|
||||
* 0x00bff - (end+1)
|
||||
*/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
istackbase = g_enbss;
|
||||
istacksize = CONFIG_ARCH_INTERRUPTSTACK;
|
||||
|
||||
/* Show interrupt stack info */
|
||||
|
||||
_alert("sp: %04x\n", sp);
|
||||
_alert("IRQ stack:\n");
|
||||
_alert(" base: %04x\n", istackbase);
|
||||
_alert(" size: %04x\n", istacksize);
|
||||
|
||||
/* Does the current stack pointer lie within the interrupt
|
||||
* stack?
|
||||
*/
|
||||
|
||||
if (sp >= istackbase && sp < istackbase + istacksize)
|
||||
{
|
||||
/* Yes.. dump the interrupt stack */
|
||||
|
||||
m16c_stackdump(sp, istackbase + istacksize);
|
||||
|
||||
/* Extract the user stack pointer from the register area */
|
||||
|
||||
sp = m16c_getusersp();
|
||||
_alert("sp: %04x\n", sp);
|
||||
}
|
||||
else if (g_current_regs)
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within the interrupt stack\n");
|
||||
m16c_stackdump(istackbase, istackbase + istacksize);
|
||||
}
|
||||
|
||||
/* Show user stack info */
|
||||
|
||||
_alert("User stack:\n");
|
||||
_alert(" base: %04x\n", ustackbase);
|
||||
_alert(" size: %04x\n", ustacksize);
|
||||
#else
|
||||
_alert("sp: %04x\n", sp);
|
||||
_alert("stack base: %04x\n", ustackbase);
|
||||
_alert("stack size: %04x\n", ustacksize);
|
||||
#endif
|
||||
|
||||
/* Dump the user stack if the stack pointer lies within the allocated user
|
||||
* stack memory.
|
||||
*/
|
||||
|
||||
if (sp >= ustackbase && sp < ustackbase + ustacksize)
|
||||
{
|
||||
m16c_stackdump(sp, ustackbase + ustacksize);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within allocated stack\n");
|
||||
m16c_stackdump(ustackbase, ustackbase + ustacksize);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_STACKDUMP */
|
|
@ -1,5 +1,5 @@
|
|||
/****************************************************************************
|
||||
* arch/z16/src/common/z16_stackdump.c
|
||||
* arch/renesas/src/m16c/m16c_registerdump.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -23,68 +23,51 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <nuttx/syslog/syslog.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "renesas_internal.h"
|
||||
#include "chip.h"
|
||||
#include "sched/sched.h"
|
||||
#include "z16_internal.h"
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_getsp
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
/* To be provided */
|
||||
|
||||
/****************************************************************************
|
||||
* Name: z16_stackdump
|
||||
****************************************************************************/
|
||||
|
||||
void z16_stackdump(void)
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
FAR struct tcb_s *rtcb = running_task();
|
||||
chipreg_t sp = up_getsp();
|
||||
chipreg_t stack_base = (chipreg_t)rtcb->stack_base_ptr;
|
||||
chipreg_t stack_size = (chipreg_t)rtcb->adj_stack_size;
|
||||
chipreg_t stack;
|
||||
chipreg_t stack_top;
|
||||
|
||||
_alert("stack_base: %08x\n", stack_base);
|
||||
_alert("stack_size: %08x\n", stack_size);
|
||||
_alert("sp: %08x\n", sp);
|
||||
|
||||
if (sp >= stack_base && sp < stack_base + stack_size)
|
||||
{
|
||||
stack = sp;
|
||||
}
|
||||
else
|
||||
{
|
||||
_err("ERROR: Stack pointer is not within allocated stack\n");
|
||||
stack = stack_base;
|
||||
}
|
||||
|
||||
stack_top = stack_base + stack_size;
|
||||
|
||||
/* Flush any buffered SYSLOG data to avoid overwrite */
|
||||
|
||||
syslog_flush();
|
||||
|
||||
for (stack = stack & ~(8 * sizeof(chipreg_t) - 1);
|
||||
stack < (stack_top & ~(8 * sizeof(chipreg_t) - 1));
|
||||
stack += 8 * sizeof(chipreg_t))
|
||||
{
|
||||
chipreg_t *ptr = (chipreg_t *)stack;
|
||||
_alert("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
uint8_t *ptr = (uint8_t *) g_current_regs;
|
||||
return (uintptr_t)(ptr[REG_SP] << 8 | ptr[REG_SP + 1]);
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_STACKDUMP */
|
||||
/****************************************************************************
|
||||
* Name: renesas_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
void renesas_registerdump(volatile uint32_t *regs)
|
||||
{
|
||||
uint8_t *ptr = (uint8_t *)regs;
|
||||
|
||||
/* Dump the interrupt registers */
|
||||
|
||||
_alert("PC: %02x%02x%02x FLG: %02x00%02x FB: %02x%02x SB: %02x%02x "
|
||||
"SP: %02x%02x\n",
|
||||
ptr[REG_FLGPCHI] & 0xff, ptr[REG_PC], ptr[REG_PC + 1],
|
||||
ptr[REG_FLGPCHI] >> 8, ptr[REG_FLG],
|
||||
ptr[REG_FB], ptr[REG_FB + 1],
|
||||
ptr[REG_SB], ptr[REG_SB + 1],
|
||||
ptr[REG_SP], ptr[REG_SP + 1]);
|
||||
|
||||
_alert("R0: %02x%02x R1: %02x%02x R2: %02x%02x A0: %02x%02x "
|
||||
"A1: %02x%02x\n",
|
||||
ptr[REG_R0], ptr[REG_R0 + 1], ptr[REG_R1], ptr[REG_R1 + 1],
|
||||
ptr[REG_R2], ptr[REG_R2 + 1], ptr[REG_R3], ptr[REG_R3 + 1],
|
||||
ptr[REG_A0], ptr[REG_A0 + 1], ptr[REG_A1], ptr[REG_A1 + 1]);
|
||||
}
|
|
@ -22,14 +22,15 @@ HEAD_ASRC = rx65n_head.S
|
|||
|
||||
CMN_CSRCS = renesas_allocateheap.c renesas_assert.c
|
||||
CMN_CSRCS += renesas_createstack.c renesas_doirq.c renesas_exit.c renesas_idle.c renesas_initialize.c
|
||||
CMN_CSRCS += renesas_lowputs.c renesas_mdelay.c renesas_nputs.c renesas_releasestack.c
|
||||
CMN_CSRCS += renesas_lowputs.c renesas_mdelay.c renesas_nputs.c
|
||||
CMN_CSRCS += renesas_releasestack.c renesas_getintstack.c
|
||||
CMN_CSRCS += renesas_stackframe.c renesas_udelay.c renesas_switchcontext.c renesas_usestack.c
|
||||
|
||||
CHIP_ASRCS = rx65n_vector.S
|
||||
CHIP_CSRCS = rx65n_lowputc.c rx65n_serial.c rx65n_copystate.c rx65n_irq.c
|
||||
CHIP_CSRCS += rx65n_schedulesigaction.c rx65n_sigdeliver.c rx65n_initialstate.c
|
||||
CHIP_CSRCS += rx65n_hardware_setup.c rx65n_port.c rx65n_sci.c
|
||||
CHIP_CSRCS += rx65n_cgc.c rx65n_dumpstate.c rx65n_vector_table.c
|
||||
CHIP_CSRCS += rx65n_cgc.c rx65n_registerdump.c rx65n_vector_table.c
|
||||
CHIP_CSRCS += rx65n_timerisr.c rx65n_sbram.c
|
||||
|
||||
ifeq ($(CONFIG_RX65N_EMAC),y)
|
||||
|
|
|
@ -1,215 +0,0 @@
|
|||
/****************************************************************************
|
||||
* arch/renesas/src/rx65n/rx65n_dumpstate.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/syslog/syslog.h>
|
||||
|
||||
#include "renesas_internal.h"
|
||||
#include "sched/sched.h"
|
||||
#include "chip.h"
|
||||
#include "arch/rx65n/irq.h"
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t s_last_regs[XCPTCONTEXT_REGS];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rx65n_getusersp
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
static inline uint16_t rx65n_getusersp(void)
|
||||
{
|
||||
uint8_t *ptr = (uint8_t *) g_current_regs;
|
||||
return (uint16_t)ptr[REG_SP] << 8 | ptr[REG_SP + 1]; /* check */
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rx65n_stackdump
|
||||
****************************************************************************/
|
||||
|
||||
static void rx65n_stackdump(uint32_t sp, uint32_t stack_top)
|
||||
{
|
||||
uint32_t stack;
|
||||
|
||||
/* Flush any buffered SYSLOG data to avoid overwrite */
|
||||
|
||||
syslog_flush();
|
||||
|
||||
for (stack = sp & ~0x1f; stack < (stack_top & ~0x1f); stack += 32)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)stack;
|
||||
_alert("%08" PRIxPTR ": %08" PRIx32 " %08" PRIx32 " %08" PRIx32
|
||||
" %08" PRIx32 " %08" PRIx32 " %08" PRIx32 " %08" PRIx32
|
||||
" %08" PRIx32 "\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rx65n_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
static inline void rx65n_registerdump(void)
|
||||
{
|
||||
volatile uint32_t *ptr = g_current_regs;
|
||||
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (ptr == NULL)
|
||||
{
|
||||
/* No.. capture user registers by hand */
|
||||
|
||||
up_saveusercontext(s_last_regs);
|
||||
ptr = s_last_regs;
|
||||
}
|
||||
|
||||
/* Dump the interrupt registers */
|
||||
|
||||
_alert("PC: %08" PRIx32 " PSW=%08" PRIx32 "\n",
|
||||
ptr[REG_PC], ptr[REG_PSW]);
|
||||
|
||||
_alert("FPSW: %08" PRIx32 " ACC0LO: %08" PRIx32 " ACC0HI: %08" PRIx32
|
||||
" ACC0GU: %08" PRIx32 "ACC1LO: %08" PRIx32 " ACC1HI: %08" PRIx32
|
||||
" ACC1GU: %08" PRIx32 "\n",
|
||||
ptr[REG_FPSW], ptr[REG_ACC0LO], ptr[REG_ACC0HI],
|
||||
ptr[REG_ACC0GU], ptr[REG_ACC1LO],
|
||||
ptr[REG_ACC1HI], ptr[REG_ACC1GU]);
|
||||
|
||||
_alert("R%d:%08" PRIx32 " %08" PRIx32 " %08" PRIx32 " %08" PRIx32
|
||||
" %08" PRIx32 " %08" PRIx32 " %08" PRIx32 "\n", 0,
|
||||
ptr[REG_R1], ptr[REG_R2], ptr[REG_R3],
|
||||
ptr[REG_R4], ptr[REG_R5], ptr[REG_R6], ptr[REG_R7]);
|
||||
|
||||
_alert("R%d: %08" PRIx32 " %08" PRIx32 " %08" PRIx32 " %08" PRIx32
|
||||
" %08" PRIx32 " %08" PRIx32 " %08" PRIx32 " %08" PRIx32 "\n", 8,
|
||||
ptr[REG_R8], ptr[REG_R9], ptr[REG_R10], ptr[REG_R11],
|
||||
ptr[REG_R12], ptr[REG_R13], ptr[REG_R14], ptr[REG_R15]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: renesas_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
void renesas_dumpstate(void)
|
||||
{
|
||||
struct tcb_s *rtcb = running_task();
|
||||
uint32_t sp = up_getsp();
|
||||
uint32_t ustackbase;
|
||||
uint32_t ustacksize;
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uint32_t istackbase;
|
||||
uint32_t istacksize;
|
||||
#endif
|
||||
|
||||
/* Dump the registers (if available) */
|
||||
|
||||
rx65n_registerdump();
|
||||
|
||||
/* Get the limits on the user stack memory */
|
||||
|
||||
ustackbase = (uint32_t)rtcb->stack_base_ptr;
|
||||
ustacksize = (uint32_t)rtcb->adj_stack_size;
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
istackbase = ebss; /* check how to declare ebss, as of now declared in chip.h */
|
||||
|
||||
istacksize = CONFIG_ARCH_INTERRUPTSTACK & ~3;
|
||||
|
||||
/* Show interrupt stack info */
|
||||
|
||||
_alert("sp: %08" PRIx32 "\n", sp);
|
||||
_alert("IRQ stack:\n");
|
||||
_alert(" base: %08" PRIx32 "\n", istackbase);
|
||||
_alert(" size: %08" PRIx32 "\n", istacksize);
|
||||
|
||||
/* Does the current stack pointer lie within the interrupt
|
||||
* stack?
|
||||
*/
|
||||
|
||||
if (sp >= istackbase && sp < istackbase + istacksize)
|
||||
{
|
||||
/* Yes.. dump the interrupt stack */
|
||||
|
||||
rx65n_stackdump(sp, istackbase + istacksize);
|
||||
|
||||
/* Extract the user stack pointer from the register area */
|
||||
|
||||
sp = rx65n_getusersp();
|
||||
_alert("sp: %08" PRIx32 "\n", sp);
|
||||
}
|
||||
else if (g_current_regs)
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within the interrupt stack\n");
|
||||
rx65n_stackdump(istackbase, istackbase + istacksize);
|
||||
}
|
||||
|
||||
/* Show user stack info */
|
||||
|
||||
_alert("User stack:\n");
|
||||
_alert(" base: %08" PRIx32 "\n", ustackbase);
|
||||
_alert(" size: %08" PRIx32 "\n", ustacksize);
|
||||
#else
|
||||
_alert("sp: %08" PRIx32 "\n", sp);
|
||||
_alert("stack base: %08" PRIx32 "\n", ustackbase);
|
||||
_alert("stack size: %08" PRIx32 "\n", ustacksize);
|
||||
#endif
|
||||
|
||||
/* Dump the user stack if the stack pointer lies within the allocated user
|
||||
* stack memory.
|
||||
*/
|
||||
|
||||
if (sp >= ustackbase && sp < ustackbase + ustacksize)
|
||||
{
|
||||
rx65n_stackdump(sp, ustackbase + ustacksize);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within allocated stack\n");
|
||||
rx65n_stackdump(ustackbase, ustackbase + ustacksize);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_STACKDUMP */
|
78
arch/renesas/src/rx65n/rx65n_registerdump.c
Normal file
78
arch/renesas/src/rx65n/rx65n_registerdump.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
/****************************************************************************
|
||||
* arch/renesas/src/rx65n/rx65n_registerdump.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "renesas_internal.h"
|
||||
#include "chip.h"
|
||||
#include "arch/rx65n/irq.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
return g_current_regs[REG_SP];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: rx65n_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
void renesas_registerdump(volatile uint32_t *regs)
|
||||
{
|
||||
/* Dump the interrupt registers */
|
||||
|
||||
_alert("PC: %08" PRIx32 " PSW=%08" PRIx32 "\n",
|
||||
regs[REG_PC], regs[REG_PSW]);
|
||||
|
||||
_alert("FPSW: %08" PRIx32 " ACC0LO: %08" PRIx32 " ACC0HI: %08" PRIx32
|
||||
" ACC0GU: %08" PRIx32 "ACC1LO: %08" PRIx32 " ACC1HI: %08" PRIx32
|
||||
" ACC1GU: %08" PRIx32 "\n",
|
||||
regs[REG_FPSW], regs[REG_ACC0LO], regs[REG_ACC0HI],
|
||||
regs[REG_ACC0GU], regs[REG_ACC1LO],
|
||||
regs[REG_ACC1HI], regs[REG_ACC1GU]);
|
||||
|
||||
_alert("R%d:%08" PRIx32 " %08" PRIx32 " %08" PRIx32 " %08" PRIx32
|
||||
" %08" PRIx32 " %08" PRIx32 " %08" PRIx32 "\n", 0,
|
||||
regs[REG_R1], regs[REG_R2], regs[REG_R3],
|
||||
regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]);
|
||||
|
||||
_alert("R%d: %08" PRIx32 " %08" PRIx32 " %08" PRIx32 " %08" PRIx32
|
||||
" %08" PRIx32 " %08" PRIx32 " %08" PRIx32 " %08" PRIx32 "\n", 8,
|
||||
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11],
|
||||
regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
|
||||
}
|
|
@ -24,13 +24,13 @@ CMN_CSRCS = renesas_allocateheap.c renesas_assert.c
|
|||
CMN_CSRCS += renesas_createstack.c renesas_doirq.c renesas_exit.c renesas_idle.c renesas_initialize.c
|
||||
CMN_CSRCS += renesas_initialstate.c renesas_lowputs.c
|
||||
CMN_CSRCS += renesas_mdelay.c renesas_nputs.c renesas_releasestack.c
|
||||
CMN_CSRCS += renesas_stackframe.c renesas_udelay.c
|
||||
CMN_CSRCS += renesas_stackframe.c renesas_udelay.c renesas_getintstack.c
|
||||
CMN_CSRCS += sh1_schedulesigaction.c sh1_sigdeliver.c
|
||||
CMN_CSRCS += renesas_switchcontext.c renesas_usestack.c
|
||||
|
||||
CHIP_ASRCS = sh1_vector.S sh1_saveusercontext.S
|
||||
CHIP_CSRCS = sh1_lowputc.c sh1_irq.c sh1_serial.c sh1_initialstate.c
|
||||
CHIP_CSRCS += sh1_copystate.c sh1_dumpstate.c
|
||||
CHIP_CSRCS += sh1_copystate.c sh1_registerdump.c
|
||||
|
||||
ifneq ($(CONFIG_SCHED_TICKLESS),y)
|
||||
CHIP_CSRCS += sh1_timerisr.c
|
||||
|
|
|
@ -44,15 +44,6 @@
|
|||
* Public Data
|
||||
************************************************************************************/
|
||||
|
||||
/* Address of the saved user stack pointer */
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
# if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
extern uint8_t g_intstackalloc[];
|
||||
extern uint8_t g_intstacktop[];
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/************************************************************************************
|
||||
* Public Functions Prototypes
|
||||
************************************************************************************/
|
||||
|
|
|
@ -1,195 +0,0 @@
|
|||
/****************************************************************************
|
||||
* arch/renesas/src/sh1/sh1_dumpstate.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/syslog/syslog.h>
|
||||
|
||||
#include "renesas_internal.h"
|
||||
#include "sched/sched.h"
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static uint32_t s_last_regs[XCPTCONTEXT_REGS];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sh1_stackdump
|
||||
****************************************************************************/
|
||||
|
||||
static void sh1_stackdump(uint32_t sp, uint32_t stack_top)
|
||||
{
|
||||
uint32_t stack;
|
||||
|
||||
/* Flush any buffered SYSLOG data to avoid overwrite */
|
||||
|
||||
syslog_flush();
|
||||
|
||||
for (stack = sp & ~0x1f; stack < (stack_top & ~0x1f); stack += 32)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)stack;
|
||||
_alert("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sh1_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
static inline void sh1_registerdump(void)
|
||||
{
|
||||
volatile uint32_t *ptr = g_current_regs;
|
||||
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (ptr == NULL)
|
||||
{
|
||||
/* No.. capture user registers by hand */
|
||||
|
||||
up_saveusercontext(s_last_regs);
|
||||
regs = s_last_regs;
|
||||
}
|
||||
|
||||
/* Dump the interrupt registers */
|
||||
|
||||
_alert("PC: %08x SR=%08x\n",
|
||||
ptr[REG_PC], ptr[REG_SR]);
|
||||
|
||||
_alert("PR: %08x GBR: %08x MACH: %08x MACL: %08x\n",
|
||||
ptr[REG_PR], ptr[REG_GBR], ptr[REG_MACH], ptr[REG_MACL]);
|
||||
|
||||
_alert("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n", 0,
|
||||
ptr[REG_R0], ptr[REG_R1], ptr[REG_R2], ptr[REG_R3],
|
||||
ptr[REG_R4], ptr[REG_R5], ptr[REG_R6], ptr[REG_R7]);
|
||||
|
||||
_alert("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n", 8,
|
||||
ptr[REG_R8], ptr[REG_R9], ptr[REG_R10], ptr[REG_R11],
|
||||
ptr[REG_R12], ptr[REG_R13], ptr[REG_R14], ptr[REG_R15]);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: renesas_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
void renesas_dumpstate(void)
|
||||
{
|
||||
struct tcb_s *rtcb = running_task();
|
||||
uint32_t sp = up_getsp();
|
||||
uint32_t ustackbase;
|
||||
uint32_t ustacksize;
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uint32_t istackbase;
|
||||
uint32_t istacksize;
|
||||
#endif
|
||||
|
||||
/* Dump the registers (if available) */
|
||||
|
||||
sh1_registerdump();
|
||||
|
||||
/* Get the limits on the user stack memory */
|
||||
|
||||
ustackbase = (uint32_t)rtcb->stack_base_ptr;
|
||||
ustacksize = (uint32_t)rtcb->adj_stack_size;
|
||||
|
||||
/* Get the limits on the interrupt stack memory */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
istackbase = (uint32_t)g_intstackalloc;
|
||||
istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3);
|
||||
|
||||
/* Show interrupt stack info */
|
||||
|
||||
_alert("sp: %08x\n", sp);
|
||||
_alert("IRQ stack:\n");
|
||||
_alert(" base: %08x\n", istackbase);
|
||||
_alert(" size: %08x\n", istacksize);
|
||||
|
||||
/* Does the current stack pointer lie within the interrupt
|
||||
* stack?
|
||||
*/
|
||||
|
||||
if (sp >= istackbase && sp < istackbase + istacksize)
|
||||
{
|
||||
/* Yes.. dump the interrupt stack */
|
||||
|
||||
sh1_stackdump(sp, istackbase + istacksize);
|
||||
|
||||
/* Extract the user stack pointer which should lie
|
||||
* at the base of the interrupt stack.
|
||||
*/
|
||||
|
||||
sp = g_intstacktop;
|
||||
_alert("sp: %08x\n", sp);
|
||||
}
|
||||
else if (g_current_regs)
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within the interrupt stack\n");
|
||||
sh1_stackdump(istackbase, istackbase + istacksize);
|
||||
}
|
||||
|
||||
/* Show user stack info */
|
||||
|
||||
_alert("User stack:\n");
|
||||
_alert(" base: %08x\n", ustackbase);
|
||||
_alert(" size: %08x\n", ustacksize);
|
||||
#else
|
||||
_alert("sp: %08x\n", sp);
|
||||
_alert("stack base: %08x\n", ustackbase);
|
||||
_alert("stack size: %08x\n", ustacksize);
|
||||
#endif
|
||||
|
||||
/* Dump the user stack if the stack pointer lies within the allocated user
|
||||
* stack memory.
|
||||
*/
|
||||
|
||||
if (sp >= ustackbase && sp < ustackbase + ustacksize)
|
||||
{
|
||||
sh1_stackdump(sp, ustackbase + ustacksize);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within allocated stack\n");
|
||||
sh1_stackdump(ustackbase, ustackbase + ustacksize);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CONFIG_ARCH_STACKDUMP */
|
70
arch/renesas/src/sh1/sh1_registerdump.c
Normal file
70
arch/renesas/src/sh1/sh1_registerdump.c
Normal file
|
@ -0,0 +1,70 @@
|
|||
/****************************************************************************
|
||||
* arch/renesas/src/sh1/sh1_registerdump.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "renesas_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
return g_current_regs[REG_SP];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: renesas_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
void renesas_registerdump(volatile uint32_t *regs)
|
||||
{
|
||||
/* Dump the interrupt registers */
|
||||
|
||||
_alert("PC: %08x SR=%08x\n",
|
||||
regs[REG_PC], regs[REG_SR]);
|
||||
|
||||
_alert("PR: %08x GBR: %08x MACH: %08x MACL: %08x\n",
|
||||
regs[REG_PR], regs[REG_GBR], regs[REG_MACH], regs[REG_MACL]);
|
||||
|
||||
_alert("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n", 0,
|
||||
regs[REG_R0], regs[REG_R1], regs[REG_R2], regs[REG_R3],
|
||||
regs[REG_R4], regs[REG_R5], regs[REG_R6], regs[REG_R7]);
|
||||
|
||||
_alert("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n", 8,
|
||||
regs[REG_R8], regs[REG_R9], regs[REG_R10], regs[REG_R11],
|
||||
regs[REG_R12], regs[REG_R13], regs[REG_R14], regs[REG_R15]);
|
||||
}
|
||||
|
|
@ -34,7 +34,7 @@ CMN_CSRCS += riscv_releasestack.c riscv_stackframe.c riscv_schedulesigaction.c
|
|||
CMN_CSRCS += riscv_sigdeliver.c riscv_switchcontext.c riscv_usestack.c
|
||||
CMN_CSRCS += riscv_idle.c riscv_tcbinfo.c riscv_cpuidlestack.c
|
||||
CMN_CSRCS += riscv_exception.c riscv_getnewintctx.c riscv_doirq.c
|
||||
CMN_CSRCS += riscv_saveusercontext.c
|
||||
CMN_CSRCS += riscv_saveusercontext.c riscv_getintstack.c riscv_registerdump.c
|
||||
|
||||
ifneq ($(CONFIG_ALARM_ARCH),y)
|
||||
ifneq ($(CONFIG_TIMER_ARCH),y)
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include <stdint.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/tls.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/board.h>
|
||||
|
||||
|
@ -41,8 +40,6 @@
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
@ -50,295 +47,18 @@
|
|||
static uint8_t s_last_regs[XCPTCONTEXT_SIZE];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_stackdump
|
||||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
static void riscv_stackdump(uintptr_t sp, uintptr_t stack_top)
|
||||
{
|
||||
uintptr_t stack;
|
||||
|
||||
for (stack = sp & ~0x1f; stack < (stack_top & ~0x1f); stack += 32)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)stack;
|
||||
_alert("%" PRIxREG ": %08" PRIx32 " %08" PRIx32 " %08" PRIx32
|
||||
" %08" PRIx32 " %08" PRIx32 " %08" PRIx32 " %08" PRIx32
|
||||
" %08" PRIx32 "\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
static inline void riscv_registerdump(volatile uintptr_t *regs)
|
||||
{
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
_alert("EPC: %" PRIxREG "\n", regs[REG_EPC]);
|
||||
_alert("A0: %" PRIxREG " A1: %" PRIxREG " A2: %" PRIxREG
|
||||
" A3: %" PRIxREG "\n",
|
||||
regs[REG_A0], regs[REG_A1], regs[REG_A2], regs[REG_A3]);
|
||||
_alert("A4: %" PRIxREG " A5: %" PRIxREG " A6: %" PRIxREG
|
||||
" A7: %" PRIxREG "\n",
|
||||
regs[REG_A4], regs[REG_A5], regs[REG_A6], regs[REG_A7]);
|
||||
_alert("T0: %" PRIxREG " T1: %" PRIxREG " T2: %" PRIxREG
|
||||
" T3: %" PRIxREG "\n",
|
||||
regs[REG_T0], regs[REG_T1], regs[REG_T2], regs[REG_T3]);
|
||||
_alert("T4: %" PRIxREG " T5: %" PRIxREG " T6: %" PRIxREG "\n",
|
||||
regs[REG_T4], regs[REG_T5], regs[REG_T6]);
|
||||
_alert("S0: %" PRIxREG " S1: %" PRIxREG " S2: %" PRIxREG
|
||||
" S3: %" PRIxREG "\n",
|
||||
regs[REG_S0], regs[REG_S1], regs[REG_S2], regs[REG_S3]);
|
||||
_alert("S4: %" PRIxREG " S5: %" PRIxREG " S6: %" PRIxREG
|
||||
" S7: %" PRIxREG "\n",
|
||||
regs[REG_S4], regs[REG_S5], regs[REG_S6], regs[REG_S7]);
|
||||
_alert("S8: %" PRIxREG " S9: %" PRIxREG " S10: %" PRIxREG
|
||||
" S11: %" PRIxREG "\n",
|
||||
regs[REG_S8], regs[REG_S9], regs[REG_S10], regs[REG_S11]);
|
||||
#ifdef RISCV_SAVE_GP
|
||||
_alert("GP: %" PRIxREG " SP: %" PRIxREG " FP: %" PRIxREG
|
||||
" TP: %" PRIxREG " RA: %" PRIxREG "\n",
|
||||
regs[REG_GP], regs[REG_SP], regs[REG_FP], regs[REG_TP],
|
||||
regs[REG_RA]);
|
||||
#else
|
||||
_alert("SP: %" PRIxREG " FP: %" PRIxREG " TP: %" PRIxREG
|
||||
" RA: %" PRIxREG "\n",
|
||||
regs[REG_SP], regs[REG_FP], regs[REG_TP], regs[REG_RA]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_dump_task
|
||||
****************************************************************************/
|
||||
|
||||
static void riscv_dump_task(struct tcb_s *tcb, void *arg)
|
||||
{
|
||||
char args[64] = "";
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
uint32_t stack_filled = 0;
|
||||
uint32_t stack_used;
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CPULOAD
|
||||
struct cpuload_s cpuload;
|
||||
uint32_t fracpart;
|
||||
uint32_t intpart;
|
||||
uint32_t tmp;
|
||||
|
||||
clock_cpuload(tcb->pid, &cpuload);
|
||||
|
||||
if (cpuload.total > 0)
|
||||
{
|
||||
tmp = (1000 * cpuload.active) / cpuload.total;
|
||||
intpart = tmp / 10;
|
||||
fracpart = tmp - 10 * intpart;
|
||||
}
|
||||
else
|
||||
{
|
||||
intpart = 0;
|
||||
fracpart = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
stack_used = up_check_tcbstack(tcb);
|
||||
if (tcb->adj_stack_size > 0 && stack_used > 0)
|
||||
{
|
||||
/* Use fixed-point math with one decimal place */
|
||||
|
||||
stack_filled = 10 * 100 * stack_used / tcb->adj_stack_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISABLE_PTHREAD
|
||||
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD)
|
||||
{
|
||||
struct pthread_tcb_s *ptcb = (struct pthread_tcb_s *)tcb;
|
||||
|
||||
snprintf(args, sizeof(args), " %p", ptcb->arg);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
char **argv = tcb->group->tg_info->argv + 1;
|
||||
size_t npos = 0;
|
||||
|
||||
while (*argv != NULL && npos < sizeof(args))
|
||||
{
|
||||
npos += snprintf(args + npos, sizeof(args) - npos, " %s", *argv++);
|
||||
}
|
||||
}
|
||||
|
||||
/* Dump interesting properties of this task */
|
||||
|
||||
_alert(" %4d %4d"
|
||||
#ifdef CONFIG_SMP
|
||||
" %4d"
|
||||
#endif
|
||||
" %7lu"
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
" %7lu %3" PRId32 ".%1" PRId32 "%%%c"
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CPULOAD
|
||||
" %3" PRId32 ".%01" PRId32 "%%"
|
||||
#endif
|
||||
" %s%s\n"
|
||||
, tcb->pid, tcb->sched_priority
|
||||
#ifdef CONFIG_SMP
|
||||
, tcb->cpu
|
||||
#endif
|
||||
, (unsigned long)tcb->adj_stack_size
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
, (unsigned long)up_check_tcbstack(tcb)
|
||||
, stack_filled / 10, stack_filled % 10
|
||||
, (stack_filled >= 10 * 80 ? '!' : ' ')
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CPULOAD
|
||||
, intpart, fracpart
|
||||
#endif
|
||||
#if CONFIG_TASK_NAME_SIZE > 0
|
||||
, tcb->name
|
||||
#else
|
||||
, "<noname>"
|
||||
#endif
|
||||
, args
|
||||
);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_dump_backtrace
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SCHED_BACKTRACE
|
||||
static void riscv_dump_backtrace(struct tcb_s *tcb, void *arg)
|
||||
{
|
||||
/* Show back trace */
|
||||
|
||||
sched_dumpstack(tcb->pid);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_showtasks
|
||||
****************************************************************************/
|
||||
|
||||
static inline void riscv_showtasks(void)
|
||||
{
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||
# ifdef CONFIG_STACK_COLORATION
|
||||
uint32_t stack_used = up_check_intstack();
|
||||
uint32_t stack_filled = 0;
|
||||
|
||||
if ((CONFIG_ARCH_INTERRUPTSTACK & ~15) > 0 && stack_used > 0)
|
||||
{
|
||||
/* Use fixed-point math with one decimal place */
|
||||
|
||||
stack_filled = 10 * 100 *
|
||||
stack_used / (CONFIG_ARCH_INTERRUPTSTACK & ~15);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Dump interesting properties of each task in the crash environment */
|
||||
|
||||
_alert(" PID PRI"
|
||||
#ifdef CONFIG_SMP
|
||||
" CPU"
|
||||
#endif
|
||||
" STACK"
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
" USED FILLED "
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CPULOAD
|
||||
" CPU"
|
||||
#endif
|
||||
" COMMAND\n");
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||
_alert(" ---- ----"
|
||||
# ifdef CONFIG_SMP
|
||||
" ----"
|
||||
# endif
|
||||
" %7u"
|
||||
# ifdef CONFIG_STACK_COLORATION
|
||||
" %7" PRId32 " %3" PRId32 ".%1" PRId32 "%%%c"
|
||||
# endif
|
||||
# ifdef CONFIG_SCHED_CPULOAD
|
||||
" ----"
|
||||
# endif
|
||||
" irq\n"
|
||||
, (CONFIG_ARCH_INTERRUPTSTACK & ~15)
|
||||
# ifdef CONFIG_STACK_COLORATION
|
||||
, stack_used
|
||||
, stack_filled / 10, stack_filled % 10,
|
||||
(stack_filled >= 10 * 80 ? '!' : ' ')
|
||||
# endif
|
||||
);
|
||||
#endif
|
||||
|
||||
nxsched_foreach(riscv_dump_task, NULL);
|
||||
#ifdef CONFIG_SCHED_BACKTRACE
|
||||
nxsched_foreach(riscv_dump_backtrace, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_dump_stack
|
||||
****************************************************************************/
|
||||
|
||||
static void riscv_dump_stack(const char *tag, uintptr_t sp,
|
||||
uintptr_t base, uint32_t size, bool force)
|
||||
{
|
||||
uintptr_t top = base + size;
|
||||
|
||||
_alert("%s Stack:\n", tag);
|
||||
_alert("sp: %08" PRIxPTR "\n", sp);
|
||||
_alert(" base: %08" PRIxPTR "\n", base);
|
||||
_alert(" size: %08" PRIx32 "\n", size);
|
||||
|
||||
if (sp >= base && sp < top)
|
||||
{
|
||||
riscv_stackdump(sp, top);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: %s Stack pointer is not within the stack\n", tag);
|
||||
|
||||
if (force)
|
||||
{
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
uint32_t remain;
|
||||
|
||||
remain = size - riscv_stack_check((uintptr_t)base, size);
|
||||
base += remain;
|
||||
size -= remain;
|
||||
#endif
|
||||
|
||||
#if CONFIG_ARCH_STACKDUMP_MAX_LENGTH > 0
|
||||
if (size > CONFIG_ARCH_STACKDUMP_MAX_LENGTH)
|
||||
{
|
||||
size = CONFIG_ARCH_STACKDUMP_MAX_LENGTH;
|
||||
}
|
||||
#endif
|
||||
|
||||
riscv_stackdump(base, base + size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
static void riscv_dumpstate(void)
|
||||
void up_assert(void)
|
||||
{
|
||||
struct tcb_s *rtcb = running_task();
|
||||
uintptr_t sp = up_getsp();
|
||||
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
|
||||
/* Update the xcp context */
|
||||
|
||||
|
@ -352,64 +72,5 @@ static void riscv_dumpstate(void)
|
|||
rtcb->xcp.regs = (uintptr_t *)s_last_regs;
|
||||
}
|
||||
|
||||
/* Show back trace */
|
||||
|
||||
#ifdef CONFIG_SCHED_BACKTRACE
|
||||
sched_dumpstack(rtcb->pid);
|
||||
#endif
|
||||
|
||||
/* Dump the registers (if available) */
|
||||
|
||||
riscv_registerdump(rtcb->xcp.regs);
|
||||
|
||||
/* Get the limits on the interrupt stack memory */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||
riscv_dump_stack("IRQ", sp,
|
||||
(uintptr_t)g_intstackalloc,
|
||||
(CONFIG_ARCH_INTERRUPTSTACK & ~15),
|
||||
!!CURRENT_REGS);
|
||||
if (CURRENT_REGS)
|
||||
{
|
||||
sp = CURRENT_REGS[REG_SP];
|
||||
}
|
||||
#endif
|
||||
|
||||
riscv_dump_stack("User", sp,
|
||||
(uintptr_t)rtcb->stack_base_ptr,
|
||||
(uint32_t)rtcb->adj_stack_size,
|
||||
#ifdef CONFIG_ARCH_KERNEL_STACK
|
||||
false
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
);
|
||||
|
||||
#ifdef CONFIG_ARCH_KERNEL_STACK
|
||||
riscv_dump_stack("Kernel", sp,
|
||||
(uintptr_t)rtcb->xcp.kstack,
|
||||
CONFIG_ARCH_KERNEL_STACKSIZE,
|
||||
false);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
# define riscv_dumpstate()
|
||||
#endif /* CONFIG_ARCH_STACKDUMP */
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
void up_assert(const char *filename, int lineno)
|
||||
{
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
riscv_dumpstate();
|
||||
|
||||
/* Dump the state of all tasks (if available) */
|
||||
|
||||
riscv_showtasks();
|
||||
}
|
||||
|
|
44
arch/risc-v/src/common/riscv_getintstack.c
Normal file
44
arch/risc-v/src/common/riscv_getintstack.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/****************************************************************************
|
||||
* arch/risc-v/src/common/riscv_getintstack.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "riscv_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_intstackbase
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uintptr_t up_get_intstackbase(void)
|
||||
{
|
||||
return (uintptr_t)g_intstackalloc;
|
||||
}
|
||||
#endif
|
|
@ -277,6 +277,8 @@ size_t riscv_stack_check(uintptr_t alloc, size_t size);
|
|||
void riscv_stack_color(void *stackbase, size_t nbytes);
|
||||
#endif
|
||||
|
||||
void riscv_registerdump(volatile uintptr_t *regs);
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
void riscv_cpu_boot(int cpu);
|
||||
int riscv_pause_handler(int irq, void *c, void *arg);
|
||||
|
|
89
arch/risc-v/src/common/riscv_registerdump.c
Normal file
89
arch/risc-v/src/common/riscv_registerdump.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
/****************************************************************************
|
||||
* arch/risc-v/src/common/riscv_registerdump.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/irq.h>
|
||||
|
||||
#include "riscv_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
return CURRENT_REGS[REG_SP];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
void riscv_registerdump(volatile uintptr_t *regs)
|
||||
{
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
_alert("EPC: %" PRIxREG "\n", regs[REG_EPC]);
|
||||
_alert("A0: %" PRIxREG " A1: %" PRIxREG " A2: %" PRIxREG
|
||||
" A3: %" PRIxREG "\n",
|
||||
regs[REG_A0], regs[REG_A1], regs[REG_A2], regs[REG_A3]);
|
||||
_alert("A4: %" PRIxREG " A5: %" PRIxREG " A6: %" PRIxREG
|
||||
" A7: %" PRIxREG "\n",
|
||||
regs[REG_A4], regs[REG_A5], regs[REG_A6], regs[REG_A7]);
|
||||
_alert("T0: %" PRIxREG " T1: %" PRIxREG " T2: %" PRIxREG
|
||||
" T3: %" PRIxREG "\n",
|
||||
regs[REG_T0], regs[REG_T1], regs[REG_T2], regs[REG_T3]);
|
||||
_alert("T4: %" PRIxREG " T5: %" PRIxREG " T6: %" PRIxREG "\n",
|
||||
regs[REG_T4], regs[REG_T5], regs[REG_T6]);
|
||||
_alert("S0: %" PRIxREG " S1: %" PRIxREG " S2: %" PRIxREG
|
||||
" S3: %" PRIxREG "\n",
|
||||
regs[REG_S0], regs[REG_S1], regs[REG_S2], regs[REG_S3]);
|
||||
_alert("S4: %" PRIxREG " S5: %" PRIxREG " S6: %" PRIxREG
|
||||
" S7: %" PRIxREG "\n",
|
||||
regs[REG_S4], regs[REG_S5], regs[REG_S6], regs[REG_S7]);
|
||||
_alert("S8: %" PRIxREG " S9: %" PRIxREG " S10: %" PRIxREG
|
||||
" S11: %" PRIxREG "\n",
|
||||
regs[REG_S8], regs[REG_S9], regs[REG_S10], regs[REG_S11]);
|
||||
#ifdef RISCV_SAVE_GP
|
||||
_alert("GP: %" PRIxREG " SP: %" PRIxREG " FP: %" PRIxREG
|
||||
" TP: %" PRIxREG " RA: %" PRIxREG "\n",
|
||||
regs[REG_GP], regs[REG_SP], regs[REG_FP], regs[REG_TP],
|
||||
regs[REG_RA]);
|
||||
#else
|
||||
_alert("SP: %" PRIxREG " FP: %" PRIxREG " TP: %" PRIxREG
|
||||
" RA: %" PRIxREG "\n",
|
||||
regs[REG_SP], regs[REG_FP], regs[REG_TP], regs[REG_RA]);
|
||||
#endif
|
||||
}
|
||||
|
|
@ -52,45 +52,6 @@
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: riscv_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_SYSCALL_INFO
|
||||
static void riscv_registerdump(const uintptr_t *regs)
|
||||
{
|
||||
svcinfo("EPC: %" PRIxREG "\n",
|
||||
regs[REG_EPC]);
|
||||
svcinfo("A0: %" PRIxREG " A1: %" PRIxREG " A2: %" PRIxREG " A3: %" PRIxREG
|
||||
" A4: %" PRIxREG " A5: %" PRIxREG " A6: %" PRIxREG " A7: %" PRIxREG
|
||||
"\n",
|
||||
regs[REG_A0], regs[REG_A1], regs[REG_A2], regs[REG_A3],
|
||||
regs[REG_A4], regs[REG_A5], regs[REG_A6], regs[REG_A7]);
|
||||
svcinfo("T0: %" PRIxREG " T1: %" PRIxREG " T2: %" PRIxREG " T3: %" PRIxREG
|
||||
" T4: %" PRIxREG " T5: %" PRIxREG " T6: %" PRIxREG "\n",
|
||||
regs[REG_T0], regs[REG_T1], regs[REG_T2], regs[REG_T3],
|
||||
regs[REG_T4], regs[REG_T5], regs[REG_T6]);
|
||||
svcinfo("S0: %" PRIxREG " S1: %" PRIxREG " S2: %" PRIxREG " S3: %" PRIxREG
|
||||
" S4: %" PRIxREG " S5: %" PRIxREG " S6: %" PRIxREG " S7: %" PRIxREG
|
||||
"\n",
|
||||
regs[REG_S0], regs[REG_S1], regs[REG_S2], regs[REG_S3],
|
||||
regs[REG_S4], regs[REG_S5], regs[REG_S6], regs[REG_S7]);
|
||||
svcinfo("S8: %" PRIxREG " S9: %" PRIxREG " S10: %"PRIxREG
|
||||
" S11: %" PRIxREG "\n",
|
||||
regs[REG_S8], regs[REG_S9], regs[REG_S10], regs[REG_S11]);
|
||||
#ifdef RISCV_SAVE_GP
|
||||
svcinfo("GP: %" PRIxREG " SP: %" PRIxREG " FP: %" PRIxREG
|
||||
" TP: %" PRIxREG " RA: %" PRIxREG "\n",
|
||||
regs[REG_GP], regs[REG_SP], regs[REG_FP], regs[REG_TP],
|
||||
regs[REG_RA]);
|
||||
#else
|
||||
svcinfo("SP: %" PRIxREG " FP: %" PRIxREG " TP: %" PRIxREG " RA: %" PRIxREG
|
||||
"\n",
|
||||
regs[REG_SP], regs[REG_FP], regs[REG_TP], regs[REG_RA]);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dispatch_syscall
|
||||
*
|
||||
|
@ -552,7 +513,7 @@ int riscv_swint(int irq, void *context, void *arg)
|
|||
if (regs != CURRENT_REGS)
|
||||
{
|
||||
svcinfo("SWInt Return: Context switch!\n");
|
||||
riscv_registerdump((const uintptr_t *)CURRENT_REGS);
|
||||
riscv_registerdump(CURRENT_REGS);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -71,20 +71,10 @@
|
|||
*
|
||||
****************************************************************************/
|
||||
|
||||
void up_assert(const char *filename, int lineno)
|
||||
void up_assert(void)
|
||||
{
|
||||
struct tcb_s *rtcb = running_task();
|
||||
|
||||
/* Show back trace */
|
||||
|
||||
#ifdef CONFIG_SCHED_BACKTRACE
|
||||
sched_dumpstack(rtcb->pid);
|
||||
#endif
|
||||
|
||||
/* Flush any buffered SYSLOG data (from the above) */
|
||||
|
||||
syslog_flush();
|
||||
|
||||
if (CURRENT_REGS || is_idle_task(rtcb))
|
||||
{
|
||||
/* Exit the simulation */
|
||||
|
|
|
@ -24,7 +24,7 @@ CMN_CSRCS += sparc_allocateheap.c sparc_assert.c
|
|||
CMN_CSRCS += sparc_createstack.c sparc_exit.c sparc_idle.c sparc_initialize.c
|
||||
CMN_CSRCS += sparc_lowputs.c sparc_mdelay.c
|
||||
CMN_CSRCS += sparc_modifyreg8.c sparc_modifyreg16.c sparc_modifyreg32.c
|
||||
CMN_CSRCS += sparc_nputs.c sparc_releasestack.c
|
||||
CMN_CSRCS += sparc_nputs.c sparc_releasestack.c sparc_getintstack.c
|
||||
CMN_CSRCS += sparc_stackframe.c sparc_udelay.c sparc_usestack.c
|
||||
|
||||
# Configuration-dependent common files
|
||||
|
|
|
@ -34,7 +34,7 @@
|
|||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
void up_assert(const char *filename, int lineno)
|
||||
void up_assert(void)
|
||||
{
|
||||
sparc_dumpstate();
|
||||
sparc_registerdump(CURRENT_REGS);
|
||||
}
|
||||
|
|
44
arch/sparc/src/common/sparc_getintstack.c
Normal file
44
arch/sparc/src/common/sparc_getintstack.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/****************************************************************************
|
||||
* arch/sparc/src/common/sparc_getintstack.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sparc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_intstackbase
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uintptr_t up_get_intstackbase(void)
|
||||
{
|
||||
return (uintptr_t)sparc_intstack_alloc();
|
||||
}
|
||||
#endif
|
|
@ -185,11 +185,7 @@ void sparc_lowputs(const char *str);
|
|||
|
||||
/* Debug */
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
void sparc_dumpstate(void);
|
||||
#else
|
||||
# define sparc_dumpstate()
|
||||
#endif
|
||||
void sparc_registerdump(volatile uint32_t *regs);
|
||||
|
||||
/* Software interrupt 0 handler */
|
||||
|
||||
|
|
|
@ -27,10 +27,4 @@ CMN_CSRCS += sparc_v8_copystate.c sparc_v8_doirq.c
|
|||
CMN_CSRCS += sparc_v8_initialstate.c sparc_v8_irq.c
|
||||
CMN_CSRCS += sparc_v8_schedulesigaction.c
|
||||
CMN_CSRCS += sparc_v8_sigdeliver.c sparc_v8_swint1.c sparc_v8_systemreset.c
|
||||
CMN_CSRCS += sparc_v8_switchcontext.c
|
||||
|
||||
# Configuration-dependent common files
|
||||
|
||||
ifeq ($(CONFIG_ARCH_STACKDUMP),y)
|
||||
CMN_CSRCS += sparc_v8_dumpstate.c
|
||||
endif
|
||||
CMN_CSRCS += sparc_v8_switchcontext.c sparc_v8_registerdump.c
|
||||
|
|
|
@ -1,216 +0,0 @@
|
|||
/****************************************************************************
|
||||
* arch/sparc/src/sparc_v8/sparc_v8_dumpstate.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <arch/board/board.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "sparc_internal.h"
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_stackdump
|
||||
****************************************************************************/
|
||||
|
||||
static void up_stackdump(uint32_t sp, uint32_t stack_base)
|
||||
{
|
||||
uint32_t stack ;
|
||||
|
||||
for (stack = sp & ~0x1f; stack < stack_base; stack += 32)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)stack;
|
||||
_alert("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
static inline void up_registerdump(void)
|
||||
{
|
||||
uint32_t *regs = (uint32_t *)CURRENT_REGS; /* Don't need volatile here */
|
||||
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (regs)
|
||||
{
|
||||
_alert("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
0,
|
||||
regs[REG_R16], regs[REG_R17],
|
||||
regs[REG_R18], regs[REG_R19],
|
||||
regs[REG_R20], regs[REG_R21],
|
||||
regs[REG_R22], regs[REG_R23]);
|
||||
|
||||
_alert("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
8,
|
||||
regs[REG_R24], regs[REG_R25],
|
||||
regs[REG_R26], regs[REG_R27],
|
||||
regs[REG_R28], regs[REG_R29],
|
||||
regs[REG_R30], regs[REG_R31]);
|
||||
|
||||
_alert("SR: %08x\n", regs[REG_R14]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sparc_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
void sparc_dumpstate(void)
|
||||
{
|
||||
struct tcb_s *rtcb = running_task();
|
||||
uint32_t sp = up_getsp();
|
||||
uint32_t ustackbase;
|
||||
uint32_t ustacksize;
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uint32_t istackbase;
|
||||
uint32_t istacksize;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Show the CPU number */
|
||||
|
||||
_alert("CPU%d:\n", up_cpu_index());
|
||||
#endif
|
||||
|
||||
/* Dump the registers (if available) */
|
||||
|
||||
up_registerdump();
|
||||
|
||||
/* Get the limits on the user stack memory */
|
||||
|
||||
if (rtcb->pid == IDLE_PROCESS_ID) /* Check for CPU0 IDLE thread */
|
||||
{
|
||||
ustackbase = g_idle_topstack - 4;
|
||||
ustacksize = CONFIG_IDLETHREAD_STACKSIZE;
|
||||
}
|
||||
else
|
||||
{
|
||||
ustackbase = (uint32_t)rtcb->stack_base_ptr;
|
||||
ustacksize = (uint32_t)rtcb->adj_stack_size;
|
||||
}
|
||||
|
||||
/* Get the limits on the interrupt stack memory */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
istackbase = (uint32_t)sparc_intstack_alloc();
|
||||
istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3) - 4;
|
||||
|
||||
/* Show interrupt stack info */
|
||||
|
||||
_alert("sp: %08x\n", sp);
|
||||
_alert("IRQ stack:\n");
|
||||
_alert(" base: %08x\n", istackbase);
|
||||
_alert(" size: %08x\n", istacksize);
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
_alert(" used: %08x\n", up_check_intstack());
|
||||
#endif
|
||||
|
||||
/* Does the current stack pointer lie within the interrupt
|
||||
* stack?
|
||||
*/
|
||||
|
||||
if (sp <= istackbase && sp > istackbase - istacksize)
|
||||
{
|
||||
/* Yes.. dump the interrupt stack */
|
||||
|
||||
up_stackdump(sp, istackbase);
|
||||
}
|
||||
else if (CURRENT_REGS)
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within the interrupt stack\n");
|
||||
up_stackdump(istackbase - istacksize, istackbase);
|
||||
}
|
||||
|
||||
/* Extract the user stack pointer if we are in an interrupt handler.
|
||||
* If we are not in an interrupt handler. Then sp is the user stack
|
||||
* pointer (and the above range check should have failed).
|
||||
*/
|
||||
|
||||
if (CURRENT_REGS)
|
||||
{
|
||||
sp = CURRENT_REGS[REG_I6];
|
||||
_alert("sp: %08x\n", sp);
|
||||
}
|
||||
|
||||
_alert("User stack:\n");
|
||||
_alert(" base: %08x\n", ustackbase);
|
||||
_alert(" size: %08x\n", ustacksize);
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
_alert(" used: %08x\n", up_check_tcbstack(rtcb));
|
||||
#endif
|
||||
|
||||
/* Dump the user stack if the stack pointer lies within the allocated user
|
||||
* stack memory.
|
||||
*/
|
||||
|
||||
if (sp <= ustackbase && sp > ustackbase - ustacksize)
|
||||
{
|
||||
up_stackdump(sp, ustackbase);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within allocated stack\n");
|
||||
up_stackdump(ustackbase - ustacksize, ustackbase);
|
||||
}
|
||||
#else
|
||||
_alert("sp: %08x\n", sp);
|
||||
_alert("stack base: %08x\n", ustackbase);
|
||||
_alert("stack size: %08x\n", ustacksize);
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
_alert("stack used: %08x\n", up_check_tcbstack(rtcb));
|
||||
#endif
|
||||
|
||||
/* Dump the user stack if the stack pointer lies within the allocated user
|
||||
* stack memory.
|
||||
*/
|
||||
|
||||
if (sp > ustackbase || sp <= ustackbase - ustacksize)
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within allocated stack\n");
|
||||
up_stackdump(ustackbase - ustacksize, ustackbase);
|
||||
}
|
||||
else
|
||||
{
|
||||
up_stackdump(sp, ustackbase);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
75
arch/sparc/src/sparc_v8/sparc_v8_registerdump.c
Normal file
75
arch/sparc/src/sparc_v8/sparc_v8_registerdump.c
Normal file
|
@ -0,0 +1,75 @@
|
|||
/****************************************************************************
|
||||
* arch/sparc/src/sparc_v8/sparc_v8_registerdump.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/arch.h>
|
||||
|
||||
#include "sparc_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
return CURRENT_REGS[REG_I6];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sparc_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
void sparc_registerdump(volatile uint32_t *regs)
|
||||
{
|
||||
/* Are user registers available from interrupt processing? */
|
||||
|
||||
if (regs)
|
||||
{
|
||||
_alert("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
0,
|
||||
regs[REG_R16], regs[REG_R17],
|
||||
regs[REG_R18], regs[REG_R19],
|
||||
regs[REG_R20], regs[REG_R21],
|
||||
regs[REG_R22], regs[REG_R23]);
|
||||
|
||||
_alert("R%d: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
8,
|
||||
regs[REG_R24], regs[REG_R25],
|
||||
regs[REG_R26], regs[REG_R27],
|
||||
regs[REG_R28], regs[REG_R29],
|
||||
regs[REG_R30], regs[REG_R31]);
|
||||
|
||||
_alert("SR: %08x\n", regs[REG_R14]);
|
||||
}
|
||||
}
|
|
@ -40,18 +40,6 @@
|
|||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_DEBUG_SYSCALL_INFO
|
||||
static void up_registerdump(const uint32_t *regs)
|
||||
{
|
||||
}
|
||||
#else
|
||||
# define up_registerdump(regs)
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: dispatch_syscall
|
||||
*
|
||||
|
@ -229,7 +217,7 @@ int sparc_swint1(int irq, void *context, void *arg)
|
|||
if (regs != CURRENT_REGS)
|
||||
{
|
||||
svcinfo("SWInt Return: Context switch!\n");
|
||||
up_registerdump((const uint32_t *)CURRENT_REGS);
|
||||
up_registerdump(CURRENT_REGS);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -40,50 +40,19 @@
|
|||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static uint32_t s_last_regs[XCPTCONTEXT_REGS];
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: x86_stackdump
|
||||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static void x86_stackdump(uint32_t sp, uint32_t stack_top)
|
||||
void up_assert(void)
|
||||
{
|
||||
uint32_t stack;
|
||||
|
||||
for (stack = sp & ~0x1f; stack < (stack_top & ~0x1f); stack += 32)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)stack;
|
||||
_alert("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: x86_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static void x86_dumpstate(void)
|
||||
{
|
||||
struct tcb_s *rtcb = running_task();
|
||||
uint32_t sp = up_getsp();
|
||||
uint32_t ustackbase;
|
||||
uint32_t ustacksize;
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uint32_t istackbase;
|
||||
uint32_t istacksize;
|
||||
#endif
|
||||
|
||||
/* Dump the registers (if available) */
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
|
||||
if (g_current_regs != NULL)
|
||||
{
|
||||
|
@ -96,87 +65,4 @@ static void x86_dumpstate(void)
|
|||
up_saveusercontext(s_last_regs);
|
||||
x86_registerdump(s_last_regs);
|
||||
}
|
||||
|
||||
/* Get the limits on the user stack memory */
|
||||
|
||||
ustackbase = (uint32_t)rtcb->stack_base_ptr;
|
||||
ustacksize = (uint32_t)rtcb->adj_stack_size;
|
||||
|
||||
/* Get the limits on the interrupt stack memory */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
istackbase = (uint32_t)g_intstackalloc;
|
||||
istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3);
|
||||
|
||||
/* Show interrupt stack info */
|
||||
|
||||
_alert("sp: %08x\n", sp);
|
||||
_alert("IRQ stack:\n");
|
||||
_alert(" base: %08x\n", istackbase);
|
||||
_alert(" size: %08x\n", istacksize);
|
||||
|
||||
/* Does the current stack pointer lie within the interrupt
|
||||
* stack?
|
||||
*/
|
||||
|
||||
if (sp >= istackbase && sp < istackbase + istacksize)
|
||||
{
|
||||
/* Yes.. dump the interrupt stack */
|
||||
|
||||
x86_stackdump(sp, istackbase + istacksize);
|
||||
|
||||
/* Extract the user stack pointer which should lie
|
||||
* at the base of the interrupt stack.
|
||||
*/
|
||||
|
||||
sp = g_intstacktop;
|
||||
_alert("sp: %08x\n", sp);
|
||||
}
|
||||
else if (g_current_regs)
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within the interrupt stack\n");
|
||||
x86_stackdump(istackbase, istackbase + istacksize);
|
||||
}
|
||||
|
||||
/* Show user stack info */
|
||||
|
||||
_alert("User stack:\n");
|
||||
_alert(" base: %08x\n", ustackbase);
|
||||
_alert(" size: %08x\n", ustacksize);
|
||||
#else
|
||||
_alert("sp: %08x\n", sp);
|
||||
_alert("stack base: %08x\n", ustackbase);
|
||||
_alert("stack size: %08x\n", ustacksize);
|
||||
#endif
|
||||
|
||||
/* Dump the user stack if the stack pointer lies within the allocated user
|
||||
* stack memory.
|
||||
*/
|
||||
|
||||
if (sp >= ustackbase && sp < ustackbase + ustacksize)
|
||||
{
|
||||
x86_stackdump(sp, ustackbase + ustacksize);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within allocated stack\n");
|
||||
x86_stackdump(ustackbase, ustackbase + ustacksize);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define x86_dumpstate()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
void up_assert(const char *filename, int lineno)
|
||||
{
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
x86_dumpstate();
|
||||
}
|
||||
|
|
44
arch/x86/src/common/x86_getintstack.c
Normal file
44
arch/x86/src/common/x86_getintstack.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/****************************************************************************
|
||||
* arch/x86/src/common/x86_getintstack.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "x86_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_intstackbase
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uintptr_t up_get_intstackbase(void)
|
||||
{
|
||||
return (uintptr_t)g_intstackalloc;
|
||||
}
|
||||
#endif
|
|
@ -33,6 +33,15 @@
|
|||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
return g_current_regs[REG_ESP];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: x86_registerdump
|
||||
****************************************************************************/
|
||||
|
|
|
@ -30,7 +30,7 @@ CMN_CSRCS += i486_createstack.c i486_initialstate.c
|
|||
CMN_CSRCS += x86_allocateheap.c x86_assert.c x86_copystate.c
|
||||
CMN_CSRCS += x86_exit.c x86_initialize.c x86_mdelay.c x86_udelay.c
|
||||
CMN_CSRCS += x86_modifyreg8.c x86_modifyreg16.c x86_modifyreg32.c
|
||||
CMN_CSRCS += x86_nputs.c x86_switchcontext.c
|
||||
CMN_CSRCS += x86_nputs.c x86_switchcontext.c x86_getintstack.c
|
||||
CMN_CSRCS += i486_irq.c i486_regdump.c i486_releasestack.c
|
||||
CMN_CSRCS += i486_savestate.c i486_sigdeliver.c
|
||||
CMN_CSRCS += i486_schedulesigaction.c i486_stackframe.c
|
||||
|
|
|
@ -35,124 +35,6 @@
|
|||
#include "sched/sched.h"
|
||||
#include "x86_64_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: x86_64_stackdump
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static void x86_64_stackdump(uint64_t sp, uint64_t stack_top)
|
||||
{
|
||||
uint64_t stack;
|
||||
|
||||
for (stack = sp & ~0x1f; stack < (stack_top & ~0x1f); stack += 32)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)stack;
|
||||
_alert("%016" PRIx64 ": %08" PRIx32 " %08" PRIx32 " %08" PRIx32
|
||||
" %08" PRIx32 " %08" PRIx32 " %08" PRIx32 " %08" PRIx32
|
||||
" %08" PRIx32 "\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: x86_64_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
static void x86_64_dumpstate(void)
|
||||
{
|
||||
struct tcb_s *rtcb = running_task();
|
||||
uint64_t sp = up_getsp();
|
||||
uint64_t ustackbase;
|
||||
uint64_t ustacksize;
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uint64_t istackbase;
|
||||
uint64_t istacksize;
|
||||
#endif
|
||||
|
||||
/* Get the limits on the user stack memory */
|
||||
|
||||
ustackbase = (uint64_t)rtcb->stack_base_ptr;
|
||||
ustacksize = (uint64_t)rtcb->adj_stack_size;
|
||||
|
||||
/* Get the limits on the interrupt stack memory */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
istackbase = (uint64_t)g_intstackalloc;
|
||||
istacksize = (CONFIG_ARCH_INTERRUPTSTACK & ~3);
|
||||
|
||||
/* Show interrupt stack info */
|
||||
|
||||
_alert("sp: %016" PRIx64 "\n", sp);
|
||||
_alert("IRQ stack:\n");
|
||||
_alert(" base: %016" PRIx64 "\n", istackbase);
|
||||
_alert(" size: %016" PRIx64 "\n", istacksize);
|
||||
|
||||
/* Does the current stack pointer lie within the interrupt
|
||||
* stack?
|
||||
*/
|
||||
|
||||
if (sp >= istackbase && sp < istackbase + istacksize)
|
||||
{
|
||||
/* Yes.. dump the interrupt stack */
|
||||
|
||||
x86_64_stackdump(sp, istackbase + istacksize);
|
||||
|
||||
/* Extract the user stack pointer which should lie
|
||||
* at the base of the interrupt stack.
|
||||
*/
|
||||
|
||||
sp = g_intstacktop;
|
||||
_alert("sp: %016" PRIx64 "\n", sp);
|
||||
}
|
||||
else if (g_current_regs)
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within the interrupt stack\n");
|
||||
x86_64_stackdump(istackbase, istackbase + istacksize);
|
||||
}
|
||||
|
||||
/* Show user stack info */
|
||||
|
||||
_alert("User stack:\n");
|
||||
_alert(" base: %016" PRIx64 "\n", ustackbase);
|
||||
_alert(" size: %016" PRIx64 "\n", ustacksize);
|
||||
#else
|
||||
_alert("sp: %016" PRIx64 "\n", sp);
|
||||
_alert("stack base: %016" PRIx64 "\n", ustackbase);
|
||||
_alert("stack size: %016" PRIx64 "\n", ustacksize);
|
||||
#endif
|
||||
|
||||
/* Dump the user stack if the stack pointer lies within the allocated user
|
||||
* stack memory.
|
||||
*/
|
||||
|
||||
if (sp >= ustackbase && sp < ustackbase + ustacksize)
|
||||
{
|
||||
x86_64_stackdump(sp, ustackbase + ustacksize);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: Stack pointer is not within allocated stack\n");
|
||||
x86_64_stackdump(ustackbase, ustackbase + ustacksize);
|
||||
}
|
||||
|
||||
/* Then dump the registers (if available) */
|
||||
|
||||
if (g_current_regs != NULL)
|
||||
{
|
||||
x86_64_registerdump((uint64_t *)g_current_regs);
|
||||
}
|
||||
}
|
||||
#else
|
||||
# define x86_64_dumpstate()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
@ -161,8 +43,12 @@ static void x86_64_dumpstate(void)
|
|||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
void up_assert(const char *filename, int lineno)
|
||||
void up_assert(void)
|
||||
{
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
x86_64_dumpstate();
|
||||
|
||||
if (g_current_regs != NULL)
|
||||
{
|
||||
x86_64_registerdump((uint64_t *)g_current_regs);
|
||||
}
|
||||
}
|
||||
|
|
44
arch/x86_64/src/common/x86_64_getintstack.c
Normal file
44
arch/x86_64/src/common/x86_64_getintstack.c
Normal file
|
@ -0,0 +1,44 @@
|
|||
/****************************************************************************
|
||||
* arch/x86_64/src/common/x86_64_getintstack.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "x86_64_internal.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_get_intstackbase
|
||||
****************************************************************************/
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 3
|
||||
uintptr_t up_get_intstackbase(void)
|
||||
{
|
||||
return (uintptr_t)g_intstackalloc;
|
||||
}
|
||||
#endif
|
|
@ -23,7 +23,7 @@
|
|||
CMN_CSRCS += x86_64_allocateheap.c x86_64_assert.c x86_64_copystate.c
|
||||
CMN_CSRCS += x86_64_mdelay.c x86_64_udelay.c x86_64_exit.c x86_64_initialize.c
|
||||
CMN_CSRCS += x86_64_modifyreg8.c x86_64_modifyreg16.c x86_64_modifyreg32.c x86_64_nputs.c
|
||||
CMN_CSRCS += x86_64_switchcontext.c
|
||||
CMN_CSRCS += x86_64_switchcontext.c x86_64_getintstack.c
|
||||
CMN_CSRCS += intel64_restore_auxstate.c intel64_createstack.c intel64_initialstate.c
|
||||
CMN_CSRCS += intel64_regdump.c intel64_releasestack.c intel64_map_region.c
|
||||
CMN_CSRCS += intel64_savestate.c intel64_sigdeliver.c
|
||||
|
|
|
@ -34,6 +34,15 @@
|
|||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: up_getusrsp
|
||||
****************************************************************************/
|
||||
|
||||
uintptr_t up_getusrsp(void)
|
||||
{
|
||||
return g_current_regs[REG_RSP];
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: x86_64_registerdump
|
||||
****************************************************************************/
|
||||
|
|
|
@ -36,7 +36,7 @@ CMN_CSRCS += xtensa_nputs.c xtensa_releasestack.c
|
|||
CMN_CSRCS += xtensa_schedsigaction.c
|
||||
CMN_CSRCS += xtensa_sigdeliver.c xtensa_stackframe.c xtensa_udelay.c
|
||||
CMN_CSRCS += xtensa_switchcontext.c xtensa_usestack.c xtensa_swint.c
|
||||
CMN_CSRCS += xtensa_saveusercontext.c
|
||||
CMN_CSRCS += xtensa_saveusercontext.c xtensa_getintstack.c xtensa_registerdump.c
|
||||
|
||||
# Configuration-dependent common Xtensa files
|
||||
|
||||
|
@ -44,10 +44,6 @@ ifeq ($(CONFIG_DEBUG_TCBINFO),y)
|
|||
CMN_CSRCS += xtensa_tcbinfo.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_DEBUG_ALERT),y)
|
||||
CMN_CSRCS += xtensa_dumpstate.c
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_ARCH_FPU),y)
|
||||
CMN_CSRCS += xtensa_fpucmp.c
|
||||
endif
|
||||
|
|
|
@ -216,11 +216,7 @@ void xtensa_lowputs(const char *str);
|
|||
|
||||
/* Debug */
|
||||
|
||||
#ifdef CONFIG_ARCH_STACKDUMP
|
||||
void xtensa_dumpstate(void);
|
||||
#else
|
||||
# define xtensa_dumpstate()
|
||||
#endif
|
||||
void xtensa_registerdump(uintptr_t *regs);
|
||||
|
||||
/* Common XTENSA functions */
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <debug.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/board.h>
|
||||
|
@ -37,19 +38,10 @@
|
|||
#include "xtensa.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xtensa_assert
|
||||
****************************************************************************/
|
||||
|
||||
static void xtensa_assert(void)
|
||||
{
|
||||
/* Dump the processor state */
|
||||
|
||||
xtensa_dumpstate();
|
||||
}
|
||||
static uint8_t s_last_regs[XCPTCONTEXT_SIZE];
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
|
@ -59,10 +51,27 @@ static void xtensa_assert(void)
|
|||
* Name: up_assert
|
||||
****************************************************************************/
|
||||
|
||||
void up_assert(const char *filename, int lineno)
|
||||
void up_assert(void)
|
||||
{
|
||||
struct tcb_s *rtcb = running_task();
|
||||
|
||||
board_autoled_on(LED_ASSERTION);
|
||||
xtensa_assert();
|
||||
|
||||
/* Update the xcp context */
|
||||
|
||||
if (CURRENT_REGS)
|
||||
{
|
||||
rtcb->xcp.regs = (uint32_t *)CURRENT_REGS;
|
||||
}
|
||||
else
|
||||
{
|
||||
up_saveusercontext(s_last_regs);
|
||||
rtcb->xcp.regs = (uint32_t *)s_last_regs;
|
||||
}
|
||||
|
||||
/* Dump the registers (if available) */
|
||||
|
||||
xtensa_registerdump(rtcb->xcp.regs);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -105,7 +114,7 @@ void xtensa_panic(int xptcode, uint32_t *regs)
|
|||
_alert("Unhandled Exception %d\n", xptcode);
|
||||
#endif
|
||||
|
||||
xtensa_assert(); /* Should not return */
|
||||
PANIC(); /* Should not return */
|
||||
for (; ; );
|
||||
}
|
||||
|
||||
|
@ -208,6 +217,6 @@ void xtensa_user_panic(int exccause, uint32_t *regs)
|
|||
_alert("User Exception: EXCCAUSE=%04x\n", exccause);
|
||||
#endif
|
||||
|
||||
xtensa_assert(); /* Should not return */
|
||||
PANIC(); /* Should not return */
|
||||
for (; ; );
|
||||
}
|
||||
|
|
|
@ -180,11 +180,7 @@ ssize_t up_check_stack_remain(void)
|
|||
#if CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||
size_t up_check_intstack(void)
|
||||
{
|
||||
#ifdef CONFIG_SMP
|
||||
return xtensa_stack_check(xtensa_intstack_alloc(), INTSTACK_SIZE);
|
||||
#else
|
||||
return xtensa_stack_check((uintptr_t)g_intstackalloc, INTSTACK_SIZE);
|
||||
#endif
|
||||
return xtensa_stack_check(up_get_intstackbase(), INTSTACK_SIZE);
|
||||
}
|
||||
|
||||
size_t up_check_intstack_remain(void)
|
||||
|
|
|
@ -1,397 +0,0 @@
|
|||
/****************************************************************************
|
||||
* arch/xtensa/src/common/xtensa_dumpstate.c
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you 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.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include <nuttx/irq.h>
|
||||
#include <nuttx/tls.h>
|
||||
#include <nuttx/arch.h>
|
||||
#include <nuttx/syslog/syslog.h>
|
||||
|
||||
#include <arch/xtensa/xtensa_corebits.h>
|
||||
#include <arch/board/board.h>
|
||||
#include <arch/chip/core-isa.h>
|
||||
|
||||
#include "sched/sched.h"
|
||||
#include "xtensa.h"
|
||||
|
||||
#ifdef CONFIG_DEBUG_ALERT
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static uint8_t s_last_regs[XCPTCONTEXT_SIZE];
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xtensa_dump_task
|
||||
****************************************************************************/
|
||||
|
||||
static void xtensa_dump_task(struct tcb_s *tcb, void *arg)
|
||||
{
|
||||
char args[64] = "";
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
uint32_t stack_filled = 0;
|
||||
uint32_t stack_used;
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CPULOAD
|
||||
struct cpuload_s cpuload;
|
||||
uint32_t fracpart;
|
||||
uint32_t intpart;
|
||||
uint32_t tmp;
|
||||
|
||||
clock_cpuload(tcb->pid, &cpuload);
|
||||
|
||||
if (cpuload.total > 0)
|
||||
{
|
||||
tmp = (1000 * cpuload.active) / cpuload.total;
|
||||
intpart = tmp / 10;
|
||||
fracpart = tmp - 10 * intpart;
|
||||
}
|
||||
else
|
||||
{
|
||||
intpart = 0;
|
||||
fracpart = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
stack_used = up_check_tcbstack(tcb);
|
||||
if (tcb->adj_stack_size > 0 && stack_used > 0)
|
||||
{
|
||||
/* Use fixed-point math with one decimal place */
|
||||
|
||||
stack_filled = 10 * 100 * stack_used / tcb->adj_stack_size;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISABLE_PTHREAD
|
||||
if ((tcb->flags & TCB_FLAG_TTYPE_MASK) == TCB_FLAG_TTYPE_PTHREAD)
|
||||
{
|
||||
struct pthread_tcb_s *ptcb = (struct pthread_tcb_s *)tcb;
|
||||
|
||||
snprintf(args, sizeof(args), " %p", ptcb->arg);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
char **argv = tcb->group->tg_info->argv + 1;
|
||||
size_t npos = 0;
|
||||
|
||||
while (*argv != NULL && npos < sizeof(args))
|
||||
{
|
||||
npos += snprintf(args + npos, sizeof(args) - npos, " %s", *argv++);
|
||||
}
|
||||
}
|
||||
|
||||
/* Dump interesting properties of this task */
|
||||
|
||||
_alert(" %4d %4d"
|
||||
#ifdef CONFIG_SMP
|
||||
" %4d"
|
||||
#endif
|
||||
" %7lu"
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
" %7lu %3" PRId32 ".%1" PRId32 "%%%c"
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CPULOAD
|
||||
" %3" PRId32 ".%01" PRId32 "%%"
|
||||
#endif
|
||||
" %s%s\n"
|
||||
, tcb->pid, tcb->sched_priority
|
||||
#ifdef CONFIG_SMP
|
||||
, tcb->cpu
|
||||
#endif
|
||||
, (unsigned long)tcb->adj_stack_size
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
, (unsigned long)up_check_tcbstack(tcb)
|
||||
, stack_filled / 10, stack_filled % 10
|
||||
, (stack_filled >= 10 * 80 ? '!' : ' ')
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CPULOAD
|
||||
, intpart, fracpart
|
||||
#endif
|
||||
#if CONFIG_TASK_NAME_SIZE > 0
|
||||
, tcb->name
|
||||
#else
|
||||
, "<noname>"
|
||||
#endif
|
||||
, args
|
||||
);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xtensa_dump_backtrace
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef CONFIG_SCHED_BACKTRACE
|
||||
static void xtensa_dump_backtrace(struct tcb_s *tcb, void *arg)
|
||||
{
|
||||
/* Show back trace */
|
||||
|
||||
sched_dumpstack(tcb->pid);
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xtensa_showtasks
|
||||
****************************************************************************/
|
||||
|
||||
static inline void xtensa_showtasks(void)
|
||||
{
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||
# ifdef CONFIG_STACK_COLORATION
|
||||
uint32_t stack_used = up_check_intstack();
|
||||
uint32_t stack_filled = 0;
|
||||
|
||||
if ((CONFIG_ARCH_INTERRUPTSTACK & ~15) > 0 && stack_used > 0)
|
||||
{
|
||||
/* Use fixed-point math with one decimal place */
|
||||
|
||||
stack_filled = 10 * 100 *
|
||||
stack_used / (CONFIG_ARCH_INTERRUPTSTACK & ~15);
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Dump interesting properties of each task in the crash environment */
|
||||
|
||||
_alert(" PID PRI"
|
||||
#ifdef CONFIG_SMP
|
||||
" CPU"
|
||||
#endif
|
||||
" STACK"
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
" USED FILLED "
|
||||
#endif
|
||||
#ifdef CONFIG_SCHED_CPULOAD
|
||||
" CPU"
|
||||
#endif
|
||||
" COMMAND\n");
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||
_alert(" ---- ----"
|
||||
# ifdef CONFIG_SMP
|
||||
" ----"
|
||||
# endif
|
||||
" %7u"
|
||||
# ifdef CONFIG_STACK_COLORATION
|
||||
" %7" PRId32 " %3" PRId32 ".%1" PRId32 "%%%c"
|
||||
# endif
|
||||
# ifdef CONFIG_SCHED_CPULOAD
|
||||
" ----"
|
||||
# endif
|
||||
" irq\n"
|
||||
, (CONFIG_ARCH_INTERRUPTSTACK & ~15)
|
||||
# ifdef CONFIG_STACK_COLORATION
|
||||
, stack_used
|
||||
, stack_filled / 10, stack_filled % 10,
|
||||
(stack_filled >= 10 * 80 ? '!' : ' ')
|
||||
# endif
|
||||
);
|
||||
#endif
|
||||
|
||||
nxsched_foreach(xtensa_dump_task, NULL);
|
||||
#ifdef CONFIG_SCHED_BACKTRACE
|
||||
nxsched_foreach(xtensa_dump_backtrace, NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xtensa_stackdump
|
||||
****************************************************************************/
|
||||
|
||||
static void xtensa_stackdump(uint32_t sp, uint32_t stack_top)
|
||||
{
|
||||
uint32_t stack;
|
||||
|
||||
/* Flush any buffered SYSLOG data to avoid overwrite */
|
||||
|
||||
syslog_flush();
|
||||
|
||||
for (stack = sp & ~0x1f; stack < (stack_top & ~0x1f); stack += 32)
|
||||
{
|
||||
uint32_t *ptr = (uint32_t *)stack;
|
||||
_alert("%08x: %08x %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
stack, ptr[0], ptr[1], ptr[2], ptr[3],
|
||||
ptr[4], ptr[5], ptr[6], ptr[7]);
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xtensa_registerdump
|
||||
****************************************************************************/
|
||||
|
||||
static inline void xtensa_registerdump(uintptr_t *regs)
|
||||
{
|
||||
_alert(" PC: %08lx PS: %08lx\n",
|
||||
(unsigned long)regs[REG_PC], (unsigned long)regs[REG_PS]);
|
||||
_alert(" A0: %08lx A1: %08lx A2: %08lx A3: %08lx\n",
|
||||
(unsigned long)regs[REG_A0], (unsigned long)regs[REG_A1],
|
||||
(unsigned long)regs[REG_A2], (unsigned long)regs[REG_A3]);
|
||||
_alert(" A4: %08lx A5: %08lx A6: %08lx A7: %08lx\n",
|
||||
(unsigned long)regs[REG_A4], (unsigned long)regs[REG_A5],
|
||||
(unsigned long)regs[REG_A6], (unsigned long)regs[REG_A7]);
|
||||
_alert(" A8: %08lx A9: %08lx A10: %08lx A11: %08lx\n",
|
||||
(unsigned long)regs[REG_A8], (unsigned long)regs[REG_A9],
|
||||
(unsigned long)regs[REG_A10], (unsigned long)regs[REG_A11]);
|
||||
_alert(" A12: %08lx A13: %08lx A14: %08lx A15: %08lx\n",
|
||||
(unsigned long)regs[REG_A12], (unsigned long)regs[REG_A13],
|
||||
(unsigned long)regs[REG_A14], (unsigned long)regs[REG_A15]);
|
||||
_alert(" SAR: %08lx CAUSE: %08lx VADDR: %08lx\n",
|
||||
(unsigned long)regs[REG_SAR], (unsigned long)regs[REG_EXCCAUSE],
|
||||
(unsigned long)regs[REG_EXCVADDR]);
|
||||
#if XCHAL_HAVE_LOOPS != 0
|
||||
_alert(" LBEG: %08lx LEND: %08lx LCNT: %08lx\n",
|
||||
(unsigned long)regs[REG_LBEG], (unsigned long)regs[REG_LEND],
|
||||
(unsigned long)regs[REG_LCOUNT]);
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xtensa_dump_stack
|
||||
****************************************************************************/
|
||||
|
||||
static void xtensa_dump_stack(const char *tag, uint32_t sp,
|
||||
uint32_t base, uint32_t size, bool force)
|
||||
{
|
||||
uint32_t top = base + size;
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
uint32_t used = xtensa_stack_check((uintptr_t)base, size);
|
||||
#endif
|
||||
|
||||
_alert("%s Stack:\n", tag);
|
||||
_alert("sp: %08" PRIx32 "\n", sp);
|
||||
_alert(" base: %08" PRIx32 "\n", base);
|
||||
_alert(" size: %08" PRIx32 "\n", size);
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
_alert(" used: %08" PRIx32 "\n", used);
|
||||
#endif
|
||||
|
||||
if (sp >= base && sp < top)
|
||||
{
|
||||
xtensa_stackdump(sp, top);
|
||||
}
|
||||
else
|
||||
{
|
||||
_alert("ERROR: %s Stack pointer is not within the stack\n", tag);
|
||||
|
||||
if (force)
|
||||
{
|
||||
#ifdef CONFIG_STACK_COLORATION
|
||||
base += size - used;
|
||||
size = used;
|
||||
#endif
|
||||
|
||||
#if CONFIG_ARCH_STACKDUMP_MAX_LENGTH > 0
|
||||
if (size > CONFIG_ARCH_STACKDUMP_MAX_LENGTH)
|
||||
{
|
||||
size = CONFIG_ARCH_STACKDUMP_MAX_LENGTH;
|
||||
}
|
||||
#endif
|
||||
|
||||
xtensa_stackdump(base, base + size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: xtensa_dumpstate
|
||||
****************************************************************************/
|
||||
|
||||
void xtensa_dumpstate(void)
|
||||
{
|
||||
struct tcb_s *rtcb = running_task();
|
||||
uint32_t sp = up_getsp();
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
/* Show the CPU number */
|
||||
|
||||
_alert("CPU%d:\n", up_cpu_index());
|
||||
#endif
|
||||
|
||||
/* Update the xcp context */
|
||||
|
||||
if (CURRENT_REGS)
|
||||
{
|
||||
rtcb->xcp.regs = (uint32_t *)CURRENT_REGS;
|
||||
}
|
||||
else
|
||||
{
|
||||
up_saveusercontext(s_last_regs);
|
||||
rtcb->xcp.regs = (uint32_t *)s_last_regs;
|
||||
}
|
||||
|
||||
/* Dump the registers (if available) */
|
||||
|
||||
xtensa_registerdump(rtcb->xcp.regs);
|
||||
|
||||
/* Dump the backtrace */
|
||||
|
||||
#if defined(CONFIG_XTENSA_DUMPBT_ON_ASSERT) && \
|
||||
defined(CONFIG_SCHED_BACKTRACE)
|
||||
sched_dumpstack(rtcb->pid);
|
||||
#endif
|
||||
|
||||
/* Dump the irq stack */
|
||||
|
||||
#if CONFIG_ARCH_INTERRUPTSTACK > 15
|
||||
xtensa_dump_stack("IRQ", sp,
|
||||
# ifdef CONFIG_SMP
|
||||
(uint32_t)xtensa_intstack_alloc(),
|
||||
# else
|
||||
(uint32_t)g_intstackalloc,
|
||||
# endif
|
||||
INTSTACK_SIZE,
|
||||
!!CURRENT_REGS);
|
||||
|
||||
if (CURRENT_REGS)
|
||||
{
|
||||
sp = CURRENT_REGS[REG_A1];
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Dump the user stack */
|
||||
|
||||
xtensa_dump_stack("User", sp,
|
||||
(uint32_t)rtcb->stack_base_ptr,
|
||||
(uint32_t)rtcb->adj_stack_size,
|
||||
true);
|
||||
|
||||
/* Dump the state of all tasks (if available) */
|
||||
|
||||
xtensa_showtasks();
|
||||
}
|
||||
|
||||
#endif /* CONFIG_DEBUG_ALERT */
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue