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