如何在静态类成员中存储寄存器基地址列表并对其进行计数?

Dan*_* K. 5 c++ embedded microcontroller cpu-registers

我正在研究嵌入式设备的微控制器。这些控制器提供多个使用寄存器进行配置和控制的外设。外设通常具有与其关联的特定寄存器组。多个相同类型的外设(例如,Timer0、Timer1...)具有相同的寄存器组,但它们位于不同的基地址。

通常制造商提供头文件来定义每个外设的寄存器和相关地址。

例如,可以提供定时器外设的头文件:

typedef struct {
  uint32_t IR;                                
  uint32_t TCR;                              
  uint32_t TC;                               
  uint32_t MCR;                              
  uint32_t MR[4];                            
} CTIMER_Type;

#define CTIMER0_BASE                             (0x40008000u)
#define CTIMER0                                  ((CTIMER_Type *)CTIMER0_BASE)
#define CTIMER1_BASE                             (0x40009000u)
#define CTIMER1                                  ((CTIMER_Type *)CTIMER1_BASE)
#define CTIMER_BASE_PTRS                         { CTIMER0, CTIMER1 }
Run Code Online (Sandbox Code Playgroud)

这些头文件特定于特定设备。在此示例中,提供了有关定时器外设的信息:有两个定时器,它们的寄存器组分别位于CTIMER0 a nd CTIMER1

使用 C,我可以使用以下命令将基址寄存器地址列表拉CTIMER_BASE_PTRS入我的实现中:

static CTIMER_Type * ctimers[] =  CTIMER_BASE_PTRS;
static int timers_count = sizeof(ctimers)/sizeof(*ctimers);

Run Code Online (Sandbox Code Playgroud)

现在使用 C++,我想编写一个驱动程序类并包含可用计时器的列表CTIMER_BASE_PTRS。我还想计算可用计时器的数量。

我想出了这段代码,您可以自己尝试一下

#include <stdio.h>
#include <type_traits>
#include <stdint.h>

/* usually provided by chip manufacturer through chip specific include file */
typedef struct {
  uint32_t IR;                                
  uint32_t TCR;                              
  uint32_t TC;                               
  uint32_t MCR;                              
  uint32_t MR[4];                            
} CTIMER_Type;

#define CTIMER0_BASE                             (0x40008000u)
#define CTIMER0                                  ((CTIMER_Type *)CTIMER0_BASE)
#define CTIMER1_BASE                             (0x40009000u)
#define CTIMER1                                  ((CTIMER_Type *)CTIMER1_BASE)
#define CTIMER_BASE_PTRS                         { CTIMER0, CTIMER1 }
/* end manufacturer include file */

static CTIMER_Type * ctimers[] =  CTIMER_BASE_PTRS;

class TimerDriver_base  {
public:
    TimerDriver_base() {
        printf("No of timers available:%i\n", timers_count);
    }
private:
     constexpr static int timers_count = sizeof(ctimers)/sizeof(*ctimers);
    
    // A
    // uncommenting next line prompts compiler error: 'reinterpret_cast' from integer to pointer
    //constexpr static CTIMER_Type * ctimers1[] =  CTIMER_BASE_PTRS;

    // B
    static CTIMER_Type * ctimers2[];
    // uncommenting next line prompts compiler error: invalid application of 'sizeof' to incomplete type 'CTIMER_Type* []'
    // constexpr static int timers_count2 = sizeof(ctimers2)/sizeof(*ctimers2);

};

// B
CTIMER_Type * TimerDriver_base::ctimers2[] =  CTIMER_BASE_PTRS;

int main()
{
    TimerDriver_base MyTimer;
}
Run Code Online (Sandbox Code Playgroud)

我尝试包含计时器列表ctimers[]到驱动程序类中:

A) 使用定义CTIMER_BASE_PTRS初始化一个静态constexpr。那失败了 - 似乎 C++ 不允许在 constexpr 中进行强制转换。

B) 使用定义CTIMER_BASE_PTRS来初始化静态指针数组。没关系,但是我无法计算它的大小。

由于两种方法都失败了,我求助于静态全局变量(如 C 代码中所示)。但这可能是由于我对 C++ 的熟练程度有限。因此我想知道:

如何定义驱动程序列表ctimers[]如何定义类中的

谢谢。担

app*_*ple 1

由于reinterpret_cast常量表达式中不允许,两者都会失败*


你可以用inline static它代替。

我还使用 C++ 容器(但原始数组也可以)。

struct TimerDriver_base  {
    inline static std::array ctimers2 = CTIMER_BASE_PTRS;
    static constexpr auto size = std::tuple_size<decltype(ctimers2)>::value;
    // size is also accessible as `TimerDriver_base::ctimers2.size()`
};
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/4eq9j79fY



* 如果将命名空间范围一更改为此,它也会失败

static constexpr CTIMER_Type * ctimers[] =  CTIMER_BASE_PTRS;
Run Code Online (Sandbox Code Playgroud)