Skip to content

Commit

Permalink
all: add HiFive1 rev B board with RISC-V architecture
Browse files Browse the repository at this point in the history
This page has been a big help in adding support for this new chip:
https://wiki.osdev.org/HiFive-1_Bare_Bones
  • Loading branch information
aykevl authored and deadprogram committed Jul 7, 2019
1 parent f0eb4ee commit ffa38b1
Show file tree
Hide file tree
Showing 37 changed files with 485 additions and 74 deletions.
20 changes: 15 additions & 5 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ commands:
- run: go install .
- run: go test -v
- run: make gen-device -j4
- run: make smoketest
- run: make smoketest RISCV=0
- save_cache:
key: go-cache-{{ checksum "Gopkg.lock" }}-{{ .Environment.CIRCLE_BUILD_NUM }}
paths:
Expand Down Expand Up @@ -100,7 +100,7 @@ commands:
- llvm-source-linux
- restore_cache:
keys:
- llvm-build-8-linux-v6
- llvm-build-8-linux-v7
- run:
name: "Build LLVM"
command: |
Expand All @@ -118,7 +118,7 @@ commands:
make llvm-build
fi
- save_cache:
key: llvm-build-8-linux-v6
key: llvm-build-8-linux-v7
paths:
llvm-build
- run:
Expand Down Expand Up @@ -149,6 +149,11 @@ commands:
tar -C ~/lib -xf /tmp/tinygo.linux-amd64.tar.gz
ln -s ~/lib/tinygo/bin/tinygo /go/bin/tinygo
tinygo version
- run:
name: "Download SiFive GNU toolchain"
command: |
curl -O https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.2.0-2019.05.3-x86_64-linux-ubuntu14.tar.gz
sudo tar -C /usr/local --strip-components=1 -xf riscv64-unknown-elf-gcc-8.2.0-2019.05.3-x86_64-linux-ubuntu14.tar.gz
- run: make smoketest
build-macos:
steps:
Expand All @@ -173,7 +178,7 @@ commands:
- llvm-project
- restore_cache:
keys:
- llvm-build-8-macos-v5
- llvm-build-8-macos-v6
- run:
name: "Build LLVM"
command: |
Expand All @@ -185,7 +190,7 @@ commands:
make llvm-build
fi
- save_cache:
key: llvm-build-8-macos-v5
key: llvm-build-8-macos-v6
paths:
llvm-build
- run:
Expand All @@ -209,6 +214,11 @@ commands:
tar -C /usr/local/opt -xf /tmp/tinygo.darwin-amd64.tar.gz
ln -s /usr/local/opt/tinygo/bin/tinygo /usr/local/bin/tinygo
tinygo version
- run:
name: "Download SiFive GNU toolchain"
command: |
curl -O https://static.dev.sifive.com/dev-tools/riscv64-unknown-elf-gcc-8.2.0-2019.05.3-x86_64-apple-darwin.tar.gz
sudo tar -C /usr/local --strip-components=1 -xf riscv64-unknown-elf-gcc-8.2.0-2019.05.3-x86_64-apple-darwin.tar.gz
- run: make smoketest AVR=0


