Программный драйвер аналого-цифрового преобразователя

Я занимаюсь разработкой программного драйвера для внутреннего аналого-цифрового преобразователя на эта платформа. Периферийное устройство аналого-цифрового преобразователя описано ниже. документ. Драйвер написан на C ++ и основан на существующем драйвере, который был разработан производителем платформы на языке C. Причина, по которой я решил обернуть существующий драйвер в C ++, заключается в том, что я хотел бы достичь состояния, в котором этот драйвер представляет собой согласованный уровень аппаратной абстракции с другими моими драйверами, уже написанными на C ++. Во время разработки драйвера я имел в виду приведенную ниже схему оборудования, которая описывает, как внутренний аналого-цифровой преобразователь будет использоваться в моем приложении.

введите описание изображения здесь

Что касается дизайна драйвера, я выбрал следующий подход:

  • Я решил инкапсулировать драйвер в класс AdcInt который предлагает интерфейс для использования аналого-цифрового преобразователя с верхнего уровня программного обеспечения. Предполагаемое использование драйвера следующее. После создания драйвера initialize вызывается метод. В update метод должен вызываться периодически (например, из задачи RTOS) с соответствующим периодом относительно выбранных физических величин. Как только метод isReady вернет true, клиентский код может начать считывать образцы a / d через getValue метод или отслеживать возникновение тревоги через isAlarmActive метод

  • в связи с тем, что периферийное устройство a / d может быть сконфигурировано разнообразным образом, я решил определить специальный класс AdcIntCfgManager который управляет этой конфигурацией, т.е. работает на
    AdcIntCfg struct (которая заполняется программистом более высокого уровня) и предлагает набор методов для получения данных конфигурации

AdcInt.h

#include "AdcIntCfgManager.h"
#include "xsysmon.h"
#include <cstdint>

class AdcInt
{
public:
  enum class Input
  {
    kChannel00,
    kChannel01,
    kChannel02,
    kChannel03,
    kChannel04,
    kChannel05,
    kChannel06,
    kChannel07,
    kChannel08,
    kChannel09,
    kChannel10,
    kChannel11,
    kChannel12,
    kNoChannels,
    kOnChipTemp,
    kVccInt,
    kVccAux,
    kVrefP,
    kVrefN,
    kVBram,
    kVccPInt,
    kVccPAux,
    kVccOddr,
    kNoInputs
  };

  AdcInt(AdcIntCfgManager *_configuration_manager, uint16_t _xadc_device_id,
         uint8_t _xadc_interrupt_id);

  void initialize();

  void update();

  bool isReady();

  bool getValue(Input input, float &var);
  
  bool isAlarmActive(AdcIntCfgManager::Alarm alarm);

  void handle_interrupt();

private:
  
  class AnalogInput
  {
  public:
    AnalogInput();

    void initialize(XSysMon *_xadc_driver, uint8_t _addr, bool _enable,
                    float _norm);

    bool isEnabled();

    float getValue();

    bool isReady();

    void notify();

  private:
    uint8_t addr;
    uint16_t value;
    float norm;
    bool enabled;
    bool ready;
    AdcIntCfgManager::ChannelType type;
    XSysMon *xadc_driver;
  };

  class Sensor
  {
  public:
    Sensor();

    void initialize(XSysMon *_xadc_driver, uint8_t _addr, bool _enable,
                    AdcIntCfgManager::OnChipSensorType _type);

    bool isEnabled();

    float getValue();

    bool isReady();

    void notify();

  private:
    uint8_t addr;
    AdcIntCfgManager::OnChipSensorType type;
    uint16_t value;
    bool enabled;
    bool ready;
    XSysMon *xadc_driver;
  };

  class Alarm
  {
  public:
    Alarm();

    void initialize(bool _enable, uint32_t _activate_mask,
                    uint32_t _deactivate_mask);

    bool isEnabled();

    bool isActive();

    void notify(uint32_t status);

  private:
    uint32_t activate_mask;
    uint32_t deactivate_mask;
    bool enabled;
    bool active;
  };

  class ChannelAddressMonitor
  {
  public:
    ChannelAddressMonitor();

    void refreshAddress();

    uint8_t getChannelAddress();

  private:
    uint8_t channel_address;
  };

  static const uint32_t NON_EXISTING_ALARM_ACTIVE_MASK = 0x00000000;
  static const uint32_t NON_EXISTING_ALARM_DEACTIVE_MASK = 0x00000000;

  static const uint64_t sensor_masks[static_cast<uint8_t>(
      AdcIntCfgManager::OnChipSensor::kNoOnChipSensors)];

  static const uint16_t calibration_masks[static_cast<uint8_t>(
      AdcIntCfgManager::Calibration::kNoCalibrations)];

  static const uint32_t
      alarm_masks[static_cast<uint8_t>(AdcIntCfgManager::Alarm::kNoAlarms)];

  static const uint16_t threshold_masks[static_cast<uint8_t>(
      AdcIntCfgManager::AlarmThresholdName::kNoAlarmThresholdNames)];

  static const uint8_t sensors_address[static_cast<uint8_t>(
      AdcIntCfgManager::OnChipSensor::kNoOnChipSensors)];

  static const uint32_t alarm_activate_masks[static_cast<uint8_t>(
      AdcIntCfgManager::Alarm::kNoAlarms)];

  static const uint32_t alarm_deactivate_masks[static_cast<uint8_t>(
      AdcIntCfgManager::Alarm::kNoAlarms)];

  static bool isEndOfSequenceInterrupt(uint32_t status);

  static bool isAlarmInterrupt(uint32_t status);

  static float temperatureRawToC(uint16_t raw_temp);

  static uint16_t temperatureCToRaw(float temp);

  static float voltageRawToV(uint16_t raw_voltage);

  static uint16_t voltageVToRaw(float voltage);

  AdcIntCfgManager *configuration_manager;
  AnalogInput analog_inputs[static_cast<uint8_t>(
      AdcIntCfgManager::Channel::kNoChannels)];
  Sensor sensors[static_cast<uint8_t>(
      AdcIntCfgManager::OnChipSensor::kNoOnChipSensors)];
  Alarm alarms[static_cast<uint8_t>(AdcIntCfgManager::Alarm::kNoAlarms)];
  ChannelAddressMonitor channel_address_monitor;

  XSysMon xadc_driver;
  uint16_t xadc_device_id;
  uint8_t xadc_interrupt_id;

  void startConversion();

  bool isBusy();

  bool getChannelValue(AdcIntCfgManager::Channel channel, float &var);

  bool getOnChipSensorValue(AdcIntCfgManager::OnChipSensor sensor, float &var);

  int configureSequencerChannels(uint64_t channels_mask);

  int configureSettlingTime(uint64_t channels_mask);

  void configureCalibration();

  void configureAlarms();

  void configureLowerAlarmThreshold(AdcIntCfgManager::Alarm alarm);

