File tree 1 file changed +12
-2
lines changed
1 file changed +12
-2
lines changed Original file line number Diff line number Diff line change @@ -145,6 +145,8 @@ void analogWrite(uint8_t pin, int val)
145
145
uint16_t * timer_cmp_out ;
146
146
TCB_t * timer_B ;
147
147
148
+ uint8_t savedSREG ;
149
+
148
150
/* Find out Port and Pin to correctly handle port mux, and timer. */
149
151
switch (digital_pin_timer ) {
150
152
@@ -153,7 +155,10 @@ void analogWrite(uint8_t pin, int val)
153
155
timer_cmp_out = ((uint16_t * ) (& TCA0 .SINGLE .CMP0BUF )) + bit_pos ;
154
156
155
157
/* Configure duty cycle for correct compare channel */
156
- (* timer_cmp_out ) = (val );
158
+ savedSREG = SREG ;
159
+ cli ();
160
+ (* timer_cmp_out ) = (val ); // non-atomic 16-bit write operation
161
+ SREG = savedSREG ;
157
162
158
163
/* Enable output on pin */
159
164
TCA0 .SINGLE .CTRLB |= (1 << (TCA_SINGLE_CMP0EN_bp + bit_pos ));
@@ -170,7 +175,12 @@ void analogWrite(uint8_t pin, int val)
170
175
timer_B = ((TCB_t * )& TCB0 + (digital_pin_timer - TIMERB0 ));
171
176
172
177
/* set duty cycle */
173
- timer_B -> CCMPH = val ;
178
+ // (16-bit read/write operation are non-atomic and use a temporary register)
179
+ savedSREG = SREG ;
180
+ cli ();
181
+ timer_B -> CCMPL = timer_B -> CCMPL ; // copy CCMPL into temporary register
182
+ timer_B -> CCMPH = val ; // set CCMPH value + copy temporary register content into CCMPL
183
+ SREG = savedSREG ;
174
184
175
185
/* Enable Timer Output */
176
186
timer_B -> CTRLB |= (TCB_CCMPEN_bm );
You can’t perform that action at this time.
0 commit comments