New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

nrf52840-mdk support #30

Closed
Chillance opened this Issue Sep 30, 2018 · 42 comments

Comments

Projects
None yet
3 participants
@Chillance
Copy link

Chillance commented Sep 30, 2018

I really like this tinygo project and am trying to figure out how to add support for this neat little thing: https://wiki.makerdiary.com/nrf52840-mdk/

I've managed to add this as target:

{
	"llvm-target": "armv7em-none-eabi",
	"build-tags": ["nrf52840_mdk", "nrf52840", "nrf", "arm", "js", "wasm"],
	"linker": "arm-none-eabi-gcc",
	"pre-link-args": ["-nostdlib", "-nostartfiles", "-mcpu=cortex-m4", "-mthumb", "-T", "targets/nrf52.ld", "-Wl,--gc-sections", "-fno-exceptions", "-fno-unwind-tables", "-ffunction-sections", "-fdata-sections", "-Os", "-DNRF52840_XXAA", "-Ilib/CMSIS/CMSIS/Include", "lib/nrfx/mdk/system_nrf52.c", "src/device/nrf/nrf52.s"],
	"objcopy": "arm-none-eabi-objcopy",
	"flash": "nrfjprog -f nrf52 --sectorerase --program {hex} --reset"
}

And added machine/board_nrf52840-mdk.go (which is just a copy of board_pca10040.go for now)

// +build nrf,nrf52840_mdk

package machine

// LEDs on the nrf52840-mdk (nRF52840 dev board)
const (
	LED  = LED1
	LED1 = 17
	LED2 = 18
	LED3 = 19
	LED4 = 20
)

// Buttons on the nrf52840-mdk (nRF52840 dev board)
const (
	BUTTON  = BUTTON1
	BUTTON1 = 13
	BUTTON2 = 14
	BUTTON3 = 15
	BUTTON4 = 16
)

When I now run: tinygo flash -target=nrf52840-mdk examples/button

I get:

github.com/aykevl/tinygo/src/runtime/runtime_nrf.go:33:12: invalid operation: nrf.UART0 (variable of type *device/nrf.UART_Type) has no field or method PSELTXD

So, obviously, I'm missing something. But, I can't add "nrf52" to the build-tags, because then I get a bunch of re-declaration errors:

GPIO_PIN_CNF_DRIVE_D0S1 redeclared in this block
...

So, anyone here wanna help me adding support for this dev board? I'm new to this code, and figured it would be quicker to ask about this here since I couldn't find anything on the wiki about how to add a new board. Wasn't as straight forward as I thought, unless I'm missing something.

Thanks!

@aykevl

This comment has been minimized.

Copy link
Member

aykevl commented Oct 1, 2018

I'm happy to see so much interest in this project :D

I just wrote this wiki page as a guide to adding support for new boards: https://github.com/aykevl/tinygo/wiki/Adding-a-new-board. Of course, feel free to add/change things if they're not quite right or there are missing parts.

Luckily, the nrf52832 is already supported so adding support for the nrf52840 shouldn't be too hard. However, there is an odd thing with the nrf52* chips. Originally, Nordic intended to use nrf52 as the chip family but later on decided to instead add the nrf52840 which is actually quite different (and more advanced) than the nrf52832 chip. But they already used "nrf52" as an identifier for the nrf52832 family so they decided to use new names (nrf52840 and nrf52810) for other chips. In other words, you are correct in using nrf52840 and not nrf52 in the list of build tags although it may seem strange.

Regarding the error in the runtime: you're probably hitting a problem with differences between these chips. You will most likely need to split UART support between nrf52832 and nrf52840, for example by adding two new files (runtime_nrf52832.go and runtime_nrf52840.go) and moving initUART() there.
In fact, currently the runtime uses a rather dirty hack by hardcoding the PCA10040 TX pin in the runtime, which made sense at the time but should be fixed at some point. For now, I'd suggest doing the same for the nrf52840 until this gets a proper fix.

@aykevl

This comment has been minimized.

Copy link
Member

aykevl commented Oct 1, 2018

Due to a bug / missing feature in the register descriptor generator script, UART pin selection wasn't included yet on the nrf52840. I have added it in a72d0b7, pins can be configured with UART0.PSEL.TXD. Make sure to update to master and to regenerate register descriptors with make gen-device-nrf.

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 1, 2018

Hey, thanks for quick response and fixing that issue. I'm hoping this project can grow super big. :)

However I get:

src/github.com/aykevl/tinygo/src/device/nrf/nrf52840.go:1596:3: _padding6 redeclared
src/github.com/aykevl/tinygo/src/device/nrf/nrf52840.go:1594:3: 	other declaration of _padding6
src/github.com/aykevl/tinygo/src/device/nrf/nrf52840.go:1598:3: _padding6 redeclared
src/github.com/aykevl/tinygo/src/device/nrf/nrf52840.go:1594:3: 	other declaration of _padding6
src/github.com/aykevl/tinygo/src/device/nrf/nrf52840.go:1600:3: _padding6 redeclared
src/github.com/aykevl/tinygo/src/device/nrf/nrf52840.go:1594:3: 	other declaration of _padding6

when I try to build the button example.

@aykevl

This comment has been minimized.

Copy link
Member

aykevl commented Oct 1, 2018

Whoops, I made a mistake with the previous commit. That should be fixed now.

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 2, 2018

Ok, now it builds! Now I just need to get flashing going, which isn't straight forwards either. openocd was easy enough to install in Ubuntu. But, anyone here know what parameters to use for this board?

"flash": "openocd -f interface/?.cfg -f target/nrf52??.cfg -c 'program {hex} reset exit'"

When this works, I can finally start to make sure pins and all other things match correctly.

@deadprogram

This comment has been minimized.

Copy link
Member

deadprogram commented Oct 2, 2018

Hi @Chillance you might want to investigate if you can use the jlink bootloader along with nrfjprog like described here https://learn.adafruit.com/circuitpython-on-the-nrf52/nrf52840-bootloader

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 2, 2018

Hi @deadprogram
I tried nrfjprog, but I got this:

ERROR: JLinkARM DLL not found. Please reinstall latest JLinkARM.

and got tired of trying to fix it since google search didn't help much...

@deadprogram

This comment has been minimized.

Copy link
Member

deadprogram commented Oct 2, 2018

The answer to that is to follow these instructions to install jlink & nrfjprog, which are the same for all the nrf boards:

https://docs.zephyrproject.org/1.8.0/boards/arm/nrf52_pca10040/doc/nordic_segger.html#nordic-segger

@aykevl

This comment has been minimized.

Copy link
Member

aykevl commented Oct 2, 2018

Yeah JLinkARM can be problematic. I know I had the same problem once but that was long ago so I don't know what the fix was anymore.

Regarding OpenOCD:
In general, the interface is the programmer you're using. When you're not really using any programmer, most likely one is included on the board itself so you'd have to look it up and how it can be used from OpenOCD. Reading the documentation it is DAPLink which appears to be supported with interface/cmsis-dap.cfg after some quick googling.
You could just try using target/nrf51.cfg as the target type, it might just work. Or if you have a newer OpenOCD target/nrf52.cfg.

Also, I see this board has drag-and-drop programming, probably using .hex files. TinyGo has support for .hex files, you can get a .hex file this way:

tinygo -o program.hex -target nrf52840-mdk examples/serial
@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 2, 2018

Well, thanks and special thank you to @aykevl ! I've been doing AVR's before, so currently learning about this type of micro-controllers. Flashing with DFU or using DPI with AVR's has been quite a breeze. With this, there seems to be so many ways it's overwhelming.

But anyway:

"flash": "openocd -f interface/cmsis-dap.cfg -f target/nrf51.cfg -c 'program {hex} reset exit'"

certainly seemed to have worked! Well, it flashed, but need to fix the program. The tinygo way to create hex and drag that over also seemed to work.

Again, big thanks!

I will see if I can update the code and get it working properly. Then I could supply a pull req...

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 2, 2018

Whoho! LED seems to work. So freaking sweet. But for some reason Button doesn't.

According to https://wiki.makerdiary.com/nrf52840-mdk/images/nrf52840-mdk-pinout.jpg LED's are P0.22 to P0.24. Which I just translate to 22 to 24 like so:

// LEDs on the nrf52840-mdk (nRF52840 dev board)
const (
	LED  = LED1
	LED1 = 22
	LED2 = 23
	LED3 = 24
)

And this works. But button being P1.00, 100 doesn't for some reason...

@aykevl

This comment has been minimized.

Copy link
Member

aykevl commented Oct 3, 2018

Great that you got it working :D

Yes, P1.xx pins only exist on the nRF52840 so they have not been implemented yet. They can be controlled with nrf.P1 I guess. This means that the nrf52840 needs a separate GPIO implementation that also checks the port number.

