YAHAL
Yet Another Hardware Abstraction Library
Loading...
Searching...
No Matches
clock_msp432.cpp
1/*
2 * clockmsp432.cpp
3 *
4 * Created on: 17.04.2016
5 * Author: Andreas Terstegge
6 */
7
8#include <cassert>
9#include <clock_msp432.h>
10#include "msp.h"
11
12#if 0
13
14clock_msp432::clock_msp432() {
15 // Initialize calibration factors
16 kalib04 = (768 - TLV->DCOIR_FCAL_RSEL04);
17 kalib04 += 1.0f / *((float *)(&TLV->DCOIR_CONSTK_RSEL04));
18 kalib04 *= 8.00f;
19 kalib5 = (768 - TLV->DCOIR_FCAL_RSEL04); // DCOIR_FCAL_RSEL5 not set!
20 kalib5 += 1.0f / *((float *)(&TLV->DCOIR_CONSTK_RSEL5));
21 kalib5 *= 8.00f;
22 // initialize PJ so that the LFXT and HFXT are usable
23 PJ->SEL0 |= 0x0F;
24 PJ->SEL1 &= ~0x0F;
25
26 // Set power mode so 48MHz can be used
27
28}
29
30clock_msp432::~clock_msp432() {
31}
32
33void clock_msp432::setOscFrequency(CLKSYS::OSC clk, uint32_t hz) {
34 // Unlock the clock system
35 CS->KEY = CS_KEY_VAL;
36 switch(clk) {
38 // DCO Configuration //
40 case CLKSYS::DCO: {
41 assert(hz>=1000000 && hz<=64000000);
42
43 int16_t maxtune04 = (int16_t)(TLV->DCOIR_MAXPOSTUNE_RSEL04);
44 int16_t mintune04 = (int16_t)(TLV->DCOIR_MAXNEGTUNE_RSEL04 | 0xffffe000);
45 int16_t maxtune5 = (int16_t)(TLV->DCOIR_MAXPOSTUNE_RSEL5);
46 int16_t mintune5 = (int16_t)(TLV->DCOIR_MAXNEGTUNE_RSEL5 | 0xffffe000);
47 float f_center = 1500000;
48 float tune;
49 uint8_t rsel;
50 for (rsel=0; rsel <= 5; ++rsel) {
51 tune = 1.0f - (f_center / (float)hz);
52 if (rsel <= 4) {
53 tune *= kalib04;
54 if ((tune <= maxtune04) && (tune >= mintune04))
55 break;
56 f_center *= 2;
57 } else {
58 tune *= kalib5;
59 if ((tune <= maxtune5) && (tune >= mintune5))
60 break;
61 f_center *= 2;
62 }
63 }
64 assert(rsel < 6);
65 // Mostly default values for DCO (internal resistor)
66 int16_t tune_int = (int16_t)(tune + 0.5f);
67 CS->CTL0 = (rsel << CS_CTL0_DCORSEL_OFS) | (tune_int & 0x1fff);
68 break;
69 }
71 // REFO Configuration //
73 case CLKSYS::REFO: {
74 assert(hz==32768 || hz==128000);
75 if (hz==32768) {
76 CS->CLKEN &= ~CS_CLKEN_REFOFSEL;
77 } else {
78 CS->CLKEN |= CS_CLKEN_REFOFSEL;
79 }
80 break;
81 }
82 default: assert(false);
83 }
84 // lock clock system (prevent unintended access)
85 CS->KEY = 0;
86}
87
88uint32_t clock_msp432::getOscFrequency(CLKSYS::OSC osc) {
89 switch(osc) {
90 case CLKSYS::LFXT: return 32768;
91 case CLKSYS::HFXT: return 48000000;
92 case CLKSYS::DCO: return getDcoFrequency();
93 case CLKSYS::VLO: return 10000;
94 case CLKSYS::REFO: return (CS->CLKEN & CS_CLKEN_REFOFSEL) ? 128000 : 32768;
95 case CLKSYS::MODOSC: return 24000000;
96 };
97 return 0;
98}
99
100uint32_t clock_msp432::getClockFrequency(CLKSYS::CLK clk) {
101 uint8_t oscsel;
102 uint32_t f;
103 uint8_t shift = 0;
104 switch(clk) {
105 case CLKSYS::ACLK: {
106 oscsel = (CS->CTL1 & CS_CTL1_SELA_MASK) >> CS_CTL1_SELA_OFS;
107 shift = (CS->CTL1 & CS_CTL1_DIVA_MASK) >> CS_CTL1_DIVA_OFS;
108 break;
109 }
110 case CLKSYS::MCLK: {
111 oscsel = (CS->CTL1 & CS_CTL1_SELM_MASK) >> CS_CTL1_SELM_OFS;
112 shift = (CS->CTL1 & CS_CTL1_DIVM_MASK) >> CS_CTL1_DIVM_OFS;
113 break;
114 }
115 case CLKSYS::HSMCLK: {
116 oscsel = (CS->CTL1 & CS_CTL1_SELS_MASK) >> CS_CTL1_SELS_OFS;
117 shift = (CS->CTL1 & CS_CTL1_DIVHS_MASK) >> CS_CTL1_DIVHS_OFS;
118 break;
119 }
120 case CLKSYS::SMCLK: {
121 oscsel = (CS->CTL1 & CS_CTL1_SELS_MASK) >> CS_CTL1_SELS_OFS;
122 shift = (CS->CTL1 & CS_CTL1_DIVS_MASK) >> CS_CTL1_DIVS_OFS;
123 break;
124 }
125 case CLKSYS::BCLK: {
126 oscsel = (CS->CTL1 & CS_CTL1_SELB) >> (CS_CTL1_SELB_OFS-1);
127 shift = 0;
128 break;
129 }
130 }
131 switch(oscsel) {
132 case 0: f=getOscFrequency(CLKSYS::LFXT); break;
133 case 1: f=getOscFrequency(CLKSYS::VLO); break;
134 case 2: f=getOscFrequency(CLKSYS::REFO); break;
135 case 3: f=getOscFrequency(CLKSYS::DCO); break;
136 case 4: f=getOscFrequency(CLKSYS::MODOSC); break;
137 case 5: f=getOscFrequency(CLKSYS::HFXT); break;
138 default: assert(false);
139 }
140 return f >> shift;
141}
142
143
144void clock_msp432::setCLockSource(CLKSYS::CLK clk, CLKSYS::OSC osc, uint8_t div) {
145 assert ((div > 0) && (div < 129) && !(div & (div-1)));
146 // Unlock the clock system
147 CS->KEY = CS_KEY_VAL;
148 // Calculate the div value (0...7) representing dividing
149 // factors of 1,2,4,8,16,32,64 and 128
150 uint8_t div_val = 0;
151 uint8_t osc_shift = 0;
152 uint8_t div_shift = 0;
153 while (!(div & 0x01)) {
154 div >>= 1;
155 div_val++;
156 }
157 switch(clk) {
158 case CLKSYS::ACLK: {
159 assert(osc == CLKSYS::LFXT ||
160 osc == CLKSYS::VLO ||
161 osc == CLKSYS::REFO);
162 osc_shift = CS_CTL1_SELA_OFS;
163 div_shift = CS_CTL1_DIVA_OFS;
164 break;
165 }
166 case CLKSYS::MCLK: {
167 osc_shift = CS_CTL1_SELM_OFS;
168 div_shift = CS_CTL1_DIVM_OFS;
169 break;
170 }
171 case CLKSYS::HSMCLK: {
172 osc_shift = CS_CTL1_SELS_OFS;
173 div_shift = CS_CTL1_DIVHS_OFS;
174 break;
175 }
176 case CLKSYS::SMCLK: {
177 osc_shift = CS_CTL1_SELS_OFS;
178 div_shift = CS_CTL1_DIVS_OFS;
179 break;
180 }
181 case CLKSYS::BCLK: {
182 assert(div == 1);
183 switch(osc) {
184 case CLKSYS::LFXT: CS->CTL1 &= ~CS_CTL1_SELB; break;
185 case CLKSYS::REFO: CS->CTL1 |= CS_CTL1_SELB; break;
186 default: assert(false);
187 }
188 break;
189 }
190 }
191
192 if (clk != CLKSYS::BCLK) {
193 CS->CTL1 &= ~ (0x07 << osc_shift);
194 switch(osc) {
195 case CLKSYS::LFXT: CS->CTL1 |= 0x00 << osc_shift; break;
196 case CLKSYS::VLO: CS->CTL1 |= 0x01 << osc_shift; break;
197 case CLKSYS::REFO: CS->CTL1 |= 0x02 << osc_shift; break;
198 case CLKSYS::DCO: CS->CTL1 |= 0x03 << osc_shift; break;
199 case CLKSYS::MODOSC: CS->CTL1 |= 0x04 << osc_shift; break;
200 case CLKSYS::HFXT: CS->CTL1 |= 0x05 << osc_shift; break;
201 }
202 CS->CTL1 &= ~ (0x07 << div_shift);
203 CS->CTL1 |= div_val << div_shift;
204 }
205
206 // lock clock system (prevent unintended access)
207 CS->KEY = 0;
208}
209
210uint32_t clock_msp432::getDcoFrequency() {
211 uint8_t rsel = ((CS->CTL0 & CS_CTL0_DCORSEL_MASK) >> CS_CTL0_DCORSEL_OFS);
212 float kalib = (rsel <= 4) ? kalib04 : kalib5;
213 uint32_t f_center = 1500000 << rsel;
214 int16_t tune = (CS->CTL0 & 0x1fff);
215 if (tune & 0x1000) tune |= 0xe000; // extend sign
216 float f = (float)f_center / (kalib - (float)tune) * kalib;
217 return (uint32_t)(f + 0.5f);
218}
219
220#endif
#define CS_CTL1_DIVS_MASK
#define CS_CTL1_SELS_MASK
#define CS_CTL0_DCORSEL_MASK
#define CS_CTL0_DCORSEL_OFS
#define CS_CTL1_DIVA_MASK
#define CS_CTL1_DIVM_OFS
#define CS_CTL1_SELM_MASK
#define CS_CTL1_SELB_OFS
#define CS_CTL1_SELA_MASK
#define CS_CTL1_DIVA_OFS
#define CS_KEY_VAL
#define CS_CLKEN_REFOFSEL
#define CS_CTL1_SELS_OFS
#define CS_CTL1_DIVHS_OFS
#define CS_CTL1_DIVHS_MASK
#define CS_CTL1_DIVS_OFS
#define CS_CTL1_SELB
#define CS_CTL1_DIVM_MASK
#define CS_CTL1_SELM_OFS
#define CS_CTL1_SELA_OFS