1 //*****************************************************************************
2 //
3 //! @file am_reg_macros.h
4 //!
5 //! @brief Helper macros for using hardware registers.
6 //
7 //*****************************************************************************
8 
9 //*****************************************************************************
10 //
11 // Copyright (c) 2023, Ambiq Micro, Inc.
12 // All rights reserved.
13 //
14 // Redistribution and use in source and binary forms, with or without
15 // modification, are permitted provided that the following conditions are met:
16 //
17 // 1. Redistributions of source code must retain the above copyright notice,
18 // this list of conditions and the following disclaimer.
19 //
20 // 2. Redistributions in binary form must reproduce the above copyright
21 // notice, this list of conditions and the following disclaimer in the
22 // documentation and/or other materials provided with the distribution.
23 //
24 // 3. Neither the name of the copyright holder nor the names of its
25 // contributors may be used to endorse or promote products derived from this
26 // software without specific prior written permission.
27 //
28 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
32 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 // POSSIBILITY OF SUCH DAMAGE.
39 //
40 // This is part of revision release_sdk_4_4_0-3c5977e664 of the AmbiqSuite Development Package.
41 //
42 //*****************************************************************************
43 
44 #ifndef AM_REG_MACROS_H
45 #define AM_REG_MACROS_H
46 
47 #ifdef __cplusplus
48 extern "C"
49 {
50 #endif
51 
52 //*****************************************************************************
53 //
54 // For direct 32-bit access to a register or memory location, use AM_REGVAL:
55 //      AM_REGVAL(0x1234567) |= 0xDEADBEEF;
56 //
57 //*****************************************************************************
58 #define AM_REGVAL(x)               (*((volatile uint32_t *)(x)))
59 #define AM_REGVAL_FLOAT(x)         (*((volatile float *)(x)))
60 
61 //*****************************************************************************
62 //
63 // AM_REGADDR()
64 // One thing CMSIS does not do well natively is to provide for static register
65 // address computation. The address-of operator (e.g. &periph->reg) is helpful,
66 // but does run into problems, such as when attempting to cast the resulting
67 // pointer to a uint32_t.  The standard C macro, offsetof() can help.
68 //
69 // Use AM_REGADDR() for single-module peripherals.
70 // Use AM_REGADDRn() for multi-module peripherals (e.g. IOM, UART).
71 //
72 //*****************************************************************************
73 #define AM_REGADDR(periph, reg) ( periph##_BASE + offsetof(periph##_Type, reg) )
74 
75 #define AM_REGADDRn(periph, n, reg) ( periph##0_BASE                    +   \
76                                       offsetof(periph##0_Type, reg)     +   \
77                                       (n * (periph##1_BASE - periph##0_BASE)) )
78 
79 //*****************************************************************************
80 //
81 // Bitfield macros.
82 //
83 //*****************************************************************************
84 #ifdef CMSIS_BFNOT
85 #define AM_BFW(module, reg, field, value)                                   \
86     (module->reg = ((module->reg & ~(module##_##reg##_##field##_Msk)) |     \
87     _VAL2FLD(module##_##reg##_##field, value)))
88 
89 #define AM_BFR(module, reg, field)                                          \
90     _FLD2VAL(module##_##reg##_##field, module->reg)
91 
92 #define AM_BFRn(module, instance, reg, field)                               \
93     (_FLD2VAL(module##0_##reg##_##field,                                    \
94      *((volatile uint32_t *)(AM_REGADDRn(module, instance, reg)))) )
95 
96 #define AM_BFWn(module, instance, reg, field, value)                        \
97     (*((volatile uint32_t *)(AM_REGADDRn(module, instance, reg))) =         \
98      (((*((volatile uint32_t *)(AM_REGADDRn(module, instance, reg)))) &     \
99      ~(module##0_##reg##_##field##_Msk) ) |                                 \
100      _VAL2FLD(module##0_##reg##_##field, value)) )
101 
102 #endif
103 
104 //*****************************************************************************
105 //
106 // Critical section assembly macros
107 //
108 // These macros implement critical section protection using inline assembly
109 // for various compilers.  They are intended to be used in other register
110 // macros or directly in sections of code.
111 //
112 // Important usage note: These macros create a local scope and therefore MUST
113 // be used in pairs.
114 //
115 //*****************************************************************************
116 #define AM_CRITICAL_BEGIN                                                   \
117     if ( 1 )                                                                \
118     {                                                                       \
119         volatile uint32_t ui32Primask_04172010;                             \
120         ui32Primask_04172010 = am_hal_interrupt_master_disable();
121 
122 #define AM_CRITICAL_END                                                     \
123         am_hal_interrupt_master_set(ui32Primask_04172010);                  \
124     }
125 
126 //*****************************************************************************
127 //
128 // Compiler-specific macros.
129 //
130 // Macros that accomplish compiler-specific tasks.
131 // For example, suppression of certain compiler warnings.
132 //
133 //*****************************************************************************
134 #if defined(__IAR_SYSTEMS_ICC__)
135 /* Suppress IAR compiler warning about volatile ordering  */
136 #define DIAG_SUPPRESS_VOLATILE_ORDER()  _Pragma("diag_suppress=Pa082")
137 /* Restore IAR compiler warning to default */
138 #define DIAG_DEFAULT_VOLATILE_ORDER()   _Pragma("diag_default=Pa082")
139 #else
140 #define DIAG_SUPPRESS_VOLATILE_ORDER()
141 #define DIAG_DEFAULT_VOLATILE_ORDER()
142 #endif
143 
144 //
145 // The intrinsic for IAR's CLZ instruction is different than other compilers.
146 //
147 #ifdef __IAR_SYSTEMS_ICC__
148 #define AM_ASM_CLZ(ui32val)     __CLZ(ui32val)
149 #else
150 #define AM_ASM_CLZ(ui32val)     __builtin_clz(ui32val)
151 #endif
152 
153 #ifdef __cplusplus
154 }
155 #endif
156 
157 #endif // AM_REG_MACROS_H
158 
159