  void configureUpperAlarmThreshold(AdcIntCfgManager::Alarm alarm);

  void configureOperMode();

  void configureInterrupts();

  void initializeAnalogInputs();

  void initializeSensors();

  void initializeAlarms();

  void notifySensors();

  void notifyAlarms(uint32_t status);

  uint64_t getChannelsMask();

  uint16_t getCalibrationMask();

  uint32_t getAlarmMask();

  uint16_t getAlarmThresholdLowerMask(AdcIntCfgManager::Alarm alarm);

  uint16_t getAlarmThresholdUpperMask(AdcIntCfgManager::Alarm alarm);

  uint32_t getAlarmActivateMask(AdcIntCfgManager::Alarm alarm);

  uint32_t getAlarmDeactivateMask(AdcIntCfgManager::Alarm alarm);

  uint32_t getAlarmsInterruptEnableMask();

  uint8_t getOnChipSensorAddress(AdcIntCfgManager::OnChipSensor sensor);

};

AdcInt.cpp

#include "AdcInt.h"
#include <iostream>

using namespace std;

const uint64_t AdcInt::sensor_masks[static_cast<uint8_t>(
    AdcIntCfgManager::OnChipSensor::kNoOnChipSensors)] = {
    XSM_SEQ_CH_TEMP,    XSM_SEQ_CH_VCCINT,  XSM_SEQ_CH_VCCAUX,
    XSM_SEQ_CH_VREFP,   XSM_SEQ_CH_VREFN,   XSM_SEQ_CH_VBRAM,
    XSM_SEQ_CH_VCCPINT, XSM_SEQ_CH_VCCPAUX, XSM_SEQ_CH_VCCPDRO};

const uint16_t AdcInt::calibration_masks[static_cast<uint8_t>(
    AdcIntCfgManager::Calibration::kNoCalibrations)] = {
    XSM_CFR1_CAL_ADC_OFFSET_MASK, XSM_CFR1_CAL_ADC_GAIN_OFFSET_MASK,
    XSM_CFR1_CAL_PS_OFFSET_MASK, XSM_CFR1_CAL_PS_GAIN_OFFSET_MASK};

const uint32_t AdcInt::alarm_masks[static_cast<uint8_t>(
    AdcIntCfgManager::Alarm::kNoAlarms)] = {
    XSM_CFR_OT_MASK,          XSM_CFR_ALM_TEMP_MASK,   XSM_CFR_ALM_VCCINT_MASK,
    XSM_CFR_ALM_VCCAUX_MASK,  XSM_CFR_ALM_VBRAM_MASK,  XSM_CFR_ALM_VCCPINT_MASK,
    XSM_CFR_ALM_VCCPAUX_MASK, XSM_CFR_ALM_VCCPDRO_MASK};

const uint16_t AdcInt::threshold_masks[static_cast<uint8_t>(
    AdcIntCfgManager::AlarmThresholdName::kNoAlarmThresholdNames)] = {
    XSM_ATR_TEMP_UPPER,    XSM_ATR_VCCINT_UPPER,  XSM_ATR_VCCAUX_UPPER,
    XSM_ATR_OT_UPPER,      XSM_ATR_TEMP_LOWER,    XSM_ATR_VCCINT_LOWER,
    XSM_ATR_VCCAUX_LOWER,  XSM_ATR_OT_LOWER,      XSM_ATR_VBRAM_UPPER,
    XSM_ATR_VCCPINT_UPPER, XSM_ATR_VCCPAUX_UPPER, XSM_ATR_VCCPDRO_UPPER,
    XSM_ATR_VBRAM_LOWER,   XSM_ATR_VCCPINT_LOWER, XSM_ATR_VCCPAUX_LOWER,
    XSM_ATR_VCCPDRO_LOWER};

const uint8_t AdcInt::sensors_address[static_cast<uint8_t>(
    AdcIntCfgManager::OnChipSensor::kNoOnChipSensors)] = {
    XSM_CH_TEMP,  XSM_CH_VCCINT,   XSM_CH_VCCAUX,  XSM_CH_VREFP,  XSM_CH_VREFN,
    XSM_CH_VBRAM, XSM_CH_VCCLPINT, XSM_CH_VCCPAUX, XSM_CH_VCCPDRO};

const uint32_t AdcInt::alarm_activate_masks[static_cast<uint8_t>(
    AdcIntCfgManager::Alarm::kNoAlarms)] = {XSM_IPIXR_OT_MASK,
                                            XSM_IPIXR_TEMP_MASK,
                                            XSM_IPIXR_VCCINT_MASK,
                                            XSM_IPIXR_VCCAUX_MASK,
                                            XSM_IPIXR_VBRAM_MASK,
                                            NON_EXISTING_ALARM_ACTIVE_MASK,
                                            NON_EXISTING_ALARM_ACTIVE_MASK,
                                            NON_EXISTING_ALARM_ACTIVE_MASK};

const uint32_t AdcInt::alarm_deactivate_masks[static_cast<uint8_t>(
    AdcIntCfgManager::Alarm::kNoAlarms)] = {
    XSM_IPIXR_OT_DEACTIVE_MASK,       XSM_IPIXR_TEMP_DEACTIVE_MASK,
    NON_EXISTING_ALARM_DEACTIVE_MASK, NON_EXISTING_ALARM_DEACTIVE_MASK,
    NON_EXISTING_ALARM_DEACTIVE_MASK, NON_EXISTING_ALARM_DEACTIVE_MASK,
    NON_EXISTING_ALARM_DEACTIVE_MASK, NON_EXISTING_ALARM_DEACTIVE_MASK};

AdcInt::AdcInt(AdcIntCfgManager *_configuration_manager,
               uint16_t _xadc_device_id, uint8_t _xadc_interrupt_id)
{
  configuration_manager = _configuration_manager;
  xadc_device_id = _xadc_device_id;
  xadc_interrupt_id = _xadc_interrupt_id;
}

void AdcInt::initialize()
{
  XSysMon_Config *xadc_cfg;
  int oper_result;
  uint64_t channels_mask;

  xadc_cfg = XSysMon_LookupConfig(xadc_device_id);
  if (xadc_cfg == NULL) {
    cout << "xadc device id hasn't been found" << endl;
  } else {
    oper_result =
        XSysMon_CfgInitialize(&xadc_driver, xadc_cfg, xadc_cfg->BaseAddress);
    if (oper_result != XST_SUCCESS) {
        cout << "xadc driver initialization failed" << endl;
    } else {
      channels_mask = getChannelsMask();
      oper_result = configureSequencerChannels(channels_mask);
      if (oper_result != XST_SUCCESS) {
        cout << "xadc sequencer channels configuration failed" << endl;
      } else {
        XSysMon_SetAdcClkDivisor(&xadc_driver,
                                 configuration_manager->getClkDivRatio());
        XSysMon_SetAvg(&xadc_driver,
                       configuration_manager->getNoAveragedSamples());
        oper_result = configureSettlingTime(channels_mask);
        if (oper_result != XST_SUCCESS) {
          cout << "xadc settling time configuration failed" << endl;
        } else {
          configureCalibration();
          configureAlarms();
          configureOperMode();
          initializeAnalogInputs();
          initializeSensors();
          initializeAlarms();
          configureInterrupts();
        }
      }
    }
  }
}

void AdcInt::update()
{
  if (isBusy() == false) {
    startConversion();
  }
}

bool AdcInt::isReady()
{
  for (AnalogInput &input : analog_inputs) {
    if (input.isReady() == false) {
      return false;
    }
  }

  for (Sensor &sensor : sensors) {
    if (sensor.isReady() == false) {
      return false;
    }
  }
  return true;
}

bool AdcInt::getValue(Input input, float &var)
{
  if (static_cast<uint8_t>(input) < static_cast<uint8_t>(Input::kNoChannels)) {
    return getChannelValue(static_cast<AdcIntCfgManager::Channel>(input), var);
  } else if ((static_cast<uint8_t>(input) >
              static_cast<uint8_t>(Input::kNoChannels)) &&
             (static_cast<uint8_t>(input) <
              static_cast<uint8_t>(Input::kNoInputs))) {
    uint8_t sensor_index = static_cast<uint8_t>(input) -
                           static_cast<uint8_t>(Input::kNoChannels) - 1;
    return getOnChipSensorValue(
        static_cast<AdcIntCfgManager::OnChipSensor>(sensor_index), var);
  } else {
    return false;
  }
}

bool AdcInt::isAlarmActive(AdcIntCfgManager::Alarm alarm)
{
  return alarms[static_cast<uint8_t>(alarm)].isActive();
}

void AdcInt::handle_interrupt()
{
  uint32_t status = XSysMon_IntrGetStatus(&xadc_driver);

  if (isEndOfSequenceInterrupt(status)) {
    analog_inputs[channel_address_monitor.getChannelAddress()].notify();
    notifySensors();
    channel_address_monitor.refreshAddress();
  } else if (isAlarmInterrupt(status)) {
    notifyAlarms(status);
  }
}

AdcInt::AnalogInput::AnalogInput()
{
  value = 0;
  ready = true;
  enabled = false;
}

void AdcInt::AnalogInput::initialize(XSysMon *_xadc_driver, uint8_t _addr,
                                     bool _enable, float _norm)
{
  addr = _addr;
  enabled = _enable;
  norm = _norm;
  xadc_driver = _xadc_driver;
}

bool AdcInt::AnalogInput::isEnabled()
{
  return enabled;
}

float AdcInt::AnalogInput::getValue()
{
  return (value / 4096.0 * norm);
}

bool AdcInt::AnalogInput::isReady()
{
  return ready;
}

void AdcInt::AnalogInput::notify()
{
  if (enabled) {
    value = XSysMon_GetAdcData(xadc_driver, addr);
  }
}

AdcInt::Sensor::Sensor()
{
  value = 0;
  ready = true;
  enabled = false;
}

void AdcInt::Sensor::initialize(XSysMon *_xadc_driver, uint8_t _addr,
                                bool _enable,
                                AdcIntCfgManager::OnChipSensorType _type)
{
  addr = _addr;
  type = _type;
  enabled = _enable;
  xadc_driver = _xadc_driver;
}

bool AdcInt::Sensor::isEnabled()
{
  return enabled;
}

float AdcInt::Sensor::getValue()
{
  float ret_val;

  if (type == AdcIntCfgManager::OnChipSensorType::kVoltageSensor) {
    ret_val = voltageRawToV(value);
  } else if (type == AdcIntCfgManager::OnChipSensorType::kTemperatureSensor) {
    ret_val = temperatureRawToC(value);
  }

  return ret_val;
}

bool AdcInt::Sensor::isReady()
{
  return ready;
}

void AdcInt::Sensor::notify()
{
  if (enabled) {
    value = XSysMon_GetAdcData(xadc_driver, addr);
  }
}

AdcInt::Alarm::Alarm()
{
  active = false;
  enabled = false;
}

void AdcInt::Alarm::initialize(bool _enable, uint32_t _activate_mask,
                               uint32_t _deactivate_mask)
{
  activate_mask = _activate_mask;
  deactivate_mask = _deactivate_mask;
  enabled = _enable;
}

bool AdcInt::Alarm::isEnabled()
{
  return enabled;
}

bool AdcInt::Alarm::isActive()
{
  return active;
}

void AdcInt::Alarm::notify(uint32_t status)
{
  if (enabled) {
    if (status & activate_mask) {
      active = true;
    } else if (status & deactivate_mask) {
      active = false;
    }
  }
}

AdcInt::ChannelAddressMonitor::ChannelAddressMonitor()
{
  channel_address = 0;
}

void AdcInt::ChannelAddressMonitor::refreshAddress()
{
  if (++channel_address ==
      static_cast<uint8_t>(AdcIntCfgManager::Channel::kNoChannels)) {
    channel_address = 0;
  }
}

uint8_t AdcInt::ChannelAddressMonitor::getChannelAddress()
{
  return channel_address;
}

void AdcInt::startConversion()
{
  XSysMon_StartAdcConversion(&xadc_driver);
}

bool AdcInt::isBusy()
{
  return ((XSysMon_GetStatus(&xadc_driver) & XSM_SR_BUSY_MASK) != 0);
}

bool AdcInt::getChannelValue(AdcIntCfgManager::Channel channel, float &var)
{
  bool enabled = false;
  uint8_t index = static_cast<uint8_t>(channel);
  if (analog_inputs[index].isEnabled()) {
    var = analog_inputs[index].getValue();
    enabled = true;
  }
  return enabled;
}

bool AdcInt::getOnChipSensorValue(AdcIntCfgManager::OnChipSensor sensor,
                                  float &var)
{
  bool enabled = false;
  uint8_t index = static_cast<uint8_t>(sensor);
  if (sensors[index].isEnabled()) {
    var = sensors[index].getValue();
    enabled = true;
  }
  return enabled;
}

bool AdcInt::isEndOfSequenceInterrupt(uint32_t status)
{
  if (status & XSM_IPIXR_EOS_MASK) {
    return true;
  } else {
    return false;
  }
}

bool AdcInt::isAlarmInterrupt(uint32_t status)
{
  if ((status & XSM_IPIXR_VBRAM_MASK) |
      (status & XSM_IPIXR_TEMP_DEACTIVE_MASK) |
      (status & XSM_IPIXR_OT_DEACTIVE_MASK) | (status & XSM_IPIXR_VCCAUX_MASK) |
      (status & XSM_IPIXR_VCCINT_MASK) | (status & XSM_IPIXR_TEMP_MASK) |
      (status & XSM_IPIXR_OT_MASK)) {
    return true;
  } else {
    return false;
  }
}

