public inbox for ecos-devel@sourceware.org
 help / color / mirror / Atom feed
* Generic GPIO framework
@ 2010-05-28 14:49 Simon Kallweit
  2010-05-28 22:06 ` Steven Clugston
  2010-05-29  9:17 ` Christophe Coutand
  0 siblings, 2 replies; 4+ messages in thread
From: Simon Kallweit @ 2010-05-28 14:49 UTC (permalink / raw)
  To: eCos developers

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

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: Generic GPIO framework
  2010-05-28 14:49 Generic GPIO framework Simon Kallweit
@ 2010-05-28 22:06 ` Steven Clugston
  2010-05-29  9:17 ` Christophe Coutand
  1 sibling, 0 replies; 4+ messages in thread
From: Steven Clugston @ 2010-05-28 22:06 UTC (permalink / raw)
  To: ecos-devel

I for one would like to see this included so I hope the maintainers see fit to do so.

This could be used to create drivers that are more generic for add-on devices (bit-bang buses/LCD screens) that otherwise sometimes find their way into HAL because pin platform specific pin macro definitions are needed somewhere to actually act on the hardware. A common GPIO interface could allow a driver to be written for a device without knowing or caring exactly what the pin assignment will be and what HAL macros are needed to change the pin states. Obviously this would need to be defined somewhere board specific instead but at least then the driver code will work for more than one board.

Might slight concern is that checking or changing a pin state often might incur an extra stack push/pop overhead (over the HAL macros) if the get/set functions are not inlined.

Steven

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: Generic GPIO framework
  2010-05-28 14:49 Generic GPIO framework Simon Kallweit
  2010-05-28 22:06 ` Steven Clugston
@ 2010-05-29  9:17 ` Christophe Coutand
  2010-05-31  7:41   ` Sergei Gavrikov
  1 sibling, 1 reply; 4+ messages in thread
From: Christophe Coutand @ 2010-05-29  9:17 UTC (permalink / raw)
  To: Simon Kallweit, eCos developers

While I think it is possible to write generic drivers (for sensors, step
motors, LCD etc.) using the platform GPIO, a common way of doing would
make it easier to share drivers.

Maybe the interface should be more compact:

1. cyg_gpio_set_config, which would include:

    - An extended version of cyg_gpio_configure (Some devices are
allowing more than setting IN/OUT buffer type. You might have the option
to configure the output in open collector mode etc.. FPGA also allow to
configure the driver type and strength, maybe some CPU have this
option?).
    - A way of enable / disabling interrupt for that IO

2. cyg_gpio_get_config, which would include:
    - Allow to retrieve all settings from cyg_gpio_set_config
    - cyg_gpio_has_irq
    - cyg_gpio_to_irq

cyg_gpio_is_valid could also be part of cyg_gpio_get_config

3. cyg_gpio_set

4. cyg_gpio_get

Christophe


-----Original Message-----
From: ecos-devel-owner@ecos.sourceware.org
[mailto:ecos-devel-owner@ecos.sourceware.org] On Behalf Of Simon
Kallweit
Sent: 28. mai 2010 16:49
To: eCos developers
Subject: 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

^ permalink raw reply	[flat|nested] 4+ messages in thread

* RE: Generic GPIO framework
  2010-05-29  9:17 ` Christophe Coutand
@ 2010-05-31  7:41   ` Sergei Gavrikov
  0 siblings, 0 replies; 4+ messages in thread
From: Sergei Gavrikov @ 2010-05-31  7:41 UTC (permalink / raw)
  To: Christophe Coutand; +Cc: Simon Kallweit, eCos developers

Hi

And may be to have even more generic I/O driver -- `parport`, then
the driver's interface would be

  cyg_io_{read,write}
  cyg_io_{set,get}_config

and to get the eCos parallel I/O devices like /dev/parX.

Generic layer:
   io/parport/*

Devices:
   devs/parport/*

My $0.02.

Sergei

On Sat, 29 May 2010, Christophe Coutand wrote:

> While I think it is possible to write generic drivers (for sensors, step
> motors, LCD etc.) using the platform GPIO, a common way of doing would
> make it easier to share drivers.
>
> Maybe the interface should be more compact:
>
> 1. cyg_gpio_set_config, which would include:
>
>    - An extended version of cyg_gpio_configure (Some devices are
> allowing more than setting IN/OUT buffer type. You might have the option
> to configure the output in open collector mode etc.. FPGA also allow to
> configure the driver type and strength, maybe some CPU have this
> option?).
>    - A way of enable / disabling interrupt for that IO
>
> 2. cyg_gpio_get_config, which would include:
>    - Allow to retrieve all settings from cyg_gpio_set_config
>    - cyg_gpio_has_irq
>    - cyg_gpio_to_irq
>
> cyg_gpio_is_valid could also be part of cyg_gpio_get_config
>
> 3. cyg_gpio_set
>
> 4. cyg_gpio_get
>
> Christophe
>
>
> -----Original Message-----
> From: ecos-devel-owner@ecos.sourceware.org
> [mailto:ecos-devel-owner@ecos.sourceware.org] On Behalf Of Simon
> Kallweit
> Sent: 28. mai 2010 16:49
> To: eCos developers
> Subject: 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
>

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-05-31  7:41 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-05-28 14:49 Generic GPIO framework Simon Kallweit
2010-05-28 22:06 ` Steven Clugston
2010-05-29  9:17 ` Christophe Coutand
2010-05-31  7:41   ` Sergei Gavrikov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).