-
Notifications
You must be signed in to change notification settings - Fork 997
nrf52840: implement USB-CDC #883
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
Conversation
|
This isn't done yet but I wanted to post what I've done so far in case anyone has bandwidth to test, provide feedback, or help finish it. I think it's getting close. |
aykevl
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A quick superficial review. I haven't done an in-depth review as that's hard to do with all the TODOs around, I assume at least some of those will get fixed anyway.
src/machine/usb_nrf52840.go
Outdated
| // TODO: do a "real" conversion that supports more than just ascii chars | ||
| for i, char := range in { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that you're already decoding Unicode code points here: char is actually a single Unicode code point (and i is the index into the string, which will increase by more than 1 when decoding non-ASCII characters).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just copied what was done here except I'm iterating runes instead of bytes. Neither this implementation or the other will work for anything except ascii characters. I was worried about pulling in the unicode package to convert, but it looks like I can do that fairly easily.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, it was more of a hint. And yeah, if possible it would be best to avoid the unicode package (it is really big and currently slow to compile).
|
I have this board and I can try testing soon. Thanks for implementing this |
b483232 to
a71c9f3
Compare
|
I seem to be stuck. The device seems to connect to my Mac and shows up as a serial port that I can open via I'm having this same problem with a nRF PWM driver that I'm writing too. It seems like whenever I enable an interrupt (even if the interrupt function is an empty function), everything stops working. In order to move this forward I think I need to connect a serial adapter to my board's UART pins so I can get some additional debugging output. I'll see if I can find something at my office tomorrow. |
c8c8e39 to
efbff51
Compare
|
Questions that need to be answered:
|
For this one my vote would definitely be to make the USBCDC the default output. |
Considering how much code it is, it sounds good to keep it in a separate file (close to usb.go).
That depends on the board. For the Bluefruit I think |
What if we added something like this to type ByteWriter interface {
func WriteByte(c byte) error
}
var DEFAULT_OUTPUT ByteWriterThen |
|
I tested this on Circuit Playground Bluefruit and Adafruit CLUE boards, and it appears to work flawlessly so far. With respect to the default output... I wonder if it might be enough to move the definition of the UART0 out of machine_nrf.go and into the individual board_*.go files? I think that could be addressed in a separate if you didn't want this one to get larger. |
|
I wouldn't mind moving where After a quick review, it looks like these are the currently supported nRF52840 based boards:
Of those, I'm guessing CPB and nRF52840-mdk would probably want USB-CDC to be UART0, while reel board and PCA10056 would probably want the actual UART? This is all just based on pictures of the boards on the internet, I'm not that familiar with any of them except for CPB. |
82a893c to
8b15a78
Compare
|
Looks like the smoke tests depend on |
aykevl
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right. This breaks because of support for play.tinygo.org.
I would say that the appropriate solution is to create a new board_reelboard_baremetal.go (and similar) that contains the UART. It's not pretty, but that's how we worked around the problem in #766 for example.
src/machine/board_pca10056.go
Outdated
| // UART0 is the NRF UART and UART1 is the nRF52840's USB device | ||
| var ( | ||
| UART0 = NRF_UART0 | ||
| UART1 = USB |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The nrf52840 has an UART1 (actually UARTE1) so this would conflict.
I think it would be better to leave UART1 undefined and expect programs to use machine.USB if they specifically need to write to that output.
(The same is true for other boards that primarily use a real UART for output).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I also leave UART1 undefined for boards that will use USB as the primary output? (programs would have to access NRF_UART0 if they want to want to use the real UART)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I also leave
UART1undefined for boards that will useUSBas the primary output? (programs would have to accessNRF_UART0if they want to want to use the real UART)
Not sure. @deadprogram any opinion on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So up until now, we have typically treated UART0 as either a "real" UART or the USB-CDC interface, depending on what the board supports.
However, that now seems a little clumsy. I think we should make a chance and instead do something like what we do with machine.LED to have a well-known alias. We could name it something like machine.SERIAL or machine.SERIALPORT.
- Boards where there is a USB-CDC like basically all of the Adafruit boards,
machine.SERIAL = machine.USB. - Boards where there the "default" is actually a UART perhaps via a debug chip. then
machine.SERIAL = machine.UART0.
If the user code needs to communicate with a specific UART, then that is easily handled. The default is the "sensible" option. And we can define all of the available ports per board without having to leave something out, or renumber.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds very reasonable. Completely agree.
That would also fix weird cases like this:
tinygo/src/machine/board_bluepill.go
Lines 62 to 68 in 1d913a6
| // USART1 is the first hardware serial port on the STM32. | |
| // Both UART0 and UART1 refer to USART1. | |
| UART0 = UART{ | |
| Buffer: NewRingBuffer(), | |
| Bus: stm32.USART1, | |
| } | |
| UART1 = &UART0 |
However, this machine.SERIAL (or maybe machine.Serial?) should probably be implemented in a separate PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
machine.Serial seems good. Also sounds good to make those changes in a separate PR.
I merged #893 so now there are five boards. This PR should be rebased on top of the dev branch to make sure that board is also included. |
This is based on the implementation in machine_atsamd51.go, with changes made to use the USBD registers found on the nRF52840.
It turns out I needed to read the manual a little better in order to see the sequence of actions and events that the nrf USBD device expects.
Previously it was attempting to reset the register by setting it to zero, but the manual says to reset bits you need to set them to 1. Once this was changed, the device began properly acknowledging when it received data from the host on the out endpoint.
This change allows the `board_*.go` files to choose which device will be UART0 and which will be UART1. For some it makes sense for the USB connection to be UART0 and for others it may not.
Create separate board_*_baremetal.go files for reelboard and pca10056 which will define UART0, in order to continue to allow support for these with the tinygo playground. Also switches the adafruit clue board to use the USB as UART0.
8b15a78 to
a3dc24a
Compare
...and to remove confusion with the UARTE1 device.
af23e9b to
1a09af5
Compare
|
Is there anything else outstanding on this PR before it can be merged? It would appear to be ready. |
|
#904 will add three more nRF52 based boards, all of them default UART0 to be the CDC and UART1 being the device's TX and RX pins so definitely a +1 on UART0 being USB-CDC. |
|
As far as I know it's ready. Unless someone tells me something needs to be changed. |
|
OK, lets merge then. Massive thanks to @syoder for all your work on this, and also to everyone who helped test, provide feedback, and otherwise help make it happen! |
This is based on the implementation in
machine_atsamd51.go, with changes made to use the USBD registers found on the nRF52840.