4. HAL中的回调机制

任务目标

在HAL模块中实现异步回调机制:上层通过HAL接口注册回调函数,底层在独立线程中模拟事件发生,触发回调将事件数据传递回上层。本案例聚焦HAL层回调的完整链路,不涉及具体硬件。

核心实现

// hal_callback.h
#ifndef HAL_CALLBACK_H
#define HAL_CALLBACK_H

#include <stdint.h>

#ifdef __cplusplus
extern "C" {
#endif

typedef enum {
    HAL_EVENT_DATA_READY = 1,
    HAL_EVENT_ERROR
} hal_event_type_t;

typedef struct {
    hal_event_type_t type;
    uint32_t value;
} hal_event_t;

// 回调函数原型:上层实现,HAL层调用
typedef void (*hal_event_callback_t)(const hal_event_t *event, void *user_data);

// HAL接口
int hal_callback_init(void);
int hal_callback_register_callback(hal_event_callback_t cb, void *user_data);
int hal_callback_start(void);
int hal_callback_stop(void);
void hal_callback_deinit(void);

#ifdef __cplusplus
}
#endif

#endif // HAL_CALLBACK_H
// hal_callback.c
#include "hal_callback.h"
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

static pthread_t s_thread;
static volatile int s_running = 0;
static hal_event_callback_t s_cb = NULL;
static void *s_user_data = NULL;
static pthread_mutex_t s_lock = PTHREAD_MUTEX_INITIALIZER;

static void *event_loop(void *arg) {
    (void)arg;
    uint32_t counter = 0;
    while (s_running) {
        usleep(500000); // 模拟500ms事件周期

        hal_event_t event;
        memset(&event, 0, sizeof(event));
        event.type = HAL_EVENT_DATA_READY;
        event.value = ++counter;

        pthread_mutex_lock(&s_lock);
        hal_event_callback_t cb = s_cb;
        void *user_data = s_user_data;
        pthread_mutex_unlock(&s_lock);

        if (cb) {
            cb(&event, user_data);
        }
    }
    return NULL;
}

int hal_callback_init(void) {
    s_cb = NULL;
    s_user_data = NULL;
    s_running = 0;
    return 0;
}

int hal_callback_register_callback(hal_event_callback_t cb, void *user_data) {
    if (!cb) return -1;
    pthread_mutex_lock(&s_lock);
    s_cb = cb;
    s_user_data = user_data;
    pthread_mutex_unlock(&s_lock);
    return 0;
}

int hal_callback_start(void) {
    if (s_running) return 0;
    s_running = 1;
    if (pthread_create(&s_thread, NULL, event_loop, NULL) != 0) {
        s_running = 0;
        return -1;
    }
    return 0;
}

int hal_callback_stop(void) {
    if (!s_running) return 0;
    s_running = 0;
    pthread_join(s_thread, NULL);
    return 0;
}

void hal_callback_deinit(void) {
    hal_callback_stop();
    pthread_mutex_destroy(&s_lock);
}
// test_client.c(上层调用示例)
#include "hal_callback.h"
#include <stdio.h>

static void on_hal_event(const hal_event_t *event, void *user_data) {
    int *count = (int *)user_data;
    (*count)++;
    printf("[callback] type=%d value=%u (total=%d)\n",
           event->type, event->value, *count);
}

int main(void) {
    int callback_count = 0;

    hal_callback_init();
    hal_callback_register_callback(on_hal_event, &callback_count);
    hal_callback_start();

    // 运行3秒后停止
    sleep(3);
    hal_callback_stop();
    hal_callback_deinit();

    printf("Total callbacks received: %d\n", callback_count);
    return 0;
}

编译与运行

gcc -o hal_callback_test hal_callback.c test_client.c -lpthread
./hal_callback_test

验证方法

  • 程序运行约3秒后自动退出,打印Total callbacks received: N。
  • 由于事件周期为500ms,预期N≈6(允许因调度略有偏差)。
  • stdout中应出现约6行[callback] type=1 value=1..6格式的输出,value递增且无重复。
  • 若N为0,说明回调未触发,检查线程创建或回调注册是否成功。

关键说明

  • 回调在HAL内部线程中执行,上层回调函数中不应执行耗时操作或直接调用HAL的stop/deinit,避免死锁。
  • 注册回调使用互斥锁保护,防止注册与事件触发并发竞争。
  • 本示例使用usleep模拟底层事件,实际硬件场景中可在中断或事件循环中调用回调。
上层 (Client) test_client.c on_hal_event() HAL层 hal_callback.c register/start/stop 事件源 内部线程 usleep(500ms) ①注册回调 ②启动 ③事件 ④异步回调 (HAL线程 → 上层函数) 数据流 hal_event_t { type, value } type: DATA_READY / ERROR value: 递增计数器 时序 ① 注册回调函数 ② 启动事件线程 ③ 事件→回调→上层