Files
OpenCellular/board/keyborg/runtime.c
Vincent Palatin 6473343075 better unhandled exception panic without runtime
On panic, reboot properly the CPU rather than just jumping to the reset
vector as that might lead to some incorrect initializations.

Properly plug the div by 0 to the panic handling.

Add a small trace if the debug output is activated.

Signed-off-by: Vincent Palatin <vpalatin@chromium.org>

BRANCH=none
BUG=chrome-os-partner:29840
TEST=add adhoc code triggering a data abort and see the firmware
printing a trace, then rebooting immediatly in a working state.

Change-Id: I1d5a98d9113c8ae08e05588a40f941d1ed22cebe
Reviewed-on: https://chromium-review.googlesource.com/206268
Reviewed-by: Vic Yang <victoryang@chromium.org>
Tested-by: Vincent Palatin <vpalatin@chromium.org>
Commit-Queue: Vincent Palatin <vpalatin@chromium.org>
2014-07-03 02:56:52 +00:00

144 lines
2.6 KiB
C

/* Copyright (c) 2014 The Chromium OS Authors. All rights reserved.
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
/* tiny substitute of the runtime layer */
#include "common.h"
#include "cpu.h"
#include "debug.h"
#include "master_slave.h"
#include "registers.h"
#include "task.h"
#include "timer.h"
#include "util.h"
volatile uint32_t last_event;
static uint32_t last_deadline;
static uint8_t need_wfi;
timestamp_t get_time(void)
{
timestamp_t t;
uint32_t hi, lo;
do {
hi = STM32_TIM_CNT(3);
lo = STM32_TIM_CNT(2);
} while (hi != STM32_TIM_CNT(3));
t.le.lo = (hi << 16) | lo;
t.le.hi = 0;
return t;
}
void udelay(unsigned us)
{
unsigned t0 = get_time().le.lo;
while ((get_time().le.lo - t0) < us)
;
}
void task_enable_irq(int irq)
{
CPU_NVIC_EN(0) = 1 << irq;
}
void task_disable_irq(int irq)
{
CPU_NVIC_DIS(0) = 1 << irq;
}
void task_clear_pending_irq(int irq)
{
CPU_NVIC_UNPEND(0) = 1 << irq;
}
uint32_t task_set_event(task_id_t tskid, uint32_t event, int wait)
{
last_event = event;
return 0;
}
void tim2_interrupt(void)
{
if (STM32_TIM_CNT(3) == last_deadline >> 16) {
STM32_TIM_DIER(2) = 0;
task_clear_pending_irq(STM32_IRQ_TIM2);
last_event = 1 << 29 /* task event wake */;
need_wfi = 0;
} else {
need_wfi = 1;
}
}
DECLARE_IRQ(STM32_IRQ_TIM2, tim2_interrupt, 1);
void __hw_clock_event_set(uint32_t deadline)
{
last_deadline = deadline;
STM32_TIM_CCR1(2) = deadline & 0xffff;
STM32_TIM_SR(2) = ~2;
STM32_TIM_DIER(2) |= 2;
}
uint32_t task_wait_event(int timeout_us)
{
uint32_t evt;
/* the event already happened */
if (last_event || !timeout_us) {
evt = last_event;
last_event = 0;
return evt;
}
/* set timeout on timer */
if (timeout_us > 0)
__hw_clock_event_set(get_time().le.lo + timeout_us);
do {
/* sleep until next interrupt */
asm volatile("wfi");
} while (need_wfi);
STM32_TIM_DIER(2) = 0; /* disable match interrupt */
evt = last_event;
last_event = 0;
return evt;
}
void system_reboot(void)
{
if (master_slave_is_master()) {
/* Ask the slave to reboot as well */
STM32_GPIO_BSRR(GPIO_A) = 1 << (6 + 16);
udelay(10 * MSEC); /* The slave reboots in 5 ms */
}
/* Ask the watchdog to trigger a hard reboot */
STM32_IWDG_KR = 0x5555;
STM32_IWDG_RLR = 0x1;
STM32_IWDG_KR = 0xcccc;
/* wait for the watchdog */
while (1)
;
}
/* Unhandled exception panic */
void exception_panic(void)
{
debug_printf("PANIC\n");
system_reboot();
}
/* --- stubs --- */
void __hw_timer_enable_clock(int n, int enable)
{ /* Done in hardware init */ }
void usleep(unsigned us)
{ /* Used only as a workaround */ }