float AdcInt::temperatureRawToC(uint16_t raw_temp)
{
  // see ug480 on page 33
  return ((raw_temp * 503.975) / 4096.0 - 273.15);
}

uint16_t AdcInt::temperatureCToRaw(float temp)
{
  // see ug480 on page 33
  return (4096.0 * (temp + 273.15) / 503.975);
}

float AdcInt::voltageRawToV(uint16_t raw_voltage)
{
  // see ug480 on page 34
  return (raw_voltage * 3.0 / 4096.0);
}

uint16_t AdcInt::voltageVToRaw(float voltage)
{
  // see ug480 on page 34
  return (voltage * 4096.0 / 3.0);
}

int AdcInt::configureSequencerChannels(uint64_t channels_mask)
{
  // disable sequencer before configuration (please see the xsysmon_extmux_example.c from Xilinx)
  XSysMon_SetSequencerMode(&xadc_driver, XSM_SEQ_MODE_SAFE);
  int oper_result = XSysMon_SetSeqChEnables(&xadc_driver, channels_mask);
  return oper_result;
}

int AdcInt::configureSettlingTime(uint64_t channels_mask)
{
  int oper_result = XST_SUCCESS;
  if (configuration_manager->isIncreasedSettlingTimeEnabled()) {
    oper_result = XSysMon_SetSeqAcqTime(&xadc_driver, channels_mask);
  }
  return oper_result;
}

void AdcInt::configureCalibration()
{
  uint16_t calibration_mask = getCalibrationMask();
  XSysMon_SetCalibEnables(&xadc_driver, calibration_mask);
}

void AdcInt::configureAlarms()
{
  uint32_t alarms_mask = getAlarmMask();
  XSysMon_SetAlarmEnables(&xadc_driver, alarms_mask);

  for (uint8_t alarm = 0;
       alarm < static_cast<uint8_t>(AdcIntCfgManager::Alarm::kNoAlarms);
       alarm++) {
    if (configuration_manager->isAlarmEnabled(
            static_cast<AdcIntCfgManager::Alarm>(alarm))) {
      configureLowerAlarmThreshold(static_cast<AdcIntCfgManager::Alarm>(alarm));
      configureUpperAlarmThreshold(static_cast<AdcIntCfgManager::Alarm>(alarm));
    }
  }
}

void AdcInt::configureLowerAlarmThreshold(AdcIntCfgManager::Alarm alarm)
{
  float threshold;
  uint8_t threshold_mask;
  uint16_t raw_threshold;

  threshold = configuration_manager->getAlarmThresholdLower(alarm);
  threshold_mask = getAlarmThresholdLowerMask(alarm);
  if (configuration_manager->getAlarmType(alarm) ==
      AdcIntCfgManager::AlarmType::kTemperatureAlarm) {
    raw_threshold = temperatureCToRaw(threshold);
  } else if (configuration_manager->getAlarmType(alarm) ==
             AdcIntCfgManager::AlarmType::kVoltageAlarm) {
    raw_threshold = voltageVToRaw(threshold);
  }
  XSysMon_SetAlarmThreshold(&xadc_driver, threshold_mask, raw_threshold);
}

void AdcInt::configureUpperAlarmThreshold(AdcIntCfgManager::Alarm alarm)
{
  float threshold;
  uint8_t threshold_mask;
  uint16_t raw_threshold;

  threshold = configuration_manager->getAlarmThresholdUpper(alarm);
  threshold_mask = getAlarmThresholdUpperMask(alarm);
  if (configuration_manager->getAlarmType(alarm) ==
      AdcIntCfgManager::AlarmType::kTemperatureAlarm) {
    raw_threshold = temperatureCToRaw(threshold);
  } else if (configuration_manager->getAlarmType(alarm) ==
             AdcIntCfgManager::AlarmType::kVoltageAlarm) {
    raw_threshold = voltageVToRaw(threshold);
  }
  XSysMon_SetAlarmThreshold(&xadc_driver, threshold_mask, raw_threshold);
}

void AdcInt::configureOperMode()
{
  // external multiplexer connection
  XSysMon_SetExtenalMux(&xadc_driver, XSM_CH_VPVN);
  // single pass mode of operation
  XSysMon_SetSequencerMode(&xadc_driver, XSM_SEQ_MODE_ONEPASS);
}

void AdcInt::configureInterrupts()
{
  XSysMon_IntrEnable(&xadc_driver,
                     XSM_IPIXR_EOS_MASK | getAlarmsInterruptEnableMask());
  XSysMon_IntrGlobalEnable(&xadc_driver);
  platform::drivers::InterruptController::instance().connect(xadc_interrupt_id,
                                                             *this);
}

void AdcInt::initializeAnalogInputs()
{
  for (uint8_t input = 0;
       input < static_cast<uint8_t>(AdcIntCfgManager::Channel::kNoChannels);
       input++) {
    analog_inputs[input].initialize(
        &xadc_driver, XSM_CH_VPVN,
        configuration_manager->isChannelEnabled(
            static_cast<AdcIntCfgManager::Channel>(input)),
        configuration_manager->getChannelNorm(
            static_cast<AdcIntCfgManager::Channel>(input)));
  }
}

void AdcInt::initializeSensors()
{
  for (uint8_t sensor = 0;
       sensor <
       static_cast<uint8_t>(AdcIntCfgManager::OnChipSensor::kNoOnChipSensors);
       sensor++) {
    sensors[sensor].initialize(
        &xadc_driver,
        getOnChipSensorAddress(
            static_cast<AdcIntCfgManager::OnChipSensor>(sensor)),
        configuration_manager->isOnChipSensorEnabled(
            static_cast<AdcIntCfgManager::OnChipSensor>(sensor)),
        configuration_manager->getSensorType(
            static_cast<AdcIntCfgManager::OnChipSensor>(sensor)));
  }
}

void AdcInt::initializeAlarms()
{
  for (uint8_t alarm = 0;
       alarm < static_cast<uint8_t>(AdcIntCfgManager::Alarm::kNoAlarms);
       alarm++) {
    alarms[alarm].initialize(
        configuration_manager->isAlarmEnabled(
            static_cast<AdcIntCfgManager::Alarm>(alarm)),
        getAlarmActivateMask(static_cast<AdcIntCfgManager::Alarm>(alarm)),
        getAlarmDeactivateMask(static_cast<AdcIntCfgManager::Alarm>(alarm)));
  }
}

void AdcInt::notifySensors()
{
  for (Sensor &sensor : sensors) {
    sensor.notify();
  }
}

void AdcInt::notifyAlarms(uint32_t status)
{
  for (Alarm &alarm : alarms) {
    alarm.notify(status);
  }
}

