After reading Design Patterns for Embedded Systems in C I changed the way I implement device drivers. The book suggests that a typical device driver header file has this implementation.
/* Encapsulated device handle using 'opaque' pointer */
typedef struct device device_t;
/* Allocated dynamically */
device_t* device_create( i2c_t* bus, const uint8_t address );
void device_destroy( device_t* me );
int device_initialize( device_t* me );
int device_deinitialize( device_t* me );
int device_isAvailable( device_t* me );
int device_configure( device_t* me, const device_config_t config );
Yes I know C is not object-oriented but I like how clean the code smells. I changed the code a little bit. I sacrificed device handle encapsulation in order to be able to allocate it statically.
/* Public(no ecapsulation) device handle */
typedef struct device
{
int public_member1;
int public_member2;
} device_t;
/* Allocated statically */
device_t device_create( i2c_t* bus, const uint8_t address );
int device_initialize( device_t* me );
int device_deinitialize( device_t* me );
int device_isAvailable( device_t* me );
int device_configure( device_t* me, const device_config_t config );
I would rather not allocate dynamically if possible since I fear memory fragmentation but I will if it is a good design desicion. Since my project is embedded and my target an cortex-m0 I wanted to know if I could use static allocation and ecapsulation together..
Update:
I give two different implementations of device_create for the above code
Dynamically:
device_t* device_create( i2c_t* bus, const uint8_t address )
{
/* Check input */
if( bus == NULL )
{
return NULL;
}
/* Create handle */
device_t* aux = (device_t*)malloc( sizeof( device_t ) );
if( aux == NULL )
{
return NULL;
}
/* Initialize handle */
init( aux, bus, address );
/* Return handle */
return aux;
}
Statically:
device_t device_create( i2c_t* bus, const uint8_t address )
{
/* Check input */
if( bus == NULL )
{
return NULL;
}
/* Create handle */
device_t aux;
/* Initialize handle */
init( &aux, bus, address );
/* Return handle */
return aux;
}