summaryrefslogtreecommitdiffstats
path: root/c/src/lib/libbsp
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-19 06:18:55 +0200
committerSebastian Huber <sebastian.huber@embedded-brains.de>2018-04-20 09:49:37 +0200
commitef7845482a3863fb1b4fd6d42408deb69f959d2e (patch)
tree65b38cbc566fcad2c02d27ee3eb0479d020544a7 /c/src/lib/libbsp
parentbsps: Move shared btimer support to bsps (diff)
downloadrtems-ef7845482a3863fb1b4fd6d42408deb69f959d2e.tar.bz2
bsps: Move gpio.c to bsps
This patch is a part of the BSP source reorganization. Update #3285.
Diffstat (limited to 'c/src/lib/libbsp')
-rw-r--r--c/src/lib/libbsp/arm/beagle/Makefile.am2
-rw-r--r--c/src/lib/libbsp/arm/raspberrypi/Makefile.am2
-rw-r--r--c/src/lib/libbsp/shared/gpio.c1980
3 files changed, 2 insertions, 1982 deletions
diff --git a/c/src/lib/libbsp/arm/beagle/Makefile.am b/c/src/lib/libbsp/arm/beagle/Makefile.am
index d9923d1248..889dbe5b41 100644
--- a/c/src/lib/libbsp/arm/beagle/Makefile.am
+++ b/c/src/lib/libbsp/arm/beagle/Makefile.am
@@ -43,7 +43,7 @@ librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspfatal-default.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/bspgetworkarea-default.c
librtemsbsp_a_SOURCES += ../../shared/sbrk.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/start/stackalloc.c
-librtemsbsp_a_SOURCES += ../../shared/gpio.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/gpio/gpio-support.c
librtemsbsp_a_SOURCES += ../../shared/cpucounterdiff.c
librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/btimer/btimer-stub.c
librtemsbsp_a_SOURCES += ../../shared/cpucounterread.c
diff --git a/c/src/lib/libbsp/arm/raspberrypi/Makefile.am b/c/src/lib/libbsp/arm/raspberrypi/Makefile.am
index eb5d6b8474..0c7587a544 100644
--- a/c/src/lib/libbsp/arm/raspberrypi/Makefile.am
+++ b/c/src/lib/libbsp/arm/raspberrypi/Makefile.am
@@ -88,7 +88,7 @@ librtemsbsp_a_SOURCES += clock/clockdrv.c
librtemsbsp_a_SOURCES += misc/timer.c
# GPIO
-librtemsbsp_a_SOURCES += ../../shared/gpio.c
+librtemsbsp_a_SOURCES += ../../../../../../bsps/shared/dev/gpio/gpio-support.c
librtemsbsp_a_SOURCES += gpio/rpi-gpio.c
# RTC
diff --git a/c/src/lib/libbsp/shared/gpio.c b/c/src/lib/libbsp/shared/gpio.c
deleted file mode 100644
index 9ceeb4070f..0000000000
--- a/c/src/lib/libbsp/shared/gpio.c
+++ /dev/null
@@ -1,1980 +0,0 @@
-/**
- * @file gpio.c
- *
- * @ingroup rtems_gpio
- *
- * @brief RTEMS GPIO API implementation.
- */
-
-/*
- * Copyright (c) 2014-2015 Andre Marques <andre.lousa.marques at gmail.com>
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rtems.org/license/LICENSE.
- */
-
-#include <rtems/score/atomic.h>
-#include <rtems/chain.h>
-#include <bsp/irq-generic.h>
-#include <bsp/gpio.h>
-#include <assert.h>
-#include <stdlib.h>
-
-/**
- * @brief GPIO API mutex attributes.
- */
-#define MUTEX_ATTRIBUTES ( \
- RTEMS_LOCAL \
- | RTEMS_PRIORITY \
- | RTEMS_BINARY_SEMAPHORE \
- | RTEMS_INHERIT_PRIORITY \
- | RTEMS_NO_PRIORITY_CEILING \
-)
-
-#define CREATE_LOCK(name, lock_id) rtems_semaphore_create( \
- name, \
- 1, \
- MUTEX_ATTRIBUTES, \
- 0, \
- lock_id \
-)
-
-#define ACQUIRE_LOCK(m) assert ( rtems_semaphore_obtain(m, \
- RTEMS_WAIT, \
- RTEMS_NO_TIMEOUT \
- ) == RTEMS_SUCCESSFUL )
-
-#define RELEASE_LOCK(m) assert ( rtems_semaphore_release(m) == RTEMS_SUCCESSFUL )
-
-/**
- * @brief Object containing relevant information about a GPIO group.
- *
- * Encapsulates relevant data for a GPIO pin group.
- */
-struct rtems_gpio_group
-{
- rtems_chain_node node;
-
- uint32_t *digital_inputs;
- uint32_t digital_input_bank;
- uint32_t input_count;
-
- uint32_t *digital_outputs;
- uint32_t digital_output_bank;
- uint32_t output_count;
-
- uint32_t *bsp_speficifc_pins;
- uint32_t bsp_specific_bank;
- uint32_t bsp_specific_pin_count;
-
- rtems_id group_lock;
-};
-
-/**
- * @brief Object containing relevant information to a list of user-defined
- * interrupt handlers.
- *
- * Encapsulates relevant data for a GPIO interrupt handler.
- */
-typedef struct
-{
- rtems_chain_node node;
-
- /* User-defined ISR routine. */
- rtems_gpio_irq_state (*handler) (void *arg);
-
- /* User-defined arguments for the ISR routine. */
- void *arg;
-} gpio_handler_node;
-
-/**
- * @brief Object containing relevant information of a pin's interrupt
- * configuration/state.
- *
- * Encapsulates relevant data of a GPIO pin interrupt state.
- */
-typedef struct
-{
- /* Currently active interrupt. */
- rtems_gpio_interrupt active_interrupt;
-
- /* ISR shared flag. */
- rtems_gpio_handler_flag handler_flag;
-
- /* Linked list of interrupt handlers. */
- rtems_chain_control handler_chain;
-
- /* Switch-deboucing information. */
- uint32_t debouncing_tick_count;
- rtems_interval last_isr_tick;
-} gpio_pin_interrupt_state;
-
-/**
- * @brief Object containing information on a GPIO pin.
- *
- * Encapsulates relevant data about a GPIO pin.
- */
-typedef struct
-{
- rtems_gpio_function pin_function;
-
- /* GPIO pull resistor configuration. */
- rtems_gpio_pull_mode resistor_mode;
-
- /* If true inverts digital in/out applicational logic. */
- bool logic_invert;
-
- /* True if the pin is on a group. */
- bool on_group;
-
- /* Interrupt data for a pin. This field is NULL if no interrupt is enabled
- * on the pin. */
- gpio_pin_interrupt_state *interrupt_state;
-} gpio_pin;
-
-/**
- * @brief Object containing relevant information regarding a GPIO bank state.
- *
- * Encapsulates relevant data for a GPIO bank.
- */
-typedef struct
-{
- uint32_t bank_number;
- uint32_t interrupt_counter;
- rtems_id lock;
-
- /* If TRUE the interrupts on the bank will be called
- * by a rtems interrupt server, otherwise they will be handled
- * in the normal ISR context. */
- bool threaded_interrupts;
-} gpio_bank;
-
-static gpio_pin gpio_pin_state[BSP_GPIO_PIN_COUNT];
-static Atomic_Flag init_flag = ATOMIC_INITIALIZER_FLAG;
-static gpio_bank gpio_bank_state[GPIO_BANK_COUNT];
-static Atomic_Uint threaded_interrupt_counter = ATOMIC_INITIALIZER_UINT(0);
-static rtems_chain_control gpio_group;
-
-#define BANK_NUMBER(pin_number) pin_number / BSP_GPIO_PINS_PER_BANK
-#define PIN_NUMBER(pin_number) pin_number % BSP_GPIO_PINS_PER_BANK
-
-static int debounce_switch(gpio_pin_interrupt_state *interrupt_state)
-{
- rtems_interval time;
-
- time = rtems_clock_get_ticks_since_boot();
-
- /* If not enough time has elapsed since last interrupt. */
- if (
- (time - interrupt_state->last_isr_tick) <
- interrupt_state->debouncing_tick_count
- ) {
- return -1;
- }
-
- interrupt_state->last_isr_tick = time;
-
- return 0;
-}
-
-/* Returns the amount of pins in a bank. */
-static uint32_t get_bank_pin_count(uint32_t bank)
-{
- /* If the current bank is the last bank, which may not be completely filled. */
- if ( bank == GPIO_BANK_COUNT - 1 ) {
- return GPIO_LAST_BANK_PINS;
- }
-
- return BSP_GPIO_PINS_PER_BANK;
-}
-
-/* GPIO generic bank ISR. This may be called directly as response to an
- * interrupt, or by the rtems interrupt server task if the GPIO bank
- * uses threading interrupt handling. */
-static void generic_bank_isr(void *arg)
-{
- gpio_pin_interrupt_state *interrupt_state;
- rtems_chain_control *handler_list;
- rtems_chain_node *node;
- rtems_chain_node *next_node;
- gpio_handler_node *isr_node;
- rtems_vector_number vector;
- uint32_t event_status;
- uint32_t bank_number;
- uint32_t bank_start_pin;
- uint8_t handled_count;
- uint8_t rv;
- uint8_t i;
-
- bank_number = *((uint32_t*) arg);
-
- assert ( bank_number >= 0 && bank_number < GPIO_BANK_COUNT );
-
- /* Calculate bank start address in the pin_state array. */
- bank_start_pin = bank_number * BSP_GPIO_PINS_PER_BANK;
-
- vector = rtems_gpio_bsp_get_vector(bank_number);
-
- /* If this bank does not use threaded interrupts we have to
- * disable the vector. Otherwise the interrupt server does it. */
- if ( gpio_bank_state[bank_number].threaded_interrupts == false ) {
- /* Prevents more interrupts from being generated on GPIO. */
- bsp_interrupt_vector_disable(vector);
- }
-
- /* Obtains a 32-bit bitmask, with the pins currently reporting interrupts
- * signaled with 1. */
- event_status = rtems_gpio_bsp_interrupt_line(vector);
-
- /* Iterates through the bitmask and calls the corresponding handler
- * for active interrupts. */
- for ( i = 0; i < get_bank_pin_count(bank_number); ++i ) {
- /* If active, wake the corresponding pin's ISR task. */
- if ( event_status & (1 << i) ) {
- interrupt_state = gpio_pin_state[bank_start_pin + i].interrupt_state;
-
- assert ( interrupt_state != NULL );
-
- handled_count = 0;
-
- if ( gpio_bank_state[bank_number].threaded_interrupts ) {
- ACQUIRE_LOCK(gpio_bank_state[bank_number].lock);
- }
-
- /* If this pin has the debouncing function attached, call it. */
- if ( interrupt_state->debouncing_tick_count > 0 ) {
- rv = debounce_switch(interrupt_state);
-
- /* If the handler call was caused by a switch bounce,
- * ignores and move on. */
- if ( rv < 0 ) {
- if ( gpio_bank_state[bank_number].threaded_interrupts ) {
- RELEASE_LOCK(gpio_bank_state[bank_number].lock);
- }
-
- continue;
- }
- }
-
- handler_list = &interrupt_state->handler_chain;
-
- node = rtems_chain_first(handler_list);
-
- /* Iterate the ISR list. */
- while ( !rtems_chain_is_tail(handler_list, node) ) {
- isr_node = (gpio_handler_node *) node;
-
- next_node = node->next;
-
- if ( (isr_node->handler)(isr_node->arg) == IRQ_HANDLED ) {
- ++handled_count;
- }
-
- node = next_node;
- }
-
- /* If no handler assumed the interrupt,
- * treat it as a spurious interrupt. */
- if ( handled_count == 0 ) {
- bsp_interrupt_handler_default(rtems_gpio_bsp_get_vector(bank_number));
- }
-
- if ( gpio_bank_state[bank_number].threaded_interrupts ) {
- RELEASE_LOCK(gpio_bank_state[bank_number].lock);
- }
- }
- }
-
- if ( gpio_bank_state[bank_number].threaded_interrupts == false ) {
- bsp_interrupt_vector_enable(vector);
- }
-}
-
-/* Verifies if all pins in the received pin array are from the same bank and
- * have the defined GPIO function. Produces bitmask of the received pins. */
-static rtems_status_code get_pin_bitmask(
- uint32_t *pins,
- uint32_t pin_count,
- uint32_t *bank_number,
- uint32_t *bitmask,
- rtems_gpio_function function
-) {
- uint32_t pin_number;
- uint32_t bank;
- uint8_t i;
-
- if ( pin_count < 1 ) {
- return RTEMS_UNSATISFIED;
- }
-
- *bitmask = 0;
-
- for ( i = 0; i < pin_count; ++i ) {
- pin_number = pins[i];
-
- if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
- return RTEMS_INVALID_ID;
- }
-
- bank = BANK_NUMBER(pin_number);
-
- if ( i == 0 ) {
- *bank_number = bank;
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
- }
- else if ( bank != *bank_number ) {
- RELEASE_LOCK(gpio_bank_state[*bank_number].lock);
-
- return RTEMS_UNSATISFIED;
- }
-
- if (
- gpio_pin_state[pin_number].pin_function != function ||
- gpio_pin_state[pin_number].on_group
- ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_NOT_CONFIGURED;
- }
-
- *bitmask |= (1 << PIN_NUMBER(pin_number));
- }
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_SUCCESSFUL;
-}
-
-static rtems_status_code check_same_bank_and_availability(
- const rtems_gpio_pin_conf *pin_confs,
- uint32_t pin_count,
- uint32_t *bank_number,
- uint32_t *pins
-) {
- uint32_t pin_number;
- uint32_t bank;
- uint8_t i;
-
- for ( i = 0; i < pin_count; ++i ) {
- pin_number = pin_confs[i].pin_number;
-
- bank = BANK_NUMBER(pin_number);
-
- if ( i == 0 ) {
- *bank_number = bank;
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
- }
- else if ( bank != *bank_number ) {
- RELEASE_LOCK(gpio_bank_state[*bank_number].lock);
-
- return RTEMS_UNSATISFIED;
- }
-
- if ( gpio_pin_state[pin_number].pin_function != NOT_USED ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_RESOURCE_IN_USE;
- }
-
- pins[i] = PIN_NUMBER(pin_number);
- }
-
- RELEASE_LOCK(gpio_bank_state[*bank_number].lock);
-
- return RTEMS_SUCCESSFUL;
-}
-
-static rtems_status_code setup_resistor_and_interrupt_configuration(
- uint32_t pin_number,
- rtems_gpio_pull_mode pull_mode,
- rtems_gpio_interrupt_configuration *interrupt_conf
-) {
- gpio_pin_interrupt_state *interrupt_state;
- rtems_status_code sc;
- uint32_t bank;
-
- sc = rtems_gpio_resistor_mode(pin_number, pull_mode);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
-#if defined(DEBUG)
- printk("rtems_gpio_resistor_mode failed with status code %d\n", sc);
-#endif
-
- return RTEMS_UNSATISFIED;
- }
-
- if ( interrupt_conf != NULL ) {
- bank = BANK_NUMBER(pin_number);
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- sc = rtems_gpio_enable_interrupt(
- pin_number,
- interrupt_conf->active_interrupt,
- interrupt_conf->handler_flag,
- interrupt_conf->threaded_interrupts,
- interrupt_conf->handler,
- interrupt_conf->arg
- );
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
-#if defined(DEBUG)
- printk(
- "rtems_gpio_enable_interrupt failed with status code %d\n",
- sc
- );
-#endif
-
- return RTEMS_UNSATISFIED;
- }
-
- interrupt_state = gpio_pin_state[pin_number].interrupt_state;
-
- interrupt_state->debouncing_tick_count =
- interrupt_conf->debounce_clock_tick_interval;
-
- interrupt_state->last_isr_tick = 0;
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
- }
-
- return RTEMS_SUCCESSFUL;
-}
-
-static rtems_status_code gpio_multi_select(
- const rtems_gpio_pin_conf *pins,
- uint8_t pin_count,
- bool on_group
-) {
- rtems_status_code sc;
- uint32_t pin_number;
- uint32_t bank;
- uint8_t i;
-
- /* If the BSP has multi select capabilities. */
-#ifdef BSP_GPIO_PINS_PER_SELECT_BANK
- rtems_gpio_multiple_pin_select
- pin_data[GPIO_SELECT_BANK_COUNT][BSP_GPIO_PINS_PER_SELECT_BANK];
- rtems_gpio_specific_data *bsp_data;
-
- /* Since each platform may have more than two functions to assign to a pin,
- * each pin requires more than one bit in the selection register to
- * properly assign a function to it.
- * Therefore a selection bank (pin selection register) will support fewer pins
- * than a regular bank, meaning that there will be more selection banks than
- * regular banks, which have to be handled separately.
- *
- * This field records the select bank number relative to the GPIO bank. */
- uint32_t select_bank;
- uint32_t bank_number;
- uint32_t select_bank_counter[GPIO_SELECT_BANK_COUNT];
- uint32_t select_count;
- uint32_t pin;
-
- if ( pin_count == 0 ) {
- return RTEMS_SUCCESSFUL;
- }
-
- for ( i = 0; i < GPIO_SELECT_BANK_COUNT; ++i ) {
- select_bank_counter[i] = 0;
- }
-
- for ( i = 0; i < pin_count; ++i ) {
- pin_number = pins[i].pin_number;
-
- if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
- return RTEMS_INVALID_ID;
- }
-
- bank = BANK_NUMBER(pin_number);
- pin = PIN_NUMBER(pin_number);
-
- if ( i == 0 ) {
- bank_number = bank;
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
- }
- else if ( bank != bank_number ) {
- RELEASE_LOCK(gpio_bank_state[bank_number].lock);
-
- return RTEMS_UNSATISFIED;
- }
-
- /* If the pin is already being used returns with an error. */
- if ( gpio_pin_state[pin_number].pin_function != NOT_USED ) {
- RELEASE_LOCK(gpio_bank_state[bank_number].lock);
-
- return RTEMS_RESOURCE_IN_USE;
- }
-
- select_bank = (pin_number / BSP_GPIO_PINS_PER_SELECT_BANK) -
- (bank * GPIO_SELECT_BANK_COUNT);
-
- select_count = select_bank_counter[select_bank];
-
- pin_data[select_bank][select_count].pin_number = pin_number;
- pin_data[select_bank][select_count].function = pins[i].function;
-
- if ( pins[i].function == BSP_SPECIFIC ) {
- bsp_data = (rtems_gpio_specific_data *) pins[i].bsp_specific;
-
- if ( bsp_data == NULL ) {
- RELEASE_LOCK(gpio_bank_state[bank_number].lock);
-
- return RTEMS_UNSATISFIED;
- }
-
- pin_data[select_bank][select_count].io_function = bsp_data->io_function;
- pin_data[select_bank][select_count].bsp_specific = bsp_data->pin_data;
- }
- else {
- /* io_function takes a dummy value, as it will not be used. */
- pin_data[select_bank][select_count].io_function = 0;
- pin_data[select_bank][select_count].bsp_specific = pins[i].bsp_specific;
- }
-
- ++select_bank_counter[select_bank];
- }
-
- for ( i = 0; i < GPIO_SELECT_BANK_COUNT; ++i ) {
- if ( select_bank_counter[i] == 0 ) {
- continue;
- }
-
- sc = rtems_gpio_bsp_multi_select(
- pin_data[i], select_bank_counter[i], i +
- (bank_number * GPIO_SELECT_BANK_COUNT)
- );
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(gpio_bank_state[bank_number].lock);
-
- return sc;
- }
- }
-
- for ( i = 0; i < pin_count; ++i ) {
- pin_number = pins[i].pin_number;
-
- /* Fill other pin state information. */
- gpio_pin_state[pin_number].pin_function = pins[i].function;
- gpio_pin_state[pin_number].logic_invert = pins[i].logic_invert;
- gpio_pin_state[pin_number].on_group = on_group;
-
- sc = setup_resistor_and_interrupt_configuration(
- pin_number,
- pins[i].pull_mode,
- pins[i].interrupt
- );
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(gpio_bank_state[bank_number].lock);
-
- return sc;
- }
-
- bank = BANK_NUMBER(pin_number);
- pin = PIN_NUMBER(pin_number);
-
- if ( pins[i].function == DIGITAL_OUTPUT ) {
- if ( pins[i].output_enabled == true ) {
- sc = rtems_gpio_bsp_set(bank, pin);
- }
- else {
- sc = rtems_gpio_bsp_clear(bank, pin);
- }
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(gpio_bank_state[bank_number].lock);
-
- return sc;
- }
- }
- }
-
- RELEASE_LOCK(gpio_bank_state[bank_number].lock);
-
- return sc;
-
- /* If the BSP does not provide pin multi-selection,
- * configures each pin sequentially. */
-#else
- for ( i = 0; i < pin_count; ++i ) {
- pin_number = pins[i].pin_number;
-
- if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
- return RTEMS_INVALID_ID;
- }
-
- bank = BANK_NUMBER(pin_number);
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- /* If the pin is already being used returns with an error. */
- if ( gpio_pin_state[pin_number].pin_function != NOT_USED ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_RESOURCE_IN_USE;
- }
- }
-
- for ( i = 0; i < pin_count; ++i ) {
- sc = rtems_gpio_request_configuration(&pins[i]);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- return sc;
- }
-
- gpio_pin_state[pins[i].pin_number].on_group = on_group;
- }
-
- return RTEMS_SUCCESSFUL;
-#endif
-}
-
-rtems_status_code rtems_gpio_initialize(void)
-{
- rtems_status_code sc;
- uint32_t i;
-
- if ( _Atomic_Flag_test_and_set(&init_flag, ATOMIC_ORDER_RELAXED) == true ) {
- return RTEMS_SUCCESSFUL;
- }
-
- for ( i = 0; i < GPIO_BANK_COUNT; ++i ) {
- sc = CREATE_LOCK(
- rtems_build_name('G', 'I', 'N', 'T'),
- &gpio_bank_state[i].lock
- );
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- return sc;
- }
-
- gpio_bank_state[i].bank_number = i;
- gpio_bank_state[i].interrupt_counter = 0;
-
- /* The threaded_interrupts field is initialized during
- * rtems_gpio_enable_interrupt(), as its value is never used before. */
- }
-
- for ( i = 0; i < BSP_GPIO_PIN_COUNT; ++i ) {
- gpio_pin_state[i].pin_function = NOT_USED;
- gpio_pin_state[i].resistor_mode = NO_PULL_RESISTOR;
- gpio_pin_state[i].logic_invert = false;
- gpio_pin_state[i].on_group = false;
- gpio_pin_state[i].interrupt_state = NULL;
- }
-
- /* Initialize GPIO groups chain. */
- rtems_chain_initialize_empty(&gpio_group);
-
- return RTEMS_SUCCESSFUL;
-}
-
-rtems_gpio_group *rtems_gpio_create_pin_group(void)
-{
- struct rtems_gpio_group *group;
-
- group = (struct rtems_gpio_group *) malloc(sizeof(struct rtems_gpio_group));
-
- return group;
-}
-
-rtems_status_code rtems_gpio_define_pin_group(
- const rtems_gpio_group_definition *group_definition,
- rtems_gpio_group *group
-) {
- rtems_status_code sc;
-
- if ( group_definition == NULL || group == NULL ) {
- return RTEMS_UNSATISFIED;
- }
-
- if (
- group_definition->input_count == 0 &&
- group_definition->output_count == 0 &&
- group_definition->bsp_specific_pin_count == 0
- ) {
- return RTEMS_UNSATISFIED;
- }
-
- group->input_count = group_definition->input_count;
-
- if ( group->input_count > 0 ) {
- group->digital_inputs =
- (uint32_t *) malloc(group->input_count * sizeof(uint32_t));
-
- /* Evaluate if the pins that will constitute the group are available and
- * that pins with the same function within the group all belong
- * to the same pin group. */
- sc = check_same_bank_and_availability(
- group_definition->digital_inputs,
- group->input_count,
- &group->digital_input_bank,
- group->digital_inputs
- );
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- return sc;
- }
- }
- else {
- group->digital_inputs = NULL;
- }
-
- group->output_count = group_definition->output_count;
-
- if ( group->output_count > 0 ) {
- group->digital_outputs =
- (uint32_t *) malloc(group->output_count * sizeof(uint32_t));
-
- sc = check_same_bank_and_availability(
- group_definition->digital_outputs,
- group->output_count,
- &group->digital_output_bank,
- group->digital_outputs
- );
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- return sc;
- }
- }
- else {
- group->digital_outputs = NULL;
- }
-
- group->bsp_specific_pin_count = group_definition->bsp_specific_pin_count;
-
- if ( group->bsp_specific_pin_count > 0 ) {
- group->bsp_speficifc_pins =
- (uint32_t *) malloc(
- group->bsp_specific_pin_count *
- sizeof(uint32_t)
- );
-
- sc = check_same_bank_and_availability(
- group_definition->bsp_specifics,
- group->bsp_specific_pin_count,
- &group->bsp_specific_bank,
- group->bsp_speficifc_pins
- );
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- return sc;
- }
- }
- else {
- group->bsp_speficifc_pins = NULL;
- }
-
- /* Request the pins. */
- sc = gpio_multi_select(
- group_definition->digital_inputs,
- group_definition->input_count,
- true
- );
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- return RTEMS_UNSATISFIED;
- }
-
- sc = gpio_multi_select(
- group_definition->digital_outputs,
- group_definition->output_count,
- true
- );
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- sc = rtems_gpio_release_multiple_pins(
- group_definition->digital_inputs,
- group_definition->input_count
- );
-
- assert ( sc == RTEMS_SUCCESSFUL );
-
- return RTEMS_UNSATISFIED;
- }
-
- sc = gpio_multi_select(
- group_definition->bsp_specifics,
- group_definition->bsp_specific_pin_count,
- true
- );
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- sc = rtems_gpio_release_multiple_pins(
- group_definition->digital_inputs,
- group_definition->input_count
- );
-
- assert ( sc == RTEMS_SUCCESSFUL );
-
- sc = rtems_gpio_release_multiple_pins(
- group_definition->digital_outputs,
- group_definition->output_count
- );
-
- assert ( sc == RTEMS_SUCCESSFUL );
-
- return RTEMS_UNSATISFIED;
- }
-
- /* Create group lock. */
- sc = CREATE_LOCK(rtems_build_name('G', 'R', 'P', 'L'), &group->group_lock);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- return sc;
- }
-
- rtems_chain_append(&gpio_group, &group->node);
-
- return RTEMS_SUCCESSFUL;
-}
-
-rtems_status_code rtems_gpio_write_group(uint32_t data, rtems_gpio_group *group)
-{
- rtems_status_code sc = RTEMS_SUCCESSFUL;
- uint32_t set_bitmask;
- uint32_t clear_bitmask;
- uint32_t bank;
- uint32_t pin;
- uint8_t i;
-
- if ( group->output_count == 0 ) {
- return RTEMS_NOT_DEFINED;
- }
-
- bank = group->digital_output_bank;
-
- /* Acquire bank lock for the digital output pins. */
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- /* Acquire group lock. */
- ACQUIRE_LOCK(group->group_lock);
-
- set_bitmask = 0;
- clear_bitmask = 0;
-
- for ( i = 0; i < group->output_count; ++i ) {
- pin = group->digital_outputs[i];
-
- if ( (data & (1 << i)) == 0 ) {
- clear_bitmask |= (1 << pin);
- }
- else {
- set_bitmask |= (1 << pin);
- }
- }
-
- /* Set the logical highs. */
- if ( set_bitmask > 0 ) {
- sc = rtems_gpio_bsp_multi_set(bank, set_bitmask);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(group->group_lock);
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return sc;
- }
- }
-
- /* Set the logical lows. */
- if ( clear_bitmask > 0 ) {
- sc = rtems_gpio_bsp_multi_clear(bank, clear_bitmask);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(group->group_lock);
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return sc;
- }
- }
-
- RELEASE_LOCK(group->group_lock);
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_SUCCESSFUL;
-}
-
-uint32_t rtems_gpio_read_group(rtems_gpio_group *group)
-{
- uint32_t read_bitmask;
- uint32_t bank;
- uint32_t pin;
- uint32_t rv;
- uint8_t i;
-
- if ( group->input_count == 0 ) {
- return GPIO_INPUT_ERROR;
- }
-
- bank = group->digital_input_bank;
-
- /* Acquire bank lock for the digital input pins. */
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- /* Acquire group lock. */
- ACQUIRE_LOCK(group->group_lock);
-
- read_bitmask = 0;
-
- for ( i = 0; i < group->input_count; ++i ) {
- pin = group->digital_inputs[i];
-
- read_bitmask |= (1 << pin);
- }
-
- rv = rtems_gpio_bsp_multi_read(bank, read_bitmask);
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
- RELEASE_LOCK(group->group_lock);
-
- return rv;
-}
-
-rtems_status_code rtems_gpio_group_bsp_specific_operation(
- rtems_gpio_group *group,
- void *arg
-) {
- rtems_status_code sc;
- uint32_t bank;
-
- if ( group->bsp_specific_pin_count == 0 ) {
- return RTEMS_NOT_DEFINED;
- }
-
- bank = group->bsp_specific_bank;
-
- /* Acquire bank lock for the BSP specific function pins. */
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- /* Acquire group lock. */
- ACQUIRE_LOCK(group->group_lock);
-
- sc = rtems_gpio_bsp_specific_group_operation(
- bank,
- group->bsp_speficifc_pins,
- group->bsp_specific_pin_count,
- arg
- );
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
- RELEASE_LOCK(group->group_lock);
-
- return sc;
-}
-
-rtems_status_code rtems_gpio_multi_select(
- const rtems_gpio_pin_conf *pins,
- uint8_t pin_count
-) {
- return gpio_multi_select(pins, pin_count, false);
-}
-
-rtems_status_code rtems_gpio_request_configuration(
- const rtems_gpio_pin_conf *conf
-) {
- rtems_status_code sc;
-
- sc = rtems_gpio_request_pin(
- conf->pin_number,
- conf->function,
- conf->output_enabled,
- conf->logic_invert,
- conf->bsp_specific
- );
-
- if ( sc != RTEMS_SUCCESSFUL ) {
-#if defined(DEBUG)
- printk("rtems_gpio_request_pin failed with status code %d\n",sc);
-#endif
-
- return RTEMS_UNSATISFIED;
- }
-
- return setup_resistor_and_interrupt_configuration(
- conf->pin_number,
- conf->pull_mode,
- conf->interrupt
- );
-}
-
-rtems_status_code rtems_gpio_update_configuration(
- const rtems_gpio_pin_conf *conf
-) {
- rtems_gpio_interrupt_configuration *interrupt_conf;
- gpio_pin_interrupt_state *interrupt_state;
- rtems_status_code sc;
- uint32_t bank;
-
- if ( conf->pin_number < 0 || conf->pin_number >= BSP_GPIO_PIN_COUNT ) {
- return RTEMS_INVALID_ID;
- }
-
- bank = BANK_NUMBER(conf->pin_number);
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- /* If the pin is not being used returns with an error. */
- if ( gpio_pin_state[conf->pin_number].pin_function == NOT_USED ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_NOT_CONFIGURED;
- }
-
- sc = rtems_gpio_resistor_mode(conf->pin_number, conf->pull_mode);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
-#if defined(DEBUG)
- printk("rtems_gpio_resistor_mode failed with status code %d\n", sc);
-#endif
-
- return RTEMS_UNSATISFIED;
- }
-
- interrupt_conf = (rtems_gpio_interrupt_configuration *) conf->interrupt;
-
- interrupt_state = gpio_pin_state[conf->pin_number].interrupt_state;
-
- if ( interrupt_state != NULL ) {
- sc = rtems_gpio_disable_interrupt(conf->pin_number);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
-#if defined(DEBUG)
- printk(
- "rtems_gpio_disable_interrupt failed with status code %d\n",
- sc
- );
-#endif
-
- return RTEMS_UNSATISFIED;
- }
- }
-
- if ( interrupt_conf != NULL ) {
- sc = rtems_gpio_enable_interrupt(
- conf->pin_number,
- interrupt_conf->active_interrupt,
- interrupt_conf->handler_flag,
- interrupt_conf->threaded_interrupts,
- interrupt_conf->handler,
- interrupt_conf->arg
- );
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
-#if defined(DEBUG)
- printk(
- "rtems_gpio_enable_interrupt failed with status code %d\n",
- sc
- );
-#endif
-
- return RTEMS_UNSATISFIED;
- }
- }
-
- if ( interrupt_conf != NULL && interrupt_state != NULL ) {
- if (
- interrupt_conf->debounce_clock_tick_interval !=
- interrupt_state->debouncing_tick_count
- ) {
- interrupt_state->debouncing_tick_count =
- interrupt_conf->debounce_clock_tick_interval;
-
- interrupt_state->last_isr_tick = 0;
- }
- }
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_SUCCESSFUL;
-}
-
-rtems_status_code rtems_gpio_multi_set(
- uint32_t *pin_numbers,
- uint32_t pin_count
-) {
- rtems_status_code sc;
- uint32_t bitmask;
- uint32_t bank;
-
- sc = get_pin_bitmask(pin_numbers, pin_count, &bank, &bitmask, DIGITAL_OUTPUT);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- return sc;
- }
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- sc = rtems_gpio_bsp_multi_set(bank, bitmask);
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return sc;
-}
-
-rtems_status_code rtems_gpio_multi_clear(
- uint32_t *pin_numbers,
- uint32_t pin_count
-) {
- rtems_status_code sc;
- uint32_t bitmask;
- uint32_t bank;
-
- sc = get_pin_bitmask(pin_numbers, pin_count, &bank, &bitmask, DIGITAL_OUTPUT);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- return sc;
- }
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- sc = rtems_gpio_bsp_multi_clear(bank, bitmask);
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return sc;
-}
-
-uint32_t rtems_gpio_multi_read(
- uint32_t *pin_numbers,
- uint32_t pin_count
-) {
- rtems_status_code sc;
- uint32_t bitmask;
- uint32_t bank;
- uint32_t rv;
-
- sc = get_pin_bitmask(pin_numbers, pin_count, &bank, &bitmask, DIGITAL_INPUT);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- return GPIO_INPUT_ERROR;
- }
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- rv = rtems_gpio_bsp_multi_read(bank, bitmask);
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return rv;
-}
-
-rtems_status_code rtems_gpio_set(uint32_t pin_number)
-{
- rtems_status_code sc;
- uint32_t bank;
- uint32_t pin;
-
- if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
- return RTEMS_INVALID_ID;
- }
-
- bank = BANK_NUMBER(pin_number);
- pin = PIN_NUMBER(pin_number);
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- if (
- gpio_pin_state[pin_number].pin_function != DIGITAL_OUTPUT ||
- gpio_pin_state[pin_number].on_group
- ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
-#if defined(DEBUG)
- printk("Can only set digital output pins\n");
-#endif
-
- return RTEMS_NOT_CONFIGURED;
- }
-
- if ( gpio_pin_state[pin_number].logic_invert ) {
- sc = rtems_gpio_bsp_clear(bank, pin);
- }
- else {
- sc = rtems_gpio_bsp_set(bank, pin);
- }
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return sc;
-}
-
-rtems_status_code rtems_gpio_clear(uint32_t pin_number)
-{
- rtems_status_code sc;
- uint32_t bank;
- uint32_t pin;
-
- if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
- return RTEMS_INVALID_ID;
- }
-
- bank = BANK_NUMBER(pin_number);
- pin = PIN_NUMBER(pin_number);
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- if (
- gpio_pin_state[pin_number].pin_function != DIGITAL_OUTPUT ||
- gpio_pin_state[pin_number].on_group
- ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
-#if defined(DEBUG)
- printk("Can only clear digital output pins\n");
-#endif
-
- return RTEMS_NOT_CONFIGURED;
- }
-
- if ( gpio_pin_state[pin_number].logic_invert ) {
- sc = rtems_gpio_bsp_set(bank, pin);
- }
- else {
- sc = rtems_gpio_bsp_clear(bank, pin);
- }
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return sc;
-}
-
-int rtems_gpio_get_value(uint32_t pin_number)
-{
- uint32_t bank;
- uint32_t pin;
- uint32_t rv;
-
- if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
- return -1;
- }
-
- bank = BANK_NUMBER(pin_number);
- pin = PIN_NUMBER(pin_number);
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- if (
- gpio_pin_state[pin_number].pin_function != DIGITAL_INPUT ||
- gpio_pin_state[pin_number].on_group
- ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
-#if defined(DEBUG)
- printk("Can only read digital input pins\n");
-#endif
-
- return -1;
- }
-
- rv = rtems_gpio_bsp_get_value(bank, pin);
-
- if ( rv == GPIO_INPUT_ERROR ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return -1;
- }
-
- if ( gpio_pin_state[pin_number].logic_invert ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return !rv;
- }
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return rv > 0;
-}
-
-rtems_status_code rtems_gpio_request_pin(
- uint32_t pin_number,
- rtems_gpio_function function,
- bool output_enabled,
- bool logic_invert,
- void *bsp_specific
-) {
- rtems_gpio_specific_data *bsp_data;
- rtems_status_code sc = RTEMS_SUCCESSFUL;
- uint32_t bank;
- uint32_t pin;
-
- if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
- return RTEMS_INVALID_ID;
- }
-
- bank = BANK_NUMBER(pin_number);
- pin = PIN_NUMBER(pin_number);
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- /* If the pin is already being used returns with an error. */
- if ( gpio_pin_state[pin_number].pin_function != NOT_USED ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_RESOURCE_IN_USE;
- }
-
- switch ( function ) {
- case DIGITAL_INPUT:
- sc = rtems_gpio_bsp_select_input(bank, pin, bsp_specific);
- break;
- case DIGITAL_OUTPUT:
- sc = rtems_gpio_bsp_select_output(bank, pin, bsp_specific);
- break;
- case BSP_SPECIFIC:
- bsp_data = (rtems_gpio_specific_data *) bsp_specific;
-
- if ( bsp_data == NULL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_UNSATISFIED;
- }
-
- sc = rtems_gpio_bsp_select_specific_io(
- bank,
- pin,
- bsp_data->io_function,
- bsp_data->pin_data
- );
- break;
- case NOT_USED:
- default:
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_NOT_DEFINED;
- }
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return sc;
- }
-
- /* If the function was successfully assigned to the pin,
- * record that information on the gpio_pin_state structure. */
- gpio_pin_state[pin_number].pin_function = function;
- gpio_pin_state[pin_number].logic_invert = logic_invert;
-
- if ( function == DIGITAL_OUTPUT ) {
- if ( output_enabled == true ) {
- sc = rtems_gpio_bsp_set(bank, pin);
- }
- else {
- sc = rtems_gpio_bsp_clear(bank, pin);
- }
- }
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return sc;
-}
-
-rtems_status_code rtems_gpio_resistor_mode(
- uint32_t pin_number,
- rtems_gpio_pull_mode mode
-) {
- rtems_status_code sc;
- uint32_t bank;
- uint32_t pin;
-
- if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
- return RTEMS_INVALID_ID;
- }
-
- bank = BANK_NUMBER(pin_number);
- pin = PIN_NUMBER(pin_number);
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- /* If the desired actuation mode is already set, silently exits.
- * The NO_PULL_RESISTOR is a special case, as some platforms have
- * pull-up resistors enabled on startup, so this state may have to
- * be reinforced in the hardware. */
- if (
- gpio_pin_state[pin_number].resistor_mode == mode &&
- mode != NO_PULL_RESISTOR
- ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_SUCCESSFUL;
- }
-
- sc = rtems_gpio_bsp_set_resistor_mode(bank, pin, mode);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return sc;
- }
-
- gpio_pin_state[pin_number].resistor_mode = mode;
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_SUCCESSFUL;
-}
-
-rtems_status_code rtems_gpio_release_pin(uint32_t pin_number)
-{
- gpio_pin_interrupt_state *interrupt_state;
- rtems_status_code sc;
- uint32_t bank;
-
- if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
- return RTEMS_INVALID_ID;
- }
-
- bank = BANK_NUMBER(pin_number);
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- interrupt_state = gpio_pin_state[pin_number].interrupt_state;
-
- /* If the pin has an enabled interrupt then remove the handler(s)
- * and disable interrupts on that pin. */
- if ( interrupt_state != NULL ) {
- sc = rtems_gpio_disable_interrupt(pin_number);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return sc;
- }
- }
-
- gpio_pin_state[pin_number].pin_function = NOT_USED;
- gpio_pin_state[pin_number].resistor_mode = NO_PULL_RESISTOR;
- gpio_pin_state[pin_number].logic_invert = false;
- gpio_pin_state[pin_number].on_group = false;
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_SUCCESSFUL;
-}
-
-rtems_status_code rtems_gpio_release_configuration(
- const rtems_gpio_pin_conf *conf
-) {
- if ( conf == NULL ) {
- return RTEMS_UNSATISFIED;
- }
-
- return rtems_gpio_release_pin(conf->pin_number);
-}
-
-rtems_status_code rtems_gpio_release_multiple_pins(
- const rtems_gpio_pin_conf *pins,
- uint32_t pin_count
-) {
- rtems_status_code sc;
- uint32_t i;
-
- if ( pins == NULL ) {
- return RTEMS_UNSATISFIED;
- }
-
- for ( i = 0; i < pin_count; ++i ) {
- sc = rtems_gpio_release_pin(pins[i].pin_number);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- return sc;
- }
- }
-
- return RTEMS_SUCCESSFUL;
-}
-
-rtems_status_code rtems_gpio_release_pin_group(
- rtems_gpio_group *group
-) {
- rtems_status_code sc;
- uint8_t i;
-
- ACQUIRE_LOCK(group->group_lock);
-
- sc = rtems_semaphore_flush(group->group_lock);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(group->group_lock);
-
- return sc;
- }
-
- RELEASE_LOCK(group->group_lock);
-
- /* Deletes the group lock. */
- sc = rtems_semaphore_delete(group->group_lock);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- return sc;
- }
-
- /* Pin releasing. */
- for ( i = 0; i < group->input_count; ++i ) {
- sc = rtems_gpio_release_pin(group->digital_inputs[i]);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- return sc;
- }
- }
-
- if ( group->input_count > 0 ) {
- free(group->digital_inputs);
- }
-
- for ( i = 0; i < group->output_count; ++i ) {
- sc = rtems_gpio_release_pin(group->digital_outputs[i]);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- return sc;
- }
- }
-
- if ( group->output_count > 0 ) {
- free(group->digital_outputs);
- }
-
- for ( i = 0; i < group->bsp_specific_pin_count; ++i ) {
- sc = rtems_gpio_release_pin(group->bsp_speficifc_pins[i]);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- return sc;
- }
- }
-
- if ( group->bsp_specific_pin_count > 0 ) {
- free(group->bsp_speficifc_pins);
- }
-
- rtems_chain_extract(&group->node);
-
- free(group);
-
- return RTEMS_SUCCESSFUL;
-}
-
-rtems_status_code rtems_gpio_debounce_switch(uint32_t pin_number, int ticks)
-{
- gpio_pin_interrupt_state *interrupt_state;
- uint32_t bank;
-
- if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
- return RTEMS_INVALID_ID;
- }
-
- bank = BANK_NUMBER(pin_number);
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- interrupt_state = gpio_pin_state[pin_number].interrupt_state;
-
- /* If no interrupt configuration is set for this pin, or if the pin is
- * not set as a digital input, or the pin in on a group. */
- if (
- interrupt_state == NULL ||
- gpio_pin_state[pin_number].pin_function != DIGITAL_INPUT ||
- gpio_pin_state[pin_number].on_group
- ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_NOT_CONFIGURED;
- }
-
- interrupt_state->debouncing_tick_count = ticks;
- interrupt_state->last_isr_tick = 0;
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_SUCCESSFUL;
-}
-
-rtems_status_code rtems_gpio_interrupt_handler_install(
- uint32_t pin_number,
- rtems_gpio_irq_state (*handler) (void *arg),
- void *arg
-) {
- gpio_pin_interrupt_state *interrupt_state;
- gpio_handler_node *isr_node;
- uint32_t bank;
-
- if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
- return RTEMS_INVALID_ID;
- }
-
- bank = BANK_NUMBER(pin_number);
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- interrupt_state = gpio_pin_state[pin_number].interrupt_state;
-
- /* If no interrupt configuration is set for this pin. */
- if ( interrupt_state == NULL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_NOT_CONFIGURED;
- }
-
- /* If the current pin has no interrupt enabled
- * then it does not need an handler. */
- if ( interrupt_state->active_interrupt == NONE ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_NOT_CONFIGURED;
- }
- /* If the pin already has an enabled interrupt but the installed handler
- * is set as unique. */
- else if (
- interrupt_state->handler_flag == UNIQUE_HANDLER &&
- !rtems_chain_is_empty(&interrupt_state->handler_chain)
- ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_TOO_MANY;
- }
-
- /* Update the pin's ISR list. */
- isr_node = (gpio_handler_node *) malloc(sizeof(gpio_handler_node));
-
- if ( isr_node == NULL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_NO_MEMORY;
- }
-
- isr_node->handler = handler;
- isr_node->arg = arg;
-
- rtems_chain_append(&interrupt_state->handler_chain, &isr_node->node);
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_SUCCESSFUL;
-}
-
-rtems_status_code rtems_gpio_enable_interrupt(
- uint32_t pin_number,
- rtems_gpio_interrupt interrupt,
- rtems_gpio_handler_flag flag,
- bool threaded_handling,
- rtems_gpio_irq_state (*handler) (void *arg),
- void *arg
-) {
- gpio_pin_interrupt_state *interrupt_state;
- rtems_vector_number vector;
- rtems_status_code sc;
- uint32_t bank;
- uint32_t pin;
-
- if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
- return RTEMS_INVALID_ID;
- }
-
- bank = BANK_NUMBER(pin_number);
- pin = PIN_NUMBER(pin_number);
-
- vector = rtems_gpio_bsp_get_vector(bank);
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- if (
- gpio_pin_state[pin_number].pin_function != DIGITAL_INPUT ||
- gpio_pin_state[pin_number].on_group
- ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_NOT_CONFIGURED;
- }
-
- /* If the bank already has at least one interrupt enabled on a pin,
- * then new interrupts on this bank must follow the current
- * threading policy. */
- if (
- gpio_bank_state[bank].interrupt_counter > 0 &&
- gpio_bank_state[bank].threaded_interrupts != threaded_handling
- ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_RESOURCE_IN_USE;
- }
-
- /* If an interrupt configuration is already in place for this pin. */
- if ( gpio_pin_state[pin_number].interrupt_state != NULL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_RESOURCE_IN_USE;
- }
-
- gpio_pin_state[pin_number].interrupt_state =
- (gpio_pin_interrupt_state *) malloc(sizeof(gpio_pin_interrupt_state));
-
- if ( gpio_pin_state[pin_number].interrupt_state == NULL ) {
- return RTEMS_NO_MEMORY;
- }
-
- interrupt_state = gpio_pin_state[pin_number].interrupt_state;
- interrupt_state->active_interrupt = NONE;
- interrupt_state->debouncing_tick_count = 0;
- interrupt_state->last_isr_tick = 0;
-
- rtems_chain_initialize_empty( &interrupt_state->handler_chain );
-
- interrupt_state->active_interrupt = interrupt;
- interrupt_state->handler_flag = flag;
-
- /* Installs the interrupt handler on the GPIO pin
- * tracking structure. */
- sc = rtems_gpio_interrupt_handler_install(pin_number, handler, arg);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- free(interrupt_state);
- gpio_pin_state[pin_number].interrupt_state = NULL;
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_UNSATISFIED;
- }
-
- if ( threaded_handling ) {
- if (
- _Atomic_Load_uint(&threaded_interrupt_counter, ATOMIC_ORDER_RELAXED) == 0
- ) {
- sc = rtems_interrupt_server_initialize(
- INTERRUPT_SERVER_PRIORITY,
- INTERRUPT_SERVER_STACK_SIZE,
- INTERRUPT_SERVER_MODES,
- INTERRUPT_SERVER_ATTRIBUTES,
- NULL
- );
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_UNSATISFIED;
- }
- }
-
- if ( gpio_bank_state[bank].interrupt_counter == 0 ) {
- sc = rtems_interrupt_server_handler_install(
- RTEMS_ID_NONE,
- vector,
- "GPIO_HANDLER",
- RTEMS_INTERRUPT_UNIQUE,
- (rtems_interrupt_handler) generic_bank_isr,
- &gpio_bank_state[bank].bank_number
- );
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_UNSATISFIED;
- }
-
- _Atomic_Fetch_add_uint(
- &threaded_interrupt_counter,
- 1,
- ATOMIC_ORDER_RELAXED
- );
- }
- }
- else if ( gpio_bank_state[bank].interrupt_counter == 0 ) {
- sc = rtems_interrupt_handler_install(
- vector,
- "GPIO_HANDLER",
- RTEMS_INTERRUPT_UNIQUE,
- (rtems_interrupt_handler) generic_bank_isr,
- &gpio_bank_state[bank].bank_number
- );
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_UNSATISFIED;
- }
- }
-
- sc = rtems_gpio_bsp_enable_interrupt(bank, pin, interrupt);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_UNSATISFIED;
- }
-
- /* If this was the first interrupt enabled on this GPIO bank,
- * record the threading policy. */
- if ( gpio_bank_state[bank].interrupt_counter == 0 ) {
- gpio_bank_state[bank].threaded_interrupts = threaded_handling;
- }
-
- ++gpio_bank_state[bank].interrupt_counter;
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_SUCCESSFUL;
-}
-
-rtems_status_code rtems_gpio_interrupt_handler_remove(
- uint32_t pin_number,
- rtems_gpio_irq_state (*handler) (void *arg),
- void *arg
-) {
- gpio_pin_interrupt_state *interrupt_state;
- rtems_chain_control *handler_list;
- rtems_chain_node *node;
- rtems_chain_node *next_node;
- gpio_handler_node *isr_node;
- uint32_t bank;
-
- if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
- return RTEMS_INVALID_ID;
- }
-
- bank = BANK_NUMBER(pin_number);
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- interrupt_state = gpio_pin_state[pin_number].interrupt_state;
-
- /* If no interrupt configuration is set for this pin. */
- if ( interrupt_state == NULL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_NOT_CONFIGURED;
- }
-
- handler_list = &interrupt_state->handler_chain;
-
- node = rtems_chain_first(handler_list);
-
- /* If the first node is also the last handler for this pin, disables
- * interrupts on this pin as there will be no handler to handle it.
- * This also removes the remaining handler. */
- if ( rtems_chain_is_last(node) ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return rtems_gpio_disable_interrupt(pin_number);
- }
-
- /* Iterate the ISR list. */
- while ( !rtems_chain_is_tail(handler_list, node) ) {
- isr_node = (gpio_handler_node *) node;
-
- next_node = node->next;
-
- if ( isr_node->handler == handler && isr_node->arg == arg ) {
- rtems_chain_extract(node);
-
- break;
- }
-
- node = next_node;
- }
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_SUCCESSFUL;
-}
-
-rtems_status_code rtems_gpio_disable_interrupt(uint32_t pin_number)
-{
- gpio_pin_interrupt_state *interrupt_state;
- rtems_chain_control *handler_list;
- rtems_chain_node *node;
- rtems_chain_node *next_node;
- rtems_vector_number vector;
- rtems_status_code sc;
- uint32_t bank;
- uint32_t pin;
-
- if ( pin_number < 0 || pin_number >= BSP_GPIO_PIN_COUNT ) {
- return RTEMS_INVALID_ID;
- }
-
- bank = BANK_NUMBER(pin_number);
- pin = PIN_NUMBER(pin_number);
-
- vector = rtems_gpio_bsp_get_vector(bank);
-
- ACQUIRE_LOCK(gpio_bank_state[bank].lock);
-
- interrupt_state = gpio_pin_state[pin_number].interrupt_state;
-
- /* If no interrupt configuration is set for this pin. */
- if ( interrupt_state == NULL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_NOT_CONFIGURED;
- }
-
- sc = rtems_gpio_bsp_disable_interrupt(bank, pin, interrupt_state->active_interrupt);
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_UNSATISFIED;
- }
-
- interrupt_state->active_interrupt = NONE;
-
- handler_list = &interrupt_state->handler_chain;
-
- node = rtems_chain_first(handler_list);
-
- /* Iterate the ISR list. */
- while ( !rtems_chain_is_tail(handler_list, node) ) {
- next_node = node->next;
-
- rtems_chain_extract(node);
-
- node = next_node;
- }
-
- /* If this is the last GPIO interrupt are left in this bank,
- * removes the handler. */
- if ( gpio_bank_state[bank].interrupt_counter == 1 ) {
- if ( gpio_bank_state[bank].threaded_interrupts ) {
- sc = rtems_interrupt_server_handler_remove(
- RTEMS_ID_NONE,
- vector,
- (rtems_interrupt_handler) generic_bank_isr,
- &gpio_bank_state[bank].bank_number
- );
- }
- else {
- sc = rtems_interrupt_handler_remove(
- vector,
- (rtems_interrupt_handler) generic_bank_isr,
- &gpio_bank_state[bank].bank_number
- );
- }
-
- if ( sc != RTEMS_SUCCESSFUL ) {
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_UNSATISFIED;
- }
- }
-
- /* Free the pin's interrupt state structure. */
- free(interrupt_state);
-
- --gpio_bank_state[bank].interrupt_counter;
-
- if ( gpio_bank_state[bank].threaded_interrupts ) {
- _Atomic_Fetch_sub_uint(&threaded_interrupt_counter, 1, ATOMIC_ORDER_RELAXED);
- }
-
- RELEASE_LOCK(gpio_bank_state[bank].lock);
-
- return RTEMS_SUCCESSFUL;
-}