Browse Source

HAL_ChibiOS: added wait_pin() implementation

c415-sdk
Andrew Tridgell 5 years ago
parent
commit
450871cde1
  1. 71
      libraries/AP_HAL_ChibiOS/GPIO.cpp
  2. 7
      libraries/AP_HAL_ChibiOS/GPIO.h

71
libraries/AP_HAL_ChibiOS/GPIO.cpp

@ -30,6 +30,7 @@ static struct gpio_entry {
AP_HAL::GPIO::irq_handler_fn_t fn; // callback for GPIO interface AP_HAL::GPIO::irq_handler_fn_t fn; // callback for GPIO interface
bool is_input; bool is_input;
uint8_t mode; uint8_t mode;
thread_reference_t thd_wait;
} _gpio_tab[] = HAL_GPIO_PINS; } _gpio_tab[] = HAL_GPIO_PINS;
#define NUM_PINS ARRAY_SIZE(_gpio_tab) #define NUM_PINS ARRAY_SIZE(_gpio_tab)
@ -219,7 +220,7 @@ bool GPIO::attach_interrupt(uint8_t pin,
return _attach_interrupt(g->pal_line, proc, mode); 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; uint32_t chmode = 0;
switch(mode) { switch(mode) {
@ -239,11 +240,9 @@ bool GPIO::_attach_interrupt(ioline_t line, palcallback_t cb, void *p, uint8_t m
break; break;
} }
osalSysLock();
palevent_t *pep = pal_lld_get_line_event(line); palevent_t *pep = pal_lld_get_line_event(line);
if (pep->cb && p != nullptr) { if (pep->cb && p != nullptr) {
// the pad is already being used for a callback // the pad is already being used for a callback
osalSysUnlock();
return false; return false;
} }
@ -254,11 +253,18 @@ bool GPIO::_attach_interrupt(ioline_t line, palcallback_t cb, void *p, uint8_t m
palDisableLineEventI(line); palDisableLineEventI(line);
palSetLineCallbackI(line, cb, p); palSetLineCallbackI(line, cb, p);
palEnableLineEventI(line, chmode); palEnableLineEventI(line, chmode);
osalSysUnlock();
return true; 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) bool GPIO::usb_connected(void)
{ {
return _usb_connected; return _usb_connected;
@ -288,14 +294,14 @@ void DigitalSource::toggle()
palToggleLine(line); palToggleLine(line);
} }
void pal_interrupt_cb(void *arg) static void pal_interrupt_cb(void *arg)
{ {
if (arg != nullptr) { if (arg != nullptr) {
((AP_HAL::Proc)arg)(); ((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(); const uint32_t now = AP_HAL::micros();
@ -309,3 +315,56 @@ void pal_interrupt_cb_functor(void *arg)
} }
(g->fn)(g->pin_num, palReadLine(g->pal_line), now); (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;
}

7
libraries/AP_HAL_ChibiOS/GPIO.h

@ -56,10 +56,17 @@ public:
/* attach interrupt via ioline_t */ /* attach interrupt via ioline_t */
bool _attach_interrupt(ioline_t line, AP_HAL::Proc p, uint8_t mode); bool _attach_interrupt(ioline_t line, AP_HAL::Proc p, uint8_t mode);
/*
block waiting for a pin to change. A timeout of 0 means wait
forever. Return true on pin change, false on timeout
*/
bool wait_pin(uint8_t pin, INTERRUPT_TRIGGER_TYPE mode, uint32_t timeout_us) override;
private: private:
bool _usb_connected; bool _usb_connected;
bool _ext_started; bool _ext_started;
bool _attach_interruptI(ioline_t line, palcallback_t cb, void *p, uint8_t mode);
bool _attach_interrupt(ioline_t line, palcallback_t cb, void *p, uint8_t mode); bool _attach_interrupt(ioline_t line, palcallback_t cb, void *p, uint8_t mode);
#ifdef HAL_PIN_ALT_CONFIG #ifdef HAL_PIN_ALT_CONFIG
void setup_alt_config(void); void setup_alt_config(void);

Loading…
Cancel
Save