uint64_t AdcInt::getChannelsMask()
{
  uint64_t channels_mask = 0;

  if (configuration_manager->isCalibrationEnabled()) {
    channels_mask |= XSM_SEQ_CH_CALIB;
  }

  for (uint8_t sensor = 0;
       sensor <
       static_cast<uint8_t>(AdcIntCfgManager::OnChipSensor::kNoOnChipSensors);
       sensor++) {
    if (configuration_manager->isOnChipSensorEnabled(
            static_cast<AdcIntCfgManager::OnChipSensor>(sensor))) {
      channels_mask |= sensor_masks[sensor];
    }
  }

  // external multiplexer connection
  channels_mask |= XSM_SEQ_CH_VPVN;

  return channels_mask;
}

uint16_t AdcInt::getCalibrationMask()
{
  uint16_t calibration_mask = 0;

  for (uint8_t calibration = 0;
       calibration <
       static_cast<uint8_t>(AdcIntCfgManager::Calibration::kNoCalibrations);
       calibration++) {
    if (configuration_manager->isCalibrationTypeEnabled(
            static_cast<AdcIntCfgManager::Calibration>(calibration))) {
      calibration_mask |= calibration_masks[calibration];
    }
  }

  return calibration_mask;
}

uint32_t AdcInt::getAlarmMask()
{
  uint32_t alarm_mask = 0;

  for (uint8_t alarm = 0;
       alarm < static_cast<uint8_t>(AdcIntCfgManager::Alarm::kNoAlarms);
       alarm++) {
    if (configuration_manager->isAlarmEnabled(
            static_cast<AdcIntCfgManager::Alarm>(alarm))) {
      alarm_mask |= alarm_masks[alarm];
    }
  }

  return alarm_mask;
}

uint16_t AdcInt::getAlarmThresholdLowerMask(AdcIntCfgManager::Alarm alarm)
{
  return (threshold_masks[static_cast<uint8_t>(
      configuration_manager->getAlarmLowerThresholdName(alarm))]);
}

uint16_t AdcInt::getAlarmThresholdUpperMask(AdcIntCfgManager::Alarm alarm)
{
  return (threshold_masks[static_cast<uint8_t>(
      configuration_manager->getAlarmUpperThresholdName(alarm))]);
}

uint32_t AdcInt::getAlarmActivateMask(AdcIntCfgManager::Alarm alarm)
{
  return alarm_activate_masks[static_cast<uint8_t>(alarm)];
}

uint32_t AdcInt::getAlarmDeactivateMask(AdcIntCfgManager::Alarm alarm)
{
  return alarm_deactivate_masks[static_cast<uint8_t>(alarm)];
}

uint32_t AdcInt::getAlarmsInterruptEnableMask()
{
  uint32_t alarms_interrupt_enable_mask = 0;
  for (uint8_t alarm = 0;
       alarm < static_cast<uint8_t>(AdcIntCfgManager::Alarm::kNoAlarms);
       alarm++) {
    if (configuration_manager->isAlarmEnabled(
            static_cast<AdcIntCfgManager::Alarm>(alarm))) {
      alarms_interrupt_enable_mask |= alarm_activate_masks[alarm];
    }
  }
  return alarms_interrupt_enable_mask;
}

uint8_t AdcInt::getOnChipSensorAddress(AdcIntCfgManager::OnChipSensor sensor)
{
  return sensors_address[static_cast<uint8_t>(sensor)];
}

AdcIntCfgManager.h

#include <cstdint>

class AdcIntCfgManager
{
public:
  enum class Channel {
    kChannel00,
    kChannel01,
    kChannel02,
    kChannel03,
    kChannel04,
    kChannel05,
    kChannel06,
    kChannel07,
    kChannel08,
    kChannel09,
    kChannel10,
    kChannel11,
    kChannel12,
    kNoChannels
  };

  enum class OnChipSensor {
    kOnChipTemp,
    kVccInt,
    kVccAux,
    kVrefP,
    kVrefN,
    kVBram,
    kVccPInt,
    kVccPAux,
    kVccOddr,
    kNoOnChipSensors
  };

  enum class ChannelType { kUnipolar, kBipolar };

  enum class ChannelEnable { kChannelDisabled, kChannelEnabled };

  struct ChannelCfg
  {
    Channel channel;
    ChannelType type;
    ChannelEnable enable;
    float norm;
  };

  enum class AdcClockDivRatio {
    kADCCLK_DCLK_DIV_002, 
    kADCCLK_DCLK_DIV_003 = 3, 
    kADCCLK_DCLK_DIV_004 = 4, 
    kADCCLK_DCLK_DIV_255 = 255 
  };

  enum class OnChipSensorType { kVoltageSensor, kTemperatureSensor };

  enum class OnChipSensorEnable { kSensorDisabled, kSensorEnabled };

  struct OnChipSensorsCfg
  {
    OnChipSensor sensor;
    OnChipSensorType type;
    OnChipSensorEnable enable;
  };

  enum class Averaging {
    kAveragingFrom_0_Samples,
    kAveragingFrom_16_Samples,
    kAveragingFrom_64_Samples,
    kAveragingFrom_256_Samples
  };

  enum class Calibration {
    kAdcOffsetCorrection,
    kAdcOffsetGainCorrection,
    kSupplySensorOffsetCorrection,
    kSupplySensorOffsetGainCorrection,
    kNoCalibrations
  };

  enum class CalibrationEnable { kCalibrationDisabled, kCalibrationEnabled };

  struct CalibrationCfg
  {
    Calibration calibration;
    CalibrationEnable enable;
  };

  enum class SettlingTime { kSettlingTime_4_ADCCLK, kSettlingTime_10_ADCCLK };

  enum class Alarm {
    kOverTemperature,
    kOnChipTemperature,
    kVccInt,
    kVccAux,
    kVBram,
    kVccPInt,
    kVccPAux,
    kVccOddr,
    kNoAlarms
  };

  enum class AlarmType { kTemperatureAlarm, kVoltageAlarm };

  enum class AlarmEnable { kAlarmDisabled, kAlarmEnabled };

  enum class AlarmThresholdName {
    kOnChipTemperatureUpper,
    kVccIntUpper,
    kVccAuxUpper,
    kOverTemperatureSet,
    kOnChipTemperatureLower,
    kVccIntLower,
    kVccAuxLower,
    kOverTemperatureReset,
    kVBramUpper,
    kVccPIntUpper,
    kVccPAuxUpper,
    kVccOddrUpper,
    kVBramLower,
    kVccPIntLower,
    kVccPAuxLower,
    kVccOddrLower,
    kNoAlarmThresholdNames
  };

  struct AlarmThreshold
  {
    AlarmThresholdName name;
    float value;
  };

  struct AlarmsCfg
  {
    Alarm alarm;
    AlarmType type;
    AlarmEnable enable;
    AlarmThreshold lower_threshold;
    AlarmThreshold upper_threshold;
  };

