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.Logging;
11 using Antmicro.Renode.Peripherals.Bus;
12 
13 namespace Antmicro.Renode.Peripherals.GPIOPort
14 {
15     [AllowedTranslations(AllowedTranslation.WordToDoubleWord)]
16 
17     public class STM32F4GPIOPort : BaseGPIOPort, IDoubleWordPeripheral
18     {
STM32F4GPIOPort(IMachine machine, uint modeResetValue = 0, uint outputSpeedResetValue = 0, uint pullUpPullDownResetValue = 0)19         public STM32F4GPIOPort(IMachine machine, uint modeResetValue = 0, uint outputSpeedResetValue = 0, uint pullUpPullDownResetValue = 0) : base(machine, 16)
20         {
21             this.modeResetValue = modeResetValue;
22             this.outputSpeedResetValue = outputSpeedResetValue;
23             this.pullUpPullDownResetValue = pullUpPullDownResetValue;
24             Reset();
25         }
26 
ReadDoubleWord(long offset)27         public uint ReadDoubleWord(long offset)
28         {
29             uint returnValue = 0;
30             switch((Registers)offset)
31             {
32             case Registers.GPIOx_MODE: // GPIO port mode register
33                 returnValue = gpiox_mode;
34                 break;
35             case Registers.GPIOx_OTYPER: // GPIO port output type register
36                 returnValue = gpiox_otyper;
37                 break;
38             case Registers.GPIOx_OSPEEDR: // GPIO port output speed register
39                 returnValue = gpiox_ospeedr;
40                 break;
41             case Registers.GPIOx_PUPDR: // GPIO port pull-up/pull-down register register
42                 returnValue = gpiox_pupdr;
43                 break;
44             case Registers.GPIOx_IDR: // GPIO port input data register
45                 var value = 0u;
46                 for(var i = 0; i < State.Length; i++)
47                 {
48                     if(State[i])
49                     {
50                         value |= 1u << i;
51                     }
52                 }
53                 returnValue = value;
54                 break;
55             case Registers.GPIOx_ODR: // GPIO port output data register
56                 returnValue = gpiox_odr & 0xFFFF;
57                 break;
58             case Registers.GPIOx_LCKR: // GPIO port lock register
59                 returnValue = gpiox_lckr & 0x1FFFF;
60                 break;
61             case Registers.GPIOx_BSRR: // GPIO port bit set/reset register
62                 returnValue = gpiox_afrl;
63                 break;
64             case Registers.GPIOx_AFRL: // GPIO alternate function low register
65                 returnValue = gpiox_afrh;
66                 break;
67             case Registers.GPIOx_AFRH: // GPIO alternate function high register
68                 returnValue = 0;
69                 break;
70             default:
71                 this.LogUnhandledRead(offset);
72                 returnValue = 0;
73                 break;
74             }
75             return returnValue;
76         }
77 
WriteDoubleWord(long offset, uint value)78         public void WriteDoubleWord(long offset, uint value)
79         {
80             switch((Registers)offset)
81             {
82             case Registers.GPIOx_MODE: // GPIO port mode register
83                 gpiox_mode = value;
84                 break;
85             case Registers.GPIOx_OTYPER: // GPIO port output type register
86                 gpiox_otyper = value;
87                 break;
88             case Registers.GPIOx_OSPEEDR: // GPIO port output speed register
89                 gpiox_ospeedr = value;
90                 break;
91             case Registers.GPIOx_PUPDR: // GPIO port pull-up/pull-down register register
92                 gpiox_pupdr = value;
93                 break;
94             case Registers.GPIOx_IDR: // GPIO port input data register
95                 break;
96             case Registers.GPIOx_ODR: // GPIO port output data register
97                 gpiox_odr = value;
98                 SetConnectionsStateUsingBits(gpiox_odr);
99                 break;
100             case Registers.GPIOx_LCKR: // GPIO port lock register
101                 gpiox_lckr = value;
102                 break;
103             case Registers.GPIOx_BSRR: // GPIO port bit set/reset register
104                 gpiox_bsrr = value;
105                 for(var i = 0; i < 16; ++i)
106                 {
107                     if((gpiox_bsrr & 1u << i) != 0)
108                     {
109                         Connections[i].Set();
110                         State[i] = true;
111                     }
112                 }
113                 for(var i = 16; i < 32; ++i)
114                 {
115                     if((gpiox_bsrr & 1u << i) != 0)
116                     {
117                         Connections[i - 16].Unset();
118                         State[i - 16] = false;
119                     }
120                 }
121                 break;
122             case Registers.GPIOx_AFRL: // GPIO alternate function low register
123                 gpiox_afrl = value;
124                 break;
125             case Registers.GPIOx_AFRH: // GPIO alternate function high register
126                 gpiox_afrh = value;
127                 break;
128             default:
129                 this.LogUnhandledWrite(offset, value);
130                 break;
131             }
132             return;
133         }
134 
OnGPIO(int number, bool value)135         public override void OnGPIO(int number, bool value)
136         {
137             base.OnGPIO(number, value);
138             Connections[number].Set(value);
139         }
140 
Reset()141         public override void Reset()
142         {
143             base.Reset();
144             gpiox_mode = modeResetValue;
145             gpiox_otyper = 0;
146             gpiox_ospeedr = outputSpeedResetValue;
147             gpiox_pupdr = pullUpPullDownResetValue;
148             gpiox_odr = 0;
149             gpiox_bsrr = 0;
150             gpiox_lckr = 0;
151             gpiox_afrl = 0;
152             gpiox_afrh = 0;
153 
154         }
155 
156         private uint gpiox_mode;
157         private uint gpiox_otyper;
158         private uint gpiox_ospeedr;
159         private uint gpiox_pupdr;
160         private uint gpiox_odr;
161         private uint gpiox_bsrr;
162         private uint gpiox_lckr;
163         private uint gpiox_afrl;
164         private uint gpiox_afrh;
165 
166         private readonly uint modeResetValue;
167         private readonly uint outputSpeedResetValue;
168         private readonly uint pullUpPullDownResetValue;
169 
170         // Source: Chapter 7.4 in RM0090 Cortex M4 Reference Manual (Doc ID 018909 Rev 4)
171         // for STM32F40xxx, STM32F41xxx, STM32F42xxx, STM32F43xxx advanced ARM-based 32-bit MCUs
172         private enum Registers
173         {
174             GPIOx_MODE      = 0x00, // GPIO port mode register - Read-Write
175             GPIOx_OTYPER    = 0x04, // GPIO port output type register - Read-Write
176             GPIOx_OSPEEDR   = 0x08, // GPIO port output speed register - Read-Write
177             GPIOx_PUPDR     = 0x0C, // GPIO port pull-up/pull-down register - Read-Write
178             GPIOx_IDR       = 0x10, // GPIO port input data register - Read-only
179             GPIOx_ODR       = 0x14, // GPIO port output data register - Read-Write
180             GPIOx_BSRR      = 0x18, // GPIO port bit set/reset register - Write-Only
181             GPIOx_LCKR      = 0x1C, // GPIO port configuration lock register - Read-Write
182             GPIOx_AFRL      = 0x20, // GPIO alternate function low register - Read-Write
183             GPIOx_AFRH      = 0x24  // GPIO alternate function high register - Read-Write
184         }
185     }
186 }
187 
188