裸机嵌入式系统的引脚配置器和数据库

问题描述 投票:0回答:2

寻找有关管理裸机嵌入式系统(〜80MHz,〜64kRAM)的许多引脚的配置的书或其他在线资源。我认为此代码(/层)的一个方面是一个很小的数据库,而我看到的另一个方面是(通过Set / Get)通过数据库使用这些引脚(输出/输入)。

嵌入式裸机系统工具和技术似乎落后于其他计算领域。因此,我想阅读(如果有的话)其他人在该主题上的经验。

主题1:通过使用数据结构(/数据库)管理(/配置)一个位置(/模块)中的所有引脚。开机后,引脚根本不会经常更改“模式”(如果有的话)。对于我来说,拥有一个文件(/模块)是有意义的,在该文件中,所有64-100引脚(嵌入式ARM uC常见)都配置有各自的端口名,引脚号,pull_direction,速度,pin_mode(输入,输出或模拟),pin_function (UART,ADC,DAC,比较器等…..)。最后,pin_ID可以用作每个引脚的标识符,或者,如果可以的话,可以用作引脚名称。

主题2:一个适合嵌入式裸机应用程序的小型数据库。通过数据库管理所有这些引脚。例如,所有这些引脚在运行期间的任何给定时刻也可以具有pin_value。我想从数据库中读取和修改这些pin_value值。扩展以上关于引脚配置和pin_value存储的概念,我们将获得虚拟引脚。虚拟引脚的行为类似于物理引脚。它将具有pin_ID,pin_mode和pin_value。例如,我们有一个uC,它查看信号的零交叉。过零检测只能从零变为一,然后再变为数字输入。我们可以说这具有ZC_ID的pin_ID,INPUT_MODE的pin_mode和值为CLASS_VIRTUAL_DIGITAL的pin_class的新引脚类型。

主题3:连接数据库。我们应用程序的其他模块可以通过数据库访问物理或虚拟引脚值更改。我们的应用程序应该能够通过对pin_ID的简单了解来读写物理或虚拟引脚。例如:

Get_Value(uint32_t pin_ID,uint32_t值)

Set_Value(uint32_t pin_ID,uint32_t值)

然后,基础代码确定此pin_ID是对gpio引脚还是虚拟引脚的简单写入/读取。同样,在现代互联世界中,我需要读写外部设备或服务器。我想使用相同的数据库接口来执行此操作。即,服务器将具有更新值的消息发送到uC模块,在该模块中,数据库将使用新值进行更新。然后,我们的应用程序可以从数据库中读取新值。

总结我正在寻找以下书籍的章节,博客,应用笔记或示例项目:引脚配置管理器,适用于速度慢,内存受限的裸机微控制器的数据库。

谢谢

database embedded microcontroller iot bare-metal
2个回答
0
投票

主题1:通过使用数据结构来管理(/配置)一个位置(/模块)中的所有引脚

这应该是完全可行的;实际上,我(和我认为的其他程序员)完全是这样做的:在系统初始化时,所有引脚都从其默认状态(输入)配置为带上拉或输出的输入,或者与某些特殊的内部硬件(例如例如UART。

主题2:一个适合嵌入式裸机应用程序的小型数据库。通过数据库管理所有这些引脚。例如,所有这些引脚在运行期间的任何给定时刻也可以具有pin_value。我想从数据库中读取和修改这些pin_value值。扩展以上关于引脚配置和pin_value存储的概念,我们将获得虚拟引脚。

再次可行,实际上是非常简单的方式。有时我在ram中使用单个整数,其中每一位都反映引脚的状态或其他状态。中断处理程序更新这些位,然后前台进程查看它们。对于输出,它是相同的,相反的:前台写入这些位,而中断使用这些位来修改实际引脚。因此,我最后得到两个变量(input_statuses和output_statuses),例如,可以通过串行,蓝牙或以太网远程读写。

但是从这一点到数据库,相距甚远。通常,出于性能和低成本的考虑,嵌入式应用程序靠近硬件而没有太多的虚拟化。但是谁知道您的要求呢?也许您的预算很大,功能强大的处理器,对速度的需求很少。


0
投票

在GPIO的特定情况下,最好的想法是使抽象层的方式越少越好

您需要一个功能来设置端口或引脚,并可能需要一些时钟和引脚路由设置。但是,最好通过直接写入数据寄存器直接进行端口访问。为什么?因为如果您进行这样的HAL:

pin_t pin_allocate (port, pin);
void pin_set (pin_t* p);

[pin_t是抽象的,不透明的类型,那么您可能会遇到非常细微的重新输入错误,这些错误是由于应用程序程序员无法跟踪代码的运行情况而造成的。

考虑这种情况:

// BAD DESIGN, don't do this

static pin_t* led;
statci pin_t* relay;

void main (void)
{
  led = pin_allocate(PORTA, 0);
  relay = pin_allocate(PORTA, 1);
  ...

  pin_set(led);  
}

...

void PORTA_ISR (void)
{
  pin_set(relay);
}

此代码中有一个竞态条件错误,但抽象层完全将其隐藏。

  • 某些代码已将引脚用于驱动继电器。即将设置LED。
  • pin_set()可能存储端口寄存器的值,并准备进行按位或。
  • ISR罢工。将端口寄存器写入用于设置继电器的值。
  • 从子程序返回。对端口寄存器的LED写入已完成,并且继电器输出已清除。
  • 这将表现为一种罕见的间歇性现象,其中继电器无法设置,相反,我们在线圈上遇到短时的毛刺,太短而无法驱动它。
  • 如果程序员最终误认为竞争条件错误,他们可能会开始调查对relay变量的访问。但是该变量本身可能受到保护并且是线程安全的-问题出在HAL之下。

我已经多次看到以上情况,这是所有类别中最难发现的错误之一。所以我的建议是不要在软件中过度设计。

而是通过PCB示意图]跟踪引脚,这是规范性文件。任何编写代码必须的人都在决定使用某个引脚之前先查看原理图,而不是仅仅盯着自己的软件。在开始编写任何代码之前,请查找与其他硬件的潜在冲突。

此外,GPIO可能是实时关键的,抽象层意味着开销。

© www.soinside.com 2019 - 2024. All rights reserved.