Imx6ull uart DMA

Dear Community,
I need to enable DMA on a uart in order to transfer a lot of bytes (a firmware) to a MCU that runs a LoRa concentrator.
Using kernel 4.14.122 everything works as expected even not enabling DMA, but updating to BSP 6.2.0 with kernel 6.1.22 it seems that the serial communication hangs when I try to write more than 32 bytes over the uart.
This is the reason why I try to enable DMA, and I add this to my device tree definition:

+    dmas = <&sdma 18 4 1>, <&sdma 19 4 2>;
+    dma-names = "rx", "tx";

The values was taken by an example in kernel 6.4.x, I am not sure about the 18, 19…

My question is: how can I know that values?

I am using uart6, and the “simple” communication work as expected (the pinmuxing is ok).

Here is my complete uart6 definition:

+&uart6 {
+    pinctrl-names = "default";
+    pinctrl-0 = <&pinctrl_uart6>;
+    dmas = <&sdma 18 4 1>, <&sdma 19 4 2>;
+    dma-names = "rx", "tx";
+    fsl,dte-mode;
+    status = "okay";

Thanks in advance,

I never trust anything on Stack Overflow, but

I’m guessing you need to dig through the links on how to change the default buffer size in the kernel and rebuild. It sounds like somebody “helped you out” by changing the default size from 4096 to 32. No cool. That will bust things all over the place. You should be able to quickly fix this as part of your Yocto build.

Then file a bug report with Toradex!

You are just the Canary in this coal mine. 32 bytes is enough for an actual VT 100 terminal running up to 9600 baud . . . maybe. 2400 baud definitely.

There is a ton of serial comm still happening in the embedded world. This change should not have been allowed.

Thanks @seasoned_geek for your hint, I take a look at the post but I can’t find any useful way to change my situation.
I am trying to understand the buffer management in the drivers/tty/serial/imx.c but I wonder to enable DMA in order to solve my issue.

You didn’t have any issues until someone changed the buffer size . . . or the page size.

Btw, you have ensured that in this build stty is disabled, correct? Something in the back of my mind remembers the stty login daemon having a 32 byte limit.

Honestly, I believe DMA to be a Red Herring.

I really hate Stack Overflow given all of the bad information on it, but the answer with 6 votes on how to check the buffer sizes is where you need to start.

Build that little test snippet into a stand alone program. Run it on under both the BSP that worked and the new one with the 32 byte problem. If you get the exact same numbers back for both, DMA is not going to fix your problem. The new BSP has stty or some other daemon running on the serial port you are trying to use. It could also be the default flow control has changed and your program simply never set it because the default “just worked.”

Sorry if my calling it stty was confusing. On a lot of platforms it has had a lot of names. I guess getty is the current name here. We aren’t running Arch, but their Wiki has a pretty good write-up.

Actually, I skimmed through the Toradex discussion link on removing getty. It’s pretty good. Admittedly, I’m typing this answer lying awake in bed unable to get back to sleep, not fully caffeinated in my office hitting on all developer cylinders, but you need to write a stand alone program to run on both BSP verifying buffer sizes . . . then you need to kill getty.

Hi @seasoned_geek , thank you for the suggestion about getty.
Both old and new BSP have the same getty configuration and service at startup, I remark that old BSP based on kernel 4.14.122 works without any problem. So I don’t think that the problem relies on getty.
Then I try to include in mainline kernel the changes that I see in nxp kernel about imx.c file, but unfortunately nothing changes again…

Best regards,

Here is a simple piece of code that I write to test serial communication.
stress_serial.cpp (10.3 KB)
You can run it on board and on workstation using -t r and -t w flags.

I try it on BSP 6.2.0 with my kernel modifications and the communications stops after 32 bytes.
Same behavior with image 6.3.0-build7 downloaded with easy installer on /dev/ttymxc4 .

What about just shorting TX with RX and running your test? Are you sure your PC side is OK? Is it virtual machine or vanilla Linux PC? VM may have additional issues.
Shorted imx6ull TX+RX with your test give no errors with DMA enabled

Hi @Edward, thank you for the suggestion, however I try with a PC and connecting another module with same result.

Do you enable DMA on imx6ull? Can you please share your device-tree configuration?

Best regards,

Like I wrote, DMA enabled. Running on /dev/ttymxc1, which is uart2 in patched imx6ul.dtsi, which is further included by imx6ull.dts, which enables the node:

		uart2: serial@21e8000 {
			compatible = "fsl,imx6ul-uart",
			reg = <0x021e8000 0x4000>;
			interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
			clocks = <&clks IMX6UL_CLK_UART2_IPG>,
				 <&clks IMX6UL_CLK_UART2_SERIAL>;
			clock-names = "ipg", "per";
			dmas = <&sdma 27 4 0>, <&sdma 28 4 0>;
			dma-names = "rx", "tx";
			status = "disabled";

After running your test for a while via RX-TX shortcut cat /proc/interrupts confirms DMA is working

47: 4315 GPC 2 Level sdma

58: 0 GPC 27 Level 21e8000.serial

I’m using Linux in VM, and yes, it gets stuck running test with PC. I don’t know what really causes it. But it’s not just imx6ull, another CPU, which uses fsl_lpuart gaves the same results, so perhaps it has somewhat to do with PC/VM or something else? Slight baudrate mismatch with back to back transfers may lead to framing errors or smth like that. I don’t know yet how Linux handles UART errors. So please try as well with shorted TX to RX pins.

Thanks @Edward for the suggestion, even if I don’t understand how you can test the same port with 2 process that read and write from it.
However I connect /dev/ttymxc1 to /dev/ttymxc4 to avoid external issues and the result is the same, after 32 bytes the serial port stops to work.

Here is my /proc/interrupts print, that is similar to your, so I guess that DMA is enable or at least configured like in your setup for both ttymxc1 (21e8000) and ttymxc4 (21f4000):

199:        423       GPC  26 Level     2020000.serial
200:        346       GPC  27 Level     21e8000.serial
201:        349       GPC  30 Level     21f4000.serial

Your code is made so that writing server sends some data, then keeps waiting to receive it back. So using single server with “-t w” and RX TX shorted you receive what you send and your code is going like it was remote server. Perhaps make it waiting for inverted data coming back :slight_smile:

Clearly you have DMA disabled. With DMA enabled you would see zero interrupt events for particular serial instance in /proc/interrupts like I see on my imx6ull. Except, perhaps for serial console, which depending on kernel command line, kernel may try to initialize before DMA is available, which will led to no DMA for serial console port.

I though you experience the same what I saw. In my case, when using VM + Colibri, one of servers stopped reading data after random amount of bytes sends back and forwards. It could stop at 80 at 200. I don’t know yet what caused it. If you always stop at 32, then perhaps it due to lack of DMA, I’m not sure.

Oh. Repeating the same with different PC, with servers on both ends, on VM and on Colibri. Works well, all 1000+ cycles, no matter is DMA enabled or not. With DMA enabled test of course takes less time, because I get one or few “read: xxx” messages per your Cycle instead of bunch of “read: 1” messages in interrupt driven mode.

So please check your PC hardware, it may be defective like it was in my case.

Hi @Edward , I confused about the meaning of the /proc/interrupts output. Thank you for the clarification.

Finally I enable DMA on serial port copying the dmas definitions from the 4.14.122 device-tree for each serial port.

Now the test runs for 16000+ cycles using two port on the board (ttymxc1 and ttymxc5, both with DMA enable).

Thank you @Edward @seasoned_geek for your help and suggestions about my problem.

Best regards,