How to enable DMA transfers for UART?


Stefan Jaritz
 

Hey,

I am currently experimenting with ZephyrOS on different tasks. My base is an own dev board which has a stm32f4xx MCU that connects different ICs etc. via UART, I2C, SPI & GPIOs.

Currently the UART ISR is too slow to catch all chars at a rx burst. Usually I am using UART + DMA transfers to relieve the MCU and save energy.

I checked the UART stm32 api and saw that it is not utilizing things like uart DMA transfers. But there is an complete DMA API available. Yeah! Now I looked at the sample section to get a blueprint for doing so. Ups! Nothing

So I am asking for help or some example how to do an UART & DMA.

Think having an ringbuffer for rx and an intr firing after n Bytes received via DMA. Also doing the tx via DMA would be perfect. Any ideas to setup the Zephyr drivers to do so?

Kind regards!

Stefan

PS: there is an nice article on that here

http://stm32f4-discovery.net/2017/07/stm32-tutorial-efficiently-receive-uart-data-using-dma/


Li, Jun R
 

Stefan,
I've ever implemented a DMA-enabled UART on STM32F4 boards, but based on much old version of zephyr. I can try rebasing it to the latest zephyr if you are interested.

Regards,
Jun


On 3/19/19, 08:18, "devel@lists.zephyrproject.org on behalf of Stefan Jaritz" <devel@lists.zephyrproject.org on behalf of stefan@kokoontech.com> wrote:

Hey,

I am currently experimenting with ZephyrOS on different tasks. My base
is an own dev board which has a stm32f4xx MCU that connects different
ICs etc. via UART, I2C, SPI & GPIOs.

Currently the UART ISR is too slow to catch all chars at a rx burst.
Usually I am using UART + DMA transfers to relieve the MCU and save energy.

I checked the UART stm32 api and saw that it is not utilizing things
like uart DMA transfers. But there is an complete DMA API available.
Yeah! Now I looked at the sample section to get a blueprint for doing
so. Ups! Nothing

So I am asking for help or some example how to do an UART & DMA.

Think having an ringbuffer for rx and an intr firing after n Bytes
received via DMA. Also doing the tx via DMA would be perfect. Any ideas
to setup the Zephyr drivers to do so?

Kind regards!

Stefan

PS: there is an nice article on that here

http://stm32f4-discovery.net/2017/07/stm32-tutorial-efficiently-receive-uart-data-using-dma/


Paul Sokolovsky
 

Hello Stefan,

On Tue, 19 Mar 2019 15:18:02 +0000
"Stefan Jaritz" <stefan@kokoontech.com> wrote:

Hey,

I am currently experimenting with ZephyrOS on different tasks. My
base is an own dev board which has a stm32f4xx MCU that connects
different ICs etc. via UART, I2C, SPI & GPIOs.

Currently the UART ISR is too slow to catch all chars at a rx burst.
Usually I am using UART + DMA transfers to relieve the MCU and save
energy.
[]

So I am asking for help or some example how to do an UART & DMA.

Think having an ringbuffer for rx and an intr firing after n Bytes
received via DMA. Also doing the tx via DMA would be perfect. Any
ideas to setup the Zephyr drivers to do so?
Recently, a new "async" UART API was added to Zephyr, whose
implementation could leverage DMA support (that was one of usecases for
this API). There's an open ticket to implement it for STM32:
https://github.com/zephyrproject-rtos/zephyr/issues/13955

You're welcome to cooperate with the STM32 maintainers on implementing
it.

[]

--
Best Regards,
Paul

Linaro.org | Open source software for ARM SoCs
Follow Linaro: http://www.facebook.com/pages/Linaro
http://twitter.com/#!/linaroorg - http://www.linaro.org/linaro-blog


Stefan Jaritz
 

Hey

I done a demo driver implementation:

https://github.com/StefJar/zephyr_stm32_uart3_dma_driver

Some problems I was facing:

- DMA API: the current one doesn't support ring buffer setups

- UART API: the current API is not mapping the IDLE event.

- UART API: no callbacks possible for event driven rx

