news 2026/3/22 14:41:55

CallBackRef函数

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CallBackRef函数

CallBackRef 是什么:为什么回调里既要函数指针,也要一个 void* 上下文

在 Xilinx 驱动(例如XSpiPs)里,经常能看到这样的接口:

voidXSpiPs_SetStatusHandler(XSpiPs*InstancePtr,void*CallBackRef,XSpiPs_StatusHandler FunctionPtr);

很多人第一次看会困惑:既然已经传了回调函数FunctionPtr,为什么还需要一个CallBackRef

答案是:FunctionPtr决定“做什么”(代码),而CallBackRef决定“对谁做”(上下文数据)。
这两者解决的是两个不同维度的问题。


1. FunctionPtr:回调函数指针(代码地址)

回调函数指针告诉驱动:发生事件时调用哪段逻辑。例如 SPI 传输完成、模式错误等事件:

  • 传输完成 → 通知上层继续下一步
  • 错误发生 → 记录日志、重试或上报

驱动不可能替所有应用场景写死策略,所以用函数指针把“策略”交给用户。


2. CallBackRef:回调上下文指针(数据地址)

C 语言的函数指针不携带上下文,回调函数执行时,如果要访问某个对象或状态,就需要一个入口指针。CallBackRef就是这个入口。

它的特点:

  • 类型是void *:可以指向任何用户自定义的数据结构
  • 驱动不会解析它:仅在触发回调时原样传回
  • 在回调函数中由用户将其强制转换回真实类型

这相当于在 C 语言里用“函数指针 + void*”手工模拟面向对象里的“成员函数回调”或“闭包”。


3. 为什么不能只用一个回调函数?

如果只用FunctionPtr,回调函数怎么知道它在服务哪个对象?

例如一个工程里可能有多个 SPI 设备或多条总线:

  • SPI0 控制 AD9528
  • SPI1 控制 Flash 或 ADC
  • 或同一 SPI 上挂多个片选设备

如果只有函数指针,回调函数就必须依赖全局变量来区分“这是哪一个设备的完成事件”,工程规模一大就会:

  • 难以复用
  • 容易写错
  • 多实例难维护

有了CallBackRef,同一个回调函数可以用于多实例,只要传不同的上下文指针即可。


4. 最典型的用法:传一个“上下文结构体”

这是最推荐的方式:用结构体保存你在回调里需要用到的所有信息。

