1 // 2 // Copyright (c) 2010-2018 Antmicro 3 // Copyright (c) 2011-2015 Realtime Embedded 4 // 5 // This file is licensed under the MIT License. 6 // Full license text is available in 'licenses/MIT.txt'. 7 // 8 using System; 9 using Antmicro.Renode.Core; 10 using Antmicro.Renode.Peripherals.Bus; 11 using Antmicro.Renode.Utilities; 12 using Antmicro.Renode.Peripherals.Timers; 13 using Antmicro.Renode.Time; 14 15 /* 16 0x000 TIMERn_CTRL RW Control Register 17 0x004 TIMERn_CMD W1 Command Register 18 0x008 TIMERn_STATUS R Status Register 19 0x00C TIMERn_IEN RW Interrupt Enable Register 20 0x010 TIMERn_IF R Interrupt Flag Register 21 0x014 TIMERn_IFS W1 Interrupt Flag Set Register 22 0x018 TIMERn_IFC W1 Interrupt Flag Clear Register 23 0x01C TIMERn_TOP RWH Counter Top Value Register 24 0x020 TIMERn_TOPB RW Counter Top Value Buffer Register 25 0x024 TIMERn_CNT RWH Counter Value Register 26 0x028 TIMERn_ROUTE RW I/O Routing Register 27 0x030 TIMERn_CC0_CTRL RW CC Channel Control Register 28 */ 29 using Antmicro.Renode.Logging; 30 31 namespace Antmicro.Renode.Peripherals.Timers 32 { 33 public class Efm32Timer : LimitTimer, IDoubleWordPeripheral 34 { Efm32Timer(IMachine machine)35 public Efm32Timer(IMachine machine) : base(machine.ClockSource, 48000000, direction: Direction.Ascending, limit: 0x100000, enabled: false) 36 { 37 AutoUpdate = true; 38 IRQ = new GPIO(); 39 } 40 41 public GPIO IRQ { get; private set; } 42 OnLimitReached()43 protected override void OnLimitReached() 44 { 45 IRQ.Set(true); 46 } 47 ReadDoubleWord(long offset)48 public uint ReadDoubleWord(long offset) 49 { 50 if(offset == 0x24) 51 { 52 return (uint)(Value); 53 } 54 55 return 0; 56 } 57 WriteDoubleWord(long offset, uint value)58 public void WriteDoubleWord(long offset, uint value) 59 { 60 if(offset == 0x00) 61 { 62 int prescaler = (int)(value & 0xF000000) >> 24; 63 prescaler = 1 << prescaler; 64 Divider = prescaler; 65 //TODO: Hack. Should support UPDOWN on 2 and quadrature decoder on 3 66 if((value & 0x3) == 0) 67 { 68 Direction = Direction.Ascending; 69 } else 70 { 71 Direction = Direction.Descending; 72 } 73 this.NoisyLog("CTRL, prescaler = {0}", prescaler); 74 } 75 if(offset == 0x4) 76 { 77 if((value & 0x1) == 0x1) 78 { 79 if(!Enabled) 80 { 81 Enabled = true; 82 } 83 this.NoisyLog("Timer started"); 84 } 85 else if((value & 0x2) == 0x2) 86 { 87 IRQ.Set(false); 88 //this.Disable(); // TODO: timer stopping temporary disabled due to excessive thread usage 89 this.NoisyLog("Timer stopped"); 90 } 91 } 92 if(offset == 0x0C) 93 { 94 if((value & 0x2) == 0x2) 95 { 96 // underflow irq 97 EventEnabled = true; 98 99 this.NoisyLog("IRQ ENABLED"); 100 } else 101 { 102 EventEnabled = false; 103 IRQ.Set(false); 104 } 105 } 106 if(offset == 0x18) 107 { 108 if((value & 0x3) > 0) 109 { 110 ClearInterrupt(); 111 IRQ.Set(false); 112 } 113 114 } 115 if(offset == 0x24) 116 { 117 Value = value; 118 } 119 } 120 121 } 122 } 123 124