With the current design of the UART and DMA API it seems to be challenging to get a nice fusion.

So I was implementing a simple API for the demo, making block writes possible and calling a callback when data is received. I didn't used the UART and DMA API because it would became a dirty hack, while calling functions form that API & overwriting/patching the ISRs. So I decided for a lean straight forward implementation.

In my case I am interested into SPI + DMA and USB ACM + DMA. From an energy perspective it is much better to use DMA transfers for the peripheral IOs (We can put the MCU to sleep).

Maybe it is worth to put a thought on using DMA for peripherals by default and only the special case is doing polling or RX/TX handling via uart etc. ISRs.

Stefan

On 20/03/2019 15:37, Paul Sokolovsky wrote:
Hello Stefan,

On Tue, 19 Mar 2019 15:18:02 +0000
"Stefan Jaritz" <stefan@kokoontech.com> wrote:

Hey,

I am currently experimenting with ZephyrOS on different tasks. My
base is an own dev board which has a stm32f4xx MCU that connects
different ICs etc. via UART, I2C, SPI & GPIOs.

Currently the UART ISR is too slow to catch all chars at a rx burst.
Usually I am using UART + DMA transfers to relieve the MCU and save
energy.
[]

So I am asking for help or some example how to do an UART & DMA.

Think having an ringbuffer for rx and an intr firing after n Bytes
received via DMA. Also doing the tx via DMA would be perfect. Any
ideas to setup the Zephyr drivers to do so?
Recently, a new "async" UART API was added to Zephyr, whose
implementation could leverage DMA support (that was one of usecases for
this API). There's an open ticket to implement it for STM32:
https://github.com/zephyrproject-rtos/zephyr/issues/13955

You're welcome to cooperate with the STM32 maintainers on implementing
it.

[]


Erwan Gouriou
 

Hi Stefan,

On Tue, 26 Mar 2019 at 13:01, Stefan Jaritz <stefan@...> wrote:
Hey

I done a demo driver implementation:

https://github.com/StefJar/zephyr_stm32_uart3_dma_driver

Some problems I was facing:

- DMA API: the current one doesn't support ring buffer setups

- UART API: the current API is not mapping the IDLE event.

- UART API: no callbacks possible for event driven rx

With the current design of the UART and DMA API it seems to be
challenging to get a nice fusion.

So I was implementing a simple API for the demo, making block writes
possible and calling a callback when data is received. I didn't used the
UART and DMA API because it would became a dirty hack, while calling
functions form that API & overwriting/patching the ISRs. So I decided
for a lean straight forward implementation.

Thanks for sharing code and experience, this is useful!
 
In my case I am interested into SPI + DMA and USB ACM + DMA. From an
energy perspective it is much better to use DMA transfers for the
peripheral IOs (We can put the MCU to sleep).

Indeed, we should have a proper DMA driver that could be called from other drivers.

Maybe it is worth to put a thought on using DMA for peripherals by
default and only the special case is doing polling or RX/TX handling via
uart etc. ISRs.

While I agree DMA has numerous benefits, I don't think this should be the only configuration,
nor the default one. Main issue is initial complexity and configuration needs.
People should be able to use the async API first and then enable DMA once they feel comfortable
with the API.

 Erwan

Stefan

On 20/03/2019 15:37, Paul Sokolovsky wrote:
> Hello Stefan,
>
> On Tue, 19 Mar 2019 15:18:02 +0000
> "Stefan Jaritz" <stefan@...> wrote:
>
>> Hey,
>>
>> I am currently experimenting with ZephyrOS on different tasks. My
>> base is an own dev board which has a stm32f4xx MCU that connects
>> different ICs etc. via UART, I2C, SPI & GPIOs.
>>
>> Currently the UART ISR is too slow to catch all chars at a rx burst.
>> Usually I am using UART + DMA transfers to relieve the MCU and save
>> energy.
>>
> []
>
>> So I am asking for help or some example how to do an UART & DMA.
>>
>> Think having an ringbuffer for rx and an intr firing after n Bytes
>> received via DMA. Also doing the tx via DMA would be perfect. Any
>> ideas to setup the Zephyr drivers to do so?
> Recently, a new "async" UART API was added to Zephyr, whose
> implementation could leverage DMA support (that was one of usecases for
> this API). There's an open ticket to implement it for STM32:
> https://github.com/zephyrproject-rtos/zephyr/issues/13955
>
> You're welcome to cooperate with the STM32 maintainers on implementing
> it.
>
> []
>




