timer to setup interrupt quotas for a 100ms period from monitor thread */
| 605 | monitor thread |
| 606 | */ |
| 607 | void GPIO::timer_tick() |
| 608 | { |
| 609 | // allow 100k interrupts/second max for GPIO interrupt sources, which is |
| 610 | // 10k per 100ms call to timer_tick() |
| 611 | #if HAVE_GPIO_PINS |
| 612 | const uint16_t quota = 10000U; |
| 613 | for (uint8_t i=0; i<ARRAY_SIZE(_gpio_tab); i++) { |
| 614 | if (_gpio_tab[i].isr_quota != 1) { |
| 615 | // Reset quota for next tick |
| 616 | _gpio_tab[i].isr_quota = quota; |
| 617 | continue; |
| 618 | } |
| 619 | // we ran out of ISR quota for this pin since the last |
| 620 | // check. This is not really an internal error, but we use |
| 621 | // INTERNAL_ERROR() to get the reporting mechanism |
| 622 | |
| 623 | if (_gpio_tab[i].isr_disabled_ticks == 0) { |
| 624 | #ifndef HAL_NO_UARTDRIVER |
| 625 | GCS_SEND_TEXT(MAV_SEVERITY_ERROR,"ISR flood on pin %u", _gpio_tab[i].pin_num); |
| 626 | #endif |
| 627 | // Only trigger internal error if armed |
| 628 | if (hal.util->get_soft_armed()) { |
| 629 | INTERNAL_ERROR(AP_InternalError::error_t::gpio_isr); |
| 630 | } |
| 631 | } |
| 632 | if (hal.util->get_soft_armed()) { |
| 633 | // Don't start counting until disarmed |
| 634 | _gpio_tab[i].isr_disabled_ticks = 1; |
| 635 | continue; |
| 636 | } |
| 637 | |
| 638 | // Increment disabled ticks, don't wrap |
| 639 | if (_gpio_tab[i].isr_disabled_ticks < UINT8_MAX) { |
| 640 | _gpio_tab[i].isr_disabled_ticks++; |
| 641 | } |
| 642 | |
| 643 | // 100 * 100ms = 10 seconds |
| 644 | const uint8_t ISR_retry_ticks = 100U; |
| 645 | if ((_gpio_tab[i].isr_disabled_ticks > ISR_retry_ticks) && (_gpio_tab[i].fn != nullptr)) { |
| 646 | // Try re-enabling |
| 647 | #ifndef HAL_NO_UARTDRIVER |
| 648 | GCS_SEND_TEXT(MAV_SEVERITY_NOTICE, "Retrying pin %d after ISR flood", _gpio_tab[i].pin_num); |
| 649 | #endif |
| 650 | if (attach_interrupt(_gpio_tab[i].pin_num, _gpio_tab[i].fn, _gpio_tab[i].isr_mode)) { |
| 651 | // Success, reset quota |
| 652 | _gpio_tab[i].isr_quota = quota; |
| 653 | } else { |
| 654 | // Failed, reset disabled count to try again later |
| 655 | _gpio_tab[i].isr_disabled_ticks = 1; |
| 656 | } |
| 657 | } |
| 658 | } |
| 659 | #endif // HAVE_GPIO_PINS |
| 660 | } |
| 661 | |
| 662 | // Check for ISR floods |
| 663 | bool GPIO::arming_checks(size_t buflen, char *buffer) const |
no test coverage detected