Expand Down
6 changes: 4 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ src/device/avr/*.ld
src/device/avr/*.s
src/device/nrf/*.go
src/device/nrf/*.s
src/device/stm32/*.go
src/device/stm32/*.s
src/device/sam/*.go
src/device/sam/*.s
src/device/sifive/*.go
src/device/sifive/*.s
src/device/stm32/*.go
src/device/stm32/*.s
vendor
llvm
llvm-build
2 changes: 1 addition & 1 deletion .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
url = https://github.com/avr-rust/avr-mcu.git
[submodule "lib/cmsis-svd"]
path = lib/cmsis-svd
url = https://github.com/posborne/cmsis-svd
url = https://github.com/tinygo-org/cmsis-svd
[submodule "lib/compiler-rt"]
path = lib/compiler-rt
url = https://github.com/llvm-mirror/compiler-rt.git
Expand Down
11 changes: 9 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ fmt-check:
@unformatted=$$(gofmt -l $(FMT_PATHS)); [ -z "$$unformatted" ] && exit 0; echo "Unformatted:"; for fn in $$unformatted; do echo " $$fn"; done; exit 1


gen-device: gen-device-avr gen-device-nrf gen-device-sam gen-device-stm32
gen-device: gen-device-avr gen-device-nrf gen-device-sam gen-device-sifive gen-device-stm32

gen-device-avr:
./tools/gen-device-avr.py lib/avr/packs/atmega src/device/avr/
Expand All @@ -56,6 +56,10 @@ gen-device-sam:
./tools/gen-device-svd.py lib/cmsis-svd/data/Atmel/ src/device/sam/ --source=https://github.com/posborne/cmsis-svd/tree/master/data/Atmel
go fmt ./src/device/sam

gen-device-sifive:
./tools/gen-device-svd.py lib/cmsis-svd/data/SiFive-Community/ src/device/sifive/ --source=https://github.com/AdaCore/svd2ada/tree/master/CMSIS-SVD/SiFive-Community
go fmt ./src/device/sifive

gen-device-stm32:
./tools/gen-device-svd.py lib/cmsis-svd/data/STMicro/ src/device/stm32/ --source=https://github.com/posborne/cmsis-svd/tree/master/data/STMicro
go fmt ./src/device/stm32
Expand All @@ -69,7 +73,7 @@ llvm-source: llvm-project/README.md
# Configure LLVM.
TINYGO_SOURCE_DIR=$(shell pwd)
$(LLVM_BUILDDIR)/build.ninja: llvm-source
mkdir -p $(LLVM_BUILDDIR); cd $(LLVM_BUILDDIR); cmake -G Ninja $(TINYGO_SOURCE_DIR)/llvm-project/llvm "-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64;WebAssembly" "-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=AVR" -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=OFF -DLIBCLANG_BUILD_STATIC=ON -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD=OFF
mkdir -p $(LLVM_BUILDDIR); cd $(LLVM_BUILDDIR); cmake -G Ninja $(TINYGO_SOURCE_DIR)/llvm-project/llvm "-DLLVM_TARGETS_TO_BUILD=X86;ARM;AArch64;WebAssembly" "-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=AVR;RISCV" -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_ASSERTIONS=OFF -DLIBCLANG_BUILD_STATIC=ON -DLLVM_ENABLE_TERMINFO=OFF -DLLVM_ENABLE_ZLIB=OFF -DLLVM_ENABLE_PROJECTS="clang;lld" -DLLVM_TOOL_CLANG_TOOLS_EXTRA_BUILD=OFF

# Build LLVM.
$(LLVM_BUILDDIR): $(LLVM_BUILDDIR)/build.ninja
Expand Down Expand Up @@ -123,6 +127,9 @@ smoketest:
ifneq ($(AVR), 0)
tinygo build -size short -o test.elf -target=arduino examples/blinky1
tinygo build -size short -o test.elf -target=digispark examples/blinky1
endif
ifneq ($(RISCV), 0)
tinygo build -size short -o test.elf -target=hifive1b examples/blinky1
endif
tinygo build -o wasm.wasm -target=wasm examples/wasm/export
tinygo build -o wasm.wasm -target=wasm examples/wasm/main
Expand Down
10 changes: 5 additions & 5 deletions compiler/compiler.go
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ func (c *Compiler) Compile(mainPath string) []error {
return path
} else if path == "syscall" {
for _, tag := range c.BuildTags {
if tag == "avr" || tag == "cortexm" || tag == "darwin" {
if tag == "avr" || tag == "cortexm" || tag == "darwin" || tag == "riscv" {
return path
}
}
Expand Down Expand Up @@ -1304,11 +1304,11 @@ func (c *Compiler) parseCall(frame *Frame, instr *ssa.CallCommon) (llvm.Value, e
if fn := instr.StaticCallee(); fn != nil {
name := fn.RelString(nil)
switch {
case name == "device/arm.ReadRegister":
return c.emitReadRegister(instr.Args)
case name == "device/arm.Asm" || name == "device/avr.Asm":
case name == "device/arm.ReadRegister" || name == "device/riscv.ReadRegister":
return c.emitReadRegister(name, instr.Args)
case name == "device/arm.Asm" || name == "device/avr.Asm" || name == "device/riscv.Asm":
return c.emitAsm(instr.Args)
case name == "device/arm.AsmFull" || name == "device/avr.AsmFull":
case name == "device/arm.AsmFull" || name == "device/avr.AsmFull" || name == "device/riscv.AsmFull":
return c.emitAsmFull(frame, instr)
case strings.HasPrefix(name, "device/arm.SVCall"):
return c.emitSVCall(frame, instr.Args)
Expand Down
2 changes: 1 addition & 1 deletion compiler/gc.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func (c *Compiler) needsStackObjects() bool {
return false
}
for _, tag := range c.BuildTags {
if tag == "cortexm" {
if tag == "cortexm" || tag == "tinygo.riscv" {
return false
}
}
Expand Down
13 changes: 11 additions & 2 deletions compiler/inlineasm.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,19 @@ import (
// func ReadRegister(name string) uintptr
//
// The register name must be a constant, for example "sp".
func (c *Compiler) emitReadRegister(args []ssa.Value) (llvm.Value, error) {
func (c *Compiler) emitReadRegister(name string, args []ssa.Value) (llvm.Value, error) {
fnType := llvm.FunctionType(c.uintptrType, []llvm.Type{}, false)
regname := constant.StringVal(args[0].(*ssa.Const).Value)
target := llvm.InlineAsm(fnType, "mov $0, "+regname, "=r", false, false, 0)
var asm string
switch name {
case "device/arm.ReadRegister":
asm = "mov $0, " + regname
case "device/riscv.ReadRegister":
asm = "mv $0, " + regname
default:
panic("unknown architecture")
}
target := llvm.InlineAsm(fnType, asm, "=r", false, false, 0)
return c.builder.CreateCall(target, nil, ""), nil
}

Expand Down
10 changes: 10 additions & 0 deletions src/device/riscv/riscv.go
Original file line number Diff line number Diff line change
@@ -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 changes: 13 additions & 0 deletions src/device/riscv/start.S
Original file line number Diff line number Diff line change
@@ -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 changes: 38 additions & 0 deletions src/machine/board_fe310.go
Original file line number Diff line number Diff line change
@@ -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 changes: 19 additions & 0 deletions src/machine/board_hifive1b.go
Original file line number Diff line number Diff line change
@@ -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
)
2 changes: 1 addition & 1 deletion src/machine/i2c.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !stm32f4disco
// +build !stm32f4disco,!hifive1b

package machine

Expand Down
54 changes: 54 additions & 0 deletions src/machine/machine_fe310.go
Original file line number Diff line number Diff line change
@@ -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))
}
2 changes: 1 addition & 1 deletion src/machine/machine_generic.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !avr,!nrf,!sam,!stm32
// +build !avr,!nrf,!sam,!sifive,!stm32

package machine

Expand Down
2 changes: 1 addition & 1 deletion src/machine/spi.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build !stm32f407,!avr
// +build !stm32f407,!avr,!hifive1b

package machine

Expand Down
2 changes: 1 addition & 1 deletion src/machine/uart.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build avr nrf sam stm32
// +build avr nrf sam sifive stm32

package machine

Expand Down
2 changes: 1 addition & 1 deletion src/os/file_other.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build avr cortexm wasm
// +build avr cortexm tinygo.riscv wasm

package os

Expand Down
2 changes: 1 addition & 1 deletion src/os/file_unix.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build darwin linux,!avr,!cortexm
// +build darwin linux,!avr,!cortexm,!tinygo.riscv

package os

Expand Down
2 changes: 1 addition & 1 deletion src/runtime/arch_arm.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// +build arm,!avr,!cortexm
// +build arm,!avr,!cortexm,!tinygo.riscv

package runtime

Expand Down
17 changes: 1 addition & 16 deletions src/runtime/arch_avr.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading

0 comments on commit ffa38b1

Please sign in to comment.