1 | /****************************************************************************** |
---|
2 | * |
---|
3 | * Copyright 2013 Altera Corporation. All Rights Reserved. |
---|
4 | * |
---|
5 | * Redistribution and use in source and binary forms, with or without |
---|
6 | * modification, are permitted provided that the following conditions are met: |
---|
7 | * |
---|
8 | * 1. Redistributions of source code must retain the above copyright notice, |
---|
9 | * this list of conditions and the following disclaimer. |
---|
10 | * |
---|
11 | * 2. Redistributions in binary form must reproduce the above copyright notice, |
---|
12 | * this list of conditions and the following disclaimer in the documentation |
---|
13 | * and/or other materials provided with the distribution. |
---|
14 | * |
---|
15 | * 3. The name of the author may not be used to endorse or promote products |
---|
16 | * derived from this software without specific prior written permission. |
---|
17 | * |
---|
18 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR |
---|
19 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
---|
20 | * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO |
---|
21 | * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
---|
22 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT |
---|
23 | * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
---|
24 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
---|
25 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
---|
26 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY |
---|
27 | * OF SUCH DAMAGE. |
---|
28 | * |
---|
29 | ******************************************************************************/ |
---|
30 | |
---|
31 | #include <stdint.h> |
---|
32 | #include <stdlib.h> |
---|
33 | #include <stdbool.h> |
---|
34 | |
---|
35 | #include <bsp/socal/hps.h> |
---|
36 | #include <bsp/socal/socal.h> |
---|
37 | #include <bsp/socal/alt_gpio.h> |
---|
38 | #include <bsp/socal/alt_rstmgr.h> |
---|
39 | #include <bsp/hwlib.h> |
---|
40 | #include <bsp/alt_generalpurpose_io.h> |
---|
41 | |
---|
42 | |
---|
43 | /****************************************************************************************/ |
---|
44 | /******************************* Useful local definitions *******************************/ |
---|
45 | /****************************************************************************************/ |
---|
46 | |
---|
47 | #define ALT_GPIO_EOPA ALT_GPIO_1BIT_28 |
---|
48 | #define ALT_GPIO_EOPB ALT_GPIO_1BIT_57 |
---|
49 | #define ALT_GPIO_EOPC ALT_HLGPI_15 |
---|
50 | #define ALT_GPIO_BITMASK 0x1FFFFFFF |
---|
51 | |
---|
52 | // expands the zero or one bit to the 29-bit GPIO word |
---|
53 | #define ALT_GPIO_ALLORNONE(tst) ((uint32_t) ((tst == 0) ? 0 : ALT_GPIO_BITMASK)) |
---|
54 | |
---|
55 | |
---|
56 | /****************************************************************************************/ |
---|
57 | /* alt_gpio_init() initializes the GPIO modules */ |
---|
58 | /****************************************************************************************/ |
---|
59 | |
---|
60 | ALT_STATUS_CODE alt_gpio_init(void) |
---|
61 | { |
---|
62 | // put GPIO modules into system manager reset if not already there |
---|
63 | alt_gpio_uninit(); |
---|
64 | // release GPIO modules from system reset (w/ two-instruction delay) |
---|
65 | alt_replbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_GPIO0_SET_MSK | |
---|
66 | ALT_RSTMGR_PERMODRST_GPIO1_SET_MSK | |
---|
67 | ALT_RSTMGR_PERMODRST_GPIO2_SET_MSK, 0); |
---|
68 | return ALT_E_SUCCESS; |
---|
69 | } |
---|
70 | |
---|
71 | |
---|
72 | /****************************************************************************************/ |
---|
73 | /* alt_gpio_uninit() uninitializes the GPIO modules */ |
---|
74 | /****************************************************************************************/ |
---|
75 | |
---|
76 | ALT_STATUS_CODE alt_gpio_uninit(void) |
---|
77 | { |
---|
78 | // put all GPIO modules into system manager reset |
---|
79 | alt_replbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_GPIO0_SET_MSK | |
---|
80 | ALT_RSTMGR_PERMODRST_GPIO1_SET_MSK | |
---|
81 | ALT_RSTMGR_PERMODRST_GPIO2_SET_MSK, |
---|
82 | ALT_GPIO_BITMASK); |
---|
83 | return ALT_E_SUCCESS; |
---|
84 | } |
---|
85 | |
---|
86 | |
---|
87 | /****************************************************************************************/ |
---|
88 | /* alt_gpio_port_datadir_set() sets the specified GPIO data bits to use the data */ |
---|
89 | /* direction(s) specified. 0 = input (default). 1 = output. */ |
---|
90 | /****************************************************************************************/ |
---|
91 | |
---|
92 | ALT_STATUS_CODE alt_gpio_port_datadir_set(ALT_GPIO_PORT_t gpio_pid, |
---|
93 | uint32_t mask, uint32_t config) |
---|
94 | { |
---|
95 | volatile uint32_t *addr; |
---|
96 | |
---|
97 | if ((mask & ~ALT_GPIO_BITMASK) || (config & ~ALT_GPIO_BITMASK)) { return ALT_E_ERROR; } |
---|
98 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_SWPORTA_DDR_ADDR; } |
---|
99 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_SWPORTA_DDR_ADDR; } |
---|
100 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_SWPORTA_DDR_ADDR; } |
---|
101 | else { return ALT_E_BAD_ARG; } |
---|
102 | |
---|
103 | alt_replbits_word(addr, mask, config); |
---|
104 | return ALT_E_SUCCESS; |
---|
105 | } |
---|
106 | |
---|
107 | |
---|
108 | /****************************************************************************************/ |
---|
109 | /* alt_gpio_port_datadir_get() returns the data direction configuration of selected */ |
---|
110 | /* bits of the designated GPIO module. */ |
---|
111 | /****************************************************************************************/ |
---|
112 | |
---|
113 | uint32_t alt_gpio_port_datadir_get(ALT_GPIO_PORT_t gpio_pid, |
---|
114 | uint32_t mask) |
---|
115 | { |
---|
116 | volatile uint32_t *addr; |
---|
117 | |
---|
118 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_SWPORTA_DDR_ADDR; } |
---|
119 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_SWPORTA_DDR_ADDR; } |
---|
120 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_SWPORTA_DDR_ADDR; } |
---|
121 | else { return 0; } |
---|
122 | |
---|
123 | return alt_read_word(addr) & mask; |
---|
124 | } |
---|
125 | |
---|
126 | |
---|
127 | /****************************************************************************************/ |
---|
128 | /* alt_gpio_port_data_write() sets the GPIO data outputs of the specified GPIO module */ |
---|
129 | /* to a one or zero. Actual outputs are only set if the data direction for that bit(s) */ |
---|
130 | /* has previously been set to configure them as output(s). */ |
---|
131 | /****************************************************************************************/ |
---|
132 | |
---|
133 | ALT_STATUS_CODE alt_gpio_port_data_write(ALT_GPIO_PORT_t gpio_pid, |
---|
134 | uint32_t mask, uint32_t val) |
---|
135 | { |
---|
136 | volatile uint32_t *addr; |
---|
137 | |
---|
138 | if ((mask & ~ALT_GPIO_BITMASK) || (val & ~ALT_GPIO_BITMASK)) { return ALT_E_ERROR; } |
---|
139 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_SWPORTA_DR_ADDR; } |
---|
140 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_SWPORTA_DR_ADDR; } |
---|
141 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_SWPORTA_DR_ADDR; } |
---|
142 | else { return ALT_E_BAD_ARG; } |
---|
143 | |
---|
144 | alt_replbits_word(addr, mask, val); |
---|
145 | return ALT_E_SUCCESS; |
---|
146 | } |
---|
147 | |
---|
148 | |
---|
149 | /****************************************************************************************/ |
---|
150 | /* alt_gpio_port_data_read() returns the value of the data inputs of the specified */ |
---|
151 | /* GPIO module. Data direction for these bits must have been previously set to inputs. */ |
---|
152 | /****************************************************************************************/ |
---|
153 | |
---|
154 | #if (!ALT_GPIO_DATAREAD_TEST_MODE) |
---|
155 | /* This is the production code version. For software unit testing, set the */ |
---|
156 | /* ALT_GPIO_DATAREAD_TEST_MODE flag to true in the makefile, which will compile */ |
---|
157 | /* the GPIO test software version of alt_gpio_port_data_read() instead. */ |
---|
158 | |
---|
159 | uint32_t alt_gpio_port_data_read(ALT_GPIO_PORT_t gpio_pid, uint32_t mask) |
---|
160 | { |
---|
161 | volatile uint32_t *addr; |
---|
162 | |
---|
163 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_EXT_PORTA_ADDR; } |
---|
164 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_EXT_PORTA_ADDR; } |
---|
165 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_EXT_PORTA_ADDR; } |
---|
166 | else { return 0; } |
---|
167 | |
---|
168 | return alt_read_word(addr) & mask; |
---|
169 | } |
---|
170 | #endif |
---|
171 | |
---|
172 | |
---|
173 | /****************************************************************************************/ |
---|
174 | /* alt_gpio_port_int_type_set() sets selected signals of the specified GPIO port to */ |
---|
175 | /* be either level-sensitive ( =0) or edge-triggered ( =1). */ |
---|
176 | /****************************************************************************************/ |
---|
177 | |
---|
178 | ALT_STATUS_CODE alt_gpio_port_int_type_set(ALT_GPIO_PORT_t gpio_pid, |
---|
179 | uint32_t mask, uint32_t config) |
---|
180 | { |
---|
181 | volatile uint32_t *addr; |
---|
182 | |
---|
183 | if ((mask & ~ALT_GPIO_BITMASK) || (config & ~ALT_GPIO_BITMASK)) { return ALT_E_ERROR; } |
---|
184 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTTYPE_LEVEL_ADDR; } |
---|
185 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTTYPE_LEVEL_ADDR; } |
---|
186 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTTYPE_LEVEL_ADDR; } |
---|
187 | else { return ALT_E_BAD_ARG; } |
---|
188 | |
---|
189 | alt_replbits_word(addr, mask, config); |
---|
190 | return ALT_E_SUCCESS; |
---|
191 | } |
---|
192 | |
---|
193 | |
---|
194 | /****************************************************************************************/ |
---|
195 | /* alt_gpio_port_int_type_get() returns the interrupt configuration (edge-triggered or */ |
---|
196 | /* level-triggered) for the specified signals of the specified GPIO module. */ |
---|
197 | /****************************************************************************************/ |
---|
198 | |
---|
199 | uint32_t alt_gpio_port_int_type_get(ALT_GPIO_PORT_t gpio_pid, |
---|
200 | uint32_t mask) |
---|
201 | { |
---|
202 | volatile uint32_t *addr; |
---|
203 | |
---|
204 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTTYPE_LEVEL_ADDR; } |
---|
205 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTTYPE_LEVEL_ADDR; } |
---|
206 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTTYPE_LEVEL_ADDR; } |
---|
207 | else { return 0; } |
---|
208 | |
---|
209 | return alt_read_word(addr) & mask; |
---|
210 | } |
---|
211 | |
---|
212 | |
---|
213 | /****************************************************************************************/ |
---|
214 | /* alt_gpio_port_int_pol_set() sets the interrupt polarity of the signals of the */ |
---|
215 | /* specified GPIO register (when used as inputs) to active-high ( =0) or active-low */ |
---|
216 | /* ( =1). */ |
---|
217 | /****************************************************************************************/ |
---|
218 | |
---|
219 | ALT_STATUS_CODE alt_gpio_port_int_pol_set(ALT_GPIO_PORT_t gpio_pid, |
---|
220 | uint32_t mask, uint32_t config) |
---|
221 | { |
---|
222 | volatile uint32_t *addr; |
---|
223 | |
---|
224 | if ((mask & ~ALT_GPIO_BITMASK) || (config & ~ALT_GPIO_BITMASK)) { return ALT_E_ERROR; } |
---|
225 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INT_POL_ADDR; } |
---|
226 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INT_POL_ADDR; } |
---|
227 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INT_POL_ADDR; } |
---|
228 | else { return ALT_E_BAD_ARG; } |
---|
229 | |
---|
230 | alt_replbits_word(addr, mask, config); |
---|
231 | return ALT_E_SUCCESS; |
---|
232 | } |
---|
233 | |
---|
234 | |
---|
235 | /****************************************************************************************/ |
---|
236 | /* alt_gpio_port_int_pol_get() returns the active-high or active-low polarity */ |
---|
237 | /* configuration for the possible interrupt sources of the specified GPIO module. */ |
---|
238 | /* 0 = The interrupt polarity for this bit is set to active-low mode. 1 = The */ |
---|
239 | /* interrupt polarity for this bit is set to active-highmode. */ |
---|
240 | /****************************************************************************************/ |
---|
241 | |
---|
242 | uint32_t alt_gpio_port_int_pol_get(ALT_GPIO_PORT_t gpio_pid, |
---|
243 | uint32_t mask) |
---|
244 | { |
---|
245 | volatile uint32_t *addr; |
---|
246 | |
---|
247 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INT_POL_ADDR; } |
---|
248 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INT_POL_ADDR; } |
---|
249 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INT_POL_ADDR; } |
---|
250 | else { return 0; } |
---|
251 | |
---|
252 | return alt_read_word(addr) & mask; |
---|
253 | } |
---|
254 | |
---|
255 | |
---|
256 | /****************************************************************************************/ |
---|
257 | /* alt_gpio_port_debounce_set() sets the debounce configuration for input signals of */ |
---|
258 | /* the specified GPIO module. 0 - Debounce is not selected for this signal (default). */ |
---|
259 | /* 1 - Debounce is selected for this signal. */ |
---|
260 | /****************************************************************************************/ |
---|
261 | |
---|
262 | ALT_STATUS_CODE alt_gpio_port_debounce_set(ALT_GPIO_PORT_t gpio_pid, |
---|
263 | uint32_t mask, uint32_t config) |
---|
264 | { |
---|
265 | volatile uint32_t *addr; |
---|
266 | |
---|
267 | if ((mask & ~ALT_GPIO_BITMASK) || (config & ~ALT_GPIO_BITMASK)) { return ALT_E_ERROR; } |
---|
268 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_DEBOUNCE_ADDR; } |
---|
269 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_DEBOUNCE_ADDR; } |
---|
270 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_DEBOUNCE_ADDR; } |
---|
271 | else { return ALT_E_BAD_ARG; } |
---|
272 | |
---|
273 | alt_replbits_word(addr, mask, config); |
---|
274 | return ALT_E_SUCCESS; |
---|
275 | } |
---|
276 | |
---|
277 | |
---|
278 | /****************************************************************************************/ |
---|
279 | /* alt_gpio_port_debounce_get() returns the debounce configuration for the input */ |
---|
280 | /* signals of the specified GPIO register. 0 - Debounce is not selected for this */ |
---|
281 | /* signal. 1 - Debounce is selected for this signal. */ |
---|
282 | /****************************************************************************************/ |
---|
283 | |
---|
284 | uint32_t alt_gpio_port_debounce_get(ALT_GPIO_PORT_t gpio_pid, |
---|
285 | uint32_t mask) |
---|
286 | { |
---|
287 | volatile uint32_t *addr; |
---|
288 | |
---|
289 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_DEBOUNCE_ADDR; } |
---|
290 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_DEBOUNCE_ADDR; } |
---|
291 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_DEBOUNCE_ADDR; } |
---|
292 | else { return 0; } |
---|
293 | |
---|
294 | return alt_read_word(addr) & mask; |
---|
295 | } |
---|
296 | |
---|
297 | |
---|
298 | /****************************************************************************************/ |
---|
299 | /* alt_gpio_port_sync_set() sets the synchronization configuration for the signals of */ |
---|
300 | /* the specified GPIO register. This allows for synchronizing level-sensitive */ |
---|
301 | /* interrupts to the internal clock signal. This is a port-wide option that controls */ |
---|
302 | /* all level-sensitive interrupt signals of that GPIO port. */ |
---|
303 | /****************************************************************************************/ |
---|
304 | |
---|
305 | ALT_STATUS_CODE alt_gpio_port_sync_set(ALT_GPIO_PORT_t gpio_pid, uint32_t config) |
---|
306 | { |
---|
307 | volatile uint32_t *addr; |
---|
308 | |
---|
309 | config = (config != 0) ? 1 : 0; |
---|
310 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_LS_SYNC_ADDR; } |
---|
311 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_LS_SYNC_ADDR; } |
---|
312 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_LS_SYNC_ADDR; } |
---|
313 | else { return ALT_E_BAD_ARG; } |
---|
314 | |
---|
315 | alt_write_word(addr, config); |
---|
316 | return ALT_E_SUCCESS; |
---|
317 | } |
---|
318 | |
---|
319 | |
---|
320 | /****************************************************************************************/ |
---|
321 | /* alt_gpio_port_sync_get() returns the synchronization configuration for the signals */ |
---|
322 | /* of the specified GPIO register. This allows for synchronizing level-sensitive */ |
---|
323 | /* interrupts to the internal clock signal. This is a port-wide option that controls */ |
---|
324 | /* all level-sensitive interrupt signals of that GPIO port. */ |
---|
325 | /****************************************************************************************/ |
---|
326 | |
---|
327 | ALT_STATUS_CODE alt_gpio_port_sync_get(ALT_GPIO_PORT_t gpio_pid) |
---|
328 | { |
---|
329 | volatile uint32_t *addr; |
---|
330 | |
---|
331 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_LS_SYNC_ADDR; } |
---|
332 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_LS_SYNC_ADDR; } |
---|
333 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_LS_SYNC_ADDR; } |
---|
334 | else { return ALT_E_BAD_ARG; } // error |
---|
335 | |
---|
336 | return (alt_read_word(addr) != 0) ? ALT_E_TRUE : ALT_E_FALSE; |
---|
337 | } |
---|
338 | |
---|
339 | |
---|
340 | /****************************************************************************************/ |
---|
341 | /* alt_gpio_port_config() configures a group of GPIO signals with the same parameters. */ |
---|
342 | /* Allows for configuring all parameters of a given port at one time. */ |
---|
343 | /****************************************************************************************/ |
---|
344 | |
---|
345 | ALT_STATUS_CODE alt_gpio_port_config(ALT_GPIO_PORT_t gpio_pid, |
---|
346 | uint32_t mask, ALT_GPIO_PIN_DIR_t dir, ALT_GPIO_PIN_TYPE_t type, |
---|
347 | ALT_GPIO_PIN_POL_t pol, ALT_GPIO_PIN_DEBOUNCE_t debounc, |
---|
348 | uint32_t data) |
---|
349 | { |
---|
350 | ALT_STATUS_CODE ret; |
---|
351 | |
---|
352 | // set all affected GPIO bits to inputs |
---|
353 | ret = alt_gpio_port_datadir_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(ALT_GPIO_PIN_INPUT)); |
---|
354 | // the ALT_GPIO_ALLORNONE() macro expands the zero or one bit to the 29-bit GPIO word |
---|
355 | |
---|
356 | // set trigger type |
---|
357 | if (ret == ALT_E_SUCCESS) |
---|
358 | { |
---|
359 | ret = alt_gpio_port_int_type_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(type)); |
---|
360 | } |
---|
361 | |
---|
362 | // set polarity |
---|
363 | if (ret == ALT_E_SUCCESS) |
---|
364 | { |
---|
365 | alt_gpio_port_int_pol_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(pol)); |
---|
366 | } |
---|
367 | |
---|
368 | // set debounce |
---|
369 | if (ret == ALT_E_SUCCESS) |
---|
370 | { |
---|
371 | alt_gpio_port_debounce_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(debounc)); |
---|
372 | } |
---|
373 | |
---|
374 | // set data output(s) |
---|
375 | if (ret == ALT_E_SUCCESS) |
---|
376 | { |
---|
377 | alt_gpio_port_data_write(gpio_pid, mask, ALT_GPIO_ALLORNONE(data)); |
---|
378 | } |
---|
379 | |
---|
380 | if (ret == ALT_E_SUCCESS) |
---|
381 | { |
---|
382 | // set data direction of one or more bits to select output |
---|
383 | ret = alt_gpio_port_datadir_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(dir)); |
---|
384 | } |
---|
385 | |
---|
386 | return ret; |
---|
387 | } |
---|
388 | |
---|
389 | |
---|
390 | /****************************************************************************************/ |
---|
391 | /* Enables the specified GPIO data register interrupts. */ |
---|
392 | /****************************************************************************************/ |
---|
393 | |
---|
394 | ALT_STATUS_CODE alt_gpio_port_int_enable(ALT_GPIO_PORT_t gpio_pid, uint32_t config) |
---|
395 | { |
---|
396 | volatile uint32_t *addr; |
---|
397 | |
---|
398 | if (config & ~ALT_GPIO_BITMASK) { return ALT_E_ERROR; } |
---|
399 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTEN_ADDR; } |
---|
400 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTEN_ADDR; } |
---|
401 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTEN_ADDR; } |
---|
402 | else { return ALT_E_BAD_ARG; } |
---|
403 | |
---|
404 | alt_replbits_word(addr, config, UINT32_MAX); |
---|
405 | return ALT_E_SUCCESS; |
---|
406 | } |
---|
407 | |
---|
408 | |
---|
409 | /****************************************************************************************/ |
---|
410 | /* Disables the specified GPIO data module interrupts. */ |
---|
411 | /****************************************************************************************/ |
---|
412 | |
---|
413 | ALT_STATUS_CODE alt_gpio_port_int_disable(ALT_GPIO_PORT_t gpio_pid, uint32_t config) |
---|
414 | { |
---|
415 | volatile uint32_t *addr; |
---|
416 | |
---|
417 | if (config & ~ALT_GPIO_BITMASK) { return ALT_E_ERROR; } |
---|
418 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTEN_ADDR; } |
---|
419 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTEN_ADDR; } |
---|
420 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTEN_ADDR; } |
---|
421 | else { return ALT_E_BAD_ARG; } |
---|
422 | |
---|
423 | alt_replbits_word(addr, config, 0); |
---|
424 | return ALT_E_SUCCESS; |
---|
425 | } |
---|
426 | |
---|
427 | |
---|
428 | |
---|
429 | /****************************************************************************************/ |
---|
430 | /* Get the current state of the specified GPIO port interrupts enables. */ |
---|
431 | /****************************************************************************************/ |
---|
432 | |
---|
433 | uint32_t alt_gpio_port_int_enable_get(ALT_GPIO_PORT_t gpio_pid) |
---|
434 | { |
---|
435 | volatile uint32_t *addr; |
---|
436 | |
---|
437 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTEN_ADDR; } |
---|
438 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTEN_ADDR; } |
---|
439 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTEN_ADDR; } |
---|
440 | else { return 0; } |
---|
441 | |
---|
442 | return alt_read_word(addr); |
---|
443 | } |
---|
444 | |
---|
445 | |
---|
446 | /****************************************************************************************/ |
---|
447 | /* Masks or unmasks selected interrupt source bits of the data register of the */ |
---|
448 | /* specified GPIO module. Uses a second bit mask to determine which signals may be */ |
---|
449 | /* changed by this call. */ |
---|
450 | /****************************************************************************************/ |
---|
451 | |
---|
452 | ALT_STATUS_CODE alt_gpio_port_int_mask_set(ALT_GPIO_PORT_t gpio_pid, |
---|
453 | uint32_t mask, uint32_t val) |
---|
454 | { |
---|
455 | volatile uint32_t *addr; |
---|
456 | |
---|
457 | if ((mask & ~ALT_GPIO_BITMASK) || (val & ~ALT_GPIO_BITMASK)) { return ALT_E_ERROR; } |
---|
458 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTMSK_ADDR; } |
---|
459 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTMSK_ADDR; } |
---|
460 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTMSK_ADDR; } |
---|
461 | else { return ALT_E_BAD_ARG; } // argument error |
---|
462 | |
---|
463 | alt_replbits_word(addr, mask, val); |
---|
464 | return ALT_E_SUCCESS; |
---|
465 | } |
---|
466 | |
---|
467 | |
---|
468 | /****************************************************************************************/ |
---|
469 | /* Returns the interrupt source mask of the specified GPIO module. */ |
---|
470 | /****************************************************************************************/ |
---|
471 | |
---|
472 | uint32_t alt_gpio_port_int_mask_get(ALT_GPIO_PORT_t gpio_pid) |
---|
473 | { |
---|
474 | volatile uint32_t *addr; |
---|
475 | |
---|
476 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTMSK_ADDR; } |
---|
477 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTMSK_ADDR; } |
---|
478 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTMSK_ADDR; } |
---|
479 | else { return 0; } // error |
---|
480 | |
---|
481 | return alt_read_word(addr); |
---|
482 | } |
---|
483 | |
---|
484 | |
---|
485 | /****************************************************************************************/ |
---|
486 | /* alt_gpio_port_int_status_get() returns the interrupt pending status of all signals */ |
---|
487 | /* of the specified GPIO register. */ |
---|
488 | /****************************************************************************************/ |
---|
489 | |
---|
490 | uint32_t alt_gpio_port_int_status_get(ALT_GPIO_PORT_t gpio_pid) |
---|
491 | { |
---|
492 | volatile uint32_t *addr; |
---|
493 | |
---|
494 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTSTAT_ADDR; } |
---|
495 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTSTAT_ADDR; } |
---|
496 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTSTAT_ADDR; } |
---|
497 | else { return 0; } // error |
---|
498 | |
---|
499 | return alt_read_word(addr); |
---|
500 | } |
---|
501 | |
---|
502 | |
---|
503 | /****************************************************************************************/ |
---|
504 | /* Clear the interrupt pending status of selected signals of the specified GPIO */ |
---|
505 | /* register. */ |
---|
506 | /****************************************************************************************/ |
---|
507 | |
---|
508 | ALT_STATUS_CODE alt_gpio_port_int_status_clear(ALT_GPIO_PORT_t gpio_pid, |
---|
509 | uint32_t clrmask) |
---|
510 | { |
---|
511 | volatile uint32_t *addr; |
---|
512 | |
---|
513 | if (clrmask & ~ALT_GPIO_BITMASK) { return ALT_E_ERROR; } |
---|
514 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_INTSTAT_ADDR; } |
---|
515 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTSTAT_ADDR; } |
---|
516 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTSTAT_ADDR; } |
---|
517 | else { return ALT_E_BAD_ARG; } // argument error |
---|
518 | |
---|
519 | alt_write_word(addr, clrmask); |
---|
520 | return ALT_E_SUCCESS; |
---|
521 | } |
---|
522 | |
---|
523 | |
---|
524 | /****************************************************************************************/ |
---|
525 | /* alt_gpio_port_idcode_get() returns the ID code of the specified GPIO module. */ |
---|
526 | /****************************************************************************************/ |
---|
527 | |
---|
528 | uint32_t alt_gpio_port_idcode_get(ALT_GPIO_PORT_t gpio_pid) |
---|
529 | { |
---|
530 | volatile uint32_t *addr; |
---|
531 | |
---|
532 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_ID_CODE_ADDR; } |
---|
533 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_ID_CODE_ADDR; } |
---|
534 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_ID_CODE_ADDR; } |
---|
535 | else { return 0; } |
---|
536 | |
---|
537 | return alt_read_word(addr); |
---|
538 | } |
---|
539 | |
---|
540 | |
---|
541 | /****************************************************************************************/ |
---|
542 | /* alt_gpio_port_ver_get() returns the version code of the specified GPIO module. */ |
---|
543 | /****************************************************************************************/ |
---|
544 | |
---|
545 | uint32_t alt_gpio_port_ver_get(ALT_GPIO_PORT_t gpio_pid) |
---|
546 | { |
---|
547 | volatile uint32_t *addr; |
---|
548 | |
---|
549 | if (gpio_pid == ALT_GPIO_PORTA) { addr = ALT_GPIO0_VER_ID_CODE_ADDR; } |
---|
550 | else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_VER_ID_CODE_ADDR; } |
---|
551 | else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_VER_ID_CODE_ADDR; } |
---|
552 | else { return 0; } |
---|
553 | |
---|
554 | return alt_read_word(addr); |
---|
555 | } |
---|
556 | |
---|
557 | |
---|
558 | /****************************************************************************************/ |
---|
559 | /* alt_gpio_bit_config() configures one bit (signal) of the GPIO ports. */ |
---|
560 | /****************************************************************************************/ |
---|
561 | |
---|
562 | ALT_STATUS_CODE alt_gpio_bit_config(ALT_GPIO_1BIT_t signal_num, |
---|
563 | ALT_GPIO_PIN_DIR_t dir, ALT_GPIO_PIN_TYPE_t type, |
---|
564 | ALT_GPIO_PIN_POL_t pol, ALT_GPIO_PIN_DEBOUNCE_t debounce, |
---|
565 | ALT_GPIO_PIN_DATA_t data) |
---|
566 | { |
---|
567 | ALT_GPIO_PORT_t pid; |
---|
568 | uint32_t mask; |
---|
569 | |
---|
570 | pid = alt_gpio_bit_to_pid(signal_num); |
---|
571 | mask = 0x1 << alt_gpio_bit_to_port_pin(signal_num); |
---|
572 | return alt_gpio_port_config(pid, mask, dir, type, pol, debounce, data); |
---|
573 | } |
---|
574 | |
---|
575 | |
---|
576 | /****************************************************************************************/ |
---|
577 | /* Returns the configuration parameters of a given GPIO bit. */ |
---|
578 | /****************************************************************************************/ |
---|
579 | |
---|
580 | ALT_STATUS_CODE alt_gpio_bitconfig_get(ALT_GPIO_1BIT_t signal_num, |
---|
581 | ALT_GPIO_CONFIG_RECORD_t *config) |
---|
582 | { |
---|
583 | ALT_STATUS_CODE ret = ALT_E_ERROR; |
---|
584 | ALT_GPIO_PORT_t pid; |
---|
585 | uint32_t mask, shift; |
---|
586 | |
---|
587 | if ((config != NULL) && (signal_num != ALT_END_OF_GPIO_SIGNALS) && (signal_num <= ALT_LAST_VALID_GPIO_BIT)) |
---|
588 | { |
---|
589 | pid = alt_gpio_bit_to_pid(signal_num); |
---|
590 | shift = alt_gpio_bit_to_port_pin(signal_num); |
---|
591 | if ((pid != ALT_GPIO_PORT_UNKNOWN) && (shift <= ALT_GPIO_BIT_MAX)) |
---|
592 | { |
---|
593 | config->signal_number = signal_num; |
---|
594 | mask = 0x00000001 << shift; |
---|
595 | config->direction = (alt_gpio_port_datadir_get(pid, mask) == 0) ? ALT_GPIO_PIN_INPUT : ALT_GPIO_PIN_OUTPUT; |
---|
596 | config->type = (alt_gpio_port_int_type_get(pid, mask) == 0) ? ALT_GPIO_PIN_LEVEL_TRIG_INT : ALT_GPIO_PIN_EDGE_TRIG_INT; |
---|
597 | |
---|
598 | // save the following data whatever the state of config->direction |
---|
599 | config->polarity = (alt_gpio_port_int_pol_get(pid, mask) == 0) ? ALT_GPIO_PIN_ACTIVE_LOW : ALT_GPIO_PIN_ACTIVE_HIGH; |
---|
600 | config->debounce = (alt_gpio_port_debounce_get(pid, mask) == 0) ? ALT_GPIO_PIN_NODEBOUNCE : ALT_GPIO_PIN_DEBOUNCE; |
---|
601 | config->data = (alt_gpio_port_data_read(pid, mask) == 0) ? ALT_GPIO_PIN_DATAZERO : ALT_GPIO_PIN_DATAONE; |
---|
602 | ret = ALT_E_SUCCESS; |
---|
603 | } |
---|
604 | } |
---|
605 | return ret; |
---|
606 | } |
---|
607 | |
---|
608 | |
---|
609 | /****************************************************************************************/ |
---|
610 | /* alt_gpio_group_config() configures a list of GPIO bits. The GPIO bits do not have */ |
---|
611 | /* to be configured the same, as was the case for the mask version of this function, */ |
---|
612 | /* alt_gpio_port_config(). Each bit may be configured differently and bits may be */ |
---|
613 | /* listed in any order. */ |
---|
614 | /****************************************************************************************/ |
---|
615 | |
---|
616 | ALT_STATUS_CODE alt_gpio_group_config(ALT_GPIO_CONFIG_RECORD_t* config_array, uint32_t len) |
---|
617 | { |
---|
618 | ALT_STATUS_CODE ret = ALT_E_ERROR; |
---|
619 | |
---|
620 | if (config_array != NULL) |
---|
621 | { |
---|
622 | if (config_array->signal_number == ALT_END_OF_GPIO_SIGNALS) { ret = ALT_E_SUCCESS; } |
---|
623 | // catches the condition where the pointers are good, but the |
---|
624 | // first index is the escape character - which isn't an error |
---|
625 | else |
---|
626 | { |
---|
627 | for (; (len-- > 0) && (config_array->signal_number != ALT_END_OF_GPIO_SIGNALS) && (config_array != NULL); config_array++) |
---|
628 | { |
---|
629 | ret = alt_gpio_bit_config(config_array->signal_number, |
---|
630 | config_array->direction, config_array->type, config_array->polarity, |
---|
631 | config_array->debounce, config_array->data); |
---|
632 | if ((config_array->direction == ALT_GPIO_PIN_OUTPUT) && (ret == ALT_E_SUCCESS)) |
---|
633 | { |
---|
634 | // if the pin is set to be an output, set it to the correct value |
---|
635 | alt_gpio_port_data_write(alt_gpio_bit_to_pid(config_array->signal_number), |
---|
636 | 0x1 << alt_gpio_bit_to_port_pin(config_array->signal_number), |
---|
637 | ALT_GPIO_ALLORNONE(config_array->data)); |
---|
638 | // ret should retain the value returned by alt_gpio_bit_config() above |
---|
639 | // and should not be changed by the alt_gpio_port_data_write() call. |
---|
640 | } |
---|
641 | if (((ret != ALT_E_SUCCESS) && (config_array->signal_number <= ALT_LAST_VALID_GPIO_BIT)) |
---|
642 | || ((ret == ALT_E_SUCCESS) && (config_array->signal_number > ALT_LAST_VALID_GPIO_BIT))) |
---|
643 | { |
---|
644 | ret = ALT_E_ERROR; |
---|
645 | break; |
---|
646 | } |
---|
647 | } |
---|
648 | } |
---|
649 | } |
---|
650 | return ret; |
---|
651 | } |
---|
652 | |
---|
653 | |
---|
654 | /****************************************************************************************/ |
---|
655 | /* Returns a list of the pin signal indices and the associated configuration settings */ |
---|
656 | /* (data direction, interrupt type, polarity, debounce, and synchronization) of that */ |
---|
657 | /* list of signals. Only the signal indices in the first field of each configuration */ |
---|
658 | /* record need be filled in. This function will fill in all the other fields of the */ |
---|
659 | /* configuration record, returning all configuration parameters in the array. A signal */ |
---|
660 | /* number index in the array equal to ALT_END_OF_GPIO_SIGNALS (-1) also terminates the */ |
---|
661 | /* function. */ |
---|
662 | /****************************************************************************************/ |
---|
663 | |
---|
664 | ALT_STATUS_CODE alt_gpio_group_config_get(ALT_GPIO_CONFIG_RECORD_t *config_array, |
---|
665 | uint32_t len) |
---|
666 | { |
---|
667 | ALT_STATUS_CODE ret = ALT_E_ERROR; |
---|
668 | |
---|
669 | if ((config_array != NULL) && (config_array->signal_number == ALT_END_OF_GPIO_SIGNALS)) |
---|
670 | { |
---|
671 | ret = ALT_E_SUCCESS; |
---|
672 | } |
---|
673 | else |
---|
674 | { |
---|
675 | for ( ; (len > 0) && (config_array != NULL) && (config_array->signal_number != ALT_END_OF_GPIO_SIGNALS) |
---|
676 | && (config_array->signal_number <= ALT_LAST_VALID_GPIO_BIT); len--) |
---|
677 | { |
---|
678 | ret = alt_gpio_bitconfig_get(config_array->signal_number, config_array); |
---|
679 | config_array++; |
---|
680 | if (ret != ALT_E_SUCCESS) { break; } |
---|
681 | } |
---|
682 | } |
---|
683 | return ret; |
---|
684 | } |
---|
685 | |
---|
686 | /****************************************************************************************/ |
---|
687 | /* Another way to return a configuration list. The difference between this version and */ |
---|
688 | /* alt_gpio_group_config_get() is that this version follows a separate list of signal */ |
---|
689 | /* indices instead of having the signal list provided in the first field of the */ |
---|
690 | /* configuration records in the array. This function will fill in the fields of the */ |
---|
691 | /* configuration record, returning all configuration parameters in the array. A signal */ |
---|
692 | /* number index in the array equal to ALT_END_OF_GPIO_SIGNALS (-1) also terminates */ |
---|
693 | /* operation. */ |
---|
694 | /****************************************************************************************/ |
---|
695 | |
---|
696 | ALT_STATUS_CODE alt_gpio_group_config_get2(ALT_GPIO_1BIT_t* pinid_array, |
---|
697 | ALT_GPIO_CONFIG_RECORD_t *config_array, uint32_t len) |
---|
698 | { |
---|
699 | ALT_STATUS_CODE ret = ALT_E_ERROR; |
---|
700 | |
---|
701 | if ((config_array != NULL) && (pinid_array != NULL) && (*pinid_array == ALT_END_OF_GPIO_SIGNALS)) |
---|
702 | { |
---|
703 | ret = ALT_E_SUCCESS; |
---|
704 | // catches the condition where the pointers are good, but the |
---|
705 | // first index is the escape character - which isn't an error |
---|
706 | } |
---|
707 | else |
---|
708 | { |
---|
709 | for ( ;(len > 0) && (pinid_array != NULL) && (*pinid_array != ALT_END_OF_GPIO_SIGNALS) && (config_array != NULL); len--) |
---|
710 | { |
---|
711 | ret = alt_gpio_bitconfig_get(*pinid_array, config_array); |
---|
712 | config_array++; |
---|
713 | pinid_array++; |
---|
714 | if (ret != ALT_E_SUCCESS) { break; } |
---|
715 | } |
---|
716 | } |
---|
717 | return ret; |
---|
718 | } |
---|
719 | |
---|
720 | |
---|
721 | /****************************************************************************************/ |
---|
722 | /* A useful utility function. Extracts the GPIO port ID from the supplied GPIO Signal */ |
---|
723 | /* Index Number. */ |
---|
724 | /****************************************************************************************/ |
---|
725 | |
---|
726 | ALT_GPIO_PORT_t alt_gpio_bit_to_pid(ALT_GPIO_1BIT_t pin_num) |
---|
727 | { |
---|
728 | ALT_GPIO_PORT_t pid = ALT_GPIO_PORT_UNKNOWN; |
---|
729 | |
---|
730 | if (pin_num <= ALT_GPIO_EOPA) { pid = ALT_GPIO_PORTA; } |
---|
731 | else if (pin_num <= ALT_GPIO_EOPB) { pid = ALT_GPIO_PORTB; } |
---|
732 | else if (pin_num <= ALT_GPIO_EOPC) { pid = ALT_GPIO_PORTC; } |
---|
733 | return pid; |
---|
734 | } |
---|
735 | |
---|
736 | |
---|
737 | /****************************************************************************************/ |
---|
738 | /* A useful utility function. Extracts the GPIO signal (pin) mask from the supplied */ |
---|
739 | /* GPIO Signal Index Number. */ |
---|
740 | /****************************************************************************************/ |
---|
741 | |
---|
742 | ALT_GPIO_PORTBIT_t alt_gpio_bit_to_port_pin(ALT_GPIO_1BIT_t pin_num) |
---|
743 | { |
---|
744 | if (pin_num <= ALT_GPIO_EOPA) {} |
---|
745 | else if (pin_num <= ALT_GPIO_EOPB) { pin_num -= (ALT_GPIO_EOPA + 1); } |
---|
746 | else if (pin_num <= ALT_GPIO_EOPC) { pin_num -= (ALT_GPIO_EOPB + 1); } |
---|
747 | else { return ALT_END_OF_GPIO_PORT_SIGNALS; } |
---|
748 | return (ALT_GPIO_PORTBIT_t) pin_num; |
---|
749 | } |
---|
750 | |
---|
751 | |
---|
752 | /****************************************************************************************/ |
---|
753 | /* A useful utility function. Extracts the GPIO Signal Index Number from the supplied */ |
---|
754 | /* GPIO port ID and signal mask. If passed a bitmask composed of more than one signal, */ |
---|
755 | /* the signal number of the lowest bitmask presented is returned. */ |
---|
756 | /****************************************************************************************/ |
---|
757 | |
---|
758 | ALT_GPIO_1BIT_t alt_gpio_port_pin_to_bit(ALT_GPIO_PORT_t pid, |
---|
759 | uint32_t bitmask) |
---|
760 | { |
---|
761 | uint32_t i; |
---|
762 | |
---|
763 | for (i=0; i <= ALT_GPIO_BITNUM_MAX ;i++) |
---|
764 | { |
---|
765 | if (bitmask & 0x00000001) |
---|
766 | { |
---|
767 | if (pid == ALT_GPIO_PORTA) {} |
---|
768 | else if (pid == ALT_GPIO_PORTB) { i += ALT_GPIO_EOPA + 1; } |
---|
769 | else if (pid == ALT_GPIO_PORTC) { i += ALT_GPIO_EOPB + 1; } |
---|
770 | else { return ALT_END_OF_GPIO_SIGNALS; } |
---|
771 | return (ALT_GPIO_1BIT_t) i; |
---|
772 | } |
---|
773 | bitmask >>= 1; |
---|
774 | } |
---|
775 | return ALT_END_OF_GPIO_SIGNALS; |
---|
776 | } |
---|
777 | |
---|