Manejo de múltiples periféricos del mismo tipo en C

61 views
Skip to first unread message

Gaspar Santamarina

unread,
Jan 23, 2020, 9:30:06 AM1/23/20
to embebidos32@
Buenas,
Cuál es "la mejor forma" de armar una librería para el manejo de un periférico externo, del cual voy a tener varias instancias?. En C++ lo hago con clases, obviamente, pero en C cómo se suele hacer?.

Saludos,
Gaspar.

Pedro Martos

unread,
Jan 23, 2020, 9:54:50 AM1/23/20
to embeb...@googlegroups.com
Hola,
Una duda: son varias instancias de software que acceden a un mismo hardware o cada instancia de software tiene un hardware asociado de uso exclusivo?

cordialmente,
Pedro

--
-- Recibiste este mensaje porque estás suscripto al Grupo Google Embebidos32. Para postear en este grupo, escribe un email a embeb...@googlegroups.com. Para des-suscribirte, envía un email a embebidos32...@googlegroups.com. Para más opciones, visita el sitio del grupo en https://groups.google.com/d/forum/embebidos32?hl=es
---
Has recibido este mensaje porque estás suscrito al grupo "Embebidos32" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a embebidos32...@googlegroups.com.
Para ver esta conversación en el sitio web, visita https://groups.google.com/d/msgid/embebidos32/CACtv%2BiePCNqD2Q25rZrZiKfFCULK9FsCwBj%2B%3DGmVtVNyezAEFQ%40mail.gmail.com.


--

Ing. Mirko Serra

unread,
Jan 23, 2020, 10:02:38 AM1/23/20
to embeb...@googlegroups.com
Lo normal sería:
- tener una función de inicialización de la librería y una de desinicialización (aunque no hagan nada, pero tipicamente, pedir un buffer de datos internos y guardarlos en un puntero global; o mejor devolver una instancia de la librería, que internamente sería ese puntero a tu estructura de datos)
- lo mismo para cada instancia del dispositivo (equivalentes a un new/delete), que te devuelven un id de dispositivo (una entrada en una tabla en la estructura anterior o un puntero a la estructura del dispositivo). Lo primero te permite asegurar que un llamado a milibreria_cleanup(instancia) libera todo.
- nombres descriptivos: C no permite namespaces ni scope de clases en los nombres (ni overloads), así que te toca llamar a las funciones: mylib_i2c_read() por ejemplo. Lo mismo para los enums, por favor no definas OK, sino MYLIB_OK.
- usar typedefs. No devuelvas "int" como código de error, eso es horrible. Devolvé mylib_errcode_t. Y tratar de no comparar errcode < 0 sino aunque sea un #define que sea MYLIB_ISERROR(x) ((x) != MYLIB_OK) o algo así. Es más portable y más legible.
- indentar con un número lógico de espacios (ej. no 3) ;)

Una forma de verlo es que generes el código en C++ del wrapper que crearía el cliente. Y de ahí te crees las funciones de C necesarias. Por ejemplo:

namespace mylib {
class I2C
{
public:
  I2C() : libinstance(MyLib::getInstance()), devinstance(mylib_i2c_new(libinstance))
  {
    if (!devinstance) {
      throw something;
    }
  }
  ~I2C()
  {
    mylib_i2c_delete(libinstance, devinstance);
  }
  ssize_t read(char* buffer, size_t qty)
  {
    ssize_t qty_ret= 0;
    if (MYLIB_ISERROR(mylib_i2c_read(libinstance, devinstance, buffer, qty, &qty_ret))) {
      throw somethingelse;
    }
    return qty_ret;
  }
private:
  mylib* libinstance=nullptr;
  mydev* devinstance=nullptr;
} // class I2C
} // namespace mylib

Ing. Mirko Serra.


--

Franco Bucafusco

unread,
Jan 23, 2020, 10:09:34 AM1/23/20
to embebidos32@



--------------------------------------------------------- Franco Bucafusco ---------------------------------------------------------


Gustavo Fernández

unread,
Jan 23, 2020, 10:29:27 AM1/23/20
to embeb...@googlegroups.com
Estimado, buen día!

Quizás le sirva utilizar punteros, le dejo un ejemplo simple!

#include <stdio.h>

typedef void (*funcLamp)(void);

typedef struct {
funcLamp lamp;
} Lampara;

void on(void) {
puts("Encender");
}

void off(void) {
puts("Apagar");
}

int main(void) {
Lampara encender = { &on };
Lampara apagar = { &off };

encender.lamp();
apagar.lamp();

return 0;
}

Gaspar Santamarina

unread,
Jan 23, 2020, 10:57:16 AM1/23/20
to embebidos32@
El jue., 23 ene. 2020 a las 15:09, 'Franco Bucafusco' via Embebidos32 (<embeb...@googlegroups.com>) escribió:

Buenísimo Franco, esto es lo que tenía mas o menos en mente, así que voy por acá. 

Gracias.

Saludos,
Gaspar.
 

Eric Pernia

unread,
Jan 23, 2020, 11:50:33 AM1/23/20
to embebidos32@
Buenas Gaspar, esto te puede ayudar:


Desde la página 21 en adelante. En partucular la idea básica de tener objetos en C es que tenés que pasar un puntero a la estructura del mismo, donde guardas el estado del objeto (puede ser memoria dinámica o estática). Es por esto que en la página 24 puse:

Se destaca que en una implementación de la biblioteca para lenguajes no orientados a objetos, en lugar de métodos se tiene funciones y por lo tanto, se deberá agregar en cada una el parámetro "this" que corresponde a una referencia al objeto sobre el cual se ejecuta el método. Por ejemplo, en un lenguaje con objetos como Javascript tendrá,

uart0.init( 9600 )

<objeto>.<método>( <parámetros> )


mientras que en un lenguaje sin objetos como C,

uartInit( UART0, 9600 )

<función>( <objeto>, <parámetros> )

El objeto en C va por referencia (por ejemplo un puntero a la estructura), luego con cada variable de la estructura tenés una instancia diferente.

Saludos.
Eric.



--
-- Recibiste este mensaje porque estás suscripto al Grupo Google Embebidos32. Para postear en este grupo, escribe un email a embeb...@googlegroups.com. Para des-suscribirte, envía un email a embebidos32...@googlegroups.com. Para más opciones, visita el sitio del grupo en https://groups.google.com/d/forum/embebidos32?hl=es
---
Has recibido este mensaje porque estás suscrito al grupo "Embebidos32" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a embebidos32...@googlegroups.com.

Ramiro Vera

unread,
Jan 23, 2020, 3:44:16 PM1/23/20
to embeb...@googlegroups.com
Hola, aporto mi granito.

Podés por cada periférico hacer un .h y .c con sus definiciones y tipos enumerativos y luego incluirlos en el Main.
Cada periférico puede tener un initializeXXX() y un updateXXX() principales y demás funciones que solo serán usados por ellas dos.

En base a como van cambiando los estados de  dichos perifericos, una técnica es la inversión de control. Básicamente pateas estados, flags, etc( booleanos o no) a una lógica de negocios en dónde se encarga de la lógica principal del programa. 
 Dicha lógica también tiene un initialize con callbacks (punteros a función) de cada periférico y un update en dónde entiende los flags que recibio de los periféricos e utiliza los callbacks para ejecutar algo o comunicarse con otro periférico.
Esperó haber ayudado algo

Saludos 

--
-- Recibiste este mensaje porque estás suscripto al Grupo Google Embebidos32. Para postear en este grupo, escribe un email a embeb...@googlegroups.com. Para des-suscribirte, envía un email a embebidos32...@googlegroups.com. Para más opciones, visita el sitio del grupo en https://groups.google.com/d/forum/embebidos32?hl=es
---
Has recibido este mensaje porque estás suscrito al grupo "Embebidos32" de Grupos de Google.
Para cancelar la suscripción a este grupo y dejar de recibir sus mensajes, envía un correo electrónico a embebidos32...@googlegroups.com.

Gaspar Santamarina

unread,
Jan 24, 2020, 7:47:01 AM1/24/20
to embebidos32@
El jue., 23 ene. 2020 a las 16:50, Eric Pernia (<ericp...@gmail.com>) escribió:

Buenísimo Eric, quedó mucho mas claro. Muchas gracias.

Saludos,
Gaspar.
Reply all
Reply to author
Forward
0 new messages