read () / ioctl мешает сигналу GPIO?

Я подключаю встроенную плату Linux (на основе imx233) и MCU MSP430. Они подключаются через 4-контактный SPI, но я использую GPIO для выбора микросхемы на плате Linux. Что я делаю, так это использую опрос для обнаружения спадающего фронта GPIO (номер 52), а затем выполняю чтение SPI либо ioctl, либо read()

int main(void)
{

    /********************************LINUX SCHEDULING**********************************/
        sp.sched_priority = sched_get_priority_max(SCHED_FIFO); //scheduling
        sched_setscheduler(0, SCHED_FIFO, &sp); //scheduling
    /********************************LINUX SCHEDULING_END******************************/    

    struct pollfd fdset[2]; //declare the poll to be used in interrupt catching
    int nfds = 2;
    int gpio_fd, timeout, rc;
    char *buf[MAX_BUF]; //max=64byte
    int len;

    initialize(); //gpio's are set to SPI_SLAVE
//    spi_init();

    gpio_fd = gpio_fd_open(CHIP_SELECT_PIN); //the CS(SS) pin is opened
    timeout = POLL_TIMEOUT; //timeout 3 sec is set
  //  uint8_t voidFirstDetection = 1;

    while (1) {
        memset((void*)fdset, 0, sizeof(fdset));
        fdset[0].fd = NULL;
        fdset[0].events = POLLIN;
        fdset[1].fd = gpio_fd;
        fdset[1].events = POLLPRI;

        /*** POLL starts to detect chipselects****/
        rc = poll(fdset, nfds, timeout);

        if (rc < 0) {
            printf("\npoll() failed!\n");
            return -1;
        }

        if (rc == 0) {
            printf(".");
        }

        if (fdset[1].revents & POLLPRI ) {  //HERE I need to run SPI_read
                len = read(fdset[1].fd, buf, MAX_BUF);
    /*        if(voidFirstDetection){
              voidFirstDetection = 0;
            }else{*/
                 printf("\npoll() GPIO %d interrupt occurred\n", CHIP_SELECT_PIN);

                 int fd = open(device, O_RDWR);
                 if (fd < 0){
                   //  snprintf(systemlogmsg, sizeof(systemlogmsg), "[1181]: errno:%s Cannot open /dev/spidev ", strerror(errno));
                    // error_logging(systemlogmsg, LOGLEVEL_ERROR);
                     printf("error spi recive\n");
                 }
                 //spi_transfer(fd);
                 do_read(fd);
                 close(fd);
        //    }
        }

    }

    gpio_fd_close(gpio_fd);
    return 0;
}

Приведенный выше код работает нормально, поскольку он генерирует прерывание только на заднем фронте сигнала. Я использую любой из приведенных ниже кодов при обнаружении прерывания для чтения /dev/spidev1-0

static void do_read(int fd)
{
    unsigned char   buf[1], *bp;
    int     status;
    int len = 1;

    /* read at least 2 bytes, no more than 32 */
    memset(buf, 0, sizeof buf);

    status = read(fd, buf, len);
    if (status < 0) {
        perror("read");
        return;
    }
    if (status != len) {
        fprintf(stderr, "short read\n");
        return;
    }

    printf("read(%2d, %2d): %02x %02x,", len, status,
        buf[0], buf[1]);
    status -= 2;
    bp = buf + 2;
    while (status-- > 0)
        printf(" %02x", *bp++);
    printf("\n");
}

static void spi_transfer(int fd)
{
    int ret;
    uint8_t tx[2];
    uint8_t rx[3] = {0 };
    struct spi_ioc_transfer tr = {
        .tx_buf = 0,
        .rx_buf = (unsigned long)rx,
        .len = ARRAY_SIZE(tx),
        .delay_usecs = delay,
        .speed_hz = speed,
        .bits_per_word = bits,
    };


    ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
    if (ret < 1){
        printf("can't send spi message");
        exit(1);
    }

    for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
        if (!(ret % 6))
            puts("");
        printf("%.2X ", rx[ret]);
    }
    puts("");
}

Каждый раз, когда выполняется строка ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); на spi_transfer() или status = read(fd, buf, len); на do_read(), я вижу бесконечный цикл, который обнаруживает прерывание на GPIO52 (выбор микросхемы). Я пытаюсь наблюдать за GPIO через осциллограф, но я не вижу никаких изменений сигнала (это может быть всплеск, который мой осциллограф не может обнаружить), однако, когда я подключаю chipselect к Vcc, он не получает бесконечного цикла. Поскольку я нахожусь на ранней стадии, я установил один из GPIO MCU в качестве выхода и постоянный высокий логический уровень. Я использую GPIO52 (выбор чипа) в качестве входа, потому что моя цель - передать данные с MCU на плату Linux.

Я предполагаю, что read() и ioctl каким-то образом влияют на GPIO, чтобы потреблять больше тока, чем может обеспечить GPIO. Если это проблема, что я могу сделать, чтобы ioctl или read () не мешали GPIO. Или вы думаете, что проблема может быть в другом?


person Angs    schedule 26.09.2014    source источник


Ответы (1)


Мне повезло, что я быстро нашел проблему. Связал основания обеих досок и теперь все работает нормально. Я сохраню сообщение, так как у кого-то может быть такая же проблема. Но мне все еще любопытно, как ioctl или read нарушают уровень сигнала GPIO

person Angs    schedule 26.09.2014