zoukankan      html  css  js  c++  java
  • Chrome EC框架探索_0.0_引言

    0.0 引言

            嵌入式硬件抽象框架常常面临着这样的尴尬:封装层次较高的(arduino,mbed)不能充分暴露必要的API并面临着性能问题,封装层次较低的(HAL,LL)接口复杂且开发困难。近日发现的一个框架Chrome Embed Controller(下简称EC)较好地权衡了开发效率和运行效率,还具有其他的一些可贵的特性。先来看看EC的几个常用API:

      //GPIO declaration //GPIO(name, pin, flag)
    GPIO(PD11,          PIN(D, 11), GPIO_OUT_HIGH)//declare as output
    GPIO(PC6,       PIN(C, 6), GPIO_INPUT) //declare as input
     
    gpio_set_level(GPIO_PD11, 1); //set GPIO output
    int input = gpio_get_level(GPIO_PC6); //read GPIO input
     
    //initialize an i2c port
    GPIO(I2C1_SCL, PIN(B, 6), GPIO_ODR_HIGH) // I2C port 1 SCL
    GPIO(I2C1_SDA, PIN(B, 7), GPIO_ODR_HIGH) // I2C port 1 SDA
    ALTERNATE(PIN_MASK(B, 0x00C0), GPIO_ALT_F1, MODULE_I2C, GPIO_PULL_UP)
    const struct i2c_port_t i2c_ports[] = {
    {"test", STM32_I2C2_PORT, 100, GPIO_I2C2_SCL, GPIO_I2C2_SDA},
    };
    const unsigned int i2c_ports_used = ARRAY_SIZE(i2c_ports);
     
    //int i2c_write8(int port, int slave_addr, int offset, int data)
    i2c_write8(1, 0x40, 0x2 + bank, 0x4C); //write u2c output
    //int i2c_read8(int port, int slave_addr, int offset, int *data)
    i2c_read8(1, 0x40, 0x6 + bank, & tmp); //read i2c input
     

    怎么样,是不是比stdlib和HAL什么的简洁多了?作为一个为专门用途设计的框架,将EC用于通用开发的资料哪怕在国外也寥寥无几。本文首先是我自己探索EC过程中的笔记,更希望能让这样一个优秀且有巨大潜力的框架为嵌入式开发者所知、所用。

    What's EC?

    • EC是较新的chromebook上用于硬件管理和启动引导的硬件
    • chromebook团队认为传统BIOS是bullshit,于是自己用通用嵌入式SoC实现了一个作为替代(所以不要对Google说you can you up, the do can and they will up)
    • EC也指运行在该硬件上的嵌入式程序框架,Google团队将其基于BSD License开源(后文中的EC多指该框架)
    • EC具有传统BIOS启动和引导OS以及硬件管理的功能,所以需要与CPU(也称AP,应用处理器)通信
    • EC还直接控制着chromebook上的诸多设备,如键盘,PMU,各种传感器等,所以集成了它们的驱动
    • 尽管EC原本设计用于chromebook,但可以直接移植到独立的MCU上,即我们可以将它用于自己的项目。这也是本文的主要目的。

    How does EC works?

    任务(Tasks)

    • EC并没有暴露程序入口点(main函数)。我们的程序需要以任务的形式交给调度器执行。
    • 和其他任务调度器一样,EC中的任务是函数
    • 任务有预设的优先级,并在中断时发生抢占
    • 用户把需要执行的任务声明在一个单独文件里

    模块(Modules)

    • 模块就是封装好的各个功能单元,有程序体和对应的头文件
    • 既包括SoC上的外设(UART, SPI, etc.)又包括一些硬件设备(传感器,键盘,etc.),还有非硬件的控制逻辑(手势控制,SHA1,etc.)。
    • 通过头文件引入工程,含有初始化函数(配置使用前需要设定的一些寄存器)

    控制台(Console)

    • EC使用I2C,SPI或LPC总线与AP通信,尽管EC实际上最终被映射成一个USB设备
    • EC的console执行用户在终端上发来的一些预定义的指令,可以是自带的或用户自定义的,包括打印运行状态,硬件操作和模块的一些操作等。每个模块的操作指令定义在独立的文件里。
    • EC可以直接通过控制台升级固件
    • 控制台也是一个模块,它在debug时可以提供极大的便利,在生产时若不需要也可以不引入

    多平台适配(标题格式还想再挣扎一下)

    • 由于不同型号的chromebook使用不同种类的EC控制器,EC固件需要进行跨平台适配
    • EC巧妙设计的API允许用户只针对不同SoC做少量设定即可移植代码
    • 这些设定以宏定义的形式暴露给用户,包括系统时钟,FLASH和RAM大小等
    • 每个平台的设定被写入独立的config文件中
    • 注意:本教程以STM32为平台

    Why EC?

    • Light and Fast

      EC不基于任何现有框架,而是直接对寄存器操作进行了一定层次的封装。这使得它甚至可以运行在32MHz/16kb RAM的STM32L151上——除非自己造轮子,这可能是现在最轻量的多任务嵌入式框架了。
    • 简明的API

      例如,要声明一个GPIO引脚,只需要写一行 GPIO(name, pin, flags) ,让GPIO_XXXX()、GPIO_Typedef啥的都见鬼去吧
    • 跨平台硬件抽象

      正如前文所述,EC是一个跨平台框架,目前已涉及意法STM32、德仪TM4、新唐npcx、Microchip mec1322等产品线,覆盖ARM cortex-m, cortex-m0, nds32等架构。EC将各平台上不同的底层操作封装成统一、高级、简洁的API供用户调用,实现了跨平台、高性能的硬件抽象。
    • 专长

      如果你正在寻找一个合适的方案来辅助高级SoC(比如AP)的启动和硬件管理,那EC无疑是你的极佳选择!EC集成了boot,电源管理,常见IO设备驱动等必要的功能,可以大大简化你的开发流程。又或者你想驱动一些只有在笔记本上应用较多的设备,这些库对于嵌入式MCU不太常见(e.g.触摸板,PD物理层,etc.),EC很可能包含了这些驱动。
    • Google,Yes!

      EC由Google团队开发和维护。EC为千万台chromebook产品提供底层支持。EC有完善的单元和闭环测试程序。EC迄今已有5年的历史,其间很好地证明了它可以胜任传统BIOS的工作并且做得更好。这几点保证了EC的代码质量和健壮性——相比之下,把个人建立和维护的封装库用在某些场合就显得不那么令人放心了。另外,EC的维护和更新至今仍然非常活跃,并且团队对于合并修改的请求的响应非常积极。

    ……But noting is perfect

    你不能……

    • 使用堆

      EC的任务调度器的内存分配机制不允许使用动态内存。尽管如此,EC仍然提供了一个共享缓冲区(Shared Memory Buffer)——目前仅用于debug。实际上因为缺少MMU,降低的可靠性和高昂的开销,在嵌入式系统上使用动态内存一直不被建议。而禁用堆从根本上杜绝了内存泄漏,这在稳定性上带来的巨大提升使得副作用的一点点限制显得不值一提了。
    • ……以及那些并不是很通用的外设

      用作EC的MCU大多较为低端,所以很多高端MCU才有的功能并没有被EC实现或高层封装(e.g.DAC,FSMC,Ethernet,etc.),一些显然对于chromebook没用的功能也同样没有(e.g. CAN)。你可能想自己实现一些外设封装库,但要注意不要与EC的内存管理和资源锁机制冲突。
    • 没有一颗热爱折腾的心

      如果你对嵌入式开发毫无兴趣而只想make things work,EC极可能不是你的最佳选择。EC不是被设计用于通用嵌入式开发的,没有arduino、mbed等流行平台那样完善的生态和丰富的资源——实际上有关于使用EC进行通用开发的资料少得可怜。这意味着你需要自己实现每个EC未封装的功能并有相当的解决问题的能力。

    ……以及我个人的一点吐槽(TL;DR)

    • 泛滥的宏

      EC在宏的应用上简直称得上出(sang)神(xin)入(bing)化(kuang),例如GPIO的三种声明全都是宏函数你敢信?虽然知道在嵌入式系统上为了提升运行时效率这是常规操作,但读源码的时候我还是想【脏话】
    • 简单不简约

      虽然EC并没有mbed等平台那样的宏图壮志,但却有着不输任何框架的独创设计——"独创"在这里没有褒义。EC使用枚举来声明引脚和任务,使用数组来声明外设,与主流框架使用函数的声明风格相比显得特立独行。尤其是任务和引脚的声明都需要写在独立的文件里,应该是出于被多个文件依赖和增加可维护性的考虑。这样的设计似乎有点声明式的味道,可能有更好的性能,也可能是为了简化针对多任务的统一资源管理的妥协。但无疑的是,这种集中的静态的声明风格损失了灵活性,增加了代码移植和进一步封装的难度,并产生了额外的学习负担。
    • 向上污染的底层特性

      EC的封装为我们省去了大量繁琐的初始化和配置等操作,但恼人的底层特性仍有部分残余,比如基于位操作的配置和令人眼花缭乱的16进制常量。可以通过添加一些简单的宏摆脱这些麻烦,不知为什么已经大面积使用宏的EC没有这么做。更致命的是,这些大量的宏给进一步的高层封装带来了巨大的困难,实际上除非从底层重构,我想不出在接口中完全消除这些宏的办法。

    参考资料

  • 相关阅读:
    第十篇 数据类型总结
    第九篇 字典类型的内置方法
    第二篇 输入与输出以及基础运算符
    <爬虫实战>糗事百科
    <读书笔记>如何入门爬虫?
    <读书笔记>001-以解决问题为导向的python编程实践
    <小白学技术>将python脚本导出为exe可执行程序
    <Django> 第三方扩展
    <Django> 高级(其他知识点)
    <Django> MVT三大块之Template(模板)
  • 原文地址:https://www.cnblogs.com/Excr/p/11823530.html
Copyright © 2011-2022 走看看