1 /*
2 * Copyright (c) 2015 - 2023, Nordic Semiconductor ASA
3 *
4 * Modifications to the GPIO HAL to use with simulation models
5 *
6 * Code which is not copied from the nRFx HAL is licensed as:
7 * SPDX-License-Identifier: Apache-2.0
8 *
9 * Most of the code of the functions below is taken from the NRFx HAL with minor
10 * modifications, specially:
11 * nrf_gpio_cfg()
12 * nrf_gpio_reconfigure()
13 * nrf_gpio_port_pin_output_set()
14 * nrf_gpio_port_pin_input_set()
15 * nrf_gpio_pin_dir_set()
16 * nrf_gpio_pin_toggle()
17 * nrf_gpio_port_detect_latch_set()
18 * nrf_gpio_pin_latch_clear()
19 * nrf_gpio_latches_read_and_clear()
20 * For that code, the original license applies:
21 *
22 * SPDX-License-Identifier: BSD-3-Clause
23 *
24 * Redistribution and use in source and binary forms, with or without
25 * modification, are permitted provided that the following conditions are met:
26 *
27 * 1. Redistributions of source code must retain the above copyright notice, this
28 * list of conditions and the following disclaimer.
29 *
30 * 2. Redistributions in binary form must reproduce the above copyright
31 * notice, this list of conditions and the following disclaimer in the
32 * documentation and/or other materials provided with the distribution.
33 *
34 * 3. Neither the name of the copyright holder nor the names of its
35 * contributors may be used to endorse or promote products derived from this
36 * software without specific prior written permission.
37 *
38 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
39 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
42 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
43 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
44 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
45 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
46 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
48 * POSSIBILITY OF SUCH DAMAGE.
49 */
50
51 #include <stdint.h>
52 #include "NRF_GPIO.h"
53 #include "hal/nrf_gpio.h"
54 #include "bs_tracing.h"
55
gpio_number_from_ptr(NRF_GPIO_Type const * p_reg)56 static int gpio_number_from_ptr(NRF_GPIO_Type const * p_reg){
57 int i = ( (int)p_reg - (int)&NRF_GPIO_regs[0] ) / sizeof(NRF_GPIO_Type);
58 return i;
59 }
60
61 extern NRF_GPIO_Type * nrf_gpio_pin_port_decode(uint32_t * p_pin);
62
nrf_gpio_cfg(uint32_t pin_number,nrf_gpio_pin_dir_t dir,nrf_gpio_pin_input_t input,nrf_gpio_pin_pull_t pull,nrf_gpio_pin_drive_t drive,nrf_gpio_pin_sense_t sense)63 void nrf_gpio_cfg(
64 uint32_t pin_number,
65 nrf_gpio_pin_dir_t dir,
66 nrf_gpio_pin_input_t input,
67 nrf_gpio_pin_pull_t pull,
68 nrf_gpio_pin_drive_t drive,
69 nrf_gpio_pin_sense_t sense)
70 {
71 NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number);
72 uint32_t cnf = reg->PIN_CNF[pin_number];
73
74 uint32_t to_update = GPIO_PIN_CNF_DIR_Msk |
75 GPIO_PIN_CNF_INPUT_Msk |
76 GPIO_PIN_CNF_PULL_Msk |
77 #if defined(GPIO_PIN_CNF_DRIVE_Msk)
78 GPIO_PIN_CNF_DRIVE_Msk |
79 #else
80 GPIO_PIN_CNF_DRIVE0_Msk |
81 GPIO_PIN_CNF_DRIVE1_Msk |
82 #endif
83 GPIO_PIN_CNF_SENSE_Msk;
84
85 /* Clear fields that will be updated. */
86 cnf &= ~to_update;
87 cnf |= ((uint32_t)dir << GPIO_PIN_CNF_DIR_Pos) |
88 ((uint32_t)input << GPIO_PIN_CNF_INPUT_Pos) |
89 ((uint32_t)pull << GPIO_PIN_CNF_PULL_Pos) |
90 #if defined(GPIO_PIN_CNF_DRIVE_Pos)
91 ((uint32_t)drive << GPIO_PIN_CNF_DRIVE_Pos) |
92 #else
93 ((uint32_t)drive << GPIO_PIN_CNF_DRIVE0_Pos) |
94 #endif
95 ((uint32_t)sense << GPIO_PIN_CNF_SENSE_Pos);
96
97 reg->PIN_CNF[pin_number] = cnf;
98
99 nrf_gpio_regw_sideeffects_PIN_CNF(gpio_number_from_ptr(reg), pin_number);
100 }
101
nrf_gpio_reconfigure(uint32_t pin_number,const nrf_gpio_pin_dir_t * p_dir,const nrf_gpio_pin_input_t * p_input,const nrf_gpio_pin_pull_t * p_pull,const nrf_gpio_pin_drive_t * p_drive,const nrf_gpio_pin_sense_t * p_sense)102 void nrf_gpio_reconfigure(uint32_t pin_number,
103 const nrf_gpio_pin_dir_t * p_dir,
104 const nrf_gpio_pin_input_t * p_input,
105 const nrf_gpio_pin_pull_t * p_pull,
106 const nrf_gpio_pin_drive_t * p_drive,
107 const nrf_gpio_pin_sense_t * p_sense)
108 {
109 NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number);
110 uint32_t cnf = reg->PIN_CNF[pin_number];
111 uint32_t to_update = (p_dir ? GPIO_PIN_CNF_DIR_Msk : 0) |
112 (p_input ? GPIO_PIN_CNF_INPUT_Msk : 0) |
113 (p_pull ? GPIO_PIN_CNF_PULL_Msk : 0) |
114 #if defined(GPIO_PIN_CNF_DRIVE_Msk)
115 (p_drive ? GPIO_PIN_CNF_DRIVE_Msk : 0) |
116 #else
117 (p_drive ? (GPIO_PIN_CNF_DRIVE0_Msk | GPIO_PIN_CNF_DRIVE1_Msk) : 0) |
118 #endif
119 (p_sense ? GPIO_PIN_CNF_SENSE_Msk : 0);
120
121 /* Clear fields that will be updated. */
122 cnf &= ~to_update;
123 cnf |= ((uint32_t)(p_dir ? *p_dir : 0) << GPIO_PIN_CNF_DIR_Pos) |
124 ((uint32_t)(p_input ? *p_input : 0) << GPIO_PIN_CNF_INPUT_Pos) |
125 ((uint32_t)(p_pull ? *p_pull : 0) << GPIO_PIN_CNF_PULL_Pos) |
126 #if defined(GPIO_PIN_CNF_DRIVE_Pos)
127 ((uint32_t)(p_drive ? *p_drive : 0) << GPIO_PIN_CNF_DRIVE_Pos) |
128 #else
129 ((uint32_t)(p_drive ? *p_drive : 0) << GPIO_PIN_CNF_DRIVE0_Pos) |
130 #endif
131 ((uint32_t)(p_sense ? *p_sense : 0)<< GPIO_PIN_CNF_SENSE_Pos);
132
133 reg->PIN_CNF[pin_number] = cnf;
134
135 nrf_gpio_regw_sideeffects_PIN_CNF(gpio_number_from_ptr(reg), pin_number);
136 }
137
138
nrf_gpio_port_pin_output_set(NRF_GPIO_Type * p_reg,uint32_t pin_number)139 void nrf_gpio_port_pin_output_set(NRF_GPIO_Type * p_reg, uint32_t pin_number)
140 {
141 uint32_t cnf = ((uint32_t)NRF_GPIO_PIN_DIR_OUTPUT << GPIO_PIN_CNF_DIR_Pos) |
142 ((uint32_t)NRF_GPIO_PIN_INPUT_DISCONNECT << GPIO_PIN_CNF_INPUT_Pos) |
143 ((uint32_t)NRF_GPIO_PIN_NOPULL << GPIO_PIN_CNF_PULL_Pos) |
144 #if defined(GPIO_PIN_CNF_DRIVE_Pos)
145 ((uint32_t)NRF_GPIO_PIN_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
146 #else
147 ((uint32_t)NRF_GPIO_PIN_S0S1 << GPIO_PIN_CNF_DRIVE0_Pos) |
148 #endif
149 ((uint32_t)NRF_GPIO_PIN_NOSENSE << GPIO_PIN_CNF_SENSE_Pos);
150 p_reg->PIN_CNF[pin_number] = cnf;
151 nrf_gpio_regw_sideeffects_PIN_CNF(gpio_number_from_ptr(p_reg), pin_number);
152 }
153
nrf_gpio_port_pin_input_set(NRF_GPIO_Type * p_reg,uint32_t pin_number,nrf_gpio_pin_pull_t pull_config)154 void nrf_gpio_port_pin_input_set(NRF_GPIO_Type * p_reg,
155 uint32_t pin_number,
156 nrf_gpio_pin_pull_t pull_config)
157 {
158 uint32_t cnf = ((uint32_t)NRF_GPIO_PIN_DIR_INPUT << GPIO_PIN_CNF_DIR_Pos) |
159 ((uint32_t)NRF_GPIO_PIN_INPUT_CONNECT << GPIO_PIN_CNF_INPUT_Pos) |
160 ((uint32_t)pull_config << GPIO_PIN_CNF_PULL_Pos) |
161 #if defined(GPIO_PIN_CNF_DRIVE_Pos)
162 ((uint32_t)NRF_GPIO_PIN_S0S1 << GPIO_PIN_CNF_DRIVE_Pos) |
163 #else
164 ((uint32_t)NRF_GPIO_PIN_S0S1 << GPIO_PIN_CNF_DRIVE0_Pos) |
165 #endif
166 ((uint32_t)NRF_GPIO_PIN_NOSENSE << GPIO_PIN_CNF_SENSE_Pos);
167 p_reg->PIN_CNF[pin_number] = cnf;
168 nrf_gpio_regw_sideeffects_PIN_CNF(gpio_number_from_ptr(p_reg), pin_number);
169 }
170
nrf_gpio_pin_dir_set(uint32_t pin_number,nrf_gpio_pin_dir_t direction)171 void nrf_gpio_pin_dir_set(uint32_t pin_number, nrf_gpio_pin_dir_t direction)
172 {
173 if (direction == NRF_GPIO_PIN_DIR_INPUT)
174 {
175 nrf_gpio_cfg(
176 pin_number,
177 NRF_GPIO_PIN_DIR_INPUT,
178 NRF_GPIO_PIN_INPUT_CONNECT,
179 NRF_GPIO_PIN_NOPULL,
180 NRF_GPIO_PIN_S0S1,
181 NRF_GPIO_PIN_NOSENSE);
182 }
183 else
184 {
185 NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number);
186 reg->DIRSET = (1UL << pin_number);
187
188 nrf_gpio_regw_sideeffects_DIRSET(gpio_number_from_ptr(reg));
189 }
190 }
191
nrf_gpio_pin_toggle(uint32_t pin_number)192 void nrf_gpio_pin_toggle(uint32_t pin_number)
193 {
194 NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number);
195 unsigned int port = gpio_number_from_ptr(reg);
196
197 uint32_t pins_state = reg->OUT;
198
199 reg->OUTSET = (~pins_state & (1UL << pin_number));
200 nrf_gpio_regw_sideeffects_OUTSET(port);
201 reg->OUTCLR = (pins_state & (1UL << pin_number));
202 nrf_gpio_regw_sideeffects_OUTCLR(port);
203 }
204
205
nrf_gpio_port_dir_output_set(NRF_GPIO_Type * p_reg,uint32_t out_mask)206 void nrf_gpio_port_dir_output_set(NRF_GPIO_Type * p_reg, uint32_t out_mask)
207 {
208 p_reg->DIRSET = out_mask;
209 nrf_gpio_regw_sideeffects_DIRSET(gpio_number_from_ptr(p_reg));
210 }
211
212
nrf_gpio_port_dir_input_set(NRF_GPIO_Type * p_reg,uint32_t in_mask)213 void nrf_gpio_port_dir_input_set(NRF_GPIO_Type * p_reg, uint32_t in_mask)
214 {
215 p_reg->DIRCLR = in_mask;
216 nrf_gpio_regw_sideeffects_DIRCLR(gpio_number_from_ptr(p_reg));
217 }
218
nrf_gpio_port_dir_write(NRF_GPIO_Type * p_reg,uint32_t value)219 void nrf_gpio_port_dir_write(NRF_GPIO_Type * p_reg, uint32_t value)
220 {
221 p_reg->DIR = value;
222 nrf_gpio_regw_sideeffects_DIR(gpio_number_from_ptr(p_reg));
223 }
224
nrf_gpio_port_out_write(NRF_GPIO_Type * p_reg,uint32_t value)225 void nrf_gpio_port_out_write(NRF_GPIO_Type * p_reg, uint32_t value)
226 {
227 p_reg->OUT = value;
228 nrf_gpio_regw_sideeffects_OUT(gpio_number_from_ptr(p_reg));
229 }
230
nrf_gpio_port_out_set(NRF_GPIO_Type * p_reg,uint32_t set_mask)231 void nrf_gpio_port_out_set(NRF_GPIO_Type * p_reg, uint32_t set_mask)
232 {
233 p_reg->OUTSET = set_mask;
234 nrf_gpio_regw_sideeffects_OUTSET(gpio_number_from_ptr(p_reg));
235 }
236
237
nrf_gpio_port_out_clear(NRF_GPIO_Type * p_reg,uint32_t clr_mask)238 void nrf_gpio_port_out_clear(NRF_GPIO_Type * p_reg, uint32_t clr_mask)
239 {
240 p_reg->OUTCLR = clr_mask;
241 nrf_gpio_regw_sideeffects_OUTCLR(gpio_number_from_ptr(p_reg));
242 }
243
nrf_gpio_port_detect_latch_set(NRF_GPIO_Type * p_reg,bool enable)244 void nrf_gpio_port_detect_latch_set(NRF_GPIO_Type * p_reg, bool enable)
245 {
246 p_reg->DETECTMODE = (enable ? GPIO_DETECTMODE_DETECTMODE_LDETECT :
247 GPIO_DETECTMODE_DETECTMODE_Default);
248 nrf_gpio_regw_sideeffects_DETECTMODE(gpio_number_from_ptr(p_reg));
249 }
250
nrf_gpio_latches_read_and_clear(uint32_t start_port,uint32_t length,uint32_t * p_masks)251 void nrf_gpio_latches_read_and_clear(uint32_t start_port,
252 uint32_t length,
253 uint32_t * p_masks)
254 {
255 NRF_GPIO_Type * gpio_regs[GPIO_COUNT] = GPIO_REG_LIST;
256 uint32_t i;
257
258 for (i = start_port; i < (start_port + length); i++)
259 {
260 *p_masks = gpio_regs[i]->LATCH;
261
262 // The LATCH register is cleared by writing a '1' to the bit that shall be cleared.
263 gpio_regs[i]->LATCH = *p_masks;
264 nrf_gpio_regw_sideeffects_LATCH(gpio_number_from_ptr(gpio_regs[i]));
265
266 p_masks++;
267 }
268 }
269
nrf_gpio_pin_latch_clear(uint32_t pin_number)270 void nrf_gpio_pin_latch_clear(uint32_t pin_number)
271 {
272 NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number);
273
274 reg->LATCH = (1 << pin_number);
275 nrf_gpio_regw_sideeffects_LATCH(gpio_number_from_ptr(reg));
276 }
277