|
|
|
@ -30,6 +30,7 @@ static struct gpio_entry {
@@ -30,6 +30,7 @@ static struct gpio_entry {
|
|
|
|
|
AP_HAL::GPIO::irq_handler_fn_t fn; // callback for GPIO interface
|
|
|
|
|
bool is_input; |
|
|
|
|
uint8_t mode; |
|
|
|
|
thread_reference_t thd_wait; |
|
|
|
|
} _gpio_tab[] = HAL_GPIO_PINS; |
|
|
|
|
|
|
|
|
|
#define NUM_PINS ARRAY_SIZE(_gpio_tab) |
|
|
|
@ -219,7 +220,7 @@ bool GPIO::attach_interrupt(uint8_t pin,
@@ -219,7 +220,7 @@ bool GPIO::attach_interrupt(uint8_t pin,
|
|
|
|
|
return _attach_interrupt(g->pal_line, proc, mode); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool GPIO::_attach_interrupt(ioline_t line, palcallback_t cb, void *p, uint8_t mode) |
|
|
|
|
bool GPIO::_attach_interruptI(ioline_t line, palcallback_t cb, void *p, uint8_t mode) |
|
|
|
|
{ |
|
|
|
|
uint32_t chmode = 0; |
|
|
|
|
switch(mode) { |
|
|
|
@ -239,11 +240,9 @@ bool GPIO::_attach_interrupt(ioline_t line, palcallback_t cb, void *p, uint8_t m
@@ -239,11 +240,9 @@ bool GPIO::_attach_interrupt(ioline_t line, palcallback_t cb, void *p, uint8_t m
|
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
osalSysLock(); |
|
|
|
|
palevent_t *pep = pal_lld_get_line_event(line); |
|
|
|
|
if (pep->cb && p != nullptr) { |
|
|
|
|
// the pad is already being used for a callback
|
|
|
|
|
osalSysUnlock(); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -254,11 +253,18 @@ bool GPIO::_attach_interrupt(ioline_t line, palcallback_t cb, void *p, uint8_t m
@@ -254,11 +253,18 @@ bool GPIO::_attach_interrupt(ioline_t line, palcallback_t cb, void *p, uint8_t m
|
|
|
|
|
palDisableLineEventI(line); |
|
|
|
|
palSetLineCallbackI(line, cb, p); |
|
|
|
|
palEnableLineEventI(line, chmode); |
|
|
|
|
osalSysUnlock(); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool GPIO::_attach_interrupt(ioline_t line, palcallback_t cb, void *p, uint8_t mode) |
|
|
|
|
{ |
|
|
|
|
osalSysLock(); |
|
|
|
|
bool ret = _attach_interruptI(line, cb, p, mode); |
|
|
|
|
osalSysUnlock(); |
|
|
|
|
return ret; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool GPIO::usb_connected(void) |
|
|
|
|
{ |
|
|
|
|
return _usb_connected; |
|
|
|
@ -288,14 +294,14 @@ void DigitalSource::toggle()
@@ -288,14 +294,14 @@ void DigitalSource::toggle()
|
|
|
|
|
palToggleLine(line); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void pal_interrupt_cb(void *arg) |
|
|
|
|
static void pal_interrupt_cb(void *arg) |
|
|
|
|
{ |
|
|
|
|
if (arg != nullptr) { |
|
|
|
|
((AP_HAL::Proc)arg)(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void pal_interrupt_cb_functor(void *arg) |
|
|
|
|
static void pal_interrupt_cb_functor(void *arg) |
|
|
|
|
{ |
|
|
|
|
const uint32_t now = AP_HAL::micros(); |
|
|
|
|
|
|
|
|
@ -309,3 +315,56 @@ void pal_interrupt_cb_functor(void *arg)
@@ -309,3 +315,56 @@ void pal_interrupt_cb_functor(void *arg)
|
|
|
|
|
} |
|
|
|
|
(g->fn)(g->pin_num, palReadLine(g->pal_line), now); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
handle interrupt from pin change for wait_pin() |
|
|
|
|
*/ |
|
|
|
|
static void pal_interrupt_wait(void *arg) |
|
|
|
|
{ |
|
|
|
|
osalSysLockFromISR(); |
|
|
|
|
struct gpio_entry *g = (gpio_entry *)arg; |
|
|
|
|
if (g == nullptr || g->thd_wait == nullptr) { |
|
|
|
|
osalSysUnlockFromISR(); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
osalThreadResumeI(&g->thd_wait, MSG_OK); |
|
|
|
|
osalSysUnlockFromISR(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
block waiting for a pin to change. A timeout of 0 means wait |
|
|
|
|
forever. Return true on pin change, false on timeout |
|
|
|
|
*/ |
|
|
|
|
bool GPIO::wait_pin(uint8_t pin, INTERRUPT_TRIGGER_TYPE mode, uint32_t timeout_us) |
|
|
|
|
{ |
|
|
|
|
struct gpio_entry *g = gpio_by_pin_num(pin); |
|
|
|
|
if (!g) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
osalSysLock(); |
|
|
|
|
if (g->thd_wait) { |
|
|
|
|
// only allow single waiter
|
|
|
|
|
osalSysUnlock(); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
g->thd_wait = chThdGetSelfX(); |
|
|
|
|
|
|
|
|
|
if (!_attach_interruptI(g->pal_line, |
|
|
|
|
palcallback_t(pal_interrupt_wait), |
|
|
|
|
g, |
|
|
|
|
mode)) { |
|
|
|
|
g->thd_wait = nullptr; |
|
|
|
|
osalSysUnlock(); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
msg_t msg = osalThreadSuspendTimeoutS(&g->thd_wait, TIME_US2I(timeout_us)); |
|
|
|
|
g->thd_wait = nullptr; |
|
|
|
|
_attach_interruptI(g->pal_line, |
|
|
|
|
palcallback_t(nullptr), |
|
|
|
|
g, |
|
|
|
|
mode); |
|
|
|
|
osalSysUnlock(); |
|
|
|
|
return msg != MSG_TIMEOUT; |
|
|
|
|
} |
|
|
|
|