Для реализации собственно драйвера от классов, определенных в общем драйвере, должна быть получены следующие производные классы: |
MyHWObject (не обязательный, описывает дополнительные свойства специальных аппаратных данных) — производный от HWObject. |
MyHWMapper (в производном методе actualize(..) производится сопоставление аппаратных объектов с адресами периферии, здесь же создается и настраивается подходящее преобразование для каждого из аппаратных объектов) — производный от HWMapper. |
MyDrvResource (не обязательный, служит для реализации внутренних точек данных и управлением специфичных для драйвера настроек; производный метод readSection() всегда должен вызывать метод commonKeyWord(), в котором происходит обработка ресурсов общего драйвера), производный от DrvResource. |
MyHWService (используется для подключения к специальной периферии, учитывает связь с оборудованием, протоколы передачи, отправляет заранее созданные аппаратные объекты в указанном направлении на периферию, при необходимости упаковывает их в протокол-зависимые телеграммы. Обрабатывает входящие данные в направлении аларма и преобразует их в аппаратные объекты, которые затем направляются с помощью функции toDP() DrvManager в менеджер событий), производный от HWService. |
MyDrvManager (устанавливает специальные производные объекты собственного драйвера, формирует каркас класса), производный от DrvManager. |
MyTransformation (для каждого специального типа данных периферии должен быть создан отдельный объект преобразования, производный от базового класса Transformation). |
main() (Главная программа, не является отдельным классом. Создается объект MyDrvManager). |
При необходимости различные вспомогательные объекты |
Типовая главная программа для специального драйвера может иметь, к примеру, следующий вид: // глобальные объекты MyResources resources; MyDrvManager *g_driver; // обработчик прерываний void sigReceiver( int sigNum ) { g_driver->signalHandler( sigNum ); } int main( int argc, char *argv[] ) { MyResources::init( argc, argv ); if ( Resources::getHelpFlag() ) MyResources::printHelp(); else { g_driver = new MyDrvManager; signal( SIGINT, sigReceiver ); g_driver->mainProcedure( argc, argv ); } return 0; } MyResources::init(int argc, char *argv[]) { begin(argc,argv[]); while (readSection() || generalSection()) ; // чтение параметров драйвера из файла конфигурации end(argc, argv); } |
Типовой метод workProc() класса MyHWService может иметь следующий вид: void MyHWService::workProc() { TimeVar now; MyHWObject myObj; myObj.setOrgTime(now); // ввод исходного времени myObj.setAddress(address); // упрощенное предположение: // аппаратный адрес вводится из внешнего источника в строковый адрес HWObject *pDp = DrvManager::getHWMapperPtr()-> findHWObject(&myObj); // поиск соответствующего аппаратного объекта в HWMapper if (pDp) // найден? { // да myObj.setDlen(pDp->getDlen()); // длина данных берется из HWMapper PVSSchar *pBuf = new PVSSchar[myObj.getDlen()]; // создание нового буфера данных memcpy(pBuf,dataBuf,myObj.getDlen()); // Предположение: данные периферии доступны в dataBuf myObj.setData(pBuf); if (data_invalid) // данные допустимые? myObj.setSbit(DRV_INVALID); // установка бита ошибки DrvManager::getSelfPtr()->toDp(&myObj, pDp); } else … // Сообщение об ошибке } |
Для этой функции предполагается, что данные с адреса address (соответствует указанному адресу периферии) находятся в буфере dataBuf (один символ *), данные считаются недопустимыми, если установлен (логический) флаг data_invalid. |
Соответствующая функция HWService writeData(), задающая точки данных на периферии, аналогично приведенной выше функции, может иметь следующий вид: void writeData(HWObject *myObj) { address = myObj->getAddress(); // задает соответствующий адрес memcpy(dataBuf,myObj->getData(),myObj->getDlen()); // повторное копирование данных } |
В этом случае также предполагается, что данные с адреса «address» будут сделаны доступными (на этот раз нашим простым драйвером) в буфере dataBuf (который уже должен существовать). На самом деле эти две простые функции приведены только для того чтобы прояснить механизм. Реальный драйвер мог, к примеру, составить телеграмму в направлении отправки в writeData(), которая бы затем была отправлена по TCP/IP-подключению партнеру. В направлении приема (в workProc()) подобная телеграмма перед ее отправкой функцией toDp() общему драйверу была бы интерпретирована, из нее были бы извлечены адрес и необработанные данные, которые были бы записаны в myObj. |