Browse Source

Add 03-clock.

master
flabbergast 5 months ago
parent
commit
14c5d31dbe
  1. BIN
      02-chase.gif
  2. 30
      03-clock/Makefile
  3. 53
      03-clock/main.s
  4. 1
      03-clock/memmap
  5. 57
      03-clock/p_clock.s
  6. 35
      03-clock/p_delay.s
  7. 45
      03-clock/platform_regs.inc

BIN
02-chase.gif

After

Width: 320  |  Height: 180  |  Size: 740 KiB

30
03-clock/Makefile

@ -0,0 +1,30 @@
PROG ?= main
JLINKEXE ?= ~/.platformio/packages/tool-jlink/JLinkExe
PREFIX ?= riscv32-elf-
ARCH ?= rv32imac
AFLAGS = --warn --fatal-warnings
LDFLAGS = -m elf32lriscv -b elf32-littleriscv
all: $(PROG).hex
$(PROG).o: $(PROG).s
$(PREFIX)as -march=$(ARCH) $(AFLAGS) $(PROG).s -o $(PROG).o
$(PROG).hex: memmap $(PROG).o
$(PREFIX)ld $(LDFLAGS) -o $(PROG).elf -T memmap $(PROG).o
$(PREFIX)objdump -Mnumeric -D $(PROG).elf > $(PROG).list
$(PREFIX)objcopy $(PROG).elf $(PROG).bin -O binary
$(PREFIX)objcopy $(PROG).elf $(PROG).hex -O ihex
flash: $(PROG).hex
echo -e "loadfile $(PROG).hex\nr\ng\nexit\n" | $(JLINKEXE) -device FE310 -if JTAG -speed 4000 -si JTAG -jtagconf -1,-1 -autoconnect 1
clean:
rm -f *.bin
rm -f *.hex
rm -f *.o
rm -f *.elf
rm -f *.list

53
03-clock/main.s

@ -0,0 +1,53 @@
#
#
# 2021 flabbergast <flabbergast@drak.xyz>
# Unlicense: https://unlicense.org/
#
.option norelax
# -----------------------------------------------------------------------------
# Code begins here
# -----------------------------------------------------------------------------
.text
j Reset # Instead of a true vector table
# -----------------------------------------------------------------------------
# Include any supporting code
# -----------------------------------------------------------------------------
.include "platform_regs.inc"
.include "p_clock.s"
.include "p_delay.s"
# -----------------------------------------------------------------------------
Reset: # Execution begins here
# -----------------------------------------------------------------------------
# Set base address for interrupt handler
# la x15, irq_collection
# csrrs zero, mtvec, x15
# the board (usually) runs on 13.8MHz HFROSC on boot?
call clock_extcryst # switch to external crystal, 16MHz
# call clock_pll_64mhz # switch to 64MHz PLL driven by 16MHz ext crystal
li s1, GPIO_CTRL_BASE
li s2, 0b111111<<18 # pins 18-23
sw s2, GPIO_OUTPUT_EN(s1) # set as outputs
li a0, 200 # delay in ms
li s2, 0b1<<18 # start with pin 18
li s3, 0b1<<23 # end with pin 23
1:
sw s2, GPIO_OUTPUT_VAL(s1) # make the pin high
# call delay
call deelay
slli s2, s2, 1 # move one to the left
bleu s2, s3, 1b # did we move past last pin?
li s2, 0b1<<18 # back to the first pin
j 1b
end:
j end

1
03-clock/memmap

@ -0,0 +1 @@
../memmap

57
03-clock/p_clock.s

@ -0,0 +1,57 @@
.align 2
.include "platform_regs.inc"
# switch to external crystal (16MHz on red-v thing)
clock_extcryst:
li t0, PRCI_BASE
1: # Wait for crystal to oscillate
lw t1, PRCI_HFXOSCCFG(t0) # hfxoscen(bit30) is on by default on reset
bgtz t1, 1b # ... hfxoscrdy(bit31): makes value negative
li t1, 0x00070df1 # 0x00060df1 | (1<<16) | (1<<17) | (1<<18)
# = Reset value | PLLSEL | PLLREFSEL | PLLBYPASS
sw t1, PRCI_PLLCFG(t0) # Select crystal as the main clock source
ret
# switch to 64MHz PLL driven by 16MHz external crystal
clock_pll_64mhz:
li t0, PRCI_BASE
1: # Wait for crystal to oscillate
lw t1, PRCI_HFXOSCCFG(t0) # hfxoscen(bit30) is on by default on reset
bgtz t1, 1b # ... hfxoscrdy(bit31): makes value negative
# Set PLL to 64 MHz (don't activate); 64 = 16 /(2^1) *(2*(31+1)) /(2^3)
li t1, 0x20df1 # pllr=1, pllf=0x1f, pllq=0x3 (reset vals)
sw t1, PRCI_PLLCFG(t0) # pllsel=0, pllrefsel=1, pllbypass=0(!)
2: # Wait for PLL to lock: plllock(bit31): sign bit
lw t1, PRCI_PLLCFG(t0)
bgtz t1, 2b
li t1, 0x30df1 # pllsel=1 (on top of the above)
sw t1, PRCI_PLLCFG(t0)
ret
# switch to 320MHz PLL driven by 16MHz external crystal
# (the board gets quite warm!)
clock_pll_320mhz:
li t0, PRCI_BASE
1: # Wait for crystal to oscillate
lw t1, PRCI_HFXOSCCFG(t0) # hfxoscen(bit30) is on by default on reset
bgtz t1, 1b # ... hfxoscrdy(bit31): makes value negative
# Set PLL to 320 MHz (don't activate); 320 = 16 /(2^1) *(2*(39+1)) /(2^1)
li t1, 0x20671 # pllr=1, pllf=0x27(!), pllq=1(!)
sw t1, PRCI_PLLCFG(t0) # pllsel=0, pllrefsel=1, pllbypass=0(!)
2: # Wait for PLL to lock: plllock(bit31): sign bit
lw t1, PRCI_PLLCFG(t0)
bgtz t1, 2b
li t1, 0x30671 # pllsel=1 (on top of the above)
sw t1, PRCI_PLLCFG(t0)
ret

