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  }