1 // 2 // Copyright (c) 2010-2018 Antmicro 3 // 4 // This file is licensed under the MIT License. 5 // Full license text is available in 'licenses/MIT.txt'. 6 // 7 using Antmicro.Renode.Peripherals.Bus; 8 using Antmicro.Renode.Logging; 9 using Antmicro.Renode.Core.Structure.Registers; 10 using System.Collections.Generic; 11 using Antmicro.Renode.Core; 12 using Antmicro.Renode.Peripherals.Timers; 13 14 namespace Antmicro.Renode.Peripherals 15 { 16 public class STM32L_RTC : LimitTimer, IDoubleWordPeripheral 17 { STM32L_RTC(IMachine machine)18 public STM32L_RTC(IMachine machine) : base(machine.ClockSource, 1000, eventEnabled: true, autoUpdate: true) // this frequency is a blind guess 19 { 20 IRQ = new GPIO(); 21 LimitReached += () => 22 { 23 if(wakeupTimerInterruptEnable.Value) 24 { 25 wakeupTimerFlag.Value = true; 26 this.DebugLog("Setting IRQ"); 27 IRQ.Set(); 28 } 29 }; 30 SetupRegisters(); 31 } 32 Reset()33 public override void Reset() 34 { 35 base.Reset(); 36 registers.Reset(); 37 IRQ.Unset(); 38 } 39 ReadDoubleWord(long offset)40 public uint ReadDoubleWord(long offset) 41 { 42 return registers.Read(offset); 43 } 44 WriteDoubleWord(long offset, uint value)45 public void WriteDoubleWord(long offset, uint value) 46 { 47 registers.Write(offset, value); 48 } 49 50 public GPIO IRQ { get; private set; } 51 SetupRegisters()52 private void SetupRegisters() 53 { 54 var control = new DoubleWordRegister(this) 55 .WithEnumField<DoubleWordRegister, ClockMode>(0, 3, name: "WUCKSEL", writeCallback: (_, value) => 56 { 57 this.DebugLog("Setting wucksel to {0}", value); 58 // for now we ignore changing clock frequency 59 }) 60 .WithFlag(10, name: "WUTE", writeCallback: (_, value) => 61 { 62 this.DebugLog(value ? "Enabling timer" : "Disabling timer"); 63 Enabled = value; 64 }); 65 wakeupTimerInterruptEnable = control.DefineFlagField(14, name: "WUTIE"); 66 67 var initializationStatus = new DoubleWordRegister(this, 0x7); 68 wakeupTimerFlag = initializationStatus.DefineFlagField(10, FieldMode.Read | FieldMode.WriteZeroToClear, name: "WUTF", writeCallback: (_, value) => 69 { 70 if(!value) 71 { 72 this.DebugLog("Clearing IRQ"); 73 IRQ.Unset(); 74 } 75 }); 76 77 var wakeupTimer = new DoubleWordRegister(this).WithValueField(0, 16, name: "WUT", writeCallback: (_, value) => 78 { 79 this.DebugLog("Setting limit to {0}", value); 80 Limit = value; 81 }); 82 83 var registerDictionary = new Dictionary<long, DoubleWordRegister> { 84 { (long)Registers.Control, control }, 85 { (long)Registers.InitializationStatus, initializationStatus }, 86 { (long)Registers.WakeupTimer, wakeupTimer } 87 }; 88 registers = new DoubleWordRegisterCollection(this, registerDictionary); 89 } 90 91 private enum ClockMode 92 { 93 RTC_16, 94 RTC_8, 95 RTC_4, 96 RTC_2, 97 CK_SPRE1, 98 CK_SPRE2, 99 CK_SPRE3, 100 CK_SPRE4 101 } 102 103 private enum Registers 104 { 105 Control = 0x8, 106 InitializationStatus = 0xC, 107 WakeupTimer = 0x14 108 } 109 110 private DoubleWordRegisterCollection registers; 111 private IFlagRegisterField wakeupTimerFlag; 112 private IFlagRegisterField wakeupTimerInterruptEnable; 113 } 114 } 115 116