面对的问题
首先看我们的工作模型是怎么样。
硬件设计一代接着一代进行,前后之间的设计可能有:1. 把一个功能砍了(硬件为了保
证兼容性一般不会这样); 2. 新加了一个功能; 3. 改了一个功能(为了兼容性一般也不会
这样); 4. 改了一个功能,但是为了兼容性还支持老的使用方式。
Linux驱动开发,我们一般先直接上传到Linux主线。然后,根据需要回合到各个实际使用
的发行版本中。各个发型版本中因为要做质量控制,所以在发布后,有可能只回合bugfix,
不做大特性的回合。
1 | mainline: a -> b -> c -> d -> e -> f -> g |
软件兼容性要求我们:1. 加一个新特性的时候,不能破坏老特性的使用; 2. 老的软件
在新的硬件上使用时,老的特性还是可以使用的。
解决办法
针对上面的,软件兼容性要求第一点,我们不能改动已有的对外接口,比如各种内核ABI
接口(sysfs,debugfs,ioctl,mmap等等)。
针对以上第二点,软件中不能用硬件版本号区分特性,比如:
1 | if (harware version == X) |
上面这样,在hardware version == X + 1硬件时,老的软件feature_one就无法使用了。
一般的做法是, 通过预留的功能使能标记来判断是否有该功能。而hardware version只用
来修复正常流程里的bug。
1 | if (feature_on_enable()) |
对于纯粹新加的硬件,我们只要原子的加上一个相关的支持补丁就可以,没有回合这个
补丁就不支持新的功能。
对于硬件设计中的第4点。我们可以把改动后的功能认为是正常流程,而把兼容之前的
硬件设计作为一个bug用hardware version隔开。具体可以:
1 | if (harware version == X) |
这里我们假设硬件在X + 1这个版本上对feature_one做了如上第4点里的改动。
我们加一个原子的补丁,把硬件为了向前兼容做的努力看成是一个特殊硬件版本的bug,
而新的改动,我们把它看成是主流程。这样,如果不合这个补丁,之前老的软件可以运行
在新的硬件上。合入这个补丁,新的软件可以跑在新的硬件上,并且使用改动后的特性,
新的软件也可以跑在老的硬件上,同时新的软件也可以兼容更新的硬件(只要硬件保证兼容)。