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