am335x system upgrade kernel uart(七)

1      Scope of Document

This document describes UART hardware design, uart driver porting

2      Requiremen

2.1     Function Requirement

Uboot enable uart0 for debug, Kernel enable uart0 uart1 uart2 uart3.

2.2     Performance Requirement

Support common uart rx tx function.

3      Hardware Overview

uart interface,pin map:

// uart 0

AM335X_UART0_RXD

AM335X_UART0_TXD

// uart 1

AM335X_UART1_RXD

AM335X_UART1_TXD

// uart 2

AM335X_UART2_RXD

AM335X_UART2_TXD

// uart 3

AM335X_UART3_RXD

AM335X_UART3_TXD

 

 

                  Figure 1 uart interface block diagram

4      Functional Description

4.1     UART DRIVER Overview

The UART Driver enables the UART’s available on the device. The driver configures the UART hardware and interfaces with a number of standard linux tools (ex. stty, minicom, etc.) to enable the configuration and usage of the hardware. The H/W UARTs available will vary by SoC and system configuration.

                     

4.2     UART

4.2.1 Overview

The UART driver can be used to send/receive raw ASCII characters from the User Interface as shown by the below diagram..

4.2.1 User Layer

The UART driver leverages the TTY framework within Linux. This framework uses typical file I/O operations to interact with the UART. This interface allows userspace modules to easily be developed to read/write the /dev/ttyxx to exchange data over the UART. Since this is a very common Linux framework, there are many standard tools that can be used to interact with it. These tools, like stty, minicom, picocom, and many others, can easily be used to exercise a UART for data exchange.

 

Features

  • Exposes UART to User Space via /dev/tty*
  • Supports multiple baud rates and UART capabilities
  • Hardware Flow Control

5      Porting

5.1     Uboot porting

In uboot default enable debug uart, so do not need to modify.

5.2     Kernel porting

Index: am335x-evm.dts

      uart1_pins: pinmux_uart1_pins {

             pinctrl-single,pins = <

                  AM33XX_IOPAD(0x980, PIN_INPUT_PULLUP | MUX_MODE1)      /* uart1_rxd.uart1_rxd */

                   AM33XX_IOPAD(0x984, PIN_OUTPUT_PULLDOWN | MUX_MODE1)  /* uart1_txd.uart1_txd */

             >;

      };

     uart2_pins: pinmux_uart2_pins {

            pinctrl-single,pins = <

                   AM33XX_IOPAD(0x92c, PIN_INPUT_PULLUP | MUX_MODE1)      /* mii1_txclk.uart2_rxd */

                   AM33XX_IOPAD(0x930, PIN_OUTPUT_PULLDOWN | MUX_MODE1)  /* mii1_rxclk.uart2_txd */

            >;

     };

     uart3_pins: pinmux_uart3_pins {

            pinctrl-single,pins = <

                   AM33XX_IOPAD(0x934, PIN_INPUT_PULLUP | MUX_MODE1)      /* mii1_rxd3.uart3_rxd */

                   AM33XX_IOPAD(0x938, PIN_OUTPUT_PULLDOWN | MUX_MODE1)  /* mii1_rxd2.uart3_txd */

            >;

     };

 &uart1 {

      pinctrl-names = "default";

      pinctrl-0 = <&uart1_pins>;

     status = "okay";

};

&uart2 {

     pinctrl-names = "default";

     pinctrl-0 = <&uart2_pins>;

      status = "okay";

 };

&uart3 {

     pinctrl-names = "default";

     pinctrl-0 = <&uart3_pins>;

     status = "okay";

};

6      Follow-up

Uart loop test code:

#include     <stdio.h>

#include     <stdlib.h>

#include     <string.h>

#include     <unistd.h>

#include     <sys/types.h>

#include     <sys/stat.h> 

#include     <fcntl.h> 

#include     <termios.h>

#include     <errno.h>

#include     <pthread.h>

#include     <sys/ioctl.h>

#define FALSE 1

#define TRUE 0

int fd=-1;

char buff[512];

int speed_arr[] = {  B115200, B57600, B38400, B19200, B9600, B4800,

                  B2400, B1200};

int name_arr[] = {115200, 57600, 38400,  19200,  9600,  4800,  2400, 1200};

#define debugnum(data,len,prefix) 

{

        unsigned int i;  

        for (i = 0;i < len;i++) {

                if(prefix) 

                        printf("0x%02x ",data[i]);

                else 

                        printf("%02x ",data[i]);

        }

}

