Browse Source

nrf: add micro:bit board

pull/38/merge
Ayke van Laethem 6 years ago
parent
commit
bc9210b674
No known key found for this signature in database GPG Key ID: E97FF5335DFDFDED
  1. 32
      src/machine/board_microbit.go
  2. 3
      src/machine/board_pca10040.go
  3. 22
      src/machine/machine_nrf.go
  4. 17
      src/machine/machine_nrf51.go
  5. 10
      src/machine/machine_nrf52.go
  6. 2
      src/runtime/runtime_nrf.go
  7. 1
      targets/arm.ld
  8. 25
      targets/microbit.json
  9. 10
      targets/nrf51.ld
  10. 37
      tools/gen-device-svd.py

32
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
)

3
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

22
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) |

17
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()
}

10
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.

2
src/runtime/runtime_nrf.go

@ -28,7 +28,9 @@ func init() {
}
func initLFCLK() {
if machine.HasLowFrequencyCrystal {
nrf.CLOCK.LFCLKSRC = nrf.CLOCK_LFCLKSTAT_SRC_Xtal
}
nrf.CLOCK.TASKS_LFCLKSTART = 1
for nrf.CLOCK.EVENTS_LFCLKSTARTED == 0 {
}

1
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

25
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"]
}

10
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"

37
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

Loading…
Cancel
Save