mirror of
https://github.com/DCC-EX/CommandStation-EX.git
synced 2024-12-23 21:01:25 +01:00
Protect port registers from change during interrupt code in differnet way
This commit is contained in:
parent
84e44df47c
commit
76c5608181
@ -148,11 +148,17 @@ bool MotorDriver::isPWMCapable() {
|
|||||||
void MotorDriver::setPower(POWERMODE mode) {
|
void MotorDriver::setPower(POWERMODE mode) {
|
||||||
bool on=mode==POWERMODE::ON;
|
bool on=mode==POWERMODE::ON;
|
||||||
if (on) {
|
if (on) {
|
||||||
|
noInterrupts();
|
||||||
IODevice::write(powerPin,HIGH);
|
IODevice::write(powerPin,HIGH);
|
||||||
|
interrupts();
|
||||||
if (isProgTrack)
|
if (isProgTrack)
|
||||||
DCCWaveform::progTrack.clearResets();
|
DCCWaveform::progTrack.clearResets();
|
||||||
}
|
}
|
||||||
else IODevice::write(powerPin,LOW);
|
else {
|
||||||
|
noInterrupts();
|
||||||
|
IODevice::write(powerPin,LOW);
|
||||||
|
interrupts();
|
||||||
|
}
|
||||||
powerMode=mode;
|
powerMode=mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -164,10 +170,14 @@ void MotorDriver::setPower(POWERMODE mode) {
|
|||||||
// (HIGH == release brake) and setBrake does
|
// (HIGH == release brake) and setBrake does
|
||||||
// compensate for that.
|
// compensate for that.
|
||||||
//
|
//
|
||||||
void MotorDriver::setBrake(bool on) {
|
void MotorDriver::setBrake(bool on, bool interruptContext) {
|
||||||
if (brakePin == UNUSED_PIN) return;
|
if (brakePin == UNUSED_PIN) return;
|
||||||
if (on ^ invertBrake) setHIGH(fastBrakePin);
|
if (!interruptContext) {noInterrupts();}
|
||||||
else setLOW(fastBrakePin);
|
if (on ^ invertBrake)
|
||||||
|
setHIGH(fastBrakePin);
|
||||||
|
else
|
||||||
|
setLOW(fastBrakePin);
|
||||||
|
if (!interruptContext) {interrupts();}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MotorDriver::canMeasureCurrent() {
|
bool MotorDriver::canMeasureCurrent() {
|
||||||
@ -214,30 +224,18 @@ void MotorDriver::setDCSignal(byte speedcode) {
|
|||||||
if (invertBrake)
|
if (invertBrake)
|
||||||
brake=255-brake;
|
brake=255-brake;
|
||||||
analogWrite(brakePin,brake);
|
analogWrite(brakePin,brake);
|
||||||
// as the port registers can be shadowed to get syncronized DCC signals
|
|
||||||
// we need to take care of that and we have to turn off interrupts during
|
|
||||||
// that time as otherwise setDCCSignal() which is called from interrupt
|
|
||||||
// contect can undo whatever we do here.
|
|
||||||
if (fastSignalPin.shadowinout != NULL) {
|
|
||||||
if (HAVE_PORTA(fastSignalPin.shadowinout == &PORTA)) {
|
if (HAVE_PORTA(fastSignalPin.shadowinout == &PORTA)) {
|
||||||
noInterrupts();
|
|
||||||
HAVE_PORTA(shadowPORTA=PORTA);
|
HAVE_PORTA(shadowPORTA=PORTA);
|
||||||
setSignal(tDir);
|
setSignal(tDir);
|
||||||
HAVE_PORTA(PORTA=shadowPORTA);
|
HAVE_PORTA(PORTA=shadowPORTA);
|
||||||
interrupts();
|
|
||||||
} else if (HAVE_PORTB(fastSignalPin.shadowinout == &PORTB)) {
|
} else if (HAVE_PORTB(fastSignalPin.shadowinout == &PORTB)) {
|
||||||
noInterrupts();
|
|
||||||
HAVE_PORTB(shadowPORTB=PORTB);
|
HAVE_PORTB(shadowPORTB=PORTB);
|
||||||
setSignal(tDir);
|
setSignal(tDir);
|
||||||
HAVE_PORTB(PORTB=shadowPORTB);
|
HAVE_PORTB(PORTB=shadowPORTB);
|
||||||
interrupts();
|
|
||||||
} else if (HAVE_PORTC(fastSignalPin.shadowinout == &PORTC)) {
|
} else if (HAVE_PORTC(fastSignalPin.shadowinout == &PORTC)) {
|
||||||
noInterrupts();
|
|
||||||
HAVE_PORTC(shadowPORTC=PORTC);
|
HAVE_PORTC(shadowPORTC=PORTC);
|
||||||
setSignal(tDir);
|
setSignal(tDir);
|
||||||
HAVE_PORTC(PORTC=shadowPORTC);
|
HAVE_PORTC(PORTC=shadowPORTC);
|
||||||
interrupts();
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
setSignal(tDir);
|
setSignal(tDir);
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,14 @@ class MotorDriver {
|
|||||||
byte current_pin, float senseFactor, unsigned int tripMilliamps, byte faultPin);
|
byte current_pin, float senseFactor, unsigned int tripMilliamps, byte faultPin);
|
||||||
virtual void setPower( POWERMODE mode);
|
virtual void setPower( POWERMODE mode);
|
||||||
virtual POWERMODE getPower() { return powerMode;}
|
virtual POWERMODE getPower() { return powerMode;}
|
||||||
__attribute__((always_inline)) inline void setSignal( bool high) {
|
// as the port registers can be shadowed to get syncronized DCC signals
|
||||||
|
// we need to take care of that and we have to turn off interrupts if
|
||||||
|
// we setSignal() or setBrake() or setPower() during that time as
|
||||||
|
// otherwise the call from interrupt context can undo whatever we do
|
||||||
|
// from outside interrupt
|
||||||
|
virtual void setBrake( bool on, bool interruptContext=false);
|
||||||
|
__attribute__((always_inline)) inline void setSignal( bool high, bool interruptContext=false) {
|
||||||
|
if (!interruptContext) {noInterrupts();}
|
||||||
if (trackPWM) {
|
if (trackPWM) {
|
||||||
DCCTimer::setPWM(signalPin,high);
|
DCCTimer::setPWM(signalPin,high);
|
||||||
}
|
}
|
||||||
@ -119,6 +126,7 @@ class MotorDriver {
|
|||||||
if (dualSignal) setHIGH(fastSignalPin2);
|
if (dualSignal) setHIGH(fastSignalPin2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!interruptContext) {interrupts();}
|
||||||
};
|
};
|
||||||
inline void enableSignal(bool on) {
|
inline void enableSignal(bool on) {
|
||||||
if (on)
|
if (on)
|
||||||
@ -127,7 +135,6 @@ class MotorDriver {
|
|||||||
pinMode(signalPin, INPUT);
|
pinMode(signalPin, INPUT);
|
||||||
};
|
};
|
||||||
inline byte getSignalPin() { return signalPin; };
|
inline byte getSignalPin() { return signalPin; };
|
||||||
virtual void setBrake( bool on);
|
|
||||||
virtual void setDCSignal(byte speedByte);
|
virtual void setDCSignal(byte speedByte);
|
||||||
virtual int getCurrentRaw();
|
virtual int getCurrentRaw();
|
||||||
virtual int getCurrentRawInInterrupt();
|
virtual int getCurrentRawInInterrupt();
|
||||||
|
@ -92,7 +92,7 @@ void TrackManager::setDCCSignal( bool on) {
|
|||||||
HAVE_PORTA(shadowPORTA=PORTA);
|
HAVE_PORTA(shadowPORTA=PORTA);
|
||||||
HAVE_PORTB(shadowPORTB=PORTB);
|
HAVE_PORTB(shadowPORTB=PORTB);
|
||||||
HAVE_PORTC(shadowPORTC=PORTC);
|
HAVE_PORTC(shadowPORTC=PORTC);
|
||||||
APPLY_BY_MODE(TRACK_MODE_MAIN,setSignal(on));
|
APPLY_BY_MODE(TRACK_MODE_MAIN,setSignal(on, true));
|
||||||
HAVE_PORTA(PORTA=shadowPORTA);
|
HAVE_PORTA(PORTA=shadowPORTA);
|
||||||
HAVE_PORTB(PORTB=shadowPORTB);
|
HAVE_PORTB(PORTB=shadowPORTB);
|
||||||
HAVE_PORTC(PORTC=shadowPORTC);
|
HAVE_PORTC(PORTC=shadowPORTC);
|
||||||
@ -110,7 +110,7 @@ void TrackManager::setPROGSignal( bool on) {
|
|||||||
HAVE_PORTA(shadowPORTA=PORTA);
|
HAVE_PORTA(shadowPORTA=PORTA);
|
||||||
HAVE_PORTB(shadowPORTB=PORTB);
|
HAVE_PORTB(shadowPORTB=PORTB);
|
||||||
HAVE_PORTC(shadowPORTC=PORTC);
|
HAVE_PORTC(shadowPORTC=PORTC);
|
||||||
APPLY_BY_MODE(TRACK_MODE_PROG,setSignal(on));
|
APPLY_BY_MODE(TRACK_MODE_PROG,setSignal(on, true));
|
||||||
HAVE_PORTA(PORTA=shadowPORTA);
|
HAVE_PORTA(PORTA=shadowPORTA);
|
||||||
HAVE_PORTB(PORTB=shadowPORTB);
|
HAVE_PORTB(PORTB=shadowPORTB);
|
||||||
HAVE_PORTC(PORTC=shadowPORTC);
|
HAVE_PORTC(PORTC=shadowPORTC);
|
||||||
|
Loading…
Reference in New Issue
Block a user