<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>