diff --git a/Project/Src/rt-thread/ports/cpuport.c b/Project/Src/rt-thread/ports/cpuport.c index e74c337..c75dc84 100644 --- a/Project/Src/rt-thread/ports/cpuport.c +++ b/Project/Src/rt-thread/ports/cpuport.c @@ -1,11 +1,7 @@ /* - * File : cpuport.c - * This file is part of RT-Thread RTOS - * COPYRIGHT (C) 2006 - 2014, RT-Thread Development Team + * Copyright (c) 2006-2021, RT-Thread Development Team * - * The license and distribution terms for this file may be - * found in the file LICENSE in this distribution or at - * http://www.rt-thread.org/license/LICENSE + * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes @@ -17,13 +13,21 @@ * 2012-12-23 aozima stack addr align to 8byte. * 2012-12-29 Bernard Add exception hook. * 2013-06-23 aozima support lazy stack optimized. + * 2018-07-24 aozima enhancement hard fault exception handler. + * 2019-07-03 yangjie add __rt_ffs() for armclang. + * 2022-06-12 jonas fixed __rt_ffs() for armclang. */ #include -#define USE_FPU /* ARMCC */ ( (defined ( __CC_ARM ) && defined ( __TARGET_FPU_VFP )) \ - /* IAR */ || (defined ( __ICCARM__ ) && defined ( __ARMVFP__ )) \ +#if /* ARMCC */ ( (defined ( __CC_ARM ) && defined ( __TARGET_FPU_VFP )) \ + /* Clang */ || (defined ( __clang__ ) && defined ( __VFP_FP__ ) && !defined(__SOFTFP__)) \ + /* IAR */ || (defined ( __ICCARM__ ) && defined ( __ARMVFP__ )) \ /* GNU */ || (defined ( __GNUC__ ) && defined ( __VFP_FP__ ) && !defined(__SOFTFP__)) ) +#define USE_FPU 1 +#else +#define USE_FPU 0 +#endif /* exception and interrupt handler table */ rt_uint32_t rt_interrupt_from_thread; @@ -177,14 +181,199 @@ rt_uint8_t *rt_hw_stack_init(void *tentry, * * @param exception_handle the exception handling hook function. */ -void rt_hw_exception_install(rt_err_t (*exception_handle)(void* context)) +void rt_hw_exception_install(rt_err_t (*exception_handle)(void *context)) { rt_exception_hook = exception_handle; } -void rt_hw_hard_fault_exception(struct exception_stack_frame *exception_stack) +#define SCB_CFSR (*(volatile const unsigned *)0xE000ED28) /* Configurable Fault Status Register */ +#define SCB_HFSR (*(volatile const unsigned *)0xE000ED2C) /* HardFault Status Register */ +#define SCB_MMAR (*(volatile const unsigned *)0xE000ED34) /* MemManage Fault Address register */ +#define SCB_BFAR (*(volatile const unsigned *)0xE000ED38) /* Bus Fault Address Register */ +#define SCB_AIRCR (*(volatile unsigned long *)0xE000ED0C) /* Reset control Address Register */ +#define SCB_RESET_VALUE 0x05FA0004 /* Reset value, write to SCB_AIRCR can reset cpu */ + +#define SCB_CFSR_MFSR (*(volatile const unsigned char*)0xE000ED28) /* Memory-management Fault Status Register */ +#define SCB_CFSR_BFSR (*(volatile const unsigned char*)0xE000ED29) /* Bus Fault Status Register */ +#define SCB_CFSR_UFSR (*(volatile const unsigned short*)0xE000ED2A) /* Usage Fault Status Register */ + +static void usage_fault_track(void) { + rt_kprintf("usage fault:\n"); + rt_kprintf("SCB_CFSR_UFSR:0x%02X ", SCB_CFSR_UFSR); + + if(SCB_CFSR_UFSR & (1<<0)) + { + /* [0]:UNDEFINSTR */ + rt_kprintf("UNDEFINSTR "); + } + + if(SCB_CFSR_UFSR & (1<<1)) + { + /* [1]:INVSTATE */ + rt_kprintf("INVSTATE "); + } + + if(SCB_CFSR_UFSR & (1<<2)) + { + /* [2]:INVPC */ + rt_kprintf("INVPC "); + } + + if(SCB_CFSR_UFSR & (1<<3)) + { + /* [3]:NOCP */ + rt_kprintf("NOCP "); + } + + if(SCB_CFSR_UFSR & (1<<8)) + { + /* [8]:UNALIGNED */ + rt_kprintf("UNALIGNED "); + } + + if(SCB_CFSR_UFSR & (1<<9)) + { + /* [9]:DIVBYZERO */ + rt_kprintf("DIVBYZERO "); + } + + rt_kprintf("\n"); +} + +static void bus_fault_track(void) +{ + rt_kprintf("bus fault:\n"); + rt_kprintf("SCB_CFSR_BFSR:0x%02X ", SCB_CFSR_BFSR); + + if(SCB_CFSR_BFSR & (1<<0)) + { + /* [0]:IBUSERR */ + rt_kprintf("IBUSERR "); + } + + if(SCB_CFSR_BFSR & (1<<1)) + { + /* [1]:PRECISERR */ + rt_kprintf("PRECISERR "); + } + + if(SCB_CFSR_BFSR & (1<<2)) + { + /* [2]:IMPRECISERR */ + rt_kprintf("IMPRECISERR "); + } + + if(SCB_CFSR_BFSR & (1<<3)) + { + /* [3]:UNSTKERR */ + rt_kprintf("UNSTKERR "); + } + + if(SCB_CFSR_BFSR & (1<<4)) + { + /* [4]:STKERR */ + rt_kprintf("STKERR "); + } + + if(SCB_CFSR_BFSR & (1<<7)) + { + rt_kprintf("SCB->BFAR:%08X\n", SCB_BFAR); + } + else + { + rt_kprintf("\n"); + } +} + +static void mem_manage_fault_track(void) +{ + rt_kprintf("mem manage fault:\n"); + rt_kprintf("SCB_CFSR_MFSR:0x%02X ", SCB_CFSR_MFSR); + + if(SCB_CFSR_MFSR & (1<<0)) + { + /* [0]:IACCVIOL */ + rt_kprintf("IACCVIOL "); + } + + if(SCB_CFSR_MFSR & (1<<1)) + { + /* [1]:DACCVIOL */ + rt_kprintf("DACCVIOL "); + } + + if(SCB_CFSR_MFSR & (1<<3)) + { + /* [3]:MUNSTKERR */ + rt_kprintf("MUNSTKERR "); + } + + if(SCB_CFSR_MFSR & (1<<4)) + { + /* [4]:MSTKERR */ + rt_kprintf("MSTKERR "); + } + + if(SCB_CFSR_MFSR & (1<<7)) + { + /* [7]:MMARVALID */ + rt_kprintf("SCB->MMAR:%08X\n", SCB_MMAR); + } + else + { + rt_kprintf("\n"); + } +} + +static void hard_fault_track(void) +{ + if(SCB_HFSR & (1UL<<1)) + { + /* [1]:VECTBL, Indicates hard fault is caused by failed vector fetch. */ + rt_kprintf("failed vector fetch\n"); + } + + if(SCB_HFSR & (1UL<<30)) + { + /* [30]:FORCED, Indicates hard fault is taken because of bus fault, + memory management fault, or usage fault. */ + if(SCB_CFSR_BFSR) + { + bus_fault_track(); + } + + if(SCB_CFSR_MFSR) + { + mem_manage_fault_track(); + } + + if(SCB_CFSR_UFSR) + { + usage_fault_track(); + } + } + + if(SCB_HFSR & (1UL<<31)) + { + /* [31]:DEBUGEVT, Indicates hard fault is triggered by debug event. */ + rt_kprintf("debug event\n"); + } +} + +struct exception_info +{ + rt_uint32_t exc_return; + struct stack_frame stack_frame; +}; + +void rt_hw_hard_fault_exception(struct exception_info *exception_info) +{ +#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS) extern long list_thread(void); +#endif + struct exception_stack_frame *exception_stack = &exception_info->stack_frame.exception_stack_frame; + struct stack_frame *context = &exception_info->stack_frame; if (rt_exception_hook != RT_NULL) { @@ -194,32 +383,53 @@ void rt_hw_hard_fault_exception(struct exception_stack_frame *exception_stack) if (result == RT_EOK) return; } - rt_kprintf("psr: 0x%08x\n", exception_stack->psr); - rt_kprintf(" pc: 0x%08x\n", exception_stack->pc); - rt_kprintf(" lr: 0x%08x\n", exception_stack->lr); - rt_kprintf("r12: 0x%08x\n", exception_stack->r12); - rt_kprintf("r03: 0x%08x\n", exception_stack->r3); - rt_kprintf("r02: 0x%08x\n", exception_stack->r2); - rt_kprintf("r01: 0x%08x\n", exception_stack->r1); - rt_kprintf("r00: 0x%08x\n", exception_stack->r0); + rt_kprintf("psr: 0x%08x\n", context->exception_stack_frame.psr); - rt_kprintf("hard fault on thread: %s\n", rt_thread_self()->name); + rt_kprintf("r00: 0x%08x\n", context->exception_stack_frame.r0); + rt_kprintf("r01: 0x%08x\n", context->exception_stack_frame.r1); + rt_kprintf("r02: 0x%08x\n", context->exception_stack_frame.r2); + rt_kprintf("r03: 0x%08x\n", context->exception_stack_frame.r3); + rt_kprintf("r04: 0x%08x\n", context->r4); + rt_kprintf("r05: 0x%08x\n", context->r5); + rt_kprintf("r06: 0x%08x\n", context->r6); + rt_kprintf("r07: 0x%08x\n", context->r7); + rt_kprintf("r08: 0x%08x\n", context->r8); + rt_kprintf("r09: 0x%08x\n", context->r9); + rt_kprintf("r10: 0x%08x\n", context->r10); + rt_kprintf("r11: 0x%08x\n", context->r11); + rt_kprintf("r12: 0x%08x\n", context->exception_stack_frame.r12); + rt_kprintf(" lr: 0x%08x\n", context->exception_stack_frame.lr); + rt_kprintf(" pc: 0x%08x\n", context->exception_stack_frame.pc); -#ifdef RT_USING_FINSH - list_thread(); + if (exception_info->exc_return & (1 << 2)) + { + rt_kprintf("hard fault on thread: %s\r\n\r\n", rt_thread_self()->name); + +#if defined(RT_USING_FINSH) && defined(MSH_USING_BUILT_IN_COMMANDS) + list_thread(); #endif + } + else + { + rt_kprintf("hard fault on handler\r\n\r\n"); + } + + if ( (exception_info->exc_return & 0x10) == 0) + { + rt_kprintf("FPU active!\r\n"); + } + + hard_fault_track(); while (1); } /** - * shutdown CPU + * reset CPU */ -void rt_hw_cpu_shutdown(void) +void rt_hw_cpu_reset(void) { - rt_kprintf("shutdown...\n"); - - RT_ASSERT(0); + SCB_AIRCR = SCB_RESET_VALUE; } #ifdef RT_USING_CPU_FFS @@ -246,6 +456,24 @@ __asm int __rt_ffs(int value) exit BX lr } +#elif defined(__clang__) +int __rt_ffs(int value) +{ + __asm volatile( + "CMP %1, #0x00 \n" + "BEQ 1f \n" + + "RBIT %1, %1 \n" + "CLZ %0, %1 \n" + "ADDS %0, %0, #0x01 \n" + + "1: \n" + + : "=r"(value) + : "r"(value) + ); + return value; +} #elif defined(__IAR_SYSTEMS_ICC__) int __rt_ffs(int value) {