<div dir="ltr">Hi Andre,<div><br></div><div>Great API and happy to know that it is merged with main line. </div><div><br></div><div>Eventually I implemented GPIO driver for BBB using this API. After debugging for rtems_gpio_get_value() on BBB I found the following bug. </div><div><br></div><div>For BBB, GPIO pin nos. varies from 0 to 32. So function return type would be uint32_t instead of uint8_t.</div><div><br></div><div>For BBB I wrote :-</div><div><br></div><div>uint32_t rtems_gpio_bsp_get_value(uint32_t bank, uint32_t pin)</div><div>{</div><div>  return (mmio_read(bbb_reg(bank, AM335X_GPIO_DATAIN)) & BIT(pin));</div><div>}</div><div><br></div><div>Thanks.</div><div><br></div><div>Best Regards,</div><div>Ketul </div><div class="gmail_extra"><br><div class="gmail_quote">On 27 July 2015 at 21:31, Andre Marques <span dir="ltr"><<a href="mailto:andre.lousa.marques@gmail.com" target="_blank">andre.lousa.marques@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Changes relative to the previous patch set:<br>
<br>
- Moved GPIO pin interrupts to rtems chains, instead of a local linked list;<br>
- Restructured the pin tracking structure, separating the interrupt information for each pin meaning that a pin without any interrupt enabled only requires 8 bytes, while keeping interrupt information (handling information, handler chain control, ...) requires 24 additional bytes (total of 32 bytes per pin with interrupts enabled);<br>
-  Added support for 'parallel' pin function assignment, allowing the function assignment to be set for multiple pins in a single GPIO hardware call. If a BSP does not support this feature it becomes a sequence of individual calls per pin. Also added support for GPIO pin groupings, allowing to write and read byte data to a series of pins which behave as a single entity;<br>
- Added bank tracking structure to maintain the bank lock and bank level interrupt information (threaded/normal handling, interrupt counter);<br>
- Changed GPIO settings to BSP defined constants, reducing dynamic memory allocation;<br>
- Switched interrupt tasks for a rtems interrupt server, with the possibility of using normal interrupts (user handlers being called within ISR context).<br>
---<br>
 c/src/lib/libbsp/Makefile.am           |    3 +-<br>
 c/src/lib/libbsp/<a href="http://preinstall.am" rel="noreferrer" target="_blank">preinstall.am</a>         |    4 +<br>
 c/src/lib/libbsp/shared/gpio.c         | 1977 ++++++++++++++++++++++++++++++++<br>
 c/src/lib/libbsp/shared/include/gpio.h |  948 +++++++++++++++<br>
 4 files changed, 2931 insertions(+), 1 deletion(-)<br>
 create mode 100644 c/src/lib/libbsp/shared/gpio.c<br>
 create mode 100644 c/src/lib/libbsp/shared/include/gpio.h<br>
<br>
diff --git a/c/src/lib/libbsp/Makefile.am b/c/src/lib/libbsp/Makefile.am<br>
index 3cab4d7..a039a98 100644<br>
--- a/c/src/lib/libbsp/Makefile.am<br>
+++ b/c/src/lib/libbsp/Makefile.am<br>
@@ -9,7 +9,7 @@ EXTRA_DIST = MERGE.PROCEDURE <a href="http://bsp.am" rel="noreferrer" target="_blank">bsp.am</a><br>
 EXTRA_DIST += shared/bootcard.c shared/bspclean.c \<br>
     shared/bsplibc.c shared/bsppost.c shared/console-polled.c \<br>
     shared/console.c shared/gnatinstallhandler.c shared/sbrk.c \<br>
-    shared/tod.c<br>
+    shared/tod.c shared/gpio.c<br>
 EXTRA_DIST += shared/vmeUniverse/vmeUniverse.c \<br>
     shared/vmeUniverse/vmeUniverse.h \<br>
     shared/vmeUniverse/vmeUniverseDMA.h \<br>
@@ -35,6 +35,7 @@ include_bsp_HEADERS =<br>
 include_bsp_HEADERS += shared/include/default-initial-extension.h<br>
 include_bsp_HEADERS += shared/include/fatal.h<br>
 include_bsp_HEADERS += shared/include/console-termios.h<br>
+include_bsp_HEADERS += shared/include/gpio.h<br>
<br>
 include $(srcdir)/<a href="http://preinstall.am" rel="noreferrer" target="_blank">preinstall.am</a><br>
 include $(top_srcdir)/automake/<a href="http://subdirs.am" rel="noreferrer" target="_blank">subdirs.am</a><br>
