030 外设驱动框架:分层设计与硬件抽象层(HAL)
一次让我通宵的GPIO中断
凌晨三点,示波器上的波形还在乱跳。我盯着屏幕上的中断响应时间,从预期的5微秒变成了50微秒,整整差了一个数量级。更诡异的是,同样的代码在开发板上跑得好好的,换到量产板上就崩了。
排查到最后,问题出在一个看似“优雅”的设计上——我在应用层直接调用了寄存器级别的GPIO操作。开发板的GPIO控制器是NXP的,量产板换成了ST的,寄存器地址完全不一样。那个“优雅”的代码,在移植时变成了噩梦。
那次之后,我彻底理解了为什么Linux内核要搞出那么复杂的驱动框架。不是闲得慌,是血的教训换来的。
裸机驱动的“三层架构”
很多人觉得裸机程序简单,不需要什么架构。但当你面对一个包含SPI Flash、I2C传感器、UART调试口、PWM电机控制、ADC采样的系统时,没有分层设计,代码就是一团乱麻。
我习惯把外设驱动拆成三层,从下往上分别是:
硬件访问层(HAL):直接跟寄存器打交道,封装成最基础的读写接口。比如hal_gpio_set_pin(GPIOA, 3, HIGH)这种。
外设驱动层(Driver):基于HAL实现具体外设的功能逻辑。比如SPI Flash的擦除、写入、读取命令序列。
应用接口层(API):给上层应用调用的简洁接口。比如flash_write_page(addr