1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

Fix crash in Servo library when flash caching is disabled (#898)

This commit is contained in:
Ivan Grokhotkov 2015-10-18 22:30:32 +03:00
parent 000e762af3
commit 28890b39e6
2 changed files with 34 additions and 23 deletions

View File

@ -28,7 +28,7 @@ const uint32_t c_CycleCompensation = 4; // compensation us to trim adjust for d
struct ServoInfo { struct ServoInfo {
uint8_t pin : 6; // a pin number from 0 to 63 uint8_t pin : 6; // a pin number from 0 to 63
uint8_t isActive : 1; // true if this channel is enabled, pin not pulsed if false uint8_t isActive : 1; // true if this channel is enabled, pin not pulsed if false
}; };
struct ServoState { struct ServoState {
@ -57,7 +57,11 @@ static uint8_t s_servoCount = 0; // the total number of attached s_se
// Interrupt handler template method that takes a class that implements // Interrupt handler template method that takes a class that implements
// a standard set of methods for the timer abstraction // a standard set of methods for the timer abstraction
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
template <class T> void Servo_Handler(T* timer) template <class T>
static void Servo_Handler(T* timer) ICACHE_RAM_ATTR;
template <class T>
static void Servo_Handler(T* timer)
{ {
uint8_t servoIndex; uint8_t servoIndex;
@ -75,7 +79,7 @@ template <class T> void Servo_Handler(T* timer)
} }
timer->nextChannel(); timer->nextChannel();
} }
servoIndex = SERVO_INDEX(timer->timerId(), timer->getCurrentChannel()); servoIndex = SERVO_INDEX(timer->timerId(), timer->getCurrentChannel());
if (servoIndex < s_servoCount && timer->getCurrentChannel() < SERVOS_PER_TIMER) { if (servoIndex < s_servoCount && timer->getCurrentChannel() < SERVOS_PER_TIMER) {
@ -96,20 +100,32 @@ template <class T> void Servo_Handler(T* timer)
// at least REFRESH_INTERVAL has elapsed // at least REFRESH_INTERVAL has elapsed
timer->SetCycleCompare(timer->GetCycleCount() + c_CycleCompensation * 2); timer->SetCycleCompare(timer->GetCycleCount() + c_CycleCompensation * 2);
} }
timer->setEndOfCycle(); timer->setEndOfCycle();
} }
} }
static void handler0() ICACHE_RAM_ATTR;
static void handler0()
{
Servo_Handler<ServoTimer0>(&s_servoTimer0);
}
static void handler1() ICACHE_RAM_ATTR;
static void handler1()
{
Servo_Handler<ServoTimer1>(&s_servoTimer1);
}
static void initISR(ServoTimerSequence timerId) static void initISR(ServoTimerSequence timerId)
{ {
#if !defined (SERVO_EXCLUDE_TIMER0) #if !defined (SERVO_EXCLUDE_TIMER0)
if (timerId == ServoTimerSequence_Timer0) if (timerId == ServoTimerSequence_Timer0)
s_servoTimer0.InitInterrupt([]() {Servo_Handler<ServoTimer0>(&s_servoTimer0); }); s_servoTimer0.InitInterrupt(&handler0);
#endif #endif
#if !defined (SERVO_EXCLUDE_TIMER1) #if !defined (SERVO_EXCLUDE_TIMER1)
if (timerId == ServoTimerSequence_Timer1) if (timerId == ServoTimerSequence_Timer1)
s_servoTimer1.InitInterrupt([]() {Servo_Handler<ServoTimer1>(&s_servoTimer1); }); s_servoTimer1.InitInterrupt(&handler1);
#endif #endif
} }
@ -169,13 +185,13 @@ uint8_t Servo::attach(int pin, int minUs, int maxUs)
pinMode(pin, OUTPUT); // set servo pin to output pinMode(pin, OUTPUT); // set servo pin to output
digitalWrite(pin, LOW); digitalWrite(pin, LOW);
s_servos[_servoIndex].info.pin = pin; s_servos[_servoIndex].info.pin = pin;
// keep the min and max within 200-3000 us, these are extreme // keep the min and max within 200-3000 us, these are extreme
// ranges and should support extreme servos while maintaining // ranges and should support extreme servos while maintaining
// reasonable ranges // reasonable ranges
_maxUs = max(250, min(3000, maxUs)); _maxUs = max(250, min(3000, maxUs));
_minUs = max(200, min(_maxUs, minUs)); _minUs = max(200, min(_maxUs, minUs));
// initialize the timerId if it has not already been initialized // initialize the timerId if it has not already been initialized
timerId = SERVO_INDEX_TO_TIMER(_servoIndex); timerId = SERVO_INDEX_TO_TIMER(_servoIndex);
if (!isTimerActive(timerId)) { if (!isTimerActive(timerId)) {
@ -242,5 +258,4 @@ bool Servo::attached()
return s_servos[_servoIndex].info.isActive; return s_servos[_servoIndex].info.isActive;
} }
#endif #endif

View File

@ -18,7 +18,7 @@
// //
// Defines for timer abstractions used with Servo library // Defines for timer abstractions used with Servo library
// //
// ServoTimerSequence enumerates the sequence that the timers should be allocated // ServoTimerSequence enumerates the sequence that the timers should be allocated
// ServoTimerSequence_COUNT indicates how many timers are available. // ServoTimerSequence_COUNT indicates how many timers are available.
// //
@ -47,7 +47,7 @@ public:
} }
uint32_t usToTicks(uint32_t us) const uint32_t usToTicks(uint32_t us) const
{ {
return (clockCyclesPerMicrosecond() * us); // converts microseconds to tick return (clockCyclesPerMicrosecond() * us); // converts microseconds to tick
} }
@ -56,7 +56,7 @@ public:
return (ticks / clockCyclesPerMicrosecond()); // converts from ticks back to microseconds return (ticks / clockCyclesPerMicrosecond()); // converts from ticks back to microseconds
} }
void InitInterrupt(timercallback handler) void InitInterrupt(timercallback handler)
{ {
timer0_isr_init(); timer0_isr_init();
timer0_attachInterrupt(handler); timer0_attachInterrupt(handler);
@ -64,7 +64,7 @@ public:
void ResetInterrupt() {}; // timer0 doesn't have a clear interrupt void ResetInterrupt() {}; // timer0 doesn't have a clear interrupt
void StopInterrupt() void StopInterrupt()
{ {
timer0_detachInterrupt(); timer0_detachInterrupt();
} }
@ -74,7 +74,7 @@ public:
timer0_write(ESP.getCycleCount() + value); timer0_write(ESP.getCycleCount() + value);
} }
void SetCycleCompare(uint32_t value) void SetCycleCompare(uint32_t value)
{ {
timer0_write(_cycleStart + value); timer0_write(_cycleStart + value);
} }
@ -96,12 +96,12 @@ public:
return _currentChannel; return _currentChannel;
} }
void nextChannel() void nextChannel()
{ {
_currentChannel++; _currentChannel++;
} }
void setEndOfCycle() void setEndOfCycle()
{ {
_currentChannel = -1; _currentChannel = -1;
} }
@ -111,7 +111,7 @@ public:
return (_currentChannel == -1); return (_currentChannel == -1);
} }
ServoTimerSequence timerId() const ServoTimerSequence timerId() const
{ {
return ServoTimerSequence_Timer0; return ServoTimerSequence_Timer0;
} }
@ -221,7 +221,3 @@ private:
}; };
#endif #endif