1 //
2 // Copyright (c) 2010-2023 Antmicro
3 //
4 // This file is licensed under the MIT License.
5 // Full license text is available in 'licenses/MIT.txt'.
6 //
7 using System;
8 using Antmicro.Renode.Core;
9 using Antmicro.Renode.Core.Structure.Registers;
10 using Antmicro.Renode.Logging;
11 using Antmicro.Renode.Peripherals.Bus;
12 
13 namespace Antmicro.Renode.Peripherals.Miscellaneous
14 {
15     [AllowedTranslations(AllowedTranslation.ByteToDoubleWord | AllowedTranslation.WordToDoubleWord)]
16     public class STM32WBA_RCC : BasicDoubleWordPeripheral, IKnownSize
17     {
STM32WBA_RCC(IMachine machine, IHasFrequency nvic = null, IHasFrequency lptim1 = null, IHasFrequency lptim2 = null, long lsiFrequency = DefaultLsiFrequency, long lseFrequency = DefaultLseFrequency, long hseFrequency = DefaultHseFreqeuency)18         public STM32WBA_RCC(IMachine machine, IHasFrequency nvic = null, IHasFrequency lptim1 = null, IHasFrequency lptim2 = null,
19             long lsiFrequency = DefaultLsiFrequency, long lseFrequency = DefaultLseFrequency, long hseFrequency = DefaultHseFreqeuency) : base(machine)
20         {
21             this.nvic = nvic;
22             this.lptim1 = lptim1;
23             this.lptim2 = lptim2;
24             this.lsiFrequency = lsiFrequency;
25             this.lseFrequency = lseFrequency;
26             this.hseFrequency = hseFrequency;
27             DefineRegisters();
28             Reset();
29         }
30 
Reset()31         public override void Reset()
32         {
33             base.Reset();
34             UpdateClocks();
35         }
36 
37         public long Size => 0x400;
38 
TrySetFrequency(IHasFrequency timer, long frequency)39         private static void TrySetFrequency(IHasFrequency timer, long frequency)
40         {
41             if(timer != null)
42             {
43                 timer.Frequency = frequency;
44             }
45         }
46 
UpdateClocks()47         private void UpdateClocks()
48         {
49             TrySetFrequency(nvic, SystemClock);
50             TrySetFrequency(lptim1, LpTimer1Clock);
51             TrySetFrequency(lptim2, LpTimer2Clock);
52         }
53 
DefineRegisters()54         private void DefineRegisters()
55         {
56             // Keep in mind that most of these registers do not affect other
57             // peripherals or their clocks.
58             Registers.ClockControl.Define(this, 0x500)
59                 .WithReservedBits(0, 8)
60                 .WithFlag(8, out var hsi16ClockEnable, name: "HSION")
61                 .WithFlag(9, name: "HSIKERON")
62                 .WithFlag(10, FieldMode.Read, valueProviderCallback: _ => hsi16ClockEnable.Value, name: "HSIRDY")
63                 .WithReservedBits(11, 5)
64                 .WithFlag(16, out var hseClockEnable, name: "HSEON")
65                 .WithFlag(17, FieldMode.Read, valueProviderCallback: _ => hseClockEnable.Value, name: "HSERDY")
66                 .WithReservedBits(18, 1)
67                 .WithTaggedFlag("HSECSSON", 19)
68                 .WithFlag(20, out hsePrescaler, name: "HSEPRE")
69                 .WithReservedBits(21, 3)
70                 .WithFlag(24, out var pll1Enable, name: "PLL1ON")
71                 .WithFlag(25, FieldMode.Read, valueProviderCallback: _ => pll1Enable.Value)
72                 .WithReservedBits(26, 6)
73                 .WithChangeCallback((_, __) => UpdateClocks());
74                 ;
75 
76             Registers.InternalClockSourcesCalibration3.Define(this, 0x100000)
77                 .WithTag("HSICAL", 0, 12)
78                 .WithReservedBits(12, 4)
79                 .WithTag("HSITRIM", 16, 5)
80                 .WithReservedBits(21, 11)
81                 ;
82 
83             Registers.ClockConfiguration1.Define(this)
84                 .WithEnumField(0, 2, out systemClockSwitch, name: "SW")
85                 .WithEnumField<DoubleWordRegister, SystemClockSource>(2, 2, FieldMode.Read, name: "SWS",
86                     valueProviderCallback: _ => systemClockSwitch.Value)
87                 .WithReservedBits(4, 20)
88                 .WithValueField(24, 4, name: "MCOSEL")
89                 .WithValueField(28, 3, name: "MCOPRE")
90                 .WithReservedBits(31, 1)
91                 .WithChangeCallback((_, __) => UpdateClocks());
92                 ;
93 
94             Registers.ClockConfiguration2.Define(this)
95                 .WithValueField(0, 3, out ahbPrescaler, name: "HPRE")
96                 .WithReservedBits(3, 1)
97                 .WithValueField(4, 3, out apb1Prescaler, name: "PPRE1")
98                 .WithReservedBits(7, 1)
99                 .WithValueField(8, 3, out apb2Prescaler, name: "PPRE2")
100                 .WithReservedBits(11, 21)
101                 .WithChangeCallback((_, __) => UpdateClocks());
102                 ;
103 
104             Registers.ClockConfiguration3.Define(this)
105                 .WithReservedBits(0, 4)
106                 .WithValueField(4, 3, out apb7Prescaler, name: "PPRE7")
107                 .WithReservedBits(7, 25)
108                 .WithChangeCallback((_, __) => UpdateClocks());
109                 ;
110 
111             Registers.Pll1Configuration.Define(this)
112                 .WithEnumField(0, 2, out pll1Source, name: "PLL1SRC")
113                 .WithValueField(2, 2, name: "PLL1RGE")
114                 .WithFlag(4, name: "PLL1FRACEN")
115                 .WithReservedBits(5, 3)
116                 .WithValueField(8, 3, out pll1Prescaler, name: "PLL1M")
117                 .WithReservedBits(11, 5)
118                 .WithFlag(16, name: "PLL1PEN")
119                 .WithFlag(17, name: "PLL1QEN")
120                 .WithFlag(18, name: "PLL1REN")
121                 .WithReservedBits(19, 1)
122                 .WithFlag(20, out var pll1SysclkDivide, name: "PLL1RCLKPRE") // 1 - divided
123                 .WithFlag(21, name: "PLL1RCLKPRESTEP")
124                 .WithFlag(22, FieldMode.Read, valueProviderCallback: _ => !pll1SysclkDivide.Value, name: "PLL1RCLKPRERDY") // 1 - not divided
125                 .WithReservedBits(23, 9)
126                 .WithChangeCallback((_, __) => UpdateClocks());
127                 ;
128 
129             Registers.Pll1Dividers.Define(this, 0x01010280)
130                 .WithValueField(0, 9, out pll1Multiplier, name: "PLL1N")
131                 .WithValueField(9, 7, out pll1DividerP, name: "PLL1P")
132                 .WithValueField(16, 7, out pll1DividerQ, name: "PLL1Q")
133                 .WithReservedBits(23, 1)
134                 .WithValueField(24, 7, out pll1DividerR, name: "PLL1R")
135                 .WithReservedBits(31, 1)
136                 .WithChangeCallback((_, __) => UpdateClocks());
137                 ;
138 
139             Registers.Pll1FractionalDivider.Define(this)
140                 .WithReservedBits(0, 3)
141                 .WithTag("PLL1FRACN", 3, 13)
142                 .WithReservedBits(16, 16)
143                 ;
144 
145             Registers.ClockInterruptEnable.Define(this)
146                 .WithFlag(0, out var lsi1ReadyInterruptEnable, name: "LSI1RDYIE")
147                 .WithFlag(1, out var lseReadyInterruptEnable, name: "LSERDYIE")
148                 .WithReservedBits(2, 1)
149                 .WithFlag(3, out var hsiReadyInterruptEnable, name: "HSIRDYIE")
150                 .WithFlag(4, out var hseReadyInterruptEnable, name: "HSERDYIE")
151                 .WithReservedBits(5, 1)
152                 .WithFlag(6, out var pll1ReadyInterruptEnable, name: "PLL1RDYIE")
153                 .WithReservedBits(7, 25)
154                 ;
155 
156             Registers.ClockInterruptFlag.Define(this)
157                 .WithFlag(0, FieldMode.Read, valueProviderCallback: _ => lsi1ReadyInterruptEnable.Value, name: "LSI1RDYF")
158                 .WithFlag(1, FieldMode.Read, valueProviderCallback: _ => lseReadyInterruptEnable.Value, name: "LSERDYF")
159                 .WithReservedBits(2, 1)
160                 .WithFlag(3, FieldMode.Read, valueProviderCallback: _ => hsiReadyInterruptEnable.Value, name: "HSIRDYF")
161                 .WithFlag(4, FieldMode.Read, valueProviderCallback: _ => hseReadyInterruptEnable.Value, name: "HSERDYF")
162                 .WithReservedBits(5, 1)
163                 .WithFlag(6, FieldMode.Read, valueProviderCallback: _ => pll1ReadyInterruptEnable.Value, name: "PLL1RDYF")
164                 .WithReservedBits(7, 3)
165                 .WithFlag(10, FieldMode.Read, valueProviderCallback: _ => false, name: "HSECSSF")
166                 .WithReservedBits(11, 21)
167                 ;
168 
169             Registers.ClockInterruptClear.Define(this)
170                 .WithFlag(0, FieldMode.Write, writeCallback: (_, value) => { if(value) { lsi1ReadyInterruptEnable.Value = false; } }, name: "LSI1RDYC")
171                 .WithFlag(1, FieldMode.Write, writeCallback: (_, value) => { if(value) { lseReadyInterruptEnable.Value = false; } }, name: "LSERDYC")
172                 .WithReservedBits(2, 1)
173                 .WithFlag(3, FieldMode.Write, writeCallback: (_, value) => { if(value) { hsiReadyInterruptEnable.Value = false; } }, name: "HSIRDYC")
174                 .WithFlag(4, FieldMode.Write, writeCallback: (_, value) => { if(value) { hseReadyInterruptEnable.Value = false; } }, name: "HSERDYC")
175                 .WithReservedBits(5, 1)
176                 .WithFlag(6, FieldMode.Write, writeCallback: (_, value) => { if(value) { pll1ReadyInterruptEnable.Value = false; } }, name: "PLL1RDYC")
177                 .WithReservedBits(7, 3)
178                 .WithFlag(10, FieldMode.Write, name: "HSECSSC")
179                 .WithReservedBits(11, 21)
180                 ;
181 
182             Registers.Ahb1PeripheralReset.Define(this)
183                 .WithTaggedFlag("GPDMA1RST", 0)
184                 .WithReservedBits(1, 11)
185                 .WithTaggedFlag("CRCRST", 12)
186                 .WithReservedBits(13, 3)
187                 .WithTaggedFlag("TSCRST", 16)
188                 .WithReservedBits(17, 15)
189                 ;
190 
191             Registers.Ahb2PeripheralReset.Define(this)
192                 .WithTaggedFlag("GPIOARST", 0)
193                 .WithTaggedFlag("GPIOBRST", 1)
194                 .WithTaggedFlag("GPIOCRST", 2)
195                 .WithReservedBits(3, 4)
196                 .WithTaggedFlag("GPIOHRST", 7)
197                 .WithReservedBits(8, 8)
198                 .WithTaggedFlag("AESRST", 16)
199                 .WithTaggedFlag("HASHRST", 17)
200                 .WithTaggedFlag("RNGRST", 18)
201                 .WithTaggedFlag("SAESRST", 19)
202                 .WithTaggedFlag("HSEMRST", 20)
203                 .WithTaggedFlag("PKARST", 21)
204                 .WithReservedBits(22, 10)
205                 ;
206 
207             Registers.Ahb4PeripheralReset.Define(this)
208                 .WithReservedBits(0, 5)
209                 .WithTaggedFlag("ADC4RST", 5)
210                 .WithReservedBits(6, 26)
211                 ;
212 
213             Registers.Ahb5PeripheralReset.Define(this)
214                 .WithTaggedFlag("RADIORST", 0)
215                 .WithReservedBits(1, 31)
216                 ;
217 
218             Registers.Apb1PeripheralReset1.Define(this)
219                 .WithTaggedFlag("TIM2RST", 0)
220                 .WithTaggedFlag("TIM3RST", 1)
221                 .WithReservedBits(2, 15)
222                 .WithTaggedFlag("USART2RST", 17)
223                 .WithReservedBits(18, 3)
224                 .WithTaggedFlag("I2C1RST", 21)
225                 .WithReservedBits(22, 10)
226                 ;
227 
228             Registers.Apb1PeripheralReset2.Define(this)
229                 .WithReservedBits(0, 5)
230                 .WithTaggedFlag("LPTIM2RST", 5)
231                 .WithReservedBits(6, 26)
232                 ;
233 
234             Registers.Apb2PeripheralReset.Define(this)
235                 .WithReservedBits(0, 11)
236                 .WithTaggedFlag("TIM1RST", 11)
237                 .WithTaggedFlag("SPI1RST", 12)
238                 .WithReservedBits(13, 1)
239                 .WithTaggedFlag("USART1RST", 14)
240                 .WithReservedBits(15, 2)
241                 .WithTaggedFlag("TIM16RST", 17)
242                 .WithTaggedFlag("TIM17RST", 18)
243                 .WithReservedBits(19, 13)
244                 ;
245 
246             Registers.Apb7PeripheralReset.Define(this)
247                 .WithReservedBits(0, 1)
248                 .WithTaggedFlag("SYSCFGRST", 1)
249                 .WithReservedBits(2, 3)
250                 .WithTaggedFlag("SPI3RST", 5)
251                 .WithTaggedFlag("LPUART1RST", 6)
252                 .WithTaggedFlag("I2C3RST", 7)
253                 .WithTaggedFlag("LPTIM1RST", 11)
254                 .WithReservedBits(12, 20)
255                 ;
256 
257             Registers.Ahb1PeripheralClockEnable.Define(this, 0x80000100)
258                 .WithFlag(0, name: "GPDMA1EN")
259                 .WithReservedBits(1, 7)
260                 .WithFlag(8, name: "FLASHEN")
261                 .WithReservedBits(9, 3)
262                 .WithFlag(12, name: "CRCEN")
263                 .WithReservedBits(13, 3)
264                 .WithFlag(16, name: "TSCEN")
265                 .WithFlag(17, name: "RAMCFGEN")
266                 .WithReservedBits(18, 6)
267                 .WithFlag(24, name: "GTZC1EN")
268                 .WithReservedBits(25, 6)
269                 .WithFlag(31, name: "SRAM1EN")
270                 ;
271 
272             Registers.Ahb2PeripheralClockEnable.Define(this, 0x40000000)
273                 .WithFlag(0, name: "GPIOAEN")
274                 .WithFlag(1, name: "GPIOBEN")
275                 .WithFlag(2, name: "GPIOCEN")
276                 .WithReservedBits(3, 4)
277                 .WithFlag(7, name: "GPIOHEN")
278                 .WithReservedBits(8, 8)
279                 .WithFlag(16, name: "AESEN")
280                 .WithFlag(17, name: "HASHEN")
281                 .WithFlag(18, name: "RNGEN")
282                 .WithFlag(19, name: "SAESEN")
283                 .WithFlag(20, name: "HSEMEN")
284                 .WithFlag(21, name: "PKAEN")
285                 .WithReservedBits(22, 8)
286                 .WithFlag(30, name: "SRAM2EN")
287                 .WithReservedBits(31, 1)
288                 ;
289 
290             Registers.Ahb4PeripheralClockEnable.Define(this)
291                 .WithReservedBits(0, 2)
292                 .WithFlag(2, name: "PWREN")
293                 .WithReservedBits(3, 2)
294                 .WithFlag(5, name: "ADC4EN")
295                 .WithReservedBits(6, 26)
296                 ;
297 
298             Registers.Ahb5PeripheralClockEnable.Define(this)
299                 .WithFlag(0, name: "RADIOEN")
300                 .WithReservedBits(1, 31)
301                 ;
302 
303             Registers.Apb1PeripheralClockEnable1.Define(this)
304                 .WithFlag(0, name: "TIM2EN")
305                 .WithFlag(1, name: "TIM3EN")
306                 .WithReservedBits(2, 9)
307                 .WithFlag(11, name: "WWDGEN")
308                 .WithReservedBits(12, 5)
309                 .WithFlag(17, name: "USART2EN")
310                 .WithReservedBits(18, 3)
311                 .WithFlag(21, name: "I2C1EN")
312                 .WithReservedBits(22, 10)
313                 ;
314 
315             Registers.Apb1PeripheralClockEnable2.Define(this)
316                 .WithReservedBits(0, 5)
317                 .WithFlag(5, name: "LPTIM2EN")
318                 .WithReservedBits(6, 26)
319                 ;
320 
321             Registers.Apb2PeripheralClockEnable.Define(this)
322                 .WithReservedBits(0, 11)
323                 .WithFlag(11, name: "TIM1EN")
324                 .WithFlag(12, name: "SPI1EN")
325                 .WithReservedBits(13, 1)
326                 .WithFlag(14, name: "USART1EN")
327                 .WithReservedBits(15, 2)
328                 .WithFlag(17, name: "TIM16EN")
329                 .WithFlag(18, name: "TIM17EN")
330                 .WithReservedBits(19, 13)
331                 ;
332 
333             Registers.Apb7PeripheralClockEnable.Define(this)
334                 .WithReservedBits(0, 1)
335                 .WithFlag(1, name: "SYSCFGEN")
336                 .WithReservedBits(2, 3)
337                 .WithFlag(5, name: "SPI3EN")
338                 .WithFlag(6, name: "LPUART1EN")
339                 .WithFlag(7, name: "I2C3EN")
340                 .WithReservedBits(8, 3)
341                 .WithFlag(11, name: "LPTIM1EN")
342                 .WithReservedBits(12, 9)
343                 .WithFlag(21, name: "RTCAPBEN")
344                 .WithReservedBits(22, 10)
345                 ;
346 
347             Registers.Ahb1PeripheralClockEnableInSleepMode.Define(this, 0xffffffff)
348                 .WithFlag(0, name: "GPDMA1SMEN")
349                 .WithReservedBits(1, 7)
350                 .WithFlag(8, name: "FLASHSMEN")
351                 .WithReservedBits(9, 3)
352                 .WithFlag(12, name: "CRCSMEN")
353                 .WithReservedBits(13, 3)
354                 .WithFlag(16, name: "TSCSMEN")
355                 .WithFlag(17, name: "RAMCFGSMEN")
356                 .WithReservedBits(18, 6)
357                 .WithFlag(24, name: "GTZC1SMEN")
358                 .WithReservedBits(25, 4)
359                 .WithFlag(29, name: "ICACHESMEN")
360                 .WithReservedBits(30, 1)
361                 .WithFlag(31, name: "SRAM1SMEN")
362                 ;
363 
364             Registers.Ahb2PeripheralClockEnableInSleepMode.Define(this, 0xffffffff)
365                 .WithFlag(0, name: "GPIOASMEN")
366                 .WithFlag(1, name: "GPIOBSMEN")
367                 .WithFlag(2, name: "GPIOCSMEN")
368                 .WithReservedBits(3, 4)
369                 .WithFlag(7, name: "GPIOHSMEN")
370                 .WithReservedBits(8, 8)
371                 .WithFlag(16, name: "AESSMEN")
372                 .WithFlag(17, name: "HASHSMEN")
373                 .WithFlag(18, name: "RNGSMEN")
374                 .WithFlag(19, name: "SAESSMEN")
375                 .WithReservedBits(20, 1)
376                 .WithFlag(21, name: "PKASMEN")
377                 .WithReservedBits(22, 8)
378                 .WithFlag(30, name: "SRAM2SMEN")
379                 .WithReservedBits(31, 1)
380                 ;
381 
382             Registers.Ahb4PeripheralClockEnableInSleepMode.Define(this, 0xffffffff)
383                 .WithReservedBits(0, 2)
384                 .WithFlag(2, name: "PWRSMEN")
385                 .WithReservedBits(3, 2)
386                 .WithFlag(5, name: "ADC4SMEN")
387                 .WithReservedBits(6, 26)
388                 ;
389 
390             Registers.Ahb5PeripheralClockEnableInSleepMode.Define(this, 0xffffffff)
391                 .WithFlag(0, name: "RADIOSMEN")
392                 .WithReservedBits(1, 31)
393                 ;
394 
395             Registers.Apb1PeripheralClockEnableInSleepMode1.Define(this)
396                 .WithFlag(0, name: "TIM2SMEN")
397                 .WithFlag(1, name: "TIM3SMEN")
398                 .WithReservedBits(2, 9)
399                 .WithFlag(11, name: "WWDGSMEN")
400                 .WithReservedBits(12, 5)
401                 .WithFlag(17, name: "USART2SMEN")
402                 .WithReservedBits(18, 3)
403                 .WithFlag(21, name: "I2C1SMEN")
404                 .WithReservedBits(22, 10)
405                 ;
406 
407             Registers.Apb1PeripheralClockEnableInSleepMode2.Define(this)
408                 .WithReservedBits(0, 5)
409                 .WithFlag(5, name: "LPTIM2SMEN")
410                 .WithReservedBits(6, 26)
411                 ;
412 
413             Registers.Apb2PeripheralClockEnableInSleepMode.Define(this, 0xffffffff)
414                 .WithReservedBits(0, 11)
415                 .WithFlag(11, name: "TIM1SMEN")
416                 .WithFlag(12, name: "SPI1SMEN")
417                 .WithReservedBits(13, 1)
418                 .WithFlag(14, name: "USART1SMEN")
419                 .WithReservedBits(15, 2)
420                 .WithFlag(17, name: "TIM16SMEN")
421                 .WithFlag(18, name: "TIM17SMEN")
422                 .WithReservedBits(19, 13)
423                 ;
424 
425             Registers.Apb7PeripheralClockEnableInSleepMode.Define(this, 0xffffffff)
426                 .WithReservedBits(0, 1)
427                 .WithFlag(1, name: "SYSCFGSMEN")
428                 .WithReservedBits(2, 3)
429                 .WithFlag(5, name: "SPI3SMEN")
430                 .WithFlag(6, name: "LPUART1SMEN")
431                 .WithFlag(7, name: "I2C3SMEN")
432                 .WithReservedBits(8, 3)
433                 .WithFlag(11, name: "LPTIM1SMEN")
434                 .WithReservedBits(12, 9)
435                 .WithFlag(21, name: "RTCAPBSMEN")
436                 .WithReservedBits(22, 10)
437                 ;
438 
439             Registers.PeripheralsIndependentClockConfiguration1.Define(this)
440                 .WithValueField(0, 2, name: "USART1SEL")
441                 .WithValueField(2, 2, name: "USART2SEL")
442                 .WithReservedBits(4, 6)
443                 .WithValueField(10, 2, name: "I2C1SEL")
444                 .WithReservedBits(12, 6)
445                 .WithEnumField(18, 2, out lpTimer2Clock, name: "LPTIM2SEL")
446                 .WithValueField(20, 2, name: "SPI1SEL")
447                 .WithTag("SYSTICKSEL", 22, 2)
448                 .WithReservedBits(24, 7)
449                 .WithFlag(31, name: "TIMICSEL")
450                 .WithChangeCallback((_, __) => UpdateClocks());
451                 ;
452 
453             Registers.PeripheralsIndependentClockConfiguration2.Define(this)
454                 .WithReservedBits(0, 12)
455                 .WithValueField(12, 2, name: "RNGSEL")
456                 .WithReservedBits(14, 8)
457                 ;
458 
459             Registers.PeripheralsIndependentClockConfiguration3.Define(this)
460                 .WithValueField(0, 2, name: "LPUART1SEL")
461                 .WithReservedBits(2, 1)
462                 .WithValueField(3, 2, name: "SPI3SEL")
463                 .WithReservedBits(5, 1)
464                 .WithValueField(6, 2, name: "I2C3SEL")
465                 .WithReservedBits(8, 2)
466                 .WithEnumField(10, 2, out lpTimer1Clock, name: "LPTIM1SEL")
467                 .WithValueField(12, 3, name: "ADCSEL")
468                 .WithReservedBits(15, 17)
469                 .WithChangeCallback((_, __) => UpdateClocks());
470                 ;
471 
472             Registers.BackupDomainControl1.Define(this, 0x8)
473                 .WithFlag(0, out var lseEnable, name: "LSEON")
474                 .WithFlag(1, FieldMode.Read, valueProviderCallback: _ => lseEnable.Value, name: "LSERDY")
475                 .WithFlag(2, name: "LSEBYP")
476                 .WithValueField(3, 2, name: "LSEDRV")
477                 .WithFlag(5, name: "LSECSSON")
478                 .WithFlag(6, FieldMode.Read, valueProviderCallback: _ => false, name: "LSECSSD")
479                 .WithFlag(7, out var lseSystemClockEnable, name: "LSESYSEN")
480                 .WithValueField(8, 2, name: "RTCSEL")
481                 .WithReservedBits(10, 1)
482                 .WithFlag(11, FieldMode.Read, valueProviderCallback: _ => lseSystemClockEnable.Value, name: "LSESYSRDY")
483                 .WithFlag(12, name: "LSEGFON")
484                 .WithValueField(13, 2, name: "LSETRIM")
485                 .WithReservedBits(15, 1)
486                 .WithFlag(16, name: "BDRST")
487                 .WithReservedBits(17, 1)
488                 .WithTag("RADIOSTSEL", 18, 2)
489                 .WithReservedBits(20, 4)
490                 .WithFlag(24, name: "LSCOEN")
491                 .WithFlag(25, name: "LSCOSEL")
492                 .WithFlag(26, out var lsi1Enable, name: "LSI1ON")
493                 .WithFlag(27, FieldMode.Read, valueProviderCallback: _ => lsi1Enable.Value, name: "LSI1RDY")
494                 .WithFlag(28, name: "LSI1PREDIV")
495                 .WithReservedBits(29, 3)
496                 ;
497 
498             Registers.ControlStatus.Define(this, 0xc000000)
499                 .WithReservedBits(0, 23)
500                 .WithTaggedFlag("RMVF", 23)
501                 .WithReservedBits(24, 1)
502                 .WithTaggedFlag("OBLRSTF", 25)
503                 .WithTaggedFlag("PINRSTF", 26)
504                 .WithTaggedFlag("BORRSTF", 27)
505                 .WithTaggedFlag("SFTRSTF", 28)
506                 .WithTaggedFlag("IWDGRSTF", 29)
507                 .WithTaggedFlag("WWDGRSTF", 30)
508                 .WithTaggedFlag("LPWRRSTF", 31)
509                 ;
510 
511             Registers.BackupDomainControl2.Define(this)
512                 .WithValueField(0, 3, name: "LSI2MODE")
513                 .WithReservedBits(3, 1)
514                 .WithValueField(4, 4, name: "LSI2CFG")
515                 .WithReservedBits(8, 24)
516                 ;
517 
518             Registers.SecureConfiguration.Define(this)
519                 .WithFlag(0, name: "HSISEC")
520                 .WithFlag(1, name: "HSESEC")
521                 .WithReservedBits(2, 1)
522                 .WithFlag(3, name: "LSISEC")
523                 .WithFlag(4, name: "LSESEC")
524                 .WithFlag(5, name: "SYSCLKSEC")
525                 .WithFlag(6, name: "PRESCSEC")
526                 .WithFlag(7, name: "PLL1SEC")
527                 .WithReservedBits(8, 4)
528                 .WithFlag(12, name: "RMVFSEC")
529                 .WithReservedBits(13, 19)
530                 ;
531 
532             Registers.PrivilegeConfiguration.Define(this)
533                 .WithFlag(0, name: "SPRIV")
534                 .WithFlag(1, name: "NSPRIV")
535                 .WithReservedBits(2, 30)
536                 ;
537 
538             Registers.ClockConfiguration4.Define(this, 0x10)
539                 .WithValueField(0, 3, name: "HPRE5")
540                 .WithReservedBits(3, 1)
541                 .WithFlag(4, name: "HDIV5")
542                 .WithReservedBits(5, 27)
543                 ;
544 
545             Registers.RadioPeripheralClockEnable.Define(this)
546                 .WithReservedBits(0, 1)
547                 .WithFlag(1, out var basebandClockEnable, name: "BBCLKEN")
548                 .WithReservedBits(2, 14)
549                 .WithTaggedFlag("STRADIOCLKON", 16)
550                 .WithFlag(17, FieldMode.Read, valueProviderCallback: _ => basebandClockEnable.Value, name: "RADIOCLKRDY")
551                 .WithReservedBits(18, 14)
552                 ;
553 
554             Registers.ExternalClockSourcesCalibration.Define(this, 0x200000)
555                 .WithReservedBits(0, 16)
556                 .WithValueField(16, 6, name: "HSETRIM")
557                 .WithReservedBits(22, 10)
558                 ;
559 
560         }
561 
PrescaleApbAhb(long input, IValueRegisterField prescaler)562         private long PrescaleApbAhb(long input, IValueRegisterField prescaler)
563         {
564             var ppre = (int)prescaler.Value;
565             // 0xx - no division
566             if((ppre & 4) == 0)
567             {
568                 return input;
569             }
570             // 1xx - divided by 2^(xx + 1), i.e. 00 -> 2, 01 -> 4, ...
571             var logDivisor = (ppre & 3) + 1;
572             return input >> logDivisor;
573         }
574 
GetLpTimerClock(LpTimerClockSource source, long apbFrequency)575         private long GetLpTimerClock(LpTimerClockSource source, long apbFrequency)
576         {
577             switch(source)
578             {
579                 case LpTimerClockSource.Apb:
580                     return apbFrequency;
581                 case LpTimerClockSource.Lsi:
582                     return lsiFrequency;
583                 case LpTimerClockSource.Hsi16:
584                     return Hsi16Frequency;
585                 case LpTimerClockSource.Lse:
586                     return lseFrequency;
587                 default:
588                     throw new ArgumentException("Unreachable: Invalid LpTimer clock source");
589             }
590         }
591 
592         // Clock tree
593         private long DividedHse32 => hseFrequency / (hsePrescaler.Value ? 2 : 1);
594         private long Pll1Source
595         {
596             get
597             {
598                 switch(pll1Source.Value)
599                 {
600                     default:
601                         this.Log(LogLevel.Warning, "PLL1 frequency was required without a valid PLL source configured");
602                         goto case PllEntryClockSource.Hsi16;
603                     case PllEntryClockSource.None:
604                         return 0;
605                     case PllEntryClockSource.DividedHse32:
606                         return DividedHse32;
607                     case PllEntryClockSource.Hsi16:
608                         return Hsi16Frequency;
609                 }
610             }
611         }
612         private long Pll1VcoInput => Pll1Source / ((long)pll1Prescaler.Value + 1);
613         private long Pll1VcoOutput => Pll1VcoInput * ((long)pll1Multiplier.Value + 1);
614         private long Pll1Pclk => Pll1VcoOutput / ((long)pll1DividerP.Value + 1);
615         private long Pll1Qclk => Pll1VcoOutput / ((long)pll1DividerQ.Value + 1);
616         private long Pll1Rclk => Pll1VcoOutput / ((long)pll1DividerR.Value + 1);
617         private long SystemClock
618         {
619             get
620             {
621                 switch(systemClockSwitch.Value)
622                 {
623                     default:
624                     case SystemClockSource.Hsi16:
625                         return Hsi16Frequency;
626                     case SystemClockSource.DividedHse32:
627                         return DividedHse32;
628                     case SystemClockSource.Pll1Rclk:
629                         return Pll1Rclk;
630                 }
631             }
632         }
633         private long AhbClock => PrescaleApbAhb(SystemClock, ahbPrescaler); // hclk1
634         private long Apb1Clock => PrescaleApbAhb(AhbClock, apb1Prescaler); // pclk1
635         private long Apb2Clock => PrescaleApbAhb(AhbClock, apb2Prescaler); // pclk2
636         private long Apb7Clock => PrescaleApbAhb(AhbClock, apb7Prescaler); // pclk7
637         private long LpTimer1Clock => GetLpTimerClock(lpTimer1Clock.Value, Apb7Clock);
638         private long LpTimer2Clock => GetLpTimerClock(lpTimer2Clock.Value, Apb1Clock);
639 
640         private IFlagRegisterField hsePrescaler;
641         private IEnumRegisterField<SystemClockSource> systemClockSwitch;
642         private IValueRegisterField ahbPrescaler;
643         private IValueRegisterField apb1Prescaler;
644         private IValueRegisterField apb2Prescaler;
645         private IValueRegisterField apb7Prescaler;
646         private IEnumRegisterField<PllEntryClockSource> pll1Source;
647         private IValueRegisterField pll1Prescaler; // PLL1M
648         private IValueRegisterField pll1Multiplier; // PLL1N
649         private IValueRegisterField pll1DividerP; // PLL1P
650         private IValueRegisterField pll1DividerQ; // PLL1Q
651         private IValueRegisterField pll1DividerR; // PLL1R
652         private IEnumRegisterField<LpTimerClockSource> lpTimer1Clock;
653         private IEnumRegisterField<LpTimerClockSource> lpTimer2Clock;
654 
655         private readonly IHasFrequency nvic;
656         private readonly IHasFrequency lptim1;
657         private readonly IHasFrequency lptim2;
658         private readonly long lsiFrequency;
659         private readonly long lseFrequency;
660         private readonly long hseFrequency;
661 
662         private const long DefaultLsiFrequency = 32000;
663         private const long DefaultLseFrequency = 32768;
664         private const long DefaultHseFreqeuency = 32000000;
665         private const long Hsi16Frequency = 16000000;
666 
667         private enum PllEntryClockSource
668         {
669             None = 0,
670             // 1 = reserved
671             Hsi16 = 2,
672             DividedHse32 = 3,
673         }
674 
675         private enum SystemClockSource
676         {
677             Hsi16 = 0,
678             // 1 = reserved
679             DividedHse32 = 2,
680             Pll1Rclk = 3,
681         }
682 
683         private enum LpTimerClockSource
684         {
685             Apb = 0,
686             Lsi = 1,
687             Hsi16 = 2,
688             Lse = 3,
689         }
690 
691         private enum Registers
692         {
693             ClockControl = 0x0, // CR
694             // gap intended
695             InternalClockSourcesCalibration3 = 0x10, // ICSCR3
696             // gap intended
697             ClockConfiguration1 = 0x1c, // CFGR1
698             ClockConfiguration2 = 0x20, // CFGR2
699             ClockConfiguration3 = 0x24, // CFGR3
700             Pll1Configuration = 0x28, // PLL1CFGR
701             // gap intended
702             Pll1Dividers = 0x34, // PLL1DIVR
703             Pll1FractionalDivider = 0x38, // PLL1FRACR
704             // gap intended
705             ClockInterruptEnable = 0x50, // CIER
706             ClockInterruptFlag = 0x54, // CIFR
707             ClockInterruptClear = 0x58, // CICR
708             // gap intended
709             Ahb1PeripheralReset = 0x60, // AHB1RSTR
710             Ahb2PeripheralReset = 0x64, // AHB2RSTR
711             // gap intended
712             Ahb4PeripheralReset = 0x6c, // AHB4RSTR
713             Ahb5PeripheralReset = 0x70, // AHB5RSTR
714             Apb1PeripheralReset1 = 0x74, // APB1RSTR1
715             Apb1PeripheralReset2 = 0x78, // APB1RSTR2
716             Apb2PeripheralReset = 0x7c, // APB2RSTR
717             Apb7PeripheralReset = 0x80, // APB7RSTR
718             // gap intended
719             Ahb1PeripheralClockEnable = 0x88, // AHB1ENR
720             Ahb2PeripheralClockEnable = 0x8c, // AHB2ENR
721             // gap intended
722             Ahb4PeripheralClockEnable = 0x94, // AHB4ENR
723             Ahb5PeripheralClockEnable = 0x98, // AHB5ENR
724             Apb1PeripheralClockEnable1 = 0x9c, // APB1ENR1
725             Apb1PeripheralClockEnable2 = 0xa0, // APB1ENR2
726             Apb2PeripheralClockEnable = 0xa4, // APB2ENR
727             Apb7PeripheralClockEnable = 0xa8, // APB7ENR
728             // gap intended
729             Ahb1PeripheralClockEnableInSleepMode = 0xb0, // AHB1SMENR
730             Ahb2PeripheralClockEnableInSleepMode = 0xb4, // AHB2SMENR
731             // gap intended
732             Ahb4PeripheralClockEnableInSleepMode = 0xbc, // AHB4SMENR
733             Ahb5PeripheralClockEnableInSleepMode = 0xc0, // AHB5SMENR
734             Apb1PeripheralClockEnableInSleepMode1 = 0xc4, // APB1SMENR1
735             Apb1PeripheralClockEnableInSleepMode2 = 0xc8, // APB1SMENR2
736             Apb2PeripheralClockEnableInSleepMode = 0xcc, // APB2SMENR
737             Apb7PeripheralClockEnableInSleepMode = 0xd0, // APB7SMENR
738             // gap intended
739             PeripheralsIndependentClockConfiguration1 = 0xe0, // CCIPR1
740             PeripheralsIndependentClockConfiguration2 = 0xe4, // CCIPR2
741             PeripheralsIndependentClockConfiguration3 = 0xe8, // CCIPR3
742             // gap intended
743             BackupDomainControl1 = 0xf0, // BDCR1
744             ControlStatus = 0xf4, // CSR
745             BackupDomainControl2 = 0xf8, // BDCR2
746             // gap intended
747             SecureConfiguration = 0x110, // SECCFGR
748             PrivilegeConfiguration = 0x114, // PRIVCFGR
749             // gap intended
750             ClockConfiguration4 = 0x200, // CFGR4
751             // gap intended
752             RadioPeripheralClockEnable = 0x208, // RADIOENR
753             // gap intended
754             ExternalClockSourcesCalibration = 0x210, // ECSCR1
755         }
756     }
757 }
758