在C中的AM335x上启用GPIO

在C中的AM335x上启用GPIO,c,gpio,beagleboneblack,C,Gpio,Beagleboneblack,我有以下函数initGPIO。目标是使用am335x在beaglebone上启用GPIOs 0、1和2。如何将相应的GPIO设置启用到头文件中给定的reg_GPIO?我有头文件GPIO.h,其中包含GPIO的编号、寄存器编号和寄存器结构。我已尝试在函数initGPIO中设置GPIO。这有意义吗 gpio.h #include <stdint.h> #include <stdbool.h> #define GPIO0 0 /*!< GPIO 0 number */

我有以下函数initGPIO。目标是使用am335x在beaglebone上启用GPIOs 0、1和2。如何将相应的GPIO设置启用到头文件中给定的reg_GPIO?我有头文件GPIO.h,其中包含GPIO的编号、寄存器编号和寄存器结构。我已尝试在函数initGPIO中设置GPIO。这有意义吗

gpio.h

#include <stdint.h>
#include <stdbool.h>

#define GPIO0 0  /*!< GPIO 0 number */
#define GPIO1 1 /*!< GPIO 1 number */
#define GPIO2 2 /*!< GPIO 2 number */
#define GPIO3 3 /*!< GPIO 3 number */

// Base address for each gpio hardware module.
#define GPIO0_REG  0x44E07000  //<! gpio0 hardware module address.
#define GPIO1_REG  0x4804C000  //<! gpio1 hardware module address.
#define GPIO2_REG  0x481AC000  //<! gpio2 hardware module address.
#define GPIO3_REG  0x481AE000  //<! gpio3 hardware module address.

// Register Structure
typedef struct
{
    volatile uint32_t irqstatus_set_0;   // Offset 0x34 - Enables specific interrupt event to trigger.
    volatile uint32_t irqstatus_set_1;   // Offset 0x38 - Enables specific interrupt event to trigger.
    volatile uint32_t irqwaken_0;        // Offset 0x44 - Enables wakeup events on an interrupt.
    volatile uint32_t irqwaken_1;        // Offset 0x48 - Enables wakeup events on an interrupt.
    volatile uint32_t ctrl;  // Offset 0x130 - Controls clock gating functionality, i.e. enables module.
    volatile uint32_t oe; // Offset 0x134 – Output Enable pin (clear bit to 0) output capability.
    volatile uint32_t datain;            // Offset 0x138 - Registers data read from the GPIO pins.
    volatile uint32_t dataout;           // Offset 0x13c - Sets value of GPIO output pins.
    volatile uint32_t cleardataout;      // Offset 0x190 - Clears to 0 bits in dataout
    volatile uint32_t setdataout;        // Offset 0x194 - Sets to 1 bits in dataout
} GPIO_REGS;


void initGPIO();

#包括
#包括
#定义GPIO0/*!
/*!
 * \brief Initialize GPIOs.
 *
 * Enables GPIO0, GPIO1, and GPIO2 (GPIO3 not used in IDP. Also configures the output pins
 * used in the IDP to control relays and address the ADC's on relays.
 *
 *****************************************************************************************/
