--- bsps/include/bsp/gpio2.h | 528 ++++++++++++++++++++++++ bsps/include/bsp/periph_api.h | 142 +++++++ bsps/shared/dev/gpio/gpio.c | 212 ++++++++++ bsps/shared/dev/periph_api/periph_api.c | 101 +++++ spec/build/bsps/obj.yml | 4 +- 5 files changed, 986 insertions(+), 1 deletion(-) create mode 100644 bsps/include/bsp/gpio2.h create mode 100644 bsps/include/bsp/periph_api.h create mode 100644 bsps/shared/dev/gpio/gpio.c create mode 100644 bsps/shared/dev/periph_api/periph_api.c
diff --git a/bsps/include/bsp/gpio2.h b/bsps/include/bsp/gpio2.h new file mode 100644 index 0000000000..9cb1c720ab --- /dev/null +++ b/bsps/include/bsp/gpio2.h @@ -0,0 +1,528 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/* + * Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LIBBSP_BSP_GPIO2_H +#define LIBBSP_BSP_GPIO2_H + +#include <bsp.h> +#include <rtems.h> + +/** + * Configure the maximum number of GPIO controllers used in + * a application. + * + * The macro CONFIGURE_GPIO_MAXIMUM_CONTROLLERS can be + * defined in application code. If it is not defined, + * it will default to BSP_GPIO_NUM_CONTROLLERS. If BSP's + * number of controllers is not defined, it will default + * to 1. + */ +#ifndef CONFIGURE_GPIO_MAXIMUM_CONTROLLERS + +#ifndef BSP_GPIO_NUM_CONTROLLERS +#define CONFIGURE_GPIO_MAXIMUM_CONTROLLERS 1 +#else +#define CONFIGURE_GPIO_MAXIMUM_CONTROLLERS BSP_GPIO_NUM_CONTROLLERS +#endif /* BSP_GPIO_NUM_CONTROLLERS */ + +#endif /* CONFIGURE_GPIO_MAXIMUM_CONTROLLERS */ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @brief Macro to initialize rtems_gpio. + * + * @param gpioh pointer to GPIO handlers + */ +#define RTEMS_GPIO_BUILD_BASE(_gpio_handlers) \ + (rtems_gpio) { .virtual_pin = 0, \ + .gpio_handlers = ( _gpio_handlers ), \ + .api = NULL \ + }; + +/** + * @name GPIO data structures + * + * @{ + */ + +/** + * @brief GPIO bit set and reset enumeration. + */ +typedef enum { + RTEMS_GPIO_PIN_RESET = 0, + RTEMS_GPIO_PIN_SET = 1 +} rtems_gpio_pin_state; + +/** + * @brief GPIO pin modes. + */ +typedef enum { + RTEMS_GPIO_PINMODE_OUTPUT = 0, + RTEMS_GPIO_PINMODE_OUTPUT_PP = 0, + RTEMS_GPIO_PINMODE_OUTPUT_OD = 1, + RTEMS_GPIO_PINMODE_INPUT = 2, + RTEMS_GPIO_PINMODE_ANALOG = 3, + RTEMS_GPIO_PINMODE_BSP_SPECIFIC = 4 +} rtems_gpio_pin_mode; + +/** + * @brief GPIO pull resistor configuration. Defines pull-up or + * pull-down activation. + */ +typedef enum { + RTEMS_GPIO_NOPULL, + RTEMS_GPIO_PULLUP, + RTEMS_GPIO_PULLDOWN +} rtems_gpio_pull; + +/** + * @brief Interrupt modes enumeration. + */ +typedef enum { + RTEMS_GPIO_INT_TRIG_NONE = 0, + RTEMS_GPIO_INT_TRIG_FALLING, + RTEMS_GPIO_INT_TRIG_RISING, + RTEMS_GPIO_INT_TRIG_BOTH_EDGES, + RTEMS_GPIO_INT_TRIG_LOW, + RTEMS_GPIO_INT_TRIG_HIGH +} rtems_gpio_interrupt_trig; + +typedef struct rtems_gpio_handlers rtems_gpio_handlers; +typedef struct rtems_gpio rtems_gpio; +/** + * @brief Typedef of the function pointer of an ISR. + */ +typedef void (*rtems_gpio_isr)(void *); + +#include <bsp/periph_api.h> + +/** + * @brief Structure containing pointers to handlers of a + * BSP/driver. Each BSP/driver must define its own + * handlers and create an object of this structure + * with pointers to those handlers. + */ +struct rtems_gpio_handlers { + /** + * @brief This member is the pointer to a handler for setting + * pin mode. + * + * Pin modes are from rtems_gpio_pin_mode enumeration. + */ + rtems_status_code (*set_pin_mode)(rtems_gpio *, rtems_gpio_pin_mode); + + /** + * @brief This member is the pointer to a handler for setting + * pull resistor mode. + * + * Pull resistor modes are from rtems_gpio_pull enumeration. + */ + rtems_status_code (*set_pull)(rtems_gpio *, rtems_gpio_pull); + + /** + * @brief This member is the pointer to a handler for configuring + * interrupt of a pin. + * + * This handler should register ISR and its argument, interrupt + * trigger mode, and pull resister mode for the pin. + * + * @note Enabling interrupt should be done in enable_interrupt() + * handler. + */ + rtems_status_code (*configure_interrupt)(rtems_gpio *, rtems_gpio_isr, void *, rtems_gpio_interrupt_trig, rtems_gpio_pull); + + /** + * @brief This member is the pointer to a handler for removing + * interrupt settings of a pin. + * + * Interrupt settings can be ISR address, pin configuration, etc. + */ + rtems_status_code (*remove_interrupt)(rtems_gpio *); + + /** + * @brief This member is the pointer to a handler for enabling + * interrupt functionality of a pin. + */ + rtems_status_code (*enable_interrupt)(rtems_gpio *); + + /** + * @brief This member is the pointer to a handler for disabling + * interrupt of a pin. + */ + rtems_status_code (*disable_interrupt)(rtems_gpio *); + + /** + * @brief This member is the pointer to a handler for reading + * the digital value of a pin. + * + * The returned value should be in rtems_gpio_pin_state enum. + */ + rtems_status_code (*read)(rtems_gpio *, rtems_gpio_pin_state *); + + /** + * @brief This member is the pointer to a handler for writing + * a digital value to a pin. + */ + rtems_status_code (*write)(rtems_gpio *, rtems_gpio_pin_state); + + /** + * @brief This member is the pointer to a handler for toggling + * a pin. + * + * It should change pin state from SET to RESET or vice versa. + */ + rtems_status_code (*toggle)(rtems_gpio *); + +}; + +/** + * @brief Structure representing a GPIO object. + * + * BSP/drivers need to define their own GPIO structures with + * rtems_gpio being the first member. + */ +struct rtems_gpio { + /** + * @brief This member is a virtual pin number, counting from + * 0 (zero). + */ + uint32_t virtual_pin; + /** + * @brief This member is a pointer to a structure containing + * pointers to handlers of a GPIO controller. + */ + const rtems_gpio_handlers *gpio_handlers; + /** + * @brief This member is a pointer to a peripheral API. + */ + rtems_periph_api *api; +}; + +/** @} */ + +/** + * @name GPIO System operations + * + * Functions in this group should not be called by user + * applications. They are used by BSP/drivers only. + * + * @{ + */ + +/** + * @brief Perform initialization for GPIO system and + * Peripheral API system. + * This function is called automatically using + * SYSINIT. + */ +extern void rtems_gpio_start( + void +); + +/** + * @brief Registers a GPIO controller with GPIO manager. + * + * This function registers the pointer to BSP/driver-specific + * get_gpio() and destroy_gpio() functions. Those two functions + * are for creating and destroying GPIO objects. It also takes + * the number of pins of each BSP/driver for mapping into a + * flat pin numbering system (virtual pin number). + * This function also help register peripherals API get() + * and remove() functions. + * + * @param get_gpio The pointer to BSP/driver-specific get_gpio() + * @param destroy_gpio The pointer to BSP/driver-specific + * destroy_gpio() + * @param get_api The pointer to BSP/driver-specific get_api() + * @param remove_api The pointer to BSP/driver-specific remove_api() + * @param pin_count The number of GPIO pins in the controller + * + * @retval RTEMS_SUCCESSFUL Controller registered successfully + * @retval RTEMS_TOO_MANY if the maximum number of controllers are + * already registered + */ +extern rtems_status_code rtems_gpio_register( + rtems_status_code (*get_gpio)(uint32_t, rtems_gpio **), + rtems_status_code (*destroy_gpio)(rtems_gpio *), + rtems_periph_api *(*get_api)(rtems_gpio *, rtems_periph_api_type), + rtems_status_code (*remove_api)(rtems_gpio *), + uint32_t pin_count +); + +/** @} */ + +/** + * @name GPIO BSP functions + * + * BSP and drivers need to implement these. + * + * @{ + */ + +/** + * @brief Wrapper to perform all BSP controllers registering + * with the GPIO manager. + * + * This function must be implemented by BSP. It should call + * rtems_gpio_register() to register each integrated GPIO + * controller. + */ +extern rtems_status_code bsp_gpio_register_controllers( + void +); + +/** @} */ + +/** + * @name GPIO Application operations + * + * @{ + */ + +/** + * @brief Get the GPIO object containing information + * about the specified pin. + * + * This function maps the virtual pin to intermediate pin, + * and pass to the BSP/driver-specific function to get a + * GPIO object. + * + * @note Warning: this function may use malloc(). When you + * are done with the GPIO object, call rtems_gpio_destroy() + * to avoid memory leak. + * + * @param virt_pin The virtual pin number. + * @param[out] out The pointer to the pointer to the output + * GPIO object. + * + * @retval RTEMS_SUCCESSFUL + * @retval RTEMS_UNSTISFIED if the virtual pin number + * is invalid (i.e. out of range) + */ +extern rtems_status_code rtems_gpio_get( + uint32_t virt_pin, + rtems_gpio **out +); + +/** + * @brief Destroy a GPIO object + * + * This function should be called on an GPIO object which is + * no longer used to avoid memory leak. Internally it can + * use free(). + * + * @param[in] base The pointer to the GPIO object. + * + * @retval RTEMS_SUCCESSFUL + * @retval RTEMS_UNSATISFIED + */ +extern rtems_status_code rtems_gpio_destroy( + rtems_gpio *base +); + +/** + * @brief Sets the pin mode of a pin. + * + * This function calls the registered BSP/driver-specific handler. + * It can be used to set the pin mode for a pin. + * + * @param[in] base The GPIO object to be configured. + * @param mode The pin mode from the enumeration rtems_gpio_pin_mode + * + * @retval RTEMS_SUCCESSFUL GPIO configured successfully. + * @retval RTEMS_UNSATISFIED Could not set the pin mode. + * @retval @see BSP/driver-specific function for other return codes. + */ +extern rtems_status_code rtems_gpio_set_pin_mode( + rtems_gpio *base, + rtems_gpio_pin_mode mode +); + +/** + * @brief Sets the pin's pull resistor configuration. + * + * This function calls the registered BSP/driver-specific handler. + * It can be used to set the pull resistor mode for a pin. + * + * @param[in] base The GPIO object to be configured. + * @param mode The pull mode from the enumeration rtems_gpio_pull + * + * @retval RTEMS_SUCCESSFUL GPIO configured successfully. + * @retval RTEMS_UNSATISFIED Could not set the pull resistor mode. + * @retval @see BSP/driver-specific function for other return codes. + */ +extern rtems_status_code rtems_gpio_set_pull( + rtems_gpio *base, + rtems_gpio_pull pull +); + +/** + * @brief Configure interrupt on a GPIO pin. + * + * This function calls the registered BSP/driver-specific handler. + * It can be used to set up a pin for interrupt mode. + * + * @note This only configures the interrupt but not enable it. Use + * rtems_gpio_enable_interrupt() to actually enable interrupt. + * + * @param[in] base The GPIO object to be configured. + * @param isr The pointer to the ISR to be attached to this pin. + * @param[in] arg The pointer to the argument of the ISR. + * @param trig The trigger mode + * @param pull The pull resistor mode + * + * @retval RTEMS_SUCCESSFUL Interrupt configured successfully. + * @retval RTEMS_UNSATISFIED Could not configure interrupt. + * @retval @see BSP/driver-specific function for other return codes. + */ +extern rtems_status_code rtems_gpio_configure_interrupt( + rtems_gpio *base, + rtems_gpio_isr isr, + void *arg, + rtems_gpio_interrupt_trig trig, + rtems_gpio_pull pull +); + +/** + * @brief Remove interrupt settings for a pin. + * + * This function calls the registered BSP/driver-specific handler. + * It can be used to remove interrupt configuration of a pin like + * ISR, ISR argument, pin mode, etc. + * + * @note This only removes the interrupt but not disable it. Use + * rtems_gpio_disable_interrupt() to actually disable + * interrupt. + * + * @param[in] base The GPIO object to be configured. + * + * @retval RTEMS_SUCCESSFUL Interrupt removed successfully. + * @retval RTEMS_UNSATISFIED Could not remove interrupt. + * @retval @see BSP/driver-specific function for other return codes. + */ +extern rtems_status_code rtems_gpio_remove_interrupt( + rtems_gpio *base +); + +/** + * @brief Enable interrupt on a GPIO pin. + * + * This function calls the registered BSP/driver-specific handler. + * + * @note This function only enables the interrupt (e.g. the vector) + * but not configure the pin. Use + * rtems_gpio_configure_interrupt() for pin configuration. + * + * @param[in] base The GPIO object to be configured. + * + * @retval RTEMS_SUCCESSFUL Interrupt enabled successfully. + * @retval RTEMS_UNSATISFIED Could not enable interrupt. + * @retval @see BSP/driver-specific function for other return codes. + */ +extern rtems_status_code rtems_gpio_enable_interrupt( + rtems_gpio *base +); + +/** + * @brief Disable interrupt on a GPIO pin. + * + * This function calls the registered BSP/driver-specific handler. + * + * @note This function only disables the interrupt (e.g. the vector) + * but not remove the pin's configurations. Use + * rtems_gpio_remove_interrupt() for the latter purpose. + * + * @param[in] base The GPIO object to be configured. + * + * @retval RTEMS_SUCCESSFUL Interrupt disabled successfully. + * @retval RTEMS_UNSATISFIED Could not disable interrupt. + * @retval @see BSP/driver-specific function for other return codes. + */ +extern rtems_status_code rtems_gpio_disable_interrupt( + rtems_gpio *base +); + +/** + * @brief Writes a digital value to a pin. + * + * This function calls the registered BSP/driver-specific handler. + * + * @param[in] base The GPIO object that has information about the + * pin. + * @param value The state to be written to the pin. + * + * @retval RTEMS_SUCCESSFUL Pin successfully written. + * @retval @see BSP/driver-specific function for other return codes. + */ +extern rtems_status_code rtems_gpio_write( + rtems_gpio *base, + rtems_gpio_pin_state value +); + +/** + * @brief Reads the digital value of a pin. + * + * This function calls the registered BSP/driver-specific handler. + * + * @param[in] base The GPIO object that has information about the + * pin. + * + * @param[out] value The state of the pin. + * + * @retval RTEMS_SUCCESSFUL Pin succesfully read. + * @retval @see BSP/driver-specific function for other return codes. + */ +extern rtems_status_code rtems_gpio_read( + rtems_gpio *base, + rtems_gpio_pin_state *value +); + +/** + * @brief Toggles the state of a GPIO pin. + * + * This function calls the registered BSP/driver-specific handler. + * + * @param[in] base The GPIO object that has information about the + * pin. + * + * @retval RTEMS_SUCCESSFUL Pin successfully toggled. + * @retval @see BSP/driver-specific function for other return codes. + */ +extern rtems_status_code rtems_gpio_toggle( + rtems_gpio *base +); + +/** @} */ + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_BSP_GPIO2_H */ diff --git a/bsps/include/bsp/periph_api.h b/bsps/include/bsp/periph_api.h new file mode 100644 index 0000000000..fb02b701dc --- /dev/null +++ b/bsps/include/bsp/periph_api.h @@ -0,0 +1,142 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/* + * Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef LIBBSP_BSP_PERIPH_API_H +#define LIBBSP_BSP_PERIPH_API_H + +#include <bsp.h> +#include <rtems.h> + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/** + * @brief Enumeration of supported peripheral APIs. + */ +typedef enum { + RTEMS_PERIPH_API_TYPE_ADC +} rtems_periph_api_type; + +/** + * @brief The base structure of peripheral APIs. + * All peripheral APIs must have this struct as + * their first member. + * + * @see rtems_adc_api for example implementation. + */ +typedef struct rtems_periph_api rtems_periph_api; + +#include <bsp/gpio2.h> + +/** + * rtems_periph_api structure definition. + */ +struct rtems_periph_api { + /** + * @brief This member tells the type of this + * API. + */ + rtems_periph_api_type api_type; + /** + * @brief This member is a pointer to a + * BSP/driver-specific function that + * performs initialization for the + * API. + */ + void (*init)(rtems_gpio *pin); +}; + +/** + * @brief Register a handler to get API pointer. + * + * @param[in] get_api pointer to a handler to + * get an API with specified type. + * @param index the index of the GPIO controller. + */ +void rtems_periph_api_register_api( + rtems_periph_api *(*get_api)(rtems_gpio *, rtems_periph_api_type), + rtems_status_code (*remove_api)(rtems_gpio *), + uint32_t index +); + +/** + * @brief Performs initialization for peripheral + * API system. + * This function registers some variables that + * the peripheral API utilize from GPIO API. + * + * @param get_ctrl_index Pointer to a helper + * that returns a GPIO controller index + * of a pin. + * @param num_ctrl Pointer to a variable that + * tells the number of registered GPIO + * controllers. + */ +void rtems_periph_api_start( + uint32_t (*get_ctrl_index)(uint32_t), + uint32_t *num_ctrl +); + +/** + * @brief Assign an API to a GPIO object and + * initialize it. + * + * @note This function may use malloc(). + * @note This function calls the handler init(). + * + * @param pin The rtems_gpio object representing + * a pin. + * @param type The peripheral API type. + * + * @retval RTEMS_SUCCESSFUL if an API is set + * correctly. + * @retval RTEMS_UNSATISFIED if the API type is + * invalid for this pin. + * @retval RTEMS_NO_MEMORY if memory cannot be + * allocated for API object. + */ +rtems_status_code rtems_periph_api_set_api( + rtems_gpio *pin, + rtems_periph_api_type type +); + +/** + * @brief Remove the API assigned to a pin by + * setting the pointer to NULL. + * + * @retval RTEMS_SUCCESSFUL + */ +rtems_status_code rtems_periph_api_remove_api( + rtems_gpio *pin +); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* LIBBSP_BSP_PERIPH_API_H */ diff --git a/bsps/shared/dev/gpio/gpio.c b/bsps/shared/dev/gpio/gpio.c new file mode 100644 index 0000000000..295b9c3738 --- /dev/null +++ b/bsps/shared/dev/gpio/gpio.c @@ -0,0 +1,212 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/* + * Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <bsp/gpio2.h> +#include <rtems/sysinit.h> + +/** + * @brief An array to store all registered GPIO controllers. + */ +static rtems_status_code (*get_gpio_table[CONFIGURE_GPIO_MAXIMUM_CONTROLLERS])(uint32_t, rtems_gpio **); + +/** + * @brief An array to store all registered GPIO controllers. + */ +static rtems_status_code (*destroy_gpio_table[CONFIGURE_GPIO_MAXIMUM_CONTROLLERS])(rtems_gpio *); + +/** + * @brief An array to store the boundaries of pin index of + * GPIO controllers. + * + * Example with 2 16-pin controllers and 1 32-pin controller, + * the pin_map will be: + * { 0, 16, 32, 64} + * Value 0 is always at index 0 for convenience of calculation. + * The length of this array is always 1+(number of controllers). + */ +static uint32_t pin_map[CONFIGURE_GPIO_MAXIMUM_CONTROLLERS+1] = {0}; + +/** + * @brief The number of controllers registered. + */ +static uint32_t num_ctrl = 0; + +static uint32_t get_ctrl_index( + uint32_t virtual_pin +); + +static uint32_t get_ctrl_index( + uint32_t virtual_pin +) +{ + uint32_t i; + // TODO: binary search + for (i = 1; i <= num_ctrl; ++i) { + if (virtual_pin < pin_map[i]) { + break; + } + } + return i-1; +} + +rtems_status_code rtems_gpio_register( + rtems_status_code (*get_gpio)(uint32_t, rtems_gpio **), + rtems_status_code (*destroy_gpio)(rtems_gpio *), + rtems_periph_api *(*get_api)(rtems_gpio *, rtems_periph_api_type), + rtems_status_code (*remove_api)(rtems_gpio *), + uint32_t pin_count +) +{ +// rtems_interrupt_level level; + + if (num_ctrl == CONFIGURE_GPIO_MAXIMUM_CONTROLLERS) + return RTEMS_TOO_MANY; + +// rtems_interrupt_disable(level); + get_gpio_table[num_ctrl] = get_gpio; + destroy_gpio_table[num_ctrl] = destroy_gpio; + + rtems_periph_api_register_api(get_api, remove_api, num_ctrl); + + pin_map[num_ctrl+1] = pin_map[num_ctrl] + pin_count; + ++num_ctrl; +// rtems_interrupt_enable(level); + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code rtems_gpio_get( + uint32_t virt_pin, + rtems_gpio **out +) +{ + uint32_t i = get_ctrl_index(virt_pin); + if (i >= num_ctrl) + return RTEMS_UNSATISFIED; + + uint32_t pin = virt_pin - pin_map[i]; + rtems_status_code sc = (*get_gpio_table[i])(pin, out); + if (sc == RTEMS_SUCCESSFUL) { + (*out)->virtual_pin = virt_pin; + } + return sc; +} + +rtems_status_code rtems_gpio_destroy( + rtems_gpio *base +) +{ + uint32_t i = get_ctrl_index(base->virtual_pin); + if (i >= num_ctrl) + return RTEMS_UNSATISFIED; + return (*destroy_gpio_table[i])(base); +} + +void rtems_gpio_start( + void +) +{ + rtems_periph_api_start(get_ctrl_index, &num_ctrl); + bsp_gpio_register_controllers(); +} +RTEMS_SYSINIT_ITEM( + rtems_gpio_start, + RTEMS_SYSINIT_DEVICE_DRIVERS, + RTEMS_SYSINIT_ORDER_LAST_BUT_1 +); + +rtems_status_code rtems_gpio_set_pin_mode( + rtems_gpio *base, + rtems_gpio_pin_mode mode +) +{ + return base->gpio_handlers->set_pin_mode(base, mode); +} + +rtems_status_code rtems_gpio_set_pull( + rtems_gpio *base, + rtems_gpio_pull pull +) +{ + return base->gpio_handlers->set_pull(base, pull); +} + +rtems_status_code rtems_gpio_configure_interrupt( + rtems_gpio *base, + rtems_gpio_isr isr, + void *arg, + rtems_gpio_interrupt_trig trig, + rtems_gpio_pull pull +) +{ + return base->gpio_handlers->configure_interrupt(base, isr, arg, trig, pull); +} + +rtems_status_code rtems_gpio_remove_interrupt( + rtems_gpio *base +) +{ + return base->gpio_handlers->remove_interrupt(base); +} + +rtems_status_code rtems_gpio_enable_interrupt( + rtems_gpio *base +) +{ + return base->gpio_handlers->enable_interrupt(base); +} + +rtems_status_code rtems_gpio_disable_interrupt( + rtems_gpio *base +) +{ + return base->gpio_handlers->disable_interrupt(base); +} + +rtems_status_code rtems_gpio_write( + rtems_gpio *base, + rtems_gpio_pin_state value +) +{ + return base->gpio_handlers->write(base, value); +} + +rtems_status_code rtems_gpio_read( + rtems_gpio *base, + rtems_gpio_pin_state *value +) +{ + return base->gpio_handlers->read(base, value); +} + +rtems_status_code rtems_gpio_toggle( + rtems_gpio *base +) +{ + return base->gpio_handlers->toggle(base); +} + diff --git a/bsps/shared/dev/periph_api/periph_api.c b/bsps/shared/dev/periph_api/periph_api.c new file mode 100644 index 0000000000..4bc6b02939 --- /dev/null +++ b/bsps/shared/dev/periph_api/periph_api.c @@ -0,0 +1,101 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ + +/* + * Copyright (C) 2022 Duc Doan (dtbpkmte at gmail.com) + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include <bsp/periph_api.h> + +/** + * @brief An array to store handlers to get peripheral + * API of each registered GPIO controller. + */ +static rtems_periph_api *(*get_api_table[CONFIGURE_GPIO_MAXIMUM_CONTROLLERS])(rtems_gpio *, rtems_periph_api_type); + +/** + * @brief An array to store handlers to remove peripheral + * API of each registered GPIO controller. + */ +static rtems_status_code (*remove_api_table[CONFIGURE_GPIO_MAXIMUM_CONTROLLERS])(rtems_gpio *); + +/** + * Mirrors to GPIO private variables/ + */ +static uint32_t (*get_ctrl_index_ptr)(uint32_t); +static uint32_t *num_ctrl_ptr; + + +void rtems_periph_api_start( + uint32_t (*get_ctrl_index)(uint32_t), + uint32_t *num_ctrl +) +{ + get_ctrl_index_ptr = get_ctrl_index; + num_ctrl_ptr = num_ctrl; +} + +void rtems_periph_api_register_api( + rtems_periph_api *(*get_api)(rtems_gpio *, rtems_periph_api_type), + rtems_status_code (*remove_api)(rtems_gpio *), + uint32_t index +) +{ + get_api_table[index] = get_api; + remove_api_table[index] = remove_api; +} + +rtems_status_code rtems_periph_api_set_api( + rtems_gpio *pin, + rtems_periph_api_type type +) +{ + // Prevent memory-leak by removing the old API + // first. + if (pin->api != NULL) + rtems_periph_api_remove_api(pin); + + uint32_t i = (*get_ctrl_index_ptr)(pin->virtual_pin); + if (i >= *num_ctrl_ptr) + return RTEMS_UNSATISFIED; + + pin->api = (*get_api_table[i])(pin, type); + if (pin->api == NULL) + return RTEMS_UNSATISFIED; + + // Initialize the API object + pin->api->init(pin); + + return RTEMS_SUCCESSFUL; +} + +rtems_status_code rtems_periph_api_remove_api( + rtems_gpio *pin +) +{ + uint32_t i = (*get_ctrl_index_ptr)(pin->virtual_pin); + if (i >= *num_ctrl_ptr) + return RTEMS_UNSATISFIED; + + return (*remove_api_table[i])(pin); +} diff --git a/spec/build/bsps/obj.yml b/spec/build/bsps/obj.yml index ce05c11c0e..80736c197d 100644 --- a/spec/build/bsps/obj.yml +++ b/spec/build/bsps/obj.yml @@ -16,7 +16,7 @@ install: - bsps/include/bsp/default-initial-extension.h - bsps/include/bsp/fatal.h - bsps/include/bsp/fdt.h - - bsps/include/bsp/gpio.h + - bsps/include/bsp/periph_api.h - bsps/include/bsp/gpio2.h - bsps/include/bsp/irq-default.h - bsps/include/bsp/irq-generic.h @@ -71,6 +71,8 @@ links: - role: build-dependency uid: objnosmp source: +- bsps/shared/dev/gpio/gpio.c +- bsps/shared/dev/periph_api/periph_api.c - bsps/shared/dev/display/disp_hcms29xx.c - bsps/shared/dev/display/font_hcms29xx.c - bsps/shared/dev/i2c/i2c-2b-eeprom.c -- 2.36.1 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel