aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAyke van Laethem <[email protected]>2018-10-05 14:14:32 +0200
committerAyke van Laethem <[email protected]>2018-10-06 13:04:14 +0200
commitbc9210b6740dc7ff9146238ccb5b4014965a92cd (patch)
tree4bc7f0bf265100197129d74f19e7ae90ae0d9113
parente4fa1a8288f7f0d539cbf0df26d554cac89ab8a6 (diff)
downloadtinygo-bc9210b6740dc7ff9146238ccb5b4014965a92cd.tar.gz
tinygo-bc9210b6740dc7ff9146238ccb5b4014965a92cd.zip
nrf: add micro:bit board
-rw-r--r--src/machine/board_microbit.go32
-rw-r--r--src/machine/board_pca10040.go3
-rw-r--r--src/machine/machine_nrf.go22
-rw-r--r--src/machine/machine_nrf51.go17
-rw-r--r--src/machine/machine_nrf52.go10
-rw-r--r--src/runtime/runtime_nrf.go4
-rw-r--r--targets/arm.ld1
-rw-r--r--targets/microbit.json25
-rw-r--r--targets/nrf51.ld10
-rwxr-xr-xtools/gen-device-svd.py37
10 files changed, 139 insertions, 22 deletions
diff --git a/src/machine/board_microbit.go b/src/machine/board_microbit.go
new file mode 100644
index 000000000..9a23718bc
--- /dev/null
+++ b/src/machine/board_microbit.go
@@ -0,0 +1,32 @@
+// +build nrf,microbit
+
+package machine
+
+// The micro:bit does not have a 32kHz crystal on board.
+const HasLowFrequencyCrystal = false
+
+// Buttons on the micro:bit (A and B)
+const (
+ BUTTON = BUTTON1
+ BUTTON1 = 5
+ BUTTON2 = 11
+)
+
+// UART pins
+const (
+ UART_TX_PIN = 24
+ UART_RX_PIN = 25
+)
+
+// ADC pins
+const (
+ ADC0 = 0
+ ADC1 = 1
+ ADC2 = 2
+)
+
+// I2C pins
+const (
+ SDA_PIN = 20
+ SCL_PIN = 19
+)
diff --git a/src/machine/board_pca10040.go b/src/machine/board_pca10040.go
index 3ba0c5f7a..065fda199 100644
--- a/src/machine/board_pca10040.go
+++ b/src/machine/board_pca10040.go
@@ -2,6 +2,9 @@
package machine
+// The PCA10040 has a low-frequency (32kHz) crystal oscillator on board.
+const HasLowFrequencyCrystal = true
+
// LEDs on the PCA10040 (nRF52832 dev board)
const (
LED = LED1
diff --git a/src/machine/machine_nrf.go b/src/machine/machine_nrf.go
index 9308b9e78..f155da07c 100644
--- a/src/machine/machine_nrf.go
+++ b/src/machine/machine_nrf.go
@@ -19,22 +19,25 @@ const (
// Configure this pin with the given configuration.
func (p GPIO) Configure(config GPIOConfig) {
cfg := config.Mode | nrf.GPIO_PIN_CNF_DRIVE_S0S1 | nrf.GPIO_PIN_CNF_SENSE_Disabled
- nrf.P0.PIN_CNF[p.Pin] = nrf.RegValue(cfg)
+ port, pin := p.getPortPin()
+ port.PIN_CNF[pin] = nrf.RegValue(cfg)
}
// Set the pin to high or low.
// Warning: only use this on an output pin!
func (p GPIO) Set(high bool) {
+ port, pin := p.getPortPin()
if high {
- nrf.P0.OUTSET = 1 << p.Pin
+ port.OUTSET = 1 << pin
} else {
- nrf.P0.OUTCLR = 1 << p.Pin
+ port.OUTCLR = 1 << pin
}
}
// Get returns the current value of a GPIO pin.
func (p GPIO) Get() bool {
- return (nrf.P0.IN>>p.Pin)&1 != 0
+ port, pin := p.getPortPin()
+ return (port.IN>>pin)&1 != 0
}
// UART
@@ -62,7 +65,7 @@ func (uart UART) Configure(config UARTConfig) {
nrf.UART0.INTENSET = nrf.UART_INTENSET_RXDRDY_Msk
// Enable RX IRQ.
- arm.EnableIRQ(nrf.IRQ_UARTE0_UART0)
+ arm.EnableIRQ(nrf.IRQ_UART0)
}
// SetBaudRate sets the communication speed for the UART.
@@ -89,8 +92,7 @@ func (uart UART) WriteByte(c byte) error {
return nil
}
-//go:export UARTE0_UART0_IRQHandler
-func handleUART0() {
+func (uart UART) handleInterrupt() {
if nrf.UART0.EVENTS_RXDRDY != 0 {
bufferPut(byte(nrf.UART0.RXD))
nrf.UART0.EVENTS_RXDRDY = 0x0
@@ -128,13 +130,15 @@ func (i2c I2C) Configure(config I2CConfig) {
}
// do config
- nrf.P0.PIN_CNF[config.SCL] = (nrf.GPIO_PIN_CNF_DIR_Input << nrf.GPIO_PIN_CNF_DIR_Pos) |
+ sclPort, sclPin := GPIO{config.SCL}.getPortPin()
+ sclPort.PIN_CNF[sclPin] = (nrf.GPIO_PIN_CNF_DIR_Input << nrf.GPIO_PIN_CNF_DIR_Pos) |
(nrf.GPIO_PIN_CNF_INPUT_Connect << nrf.GPIO_PIN_CNF_INPUT_Pos) |
(nrf.GPIO_PIN_CNF_PULL_Pullup << nrf.GPIO_PIN_CNF_PULL_Pos) |
(nrf.GPIO_PIN_CNF_DRIVE_S0D1 << nrf.GPIO_PIN_CNF_DRIVE_Pos) |
(nrf.GPIO_PIN_CNF_SENSE_Disabled << nrf.GPIO_PIN_CNF_SENSE_Pos)
- nrf.P0.PIN_CNF[config.SDA] = (nrf.GPIO_PIN_CNF_DIR_Input << nrf.GPIO_PIN_CNF_DIR_Pos) |
+ sdaPort, sdaPin := GPIO{config.SDA}.getPortPin()
+ sdaPort.PIN_CNF[sdaPin] = (nrf.GPIO_PIN_CNF_DIR_Input << nrf.GPIO_PIN_CNF_DIR_Pos) |
(nrf.GPIO_PIN_CNF_INPUT_Connect << nrf.GPIO_PIN_CNF_INPUT_Pos) |
(nrf.GPIO_PIN_CNF_PULL_Pullup << nrf.GPIO_PIN_CNF_PULL_Pos) |
(nrf.GPIO_PIN_CNF_DRIVE_S0D1 << nrf.GPIO_PIN_CNF_DRIVE_Pos) |
diff --git a/src/machine/machine_nrf51.go b/src/machine/machine_nrf51.go
new file mode 100644
index 000000000..29abf989a
--- /dev/null
+++ b/src/machine/machine_nrf51.go
@@ -0,0 +1,17 @@
+// +build nrf51
+
+package machine
+
+import (
+ "device/nrf"
+)
+
+// Get peripheral and pin number for this GPIO pin.
+func (p GPIO) getPortPin() (*nrf.GPIO_Type, uint8) {
+ return nrf.GPIO, p.Pin
+}
+
+//go:export UART0_IRQHandler
+func handleUART0() {
+ UART0.handleInterrupt()
+}
diff --git a/src/machine/machine_nrf52.go b/src/machine/machine_nrf52.go
index f62c10f1d..1022df58e 100644
--- a/src/machine/machine_nrf52.go
+++ b/src/machine/machine_nrf52.go
@@ -7,6 +7,16 @@ import (
"unsafe"
)
+// Get peripheral and pin number for this GPIO pin.
+func (p GPIO) getPortPin() (*nrf.GPIO_Type, uint8) {
+ return nrf.P0, p.Pin
+}
+
+//go:export UARTE0_UART0_IRQHandler
+func handleUART0() {
+ UART0.handleInterrupt()
+}
+
// InitADC initializes the registers needed for ADC.
func InitADC() {
return // no specific setup on nrf52 machine.
diff --git a/src/runtime/runtime_nrf.go b/src/runtime/runtime_nrf.go
index 067549503..893a48a06 100644
--- a/src/runtime/runtime_nrf.go
+++ b/src/runtime/runtime_nrf.go
@@ -28,7 +28,9 @@ func init() {
}
func initLFCLK() {
- nrf.CLOCK.LFCLKSRC = nrf.CLOCK_LFCLKSTAT_SRC_Xtal
+ if machine.HasLowFrequencyCrystal {
+ nrf.CLOCK.LFCLKSRC = nrf.CLOCK_LFCLKSTAT_SRC_Xtal
+ }
nrf.CLOCK.TASKS_LFCLKSTART = 1
for nrf.CLOCK.EVENTS_LFCLKSTARTED == 0 {
}
diff --git a/targets/arm.ld b/targets/arm.ld
index 1cf417831..59bbf34be 100644
--- a/targets/arm.ld
+++ b/targets/arm.ld
@@ -10,6 +10,7 @@ SECTIONS
*(.text*)
*(.rodata)
*(.rodata*)
+ . = ALIGN(4);
} >FLASH_TEXT
/* Put the stack at the bottom of RAM, so that the application will
diff --git a/targets/microbit.json b/targets/microbit.json
new file mode 100644
index 000000000..02f4fc263
--- /dev/null
+++ b/targets/microbit.json
@@ -0,0 +1,25 @@
+{
+ "llvm-target": "armv6m-none-eabi",
+ "build-tags": ["microbit", "nrf51822", "nrf51", "nrf", "arm", "js", "wasm"],
+ "linker": "arm-none-eabi-gcc",
+ "pre-link-args": [
+ "-nostdlib",
+ "-nostartfiles",
+ "-mcpu=cortex-m0",
+ "-mthumb",
+ "-T", "targets/nrf51.ld",
+ "-Wl,--gc-sections",
+ "-fno-exceptions", "-fno-unwind-tables",
+ "-ffunction-sections", "-fdata-sections",
+ "-Os",
+ "-DNRF51",
+ "-Ilib/CMSIS/CMSIS/Include",
+ "lib/nrfx/mdk/system_nrf51.c",
+ "src/device/nrf/nrf51.s"
+ ],
+ "objcopy": "arm-none-eabi-objcopy",
+ "flash": "openocd -f interface/cmsis-dap.cfg -f target/nrf51.cfg -c 'program {hex} reset exit'",
+ "ocd-daemon": ["openocd", "-f", "interface/cmsis-dap.cfg", "-f", "target/nrf51.cfg"],
+ "gdb": "arm-none-eabi-gdb",
+ "gdb-initial-cmds": ["target remote :3333", "monitor halt", "load", "monitor reset", "c"]
+}
diff --git a/targets/nrf51.ld b/targets/nrf51.ld
new file mode 100644
index 000000000..442ae1b04
--- /dev/null
+++ b/targets/nrf51.ld
@@ -0,0 +1,10 @@
+
+MEMORY
+{
+ FLASH_TEXT (rw) : ORIGIN = 0x00000000, LENGTH = 256K /* .text */
+ RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 16K
+}
+
+_stack_size = 2K;
+
+INCLUDE "targets/arm.ld"
diff --git a/tools/gen-device-svd.py b/tools/gen-device-svd.py
index ab361d139..0fd1ecf47 100755
--- a/tools/gen-device-svd.py
+++ b/tools/gen-device-svd.py
@@ -54,19 +54,16 @@ def readSVD(path, sourceURL):
if groupNameTags:
groupName = getText(groupNameTags[0])
- for interrupt in periphEl.findall('interrupt'):
+ interruptEls = periphEl.findall('interrupt')
+ for interrupt in interruptEls:
intrName = getText(interrupt.find('name'))
intrIndex = int(getText(interrupt.find('value')))
- if intrName in interrupts:
- if interrupts[intrName]['index'] != intrIndex:
- raise ValueError('interrupt with the same name has different indexes: ' + intrName)
- interrupts[intrName]['description'] += ' // ' + description
- else:
- interrupts[intrName] = {
- 'name': intrName,
- 'index': intrIndex,
- 'description': description,
- }
+ addInterrupt(interrupts, intrName, intrIndex, description)
+ # As a convenience, also use the peripheral name as the interrupt
+ # name. Only do that for the nrf for now, as the stm32 .svd files
+ # don't always put interrupts in the correct peripheral...
+ if len(interruptEls) == 1 and deviceName.startswith('nrf'):
+ addInterrupt(interrupts, name, intrIndex, description)
if periphEl.get('derivedFrom') or groupName in groups:
if periphEl.get('derivedFrom'):
@@ -150,6 +147,20 @@ def readSVD(path, sourceURL):
return device
+def addInterrupt(interrupts, intrName, intrIndex, description):
+ if intrName in interrupts:
+ if interrupts[intrName]['index'] != intrIndex:
+ raise ValueError('interrupt with the same name has different indexes: %s (%d vs %d)'
+ % (intrName, interrupts[intrName]['index'], intrIndex))
+ if description not in interrupts[intrName]['description'].split(' // '):
+ interrupts[intrName]['description'] += ' // ' + description
+ else:
+ interrupts[intrName] = {
+ 'name': intrName,
+ 'index': intrIndex,
+ 'description': description,
+ }
+
def parseRegister(groupName, regEl, baseAddress, bitfieldPrefix=''):
regName = getText(regEl.find('name'))
regDescription = getText(regEl.find('description'))
@@ -400,8 +411,10 @@ Default_Handler:
'''.format(**device.metadata))
num = 0
for intr in device.interrupts:
+ if intr['index'] == num - 1:
+ continue
if intr['index'] < num:
- raise ValueError('interrupt numbers are not sorted or contain a duplicate')
+ raise ValueError('interrupt numbers are not sorted')
while intr['index'] > num:
out.write(' .long 0\n')
num += 1