龙芯开源社区

 找回密码
 注册新用户(newuser)
查看: 2323|回复: 7

龙芯1b串

[复制链接]
发表于 2013-12-24 21:45:33 | 显示全部楼层 |阅读模式
龙芯1B中提供了  ttyS0 到 ttyS5  6个串口,连接pc使用的是ttyS2,那么其余的串口驱动分别是什么?   在串口驱动中没有看到 file_operations 却可以使用文件操作的方式 (open ,read, write)进行操作?  求大神作答,谢谢啦
发表于 2013-12-25 10:35:38 | 显示全部楼层
内核配置中可以支持6个串口或者更多,但是在原理图中只能看到5个串口(UART0,UART2,UART3,UART4,和UART5)。UART1和网口1有引脚复用,因为开发板引出了2个网口,所以UART1就被没实现。
    串口驱动不是简单的字符设备驱动,再加上龙芯1B开发板把串口驱动放到了platform框架中,所以看不到read,write。但是有类似的。比如源文件“1b-linux-3.0-d8b47bb/drivers/tty/serial/8250.c”中的static struct uart_ops serial8250_pops就类似file_operations定义了相关接口函数。
    另外,platform框架参考源文件“1b-linux-3.0-d8b47bb/arch/mips/loongson/ls1x/platform.c”中的static struct plat_serial8250_port uart8250_data[]
    希望对你有帮助。
 楼主| 发表于 2013-12-25 20:02:32 | 显示全部楼层
回复 2# caogos

非常感谢你的回答,我回去研究一下;如果通过对 设备文件读写的方式(open,read,write)操作ttyS0 是否可行呢?
发表于 2013-12-26 10:46:31 | 显示全部楼层
回复 3# zl1990


    可以通过read,write的方式操作ttyS2,实际上也是这样做的。
    现在贴上网友的一个例子:
    这个例子中,需要打开串口1,设置9600波特率、8位数据位、1位停止位以及空校验,之后利用while语句循环判断串口中是否可以读出数据,将串口中数据连续读出后重新写回到串口中。该程序可与minicom联合测试。
#include     <stdio.h>
#include     <stdlib.h>
#include     <unistd.h>  
#include     <sys/types.h>
#include     <sys/stat.h>
#include     <fcntl.h>
#include     <termios.h>
#include     <errno.h>
   
main()
{
    int fd;
    int i;
    int len;
    int n = 0;      
    char read_buf[256];
    char write_buf[256];
    struct termios opt;
   
    fd = open("/dev/ttyS0", O_RDWR | O_NOCTTY);    //默认为阻塞读方式
    if(fd == -1)
    {
        perror("open serial 0\n");
        exit(0);
    }

    tcgetattr(fd, &opt);      
    cfsetispeed(&opt, B9600);
    cfsetospeed(&opt, B9600);
   
    if(tcsetattr(fd, TCSANOW, &opt) != 0 )
    {     
       perror("tcsetattr error");
       return -1;
    }
   
    opt.c_cflag &= ~CSIZE;  
    opt.c_cflag |= CS8;   
    opt.c_cflag &= ~CSTOPB;
    opt.c_cflag &= ~PARENB;
    opt.c_cflag &= ~INPCK;
    opt.c_cflag |= (CLOCAL | CREAD);

    opt.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);

    opt.c_oflag &= ~OPOST;
    opt.c_oflag &= ~(ONLCR | OCRNL);    //添加的

    opt.c_iflag &= ~(ICRNL | INLCR);
    opt.c_iflag &= ~(IXON | IXOFF | IXANY);    //添加的
   
    opt.c_cc[VTIME] = 0;
    opt.c_cc[VMIN] = 0;
   
    tcflush(fd, TCIOFLUSH);

    printf("configure complete\n");
   
    if(tcsetattr(fd, TCSANOW, &opt) != 0)
    {
        perror("serial error");
        return -1;
    }
    printf("start send and receive data\n");
  
    while(1)
    {   
        n = 0;
        len = 0;
        bzero(read_buf, sizeof(read_buf));    //类似于memset
        bzero(write_buf, sizeof(write_buf));

        while( (n = read(fd, read_buf, sizeof(read_buf))) > 0 )
        {
            for(i = len; i < (len + n); i++)
            {
                write_buf = read_buf[i - len];
            }
            len += n;
        }
        write_buf[len] = '\0';
              
        printf("Len %d \n", len);
        printf("%s \n", write_buf);

        n = write(fd, write_buf, len);
        printf("write %d chars\n",n);
        
        sleep(2);
    }
}

详情参考:http://www.cnblogs.com/lovemo1314/archive/2010/10/29/1864327.html
发表于 2013-12-26 10:49:57 | 显示全部楼层
回复 3# zl1990


    我把再龙芯1B开发板上运行的串口例子也贴上,我这里还有些串口方面的资料,如果需要请加qq
    帖子有字数限制,所以做两个帖子发
[root@localhost uart]# cat serial.c
/**********************************************
*  *RS-232
*  *date:2008-02-20
**********************************************/
#include <stdio.h>              // printf
#include <fcntl.h>              // open
#include <string.h>             // bzero
#include <stdlib.h>             // exit
#include <sys/times.h>          // times
#include <sys/types.h>          // pid_t
#include <termios.h>            //termios, tcgetattr(), tcsetattr()
#include <unistd.h>
#include <sys/ioctl.h>          // ioctl


typedef struct{
        char    prompt;         //prompt after reciving data
        int     baudrate;               //baudrate
        char    databit;                //data bits, 5, 6, 7, 8
        char    debug;          //debug mode, 0: none, 1: debug
        char    echo;                   //echo mode, 0: none, 1: echo
        char    fctl;                   //flow control, 0: none, 1: hardware, 2: software
        char    tty;                    //tty: 0, 1, 2, 3, 4, 5, 6, 7
        char    parity;         //parity 0: none, 1: odd, 2: even
        char    stopbit;                //stop bits, 1, 2
        const int reserved;     //reserved, must be zero
}portinfo_t;
typedef portinfo_t *pportinfo_t;


#define TTY_DEV         "/dev/ttyS"     //端口路径

#define TIMEOUT_SEC(buflen,baud) (buflen*20/baud+2)  //接收超时
#define TIMEOUT_USEC 0
/*******************************************
*      获得端口名称
********************************************/
char *get_ptty(pportinfo_t pportinfo)
{
        char *ptty;

        switch(pportinfo->tty){
                case '0':{
                        ptty = TTY_DEV"0";
                }break;
                case '1':{
                        ptty = TTY_DEV"1";
                }break;
                case '2':{
                        ptty = TTY_DEV"2";
                }break;
        }
        return(ptty);
}

/*******************************************
*      波特率转换函数(请确认是否正确)
********************************************/
int convbaud(unsigned long int baudrate)
{
        switch(baudrate){
                case 2400:
                        return B2400;
                case 4800:
                        return B4800;
                case 9600:
                        return B9600;
                case 19200:
                        return B19200;
                case 38400:
                        return B38400;
                case 57600:
                        return B57600;
                case 115200:
                        return B115200;
                default:
                        return B9600;
        }
}

/*******************************************
*      Setup comm attr
*      fdcom: 串口文件描述符,pportinfo: 待设置的端口信息(请确认)
*
********************************************/
int PortSet(int fdcom, const pportinfo_t pportinfo)
{
        struct termios termios_old, termios_new;
        int     baudrate, tmp;
        char    databit, stopbit, parity, fctl;

        bzero(&termios_old, sizeof(termios_old));
        bzero(&termios_new, sizeof(termios_new));
        cfmakeraw(&termios_new);
        tcgetattr(fdcom, &termios_old);                 //get the serial port attributions
        /*------------设置端口属性----------------*/
        //baudrates
        baudrate = convbaud(pportinfo -> baudrate);
        cfsetispeed(&termios_new, baudrate);            //填入串口输入端的波特率
        cfsetospeed(&termios_new, baudrate);            //填入串口输出端的波特率
        termios_new.c_cflag |= CLOCAL;                  //控制模式,保证程序不会成为端口的占有者
        termios_new.c_cflag |= CREAD;                   //控制模式,使能端口读取输入的数据

        // 控制模式,flow control
        fctl = pportinfo-> fctl;
        switch(fctl){
                case '0':{
                        termios_new.c_cflag &= ~CRTSCTS;                //no flow control
                }break;
                case '1':{
                        termios_new.c_cflag |= CRTSCTS;                 //hardware flow control
                }break;
                case '2':{
                        termios_new.c_iflag |= IXON | IXOFF |IXANY;     //software flow control
                }break;
        }

        //控制模式,data bits
        termios_new.c_cflag &= ~CSIZE;          //控制模式,屏蔽字符大小位
        databit = pportinfo -> databit;
        switch(databit){
                case '5':
                        termios_new.c_cflag |= CS5;
                case '6':
                        termios_new.c_cflag |= CS6;
                case '7':
                        termios_new.c_cflag |= CS7;
                default:
                        termios_new.c_cflag |= CS8;
        }

        //控制模式 parity check
        parity = pportinfo -> parity;
        switch(parity){
                case '0':{
                        termios_new.c_cflag &= ~PARENB;         //no parity check
                }break;
                case '1':{
                        termios_new.c_cflag |= PARENB;          //odd check
                        termios_new.c_cflag &= ~PARODD;
                }break;
                case '2':{
                        termios_new.c_cflag |= PARENB;          //even check
                        termios_new.c_cflag |= PARODD;
                }break;
        }

        //控制模式,stop bits
        stopbit = pportinfo -> stopbit;
        if(stopbit == '2'){
                termios_new.c_cflag |= CSTOPB;  //2 stop bits
        }
        else{
                termios_new.c_cflag &= ~CSTOPB; //1 stop bits
        }

        //other attributions default
        termios_new.c_oflag &= ~OPOST;                  //输出模式,原始数据输出
        termios_new.c_cc[VMIN]  = 1;                    //控制字符, 所要读取字符的最小数量
        termios_new.c_cc[VTIME] = 1;                    //控制字符, 读取第一个字符的等待时间    unit: (1/10)second

        tcflush(fdcom, TCIFLUSH);                               //溢出的数据可以接收,但不读
        tmp = tcsetattr(fdcom, TCSANOW, &termios_new);  //设置新属性,TCSANOW:所有改变立即生效 tcgetattr(fdcom, &termios_old);
        return(tmp);
}
发表于 2013-12-26 10:50:26 | 显示全部楼层
(续)上一贴

