The full code of the program that I used to isolate the effect of TCCRnA is as follows, with variations showing when OCRnx work as expected and when they behave oddly. The loop function was always empty and is thus omitted from all code posted here.
The Working Configurations:
Using Normal Setting:
void setup()
{
Serial.begin(38400);
pinMode(11, OUTPUT);
TCCR2A = bit(COM2A0) | bit(WGM21);
OCR2A = 1;
TCCR2B = bit(CS20);
pinMode(10, OUTPUT);
TCCR1A = bit(COM1B0);
OCR1A = 249;
OCR1B = 248;
TCCR1B = bit(WGM12) | bit(CS10);
Serial.println("Configured");
Serial.print("OCR2A: ");
Serial.println(OCR2A);
Serial.print("OCR1A: ");
Serial.println(OCR1A);
Serial.print("OCR1B: ");
Serial.println(OCR1B);
}
Serial Monitor:
Configured
OCR2A: 1
OCR1A: 249
OCR1B: 248
Scope Measurements:
31.9kHz from pin 11
4MHz from pin 10
Using asm:
void setup()
{
Serial.begin(38400);
pinMode(11, OUTPUT);
__asm__("push r16\n\t ldi r16, 0b01000010\n\t sts 0xB0, r16\n\t pop r16");
OCR2A = 1;
TCCR2B = bit(CS20);
pinMode(10, OUTPUT);
__asm__("push r16\n\t ldi r16, 0b00010000\n\t sts 0x80, r16\n\t pop r16");
OCR1A = 249;
OCR1B = 248;
TCCR1B = bit(WGM12) | bit(CS10);
Serial.println("Configured");
Serial.print("OCR2A: ");
Serial.println(OCR2A);
Serial.print("OCR1A: ");
Serial.println(OCR1A);
Serial.print("OCR1B: ");
Serial.println(OCR1B);
}
Serial Monitor:
Configured
OCR2A: 1
OCR1A: 249
OCR1B: 248
Scope Measurements:
31.9kHz on pin 11
4MHz on pin 10
The Odd Configurations:
Using Normal Setting:
void setup()
{
Serial.begin(38400);
pinMode(11, OUTPUT);
OCR2A = 1;
TCCR2A = bit(COM2A0) | bit(WGM21);
TCCR2B = bit(CS20);
pinMode(10, OUTPUT);
OCR1A = 249;
OCR1B = 248;
TCCR1A = bit(COM1B0);
TCCR1B = bit(WGM12) | bit(CS10);
Serial.println("Configured");
Serial.print("OCR2A: ");
Serial.println(OCR2A);
Serial.print("OCR1A: ");
Serial.println(OCR1A);
Serial.print("OCR1B: ");
Serial.println(OCR1B);
}
Serial Monitor:
Configured
OCR2A: 1
OCR1A: 0
OCR1B: 0
Scope Measurements:
8MHz on pin 11
8MHz on pin 10
Using asm:
void setup()
{
Serial.begin(38400);
pinMode(11, OUTPUT);
OCR2A = 1;
__asm__("push r16\n\t ldi r16, 0b01000010\n\t sts 0xB0, r16\n\t pop r16");
TCCR2B = bit(CS20);
pinMode(10, OUTPUT);
OCR1A = 249;
OCR1B = 248;
__asm__("push r16\n\t ldi r16, 0b00010000\n\t sts 0x80, r16\n\t pop r16");
TCCR1B = bit(WGM12) | bit(CS10);
Serial.println("Configured");
Serial.print("OCR2A: ");
Serial.println(OCR2A);
Serial.print("OCR1A: ");
Serial.println(OCR1A);
Serial.print("OCR1B: ");
Serial.println(OCR1B);
}
Serial Monitor:
Configured
OCR2A: 1
OCR1A: 0
OCR1B: 0
Scope Measurements:
8MHz on pin 11
8MHz on pin 10
As you can hopefully see, in The Working Configurations, setting OCRnx after TCCRnA produced the output one would expect, but in The Odd Configurations, setting OCRnx before TCCRnA resulted in 8MHz outputs in all cases and is reflected in the Serial Monitor outputs for T/C 1.
I'm not sure why OCR2A is reporting 1, which is in contradiction to the physical output, but refer to the OCR1x as they are coherent with the physical measurements and show the values being set to 0 in The Odd Configurations.
I think (and therefore I am) seeing that in the fact that setting the registers in the 'odd' order in asm written outside the ArduinoIDE results in normal operation whereas the 'odd' order written in normal Arduino results in the oddity. This, therefore indicates that some point in the ArduinoIDE chain between the user hitting upload and it being flashed onto the chip is the cause (otherwise the asm would too). If you would like to see the AVR_Sim assembly code that shows this, I can provide that as well.
Yes, as shown in the assignment order in The Normal Configurations, setting TCCRnB last did not result in any oddities. I also tried moving the TCCRnB assignment to various points throughout the T/C configuration and never saw any changes. In fact, in most situations, one would only want to set the clock source after all the other registers have been set, lest the counter surpasses your CTC value before you set it and run away until overflow.
Is the initialization code added before the setup() function? If so, when the user's setup() function assigns values to these registers, it overwrites any ones in there previously, even if they are just written a few instructions ago (assuming simple assignment and not any compound bitwise assignment). If the initialization code went after the the setup() function, I would expect none of this to work at all. I thus believe that it is not the initialization code causing this.