Enable and access AUART on iMX28

cancel
Showing results for 
Search instead for 
Did you mean: 

Enable and access AUART on iMX28

Jump to solution
2,107 Views
Contributor IV

Hello all.

I designed my own PCB with a iMX28.

I based my design on the mx28evk board and I use Yocto + Linux kernel 3.12 + the devicetree for iMX28EVK.

Because my design is not the same than the mx28evk, I modified the pin muxing in ~/fsl-community-bsp/build/tmp/work/imx28evk-poky-linux-gnueabi/u-boot-fslc/v2013.10-r0/git/board/freescale/mx28evk/mx28evk.c

I have a iMX283 and I need to use all AUART and SPI + some GPIOs, so, in mx28evk.c I wrote :

        int board_early_init_f(void)

    {

    /* IO0 clock at 480MHz */

    mxs_set_ioclk(MXC_IOCLK0, 480000);

    /* IO1 clock at 480MHz */

    mxs_set_ioclk(MXC_IOCLK1, 480000);

   

    /* SSP0 clock at 96MHz */

    mxs_set_sspclk(MXC_SSPCLK0, 96000, 0);

    /* SSP2 clock at 160MHz */

    mxs_set_sspclk(MXC_SSPCLK2, 160000, 0);

   

    // GPIOs

    mxs_iomux_setup_pad(MX28_PAD_LCD_D16__GPIO_1_16 | MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D17__GPIO_1_17 | MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D18__GPIO_1_18 | MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D19__GPIO_1_19 | MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D20__GPIO_1_20 | MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D21__GPIO_1_21 | MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D22__GPIO_1_22 | MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D23__GPIO_1_23 | MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL);

   

    mxs_iomux_setup_pad(MX28_PAD_SSP2_SS1__GPIO_2_20 | MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL);

    mxs_iomux_setup_pad(MX28_PAD_SSP2_SS2__GPIO_2_21 | MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL);

   

    mxs_iomux_setup_pad(MX28_PAD_SAIF0_MCLK__GPIO_3_20 | MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL);

    mxs_iomux_setup_pad(MX28_PAD_SAIF0_LRCLK__GPIO_3_21 | MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL);

    mxs_iomux_setup_pad(MX28_PAD_SAIF1_SDATA0__GPIO_3_26 | MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL);

    mxs_iomux_setup_pad(MX28_PAD_PWM4__GPIO_3_29 | MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL);

   

    // AUART

    mxs_iomux_setup_pad(MX28_PAD_AUART0_RX__AUART0_RX);

    mxs_iomux_setup_pad(MX28_PAD_AUART0_TX__AUART0_TX);

    mxs_iomux_setup_pad(MX28_PAD_AUART0_CTS__AUART0_CTS);

    mxs_iomux_setup_pad(MX28_PAD_AUART0_RTS__AUART0_RTS);

   

    mxs_iomux_setup_pad(MX28_PAD_AUART1_RX__AUART1_RX);

    mxs_iomux_setup_pad(MX28_PAD_AUART1_TX__AUART1_TX);

   

    mxs_iomux_setup_pad(MX28_PAD_SSP2_SCK__AUART2_RX);

    mxs_iomux_setup_pad(MX28_PAD_SSP2_MOSI__AUART2_TX);

   

    mxs_iomux_setup_pad(MX28_PAD_SSP2_MISO__AUART3_RX);

    mxs_iomux_setup_pad(MX28_PAD_SSP2_SS0__AUART3_TX);

   

    mxs_iomux_setup_pad(MX28_PAD_SAIF0_BITCLK__AUART4_RX);

    mxs_iomux_setup_pad(MX28_PAD_SAIF0_SDATA0__AUART4_TX);

   

    mxs_iomux_setup_pad(MX28_PAD_PWM0__DUART_RX);

    mxs_iomux_setup_pad(MX28_PAD_PWM1__DUART_TX);

   

    // LCD

    mxs_iomux_setup_pad(MX28_PAD_LCD_D00__LCD_D0);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D01__LCD_D1);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D02__LCD_D2);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D03__LCD_D3);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D04__LCD_D4);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D05__LCD_D5);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D06__LCD_D6);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D07__LCD_D7);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D08__LCD_D8);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D09__LCD_D9);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D10__LCD_D10);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D11__LCD_D11);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D12__LCD_D12);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D13__LCD_D13);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D14__LCD_D14);

    mxs_iomux_setup_pad(MX28_PAD_LCD_D15__LCD_D15);

    mxs_iomux_setup_pad(MX28_PAD_LCD_RS__LCD_RS);

    mxs_iomux_setup_pad(MX28_PAD_LCD_RD_E__LCD_VSYNC);

    mxs_iomux_setup_pad(MX28_PAD_LCD_WR_RWN__LCD_HSYNC);

    mxs_iomux_setup_pad(MX28_PAD_LCD_CS__LCD_ENABLE);

   

    // SSP0

    mxs_iomux_setup_pad(MX28_PAD_SSP0_DATA0__SSP0_D0);

    mxs_iomux_setup_pad(MX28_PAD_SSP0_DATA1__SSP0_D1);

    mxs_iomux_setup_pad(MX28_PAD_SSP0_DATA2__SSP0_D2);

    mxs_iomux_setup_pad(MX28_PAD_SSP0_DATA3__SSP0_D3);

    mxs_iomux_setup_pad(MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT);

    mxs_iomux_setup_pad(MX28_PAD_SSP0_SCK__SSP0_SCK);

    mxs_iomux_setup_pad(MX28_PAD_SSP0_CMD__SSP0_CMD);

   

    // SSP2

    mxs_iomux_setup_pad(MX28_PAD_SSP0_DATA4__SSP2_D0);

    mxs_iomux_setup_pad(MX28_PAD_SSP0_DATA5__SSP2_D3);

    mxs_iomux_setup_pad(MX28_PAD_SSP0_DATA6__SSP2_CMD);

    mxs_iomux_setup_pad(MX28_PAD_SSP0_DATA7__SSP2_SCK);

   

    // USB ID

    mxs_iomux_setup_pad(MX28_PAD_PWM2__USB0_ID);

   

    return 0;

    }

