【问题标题】:Memory-mapped C++ objects non hardware members内存映射的 C++ 对象非硬件成员
【发布时间】:2021-08-06 20:14:44
【问题描述】:

我正在使用 C++ 为一块内存映射硬件开发一个驱动程序,并且我定义了一个代表这个设备的类。它看起来像这样:

class device
{
method1();
method2();

private:
device_register reg1;
device_register reg2;

}

该类有两个文件:device.cpp 和 device.h。成员变量代表设备本身的实际寄存器。现在我想在设备本身上定义更多不是实际寄存器的成员,但我不能在类中定义它们,因为如果我这样做,它们将在设备的内存映射位置定义,该位置可能包含其他设备/寄存器.如果我将它们定义为公共,则会破坏标准布局,并且该类将不再起作用。

所以我所做的就是将它们定义为类定义之外的全局变量。问题是如果我定义了多个对象,它们都会共享这些全局变量,但我希望每个对象都有自己的,我该怎么做呢?

【问题讨论】:

  • 你能有两个子类:device_hwdevice_sw,然后是一个device 类,每个子类都有一个吗?
  • 是吗?你会在哪里使用 c++ 驱动程序?
  • @AdrianMole 我可以,但其他答案更容易。不过还是谢谢。

标签: c++ object memory-mapped-io


【解决方案1】:

也许您可以使用带有指向当前“设备”的指针的单独类


class device_glob {

private :
  device * mmaped_device;
  int other_attrib;
};

您可能可以在 ctor 中的映射位置分配设备。然后您需要将其集成到您正在使用的任何注册表系统中,以获取当前设备的引用/指针。

【讨论】:

    【解决方案2】:

    您应该为寄存器创建一个单独的 POD(普通旧数据)结构,因为即使不添加额外的数据成员,非 POD 类/结构也可能破坏您的内存映射。在 POD 类型中,第一个数据成员的偏移量保证为 0,这是您需要的。在非 POD 类型中,并不总是遵循此合同,例如它可能会被 vtables 或 RTTI 中断。诚然,您可以尽职尽责地避免只会更改第一个数据成员的偏移量的更改,但更强大的解决方案是坚持所有 POD 要求,以便标准要求您的编译器执行您想要的操作。

    可以在 cppreference here 中找到对 POD 类型的要求,但一个简单的记忆方法是,除了本机类型成员之外什么都没有的结构将始终是 POD。

    您还应该确保寄存器被标记为“volatile”,尽管我有一种预感,如果您已经有一个特殊的“device_register” typedef,它会包含一个 volatile 说明符。在这种情况下,您不需要在自己的结构中额外添加一个。

    例子:

    struct MyPeripheralRegisters
    {
    volatile device_register reg1;
    volatile device_register reg2;
    };
    
    class MyPeripheralDriver
    {
    private:
      MyPeripheralRegisters* hardware = MY_MEMORY_MAPPED_ADDR;
      int my_private_state;
    public:
      void method1();
      void method2();
    };
    

    内存映射组件的这种模式通常用于嵌入式驱动程序库中,因此它具有最小惊讶原则。

    【讨论】:

    • 这就是我想做的,也是我可能会去做的。但是如果我没有 MY_MEMORY_MAPPED_ADDR 怎么办?就我而言,我会在枚举 PCI 总线后得到它。我可以通过ctor传递这个地址吗?
    • @effendi 如果地址在初始化期间立即可用,MyPeripheralDriver 的 ctor 确实是设置每个 RAII 的 MyPeripheralDriver.hardware 值的好地方。 MyPeripheralRegisters 结构基本上是一个解码器键 - 只要您可以获得指向第一个寄存器的指针,您就可以将其存储为指向 MyPeripheralRegisters 的指针并以这种方式获得可读的寄存器访问。 (您可能还对“位域”感兴趣,它是一种晦涩的句法糖,用于表示各个位的含义。)
    猜你喜欢
    • 1970-01-01
    • 2011-11-01
    • 2019-09-19
    • 2016-02-23
    • 1970-01-01
    • 1970-01-01
    • 2016-12-08
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多