35
03-clock/p_delay.s

@ -0,0 +1,35 @@
.align 2
.include "platform_regs.inc"
.equ MTIME_FREQUENCY, 33 # 32_768 Hz clock
# a0: delay value in milliseconds
# (should be less than 0xFFFF_FFFF/33/4)
delay:
li t0, CLINT_CTRL_BASE+CLINT_MTIME # Load the timer registers base
lw t1, 0(t0) # Load the current value of the timer
li t2, MTIME_FREQUENCY # Get our clock frequency
mul t2, t2, a0 # Multiply milliseconds with frequency
add t2, t1, t2 # Target mtime is now in t2
bltu t2, t1, 2f # Overflown back to zero?
# if yes, (signed)t1<0
1:
lw t1, 0(t0) # Read mtime value again
bltu t1, t2, 1b # Keep looping until timout
ret
2: # Overflown branch
lw t1, 0(t0) # Read mtime; t1 can be "<0"
blt t1, t2, 2b # Do signed compare
ret
deelay:
li a0, 8000000
# a0: (delay in cycles)/2
busy_delay_cycles:
1:
addi a0, a0, -1
bnez a0, 1b
ret

45
03-clock/platform_regs.inc

@ -0,0 +1,45 @@
# SPDX-License-Identifier: Unlicense
# Copyright (c) 2018 Western Digital Corporation or its affiliates.
.equ GPIO_CTRL_BASE, 0x10012000
.equ GPIO_INPUT_VAL, 0x00
.equ GPIO_INPUT_EN, 0x04
.equ GPIO_OUTPUT_EN, 0x08
.equ GPIO_OUTPUT_VAL, 0x0C
.equ GPIO_PUE, 0x10
.equ GPIO_DS, 0x14
.equ GPIO_RISE_IE, 0x18
.equ GPIO_RISE_IP, 0x1C
.equ GPIO_FALL_IE, 0x20
.equ GPIO_FALL_IP, 0x24
.equ GPIO_HIGH_IE, 0x28
.equ GPIO_HIGH_IP, 0x2C
.equ GPIO_LOW_IE, 0x30
.equ GPIO_LOW_IP, 0x34
.equ GPIO_IOF_EN, 0x38
.equ GPIO_IOF_SEL, 0x3C
.equ GPIO_OUTPUT_XOR, 0x40
.equ CLINT_CTRL_BASE, 0x02000000
.equ CLINT_MSIP, 0x0000
.equ CLINT_MTIMECMP, 0x4000
.equ CLINT_MTIME, 0xBFF8
.equ PRCI_BASE, 0x10008000
.equ PRCI_HFROSCCFG, 0x00 # Ring osc config
.equ PRCI_HFXOSCCFG, 0x04 # XTAL osc config
.equ PRCI_PLLCFG, 0x08 # PLL config
.equ PRCI_PLLOUTDIV, 0x0C
.equ PRCI_PROCMONCFG, 0xF0
.equ PRCI_PLLCFG_PLLSEL, 1<<16 # PLL selected as clock source
.equ PRCI_PLLCFG_PLLREFSEL, 1<<17 # PLL to take XTAL as reference
.equ PRCI_PLLCFG_PLLBYPASS, 1<<18 # PLL bypassed and shut off
.equ UART0_BASE, 0x10013000
.equ UART0_TXDATA, 0x00
.equ UART0_RXDATA, 0x04
.equ UART0_TXCTRL, 0x08
.equ UART0_RXCTRL, 0x0C
.equ UART0_IE, 0x10
.equ UART0_IP, 0x14
.equ UART0_DIV, 0x18
Loading…
Cancel
Save