From 49e4bf10dcbbea8ce389da7c453b768bb3095b1e Mon Sep 17 00:00:00 2001 From: Claudio Indellicati <c.indellicati@arduino.cc> Date: Tue, 24 Mar 2015 17:38:35 +0100 Subject: [PATCH] Added missing synchronization code to analogWrite(). --- cores/arduino/wiring_analog.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/cores/arduino/wiring_analog.c b/cores/arduino/wiring_analog.c index 6cd6abe6..ec911de6 100644 --- a/cores/arduino/wiring_analog.c +++ b/cores/arduino/wiring_analog.c @@ -42,6 +42,18 @@ static void syncDAC() { ; } +// Wait for synchronization of registers between the clock domains +static __inline__ void syncTC_8(Tc* TCx) __attribute__((always_inline, unused)); +static void syncTC_8(Tc* TCx) { + while (TCx->COUNT8.STATUS.bit.SYNCBUSY); +} + +// Wait for synchronization of registers between the clock domains +static __inline__ void syncTCC(Tcc* TCCx) __attribute__((always_inline, unused)); +static void syncTCC(Tcc* TCCx) { + while (TCCx->SYNCBUSY.reg & TCC_SYNCBUSY_MASK); +} + void analogReadResolution( int res ) { _readResolution = res ; @@ -236,8 +248,6 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue ) case 1: // TCC1 // Enable GCLK for TCC0 and TCC1 (timer counter input clock) GCLK->CLKCTRL.reg = (uint16_t) (GCLK_CLKCTRL_CLKEN | GCLK_CLKCTRL_GEN_GCLK0 | GCLK_CLKCTRL_ID( GCM_TCC0_TCC1 )) ; - - while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ; break ; case 2: // TCC2 @@ -259,6 +269,8 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue ) break ; } + while ( GCLK->STATUS.bit.SYNCBUSY == 1 ) ; + ulValue = mapResolution(ulValue, _writeResolution, 8); // Set PORT @@ -268,30 +280,39 @@ void analogWrite( uint32_t ulPin, uint32_t ulValue ) // Disable TCx TCx->COUNT8.CTRLA.reg &= ~TC_CTRLA_ENABLE; + syncTC_8(TCx); // Set Timer counter Mode to 8 bits TCx->COUNT8.CTRLA.reg |= TC_CTRLA_MODE_COUNT8; // Set TCx as normal PWM TCx->COUNT8.CTRLA.reg |= TC_CTRLA_WAVEGEN_NPWM; // Set TCx in waveform mode Normal PWM TCx->COUNT8.CC[Channelx].reg = (uint8_t) ulValue; + syncTC_8(TCx); // Set PER to maximum counter value (resolution : 0xFF) TCx->COUNT8.PER.reg = 0xFF; + syncTC_8(TCx); // Enable TCx TCx->COUNT8.CTRLA.reg |= TC_CTRLA_ENABLE; + syncTC_8(TCx); } else { // -- Configure TCC // Disable TCCx TCCx->CTRLA.reg &= ~TCC_CTRLA_ENABLE; + syncTCC(TCCx); // Set TCx as normal PWM TCCx->WAVE.reg |= TCC_WAVE_WAVEGEN_NPWM; + syncTCC(TCCx); // Set TCx in waveform mode Normal PWM TCCx->CC[Channelx].reg = (uint32_t)ulValue; + syncTCC(TCCx); // Set PER to maximum counter value (resolution : 0xFF) TCCx->PER.reg = 0xFF; + syncTCC(TCCx); // Enable TCCx TCCx->CTRLA.reg |= TCC_CTRLA_ENABLE ; + syncTCC(TCCx); } return ; -- GitLab