  struct AdcIntCfg
  {
    ChannelCfg channels_cfg[static_cast<uint8_t>(
        Channel::
            kNoChannels)]; 
    OnChipSensorsCfg sensors_cfg[static_cast<uint8_t>(
        OnChipSensor::kNoOnChipSensors)]; 
    AdcClockDivRatio
        clock_div_ratio; 
    SettlingTime settling_time; 
    Averaging averaging; 
    CalibrationCfg calibration_cfg[static_cast<uint8_t>(
        Calibration::kNoCalibrations)]; 
    AlarmsCfg alarms_cfg[static_cast<uint8_t>(
        Alarm::
            kNoAlarms)]; 
  };

  AdcIntCfgManager(const AdcIntCfg *_configuration);

  uint8_t getClkDivRatio();

  bool isIncreasedSettlingTimeEnabled();

  uint8_t getNoAveragedSamples();

  bool isCalibrationEnabled();

  bool isCalibrationTypeEnabled(Calibration type);

  bool isAlarmEnabled(Alarm alarm);

  float getAlarmThresholdLower(Alarm alarm);

  float getAlarmThresholdUpper(Alarm alarm);

  AlarmType getAlarmType(Alarm alarm);

  AlarmThresholdName getAlarmLowerThresholdName(Alarm alarm);

  AlarmThresholdName getAlarmUpperThresholdName(Alarm alarm);

  bool isChannelEnabled(Channel channel);

  ChannelType getChannelType(Channel channel);

  float getChannelNorm(Channel channel);

  bool isOnChipSensorEnabled(OnChipSensor sensor);

  OnChipSensorType getSensorType(OnChipSensor sensor);

private:

  const AdcIntCfg *configuration;

};

AdcIntCfgManager.cpp

#include "AdcIntCfgManager.h"

AdcIntCfgManager::AdcIntCfgManager(const AdcIntCfg *_configuration)
{
  configuration = _configuration;
}

uint8_t AdcIntCfgManager::getClkDivRatio()
{
  return static_cast<uint8_t>(configuration->clock_div_ratio);
}

bool AdcIntCfgManager::isIncreasedSettlingTimeEnabled()
{
  return (configuration->settling_time ==
          SettlingTime::kSettlingTime_10_ADCCLK);
}

uint8_t AdcIntCfgManager::getNoAveragedSamples()
{
  return static_cast<uint8_t>(configuration->averaging);
}

bool AdcIntCfgManager::isCalibrationEnabled()
{
  bool ret_val = false;

  for (uint8_t i = 0; i < static_cast<uint8_t>(Calibration::kNoCalibrations);
       i++) {
    if (configuration->calibration_cfg[i].enable ==
        CalibrationEnable::kCalibrationEnabled) {
      ret_val = true;
      break;
    }
  }
  return ret_val;
}

bool AdcIntCfgManager::isCalibrationTypeEnabled(Calibration type)
{
  if (configuration->calibration_cfg[static_cast<uint8_t>(type)].enable ==
      CalibrationEnable::kCalibrationEnabled) {
    return true;
  } else {
    return false;
  }
}

bool AdcIntCfgManager::isAlarmEnabled(Alarm alarm)
{
  return (configuration->alarms_cfg[static_cast<uint8_t>(alarm)].enable ==
          AlarmEnable::kAlarmEnabled);
}

float AdcIntCfgManager::getAlarmThresholdLower(Alarm alarm)
{
  return (configuration->alarms_cfg[static_cast<uint8_t>(alarm)]
              .lower_threshold.value);
}

float AdcIntCfgManager::getAlarmThresholdUpper(Alarm alarm)
{
  return (configuration->alarms_cfg[static_cast<uint8_t>(alarm)]
              .upper_threshold.value);
}

AdcIntCfgManager::AlarmType AdcIntCfgManager::getAlarmType(Alarm alarm)
{
  return (configuration->alarms_cfg[static_cast<uint8_t>(alarm)].type);
}

AdcIntCfgManager::AlarmThresholdName
AdcIntCfgManager::getAlarmLowerThresholdName(Alarm alarm)
{
  return (configuration->alarms_cfg[static_cast<uint8_t>(alarm)]
              .lower_threshold.name);
}

AdcIntCfgManager::AlarmThresholdName
AdcIntCfgManager::getAlarmUpperThresholdName(Alarm alarm)
{
  return (configuration->alarms_cfg[static_cast<uint8_t>(alarm)]
              .upper_threshold.name);
}

bool AdcIntCfgManager::isChannelEnabled(Channel channel)
{
  if (configuration->channels_cfg[static_cast<uint8_t>(channel)].enable ==
      ChannelEnable::kChannelEnabled) {
    return true;
  } else {
    return false;
  }
}

float AdcIntCfgManager::getChannelNorm(Channel channel)
{
  return (configuration->channels_cfg[static_cast<uint8_t>(channel)].norm);
}

AdcIntCfgManager::ChannelType AdcIntCfgManager::getChannelType(Channel channel)
{
  return (configuration->channels_cfg[static_cast<uint8_t>(channel)].type);
}

bool AdcIntCfgManager::isOnChipSensorEnabled(OnChipSensor sensor)
{
  if (configuration->sensors_cfg[static_cast<uint8_t>(sensor)].enable ==
      OnChipSensorEnable::kSensorEnabled) {
    return true;
  } else {
    return false;
  }
}

AdcIntCfgManager::OnChipSensorType
AdcIntCfgManager::getSensorType(OnChipSensor sensor)
{
  return (configuration->sensors_cfg[static_cast<uint8_t>(sensor)].type);
}

Предполагаемое использование драйвера следующее:

  • вся информация о конфигурации находится в FpgaPeripheralsCfg класс
  • экземпляр AdcInt находится вместе с экземплярами других драйверов в «контейнере» FpgaDrivers

FpgaPeripheralsCfg.h

#include "AdcIntCfgManager.h"

class FpgaPeripheralsCfg
{
public:
  AdcIntCfgManager adc_int_cfg_manager;
  