This should not be too difficult to implement, the AVR does something similar. The nrfx HAL from Nordic simply counts further so P1.00 == 32, P1.01 == 33 etc, I think it's best to keep that convention.

@aykevl aykevl closed this Oct 3, 2018

@aykevl

This comment has been minimized.

Copy link
Member

aykevl commented Oct 3, 2018

Whoops closed by accident (wrong button)

@aykevl aykevl reopened this Oct 3, 2018

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 3, 2018

So, there can never be a P0.32? :)

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 3, 2018

Setting buttonpin to 32 in the button example didn't seem to work. Button pressed should change the LED, but nothing happens still, so I can only assume it still is not the right number for the button for this board...

@aykevl

This comment has been minimized.

Copy link
Member

aykevl commented Oct 3, 2018

So, there can never be a P0.32? :)

The way I understand their numbering scheme, no.

Setting buttonpin to 32 in the button example didn't seem to work. Button pressed should change the LED, but nothing happens still, so I can only assume it still is not the right number for the button for this board...

Correct, it is not yet implemented as it wasn't necessary before.

EDIT: to be clear, it is the right number but pins >= 32 haven't been implemented by the machine package.

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 3, 2018

Hmm, should I create an issue for it to be done then or?

@aykevl

This comment has been minimized.

Copy link
Member

aykevl commented Oct 4, 2018

You can, but of course by now I'm aware of it. I could implement it but I don't have the hardware to test on.

However, you can try to implement it yourself. Patches are welcome :) GPIO is implemented in https://github.com/aykevl/tinygo/blob/master/src/machine/machine_nrf.go. You'll have to replace nrf.P0 with calls to a chip-specific getPort() like in the stm32 port: https://github.com/aykevl/tinygo/blob/master/src/machine/machine_stm32.go.

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 4, 2018

I can also test it for you, but sure, I can see if I can make it as well...

@aykevl

This comment has been minimized.

Copy link
Member

aykevl commented Oct 5, 2018

It will get a lot easier after #38 is merged. It splits up pin handling in chip-specific files.

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 5, 2018

Ok, cool. So, I wait until that is done. Or, you will also do the GPIO thing?

@aykevl

This comment has been minimized.

Copy link
Member

aykevl commented Oct 6, 2018