I recompiled U-boot and uploaded it on my board.

So now, I can use all my GPIOs without any problems. But in /dev/ I only have ttyAPP0 and ttyAPP3. I can't access the others AUART. Also, I have nothing to access SPI.

So what can I do to resolve that ? What did I miss ?

Many thanks in advance.

Labels (3)
0 Kudos
1 Solution
52 Views
NXP Employee
NXP Employee

If you are using the arch/arm/boot/dts/imx28-evk.dts file then it only uses auart0 and auart3.

You need to manually add the other auart nodes in the device tree file in order to get it functional in the kernel.

Regards,

Fabio Estevam

View solution in original post

0 Kudos
21 Replies
50 Views
Contributor IV

Hello all,

I made a patch to add UART/RS485 transciever support and everything work perfectly for me.

This is my patch and the result at the logic analyser. Can you tell me if it seems ok for you or if I did a mistake (something to never do for example) ?

thank you

Patch : http://pastebin.com/LHapDiwD

Result :

I've only 9µs between the last bit sent and the RTS release.

RS485.JPG.jpg

0 Kudos
46 Views
Senior Contributor I

Hi Damien,

this picture looks great.

Here are my questions:

Which exact kernel version does the patch applies to?

Have you tested the system under load?

Also i have a suggestion to your code:

@@ -309,6 +312,10 @@

        if (uart_tx_stopped(&s->port))

                mxs_auart_stop_tx(&s->port);

+       if(test_bit(MXS_AUART_RS485, &s->flags)) {

+               while ((readl(s->port.membase + AUART_STAT) & AUART_STAT_BUSY));

+               writel(AUART_CTRL2_RTS, s->port.membase + AUART_CTRL2_SET);

+       }

}

static void mxs_auart_rx_char(struct mxs_auart_port *s)

The while loop relies on the assumption that the busy bit disappear. It's better to have a timeout here.

The real problem is that this loop is in interrupt context (as far as i know) and prevents the cpu from doing other tasks.

That's the reason why i try to implement this with a timer.

0 Kudos
46 Views
Contributor IV

Hello,

Thank you for your answer.

My kernel version is 3.12.13-fslc.

Yes I tested it with all my software running (including gprs connection) and everything work well.

Of course this loop can be a problem but I assume that the busy bit will be release and it must be, otherwise the processor would be deficient.

So it's why I didn't use a timer because the busy bit will be release in any case. and the software is lighter without.

I don't think it's an interrupt because is the TX function and not RX.

I need this loop because I need to wait all bits transmited before release the RTS and I need to release the RTS pin before leaving the function (for timing optimization).

Now the time took by the tx function depends of the baudrate, and the maximum transmited bytes in one run is 16 bytes.

So at 9600 bds it takes maximum 16ms.

And at 115200bds it takes maximum 1.4ms.

0 Kudos
53 Views
NXP Employee
NXP Employee

If you are using the arch/arm/boot/dts/imx28-evk.dts file then it only uses auart0 and auart3.

You need to manually add the other auart nodes in the device tree file in order to get it functional in the kernel.

Regards,

Fabio Estevam

View solution in original post

0 Kudos
50 Views
Contributor IV

Many thanks for this answer. You're right, in my imx28-evk.dts I have only auart0 and auart3.

But I have 7 imx28-evk.dts :

