Skip to content

Commit

Permalink
[BUG] Ensure ESP32 system timer is valid before use.
Browse files Browse the repository at this point in the history
* Add debug messages & a runtime assert to ensure we correctly allocated a system timer in `IRrecv::enableIRIn()`.
* Limit the max number of the system timer to the appropriate size for the ESP32. ESP32-C3's only have two system timers (0-1), the rest have 4 (0-3).
* Done in such a way it should be correct for future ESP32 models.

Ref: https://docs.espressif.com/projects/arduino-esp32/en/latest/api/timer.html

Fixes #1751
  • Loading branch information
crankyoldgit committed Mar 5, 2022
1 parent ca226a5 commit 03e1f06
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 5 deletions.
14 changes: 11 additions & 3 deletions src/IRrecv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,13 +261,14 @@ static void USE_IRAM_ATTR gpio_intr() {
/// capturing data. (Default: kTimeoutMs)
/// @param[in] save_buffer Use a second (save) buffer to decode from.
/// (Default: false)
/// @param[in] timer_num Nr. of the ESP32 timer to use (0 to 3) (ESP32 Only)
/// @param[in] timer_num Nr. of the ESP32 timer to use. (0 to 3) (ESP32 Only)
/// or (0 to 1) (ESP32-C3)
#if defined(ESP32)
IRrecv::IRrecv(const uint16_t recvpin, const uint16_t bufsize,
const uint8_t timeout, const bool save_buffer,
const uint8_t timer_num) {
// There are only 4 timers. 0 to 3.
_timer_num = std::min(timer_num, (uint8_t)3);
// Ensure we use a valid timer number.
_timer_num = std::min(timer_num, (uint8_t)(SOC_TIMER_GROUP_TOTAL_TIMERS - 1));
#else // ESP32
/// @cond IGNORE
/// Class constructor
Expand Down Expand Up @@ -353,6 +354,13 @@ void IRrecv::enableIRIn(const bool pullup) {
// Initialise the ESP32 timer.
// 80MHz / 80 = 1 uSec granularity.
timer = timerBegin(_timer_num, 80, true);
#ifdef DEBUG
if (timer == NULL) {
DPRINT("FATAL: Unable enable system timer: ");
DPRINTLN((uint16_t)_timer_num);
}
#endif // DEBUG
assert(timer != NULL); // Check we actually got the timer.
// Set the timer so it only fires once, and set it's trigger in uSeconds.
timerAlarmWrite(timer, MS_TO_USEC(params.timeout), ONCE);
// Note: Interrupt needs to be attached before it can be enabled or disabled.
Expand Down
7 changes: 5 additions & 2 deletions src/IRrecv.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,8 +52,11 @@ const uint16_t kMaxTimeoutMs = kRawTick * (UINT16_MAX / MS_TO_USEC(1));
const uint32_t kFnvPrime32 = 16777619UL;
const uint32_t kFnvBasis32 = 2166136261UL;

// Which of the ESP32 timers to use by default. (0-3)
const uint8_t kDefaultESP32Timer = 3;
#ifdef ESP32
// Which of the ESP32 timers to use by default.
// (3 for most ESP32s, 1 for ESP32-C3s)
const uint8_t kDefaultESP32Timer = SOC_TIMER_GROUP_TOTAL_TIMERS - 1;
#endif // ESP32

#if DECODE_AC
// Hitachi AC is the current largest state size.
Expand Down

0 comments on commit 03e1f06

Please sign in to comment.