Support for multiple UARTs

I’m trying to write an application where I need communication over 2 UARTs (one to receive messages from MIDI or other Daisies, and one to get messages from a Raspberry Pi Pico handling connection to other peripherals).

In libDaisy it looks like UartHandler in uart.h only works with USART1. I’ve looked at modifying it to allow uhandle.huart1.Instance to take other values than USART1, but then realized that there’s a lot of other code in there such as in HAL_UART_RxCpltCallback() and HAL_UART_MspInit() that appear to only be implemented to handle USART1.

Looks like quite a lot of scary looking stuff in there such as what DMA stream to use!

Is there a way of getting another UART working with libDaisy?

There’s no support for multiple UARTs in libDaisy and I would expect it to be supported only if there’s actual hardware that uses it.

However, you don’t need to use more than one UART in this case. You can design a protocol for connecting multiple devices in a ring bus, then you only would need to use a single UART per devices and forward messages between peers. So if you want to have communication between Daisy1, Daisy2, RPi, you would connect them like TX Daisy1 → RX Daisy2, TX Daisy2 → RX RPi, TX RPi → RX Daisy1. The rest should be handled in software by your protocol, i.e. device reconnect, enumertion, counting number of hops for messages, serializing MIDI and command data, etc.

This is the approach that is used in OWL firmware for connecting multiple devices.

1 Like

I’m afraid that a ring bus isn’t going to be a practical option in this case. For instance MIDI is at a very different baud rate (31,250 bps) than I’m aiming to be communicating between the Pico and the Daisy (921.6 bps).

Since MIDI uses USART1 there don’t currently appear to be any other UARTs available for other purposes if you’re using libDaisy.

You don’t need to use 31.25kbaud MIDI if you’re in control of software side of all connected devices. For OWL we use 112500 baud for serial communication, I would expect it to be usable for anything with an UART port. Also, my suggestion was not to use straight MIDI data, instead of that design a protocol that would allow you to relay MIDI or additional commands over UART.

Not sure where that number comes from, but this is ridiculously slow.

The MIDI is coming from an external device (keyboard), so that’s not something I can control.

That should have been 921.8 kbps (of course).

Oh ok, I’ve read it like you’re going to receive MIDI from Daisy, I see what you mean now.

In such case, maybe you should be using a single UART for MIDI input and SPI for communication between multiple devices. This would give you much higher bandwidth too at the cost of a few pins for chip selection. Or I2C as a slower alternative.

I think that with libDaisy you’ll be able to use only async UART mode, for high speed transmission you probably would need to use synchronous with an extra pin for clock. If you’re trying to avoid modify libDaisy, you might consider more suitable protocols.

Unfortunately I’m already using the SPI for other purposes (running an OLED display).

It’s a bit frustrating seeing the other USARTs and UARTs on the Daisy Seed pinout if they’re not accessible for custom use! Looking at the code it looks like the original intention in UartHandler was to be able to handle different UARTs, but that hasn’t been implemented yet.

You can use multiple devices on a single SPI bus, using several CS pins for selecting active slave chip. Display only needs to be updated once every 20ms or so, so SPI certainly can be shared. But I’m not sure the level of support of this in libDaisy, I’m not really using it myself.

@shensley probably has some suggestions for this. I recall that there were some plans to improve support for using UART/SPI/I2C for connecting custom hardware.

Hi! Updating the drivers to be a bit more configurable and allow multiple peripherals is pretty high up on the list. We have pretty flexible support for multiple I2C (master) peripherals, and both UART and SPI are next to get this treatment.

I would agree with @antisvin that using SPI (even sharing the bus with the display) will grant you higher bandwidth than UART, but the flexibility for both of these devices is still lacking compared to other parts of libDaisy.

I can try to slot some time to get started on the UART update over the next few weeks.

That’s great to hear that UART and SPI are high on the list! Looking forawrd to see what you do. Could be a great help with a number of things I’m planning.

I’ve been looking at bit more into SPI and it looks like that might be possible, though I guess I’d have to configure the Pico as a secondary rather than the main device on the SPI. From their API it looks like it should be possible, though there appears to be a lack of any examples out there yet showing how that’s done so far.

This is definitely supported on RPi Pico, i.e. see “spi_set_slave” function in their C++ SDK docs.

Hi. Sorry to jump on this thread but I’d also like to be able to use multiple UARTs from the Daisy. I’m using DaisyDuino and would like to be able to use UART4 (pins 12 & 13). SPI is already being used for an OLED. I2C is another option but would require the redesign of an external board that I’m communicating with via USART1. That’s not impossible but the addition of UART4 support would be more convenient.

Thanks!

1 Like

We’re in the process of wrapping up a PR that will introduce the ability to use any of the available UART pins exposed on the Daisy. This should be ready very soon.

For now the existing DMA receive functionality will still be limited to the USART1 peripheral, but we will add the ability to use DMA/Interrupt modes of communication, as well as synchronous behavior for the peripherals that support it in future updates.

3 Likes

Excellent, thanks very much, I look forward to the update :slightly_smiling_face:

1 Like

I’ll weigh in on really wanting a second UART! Since it’s been a couple of months, I thought I’d check to see if this is available yet? Thanks!

I know that this is not a convenient solution, but you could consider to make the change in libDaisy yourself.
You can take the I2C driver as a blueprint. For example, there’s code for handling the DMA scheduling so that a single DMA can be used for all peripherals that are in use.

You can make a Pull Request early and mark it as “incomplete/work in progress” while you work on it. Then others can chime in and assist where needed.

No need to modify! Multiple uart support is a part of libdaisy. You can check out the new UartHandler here.

1 Like

Hooray! I feel a bit like Dorothy in the Wizard of Oz - I had it with me the whole time (at least since late April) and never knew! Can’t wait to give it a try :slight_smile: I will point out that the uart.h file still has the comment at the top “currently only handles USART1 in UART mode”. I remember seeing that comment and believing it. I’m delighted it’s no longer true!!!

Does that contradict the TODO comment at the top of the file, or am I just misreading it?

Yeah that comment is now out of date. I’ll add an issue to update those.