arm: implement __svc on Cortex M0

This is needed for irq_offload() and k_oops()/k_panic()

Issue: ZEP-2221
Signed-off-by: Andrew Boie <andrew.p.boie@intel.com>
This commit is contained in:
Andrew Boie 2017-06-01 13:36:44 -07:00 committed by Anas Nashif
commit a2156fec2c
4 changed files with 59 additions and 10 deletions

View file

@ -47,7 +47,7 @@ SECTION_SUBSEC_FUNC(exc_vector_table,_vector_table_section,_vector_table)
.word __reserved .word __reserved
.word __reserved .word __reserved
.word __reserved .word __reserved
.word __reserved /* SVC not used for now (PendSV used instead) */ .word __svc
.word __reserved .word __reserved
#elif defined(CONFIG_ARMV7_M) #elif defined(CONFIG_ARMV7_M)
.word __mpu_fault .word __mpu_fault

View file

@ -39,6 +39,7 @@ GTEXT(__reset)
GTEXT(__nmi) GTEXT(__nmi)
GTEXT(__hard_fault) GTEXT(__hard_fault)
#if defined(CONFIG_ARMV6_M) #if defined(CONFIG_ARMV6_M)
GTEXT(__svc)
#elif defined(CONFIG_ARMV7_M) #elif defined(CONFIG_ARMV7_M)
GTEXT(__mpu_fault) GTEXT(__mpu_fault)
GTEXT(__bus_fault) GTEXT(__bus_fault)

View file

@ -22,9 +22,17 @@ void _irq_do_offload(void)
void irq_offload(irq_offload_routine_t routine, void *parameter) void irq_offload(irq_offload_routine_t routine, void *parameter)
{ {
int key; #if defined(CONFIG_ARMV6_M) && defined(CONFIG_ASSERT)
/* Cortex M0 hardfaults if you make a SVC call with interrupts
* locked.
*/
unsigned int key;
key = irq_lock(); __asm__ volatile("mrs %0, PRIMASK;" : "=r" (key) : : "memory");
__ASSERT(key == 0, "irq_offload called with interrupts locked\n");
#endif
k_sched_lock();
offload_routine = routine; offload_routine = routine;
offload_param = parameter; offload_param = parameter;
@ -34,6 +42,5 @@ void irq_offload(irq_offload_routine_t routine, void *parameter)
: "memory"); : "memory");
offload_routine = NULL; offload_routine = NULL;
k_sched_unlock();
irq_unlock(key);
} }

View file

@ -20,12 +20,7 @@
_ASM_FILE_PROLOGUE _ASM_FILE_PROLOGUE
GTEXT(__swap) GTEXT(__swap)
#if defined(CONFIG_ARMV6_M)
#elif defined(CONFIG_ARMV7_M)
GTEXT(__svc) GTEXT(__svc)
#else
#error Unknown ARM architecture
#endif /* CONFIG_ARMV6_M */
GTEXT(__pendsv) GTEXT(__pendsv)
GTEXT(_do_kernel_oops) GTEXT(_do_kernel_oops)
GDATA(_k_neg_eagain) GDATA(_k_neg_eagain)
@ -217,6 +212,52 @@ _thread_irq_disabled:
bx lr bx lr
#if defined(CONFIG_ARMV6_M) #if defined(CONFIG_ARMV6_M)
SECTION_FUNC(TEXT, __svc)
/* Use EXC_RETURN state to find out if stack frame is on the
* MSP or PSP
*/
ldr r0, =0x4
mov r1, lr
tst r1, r0
beq _stack_frame_msp
mrs r0, PSP
bne _stack_frame_endif
_stack_frame_msp:
mrs r0, MSP
_stack_frame_endif:
/* Figure out what SVC call number was invoked */
ldr r1, [r0, #24] /* grab address of PC from stack frame */
/* SVC is a two-byte instruction, point to it and read encoding */
subs r1, r1, #2
ldrb r1, [r1, #0]
/*
* grab service call number:
* 1: irq_offload (if configured)
* 2: kernel panic or oops (software generated fatal exception)
* Planned implementation of system calls for memory protection will
* expand this case.
*/
cmp r1, #2
beq _oops
#if CONFIG_IRQ_OFFLOAD
push {lr}
blx _irq_do_offload /* call C routine which executes the offload */
pop {r3}
mov lr, r3
#endif
/* exception return is done in _IntExit() */
b _IntExit
_oops:
push {lr}
blx _do_kernel_oops
pop {pc}
#elif defined(CONFIG_ARMV7_M) #elif defined(CONFIG_ARMV7_M)
/** /**
* *