blob: edf4b593010ce9bac7f783ae50e2741f1bcbd9a7 [file] [log] [blame]
/*----------------------------------------------------------------------------
* Copyright (c) 1999-2009 KEIL, 2009-2013 ARM Germany GmbH
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* - Neither the name of ARM nor the names of its contributors may be used
* to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*---------------------------------------------------------------------------*/
#include <syscfg/syscfg.h>
#include "os/os_trace_api.h"
.file "HAL_CM0.S"
.syntax unified
/*----------------------------------------------------------------------------
* Functions
*---------------------------------------------------------------------------*/
.thumb
.section ".text"
.align 2
/*--------------------------- os_set_env ------------------------------------*/
# void os_set_env (void);
#
# Called to switch to privileged or unprivileged thread mode. The variable
# 'os_flags' contains the CONTROL bit LSB to set the device into the
# proper mode. We also use PSP so we set bit 1 (the SPSEL bit) to 1.
#
.thumb_func
.type os_set_env, %function
.global os_set_env
os_set_env:
.fnstart
.cantunwind
MSR PSP,R0
LDR R0,=os_flags
LDRB R0,[R0]
ADDS R0, R0, #2
MSR CONTROL,R0
ISB
BX LR
.fnend
.size os_set_env, .-os_set_env
/*--------------------------- os_set_env ------------------------------------*/
/*--------------------------- os_arch_init_task_stack------------------------*/
# void os_arch_init_task_stack(os_stack_t *sf);
# NOTE: This function only stores R4 through R11 on stack. The reason we do
# this is that the application may have stored some values in some of the
# registers and we want to preserve those values (position independent code
# is a good example). The other registers are handled in the C startup code.
.thumb_func
.type os_arch_init_task_stack, %function
.global os_arch_init_task_stack
os_arch_init_task_stack:
.fnstart
MOV R3,R0
STMIA R0!,{R4-R7}
MOV R4,R8
MOV R5,R9
MOV R6,R10
MOV R7,R11
STMIA R0!,{R4-R7}
LDM R3!,{R4-R7}
BX LR
.fnend
.size os_arch_init_task_stack, .-os_arch_init_task_stack
/*--------------------------- os_set_env ------------------------------------*/
/*-------------------------- SVC_Handler ------------------------------------*/
# void SVC_Handler (void);
.thumb_func
.type SVC_Handler, %function
.global SVC_Handler
SVC_Handler:
.fnstart
.cantunwind
PUSH {R4,LR}
#if MYNEWT_VAL(OS_SYSVIEW)
BL os_trace_isr_enter
#endif
MRS R0,PSP /* Read PSP */
LDR R1,[R0,#24] /* Read Saved PC from Stack */
SUBS R1,R1,#2 /* Point to SVC Instruction */
LDRB R1,[R1] /* Load SVC Number */
CMP R1,#0
BNE SVC_User /* User SVC Number > 0 */
LDR R1,[R0,#16] /* Read saved R12 from Stack */
MOV R12, R1 /* Store in R12 */
LDMIA R0,{R0-R3} /* Read R0-R3 from stack */
BLX R12 /* Call SVC Function */
MRS R3,PSP /* Read PSP */
STMIA R3!,{R0-R2} /* Store return values */
#if MYNEWT_VAL(OS_SYSVIEW)
BL os_trace_isr_exit
#endif
POP {R4,PC} /* RETI */
/*------------------- User SVC ------------------------------*/
SVC_User:
LDR R2,=SVC_Count
LDR R2,[R2]
CMP R1,R2
BHI SVC_Done /* Overflow */
LDR R4,=SVC_Table-4
LSLS R1,R1,#2
LDR R4,[R4,R1] /* Load SVC Function Address */
MOV LR,R4
LDMIA R0,{R0-R3,R4} /* Read R0-R3,R12 from stack */
MOV R12,R4
BLX LR /* Call SVC Function */
MRS R4,PSP /* Read PSP */
STMIA R4!,{R0-R3} /* Function return values */
SVC_Done:
#if MYNEWT_VAL(OS_SYSVIEW)
BL os_trace_isr_exit
#endif
POP {R4,PC} /* RETI */
.fnend
.size SVC_Handler, .-SVC_Handler
/*-------------------------- PendSV_Handler ---------------------------------*/
# void PendSV_Handler (void);
.thumb_func
.type PendSV_Handler, %function
.global PendSV_Handler
PendSV_Handler:
.fnstart
.cantunwind
LDR R3,=g_os_run_list /* Get highest priority task ready to run */
LDR R2,[R3] /* Store in R2 */
LDR R3,=g_current_task /* Get current task */
LDR R1,[R3] /* Current task in R1 */
CMP R1,R2
BNE context_switch
BX LR /* RETI, no task switch */
context_switch:
MRS R0,PSP /* Read PSP */
SUBS R0,R0,#32
STMIA R0!,{R4-R7} /* Save Old context */
MOV R4,R8
MOV R5,R9
MOV R6,R10
MOV R7,R11
STMIA R0!,{R4-R7} /* Save Old context */
SUBS R0,R0,#32
STR R0,[R1,#0] /* Update stack pointer in current task */
STR R2,[R3] /* g_current_task = highest ready */
LDR R0,[R2,#0] /* get stack pointer of task we will start */
ADDS R0,R0, #16
LDMIA R0!,{R4-R7} /* Restore New Context */
MOV R8,R4
MOV R9,R5
MOV R10,R6
MOV R11,R7
MSR PSP,R0 /* Write PSP */
SUBS R0,R0,#32
LDMIA R0!,{R4-R7} /* Restore New Context */
#if MYNEWT_VAL(OS_SYSVIEW)
PUSH {R4,LR}
MOV R0, R2
BL os_trace_task_start_exec
POP {R4,PC}
#else
BX LR /* Return to Thread Mode */
#endif
.fnend
.size PendSV_Handler, .-PendSV_Handler
/*-------------------------- SysTick_Handler --------------------------------*/
# void SysTick_Handler (void);
.thumb_func
.type SysTick_Handler, %function
.global SysTick_Handler
SysTick_Handler:
.fnstart
.cantunwind
PUSH {R4,LR} /* Save EXC_RETURN */
#if MYNEWT_VAL(OS_SYSVIEW)
BL os_trace_isr_enter
#endif
BL timer_handler
#if MYNEWT_VAL(OS_SYSVIEW)
BL os_trace_isr_exit
#endif
POP {R4,PC} /* Restore EXC_RETURN */
.fnend
.size SysTick_Handler, .-SysTick_Handler
/* divide-by-zero */
.thumb_func
.type __aeabi_idiv0, %function
.global __aeabi_idiv0
.global __aeabi_ldiv0
__aeabi_idiv0:
__aeabi_ldiv0:
.fnstart
.cantunwind
push {r0,r1,r5}
ldr r0, =file_name
ldr r1, =__LINE__
ldr r5, =__assert_func
bx r5
.fnend
.size __aeabi_idiv0, .-__aeabi_idiv0
/*-------------------------- Defalt IRQ --------------------------------*/
.thumb_func
.type os_default_irq_asm, %function
.global os_default_irq_asm
os_default_irq_asm:
.fnstart
.cantunwind
#if MYNEWT_VAL(OS_SYSVIEW)
PUSH {R4,LR}
BL os_trace_isr_enter
#endif
/*
* LR = 0xfffffff9 if we were using MSP as SP
* LR = 0xfffffffd if we were using PSP as SP
*/
MOV R0,LR
MOVS R1,#4
TST R0,R1
MRS R12,MSP
BEQ using_msp_as_sp
MRS R12,PSP
using_msp_as_sp:
/*
* Push the "trap frame" structure onto stack by moving R8-R11 into
* R0-R3 and then pushing R0-R3. LR gets pushed as well with LR
* residing at higher memory, R8 at the lower memory address.
*/
MOV R0,R8
MOV R1,R9
MOV R2,R10
MOV R3,R11
#if MYNEWT_VAL(OS_SYSVIEW)
PUSH {R0-R3}
#else
PUSH {R0-R3, LR}
#endif
/* Now push r3 - r7. R3 is the lowest memory address. */
MOV R3,R12
PUSH {R3-R7}
MOV R0, SP
BL os_default_irq
POP {R3-R7}
POP {R0-R3}
MOV R8,R0
MOV R9,R1
MOV R10,R2
MOV R11,R3
#if MYNEWT_VAL(OS_SYSVIEW)
BL os_trace_isr_exit
POP {R4,PC}
#else
POP {PC} /* Restore EXC_RETURN */
#endif
.fnend
.size os_default_irq_asm, .-os_default_irq_asm
/*
* Prevent libgcc unwind stuff from getting pulled in.
*/
.section ".data"
.global __aeabi_unwind_cpp_pr0
__aeabi_unwind_cpp_pr0:
.section ".rodata"
file_name:
.asciz __FILE__
.end
/*----------------------------------------------------------------------------
* end of file
*---------------------------------------------------------------------------*/