Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:22:43

0001 /**
0002  * @file
0003  *
0004  * @ingroup RTEMSBSPsARMCycVContrib
0005  */
0006 
0007 /******************************************************************************
0008 *
0009 * Copyright 2013 Altera Corporation. All Rights Reserved.
0010 *
0011 * Redistribution and use in source and binary forms, with or without
0012 * modification, are permitted provided that the following conditions are met:
0013 *
0014 * 1. Redistributions of source code must retain the above copyright notice,
0015 * this list of conditions and the following disclaimer.
0016 *
0017 * 2. Redistributions in binary form must reproduce the above copyright notice,
0018 * this list of conditions and the following disclaimer in the documentation
0019 * and/or other materials provided with the distribution.
0020 *
0021 * 3. The name of the author may not be used to endorse or promote products
0022 * derived from this software without specific prior written permission.
0023 *
0024 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY EXPRESS OR
0025 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
0026 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED. IN NO
0027 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
0028 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
0029 * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
0030 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
0031 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
0032 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
0033 * OF SUCH DAMAGE.
0034 *
0035 ******************************************************************************/
0036 
0037 #include    <stdint.h>
0038 #include    <stdlib.h>
0039 #include    <stdbool.h>
0040 
0041 #include    <bsp/socal/hps.h>
0042 #include    <bsp/socal/socal.h>
0043 #include    <bsp/socal/alt_gpio.h>
0044 #include    <bsp/socal/alt_rstmgr.h>
0045 #include    <bsp/hwlib.h>
0046 #include    <bsp/alt_generalpurpose_io.h>
0047 
0048 
0049 /****************************************************************************************/
0050 /******************************* Useful local definitions *******************************/
0051 /****************************************************************************************/
0052 
0053 #define     ALT_GPIO_EOPA       ALT_GPIO_1BIT_28
0054 #define     ALT_GPIO_EOPB       ALT_GPIO_1BIT_57
0055 #define     ALT_GPIO_EOPC       ALT_HLGPI_15
0056 #define     ALT_GPIO_BITMASK    0x1FFFFFFF
0057 
0058             // expands the zero or one bit to the 29-bit GPIO word
0059 #define     ALT_GPIO_ALLORNONE(tst)  ((uint32_t) ((tst == 0) ? 0 : ALT_GPIO_BITMASK))
0060 
0061 
0062 /****************************************************************************************/
0063 /* alt_gpio_init() initializes the GPIO modules                                         */
0064 /****************************************************************************************/
0065 
0066 ALT_STATUS_CODE alt_gpio_init(void)
0067 {
0068         // put GPIO modules into system manager reset if not already there
0069     alt_gpio_uninit();
0070         // release GPIO modules from system reset (w/ two-instruction delay)
0071     alt_replbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_GPIO0_SET_MSK |
0072             ALT_RSTMGR_PERMODRST_GPIO1_SET_MSK |
0073             ALT_RSTMGR_PERMODRST_GPIO2_SET_MSK, 0);
0074     return ALT_E_SUCCESS;
0075 }
0076 
0077 
0078 /****************************************************************************************/
0079 /* alt_gpio_uninit() uninitializes the GPIO modules                                     */
0080 /****************************************************************************************/
0081 
0082 ALT_STATUS_CODE alt_gpio_uninit(void)
0083 {
0084     // put all GPIO modules into system manager reset
0085     alt_replbits_word(ALT_RSTMGR_PERMODRST_ADDR, ALT_RSTMGR_PERMODRST_GPIO0_SET_MSK |
0086             ALT_RSTMGR_PERMODRST_GPIO1_SET_MSK |
0087             ALT_RSTMGR_PERMODRST_GPIO2_SET_MSK,
0088             ALT_GPIO_BITMASK);
0089     return ALT_E_SUCCESS;
0090 }
0091 
0092 
0093 /****************************************************************************************/
0094 /* alt_gpio_port_datadir_set() sets the specified GPIO data bits to use the data        */
0095 /* direction(s) specified. 0 = input (default). 1 = output.                             */
0096 /****************************************************************************************/
0097 
0098 ALT_STATUS_CODE alt_gpio_port_datadir_set(ALT_GPIO_PORT_t gpio_pid,
0099         uint32_t mask, uint32_t config)
0100 {
0101     volatile uint32_t   *addr;
0102 
0103     if ((mask & ~ALT_GPIO_BITMASK) || (config & ~ALT_GPIO_BITMASK))  { return ALT_E_ERROR; }
0104     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_SWPORTA_DDR_ADDR; }
0105     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_SWPORTA_DDR_ADDR; }
0106     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_SWPORTA_DDR_ADDR; }
0107     else { return ALT_E_BAD_ARG; }
0108 
0109     alt_replbits_word(addr, mask, config);
0110     return ALT_E_SUCCESS;
0111 }
0112 
0113 
0114 /****************************************************************************************/
0115 /*  alt_gpio_port_datadir_get() returns the data direction configuration of selected    */
0116 /* bits of the designated GPIO module.                                                  */
0117 /****************************************************************************************/
0118 
0119 uint32_t alt_gpio_port_datadir_get(ALT_GPIO_PORT_t gpio_pid,
0120         uint32_t mask)
0121 {
0122     volatile uint32_t   *addr;
0123 
0124     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_SWPORTA_DDR_ADDR; }
0125     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_SWPORTA_DDR_ADDR; }
0126     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_SWPORTA_DDR_ADDR; }
0127     else { return 0; }
0128 
0129     return alt_read_word(addr) & mask;
0130 }
0131 
0132 
0133 /****************************************************************************************/
0134 /* alt_gpio_port_data_write() sets the GPIO data outputs of the specified GPIO module   */
0135 /* to a one or zero. Actual outputs are only set if the data direction for that bit(s)  */
0136 /* has previously been set to configure them as output(s).                              */
0137 /****************************************************************************************/
0138 
0139 ALT_STATUS_CODE alt_gpio_port_data_write(ALT_GPIO_PORT_t gpio_pid,
0140         uint32_t mask, uint32_t val)
0141 {
0142     volatile uint32_t   *addr;
0143 
0144     if ((mask & ~ALT_GPIO_BITMASK) || (val & ~ALT_GPIO_BITMASK))  { return ALT_E_ERROR; }
0145     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_SWPORTA_DR_ADDR; }
0146     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_SWPORTA_DR_ADDR; }
0147     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_SWPORTA_DR_ADDR; }
0148     else { return ALT_E_BAD_ARG; }
0149 
0150     alt_replbits_word(addr, mask, val);
0151     return ALT_E_SUCCESS;
0152 }
0153 
0154 
0155 /****************************************************************************************/
0156 /* alt_gpio_port_data_read() returns the value of the data inputs of the specified      */
0157 /* GPIO module. Data direction for these bits must have been previously set to inputs.  */
0158 /****************************************************************************************/
0159 
0160 #if (!ALT_GPIO_DATAREAD_TEST_MODE)
0161     /* This is the production code version. For software unit testing, set the      */
0162     /* ALT_GPIO_DATAREAD_TEST_MODE flag to true in the makefile, which will compile */
0163     /* the GPIO test software version of alt_gpio_port_data_read() instead.         */
0164 
0165 uint32_t alt_gpio_port_data_read(ALT_GPIO_PORT_t gpio_pid, uint32_t mask)
0166 {
0167     volatile uint32_t   *addr;
0168 
0169     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_EXT_PORTA_ADDR; }
0170     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_EXT_PORTA_ADDR; }
0171     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_EXT_PORTA_ADDR; }
0172     else { return 0; }
0173 
0174     return alt_read_word(addr) & mask;
0175 }
0176 #endif
0177 
0178 
0179 /****************************************************************************************/
0180 /* alt_gpio_port_int_type_set() sets selected signals of the specified GPIO port to     */
0181 /* be either level-sensitive ( =0) or edge-triggered ( =1).                             */
0182 /****************************************************************************************/
0183 
0184 ALT_STATUS_CODE alt_gpio_port_int_type_set(ALT_GPIO_PORT_t gpio_pid,
0185         uint32_t mask, uint32_t config)
0186 {
0187     volatile uint32_t   *addr;
0188 
0189     if ((mask & ~ALT_GPIO_BITMASK) || (config & ~ALT_GPIO_BITMASK))  { return ALT_E_ERROR; }
0190     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_INTTYPE_LEVEL_ADDR; }
0191     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTTYPE_LEVEL_ADDR; }
0192     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTTYPE_LEVEL_ADDR; }
0193     else { return ALT_E_BAD_ARG; }
0194 
0195     alt_replbits_word(addr, mask, config);
0196     return ALT_E_SUCCESS;
0197 }
0198 
0199 
0200 /****************************************************************************************/
0201 /* alt_gpio_port_int_type_get() returns the interrupt configuration (edge-triggered or  */
0202 /* level-triggered) for the specified signals of the specified GPIO module.             */
0203 /****************************************************************************************/
0204 
0205 uint32_t alt_gpio_port_int_type_get(ALT_GPIO_PORT_t gpio_pid,
0206         uint32_t mask)
0207 {
0208     volatile uint32_t   *addr;
0209 
0210     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_INTTYPE_LEVEL_ADDR; }
0211     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTTYPE_LEVEL_ADDR; }
0212     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTTYPE_LEVEL_ADDR; }
0213     else { return 0; }
0214 
0215     return alt_read_word(addr) & mask;
0216 }
0217 
0218 
0219 /****************************************************************************************/
0220 /* alt_gpio_port_int_pol_set() sets the interrupt polarity of the signals of the        */
0221 /* specified GPIO register (when used as inputs) to active-high ( =0) or active-low     */
0222 /* ( =1).                                                                               */
0223 /****************************************************************************************/
0224 
0225 ALT_STATUS_CODE alt_gpio_port_int_pol_set(ALT_GPIO_PORT_t gpio_pid,
0226         uint32_t mask, uint32_t config)
0227 {
0228     volatile uint32_t   *addr;
0229 
0230     if ((mask & ~ALT_GPIO_BITMASK) || (config & ~ALT_GPIO_BITMASK))  { return ALT_E_ERROR; }
0231     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_INT_POL_ADDR; }
0232     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INT_POL_ADDR; }
0233     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INT_POL_ADDR; }
0234     else { return ALT_E_BAD_ARG; }
0235 
0236     alt_replbits_word(addr, mask, config);
0237     return ALT_E_SUCCESS;
0238 }
0239 
0240 
0241 /****************************************************************************************/
0242 /* alt_gpio_port_int_pol_get() returns the active-high or active-low polarity           */
0243 /* configuration for the possible interrupt sources of the specified GPIO module.       */
0244 /* 0 = The interrupt polarity for this bit is set to active-low mode. 1 = The           */
0245 /* interrupt polarity for this bit is set to active-highmode.                           */
0246 /****************************************************************************************/
0247 
0248 uint32_t alt_gpio_port_int_pol_get(ALT_GPIO_PORT_t gpio_pid,
0249         uint32_t mask)
0250 {
0251     volatile uint32_t   *addr;
0252 
0253     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_INT_POL_ADDR; }
0254     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INT_POL_ADDR; }
0255     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INT_POL_ADDR; }
0256     else { return 0; }
0257 
0258     return alt_read_word(addr) & mask;
0259 }
0260 
0261 
0262 /****************************************************************************************/
0263 /* alt_gpio_port_debounce_set() sets the debounce configuration for input signals of    */
0264 /* the specified GPIO module. 0 - Debounce is not selected for this signal (default).   */
0265 /* 1 - Debounce is selected for this signal.                                            */
0266 /****************************************************************************************/
0267 
0268 ALT_STATUS_CODE alt_gpio_port_debounce_set(ALT_GPIO_PORT_t gpio_pid,
0269         uint32_t mask, uint32_t config)
0270 {
0271     volatile uint32_t   *addr;
0272 
0273     if ((mask & ~ALT_GPIO_BITMASK) || (config & ~ALT_GPIO_BITMASK))  { return ALT_E_ERROR; }
0274     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_DEBOUNCE_ADDR; }
0275     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_DEBOUNCE_ADDR; }
0276     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_DEBOUNCE_ADDR; }
0277     else { return ALT_E_BAD_ARG; }
0278 
0279     alt_replbits_word(addr, mask, config);
0280     return ALT_E_SUCCESS;
0281 }
0282 
0283 
0284 /****************************************************************************************/
0285 /* alt_gpio_port_debounce_get() returns the debounce configuration for the input        */
0286 /* signals of the specified GPIO register. 0 - Debounce is not selected for this        */
0287 /* signal. 1 - Debounce is selected for this signal.                                    */
0288 /****************************************************************************************/
0289 
0290 uint32_t alt_gpio_port_debounce_get(ALT_GPIO_PORT_t gpio_pid,
0291         uint32_t mask)
0292 {
0293     volatile uint32_t   *addr;
0294 
0295     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_DEBOUNCE_ADDR; }
0296     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_DEBOUNCE_ADDR; }
0297     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_DEBOUNCE_ADDR; }
0298     else { return 0; }
0299 
0300     return alt_read_word(addr) & mask;
0301 }
0302 
0303 
0304 /****************************************************************************************/
0305 /* alt_gpio_port_sync_set() sets the synchronization configuration for the signals of   */
0306 /* the specified GPIO register. This allows for synchronizing level-sensitive           */
0307 /* interrupts to the internal clock signal. This is a port-wide option that controls    */
0308 /* all level-sensitive interrupt signals of that GPIO port.                             */
0309 /****************************************************************************************/
0310 
0311 ALT_STATUS_CODE alt_gpio_port_sync_set(ALT_GPIO_PORT_t gpio_pid, uint32_t config)
0312 {
0313     volatile uint32_t   *addr;
0314 
0315     config = (config != 0) ? 1 : 0;
0316     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_LS_SYNC_ADDR; }
0317     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_LS_SYNC_ADDR; }
0318     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_LS_SYNC_ADDR; }
0319     else { return ALT_E_BAD_ARG; }
0320 
0321     alt_write_word(addr, config);
0322     return ALT_E_SUCCESS;
0323 }
0324 
0325 
0326 /****************************************************************************************/
0327 /* alt_gpio_port_sync_get() returns the synchronization configuration for the signals   */
0328 /* of the specified GPIO register. This allows for synchronizing level-sensitive        */
0329 /* interrupts to the internal clock signal. This is a port-wide option that controls    */
0330 /* all level-sensitive interrupt signals of that GPIO port.                             */
0331 /****************************************************************************************/
0332 
0333 ALT_STATUS_CODE alt_gpio_port_sync_get(ALT_GPIO_PORT_t gpio_pid)
0334 {
0335     volatile uint32_t   *addr;
0336 
0337     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_LS_SYNC_ADDR; }
0338     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_LS_SYNC_ADDR; }
0339     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_LS_SYNC_ADDR; }
0340     else { return ALT_E_BAD_ARG; }         // error
0341 
0342     return (alt_read_word(addr) != 0) ? ALT_E_TRUE : ALT_E_FALSE;
0343 }
0344 
0345 
0346 /****************************************************************************************/
0347 /* alt_gpio_port_config() configures a group of GPIO signals with the same parameters.  */
0348 /* Allows for configuring all parameters of a given port at one time.                   */
0349 /****************************************************************************************/
0350 
0351 ALT_STATUS_CODE alt_gpio_port_config(ALT_GPIO_PORT_t gpio_pid,
0352         uint32_t mask, ALT_GPIO_PIN_DIR_t dir, ALT_GPIO_PIN_TYPE_t type,
0353         ALT_GPIO_PIN_POL_t pol, ALT_GPIO_PIN_DEBOUNCE_t debounc,
0354         uint32_t data)
0355 {
0356     ALT_STATUS_CODE     ret;
0357 
0358         // set all affected GPIO bits to inputs
0359     ret = alt_gpio_port_datadir_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(ALT_GPIO_PIN_INPUT));
0360                 // the ALT_GPIO_ALLORNONE() macro expands the zero or one bit to the 29-bit GPIO word
0361 
0362         // set trigger type
0363     if (ret == ALT_E_SUCCESS)
0364     {
0365         ret = alt_gpio_port_int_type_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(type));
0366     }
0367 
0368         // set polarity
0369     if (ret == ALT_E_SUCCESS)
0370     {
0371         alt_gpio_port_int_pol_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(pol));
0372     }
0373 
0374         // set debounce
0375     if (ret == ALT_E_SUCCESS)
0376     {
0377         alt_gpio_port_debounce_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(debounc));
0378     }
0379 
0380         // set data output(s)
0381     if (ret == ALT_E_SUCCESS)
0382     {
0383         alt_gpio_port_data_write(gpio_pid, mask, ALT_GPIO_ALLORNONE(data));
0384     }
0385 
0386     if (ret == ALT_E_SUCCESS)
0387     {
0388         // set data direction of one or more bits to select output
0389         ret = alt_gpio_port_datadir_set(gpio_pid, mask, ALT_GPIO_ALLORNONE(dir));
0390     }
0391 
0392     return ret;
0393 }
0394 
0395 
0396 /****************************************************************************************/
0397 /* Enables the specified GPIO data register interrupts.                                 */
0398 /****************************************************************************************/
0399 
0400 ALT_STATUS_CODE alt_gpio_port_int_enable(ALT_GPIO_PORT_t gpio_pid, uint32_t config)
0401 {
0402     volatile uint32_t   *addr;
0403 
0404     if (config & ~ALT_GPIO_BITMASK)      { return ALT_E_ERROR; }
0405     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_INTEN_ADDR; }
0406     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTEN_ADDR; }
0407     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTEN_ADDR; }
0408     else { return ALT_E_BAD_ARG; }
0409 
0410     alt_replbits_word(addr, config, UINT32_MAX);
0411     return ALT_E_SUCCESS;
0412 }
0413 
0414 
0415 /****************************************************************************************/
0416 /* Disables the specified GPIO data module interrupts.                                  */
0417 /****************************************************************************************/
0418 
0419 ALT_STATUS_CODE alt_gpio_port_int_disable(ALT_GPIO_PORT_t gpio_pid, uint32_t config)
0420 {
0421     volatile uint32_t   *addr;
0422 
0423     if (config & ~ALT_GPIO_BITMASK)      { return ALT_E_ERROR; }
0424     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_INTEN_ADDR; }
0425     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTEN_ADDR; }
0426     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTEN_ADDR; }
0427     else { return ALT_E_BAD_ARG; }
0428 
0429     alt_replbits_word(addr, config, 0);
0430     return ALT_E_SUCCESS;
0431 }
0432 
0433 
0434 
0435 /****************************************************************************************/
0436 /* Get the current state of the specified GPIO port interrupts enables.                 */
0437 /****************************************************************************************/
0438 
0439 uint32_t alt_gpio_port_int_enable_get(ALT_GPIO_PORT_t gpio_pid)
0440 {
0441     volatile uint32_t   *addr;
0442 
0443     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_INTEN_ADDR; }
0444     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTEN_ADDR; }
0445     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTEN_ADDR; }
0446     else { return 0; }
0447 
0448     return alt_read_word(addr);
0449 }
0450 
0451 
0452 /****************************************************************************************/
0453 /* Masks or unmasks selected interrupt source bits of the data register of the          */
0454 /* specified GPIO module. Uses a second bit mask to determine which signals may be      */
0455 /* changed by this call.                                                                */
0456 /****************************************************************************************/
0457 
0458 ALT_STATUS_CODE alt_gpio_port_int_mask_set(ALT_GPIO_PORT_t gpio_pid,
0459         uint32_t mask, uint32_t val)
0460 {
0461     volatile uint32_t   *addr;
0462 
0463     if ((mask & ~ALT_GPIO_BITMASK) || (val & ~ALT_GPIO_BITMASK))  { return ALT_E_ERROR; }
0464     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_INTMSK_ADDR; }
0465     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTMSK_ADDR; }
0466     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTMSK_ADDR; }
0467     else { return ALT_E_BAD_ARG; }         // argument error
0468 
0469     alt_replbits_word(addr, mask, val);
0470     return ALT_E_SUCCESS;
0471 }
0472 
0473 
0474 /****************************************************************************************/
0475 /* Returns the interrupt source mask of the specified GPIO module.                      */
0476 /****************************************************************************************/
0477 
0478 uint32_t alt_gpio_port_int_mask_get(ALT_GPIO_PORT_t gpio_pid)
0479 {
0480     volatile uint32_t   *addr;
0481 
0482     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_INTMSK_ADDR; }
0483     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTMSK_ADDR; }
0484     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTMSK_ADDR; }
0485     else { return 0; }         // error
0486 
0487     return alt_read_word(addr);
0488 }
0489 
0490 
0491 /****************************************************************************************/
0492 /* alt_gpio_port_int_status_get() returns the interrupt pending status of all signals   */
0493 /* of the specified GPIO register.                                                      */
0494 /****************************************************************************************/
0495 
0496 uint32_t alt_gpio_port_int_status_get(ALT_GPIO_PORT_t gpio_pid)
0497 {
0498     volatile uint32_t   *addr;
0499 
0500     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_INTSTAT_ADDR; }
0501     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTSTAT_ADDR; }
0502     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTSTAT_ADDR; }
0503     else { return 0; }         // error
0504 
0505     return alt_read_word(addr);
0506 }
0507 
0508 
0509 /****************************************************************************************/
0510 /* Clear the interrupt pending status of selected signals of the specified GPIO         */
0511 /* register.                                                                            */
0512 /****************************************************************************************/
0513 
0514 ALT_STATUS_CODE alt_gpio_port_int_status_clear(ALT_GPIO_PORT_t gpio_pid,
0515         uint32_t clrmask)
0516 {
0517     volatile uint32_t   *addr;
0518 
0519     if (clrmask & ~ALT_GPIO_BITMASK)      { return ALT_E_ERROR; }
0520     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_INTSTAT_ADDR; }
0521     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_INTSTAT_ADDR; }
0522     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_INTSTAT_ADDR; }
0523     else { return ALT_E_BAD_ARG; }         // argument error
0524 
0525     alt_write_word(addr, clrmask);
0526     return ALT_E_SUCCESS;
0527 }
0528 
0529 
0530 /****************************************************************************************/
0531 /*  alt_gpio_port_idcode_get() returns the ID code of the specified GPIO module.        */
0532 /****************************************************************************************/
0533 
0534 uint32_t alt_gpio_port_idcode_get(ALT_GPIO_PORT_t gpio_pid)
0535 {
0536     volatile uint32_t   *addr;
0537 
0538     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_ID_CODE_ADDR; }
0539     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_ID_CODE_ADDR; }
0540     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_ID_CODE_ADDR; }
0541     else { return 0; }
0542 
0543     return alt_read_word(addr);
0544 }
0545 
0546 
0547 /****************************************************************************************/
0548 /* alt_gpio_port_ver_get() returns the version code of the specified GPIO module.       */
0549 /****************************************************************************************/
0550 
0551 uint32_t alt_gpio_port_ver_get(ALT_GPIO_PORT_t gpio_pid)
0552 {
0553     volatile uint32_t   *addr;
0554 
0555     if (gpio_pid == ALT_GPIO_PORTA)      { addr = ALT_GPIO0_VER_ID_CODE_ADDR; }
0556     else if (gpio_pid == ALT_GPIO_PORTB) { addr = ALT_GPIO1_VER_ID_CODE_ADDR; }
0557     else if (gpio_pid == ALT_GPIO_PORTC) { addr = ALT_GPIO2_VER_ID_CODE_ADDR; }
0558     else { return 0; }
0559 
0560     return alt_read_word(addr);
0561 }
0562 
0563 
0564 /****************************************************************************************/
0565 /* alt_gpio_bit_config() configures one bit (signal) of the GPIO ports.                 */
0566 /****************************************************************************************/
0567 
0568 ALT_STATUS_CODE alt_gpio_bit_config(ALT_GPIO_1BIT_t signal_num,
0569         ALT_GPIO_PIN_DIR_t dir, ALT_GPIO_PIN_TYPE_t type,
0570         ALT_GPIO_PIN_POL_t pol, ALT_GPIO_PIN_DEBOUNCE_t debounce,
0571         ALT_GPIO_PIN_DATA_t data)
0572 {
0573     ALT_GPIO_PORT_t     pid;
0574     uint32_t            mask;
0575 
0576     pid = alt_gpio_bit_to_pid(signal_num);
0577     mask = 0x1 << alt_gpio_bit_to_port_pin(signal_num);
0578     return alt_gpio_port_config(pid, mask, dir, type, pol, debounce, data);
0579 }
0580 
0581 
0582 /****************************************************************************************/
0583 /* Returns the configuration parameters of a given GPIO bit.                            */
0584 /****************************************************************************************/
0585 
0586 ALT_STATUS_CODE alt_gpio_bitconfig_get(ALT_GPIO_1BIT_t signal_num,
0587         ALT_GPIO_CONFIG_RECORD_t *config)
0588 {
0589     ALT_STATUS_CODE     ret = ALT_E_ERROR;
0590     ALT_GPIO_PORT_t     pid;
0591     uint32_t            mask, shift;
0592 
0593     if ((config != NULL) && (signal_num != ALT_END_OF_GPIO_SIGNALS) && (signal_num <= ALT_LAST_VALID_GPIO_BIT))
0594     {
0595         pid = alt_gpio_bit_to_pid(signal_num);
0596         shift = alt_gpio_bit_to_port_pin(signal_num);
0597         if ((pid != ALT_GPIO_PORT_UNKNOWN) && (shift <= ALT_GPIO_BIT_MAX))
0598         {
0599             config->signal_number = signal_num;
0600             mask = 0x00000001 << shift;
0601             config->direction = (alt_gpio_port_datadir_get(pid, mask) == 0) ? ALT_GPIO_PIN_INPUT : ALT_GPIO_PIN_OUTPUT;
0602             config->type = (alt_gpio_port_int_type_get(pid, mask) == 0) ? ALT_GPIO_PIN_LEVEL_TRIG_INT : ALT_GPIO_PIN_EDGE_TRIG_INT;
0603 
0604             // save the following data whatever the state of config->direction
0605             config->polarity = (alt_gpio_port_int_pol_get(pid, mask) == 0) ? ALT_GPIO_PIN_ACTIVE_LOW : ALT_GPIO_PIN_ACTIVE_HIGH;
0606             config->debounce = (alt_gpio_port_debounce_get(pid, mask) == 0) ? ALT_GPIO_PIN_NODEBOUNCE : ALT_GPIO_PIN_DEBOUNCE;
0607             config->data = (alt_gpio_port_data_read(pid, mask) == 0) ? ALT_GPIO_PIN_DATAZERO : ALT_GPIO_PIN_DATAONE;
0608             ret = ALT_E_SUCCESS;
0609         }
0610     }
0611     return ret;
0612 }
0613 
0614 
0615 /****************************************************************************************/
0616 /* alt_gpio_group_config() configures a list of GPIO bits. The GPIO bits do not have    */
0617 /* to be configured the same, as was the case for the mask version of this function,    */
0618 /* alt_gpio_port_config(). Each bit may be configured differently and bits may be       */
0619 /* listed in any order.                                                                 */
0620 /****************************************************************************************/
0621 
0622 ALT_STATUS_CODE alt_gpio_group_config(ALT_GPIO_CONFIG_RECORD_t* config_array, uint32_t len)
0623 {
0624     ALT_STATUS_CODE         ret = ALT_E_ERROR;
0625 
0626     if (config_array != NULL)
0627     {
0628         if (config_array->signal_number == ALT_END_OF_GPIO_SIGNALS) { ret = ALT_E_SUCCESS; }
0629             // catches the condition where the pointers are good, but the
0630             // first index is the escape character - which isn't an error
0631         else
0632         {
0633             for (; (len-- > 0) && (config_array->signal_number != ALT_END_OF_GPIO_SIGNALS) && (config_array != NULL); config_array++)
0634             {
0635                 ret = alt_gpio_bit_config(config_array->signal_number,
0636                         config_array->direction, config_array->type, config_array->polarity,
0637                         config_array->debounce, config_array->data);
0638                 if ((config_array->direction == ALT_GPIO_PIN_OUTPUT) && (ret == ALT_E_SUCCESS))
0639                 {
0640                     // if the pin is set to be an output, set it to the correct value
0641                     alt_gpio_port_data_write(alt_gpio_bit_to_pid(config_array->signal_number),
0642                              0x1 << alt_gpio_bit_to_port_pin(config_array->signal_number),
0643                              ALT_GPIO_ALLORNONE(config_array->data));
0644                         // ret should retain the value returned by alt_gpio_bit_config() above
0645                         // and should not be changed by the alt_gpio_port_data_write() call.
0646                 }
0647                 if (((ret != ALT_E_SUCCESS) && (config_array->signal_number <= ALT_LAST_VALID_GPIO_BIT))
0648                     || ((ret == ALT_E_SUCCESS) && (config_array->signal_number > ALT_LAST_VALID_GPIO_BIT)))
0649                 {
0650                     ret = ALT_E_ERROR;
0651                     break;
0652                 }
0653             }
0654         }
0655     }
0656     return ret;
0657 }
0658 
0659 
0660 /****************************************************************************************/
0661 /* Returns a list of the pin signal indices and the associated configuration settings   */
0662 /* (data direction, interrupt type, polarity, debounce, and synchronization) of that    */
0663 /* list of signals. Only the signal indices in the first field of each configuration    */
0664 /* record need be filled in. This function will fill in all the other fields of the     */
0665 /* configuration record, returning all configuration parameters in the array. A signal  */
0666 /* number index in the array equal to ALT_END_OF_GPIO_SIGNALS (-1) also terminates the  */
0667 /* function.                                                                            */
0668 /****************************************************************************************/
0669 
0670 ALT_STATUS_CODE alt_gpio_group_config_get(ALT_GPIO_CONFIG_RECORD_t *config_array,
0671         uint32_t len)
0672 {
0673     ALT_STATUS_CODE     ret = ALT_E_ERROR;
0674 
0675     if ((config_array != NULL) && (config_array->signal_number == ALT_END_OF_GPIO_SIGNALS))
0676     {
0677         ret = ALT_E_SUCCESS;
0678     }
0679     else
0680     {
0681         for ( ; (len > 0) && (config_array != NULL) && (config_array->signal_number != ALT_END_OF_GPIO_SIGNALS)
0682                     && (config_array->signal_number <= ALT_LAST_VALID_GPIO_BIT); len--)
0683         {
0684             ret = alt_gpio_bitconfig_get(config_array->signal_number, config_array);
0685             config_array++;
0686             if (ret != ALT_E_SUCCESS) { break; }
0687         }
0688     }
0689     return ret;
0690 }
0691 
0692 /****************************************************************************************/
0693 /* Another way to return a configuration list. The difference between this version and  */
0694 /* alt_gpio_group_config_get() is that this version follows a separate list of signal   */
0695 /* indices instead of having the signal list provided in the first field of the         */
0696 /* configuration records in the array. This function will fill in the fields of the     */
0697 /* configuration record, returning all configuration parameters in the array. A signal  */
0698 /* number index in the array equal to ALT_END_OF_GPIO_SIGNALS (-1) also terminates      */
0699 /* operation.                                                                           */
0700 /****************************************************************************************/
0701 
0702 ALT_STATUS_CODE alt_gpio_group_config_get2(ALT_GPIO_1BIT_t* pinid_array,
0703         ALT_GPIO_CONFIG_RECORD_t *config_array, uint32_t len)
0704 {
0705     ALT_STATUS_CODE     ret = ALT_E_ERROR;
0706 
0707     if ((config_array != NULL) && (pinid_array != NULL) && (*pinid_array == ALT_END_OF_GPIO_SIGNALS))
0708     {
0709         ret = ALT_E_SUCCESS;
0710         // catches the condition where the pointers are good, but the
0711         // first index is the escape character - which isn't an error
0712     }
0713     else
0714     {
0715         for ( ;(len > 0) && (pinid_array != NULL) && (*pinid_array != ALT_END_OF_GPIO_SIGNALS) && (config_array != NULL); len--)
0716         {
0717             ret = alt_gpio_bitconfig_get(*pinid_array, config_array);
0718             config_array++;
0719             pinid_array++;
0720             if (ret != ALT_E_SUCCESS) { break; }
0721         }
0722     }
0723     return ret;
0724 }
0725 
0726 
0727 /****************************************************************************************/
0728 /* A useful utility function. Extracts the GPIO port ID from the supplied GPIO Signal   */
0729 /* Index Number.                                                                        */
0730 /****************************************************************************************/
0731 
0732 ALT_GPIO_PORT_t alt_gpio_bit_to_pid(ALT_GPIO_1BIT_t pin_num)
0733 {
0734     ALT_GPIO_PORT_t     pid = ALT_GPIO_PORT_UNKNOWN;
0735 
0736     if (pin_num <= ALT_GPIO_EOPA) { pid = ALT_GPIO_PORTA; }
0737     else if (pin_num <= ALT_GPIO_EOPB) { pid = ALT_GPIO_PORTB; }
0738     else if (pin_num <= ALT_GPIO_EOPC) { pid = ALT_GPIO_PORTC; }
0739     return pid;
0740 }
0741 
0742 
0743 /****************************************************************************************/
0744 /* A useful utility function. Extracts the GPIO signal (pin) mask from the supplied     */
0745 /* GPIO Signal Index Number.                                                           */
0746 /****************************************************************************************/
0747 
0748 ALT_GPIO_PORTBIT_t alt_gpio_bit_to_port_pin(ALT_GPIO_1BIT_t pin_num)
0749 {
0750     if (pin_num <= ALT_GPIO_EOPA) {}
0751     else if (pin_num <= ALT_GPIO_EOPB) { pin_num -= (ALT_GPIO_EOPA + 1); }
0752     else if (pin_num <= ALT_GPIO_EOPC) { pin_num -= (ALT_GPIO_EOPB + 1); }
0753     else { return ALT_END_OF_GPIO_PORT_SIGNALS; }
0754     return (ALT_GPIO_PORTBIT_t) pin_num;
0755 }
0756 
0757 
0758 /****************************************************************************************/
0759 /* A useful utility function. Extracts the GPIO Signal Index Number from the supplied   */
0760 /* GPIO port ID and signal mask. If passed a bitmask composed of more than one signal,  */
0761 /* the signal number of the lowest bitmask presented is returned.                       */
0762 /****************************************************************************************/
0763 
0764 ALT_GPIO_1BIT_t alt_gpio_port_pin_to_bit(ALT_GPIO_PORT_t pid,
0765         uint32_t bitmask)
0766 {
0767     uint32_t    i;
0768 
0769     for (i=0; i <= ALT_GPIO_BITNUM_MAX ;i++)
0770     {
0771         if (bitmask & 0x00000001)
0772         {
0773             if (pid == ALT_GPIO_PORTA) {}
0774             else if (pid == ALT_GPIO_PORTB) { i += ALT_GPIO_EOPA + 1; }
0775             else if (pid == ALT_GPIO_PORTC) { i += ALT_GPIO_EOPB + 1; }
0776             else { return ALT_END_OF_GPIO_SIGNALS; }
0777             return (ALT_GPIO_1BIT_t) i;
0778         }
0779         bitmask >>= 1;
0780     }
0781     return ALT_END_OF_GPIO_SIGNALS;
0782 }
0783