aboutsummaryrefslogtreecommitdiff
path: root/include/libopencmsis/core_cm3.h
blob: 5ad132792f64c20c0357cb4d80965b9a96db4bcb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/* big fat FIXME: this should use a consistent structure, and reference
 * functionality from libopencm3 instead of copypasting.
 *
 * particularly unimplemented features are FIXME'd extra
 * */

#ifndef OPENCMSIS_CORECM3_H
#define OPENCMSIS_CORECM3_H

/* needed in various places where we rather should include libopencm3 functionality */
#define MMIO32(addr)                    (*(volatile uint32_t *)(addr))

/* the original core_cm3.h is nonfree by arm; this provides libopencm3 variant of the symbols efm32lib needs of CMSIS. */
#include <stdint.h>

/* needed by system_efm32.h:196, guessing */
#define __INLINE inline
/* new since emlib 3.0 */
#define __STATIC_INLINE static inline

/* needed around efm32tg840f32.h:229. comparing the efm32lib definitions to the
 * libopencm3 ones, "volatile" is all that's missing. */
#define __IO volatile
#define __O volatile
#define __I volatile

/* -> style access for what is defined in libopencm3/stm32/f1/scb.h /
 * cm3/memorymap.h, as it's needed by efm32lib/inc/efm32_emu.h */

/* from stm32/f1/scb.h */
#define SCB_SCR_SLEEPDEEP_Msk  (1 << 2)
/* structure as in, for example,
 * DeviceSupport/EnergyMicro/EFM32/efm32tg840f32.h, data from
 * libopencm3/stm32/f1/scb.h. FIXME incomplete. */
typedef struct
{
	__IO uint32_t CPUID;
	__IO uint32_t ICSR;
	__IO uint32_t VTOR;
	__IO uint32_t AIRCR;
	__IO uint32_t SCR;
	__IO uint32_t CCR;
	__IO uint8_t SHPR[12]; /* FIXME: how is this properly indexed? */
	__IO uint32_t SHCSR;
} SCB_TypeDef;
#define SCB ((SCB_TypeDef *) SCB_BASE)
/* from libopencm3/cm3/memorymap.h */
#define PPBI_BASE                       0xE0000000
#define SCS_BASE                        (PPBI_BASE + 0xE000)
#define SCB_BASE                        (SCS_BASE + 0x0D00)

/* needed by efm32_emu.h, guessing and taking the implementation used in
 * lightswitch-interrupt.c */
#define __WFI() __asm__("wfi")

/* needed by efm32_cmu.h, probably it's just what gcc provides anyway */
#define __CLZ(div) __builtin_clz(div)

/* needed by efm32_aes.c. __builtin_bswap32 does the same thing as the rev instruction according to https://bugzilla.mozilla.org/show_bug.cgi?id=600106 */
#define __REV(x) __builtin_bswap32(x)

/* stubs for efm32_dbg.h */
typedef struct
{
	uint32_t DHCSR;
	uint32_t DEMCR; /* needed by efm32tg stk trace.c */
} CoreDebug_TypeDef;
/* FIXME let's just hope writes to flash are protected */
#define CoreDebug ((CoreDebug_TypeDef *) 0)
#define CoreDebug_DHCSR_C_DEBUGEN_Msk 0
#define CoreDebug_DEMCR_TRCENA_Msk 0

/* stubs for efm32_dma */

/* also used by the clock example. code taken from stm32's nvic.[hc], FIXME until
 * the generic cm3 functionality is moved out from stm32 and can be used here
 * easily (nvic_clear_pending_irq, nvic_enable_irq, nvic_disable_irq). */
#define NVIC_BASE                       (SCS_BASE + 0x0100)
#define NVIC_ISER(iser_id)		MMIO32(NVIC_BASE + 0x00 + (iser_id * 4))
#define NVIC_ICER(icer_id)		MMIO32(NVIC_BASE + 0x80 + (icer_id * 4))
#define NVIC_ICPR(icpr_id)		MMIO32(NVIC_BASE + 0x180 + (icpr_id * 4))
static inline void NVIC_ClearPendingIRQ(uint8_t irqn)
{
	NVIC_ICPR(irqn / 32) = (1 << (irqn % 32));
}
static inline void NVIC_EnableIRQ(uint8_t irqn)
{
	NVIC_ISER(irqn / 32) = (1 << (irqn % 32));
}
static inline void NVIC_DisableIRQ(uint8_t irqn)
{
	NVIC_ICER(irqn / 32) = (1 << (irqn % 32));
}