  FpgaPeripheralsCfg() :
    adc_int_cfg_manager(&adc_int_cfg)
  {
  }

private:
  AdcIntCfgManager::AdcIntCfg adc_int_cfg = {
      {{AdcIntCfgManager::Channel::kChannel00,
        AdcIntCfgManager::ChannelType::kBipolar,
        AdcIntCfgManager::ChannelEnable::kChannelEnabled, 100.0},
       {AdcIntCfgManager::Channel::kChannel01,
        AdcIntCfgManager::ChannelType::kBipolar,
        AdcIntCfgManager::ChannelEnable::kChannelEnabled, 100.0},
       {AdcIntCfgManager::Channel::kChannel02,
        AdcIntCfgManager::ChannelType::kBipolar,
        AdcIntCfgManager::ChannelEnable::kChannelEnabled, 100.0},
       {AdcIntCfgManager::Channel::kChannel03,
        AdcIntCfgManager::ChannelType::kBipolar,
        AdcIntCfgManager::ChannelEnable::kChannelEnabled, 100.0},
       {AdcIntCfgManager::Channel::kChannel04,
        AdcIntCfgManager::ChannelType::kBipolar,
        AdcIntCfgManager::ChannelEnable::kChannelEnabled, 100.0},
       {AdcIntCfgManager::Channel::kChannel05,
        AdcIntCfgManager::ChannelType::kBipolar,
        AdcIntCfgManager::ChannelEnable::kChannelEnabled, 100.0},
       {AdcIntCfgManager::Channel::kChannel06,
        AdcIntCfgManager::ChannelType::kBipolar,
        AdcIntCfgManager::ChannelEnable::kChannelEnabled, 100.0},
       {AdcIntCfgManager::Channel::kChannel07,
        AdcIntCfgManager::ChannelType::kBipolar,
        AdcIntCfgManager::ChannelEnable::kChannelEnabled, 100.0},
       {AdcIntCfgManager::Channel::kChannel08,
        AdcIntCfgManager::ChannelType::kBipolar,
        AdcIntCfgManager::ChannelEnable::kChannelEnabled, 100.0},
       {AdcIntCfgManager::Channel::kChannel09,
        AdcIntCfgManager::ChannelType::kBipolar,
        AdcIntCfgManager::ChannelEnable::kChannelEnabled, 100.0},
       {AdcIntCfgManager::Channel::kChannel10,
        AdcIntCfgManager::ChannelType::kBipolar,
        AdcIntCfgManager::ChannelEnable::kChannelEnabled, 100.0},
       {AdcIntCfgManager::Channel::kChannel11,
        AdcIntCfgManager::ChannelType::kBipolar,
        AdcIntCfgManager::ChannelEnable::kChannelEnabled, 100.0},
       {AdcIntCfgManager::Channel::kChannel12,
        AdcIntCfgManager::ChannelType::kUnipolar,
        AdcIntCfgManager::ChannelEnable::kChannelEnabled, 3.0}},
      {{AdcIntCfgManager::OnChipSensor::kOnChipTemp,
        AdcIntCfgManager::OnChipSensorType::kTemperatureSensor,
        AdcIntCfgManager::OnChipSensorEnable::kSensorEnabled},
       {AdcIntCfgManager::OnChipSensor::kVccInt,
        AdcIntCfgManager::OnChipSensorType::kVoltageSensor,
        AdcIntCfgManager::OnChipSensorEnable::kSensorEnabled},
       {AdcIntCfgManager::OnChipSensor::kVccAux,
        AdcIntCfgManager::OnChipSensorType::kVoltageSensor,
        AdcIntCfgManager::OnChipSensorEnable::kSensorEnabled},
       {AdcIntCfgManager::OnChipSensor::kVrefP,
        AdcIntCfgManager::OnChipSensorType::kVoltageSensor,
        AdcIntCfgManager::OnChipSensorEnable::kSensorEnabled},
       {AdcIntCfgManager::OnChipSensor::kVrefN,
        AdcIntCfgManager::OnChipSensorType::kVoltageSensor,
        AdcIntCfgManager::OnChipSensorEnable::kSensorEnabled},
       {AdcIntCfgManager::OnChipSensor::kVBram,
        AdcIntCfgManager::OnChipSensorType::kVoltageSensor,
        AdcIntCfgManager::OnChipSensorEnable::kSensorEnabled},
       {AdcIntCfgManager::OnChipSensor::kVccPInt,
        AdcIntCfgManager::OnChipSensorType::kVoltageSensor,
        AdcIntCfgManager::OnChipSensorEnable::kSensorEnabled},
       {AdcIntCfgManager::OnChipSensor::kVccPAux,
        AdcIntCfgManager::OnChipSensorType::kVoltageSensor,
        AdcIntCfgManager::OnChipSensorEnable::kSensorEnabled},
       {AdcIntCfgManager::OnChipSensor::kVccOddr,
        AdcIntCfgManager::OnChipSensorType::kVoltageSensor,
        AdcIntCfgManager::OnChipSensorEnable::kSensorEnabled}},
      .clock_div_ratio =
          AdcIntCfgManager::AdcClockDivRatio::kADCCLK_DCLK_DIV_002,
      .settling_time = AdcIntCfgManager::SettlingTime::kSettlingTime_4_ADCCLK,
      .averaging = AdcIntCfgManager::Averaging::kAveragingFrom_16_Samples,
      {{AdcIntCfgManager::Calibration::kAdcOffsetCorrection,
        AdcIntCfgManager::CalibrationEnable::kCalibrationEnabled},
       {AdcIntCfgManager::Calibration::kAdcOffsetGainCorrection,
        AdcIntCfgManager::CalibrationEnable::kCalibrationEnabled},
       {AdcIntCfgManager::Calibration::kSupplySensorOffsetCorrection,
        AdcIntCfgManager::CalibrationEnable::kCalibrationEnabled},
       {AdcIntCfgManager::Calibration::kSupplySensorOffsetGainCorrection,
        AdcIntCfgManager::CalibrationEnable::kCalibrationEnabled}},
      {{AdcIntCfgManager::Alarm::kOverTemperature,
        AdcIntCfgManager::AlarmType::kTemperatureAlarm,
        AdcIntCfgManager::AlarmEnable::kAlarmEnabled,
        {AdcIntCfgManager::AlarmThresholdName::kOverTemperatureReset, 90.0},
        {AdcIntCfgManager::AlarmThresholdName::kOverTemperatureSet, 125.0}},
       {AdcIntCfgManager::Alarm::kOnChipTemperature,
        AdcIntCfgManager::AlarmType::kTemperatureAlarm,
        AdcIntCfgManager::AlarmEnable::kAlarmEnabled,
        {AdcIntCfgManager::AlarmThresholdName::kOnChipTemperatureLower, 100.0},
        {AdcIntCfgManager::AlarmThresholdName::kOnChipTemperatureUpper, 125.0}},
       {AdcIntCfgManager::Alarm::kVccInt,
        AdcIntCfgManager::AlarmType::kVoltageAlarm,
        AdcIntCfgManager::AlarmEnable::kAlarmEnabled,
        {AdcIntCfgManager::AlarmThresholdName::kVccIntLower, 2.7},
        {AdcIntCfgManager::AlarmThresholdName::kVccIntUpper, 2.9}},
       {AdcIntCfgManager::Alarm::kVccAux,
        AdcIntCfgManager::AlarmType::kVoltageAlarm,
        AdcIntCfgManager::AlarmEnable::kAlarmEnabled,
        {AdcIntCfgManager::AlarmThresholdName::kVccAuxLower, 2.7},
        {AdcIntCfgManager::AlarmThresholdName::kVccAuxUpper, 2.9}},
       {AdcIntCfgManager::Alarm::kVBram,
        AdcIntCfgManager::AlarmType::kVoltageAlarm,
        AdcIntCfgManager::AlarmEnable::kAlarmEnabled,
        {AdcIntCfgManager::AlarmThresholdName::kVBramLower, 2.7},
        {AdcIntCfgManager::AlarmThresholdName::kVBramUpper, 2.9}},
       {AdcIntCfgManager::Alarm::kVccPInt,
        AdcIntCfgManager::AlarmType::kVoltageAlarm,
        AdcIntCfgManager::AlarmEnable::kAlarmEnabled,
        {AdcIntCfgManager::AlarmThresholdName::kVccPIntLower, 2.7},
        {AdcIntCfgManager::AlarmThresholdName::kVccPIntUpper, 2.9}},
       {AdcIntCfgManager::Alarm::kVccPAux,
        AdcIntCfgManager::AlarmType::kVoltageAlarm,
        AdcIntCfgManager::AlarmEnable::kAlarmEnabled,
        {AdcIntCfgManager::AlarmThresholdName::kVccPAuxLower, 2.7},
        {AdcIntCfgManager::AlarmThresholdName::kVccPAuxUpper, 2.9}},
       {AdcIntCfgManager::Alarm::kVccOddr,
        AdcIntCfgManager::AlarmType::kVoltageAlarm,
        AdcIntCfgManager::AlarmEnable::kAlarmEnabled,
        {AdcIntCfgManager::AlarmThresholdName::kVccOddrLower, 2.7},
        {AdcIntCfgManager::AlarmThresholdName::kVccOddrUpper, 2.9}}}};  
};