void initGPIO()
{

    //enable GPIOs
    GPIO_REGS gpio_regs;
    //might need to change ctrl

    gpio_regs.datain |= (GPIO0 << GPIO0_REG  );
    gpio_regs.datain |= (GPIO1 << GPIO1_REG  );
    gpio_regs.datain |= (GPIO2 << GPIO2_REG  );
}
/*!
*\brief初始化GPIOs。
*
*启用GPIO0、GPIO1和GPIO2(IDP中未使用GPIO3)。还配置输出引脚
*在IDP中用于控制继电器和寻址继电器上的ADC。
*
*****************************************************************************************/
void initGPIO()
{
//启用GPIOs
GPIO_REGS GPIO_REGS;
//可能需要更改ctrl键

gpio_regs.datain|=(GPIO0默认情况下,Beaglebones随Debian Linux提供。除非您决定放弃该功能,否则内核有一个gpio驱动程序,该驱动程序假定控制所有gpio。您不应尝试直接访问原始gpio寄存器,而应与内核驱动程序对话。最简单的方法是安装
libgpiod
(默认情况下可安装在最近的Beagles上)并调用其API。

默认情况下,Beaglebones随Debian Linux提供。除非您决定放弃该功能,否则内核有一个GPIO驱动程序,该驱动程序假定控制所有GPIO。您不应尝试直接访问原始GPIO寄存器,而应与内核驱动程序对话。最简单的方法是安装
libgpiod
(默认情况下可能安装在最新的Beagles上)并调用其API。

对于裸骨平台,可以使用您执行类似操作来访问硬件地址:

volatile GPIO_REGS* gpio1_regs = (GPIO_REGS*)0x44E07000;
volatile GPIO_REGS* gpio2_regs = (GPIO_REGS*)0x4804C000;
现在您的代码也没有这样做,但我假设这就是您的意思。 除了操作系统之外,用户空间应用程序中的内存偏移量不会一对一映射到硬件地址偏移量,这根本不起作用

如果您想直接注册访问类似的内容,您必须使用
/dev/mem
进行类似内存映射的操作,或者如果您的平台支持它,
/dev/gpiomem
(我知道Raspberry Pi支持这一点,我不确定BBB是否支持)。这将检查是否允许您访问所需的硬件地址范围,并确保地址范围在您的用户空间中正确映射

例如:

/* open /dev/mem */
int fd = open("/dev/mem", O_RDWR|O_SYNC);
if (fd >= 0) {
    /* mmap GPIO */
    volatile GPIO_REGS* gpio1_regs = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x44E07000);
    close(fd); /* No need to keep fd open after mmap */

    /* Check for MAP_FAILED error */
    if (gpio1_regs != (GPIO_REGS*)-1) {
        /* Do whatever */
(mmap的最后一个参数是放置硬件地址的位置,在本例中我使用0x44E07000。)

如需进一步阅读,另请参阅:


对于裸骨平台,您可以执行以下操作来访问硬件地址:

volatile GPIO_REGS* gpio1_regs = (GPIO_REGS*)0x44E07000;
volatile GPIO_REGS* gpio2_regs = (GPIO_REGS*)0x4804C000;
现在您的代码也没有这样做,但我假设这就是您的意思。 除了操作系统之外,用户空间应用程序中的内存偏移量不会一对一映射到硬件地址偏移量,这根本不起作用

如果您想直接注册访问类似的内容,您必须使用
/dev/mem
进行类似内存映射的操作,或者如果您的平台支持它,
/dev/gpiomem
(我知道Raspberry Pi支持这一点,我不确定BBB是否支持)。这将检查是否允许您访问所需的硬件地址范围,并确保地址范围在您的用户空间中正确映射

例如:

/* open /dev/mem */
int fd = open("/dev/mem", O_RDWR|O_SYNC);
if (fd >= 0) {
    /* mmap GPIO */
    volatile GPIO_REGS* gpio1_regs = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x44E07000);
    close(fd); /* No need to keep fd open after mmap */

    /* Check for MAP_FAILED error */
    if (gpio1_regs != (GPIO_REGS*)-1) {
        /* Do whatever */
(mmap的最后一个参数是放置硬件地址的位置,在本例中我使用0x44E07000。)

如需进一步阅读,另请参阅:


windows对应的dev/mem是什么?对于windows,这是内存映射IO访问的一个很好的起点:我对你的问题很感兴趣,我尽可能地搜索,但没有找到任何人成功运行windows(我假设windows IoT?!)在Beaglebone Black上,那你为什么要求Windows使用/dev/mem替代方案?Windows对应的dev/mem是什么?对于Windows,这是内存映射IO访问的一个很好的起点:对你的问题很感兴趣,我尽可能地搜索,但我没有找到任何人成功运行Windows(我假设Windows IoT?!)在Beaglebone Black上,那么你为什么要求Windows使用/dev/mem替代方案?是关于裸机还是假设操作系统?如果后者为真,那是哪个操作系统?更新标签!是关于裸机还是假设操作系统?如果后者为真,那是哪个操作系统?更新标签!