我一直在编写越来越复杂的固件,并且开始注意到我对设计模式和体系结构的知识有点缺乏。我正在努力发展这些技能,并希望得到一些投入。注意:这是用于微控制器的嵌入式c。
我正在为一个新项目设计一个概念,作为一个练习,如下所示:
下面是一个粗略的系统图:

现在我要做的是想出一个良好的固件架构,允许扩展性(增加多个电池、增加更多传感器、将液晶(或其他)接口从I2C更改为SPI等),以及用于测试(通过UART模拟按钮按下,用模拟值替换电池读数来测试PMIC充电固件等)。
我通常会为每个外围设备编写一个自定义驱动程序,并为每个块编写一个固件模块。我还将使用一个全局可用的get/set来实现一个标记模块,该模块将在整个系统中使用。例如,我的定时器将设置100 5Hz,5Hz,1Hz,标志,主循环将处理这些信号,并以期望的速率调用各个模块。然后,模块本身可以为主循环设置标志,以处理I2C事务完成、事务超时、温度超标等事件。
我希望从中得到一些建议,以便更好地设计系统以实现可伸缩性、封装和抽象的目标。我所做的似乎是一个伪事件驱动的系统,但是一个被黑客入侵的系统。在任何情况下,这里都是我对架构图的尝试:


发布于 2018-09-04 20:16:34
“事件总线”的概念过于复杂。在许多情况下,最简单的方法是最大限度地减少需要异步发生的事情的数量,而是有一个“主轮询”例程,它在“尽可能方便”的基础上运行,并为每个子系统调用轮询例程。在编译中拥有这样的例程可能会有帮助,这样该文件的本质将仅仅是其他子系统使用的所有轮询函数的列表,而不是任何本身具有语义的函数。如果一个人有一个"get按钮按“例程,你可以在该例程中有一个循环,这个循环调用主投票例程,直到按钮被按下,键盘超时,或者调用者需要处理的其他一些事情。这将允许使用以下代码实现主UI:
void maybe_do_something_fun(void)
{
while(1)
{
show_message("Do something fun?");
wait_for_button();
if (button_hit(YES_BUTTON))
{
... do something fun
return;
}
else if (button_hit(NO_BUTTON))
{
... do something boring
return;
}
} while(1);
}这通常比尝试拥有一个巨大的状态机要方便得多,比如,如果代码是STATE_MAYBE_DO_SOMETHING_FUN状态,并且按下了yes或no按钮,那么它将需要升级到STATE_START_DOING_SOMETHING_FUN或STATE_START_DOING_SOMETHING_BORING状态。
请注意,如果使用这种方法,则需要确保在调用main_poll之间的最坏情况下的时间始终满足通过main_poll处理的轮询操作的及时性要求,但在满足该要求的情况下,这种方法可能比执行先发制人的多线程代码所需的所有必要操作以及使其可靠工作所需的锁和其他保护程序更加方便和高效。
https://stackoverflow.com/questions/52173266
复制相似问题