1 // 2 // Copyright (c) 2010-2020 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 8 using System; 9 using System.Collections.Generic; 10 using Antmicro.Renode.Core; 11 using Antmicro.Renode.Core.Structure.Registers; 12 using Antmicro.Renode.Peripherals.Bus; 13 using Antmicro.Renode.Peripherals.Timers; 14 15 namespace Antmicro.Renode.Peripherals.Miscellaneous 16 { 17 [AllowedTranslations(AllowedTranslation.ByteToDoubleWord | AllowedTranslation.WordToDoubleWord)] 18 public sealed class STM32F4_RCC : IDoubleWordPeripheral, IKnownSize, IProvidesRegisterCollection<DoubleWordRegisterCollection> 19 { STM32F4_RCC(IMachine machine, STM32F4_RTC rtcPeripheral)20 public STM32F4_RCC(IMachine machine, STM32F4_RTC rtcPeripheral) 21 { 22 // Renode, in general, does not include clock control peripherals. 23 // While this is doable, it seldom benefits real software development 24 // and is very cumbersome to maintain. 25 // 26 // To properly support the RTC peripheral, we need to add this stub class. 27 // It is common in Renode that whenever a register is implemented, it 28 // either contains actual logic or tags, indicating not implemented fields. 29 // 30 // Here, however, we want to fake most of the registers as r/w values. 31 // Usually we implemented this logic with Python peripherals. 32 // 33 // Keep in mind that most of these registers do not affect other 34 // peripherals or their clocks. 35 var registersMap = new Dictionary<long, DoubleWordRegister> 36 { 37 {(long)Registers.ClockControl, new DoubleWordRegister(this, 0x483) 38 .WithFlag(0, out var hsion, name: "HSION") 39 .WithFlag(1, FieldMode.Read, valueProviderCallback: _ => hsion.Value, name: "HSIRDY") 40 .WithReservedBits(2, 1) 41 .WithValueField(3, 5, name: "HSITRIM") 42 .WithTag("HSICAL", 8, 8) 43 .WithFlag(16, out var hseon, name: "HSEON") 44 .WithFlag(17, FieldMode.Read, valueProviderCallback: _ => hseon.Value, name: "HSERDY") 45 .WithTag("HSEBYP", 18, 1) 46 .WithTag("CSSON", 19, 1) 47 .WithReservedBits(20, 4) 48 .WithFlag(24, out var pllon, name: "PLLON") 49 .WithFlag(25, FieldMode.Read, valueProviderCallback: _ => pllon.Value, name: "PLLRDY") 50 .WithFlag(26, out var plli2son, name: "PLLI2SON") 51 .WithFlag(27, FieldMode.Read, valueProviderCallback: _ => plli2son.Value, name: "PLLI2SRDY") 52 .WithFlag(28, out var pllsaion, name: "PLLSAION") 53 .WithFlag(29, FieldMode.Read, valueProviderCallback: _ => pllsaion.Value, name: "PLLSAIRDY") 54 .WithReservedBits(30, 2) 55 }, 56 {(long)Registers.PLLConfiguration, new DoubleWordRegister(this, 0x24003010) 57 .WithValueField(0, 6, name: "PLLM") 58 .WithValueField(6, 9, name: "PLLN") 59 .WithReservedBits(15, 1) 60 .WithValueField(16, 2, name: "PLLP") 61 .WithReservedBits(18, 4) 62 .WithValueField(22, 1, name: "PLLSRC") 63 .WithReservedBits(23, 1) 64 .WithValueField(24, 4, name: "PLLQ") 65 .WithReservedBits(28, 4) 66 }, 67 {(long)Registers.ClockConfiguration, new DoubleWordRegister(this) 68 .WithValueField(0, 2, out var systemClockSwitch, name: "SW") 69 .WithValueField(2, 2, FieldMode.Read, name: "SWS", valueProviderCallback: _ => systemClockSwitch.Value) 70 .WithValueField(4, 4, name: "HPRE") 71 .WithReservedBits(8, 2) 72 .WithValueField(10, 3, name: "PPRE1") 73 .WithValueField(13, 3, name: "PPRE2") 74 .WithValueField(16, 5, name: "RTCPRE") 75 .WithValueField(21, 2, name: "MCO1") 76 .WithValueField(23, 1, name: "I2SSCR") 77 .WithValueField(24, 3, name: "MCO1PRE") 78 .WithValueField(27, 3, name: "MCO2PRE") 79 .WithValueField(30, 2, name: "MCO2") 80 }, 81 //ClockInterrupt not implemented 82 {(long)Registers.AHB1PeripheralReset, new DoubleWordRegister(this) 83 .WithValueField(0, 11, name: "GPIOxRST") 84 .WithReservedBits(11, 1) 85 .WithFlag(12, name: "CRCRST") 86 .WithReservedBits(13, 8) 87 .WithValueField(21, 3, name: "DMAxRST") 88 .WithReservedBits(24, 1) 89 .WithFlag(25, name: "ETHMACRST") 90 .WithReservedBits(26, 3) 91 .WithFlag(29, name: "OTGHSRST") 92 .WithReservedBits(30, 2) 93 }, 94 {(long)Registers.AHB2PeripheralReset, new DoubleWordRegister(this) 95 .WithFlag(0, name: "DCMIRST") 96 .WithReservedBits(1, 3) 97 .WithFlag(4, name: "CRYPRST") 98 .WithFlag(5, name: "HASHRST") 99 .WithFlag(6, name: "RNGRST") 100 .WithFlag(7, name: "OTGFSRST") 101 .WithReservedBits(8, 24) 102 }, 103 {(long)Registers.AHB3PeripheralReset, new DoubleWordRegister(this) 104 .WithFlag(0, name: "FMCRST") 105 .WithReservedBits(1, 30) 106 }, 107 {(long)Registers.APB1PeripheralReset, new DoubleWordRegister(this) 108 .WithValueField(0, 9, name: "TIMxRST") 109 .WithReservedBits(9, 2) 110 .WithFlag(11, name: "WWDGRST") 111 .WithReservedBits(12, 2) 112 .WithValueField(14, 2, name: "SPIxRST") 113 .WithReservedBits(16, 1) 114 .WithValueField(17, 4, name: "UARTxRST") 115 .WithValueField(21, 3, name: "I2CxRST") 116 .WithReservedBits(24, 1) 117 .WithValueField(25, 2, name: "CANxRST") 118 .WithReservedBits(27, 1) 119 .WithFlag(28, name: "PWRRST") 120 .WithFlag(29, name: "DACRST") 121 .WithValueField(30, 2, name: "UARTxRST") 122 }, 123 {(long)Registers.APB2PeripheralReset, new DoubleWordRegister(this) 124 .WithValueField(0, 2, name: "TIMxRST") 125 .WithReservedBits(2, 2) 126 .WithValueField(4, 2, name: "USARTxRST") 127 .WithReservedBits(6, 2) 128 .WithFlag(8, name: "ADCRST") 129 .WithReservedBits(9, 2) 130 .WithFlag(11, name: "SDIORST") 131 .WithValueField(12, 2, name: "SPIxRST") 132 .WithFlag(14, name: "SYSCFGRST") 133 .WithReservedBits(15, 1) 134 .WithValueField(16, 3, name: "TIMxRST") 135 .WithReservedBits(19, 1) 136 .WithValueField(20, 2, name: "SPIxRST") 137 .WithFlag(22, name: "SAI1RST") 138 .WithReservedBits(23, 3) 139 .WithFlag(26, name: "LTDCRST") 140 .WithReservedBits(27, 5) 141 }, 142 {(long)Registers.AHB1PeripheralClockEnable, new DoubleWordRegister(this) 143 .WithValueField(0, 11, name: "GPIOxEN") 144 .WithReservedBits(11, 1) 145 .WithFlag(12, name: "CRCEN") 146 .WithReservedBits(13, 5) 147 .WithFlag(18, name: "BKPSRAMEN") 148 .WithReservedBits(19, 1) 149 .WithFlag(20, name: "CCMDATARAMEN") 150 .WithValueField(21, 3, name: "DMAxEN") 151 .WithReservedBits(24, 1) 152 .WithValueField(25, 4, name: "ETHMACxEN") 153 .WithValueField(29, 2, name: "OTGHSxEN") 154 .WithReservedBits(31, 1) 155 }, 156 {(long)Registers.AHB2PeripheralClockEnable, new DoubleWordRegister(this) 157 .WithFlag(0, name: "DCMIEN") 158 .WithReservedBits(1, 3) 159 .WithFlag(4, name: "CRYPEN") 160 .WithFlag(5, name: "HASHEN") 161 .WithFlag(6, name: "RNGEN") 162 .WithFlag(7, name: "OTGFSEN") 163 .WithReservedBits(8, 24) 164 }, 165 {(long)Registers.AHB3PeripheralClockEnable, new DoubleWordRegister(this) 166 .WithFlag(0, name: "FMCEN") 167 .WithReservedBits(1, 30) 168 }, 169 {(long)Registers.APB1PeripheralClockEnable, new DoubleWordRegister(this) 170 .WithValueField(0, 9, name: "TIMxEN") 171 .WithReservedBits(9, 2) 172 .WithFlag(11, name: "WWDGEN") 173 .WithReservedBits(12, 2) 174 .WithValueField(14, 2, name: "SPIxEN") 175 .WithReservedBits(16, 1) 176 .WithValueField(17, 4, name: "UARTxEN") 177 .WithValueField(21, 3, name: "I2CxEN") 178 .WithReservedBits(24, 1) 179 .WithValueField(25, 2, name: "CANxEN") 180 .WithReservedBits(27, 1) 181 .WithFlag(28, name: "PWREN") 182 .WithFlag(29, name: "DACEN") 183 .WithValueField(30, 2, name: "UARTxEN") 184 }, 185 {(long)Registers.APB2PeripheralClockEnable, new DoubleWordRegister(this) 186 .WithValueField(0, 2, name: "TIMxEN") 187 .WithReservedBits(2, 2) 188 .WithValueField(4, 2, name: "USARTxEN") 189 .WithReservedBits(6, 2) 190 .WithValueField(8, 3, name: "ADCxEN") 191 .WithFlag(11, name: "SDIOEN") 192 .WithValueField(12, 2, name: "SPIxEN") 193 .WithFlag(14, name: "SYSCFGEN") 194 .WithReservedBits(15, 1) 195 .WithValueField(16, 3, name: "TIMxEN") 196 .WithReservedBits(19, 1) 197 .WithValueField(20, 2, name: "SPIxEN") 198 .WithFlag(22, name: "SAI1EN") 199 .WithReservedBits(23, 3) 200 .WithFlag(26, name: "LTDCEN") 201 .WithReservedBits(27, 5) 202 }, 203 {(long)Registers.AHB1PeripheralClockEnableInLowPowerMode, new DoubleWordRegister(this) 204 .WithValueField(0, 11, name: "GPIOxLPEN") 205 .WithReservedBits(11, 1) 206 .WithFlag(12, name: "CRCLPEN") 207 .WithReservedBits(13, 2) 208 .WithFlag(15, name: "FLITFLPEN") 209 .WithValueField(16, 2, name: "SRAMxLPEN") 210 .WithFlag(18, name: "BKPSRAMLPEN") 211 .WithFlag(19, name: "SRAM3LPEN") 212 .WithReservedBits(20, 1) 213 .WithValueField(21, 3, name: "DMAxLPEN") 214 .WithReservedBits(24, 1) 215 .WithValueField(25, 4, name: "ETHMACxLPEN") 216 .WithValueField(29, 2, name: "OTGHSxLPEN") 217 .WithReservedBits(31, 1) 218 }, 219 {(long)Registers.AHB2PeripheralClockEnableInLowPowerMode, new DoubleWordRegister(this) 220 .WithFlag(0, name: "DCMILPEN") 221 .WithReservedBits(1, 3) 222 .WithFlag(4, name: "CRYPLPEN") 223 .WithFlag(5, name: "HASHLPEN") 224 .WithFlag(6, name: "RNGLPEN") 225 .WithFlag(7, name: "OTGFSLPEN") 226 .WithReservedBits(8, 24) 227 }, 228 {(long)Registers.AHB3PeripheralClockEnableInLowPowerMode, new DoubleWordRegister(this) 229 .WithFlag(0, name: "FMCLPEN") 230 .WithReservedBits(1, 30) 231 }, 232 {(long)Registers.APB1PeripheralClockEnableInLowPowerMode, new DoubleWordRegister(this) 233 .WithValueField(0, 9, name: "TIMxLPEN") 234 .WithReservedBits(9, 2) 235 .WithFlag(11, name: "WWDGLPEN") 236 .WithReservedBits(12, 2) 237 .WithValueField(14, 2, name: "SPIxLPEN") 238 .WithReservedBits(16, 1) 239 .WithValueField(17, 4, name: "UARTxLPEN") 240 .WithValueField(21, 3, name: "I2CxLPEN") 241 .WithReservedBits(24, 1) 242 .WithValueField(25, 2, name: "CANxLPEN") 243 .WithReservedBits(27, 1) 244 .WithFlag(28, name: "PWRLPEN") 245 .WithFlag(29, name: "DACLPEN") 246 .WithValueField(30, 2, name: "UARTxLPEN") 247 }, 248 {(long)Registers.APB2PeripheralClockEnableInLowPowerMode, new DoubleWordRegister(this) 249 .WithValueField(0, 2, name: "TIMxLPEN") 250 .WithReservedBits(2, 2) 251 .WithValueField(4, 2, name: "USARTxLPEN") 252 .WithReservedBits(6, 2) 253 .WithValueField(8, 3, name: "ADCxLPEN") 254 .WithFlag(11, name: "SDIOLPEN") 255 .WithValueField(12, 2, name: "SPIxLPEN") 256 .WithFlag(14, name: "SYSCFGLPEN") 257 .WithReservedBits(15, 1) 258 .WithValueField(16, 3, name: "TIMxLPEN") 259 .WithReservedBits(19, 1) 260 .WithValueField(20, 2, name: "SPIxLPEN") 261 .WithFlag(22, name: "SAI1LPEN") 262 .WithReservedBits(23, 3) 263 .WithFlag(26, name: "LTDCLPEN") 264 .WithReservedBits(27, 5) 265 }, 266 {(long)Registers.BackupDomainControl, new DoubleWordRegister(this) 267 .WithFlag(0, out var lseon, name: "LSEON") 268 .WithFlag(1, FieldMode.Read, valueProviderCallback: _ => lseon.Value, name: "LSERDY") 269 .WithValueField(2, 1, name: "LSEBYP") 270 .WithReservedBits(3, 5) 271 .WithValueField(8, 2, name: "RTCSEL") 272 .WithReservedBits(10, 5) 273 .WithFlag(15, name: "RTCEN", 274 writeCallback: (_, value) => 275 { 276 if(value) 277 { 278 machine.SystemBus.EnablePeripheral(rtcPeripheral); 279 } 280 else 281 { 282 machine.SystemBus.DisablePeripheral(rtcPeripheral); 283 } 284 }) 285 .WithValueField(16, 1, name: "BDRST") 286 .WithReservedBits(17, 15) 287 }, 288 {(long)Registers.ClockControlAndStatus, new DoubleWordRegister(this, 0x0E000000) 289 .WithFlag(0, out var lsion, name: "LSION") 290 .WithFlag(1, FieldMode.Read, valueProviderCallback: _ => lsion.Value, name: "LSIRDY") 291 .WithReservedBits(2, 21) 292 .WithTag("RMVF", 24, 1) 293 .WithTag("BORRSTF", 25, 1) 294 .WithTag("PINRSTF", 26, 1) 295 .WithTag("PORRSTF", 27, 1) 296 .WithTag("SFTRSTF", 28, 1) 297 .WithTag("IWDGRSTF", 29, 1) 298 .WithTag("WWDGRSTF", 30, 1) 299 .WithTag("LPWRRSTF", 31, 1) 300 }, 301 {(long)Registers.SpreadSpectrumClockGeneration, new DoubleWordRegister(this) 302 .WithValueField(0, 13, name: "MODPER") 303 .WithValueField(13, 15, name: "INCSTEP") 304 .WithReservedBits(28, 2) 305 .WithFlag(30, name: "SPREADSEL") 306 .WithFlag(31, name: "SSCGEN") 307 }, 308 {(long)Registers.PLLI2SConfiguration, new DoubleWordRegister(this, 0x24003000) 309 .WithReservedBits(0, 6) 310 .WithValueField(6, 9, name: "PLLI2SNx") 311 .WithReservedBits(15, 9) 312 .WithValueField(24, 4, name: "PLLI2SQ") 313 .WithValueField(28, 3, name: "PLLI2SRx") 314 .WithReservedBits(31, 1) 315 }, 316 {(long)Registers.PLLSAIConfiguration, new DoubleWordRegister(this, 0x24003000) 317 .WithReservedBits(0, 6) 318 .WithValueField(6, 9, name: "PLLSAIN") 319 .WithReservedBits(15, 9) 320 .WithValueField(24, 4, name: "PLLSAIQ") 321 .WithValueField(28, 3, name: "PLLSAIR") 322 .WithReservedBits(31, 1) 323 }, 324 {(long)Registers.DedicatedClockConfiguration, new DoubleWordRegister(this) 325 .WithValueField(0, 5, name: "PLLI2SDIVQ") 326 .WithReservedBits(5, 3) 327 .WithValueField(8, 5, name: "PLLSAIDIVQ") 328 .WithReservedBits(13, 3) 329 .WithValueField(16, 2, name: "PLLSAIDIVR") 330 .WithReservedBits(18, 2) 331 .WithValueField(20, 2, name: "SAI1ASRC") 332 .WithValueField(22, 2, name: "SAI1BSRC") 333 .WithFlag(24, name: "TIMPRE") 334 .WithReservedBits(25, 7) 335 }, 336 }; 337 338 RegistersCollection = new DoubleWordRegisterCollection(this, registersMap); 339 } 340 ReadDoubleWord(long offset)341 public uint ReadDoubleWord(long offset) 342 { 343 return RegistersCollection.Read(offset); 344 } 345 WriteDoubleWord(long offset, uint value)346 public void WriteDoubleWord(long offset, uint value) 347 { 348 RegistersCollection.Write(offset, value); 349 } 350 Reset()351 public void Reset() 352 { 353 RegistersCollection.Reset(); 354 } 355 356 public long Size => 0x400; 357 358 public DoubleWordRegisterCollection RegistersCollection { get; } 359 360 private enum Registers 361 { 362 ClockControl = 0x0, 363 PLLConfiguration = 0x4, 364 ClockConfiguration = 0x8, 365 ClockInterrupt = 0xC, 366 AHB1PeripheralReset = 0x10, 367 AHB2PeripheralReset = 0x14, 368 AHB3PeripheralReset = 0x18, 369 //gap 370 APB1PeripheralReset = 0x20, 371 APB2PeripheralReset = 0x24, 372 //gap 373 AHB1PeripheralClockEnable = 0x30, 374 AHB2PeripheralClockEnable = 0x34, 375 AHB3PeripheralClockEnable = 0x38, 376 APB1PeripheralClockEnable = 0x40, 377 APB2PeripheralClockEnable = 0x44, 378 AHB1PeripheralClockEnableInLowPowerMode = 0x50, 379 AHB2PeripheralClockEnableInLowPowerMode = 0x54, 380 AHB3PeripheralClockEnableInLowPowerMode = 0x58, 381 APB1PeripheralClockEnableInLowPowerMode = 0x60, 382 APB2PeripheralClockEnableInLowPowerMode = 0x64, 383 BackupDomainControl = 0x70, 384 ClockControlAndStatus = 0x74, 385 SpreadSpectrumClockGeneration = 0x80, 386 PLLI2SConfiguration = 0x84, 387 PLLSAIConfiguration = 0x88, 388 DedicatedClockConfiguration = 0x8C, 389 } 390 } 391 } 392