1 /* 2 * Copyright (c) 2012-2013 Travis Geiselbrecht 3 * 4 * Use of this source code is governed by a MIT-style 5 * license that can be found in the LICENSE file or at 6 * https://opensource.org/licenses/MIT 7 */ 8 #ifndef __ARCH_ARM_CM_H 9 #define __ARCH_ARM_CM_H 10 11 /* support header for all cortex-m class cpus */ 12 13 #include <lk/compiler.h> 14 #include <stdint.h> 15 #include <stdbool.h> 16 #include <sys/types.h> 17 #include <platform/platform_cm.h> 18 19 #if ARM_CPU_CORTEX_M0 20 #include <core_cm0.h> 21 #elif ARM_CPU_CORTEX_M0_PLUS 22 #include <core_cm0plus.h> 23 #elif ARM_CPU_CORTEX_M3 24 #include <core_cm3.h> 25 #elif ARM_CPU_CORTEX_M4 26 #include <core_cm4.h> 27 #elif ARM_CPU_CORTEX_M7 28 #include <core_cm7.h> 29 #else 30 #error "unknown cortex-m core" 31 #endif 32 33 /* registers dealing with the cycle counter */ 34 #define DWT_CTRL (0xE0001000) 35 #define DWT_CYCCNT (0xE0001004) 36 #define SCB_DEMCR (0xE000EDFC) 37 38 struct arm_cm_exception_frame { 39 uint32_t r4; 40 uint32_t r5; 41 uint32_t r6; 42 uint32_t r7; 43 uint32_t r8; 44 uint32_t r9; 45 uint32_t r10; 46 uint32_t r11; 47 uint32_t r0; 48 uint32_t r1; 49 uint32_t r2; 50 uint32_t r3; 51 uint32_t r12; 52 uint32_t lr; 53 uint32_t pc; 54 uint32_t psr; 55 }; 56 57 struct arm_cm_exception_frame_short { 58 uint32_t r0; 59 uint32_t r1; 60 uint32_t r2; 61 uint32_t r3; 62 uint32_t r12; 63 uint32_t lr; 64 uint32_t pc; 65 uint32_t psr; 66 }; 67 68 struct arm_cm_exception_frame_long { 69 uint32_t r4; 70 uint32_t r5; 71 uint32_t r6; 72 uint32_t r7; 73 uint32_t r8; 74 uint32_t r9; 75 uint32_t r10; 76 uint32_t r11; 77 uint32_t lr; 78 uint32_t r0; 79 uint32_t r1; 80 uint32_t r2; 81 uint32_t r3; 82 uint32_t r12; 83 uint32_t exc_lr; 84 uint32_t pc; 85 uint32_t psr; 86 }; 87 88 /* when fpu context save is enabled, this goes just above psr in the previous structs */ 89 struct arm_cm_exception_frame_fpu { 90 float s[16]; 91 uint32_t fpscr; 92 }; 93 94 #if ARM_CM_DYNAMIC_PRIORITY_SIZE 95 extern unsigned int arm_cm_num_irq_pri_bits; 96 extern unsigned int arm_cm_irq_pri_mask; 97 #else 98 /* if we don't want to calculate the number of priority bits, then assume 99 * the cpu implements 3 (8 priority levels), which is the minimum according to spec. 100 */ 101 #ifndef __NVIC_PRIO_BITS 102 #define __NVIC_PRIO_BITS 3 103 #endif 104 static const unsigned int arm_cm_num_irq_pri_bits = __NVIC_PRIO_BITS; 105 static const unsigned int arm_cm_irq_pri_mask = ~((1 << __NVIC_PRIO_BITS) - 1) & 0xff; 106 #endif 107 108 #if (__CORTEX_M >= 0x03) || (CORTEX_SC >= 300) 109 110 void _arm_cm_set_irqpri(uint32_t pri); 111 arm_cm_set_irqpri(uint32_t pri)112static void arm_cm_set_irqpri(uint32_t pri) { 113 if (__ISCONSTANT(pri)) { 114 if (pri == 0) { 115 __disable_irq(); // cpsid i 116 __set_BASEPRI(0); 117 } else if (pri >= 256) { 118 __set_BASEPRI(0); 119 __enable_irq(); 120 } else { 121 uint32_t _pri = pri & arm_cm_irq_pri_mask; 122 123 if (_pri == 0) 124 __set_BASEPRI(1 << (8 - arm_cm_num_irq_pri_bits)); 125 else 126 __set_BASEPRI(_pri); 127 __enable_irq(); // cpsie i 128 } 129 } else { 130 _arm_cm_set_irqpri(pri); 131 } 132 } 133 #endif 134 arm_cm_highest_priority(void)135static inline uint32_t arm_cm_highest_priority(void) { 136 return 0; 137 } 138 arm_cm_lowest_priority(void)139static inline uint32_t arm_cm_lowest_priority(void) { 140 return (1 << arm_cm_num_irq_pri_bits) - 1; 141 } 142 arm_cm_medium_priority(void)143static inline uint32_t arm_cm_medium_priority(void) { 144 return (1 << (arm_cm_num_irq_pri_bits - 1)); 145 } 146 147 #if (__CORTEX_M >= 0x03) || (CORTEX_SC >= 300) arm_cm_trigger_interrupt(int vector)148static inline void arm_cm_trigger_interrupt(int vector) { 149 NVIC->STIR = vector; 150 } 151 #endif 152 153 arm_cm_trigger_preempt(void)154static inline void arm_cm_trigger_preempt(void) { 155 SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk; 156 } 157 158 159 160 /* systick */ 161 void arm_cm_systick_init(uint32_t mhz); 162 163 /* interrupt glue */ 164 /* 165 * Platform code should put this as the first and last line of their irq handlers. 166 * Pass true to reschedule to request a preempt. 167 */ 168 void arm_cm_irq_entry(void); 169 void arm_cm_irq_exit(bool reschedule); 170 171 /* built in exception vectors */ 172 void _start(void); 173 void _nmi(void); 174 void _hardfault(void); 175 void _memmanage(void); 176 void _busfault(void); 177 void _usagefault(void); 178 void _svc(void); 179 void _debugmonitor(void); 180 void _pendsv(void); 181 void _systick(void); 182 183 #endif 184 185