source: rtems/c/src/lib/libbsp/arm/altera-cyclone-v/hwlib/src/hwmgr/alt_generalpurpose_io.c @ 3eed4f3

5
Last change on this file since 3eed4f3 was 3eed4f3, checked in by Chris Johns <chrisj@…>, on 01/04/18 at 07:10:48

bsp/altera-cyclone-v: Use public include path

Update #3254.

  • Property mode set to 100644
File size: 33.4 KB
Line 
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
60ALT_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
76ALT_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
92ALT_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
113uint32_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
133ALT_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
159uint32_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
178ALT_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
199uint32_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
219ALT_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
242uint32_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
262ALT_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
284uint32_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
305ALT_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
327ALT_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
345ALT_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
394ALT_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
413ALT_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
433uint32_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
452ALT_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
472uint32_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
490uint32_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
508ALT_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
528uint32_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
545uint32_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
562ALT_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
580ALT_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
616ALT_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
664ALT_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
696ALT_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
726ALT_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
742ALT_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
758ALT_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
Note: See TracBrowser for help on using the repository browser.