UART serial rs-422 higher data rate

Hello,
I try to communicate between 2 Apalis evaluation board through rs422 at 4Mbaud.
linux kernel version : 4.1.44-2.7.4+gb1555bf

I have the 4Mbaud with termios and this work.
But the problem come from the time occupation.
Take a look at this image :

It appears that I have a link of 4mbaud, but used only 1/3 of the time.
How can i use the uartin a better way? maybe DMA or others function to control uart…

In my main i open the uart like that (function detailled bellow) :

// open uart   
data.fd = open("/dev/ttymxc1", O_RDWR | O_NOCTTY | O_NONBLOCK);   
set_interface_attribs (data.fd, B4000000, 0);  // set speed to 4 Mbps, 8n1 (no parity)  

The function called when a new buffer arrive: (from gstreamer pipeline)

// The appsink has received a buffer
static GstFlowReturn new_sample (GstElement *sink, CustomData *data) {

GstSample *sample;   
GstBuffer *buffer;    
GstMapInfo info;
int wlen;
 
/* Retrieve the buffer */  
g_signal_emit_by_name (sink,
"pull-sample", &sample);

if (sample) 
{ 	
 
  buffer = gst_sample_get_buffer (sample);
  gst_buffer_map (buffer,&info,GST_MAP_READ);

  // write on uart
  wlen = write(data->fd, info.data, info.size); 	 
  tcdrain(data->fd);
  gst_buffer_unmap(buffer,&info);
  gst_buffer_unref (buffer);   
  }   

  return GST_FLOW_OK; 
  }

serials functions:

int set_interface_attribs (int fd, int speed, int parity) { 	

  struct termios tty;
  if (tcgetattr (fd, &tty) != 0)
  {
    printf ("error %d from tcgetattr", errno);
    return EXIT_FAILURE;
  }
 
  cfsetospeed(&tty, (speed_t)speed);
  cfsetispeed(&tty, (speed_t)speed);
  tty.c_cflag |= (CLOCAL | CREAD);    /* ignore modem controls */
  tty.c_cflag &= ~CSIZE;
  tty.c_cflag |= CS8;         /* 8-bit characters */
  tty.c_cflag &= ~PARENB;     /* no parity bit */
  tty.c_cflag &= ~CSTOPB;     /* only need 1 stop bit */
  tty.c_cflag &= ~CRTSCTS;    /* no hardware flowcontrol */

  /* setup for non-canonical mode */
 tty.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
 tty.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
 tty.c_oflag &= ~OPOST;
 
 /* fetch bytes as they become available */
tty.c_cc[VMIN] = 0;
tty.c_cc[VTIME] = 5;

 if (tcsetattr (fd, TCSANOW, &tty) != 0)
 {
  	printf ("error %d from tcsetattr", errno);
    return EXIT_FAILURE;
 }
return 0; }

EDIT 21/03/2018 11:54

I tried to bypass the tcdrain function using ioctl functions :

while(nbbytes!=0){
 ioctl(data->fd, TIOCOUTQ, &nbbytes);
printf("ioctl => %d\n",nbbytes);
usleep(1);
 }

but the result return buffer max size and directly 0. Nothing change on the rs422 link…
I don’t understand why my buffer is not decremented slowly.

Any idea?

EDIT 2 21/03/2018 15h45 :
thank you jaski.tx for updating my post.

Here, I may have found a solution but i don’t understand what to do to deactivate DMA…:

To prevent this issue you can disable the RX-DMA of the desired UART by changing the uart block of your DTS file (this example works for ttymxc4):

 &uart5 {
     status = "okay";
     dma-names = "","tx";
 };

EDIT 3 22/03/2018 08:18 :
can someone could give me a linux image without DMA on uart in this list :
https://developer.toradex.com/files/toradex-dev/uploads/media/Colibri/Linux/Images/old/

I’m currently use this one :
Apalis-iMX6_LXDE-Image_2.7-20180104.tar.bz2

Hi morel

Good that you found the solution. Unfortunately there is no image file without DMA on Uart?
But you can compile yourself the kernel and the device tree following the instructions on this site.

Best regards, Jaski

It’ a potential solution. I’m not sure…

did you try it?

In the file :
./arch/arm/boot/dts/imx6qdl-apalis.dtsi
i found :

&uart2 {
        pinctrl-names = "default";
#ifndef USE_UART_IN_DCE_MODE
        pinctrl-0 = <&pinctrl_uart2_dte>;
        fsl,dte-mode;
        fsl,uart-has-rtscts;
#else
        pinctrl-0 = <&pinctrl_uart2_dce>;
#endif
        status = "disabled";
};

In the file :
./arch/arm/boot/dts/imx6qdl-apalis-eval.dtsi
i found

&uart2 {
        status = "okay";
#if 0
        linux,rs485-enabled-at-boot-time;
#endif
};

My modification in the file :
./arch/arm/boot/dts/imx6qdl-apalis-eval.dtsi