Li, Jun R
 

Hi Stefan and Erwan,

I’m rebasing my previous implementations to the latest master branch and you can find it here: https://github.com/zephyrproject-rtos/zephyr/pull/14916

I’m still working on it since it is still lacking a couple of things and there are some bugs affecting RX. But the basic idea is to use UART IDLE to define the end of a RX DMA transaction.

 

If you think it is worth keeping going, let’s work together to make it happen.

 

Best Regards,

Jun

 

 

 

 

 

From: Erwan Gouriou <erwan.gouriou@...>
Date: Tuesday, March 26, 2019 at 08:10
To: Stefan Jaritz <stefan@...>
Cc: Paul Sokolovsky <paul.sokolovsky@...>, devel <devel@...>, John J Li <jun.r.li@...>
Subject: Re: [Zephyr-devel] How to enable DMA transfers for UART?

 

Hi Stefan,

 

On Tue, 26 Mar 2019 at 13:01, Stefan Jaritz <stefan@...> wrote:

Hey

I done a demo driver implementation:

https://github.com/StefJar/zephyr_stm32_uart3_dma_driver

Some problems I was facing:

- DMA API: the current one doesn't support ring buffer setups

- UART API: the current API is not mapping the IDLE event.

- UART API: no callbacks possible for event driven rx

With the current design of the UART and DMA API it seems to be
challenging to get a nice fusion.

So I was implementing a simple API for the demo, making block writes
possible and calling a callback when data is received. I didn't used the
UART and DMA API because it would became a dirty hack, while calling
functions form that API & overwriting/patching the ISRs. So I decided
for a lean straight forward implementation.

Thanks for sharing code and experience, this is useful!

 

In my case I am interested into SPI + DMA and USB ACM + DMA. From an
energy perspective it is much better to use DMA transfers for the
peripheral IOs (We can put the MCU to sleep).

Indeed, we should have a proper DMA driver that could be called from other drivers.

 

Maybe it is worth to put a thought on using DMA for peripherals by
default and only the special case is doing polling or RX/TX handling via
uart etc. ISRs.

While I agree DMA has numerous benefits, I don't think this should be the only configuration,

nor the default one. Main issue is initial complexity and configuration needs.

People should be able to use the async API first and then enable DMA once they feel comfortable

with the API.

 

 Erwan

 

Stefan

On 20/03/2019 15:37, Paul Sokolovsky wrote:
> Hello Stefan,
>
> On Tue, 19 Mar 2019 15:18:02 +0000
> "Stefan Jaritz" <stefan@...> wrote:
>
>> Hey,
>>
>> I am currently experimenting with ZephyrOS on different tasks. My
>> base is an own dev board which has a stm32f4xx MCU that connects
>> different ICs etc. via UART, I2C, SPI & GPIOs.
>>
>> Currently the UART ISR is too slow to catch all chars at a rx burst.
>> Usually I am using UART + DMA transfers to relieve the MCU and save
>> energy.
>>
> []
>
>> So I am asking for help or some example how to do an UART & DMA.
>>
>> Think having an ringbuffer for rx and an intr firing after n Bytes
>> received via DMA. Also doing the tx via DMA would be perfect. Any
>> ideas to setup the Zephyr drivers to do so?
> Recently, a new "async" UART API was added to Zephyr, whose
> implementation could leverage DMA support (that was one of usecases for
> this API). There's an open ticket to implement it for STM32:
> https://github.com/zephyrproject-rtos/zephyr/issues/13955
>
> You're welcome to cooperate with the STM32 maintainers on implementing
> it.
>
> []
>