/home/mx28/fsl-community-bsp/build/tmp/sysroots/imx28evk/usr/src/kernel/arch/arm/boot/dts/imx28-evk.dts

/home/mx28/fsl-community-bsp/build/tmp/work/armv5te-poky-linux-gnueabi/linux-libc-headers/3.10-r0/linux-3.10/arch/arm/boot/dts/imx28-evk.dts

/home/mx28/fsl-community-bsp/build/tmp/work/imx28evk-poky-linux-gnueabi/linux-fslc/3.12+gitAUTOINC+1cd7a83434-r0/git/arch/arm/boot/dts/imx28-evk.dts

/home/mx28/fsl-community-bsp/build/tmp/work/imx28evk-poky-linux-gnueabi/linux-fslc/3.12+gitAUTOINC+1cd7a83434-r0/image/usr/src/kernel/arch/arm/boot/dts/imx28-evk.dts

/home/mx28/fsl-community-bsp/build/tmp/work/imx28evk-poky-linux-gnueabi/linux-fslc/3.12+gitAUTOINC+1cd7a83434-r0/package/usr/src/kernel/arch/arm/boot/dts/imx28-evk.dts

/home/mx28/fsl-community-bsp/build/tmp/work/imx28evk-poky-linux-gnueabi/linux-fslc/3.12+gitAUTOINC+1cd7a83434-r0/packages-split/kernel-dev/usr/src/kernel/arch/arm/boot/dts/imx28-evk.dts

/home/mx28/fsl-community-bsp/build/tmp/work/imx28evk-poky-linux-gnueabi/linux-fslc/3.12+gitAUTOINC+1cd7a83434-r0/sysroot-destdir/usr/src/kernel/arch/arm/boot/dts/imx28-evk.dts

Do I need to edit all these 7 imx28-evk.dts or only one (in this case, which one) ?

Many thanks for all.

0 Kudos
50 Views
NXP Employee
NXP Employee

I am not very familiar with Yocto and I build the dtb and kernel manually on my daily work.

I would say it is that the only first occurence that you need to change, but if this does not work, then post it to meta-fsl-arm mailing list;

I build the dtb manually, by just doing 'make imx28-evk.dtb' and then I use the generated dtb via NFS or flash it to the SD card.

Regards,

Fabio Estevam

50 Views
Contributor IV

Many thanks, I edited /home/mx28/fsl-community-bsp/build/tmp/work/imx28evk-poky-linux-gnueabi/linux-fslc/3.12+gitAUTOINC+1cd7a83434-r0/git/arch/arm/boot/dts/imx28-evk.dts and compiled it with .../git/scripts/dtc/dtc and put the dtb file on my sdcard.

Now I have access to all AUART.

But I have another question, on my AUART0 , I use RTS to control a RS485 transceiver and RTS is active high but I need it to be active low, how can I do it ?

Many thanks

0 Kudos
50 Views
NXP Employee
NXP Employee

Hi Damien,

First, please make sure you pass the property 'fsl,uart-has-rtscts' in the auart0 node, so that RTS and CTS could be used.

About inverting RTS: bit 31 of register HW_UARTAPP_CTRL2 allows the inversion of RTS output.

I made a patch (untested) do that you could try it. For the auart0 node you would need to add 'fsl,invert-rtscts' to auart0 (and also fsl,uart-has-rtscts).

http://pastebin.com/MTZgg9zA

Please let me know if this works.

Regards,

Fabio Estevam

0 Kudos
50 Views
Contributor IV

Hi.

Many thanks for this answer.

'fsl,uart-has-rtscts' is well passed in the auart0 node.

I applied your patch and verified that it was well applied.


I did " bitbake -f -c compile virtual/kernel" then "bitbake virtual/kernel" and "bitbake myown-image"


I put the new uImage and new rootfs on my sd card with the updated dtb file. But with this new configuration, RTS is still not inverted.


This is auart0 node in my dts file :

auart0: serial@8006a000 {

  pinctrl-names = "default";

  pinctrl-0 = <&auart0_pins_a>;

  fsl,uart-has-rtscts;

  fsl,invert-rtscts;

  status = "okay";

  };

Do you have an idea ?

Many thanks


0 Kudos
50 Views
Contributor IV

Any idea to solve that ?

I still search for the solution.

Many thanks

0 Kudos
50 Views
Contributor IV

Hi,

I put a lot of printk's in mxs-auart.c and it looks like the program do not enter in static void mxs_auart_settermios(...), so the register is not edited.

How can I force it to enter in static void mxs_auart_settermios(...) ?

Many thanks and best regards

0 Kudos
50 Views
Senior Contributor I

Hi Damien,

have you tried to configure the AUART with stty or something?

0 Kudos
50 Views
Contributor IV

Hi,