void set_speed(int fd, int speed)

{

    int   i;

    int   status;

    struct termios   Opt;

    tcgetattr(fd, &Opt);

    for ( i= 0;  i < sizeof(speed_arr) / sizeof(int);  i++)

    {

     if (speed == name_arr[i])

     {

         tcflush(fd, TCIOFLUSH);

           cfsetispeed(&Opt, speed_arr[i]);

           cfsetospeed(&Opt, speed_arr[i]);

           status = tcsetattr(fd, TCSANOW, &Opt);

           if (status != 0)

              perror("tcsetattr fd1");

           return;

          }

       tcflush(fd,TCIOFLUSH);

    }

}

int set_Parity(int fd,int databits,int stopbits,int parity)

{

    struct termios options;

    if  ( tcgetattr( fd,&options)  !=  0)

    {

      perror("SetupSerial 1");

      return(FALSE);

    }

    options.c_cflag &= ~CSIZE;

    switch (databits)

    {

    case 7:

       options.c_cflag |= CS7;

       break;

    case 8:

       options.c_cflag |= CS8;

       break;

    default:

       fprintf(stderr,"Unsupported data size ");

       return (FALSE);

    }

    switch (parity)

    {

    case 'n':

    case 'N':

       options.c_cflag &= ~PARENB;  

       options.c_iflag &= ~INPCK;  

       break;

    case 'o':

    case 'O':

       options.c_cflag |= (PARODD | PARENB);

       options.c_iflag |= INPCK;          

       break;

    case 'e':

    case 'E':

       options.c_cflag |= PARENB;    

       options.c_cflag &= ~PARODD;

       options.c_iflag |= INPCK;    

       break;

    case 'S':

    case 's': 

       options.c_cflag &= ~PARENB;

       options.c_cflag &= ~CSTOPB;

       break;

    default:

       fprintf(stderr,"Unsupported parity ");

       return (FALSE);

    }

    switch (stopbits)

    {

    case 1:

       options.c_cflag &= ~CSTOPB;

       break;

    case 2:

       options.c_cflag |= CSTOPB;

       break;

    default:

       fprintf(stderr,"Unsupported stop bits ");

       return (FALSE);

    }

       options.c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON);

       options.c_oflag &= ~OPOST;

       options.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG|IEXTEN);

    /* Set input parity option */

   

    if (parity != 'n')

       options.c_iflag |= INPCK;

    options.c_cc[VTIME] = 150; // 15 seconds

    options.c_cc[VMIN] = 0;

   

   

              tcflush(fd,TCIFLUSH); /* Update the options and do it NOW */

    if (tcsetattr(fd,TCSANOW,&options) != 0)

    {

       perror("SetupSerial 3");

       return (FALSE);

    }

    return (TRUE);

}

void receivethread(void)

{

  int nread;

  while(1)   

  {

    

       if((nread = read(fd,buff,100))>0) //接收数据

       {

           printf("[RECEIVE] Len is %d,content is : ",nread);

           buff[nread]='';

           printf("%s ",buff);

       }

      

       usleep(100/**1000*/);

   }

 return;

}

int main(int argc, char *argv[])

{

    char str[500];

    pthread_t receiveid;

    int  c, ctrlbits;

       /*

              参数个数小于1则返回,按如下方式执行:

              ./uart_test /dev/ttyAT1

       */

       if (argc < 2) {

              printf("Useage: %s dev ", argv[0]);

              exit(0);

    }

       printf("test ");

    fd = open(argv[1], O_RDWR);

       if (fd < 0){

              printf("open device %s faild ", argv[1]);

              exit(0);

       }

   

       set_speed(fd,115200); //设置串口波特率

      

       set_Parity(fd,8,1,'N'); //设置8位数据位,1位停止位,无校验等其他设置。

      

       pthread_create(&receiveid,NULL,(void*)receivethread,NULL);//创建接收线程

    while(1)

    {

      printf("Please Input string to send to %s :",argv[1]);

      scanf("%s", str);

      if(strlen(str)>0){

              //发送数据

                     write(fd, str, strlen(str)); 

                     write(fd, " ", strlen(" "));

                            usleep(200*1000);     

         }  

         

      }     

    close(fd);

    exit(0);

}

原文地址:https://www.cnblogs.com/lianghong881018/p/10026511.html