forked from len0rd/rockbox
M-profile cores manage interrupts differently from classic cores and lack the FIQ. Split the interrupt management parts out into separate headers but keep the endian swapping routines (which are not profile-dependent) in the common system-arm header. The initial part of the vector table is common to all Cortex-M CPUs and is intended to be included by the target linker script, with the vendor-specific part of the vector table appended to it. Change-Id: Ib2ad5b9dc41db27940e39033cfef4308923db66d
148 lines
3.7 KiB
C
148 lines
3.7 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright (C) 2002 by wavey@wavey.org
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
|
* KIND, either express or implied.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "config.h"
|
|
#include <stdio.h>
|
|
#include <stdarg.h>
|
|
#include <string.h>
|
|
#include "panic.h"
|
|
#include "lcd.h"
|
|
#include "font.h"
|
|
#include "debug.h"
|
|
#include "led.h"
|
|
#include "power.h"
|
|
#include "system.h"
|
|
#include "logf.h"
|
|
#include "rbversion.h"
|
|
|
|
#ifdef HAVE_RB_BACKTRACE
|
|
#include "gcc_extensions.h"
|
|
#include "backtrace.h"
|
|
#endif
|
|
|
|
#if (defined(CPU_MIPS) && (CONFIG_PLATFORM & PLATFORM_NATIVE))
|
|
/* TODO: see comment above exception_dump in system-mips.c */
|
|
char panic_buf[128];
|
|
#else
|
|
static char panic_buf[128];
|
|
#endif
|
|
|
|
#define LINECHARS (LCD_WIDTH/SYSFONT_WIDTH) - 2
|
|
|
|
#if defined(CPU_ARM) && defined(HAVE_RB_BACKTRACE)
|
|
void panicf_f( const char *fmt, ...) USED_ATTR;
|
|
|
|
/* we wrap panicf() here with naked function to catch SP value */
|
|
void __attribute__((naked)) panicf( const char *fmt, ...)
|
|
{
|
|
(void)fmt;
|
|
asm volatile ("mov r4, sp \n"
|
|
"b panicf_f \n"
|
|
);
|
|
while (1);
|
|
}
|
|
|
|
/*
|
|
* "Dude. This is pretty fucked-up, right here."
|
|
*/
|
|
void panicf_f( const char *fmt, ...)
|
|
{
|
|
int sp;
|
|
|
|
asm volatile ("mov %[SP],r4 \n"
|
|
: [SP] "=r" (sp)
|
|
);
|
|
|
|
int pc = (int)__builtin_return_address(0);
|
|
#elif defined(BACKTRACE_MIPSUNWINDER)
|
|
void panicf( const char *fmt, ... )
|
|
{
|
|
/* NOTE: these are obtained by the backtrace lib */
|
|
const int pc = 0;
|
|
const int sp = 0;
|
|
#else
|
|
void panicf( const char *fmt, ...)
|
|
{
|
|
#endif
|
|
va_list ap;
|
|
|
|
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
|
/* Disable interrupts */
|
|
#if defined(CPU_ARM_CLASSIC)
|
|
disable_interrupt(IRQ_FIQ_STATUS);
|
|
#else
|
|
set_irq_level(DISABLE_INTERRUPTS);
|
|
#endif
|
|
#endif /* SIMULATOR */
|
|
|
|
va_start( ap, fmt );
|
|
vsnprintf( panic_buf, sizeof(panic_buf), fmt, ap );
|
|
va_end( ap );
|
|
|
|
lcd_set_viewport(NULL);
|
|
|
|
int y = 1;
|
|
|
|
#if LCD_DEPTH > 1
|
|
lcd_set_backdrop(NULL);
|
|
lcd_set_drawinfo(DRMODE_SOLID, LCD_BLACK, LCD_WHITE);
|
|
#endif
|
|
|
|
lcd_clear_display();
|
|
lcd_setfont(FONT_SYSFIXED);
|
|
lcd_puts(1, y++, (unsigned char *) "*PANIC* (" RBVERSION ")");
|
|
{
|
|
/* wrap panic line */
|
|
int i, len = strlen(panic_buf);
|
|
for (i=0; i<len; i+=LINECHARS) {
|
|
unsigned char c = panic_buf[i+LINECHARS];
|
|
panic_buf[i+LINECHARS] = 0;
|
|
lcd_puts(1, y++, (unsigned char *)panic_buf+i);
|
|
panic_buf[i+LINECHARS] = c;
|
|
}
|
|
}
|
|
|
|
#if defined(HAVE_RB_BACKTRACE)
|
|
rb_backtrace(pc, sp, &y);
|
|
#endif
|
|
#ifdef ROCKBOX_HAS_LOGF
|
|
logf_panic_dump(&y);
|
|
#endif
|
|
|
|
lcd_update();
|
|
DEBUGF("%s", panic_buf);
|
|
|
|
#ifdef HAVE_ADJUSTABLE_CPU_FREQ
|
|
if (cpu_boost_lock())
|
|
{
|
|
set_cpu_frequency(0);
|
|
cpu_boost_unlock();
|
|
}
|
|
#endif /* HAVE_ADJUSTABLE_CPU_FREQ */
|
|
|
|
#ifdef HAVE_ATA_POWER_OFF
|
|
ide_power_enable(false);
|
|
#endif
|
|
|
|
system_exception_wait(); /* if this returns, try to reboot */
|
|
system_reboot();
|
|
while (1); /* halt */
|
|
}
|