No, I don't use stty. AUARTs are configured automaticaly by the kernel on boot.

Many thanks

0 Kudos
50 Views
Senior Contributor I

The kernel wouldn't never call mxs_auart_settermios() on boot. That's normally done from userspace like stty or another termios program.

The kernel never know about baudrate of the device you want to connect to AUART.

0 Kudos
50 Views
Contributor IV

Ok, now I'm in.

with my script python :

import serial

ser = serial.Serial('/dev/ttyAPP0',9600,rtscts=1).

I have :

[ 4430.999859] UART_RS485: Looks inverted

[ 4431.003660] UART_RS485: Inverted

[ 4431.010089] UART_RS485: 3340943873  -> 0xC722C201

But my AUART DONT WORK at all. I have nothing on my scope...

If just after that I try :

import serial

ser = serial.Serial('/dev/ttyAPP0',9600).

I have only :

[ 4437.577211] UART_RS485: 3223454465  -> 0xC0220301

But my AUART is working AND RTS is inverted (because the previous step).

The difference between the two state of the ctrl2 register is the DMA. DMA is enable when the AUART don't work and disable when AUART work.

Why DMA cause this problem ? And how Can I fix that ?

Many thanks

0 Kudos
50 Views
Contributor IV

I think I understood what is wrong.

In my board, I don't use CTS with AUART, I use CTS pin as GPIO (3_2).

So I think AUART waits a signal on CTS before sending, but as CTS is not used, Data is not transmitted and I have a timeout...

Is it possible to use only RTS ? With no CTS ?

Many thanks.

0 Kudos
50 Views
Senior Contributor I

Hello Damien,

from my point of view the modifications send by Fabio aren't necessary. You need a RS485 capable uart driver. Unfortunately the auart driver of the i.MX28 (mxs-auart) doesn't have this feature.

To your question, in RS485 mode CTS isn't necessary. But i don't know if it's possible to define only 3 pins for your auart in the devicetree file and still using the CTS pin as GPIO.

0 Kudos
50 Views
Contributor IV

Thank you for your answer.

On my side, I worked on that since my last post and I removed all the modifications made by the patch. I only edited the dtsi file :

auart0_pins_a: auart0@0 {

  reg = <0>;

  fsl,pinmux-ids = <

  0x3000 /* MX28_PAD_AUART0_RX__AUART0_RX */

  0x3010 /* MX28_PAD_AUART0_TX__AUART0_TX */

  /*0x3020  MX28_PAD_AUART0_CTS__AUART0_CTS */

  0x3030 /* MX28_PAD_AUART0_RTS__AUART0_RTS */

  >;

  fsl,drive-strength = <0>;

  fsl,voltage = <1>;

  fsl,pull-up = <0>;

  };

As you can see, I disabled CTS and now I'm able to use it as GPIO.

Indeed, I found that IMX28 is not able to drive automaticaly /RE DE pins of a rs485 - uart converter, so I did it by myself and my python code looks like that :

import serial

ser=serial.Serial('/dev/ttyAPP0',19200)

self.ser.flushInput()

self.ser.flushOutput()

self.ser.setRTS(False) #Stop listening RS485

self.ser.write("test") #Write data

self.ser.flush()

self.ser.setRTS(True) #Listen RS485

data = self.ser.read(1)

n = self.ser.inWaiting()

if n :

  data += self.ser.read(n)

print data

Everything works fine like that.

So many thanks for your help

0 Kudos
50 Views
Senior Contributor I

I tried to develop RS485 support for mxs-auart, but i stuck. So we used a hardware solution for this.

Because i think there are other developers for the i.MX28 platform how needs RS485, i want to share my last development state. May be it's helpful for anybody to develop this not from scratch. The code based on a old patch for the armadeus platform and the atmel serial driver. The patch applies to mainline kernel 3.10 but i think it should be easy to port to a newer kernel.

Please keep in mind it's not working, so don't expect to much.

0 Kudos
50 Views
Contributor IV

For the baudrate, my python script do it :

import serial

ser = serial.Serial('/dev/ttyAPP0',9600,timeout=1).

I suppose it does the same than stty ?

But RTS is not inverted.

Thanks a lot.

EDIT : I did a mistake, you're right. When I run my python script, my printk tell me that I enter in static void mxs_auart_settermios(...), but not in :

/* figure out the hardware flow control settings */

  if (cflag & CRTSCTS) {

       printk(KERN_WARNING "UART_RS485: Looks inverted\n");

       if (test_bit(MXS_AUART_INVERT_RTSCTS, &s->flags))

            ctrl2 |= AUART_CTRL2_INVERT_RTS | AUART_CTRL2_INVERT_CTS;

            printk(KERN_WARNING "UART_RS485: Inverted\n");

I don't have my 2 printk's.

0 Kudos