Teensy 3.6 CMT primary prescaler and FrequencyTimer2 library

Yichi_Yang

New member
I'm researching the possibility of using of the CMT module on Teensy 3.6 to drive a linear CCD. I determined that the easiest way is to reverse engineer the FrequencyTimer2 library, and after a bit of digging, I figured out mostly how it works. One thing bothers me though, is that while the K66 reference manual states that the primary prescaler should be used to generate a clock enable signal called intermediate frequency of approx. 8 MHz, the code in FrequencyTimer2 library appears to use the smallest primary prescaler divider possible. Given the F_BUS of 60 MHz, if the period is set to a small value, the IF will be significantly higher than the recommended 8 MHz. I wonder what is the reasoning behind the suggestion in the reference manual, and what will happen if the IF is higher than 8 MHz?

(I'm new to the teensy platform and do not have a T3.6 currently, so I cannot test this on the hardware. I'll get a T3.6 and run some tests when I get back to the States.)

Relevant excerpt from the K66 reference manual:
48.8.1 Clock divider
The CMT was originally designed to be based on an 8 MHz bus clock that could be
divided by 1, 2, 4, or 8 according to the specification. To be compatible with higher bus
frequency, the primary prescaler (PPS) was developed to receive a higher frequency and
generate a clock enable signal called intermediate frequency (IF). This IF must be
approximately equal to 8 MHz and will work as a clock enable to the secondary
prescaler. The following figure shows the clock divider block diagram.
For compatibility with previous versions of CMT, when bus clock = 8 MHz, the PPS
must be configured to zero. The PPS counter is selected according to the bus clock to
generate an intermediate frequency approximately equal to 8 MHz.

Relevant bits of code in the library:
Code:
void FrequencyTimer2::setPeriod(unsigned long period)
{
	uint8_t bdiv, cdiv=0;

	if (period == 0) period = 1;
	period *= (F_BUS / 1000000);
	if (period < 65535*16) {
		bdiv = 0;
	} else if (period < 65535*2*16) {
		bdiv = 1;
	} else if (period < 65535*3*16) {
		bdiv = 2;
	} else if (period < 65535*4*16) {
		bdiv = 3;
	} else if (period < 65535*5*16) {
		bdiv = 4;
	} else if (period < 65535*6*16) {
		bdiv = 5;
	} else if (period < 65535*7*16) {
		bdiv = 6;
	} else if (period < 65535*8*16) {
		bdiv = 7;
	} else if (period < 65535*9*16) {
		bdiv = 8;
	} else if (period < 65535*10*16) {
		bdiv = 9;
	} else if (period < 65535*11*16) {
		bdiv = 10;
	} else if (period < 65535*12*16) {
		bdiv = 11;
	} else if (period < 65535*13*16) {
		bdiv = 12;
	} else if (period < 65535*14*16) {
		bdiv = 13;
	} else if (period < 65535*15*16) {
		bdiv = 14;
	} else if (period < 65535*16*16) {
		bdiv = 15;
	} else if (period < 65535*18*16) {
		bdiv = 8;
		cdiv = 1;
	} else if (period < 65535*20*16) {
		bdiv = 9;
		cdiv = 1;
	} else if (period < 65535*22*16) {
		bdiv = 10;
		cdiv = 1;
	} else if (period < 65535*24*16) {
		bdiv = 11;
		cdiv = 1;
	} else if (period < 65535*26*16) {
		bdiv = 12;
		cdiv = 1;
	} else if (period < 65535*28*16) {
		bdiv = 13;
		cdiv = 1;
	} else if (period < 65535*30*16) {
		bdiv = 14;
		cdiv = 1;
	} else if (period < 65535*32*16) {
		bdiv = 15;
		cdiv = 1;
	} else if (period < 65535*36*16) {
		bdiv = 8;
		cdiv = 2;
	} else if (period < 65535*40*16) {
		bdiv = 9;
		cdiv = 2;
	} else if (period < 65535*44*16) {
		bdiv = 10;
		cdiv = 2;
	} else if (period < 65535*48*16) {
		bdiv = 11;
		cdiv = 2;
	} else if (period < 65535*52*16) {
		bdiv = 12;
		cdiv = 2;
	} else if (period < 65535*56*16) {
		bdiv = 13;
		cdiv = 2;
	} else if (period < 65535*60*16) {
		bdiv = 14;
		cdiv = 2;
	} else if (period < 65535*64*16) {
		bdiv = 15;
		cdiv = 2;
	} else if (period < 65535*72*16) {
		bdiv = 8;
		cdiv = 3;
	} else if (period < 65535*80*16) {
		bdiv = 9;
		cdiv = 3;
	} else if (period < 65535*88*16) {
		bdiv = 10;
		cdiv = 3;
	} else if (period < 65535*96*16) {
		bdiv = 11;
		cdiv = 3;
	} else if (period < 65535*104*16) {
		bdiv = 12;
		cdiv = 3;
	} else if (period < 65535*112*16) {
		bdiv = 13;
		cdiv = 3;
	} else if (period < 65535*120*16) {
		bdiv = 14;
		cdiv = 3;
	} else {
		bdiv = 15;
		cdiv = 3;
	}
	period /= (bdiv + 1);
	period >>= (cdiv + 4);
	if (period > 65535) period = 65535;
	// high time = (CMD1:CMD2 + 1) ÷ (fCMTCLK ÷ 8)
	// low time  = CMD3:CMD4 ÷ (fCMTCLK ÷ 8)
	SIM_SCGC4 |= SIM_SCGC4_CMT;
	CMT_MSC = 0;
	CMT_PPS = bdiv;
	CMT_CMD1 = ((period - 1) >> 8) & 255;
	CMT_CMD2 = (period - 1) & 255;
	CMT_CMD3 = (period >> 8) & 255;
	CMT_CMD4 = period & 255;
	CMT_OC = 0x60;
	CMT_MSC = (cdiv << 5) | 0x0B; // baseband mode
}
 
Last edited:
Back
Top