首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >c++中嵌入式系统硬件接口的体系结构

c++中嵌入式系统硬件接口的体系结构
EN

Software Engineering用户
提问于 2021-08-17 17:21:17
回答 1查看 258关注 0票数 -1

最近我花了很多时间研究“最好的”(读起来最优雅)。健壮、使用简单和资源友好的方法,为C++中的嵌入式系统开发低级别的硬件抽象。我目前的目标是想出一些方法来表示、配置和与Port交互。

以下是我发现的一些很好的参考资料:

虽然在这些资源中找到的所有方法都是好的,但我想要某种“混合”方法,它允许我:

  1. 将硬件外围设备表示为类的“实例”(例如,典型的MCU具有多个GPIO端口实例)
  2. 在项目的“配置”文件中以轻量级的方式引用这些实例(即董事会支持包)
  3. 提供一些方法来表示此外围设备的配置。
  4. 提供一种将配置“映射”到外围设备的方法。

基于这些要求,我想出了一种可行的方法,对我来说似乎“很好”。我的问题是,根据别人的经验,我所写的是“好”的方法吗?

代码语言:javascript
复制
#include <iostream>

/**
* @brief Describes what port to use
*/
class PortDescriptor {
public:
    constexpr PortDescriptor(unsigned int* p) : _p(p) {}
    
    inline unsigned int* ptr() const { return _p; }
    
private:
    unsigned int* _p;
};

/**
* @brief Describes what pin within a port to use
*/
class PinDescriptor {
public:
    constexpr PinDescriptor(const PortDescriptor& port, unsigned int pin) :
        _port(port),
        _pin(pin)
    {
        
    }
    
    inline const PortDescriptor& port() const { return _port; }
    inline unsigned int index() const { return _pin; }
    
private:
    const PortDescriptor& _port;
    unsigned int _pin;
};

/**
* @brief Describes the configuration for a portpin
*/
class PinConfiguration {
public:
    enum class Mode {
        INPUT,
        OUTPUT,
        ANALOG
    };
    
    enum class Pull {
        NONE,
        UP,
        DOWN
    };
    
    //Default constructor
    constexpr PinConfiguration() :
        _mode(Mode::OUTPUT),
        _openDrain(false),
        _pull(Pull::NONE)
    {
        
    }
    
    //Builder methods
    constexpr PinConfiguration& setMode(Mode v) { _mode = v; return *this; }
    constexpr PinConfiguration& setOpenDrain(bool v) { _openDrain = v; return *this; }
    constexpr PinConfiguration& setPull(Pull v) { _pull = v; return *this; }
    
    //Accessors
    inline constexpr Mode mode() const { return _mode; }
    inline constexpr bool openDrain() const { return _openDrain; }
    inline constexpr Pull pull() const { return _pull; }
    
private:
    Mode _mode;
    bool _openDrain;
    Pull _pull;
};

/**
* @brief Class which represents a port peripheral within the MCU
*
* "Class overlay" will be used to map this class onto the actual hardware
* memory address.
*/
class Port {
public:
    void configurePin(const PinDescriptor& pin, const PinConfiguration& config) {
        std::cout << "port=" << pin.port().ptr() << " pin=" << pin.index() << std::endl;
        
        //Example code
        _modeRegister |= static_cast<unsigned int>(config.mode()) << (pin.index() * 2);
        _drainRegister |= static_cast<unsigned int>(config.openDrain()) << (pin.index());
        _pullRegister |= static_cast<unsigned int>(config.pull()) << (pin.index() * 2);
    }
    
    static Port* get(const PortDescriptor& p) { return reinterpret_cast<Port*>(p.ptr()); }
    static Port* get(const PinDescriptor& p) { return reinterpret_cast<Port*>(p.port().ptr()); }
    
private:
    unsigned int _modeRegister;
    unsigned int _drainRegister;
    unsigned int _pullRegister;
};

