arm: add software reboot for QEMU

This simulates a reboot by jumping back to the address stored in the
reset vector in vector table found at address 0. It is supported from
interrupt/exception level, which means that sys_arch_reboot() in this
case finds out if it is called from thread mode or handler mode, and in
the latter case, it unwinds the nested exception stack as needed.

Change-Id: Ib67f850f8411f1ee8fc592a5f31f2f70d0af14a4
Signed-off-by: Benjamin Walsh <benjamin.walsh@windriver.com>
This commit is contained in:
Benjamin Walsh 2015-11-05 18:26:01 -05:00 committed by Anas Nashif
commit c5bb958db4
2 changed files with 96 additions and 10 deletions

View file

@ -27,6 +27,7 @@
#include <toolchain.h>
#include <sections.h>
#include <arch/cpu.h>
#include <offsets.h>
#include "vector_table.h"
_ASM_FILE_PROLOGUE
@ -87,3 +88,53 @@ SECTION_SUBSEC_FUNC(TEXT,_reset_section,__start)
#endif
b _PrepC
#if defined(CONFIG_SOC_TI_LM3S6965_QEMU)
GTEXT(_do_software_reboot)
SECTION_FUNC(TEXT,_do_software_reboot)
eors r0, r0
/* move exception table back to 0 */
ldr r1, =0xe000e000
str r0, [r1, #0xd08] /* VTOR */
ldr r0, [r0, #4]
bx r0
GTEXT(_force_exit_one_nested_irq)
SECTION_FUNC(TEXT,_force_exit_one_nested_irq)
ldr r0, =_SCS_ICSR_RETTOBASE
ldr r1, =_SCS_ICSR
ldr r1, [r1]
ands.w r0, r1
/*
* If Z flag is set, we are nested, so un-nest one level and get back to
* this function to unwind the next level; else, exit the last interrupt
* by jumping to reboot code.
*/
ittee eq
ldreq lr, =0xfffffff1
ldreq r2, =_force_exit_one_nested_irq
ldrne lr, =0xfffffffd
ldrne r2, =_do_software_reboot
ldr ip, =_interrupt_stack
add.w ip, #(__tESF_SIZEOF * 2) /* enough for a stack frame */
ldr r1, =0xfffffffe
and.w r2, r1
str r2, [ip, #(6 * 4)]
ldr r2, =0x01000000
str r2, [ip, #(7 * 4)]
ite eq
moveq sp, ip
msrne PSP, ip
bx lr
#endif

View file

@ -30,20 +30,38 @@
#define SCB_AIRCR_VECTKEY_EN_W 0x05FA
/**
*
* @brief Reset the system
*
* This routine resets the processor.
*
* @return N/A
#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.
*/
void sys_arch_reboot(int type)
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;
ARG_UNUSED(type);
reg.val = __scs.scb.aircr.val;
reg.bit.vectkey = SCB_AIRCR_VECTKEY_EN_W;
reg.bit.sysresetreq = 1;
@ -54,6 +72,23 @@ void sys_arch_reboot(int type)
;
}
}
#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();
}
/**
*