Код GPIO с использованием / dev / mem неожиданно завершает работу при установке значения бита для регистрации

Для своего проекта я пытаюсь написать код, который (1) будет контролировать входной контакт на предмет значения нарастающего фронта и (2) переключать выходной контакт в ответ. Цель состоит в том, чтобы определить распределения задержки для различных реализаций кода для разных частот на различных микроконтроллерах и небольших компьютерных платформах (Arduino, RPi, Beaglebone Black). В настоящее время я работаю над BBB (Debian v7.8) и пытаюсь реализовать код / ​​dev / mem, но код выходит по неизвестной причине до того, как будут установлены все значения регистров.

Вот весь код (EDITED после добавления кода ошибки возвращается для MMAP ()):

 /* 1.0 Pre-Main Function Operations */
/* 1.1 Definitions */
#define GPIO_0_START 0x44E07000 // GPIO_0 Bank (Not Used in Current Build)
#define GPIO_0_END 0x44E07FFF
#define GPIO_1_START 0x4804C000 // GPIO_1 Bank (PIN_LED is located here, GPIO1_21)
#define GPIO_1_END 0x4804CFFF
#define GPIO
    /* 4.5 Establish Pin Modes */
    cout << "Establishing Pin Modes.\n";
    *gpio2_oe_addr = PIN_MONITOR_0;
    cout << "PIN_MONITOR established as INPUT.\n";
START 0x481AA000 // GPIO_2 Bank ({PIN_MONITOR, PIN_CONFIRM, PIN_RESPONSE} are located here) #define GPIO
    /* 4.5 Establish Pin Modes */
    cout << "Establishing Pin Modes.\n";
    *gpio2_oe_addr = PIN_MONITOR_0;
    cout << "PIN_MONITOR established as INPUT.\n";
END 0x481AAFFF #define GPIO
unsigned int reg;
reg = *gpio_reg_addr;
reg = reg & (0xFFFFFF - BIT_SET_COMMAND)
*gpio_reg_addr = reg;
START 0x481AF000 // GPIO_3 Bank (Not Used in Current Build) #define GPIO
unsigned int reg;
reg = *gpio_reg_addr;
reg = reg & (0xFFFFFF - BIT_SET_COMMAND)
*gpio_reg_addr = reg;
END 0x481AFFFF /* 1.2 GPIO Pad Memory Sizes */ #define GPIO_0_SIZE (GPIO_0_END - GPIO_0_START) #define GPIO_1_SIZE (GPIO_1_END - GPIO_1_START) #define GPIO
    /* 4.5 Establish Pin Modes */
    cout << "Establishing Pin Modes.\n";
    *gpio2_oe_addr = PIN_MONITOR_0;
    cout << "PIN_MONITOR established as INPUT.\n";
