2013-12-30 19:00:04 -04:00
|
|
|
#include <AP_HAL.h>
|
|
|
|
|
2014-07-06 23:03:26 -03:00
|
|
|
#if CONFIG_HAL_BOARD == HAL_BOARD_LINUX
|
2013-09-22 03:01:24 -03:00
|
|
|
|
|
|
|
#include "GPIO.h"
|
2014-07-13 20:20:47 -03:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <poll.h>
|
2014-05-31 11:24:12 -03:00
|
|
|
#include <sys/mman.h>
|
|
|
|
#include <sys/stat.h>
|
2013-09-22 03:01:24 -03:00
|
|
|
|
|
|
|
using namespace Linux;
|
|
|
|
|
2014-06-04 05:44:57 -03:00
|
|
|
static const AP_HAL::HAL& hal = AP_HAL_BOARD_DRIVER;
|
2013-09-22 03:01:24 -03:00
|
|
|
LinuxGPIO::LinuxGPIO()
|
|
|
|
{}
|
|
|
|
|
|
|
|
void LinuxGPIO::init()
|
2014-07-13 20:20:47 -03:00
|
|
|
{
|
2014-07-13 19:44:59 -03:00
|
|
|
#if LINUX_GPIO_NUM_BANKS == 4
|
2014-05-31 11:24:12 -03:00
|
|
|
int mem_fd;
|
|
|
|
// Enable all GPIO banks
|
|
|
|
// Without this, access to deactivated banks (i.e. those with no clock source set up) will (logically) fail with SIGBUS
|
|
|
|
// Idea taken from https://groups.google.com/forum/#!msg/beagleboard/OYFp4EXawiI/Mq6s3sg14HoJ
|
2014-06-04 05:44:57 -03:00
|
|
|
|
|
|
|
uint8_t bank_enable[3] = { 5, 65, 105 };
|
|
|
|
int export_fd = open("/sys/class/gpio/export", O_WRONLY);
|
|
|
|
if (export_fd == -1) {
|
|
|
|
hal.scheduler->panic("unable to open /sys/class/gpio/export");
|
|
|
|
}
|
|
|
|
for (uint8_t i=0; i<3; i++) {
|
|
|
|
dprintf(export_fd, "%u\n", (unsigned)bank_enable[i]);
|
|
|
|
}
|
|
|
|
close(export_fd);
|
|
|
|
|
2014-05-31 11:24:12 -03:00
|
|
|
|
|
|
|
/* open /dev/mem */
|
|
|
|
if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
|
|
|
|
printf("can't open /dev/mem \n");
|
|
|
|
exit (-1);
|
2014-07-13 20:20:47 -03:00
|
|
|
}
|
|
|
|
|
2014-05-31 11:24:12 -03:00
|
|
|
/* mmap GPIO */
|
2014-06-04 05:44:57 -03:00
|
|
|
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) {
|
|
|
|
hal.scheduler->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;
|
2014-07-13 20:20:47 -03:00
|
|
|
}
|
|
|
|
|
2014-05-31 11:24:12 -03:00
|
|
|
close(mem_fd);
|
2014-07-13 19:44:59 -03:00
|
|
|
#endif // LINUX_GPIO_NUM_BANKS
|
2014-07-13 20:20:47 -03:00
|
|
|
}
|
2013-09-22 03:01:24 -03:00
|
|
|
|
|
|
|
void LinuxGPIO::pinMode(uint8_t pin, uint8_t output)
|
2014-07-13 20:20:47 -03:00
|
|
|
{
|
2014-06-04 05:44:57 -03:00
|
|
|
uint8_t bank = pin/32;
|
|
|
|
uint8_t bankpin = pin & 0x1F;
|
|
|
|
if (bank >= LINUX_GPIO_NUM_BANKS) {
|
|
|
|
return;
|
2014-05-31 11:24:12 -03:00
|
|
|
}
|
2014-06-04 14:18:10 -03:00
|
|
|
if (output == HAL_GPIO_INPUT) {
|
2014-06-04 05:44:57 -03:00
|
|
|
*gpio_bank[bank].oe |= (1U<<bankpin);
|
|
|
|
} else {
|
|
|
|
*gpio_bank[bank].oe &= ~(1U<<bankpin);
|
2014-07-13 20:20:47 -03:00
|
|
|
}
|
|
|
|
}
|
2014-07-13 19:44:59 -03:00
|
|
|
|
2013-09-22 03:01:24 -03:00
|
|
|
int8_t LinuxGPIO::analogPinToDigitalPin(uint8_t pin)
|
|
|
|
{
|
2014-07-13 20:20:47 -03:00
|
|
|
return -1;
|
2013-09-22 03:01:24 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t LinuxGPIO::read(uint8_t pin) {
|
2014-07-13 20:20:47 -03:00
|
|
|
|
2014-06-04 05:44:57 -03:00
|
|
|
uint8_t bank = pin/32;
|
|
|
|
uint8_t bankpin = pin & 0x1F;
|
|
|
|
if (bank >= LINUX_GPIO_NUM_BANKS) {
|
|
|
|
return 0;
|
2014-07-13 20:20:47 -03:00
|
|
|
}
|
2014-06-04 05:44:57 -03:00
|
|
|
return *gpio_bank[bank].in & (1U<<bankpin) ? HIGH : LOW;
|
2014-07-13 20:20:47 -03:00
|
|
|
|
2013-09-22 03:01:24 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
void LinuxGPIO::write(uint8_t pin, uint8_t value)
|
2014-07-13 20:20:47 -03:00
|
|
|
{
|
2014-06-04 05:44:57 -03:00
|
|
|
uint8_t bank = pin/32;
|
|
|
|
uint8_t bankpin = pin & 0x1F;
|
|
|
|
if (bank >= LINUX_GPIO_NUM_BANKS) {
|
|
|
|
return;
|
2014-05-31 11:24:12 -03:00
|
|
|
}
|
2014-06-04 05:44:57 -03:00
|
|
|
if (value == LOW) {
|
|
|
|
*gpio_bank[bank].out &= ~(1U<<bankpin);
|
|
|
|
} else {
|
|
|
|
*gpio_bank[bank].out |= 1U<<bankpin;
|
2014-07-13 20:20:47 -03:00
|
|
|
}
|
|
|
|
}
|
2013-09-22 03:01:24 -03:00
|
|
|
|
|
|
|
void LinuxGPIO::toggle(uint8_t pin)
|
2014-07-13 20:20:47 -03:00
|
|
|
{
|
|
|
|
write(pin, !read(pin));
|
|
|
|
}
|
2013-09-22 03:01:24 -03:00
|
|
|
|
|
|
|
/* Alternative interface: */
|
|
|
|
AP_HAL::DigitalSource* LinuxGPIO::channel(uint16_t n) {
|
2014-05-25 02:50:18 -03:00
|
|
|
return new LinuxDigitalSource(n);
|
2013-09-22 03:01:24 -03:00
|
|
|
}
|
|
|
|
|
|
|
|
/* Interrupt interface: */
|
2014-06-04 05:44:57 -03:00
|
|
|
bool LinuxGPIO::attach_interrupt(uint8_t interrupt_num, AP_HAL::Proc p, uint8_t mode)
|
|
|
|
{
|
2013-09-22 03:01:24 -03:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool LinuxGPIO::usb_connected(void)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
LinuxDigitalSource::LinuxDigitalSource(uint8_t v) :
|
|
|
|
_v(v)
|
2014-05-25 02:50:18 -03:00
|
|
|
{
|
2014-06-04 05:44:57 -03:00
|
|
|
|
2014-05-25 02:50:18 -03:00
|
|
|
}
|
2013-09-22 03:01:24 -03:00
|
|
|
|
|
|
|
void LinuxDigitalSource::mode(uint8_t output)
|
2014-05-25 02:50:18 -03:00
|
|
|
{
|
2014-06-04 05:44:57 -03:00
|
|
|
hal.gpio->pinMode(_v, output);
|
2014-05-25 02:50:18 -03:00
|
|
|
}
|
2013-09-22 03:01:24 -03:00
|
|
|
|
2014-06-04 05:44:57 -03:00
|
|
|
uint8_t LinuxDigitalSource::read()
|
|
|
|
{
|
|
|
|
return hal.gpio->read(_v);
|
2013-09-22 03:01:24 -03:00
|
|
|
}
|
|
|
|
|
2014-06-04 05:44:57 -03:00
|
|
|
void LinuxDigitalSource::write(uint8_t value)
|
|
|
|
{
|
|
|
|
return hal.gpio->write(_v,value);
|
2013-09-22 03:01:24 -03:00
|
|
|
}
|
|
|
|
|
2014-06-04 05:44:57 -03:00
|
|
|
void LinuxDigitalSource::toggle()
|
|
|
|
{
|
2014-05-25 02:50:18 -03:00
|
|
|
write(!read());
|
2013-09-22 03:01:24 -03:00
|
|
|
}
|
2013-12-30 19:00:04 -04:00
|
|
|
|
|
|
|
#endif // CONFIG_HAL_BOARD
|