Для своего проекта я пытаюсь написать код, который (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 GPIOunsigned 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 GPIOunsigned 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 GPIOunsigned int reg;
reg = *gpio_reg_addr;
reg = reg & (0xFFFFFF - BIT_SET_COMMAND)
*gpio_reg_addr = reg;
SIZE (GPIOunsigned int reg;
reg = *gpio_reg_addr;
reg = reg & (0xFFFFFF - BIT_SET_COMMAND)
*gpio_reg_addr = reg;
END - GPIOunsigned 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.
Спасибо!
strace ...
? - person sawdust   schedule 29.04.2016errno.h
иstrerror()
. Результатом было то, чтоmmap()
был успешным в обоих случаях, когда он используется в коде. - person reroc   schedule 29.04.2016+ 1
. Это все, что я вижу. - person sawdust   schedule 29.04.2016