You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
129 lines
3.7 KiB
129 lines
3.7 KiB
#include <AP_HAL/AP_HAL.h> |
|
|
|
#if CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_PXF || \ |
|
CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_ERLEBOARD || \ |
|
CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BBBMINI || \ |
|
CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BLUE || \ |
|
CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_POCKET |
|
|
|
#include "GPIO.h" |
|
#include <stdio.h> |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <errno.h> |
|
#include <unistd.h> |
|
#include <fcntl.h> |
|
#include <poll.h> |
|
#include <sys/mman.h> |
|
#include <sys/stat.h> |
|
|
|
#define LOW 0 |
|
#define HIGH 1 |
|
|
|
using namespace Linux; |
|
|
|
GPIO_BBB::GPIO_BBB() |
|
{} |
|
|
|
void GPIO_BBB::init() |
|
{ |
|
#if LINUX_GPIO_NUM_BANKS == 4 |
|
int mem_fd; |
|
|
|
/* open /dev/mem */ |
|
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC|O_CLOEXEC)) < 0) { |
|
printf("can't open /dev/mem \n"); |
|
exit (-1); |
|
} |
|
|
|
/* |
|
Enable all GPIO clocks |
|
Without this, access to deactivated banks (i.e. those with no clock source set up) will (logically) fail with SIGBUS |
|
*/ |
|
volatile unsigned *cm_per = (volatile unsigned *)mmap(0, CM_PER_BASE_SIZE, PROT_READ|PROT_WRITE, |
|
MAP_SHARED, mem_fd, CM_PER_BASE); |
|
if ((char *)cm_per == MAP_FAILED) { |
|
AP_HAL::panic("unable to map CM_PER registers"); |
|
} |
|
off_t cm_offsets[LINUX_GPIO_NUM_BANKS-1] = { CM_PER_GPIO1_CLKCTRL, CM_PER_GPIO2_CLKCTRL, CM_PER_GPIO3_CLKCTRL }; |
|
for (uint8_t i=0; i<LINUX_GPIO_NUM_BANKS-1; i++) { |
|
unsigned reg_value = *(cm_per + cm_offsets[i]); |
|
*(cm_per + cm_offsets[i]) = (reg_value & ~0b11) | 0b10; |
|
} |
|
munmap((void *)cm_per, CM_PER_BASE_SIZE); |
|
|
|
/* mmap GPIO */ |
|
off_t offsets[LINUX_GPIO_NUM_BANKS] = { GPIO0_BASE, GPIO1_BASE, GPIO2_BASE, GPIO3_BASE }; |
|
for (uint8_t i=0; i<LINUX_GPIO_NUM_BANKS; i++) { |
|
gpio_bank[i].base = (volatile unsigned *)mmap(0, GPIO_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, mem_fd, offsets[i]); |
|
if ((char *)gpio_bank[i].base == MAP_FAILED) { |
|
AP_HAL::panic("unable to map GPIO bank"); |
|
} |
|
gpio_bank[i].oe = gpio_bank[i].base + GPIO_OE; |
|
gpio_bank[i].in = gpio_bank[i].base + GPIO_IN; |
|
gpio_bank[i].out = gpio_bank[i].base + GPIO_OUT; |
|
} |
|
|
|
close(mem_fd); |
|
#endif // LINUX_GPIO_NUM_BANKS |
|
} |
|
|
|
void GPIO_BBB::pinMode(uint8_t pin, uint8_t output) |
|
{ |
|
uint8_t bank = pin/32; |
|
uint8_t bankpin = pin & 0x1F; |
|
if (bank >= LINUX_GPIO_NUM_BANKS) { |
|
return; |
|
} |
|
if (output == HAL_GPIO_INPUT) { |
|
*gpio_bank[bank].oe |= (1U<<bankpin); |
|
} else { |
|
*gpio_bank[bank].oe &= ~(1U<<bankpin); |
|
} |
|
} |
|
|
|
uint8_t GPIO_BBB::read(uint8_t pin) { |
|
|
|
uint8_t bank = pin/32; |
|
uint8_t bankpin = pin & 0x1F; |
|
if (bank >= LINUX_GPIO_NUM_BANKS) { |
|
return 0; |
|
} |
|
return *gpio_bank[bank].in & (1U<<bankpin) ? HIGH : LOW; |
|
|
|
} |
|
|
|
void GPIO_BBB::write(uint8_t pin, uint8_t value) |
|
{ |
|
uint8_t bank = pin/32; |
|
uint8_t bankpin = pin & 0x1F; |
|
if (bank >= LINUX_GPIO_NUM_BANKS) { |
|
return; |
|
} |
|
if (value == LOW) { |
|
*gpio_bank[bank].out &= ~(1U<<bankpin); |
|
} else { |
|
*gpio_bank[bank].out |= 1U<<bankpin; |
|
} |
|
} |
|
|
|
void GPIO_BBB::toggle(uint8_t pin) |
|
{ |
|
write(pin, !read(pin)); |
|
} |
|
|
|
/* Alternative interface: */ |
|
AP_HAL::DigitalSource* GPIO_BBB::channel(uint16_t n) { |
|
return new DigitalSource(n); |
|
} |
|
|
|
bool GPIO_BBB::usb_connected(void) |
|
{ |
|
return false; |
|
} |
|
|
|
#endif // CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_PXF || |
|
// CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_ERLEBOARD || |
|
// CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BBBMINI || |
|
// CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_BLUE || |
|
// CONFIG_HAL_BOARD_SUBTYPE == HAL_BOARD_SUBTYPE_LINUX_POCKET
|
|
|