This is the mail archive of the ecos-devel@sourceware.org mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Generic GPIO framework


Hello

I've been working on a generic GPIO framework for eCos. I wonder if there is interest in such a framework by the broad community. If so, I can take the effort to clean it up and make it ready for use by others.

Let me quickly explain what the framework does in it's current form, any feature requests are highly appreciated :)

We have a project where we need some simple digital IO (switches, sensors, LEDs etc.). As we mainly develop on the synth target, we wanted to be able to have a GPIO framework with drivers for both our hardware target (an STM32) and the synth target.

The GPIO framework (CYGPKG_IO_GPIO) provides the basic infrastructure to support GPIO "devices". Using this architecture it would be feasible to also implement GPIO drivers for let's say SPI-based GPIO expanders.

The user API is very simple:

// GPIO direction
typedef enum {
    CYG_GPIO_INPUT,
    CYG_GPIO_OUTPUT,
} cyg_gpio_dir_t;

// Checks if a virtual pin number is valid.
cyg_bool cyg_gpio_is_valid(int pin);

// Configures a pin with direction (input/output) and hardware specific flags.
void cyg_gpio_configure(int pin, cyg_gpio_dir_t dir, int flags);


// Writes to a pin.
void cyg_gpio_set(int pin, int value);

// Reads from a pin.
int cyg_gpio_get(int pin);

// Checks if a pin has a dedicated interrupt.
cyg_bool cyg_gpio_has_irq(int pin);

// Gets the interrupt vector of a pin.
cyg_vector_t cyg_gpio_to_irq(int pin);

Note that the pin number is 'virtual'. In the case of the STM32 GPIO driver, pins are mapped linearly. PA0 has pin number 0, PA15 has 15, PB0 has 16 and so on. When having multiple GPIO devices, one would have to define regions for further pins. Do you think this is OK, or should there be some 'device id' to identify the actual GPIO device to use?

Besides the simple API, there is an API to create 'observers'. An observer can be used to observe the input value of a GPIO pin. The user is notified through a callback if the input value changes. Observers can both by used in a polling mode or in interrupt mode, if the pin supports it. Also the observer implements debouncing. Observers can be used to handle simple switches for example.

The observer API looks like this:

// GPIO observer flags
typedef enum {
    CYG_GPIO_OBSERVER_DEBOUNCE  = (1<<0),
    CYG_GPIO_OBSERVER_INTERRUPT = (1<<1),
} cyg_gpio_observer_flags_t;

// GPIO observer handler
typedef void (*cyg_gpio_handler_t)(int pin, int value, void *user);

// Creates an observer.
void cyg_gpio_observer_create(struct cyg_gpio_observer *observer,
                              int pin,
                              cyg_gpio_observer_flags_t flags,
                              cyg_gpio_handler_t handler,
                              void *user);
// Destroys an observer.
void cyg_gpio_observer_destroy(struct cyg_gpio_observer *observer);

// Enables an observer.
void cyg_gpio_observer_enable(struct cyg_gpio_observer *observer);

// Disables an observer.
void cyg_gpio_observer_disable(struct cyg_gpio_observer *observer);

GPIO drivers can be written relatively simple. One has to basically provide the following functions:

// Driver functions
struct cyg_gpio_device_funs {
    void (*init)(struct cyg_gpio_device *dev);
    cyg_bool (*is_valid)(struct cyg_gpio_device *dev, int pin);
    void (*configure)(struct cyg_gpio_device *dev, int pin,
                      cyg_gpio_dir_t dir, int flags);
    void (*set)(struct cyg_gpio_device *dev, int pin, int value);
    void (*get)(struct cyg_gpio_device *dev, int pin, int *value);
    cyg_bool (*has_irq)(struct cyg_gpio_device *dev, int pin);
    cyg_vector_t (*to_irq)(struct cyg_gpio_device *dev, int pin);
};

As I said, I already have implemented drivers for the STM32 and the synthetic target.

The STM32 driver is very straight forward. It lets you define a list of valid pins for use by the application (optional) and a list of pins that should be mapped to interrupts. The driver automatically sets up the EXTI interrupt mappings for the configured pins.

The synth driver is a bit more complex. It comes with integration into the ecosynth GUI. It lets the user dynamically specify how the GPIOs are displayed by editing the target.tdf configuration file. Currently the driver will display a simple list of 'items'. Items can be labels, generic pins and LEDs (both mono and bi-color). Generic pins have a few options to simulate switches etc.

Now if anyone is interested to review my current implementation, I can prepare a tarball and put it up somewhere.

There are a few open questions, but before bringing them up I just wanted to see if anyone is interested in this.


Simon



Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]