1
0
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:
Harald Barth 2022-08-09 13:12:04 +02:00
parent 84e44df47c
commit 76c5608181
3 changed files with 37 additions and 32 deletions

View File

@ -148,11 +148,17 @@ bool MotorDriver::isPWMCapable() {
void MotorDriver::setPower(POWERMODE mode) {
bool on=mode==POWERMODE::ON;
if (on) {
noInterrupts();
IODevice::write(powerPin,HIGH);
interrupts();
if (isProgTrack)
DCCWaveform::progTrack.clearResets();
}
else IODevice::write(powerPin,LOW);
else {
noInterrupts();
IODevice::write(powerPin,LOW);
interrupts();
}
powerMode=mode;
}
@ -164,10 +170,14 @@ void MotorDriver::setPower(POWERMODE mode) {
// (HIGH == release brake) and setBrake does
// compensate for that.
//
void MotorDriver::setBrake(bool on) {
void MotorDriver::setBrake(bool on, bool interruptContext) {
if (brakePin == UNUSED_PIN) return;
if (on ^ invertBrake) setHIGH(fastBrakePin);
else setLOW(fastBrakePin);
if (!interruptContext) {noInterrupts();}
if (on ^ invertBrake)
setHIGH(fastBrakePin);
else
setLOW(fastBrakePin);
if (!interruptContext) {interrupts();}
}
bool MotorDriver::canMeasureCurrent() {
@ -214,30 +224,18 @@ void MotorDriver::setDCSignal(byte speedcode) {
if (invertBrake)
brake=255-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)) {
noInterrupts();
HAVE_PORTA(shadowPORTA=PORTA);
setSignal(tDir);
HAVE_PORTA(PORTA=shadowPORTA);
interrupts();
} else if (HAVE_PORTB(fastSignalPin.shadowinout == &PORTB)) {
noInterrupts();
HAVE_PORTB(shadowPORTB=PORTB);
setSignal(tDir);
HAVE_PORTB(PORTB=shadowPORTB);
interrupts();
} else if (HAVE_PORTC(fastSignalPin.shadowinout == &PORTC)) {
noInterrupts();
HAVE_PORTC(shadowPORTC=PORTC);
setSignal(tDir);
HAVE_PORTC(PORTC=shadowPORTC);
interrupts();
}
} else {
setSignal(tDir);
}

View File

@ -105,7 +105,14 @@ class MotorDriver {
byte current_pin, float senseFactor, unsigned int tripMilliamps, byte faultPin);
virtual void setPower( POWERMODE mode);
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) {
DCCTimer::setPWM(signalPin,high);
}
@ -119,6 +126,7 @@ class MotorDriver {
if (dualSignal) setHIGH(fastSignalPin2);
}
}
if (!interruptContext) {interrupts();}
};
inline void enableSignal(bool on) {
if (on)
@ -127,7 +135,6 @@ class MotorDriver {
pinMode(signalPin, INPUT);
};
inline byte getSignalPin() { return signalPin; };
virtual void setBrake( bool on);
virtual void setDCSignal(byte speedByte);
virtual int getCurrentRaw();
virtual int getCurrentRawInInterrupt();

View File

@ -92,7 +92,7 @@ void TrackManager::setDCCSignal( bool on) {
HAVE_PORTA(shadowPORTA=PORTA);
HAVE_PORTB(shadowPORTB=PORTB);
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_PORTB(PORTB=shadowPORTB);
HAVE_PORTC(PORTC=shadowPORTC);
@ -110,7 +110,7 @@ void TrackManager::setPROGSignal( bool on) {
HAVE_PORTA(shadowPORTA=PORTA);
HAVE_PORTB(shadowPORTB=PORTB);
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_PORTB(PORTB=shadowPORTB);
HAVE_PORTC(PORTC=shadowPORTC);