Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 1 of 1

Thread: Teensy 3.6 CMT primary prescaler and FrequencyTimer2 library

  1. #1
    Junior Member
    Join Date
    Dec 2018
    Posts
    3

    Teensy 3.6 CMT primary prescaler and FrequencyTimer2 library

    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 by Yichi_Yang; 12-29-2018 at 02:16 AM. Reason: typo

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •