Since your application, most likely, will be designed to run upon power up of the module without the support of the serial monitor, it will need to configure the clock registers on the MC9S12D hardware. The reason for this is that if the Load/Run switch is in the Run position, the serial monitor detects this setting upon powerup or reset and jumps immediately to your application as pointed to by the address you put in Flash at $F7FE/F. (If you do not program this location, the serial monitor will take control regardless of the Load/Run switch position!)
When the serial monitor starts your application following reset, it does not configure any of the hardware registers first. It goes directly to your code.
The default settings of the clock registers are such that when your application first starts up, it is running at a speed of 8 MHz, which corresponds to the module oscillator frequency (16 MHz) divided by two. Most likely you will want to change this speed. The most common value used is 24 MHz, which is the maximum the MC9S12D will support.
How is the clock set then to the speed you want? To do that, the hardware uses the following equations:
PLLClock = 2 * Oscillator * (SYNR + 1 ) / (REFDV + 1)
BusClock = PLLCock / 2
The BusClock frequency is the one we want. The Oscillator term is the frequency of the crystal oscillator attached to the chip, or the frequency being fed into the MCU on the EXTAL pin. Adapt9S12D uses a 16 MHz crystal, so this will be the oscillator value. The registers SYNR and REFDV are located in the register space at $34 and $35 respectively. The program will need to update these with the values needed to get the system clock at the desired value.
Let's take an example of a target of 24 MHz, and an oscillator frequency of 16 MHz. To get from 16 to 24, we can divide 16 by 2 (REFDV + 1) to get 8, and multiply that by 3 (SYNR + 1) to get 24. Since the SYNR and REFDV are one less than our scaling factors, we get SYNR equal to 2, and REFDV equal to 1. This makes our equation:
BusClock = (16 MHz) * (2 + 1) / (1 + 1) = 16 * 3 / 2 = 24
However one does not just write to these registers with a couple of write statements in the code. The phase lock loop (PLL) system has to first be disengaged from the system, turned on, updated, and checked for stability. Afterwards, the final step would be to engage the PLL to the rest of the MCU system.
So the programming steps become:
1. Disengage PLL from System: Clear bit 7 (MSB) in register CLKSEL ($39).
2. Turn on PLL: Set bit 6 of PLLON ($3A) register.
3. Write SYNR value into register at $34.
4. Write REFDV value into register at $35.
5. Wait at least two bus cycles before starting to check for stability. This can be done with a couple of NOP instructions in assembly.
6. Check to see that the PLL is stable: Check bit 3 of CRGFLG ($37) until it reads it is set.
7. Enable PLL to become BusClock: Set bit 7 of CLKSEL ($39).
Once this is done, the MCU bus will be running at the programmed rate as set above.
The oscillator and bus clocks are used not just to sequence through instructions and time memory and peripheral accesses. They are also used to determine the timing of several other harware module capabilities, such as SCI baud rate, RTI/COP timing, and Flash/EEPROM programming.
For example, the baud rate for any of the SCI interfaces is set by this equation:
baudRegister = ( (BusFreq / 16) * 10) / baudrate
Here the BusFreq is the system bus frequency as determined above, in KHz. This will usually be 24000 KHz. The baudrate value is the desired baud divided by 100. So 9600 becomes 96, etc. The resulting baudRegister value is then programmed into the SCIBDH and SCIBDL registers as the high and low bytes of the value, respectively.
Obviously, if the system bus clock is changed to a different value, then this will affect the baud rate programmed into the SCI module.
Setting the RTI or COP interval timers is similar. However these use the oscillator frequency rather than the PLL frequency. There are tables in the Freescale chip documentation listing what the divide values are. The oscillator frequency gets divided by the selected divide value to give the final RTI or COP frequency. For example, one can set the RTICTL register at location $3B to a value of $F7. This selects a decimal divider of 1.6 x 10^6. Since the oscillator clock is 16 MHz, this results in a 10 Hz RTI interrupt rate, or one interrupt every 100 milliseconds.