/*******************************************
*      Open serial port
*      tty: 端口号 ttyS0, ttyS1, ....
*      返回值为串口文件描述符
********************************************/
int PortOpen(pportinfo_t pportinfo)
{
        int fdcom;      //串口文件描述符
        char *ptty;

        //ptty = get_ptty(pportinfo);
        //fdcom = open(ptty, O_RDWR | O_NOCTTY | O_NDELAY);
        ptty = "/dev/ttyS0";
        fdcom = open(ptty, O_RDWR | O_NOCTTY | O_NONBLOCK);

        return (fdcom);
}

/*******************************************
*      Close serial port
********************************************/
void PortClose(int fdcom)
{
        close(fdcom);
}

/********************************************
*      send data
*      fdcom: 串口描述符,data: 待发送数据,datalen: 数据长度
*      返回实际发送长度
*********************************************/
int PortSend(int fdcom, char *data, int datalen)
{
        int len = 0;

        len = write(fdcom, data, datalen);      //实际写入的长度
        if(len == datalen){
                return (len);
        }
        else{
                tcflush(fdcom, TCOFLUSH);
                return -1;
        }
}

/*******************************************
*      receive data
*      返回实际读入的字节数
*
********************************************/
int PortRecv(int fdcom, char *data, int datalen, int baudrate)
{
        int readlen, fs_sel;
        fd_set  fs_read;
        struct timeval tv_timeout;

        FD_ZERO(&fs_read);
        FD_SET(fdcom, &fs_read);
        tv_timeout.tv_sec = TIMEOUT_SEC(datalen, baudrate);
        tv_timeout.tv_usec = TIMEOUT_USEC;

        fs_sel = select(fdcom+1, &fs_read, NULL, NULL, &tv_timeout);
        if(fs_sel){
                readlen = read(fdcom, data, datalen);
                return(readlen);
        }
        else{
                return(-1);
        }

        return (readlen);
}

//*************************Test*********************************
int main(int argc, char *argv[])
{
        int fdcom, i, j, SendLen, RecvLen,infor_length;
        struct termios termios_cur;
        char RecvBuf[20];
        unsigned char ctmp;
    char SendBuf[20];
        char *infor=argv[2];
        portinfo_t portinfo ={
                '0',                            // print prompt after receiving
                115200,                         // baudrate: 115200
                '8',                            // databit: 8
                '0',                            // debug: off
                '0',                            // echo: off
                '0',                            // flow control: none
                '1',                            // default tty: COM1
                '0',                            // parity: none
                '1',                            // stopbit: 1
                 0                              // reserved
        };
/*
        infor_length=strlen(infor);
        if(argc != 3){
                printf("Usage: <type 0 -- send 1 -- receive>\n");
                printf("   eg:");
                printf("        MyPort 0\n");
                exit(-1);
        }
*/

        fdcom = PortOpen(&portinfo);
        if(fdcom<0){
                printf("Error: open serial port error.\n");
                exit(1);
        }

        PortSet(fdcom, &portinfo);

        SendBuf[0] = '0';
        SendBuf[1] = 'K';
        SendBuf[2] = '!';
        SendBuf[3] = '\n';
        SendBuf[4] = '\0';

        PortSend(fdcom, SendBuf, 5);


    printf("\nOver!\n");

    PortClose(fdcom);
   
/*
        if(atoi(argv[1]) == 0){
                //send data
                for(i=0; i<1; i++){
                        SendLen = PortSend(fdcom, infor, infor_length);
                        if(SendLen>0){
                                printf("\n No %d send %d data information.\n", i, SendLen);
                        }
                        else{
                                printf("Error: send failed.\n");
                        }
                        sleep(1);
                }
                PortClose(fdcom);
        }
        else if(atoi(argv[1]) == 1){
                for(;;){
                        RecvLen = PortRecv(fdcom, RecvBuf, 10, portinfo.baudrate);
                        if(RecvLen>0){
                                for(i=0; i<RecvLen; i++){
                                        printf("Receive data No %d is %x.\n", i, RecvBuf[i]);
                                }
                                printf("Total frame length is %d.\n", RecvLen);
                        }
                        else{
                                printf("Error: receive error.\n");
                        }
                        sleep(2);
                }
                PortClose(fdcom);
        }
*/
        return 0;
}
[root@localhost uart]#
 楼主| 发表于 2013-12-26 11:19:19 | 显示全部楼层
回复 6# caogos


    请问大神的QQ是多少呀?
发表于 2013-12-26 14:08:28 | 显示全部楼层
回复 7# zl1990


    1207280597 简单平安

本版积分规则

小黑屋|手机版|Archiver|Lemote Inc.  

GMT+8, 2019-7-22 19:49 , Processed in 0.198797 second(s), 20 queries .

快速回复 返回顶部 返回列表