Skip to content

Commit 28890b3

Browse files
committed
Fix crash in Servo library when flash caching is disabled (#898)
1 parent 000e762 commit 28890b3

File tree

2 files changed

+34
-23
lines changed

2 files changed

+34
-23
lines changed

libraries/Servo/src/esp8266/Servo.cpp

+26-11
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const uint32_t c_CycleCompensation = 4; // compensation us to trim adjust for d
2828

2929
struct ServoInfo {
3030
uint8_t pin : 6; // a pin number from 0 to 63
31-
uint8_t isActive : 1; // true if this channel is enabled, pin not pulsed if false
31+
uint8_t isActive : 1; // true if this channel is enabled, pin not pulsed if false
3232
};
3333

3434
struct ServoState {
@@ -57,7 +57,11 @@ static uint8_t s_servoCount = 0; // the total number of attached s_se
5757
// Interrupt handler template method that takes a class that implements
5858
// a standard set of methods for the timer abstraction
5959
//------------------------------------------------------------------------------
60-
template <class T> void Servo_Handler(T* timer)
60+
template <class T>
61+
static void Servo_Handler(T* timer) ICACHE_RAM_ATTR;
62+
63+
template <class T>
64+
static void Servo_Handler(T* timer)
6165
{
6266
uint8_t servoIndex;
6367

@@ -75,7 +79,7 @@ template <class T> void Servo_Handler(T* timer)
7579
}
7680
timer->nextChannel();
7781
}
78-
82+
7983
servoIndex = SERVO_INDEX(timer->timerId(), timer->getCurrentChannel());
8084

8185
if (servoIndex < s_servoCount && timer->getCurrentChannel() < SERVOS_PER_TIMER) {
@@ -96,20 +100,32 @@ template <class T> void Servo_Handler(T* timer)
96100
// at least REFRESH_INTERVAL has elapsed
97101
timer->SetCycleCompare(timer->GetCycleCount() + c_CycleCompensation * 2);
98102
}
99-
103+
100104
timer->setEndOfCycle();
101105
}
102106
}
103107

108+
static void handler0() ICACHE_RAM_ATTR;
109+
static void handler0()
110+
{
111+
Servo_Handler<ServoTimer0>(&s_servoTimer0);
112+
}
113+
114+
static void handler1() ICACHE_RAM_ATTR;
115+
static void handler1()
116+
{
117+
Servo_Handler<ServoTimer1>(&s_servoTimer1);
118+
}
119+
104120
static void initISR(ServoTimerSequence timerId)
105121
{
106122
#if !defined (SERVO_EXCLUDE_TIMER0)
107123
if (timerId == ServoTimerSequence_Timer0)
108-
s_servoTimer0.InitInterrupt([]() {Servo_Handler<ServoTimer0>(&s_servoTimer0); });
124+
s_servoTimer0.InitInterrupt(&handler0);
109125
#endif
110126
#if !defined (SERVO_EXCLUDE_TIMER1)
111127
if (timerId == ServoTimerSequence_Timer1)
112-
s_servoTimer1.InitInterrupt([]() {Servo_Handler<ServoTimer1>(&s_servoTimer1); });
128+
s_servoTimer1.InitInterrupt(&handler1);
113129
#endif
114130
}
115131

@@ -169,13 +185,13 @@ uint8_t Servo::attach(int pin, int minUs, int maxUs)
169185
pinMode(pin, OUTPUT); // set servo pin to output
170186
digitalWrite(pin, LOW);
171187
s_servos[_servoIndex].info.pin = pin;
172-
188+
173189
// keep the min and max within 200-3000 us, these are extreme
174-
// ranges and should support extreme servos while maintaining
190+
// ranges and should support extreme servos while maintaining
175191
// reasonable ranges
176192
_maxUs = max(250, min(3000, maxUs));
177193
_minUs = max(200, min(_maxUs, minUs));
178-
194+
179195
// initialize the timerId if it has not already been initialized
180196
timerId = SERVO_INDEX_TO_TIMER(_servoIndex);
181197
if (!isTimerActive(timerId)) {
@@ -242,5 +258,4 @@ bool Servo::attached()
242258
return s_servos[_servoIndex].info.isActive;
243259
}
244260

245-
#endif
246-
261+
#endif

libraries/Servo/src/esp8266/ServoTimers.h

+8-12
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818

1919
//
2020
// Defines for timer abstractions used with Servo library
21-
//
21+
//
2222
// ServoTimerSequence enumerates the sequence that the timers should be allocated
2323
// ServoTimerSequence_COUNT indicates how many timers are available.
2424
//
@@ -47,7 +47,7 @@ struct ServoTimer0
4747
}
4848

4949

50-
uint32_t usToTicks(uint32_t us) const
50+
uint32_t usToTicks(uint32_t us) const
5151
{
5252
return (clockCyclesPerMicrosecond() * us); // converts microseconds to tick
5353
}
@@ -56,15 +56,15 @@ struct ServoTimer0
5656
return (ticks / clockCyclesPerMicrosecond()); // converts from ticks back to microseconds
5757
}
5858

59-
void InitInterrupt(timercallback handler)
59+
void InitInterrupt(timercallback handler)
6060
{
6161
timer0_isr_init();
6262
timer0_attachInterrupt(handler);
6363
}
6464

6565
void ResetInterrupt() {}; // timer0 doesn't have a clear interrupt
6666

67-
void StopInterrupt()
67+
void StopInterrupt()
6868
{
6969
timer0_detachInterrupt();
7070
}
@@ -74,7 +74,7 @@ struct ServoTimer0
7474
timer0_write(ESP.getCycleCount() + value);
7575
}
7676

77-
void SetCycleCompare(uint32_t value)
77+
void SetCycleCompare(uint32_t value)
7878
{
7979
timer0_write(_cycleStart + value);
8080
}
@@ -96,12 +96,12 @@ struct ServoTimer0
9696
return _currentChannel;
9797
}
9898

99-
void nextChannel()
99+
void nextChannel()
100100
{
101101
_currentChannel++;
102102
}
103103

104-
void setEndOfCycle()
104+
void setEndOfCycle()
105105
{
106106
_currentChannel = -1;
107107
}
@@ -111,7 +111,7 @@ struct ServoTimer0
111111
return (_currentChannel == -1);
112112
}
113113

114-
ServoTimerSequence timerId() const
114+
ServoTimerSequence timerId() const
115115
{
116116
return ServoTimerSequence_Timer0;
117117
}
@@ -221,7 +221,3 @@ struct ServoTimer1
221221
};
222222

223223
#endif
224-
225-
226-
227-

0 commit comments

Comments
 (0)