diff --git a/ports/arm7a/arm_asm_macro.h b/ports/arm7a/arm_asm_macro.h new file mode 100644 index 0000000..4d833b3 --- /dev/null +++ b/ports/arm7a/arm_asm_macro.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2011, Anup Patel. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * 3. No personal names or organizations' names associated with the + * Atomthreads project may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE ATOMTHREADS PROJECT 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 THE PROJECT OR 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. + */ +#ifndef __ARM_ASM_MACRO_H__ +#define __ARM_ASM_MACRO_H__ + +#include + +#ifdef __ASSEMBLY__ + +.macro SET_CURRENT_FLAGS flags, treg + mrs \treg, cpsr + orr \treg, \treg, #(\flags) + msr cpsr, \treg +.endm + +.macro SET_CURRENT_MODE mode + cps #(\mode) +.endm + +.macro SET_CURRENT_STACK new_stack + ldr sp, \new_stack +.endm + +.macro START_EXCEPTION_HANDLER irqname, lroffset + .align 5 +\irqname: + sub lr, lr, #\lroffset +.endm + +/* Save User Registers */ +.macro PUSH_USER_REGS + str lr, [sp, #-4]!; /* Push the return address */ + sub sp, sp, #(4*15); /* Adjust the stack pointer */ + stmia sp, {r0-r12}; /* Push user mode registers */ + add r0, sp, #(4*13); /* Adjust the stack pointer */ + stmia r0, {r13-r14}^; /* Push user mode registers */ + mov r0, r0; /* NOP for previous inst */ + mrs r0, spsr_all; /* Put the SPSR on the stack */ + str r0, [sp, #-4]! +.endm + +/* If came from priviledged mode then push banked registers */ +.macro PUSH_BANKED_REGS skip_lable + mov r4, r0 + and r0, r0, #CPSR_MODE_MASK + cmp r0, #CPSR_MODE_USER + beq \skip_lable + add r1, sp, #(4*14) + mrs r5, cpsr + orr r4, r4, #(CPSR_IRQ_DISABLED | CPSR_FIQ_DISABLED) + msr cpsr, r4 + str sp, [r1, #0] + str lr, [r1, #4] + msr cpsr, r5 + \skip_lable: +.endm + +/* Call C function to handle exception */ +.macro CALL_EXCEPTION_CFUNC cfunc + mov r0, sp + bl \cfunc +.endm + +/* If going back to priviledged mode then pull banked registers */ +.macro PULL_BANKED_REGS skip_lable + ldr r0, [sp, #0] + mov r4, r0 + and r0, r0, #CPSR_MODE_MASK + cmp r0, #CPSR_MODE_USER + beq \skip_lable + add r1, sp, #(4*14) + mrs r5, cpsr + orr r4, r4, #(CPSR_IRQ_DISABLED | CPSR_FIQ_DISABLED) + msr cpsr, r4 + ldr sp, [r1, #0] + ldr lr, [r1, #4] + msr cpsr, r5 + \skip_lable: +.endm + +/* Restore User Registers */ +.macro PULL_USER_REGS + ldr r0, [sp], #0x0004; /* Get SPSR from stack */ + msr spsr_all, r0; + ldmia sp, {r0-r14}^; /* Restore registers (user) */ + mov r0, r0; /* NOP for previous isnt */ + add sp, sp, #(4*15); /* Adjust the stack pointer */ + ldr lr, [sp], #0x0004 /* Pull return address */ +.endm + +.macro END_EXCEPTION_HANDLER + movs pc, lr +.endm + +#endif + +#endif diff --git a/ports/arm7a/atomport-private.h b/ports/arm7a/arm_defines.h similarity index 53% rename from ports/arm7a/atomport-private.h rename to ports/arm7a/arm_defines.h index a6e8aad..8de737c 100644 --- a/ports/arm7a/atomport-private.h +++ b/ports/arm7a/arm_defines.h @@ -27,27 +27,42 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#ifndef __ATOMPORT_PRIVATE_H_ -#define __ATOMPORT_PRIVATE_H_ +#ifndef __ARM_DEFINES_H_ +#define __ARM_DEFINES_H_ -#define CPSR_MODE_MASK 0x0000001f -#define CPSR_MODE_USER 0x00000010 -#define CPSR_MODE_FIQ 0x00000011 -#define CPSR_MODE_IRQ 0x00000012 -#define CPSR_MODE_SUPERVISOR 0x00000013 -#define CPSR_MODE_ABORT 0x00000017 -#define CPSR_MODE_UNDEFINED 0x0000001b -#define CPSR_MODE_SYSTEM 0x0000001f +#define CPSR_VALIDBITS_MASK 0xFF0FFFFF +#define CPSR_USERBITS_MASK 0xFFFFFC00 +#define CPSR_USERBITS_SHIFT 10 +#define CPSR_PRIVBITS_MASK 0x000003FF +#define CPSR_PRIVBITS_SHIFT 0 +#define CPSR_MODE_MASK 0x0000001f +#define CPSR_MODE_USER 0x00000010 +#define CPSR_MODE_FIQ 0x00000011 +#define CPSR_MODE_IRQ 0x00000012 +#define CPSR_MODE_SUPERVISOR 0x00000013 +#define CPSR_MODE_MONITOR 0x00000016 +#define CPSR_MODE_ABORT 0x00000017 +#define CPSR_MODE_UNDEFINED 0x0000001b +#define CPSR_MODE_SYSTEM 0x0000001f +#define CPSR_THUMB_ENABLED (1 << 5) +#define CPSR_FIQ_DISABLED (1 << 6) +#define CPSR_IRQ_DISABLED (1 << 7) +#define CPSR_ASYNC_ABORT_DISABLED (1 << 8) +#define CPSR_BE_ENABLED (1 << 9) +#define CPSR_IT2_MASK 0x0000FC00 +#define CPSR_IT2_SHIFT 10 +#define CPSR_GE_MASK 0x000F0000 +#define CPSR_GE_SHIFT 16 +#define CPSR_JAZZLE_ENABLED (1 << 24) +#define CPSR_IT1_MASK 0x06000000 +#define CPSR_IT1_SHIFT 25 +#define CPSR_COND_OVERFLOW_MASK (1 << 28) +#define CPSR_COND_OVERFLOW_SHIFT 28 +#define CPSR_COND_CARRY_MASK (1 << 29) +#define CPSR_COND_CARRY_SHIFT 29 +#define CPSR_COND_ZERO_MASK (1 << 30) +#define CPSR_COND_ZERO_SHIFT 30 +#define CPSR_COND_NEGATIVE_MASK (1 << 31) +#define CPSR_COND_NEGATIVE_SHIFT 31 -#define CPSR_THUMB_ENABLED (1 << 5) -#define CPSR_FIQ_DISABLED (1 << 6) -#define CPSR_IRQ_DISABLED (1 << 7) -#define CPSR_ASYNC_ABORT_DISABLED (1 << 8) -#define CPSR_BE_ENABLED (1 << 9) - -#define CPSR_COND_OVERFLOW (1 << 28) -#define CPSR_COND_CARRY (1 << 29) -#define CPSR_COND_ZERO (1 << 30) -#define CPSR_COND_NEGATIVE (1 << 31) - -#endif /* __ATOMPORT_PRIVATE_H_ */ +#endif /* __ARM_DEFINES_H_ */ diff --git a/ports/arm7a/arm_entry.s b/ports/arm7a/arm_entry.s index c19d651..9f21d94 100644 --- a/ports/arm7a/arm_entry.s +++ b/ports/arm7a/arm_entry.s @@ -27,71 +27,7 @@ * POSSIBILITY OF SUCH DAMAGE. */ -#include - -.macro SET_CURRENT_FLAGS flags, treg - mrs \treg, cpsr - orr \treg, \treg, #(\flags) - msr cpsr, \treg -.endm - -.macro SET_CURRENT_MODE mode - cps #(\mode) -.endm - -.macro SET_CURRENT_STACK new_stack - ldr sp, \new_stack -.endm - -.macro START_EXCEPTION_HANDLER irqname, lroffset - .align 5 -\irqname: - sub lr, lr, #\lroffset -.endm - -/* Save User Registers */ -.macro PUSH_USER_REGS - str lr, [sp, #-4]!; /* Push the return address */ - sub sp, sp, #(4*15); /* Adjust the stack pointer */ - stmia sp, {r0-r12}; /* Push user mode registers */ - add r0, sp, #(4*13); /* Adjust the stack pointer */ - stmia r0, {r13-r14}^; /* Push user mode registers */ - mov r0, r0; /* NOP for previous inst */ - mrs r0, spsr_all; /* Put the SPSR on the stack */ - str r0, [sp, #-4]! -.endm - -/* Save User Registers in FIQ */ -.macro PUSH_FIQUSER_REGS - str lr, [sp, #-4]!; /* Push the return address */ - sub sp, sp, #(4*15); /* Adjust the stack pointer */ - stmia sp, {r0-r7}; /* Push user mode registers */ - add r0, sp, #(4*8); /* Adjust the stack pointer */ - stmia r0, {r8-r14}^; /* Push user mode registers */ - mov r0, r0; /* NOP for previous inst */ - mrs r0, spsr_all; /* Put the SPSR on the stack */ - str r0, [sp, #-4]! -.endm - -/* Call C function to handle exception */ -.macro CALL_EXCEPTION_CFUNC cfunc - mov r0, sp - bl \cfunc -.endm - -/* Restore User Registers */ -.macro PULL_USER_REGS - ldr r0, [sp], #0x0004; /* Get SPSR from stack */ - msr spsr_all, r0; - ldmia sp, {r0-r14}^; /* Restore registers (user) */ - mov r0, r0; /* NOP for previous isnt */ - add sp, sp, #(4*15); /* Adjust the stack pointer */ - ldr lr, [sp], #0x0004 /* Pull return address */ -.endm - -.macro END_EXCEPTION_HANDLER - movs pc, lr -.endm +#include .section .expvect, "ax", %progbits .globl _start_vect @@ -123,18 +59,8 @@ __fiq: .global _end_vect _end_vect: -__svc_stack_end: - .word _svc_stack_end -__und_stack_end: - .word _und_stack_end -__abt_stack_end: - .word _abt_stack_end -__irq_stack_end: - .word _irq_stack_end -__fiq_stack_end: - .word _fiq_stack_end -__usr_stack_end: - .word _usr_stack_end +__initial_stack_end: + .word _initial_stack_end .globl _reset _reset: @@ -144,69 +70,82 @@ _reset: cpsid if /* Set Supervisor Mode Stack */ SET_CURRENT_MODE CPSR_MODE_SUPERVISOR - SET_CURRENT_STACK __svc_stack_end + SET_CURRENT_STACK __initial_stack_end /* Set Undefined Mode Stack */ SET_CURRENT_MODE CPSR_MODE_UNDEFINED - SET_CURRENT_STACK __und_stack_end + SET_CURRENT_STACK __initial_stack_end /* Set Abort Mode Stack */ SET_CURRENT_MODE CPSR_MODE_ABORT - SET_CURRENT_STACK __abt_stack_end + SET_CURRENT_STACK __initial_stack_end /* Set IRQ Mode Stack */ SET_CURRENT_MODE CPSR_MODE_IRQ - SET_CURRENT_STACK __irq_stack_end + SET_CURRENT_STACK __initial_stack_end /* Set FIQ Mode Stack */ SET_CURRENT_MODE CPSR_MODE_FIQ - SET_CURRENT_STACK __fiq_stack_end + SET_CURRENT_STACK __initial_stack_end /* Set System Mode Stack */ SET_CURRENT_MODE CPSR_MODE_SYSTEM - SET_CURRENT_STACK __usr_stack_end + SET_CURRENT_STACK __initial_stack_end /* Set to Supervisor Mode */ SET_CURRENT_MODE CPSR_MODE_SUPERVISOR /* Call main function */ bl main /* We should never reach here */ b . - START_EXCEPTION_HANDLER _undefined_instruction, 4 PUSH_USER_REGS + PUSH_BANKED_REGS _undefined_instruction_bankpush_skip CALL_EXCEPTION_CFUNC do_undefined_instruction + PULL_BANKED_REGS _undefined_instruction_bankpull_skip PULL_USER_REGS END_EXCEPTION_HANDLER START_EXCEPTION_HANDLER _software_interrupt, 4 PUSH_USER_REGS + PUSH_BANKED_REGS _software_interrupt_bankpush_skip CALL_EXCEPTION_CFUNC do_software_interrupt + PULL_BANKED_REGS _software_interrupt_bankpull_skip PULL_USER_REGS END_EXCEPTION_HANDLER START_EXCEPTION_HANDLER _prefetch_abort, 4 PUSH_USER_REGS + PUSH_BANKED_REGS _prefetch_abort_bankpush_skip CALL_EXCEPTION_CFUNC do_prefetch_abort + PULL_BANKED_REGS _prefetch_abort_bankpull_skip PULL_USER_REGS END_EXCEPTION_HANDLER START_EXCEPTION_HANDLER _data_abort, 8 PUSH_USER_REGS + PUSH_BANKED_REGS _data_abort_bankpush_skip CALL_EXCEPTION_CFUNC do_data_abort + PULL_BANKED_REGS _data_abort_bankpull_skip PULL_USER_REGS END_EXCEPTION_HANDLER START_EXCEPTION_HANDLER _not_used, 4 PUSH_USER_REGS + PUSH_BANKED_REGS _not_used_bankpush_skip CALL_EXCEPTION_CFUNC do_not_used + PULL_BANKED_REGS _not_used_bankpull_skip PULL_USER_REGS END_EXCEPTION_HANDLER START_EXCEPTION_HANDLER _irq, 4 PUSH_USER_REGS + PUSH_BANKED_REGS _irq_bankpush_skip CALL_EXCEPTION_CFUNC do_irq + PULL_BANKED_REGS _irq_bankpull_skip PULL_USER_REGS END_EXCEPTION_HANDLER START_EXCEPTION_HANDLER _fiq, 4 - PUSH_FIQUSER_REGS + PUSH_USER_REGS + PUSH_BANKED_REGS _fiq_bankpush_skip CALL_EXCEPTION_CFUNC do_fiq + PULL_BANKED_REGS _fiq_bankpull_skip PULL_USER_REGS END_EXCEPTION_HANDLER diff --git a/ports/arm7a/arm_irq.h b/ports/arm7a/arm_irq.h index 1f0431e..89f963f 100644 --- a/ports/arm7a/arm_irq.h +++ b/ports/arm7a/arm_irq.h @@ -31,7 +31,7 @@ #define __ARM_IRQ_H #include -#include +#include typedef int (*arm_irq_handler_t) (uint32_t irq_no, pt_regs_t * regs); diff --git a/ports/arm7a/arm_main.c b/ports/arm7a/arm_main.c index cb324f8..4e60eba 100644 --- a/ports/arm7a/arm_main.c +++ b/ports/arm7a/arm_main.c @@ -28,7 +28,6 @@ */ #include -#include #include #include #include diff --git a/ports/arm7a/atomport-asm.s b/ports/arm7a/atomport-asm.s index b211585..f1d37f2 100644 --- a/ports/arm7a/atomport-asm.s +++ b/ports/arm7a/atomport-asm.s @@ -27,6 +27,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include + .section .text /** @@ -54,5 +56,22 @@ archContextSwitch: */ .globl archFirstThreadRestore archFirstThreadRestore: - bx lr + ldr r0, [r0] + mov sp, r0 + mrs r1, cpsr + SET_CURRENT_MODE CPSR_MODE_UNDEFINED + mov sp, r0 + SET_CURRENT_MODE CPSR_MODE_ABORT + mov sp, r0 + SET_CURRENT_MODE CPSR_MODE_IRQ + mov sp, r0 + SET_CURRENT_MODE CPSR_MODE_FIQ + mov sp, r0 + msr cpsr, r1 + sub sp, sp, #(4 * 17) + ldr r0, [sp], #0x0004; /* Get CPSR from stack */ + msr spsr_all, r0; + ldmia sp, {r0-r14}; /* Restore registers */ + mov r0, r0; /* NOP for previous isnt */ + movs pc, lr diff --git a/ports/arm7a/atomport.c b/ports/arm7a/atomport.c index c2019d8..e4c7ffa 100644 --- a/ports/arm7a/atomport.c +++ b/ports/arm7a/atomport.c @@ -29,9 +29,9 @@ */ #include -#include #include #include +#include /** * This function initialises each thread's stack during creation, before the @@ -53,6 +53,18 @@ void archThreadContextInit (ATOM_TCB *tcb_ptr, void *stack_top, void (*entry_point)(UINT32), UINT32 entry_param) { + int i; + pt_regs_t *regs = (pt_regs_t *)((uint32_t)stack_top - sizeof(pt_regs_t)); + tcb_ptr->sp_save_ptr = stack_top; + regs->cpsr = CPSR_COND_ZERO_MASK | + CPSR_ASYNC_ABORT_DISABLED | CPSR_MODE_SUPERVISOR; + regs->gpr[0] = entry_param; + for (i = 1; i < 13; i++) { + regs->gpr[i] = 0x0; + } + regs->sp = (uint32_t)stack_top - sizeof(pt_regs_t) - 2048; + regs->lr = (uint32_t)entry_point; + regs->pc = (uint32_t)entry_point; } diff --git a/ports/arm7a/linker.ld b/ports/arm7a/linker.ld index 8af91e3..f91ed6e 100755 --- a/ports/arm7a/linker.ld +++ b/ports/arm7a/linker.ld @@ -64,75 +64,11 @@ SECTIONS _erodata = .; } - .cmdbtl : - { - PROVIDE(_cmdtbl_start = .); - *(.cmdtbl) - . = ALIGN(4); - PROVIDE(_cmdtbl_end = .); - } - - .modtbl : - { - PROVIDE(_modtbl_start = .); - *(.modtbl) - . = ALIGN(4); - PROVIDE(_modtbl_end = .); - } - - .svc_stack : + .initial_stack : { - PROVIDE(_svc_stack_start = .); + PROVIDE(_initial_stack_start = .); . = . + 4096; . = ALIGN(4); - PROVIDE(_svc_stack_end = .); - } - - .mon_stack : - { - PROVIDE(_mon_stack_start = .); - . = . + 4096; - . = ALIGN(4); - PROVIDE(_mon_stack_end = .); - } - - .abt_stack : - { - PROVIDE(_abt_stack_start = .); - . = . + 4096; - . = ALIGN(4); - PROVIDE(_abt_stack_end = .); - } - - .und_stack : - { - PROVIDE(_und_stack_start = .); - . = . + 4096; - . = ALIGN(4); - PROVIDE(_und_stack_end = .); - } - - .irq_stack : - { - PROVIDE(_irq_stack_start = .); - . = . + 4096; - . = ALIGN(4); - PROVIDE(_irq_stack_end = .); - } - - .fiq_stack : - { - PROVIDE(_fiq_stack_start = .); - . = . + 4096; - . = ALIGN(4); - PROVIDE(_fiq_stack_end = .); - } - - .usr_stack : - { - PROVIDE(_usr_stack_start = .); - . = . + 4096; - . = ALIGN(4); - PROVIDE(_usr_stack_end = .); + PROVIDE(_initial_stack_end = .); } }