FpgaDrivers.h

#include "AdcInt.h"

class FpgaDrivers
{
public:
  AdcInt adc_int;
  
  FpgaDrivers(FpgaPeripheralsCfg &cfg);

  void initialize(void);

private:
};

FpgaDrivers.cpp

#include "FpgaDrivers.h"

FpgaDrivers::FpgaDrivers(FpgaPeripheralsCfg &cfg) :
  adc_int(&(cfg.adc_int_cfg_manager),  0, 62)
{
}

void FpgaDrivers::initialize(void)
{
  adc_int.initialize();
}

главный

int main(int argc, char** argv) {
        
    float adc_value;
    
    FpgaPeripheralsCfg fpga_peripherals_cfg;
    FpgaDrivers drivers(fpga_peripherals_cfg);
    drivers.initialize();
    
    drivers.adc_int.update();

    if(drivers.adc_int.isReady()) {
       drivers.adc_int.getValue(platform::drivers::fpga::AdcInt::Input::kChannel00, adc_value);
    }
            
    return 0;
}

Я хотел бы попросить вас в основном оценить дизайн драйвера в целом, т.е. как драйвер разделен на классы C ++ и как эти классы взаимодействуют.

1 ответ
1

const

Вам нужно больше в нескольких местах. Подобные методы:

bool isReady();
bool getValue(Input input, float &var);
bool isAlarmActive(AdcIntCfgManager::Alarm alarm);
bool isEnabled();
float getValue();
bool isReady();

все должны получить const суффикс формы

bool isReady() const;

как обещание, что метод не изменяет this. Если что-либо из вышеперечисленного делать модифицировать this, то это означает, что метод необходимо переработать или хотя бы переименовать.

Членам нравится это:

AdcIntCfgManager::ChannelType type;
XSysMon *xadc_driver;

вероятно должно быть

const AdcIntCfgManager::ChannelType type;
XSysMon *const xadc_driver;

чтобы указать гарантию того, что они не изменятся в течение срока службы экземпляра, даже если это сделают другие члены.

Логическая избыточность

if (isBusy() == false) {

должно быть

if (!isBusy()) {

и

  if (status & XSM_IPIXR_EOS_MASK) {
    return true;
  } else {
    return false;
  }

должно быть

return status & XSM_IPIXR_EOS_MASK != 0;

его родитель

return (value / 4096.0 * norm);

не требует внешних скобок.

Комбинированное сравнение масок

  if ((status & XSM_IPIXR_VBRAM_MASK) |
      (status & XSM_IPIXR_TEMP_DEACTIVE_MASK) |
      (status & XSM_IPIXR_OT_DEACTIVE_MASK) | (status & XSM_IPIXR_VCCAUX_MASK) |
      (status & XSM_IPIXR_VCCINT_MASK) | (status & XSM_IPIXR_TEMP_MASK) |
      (status & XSM_IPIXR_OT_MASK)) {

можно упростить, сохранив константу комбинированной маски в другом месте:

const int INTERRUPT_MASK =
      XSM_IPIXR_VBRAM_MASK
    | XSM_IPIXR_TEMP_DEACTIVE_MASK
    | XSM_IPIXR_OT_DEACTIVE_MASK
    | XSM_IPIXR_VCCAUX_MASK
    | XSM_IPIXR_VCCINT_MASK
    | XSM_IPIXR_TEMP_MASK
    | XSM_IPIXR_OT_MASK;
// ...
return status & INTERRUPT_MASK != 0;

Раннее возвращение

Скорее, чем

  int oper_result = XST_SUCCESS;
  if (configuration_manager->isIncreasedSettlingTimeEnabled()) {
    oper_result = XSysMon_SetSeqAcqTime(&xadc_driver, channels_mask);
  }
  return oper_result;

Я обычно предпочитаю стиль

    if (configuration_manager->isIncreasedSettlingTimeEnabled()) {
        return XSysMon_SetSeqAcqTime(&xadc_driver, channels_mask);
    }
    return XST_SUCCESS;

Так же,

bool AdcIntCfgManager::isCalibrationEnabled()
{
  for (uint8_t i = 0; i < static_cast<uint8_t>(Calibration::kNoCalibrations);
       i++) {
    if (configuration->calibration_cfg[i].enable ==
        CalibrationEnable::kCalibrationEnabled) {
      return true;
    }
  }
  return false;
}

Недействительные аргументы

В то время как (void) — предпочтительный способ указания функций без аргументов в C, в C ++ это избыточно и может быть просто () в строках вроде

void initialize(void);

Отступ

Подумайте о переходе к более распространенному отступу с четырьмя пробелами вместо двух.

Инициализация

Имея initialize() Метод, отделенный от вашего конструктора, является чем-то вроде анти-шаблона в C ++. Подразумевается, что между временем создания вашего класса и до его инициализации он будет в недопустимом состоянии. Попытайтесь устранить это, выполнив работу initialize() в самом конструкторе. Поскольку ни одна из ваших процедур инициализации, похоже, не способна обнаружить сбой, это легко отображается в конструкторе. Если вам нужно было указать сбой, либо используйте исключения, которые гарантировали бы отсутствие недопустимого экземпляра, либо, что менее идеально, установите флаг сбоя.

  • Большое спасибо за ваши комментарии. Они мне очень помогают, но можно сказать, что они более или менее косметические. Мне больше интересно ваше мнение по поводу архитектуры драйвера. Могу я узнать ваше мнение по этому поводу?

    — L3sek


  • 1

    Правильное использование const не является косметическим и будет иметь прямое влияние на то, насколько вы можете быть уверены в правильности программы. В противном случае, еще одна вещь в моем недавнем редактировании.

    — Райндериен

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *