First version
[3rdparty/ote_partner/tlk.git] / arch / arm / arm-m / include / arch / arm / cm3.h
1 /*
2  * Copyright (c) 2012 Travis Geiselbrecht
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining
5  * a copy of this software and associated documentation files
6  * (the "Software"), to deal in the Software without restriction,
7  * including without limitation the rights to use, copy, modify, merge,
8  * publish, distribute, sublicense, and/or sell copies of the Software,
9  * and to permit persons to whom the Software is furnished to do so,
10  * subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22  */
23 #ifndef __ARCH_ARM_CM3_H
24 #define __ARCH_ARM_CM3_H
25
26 #include <platform/platform_cm3.h>
27 #include <core_cm3.h>
28
29 /* registers dealing with the cycle counter */
30 #define DWT_CTRL (0xE0001000)
31 #define DWT_CYCCNT (0xE0001004)
32 #define SCB_DEMCR (0xE000EDFC)
33
34 struct cm3_exception_frame {
35         uint32_t r4;
36         uint32_t r5;
37         uint32_t r6;
38         uint32_t r7;
39         uint32_t r8;
40         uint32_t r9;
41         uint32_t r10;
42         uint32_t r11;
43         uint32_t r0;
44         uint32_t r1;
45         uint32_t r2;
46         uint32_t r3;
47         uint32_t r12;
48         uint32_t lr;
49         uint32_t pc;
50         uint32_t psr;
51 };
52
53 struct cm3_exception_frame_short {
54         uint32_t r0;
55         uint32_t r1;
56         uint32_t r2;
57         uint32_t r3;
58         uint32_t r12;
59         uint32_t lr;
60         uint32_t pc;
61         uint32_t psr;
62 };
63
64 struct cm3_exception_frame_long {
65         uint32_t r4;
66         uint32_t r5;
67         uint32_t r6;
68         uint32_t r7;
69         uint32_t r8;
70         uint32_t r9;
71         uint32_t r10;
72         uint32_t r11;
73         uint32_t lr;
74         uint32_t r0;
75         uint32_t r1;
76         uint32_t r2;
77         uint32_t r3;
78         uint32_t r12;
79         uint32_t exc_lr;
80         uint32_t pc;
81         uint32_t psr;
82 };
83
84 #if ARM_M_DYNAMIC_PRIORITY_SIZE
85 extern unsigned int cm3_num_irq_pri_bits;
86 extern unsigned int cm3_irq_pri_mask;
87 #else
88 /* if we don't want to calculate the nubmer of priority bits, then assume
89  * the cpu implements 3 (8 priority levels), which is the minimum according to spec.
90  */
91 #ifndef ARM_M_PRIORITY_BITS
92 #define ARM_M_PRIORITY_BITS 3
93 #endif
94 static const unsigned int cm3_num_irq_pri_bits = 8 - ARM_M_PRIORITY_BITS;
95 static const unsigned int cm3_irq_pri_mask = ~((1 << ARM_M_PRIORITY_BITS) - 1) & 0xff;
96 #endif
97
98 void _cm3_set_irqpri(uint32_t pri);
99
100 static __ALWAYS_INLINE void cm3_set_irqpri(uint32_t pri)
101 {
102         if (__ISCONSTANT(pri)) {
103                 if (pri == 0) {
104                         __disable_irq(); // cpsid i
105                         __set_BASEPRI(0);
106                 } else if (pri >= 256) {
107                         __set_BASEPRI(0);
108                         __enable_irq();
109                 } else {
110                         uint32_t _pri = pri & cm3_irq_pri_mask;
111
112                         if (_pri == 0)
113                                 __set_BASEPRI(1 << (8 - cm3_num_irq_pri_bits));
114                         else
115                                 __set_BASEPRI(_pri);
116                         __enable_irq(); // cpsie i
117                 }
118         } else {
119                 _cm3_set_irqpri(pri);
120         }
121 }
122
123
124 static __ALWAYS_INLINE inline uint32_t cm3_highest_priority(void)
125 {
126         return (1 << (8 - cm3_num_irq_pri_bits));
127 }
128
129 static __ALWAYS_INLINE inline uint32_t cm3_lowest_priority(void)
130 {
131         return (255 & cm3_irq_pri_mask) & 0xff;
132 }
133
134 static __ALWAYS_INLINE inline uint32_t cm3_medium_priority(void)
135 {
136         return (128 & cm3_irq_pri_mask) & 0xff;
137 }
138
139 static __ALWAYS_INLINE inline void cm3_trigger_interrupt(int vector)
140 {
141         NVIC->STIR = vector;
142 }
143
144 static __ALWAYS_INLINE inline void cm3_trigger_preempt(void)
145 {
146         SCB->ICSR |= SCB_ICSR_PENDSVSET_Msk;
147 }
148
149 /* systick */
150 void cm3_systick_init(void);
151 void cm3_systick_set_periodic(uint32_t systick_clk_freq, lk_time_t period);
152 void cm3_systick_cancel_periodic(void);
153 /* extern void _systick(void); // override this */
154
155 #endif
156