25e50ed8f1
If logf is enabled, panic() will print the last lines. On small screens this is more or less useless, but on large screens it can be very useful for debugging. Change-Id: I26dfc76e9ac4a2ddc2def8db1616a04f943dbba3 Reviewed-on: http://gerrit.rockbox.org/709 Reviewed-by: Thomas Martitz <kugel@rockbox.org> Reviewed-by: Frank Gevaerts <frank@gevaerts.be> Tested: Frank Gevaerts <frank@gevaerts.be>
138 lines
3.3 KiB
C
138 lines
3.3 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"
|
|
|
|
#if defined(CPU_ARM)
|
|
#include "gcc_extensions.h"
|
|
#include <backtrace.h>
|
|
#endif
|
|
|
|
static char panic_buf[128];
|
|
#define LINECHARS (LCD_WIDTH/SYSFONT_WIDTH) - 2
|
|
|
|
#if defined(CPU_ARM)
|
|
void panicf_f( const char *fmt, ...);
|
|
|
|
/* we wrap panicf() here with naked function to catch SP value */
|
|
void panicf( const char *fmt, ...)
|
|
{
|
|
(void)fmt;
|
|
asm volatile ("mov r4, sp \n"
|
|
"b panicf_f \n"
|
|
);
|
|
}
|
|
|
|
/*
|
|
* "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);
|
|
#else
|
|
void panicf( const char *fmt, ...)
|
|
{
|
|
#endif
|
|
va_list ap;
|
|
|
|
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
|
|
/* Disable interrupts */
|
|
#ifdef CPU_ARM
|
|
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);
|
|
|
|
#ifdef HAVE_LCD_CHARCELLS
|
|
lcd_double_height(false);
|
|
lcd_puts(0, 0, "*PANIC*");
|
|
lcd_puts(0, 1, panic_buf);
|
|
#elif defined(HAVE_LCD_BITMAP)
|
|
int y = 1;
|
|
|
|
#if LCD_DEPTH > 1
|
|
lcd_set_backdrop(NULL);
|
|
lcd_set_drawmode(DRMODE_SOLID);
|
|
lcd_set_foreground(LCD_BLACK);
|
|
lcd_set_background(LCD_WHITE);
|
|
#endif
|
|
|
|
lcd_clear_display();
|
|
lcd_setfont(FONT_SYSFIXED);
|
|
lcd_puts(1, y++, (unsigned char *)"*PANIC*");
|
|
{
|
|
/* 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(CPU_ARM)
|
|
backtrace(pc, sp, &y);
|
|
#endif
|
|
#ifdef ROCKBOX_HAS_LOGF
|
|
logf_panic_dump(&y);
|
|
#endif
|
|
#else
|
|
/* no LCD */
|
|
#endif
|
|
|
|
lcd_update();
|
|
DEBUGF("%s", panic_buf);
|
|
|
|
set_cpu_frequency(0);
|
|
|
|
#ifdef HAVE_ATA_POWER_OFF
|
|
ide_power_enable(false);
|
|
#endif
|
|
|
|
system_exception_wait(); /* if this returns, try to reboot */
|
|
system_reboot();
|
|
while (1); /* halt */
|
|
}
|