github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/device/arm/arm.go (about) 1 // CMSIS abstraction functions. 2 // 3 // Original copyright: 4 // 5 // Copyright (c) 2009 - 2015 ARM LIMITED 6 // 7 // All rights reserved. 8 // Redistribution and use in source and binary forms, with or without 9 // modification, are permitted provided that the following conditions are met: 10 // - Redistributions of source code must retain the above copyright 11 // notice, this list of conditions and the following disclaimer. 12 // - Redistributions in binary form must reproduce the above copyright 13 // notice, this list of conditions and the following disclaimer in the 14 // documentation and/or other materials provided with the distribution. 15 // - Neither the name of ARM nor the names of its contributors may be used 16 // to endorse or promote products derived from this software without 17 // specific prior written permission. 18 // 19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 // ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE 23 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 // POSSIBILITY OF SUCH DAMAGE. 30 package arm 31 32 import "C" 33 import ( 34 "errors" 35 "runtime/volatile" 36 "unsafe" 37 ) 38 39 var errCycleCountTooLarge = errors.New("requested cycle count is too large, overflows 24 bit counter") 40 41 // Run the given assembly code. The code will be marked as having side effects, 42 // as it doesn't produce output and thus would normally be eliminated by the 43 // optimizer. 44 func Asm(asm string) 45 46 // Run the given inline assembly. The code will be marked as having side 47 // effects, as it would otherwise be optimized away. The inline assembly string 48 // recognizes template values in the form {name}, like so: 49 // 50 // arm.AsmFull( 51 // "str {value}, {result}", 52 // map[string]interface{}{ 53 // "value": 1 54 // "result": &dest, 55 // }) 56 // 57 // You can use {} in the asm string (which expands to a register) to set the 58 // return value. 59 func AsmFull(asm string, regs map[string]interface{}) uintptr 60 61 // Run the following system call (SVCall) with 0 arguments. 62 func SVCall0(num uintptr) uintptr 63 64 // Run the following system call (SVCall) with 1 argument. 65 func SVCall1(num uintptr, a1 interface{}) uintptr 66 67 // Run the following system call (SVCall) with 2 arguments. 68 func SVCall2(num uintptr, a1, a2 interface{}) uintptr 69 70 // Run the following system call (SVCall) with 3 arguments. 71 func SVCall3(num uintptr, a1, a2, a3 interface{}) uintptr 72 73 // Run the following system call (SVCall) with 4 arguments. 74 func SVCall4(num uintptr, a1, a2, a3, a4 interface{}) uintptr 75 76 const ( 77 SCS_BASE = 0xE000E000 78 SYST_BASE = SCS_BASE + 0x0010 79 NVIC_BASE = SCS_BASE + 0x0100 80 ) 81 82 // Nested Vectored Interrupt Controller (NVIC). 83 // 84 // Source: 85 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/CIHIGCIF.html 86 type NVIC_Type struct { 87 ISER [8]volatile.Register32 // Interrupt Set-enable Registers 88 _ [24]uint32 89 ICER [8]volatile.Register32 // Interrupt Clear-enable Registers 90 _ [24]uint32 91 ISPR [8]volatile.Register32 // Interrupt Set-pending Registers 92 _ [24]uint32 93 ICPR [8]volatile.Register32 // Interrupt Clear-pending Registers 94 _ [24]uint32 95 IABR [8]volatile.Register32 // Interrupt Active Bit Registers 96 _ [56]uint32 97 IPR [60]volatile.Register32 // Interrupt Priority Registers 98 } 99 100 var NVIC = (*NVIC_Type)(unsafe.Pointer(uintptr(NVIC_BASE))) 101 102 // System Timer (SYST) 103 // 104 // Source: https://static.docs.arm.com/ddi0403/e/DDI0403E_d_armv7m_arm.pdf B3.3 105 type SYST_Type struct { 106 SYST_CSR volatile.Register32 107 SYST_RVR volatile.Register32 108 SYST_CVR volatile.Register32 109 SYST_CALIB volatile.Register32 110 } 111 112 var SYST = (*SYST_Type)(unsafe.Pointer(uintptr(SYST_BASE))) 113 114 // Bitfields for SYST: System Timer 115 const ( 116 // SYST.SYST_CSR: SysTick Control and Status Register 117 SYST_CSR_ENABLE_Pos = 0x0 // Position of ENABLE field. 118 SYST_CSR_ENABLE_Msk = 0x1 // Bit mask of ENABLE field. 119 SYST_CSR_ENABLE = 0x1 // Bit ENABLE. 120 SYST_CSR_TICKINT_Pos = 0x1 // Position of TICKINT field. 121 SYST_CSR_TICKINT_Msk = 0x2 // Bit mask of TICKINT field. 122 SYST_CSR_TICKINT = 0x2 // Bit TICKINT. 123 SYST_CSR_CLKSOURCE_Pos = 0x2 // Position of CLKSOURCE field. 124 SYST_CSR_CLKSOURCE_Msk = 0x4 // Bit mask of CLKSOURCE field. 125 SYST_CSR_CLKSOURCE = 0x4 // Bit CLKSOURCE. 126 SYST_CSR_COUNTFLAG_Pos = 0x10 // Position of COUNTFLAG field. 127 SYST_CSR_COUNTFLAG_Msk = 0x10000 // Bit mask of COUNTFLAG field. 128 SYST_CSR_COUNTFLAG = 0x10000 // Bit COUNTFLAG. 129 130 // SYST.SYST_RVR: SysTick Reload Value Register 131 SYST_RVR_RELOAD_Pos = 0x0 // Position of RELOAD field. 132 SYST_RVR_RELOAD_Msk = 0xffffff // Bit mask of RELOAD field. 133 134 // SYST.SYST_CVR: SysTick Current Value Register 135 SYST_CVR_CURRENT_Pos = 0x0 // Position of CURRENT field. 136 SYST_CVR_CURRENT_Msk = 0xffffff // Bit mask of CURRENT field. 137 138 // SYST.SYST_CALIB: SysTick Calibration Value Register 139 SYST_CALIB_TENMS_Pos = 0x0 // Position of TENMS field. 140 SYST_CALIB_TENMS_Msk = 0xffffff // Bit mask of TENMS field. 141 SYST_CALIB_SKEW_Pos = 0x1e // Position of SKEW field. 142 SYST_CALIB_SKEW_Msk = 0x40000000 // Bit mask of SKEW field. 143 SYST_CALIB_SKEW = 0x40000000 // Bit SKEW. 144 SYST_CALIB_NOREF_Pos = 0x1f // Position of NOREF field. 145 SYST_CALIB_NOREF_Msk = 0x80000000 // Bit mask of NOREF field. 146 SYST_CALIB_NOREF = 0x80000000 // Bit NOREF. 147 ) 148 149 // Enable the given interrupt number. 150 func EnableIRQ(irq uint32) { 151 NVIC.ISER[irq>>5].Set(1 << (irq & 0x1F)) 152 } 153 154 // Disable the given interrupt number. 155 func DisableIRQ(irq uint32) { 156 NVIC.ICER[irq>>5].Set(1 << (irq & 0x1F)) 157 } 158 159 // Set the priority of the given interrupt number. 160 // Note that the priority is given as a 0-255 number, where some of the lower 161 // bits are not implemented by the hardware. For example, to set a low interrupt 162 // priority, use 0xc0, which is equivalent to using priority level 5 when the 163 // hardware has 8 priority levels. Also note that the priority level is inverted 164 // in ARM: a lower number means it is a more important interrupt and will 165 // interrupt ISRs with a higher interrupt priority. 166 func SetPriority(irq uint32, priority uint32) { 167 // Details: 168 // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0553a/Cihgjeed.html 169 regnum := irq / 4 170 regpos := irq % 4 171 mask := uint32(0xff) << (regpos * 8) // bits to clear 172 priority = priority << (regpos * 8) // bits to set 173 NVIC.IPR[regnum].Set((uint32(NVIC.IPR[regnum].Get()) &^ mask) | priority) 174 } 175 176 // DisableInterrupts disables all interrupts, and returns the old interrupt 177 // state. 178 // 179 //export DisableInterrupts 180 func DisableInterrupts() uintptr 181 182 // EnableInterrupts enables all interrupts again. The value passed in must be 183 // the mask returned by DisableInterrupts. 184 // 185 //export EnableInterrupts 186 func EnableInterrupts(mask uintptr) 187 188 // Set up the system timer to generate periodic tick events. 189 // This will cause SysTick_Handler to fire once per tick. 190 // The cyclecount parameter is a counter value which can range from 0 to 191 // 0xffffff. A value of 0 disables the timer. 192 func SetupSystemTimer(cyclecount uint32) error { 193 // turn it off 194 SYST.SYST_CSR.ClearBits(SYST_CSR_TICKINT | SYST_CSR_ENABLE) 195 if cyclecount == 0 { 196 // leave the system timer turned off. 197 return nil 198 } 199 if cyclecount&SYST_RVR_RELOAD_Msk != cyclecount { 200 // The cycle refresh register is only 24 bits wide. The user-specified value will overflow. 201 return errCycleCountTooLarge 202 } 203 204 // set refresh count 205 SYST.SYST_RVR.Set(cyclecount) 206 // set current counter value 207 SYST.SYST_CVR.Set(cyclecount) 208 // enable clock, enable SysTick interrupt when clock reaches 0, run it off of the processor clock 209 SYST.SYST_CSR.SetBits(SYST_CSR_TICKINT | SYST_CSR_ENABLE | SYST_CSR_CLKSOURCE) 210 return nil 211 }