/* stubs for efm32_int. FIXME: how do they do that? nvic documentation in the
 * efm32 core manual doesn't tell anything of a global on/off switch */

#define __enable_irq() 1
#define __disable_irq() 1

/* stubs for efm32_mpu FIXME */

#define SCB_SHCSR_MEMFAULTENA_Msk 0

typedef struct
{
	uint32_t CTRL;
	uint32_t RNR;
	uint32_t RBAR;
	uint32_t RASR;
} MPU_TypeDef;
/* FIXME struct at NULL */
#define MPU ((MPU_TypeDef *) 0)
#define MPU_CTRL_ENABLE_Msk 0
#define MPU_RASR_XN_Pos 0
#define MPU_RASR_AP_Pos 0
#define MPU_RASR_TEX_Pos 0
#define MPU_RASR_S_Pos 0
#define MPU_RASR_C_Pos 0
#define MPU_RASR_B_Pos 0
#define MPU_RASR_SRD_Pos 0
#define MPU_RASR_SIZE_Pos 0
#define MPU_RASR_ENABLE_Pos 0

/* required for the blink example */

/* if if (SysTick_Config(CMU_ClockFreqGet(cmuClock_CORE) / 1000)) while (1) ;
 * configures the sys ticks to 1ms, then the argument to SysTick_Config
 * describes how many cycles to wait between two systicks.
 *
 * the endless loop part looks like an "if it returns an error condition,
 * rather loop here than continue"; every other solution would involve things
 * that are dark magic to my understanding.
 *
 * implementation more or less copypasted from lib/stm32/systick.c, FIXME until
 * the generic cm3 functionality is moved out from stm32 and can be used here
 * easily (systick_set_reload, systick_interrupt_enable, systick_counter_enable
 * and systick_set_clocksource).
 *
 * modified for CMSIS style array as the powertest example needs it.
 * */
#define SYS_TICK_BASE                   (SCS_BASE + 0x0010)

/* from d0002_efm32_cortex-m3_reference_manual.pdf section 4.4 */
typedef struct
{
	uint32_t CTRL;
	uint32_t LOAD;
	uint32_t VAL;
	uint32_t CALIB;
} SysTick_TypeDef;
#define SysTick ((SysTick_TypeDef *) SYS_TICK_BASE)

#define STK_CTRL_TICKINT		(1 << 1)
#define STK_CTRL_ENABLE			(1 << 0)

#define STK_CTRL_CLKSOURCE_LSB		2
#define STK_CTRL_CLKSOURCE_AHB		1
static inline uint32_t SysTick_Config(uint32_t n_ticks)
{
	if (n_ticks & ~0x00FFFFFF) return 1;
	SysTick->LOAD = n_ticks;

	SysTick->CTRL |= (STK_CTRL_CLKSOURCE_AHB << STK_CTRL_CLKSOURCE_LSB);

	SysTick->CTRL |= STK_CTRL_TICKINT;

	SysTick->CTRL |= STK_CTRL_ENABLE;

	return 0;
}

/* stubs for efm32tg stk trace.c */
typedef struct
{
	uint32_t LAR;
	uint32_t TCR;
} ITM_TypeDef;
/* FIXME struct at NULL */
#define ITM ((ITM_TypeDef *) 0)

/* blink.h expects the isr for systicks to be named SysTick_Handler. with this,
 * its Systick_Handler function gets renamed to the weak symbol exported by
 * vector.c */
#define SysTick_Handler sys_tick_handler

/* likewise, clock.c defines GPIO_ODD_IRQHandler and GPIO_EVEN_IRQHandler */
#define GPIO_ODD_IRQHandler gpio_odd_isr
#define GPIO_EVEN_IRQHandler gpio_even_isr
#define RTC_IRQHandler rtc_isr

/* for inttemp (i should really get a list and convert them all) */

#define ADC0_IRQHandler adc0_isr

/* for the lightsense example */

#define LESENSE_IRQHandler lesense_isr
#define PCNT0_IRQHandler pcnt0_isr

#endif