blob: 2ccf71395a3a2aa12e972132e68fb842648d6f02 [file] [log] [blame]
/*
* Copyright (c) 2015 Wind River Systems, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file dynamic exception management
*/
/* can only be used with non-XIP kernels, since they don't have their vector
* table in the FLASH
*/
#if !defined(CONFIG_XIP)
#include <nanokernel.h>
#include <arch/cpu.h>
#include <misc/__assert.h>
#include <toolchain.h>
#include <sections.h>
#include "vector_table.h"
static inline int exc_can_be_connected(int num)
{
static const uint16_t connectable_exceptions = (
(1 << _EXC_MPU_FAULT) |
(1 << _EXC_BUS_FAULT) |
(1 << _EXC_USAGE_FAULT) |
(1 << _EXC_DEBUG) |
0
);
return !!(connectable_exceptions & (1 << num));
}
/*
* Can be initialized with garbage, it doesn't matter until the wrapper is
* inserted in the vector table, at which point the relevant entry will contain
* the pointer to the handler.
*/
sys_exc_handler_t *_sw_exc_table[_NUM_EXC] __noinit;
extern void _exc_wrapper(void);
void sys_exc_connect(unsigned int num, sys_exc_handler_t *handler, void *unused)
{
__ASSERT(exc_can_be_connected(num), "not a connectable exception");
_sw_exc_table[num] = handler;
/*
* The compiler sets thumb bit (bit0) of the value of the _vector_table
* symbol, probably because it is in the .text section: to get the correct
* offset in the table, mask bit0.
*/
((void **)(((uint32_t)_vector_table) & 0xfffffffe))[num] = _exc_wrapper;
}
FUNC_ALIAS(sys_exc_connect, nanoCpuExcConnect, void);
#include <misc/printk.h>
void sys_exc_esf_dump(NANO_ESF *esf)
{
printk("r0/a1: %x ", esf->a1);
printk("r1/a2: %x ", esf->a2);
printk("r2/a3: %x\n", esf->a3);
printk("r3/a4: %x ", esf->a4);
printk("r12/ip: %x ", esf->ip);
printk("r14/lr: %x\n", esf->lr);
printk("r15/pc: %x ", esf->pc);
printk("xpsr: %x\n", esf->xpsr);
#ifdef CONFIG_FLOAT
for (int i = 0; i < 16; i += 4) {
printk("s[%d]: %x s[%d]: %x s[%d]: %x s[%d]: %x\n",
i, esf->s[i], i + 1, esf->s[i + 1],
i + 2, esf->s[i + 2], i + 3, esf->s[i + 3]);
}
printk("fpscr: %x\n", esf->fpscr);
#endif
}
#endif /* CONFIG_XIP */