2015-07-22 4 views
3

У меня возникли проблемы с получением программы SPI я работаю на себя правильно, и это, кажется, какой-то вопрос с SPI_IOC_MESSAGE (N) макро.SPI_IOC_MESSAGE (N) макрос дает мне подходит

Вот пример кода, который не работает (IOCTL возвращает EINVAL (22)):

std::vector<spi_ioc_transfer> tr; 
<code that fills tr with 1+ transfers> 
// Hand the transmission(s) off to the SPI driver 
if (tr.size() > 0) 
{ 
    int ret = ioctl(fd, SPI_IOC_MESSAGE(tr.size()), tr.data()); 
    if (ret < 1) 
    { 
     int err = errno; 
    } 
} 

Мой тестовый код прямо сейчас создает вектор длины 1. Если я явно изменить код:

int ret = ioctl(fd, SPI_IOC_MESSAGE(1), tr.data()); 

... тогда ioctl (...) преуспевает, а мои биты идут по трубе. Глядя на расширение макроса SPI_IOC_MESSAGE в Eclipse, я не понимаю, почему это недовольство.

Предложения?

Я кросс-компиляции для Linux/ARM (Beaglebone Black) из 64-битной Linux VM, но я не могу видеть, что затрагивая макрос.

EDIT: Вот два макроса разложения из С препроцессора

int ret = ioctl(fd, (((1U) << (((0 +8)+8)+14)) | ((('k')) << (0 +8)) | (((0)) << 0) | ((((sizeof(char[((((tr.size())*(sizeof (struct spi_ioc_transfer))) < (1 << 14)) ? ((tr.size())*(sizeof (struct spi_ioc_transfer))) : 0)])))) << ((0 +8)+8))), tr.data()); 

и буквальным:

int ret = ioctl(fd, (((1U) << (((0 +8)+8)+14)) | ((('k')) << (0 +8)) | (((0)) << 0) | ((((sizeof(char[((((1)*(sizeof (struct spi_ioc_transfer))) < (1 << 14)) ? ((1)*(sizeof (struct spi_ioc_transfer))) : 0)])))) << ((0 +8)+8))), tr.data()); 

Абсолютно отвратительные, но я не вижу ничего удивительного в как tr.size() будет использоваться там.

Редактировать, чтобы включить то, что, кажется, ответ

#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */ 
extern "C" { 
#endif 
#include <linux/spi/spidev.h> 
#ifdef __cplusplus /* If this is a C++ compiler, use C linkage */ 
} 
#endif 

Обертывание Линукс SPI включают файл в «экстерном C» инструктирует систему, чтобы рассматривать этот раздел как обычный старый C, и это, кажется, позвольте мне позвонить SPI_IOC_MESSAGE(tr.size()) или SPI_IOC_MESSAGE(an_int) и иметь правильную вещь (проверено с помощью GDB stepthrough и анализатора сигналов).

ответ

1

Я подозреваю, что проблема может лежать в данном самородок захоронены в макроэкономическом суп:

...sizeof(char[...tr.size()...])... 

принимая к сведению, что код Linux является исключительно C, стандарт C (у меня есть C99 проект n1256 здесь) говорится, для sizeof что операнд выражения равен не оценен, а результатом является константа, , если только тип операнда не является массивом переменной длины, и в этом случае он вычисляется, а результат представляет собой целое число.

Однако стандарт C++ (проект C++ 11 n3242), похоже, не дает никаких условий, при которых операнд оценивается, и только утверждает, что результат является константой.

Таким образом, похоже, что это может быть один из углов, где C и C++ отличаются, и компиляции один как другой приводит к неопределенному поведению. В этом случае я считаю, что выбор - это просто взламывание собственной версии макроса или наличие отдельной внешней функции C, которая ее обертывает.

+1

Похоже, что это где-то близко к первопричине. Я изменил свой код, чтобы обернуть файл SPI Linux, включенный в директиву «extern C» и, похоже, исправил поведение. –

 Смежные вопросы

  • Нет связанных вопросов^_^