&uart2 {
        status = "okay";
        dma-names = "","";
#if 0
        linux,rs485-enabled-at-boot-time;
#endif
};

Question 1 : I have the V1.1 apalis module, using imx6q-apalis-eval.dtb is OK? Or imx6q-apalis_V1.0-eval.dtb ?

Question 2 : I only have to modify the imx6qdl-apalis-eval.dtsi files?

Question 3 : how can I check if my update is used?

I don’t really understand what i am doing. I hope to succeed.

Hi Morel

This developer site will explain you about the structure and customization of devicetree.

Question 1 : I have the V1.1 apalis module, using imx6q-apalis-eval.dtb is OK? Or imx6q-apalis_V1.0-eval.dtb ?

The used dtb file in defined as uboot environment variable. Usually imx6q-apalis-eval.dtb is used.

Question 2 : I only have to modify the imx6qdl-apalis-eval.dtsi files?

It depends what you want to do. I would look for the properties in the dtsi files you want to change, then you change it in the file, where it is defined. In your case, you just have to modify the file mentioned by you.

Question 3 : how can I check if my update is used?

You just need to compile the dtb file and load the dtb file in the module.

That’s work, my rs422 is fully used!!!
As expected the cpu usage is higher but that’s what i want.

But… I lost my camera input in the fight…

normally when i use this command bellow i found the ADV7280 for the analog camera adapter Analogue Camera Adapter - Toradex Evaluation Board.

Command launch in the no modified linux

root@apalis-imx6:~# dmesg | grep adv
[    6.750026] adv7280 3-0021: chip found @ 0x42 (21a8000.i2c)
[    6.796774] adv7280 3-0021: no sensor pwdn pin available
[    6.923124] adv7280 3-0021: adv7280_probe:Analog Device adv7280 not detected -5!

Command launch in my linux recompiled :

root@apalis-imx6:~# dmesg | grep adv
    [    0.000000] Linux version 4.1.44-dirty (adv@adv-VirtualBox) (gcc version 7.2.0 (GCC) ) #2 SMP Fri Mar 23 11:28:15 CET 2018
    [    3.638482] systemd[1]: System time before build time, advancing clock.

Have you an idea where i do my mistake?
For the toolchain i use

export ARCH=arm
export PATH=~/oe-core/build/tmp-glibc/sysroots/x86_64-linux/usr/bin:~/oe-core/build/tmp-glibc/sysroots/x86_64-linux/usr/bin/arm-angstrom-linux-gnueabi/:$PATH
export CROSS_COMPILE=arm-angstrom-linux-gnueabi-

I installed

sudo apt-get install device-tree-compiler
sudo apt-get install u-boot-tools
sudo apt-get install bc git libncurses5-dev lzop make

I take the linux kernel from git

git clone -b toradex_4.1-2.0.x-imx git://git.toradex.com/linux-toradex.git 
cd linux-toradex

I make the device tree

make apalis_imx6_defconfig
make nconfig
exit the device tree
change the file ./arch/arm/boot/dts/imx6qdl-apalis-eval.dtsi with nano

I compile the kernell

make -j3 uImage LOADADDR=10008000 2>&1 | tee build.log
make imx6q-apalis-eval.dtb

I update the file on my sd card with

cp ~/linux-toradex/arch/arm/boot/uImage /media/adv/SD/...
cp ~/linux-toradex/arch/arm/boot/dts/imx6q-apalis-eval.dtb /media/adv/SD/...

I boot the card / press escape

run setupdate
run update

Any mistake?

you did everything right. You can replace the kernel (uImage) from the image you used before and then just update the kernel by doing following commands:

  1. run setupdate
  2. run update_kernel

or you flash completely the old image and just with new device tree:

  1. run setupdate
  2. run update_fdt

The dma information is in the kernell? or in the dtb files?

If i understand, I have to reinstall a proper linux
After that i use

run setupdate
run update_kernell

Thank you.
I’ll keep you informed.

not working… If i update the kernell that destroy my camera input…

EDIT : can i just update the dtb files?
=> run update_fdt sorry

EDIT 2 :
According to analog camera adapter datasheet

Apalis/Colibri iMX6
The necessary drivers are provided as kernel modules.
On Apalis iMX6 the default device tree contains the needed configuration.

I’m trying to compile an unmodified kernel to see if it’s my modification that breaks the camera’s input.

EDIT 23/03/2018 15h59 :

The kernell without modification give the same result / no camera…

If i change only the device tree (with run update_fdt) that’s work. I don’t have exactly the same video input but i have something…

still a lot of work…

If anyone knows how wrong I am about building the kernel, please help me.

hi
you can update to the kernel which is working and just change the device tree.

when you compile a new kernel, you should check if the version of kernel ( uname -r ) is the same as the kernel modules (check in folder /lib/modules).

If the modules are not the same version as the kernel, then you need to make and deploy the modules, as described here.