170 lines
7.8 KiB
C
170 lines
7.8 KiB
C
// Clock.c
|
|
// Runs on the MSP432
|
|
// Daniel and Jonathan Valvano
|
|
// February 23, 2017
|
|
|
|
/* This example accompanies the book
|
|
"Embedded Systems: Introduction to Robotics,
|
|
Jonathan W. Valvano, ISBN: 9781074544300, copyright (c) 2019
|
|
For more information about my classes, my research, and my books, see
|
|
http://users.ece.utexas.edu/~valvano/
|
|
|
|
Simplified BSD License (FreeBSD License)
|
|
Copyright (c) 2019, Jonathan Valvano, All rights reserved.
|
|
|
|
Redistribution and use in source and binary forms, with or without modification,
|
|
are permitted provided that the following conditions are met:
|
|
|
|
1. Redistributions of source code must retain the above copyright notice,
|
|
this list of conditions and the following disclaimer.
|
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
this list of conditions and the following disclaimer in the documentation
|
|
and/or other materials provided with the distribution.
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
|
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
|
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
The views and conclusions contained in the software and documentation are
|
|
those of the authors and should not be interpreted as representing official
|
|
policies, either expressed or implied, of the FreeBSD Project.
|
|
*/
|
|
|
|
#include <stdint.h>
|
|
#include "msp.h"
|
|
|
|
uint32_t ClockFrequency = 3000000; // cycles/second
|
|
//static uint32_t SubsystemFrequency = 3000000; // cycles/second
|
|
|
|
// ------------Clock_InitFastest------------
|
|
// Configure the system clock to run at the fastest
|
|
// and most accurate settings. For example, if the
|
|
// LaunchPad has a crystal, it should be used here.
|
|
// Call BSP_Clock_GetFreq() to get the current system
|
|
// clock frequency for the LaunchPad.
|
|
// Input: none
|
|
// Output: none
|
|
uint32_t Prewait = 0; // loops between BSP_Clock_InitFastest() called and PCM idle (expect 0)
|
|
uint32_t CPMwait = 0; // loops between Power Active Mode Request and Current Power Mode matching requested mode (expect small)
|
|
uint32_t Postwait = 0; // loops between Current Power Mode matching requested mode and PCM module idle (expect about 0)
|
|
uint32_t IFlags = 0; // non-zero if transition is invalid
|
|
uint32_t Crystalstable = 0; // loops before the crystal stabilizes (expect small)
|
|
void Clock_Init48MHz(void){
|
|
// wait for the PCMCTL0 and Clock System to be write-able by waiting for Power Control Manager to be idle
|
|
while(PCM->CTL1&0x00000100){
|
|
// while(PCMCTL1&0x00000100){
|
|
Prewait = Prewait + 1;
|
|
if(Prewait >= 100000){
|
|
return; // time out error
|
|
}
|
|
}
|
|
// request power active mode LDO VCORE1 to support the 48 MHz frequency
|
|
PCM->CTL0 = (PCM->CTL0&~0xFFFF000F) | // clear PCMKEY bit field and AMR bit field
|
|
// PCMCTL0 = (PCMCTL0&~0xFFFF000F) | // clear PCMKEY bit field and AMR bit field
|
|
0x695A0000 | // write the proper PCM key to unlock write access
|
|
0x00000001; // request power active mode LDO VCORE1
|
|
// check if the transition is invalid (see Figure 7-3 on p344 of datasheet)
|
|
if(PCM->IFG&0x00000004){
|
|
IFlags = PCM->IFG; // bit 2 set on active mode transition invalid; bits 1-0 are for LPM-related errors; bit 6 is for DC-DC-related error
|
|
PCM->CLRIFG = 0x00000004; // clear the transition invalid flag
|
|
// to do: look at CPM bit field in PCMCTL0, figure out what mode you're in, and step through the chart to transition to the mode you want
|
|
// or be lazy and do nothing; this should work out of reset at least, but it WILL NOT work if Clock_Int32kHz() or Clock_InitLowPower() has been called
|
|
return;
|
|
}
|
|
// wait for the CPM (Current Power Mode) bit field to reflect a change to active mode LDO VCORE1
|
|
while((PCM->CTL0&0x00003F00) != 0x00000100){
|
|
CPMwait = CPMwait + 1;
|
|
if(CPMwait >= 500000){
|
|
return; // time out error
|
|
}
|
|
}
|
|
// wait for the PCMCTL0 and Clock System to be write-able by waiting for Power Control Manager to be idle
|
|
while(PCM->CTL1&0x00000100){
|
|
Postwait = Postwait + 1;
|
|
if(Postwait >= 100000){
|
|
return; // time out error
|
|
}
|
|
}
|
|
// initialize PJ.3 and PJ.2 and make them HFXT (PJ.3 built-in 48 MHz crystal out; PJ.2 built-in 48 MHz crystal in)
|
|
PJ->SEL0 |= 0x0C;
|
|
PJ->SEL1 &= ~0x0C; // configure built-in 48 MHz crystal for HFXT operation
|
|
// PJDIR |= 0x08; // make PJ.3 HFXTOUT (unnecessary)
|
|
// PJDIR &= ~0x04; // make PJ.2 HFXTIN (unnecessary)
|
|
CS->KEY = 0x695A; // unlock CS module for register access
|
|
CS->CTL2 = (CS->CTL2&~0x00700000) | // clear HFXTFREQ bit field
|
|
0x00600000 | // configure for 48 MHz external crystal
|
|
0x00010000 | // HFXT oscillator drive selection for crystals >4 MHz
|
|
0x01000000; // enable HFXT
|
|
CS->CTL2 &= ~0x02000000; // disable high-frequency crystal bypass
|
|
// wait for the HFXT clock to stabilize
|
|
while(CS->IFG&0x00000002){
|
|
CS->CLRIFG = 0x00000002; // clear the HFXT oscillator interrupt flag
|
|
Crystalstable = Crystalstable + 1;
|
|
if(Crystalstable > 100000){
|
|
return; // time out error
|
|
}
|
|
}
|
|
// configure for 2 wait states (minimum for 48 MHz operation) for flash Bank 0
|
|
FLCTL->BANK0_RDCTL = (FLCTL->BANK0_RDCTL&~0x0000F000)|FLCTL_BANK0_RDCTL_WAIT_2;
|
|
// configure for 2 wait states (minimum for 48 MHz operation) for flash Bank 1
|
|
FLCTL->BANK1_RDCTL = (FLCTL->BANK1_RDCTL&~0x0000F000)|FLCTL_BANK1_RDCTL_WAIT_2;
|
|
CS->CTL1 = 0x20000000 | // configure for SMCLK divider /4
|
|
0x00100000 | // configure for HSMCLK divider /2
|
|
0x00000200 | // configure for ACLK sourced from REFOCLK
|
|
0x00000050 | // configure for SMCLK and HSMCLK sourced from HFXTCLK
|
|
0x00000005; // configure for MCLK sourced from HFXTCLK
|
|
CS->KEY = 0; // lock CS module from unintended access
|
|
ClockFrequency = 48000000;
|
|
// SubsystemFrequency = 12000000;
|
|
}
|
|
|
|
// ------------Clock_GetFreq------------
|
|
// Return the current system clock frequency for the
|
|
// LaunchPad.
|
|
// Input: none
|
|
// Output: system clock frequency in cycles/second
|
|
uint32_t Clock_GetFreq(void){
|
|
return ClockFrequency;
|
|
}
|
|
|
|
|
|
// delay function
|
|
// which delays about 6*ulCount cycles
|
|
// ulCount=8000 => 1ms = (8000 loops)*(6 cycles/loop)*(20.83 ns/cycle)
|
|
//Code Composer Studio Code
|
|
void delay(unsigned long ulCount){
|
|
__asm ( "pdloop: subs r0, #1\n"
|
|
" bne pdloop\n");
|
|
}
|
|
|
|
// ------------Clock_Delay1us------------
|
|
// Simple delay function which delays about n microseconds.
|
|
// Inputs: n, number of us to wait
|
|
// Outputs: none
|
|
void Clock_Delay1us(uint32_t n){
|
|
n = (382*n)/100;; // 1 us, tuned at 48 MHz
|
|
while(n){
|
|
n--;
|
|
}
|
|
}
|
|
|
|
// ------------Clock_Delay1ms------------
|
|
// Simple delay function which delays about n milliseconds.
|
|
// Inputs: n, number of msec to wait
|
|
// Outputs: none
|
|
void Clock_Delay1ms(uint32_t n){
|
|
while(n){
|
|
delay(ClockFrequency/9162); // 1 msec, tuned at 48 MHz
|
|
n--;
|
|
}
|
|
}
|
|
|
|
|