как создать класс драйвера устройства C ++

Я очень хорошо знаю C, а не C ++ — и хочу создать аппаратный драйвер на C ++. Мне нужны некоторые указатели.

В C я хотел бы создать структуру с указателями на функции и соответственно заполнить указатели-функции, эфир во время выполнения или инициализацией во время компиляции {как драйверы устройств повторно инициализируются в драйверах ядра Linux}. Драйверы устройств Linux часто имеют частный элемент «драйвер», который позволяет драйверу сохранять указатель конкретной реализации (содержащий другие элементы)

Что я не знаю, как это сделать — это создать то же самое, используя классы C ++.

Мой пример был бы для последовательного порта.

Аппаратная часть драйвера — в C будет выглядеть примерно так:

struct serail_driver;
struct serial_hw_level;

struct serial_hw_level {
// points to implementation specific details
inptr_t  hw_private;

// basically pure virtual functions
int (*wrBytes)( struct serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes );
int (*rdBytes)( struct serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes );

/* there would be other member funds, but this is is a short example */
};

/* the generic serial port */
struct serial_generic_driver {
const char *name;

struct serial_hw_driver *hw_Driver;
};

/* create two serial ports at the hardware level */
struct serial_hw_level arm9_serial_port = {
.hw_private = (intptr_t)(&hw_driver_
.wr_bytes   = arm9_uart_wr_bytes,
.rd_bytes   = arm9_uart_rd_bytes
};

struct serial_hw_level usb_emulated_port = {
.hw_private = (inptr_t)(&usb_private_stuff),
.wr_bytes   = usb_serial_wr_bytes,
.rd_bytes   = usb_serial_rd_bytes
};

/* create generic serial port stuff */
struct serial_port usb_serial = {
.name = "USBSERIAL",
.hw_driver = &usb_emulated_port
};

struct serial_port hw_serial = {
.name = "HW SERIAL",
.hw_driver = &arm9_serial_port
};

Быть понятным; Мне нужны два разных уровня абстракции. Я хорошо знаю, как сделать это на прямом C — в ядре Linux — это идиотская прогулка.

Что я не знаю, как это сделать, так это обрабатывать дополнительные аппаратно-специфические вещи с помощью C ++, которые будут храниться в частных структурах данных. Кажется, что должно быть в производном классе или что-то?

Я думаю что-то вроде этого:

/* the base class */
class serial_hw_level {
intptr_t hw_private;
virtual int wr_bytes( uint8_t *pBytes, int bytes );
virtual int rd_bytes( uint8_t *pBytes, int bytes );
};

/* The generic usb serial port... */
class serial_port : public serial_hw_level {
string name;
};/* another derived class */
class usb_serial : public serial_hw_level {
int usb_endpoint;
int usb_controller;
int emualted_handshake_pins;
};

Так что у меня вроде есть VEN-диаграмма классов, мой вопрос в том, как мне это сделать в C ++. Я могу сделать это в C, это просто. Я полностью понимаю эту технику.

У меня есть два типа указателей класса, которые должны указывать на один и тот же базовый класс.

в простом C я скрываю вещи в структуре, специфичной для реализации, через ‘intptr_t private’ — который является указателем в скрытии.

Я думаю, что в C ++ это хранится в производном классе.

Эта же идея может быть расширена — и я мог бы создать класс «ByteStream» — который мог бы обрабатывать поток байтов — либо в файл, либо в последовательный порт, либо — возможно, в буфер в памяти.

Обратите внимание: я использую последовательный порт в качестве примера, но то же самое относится и к порту I2C. Я мог бы иметь порт I2C, реализованный аппаратно, или, возможно, реализованный через IO или порт SPI

Благодарю.

10

Решение

struct serial_driver;

class serial_hw_level {
public:
virtual ~serial_hw_level() { }
virtual int wrBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes) = 0;
virtual int rdBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes) = 0;
};

class arm9_uart: public serial_hw_level {
public:
arm9_uart(int sutff);
virtual ~arm9_uart();
virtual int wrBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes);
virtual int rdBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes);

private:
int arm9_stuff;
};

class usb_emulated: public serial_hw_level {
public:
usb_emulated(int endpoint, int controller, int handshake_pins);
virtual ~usb_emulated();
virtual int wrBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes);
virtual int rdBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes);

private:
int usb_endpoint;
int usb_controller;
int emulated_handshake_pins;
};

class serial_port {
public:
serial_port(const string& serial_name, serial_hw_level* driver);
~serial_port();
string get_name() const;

private:
string name;
serial_hw_level* hw_driver;
};// Implementation *.cpp files

arm9_uart::arm9_uart(int stuff)
: arm9_stuff(stuff) {
}

arm9_uart::~arm9_uart() {
// free resources
}

int arm9_uart::wrBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes) {
// do things
return 0;
}

int arm9_uart::rdBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes) {
// do things
return 0;
}usb_emulated::usb_emulated(int endpoint, int controller, int handshake_pins)
: usb_endpoint(endpoint),
usb_controller(controller),
emulated_handshake_pins(handshake_pins) {
}

usb_emulated::~usb_emulated() {
// free resources
}

int usb_emulated::wrBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes) {
// do things
return 0;
}

int usb_emulated::rdBytes(serial_driver *pDriver, uint8_t *ptr_bytes, int nBytes) {
// do things
return 0;
}

serial_port::serial_port(const string& serial_name, serial_hw_level* driver)
: name(serial_name),
hw_driver(driver) {
}

serial_port::~serial_port() {
delete hw_driver;
hw_driver = NULL;
}

string serial_port::get_name() const {
return name;
}serial_port hw_serail = {
"HW SERIAL",
new arm9_uart(arm9_stuff)
};

serial_port usb_serial = {
"USBSERIAL",
new usb_emulated(usb_endpoint, usb_controller, emulated_handshake_pins)
};

Serial_hw_level — это интерфейсный класс. Присваивание указателей на функции в C, таких как wrBytes, выполняется в C ++ с помощью указателей на виртуальные функции при создании объекта.

Класс serial_port, однако, не обязательно должен быть производным от serial_hw_level. Для этого больше подходит композиция, так как вам нужно имя для нее, а также абстрактный объект serial_hw_level.

Следующим является объекты в глобальном пространстве имен. Когда вы хотите, чтобы он был глобальным, в C вы можете просто назначить ему указатели функций. Вы даже не имеете производного класса или производного объекта. Все, что у вас есть, это базовый класс, базовый объект и назначение указателя виртуальной функции (в представлении C ++) в начальный момент времени. В C ++, когда у вас есть производные классы и указатели виртуальных функций, присваивание базовому классу достигается указателями или ссылками. Поскольку вам нужны глобальные объекты, вы можете создавать новые производные объекты, назначать их базовому указателю в начальный момент времени и удалять их непосредственно перед выходом прогресса автоматически деструктором класса serial_port.

2

Другие решения


По вопросам рекламы [email protected]