diff --git a/c/src/lib/libbsp/<a href="http://preinstall.am" rel="noreferrer" target="_blank">preinstall.am</a> b/c/src/lib/libbsp/<a href="http://preinstall.am" rel="noreferrer" target="_blank">preinstall.am</a><br>
index 651f136..bbcb7c5 100644<br>
--- a/c/src/lib/libbsp/<a href="http://preinstall.am" rel="noreferrer" target="_blank">preinstall.am</a><br>
+++ b/c/src/lib/libbsp/<a href="http://preinstall.am" rel="noreferrer" target="_blank">preinstall.am</a><br>
@@ -30,3 +30,7 @@ $(PROJECT_INCLUDE)/bsp/console-termios.h: shared/include/console-termios.h $(PRO<br>
        $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/console-termios.h<br>
 PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/console-termios.h<br>
<br>
+$(PROJECT_INCLUDE)/bsp/gpio.h: shared/include/gpio.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)<br>
+       $(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/gpio.h<br>
+PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/gpio.h<br>
+<br>
diff --git a/c/src/lib/libbsp/shared/gpio.c b/c/src/lib/libbsp/shared/gpio.c<br>
new file mode 100644<br>
index 0000000..a87b39f<br>
--- /dev/null<br>
+++ b/c/src/lib/libbsp/shared/gpio.c<br>
@@ -0,0 +1,1977 @@<br>
+/**<br>
+ * @file gpio.c<br>
+ *<br>
+ * @ingroup rtems_gpio<br>
+ *<br>
+ * @brief RTEMS GPIO API implementation.<br>
+ */<br>
+<br>
+/*<br>
+ *  Copyright (c) 2014-2015 Andre Marques <andre.lousa.marques at <a href="http://gmail.com" rel="noreferrer" target="_blank">gmail.com</a>><br>
+ *<br>
+ *  The license and distribution terms for this file may be<br>
+ *  found in the file LICENSE in this distribution or at<br>
+ *  <a href="http://www.rtems.org/license/LICENSE" rel="noreferrer" target="_blank">http://www.rtems.org/license/LICENSE</a>.<br>
+ */<br>
+<br>
+#include <rtems/score/atomic.h><br>
+#include <rtems/chain.h><br>
+#include <bsp/irq-generic.h><br>
+#include <bsp/gpio.h><br>
+#include <assert.h><br>
+#include <stdlib.h><br>
+<br>
+/**<br>
+ * @brief GPIO API mutex attributes.<br>
+ */<br>
+#define MUTEX_ATTRIBUTES (     \<br>
+  RTEMS_LOCAL                  \<br>
+  | RTEMS_PRIORITY             \<br>
+  | RTEMS_BINARY_SEMAPHORE     \<br>
+  | RTEMS_INHERIT_PRIORITY     \<br>
+  | RTEMS_NO_PRIORITY_CEILING  \<br>
+)<br>
+<br>
+#define CREATE_LOCK(name, lock_id) rtems_semaphore_create(   \<br>
+  name,                                                      \<br>
+  1,                                                         \<br>
+  MUTEX_ATTRIBUTES,                                          \<br>
+  0,                                                         \<br>
+  lock_id                                                    \<br>
+)<br>
+<br>
+#define ACQUIRE_LOCK(m) assert ( rtems_semaphore_obtain(m,               \<br>
+                                                        RTEMS_WAIT,      \<br>
+                                                        RTEMS_NO_TIMEOUT \<br>
+                                                        ) == RTEMS_SUCCESSFUL )<br>
+<br>
+#define RELEASE_LOCK(m) assert ( rtems_semaphore_release(m) == RTEMS_SUCCESSFUL )<br>
+<br>
+/**<br>
+ * @brief Object containing relevant information about a GPIO group.<br>
+ *<br>
+ * Encapsulates relevant data for a GPIO pin group.<br>
+ */<br>
+struct rtems_gpio_group<br>
+{<br>
+  rtems_chain_node node;<br>
+<br>
+  uint32_t *digital_inputs;<br>
+  uint32_t digital_input_bank;<br>
+  uint32_t input_count;<br>
+<br>
+  uint32_t *digital_outputs;<br>
+  uint32_t digital_output_bank;<br>
+  uint32_t output_count;<br>
+<br>
+  uint32_t *bsp_speficifc_pins;<br>
+  uint32_t bsp_specific_bank;<br>
+  uint32_t bsp_specific_pin_count;<br>
+<br>
+  rtems_id group_lock;<br>
+};<br>
+<br>
+/**<br>
+ * @brief Object containing relevant information to a list of user-defined<br>
+ *        interrupt handlers.<br>
+ *<br>
+ * Encapsulates relevant data for a GPIO interrupt handler.<br>
+ */<br>
+typedef struct<br>
+{<br>
+  rtems_chain_node node;<br>
+<br>
+  /* User-defined ISR routine. */<br>
+  rtems_gpio_irq_state (*handler) (void *arg);<br>
+<br>
+  /* User-defined arguments for the ISR routine. */<br>
+  void *arg;<br>
+} gpio_handler_node;<br>
+<br>
+/**<br>
+ * @brief Object containing relevant information of a pin's interrupt<br>
+ *        configuration/state.<br>
+ *<br>
+ * Encapsulates relevant data of a GPIO pin interrupt state.<br>
+ */<br>
+typedef struct<br>
+{<br>
+  /* Currently active interrupt. */<br>
+  rtems_gpio_interrupt active_interrupt;<br>
+<br>
+  /* ISR shared flag. */<br>
+  rtems_gpio_handler_flag handler_flag;<br>
+<br>
+  /* Linked list of interrupt handlers. */<br>
+  rtems_chain_control handler_chain;<br>
+<br>
+  /* Switch-deboucing information. */<br>
+  uint32_t debouncing_tick_count;<br>
+  rtems_interval last_isr_tick;<br>
+} gpio_pin_interrupt_state;<br>
+<br>
+/**<br>
+ * @brief Object containing information on a GPIO pin.<br>
+ *<br>
+ * Encapsulates relevant data about a GPIO pin.<br>
+ */<br>
+typedef struct<br>
+{<br>
+  rtems_gpio_function pin_function;<br>
+<br>
+  /* GPIO pull resistor configuration. */<br>
+  rtems_gpio_pull_mode resistor_mode;<br>
+<br>
+  /* If true inverts digital in/out applicational logic. */<br>
+  bool logic_invert;<br>
+<br>
+  /* True if the pin is on a group. */<br>
+  bool on_group;<br>
+<br>
+  /* Interrupt data for a pin. This field is NULL if no interrupt is enabled<br>
+   * on the pin. */<br>
+  gpio_pin_interrupt_state *interrupt_state;<br>
+} gpio_pin;<br>
+<br>
+/**<br>
+ * @brief Object containing relevant information regarding a GPIO bank state.<br>
+ *<br>
+ * Encapsulates relevant data for a GPIO bank.<br>
+ */<br>
+typedef struct<br>
+{<br>
+  uint32_t bank_number;<br>
+  uint32_t interrupt_counter;<br>
+  rtems_id lock;<br>
+<br>
+  /* If TRUE the interrupts on the bank will be called<br>
+   * by a rtems interrupt server, otherwise they will be handled<br>
+   * in the normal ISR context. */<br>
+  bool threaded_interrupts;<br>
+} gpio_bank;<br>
+<br>
+static gpio_pin gpio_pin_state[BSP_GPIO_PIN_COUNT];<br>
+static Atomic_Flag init_flag = ATOMIC_INITIALIZER_FLAG;<br>
+static gpio_bank gpio_bank_state[GPIO_BANK_COUNT];<br>
+static Atomic_Uint threaded_interrupt_counter = ATOMIC_INITIALIZER_UINT(0);<br>
+static rtems_chain_control gpio_group;<br>
+<br>
+#define BANK_NUMBER(pin_number) pin_number / BSP_GPIO_PINS_PER_BANK<br>
+#define PIN_NUMBER(pin_number) pin_number % BSP_GPIO_PINS_PER_BANK<br>
+<br>
+static int debounce_switch(gpio_pin_interrupt_state *interrupt_state)<br>
+{<br>
+  rtems_interval time;<br>
+<br>
+  time = rtems_clock_get_ticks_since_boot();<br>
+<br>
+  /* If not enough time has elapsed since last interrupt. */<br>
+  if (<br>
+      (time - interrupt_state->last_isr_tick) <<br>
+      interrupt_state->debouncing_tick_count<br>
+  ) {<br>
+    return -1;<br>
+  }<br>
+<br>
+  interrupt_state->last_isr_tick = time;<br>
+<br>
+  return 0;<br>
+}<br>
+<br>
+/* Returns the amount of pins in a bank. */<br>
+static uint32_t get_bank_pin_count(uint32_t bank)<br>
+{<br>
+  /* If the current bank is the last bank, which may not be completely filled. */<br>
+  if ( bank == GPIO_BANK_COUNT - 1 ) {<br>
+    return GPIO_LAST_BANK_PINS;<br>
+  }<br>
+<br>
+  return BSP_GPIO_PINS_PER_BANK;<br>
+}<br>
+<br>
+/* GPIO generic bank ISR. This may be called directly as response to an<br>
+ * interrupt, or by the rtems interrupt server task if the GPIO bank<br>
+ * uses threading interrupt handling. */<br>
+static void generic_bank_isr(void *arg)<br>
+{<br>
+  gpio_pin_interrupt_state *interrupt_state;<br>
+  rtems_chain_control *handler_list;<br>
+  rtems_chain_node *node;<br>
+  rtems_chain_node *next_node;<br>
+  gpio_handler_node *isr_node;<br>
+  rtems_vector_number vector;<br>
+  uint32_t event_status;<br>
+  uint32_t bank_number;<br>
+  uint32_t bank_start_pin;<br>
+  uint8_t handled_count;<br>
+  uint8_t rv;<br>
+  uint8_t i;<br>
+<br>
+  bank_number = *((uint32_t*) arg);<br>
+<br>
+  assert ( bank_number >= 0 && bank_number < GPIO_BANK_COUNT );<br>
+<br>
+  /* Calculate bank start address in the pin_state array. */<br>
+  bank_start_pin = bank_number * BSP_GPIO_PINS_PER_BANK;<br>
+<br>
+  vector = rtems_gpio_bsp_get_vector(bank_number);<br>
+<br>
+  /* If this bank does not use threaded interrupts we have to<br>
+   * disable the vector. Otherwise the interrupt server does it. */<br>
+  if ( gpio_bank_state[bank_number].threaded_interrupts == false ) {<br>
+    /* Prevents more interrupts from being generated on GPIO. */<br>
+    bsp_interrupt_vector_disable(vector);<br>
+  }<br>
+<br>
+  /* Obtains a 32-bit bitmask, with the pins currently reporting interrupts<br>
+   * signaled with 1. */<br>
+  event_status = rtems_gpio_bsp_interrupt_line(vector);<br>
+<br>
+  /* Iterates through the bitmask and calls the corresponding handler<br>
+   * for active interrupts. */<br>
+  for ( i = 0; i < get_bank_pin_count(bank_number); ++i ) {<br>
+    /* If active, wake the corresponding pin's ISR task. */<br>
+    if ( event_status & (1 << i) ) {<br>
+      interrupt_state = gpio_pin_state[bank_start_pin + i].interrupt_state;<br>
+<br>
+      assert ( interrupt_state != NULL );<br>
+<br>
+      handled_count = 0;<br>
+<br>
+      if ( gpio_bank_state[bank_number].threaded_interrupts ) {<br>
+        ACQUIRE_LOCK(gpio_bank_state[bank_number].lock);<br>
+      }<br>
+<br>
+      /* If this pin has the debouncing function attached, call it. */<br>
+      if ( interrupt_state->debouncing_tick_count > 0 ) {<br>
+        rv = debounce_switch(interrupt_state);<br>
+<br>
+        /* If the handler call was caused by a switch bounce,<br>
+         * ignores and move on. */<br>
+        if ( rv < 0 ) {<br>
+          if ( gpio_bank_state[bank_number].threaded_interrupts ) {<br>
+            RELEASE_LOCK(gpio_bank_state[bank_number].lock);<br>
+          }<br>
+<br>
+          continue;<br>
+        }<br>
+      }<br>
+<br>
+      handler_list = &interrupt_state->handler_chain;<br>
+<br>
+      node = rtems_chain_first(handler_list);<br>
+<br>
+      /* Iterate the ISR list. */<br>
+      while ( !rtems_chain_is_tail(handler_list, node) ) {<br>
+        isr_node = (gpio_handler_node *) node;<br>
+<br>
+        next_node = node->next;<br>
+<br>
+        if ( (isr_node->handler)(isr_node->arg) == IRQ_HANDLED ) {<br>
+          ++handled_count;<br>
+        }<br>
+<br>
+        node = next_node;<br>
+      }<br>
+<br>
+      /* If no handler assumed the interrupt,<br>
+       * treat it as a spurious interrupt. */<br>
+      if ( handled_count == 0 ) {<br>
+        bsp_interrupt_handler_default(rtems_gpio_bsp_get_vector(bank_number));<br>
+      }<br>
+<br>
+      if ( gpio_bank_state[bank_number].threaded_interrupts ) {<br>
+        RELEASE_LOCK(gpio_bank_state[bank_number].lock);<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
+  if ( gpio_bank_state[bank_number].threaded_interrupts == false ) {<br>
+    bsp_interrupt_vector_enable(vector);<br>
+  }<br>
+}<br>
+<br>
+/* Verifies if all pins in the received pin array are from the same bank and<br>
+ * have the defined GPIO function. Produces bitmask of the received pins. */<br>
+static rtems_status_code get_pin_bitmask(<br>
+  uint32_t *pins,<br>
+  uint32_t pin_count,<br>
+  uint32_t *bank_number,<br>
+  uint32_t *bitmask,<br>
+  rtems_gpio_function function<br>
+) {<br>
+  uint32_t pin_number;<br>
+  uint32_t bank;<br>
+  uint8_t i;<br>
+<br>
+  if ( pin_count < 1 ) {<br>
+    return RTEMS_UNSATISFIED;<br>
+  }<br>
+<br>
+  *bitmask = 0;<br>
+<br>
+  for ( i = 0; i < pin_count; ++i ) {<br>
+    pin_number = pins[i];<br>
+<br>
+    if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {<br>
+      return RTEMS_INVALID_ID;<br>
+    }<br>
+<br>
+    bank = BANK_NUMBER(pin_number);<br>
+<br>
+    if ( i == 0 ) {<br>
+      *bank_number = bank;<br>
+<br>
+      ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+    }<br>
+    else if ( bank != *bank_number ) {<br>
+      RELEASE_LOCK(gpio_bank_state[*bank_number].lock);<br>
+<br>
+      return RTEMS_UNSATISFIED;<br>
+    }<br>
+<br>
+    if (<br>
+        gpio_pin_state[pin_number].pin_function != function ||<br>
+        gpio_pin_state[pin_number].on_group<br>
+    ) {<br>
+      RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+      return RTEMS_NOT_CONFIGURED;<br>
+    }<br>
+<br>
+    *bitmask |= (1 << PIN_NUMBER(pin_number));<br>
+  }<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+static rtems_status_code check_same_bank_and_availability(<br>
+  const rtems_gpio_pin_conf *pin_confs,<br>
+  uint32_t pin_count,<br>
+  uint32_t *bank_number,<br>
+  uint32_t *pins<br>
+) {<br>
+  uint32_t pin_number;<br>
+  uint32_t bank;<br>
+  uint8_t i;<br>
+<br>
+  for ( i = 0; i < pin_count; ++i ) {<br>
+    pin_number = pin_confs[i].pin_number;<br>
+<br>
+    bank = BANK_NUMBER(pin_number);<br>
+<br>
+    if ( i == 0 ) {<br>
+      *bank_number = bank;<br>
+<br>
+      ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+    }<br>
+    else if ( bank != *bank_number ) {<br>
+      RELEASE_LOCK(gpio_bank_state[*bank_number].lock);<br>
+<br>
+      return RTEMS_UNSATISFIED;<br>
+    }<br>
+<br>
+    if ( gpio_pin_state[pin_number].pin_function != NOT_USED ) {<br>
+      RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+      return RTEMS_RESOURCE_IN_USE;<br>
+    }<br>
+<br>
+    pins[i] = PIN_NUMBER(pin_number);<br>
+  }<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[*bank_number].lock);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+static rtems_status_code setup_resistor_and_interrupt_configuration(<br>
+  uint32_t pin_number,<br>
+  rtems_gpio_pull_mode pull_mode,<br>
+  rtems_gpio_interrupt_configuration *interrupt_conf<br>
+) {<br>
+  gpio_pin_interrupt_state *interrupt_state;<br>
+  rtems_status_code sc;<br>
+  uint32_t bank;<br>
+<br>
+  sc = rtems_gpio_resistor_mode(pin_number, pull_mode);<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+#if defined(DEBUG)<br>
+    printk("rtems_gpio_resistor_mode failed with status code %d\n", sc);<br>
+#endif<br>
+<br>
+    return RTEMS_UNSATISFIED;<br>
+  }<br>
+<br>
+  if ( interrupt_conf != NULL ) {<br>
+    bank = BANK_NUMBER(pin_number);<br>
+<br>
+    ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    sc = rtems_gpio_enable_interrupt(<br>
+           pin_number,<br>
+           interrupt_conf->active_interrupt,<br>
+           interrupt_conf->handler_flag,<br>
+           interrupt_conf->threaded_interrupts,<br>
+           interrupt_conf->handler,<br>
+           interrupt_conf->arg<br>
+         );<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+#if defined(DEBUG)<br>
+      printk(<br>
+        "rtems_gpio_enable_interrupt failed with status code %d\n",<br>
+        sc<br>
+      );<br>
+#endif<br>
+<br>
+      return RTEMS_UNSATISFIED;<br>
+    }<br>
+<br>
+    interrupt_state = gpio_pin_state[pin_number].interrupt_state;<br>
+<br>
+    interrupt_state->debouncing_tick_count =<br>
+      interrupt_conf->debounce_clock_tick_interval;<br>
+<br>
+    interrupt_state->last_isr_tick = 0;<br>
+<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+  }<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+static rtems_status_code gpio_multi_select(<br>
+  const rtems_gpio_pin_conf *pins,<br>
+  uint8_t pin_count,<br>
+  bool on_group<br>
+) {<br>
+  rtems_status_code sc;<br>
+  uint32_t pin_number;<br>
+  uint32_t bank;<br>
+  uint8_t i;<br>
+<br>
+  /* If the BSP has multi select capabilities. */<br>
+#ifdef BSP_GPIO_PINS_PER_SELECT_BANK<br>
+  rtems_gpio_multiple_pin_select<br>
+    pin_data[GPIO_SELECT_BANK_COUNT][BSP_GPIO_PINS_PER_SELECT_BANK];<br>
+  rtems_gpio_specific_data *bsp_data;<br>
+<br>
+  /* Since each platform may have more than two functions to assign to a pin,<br>
+   * each pin requires more than one bit in the selection register to<br>
+   * properly assign a function to it.<br>
+   * Therefore a selection bank (pin selection register) will support fewer pins<br>
+   * than a regular bank, meaning that there will be more selection banks than<br>
+   * regular banks, which have to be handled separately.<br>
+   *<br>
+   * This field records the select bank number relative to the GPIO bank. */<br>
+  uint32_t select_bank;<br>
+  uint32_t bank_number;<br>
+  uint32_t select_bank_counter[GPIO_SELECT_BANK_COUNT];<br>
+  uint32_t select_count;<br>
+  uint32_t pin;<br>
+<br>
+  if ( pin_count == 0 ) {<br>
+    return RTEMS_SUCCESSFUL;<br>
+  }<br>
+<br>
+  for ( i = 0; i < GPIO_SELECT_BANK_COUNT; ++i ) {<br>
+    select_bank_counter[i] = 0;<br>
+  }<br>
+<br>
+  for ( i = 0; i < pin_count; ++i ) {<br>
+    pin_number = pins[i].pin_number;<br>
+<br>
+    if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {<br>
+      return RTEMS_INVALID_ID;<br>
+    }<br>
+<br>
+    bank = BANK_NUMBER(pin_number);<br>
+    pin = PIN_NUMBER(pin_number);<br>
+<br>
+    if ( i == 0 ) {<br>
+      bank_number = bank;<br>
+<br>
+      ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+    }<br>
+    else if ( bank != bank_number ) {<br>
+      RELEASE_LOCK(gpio_bank_state[bank_number].lock);<br>
+<br>
+      return RTEMS_UNSATISFIED;<br>
+    }<br>
+<br>
+    /* If the pin is already being used returns with an error. */<br>
+    if ( gpio_pin_state[pin_number].pin_function != NOT_USED ) {<br>
+      RELEASE_LOCK(gpio_bank_state[bank_number].lock);<br>
+<br>
+      return RTEMS_RESOURCE_IN_USE;<br>
+    }<br>
+<br>
+    select_bank = (pin_number / BSP_GPIO_PINS_PER_SELECT_BANK) -<br>
+                  (bank * GPIO_SELECT_BANK_COUNT);<br>
+<br>
+    select_count = select_bank_counter[select_bank];<br>
+<br>
+    pin_data[select_bank][select_count].pin_number = pin_number;<br>
+    pin_data[select_bank][select_count].function = pins[i].function;<br>
+<br>
+    if ( pins[i].function == BSP_SPECIFIC ) {<br>
+      bsp_data = (rtems_gpio_specific_data *) pins[i].bsp_specific;<br>
+<br>
+      if ( bsp_data == NULL ) {<br>
+        RELEASE_LOCK(gpio_bank_state[bank_number].lock);<br>
+<br>
+        return RTEMS_UNSATISFIED;<br>
+      }<br>
+<br>
+      pin_data[select_bank][select_count].io_function = bsp_data->io_function;<br>
+      pin_data[select_bank][select_count].bsp_specific = bsp_data->pin_data;<br>
+    }<br>
+    else {<br>
+      /* io_function takes a dummy value, as it will not be used. */<br>
+      pin_data[select_bank][select_count].io_function = 0;<br>
+      pin_data[select_bank][select_count].bsp_specific = pins[i].bsp_specific;<br>
+    }<br>
+<br>
+    ++select_bank_counter[select_bank];<br>
+  }<br>
+<br>
+  for ( i = 0; i < GPIO_SELECT_BANK_COUNT; ++i ) {<br>
+    if ( select_bank_counter[i] == 0 ) {<br>
+      continue;<br>
+    }<br>
+<br>
+    sc = rtems_gpio_bsp_multi_select(<br>
+           pin_data[i], select_bank_counter[i], i +<br>
+           (bank_number * GPIO_SELECT_BANK_COUNT)<br>
+         );<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      RELEASE_LOCK(gpio_bank_state[bank_number].lock);<br>
+<br>
+      return sc;<br>
+    }<br>
+  }<br>
+<br>
+  for ( i = 0; i < pin_count; ++i ) {<br>
+    pin_number = pins[i].pin_number;<br>
+<br>
+    /* Fill other pin state information. */<br>
+    gpio_pin_state[pin_number].pin_function = pins[i].function;<br>
+    gpio_pin_state[pin_number].logic_invert = pins[i].logic_invert;<br>
+    gpio_pin_state[pin_number].on_group = on_group;<br>
+<br>
+    sc = setup_resistor_and_interrupt_configuration(<br>
+           pin_number,<br>
+           pins[i].pull_mode,<br>
+           pins[i].interrupt<br>
+         );<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      RELEASE_LOCK(gpio_bank_state[bank_number].lock);<br>
+<br>
+      return sc;<br>
+    }<br>
+<br>
+    bank = BANK_NUMBER(pin_number);<br>
+    pin = PIN_NUMBER(pin_number);<br>
+<br>
+    if ( pins[i].function == DIGITAL_OUTPUT ) {<br>
+      if ( pins[i].output_enabled == true ) {<br>
+        sc = rtems_gpio_bsp_set(bank, pin);<br>
+      }<br>
+      else {<br>
+        sc = rtems_gpio_bsp_clear(bank, pin);<br>
+      }<br>
+<br>
+      if ( sc != RTEMS_SUCCESSFUL ) {<br>
+        RELEASE_LOCK(gpio_bank_state[bank_number].lock);<br>
+<br>
+        return sc;<br>
+      }<br>
+    }<br>
+  }<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank_number].lock);<br>
+<br>
+  return sc;<br>
+<br>
+  /* If the BSP does not provide pin multi-selection,<br>
+   * configures each pin sequentially. */<br>
+#else<br>
+  for ( i = 0; i < pin_count; ++i ) {<br>
+    pin_number = pins[i].pin_number;<br>
+<br>
+    if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {<br>
+      return RTEMS_INVALID_ID;<br>
+    }<br>
+<br>
+    bank = BANK_NUMBER(pin_number);<br>
+<br>
+    ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    /* If the pin is already being used returns with an error. */<br>
+    if ( gpio_pin_state[pin_number].pin_function != NOT_USED ) {<br>
+      RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+      return RTEMS_RESOURCE_IN_USE;<br>
+    }<br>
+  }<br>
+<br>
+  for ( i = 0; i < pin_count; ++i ) {<br>
+    sc = rtems_gpio_request_configuration(&pins[i]);<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+    }<br>
+<br>
+    gpio_pin_state[pins[i].pin_number].on_group = on_group;<br>
+  }<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+#endif<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_initialize(void)<br>
+{<br>
+  rtems_status_code sc;<br>
+  uint32_t i;<br>
+<br>
+  if ( _Atomic_Flag_test_and_set(&init_flag, ATOMIC_ORDER_RELAXED) == true ) {<br>
+    return RTEMS_SUCCESSFUL;<br>
+  }<br>
+<br>
+  for ( i = 0; i < GPIO_BANK_COUNT; ++i ) {<br>
+    sc = CREATE_LOCK(<br>
+           rtems_build_name('G', 'I', 'N', 'T'),<br>
+           &gpio_bank_state[i].lock<br>
+         );<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+    }<br>
+<br>
+    gpio_bank_state[i].bank_number = i;<br>
+    gpio_bank_state[i].interrupt_counter = 0;<br>
+<br>
+    /* The threaded_interrupts field is initialized during<br>
+     * rtems_gpio_enable_interrupt(), as its value is never used before. */<br>
+  }<br>
+<br>
+  for ( i = 0; i < BSP_GPIO_PIN_COUNT; ++i ) {<br>
+    gpio_pin_state[i].pin_function = NOT_USED;<br>
+    gpio_pin_state[i].resistor_mode = NO_PULL_RESISTOR;<br>
+    gpio_pin_state[i].logic_invert = false;<br>
+    gpio_pin_state[i].on_group = false;<br>
+    gpio_pin_state[i].interrupt_state = NULL;<br>
+  }<br>
+<br>
+  /* Initialize GPIO groups chain. */<br>
+  rtems_chain_initialize_empty(&gpio_group);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+rtems_gpio_group *rtems_gpio_create_pin_group(void)<br>
+{<br>
+  struct rtems_gpio_group *group;<br>
+<br>
+  group = (struct rtems_gpio_group *) malloc(sizeof(struct rtems_gpio_group));<br>
+<br>
+  return group;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_define_pin_group(<br>
+  const rtems_gpio_group_definition *group_definition,<br>
+  rtems_gpio_group *group<br>
+) {<br>
+  rtems_status_code sc;<br>
+<br>
+  if ( group_definition == NULL || group == NULL ) {<br>
+    return RTEMS_UNSATISFIED;<br>
+  }<br>
+<br>
+  if (<br>
+      group_definition->input_count == 0 &&<br>
+      group_definition->output_count == 0 &&<br>
+      group_definition->bsp_specific_pin_count == 0<br>
+  ) {<br>
+    return RTEMS_UNSATISFIED;<br>
+  }<br>
+<br>
+  group->input_count = group_definition->input_count;<br>
+<br>
+  if ( group->input_count > 0 ) {<br>
+    group->digital_inputs =<br>
+      (uint32_t *) malloc(group->input_count * sizeof(uint32_t));<br>
+<br>
+    /* Evaluate if the pins that will constitute the group are available and<br>
+     * that pins with the same function within the group all belong<br>
+     * to the same pin group. */<br>
+    sc = check_same_bank_and_availability(<br>
+           group_definition->digital_inputs,<br>
+           group->input_count,<br>
+           &group->digital_input_bank,<br>
+           group->digital_inputs<br>
+         );<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+    }<br>
+  }<br>
+  else {<br>
+    group->digital_inputs = NULL;<br>
+  }<br>
+<br>
+  group->output_count = group_definition->output_count;<br>
+<br>
+  if ( group->output_count > 0 ) {<br>
+    group->digital_outputs =<br>
+      (uint32_t *) malloc(group->output_count * sizeof(uint32_t));<br>
+<br>
+    sc = check_same_bank_and_availability(<br>
+           group_definition->digital_outputs,<br>
+           group->output_count,<br>
+           &group->digital_output_bank,<br>
+           group->digital_outputs<br>
+         );<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+    }<br>
+  }<br>
+  else {<br>
+    group->digital_outputs = NULL;<br>
+  }<br>
+<br>
+  group->bsp_specific_pin_count = group_definition->bsp_specific_pin_count;<br>
+<br>
+  if ( group->bsp_specific_pin_count > 0 ) {<br>
+    group->bsp_speficifc_pins =<br>
+      (uint32_t *) malloc(<br>
+                     group->bsp_specific_pin_count *<br>
+                     sizeof(uint32_t)<br>
+                   );<br>
+<br>
+    sc = check_same_bank_and_availability(<br>
+           group_definition->bsp_specifics,<br>
+           group->bsp_specific_pin_count,<br>
+           &group->bsp_specific_bank,<br>
+           group->bsp_speficifc_pins<br>
+         );<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+    }<br>
+  }<br>
+  else {<br>
+    group->bsp_speficifc_pins = NULL;<br>
+  }<br>
+<br>
+  /* Request the pins. */<br>
+  sc = gpio_multi_select(<br>
+         group_definition->digital_inputs,<br>
+         group_definition->input_count,<br>
+         true<br>
+       );<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    return RTEMS_UNSATISFIED;<br>
+  }<br>
+<br>
+  sc = gpio_multi_select(<br>
+         group_definition->digital_outputs,<br>
+         group_definition->output_count,<br>
+         true<br>
+       );<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    sc = rtems_gpio_release_multiple_pins(<br>
+           group_definition->digital_inputs,<br>
+           group_definition->input_count<br>
+         );<br>
+<br>
+    assert ( sc == RTEMS_SUCCESSFUL );<br>
+<br>
+    return RTEMS_UNSATISFIED;<br>
+  }<br>
+<br>
+  sc = gpio_multi_select(<br>
+         group_definition->bsp_specifics,<br>
+         group_definition->bsp_specific_pin_count,<br>
+         true<br>
+       );<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    sc = rtems_gpio_release_multiple_pins(<br>
+           group_definition->digital_inputs,<br>
+           group_definition->input_count<br>
+         );<br>
+<br>
+    assert ( sc == RTEMS_SUCCESSFUL );<br>
+<br>
+    sc = rtems_gpio_release_multiple_pins(<br>
+           group_definition->digital_outputs,<br>
+           group_definition->output_count<br>
+         );<br>
+<br>
+    assert ( sc == RTEMS_SUCCESSFUL );<br>
+<br>
+    return RTEMS_UNSATISFIED;<br>
+  }<br>
+<br>
+  /* Create group lock. */<br>
+  sc = CREATE_LOCK(rtems_build_name('G', 'R', 'P', 'L'), &group->group_lock);<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    return sc;<br>
+  }<br>
+<br>
+  rtems_chain_append(&gpio_group, &group->node);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_write_group(uint32_t data, rtems_gpio_group *group)<br>
+{<br>
+  rtems_status_code sc = RTEMS_SUCCESSFUL;<br>
+  uint32_t set_bitmask;<br>
+  uint32_t clear_bitmask;<br>
+  uint32_t bank;<br>
+  uint32_t pin;<br>
+  uint8_t i;<br>
+<br>
+  if ( group->output_count == 0 ) {<br>
+    return RTEMS_NOT_DEFINED;<br>
+  }<br>
+<br>
+  bank = group->digital_output_bank;<br>
+<br>
+  /* Acquire bank lock for the digital output pins. */<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  /* Acquire group lock. */<br>
+  ACQUIRE_LOCK(group->group_lock);<br>
+<br>
+  set_bitmask = 0;<br>
+  clear_bitmask = 0;<br>
+<br>
+  for ( i = 0; i < group->output_count; ++i ) {<br>
+    pin = group->digital_outputs[i];<br>
+<br>
+    if ( (data & (1 << i)) == 0 ) {<br>
+      clear_bitmask |= (1 << pin);<br>
+    }<br>
+    else {<br>
+      set_bitmask |= (1 << pin);<br>
+    }<br>
+  }<br>
+<br>
+  /* Set the logical highs. */<br>
+  if ( set_bitmask > 0 ) {<br>
+    sc = rtems_gpio_bsp_multi_set(bank, set_bitmask);<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      RELEASE_LOCK(group->group_lock);<br>
+      RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+      return sc;<br>
+    }<br>
+  }<br>
+<br>
+  /* Set the logical lows. */<br>
+  if ( clear_bitmask > 0 ) {<br>
+    sc = rtems_gpio_bsp_multi_clear(bank, clear_bitmask);<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      RELEASE_LOCK(group->group_lock);<br>
+      RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+      return sc;<br>
+    }<br>
+  }<br>
+<br>
+  RELEASE_LOCK(group->group_lock);<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+uint32_t rtems_gpio_read_group(rtems_gpio_group *group)<br>
+{<br>
+  uint32_t read_bitmask;<br>
+  uint32_t bank;<br>
+  uint32_t pin;<br>
+  uint32_t rv;<br>
+  uint8_t i;<br>
+<br>
+  if ( group->input_count == 0 ) {<br>
+    return 0xDEADBEEF;<br>
+  }<br>
+<br>
+  bank = group->digital_input_bank;<br>
+<br>
+  /* Acquire bank lock for the digital input pins. */<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  /* Acquire group lock. */<br>
+  ACQUIRE_LOCK(group->group_lock);<br>
+<br>
+  read_bitmask = 0;<br>
+<br>
+  for ( i = 0; i < group->input_count; ++i ) {<br>
+    pin = group->digital_inputs[i];<br>
+<br>
+    read_bitmask |= (1 << pin);<br>
+  }<br>
+<br>
+  rv = rtems_gpio_bsp_multi_read(bank, read_bitmask);<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+  RELEASE_LOCK(group->group_lock);<br>
+<br>
+  return rv;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_group_bsp_specific_operation(<br>
+  rtems_gpio_group *group,<br>
+  void *arg<br>
+) {<br>
+  rtems_status_code sc;<br>
+  uint32_t bank;<br>
+<br>
+  if ( group->bsp_specific_pin_count == 0 ) {<br>
+    return RTEMS_NOT_DEFINED;<br>
+  }<br>
+<br>
+  bank = group->bsp_specific_bank;<br>
+<br>
+  /* Acquire bank lock for the BSP specific function pins. */<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  /* Acquire group lock. */<br>
+  ACQUIRE_LOCK(group->group_lock);<br>
+<br>
+  sc = rtems_gpio_bsp_specific_group_operation(<br>
+         bank,<br>
+         group->bsp_speficifc_pins,<br>
+         group->bsp_specific_pin_count,<br>
+         arg<br>
+       );<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+  RELEASE_LOCK(group->group_lock);<br>
+<br>
+  return sc;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_multi_select(<br>
+  const rtems_gpio_pin_conf *pins,<br>
+  uint8_t pin_count<br>
+) {<br>
+  return gpio_multi_select(pins, pin_count, false);<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_request_configuration(<br>
+  const rtems_gpio_pin_conf *conf<br>
+) {<br>
+  rtems_status_code sc;<br>
+<br>
+  sc = rtems_gpio_request_pin(<br>
+         conf->pin_number,<br>
+         conf->function,<br>
+         conf->output_enabled,<br>
+         conf->logic_invert,<br>
+         conf->bsp_specific<br>
+       );<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+#if defined(DEBUG)<br>
+    printk("rtems_gpio_request_pin failed with status code %d\n",sc);<br>
+#endif<br>
+<br>
+    return RTEMS_UNSATISFIED;<br>
+  }<br>
+<br>
+  return setup_resistor_and_interrupt_configuration(<br>
+           conf->pin_number,<br>
+           conf->pull_mode,<br>
+           conf->interrupt<br>
+         );<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_update_configuration(<br>
+  const rtems_gpio_pin_conf *conf<br>
+) {<br>
+  rtems_gpio_interrupt_configuration *interrupt_conf;<br>
+  gpio_pin_interrupt_state *interrupt_state;<br>
+  rtems_status_code sc;<br>
+  uint32_t bank;<br>
+<br>
+  if ( conf->pin_number < 0 || conf->pin_number >= BSP_GPIO_PIN_COUNT ) {<br>
+    return RTEMS_INVALID_ID;<br>
+  }<br>
+<br>
+  bank = BANK_NUMBER(conf->pin_number);<br>
+<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  /* If the pin is not being used returns with an error. */<br>
+  if ( gpio_pin_state[conf->pin_number].pin_function == NOT_USED ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return RTEMS_NOT_CONFIGURED;<br>
+  }<br>
+<br>
+  sc = rtems_gpio_resistor_mode(conf->pin_number, conf->pull_mode);<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+#if defined(DEBUG)<br>
+    printk("rtems_gpio_resistor_mode failed with status code %d\n", sc);<br>
+#endif<br>
+<br>
+    return RTEMS_UNSATISFIED;<br>
+  }<br>
+<br>
+  interrupt_conf = (rtems_gpio_interrupt_configuration *) conf->interrupt;<br>
+<br>
+  interrupt_state = gpio_pin_state[conf->pin_number].interrupt_state;<br>
+<br>
+  if ( interrupt_state != NULL ) {<br>
+    sc = rtems_gpio_disable_interrupt(conf->pin_number);<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+#if defined(DEBUG)<br>
+      printk(<br>
+        "rtems_gpio_disable_interrupt failed with status code %d\n",<br>
+        sc<br>
+      );<br>
+#endif<br>
+<br>
+      return RTEMS_UNSATISFIED;<br>
+    }<br>
+  }<br>
+<br>
+  if ( interrupt_conf != NULL ) {<br>
+    sc = rtems_gpio_enable_interrupt(<br>
+           conf->pin_number,<br>
+           interrupt_conf->active_interrupt,<br>
+           interrupt_conf->handler_flag,<br>
+           interrupt_conf->threaded_interrupts,<br>
+           interrupt_conf->handler,<br>
+           interrupt_conf->arg<br>
+         );<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+#if defined(DEBUG)<br>
+      printk(<br>
+        "rtems_gpio_enable_interrupt failed with status code %d\n",<br>
+        sc<br>
+      );<br>
+#endif<br>
+<br>
+      return RTEMS_UNSATISFIED;<br>
+    }<br>
+  }<br>
+<br>
+  if ( interrupt_conf != NULL && interrupt_state != NULL ) {<br>
+    if (<br>
+        interrupt_conf->debounce_clock_tick_interval !=<br>
+        interrupt_state->debouncing_tick_count<br>
+    ) {<br>
+      interrupt_state->debouncing_tick_count =<br>
+        interrupt_conf->debounce_clock_tick_interval;<br>
+<br>
+      interrupt_state->last_isr_tick = 0;<br>
+    }<br>
+  }<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_multi_set(<br>
+ uint32_t *pin_numbers,<br>
+ uint32_t pin_count<br>
+) {<br>
+  rtems_status_code sc;<br>
+  uint32_t bitmask;<br>
+  uint32_t bank;<br>
+<br>
+  sc = get_pin_bitmask(pin_numbers, pin_count, &bank, &bitmask, DIGITAL_OUTPUT);<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    return sc;<br>
+  }<br>
+<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  sc = rtems_gpio_bsp_multi_set(bank, bitmask);<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return sc;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_multi_clear(<br>
+  uint32_t *pin_numbers,<br>
+  uint32_t pin_count<br>
+) {<br>
+  rtems_status_code sc;<br>
+  uint32_t bitmask;<br>
+  uint32_t bank;<br>
+<br>
+  sc = get_pin_bitmask(pin_numbers, pin_count, &bank, &bitmask, DIGITAL_OUTPUT);<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    return sc;<br>
+  }<br>
+<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  sc = rtems_gpio_bsp_multi_clear(bank, bitmask);<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return sc;<br>
+}<br>
+<br>
+uint32_t rtems_gpio_multi_read(<br>
+  uint32_t *pin_numbers,<br>
+  uint32_t pin_count<br>
+) {<br>
+  rtems_status_code sc;<br>
+  uint32_t bitmask;<br>
+  uint32_t bank;<br>
+  uint32_t rv;<br>
+<br>
+  sc = get_pin_bitmask(pin_numbers, pin_count, &bank, &bitmask, DIGITAL_INPUT);<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    return 0xDEADBEEF;<br>
+  }<br>
+<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  rv = rtems_gpio_bsp_multi_read(bank, bitmask);<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return rv;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_set(uint32_t pin_number)<br>
+{<br>
+  rtems_status_code sc;<br>
+  uint32_t bank;<br>
+  uint32_t pin;<br>
+<br>
+  if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {<br>
+    return RTEMS_INVALID_ID;<br>
+  }<br>
+<br>
+  bank = BANK_NUMBER(pin_number);<br>
+  pin = PIN_NUMBER(pin_number);<br>
+<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  if (<br>
+      gpio_pin_state[pin_number].pin_function != DIGITAL_OUTPUT ||<br>
+      gpio_pin_state[pin_number].on_group<br>
+  ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+#if defined(DEBUG)<br>
+    printk("Can only set digital output pins\n");<br>
+#endif<br>
+<br>
+    return RTEMS_NOT_CONFIGURED;<br>
+  }<br>
+<br>
+  if ( gpio_pin_state[pin_number].logic_invert ) {<br>
+    sc = rtems_gpio_bsp_clear(bank, pin);<br>
+  }<br>
+  else {<br>
+    sc = rtems_gpio_bsp_set(bank, pin);<br>
+  }<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return sc;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_clear(uint32_t pin_number)<br>
+{<br>
+  rtems_status_code sc;<br>
+  uint32_t bank;<br>
+  uint32_t pin;<br>
+<br>
+  if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {<br>
+    return RTEMS_INVALID_ID;<br>
+  }<br>
+<br>
+  bank = BANK_NUMBER(pin_number);<br>
+  pin = PIN_NUMBER(pin_number);<br>
+<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  if (<br>
+      gpio_pin_state[pin_number].pin_function != DIGITAL_OUTPUT ||<br>
+      gpio_pin_state[pin_number].on_group<br>
+  ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+#if defined(DEBUG)<br>
+    printk("Can only clear digital output pins\n");<br>
+#endif<br>
+<br>
+    return RTEMS_NOT_CONFIGURED;<br>
+  }<br>
+<br>
+  if ( gpio_pin_state[pin_number].logic_invert ) {<br>
+    sc = rtems_gpio_bsp_set(bank, pin);<br>
+  }<br>
+  else {<br>
+    sc = rtems_gpio_bsp_clear(bank, pin);<br>
+  }<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return sc;<br>
+}<br>
+<br>
+uint8_t rtems_gpio_get_value(uint32_t pin_number)<br></blockquote><div> uint32_t rtems_gpio_get_value(uint32_t pin_number)</div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+{<br>
+  uint32_t bank;<br>
+  uint32_t pin;<br>
+  int rv;<br></blockquote><div>uint32_t rv; </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+  if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {<br>
+    return -1;<br>
+  }<br>
+<br>
+  bank = BANK_NUMBER(pin_number);<br>
+  pin = PIN_NUMBER(pin_number);<br>
+<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  if (<br>
+      gpio_pin_state[pin_number].pin_function != DIGITAL_INPUT ||<br>
+      gpio_pin_state[pin_number].on_group<br>
+  ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+#if defined(DEBUG)<br>
+    printk("Can only read digital input pins\n");<br>
+#endif<br>
+<br>
+    return -1;<br>
+  }<br>
+<br>
+  rv = rtems_gpio_bsp_get_value(bank, pin);<br>
+<br>
+  if ( gpio_pin_state[pin_number].logic_invert && rv > 0 ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return !rv;<br>
+  }<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return ( rv > 0 ) ? 1 : rv;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_request_pin(<br>
+  uint32_t pin_number,<br>
+  rtems_gpio_function function,<br>
+  bool output_enabled,<br>
+  bool logic_invert,<br>
+  void *bsp_specific<br>
+) {<br>
+  rtems_gpio_specific_data *bsp_data;<br>
+  rtems_status_code sc = RTEMS_SUCCESSFUL;<br>
+  uint32_t bank;<br>
+  uint32_t pin;<br>
+<br>
+  if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {<br>
+    return RTEMS_INVALID_ID;<br>
+  }<br>
+<br>
+  bank = BANK_NUMBER(pin_number);<br>
+  pin = PIN_NUMBER(pin_number);<br>
+<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  /* If the pin is already being used returns with an error. */<br>
+  if ( gpio_pin_state[pin_number].pin_function != NOT_USED ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return RTEMS_RESOURCE_IN_USE;<br>
+  }<br>
+<br>
+  switch ( function ) {<br>
+    case DIGITAL_INPUT:<br>
+      sc = rtems_gpio_bsp_select_input(bank, pin, bsp_specific);<br>
+      break;<br>
+    case DIGITAL_OUTPUT:<br>
+      sc = rtems_gpio_bsp_select_output(bank, pin, bsp_specific);<br>
+      break;<br>
+    case BSP_SPECIFIC:<br>
+      bsp_data = (rtems_gpio_specific_data *) bsp_specific;<br>
+<br>
+      if ( bsp_data == NULL ) {<br>
+        RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+        return RTEMS_UNSATISFIED;<br>
+      }<br>
+<br>
+      sc = rtems_bsp_select_specific_io(<br>
+             bank,<br>
+             pin,<br>
+             bsp_data->io_function,<br>
+             bsp_data->pin_data<br>
+           );<br>
+      break;<br>
+    case NOT_USED:<br>
+    default:<br>
+      RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+      return RTEMS_NOT_DEFINED;<br>
+  }<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return sc;<br>
+  }<br>
+<br>
+  /* If the function was successfully assigned to the pin,<br>
+   * record that information on the gpio_pin_state structure. */<br>
+  gpio_pin_state[pin_number].pin_function = function;<br>
+  gpio_pin_state[pin_number].logic_invert = logic_invert;<br>
+<br>
+  if ( function == DIGITAL_OUTPUT ) {<br>
+    if ( output_enabled == true ) {<br>
+      sc = rtems_gpio_bsp_set(bank, pin);<br>
+    }<br>
+    else {<br>
+      sc = rtems_gpio_bsp_clear(bank, pin);<br>
+    }<br>
+  }<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return sc;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_resistor_mode(<br>
+  uint32_t pin_number,<br>
+  rtems_gpio_pull_mode mode<br>
+) {<br>
+  rtems_status_code sc;<br>
+  uint32_t bank;<br>
+  uint32_t pin;<br>
+<br>
+  if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {<br>
+    return RTEMS_INVALID_ID;<br>
+  }<br>
+<br>
+  bank = BANK_NUMBER(pin_number);<br>
+  pin = PIN_NUMBER(pin_number);<br>
+<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  /* If the desired actuation mode is already set, silently exits.<br>
+   * The NO_PULL_RESISTOR is a special case, as some platforms have<br>
+   * pull-up resistors enabled on startup, so this state may have to<br>
+   * be reinforced in the hardware. */<br>
+  if (<br>
+      gpio_pin_state[pin_number].resistor_mode == mode &&<br>
+      mode != NO_PULL_RESISTOR<br>
+  ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return RTEMS_SUCCESSFUL;<br>
+  }<br>
+<br>
+  sc = rtems_gpio_bsp_set_resistor_mode(bank, pin, mode);<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return sc;<br>
+  }<br>
+<br>
+  gpio_pin_state[pin_number].resistor_mode = mode;<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_release_pin(uint32_t pin_number)<br>
+{<br>
+  gpio_pin_interrupt_state *interrupt_state;<br>
+  rtems_status_code sc;<br>
+  uint32_t bank;<br>
+<br>
+  if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {<br>
+    return RTEMS_INVALID_ID;<br>
+  }<br>
+<br>
+  bank = BANK_NUMBER(pin_number);<br>
+<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  interrupt_state = gpio_pin_state[pin_number].interrupt_state;<br>
+<br>
+  /* If the pin has an enabled interrupt then remove the handler(s)<br>
+   * and disable interrupts on that pin. */<br>
+  if ( interrupt_state != NULL ) {<br>
+    sc = rtems_gpio_disable_interrupt(pin_number);<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+      return sc;<br>
+    }<br>
+  }<br>
+<br>
+  gpio_pin_state[pin_number].pin_function = NOT_USED;<br>
+  gpio_pin_state[pin_number].resistor_mode = NO_PULL_RESISTOR;<br>
+  gpio_pin_state[pin_number].logic_invert = false;<br>
+  gpio_pin_state[pin_number].on_group = false;<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_release_configuration(<br>
+  const rtems_gpio_pin_conf *conf<br>
+) {<br>
+  if ( conf == NULL ) {<br>
+    return RTEMS_UNSATISFIED;<br>
+  }<br>
+<br>
+  return rtems_gpio_release_pin(conf->pin_number);<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_release_multiple_pins(<br>
+  const rtems_gpio_pin_conf *pins,<br>
+  uint32_t pin_count<br>
+) {<br>
+  rtems_status_code sc;<br>
+  uint32_t i;<br>
+<br>
+  if ( pins == NULL ) {<br>
+    return RTEMS_UNSATISFIED;<br>
+  }<br>
+<br>
+  for ( i = 0; i < pin_count; ++i ) {<br>
+    sc = rtems_gpio_release_pin(pins[i].pin_number);<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+    }<br>
+  }<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_release_pin_group(<br>
+  rtems_gpio_group *group<br>
+) {<br>
+  rtems_status_code sc;<br>
+  uint8_t i;<br>
+<br>
+  ACQUIRE_LOCK(group->group_lock);<br>
+<br>
+  sc = rtems_semaphore_flush(group->group_lock);<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    RELEASE_LOCK(group->group_lock);<br>
+<br>
+    return sc;<br>
+  }<br>
+<br>
+  RELEASE_LOCK(group->group_lock);<br>
+<br>
+  /* Deletes the group lock. */<br>
+  sc = rtems_semaphore_delete(group->group_lock);<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    return sc;<br>
+  }<br>
+<br>
+  /* Pin releasing. */<br>
+  for ( i = 0; i < group->input_count; ++i ) {<br>
+    sc = rtems_gpio_release_pin(group->digital_inputs[i]);<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+    }<br>
+  }<br>
+<br>
+  if ( group->input_count > 0 ) {<br>
+    free(group->digital_inputs);<br>
+  }<br>
+<br>
+  for ( i = 0; i < group->output_count; ++i ) {<br>
+    sc = rtems_gpio_release_pin(group->digital_outputs[i]);<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+    }<br>
+  }<br>
+<br>
+  if ( group->output_count > 0 ) {<br>
+    free(group->digital_outputs);<br>
+  }<br>
+<br>
+  for ( i = 0; i < group->bsp_specific_pin_count; ++i ) {<br>
+    sc = rtems_gpio_release_pin(group->bsp_speficifc_pins[i]);<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      return sc;<br>
+    }<br>
+  }<br>
+<br>
+  if ( group->bsp_specific_pin_count > 0 ) {<br>
+    free(group->bsp_speficifc_pins);<br>
+  }<br>
+<br>
+  rtems_chain_extract(&group->node);<br>
+<br>
+  free(group);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_debounce_switch(uint32_t pin_number, int ticks)<br>
+{<br>
+  gpio_pin_interrupt_state *interrupt_state;<br>
+  uint32_t bank;<br>
+<br>
+  if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {<br>
+    return RTEMS_INVALID_ID;<br>
+  }<br>
+<br>
+  bank = BANK_NUMBER(pin_number);<br>
+<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  interrupt_state = gpio_pin_state[pin_number].interrupt_state;<br>
+<br>
+  /* If no interrupt configuration is set for this pin, or if the pin is<br>
+   * not set as a digital input, or the pin in on a group. */<br>
+  if (<br>
+      interrupt_state == NULL ||<br>
+      gpio_pin_state[pin_number].pin_function != DIGITAL_INPUT ||<br>
+      gpio_pin_state[pin_number].on_group<br>
+  ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return RTEMS_NOT_CONFIGURED;<br>
+  }<br>
+<br>
+  interrupt_state->debouncing_tick_count = ticks;<br>
+  interrupt_state->last_isr_tick = 0;<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_interrupt_handler_install(<br>
+  uint32_t pin_number,<br>
+  rtems_gpio_irq_state (*handler) (void *arg),<br>
+  void *arg<br>
+) {<br>
+  gpio_pin_interrupt_state *interrupt_state;<br>
+  gpio_handler_node *isr_node;<br>
+  uint32_t bank;<br>
+<br>
+  if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {<br>
+    return RTEMS_INVALID_ID;<br>
+  }<br>
+<br>
+  bank = BANK_NUMBER(pin_number);<br>
+<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  interrupt_state = gpio_pin_state[pin_number].interrupt_state;<br>
+<br>
+  /* If no interrupt configuration is set for this pin. */<br>
+   if ( interrupt_state == NULL ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return RTEMS_NOT_CONFIGURED;<br>
+  }<br>
+<br>
+  /* If the current pin has no interrupt enabled<br>
+   * then it does not need an handler. */<br>
+  if ( interrupt_state->active_interrupt == NONE ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return RTEMS_NOT_CONFIGURED;<br>
+  }<br>
+  /* If the pin already has an enabled interrupt but the installed handler<br>
+   * is set as unique. */<br>
+  else if (<br>
+           interrupt_state->handler_flag == UNIQUE_HANDLER &&<br>
+           !rtems_chain_is_empty(&interrupt_state->handler_chain)<br>
+  ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return RTEMS_TOO_MANY;<br>
+  }<br>
+<br>
+  /* Update the pin's ISR list. */<br>
+  isr_node = (gpio_handler_node *) malloc(sizeof(gpio_handler_node));<br>
+<br>
+  if ( isr_node == NULL ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return RTEMS_NO_MEMORY;<br>
+  }<br>
+<br>
+  isr_node->handler = handler;<br>
+  isr_node->arg = arg;<br>
+<br>
+  rtems_chain_append(&interrupt_state->handler_chain, &isr_node->node);<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_enable_interrupt(<br>
+  uint32_t pin_number,<br>
+  rtems_gpio_interrupt interrupt,<br>
+  rtems_gpio_handler_flag flag,<br>
+  bool threaded_handling,<br>
+  rtems_gpio_irq_state (*handler) (void *arg),<br>
+  void *arg<br>
+) {<br>
+  gpio_pin_interrupt_state *interrupt_state;<br>
+  rtems_vector_number vector;<br>
+  rtems_status_code sc;<br>
+  uint32_t bank;<br>
+  uint32_t pin;<br>
+<br>
+  if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {<br>
+    return RTEMS_INVALID_ID;<br>
+  }<br>
+<br>
+  bank = BANK_NUMBER(pin_number);<br>
+  pin = PIN_NUMBER(pin_number);<br>
+<br>
+  vector = rtems_gpio_bsp_get_vector(bank);<br>
+<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  if (<br>
+      gpio_pin_state[pin_number].pin_function != DIGITAL_INPUT ||<br>
+      gpio_pin_state[pin_number].on_group<br>
+  ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return RTEMS_NOT_CONFIGURED;<br>
+  }<br>
+<br>
+  /* If the bank already has at least one interrupt enabled on a pin,<br>
+   * then new interrupts on this bank must follow the current<br>
+   * threading policy. */<br>
+  if (<br>
+      gpio_bank_state[bank].interrupt_counter > 0 &&<br>
+      gpio_bank_state[bank].threaded_interrupts != threaded_handling<br>
+  ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return RTEMS_RESOURCE_IN_USE;<br>
+  }<br>
+<br>
+  interrupt_state = gpio_pin_state[pin_number].interrupt_state;<br>
+<br>
+  /* If an interrupt configuration is already in place for this pin. */<br>
+  if ( interrupt_state != NULL ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return RTEMS_RESOURCE_IN_USE;<br>
+  }<br>
+<br>
+  gpio_pin_state[pin_number].interrupt_state =<br>
+    (gpio_pin_interrupt_state *) malloc(sizeof(gpio_pin_interrupt_state));<br>
+<br>
+  if ( gpio_pin_state[pin_number].interrupt_state == NULL ) {<br>
+    return RTEMS_NO_MEMORY;<br>
+  }<br>
+<br>
+  gpio_pin_state[pin_number].interrupt_state->active_interrupt = NONE;<br>
+  gpio_pin_state[pin_number].interrupt_state->debouncing_tick_count = 0;<br>
+  gpio_pin_state[pin_number].interrupt_state->last_isr_tick = 0;<br>
+<br>
+  rtems_chain_initialize_empty(<br>
+    &gpio_pin_state[pin_number].interrupt_state->handler_chain<br>
+  );<br>
+<br>
+  interrupt_state = gpio_pin_state[pin_number].interrupt_state;<br>
+<br>
+  interrupt_state->active_interrupt = interrupt;<br>
+  interrupt_state->handler_flag = flag;<br>
+<br>
+  /* Installs the interrupt handler on the GPIO pin<br>
+   * tracking structure. */<br>
+  sc = rtems_gpio_interrupt_handler_install(pin_number, handler, arg);<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return RTEMS_UNSATISFIED;<br>
+  }<br>
+<br>
+  if ( threaded_handling ) {<br>
+    if (<br>
+        _Atomic_Load_uint(&threaded_interrupt_counter, ATOMIC_ORDER_RELAXED) == 0<br>
+    ) {<br>
+      sc = rtems_interrupt_server_initialize(<br>
+             INTERRUPT_SERVER_PRIORITY,<br>
+             INTERRUPT_SERVER_STACK_SIZE,<br>
+             INTERRUPT_SERVER_MODES,<br>
+             INTERRUPT_SERVER_ATTRIBUTES,<br>
+             NULL<br>
+           );<br>
+<br>
+      if ( sc != RTEMS_SUCCESSFUL ) {<br>
+        RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+        return RTEMS_UNSATISFIED;<br>
+      }<br>
+    }<br>
+<br>
+    if ( gpio_bank_state[bank].interrupt_counter == 0 ) {<br>
+      sc = rtems_interrupt_server_handler_install(<br>
+             RTEMS_ID_NONE,<br>
+             vector,<br>
+             "GPIO_HANDLER",<br>
+             RTEMS_INTERRUPT_UNIQUE,<br>
+             (rtems_interrupt_handler) generic_bank_isr,<br>
+             &gpio_bank_state[bank].bank_number<br>
+           );<br>
+<br>
+      if ( sc != RTEMS_SUCCESSFUL ) {<br>
+        RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+        return RTEMS_UNSATISFIED;<br>
+      }<br>
+<br>
+      _Atomic_Fetch_add_uint(<br>
+        &threaded_interrupt_counter,<br>
+        1,<br>
+        ATOMIC_ORDER_RELAXED<br>
+      );<br>
+    }<br>
+  }<br>
+  else if ( gpio_bank_state[bank].interrupt_counter == 0 ) {<br>
+    sc = rtems_interrupt_handler_install(<br>
+           vector,<br>
+           "GPIO_HANDLER",<br>
+           RTEMS_INTERRUPT_UNIQUE,<br>
+           (rtems_interrupt_handler) generic_bank_isr,<br>
+           &gpio_bank_state[bank].bank_number<br>
+         );<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+      return RTEMS_UNSATISFIED;<br>
+    }<br>
+  }<br>
+<br>
+  sc = rtems_bsp_enable_interrupt(bank, pin, interrupt);<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return RTEMS_UNSATISFIED;<br>
+  }<br>
+<br>
+  /* If this was the first interrupt enabled on this GPIO bank,<br>
+   * record the threading policy. */<br>
+  if ( gpio_bank_state[bank].interrupt_counter == 0 ) {<br>
+    gpio_bank_state[bank].threaded_interrupts = threaded_handling;<br>
+  }<br>
+<br>
+  ++gpio_bank_state[bank].interrupt_counter;<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_interrupt_handler_remove(<br>
+  uint32_t pin_number,<br>
+  rtems_gpio_irq_state (*handler) (void *arg),<br>
+  void *arg<br>
+) {<br>
+  gpio_pin_interrupt_state *interrupt_state;<br>
+  rtems_chain_control *handler_list;<br>
+  rtems_chain_node *node;<br>
+  rtems_chain_node *next_node;<br>
+  gpio_handler_node *isr_node;<br>
+  uint32_t bank;<br>
+<br>
+  if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {<br>
+    return RTEMS_INVALID_ID;<br>
+  }<br>
+<br>
+  bank = BANK_NUMBER(pin_number);<br>
+<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  interrupt_state = gpio_pin_state[pin_number].interrupt_state;<br>
+<br>
+  /* If no interrupt configuration is set for this pin. */<br>
+  if ( interrupt_state == NULL ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return RTEMS_NOT_CONFIGURED;<br>
+  }<br>
+<br>
+  handler_list = &interrupt_state->handler_chain;<br>
+<br>
+  node = rtems_chain_first(handler_list);<br>
+<br>
+  /* If the first node is also the last handler for this pin, disables<br>
+   * interrupts on this pin as there will be no handler to handle it.<br>
+   * This also removes the remaining handler. */<br>
+  if ( rtems_chain_is_last(node) ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return rtems_gpio_disable_interrupt(pin_number);<br>
+  }<br>
+<br>
+  /* Iterate the ISR list. */<br>
+  while ( !rtems_chain_is_tail(handler_list, node) ) {<br>
+    isr_node = (gpio_handler_node *) node;<br>
+<br>
+    next_node = node->next;<br>
+<br>
+    if ( isr_node->handler == handler && isr_node->arg == arg ) {<br>
+      rtems_chain_extract(node);<br>
+<br>
+      break;<br>
+    }<br>
+<br>
+    node = next_node;<br>
+  }<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
+<br>
+rtems_status_code rtems_gpio_disable_interrupt(uint32_t pin_number)<br>
+{<br>
+  gpio_pin_interrupt_state *interrupt_state;<br>
+  rtems_chain_control *handler_list;<br>
+  rtems_chain_node *node;<br>
+  rtems_chain_node *next_node;<br>
+  rtems_vector_number vector;<br>
+  rtems_status_code sc;<br>
+  uint32_t bank;<br>
+  uint32_t pin;<br>
+<br>
+  if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {<br>
+    return RTEMS_INVALID_ID;<br>
+  }<br>
+<br>
+  bank = BANK_NUMBER(pin_number);<br>
+  pin = PIN_NUMBER(pin_number);<br>
+<br>
+  vector = rtems_gpio_bsp_get_vector(bank);<br>
+<br>
+  ACQUIRE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  interrupt_state = gpio_pin_state[pin_number].interrupt_state;<br>
+<br>
+  /* If no interrupt configuration is set for this pin. */<br>
+  if ( interrupt_state == NULL ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return RTEMS_NOT_CONFIGURED;<br>
+  }<br>
+<br>
+  sc = rtems_bsp_disable_interrupt(bank, pin, interrupt_state->active_interrupt);<br>
+<br>
+  if ( sc != RTEMS_SUCCESSFUL ) {<br>
+    RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+    return RTEMS_UNSATISFIED;<br>
+  }<br>
+<br>
+  interrupt_state->active_interrupt = NONE;<br>
+<br>
+  handler_list = &interrupt_state->handler_chain;<br>
+<br>
+  node = rtems_chain_first(handler_list);<br>
+<br>
+  /* Iterate the ISR list. */<br>
+  while ( !rtems_chain_is_tail(handler_list, node) ) {<br>
+    next_node = node->next;<br>
+<br>
+    rtems_chain_extract(node);<br>
+<br>
+    node = next_node;<br>
+  }<br>
+<br>
+  /* If this is the last GPIO interrupt are left in this bank,<br>
+   * removes the handler. */<br>
+  if ( gpio_bank_state[bank].interrupt_counter == 1 ) {<br>
+    if ( gpio_bank_state[bank].threaded_interrupts ) {<br>
+      sc = rtems_interrupt_server_handler_remove(<br>
+             RTEMS_ID_NONE,<br>
+             vector,<br>
+             (rtems_interrupt_handler) generic_bank_isr,<br>
+             &gpio_bank_state[bank].bank_number<br>
+           );<br>
+    }<br>
+    else {<br>
+      sc = rtems_interrupt_handler_remove(<br>
+             vector,<br>
+             (rtems_interrupt_handler) generic_bank_isr,<br>
+             &gpio_bank_state[bank].bank_number<br>
+           );<br>
+    }<br>
+<br>
+    if ( sc != RTEMS_SUCCESSFUL ) {<br>
+      RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+      return RTEMS_UNSATISFIED;<br>
+    }<br>
+  }<br>
+<br>
+  /* Free the pin's interrupt state structure. */<br>
+  free(interrupt_state);<br>
+<br>
+  --gpio_bank_state[bank].interrupt_counter;<br>
+<br>
+  if ( gpio_bank_state[bank].threaded_interrupts ) {<br>
+    _Atomic_Fetch_sub_uint(&threaded_interrupt_counter, 1, ATOMIC_ORDER_RELAXED);<br>
+  }<br>
+<br>
+  RELEASE_LOCK(gpio_bank_state[bank].lock);<br>
+<br>
+  return RTEMS_SUCCESSFUL;<br>
+}<br>
diff --git a/c/src/lib/libbsp/shared/include/gpio.h b/c/src/lib/libbsp/shared/include/gpio.h<br>
new file mode 100644<br>
index 0000000..b2deb1e<br>
--- /dev/null<br>
+++ b/c/src/lib/libbsp/shared/include/gpio.h<br>
@@ -0,0 +1,948 @@<br>
+/**<br>
+ * @file gpio.h<br>
+ *<br>
+ * @ingroup rtems_gpio<br>
+ *<br>
+ * @brief RTEMS GPIO API definition.<br>
+ */<br>
+<br>
+/*<br>
+ *  Copyright (c) 2014-2015 Andre Marques <andre.lousa.marques at <a href="http://gmail.com" rel="noreferrer" target="_blank">gmail.com</a>><br>
+ *<br>
+ *  The license and distribution terms for this file may be<br>
+ *  found in the file LICENSE in this distribution or at<br>
+ *  <a href="http://www.rtems.org/license/LICENSE" rel="noreferrer" target="_blank">http://www.rtems.org/license/LICENSE</a>.<br>
+ */<br>
+<br>
+#ifndef LIBBSP_SHARED_GPIO_H<br>
+#define LIBBSP_SHARED_GPIO_H<br>
+<br>
+#include <bsp.h><br>
+#include <rtems.h><br>
+<br>
+#ifdef __cplusplus<br>
+extern "C" {<br>
+#endif /* __cplusplus */<br>
+<br>
+#if !defined(BSP_GPIO_PIN_COUNT) || !defined(BSP_GPIO_PINS_PER_BANK)<br>
+  #error "BSP_GPIO_PIN_COUNT or BSP_GPIO_PINS_PER_BANK is not defined."<br>
+#endif<br>
+<br>
+#if BSP_GPIO_PIN_COUNT <= 0 || BSP_GPIO_PINS_PER_BANK <= 0<br>
+  #error "Invalid BSP_GPIO_PIN_COUNT or BSP_GPIO_PINS_PER_BANK."<br>
+#endif<br>
+<br>
+#if BSP_GPIO_PINS_PER_BANK > 32<br>
+  #error "Invalid BSP_GPIO_PINS_PER_BANK. Must be in the range of 1 to 32."<br>
+#endif<br>
+<br>
+#define GPIO_LAST_BANK_PINS BSP_GPIO_PIN_COUNT % BSP_GPIO_PINS_PER_BANK<br>
+<br>
+#if GPIO_LAST_BANK_PINS > 0<br>
+  #define GPIO_BANK_COUNT (BSP_GPIO_PIN_COUNT / BSP_GPIO_PINS_PER_BANK) + 1<br>
+#else<br>
+  #define GPIO_BANK_COUNT BSP_GPIO_PIN_COUNT / BSP_GPIO_PINS_PER_BANK<br>
+  #define GPIO_LAST_BANK_PINS BSP_GPIO_PINS_PER_BANK<br>
+#endif<br>
+<br>
+#if defined(BSP_GPIO_PINS_PER_SELECT_BANK) && BSP_GPIO_PINS_PER_SELECT_BANK > 32<br>
+  #error "Invalid BSP_GPIO_PINS_PER_SELECT_BANK. Must under and including 32."<br>
+#elif defined(BSP_GPIO_PINS_PER_SELECT_BANK) <= 32<br>
+  #define GPIO_SELECT_BANK_COUNT \<br>
+    BSP_GPIO_PINS_PER_BANK / BSP_GPIO_PINS_PER_SELECT_BANK<br>
+#endif<br>
+<br>
+#define INTERRUPT_SERVER_PRIORITY 1<br>
+#define INTERRUPT_SERVER_STACK_SIZE 2 * RTEMS_MINIMUM_STACK_SIZE<br>
+#define INTERRUPT_SERVER_MODES RTEMS_TIMESLICE | RTEMS_PREEMPT<br>
+#define INTERRUPT_SERVER_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES<br>
+<br>
+/**<br>
+ * @name GPIO data structures<br>
+ *<br>
+ * @{<br>
+ */<br>
+<br>
+/**<br>
+ * @brief The set of possible configurations for a GPIO pull-up resistor.<br>
+ *<br>
+ * Enumerated type to define the possible pull-up resistor configurations<br>
+ * for a GPIO pin.<br>
+ */<br>
+typedef enum<br>
+{<br>
+  PULL_UP = 1,<br>
+  PULL_DOWN,<br>
+  NO_PULL_RESISTOR<br>
+} rtems_gpio_pull_mode;<br>
+<br>
+/**<br>
+ * @brief The set of possible functions a pin can have.<br>
+ *<br>
+ * Enumerated type to define a pin function.<br>
+ */<br>
+typedef enum<br>
+{<br>
+  DIGITAL_INPUT = 0,<br>
+  DIGITAL_OUTPUT,<br>
+  BSP_SPECIFIC,<br>
+  NOT_USED<br>
+} rtems_gpio_function;<br>
+<br>
+/**<br>
+ * @brief The set of possible interrupts a GPIO pin can generate.<br>
+ *<br>
+ * Enumerated type to define a GPIO pin interrupt.<br>
+ */<br>
+typedef enum<br>
+{<br>
+  FALLING_EDGE = 0,<br>
+  RISING_EDGE,<br>
+  LOW_LEVEL,<br>
+  HIGH_LEVEL,<br>
+  BOTH_EDGES,<br>
+  BOTH_LEVELS,<br>
+  NONE<br>
+} rtems_gpio_interrupt;<br>
+<br>
+/**<br>
+ * @brief The set of possible handled states an user-defined interrupt<br>
+ *        handler can return.<br>
+ *<br>
+ * Enumerated type to define an interrupt handler handled state.<br>
+ */<br>
+typedef enum<br>
+{<br>
+  IRQ_HANDLED,<br>
+  IRQ_NONE<br>
+} rtems_gpio_irq_state;<br>
+<br>
+/**<br>
+ * @brief The set of flags to specify an user-defined interrupt handler<br>
+ *        uniqueness on a GPIO pin.<br>
+ *<br>
+ * Enumerated type to define an interrupt handler shared flag.<br>
+ */<br>
+typedef enum<br>
+{<br>
+  SHARED_HANDLER,<br>
+  UNIQUE_HANDLER<br>
+} rtems_gpio_handler_flag;<br>
+<br>
+/**<br>
+ * @brief Object containing relevant information for assigning a BSP specific<br>
+ *        function to a pin.<br>
+ *<br>
+ * Encapsulates relevant data for a BSP specific GPIO function.<br>
+ */<br>
+typedef struct<br>
+{<br>
+  /* The BSP defined function code. */<br>
+  uint32_t io_function;<br>
+<br>
+  void *pin_data;<br>
+} rtems_gpio_specific_data;<br>
+<br>
+/**<br>
+ * @brief Object containing configuration information<br>
+ *        regarding interrupts.<br>
+ */<br>
+typedef struct<br>
+{<br>
+  rtems_gpio_interrupt active_interrupt;<br>
+<br>
+  rtems_gpio_handler_flag handler_flag;<br>
+<br>
+  bool threaded_interrupts;<br>
+<br>
+  /* Interrupt handler function. */<br>
+  rtems_gpio_irq_state (*handler) (void *arg);<br>
+<br>
+  /* Interrupt handler function arguments. */<br>
+  void *arg;<br>
+<br>
+  /* Software switch debounce settings. It should contain the amount of clock<br>
+   * ticks that must pass between interrupts to ensure that the interrupt<br>
+   * was not caused by a switch bounce.<br>
+   * If set to 0 this feature is disabled . */<br>
+  uint32_t debounce_clock_tick_interval;<br>
+} rtems_gpio_interrupt_configuration;<br>
+<br>
+/**<br>
+ * @brief Object containing configuration information<br>
+ *        to request/update a GPIO pin.<br>
+ */<br>
+typedef struct<br>
+{<br>
+  /* Processor pin number. */<br>
+  uint32_t pin_number;<br>
+  rtems_gpio_function function;<br>
+<br>
+  /* Pull resistor setting. */<br>
+  rtems_gpio_pull_mode pull_mode;<br>
+<br>
+  /* If digital out pin, set to TRUE to set the pin to logical high,<br>
+   * or FALSE for logical low. If not a digital out then this<br>
+   * is ignored. */<br>
+  bool output_enabled;<br>
+<br>
+  /* If true inverts digital in/out applicational logic. */<br>
+  bool logic_invert;<br>
+<br>
+  /* Pin interrupt configuration. Should be NULL if not used. */<br>
+  rtems_gpio_interrupt_configuration *interrupt;<br>
+<br>
+  /* Structure with BSP specific data, to use during the pin request.<br>
+   * If function == BSP_SPECIFIC this should have a pointer to<br>
+   * a rtems_gpio_specific_data structure.<br>
+   *<br>
+   * If not this field may be NULL. This is passed to the BSP function<br>
+   * so any BSP specific data can be passed to it through this pointer. */<br>
+  void *bsp_specific;<br>
+} rtems_gpio_pin_conf;<br>
+<br>
+/**<br>
+ * @brief Object containing configuration information<br>
+ *        to assign GPIO functions to multiple pins<br>
+ *        at the same time. To be used by BSP code only.<br>
+ */<br>
+typedef struct<br>
+{<br>
+  /* Global GPIO pin number. */<br>
+  uint32_t pin_number;<br>
+<br>
+  /* RTEMS GPIO pin function code. */<br>
+  rtems_gpio_function function;<br>
+<br>
+  /* BSP specific function code. Only used if function == BSP_SPECIFIC */<br>
+  uint32_t io_function;<br>
+<br>
+  /* BSP specific data. */<br>
+  void *bsp_specific;<br>
+} rtems_gpio_multiple_pin_select;<br>
+<br>
+/**<br>
+ * @brief Object containing configuration information<br>
+ *        to request a GPIO pin group.<br>
+ */<br>
+typedef struct<br>
+{<br>
+  const rtems_gpio_pin_conf *digital_inputs;<br>
+  uint32_t input_count;<br>
+<br>
+  const rtems_gpio_pin_conf *digital_outputs;<br>
+  uint32_t output_count;<br>
+<br>
+  const rtems_gpio_pin_conf *bsp_specifics;<br>
+  uint32_t bsp_specific_pin_count;<br>
+} rtems_gpio_group_definition;<br>
+<br>
+/**<br>
+ * @brief Opaque type for a GPIO pin group.<br>
+ */<br>
+typedef struct rtems_gpio_group rtems_gpio_group;<br>
+<br>
+/** @} */<br>
+<br>
+/**<br>
+ * @name gpio Usage<br>
+ *<br>
+ * @{<br>
+ */<br>
+<br>
+/**<br>
+ * @brief Initializes the GPIO API.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL API successfully initialized.<br>
+ * @retval * @see rtems_semaphore_create().<br>
+ */<br>
+extern rtems_status_code rtems_gpio_initialize(void);<br>
+<br>
+/**<br>
+ * @brief Instantiates a GPIO pin group.<br>
+ *        To define the group @see rtems_gpio_define_pin_group().<br>
+ *<br>
+ * @retval rtems_gpio_group pointer.<br>
+ */<br>
+extern rtems_gpio_group *rtems_gpio_create_pin_group(void);<br>
+<br>
+/**<br>
+ * @brief Requests a GPIO pin group configuration.<br>
+ *<br>
+ * @param[in] group_definition rtems_gpio_group_definition structure filled with<br>
+ *                             the group pins configurations.<br>
+ * @param[out] group Reference to the created group.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pin group was configured successfully.<br>
+ * @retval RTEMS_UNSATISFIED @var group_definition or @var group is NULL,<br>
+ *                           the @var pins are not from the same bank,<br>
+ *                           no pins were defined or could not satisfy at<br>
+ *                           least one given configuration.<br>
+ * @retval RTEMS_RESOURCE_IN_USE At least one pin is already being used.<br>
+ * @retval * @see rtems_semaphore_create().<br>
+ */<br>
+extern rtems_status_code rtems_gpio_define_pin_group(<br>
+  const rtems_gpio_group_definition *group_definition,<br>
+  rtems_gpio_group *group<br>
+);<br>
+<br>
+/**<br>
+ * @brief Writes a value to the group's digital outputs. The pins order<br>
+ *        is as defined in the group definition.<br>
+ *<br>
+ * @param[in] data Data to write/send.<br>
+ * @param[in] group Reference to the group.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Data successfully written.<br>
+ * @retval RTEMS_NOT_DEFINED Group has no output pins.<br>
+ * @retval RTEMS_UNSATISFIED Could not operate on at least one of the pins.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_write_group(<br>
+  uint32_t data,<br>
+  rtems_gpio_group *group<br>
+);<br>
+<br>
+/**<br>
+ * @brief Reads the value/level of the group's digital inputs. The pins order<br>
+ *        is as defined in the group definition.<br>
+ *<br>
+ * @param[in] group Reference to the group.<br>
+ *<br>
+ * @retval The function returns a 32-bit bitmask with the group's input pins<br>
+ *         current logical values.<br>
+ * @retval 0xDEADBEEF Group has no input pins.<br>
+ */<br>
+extern uint32_t rtems_gpio_read_group(rtems_gpio_group *group);<br>
+<br>
+/**<br>
+ * @brief Performs a BSP specific operation on a group of pins. The pins order<br>
+ *        is as defined in the group definition.<br>
+ *<br>
+ * @param[in] group Reference to the group.<br>
+ * @param[in] arg Pointer to a BSP defined structure with BSP-specific<br>
+ *                data. This field is handled by the BSP.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Operation completed with success.<br>
+ * @retval RTEMS_NOT_DEFINED Group has no BSP specific pins, or the BSP does not<br>
+ *                           support BSP specific operations for groups.<br>
+ * @retval RTEMS_UNSATISFIED Could not operate on at least one of the pins.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_group_bsp_specific_operation(<br>
+  rtems_gpio_group *group,<br>
+  void *arg<br>
+);<br>
+<br>
+/**<br>
+ * @brief Requests a GPIO pin configuration.<br>
+ *<br>
+ * @param[in] conf rtems_gpio_pin_conf structure filled with the pin information<br>
+ *                 and desired configurations.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pin was configured successfully.<br>
+ * @retval RTEMS_UNSATISFIED Could not satisfy the given configuration.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_request_configuration(<br>
+  const rtems_gpio_pin_conf *conf<br>
+);<br>
+<br>
+/**<br>
+ * @brief Updates the current configuration of a GPIO pin .<br>
+ *<br>
+ * @param[in] conf rtems_gpio_pin_conf structure filled with the pin information<br>
+ *                 and desired configurations.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pin configuration was updated successfully.<br>
+ * @retval RTEMS_INVALID_ID Pin number is invalid.<br>
+ * @retval RTEMS_NOT_CONFIGURED The pin is not being used.<br>
+ * @retval RTEMS_UNSATISFIED Could not update the pin's configuration.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_update_configuration(<br>
+  const rtems_gpio_pin_conf *conf<br>
+);<br>
+<br>
+/**<br>
+ * @brief Sets multiple output GPIO pins with the logical high.<br>
+ *<br>
+ * @param[in] pin_numbers Array with the GPIO pin numbers to set.<br>
+ * @param[in] count Number of GPIO pins to set.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL All pins were set successfully.<br>
+ * @retval RTEMS_INVALID_ID At least one pin number is invalid.<br>
+ * @retval RTEMS_NOT_CONFIGURED At least one of the received pins<br>
+ *                              is not configured as a digital output.<br>
+ * @retval RTEMS_UNSATISFIED Could not set the GPIO pins.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_multi_set(<br>
+  uint32_t *pin_numbers,<br>
+  uint32_t pin_count<br>
+);<br>
+<br>
+/**<br>
+ * @brief Sets multiple output GPIO pins with the logical low.<br>
+ *<br>
+ * @param[in] pin_numbers Array with the GPIO pin numbers to clear.<br>
+ * @param[in] count Number of GPIO pins to clear.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL All pins were cleared successfully.<br>
+ * @retval RTEMS_INVALID_ID At least one pin number is invalid.<br>
+ * @retval RTEMS_NOT_CONFIGURED At least one of the received pins<br>
+ *                              is not configured as a digital output.<br>
+ * @retval RTEMS_UNSATISFIED Could not clear the GPIO pins.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_multi_clear(<br>
+  uint32_t *pin_numbers,<br>
+  uint32_t pin_count<br>
+);<br>
+<br>
+/**<br>
+ * @brief Returns the value (level) of multiple GPIO input pins.<br>
+ *<br>
+ * @param[in] pin_numbers Array with the GPIO pin numbers to read.<br>
+ * @param[in] count Number of GPIO pins to read.<br>
+ *<br>
+ * @retval Bitmask with the values of the corresponding pins.<br>
+ *         0 for logical low and 1 for logical high.<br>
+ * @retval 0xDEADBEEF Could not read at least one pin level.<br>
+ */<br>
+extern uint32_t rtems_gpio_multi_read(<br>
+  uint32_t *pin_numbers,<br>
+  uint32_t pin_count<br>
+);<br>
+<br>
+/**<br>
+ * @brief Sets an output GPIO pin with the logical high.<br>
+ *<br>
+ * @param[in] pin_number GPIO pin number.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pin was set successfully.<br>
+ * @retval RTEMS_INVALID_ID Pin number is invalid.<br>
+ * @retval RTEMS_NOT_CONFIGURED The received pin is not configured<br>
+ *                              as a digital output.<br>
+ * @retval RTEMS_UNSATISFIED Could not set the GPIO pin.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_set(uint32_t pin_number);<br>
+<br>
+/**<br>
+ * @brief Sets an output GPIO pin with the logical low.<br>
+ *<br>
+ * @param[in] pin_number GPIO pin number.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pin was cleared successfully.<br>
+ * @retval RTEMS_INVALID_ID Pin number is invalid.<br>
+ * @retval RTEMS_NOT_CONFIGURED The received pin is not configured<br>
+ *                              as a digital output.<br>
+ * @retval RTEMS_UNSATISFIED Could not clear the GPIO pin.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_clear(uint32_t pin_number);<br>
+<br>
+/**<br>
+ * @brief Returns the value (level) of a GPIO input pin.<br>
+ *<br>
+ * @param[in] pin_number GPIO pin number.<br>
+ *<br>
+ * @retval The function returns 0 or 1 depending on the pin current<br>
+ *         logical value.<br>
+ * @retval -1 Pin number is invalid, or not a digital input pin.<br>
+ */<br>
+extern uint8_t rtems_gpio_get_value(uint32_t pin_number);<br></blockquote><div>extern uint32_t rtems_gpio_get_value(uint32_t pin_number);<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+/**<br>
+ * @brief Requests multiple GPIO pin configurations. If the BSP provides<br>
+ *        support for parallel selection each call to this function will<br>
+ *        result in a single call to the GPIO hardware, else each pin<br>
+ *        configuration will be done in individual and sequential calls.<br>
+ *        All pins must belong to the same GPIO bank.<br>
+ *<br>
+ * @param[in] pins Array of rtems_gpio_pin_conf structures filled with the pins<br>
+ *                 information and desired configurations. All pins must belong<br>
+ *                 to the same GPIO bank.<br>
+ * @param[in] pin_count Number of pin configurations in the @var pins array.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL All pins were configured successfully.<br>
+ * @retval RTEMS_INVALID_ID At least one pin number in the @var pins array<br>
+ *                          is invalid.<br>
+ * @retval RTEMS_RESOURCE_IN_USE At least one pin is already being used.<br>
+ * @retval RTEMS_UNSATISFIED Could not satisfy at least one given configuration.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_multi_select(<br>
+  const rtems_gpio_pin_conf *pins,<br>
+  uint8_t pin_count<br>
+);<br>
+<br>
+/**<br>
+ * @brief Assigns a certain function to a GPIO pin.<br>
+ *<br>
+ * @param[in] pin_number GPIO pin number.<br>
+ * @param[in] function The new function for the pin.<br>
+ * @param[in] output_enabled If TRUE and @var function is DIGITAL_OUTPUT,<br>
+ *                           then the pin is set with the logical high.<br>
+ *                           Otherwise it is set with logical low.<br>
+ * @param[in] logic_invert Reverses the digital I/O logic for DIGITAL_INPUT<br>
+ *                         and DIGITAL_OUTPUT pins.<br>
+ * @param[in] bsp_specific Pointer to a BSP defined structure with BSP-specific<br>
+ *                         data. This field is handled by the BSP.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pin was configured successfully.<br>
+ * @retval RTEMS_INVALID_ID Pin number is invalid.<br>
+ * @retval RTEMS_RESOURCE_IN_USE The received pin is already being used.<br>
+ * @retval RTEMS_UNSATISFIED Could not assign the GPIO function.<br>
+ * @retval RTEMS_NOT_DEFINED GPIO function not defined, or NOT_USED.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_request_pin(<br>
+  uint32_t pin_number,<br>
+  rtems_gpio_function function,<br>
+  bool output_enable,<br>
+  bool logic_invert,<br>
+  void *bsp_specific<br>
+);<br>
+<br>
+/**<br>
+ * @brief Configures a single GPIO pin pull resistor.<br>
+ *<br>
+ * @param[in] pin_number GPIO pin number.<br>
+ * @param[in] mode The pull resistor mode.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pull resistor successfully configured.<br>
+ * @retval RTEMS_INVALID_ID Pin number is invalid.<br>
+ * @retval RTEMS_UNSATISFIED Could not set the pull mode.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_resistor_mode(<br>
+  uint32_t pin_number,<br>
+  rtems_gpio_pull_mode mode<br>
+);<br>
+<br>
+/**<br>
+ * @brief Releases a GPIO pin, making it available to be used again.<br>
+ *<br>
+ * @param[in] pin_number GPIO pin number.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pin successfully disabled.<br>
+ * @retval RTEMS_INVALID_ID Pin number is invalid.<br>
+ * @retval * Could not disable an active interrupt on this pin,<br>
+ *           @see rtems_gpio_disable_interrupt().<br>
+ */<br>
+extern rtems_status_code rtems_gpio_release_pin(uint32_t pin_number);<br>
+<br>
+/**<br>
+ * @brief Releases a GPIO pin, making it available to be used again.<br>
+ *<br>
+ * @param[in] conf GPIO pin configuration to be released.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pin successfully disabled.<br>
+ * @retval RTEMS_UNSATISFIED Pin configuration is NULL.<br>
+ * @retval * @see rtems_gpio_release_pin().<br>
+ */<br>
+extern rtems_status_code rtems_gpio_release_configuration(<br>
+  const rtems_gpio_pin_conf *conf<br>
+);<br>
+<br>
+/**<br>
+ * @brief Releases multiple GPIO pins, making them available to be used again.<br>
+ *<br>
+ * @param[in] pins Array of rtems_gpio_pin_conf structures.<br>
+ * @param[in] pin_count Number of pin configurations in the @var pins array.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pins successfully disabled.<br>
+ * @retval RTEMS_UNSATISFIED @var pins array is NULL.<br>
+ * @retval * @see rtems_gpio_release_pin().<br>
+ */<br>
+extern rtems_status_code rtems_gpio_release_multiple_pins(<br>
+  const rtems_gpio_pin_conf *pins,<br>
+  uint32_t pin_count<br>
+);<br>
+<br>
+/**<br>
+ * @brief Releases a GPIO pin group, making the pins used available to be<br>
+ *        repurposed.<br>
+ *<br>
+ * @param[in] conf GPIO pin configuration to be released.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pins successfully disabled.<br>
+ * @retval * @see rtems_gpio_release_pin(), @see rtems_semaphore_delete() or<br>
+ *           @see rtems_semaphore_flush().<br>
+ */<br>
+extern rtems_status_code rtems_gpio_release_pin_group(<br>
+  rtems_gpio_group *group<br>
+);<br>
+<br>
+/**<br>
+ * @brief Attaches a debouncing function to a given pin/switch.<br>
+ *        Debouncing is done by requiring a certain number of clock ticks to<br>
+ *        pass between interrupts. Any interrupt fired too close to the last<br>
+ *        will be ignored as it is probably the result of an involuntary<br>
+ *        switch/button bounce after being released.<br>
+ *<br>
+ * @param[in] pin_number GPIO pin number.<br>
+ * @param[in] ticks Minimum number of clock ticks that must pass between<br>
+ *                  interrupts so it can be considered a legitimate<br>
+ *                  interrupt.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Debounce function successfully attached to the pin.<br>
+ * @retval RTEMS_INVALID_ID Pin number is invalid.<br>
+ * @retval RTEMS_NOT_CONFIGURED The current pin is not configured as a digital<br>
+ *                              input, hence it can not be connected to a switch,<br>
+ *                              or interrupts are not enabled for this pin.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_debounce_switch(<br>
+  uint32_t pin_number,<br>
+  int ticks<br>
+);<br>
+<br>
+/**<br>
+ * @brief Connects a new user-defined interrupt handler to a given pin.<br>
+ *<br>
+ * @param[in] pin_number GPIO pin number.<br>
+ * @param[in] handler Pointer to a function that will be called every time<br>
+ *                    the enabled interrupt for the given pin is generated.<br>
+ *                    This function must return information about its<br>
+ *                    handled/unhandled state.<br>
+ * @param[in] arg Void pointer to the arguments of the user-defined handler.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Handler successfully connected to this pin.<br>
+ * @retval RTEMS_NO_MEMORY Could not connect more user-defined handlers to<br>
+ *                         the given pin.<br>
+ * @retval RTEMS_NOT_CONFIGURED The given pin has no interrupt configured.<br>
+ * @retval RTEMS_INVALID_ID Pin number is invalid.<br>
+ * @retval RTEMS_TOO_MANY The pin's current handler is set as unique.<br>
+ * @retval RTEMS_RESOURCE_IN_USE The current user-defined handler for this pin<br>
+ *                               is unique.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_interrupt_handler_install(<br>
+  uint32_t pin_number,<br>
+  rtems_gpio_irq_state (*handler) (void *arg),<br>
+  void *arg<br>
+);<br>
+<br>
+/**<br>
+ * @brief Enables interrupts to be generated on a given GPIO pin.<br>
+ *        When fired that interrupt will call the given handler.<br>
+ *<br>
+ * @param[in] pin_number GPIO pin number.<br>
+ * @param[in] interrupt Type of interrupt to enable for the pin.<br>
+ * @param[in] flag Defines the uniqueness of the interrupt handler for the pin.<br>
+ * @param[in] threaded_handling Defines if the handler should be called from a<br>
+ *                              thread/task or from normal ISR contex.<br>
+ * @param[in] handler Pointer to a function that will be called every time<br>
+ *                    @var interrupt is generated. This function must return<br>
+ *                    information about its handled/unhandled state.<br>
+ * @param[in] arg Void pointer to the arguments of the user-defined handler.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Interrupt successfully enabled for this pin.<br>
+ * @retval RTEMS_UNSATISFIED Could not install the GPIO ISR, create/start<br>
+ *                           the handler task, or enable the interrupt<br>
+ *                           on the pin.<br>
+ * @retval RTEMS_INVALID_ID Pin number is invalid.<br>
+ * @retval RTEMS_NOT_CONFIGURED The received pin is not configured<br>
+ *                              as a digital input, the pin is on a<br>
+ *                              pin grouping.<br>
+ * @retval RTEMS_RESOURCE_IN_USE The pin already has an enabled interrupt,<br>
+ *                               or the handler threading policy does not match<br>
+ *                               the bank's policy.<br>
+ * @retval RTEMS_NO_MEMORY Could not store the pin's interrupt configuration.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_enable_interrupt(<br>
+  uint32_t pin_number,<br>
+  rtems_gpio_interrupt interrupt,<br>
+  rtems_gpio_handler_flag flag,<br>
+  bool threaded_handling,<br>
+  rtems_gpio_irq_state (*handler) (void *arg),<br>
+  void *arg<br>
+);<br>
+<br>
+/**<br>
+ * @brief Disconnects an user-defined interrupt handler from the given pin.<br>
+ *        If in the end there are no more user-defined handlers connected<br>
+ *        to the pin, interrupts are disabled on the given pin.<br>
+ *<br>
+ * @param[in] pin_number GPIO pin number.<br>
+ * @param[in] handler Pointer to the user-defined handler<br>
+ * @param[in] arg Void pointer to the arguments of the user-defined handler.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Handler successfully disconnected from this pin.<br>
+ * @retval RTEMS_INVALID_ID Pin number is invalid.<br>
+ * @retval RTEMS_NOT_CONFIGURED Pin has no active interrupts.<br>
+ * @retval * @see rtems_gpio_disable_interrupt()<br>
+ */<br>
+extern rtems_status_code rtems_gpio_interrupt_handler_remove(<br>
+  uint32_t pin_number,<br>
+  rtems_gpio_irq_state (*handler) (void *arg),<br>
+  void *arg<br>
+);<br>
+<br>
+/**<br>
+ * @brief Stops interrupts from being generated on a given GPIO pin<br>
+ *        and removes the corresponding handler.<br>
+ *<br>
+ * @param[in] pin_number GPIO pin number.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Interrupt successfully disabled for this pin.<br>
+ * @retval RTEMS_INVALID_ID Pin number is invalid.<br>
+ * @retval RTEMS_NOT_CONFIGURED Pin has no active interrupts.<br>
+ * @retval RTEMS_UNSATISFIED Could not remove the current interrupt handler,<br>
+ *                           could not recognize the current active interrupt<br>
+ *                           on this pin or could not disable interrupts on<br>
+ *                           this pin.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_disable_interrupt(uint32_t pin_number);<br>
+<br>
+/**<br>
+ * @brief Sets multiple output GPIO pins with the logical high.<br>
+ *        This must be implemented by each BSP.<br>
+ *<br>
+ * @param[in] bank GPIO bank number.<br>
+ * @param[in] bitmask Bitmask of GPIO pins to set in the given bank.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL All pins were set successfully.<br>
+ * @retval RTEMS_UNSATISFIED Could not set at least one of the pins.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_bsp_multi_set(<br>
+  uint32_t bank,<br>
+  uint32_t bitmask<br>
+);<br>
+<br>
+/**<br>
+ * @brief Sets multiple output GPIO pins with the logical low.<br>
+ *        This must be implemented by each BSP.<br>
+ *<br>
+ * @param[in] bank GPIO bank number.<br>
+ * @param[in] bitmask Bitmask of GPIO pins to clear in the given bank.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL All pins were cleared successfully.<br>
+ * @retval RTEMS_UNSATISFIED Could not clear at least one of the pins.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_bsp_multi_clear(<br>
+  uint32_t bank,<br>
+  uint32_t bitmask<br>
+);<br>
+<br>
+/**<br>
+ * @brief Returns the value (level) of multiple GPIO input pins.<br>
+ *        This must be implemented by each BSP.<br>
+ *<br>
+ * @param[in] bank GPIO bank number.<br>
+ * @param[in] bitmask Bitmask of GPIO pins to read in the given bank.<br>
+ *<br>
+ * @retval The function must return a bitmask with the values of the<br>
+ *         corresponding pins. 0 for logical low and 1 for logical high.<br>
+ * @retval 0xDEADBEEF Could not read at least one pin level.<br>
+ */<br>
+extern uint32_t rtems_gpio_bsp_multi_read(uint32_t bank, uint32_t bitmask);<br>
+<br>
+/**<br>
+ * @brief Performs a BSP specific operation on a group of pins.<br>
+ *        The implementation for this function may be omitted if the target<br>
+ *        does not support the feature, by returning RTEMS_NOT_DEFINED.<br>
+ *<br>
+ * @param[in] bank GPIO bank number.<br>
+ * @param[in] bitmask Bitmask of GPIO pins to clear in the given bank.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL All pins were cleared successfully.<br>
+ * @retval RTEMS_NOT_DEFINED The BSP does not support BSP specific operations<br>
+ *                           for groups.<br>
+ * @retval RTEMS_UNSATISFIED Could not clear at least one of the pins.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_bsp_specific_group_operation(<br>
+  uint32_t bank,<br>
+  uint32_t *pins,<br>
+  uint32_t pin_count,<br>
+  void *arg<br>
+);<br>
+<br>
+/**<br>
+ * @brief Assigns GPIO functions to all the given pins in a single register<br>
+ *        operation.<br>
+ *        The implementation for this function may be omitted if the target<br>
+ *        does not support the feature, by returning RTEMS_NOT_DEFINED.<br>
+ *<br>
+ * @param[in] pins Array of rtems_gpio_multiple_pin_select structures filled<br>
+ *                 with the pins desired functions. All pins belong to the<br>
+ *                 same select bank.<br>
+ * @param[in] pin_count Number of pin configurations in the @var pins array.<br>
+ * @param[in] select_bank Select bank number of the received pins.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Functions were assigned successfully.<br>
+ * @retval RTEMS_NOT_DEFINED The BSP does not support multiple pin function<br>
+ *                           assignment.<br>
+ * @retval RTEMS_UNSATISFIED Could not assign the functions to the pins.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_bsp_multi_select(<br>
+  rtems_gpio_multiple_pin_select *pins,<br>
+  uint32_t pin_count,<br>
+  uint32_t select_bank<br>
+);<br>
+<br>
+/**<br>
+ * @brief Sets an output GPIO pin with the logical high.<br>
+ *        This must be implemented by each BSP.<br>
+ *<br>
+ * @param[in] bank GPIO bank number.<br>
+ * @param[in] pin GPIO pin number within the given bank.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pin was set successfully.<br>
+ * @retval RTEMS_UNSATISFIED Could not set the given pin.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_bsp_set(uint32_t bank, uint32_t pin);<br>
+<br>
+/**<br>
+ * @brief Sets an output GPIO pin with the logical low.<br>
+ *        This must be implemented by each BSP.<br>
+ *<br>
+ * @param[in] bank GPIO bank number.<br>
+ * @param[in] pin GPIO pin number within the given bank.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pin was cleared successfully.<br>
+ * @retval RTEMS_UNSATISFIED Could not clear the given pin.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_bsp_clear(uint32_t bank, uint32_t pin);<br>
+<br>
+/**<br>
+ * @brief Returns the value (level) of a GPIO input pin.<br>
+ *        This must be implemented by each BSP.<br>
+ *<br>
+ * @param[in] bank GPIO bank number.<br>
+ * @param[in] pin GPIO pin number within the given bank.<br>
+ *<br>
+ * @retval The function must return 0 or 1 depending on the pin current<br>
+ *         logical value.<br>
+ * @retval -1 Could not read the pin level.<br>
+ */<br>
+extern uint8_t rtems_gpio_bsp_get_value(uint32_t bank, uint32_t pin);<br></blockquote><div>extern uint32_t rtems_gpio_bsp_get_value(uint32_t bank, uint32_t pin); </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
+<br>
+/**<br>
+ * @brief Assigns the digital input function to the given pin.<br>
+ *        This must be implemented by each BSP.<br>
+ *<br>
+ * @param[in] bank GPIO bank number.<br>
+ * @param[in] pin GPIO pin number within the given bank.<br>
+ * @param[in] bsp_specific Pointer to a BSP defined structure with BSP-specific<br>
+ *                         data.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Function was assigned successfully.<br>
+ * @retval RTEMS_UNSATISFIED Could not assign the function to the pin.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_bsp_select_input(<br>
+  uint32_t bank,<br>
+  uint32_t pin,<br>
+  void *bsp_specific<br>
+);<br>
+<br>
+/**<br>
+ * @brief Assigns the digital output function to the given pin.<br>
+ *        This must be implemented by each BSP.<br>
+ *<br>
+ * @param[in] bank GPIO bank number.<br>
+ * @param[in] pin GPIO pin number within the given bank.<br>
+ * @param[in] bsp_specific Pointer to a BSP defined structure with BSP-specific<br>
+ *                         data.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Function was assigned successfully.<br>
+ * @retval RTEMS_UNSATISFIED Could not assign the function to the pin.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_bsp_select_output(<br>
+  uint32_t bank,<br>
+  uint32_t pin,<br>
+  void *bsp_specific<br>
+);<br>
+<br>
+/**<br>
+ * @brief Assigns a BSP specific function to the given pin.<br>
+ *        This must be implemented by each BSP.<br>
+ *<br>
+ * @param[in] bank GPIO bank number.<br>
+ * @param[in] pin GPIO pin number within the given bank.<br>
+ * @param[in] function BSP defined GPIO function.<br>
+ * @param[in] pin_data Pointer to a BSP defined structure with BSP-specific<br>
+ *                     data.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Function was assigned successfully.<br>
+ * @retval RTEMS_UNSATISFIED Could not assign the function to the pin.<br>
+ */<br>
+extern rtems_status_code rtems_bsp_select_specific_io(<br>
+  uint32_t bank,<br>
+  uint32_t pin,<br>
+  uint32_t function,<br>
+  void *pin_data<br>
+);<br>
+<br>
+/**<br>
+ * @brief Configures a single GPIO pin pull resistor.<br>
+ *        This must be implemented by each BSP.<br>
+ *<br>
+ * @param[in] bank GPIO bank number.<br>
+ * @param[in] pin GPIO pin number within the given bank.<br>
+ * @param[in] mode The pull resistor mode.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Pull resistor successfully configured.<br>
+ * @retval RTEMS_UNSATISFIED Could not set the pull mode.<br>
+ */<br>
+extern rtems_status_code rtems_gpio_bsp_set_resistor_mode(<br>
+  uint32_t bank,<br>
+  uint32_t pin,<br>
+  rtems_gpio_pull_mode mode<br>
+);<br>
+<br>
+/**<br>
+ * @brief Reads and returns a vector/bank interrupt event line.<br>
+ *        The bitmask should indicate with a 1 if the corresponding pin<br>
+ *        as a pending interrupt, or 0 if otherwise. The function<br>
+ *        should clear the interrupt event line before returning.<br>
+ *        This must be implemented by each BSP.<br>
+ *<br>
+ * @param[in] vector GPIO vector/bank.<br>
+ *<br>
+ * @retval Bitmask (max 32-bit) representing a GPIO bank, where a bit set<br>
+ *         indicates an active interrupt on that pin.<br>
+ */<br>
+extern uint32_t rtems_gpio_bsp_interrupt_line(rtems_vector_number vector);<br>
+<br>
+/**<br>
+ * @brief Calculates a vector number for a given GPIO bank.<br>
+ *        This must be implemented by each BSP.<br>
+ *<br>
+ * @param[in] bank GPIO bank number.<br>
+ *<br>
+ * @retval The corresponding rtems_vector_number.<br>
+ */<br>
+extern rtems_vector_number rtems_gpio_bsp_get_vector(uint32_t bank);<br>
+<br>
+/**<br>
+ * @brief Enables interrupts to be generated on a given GPIO pin.<br>
+ *        This must be implemented by each BSP.<br>
+ *<br>
+ * @param[in] bank GPIO bank number.<br>
+ * @param[in] pin GPIO pin number within the given bank.<br>
+ * @param[in] interrupt Type of interrupt to enable for the pin.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Interrupt successfully enabled for this pin.<br>
+ * @retval RTEMS_UNSATISFIED Could not enable the interrupt on the pin.<br>
+ */<br>
+extern rtems_status_code rtems_bsp_enable_interrupt(<br>
+  uint32_t bank,<br>
+  uint32_t pin,<br>
+  rtems_gpio_interrupt interrupt<br>
+);<br>
+<br>
+/**<br>
+ * @brief Stops interrupts from being generated on a given GPIO pin.<br>
+ *        This must be implemented by each BSP.<br>
+ *<br>
+ * @param[in] bank GPIO bank number.<br>
+ * @param[in] pin GPIO pin number within the given bank.<br>
+ * @param[in] active_interrupt Interrupt type currently active on this pin.<br>
+ *<br>
+ * @retval RTEMS_SUCCESSFUL Interrupt successfully disabled for this pin.<br>
+ * @retval RTEMS_UNSATISFIED Could not disable interrupts on this pin.<br>
+ */<br>
+extern rtems_status_code rtems_bsp_disable_interrupt(<br>
+  uint32_t bank,<br>
+  uint32_t pin,<br>
+  rtems_gpio_interrupt interrupt<br>
+);<br>
+<br>
+/** @} */<br>
+<br>
+#ifdef __cplusplus<br>
+}<br>
+#endif /* __cplusplus */<br>
+<br>
+#endif /* LIBBSP_SHARED_GPIO_H */<br>
<span><font color="#888888">--<br>
2.3.6<br>
<br>
_______________________________________________<br>
devel mailing list<br>
<a href="mailto:devel@rtems.org" target="_blank">devel@rtems.org</a><br>
<a href="http://lists.rtems.org/mailman/listinfo/devel" rel="noreferrer" target="_blank">http://lists.rtems.org/mailman/listinfo/devel</a><br>
</font></span></blockquote></div><br></div></div>