typedefstruct{volatileintdone;u32 last_event;u32 bytes;}spi_ctx_t;staticspi_ctx_tctx;staticvoidspi_status_cb(void*ref,u32 event,u32 bytes){spi_ctx_t*c=(spi_ctx_t*)ref;// CallBackRef -> 真实类型c->last_event=event;c->bytes=bytes;c->done=1;// 通知上层“传输完成/出错”}

注册回调:

XSpiPs_SetStatusHandler(&SpiInstance,&ctx,spi_status_cb);

这样,驱动内部发生事件时会调用:

InstancePtr->StatusHandler(InstancePtr->StatusRef,EventCode,Bytes);

其中StatusRef就是你注册的CallBackRef


5. 在 FreeRTOS 中更常见:把“句柄”作为 CallBackRef

在 RTOS 场景里,回调通常发生在 ISR 中。最常见做法是 ISR 回调里唤醒任务,典型手段包括:

  • SemaphoreHandle_t信号量
  • TaskHandle_t任务通知
  • QueueHandle_t队列事件

这些 handle 在 FreeRTOS 实现中往往就是“内核对象控制块的引用/指针”,正好可放进void*,因此可以直接作为CallBackRef传入。

例如用信号量等待 SPI 完成:

staticSemaphoreHandle_t spi_sem;staticvoidspi_status_cb(void*ref,u32 event,u32 bytes){SemaphoreHandle_t sem=(SemaphoreHandle_t)ref;BaseType_t hpw=pdFALSE;if(event==XST_SPI_TRANSFER_DONE){xSemaphoreGiveFromISR(sem,&hpw);portYIELD_FROM_ISR(hpw);}}voidinit_spi_cb(void){spi_sem=xSemaphoreCreateBinary();XSpiPs_SetStatusHandler(&SpiInstance,(void*)spi_sem,spi_status_cb);}

核心思想:
CallBackRef 指向“该通知谁”的目标,回调函数负责“怎么通知”。


6. CallBackRef 使用注意事项(工程必读)

6.1 生命周期必须足够长

回调是异步发生的(中断触发),所以不能把栈上局部变量地址作为 CallBackRef

voidbad(){intlocal;XSpiPs_SetStatusHandler(&SpiInstance,&local,cb);// 错:local 很快失效}

推荐使用:

  • 全局/static变量
  • 长生命周期对象(设备结构体、RTOS 句柄)
  • 动态分配(需要你自己管理释放时机)

6.2 回调里要做的事情尽量短

尤其在 ISR 回调中:

  • 只做置位、发信号量/通知、推队列等
  • 不做耗时打印、不做阻塞等待、不做长循环

6.3 类型转换要一致

驱动不会检查类型,你传什么,回调就按你传的类型去转换。类型不一致会导致严重错误。


7. 一句话总结

  • FunctionPtr(回调函数)=行为/策略(代码)
  • CallBackRef=上下文/对象引用(数据)

二者结合,让驱动在不依赖全局变量的前提下支持:

  • 多实例
  • 可复用回调
  • ISR/RTOS 同步
  • 应用层自定义处理策略
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/16 3:16:35

Zotero PDF2zh插件:英文文献高效阅读的终极解决方案

Zotero PDF2zh插件:英文文献高效阅读的终极解决方案 【免费下载链接】zotero-pdf2zh PDF2zh for Zotero | Zotero PDF中文翻译插件 项目地址: https://gitcode.com/gh_mirrors/zo/zotero-pdf2zh 还在为阅读英文文献而头疼吗?每天花费大量时间在词…

作者头像 李华
网站建设 2026/3/15 21:14:22

Sigma文件管理器终极指南:免费开源工具打造高效数字工作空间

在日常使用电脑时,你是否曾为杂乱无章的文件管理而烦恼?传统文件管理器功能单一、界面陈旧,难以满足现代用户对高效管理的需求。Sigma文件管理器作为一款免费开源的跨平台工具,正在重新定义现代文件管理的标准。无论你是Windows还…

作者头像 李华
网站建设 2026/3/15 9:26:46

Obfuscar混淆工具完整使用指南

Obfuscar混淆工具完整使用指南 【免费下载链接】obfuscar Open source obfuscation tool for .NET assemblies 项目地址: https://gitcode.com/gh_mirrors/ob/obfuscar Obfuscar是一个开源的.NET程序集混淆工具,通过重命名元数据来保护.NET应用程序中的敏感信…

作者头像 李华
网站建设 2026/3/15 17:28:54

ST7789显示屏终极指南:MicroPython快速上手全攻略

还在为嵌入式项目的显示界面发愁吗?今天我要向你推荐一个改变游戏规则的解决方案——基于MicroPython的ST7789显示屏驱动库。无论你是刚接触嵌入式开发的新手,还是正在寻找更高效显示方案的工程师,这个项目都能让你眼前一亮! 【免…

作者头像 李华
网站建设 2026/3/21 21:43:02

手机玩游戏总卡顿?关闭这2个设置,流畅度提升一倍

很多人都有过这样的体验:手机玩游戏时突然掉帧、操作延迟,明明不是老旧机型,却总被卡顿影响体验。其实不用急着换设备,关闭两个默认开启的 “性能消耗项”,就能让游戏流畅度大幅提升。一、关闭后台应用刷新&#xff0c…

作者头像 李华
网站建设 2026/3/19 2:37:15

如何快速修复和编辑Unreal Engine游戏存档:终极免费工具指南

如何快速修复和编辑Unreal Engine游戏存档:终极免费工具指南 【免费下载链接】uesave-rs 项目地址: https://gitcode.com/gh_mirrors/ue/uesave-rs 还在为游戏存档损坏而烦恼吗?想备份珍贵游戏进度却不知从何下手?ue save-rs开源工具…

作者头像 李华