//------------------------------------------------------------------------------

//Fake peripheral registers (would normally be actual hardware registers)
unsigned int porta_registers[3];
unsigned int portb_registers[3];

//Available ports
static constexpr PortDescriptor PORTA(porta_registers);
static constexpr PortDescriptor PORTB(portb_registers);

//Available pins
static constexpr PinDescriptor PA0(PORTA, 0);
static constexpr PinDescriptor PA1(PORTA, 1);
static constexpr PinDescriptor PA2(PORTA, 2);

static constexpr PinDescriptor PB0(PORTB, 0);
static constexpr PinDescriptor PB1(PORTB, 1);
static constexpr PinDescriptor PB2(PORTB, 2);

//------------------------------------------------------------------------------

//Example configuration file for a project making use of the above HAL
static constexpr PinDescriptor RED_LED_PIN = PA0;
static constexpr PinConfiguration RED_LED_PIN_CONFIG = PinConfiguration().setMode(PinConfiguration::Mode::OUTPUT);

static constexpr PinDescriptor GREEN_LED_PIN = PB2;
static constexpr PinConfiguration GREEN_LED_PIN_CONFIG = PinConfiguration().setMode(PinConfiguration::Mode::OUTPUT).setOpenDrain(true);

int main() {
    std::cout << "TEST 1" << std::endl;
    
    std::cout << "porta_registers[0]=" << porta_registers[0] << std::endl;
    std::cout << "porta_registers[1]=" << porta_registers[1] << std::endl;
    std::cout << "porta_registers[2]=" << porta_registers[2] << std::endl;
    
    Port::get(RED_LED_PIN)->configurePin(RED_LED_PIN, RED_LED_PIN_CONFIG);
    
    std::cout << "porta_registers[0]=" << porta_registers[0] << std::endl;
    std::cout << "porta_registers[1]=" << porta_registers[1] << std::endl;
    std::cout << "porta_registers[2]=" << porta_registers[2] << std::endl;
    
    std::cout << "TEST 2" << std::endl;
    
    std::cout << "portb_registers[0]=" << portb_registers[0] << std::endl;
    std::cout << "portb_registers[1]=" << portb_registers[1] << std::endl;
    std::cout << "portb_registers[2]=" << portb_registers[2] << std::endl;
    
    Port::get(GREEN_LED_PIN)->configurePin(GREEN_LED_PIN, GREEN_LED_PIN_CONFIG);
   
    std::cout << "portb_registers[0]=" << portb_registers[0] << std::endl;
    std::cout << "portb_registers[1]=" << portb_registers[1] << std::endl;
    std::cout << "portb_registers[2]=" << portb_registers[2] << std::endl;
    
    return 0;
}

上面的例子并不代表真正的硬件代码,但希望能给您提供一般的想法。

预先感谢您的投入!

EN

回答 1

Software Engineering用户

发布于 2021-08-17 20:30:09

您是否试图为嵌入式开发设计一个框架?我会从上面开始工作下去。也就是说,首先考虑应用程序代码的需求,而不是考虑任何特定微处理器的功能。

在过去,我从顶部开始有几个界面,从而获得了很多里程。例如;

代码语言:javascript
复制
class DigitalOutput {
public:
    virtual ~DigitalOutput();
    virtual void set() = 0;
    virtual void clear() = 0;
    virtual boolean get() = 0;
};

class DigitalInput {
public:
    virtual ~DigitalInput();
    virtual boolean get() = 0;
};

class AnalogOutput {
public:
    ...
};

...

您提供的实现此类接口的所有框架都可以了解任何给定微处理器的功能。所有依赖于这些接口的应用程序代码都可以幸亏不知道它运行的硬件。该接口帮助您将这两件事分开,并且当应用程序开发人员想要测试代码的“幸福无知”部分时,它会有很大帮助。

*希望这是大多数应用程序代码。

票数 1
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/431135

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档