底层驱动为啥是MBD的“禁区”?

接口/总线/驱动

1125人已加入

描述

1 底层驱动的那些事

先说说MBD关于底层驱动的一些基本情况。

我们知道,MBD是通过建立模型来生成代码,然而并不是所有的代码都能建立模型,嵌入式系统中的底层驱动(Low Level Drivers,LLD)就属于这样的代码。之所以底层驱动代码不能建立模型,是因为其具有下面这样的特征:

  • 没有明显是数学逻辑,无法使用数学表达式表达;
  • 与芯片的外设(Peripherals,例如ADC、PWM等外设)息息相关,不同的芯片可能差别很大;
  • 严格规范的底层驱动需要满足一定的要求,例如AUTOSAR;
  • 底层驱动往往需要频繁的调用;
  • 配置底层驱动的逻辑关系往往比较复杂。

模型擅长处理的是数学问题,而底层驱动本质上是一种格式化的代码,是一套与芯片设计、功能配置联系紧密的流程式操作,所以不适合建模实现。

很多刚入门MBD的读者可能并不具备嵌入式相关的基础(学习MBD大多是机械、汽车专业的,很少有电子、自动化和计算机专业的),这里给大家看看实际的嵌入式工程中,底层驱动究竟是什么样子的。下面这段代码摘自NXP(恩智浦)电机控制工具包MCSPTE1AK144中的部分代码:

int main(void)
{
    McuClockConfig();       /* 配置时钟 */
    McuCacheConfig();       /* 配置缓存 */
    McuPowerConfig();       /* 配置功耗模式 */
    McuIntConfig();         /* 配置中断 */
    McuSimConfig();         /* 配置系统集成模块 */
    McuTrigmuxConfig();     /* 配置触发单元 */
    McuPinsConfig();        /* 配置Pin脚 */
    McuLpuartConfig();      /* 配置UART(通用异步收发) */
    McuAdcConfig();         /* 配置ADC */
    McuPdbConfig();         /* 配置延时计时器 */
    McuFtmConfig();         /* 配置PWM输出模块 */
    FMSTR_Init();           /* 配置上位机通信模块 */
    GD3000_Init();          /* 配置预驱芯片 */
    MCAT_Init();            /* 配置FOC初始化 */


    for(;;){ /* 省略 */ }   /* 进入死循环 */
    return 0;
}

可以看到,程序在进入死循环之前,全部的工作都在进行底层配置的初始化,以ADC为例,底层配置初始化调用的底层驱动API是这样的:

void McuAdcConfig (void)
{
    /* ADC0 module initialization */
    ADC_DRV_ConfigConverter(INST_ADCONV0, &adConv0_ConvConfig0);
    /* ADC1 module initialization */
    ADC_DRV_ConfigConverter(INST_ADCONV1, &adConv1_ConvConfig0);
    /* AD4 input channel is used for PhaseA stator current sensing */
    ADC_DRV_ConfigChan(INST_ADCONV0, 0, &adConv0_ChnConfig0);
    /* AD7 input channel is used for DC bus voltage sensing */
    ADC_DRV_ConfigChan(INST_ADCONV1, 0, &adConv1_ChnConfig0);
    /* AD15 input channel is used for PhaseB stator current sensing */
    ADC_DRV_ConfigChan(INST_ADCONV1, 1, &adConv1_ChnConfig1);
}

这些API由NXP的S32K1xx SDK3.0.0提供。而实际上,这些API之下还有硬件访问层(Hardware Access Layer),在这一层完全变成了寄存器位操作,那就更没办法搭建模型了。

所以,一款芯片的底层驱动本身就是一套非常复杂的软件,这样的底层软件不需要芯片使用者来开发,通常由芯片制造商提供,开发者直接使用即可。

在MBD中就没有相应的解决方案了吗?实际上是有的,这就要提到部分芯片厂商会发布的另一种MBD工具包(也称为硬件支持包)。还是以NXP为例,NXP会随着某一款芯片,发布其基于Simulink的 MBDT (Model-Based Design Toolbox)工具包。该工具包作为Simulink的扩展,可以实现大部分底层驱动的配置。例如NXP S32K1xx的MBDT,安装好后在Simulink的库中可以看到相应的底层驱动模型:

电机控制

NXP MBDT底层驱动模型 - Frome NXP MBDT

而使用模型的方式,底层驱动的初始化就变成了这样,只需要把需要初始化的模块放置在模型中即可:

电机控制

NXP MBDT底层驱动初始化 - Frome NXP MBDT

双击ADC0_Init模型可以编辑底层驱动的一些配置选项,例如采样精度等参数:

电机控制

NXP MBDT底层驱动配置示例 (ADC) - Frome NXP MBDT