SIZE (GPIO
    /* 4.5 Establish Pin Modes */
    cout << "Establishing Pin Modes.\n";
    *gpio2_oe_addr = PIN_MONITOR_0;
    cout << "PIN_MONITOR established as INPUT.\n";
END - GPIO
    /* 4.5 Establish Pin Modes */
    cout << "Establishing Pin Modes.\n";
    *gpio2_oe_addr = PIN_MONITOR_0;
    cout << "PIN_MONITOR established as INPUT.\n";
START) #define GPIO
unsigned int reg;
reg = *gpio_reg_addr;
reg = reg & (0xFFFFFF - BIT_SET_COMMAND)
*gpio_reg_addr = reg;
SIZE (GPIO
unsigned int reg;
reg = *gpio_reg_addr;
reg = reg & (0xFFFFFF - BIT_SET_COMMAND)
*gpio_reg_addr = reg;
END - GPIO
unsigned int reg;
reg = *gpio_reg_addr;
reg = reg & (0xFFFFFF - BIT_SET_COMMAND)
*gpio_reg_addr = reg;
START) /* 1.3 Memory Offsets for GPIO Bit Registers */ // Values taken from Table 25-5 (GPIO Registers) of the AM335X Technical Reference Manual #define GPIO_REVISION 0x0 #define GPIO_SYSCONFIG 0x10 #define GPIO_EOI 0x20 #define GPIO_IRQSTATUS_RAW_0 0x24 #define GPIO_IRQSTATUS_RAW_1 0x28 #define GPIO_IRQSTATUS_0 0x2C #define GPIO_IRQSTATUS_1 0x30 #define GPIO_IRQSTATUS_SET_0 0x34 #define GPIO_IRQSTATUS_SET_1 0x38 #define GPIO_IRQSTATUS_CLR_0 0x3C #define GPIO_IRQSTATUS_CLR_1 0x40 #define GPIO_IRQWAKEN_0 0x44 #define GPIO_SYSSTATUS 0x114 #define GPIO_CTRL 0x130 #define GPIO_OE 0x134 #define GPIO_DATAIN 0x138 #define GPIO_DATAOUT 0x13C #define GPIO_LEVELDETECT0 0x140 #define GPIO_LEVELDETECT1 0x144 #define GPIO_RISINGDETECT 0x148 #define GPIO_FALLINGDETECT 0x14C #define GPIO_DEBOUNCENABLE 0x150 #define GPIO_DEBOUNCINGTIME 0x154 #define GPIO_CLEARDATAOUT 0x190 #define GPIO_SETDATAOUT 0x194 /* 1.4 Register Pin NUmbers */ // Definition ~Name~ ~ADDRESS~ ~OFFSET~ #define PIN_MONITOR 70 // GPIO2_6 0x8A0 0A0 #define PIN_CONFIRM 73 // GPIO2_9 0x8AC 0AC #define PIN_LED 21 // GPIO1_21 --- --- // USR0 is controlled via another file system #define PIN_RESPONSE 74 // GPIO2_10 0x8B0 0B0 #define PIN_MONITOR_OFFSET 6 #define PIN_CONFIRM_OFFSET 9 #define PIN_LED_OFFSET 21 #define PIN_RESPONSE_OFFSET 10 /* 1.5 GPIO Directory File Path */ #define DEV_MEM_GPIO_DIR "/dev/mem" /* 1.6 Bit Setting Commands for GPIO pins & Registers */ #define PIN_MONITOR_0 (0<<PIN_MONITOR_OFFSET) #define PIN_MONITOR_1 (1<<PIN_MONITOR_OFFSET) #define PIN_LED_0 (0<<PIN_LED_OFFSET) #define PIN_LED_1 (1<<PIN_LED_OFFSET) #define PIN_CONFIRM_0 (0<<PIN_CONFIRM_OFFSET) #define PIN_CONFIRM_1 (1<<PIN_CONFIRM_OFFSET) #define PIN_RESPONSE_0 (0<<PIN_RESPONSE_OFFSET) #define PIN_RESPONSE_1 (1<<PIN_RESPONSE_OFFSET) /* 2.0 Inclusions */ #include <sys/mman.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> #include <sys/poll.h> #include <stropts.h> #include <iostream> #include <stdint.h> #include <stdio.h> #include <stdlib.h> using namespace std; /* 3.0 Function Definitions */ /* None at this time */ /* 4.0 Main Function */ int main() { /* 4.1 Initialize GPIO Array Address Pointers */ volatile unsigned int *gpio1_addr = NULL; volatile unsigned int *gpio2_addr = NULL; /* 4.2 Initialize GPIO Register Pointers */ /* 4.2.1 GPIO1 */ volatile unsigned int *gpio1_oe_addr = NULL; volatile unsigned int *gpio1_dataout_addr = NULL; volatile unsigned int *gpio1_cleardataout_addr = NULL; volatile unsigned int *gpio1_setdataout_addr = NULL; /* 4.2.2 GPIO2 */ volatile unsigned int *gpio2_irqstatus_raw0_addr = NULL; volatile unsigned int *gpio2_irqstatus_raw1_addr = NULL; volatile unsigned int *gpio2_irqstatus_0_addr = NULL; volatile unsigned int *gpio2_irqstatus_1_addr = NULL; volatile unsigned int *gpio2_irqstatus_set0_addr = NULL; volatile unsigned int *gpio2_irqstatus_set1_addr = NULL; volatile unsigned int *gpio2_irqstatus_clr0_addr = NULL; volatile unsigned int *gpio2_irqstatus_clr1_addr = NULL; volatile unsigned int *gpio2_irqwaken0_addr = NULL; volatile unsigned int *gpio2_irqwaken1_addr = NULL; volatile unsigned int *gpio2_oe_addr = NULL; volatile unsigned int *gpio2_datain_addr = NULL; volatile unsigned int *gpio2_dataout_addr = NULL; volatile unsigned int *gpio2_risingdetect_addr = NULL; volatile unsigned int *gpio2_debounenable_addr = NULL; volatile unsigned int *gpio2_debouncingtime_addr = NULL; volatile unsigned int *gpio2_cleardataout_addr = NULL; volatile unsigned int *gpio2_setdataout_addr = NULL; /* 4.3 Accessing /dev/mem/ */ int fd = open(DEV_MEM_GPIO_DIR,O_RDWR); cout << "FD Open.\n"; /* 4.4 Establishing Addresses */ // 4.4.1 GPIO Bank Addresses printf("Attempting to map GPIO_1.\nGPIO_1 starts at %X, ends at %X, and has size %X.\n",GPIO_1_START,GPIO_1_END,GPIO_1_SIZE); gpio1_addr = (unsigned int*)mmap(0, GPIO_1_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO_1_START); if (gpio1_addr == MAP_FAILED) { cout << "Unable to map GPIO_1.\n"; printf("Error Value Returned is: %s.\n",strerror(errno)); exit(1); } else { cout << "GPIO_1 mapped successfully.\n"; cout << "GPIO_1 mmap result is: " << gpio1_addr << endl; } printf("Attempting to map GPIO_2.\nGPIO_2 starts at %X, ends at %X, and has size %X.\n",GPIO
    /* 4.5 Establish Pin Modes */
    cout << "Establishing Pin Modes.\n";
    *gpio2_oe_addr = PIN_MONITOR_0;
    cout << "PIN_MONITOR established as INPUT.\n";
