MCCI Trusted Bootloader
Simple trusted bootloader and tools for small embedded systems
mcci_arm_cm0plus.h
Go to the documentation of this file.
1/*
2
3Module: mcci_arm_cm0plus.h
4
5Function:
6 ARM cm0plus definitions without CMSIS overhead.
7
8Copyright and License:
9 This file copyright (C) 2021 by
10
11 MCCI Corporation
12 3520 Krums Corners Road
13 Ithaca, NY 14850
14
15 See accompanying LICENSE file for copyright and license information.
16
17Author:
18 Terry Moore, MCCI Corporation March 2021
19
20*/
21
22#ifndef _mcci_arm_cm0plus_h_
23#define _mcci_arm_cm0plus_h_ /* prevent multiple includes */
24
25#pragma once
26
27#ifndef _mcci_bootloader_bits_h_
28# include "mcci_bootloader_bits.h"
29#endif
30
31#include <stdint.h>
32#include <stdbool.h>
33
34#ifdef __cplusplus
35extern "C" {
36#endif
37
38/****************************************************************************\
39|
40| Special function register values
41|
42\****************************************************************************/
43
44/// \name CPU Special function registers
45/// @{
46#define MCCI_CM0PLUS_SYSM_APSR UINT32_C(0x00) ///< Flags from previous instructions
47#define MCCI_CM0PLUS_SYSM_IAPSR UINT32_C(0x01) ///< Composite of IPSR and APSR
48#define MCCI_CM0PLUS_SYSM_EAPSR UINT32_C(0x02) ///< Composite of EPSR and APSR
49#define MCCI_CM0PLUS_SYSM_XPSR UINT32_C(0x03) ///< Composite of EPSR, IPSR and APSR
50#define MCCI_CM0PLUS_SYSM_IPSR UINT32_C(0x05) ///< Interrupt status register
51#define MCCI_CM0PLUS_SYSM_EPSR UINT32_C(0x06) ///< Exception status register
52#define MCCI_CM0PLUS_SYSM_IEPSR UINT32_C(0x07) ///< Composite of IPSR and EPSR
53#define MCCI_CM0PLUS_SYSM_MSP UINT32_C(0x08) ///< Main stack pointer
54#define MCCI_CM0PLUS_SYSM_PSP UINT32_C(0x09) ///< Process stack pointer
55#define MCCI_CM0PLUS_SYSM_PRIMASK UINT32_C(0x10) ///< priority mask register
56#define MCCI_CM0PLUS_SYSM_CONTROL UINT32_C(0x14) ///< control register
57
58/// \name PRIMASK special register fields
59/// @{
60#define MCCI_CM0PLUS_SR_PRIMASK_DISABLE (UINT32_C(1) << 0) ///< the bit to disable interrupts
61/// @}
62
63/* end of special-function registers */
64/// @}
65
66/****************************************************************************\
67|
68| Register addresses
69|
70\****************************************************************************/
71
72#define MCCI_CM0PLUS_SCS_BASE UINT32_C(0xE000E000)
73
74/// \name SYSTICK registers
75/// @{
76#define MCCI_CM0PLUS_SYSTICK UINT32_C(0xE000E010)
77#define MCCI_CM0PLUS_SYSTICK_CSR (MCCI_CM0PLUS_SYSTICK + 0x0)
78#define MCCI_CM0PLUS_SYSTICK_RVR (MCCI_CM0PLUS_SYSTICK + 0x4)
79#define MCCI_CM0PLUS_SYSTICK_CVR (MCCI_CM0PLUS_SYSTICK + 0x8)
80#define MCCI_CM0PLUS_SYSTICK_CALIB (MCCI_CM0PLUS_SYSTICK + 0xC)
81/// @}
82
83/// \name NVIC registers
84/// @{
85#define MCCI_CM0PLUS_NVIC UINT32_C(0xE000E100)
86#define MCCI_CM0PLUS_NVIC_ISER (MCCI_CM0PLUS_NVIC + 0x000)
87#define MCCI_CM0PLUS_NVIC_ICER (MCCI_CM0PLUS_NVIC + 0x080)
88#define MCCI_CM0PLUS_NVIC_ISPR (MCCI_CM0PLUS_NVIC + 0x100)
89#define MCCI_CM0PLUS_NVIC_ICPR (MCCI_CM0PLUS_NVIC + 0x180)
90#define MCCI_CM0PLUS_NVIC_IP0 (MCCI_CM0PLUS_NVIC + 0x300)
91#define MCCI_CM0PLUS_NVIC_IP1 (MCCI_CM0PLUS_NVIC + 0x304)
92#define MCCI_CM0PLUS_NVIC_IP2 (MCCI_CM0PLUS_NVIC + 0x308)
93#define MCCI_CM0PLUS_NVIC_IP3 (MCCI_CM0PLUS_NVIC + 0x30C)
94#define MCCI_CM0PLUS_NVIC_IP4 (MCCI_CM0PLUS_NVIC + 0x310)
95#define MCCI_CM0PLUS_NVIC_IP5 (MCCI_CM0PLUS_NVIC + 0x314)
96#define MCCI_CM0PLUS_NVIC_IP6 (MCCI_CM0PLUS_NVIC + 0x318)
97#define MCCI_CM0PLUS_NVIC_IP7 (MCCI_CM0PLUS_NVIC + 0x31C)
98/// @}
99
100/// \name SCB registers
101/// @{
102#define MCCI_CM0PLUS_SCB UINT32_C(0xE000ED00)
103#define MCCI_CM0PLUS_SCB_CPUID (MCCI_CM0PLUS_SCB + 0x00)
104#define MCCI_CM0PLUS_SCB_ICSR (MCCI_CM0PLUS_SCB + 0x04)
105#define MCCI_CM0PLUS_SCB_VTOR (MCCI_CM0PLUS_SCB + 0x08)
106#define MCCI_CM0PLUS_SCB_AIRCR (MCCI_CM0PLUS_SCB + 0x0C)
107#define MCCI_CM0PLUS_SCB_SCR (MCCI_CM0PLUS_SCB + 0x10)
108#define MCCI_CM0PLUS_SCB_CCR (MCCI_CM0PLUS_SCB + 0x14)
109#define MCCI_CM0PLUS_SCB_SHPR2 (MCCI_CM0PLUS_SCB + 0x1C)
110#define MCCI_CM0PLUS_SCB_SHPR3 (MCCI_CM0PLUS_SCB + 0x20)
111#define MCCI_CM0PLUS_SCB_SHCSR (MCCI_CM0PLUS_SCB + 0x24)
112#define MCCI_CM0PLUS_SCB_DFSR (MCCI_CM0PLUS_SCB + 0x30)
113/// @}
114
115/// \name MPU registers
116/// @{
117#define MCCI_CM0PLUS_MPU UINT32_C(0xE000ED90)
118#define MCCI_CM0PLUS_MPU_TYPE (MCCI_CM0PLUS_MPU + 0x00) //<
119#define MCCI_CM0PLUS_MPU_CTRL (MCCI_CM0PLUS_MPU + 0x04) //<
120#define MCCI_CM0PLUS_MPU_RNR (MCCI_CM0PLUS_MPU + 0x08) //<
121#define MCCI_CM0PLUS_MPU_RBAR (MCCI_CM0PLUS_MPU + 0x0C) //<
122#define MCCI_CM0PLUS_MPU_RASR (MCCI_CM0PLUS_MPU + 0x10) //<
123/// @}
124
125/****************************************************************************\
126|
127| Register bits
128|
129\****************************************************************************/
130
131/// \name SYSTICK CSR bits
132/// @{
133#define MCCI_CM0PLUS_SYSTICK_CSR_RSV17 UINT32_C(0xFFFE0000) ///< reserved
134#define MCCI_CM0PLUS_SYSTICK_CSR_COUNTFLAG (UINT32_C(1) << 16) ///< timer has counted to zero
135#define MCCI_CM0PLUS_SYSTICK_CSR_RSV3 UINT32_C(0x0000FFF8) ///< reserved
136#define MCCI_CM0PLUS_SYSTICK_CSR_CLKSOURCE (UINT32_C(1) << 2) ///< use processor (not external) clock
137#define MCCI_CM0PLUS_SYSTICK_CSR_TICKINT (UINT32_C(1) << 1) ///< enable tick exception
138#define MCCI_CM0PLUS_SYSTICK_CSR_ENABLE (UINT32_C(1) << 0) ///< enable counter
139/// @}
140
141/// \name SYSTICK RVR bits
142/// @{
143#define MCCI_CM0PLUS_SYSTICK_RVR_RSV24 UINT32_C(0xFF000000) ///< reserved, zero
144#define MCCI_CM0PLUS_SYSTICK_RVR_RELOAD UINT32_C(0x00FFFFFF) ///< reload value
145/// @}
146
147/// \name SYSTICK CVR bits
148/// @{
149#define MCCI_CM0PLUS_SYSTICK_CVR_RSV24 UINT32_C(0xFF000000) ///< reserved, read as zero
150#define MCCI_CM0PLUS_SYSTICK_CVR_CURRENT UINT32_C(0x00FFFFFF) ///< current value
151/// @}
152
153/// \name SYSTICK CALIB bits
154/// @{
155#define MCCI_CM0PLUS_SYSTICK_CALIB_NOREF (UINT32_C(1) << 31) ///< reference clock is not implemented
156#define MCCI_CM0PLUS_SYSTICK_CALIB_SKEW (UINT32_C(1) << 30) ///< 10ms cal value is inexact
157#define MCCI_CM0PLUS_SYSTICK_CALIB_RSV24 (UINT32_C(0x3F) << 24) ///< reserved, zero
158#define MCCI_CM0PLUS_SYSTICK_CALIB_TENMS UINT32_C(0x00FFFFFF) ///< if non-zero, use this as reload value for 10ms ticks
159/// @}
160
161/// \name NVIC IPR bits
162
163/// \name SCB CPUID fields
164/// @{
165#define MCCI_CM0PLUS_SCB_CPUID_IMPLEMENTER (UINT32_C(0xFF) << 24) ///< Implementer code
166#define MCCI_CM0PLUS_SCB_CPUID_VARIANT (UINT32_C(0xF) << 20) ///< Variant code
167#define MCCI_CM0PLUS_SCB_CPUID_ARCHITECTURE (UINT32_C(0xF) << 16) ///< Architecture code
168#define MCCI_CM0PLUS_SCB_CPUID_PARTNO (UINT32_C(0xFFF) << 4) ///< Part number
169#define MCCI_CM0PLUS_SCB_CPUID_REVISION (UINT32_C(0xF) << 0) ///< Revision
170/// @}
171
172/// \name SCB ICSR fields
173/// @{
174#define MCCI_CM0PLUS_SCB_ICSR_NMIPENDSET (UINT32_C(1) << 31) ///<
175#define MCCI_CM0PLUS_SCB_ICSR_RSV29 (UINT32_C(3) << 29) ///<
176#define MCCI_CM0PLUS_SCB_ICSR_PENDSVSET (UINT32_C(1) << 28) ///<
177#define MCCI_CM0PLUS_SCB_ICSR_PENDSVCLR (UINT32_C(1) << 27) ///<
178#define MCCI_CM0PLUS_SCB_ICSR_PENDSTSET (UINT32_C(1) << 26) ///<
179#define MCCI_CM0PLUS_SCB_ICSR_PENDSTCLR (UINT32_C(1) << 25) ///<
180#define MCCI_CM0PLUS_SCB_ICSR_RSV24 (UINT32_C(1) << 24) ///<
181#define MCCI_CM0PLUS_SCB_ICSR_ISRPREEMPT (UINT32_C(1) << 23) ///<
182#define MCCI_CM0PLUS_SCB_ICSR_ISRPENDING (UINT32_C(1) << 22) ///<
183#define MCCI_CM0PLUS_SCB_ICSR_VECTPENDING (UINT32_C(0x1FF) << 12) ///<
184#define MCCI_CM0PLUS_SCB_ICSR_VECTACTIVE (UINT32_C(0x1FF) << 0) ///<
185/// @}
186
187/// \name SCB VTOR fields
188/// @{
189#define MCCI_CM0PLUS_SCB_VTOR_TBLOFF UINT32_C(0xFFFFFF00) ///<
190/// @}
191
192/// \name SCB AIRCR fields (Appplication Interrupt and Reset Control)
193/// @{
194#define MCCI_CM0PLUS_SCB_AIRCR_VECTKEY (UINT32_C(0xFFFF) << 16) ///< Vector key
195#define MCCI_CM0PLUS_SCB_AIRCR_VECTKEY_VALUE (UINT32_C(0x05FA) << 16) ///< Value to write to unlock regster.
196#define MCCI_CM0PLUS_SCB_AIRCR_ENDIANNESS (UINT32_C(1) << 15) ///<
197#define MCCI_CM0PLUS_SCB_AIRCR_SYSRESETREQ (UINT32_C(1) << 2) ///<
198#define MCCI_CM0PLUS_SCB_AIRCR_VECTCLRACTIVE (UINT32_C(1) << 1) ///<
199/// @}
200
201/// \name SCB SCR fields
202/// @{
203#define MCCI_CM0PLUS_SCB_SCR_SEVONPEND (UINT32_C(1) << 4) ///<
204#define MCCI_CM0PLUS_SCB_SCR_SLEEPDEEP (UINT32_C(1) << 2) ///<
205#define MCCI_CM0PLUS_SCB_SCR_SLEEPONEXIT (UINT32_C(1) << 1) ///<
206/// @}
207
208/// \name SCB Configuration Control Register bits
209/// @{
210#define MCCI_CM0PLUS_SCB_CCR_STKALIGN (UINT32_C(1) << 9) ///<
211#define MCCI_CM0PLUS_SCB_CCR_UNALIGNED (UINT32_C(1) << 3) ///<
212/// @}
213
214/// \name SCB SHPR access
215/// @{
216#define MCCI_CM0PLUS_SCB_SHPR_PRI (UINT32_C(3) << 6) ///< priority bits within a byte
217
218#define MCCI_CM0PLUS_PRI_INDEX_SVC UINT32_C(11) ///< priority of SVCall
219#define MCCI_CM0PLUS_PRI_INDEX_PENDSV UINT32_C(14) ///< priority of PendSV
220#define MCCI_CM0PLUS_PRI_INDEX_SYSTICK UINT32_C(15) ///< priority of systick
221
222/// \brief return register for a given handler index
223static inline uint32_t
225 uint32_t handlerIndex
226 )
227 {
228 // map to either SPHR2 or SHPR3.
229 return MCCI_CM0PLUS_SCB_SHPR2 + (handlerIndex & 4);
230 }
231
232/// \brief return byte mask for a given handler index
233static inline uint32_t
235 uint32_t handlerIndex
236 )
237 {
238 // compute and return the mask for a given bit
239 return UINT32_C(0xE0) << (8 * (handlerIndex & 3));
240 }
241/// @}
242
243/// \name SCB System Handler Control and State Register bits
244/// @{
245#define MCCI_CM0PLUS_SCB_SHCSR_SVCALLPENDED (UINT32_C(1) << 15) ///<
246/// @}
247
248/****************************************************************************\
249|
250| Register access primitives
251|
252\****************************************************************************/
253
254/// \brief write a 32-bit value to a cm0plus register
255__attribute__((__always_inline__))
256static inline uint32_t
257McciArm_putReg(uint32_t reg, uint32_t val)
258 {
259 *(volatile uint32_t *)reg = val;
260 return val;
261 }
262
263/// \brief read a 32-bit value from a cm0plus register
264__attribute__((__always_inline__))
265static inline uint32_t
266McciArm_getReg(uint32_t reg)
267 {
268 return *(volatile uint32_t *)reg;
269 }
270
271/// \brief and/or 32-bit values to a cm0plus register
272__attribute__((__always_inline__))
273static inline uint32_t
274McciArm_putRegAndOr(uint32_t reg, uint32_t andVal, uint32_t orVal)
275 {
276 uint32_t const rValue = McciArm_getReg(reg);
277
278 return McciArm_putReg(
279 reg,
280 (rValue & andVal) | orVal
281 );
282 }
283
284/// \brief or 32-bit values to a cm0plus register
285__attribute__((__always_inline__))
286static inline uint32_t
287McciArm_putRegOr(uint32_t reg, uint32_t orVal)
288 {
289 uint32_t const rValue = McciArm_getReg(reg);
290
291 return McciArm_putReg(
292 reg,
293 rValue | orVal
294 );
295 }
296
297/// \brief clear out 32-bit values to a cm0plus register
298__attribute__((__always_inline__))
299static inline uint32_t
300McciArm_putRegClear(uint32_t reg, uint32_t clearVal)
301 {
302 uint32_t const rValue = McciArm_getReg(reg);
303
304 return McciArm_putReg(
305 reg,
306 rValue & ~clearVal
307 );
308 }
309
310///
311/// \brief clear and set 32-bit values to a cm0plus register
312///
313/// \param [in] reg register to be modified
314/// \param [in] clearVal mask of bits to be cleared (1 in mask clears bit in reg)
315/// \param [in] setVal mask of bits to be set
316///
317/// \note this is subtly different than \ref McciArm_putRegMasked,
318/// in that \p setVal is not modified by \p clearVal. Any bits
319/// set in \p setVal are unconditionally set in \p reg, whereas
320/// \ref McciArm_putRegMasked only changes bits that are set
321/// in its \c maskVal parameter.
322///
323/// \see McciArm_putRegMasked
324///
325__attribute__((__always_inline__))
326static inline uint32_t
327McciArm_putRegClearSet(uint32_t reg, uint32_t clearVal, uint32_t setVal)
328 {
329 uint32_t const rValue = McciArm_getReg(reg);
330
331 return McciArm_putReg(
332 reg,
333 (rValue & ~clearVal) | setVal
334 );
335 }
336
337///
338/// \brief store to cm0plus register under mask
339///
340/// \param [in] reg register to be modified
341/// \param [in] maskVal mask of bits to be modifed
342/// \param [in] modVal where \p maskVal is 1, provides values of bits
343///
344/// \note this is subtly different than \ref McciArm_putRegClearSet,
345/// in that any bits in \b ~maskVal are not changed, regardless of
346/// corresponding bits in \p modVal.
347///
348/// \see McciArm_putRegClearSet
349/// \see https://graphics.stanford.edu/~seander/bithacks.html#MaskedMerge
350///
351__attribute__((__always_inline__))
352static inline uint32_t
353McciArm_putRegMasked(uint32_t reg, uint32_t maskVal, uint32_t modVal)
354 {
355 uint32_t const rValue = McciArm_getReg(reg);
356
357 return McciArm_putReg(
358 reg,
359 rValue ^ ((rValue ^ modVal) & maskVal)
360 /* same as (rValue & ~maskVal) | (modVal & maskVal) */
361 );
362 }
363
364/****************************************************************************\
365|
366| ARM intrinsics (some of then)
367|
368\****************************************************************************/
369
370#if defined(__GNUC__) // GCC or clang, likely
371
372///
373/// \brief set main stack pointer
374///
375/// \param[in] stack new stack pointer value.
376///
377/// \note This always must be inline because once stack pointer changes,
378/// maybe hard to return!
379///
380__attribute__((__always_inline__)) static inline
381void
382McciArm_setMSP(
383 uint32_t stack
384 )
385 {
386 __asm volatile ("MSR msp,%0\n" :: "r"(stack): );
387 }
388
389///
390/// \brief get priority mask
391///
392/// \return current value of PRIMASK register
393///
394/// \note only bit 0 is implemented on CM0 Plus CPUs. If cleared, it enables
395/// interrupts; if set it enables interrupts.
396///
397__attribute__((__always_inline__)) static inline
398uint32_t
399McciArm_getPRIMASK(
400 void
401 )
402 {
403 uint32_t primask;
404
405 __asm volatile ("MRS %0,primask" : "=r"(primask));
406 return primask;
407 }
408
409///
410/// \brief set priority mask
411///
412/// \param [in] primask new value of PRIMASK register
413///
414/// \note only bit 0 is implemented on CM0 Plus CPUs. If cleared, it enables
415/// interrupts; if set it enables interrupts.
416///
417__attribute__((__always_inline__)) static inline
418void
419McciArm_setPRIMASK(
420 uint32_t primask
421 )
422 {
423 __asm volatile ("MSR primask,%0" :: "r"(primask) : "memory");
424 }
425
426///
427/// \brief Disable interrupts and return previous state
428///
429/// \return previous value of PRIMASK register.
430///
431__attribute__((__always_inline__)) static inline
432uint32_t
433McciArm_disableInterrupts(
434 void
435 )
436 {
437 uint32_t const primask = McciArm_getPRIMASK();
438 __asm volatile ("cpsid i" ::: "memory");
439 return primask;
440 }
441
442///
443/// \brief insert a data synchronization barrier
444///
445/// \details
446/// Force all pending memory operations to complete before
447// continuing.
448///
449__attribute__((always_inline)) static inline
450void McciArm_DataSynchBarrier(
451 void
452 )
453 {
454 __asm volatile ("dsb 0xF" ::: "memory");
455 }
456
457
458///
459/// \brief get IPSR
460///
461/// \return current value of IPSR register
462///
463/// \note the result is 0 for thread mode; and >= 16 for the current IRQ number.
464/// 1..15 is used for exception handlers.
465///
466__attribute__((always_inline)) static inline
467uint32_t McciArm_getIPSR(
468 void
469 )
470 {
471 uint32_t ipsr;
472
473 __asm volatile ("MRS %0, ipsr" : "=r"(ipsr));
474 return ipsr;
475 }
476
477#else
478# error "Compiler not supported"
479#endif
480
481///
482/// @brief test IPSR to see if Cortex-M0+ is in thread mode.
483///
484/// @param ipsr [in] image of IPSR register.
485///
486/// @return \c true if in thread mode, \c false otherwise.
487///
488static inline
490 {
491 return ipsr == 0;
492 }
493
494///
495/// @brief test IPSR to see if Cortex-M0+ is in an IRQ handler
496///
497/// @param ipsr [in] image of IPSR register
498///
499/// @return \c true if in an ISR, \c false otherwise.
500///
501static inline
503 {
504 return ipsr >= 16;
505 }
506
507///
508/// @brief convert IPSR value to IRQ number, if in handler.
509///
510/// @param ipsr [in] image of IPSR register
511///
512/// @return IRQ number (>= 0) if in an IRQ handler; -16 if in thread mode, -15..-1 if in an
513/// exception handler.
514///
515static inline
516int32_t McciArmIPSR_toIRQ(uint32_t ipsr)
517 {
518 return ipsr - 16;
519 }
520
521///
522/// @brief return priority of SysTick exception.
523///
524/// @return value in 0..3.
525///
526static inline
528 {
529 uint32_t const shpr3 = McciArm_getReg(MCCI_CM0PLUS_SCB_SHPR3);
530 uint32_t const shprbits = (shpr3 >> (24 + 6));
531
532 return shprbits & 3u;
533 }
534
535///
536/// @brief return priority of SVC exception.
537///
538/// @return value in 0..3.
539///
540static inline
542 {
543 uint32_t const shpr2 = McciArm_getReg(MCCI_CM0PLUS_SCB_SHPR2);
544 uint32_t const shprbits = (shpr2 >> (24 + 6));
545
546 return shprbits & 3u;
547 }
548
549///
550/// @brief return priority of PendSv exception.
551///
552/// @return value in 0..3.
553///
554static inline
556 {
557 uint32_t const shpr3 = McciArm_getReg(MCCI_CM0PLUS_SCB_SHPR3);
558 uint32_t const shprbits = (shpr3 >> (16 + 6));
559
560 return shprbits & 3u;
561 }
562
563///
564/// @brief return priority of speciified IRQ
565/// @param irq [in] interrupt request index, in [-16..31]
566/// @return interrupt priority in -1..4
567///
568/// @note if the input parameter is corresponds to a request with
569/// programmable priority, the result is 0..3. If the input
570/// is -16 (thread mode), the result is 4. If the input is any
571/// of the other higher-priority exceptions, the result is -1.
572///
573static inline
574int32_t McciArmNvic_getPriority(int32_t irq)
575 {
576 if (irq < 0 || irq >= 32)
577 {
578 switch (irq)
579 {
580 case -1: return McciArm_getSysTickPriority();
581 case -2: return McciArm_getPendSvPriority();
582 case -5: return McciArm_getSvcPriority();
583 case -16: return 4;
584 default:
585 // out of range or hard wired.
586 return -1;
587 }
588 }
589 else
590 {
591 uint32_t const ip = McciArm_getReg(MCCI_CM0PLUS_NVIC_IP0 + (irq & ~3u));
592
593 uint32_t const ipbits = ip >> (8 * (irq & 3u) + 6);
594
595 return ipbits & 3;
596 }
597 }
598
599
600/****************************************************************************\
601|
602| Vectors and so forth
603|
604\****************************************************************************/
605
606///
607/// \brief application entry contents
608///
609/// Every Cortex M0 application begins with two DWORDs. The first is
610/// the stack pointer; the second is the program counter.
611///
612/// We use MCCI Russian Doll structure nesting; this is the root
613/// of the hierarchy that forms the page zero vectors.
614///
615typedef struct Mcci_CortexAppEntryContents_s
616 {
617 uint32_t stack; //< Initial stack pointer must be multiple of 4
618 uint32_t entry; //< Initial entry point; must be odd.
620
621///
622/// \brief application entry object
623///
624/// This union wraps the app entry contents, so that we can always reference
625/// with a consistent name (`AppEntry.stack` etc.), regardless of how general
626/// or specific the pointer is.
627///
628typedef union Mcci_CortexAppEntry_u
629 {
630 Mcci_CortexAppEntryContents_t CortexAppEntry; //< reference name for application entry view.
632
633///
634/// \brief Cortex M0 interrupt vectors (low level view)
635///
636/// This structure represents the vectors page as an array of 48 32-bit vectors.
637/// It's used mostly for initialization and for building up larger structures.
638///
639typedef struct Mcci_CortexVectorsContents_s
640 {
641 uint32_t vectors[192/4];
643
644///
645/// \brief Cortex M0 interrupt vector object
646///
647/// This union wraps the interrupt vector contents, both so we can always
648/// reference fields with consistent names (`AppEntry.stack` etc.), and to allow
649/// us to view the vectors as either an AppEntry description or a table of
650/// vectors.
651///
652typedef union Mcci_CortexVectors_u
653 {
654 Mcci_CortexAppEntryContents_t CortexAppEntry; //< View instance as a CortexM0 AppEntry.
655 Mcci_CortexAppEntry_t CortexAppEntryCast; //< Downcast to an AppEntry without explicit casting
656 Mcci_CortexVectorsContents_t CortexVectors; //< View instance as vectors.
658
659/****************************************************************************\
660|
661| End of file
662|
663\****************************************************************************/
664
665#ifdef __cplusplus
666}
667#endif
668
669#endif /* _mcci_arm_cm0plus_h_ */
#define MCCI_CM0PLUS_NVIC_IP0
static uint32_t McciArm_putRegOr(uint32_t reg, uint32_t orVal)
or 32-bit values to a cm0plus register
static uint32_t McciArm_getReg(uint32_t reg)
read a 32-bit value from a cm0plus register
static uint32_t McciArm_getSvcPriority(void)
return priority of SVC exception.
static uint32_t McciArm_putReg(uint32_t reg, uint32_t val)
write a 32-bit value to a cm0plus register
#define MCCI_CM0PLUS_SCB_SHPR2
static uint32_t McciArm_getPendSvPriority(void)
return priority of PendSv exception.
static uint32_t McciArm_putRegClear(uint32_t reg, uint32_t clearVal)
clear out 32-bit values to a cm0plus register
#define MCCI_CM0PLUS_SCB_SHPR3
static uint32_t McciArm_putRegClearSet(uint32_t reg, uint32_t clearVal, uint32_t setVal)
clear and set 32-bit values to a cm0plus register
static bool McciArmIPSR_queryIrqHandler(uint32_t ipsr)
test IPSR to see if Cortex-M0+ is in an IRQ handler
static uint32_t McciCm0Plus_SCB_SHPR_getRegister(uint32_t handlerIndex)
return register for a given handler index
static bool McciArmIPSR_queryThreadMode(uint32_t ipsr)
test IPSR to see if Cortex-M0+ is in thread mode.
static int32_t McciArmNvic_getPriority(int32_t irq)
return priority of speciified IRQ
static uint32_t McciArm_putRegMasked(uint32_t reg, uint32_t maskVal, uint32_t modVal)
store to cm0plus register under mask
static uint32_t McciArm_getSysTickPriority(void)
return priority of SysTick exception.
static int32_t McciArmIPSR_toIRQ(uint32_t ipsr)
convert IPSR value to IRQ number, if in handler.
static uint32_t McciArm_putRegAndOr(uint32_t reg, uint32_t andVal, uint32_t orVal)
and/or 32-bit values to a cm0plus register
static uint32_t McciCm0Plus_SCB_SHPR_getMask(uint32_t handlerIndex)
return byte mask for a given handler index
application entry contents
uint32_t entry
uint32_t stack
Cortex M0 interrupt vectors (low level view)
application entry object
Mcci_CortexAppEntryContents_t CortexAppEntry
Cortex M0 interrupt vector object.
Mcci_CortexAppEntry_t CortexAppEntryCast
Mcci_CortexVectorsContents_t CortexVectors
Mcci_CortexAppEntryContents_t CortexAppEntry