mirror of https://github.com/ARMmbed/mbed-os.git
Modify IRQ handler processing without RTOS at Cortex-A ARM Compiler
In case of unusing RTOS, IRQ handler executes "while(1)" and it causes a program freeze. Therefore, I revised this processing. Also I added the heap setting processing and set the align to 8 byte.pull/9167/head
parent
442cbba141
commit
240060ee69
|
@ -72,7 +72,7 @@ LR_IROM1 MBED_APP_START MBED_APP_SIZE ; load region size_region
|
|||
RW_IRAM1 +0 ALIGN 0x10
|
||||
{ * (+ZI) } ; Application ZI data (.bss)
|
||||
|
||||
ARM_LIB_HEAP +0
|
||||
ARM_LIB_HEAP +0 ALIGN 0x8
|
||||
{ * (HEAP) } ; Application heap area (HEAP)
|
||||
|
||||
ARM_LIB_STACK (__RAM_BASE + __NM_RAM_SIZE) EMPTY -__STACK_SIZE ; Stack region growing down
|
||||
|
|
|
@ -45,16 +45,6 @@
|
|||
void Vectors (void) __attribute__ ((section("RESET")));
|
||||
void Reset_Handler(void);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Exception / Interrupt Handler
|
||||
*----------------------------------------------------------------------------*/
|
||||
void Undef_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void SVC_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void PAbt_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void DAbt_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void IRQ_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void FIQ_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Exception / Interrupt Vector Table
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
@ -153,10 +143,3 @@ goToSleep
|
|||
IMPORT __main
|
||||
BL __main
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Default Handler for Exceptions / Interrupts
|
||||
*----------------------------------------------------------------------------*/
|
||||
void Default_Handler(void) {
|
||||
while(1);
|
||||
}
|
||||
|
|
|
@ -45,17 +45,54 @@ extern char Image$$ARM_LIB_HEAP$$Base[];
|
|||
extern char Image$$ARM_LIB_STACK$$Base[];
|
||||
|
||||
extern __value_in_regs struct __initial_stackheap _mbed_user_setup_stackheap(uint32_t R0, uint32_t R1, uint32_t R2, uint32_t R3) {
|
||||
uint32_t zi_limit = (uint32_t)Image$$ARM_LIB_HEAP$$Base;
|
||||
uint32_t sp_limit = (uint32_t)Image$$ARM_LIB_STACK$$Base;
|
||||
|
||||
zi_limit = (zi_limit + 7) & ~0x7; // ensure zi_limit is 8-byte aligned
|
||||
|
||||
struct __initial_stackheap r;
|
||||
r.heap_base = zi_limit;
|
||||
r.heap_limit = sp_limit;
|
||||
r.heap_base = (uint32_t)Image$$ARM_LIB_HEAP$$Base;
|
||||
r.heap_limit = (uint32_t)Image$$ARM_LIB_STACK$$Base;
|
||||
return r;
|
||||
}
|
||||
|
||||
#if !defined(MBED_CONF_RTOS_PRESENT) || !MBED_CONF_RTOS_PRESENT
|
||||
|
||||
/* The single region memory model would check stack collision at run time, verifying that
|
||||
* the heap pointer is underneath the stack pointer. With two-region memory model/RTOS-less or
|
||||
* multiple threads(stacks)/RTOS, the check gets meaningless and we must disable it. */
|
||||
#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
__asm(".global __use_two_region_memory\n\t");
|
||||
__asm(".global __use_no_semihosting\n\t");
|
||||
#else
|
||||
#pragma import(__use_two_region_memory)
|
||||
#endif
|
||||
|
||||
/* Fix __user_setup_stackheap and ARM_LIB_STACK/ARM_LIB_HEAP cannot co-exist in RTOS-less build
|
||||
*
|
||||
* According AN241 (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0241b/index.html),
|
||||
* __rt_entry has the following call sequence:
|
||||
* 1. _platform_pre_stackheap_init
|
||||
* 2. __user_setup_stackheap or setup the Stack Pointer (SP) by another method
|
||||
* 3. _platform_post_stackheap_init
|
||||
* 4. __rt_lib_init
|
||||
* 5. _platform_post_lib_init
|
||||
* 6. main()
|
||||
* 7. exit()
|
||||
*
|
||||
* Per our check, when __user_setup_stackheap and ARM_LIB_STACK/ARM_LIB_HEAP co-exist, neither
|
||||
* does __user_setup_stackheap get called and nor is ARM_LIB_HEAP used to get heap base/limit,
|
||||
* which are required to pass to __rt_lib_init later. To fix the issue, by subclass'ing
|
||||
* __rt_lib_init, heap base/limit are replaced with Image$$ARM_LIB_HEAP$$ZI$$Base/Limit if
|
||||
* ARM_LIB_HEAP region is defined in scatter file.
|
||||
*
|
||||
* The overriding __rt_lib_init is needed only for rtos-less code. For rtos code, __rt_entry is
|
||||
* overridden and the overriding __rt_lib_init here gets meaningless.
|
||||
*/
|
||||
extern __value_in_regs struct __argc_argv $Super$$__rt_lib_init(unsigned heapbase, unsigned heaptop);
|
||||
|
||||
__value_in_regs struct __argc_argv $Sub$$__rt_lib_init (unsigned heapbase, unsigned heaptop)
|
||||
{
|
||||
return $Super$$__rt_lib_init((unsigned)Image$$ARM_LIB_HEAP$$Base, (unsigned)Image$$ARM_LIB_STACK$$Base);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2018 Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* Project: CMSIS-RTOS RTX
|
||||
* Title: Cortex-A Exception handlers
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "core_ca.h"
|
||||
|
||||
#define MODE_SVC 0x13
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Exception / Interrupt Handler
|
||||
*----------------------------------------------------------------------------*/
|
||||
void Undef_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void SVC_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void PAbt_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void DAbt_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void FIQ_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Default Handler for Exceptions / Interrupts
|
||||
*----------------------------------------------------------------------------*/
|
||||
void Default_Handler(void) {
|
||||
while(1);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Default IRQ Handler for Exceptions / Interrupts
|
||||
*----------------------------------------------------------------------------*/
|
||||
__WEAK __ASM void IRQ_Handler(void) {
|
||||
IMPORT IRQ_GetActiveIRQ
|
||||
IMPORT IRQ_GetHandler
|
||||
IMPORT IRQ_EndOfInterrupt
|
||||
|
||||
SUB LR, LR, #4 // Pre-adjust LR
|
||||
SRSFD SP!, #MODE_SVC // Save LR_irq and SPSR_irq on to the SVC stack
|
||||
CPS #MODE_SVC // Change to SVC mode
|
||||
PUSH {R0-R3, R12, LR} // Save APCS corruptible registers
|
||||
|
||||
MOV R3, SP // Move SP into R3
|
||||
AND R3, R3, #4 // Get stack adjustment to ensure 8-byte alignment
|
||||
SUB SP, SP, R3 // Adjust stack
|
||||
PUSH {R3, R4} // Store stack adjustment(R3) and user data(R4)
|
||||
|
||||
BLX IRQ_GetActiveIRQ // Retrieve interrupt ID into R0
|
||||
MOV R4, R0 // Move interrupt ID to R4
|
||||
|
||||
BLX IRQ_GetHandler // Retrieve interrupt handler address for current ID
|
||||
CMP R0, #0 // Check if handler address is 0
|
||||
BEQ IRQ_End // If 0, end interrupt and return
|
||||
|
||||
CPSIE i // Re-enable interrupts
|
||||
BLX R0 // Call IRQ handler
|
||||
CPSID i // Disable interrupts
|
||||
|
||||
IRQ_End
|
||||
MOV R0, R4 // Move interrupt ID to R0
|
||||
BLX IRQ_EndOfInterrupt // Signal end of interrupt
|
||||
|
||||
POP {R3, R4} // Restore stack adjustment(R3) and user data(R4)
|
||||
ADD SP, SP, R3 // Unadjust stack
|
||||
|
||||
POP {R0-R3, R12, LR} // Restore stacked APCS registers
|
||||
RFEFD SP! // Return from IRQ handler
|
||||
}
|
|
@ -72,7 +72,7 @@ LR_IROM1 MBED_APP_START MBED_APP_SIZE ; load region size_region
|
|||
RW_IRAM1 +0 ALIGN 0x10
|
||||
{ * (+ZI) } ; Application ZI data (.bss)
|
||||
|
||||
ARM_LIB_HEAP +0
|
||||
ARM_LIB_HEAP +0 ALIGN 0x8
|
||||
{ * (HEAP) } ; Application heap area (HEAP)
|
||||
|
||||
ARM_LIB_STACK (__RAM_BASE + __NM_RAM_SIZE) EMPTY -__STACK_SIZE ; Stack region growing down
|
||||
|
|
|
@ -45,16 +45,6 @@
|
|||
void Vectors (void) __attribute__ ((section("RESET")));
|
||||
void Reset_Handler(void);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Exception / Interrupt Handler
|
||||
*----------------------------------------------------------------------------*/
|
||||
void Undef_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void SVC_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void PAbt_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void DAbt_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void IRQ_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void FIQ_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Exception / Interrupt Vector Table
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
@ -153,10 +143,3 @@ goToSleep
|
|||
IMPORT __main
|
||||
BL __main
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Default Handler for Exceptions / Interrupts
|
||||
*----------------------------------------------------------------------------*/
|
||||
void Default_Handler(void) {
|
||||
while(1);
|
||||
}
|
||||
|
|
|
@ -45,17 +45,54 @@ extern char Image$$ARM_LIB_HEAP$$Base[];
|
|||
extern char Image$$ARM_LIB_STACK$$Base[];
|
||||
|
||||
extern __value_in_regs struct __initial_stackheap _mbed_user_setup_stackheap(uint32_t R0, uint32_t R1, uint32_t R2, uint32_t R3) {
|
||||
uint32_t zi_limit = (uint32_t)Image$$ARM_LIB_HEAP$$Base;
|
||||
uint32_t sp_limit = (uint32_t)Image$$ARM_LIB_STACK$$Base;
|
||||
|
||||
zi_limit = (zi_limit + 7) & ~0x7; // ensure zi_limit is 8-byte aligned
|
||||
|
||||
struct __initial_stackheap r;
|
||||
r.heap_base = zi_limit;
|
||||
r.heap_limit = sp_limit;
|
||||
r.heap_base = (uint32_t)Image$$ARM_LIB_HEAP$$Base;
|
||||
r.heap_limit = (uint32_t)Image$$ARM_LIB_STACK$$Base;
|
||||
return r;
|
||||
}
|
||||
|
||||
#if !defined(MBED_CONF_RTOS_PRESENT) || !MBED_CONF_RTOS_PRESENT
|
||||
|
||||
/* The single region memory model would check stack collision at run time, verifying that
|
||||
* the heap pointer is underneath the stack pointer. With two-region memory model/RTOS-less or
|
||||
* multiple threads(stacks)/RTOS, the check gets meaningless and we must disable it. */
|
||||
#if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050)
|
||||
__asm(".global __use_two_region_memory\n\t");
|
||||
__asm(".global __use_no_semihosting\n\t");
|
||||
#else
|
||||
#pragma import(__use_two_region_memory)
|
||||
#endif
|
||||
|
||||
/* Fix __user_setup_stackheap and ARM_LIB_STACK/ARM_LIB_HEAP cannot co-exist in RTOS-less build
|
||||
*
|
||||
* According AN241 (http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0241b/index.html),
|
||||
* __rt_entry has the following call sequence:
|
||||
* 1. _platform_pre_stackheap_init
|
||||
* 2. __user_setup_stackheap or setup the Stack Pointer (SP) by another method
|
||||
* 3. _platform_post_stackheap_init
|
||||
* 4. __rt_lib_init
|
||||
* 5. _platform_post_lib_init
|
||||
* 6. main()
|
||||
* 7. exit()
|
||||
*
|
||||
* Per our check, when __user_setup_stackheap and ARM_LIB_STACK/ARM_LIB_HEAP co-exist, neither
|
||||
* does __user_setup_stackheap get called and nor is ARM_LIB_HEAP used to get heap base/limit,
|
||||
* which are required to pass to __rt_lib_init later. To fix the issue, by subclass'ing
|
||||
* __rt_lib_init, heap base/limit are replaced with Image$$ARM_LIB_HEAP$$ZI$$Base/Limit if
|
||||
* ARM_LIB_HEAP region is defined in scatter file.
|
||||
*
|
||||
* The overriding __rt_lib_init is needed only for rtos-less code. For rtos code, __rt_entry is
|
||||
* overridden and the overriding __rt_lib_init here gets meaningless.
|
||||
*/
|
||||
extern __value_in_regs struct __argc_argv $Super$$__rt_lib_init(unsigned heapbase, unsigned heaptop);
|
||||
|
||||
__value_in_regs struct __argc_argv $Sub$$__rt_lib_init (unsigned heapbase, unsigned heaptop)
|
||||
{
|
||||
return $Super$$__rt_lib_init((unsigned)Image$$ARM_LIB_HEAP$$Base, (unsigned)Image$$ARM_LIB_STACK$$Base);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2018 Arm Limited. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*
|
||||
* Project: CMSIS-RTOS RTX
|
||||
* Title: Cortex-A Exception handlers
|
||||
*
|
||||
* -----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "core_ca.h"
|
||||
|
||||
#define MODE_SVC 0x13
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Exception / Interrupt Handler
|
||||
*----------------------------------------------------------------------------*/
|
||||
void Undef_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void SVC_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void PAbt_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void DAbt_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
void FIQ_Handler (void) __attribute__ ((weak, alias("Default_Handler")));
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Default Handler for Exceptions / Interrupts
|
||||
*----------------------------------------------------------------------------*/
|
||||
void Default_Handler(void) {
|
||||
while(1);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
Default IRQ Handler for Exceptions / Interrupts
|
||||
*----------------------------------------------------------------------------*/
|
||||
__WEAK __ASM void IRQ_Handler(void) {
|
||||
IMPORT IRQ_GetActiveIRQ
|
||||
IMPORT IRQ_GetHandler
|
||||
IMPORT IRQ_EndOfInterrupt
|
||||
|
||||
SUB LR, LR, #4 // Pre-adjust LR
|
||||
SRSFD SP!, #MODE_SVC // Save LR_irq and SPSR_irq on to the SVC stack
|
||||
CPS #MODE_SVC // Change to SVC mode
|
||||
PUSH {R0-R3, R12, LR} // Save APCS corruptible registers
|
||||
|
||||
MOV R3, SP // Move SP into R3
|
||||
AND R3, R3, #4 // Get stack adjustment to ensure 8-byte alignment
|
||||
SUB SP, SP, R3 // Adjust stack
|
||||
PUSH {R3, R4} // Store stack adjustment(R3) and user data(R4)
|
||||
|
||||
BLX IRQ_GetActiveIRQ // Retrieve interrupt ID into R0
|
||||
MOV R4, R0 // Move interrupt ID to R4
|
||||
|
||||
BLX IRQ_GetHandler // Retrieve interrupt handler address for current ID
|
||||
CMP R0, #0 // Check if handler address is 0
|
||||
BEQ IRQ_End // If 0, end interrupt and return
|
||||
|
||||
CPSIE i // Re-enable interrupts
|
||||
BLX R0 // Call IRQ handler
|
||||
CPSID i // Disable interrupts
|
||||
|
||||
IRQ_End
|
||||
MOV R0, R4 // Move interrupt ID to R0
|
||||
BLX IRQ_EndOfInterrupt // Signal end of interrupt
|
||||
|
||||
POP {R3, R4} // Restore stack adjustment(R3) and user data(R4)
|
||||
ADD SP, SP, R3 // Unadjust stack
|
||||
|
||||
POP {R0-R3, R12, LR} // Restore stacked APCS registers
|
||||
RFEFD SP! // Return from IRQ handler
|
||||
}
|
Loading…
Reference in New Issue