【问题标题】:Issue when reading tty with nfs rootfs使用 nfs rootfs 读取 tty 时出现问题
【发布时间】:2015-10-06 07:45:56
【问题描述】:

对于一个嵌入式设备(内核 3.14 和带有 OpenEmbedded 的 rootfs),我开发了一个软件来读取 tty 驱动程序上的数据。当我在板上测试时,该软件可以正常运行。 如果我为 rootfs 使用 nfs 服务器,则软件会卡在读取 tty 文件的循环上。我不能用'ctrl+c'出去,我不能在控制台上写,我有这样的消息“nfs:服务器192.168.1.40没有响应,还在尝试”

有人知道这个问题吗?

谢谢

我的软件:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/poll.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <fcntl.h>
#include <termios.h>
#include <sys/fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>

#define FALSE   0
#define TRUE    1

int print_help (int argc, char *argv[])
{
    printf("Test program for uart reception\n");
    printf("Usage :\n");
    printf("\t%s [-h -D -c]\n", argv[0]);
    printf("\t-D : use this tty device\n");
    printf("\t-c : control data to extract the trame\n");
    printf("\t-h : print help\n");
    return 0;
}

int wait_flag = TRUE ;

void signal_handler_IO (int status)
{
     //printf("received data from UART.\n");
     wait_flag = FALSE;
}

/*
 * The values for speed are B115200, B230400, B9600, B19200, B38400, B57600,
 * B1200, B2400, B4800, etc. The values for parity are 0 (meaning no parity),*
 * PARENB|PARODD (enable parity and use odd), PARENB (enable parity and use even),
 * PARENB|PARODD|CMSPAR (mark parity), and PARENB|CMSPAR (space parity).
 */
int set_interface_attribs (int fd, int speed, int parity)
{
    struct sigaction saio;
        struct termios tty;
        memset (&tty, 0, sizeof tty);


    /***/
    saio.sa_handler = signal_handler_IO;
    saio.sa_flags = 0;
    saio.sa_restorer = NULL;
    sigaction(SIGIO, &saio, NULL);

    fcntl (fd, F_SETFL, FNDELAY|FASYNC);
    fcntl (fd, F_SETOWN, getpid());
    /***/

        if (tcgetattr (fd, &tty) != 0)
        {
                printf("error from tcgetattr\n");
                return -1;
        }

        cfsetospeed (&tty, speed);
        cfsetispeed (&tty, speed);

        tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
        // disable IGNBRK for mismatched speed tests; otherwise receive break
        // as \000 chars
        tty.c_iflag &= ~IGNBRK;         // disable break processing
        tty.c_lflag = 0;                // no signaling chars, no echo,
                                        // no canonical processing
        tty.c_oflag = 0;                // no remapping, no delays
        tty.c_cc[VMIN]  = 0;            // read doesn't block
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

        tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

        tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                        // enable reading
        tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
        tty.c_cflag |= parity;
        tty.c_cflag &= ~CSTOPB;
        tty.c_cflag &= ~CRTSCTS;

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
        {
                printf("error from tcsetattr\n");
                return -1;
        }
        return 0;
}

/*
 * "Blocking" sets whether a read() on the port waits for the specified number
 * of characters to arrive. Setting no blocking means that a read() returns
 * however many characters are available without waiting for more, up to the
 * buffer limit.
 */
void set_blocking (int fd, int should_block)
{
        struct termios tty;
        memset (&tty, 0, sizeof tty);
        if (tcgetattr (fd, &tty) != 0)
        {
                printf ("error from tggetattr\n");
                return;
        }

        tty.c_cc[VMIN]  = should_block ? 1 : 0;
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

        if (tcsetattr (fd, TCSANOW, &tty) != 0)
                printf ("error setting term attributes\n");
}


int main(int argc, char *argv[]) {
    int i, j, k;
    int fd;
    char c;
    signed char index_trame = -1;
    char trame[6];
    char initChaine[30] = "Frame received on uart :";
    char *ttyDevice = "/dev/ttyAPP0";
    char chaineCar[100];
    char receptCar[6];
    char buf[255];
    char processData[512];
    char restofData[6];
    int sizeofData = 0;
    char ctrl_trame = 0;
    int loop = 0;
    int ret = 0;
    int count = 0;
    FILE* saveFile = NULL;

    /* Parse arguments */
    if (argc < 0 || argc > 4) {
        printf("Invalid number of argument\n");
        print_help(argc, argv);
        return 0;
    }
    j = 0;
    for (i=1; i<argc; i++) {
        if (argv[i][0] == '-') {
            for (k=1; argv[i][k]; k++) {
                switch (argv[i][k]) {
                    case 'D':
                        ttyDevice = argv[i+1];
                        printf("Use %s device\n",ttyDevice);
                        break;
                    case 'c':
                        ctrl_trame = 1;
                        break;
                    case 'h':
                        print_help(argc, argv);
                        break;
                    default:
                        printf("Wrong option: -%c\n", argv[i][k]);
                        print_help(argc, argv);
                        return 0;
                }
            }
        } else {
        }
        j ++;
    }/**/

    /*run program*/
    printf(" Read serial port V0.6\n");

    saveFile = fopen("receptUart.txt", "w+");
    index_trame = 0;

    /* Ouverture de la liaison serie */
    if ( (fd=open(ttyDevice, O_RDONLY | O_NOCTTY | O_SYNC)) == -1 ) {
        printf("error open %s\n", ttyDevice);
        return -1;
    }

    set_interface_attribs (fd, B2400, 0);
    set_blocking (fd, 1);

    do {
            if (wait_flag == FALSE) {
                ret = read(fd, buf, 255);
                if (ctrl_trame) {
                    for (i=0;i<ret;i++)
                        processData[sizeofData+i] = buf[i];
                    sizeofData += ret;
                    for (i=0;i<sizeofData;i++) {
                        if ((sizeofData - i) < 6) {
                            break;
                        }
                        else if (processData[i] == 0xfa) {
                            count++;
                            printf ("Received frame n %d :", count);
                            for (j=0;j<6;j++) {
                                trame[j]=processData[i];
                                printf(" h%02x", processData[i]);
                                i++;
                            }
                            i--;
                            printf("\n");
                        }
                    }
                    for(j=i;j<sizeofData;j++)
                        processData[j-i] = processData[j];
                    sizeofData -= i;
                }
                else {
                    printf ("%i data received :", ret);
                    for (i=0;i<ret;i++) {
                        printf(" h%02x", buf[i]);
                    }
                    printf("\n");
                }
                wait_flag = TRUE;
            }
    }
    while (1);

    close(fd);
    printf("GoodBye\n");

    return EXIT_SUCCESS;
}

【问题讨论】:

  • 可能是访问共享库的问题。使用strace 命令前缀运行您的程序以查看实际情况。或者尝试使用-static 选项编译/链接。
  • 当你让设备开始发出大量的中断(和/或驱动程序在其中断处理程序中花费的时间过长)时,我看到了一些表面上相似的事情,它淹没了网络控制器的中断并停止内核处理网络流量;然后您将无法返回控制台,因为您已断开网络并丢失了根文件系统。

标签: linux arm embedded-linux nfs tty


【解决方案1】:

我发现了问题:这是 devicetree 上的错误设置。 UART 端口设置为使用 CTS/RTS 线,以太网 PHY 连接到 CTS/RTS 引脚进行控制。然后这个引脚被用于 2 个驱动程序,其中一个崩溃了。 我更改了 UART 设置,它的工作原理

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-22
    • 2013-10-18
    • 2023-04-05
    • 1970-01-01
    相关资源
    最近更新 更多