Initial commit, code based on LPC1224 support and LPC812-MAX CMSIS-DAP interface...
[lpc11u3x] / include / core / lpc_core_cm0.h
1 /****************************************************************************
2  *   core/lpc_core_cm0.h
3  *
4  * Helper functions to access some registers and Cortex M0 core functionalities.
5  *
6  *
7  * Most of the code from here comes from CMSIS. Should this be rewritten ?
8  *
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
22  *
23  *************************************************************************** */
25 #ifndef LPC_CORE_CM0_H
26 #define LPC_CORE_CM0_H
28 #include <stdint.h>   /* standard types definitions */
29 #include "core/lpc_regs_11u3x.h"
32 /*******************************************************************************/
33 /*                Core Instructions                                            */
34 /*******************************************************************************/
35 /* NOP */
36 #define nop() __asm volatile ("nop" : : : "memory")
37 /* SEV : Send Event */
38 #define sev() __asm volatile ("sev" : : : "memory")
39 /* WFE : Wait For Event */
40 #define wfe() __asm volatile ("wfe" : : : "memory")
41 /* WFI : Wait For Interrupt */
42 #define wfi() __asm volatile ("wfi" : : : "memory")
45 /* Synchronization */
46 /* Instruction Synchronization Barrier : Flushes pipeline */
47 #define isb() __asm volatile ("isb" : : : "memory")
48 /* Data Synchronization Barrier : All explicit memory access completed */
49 #define dsb() __asm volatile ("dsb" : : : "memory")
50 /* Data Memory Barrier : Ensures apparent order but not completion */
51 #define dmb() __asm volatile ("dmb" : : : "memory")
55 /* Access to the Application Program Status Register (APSR). */
56 static inline uint32_t get_APSR(void)
57 {
58         uint32_t r; __asm volatile ("mrs %0, apsr" : "=r" (r)); return (r);
59 }
60 #define APSR_SATURATION  (get_APSR & (0x1 << 27))  /* bit 27  Saturation condition flag */
61 #define APSR_OVERFLOW    (get_APSR & (0x1 << 28))  /* bit 28  Overflow condition code flag */
62 #define APSR_CARRY       (get_APSR & (0x1 << 29))  /* bit 29  Carry condition code flag */
63 #define APSR_ZERO        (get_APSR & (0x1 << 30))  /* bit 30  Zero condition code flag */
64 #define APSR_NEGATIVE    (get_APSR & (0x1 << 31))  /* bit 31  Negative condition code flag */
67 /* Access the Interrupt Program Status Register (IPSR). */
68 static inline uint32_t get_IPSR(void)
69 {
70         uint32_t r; __asm volatile ("mrs %0, ipsr" : "=r" (r)); return (r);
71 }
72 #define IPSR      (get_IPSR & 0x1FF)  /* bit:  0..8  Exception number */
73 #define IPSR_IRQ0 16
74 #define IRQ_NUM   (IPSR - IPSR_IRQ0)
77 /* Control Register */
78 static inline uint32_t get_CONTROL(void)
79 {
80         uint32_t r; __asm volatile ("mrs %0, control" : "=r" (r)); return (r);
81 }
82 static inline void set_CONTROL(uint32_t control)
83 {
84         __asm volatile ("msr control, %0" : : "r" (control));
85 }
88 /* Process Stack Pointer */
89 static inline uint32_t get_process_stack_pointer(void)
90 {
91         register uint32_t r; __asm volatile ("mrs %0, psp" : "=r" (r)); return (r);
92 }
93 static inline void set_process_stack_pointer(uint32_t top_of_stack)
94 {
95         __asm volatile ("msr psp, %0" : : "r" (top_of_stack));
96 }
99 /* Main Stack Pointer */
100 static inline uint32_t get_main_stack_pointer(void)
102         register uint32_t r; __asm volatile ("mrs %0, msp" : "=r" (r)); return (r);
104 static inline void set_main_stack_pointer(uint32_t top_of_stack)
106         __asm volatile ("msr msp, %0" : : "r" (top_of_stack));
110 /* Priority Mask */
111 static inline uint32_t get_priority_mask(void)
113         uint32_t r; __asm volatile ("mrs %0, primask" : "=r" (r)); return (r);
115 static inline void set_priority_mask(uint32_t mask)
117         __asm volatile ("msr primask, %0" : : "r" (mask));
121 /* Base Priority */
122 static inline uint32_t get_base_priority(void)
124         uint32_t r; __asm volatile ("mrs %0, basepri_max" : "=r" (r)); return (r);
126 static inline void set_base_priority(uint32_t prio)
128         __asm volatile ("msr basepri, %0" : : "r" (prio));
132 /* Fault Mask */
133 static inline uint32_t get_fault_mask(void)
135         uint32_t r; __asm volatile ("mrs %0, faultmask" : "=r" (r)); return (r);
137 static inline void set_fault_mask(uint32_t mask)
139         __asm volatile ("msr faultmask, %0" : : "r" (mask));
144 /*******************************************************************************/
145 /*            Byte swap instructions                                           */
146 /*******************************************************************************/
147 /* Swap bytes of each 16-bit halfword in a 32-bit word, keeping halfword order */
148 static inline uint32_t double_byte_swap_16(volatile uint32_t value)
150         uint32_t result = 0;
151         __asm volatile ("rev16 %0, %1" : "=l" (result) : "l" (value));
152         return result;
154 /* Change endianness of a 16-bit halfword */
155 static inline uint32_t byte_swap_16(volatile uint16_t value)
157         uint32_t result = 0;
158         __asm volatile ("rev16 %0, %1" : "=l" (result) : "l" (value));
159         return (result & 0xFFFF);
161 /* Change endianness of a 32-bit word */
162 static inline uint32_t byte_swap_32(volatile uint32_t value)
164         uint32_t result = 0;
165         __asm volatile ("rev %0, %1" : "=l" (result) : "l" (value));
166         return result;
173 /*******************************************************************************/
174 /*            Interrupts                                                       */
175 /*******************************************************************************/
177 /* Cortex-M0 Processor Exceptions Numbers */
178 /* Note : entry 0 is "end stack pointer" */
179 #define RESET_IRQ       ( -15 ) /*  1 - Reset ... not an interrupt ... */
180 #define NMI_IRQ         ( -14 ) /*  2 - Non Maskable Interrupt */
181 #define HARD_FAULT_IRQ  ( -13 ) /*  3 - Cortex-M0 Hard Fault Interrupt */
182 /* Note : entry 7 is the 2’s complement of the check-sum of the previous 7 entries */
183 #define SV_CALL_IRQ     (  -5 ) /* 11 - Cortex-M0 Supervisor Call Interrupt */
184 #define PEND_SV_IRQ     (  -2 ) /* 14 - Cortex-M0 Pend SV Interrupt */
185 #define SYSTICK_IRQ     (  -1 ) /* 15 - Cortex-M0 System Tick Interrupt */
186 /* LPC12xx Specific Interrupt Numbers */
187 #define PIN_INT0_IRQ       0   /* I/O pins can be used as wakeup source. */
188 #define PIN_INT1_IRQ       1
189 #define PIN_INT2_IRQ       2
190 #define PIN_INT3_IRQ       3
191 #define PIN_INT4_IRQ       4
192 #define PIN_INT5_IRQ       5
193 #define PIN_INT6_IRQ       6
194 #define PIN_INT7_IRQ       7
195 #define GRP_INT0_IRQ       8
196 #define GRP_INT1_IRQ       9
197 #define SSP1_IRQ          14  /* 14 - SSP 1 */
198 #define I2C0_IRQ          15  /* 15 - I2C 0 */
199 #define TIMER0_IRQ        16  /* 16 - Timer 0 */
200 #define TIMER1_IRQ        17  /* 17 - Timer 1 */
201 #define TIMER2_IRQ        18  /* 18 - Timer 2 */
202 #define TIMER3_IRQ        19  /* 19 - Timer 3 */
203 #define SSP0_IRQ          20  /* 20 - SSP 0 */
204 #define UART0_IRQ         21  /* 21 - UART 0 */
205 #define USB_IRQ           22  /* 22 - USB */
206 #define USB_FIQ_IRQ       23  /* 23 - USB FIQ */
207 #define ADC_IRQ           24  /* 24 - A/D Converter */
208 #define WDT_IRQ           25  /* 25 - Watchdog */
209 #define BOD_IRQ           26  /* 26 - Brown Out Detect(BOD) */
210 #define FLASH_IRQ         27  /* 27 - Flash / EEPROM */
211 #define USB_WAKEUP_IRQ    30  /* 26 - USB Wakeup */
212 #define IOH_IRQ           31  /* 27 - I/O Handler */
215 /* Enable IRQ Interrupts
216   Enables IRQ interrupts by clearing the I-bit in the CPSR.
217   Can only be executed in Privileged modes.
218  */
219 static inline void lpc_enable_irq(void)
221         __asm volatile ("cpsie i");
224 /* Disable IRQ Interrupts
225   Disables IRQ interrupts by setting the I-bit in the CPSR.
226   Can only be executed in Privileged modes.
227  */
228 static inline void lpc_disable_irq(void)
230         __asm volatile ("cpsid i");
234 /*******************************************************************************/
235 /*                Hardware Abstraction Layer : NVIC Functions                  */
236 /*******************************************************************************/
237 /*  Enable External Interrupt
238   This function enables a device specific interrupt in the NVIC interrupt controller.
239   The interrupt number cannot be a negative value.
240   IRQ : Number of the external interrupt to enable
241  */
242 static inline void NVIC_EnableIRQ(uint32_t IRQ)
244         struct nvic_regs* nvic = LPC_NVIC;
245         nvic->int_set_enable = (1 << (IRQ & 0x1F));
248 /*  Disable External Interrupt
249   This function disables a device specific interupt in the NVIC interrupt controller.
250   The interrupt number cannot be a negative value.
251   IRQ : Number of the external interrupt to disable
252  */
253 static inline void NVIC_DisableIRQ(uint32_t IRQ)
255         struct nvic_regs* nvic = LPC_NVIC;
256         nvic->int_clear_enable = (1 << (IRQ & 0x1F));
259 /*  Get Pending Interrupt
260   This function reads the pending register in the NVIC and returns the pending bit
261     for the specified interrupt.
262   IRQ : Number of the interrupt for get pending
263   return :
264      0  Interrupt status is not pending
265      1  Interrupt status is pending
266  */
267 static inline uint32_t NVIC_GetPendingIRQ(uint32_t IRQ)
269         struct nvic_regs* nvic = LPC_NVIC;
270         return (uint32_t)((nvic->int_set_pending & (1 << (IRQ & 0x1F)))?1:0);
273 /*  Set Pending Interrupt
274   This function sets the pending bit for the specified interrupt.
275   The interrupt number cannot be a negative value.
276   IRQ : Number of the interrupt for set pending
277  */
278 static inline void NVIC_SetPendingIRQ(uint32_t IRQ)
280         struct nvic_regs* nvic = LPC_NVIC;
281         nvic->int_set_pending = (1 << (IRQ & 0x1F));
284 /*  Clear Pending Interrupt
285   This function clears the pending bit for the specified interrupt.
286   The interrupt number cannot be a negative value.
287   IRQ : Number of the interrupt for clear pending
288  */
289 static inline void NVIC_ClearPendingIRQ(uint32_t IRQ)
291         struct nvic_regs* nvic = LPC_NVIC;
292         nvic->int_clear_pending = (1 << (IRQ & 0x1F));
296 /* The following MACROS handle generation of the register offset and byte masks */
297 #define LPC_NVIC_PRIO_BITS  5  /* Number of Bits used for Priority Levels */
298 #define LPC_IRQ_BIT_SHIFT(IRQ) (((uint32_t)(IRQ) & 0x03) * 8)
299 #define LPC_IRQ_SHP_IDX(IRQ)   ((((int32_t)(IRQ) + 16) >> 2) - 1)
300 #define LPC_IRQ_IP_IDX(IRQ)    ((uint32_t)(IRQ) >> 2)
302 /*  Set Interrupt Priority
303   This function sets the priority for the specified interrupt. The interrupt
304     number can be positive to specify an external (device specific)
305     interrupt, or negative to specify an internal (core) interrupt.
306   Note: The priority cannot be set for every core interrupt.
307   IRQ : Number of the interrupt for set priority
308   priority : Priority to set
309  */
310 static inline void NVIC_SetPriority(uint32_t IRQ, uint32_t priority)
312         if ((int32_t)IRQ < 0) {
313                 if ((int32_t)IRQ > (-12)) {
314                         struct syst_ctrl_block_regs* scb = LPC_SCB;
315                         scb->shp[LPC_IRQ_SHP_IDX(IRQ)] = (scb->shp[LPC_IRQ_SHP_IDX(IRQ)] & ~(0xFF << LPC_IRQ_BIT_SHIFT(IRQ))) |
316                                 (((priority << (8 - LPC_NVIC_PRIO_BITS)) & 0xFF) << LPC_IRQ_BIT_SHIFT(IRQ));
317                 }
318         } else if (LPC_IRQ_IP_IDX(IRQ) < 8) {
319                 struct nvic_regs* nvic = LPC_NVIC;
320                 nvic->int_priority[LPC_IRQ_IP_IDX(IRQ)] = (nvic->int_priority[LPC_IRQ_IP_IDX(IRQ)] & ~(0xFF << LPC_IRQ_BIT_SHIFT(IRQ))) |
321                         (((priority << (8 - LPC_NVIC_PRIO_BITS)) & 0xFF) << LPC_IRQ_BIT_SHIFT(IRQ));
322         }
326 /*  Get Interrupt Priority
327   This function reads the priority for the specified interrupt. The interrupt
328     number can be positive to specify an external (device specific)
329     interrupt, or negative to specify an internal (core) interrupt.
330   The returned priority value is automatically aligned to the implemented
331     priority bits of the microcontroller.
332   IRQ : Number of the interrupt for get priority
333   return : Interrupt Priority
334  */
335 static inline uint32_t NVIC_GetPriority(uint32_t IRQ)
337         if ((int32_t)IRQ < 0) {
338                 if ((int32_t)IRQ > (-12)) {
339                         struct syst_ctrl_block_regs* scb = LPC_SCB;
340                         /* Get priority for Cortex-M0 system interrupts */
341                         return ((uint32_t)((scb->shp[LPC_IRQ_SHP_IDX(IRQ)] >> LPC_IRQ_BIT_SHIFT(IRQ) ) >> (8 - LPC_NVIC_PRIO_BITS)));
342                 }
343         } else if (LPC_IRQ_IP_IDX(IRQ) < 8) {
344                 struct nvic_regs* nvic = LPC_NVIC;
345                 /* Get priority for device specific interrupts */
346                 return ((uint32_t)((nvic->int_priority[LPC_IRQ_IP_IDX(IRQ)] >> LPC_IRQ_BIT_SHIFT(IRQ) ) >> (8 - LPC_NVIC_PRIO_BITS)));
347         }
351 /*  System Reset
352   This function initiate a system reset request to reset the MCU.
353  */
354 static inline void NVIC_SystemReset(void)
356         struct syst_ctrl_block_regs* scb = LPC_SCB;
357         dsb(); /* Ensure all outstanding memory accesses included buffered write are completed before reset */
358         scb->aircr = ((0x5FA << SCB_AIRCR_VECTKEY_OFFSET) | SCB_AIRCR_SYSRESETREQ);
359         dsb();  /* Ensure completion of memory access */
360         while (1); /* wait until reset */
365 /*******************************************************************************/
366 /*            Sync lock                                                        */
367 /*******************************************************************************/
368 /* There is no syncro instructions on Cortex-M0
369  * Returns the old value if the new value has been set (lock acquired)
370  */
371 static inline uint32_t sync_lock_test_and_set(volatile uint32_t *addr, uint32_t value)
373         uint32_t oldval;
374         lpc_disable_irq();
375     dsb();
376         oldval = *addr;
377         *addr = value;
378     dsb();
379         lpc_enable_irq();
380         return oldval;
382 /* Remove the lock */
383 static inline void sync_lock_release(volatile uint32_t *addr)
385     *addr = 0;
386     dsb();
391 #endif /* LPC_CORE_CM0_H */