I think it's best to wait until that PR is merged.
I can also write the necessary code (shouldn't be too hard) so you can test it on the device?

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 6, 2018

Sounds good to me. I'm setup to being able to code and flash, so I'm good to go here I suppose. Let me know when you have something to test, and I will do that. Any idea when this might happen?

@aykevl

This comment has been minimized.

Copy link
Member

aykevl commented Oct 6, 2018

Turns out that it was a bit more difficult than I expected. Here is a branch you can try: https://github.com/aykevl/tinygo/tree/nrf52840-mdk

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 11, 2018

Any progress?

@deadprogram

This comment has been minimized.

Copy link
Member

deadprogram commented Oct 11, 2018

@Chillance did you have a chance to try out the https://github.com/aykevl/tinygo/tree/nrf52840-mdk branch? Seems like the GPIO and UART should both work from looking at the code.

@aykevl

This comment has been minimized.

Copy link
Member

aykevl commented Oct 12, 2018

Yes, that branch is ready for testing. It should compile just fine but of course I couldn't test it.

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 12, 2018

Ok, I updated the button example to use pin 32 and using pullup and not using it. Still, the LED doesn't toggle when pressing the button. Here is full example:

package main

import (
	"machine"
	"time"
)

// This example assumes that the button is connected to pin 8. Change the value
// below to use a different pin.
const buttonPin = 32

func main() {
	led := machine.GPIO{machine.LED}
	led.Configure(machine.GPIOConfig{Mode: machine.GPIO_OUTPUT})

	button := machine.GPIO{buttonPin}
	button.Configure(machine.GPIOConfig{Mode: machine.GPIO_INPUT_PULLUP})
	//button.Configure(machine.GPIOConfig{Mode: machine.GPIO_INPUT})

	for {
		if button.Get() {
			led.Low()
		} else {
			led.High()
		}

		time.Sleep(time.Millisecond * 10)
	}
}

I also have this added to "board_nrf52840-mdk.go":

// LEDs on the nrf52840-mdk (nRF52840 dev board)
const (
	LED  = LED1
	LED1 = 22
	LED2 = 23
	LED3 = 24
)

I noticed that there now is:

// Get peripheral and pin number for this GPIO pin.
func (p GPIO) getPortPin() (*nrf.GPIO_Type, uint8) {
	if p.Pin > 31 {
		return nrf.P1, p.Pin - 31
	} else {
		return nrf.P0, p.Pin
	}
}

and that seems to build. I also ran "make gen-device". Still no change with LED when I press the button. The LED lights up on PULLUP. Also, the example/blinky1 works.

Any thoughts as to why the button example doesn't work?

@deadprogram

This comment has been minimized.

Copy link
Member

deadprogram commented Oct 12, 2018

@Chillance do you have the Nordic DK board https://www.nordicsemi.com/eng/Products/nRF52840-DK with built-in buttons or do you have a kit like https://wiki.makerdiary.com/nrf52840-mdk which is same SoC but different board? The latter board does not appear to have any built-in buttons nor pins to access the P1 GPIO port.

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 12, 2018

@deadprogram I have the nrf52840-mdk. If you take a look here: https://wiki.makerdiary.com/nrf52840-mdk/images/nrf52840-mdk-pinout.jpg you can see that 9 is a "User Button", P1.00. This is the button I'm trying to get working.

@aykevl

This comment has been minimized.

Copy link
Member

aykevl commented Oct 16, 2018

Aaaah I see, I made an off-by-one error. Subtracted 31 from the pin number instead of 32.

Can you try pin 33 for the button? That's the wrong number but should correct the error until I've pushed a fix.

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 16, 2018

Setting to 33, it would be 33-31 = 2, so that didn't work. Basically, it would not be 0 on P1, which explains why it didn't work. However, thanks for the tip! I changed the code myself to:

return nrf.P1, p.Pin - 32

and voilá!

buttonPin = 32 now works!

@aykevl

This comment has been minimized.

Copy link
Member

aykevl commented Oct 17, 2018

Thank you for testing!
I have sent two extra commits that should get your program to run without modifications to the machine module. If they work as well, I'll merge it all.

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 17, 2018

After push, it doesn't work for me.
Pin 32 is P1, 0 right? So shouldn't it be?

	if p.Pin > 31 {
		return nrf.P1, p.Pin - 32
	} else {
		return nrf.P0, p.Pin
	}

or

	if p.Pin >= 32 {
		return nrf.P1, p.Pin - 32
	} else {
		return nrf.P0, p.Pin
	}

Also, I need to do:

button.Configure(machine.GPIOConfig{Mode: machine.GPIO_INPUT_PULLUP})

to pullup that one for the LED to be lit and be off when pressing the button.

@aykevl

This comment has been minimized.

Copy link
Member

aykevl commented Oct 17, 2018

if p.Pin >= 32 {
   return nrf.P1, p.Pin - 32
} else {
   return nrf.P0, p.Pin
}

Isn't that exactly what I pushed?

Also, I need to do:

button.Configure(machine.GPIOConfig{Mode: machine.GPIO_INPUT_PULLUP})

to pullup that one for the LED to be lit and be off when pressing the button.

That's expected, otherwise the button input will be floating. You could just use GPIO_INPUT but you would have needed an external pull-up in that case.

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Oct 17, 2018

Oh, yes, you did. My bad. Must have been some miss somewhere, where I ran wrong code or something. Your commit works! (after I updated buttonPin and did PULLUP)

@aykevl

This comment has been minimized.

Copy link
Member

aykevl commented Oct 18, 2018

Merged in daf9222. Thank you for testing!

@aykevl aykevl closed this Oct 18, 2018

@deadprogram

This comment has been minimized.

Copy link
Member

deadprogram commented Nov 19, 2018

Hi @Chillance have you ever tried to use the UART on your nrf52840 board? For example, using the "serial" or "echo" examples?

I have a different nrf52840 board I am working with, but not able to get the UART working.

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Nov 20, 2018

@deadprogram No, I haven't tried it yet... But I suppose I could.. :)

@deadprogram

This comment has been minimized.

Copy link
Member

deadprogram commented Nov 20, 2018

Yes, please!

@Chillance

This comment has been minimized.

Copy link
Author

Chillance commented Dec 9, 2018

Ok, finally had some time to take a look. Remind me again how to test this properly.

Flashing the "echo" example and running:

sudo screen /dev/ttyACM0 115200

and start typing something, I see no output...

@deadprogram

This comment has been minimized.

Copy link
Member

deadprogram commented Dec 10, 2018

Hi @Chillance please make sure that you have done the following first:

  • pull latest code
  • git submodule update --init
  • re-run the wrapper generator make gen-device-nrf

That should address the core issue that I originally was asking you to retest, because since then several changes have been made.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment