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