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