START,GPIO
    /* 4.5 Establish Pin Modes */
    cout << "Establishing Pin Modes.\n";
    *gpio2_oe_addr = PIN_MONITOR_0;
    cout << "PIN_MONITOR established as INPUT.\n";
END,GPIO
    /* 4.5 Establish Pin Modes */
    cout << "Establishing Pin Modes.\n";
    *gpio2_oe_addr = PIN_MONITOR_0;
    cout << "PIN_MONITOR established as INPUT.\n";
SIZE); gpio2_addr = (unsigned int*)mmap(0, GPIO
    /* 4.5 Establish Pin Modes */
    cout << "Establishing Pin Modes.\n";
    *gpio2_oe_addr = PIN_MONITOR_0;
    cout << "PIN_MONITOR established as INPUT.\n";
SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, GPIO
    /* 4.5 Establish Pin Modes */
    cout << "Establishing Pin Modes.\n";
    *gpio2_oe_addr = PIN_MONITOR_0;
    cout << "PIN_MONITOR established as INPUT.\n";
START); if (gpio2_addr == MAP_FAILED) { cout << "Unable to map GPIO_2.\n"; printf("Error Value Returned is: %s.\n",strerror(errno)); exit(1); } else { cout << "GPIO_2 mapped successfully.\n"; cout << "GPIO_2 mmap result is: " << gpio2_addr << endl; } cout << "MMAP Complete.\n"; /* 4.4.2 Register Offsets */ /* 4.4.2.1 GPIO1 Registers */ gpio1_oe_addr = gpio1_addr + GPIO_OE; gpio1_dataout_addr = gpio1_addr + GPIO_DATAOUT; gpio1_cleardataout_addr = gpio1_addr + GPIO_CLEARDATAOUT; gpio1_setdataout_addr = gpio1_addr + GPIO_SETDATAOUT; cout << "GPIO 1 Register Addresses Defined.\n"; /* 4.4.2.2 GPIO2 Registers */ gpio2_irqstatus_raw0_addr = gpio2_addr + GPIO_IRQSTATUS_RAW_0; gpio2_irqstatus_raw1_addr = gpio2_addr + GPIO_IRQSTATUS_RAW_1; gpio2_irqstatus_0_addr = gpio2_addr + GPIO_IRQSTATUS_0; gpio2_irqstatus_1_addr = gpio2_addr + GPIO_IRQSTATUS_1; gpio2_irqstatus_set0_addr = gpio2_addr + GPIO_IRQSTATUS_SET_0; gpio2_irqstatus_set1_addr = gpio2_addr + GPIO_IRQSTATUS_SET_1; gpio2_irqstatus_clr0_addr = gpio2_addr + GPIO_IRQSTATUS_CLR_0; gpio2_irqstatus_clr1_addr = gpio2_addr + GPIO_IRQSTATUS_CLR_1; gpio2_irqwaken0_addr = gpio2_addr + GPIO_IRQWAKEN_0; gpio2_irqwaken1_addr = gpio2_addr + GPIO_IRQWAKEN_1; gpio2_oe_addr = gpio2_addr + GPIO_OE; gpio2_datain_addr = gpio2_addr + GPIO_DATAIN; gpio2_dataout_addr = gpio2_addr + GPIO_DATAOUT; gpio2_risingdetect_addr = gpio2_addr + GPIO_RISINGDETECT; gpio2_cleardataout_addr = gpio2_addr + GPIO_CLEARDATAOUT; gpio2_setdataout_addr = gpio2_addr + GPIO_SETDATAOUT; cout << "GPIO 2 Register Addresses Defined.\n"; /* 4.5 Establish Pin Modes */ cout << "Establishing Pin Modes.\n"; *gpio2_oe_addr = PIN_MONITOR_0; cout << "PIN_MONITOR established as INPUT.\n"; *gpio1_oe_addr = PIN_LED_1; cout << "PIN_LED established as OUTPUT.\n"; *gpio2_oe_addr = (*gpio2_oe_addr | PIN_CONFIRM_1); cout << "PIN_CONFIRM established as OUTPUT.\n"; *gpio2_oe_addr = (*gpio2_oe_addr | PIN_RESPONSE_1); cout << "PIN_RESPONSE established as OUTPUT.\n"; cout << "Pin Modes Set.\n"; /* 4.6 Confirm Platform Readiness */ cout << "Checking Platform Readiness.\n"; *gpio1_setdataout_addr = PIN_LED_1; cout << "PIN_LED on.\n"; *gpio2_setdataout_addr = PIN_CONFIRM_1; cout << "PIN_CONFIRM on.\n"; cout << "Platform Ready.\n"; /* 4.7 Primary Experiment Code || Loop */ uint32_t pollDATA[3] = {0,0,0}; uint32_t compare_DATAIN_PIN_MONITOR = 32; uint32_t pollCompare[3] = {compare_DATAIN_PIN_MONITOR,compare_DATAIN_PIN_MONITOR,0}; int run = 1; cout << "Running Experiment.\n"; while (run == 1) { pollDATA[0] = *gpio2_datain_addr; // Read GPIO2 DATAIN if ((pollDATA[0] == pollCompare[0]) && (pollDATA[1] == pollCompare[1]) && (pollDATA[2] == pollCompare[2])) { *gpio2_setdataout_addr = PIN_RESPONSE_1; usleep(1); *gpio2_cleardataout_addr = PIN_RESPONSE_1; } pollDATA[2] = pollDATA[1]; pollDATA[1] = pollDATA[0]; } cout << "Experiment Ended.\n"; /* 4.8 Post-Experiment Procedures */ *gpio1_cleardataout_addr = PIN_LED_1; *gpio2_cleardataout_addr = PIN_CONFIRM_1; *gpio2_cleardataout_addr = PIN_RESPONSE_1; cout << "Program Ended.\n"; return 0; }

Используя выходные сообщения, я определил, что код завершается, когда доходит до первой попытки установки битов:

    /* 4.5 Establish Pin Modes */
    cout << "Establishing Pin Modes.\n";
    *gpio2_oe_addr = PIN_MONITOR_0;
    cout << "PIN_MONITOR established as INPUT.\n";

Я вижу первый результат, показанный в приведенном выше фрагменте («Установка режимов вывода»), но затем код завершается. На основе примеров кодов, которые я видел по этой ссылке - Управление Beaglebone GPIO через / dev / mem - я думаю, что мне может потребоваться сделать что-то вроде этого для всех адресов регистров, которые я собираюсь использовать:

unsigned int reg;
reg = *gpio_reg_addr;
reg = reg & (0xFFFFFF - BIT_SET_COMMAND)
*gpio_reg_addr = reg;

но я не знаю почему. Верно ли это предположение, и если да, то почему? Я прочитал AM335x TRM, но, должно быть, пропустил этот шаг. Любая помощь приветствуется.

Несколько уточняющих заявлений, прежде чем кто-либо попытается глубоко погрузиться в код:

(1) Я новичок в программировании на C / C ++ и Linux. Весь мой предыдущий опыт программирования был в Matlab / Simulink и Labview. Было бы правильно предположить, что я понятия не имею, что делаю.

(2) Этот код должен прочитать значение 32b в * gpio2_datain_addr и, когда он увидит, что 3 последних считанных значения были {HIGH, HIGH, LOW}, установить PIN_RESPONSE на HIGH, приостановить на 1 нс, затем установить PIN_RESPONSE на НИЗКИЙ.

(3) Да, я проверил DeviceTree, и контакты должны быть правильно настроены для операций GPIO.

(4) РЕДАКТИРОВАТЬ: Да, я знаю, что весь мой код в Разделе 1.X правильно называется МАКРОСАМИ или определениями, но я ссылаюсь на них в зависимости от того, для какой цели они служат в коде, в отличие от того, что они номинально называют без- контекст. Это больше помогает мне узнать, что делает конкретная информация, а не то, что она собой представляет. См. Утверждение (1) для дальнейшего объяснения.

(5) РЕДАКТИРОВАТЬ: в соответствии с предложением опилок я реализовал проверку кода выхода для вызовов mmap (). Возвращаемое значение - 1 для обоих вызовов mmap (). Код все еще выходит в том месте, которое я указал ранее в OP, Section 4.5 Establishing Pin Modes. В частности, причиной проблемы является *gpio2_oe_addr = PIN_MONITOR_0.

Для справки, текущий вывод программы (РЕДАКТИРОВАНИЕ) выглядит следующим образом:

FD Open. Attempting to map GPIO_1. GPIO_1 starts at 4804C000, ends at 4804CFFF, and has size FFF. GPIO_1 mapped successfully. GPIO_1 mmap result is: 1 Attempting to map GPIO_2. GPIO_2 starts at 481AA000, ends at 481AAFFF, and has size FFF. GPIO_2 mapped successfully. GPIO_2 mmap result is: 1 MMAP Complete. GPIO_1 Register Addresses Defined. GPIO_2 Register Addresses Defined. Establishing Pin Modes.

Спасибо!


person reroc    schedule 28.04.2016    source источник
comment
код завершается по неизвестной причине - Вы проверяли код выхода? Включили ли вы дамп ядра? Вы пробовали использовать strace ...?   -  person sawdust    schedule 29.04.2016
comment
Ваша программа не утруждает себя проверкой сообщений об ошибках при каждом системном вызове. Это плохое программирование, особенно когда ваша программа работает не так, как ожидалось. Если бы у вас была проверка ошибок, вы, вероятно, узнали бы, что системные вызовы mmap () не были успешными. Кстати, то, что вы называете операциями и командами в разделе 1.x вашей программы, не генерирует код и правильно называется объявлениями и / или определениями макросов.   -  person sawdust    schedule 29.04.2016
comment
Привет опилки, спасибо за ответы. Я не проверял код выхода в mmap (), потому что предполагал, что программа выйдет из строя после выполнения команд mmap () ранее в коде. Вероятно, это просто плохая привычка из моего опыта работы с Matlab. Я выполню эти проверки сейчас, но, если команды mmap () не работают, то есть MAP_FAILED, как мне попытаться это исправить?   -  person reroc    schedule 29.04.2016
comment
Хорошо, я реализовал возврат ошибок, используя errno.h и strerror(). Результатом было то, что mmap() был успешным в обоих случаях, когда он используется в коде.   -  person reroc    schedule 29.04.2016
comment
Код все еще завершается ... - Итак, включите дамп ядра. Возвращаемое значение - 1 для обоих ... - Это не успешные возвраты. (1) Два сопоставления не могут иметь одно и то же значение. (2) Значение 1 не выравнивает страницу; следовательно, это фиктивный адрес. Кстати: вам нужно проверить возврат от всех системных вызовов, например. open (). Размер вашей памяти на единицу меньше; каждому из них нужен + 1. Это все, что я вижу.   -  person sawdust    schedule 29.04.2016