all: add HiFive1 rev B board with RISC-V architecture

This page has been a big help in adding support for this new chip:
https://wiki.osdev.org/HiFive-1_Bare_Bones
This commit is contained in:
Ayke van Laethem
2019-03-30 12:54:36 +01:00
committed by Ron Evans
parent f0eb4eef5a
commit ffa38b183b
37 changed files with 485 additions and 74 deletions
+10
View File
@@ -0,0 +1,10 @@
package riscv
// Run the given assembly code. The code will be marked as having side effects,
// as it doesn't produce output and thus would normally be eliminated by the
// optimizer.
func Asm(asm string)
// ReadRegister returns the contents of the specified register. The register
// must be a processor register, reachable with the "mov" instruction.
func ReadRegister(name string) uintptr
+13
View File
@@ -0,0 +1,13 @@
.section .init
.global _start
.type _start,@function
_start:
// Workaround for missing support of the la pseudo-instruction in Clang 8:
// https://reviews.llvm.org/D55325
lui sp, %hi(_stack_top)
addi sp, sp, %lo(_stack_top)
// see https://gnu-mcu-eclipse.github.io/arch/riscv/programmer/#the-gp-global-pointer-register
lui gp, %hi(__global_pointer$)
addi gp, gp, %lo(__global_pointer$)
call main
+38
View File
@@ -0,0 +1,38 @@
// +build hifive1b
package machine
const (
P00 Pin = 0
P01 Pin = 1
P02 Pin = 2
P03 Pin = 3
P04 Pin = 4
P05 Pin = 5
P06 Pin = 6
P07 Pin = 7
P08 Pin = 8
P09 Pin = 9
P10 Pin = 10
P11 Pin = 11
P12 Pin = 12
P13 Pin = 13
P14 Pin = 14
P15 Pin = 15
P16 Pin = 16
P17 Pin = 17
P18 Pin = 18
P19 Pin = 19
P20 Pin = 20
P21 Pin = 21
P22 Pin = 22
P23 Pin = 23
P24 Pin = 24
P25 Pin = 25
P26 Pin = 26
P27 Pin = 27
P28 Pin = 28
P29 Pin = 29
P30 Pin = 30
P31 Pin = 31
)
+19
View File
@@ -0,0 +1,19 @@
// +build hifive1b
package machine
const (
LED = LED1
LED1 = LED_RED
LED2 = LED_GREEN
LED3 = LED_BLUE
LED_RED = P22
LED_GREEN = P19
LED_BLUE = P21
)
const (
// TODO: figure out the pin numbers for these.
UART_TX_PIN = NoPin
UART_RX_PIN = NoPin
)
+1 -1
View File
@@ -1,4 +1,4 @@
// +build !stm32f4disco
// +build !stm32f4disco,!hifive1b
package machine
+54
View File
@@ -0,0 +1,54 @@
// +build fe310
package machine
import (
"device/sifive"
)
type PinMode uint8
const (
PinInput PinMode = iota
PinOutput
)
// Configure this pin with the given configuration.
func (p Pin) Configure(config PinConfig) {
sifive.GPIO0.INPUT_EN.SetBits(1 << uint8(p))
if config.Mode == PinOutput {
sifive.GPIO0.OUTPUT_EN.SetBits(1 << uint8(p))
}
}
// Set the pin to high or low.
func (p Pin) Set(high bool) {
if high {
sifive.GPIO0.PORT.SetBits(1 << uint8(p))
} else {
sifive.GPIO0.PORT.ClearBits(1 << uint8(p))
}
}
type UART struct {
Bus *sifive.UART_Type
Buffer *RingBuffer
}
var (
UART0 = UART{Bus: sifive.UART0, Buffer: NewRingBuffer()}
)
func (uart UART) Configure(config UARTConfig) {
// Assuming a 16Mhz Crystal (which is Y1 on the HiFive1), the divisor for a
// 115200 baud rate is 138.
sifive.UART0.DIV.Set(138)
sifive.UART0.TXCTRL.Set(sifive.UART_TXCTRL_ENABLE)
}
func (uart UART) WriteByte(c byte) {
for sifive.UART0.TXDATA.Get()&sifive.UART_TXDATA_FULL != 0 {
}
sifive.UART0.TXDATA.Set(uint32(c))
}
+1 -1
View File
@@ -1,4 +1,4 @@
// +build !avr,!nrf,!sam,!stm32
// +build !avr,!nrf,!sam,!sifive,!stm32
package machine
+1 -1
View File
@@ -1,4 +1,4 @@
// +build !stm32f407,!avr
// +build !stm32f407,!avr,!hifive1b
package machine
+1 -1
View File
@@ -1,4 +1,4 @@
// +build avr nrf sam stm32
// +build avr nrf sam sifive stm32
package machine
+1 -1
View File
@@ -1,4 +1,4 @@
// +build avr cortexm wasm
// +build avr cortexm tinygo.riscv wasm
package os
+1 -1
View File
@@ -1,4 +1,4 @@
// +build darwin linux,!avr,!cortexm
// +build darwin linux,!avr,!cortexm,!tinygo.riscv
package os
+1 -1
View File
@@ -1,4 +1,4 @@
// +build arm,!avr,!cortexm
// +build arm,!avr,!cortexm,!tinygo.riscv
package runtime
+1 -16
View File
@@ -2,26 +2,11 @@
package runtime
import (
"unsafe"
)
const GOARCH = "avr"
const GOARCH = "arm" // avr pretends to be arm
// The bitness of the CPU (e.g. 8, 32, 64).
const TargetBits = 8
//go:extern _heap_start
var heapStartSymbol unsafe.Pointer
//go:extern _heap_end
var heapEndSymbol unsafe.Pointer
var (
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
heapEnd = uintptr(unsafe.Pointer(&heapEndSymbol))
)
// Align on a word boundary.
func align(ptr uintptr) uintptr {
// No alignment necessary on the AVR.
-25
View File
@@ -3,8 +3,6 @@
package runtime
import (
"unsafe"
"device/arm"
)
@@ -13,29 +11,6 @@ const GOARCH = "arm"
// The bitness of the CPU (e.g. 8, 32, 64).
const TargetBits = 32
//go:extern _heap_start
var heapStartSymbol unsafe.Pointer
//go:extern _heap_end
var heapEndSymbol unsafe.Pointer
//go:extern _globals_start
var globalsStartSymbol unsafe.Pointer
//go:extern _globals_end
var globalsEndSymbol unsafe.Pointer
//go:extern _stack_top
var stackTopSymbol unsafe.Pointer
var (
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
heapEnd = uintptr(unsafe.Pointer(&heapEndSymbol))
globalsStart = uintptr(unsafe.Pointer(&globalsStartSymbol))
globalsEnd = uintptr(unsafe.Pointer(&globalsEndSymbol))
stackTop = uintptr(unsafe.Pointer(&stackTopSymbol))
)
// Align on word boundary.
func align(ptr uintptr) uintptr {
return (ptr + 3) &^ 3
+19
View File
@@ -0,0 +1,19 @@
// +build tinygo.riscv
package runtime
import "device/riscv"
const GOARCH = "arm" // riscv pretends to be arm
// The bitness of the CPU (e.g. 8, 32, 64).
const TargetBits = 32
// Align on word boundary.
func align(ptr uintptr) uintptr {
return (ptr + 3) &^ 3
}
func getCurrentStackPointer() uintptr {
return riscv.ReadRegister("sp")
}
+30
View File
@@ -0,0 +1,30 @@
// +build avr cortexm tinygo.riscv
package runtime
import (
"unsafe"
)
//go:extern _heap_start
var heapStartSymbol unsafe.Pointer
//go:extern _heap_end
var heapEndSymbol unsafe.Pointer
//go:extern _globals_start
var globalsStartSymbol unsafe.Pointer
//go:extern _globals_end
var globalsEndSymbol unsafe.Pointer
//go:extern _stack_top
var stackTopSymbol unsafe.Pointer
var (
heapStart = uintptr(unsafe.Pointer(&heapStartSymbol))
heapEnd = uintptr(unsafe.Pointer(&heapEndSymbol))
globalsStart = uintptr(unsafe.Pointer(&globalsStartSymbol))
globalsEnd = uintptr(unsafe.Pointer(&globalsEndSymbol))
stackTop = uintptr(unsafe.Pointer(&stackTopSymbol))
)
+1 -1
View File
@@ -1,5 +1,5 @@
// +build gc.conservative
// +build cortexm
// +build cortexm tinygo.riscv
package runtime
+1 -1
View File
@@ -1,5 +1,5 @@
// +build gc.conservative
// +build !cortexm
// +build !cortexm,!tinygo.riscv
package runtime
+1 -1
View File
@@ -1,5 +1,5 @@
// +build gc.conservative
// +build !cortexm
// +build !cortexm,!tinygo.riscv
package runtime
+1 -1
View File
@@ -1,5 +1,5 @@
// +build gc.conservative
// +build cortexm
// +build cortexm tinygo.riscv
package runtime
+115
View File
@@ -0,0 +1,115 @@
// +build fe310
// This file implements target-specific things for the FE310 chip as used in the
// HiFive1.
package runtime
import (
"machine"
"unsafe"
"device/riscv"
"device/sifive"
)
type timeUnit int64
const tickMicros = 32768 // RTC runs at 32.768kHz
//go:extern _sbss
var _sbss unsafe.Pointer
//go:extern _ebss
var _ebss unsafe.Pointer
//go:extern _sdata
var _sdata unsafe.Pointer
//go:extern _sidata
var _sidata unsafe.Pointer
//go:extern _edata
var _edata unsafe.Pointer
//go:export main
func main() {
preinit()
initAll()
callMain()
abort()
}
func init() {
pric_init()
machine.UART0.Configure(machine.UARTConfig{})
}
func pric_init() {
// Make sure the HFROSC is on
sifive.PRIC.HFROSCCFG.SetBits(sifive.PRIC_HFROSCCFG_ENABLE)
// Run off 16 MHz Crystal for accuracy.
sifive.PRIC.PLLCFG.SetBits(sifive.PRIC_PLLCFG_REFSEL | sifive.PRIC_PLLCFG_BYPASS)
sifive.PRIC.PLLCFG.SetBits(sifive.PRIC_PLLCFG_SEL)
// Turn off HFROSC to save power
sifive.PRIC.HFROSCCFG.ClearBits(sifive.PRIC_HFROSCCFG_ENABLE)
// Enable the RTC.
sifive.RTC.CONFIG.Set(sifive.RTC_CONFIG_ENALWAYS)
}
func preinit() {
// Initialize .bss: zero-initialized global variables.
ptr := uintptr(unsafe.Pointer(&_sbss))
for ptr != uintptr(unsafe.Pointer(&_ebss)) {
*(*uint32)(unsafe.Pointer(ptr)) = 0
ptr += 4
}
// Initialize .data: global variables initialized from flash.
src := uintptr(unsafe.Pointer(&_sidata))
dst := uintptr(unsafe.Pointer(&_sdata))
for dst != uintptr(unsafe.Pointer(&_edata)) {
*(*uint32)(unsafe.Pointer(dst)) = *(*uint32)(unsafe.Pointer(src))
dst += 4
src += 4
}
}
func putchar(c byte) {
machine.UART0.WriteByte(c)
}
func ticks() timeUnit {
// Combining the low bits and the high bits yields a time span of over 270
// years without counter rollover.
highBits := sifive.RTC.HI.Get()
for {
lowBits := sifive.RTC.LO.Get()
newHighBits := sifive.RTC.HI.Get()
if newHighBits == highBits {
// High bits stayed the same.
return timeUnit(lowBits) | (timeUnit(highBits) << 32)
}
// Retry, because there was a rollover in the low bits (happening every
// 1.5 days).
highBits = newHighBits
}
}
const asyncScheduler = false
func sleepTicks(d timeUnit) {
target := ticks() + d
for ticks() < target {
}
}
func abort() {
// lock up forever
for {
riscv.Asm("wfi")
}
}
+19
View File
@@ -0,0 +1,19 @@
// +build tinygo.riscv
package runtime
import "unsafe"
// Implement memset for LLVM.
//go:export memset
func libc_memset(ptr unsafe.Pointer, c byte, size uintptr) {
for i := uintptr(0); i < size; i++ {
*(*byte)(unsafe.Pointer(uintptr(ptr) + i)) = c
}
}
// Implement memmove for LLVM.
//go:export memmove
func libc_memmove(dst, src unsafe.Pointer, size uintptr) {
memmove(dst, src, size)
}
+1 -1
View File
@@ -1,4 +1,4 @@
// +build darwin linux,!avr,!cortexm
// +build darwin linux,!avr,!cortexm,!tinygo.riscv
package runtime