/* callback.c */
#include<stdio.h>
#include"reg_callback.h"
/* callback function definition goes here */
void my_callback(void)
{
printf("inside my_callback\n");
}
int main(void)
{
/* initialize function pointer to
my_callback */
callback ptr_my_callback=my_callback;
printf("This is a program demonstrating function callback\n");
/* register our callback function */
register_callback(ptr_my_callback);
printf("back inside main program\n");
return 0;
}
/**
* Every hardware module must have a data structure named HAL_MODULE_INFO_SYM
* and the fields of this data structure must begin with hw_module_t
* followed by module specific information.
*/
typedef struct hw_module_t
{
uint32_t tag;
uint16_t version_major;
uint16_t version_minor;
cost char* id;
const char* author;
struct hw_module_methods_t* methods;
void* dso;
uint32_t reserved[10];
}hw_module_t;
/**
* Create a function list
*/
typedef struct hw_module_methods_t
{
/** Open a specific device */
int (*open)(const struct hw_module_t* module, const char* id,
struct hw_device_t** device);
} hw_module_methods_t;
/**
* Every device data structure must begin with hw_device_t
* followed by module specific public methods and attributes.
*/
typedef struct hw_device_t
{
/** tag must be initialized to HARDWARE_DEVICE_TAG */
uint32_t tag;
uint32_t version;
struct hw_module_t* module;
uint32_t reserved[12];
int (*close)(struct hw_device_t* device)
}hw_device_t;
两个常量
/**
* Name of the hal_module_info
*/
#define HAL_MODULE_INFO_SYM HMI
/**
* Name of the hal_module_info as a string
*/
#define HAL_MODULE_INFO_SYM_AS_STR "HMI"
/**
* Get the module info associated with a module by id.
* @return: 0 == success, <0 == error and *module == NULL
*/
int hw_get_module(const char *id, const struct hw_module_t **module);
使用HAL操作LED驱动
根据基类设计LED驱动子类
typedef struct led_module_t
{
hw_module_t common;
int status;
}led_module_t;
typedef struct led_device_t
{
hw_device_t common;
int (*set_on)(led_device_t* dev);
int (*set_off)(led_device_t* dev);
}led_device_t;
static int led_open(const hw_module_t* module, const char* name, hw_device_t** device)
{
led_device_t led_device;
led_device.common.tag = HARDWARE_DEVICE_TAG;
led_device.common.version = 0;
led_device.common.module = module;
led_device.common.close = led_device_close;
led_device.set_on = led_set_on;
led_device.set_off = led_set_off;
*device = (hw_device_t*)&led_device;
}
static int led_device_close(hw_device_t* device)
{
led_device_t* dev = (led_device_t*) device;
if(dev) free(dev);
return 0;
}
static int led_set_on(led_device_t *dev)
{
//call to led HAL-Driver
LOGI("led_set_on");
return 0;
}
static int led_set_off(led_device_t *dev)
{
//call to led HAL-Driver
LOGI("led_set_off");
return 0;
}
最早使用HAL的经历是使用 ST 的 CubeMX 的 HAL 库,但是并没有深入了解 HAL 的设计意图和具体实现方法。其实,HAL 的设计在工程上有十分重要的意义,所以借此机会整理相关内容也希望加深自己的理解。
在 HAL 的设计过程中,我更加体会到抽象和封装这两个概念在软件设计中的重要性。我们在阅读或者使用他人的代码时会有十分直观的感受,“好”的代码给人的感觉总是 simple and intuitive。汉语里有一个词叫做“见微知著”,类似的一句英文可能更加直观表示出这种感觉,叫做“see the forest for the trees”,“forest”未尝不是对“trees”的一种抽象。抽象其实就是提供了一个类似的思路,从各种“微”的硬件寄存器,到“著”的上层API,充满着“大”和“小”的博弈。抽象这种方式或者说能力,更加方便我们大脑对事物的理解与认知,更符合我们的逻辑,也能让我们的工作也好生活也好更加有条不紊。