We use MTIME that is a 64 bit counter that runs at a frequency of 32768 Khz
MTIME in intended to count machine time, unlike RTC time which also exists in on the board but is more intended for measuring seconds and used as OS time.
# CLINT memory map ====================================================.equ MTIME_FREQUENCY, 32768 .equ MTIME_LOW_ADDR, 0x0200bff8 # MTIME LOW address .equ MTIME_HIGH_ADDR, 0x0200bffc # MTIME HIGH address
To measure in, milliseconds we split the high and low count
.equ ms_to_cycles_int, 32 # Integer part of 32.768 cycles per millisecond .equ ms_to_cycles_rem, 768 # Fractional remainder as parts per 1000
We can now create a function where a0 is the time to sleep in milliseconds
.globl _sleep_time _sleep_time: # Save a0 on the stack (assuming it is the delay in milliseconds) PUSH a0 # Convert milliseconds to RTC cycles li t0, 32 # Load the integer part of cycles per millisecond (32) mul t0, t0, a0 # Multiply by the number of milliseconds (a0) li t1, 768 # Load the remainder part (768) mul t1, t1, a0 # Multiply remainder by the number of milliseconds li t2, 1000 # Load the scaling factor (1000) div t1, t1, t2 # Divide to get the fractional part in cycles (as an integer) add t0, t0, t1 # Add both the integer and fractional parts # Load mtime base addresses for the Red-V board li t1, MTIME_LOW_ADDR # Load address of mtime low into t1 li t2, MTIME_HIGH_ADDR # Load address of mtime high into t2 # Get the current mtime (with consistency check) 1: lw t3, 0(t1) # Load mtime low lw t4, 0(t2) # Load mtime high lw t5, 0(t1) # Re-read mtime low for consistency bne t3, t5, 1b # Retry if inconsistent # Set target time add t6, t3, t0 # Set target time (low part) # Poll until mtime reaches the target value 2: lw t3, 0(t1) # Reload current mtime low lw t4, 0(t2) # Reload current mtime high bge t3, t6, 3f # Exit loop if current time >= target (low part) j 2b # Keep looping 3: POP a0 ret
We now create a macro
.macro SLEEP_MS ms
PUSH a0
# Load the precomputed cycle delay based on the input milliseconds
li a0, \ms
jal _sleep_time
POP a0
.endm
And can be used like this
LOG_INFO STRING_TIMING_START_MSG
SLEEP_MS 3000
LOG_INFO STRING_TIMING_END_MSG
Discussions
Become a Hackaday.io Member
Create an account to leave a comment. Already have an account? Log In.