132 lines
2.9 KiB
C
132 lines
2.9 KiB
C
/*
|
|
* Copyright (c) 2013-2014 Wind River Systems, Inc.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* @brief ARM CORTEX-M3 System Control Block interface
|
|
*
|
|
*
|
|
* Most of the SCB interface consists of simple bit-flipping methods, and is
|
|
* implemented as inline functions in scb.h. This module thus contains only data
|
|
* definitions and more complex routines, if needed.
|
|
*/
|
|
|
|
#include <kernel.h>
|
|
#include <arch/cpu.h>
|
|
#include <misc/util.h>
|
|
|
|
#define SCB_AIRCR_VECTKEY_EN_W 0x05FA
|
|
|
|
#if defined(CONFIG_SOC_TI_LM3S6965_QEMU)
|
|
/*
|
|
* QEMU is missing the support for rebooting through the SYSRESETREQ mechanism.
|
|
* Just jump back to __reset() of the image in flash, which address can
|
|
* _always_ be found in the vector table reset slot located at address 0x4.
|
|
*/
|
|
|
|
static void software_reboot(void)
|
|
{
|
|
extern void _do_software_reboot(void);
|
|
extern void _force_exit_one_nested_irq(void);
|
|
/*
|
|
* force enable interrupts locked via PRIMASK if somehow disabled: the
|
|
* boot code does not enable them
|
|
*/
|
|
__asm__ volatile("cpsie i" :::);
|
|
|
|
if (_ScbIsInThreadMode()) {
|
|
_do_software_reboot();
|
|
} else {
|
|
__asm__ volatile(
|
|
"ldr r0, =_force_exit_one_nested_irq\n\t"
|
|
"bx r0\n\t"
|
|
:::);
|
|
}
|
|
}
|
|
#define DO_REBOOT() software_reboot()
|
|
#else
|
|
static void reboot_through_sysresetreq(void)
|
|
{
|
|
union __aircr reg;
|
|
|
|
reg.val = __scs.scb.aircr.val;
|
|
reg.bit.vectkey = SCB_AIRCR_VECTKEY_EN_W;
|
|
reg.bit.sysresetreq = 1;
|
|
__scs.scb.aircr.val = reg.val;
|
|
|
|
/* the reboot is not immediate, so wait here until it takes effect */
|
|
for (;;) {
|
|
;
|
|
}
|
|
}
|
|
#define DO_REBOOT() reboot_through_sysresetreq()
|
|
#endif
|
|
|
|
/**
|
|
*
|
|
* @brief Reset the system
|
|
*
|
|
* This routine resets the processor.
|
|
*
|
|
* @return N/A
|
|
*/
|
|
|
|
void sys_arch_reboot(int type)
|
|
{
|
|
ARG_UNUSED(type);
|
|
DO_REBOOT();
|
|
}
|
|
|
|
#if defined(CONFIG_ARMV6_M)
|
|
#elif defined(CONFIG_ARMV7_M)
|
|
/**
|
|
*
|
|
* @brief Set the number of priority groups based on the number of exception
|
|
* priorities desired
|
|
*
|
|
* Exception priorities can be divided in priority groups, inside which there is
|
|
* no preemption. The priorities inside a group are only used to decide which
|
|
* exception will run when more than one is ready to be handled.
|
|
*
|
|
* The number of priorities has to be a power of two, from 1 to 128.
|
|
*
|
|
* @param n the number of priorities
|
|
*
|
|
* @return N/A
|
|
*/
|
|
void _ScbNumPriGroupSet(unsigned int n)
|
|
{
|
|
unsigned int set;
|
|
union __aircr reg;
|
|
|
|
__ASSERT(is_power_of_two(n) && (n <= 128),
|
|
"invalid number of priorities");
|
|
|
|
set = find_lsb_set(n);
|
|
|
|
reg.val = __scs.scb.aircr.val;
|
|
|
|
/* num pri bit set prigroup
|
|
* ---------------------------------
|
|
* 1 1 7
|
|
* 2 2 6
|
|
* 4 3 5
|
|
* 8 4 4
|
|
* 16 5 3
|
|
* 32 6 2
|
|
* 64 7 1
|
|
* 128 8 0
|
|
*/
|
|
|
|
reg.bit.prigroup = 8 - set;
|
|
reg.bit.vectkey = SCB_AIRCR_VECTKEY_EN_W;
|
|
|
|
__scs.scb.aircr.val = reg.val;
|
|
}
|
|
#else
|
|
#error Unknown ARM architecture
|
|
#endif /* CONFIG_ARMV6_M */
|