除了上面提到的NXP,其他芯片厂商也会提供这种类似的MBD工具包,汇总如下:

  • TI(德州仪器)
  • NXP(恩智浦)
  • ST(意法半导体)
  • Renesas(瑞萨)
  • infineon(英飞凌)
  • Microchip(微芯科技)
  • Arduino(没找到中文名
  • Raspberry Pi(树莓派)

最后两家并不是芯片厂商,Arduino是开源电子原型平台,树莓派已经属于微型电脑了,这说明了MBD的应用领域是可以上升到更加高级的场合,并非限于MCU领域。

当然还有很多其他家的MBD工具包,这里只列举了部分。以后我会选择其中的几个家,详细讲讲它们的MBD工具的使用。目前还没发现有国内芯片厂商有提供MBD开发包的。

(题外话,实际上国内MCU厂商的开发工具链都不算完整,集成开发环境IDE大多也依赖第三方Keil、IAR等,编译器也不是自己的编译器,能提供的开发工具更少,***任重而道远)

这些底层驱动模型调用的依然是原本设计好的底层驱动软件,但是Simulink并不认识这些软件,所以需要告诉Simulink真正的驱动软件在哪里。这些底层驱动模型本质上是Simulink的S-函数,S-函数是能生成代码的。芯片厂商底层驱动的配置通过S-函数的形式在模型中实现,S-函数中包含了用户的配置信息,以及底层驱动的代码。

总的来说,关于嵌入式软件的底层驱动部分,虽然不容易建模实现,但借助芯片厂商的MBD工具包,仍然可以实现建模和自动生成代码。

2 底层驱动为啥是MBD“禁区”?

故事讲到这里,似乎很圆满,为啥还被称为“禁区”呢?

我在MATLAB中文论坛的基于模型设计板块看到几篇帖子,很有参考意义,有许多大佬在这个帖子上发表了关于底层驱动的一些观点,比如刘杰博士(《基于模型设计》四部著作的作者)和老胡(MathWorks高级工程师)。

关于大佬们的观点,我总结了以下几点:

  • 在Simulink中是可以实现底层驱动的,但繁琐且效率不高;
  • MBD应当重点关注上层应用和算法,没必要做底层驱动;
  • MBD的核心是算法验证,即验证上层应用和算法。

我们可以发现,大佬们讨论的时候,都没有提到芯片厂商的MBD工具包。但可以猜测,那时的MBD工具包应该非常不完善,达不到应用的要求,所以才会围绕底层驱动是否值得做展开了激烈的讨论。现在和那时相比,MBD工具包发展了很多,它的底层驱动模块已经可以满足一些简单的应用需求,MBD工具包给的例程是可以直接下载到相应的硬件中,包括电机控制这样的算法可以直接跑起来。

但也仅仅只是满足一些简单的应用需求 ,即使是现在,MBD工具包依然存在着很多局限性。

**首先,**MBD工具包的功能没有底层驱动软件强大,可以说,芯片厂商提供的底层驱动软件能发挥芯片的100%功能,但MBD工具包就很难说了,芯片厂商移植了多少,就支持多少。而且芯片厂商也不会把底层驱动软件的全部功能都移植到MBD工具包中,因为底层驱动软件是属于芯片厂商自己的产品,你愿意把自己的产品放在别人家的平台(例如Simulink)上面吗?

**其次,**目前大多数芯片厂商的底层驱动软件已经具备了图形化的配置界面,例如NXP的Processor Expert(PE),利用该配置工具,已经可以很友好的配置底层软件,体验效果并不比在Simulink中差。

**第三,**对于芯片厂商来说,它们的资源肯定是优先投放非底层驱动软件和图形化配置界面的开发,一款芯片的MBD工具包肯定会落后与前两者发布。

**第四,**从我的使用经验来看,MBD工具包并没有底层驱动软件灵活,在熟悉了底层驱动软件后,遇到问题能很快定位到位置。而如果在MBD工具包的模型中遇到了问题,有时候不查看底层驱动软件,可能很难找到问题所在,因为MBD工具包底层本身也是调用的底层驱动软件,中间隔了一层S-函数。

**第五,**对应复杂的项目来说,使用底层驱动模块可能会大大增加模型的复杂程度,前面提到了,底层驱动模块是需要频繁调用的。

**最后,**也是一个很现实的问题,除了上述提到的芯片厂商会提供MBD工具包,如果使用的芯片不提供MBD工具包呢?毕竟现在能提供MBD工具包的是少数。

所以,即使是在2020年,老胡在回复网友时依然不建议自己搭建底层驱动接口。大佬们的观点到现在依然成立,我们在使用MBD开展项目的时候,可以不考虑底层驱动,也尽量不要涉及底层驱动。因此我把底层驱动称作MBD的“禁区”。

3 底层驱动与模型集成

我们知道,底层驱动是连接上层算法和硬件的桥梁,如果模型中不做底层驱动,那底层驱动怎么实现呢?

按照上面的结论,我们在搭建模型的时候,并不需要将底层驱动放到模型中(当然建模时要考虑底层驱动带来的影响,例如的ADC精度),所以生成的代码就只有算法,我需要做的就是在模型中将这个算法的接口做好。就像下面这样:

电机控制

算法模型 - Frome aotuMBD

这样在测试的时候,也可以直接将该模型作为参考模型进行测试,这样也将测试和建模的工作分离开了。

电机控制

算法测试 - Frome aotuMBD

接下来就是将生成的代码和底层驱动集成在一起,这一步操作需要在IDE中进行。在IDE中我们建立好工程,利用芯片厂商的配置工具将底层配置好,然后将生成的代码复制到工程中去,将模型生成的头文件包含到工程当中,在需要用到算法的地方调用生成的函数接口即可。

这里只是很简要的描述了底层驱动与模型集成的大致过程,后续我会针对不同的芯片更加详细的展示这个过程,欢迎持续关注。

可以看到,底层驱动与模型集成是需要和代码打交道的,但这正是目前使用MBD的主流方式。不要觉得MBD就是纯粹的无代码式开发,就目前来说,如果是产品级的设计,我们依然需要在底层驱动部分和代码接触,MBD工具包只能实现简单demo性质的功能。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分