需要实例化不同类/对象并在启动时确定的硬件插槽的设计模式

Design pattern for hardware slots that need different class/object instantiated and is determined on boot

本文关键字:硬件 设计模式 插槽 启动 实例化 同类 对象      更新时间:2023-10-16

对于我正在为其设计程序的嵌入式定制板来说,这是一个C++问题。如果有帮助,我们将运行 freeRTOS。主板有 3 个物理插槽/接头。1 插槽/接头有 20 个引脚,可以接受 3 个特定板中的 1 个,但将来可能会有更多的板。 另外两个插槽/针座有 18 个引脚,每个都可以占用 8 块板中的 1 个,但将来可能会有更多的板。

这些板通常通过 SPI 进行通信,但有时它们必须通过手动调用 GPIO(取决于安装的板(来敲击。由于向后兼容性问题,通信方案无法标准化(不是我能想到的(。如果最终客户选择,这些插槽中的主板必须能够插入其他不同的主板。

我有一个 SPI 类,它启动了基本硬件 SPI。我有一个插槽类,它接受指向SPI对象的指针,并包括一些重置引脚和一些测试功能,以确定哪个板插入哪个插槽。我实例化了其中 3 个插槽对象,每个物理插槽/标头一个。

在确定每个插槽包含的内容后,我现在需要为每个板设计/创建/编码类,但我遇到了一个架构问题,至少在我看来是这样。由于这是一个嵌入式系统,我想避免使用关键字"new",但这并不是一成不变的。

我的想法是,实例化每个板的副本然后只使用检测到的 3 个板会浪费空间。

在我的脑海中,我在想我的老虎机类可能应该有某种空指针,可以设置为指向在我们确定它是什么板后实例化的对象。在这种情况下,我很确定我必须使用"new"。

我知道在 C 语言中存在"联合"的概念,您可以在其中创建某种自定义类型,该类型可以是少数类型中的任何一种。创建此类型的副本时,它会为联合的最大成员分配足够的内存。你能在C++做到这一点,并将类作为工会的成员,然后以某种方式使其成为你确定要包含的插槽的类类型吗?

还有其他设计理念吗?

需要添加任何其他信息才能让某人更好地了解问题吗?

谢谢

由于这是一个嵌入式系统,我想避免使用关键字"new",但这并不是一成不变的。

您可以使用"放置新"和静态分配的内存缓冲区,其大小是已使用类大小的最大大小。像这样的东西(见在线IDE(:

#include <iostream>
class Base {
public:
Base() { std::cout << __FUNCTION__ << std::endl; }
virtual ~Base() { std::cout << __FUNCTION__ << std::endl; }
virtual void print(void) = 0; 
};
class A : public Base {
public:
A(int i_) : i(i_) { std::cout << "t" << __FUNCTION__ << " " << i << std::endl; }
virtual ~A() { std::cout << "t" << __FUNCTION__ << " " << i << std::endl; }
virtual void print(void) { std::cout << "tt" << __FUNCTION__ << " " << i << std::endl; }
private:
int i;
};
class B : public Base {
public:
B(int i_, int j_) : i(i_), j(j_) { std::cout << "t" << __FUNCTION__ << " " << i << " " << j << std::endl; }
virtual ~B() { std::cout << "t" << __FUNCTION__ << " " << i << " " << j << std::endl; }
virtual void print(void) { std::cout << "tt" << __FUNCTION__ << " " << i << " " << j << std::endl; }
private:
int i;
int j;
};
#define SIZE_IN(class, type)  ((sizeof(class)+sizeof(type)-1)/sizeof(type))
#define POOL_PLACE(class) uint8_t place_##class [ sizeof(class) ]
// Just for simple MAX() calculation
union pool_member_sizes
{
POOL_PLACE(A);
POOL_PLACE(B);
// class C, D, E, ...
};
// statically allocate pool memory for set of classes, one pool for each set
// choose required alignment by pool "type"
uint32_t pool[ SIZE_IN(pool_member_sizes, uint32_t) ];
Base *driver;
int main()
{
driver = new(pool) A(1);
driver->print();
driver->~Base();
driver = new(pool) B(2,3);
driver->print();
driver->~Base();
driver = new(pool) A(4);
driver->print();
driver->~Base();
}