// 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 #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--; } }