Проблема с использованием spi модуля beaglebone black - PullRequest
1 голос
/ 24 января 2020

У меня следующая странная проблема. Я настроил BBB для активации модуля spi1. Модуль подключен к микросхеме F-RAM (FM25CL64B). Я сделал все необходимые настройки. Присутствует /dev/spidev1.0, и я написал небольшую программу для записи и чтения из чипа, открыв /dev/spidev1.0 и используя ioctl с макросом SPI_IOC_MESSAGE.

Использование этой программе мне удалось успешно записать 32 байта текста в чип F-RAM. Чтение также казалось успешным ... Откуда я знаю, что они оба были успешными? Я использовал анализатор logi c с активированным декодером SPI, чтобы реально увидеть, что происходит на всех четырех линиях SPI. Наблюдая за всеми линиями SPI, я мог видеть, что операции записи и чтения генерируют правильные сигналы с правильной синхронизацией, и все сигналы синхронизируются c. CS включает микросхему во время транзакции, CLK синхронизирует каждый байт в 8-битных словах (как настроено), строки данных показывают правильные значения, которые я мог видеть благодаря декодеру SPI, который показывает значение байта прямо над каждым 8- битовая сигнальная последовательность строк MOSI и MISO.

Проблема в том, что, хотя я вижу, что правильная информация передается по линии MISO во время операции чтения, буфер, который я предоставляю ioctl (iSPIR, SPI_IOC_MESSAGE ( 2), xfer) заполнен нулями.

Я намеренно инициализировал этот буфер другими значениями, так что я могу видеть, записывает ли ioctl даже в него. И это так. Нули.

Теперь тот факт, что я мог видеть все байты, отправленные по строке MISO во время операции чтения, доказывает, что операция записи не только выглядела правильно в анализаторе, но фактически записывала нужные данные во время предыдущего операция записи.

Я несколько раз проверял, правильно ли настроена строка MISO, в файле dts (который я могу перестроить и переустановить по требованию). Я проверил, правильный ли это вывод и настроен ли он как вход. Кажется, все настроено правильно.

Я запустил программу как root на случай проблем с разрешениями - без разницы.

Я также реализовал spi-связь в режиме GPIO. Т.е. модуль spi отключен, все линии настроены как GPIO. CE, CLK, MOSI настроены как отупуты, а MISO настроены как входные. Таким образом, я мог реализовать всю связь в программном обеспечении, чтобы иметь полный контроль над линиями. Сделав это, на этот раз мне удалось успешно заполнить буфер правильными данными из чипа F-RAM. Т.е. операция последовательного чтения прошла нормально с чипа F-RAM до моего буфера пользовательского пространства. Мне удалось распечатать данные в консоли. Однако это работало слишком медленно. Также я считаю неэффективным использование чисто программной реализации SPI com, когда есть модуль, доступный для использования.

Чтобы написать пример программы, я использовал spi_test. c пример с открытым исходным кодом, доступный онлайн. Я также собрал и запустил spi_test. c сам без изменений, тот же результат.

Вот список моей программы (Соответствующие фрагменты):

// SPI config ...

int InitSPIReadMode(const char* pstrDeviceF)
{
        int file;
        __u8  wr_mode = SPI_MODE_0, rd_mode = SPI_MODE_0, lsb = 0, bits = 8;
        __u32 speed = CLOCK_FREQ_HZ; // 500kHz

        if((file = open(pstrDeviceF, O_RDWR)) < 0)
        {
                printf("Failed to open the bus.");
                /* ERROR HANDLING; you can check errno to see what went wrong */
                exit(1);
        }
        if(ioctl(file, SPI_IOC_RD_MODE, &rd_mode) < 0)
        {
                printf("SPI rd_mode\n");
                return -1;
        }
        if(ioctl(file, SPI_IOC_RD_LSB_FIRST, &lsb) < 0)
        {
                printf("SPI rd_lsb_fist\n");
                return -1;
        }
        if(ioctl(file, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0)
        {
                printf("SPI bits_per_word\n");
                return -1;
        }
        if(ioctl(file, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0)
        {
                printf("SPI max_speed_hz\n");
                return -1;
        }
        printf("%s: spi wr-mode=%d, spi rd-mode=%d, %d bits per word, %s, %d Hz max\n", pstrDeviceF, wr_mode, rd_mode, bits, lsb ? "(lsb first) " : "(msb first)", speed);

        xfer[0].cs_change = 0; /* Keep CS activated */
        xfer[0].delay_usecs = 0; //delay in us
        xfer[0].speed_hz = CLOCK_FREQ_HZ; //speed
        xfer[0].bits_per_word = 8; // bites per word 8

        xfer[1].cs_change = 0; /* Keep CS activated */
        xfer[1].delay_usecs = 0;
        xfer[1].speed_hz = CLOCK_FREQ_HZ;
        xfer[1].bits_per_word = 8;

        return file;
}

В основной функции: ( как показывает анализатор logi c, этот код правильно отправляет команду, адрес и затем синхронизирует 32 байта данных)


                int iSPIR = InitSPIReadMode("/dev/spidev1.0"); //open("/dev/spidev1.0", O_RDWR | O_SYNC);

                char arrInstruct[3] = { OPCO_READ, 0x00, 0x00 };
                char arrFRamData[512];

                for(int pos = 0; pos < 512; pos++) arrFRamData[pos] = pos;

                xfer[0].tx_buf = (unsigned long)arrInstruct;
                xfer[0].len = 3;

                xfer[1].rx_buf = (unsigned long)arrFRamData;
                xfer[1].len = 32;

                if(ioctl(iSPIR, SPI_IOC_MESSAGE(2), xfer) < 0) printf("ioctl write error %s.\n", strerror(errno));

// hex dumping of the arrFRamData buffer.

xfer - глобальная переменная, определяемая как:

struct spi_ioc_transfer xfer[2];

Заранее большое спасибо! :)

1 Ответ

1 голос
/ 27 января 2020

Я обнаружил, в чем проблема с моей настройкой. Но хотя теперь все работает, решение, которое я применил, вызывает больше вопросов, чем ответов.

Так что я нашел это решение в статье (https://elinux.org/BeagleBone_Black_Enable_SPIDEV) на wiki beaglebone.

Там я заметил, что в оверлее дерева устройств они устанавливают CLK в качестве входа. Чтение всей статьи ничего не дало о том, почему ЧАСЫ со стороны ВВВ должны быть входными данными. Несмотря на то, что это мастер ... В статье только объясняется, как собрать и установить новый DTBO для активации модуля SPI1.

Итак, хотя для меня это не имело никакого смысла, я не мешало бы попытаться изменить строку CLK в моей форме вывода файла DTBO на ввод, чтобы увидеть, что происходит ... И это сработало! : O

Теперь, почему это так странно, что установка работает так. Предполагается, что BBB является мастером SPI, поэтому его тактовая линия должна быть выходом, чтобы управлять этой синхронной связью. Это означает, что чип FM25CL64B должен выступать в качестве ведомого SPI. Я только что проверил таблицу и да, CLK на стороне чипов, является входом. Таким образом, CLK на BBB должен быть выходным. Вот как я настроил контакт CLK на BBB. В качестве вывода. И это не сработало.

Вот почему я так озадачен. Так что это работает, хотя оба конца линии CLK являются входами ?! Глядя на вывод анализаторов logi c, я ясно вижу, что линия CLK работает правильно. Но если оба хозяина и раба имеют входы на этой линии, не должно быть ничего, чтобы генерировать эти импульсы ?! С этой линией больше ничего не связано ...

...