Операционная система ЗОСРВ «Нейтрино» > Руководство разработчика > Основные принципы системной разработки > Запуск системы, быстрая активация устройств > Быстрая активация устройств > Общие сведения > Быстрая активация устройств с помощью минидрайверов



Быстрая активация устройств с помощью минидрайверов

Обзор технологии быстрой активации устройств

Быстрая активация устройств (которая также обозначается термином «минидрайвер») повышает степень интеграции оборудования встраиваемых систем. Развитые процессоры тесно интегрированы с периферийными устройствами и напрямую управляют такими интерфейсами, как CAN, J1850 и MOST.

Уменьшение количества микросхем и электронных компонентов сокращает затраты на оборудование, но в то же время ставит дополнительные задачи перед разработчиками программного обеспечения. Например, телематический блок управления должен начинать прием сообщений по шине CAN через 30-100 миллисекунд после включения. Проблема заключается в том, что загрузка сложных программ, которые выполняются на таких телематических устройствах, может занимать сотни миллисекунд и более.

Еще одним примером являются критически важные точки в процессе загрузки автомобильной телематической или информационно-развлекательной системы, который обычно осуществляется в «холодном» режиме (из состояния полного отключения) или после перезагрузки ЦП, при которой отключается память SDRAM. Эта система должна:

Для удовлетворения этих временных требований во многих встраиваемых системах применяется простое, но дорогостоящее решение, в состав которого входит дополнительный процессор связи или внешний модуль питания. Инновационные программные продукты компании «СВД Встраиваемые Системы» позволяют уменьшать количество дополнительного оборудования вплоть до полного отказа от него. Их основу составляют минидрайверы — небольшие высокоэффективные драйверы устройств, которые начинают работать до инициализации ядра ОС.

Знакомство с минидрайвером
Архитектура минидрайвера
Принципы работы минидрайвера
Плавная передача управления
Выполнение нескольких функций-обработчиков
Написание минидрайвера
Аппаратная платформа
Временные требования
Хранение данных
Инициализация оборудования
Доступ к оборудованию
Передача управления полноценному драйверу
Пример минидрайвера
Функция-обработчик минидрайвера
Добавление минидрайвера в систему
Сборка программы запуска
Тестовое приложение mini-peeker.c
Передача управления от минидрайвера полноценному драйверу
Особенности реализации минидрайвера
Изменение программы запуска с кодом минидрайвера
Создайте загрузочный образ с собственным минидрайвером
Отладка минидрайвера
Отображение информации о состоянии минидрайвера (после загрузки ядра)
Передача управления полнофункциональному драйверу

Знакомство с минидрайвером

При обычной загрузке ЗОСРВ «Нейтрино» драйвер не может выполняться до тех пор, пока образ операционной системы не загружен в оперативную память и ядро не инициализировано. В зависимости от конкретного оборудования (процессора, флеш-памяти, архитектуры) и размера образа длительность загрузки ОС может составлять от сотен миллисекунд до нескольких секунд. Минидрайвер запускается на ранних этапах загрузки и может соответствовать временным требованиям протоколов таких шин, как MOST и CAN.

Минидрайвер задается в коде запуска и начинает работать до того, как завершается загрузка операционной системы. Он быстро и своевременно реагирует на сообщения, которые включают оборудование, и гарантирует, что они не теряются к моменту окончания загрузки ОС. По завершении загрузки ОС минидрайвер продолжает выполняться или передает управление полнофункциональному драйверу, который имеет доступ к данным, собранным минидрайвером.

booting_minidriver.png
Рисунок 1. Процесс загрузки при использовании быстрой активации устройств

Архитектура минидрайвера

Минидрайвер состоит из двух основных компонентов:

После создания минидрайвера функция-обработчик вызывается в процессе загрузки. Первый вызов функции-обработчика выполняется таймером (опрос). После разрешения прерываний ЦП обработчик вызывается прерываниями, которые генерируются устройствами. Поскольку таймеры также генерируют прерывания, с их помощью можно опрашивать устройства, которые не генерируют прерывания.

Принципы работы минидрайвера

Минидрайвер — это функция (фрагмент кода), которую разработчик связывает с программой запуска ЗОСРВ «Нейтрино». Минидрайвер выполняется раньше, чем ядро инициализируется и система становится готовой к работе. Минидрайвер имеет доступ к устройству и может сохранять данные в буфере RAM, который доступен для считывания полнофункциональному драйверу, представляющему собой обычный процесс.

При запуске системы периодически вызывается (опрашивается) функция-обработчик минидрайвера, которая добавлена в код запуска ЗОСРВ «Нейтрино». Можно регулировать интервал опроса в соответствии с временными требованиями устройства путем внесения небольших изменений в программу запуска. После того, как в процессе загрузки системы включаются прерывания, они управляют функцией-обработчиком. При вызове обработчику передается переменная состояния (state).

Прототип функции-обработчика минидрайвера имеет вид:

int mdriver_handler( int state, void *data );

Плавная передача управления

Когда в операционной системе запускается полнофункциональный драйвер, он принимает управление от минидрайвера. Передача управления осуществляется в плавном режиме без прерывания обслуживания устройства. Полнофункциональный драйвер просто подключается к прерыванию устройства, а минидрайвер получает об этом уведомление; Затем минидрайвер может штатно завершать работу, а полнофункциональный драйвер — продолжать выполнение. Полнофункциональный драйвер имеет доступ ко всем буферам данных, которые созданы минидрайвером.

Выполнение нескольких функций-обработчиков

В минидрайвере могут выполняться несколько функций-обработчиков. Если устройство должно совершать какое-либо действие с периодом n миллисекунд, можно присоединить две функции-обработчика:

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

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

Написание минидрайвера

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

Аппаратная платформа

Получите BSP аппаратной платформы, который включает в себя исходный код программы запуска платы. Необходимо связать минидрайвер с этой программой.


Note: Если вы работаете с платформой ARM, необходимо реализовывать функцию-обработчика минидрайвера в виде позиционно-независимого кода (англ. PIC, Position Independent Code). Это означает, что если обработчик находится в состоянии MDRIVER_KERNEL, MDRIVER_PROCESS или MDRIVER_INTR_ATTACH, в нем нельзя использовать глобальные или статические переменные.

Временные требования

Поскольку при запуске системы и инициализации ядра в процессе загрузки опрашивается код минидрайвера, необходимо знать временные параметры устройства, чтобы обеспечивать выполнение опроса с достаточной частотой. Копирование загрузочного образа из флеш-памяти в RAM занимает большую часть времени выполнения программы запуска; в этот период осуществляется опрос минидрайвера.

Программа запуска содержит глобальную переменную mdriver_max, в которой хранится количество данных (в байтах), копируемых из флеш-памяти в RAM между вызовами минидрайвера. Размер данных по умолчанию составляет 16 Кбайт и должен выбираться с учетом временных требований устройства, быстродействия процессора и характеристик флеш-памяти. Эта переменная содержится в файле mdriver_max.c, который находится в библиотеке запуска.

Можно изменить значение этой переменной двумя способами:

Хранение данных

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

Местоположение этой памяти выбирается разработчиком или программой запуска. Память выделяется функцией:

paddr_t alloc_ram( phys_addr, size, alignment );

которая возвращает ее физический адрес. Эта область памяти используется при регистрации минидрайвера в программе запуска. Поскольку вышеуказанная функция резервирует область в RAM, необходимо вызывать ее после инициализации RAM с помощью функции init_raminfo().

Система не управляет этой областью памяти; ваш драйвер должен защищать ее содержимое от перезаписи и предотвращать сбои в программе запуска.

Инициализация оборудования

Если драйвер инициализирует оборудование, следует поместить код в обработчик MDRIVER_INIT минидрайвера. MDRIVER_INIT является первым состоянием минидрайвера и применяется однократно.

Доступ к оборудованию

Минидрайверу почти всегда необходимо иметь доступ к оборудованию, чтобы выполнять операции чтения и записи над его регистрами. Для работы с регистрами устройств в библиотеке запуска предусмотрены функции отображения и отмены отображения физической памяти.

При вызове обработчика минидрайвера с параметром MDRIVER_STARTUP_INIT осуществляются обращения к следующим функциям:

uintptr_t startup_io_map( size, phys_addr );
startup_io_unmap( paddr );
void * startup_memory_map( size, phys_addr );
startup_memory_unmap( paddr );

После вызова минидрайвера с параметром MDRIVER_STARTUP_PREPARE перечисленные функции становятся недоступными, и вместо них в драйвере необходимо использовать функции:

uintptr_t callout_io_map( size, phys_addr );
void * callout_memory_map( size, phys_addr );

Множество доступных вызовов зависит от этапов процесса загрузки. Если драйверу необходим доступ к оборудованию, выполните в нем следующие действия:

MDRIVER_INIT
MDRIVER_STARTUP
Используйте сохраненный указатель ptr1 во всех операциях с устройствами. Вызывать функции отображения памяти не требуется.
MDRIVER_STARTUP_PREPARE
Здесь можно вызывать функцию callout_io_map() или callout_memory_map(), однако не следует использовать указатель, который они возвращают.

После вызова одной из вышеуказанных функций следует сохранить указатель (обозначим его ptr2) в области данных минидрайвера или статической переменной отдельно от значения, которое было сохранено ранее. Используйте сохраненный указатель ptr1 во всех операциях с устройствами.
MDRIVER_STARTUP_FINI
Используйте сохраненный указатель ptr1 во всех операциях с устройствами. Поскольку минидрайвер должен использовать указатель, назначенный функцией callout_io_map() или callout_memory_map(), во всех последующих вызовах, необходимо хранить его в области данных.
MDRIVER_KERNEL
Используйте сохраненный указатель ptr2 во всех операциях с устройствами.
MDRIVER_PROCESS
Используйте сохраненный указатель ptr2 во всех операциях с устройствами.
MDRIVER_INTR_ATTACH
Используйте сохраненный указатель ptr2 во всех операциях с устройствами.

Передача управления полноценному драйверу

После запуска ядра минидрайвер может передавать управление полнофункциональному драйверу и штатно завершать работу. При передаче управления полнофункциональный драйвер выполняет следующие действия:

Минидрайвер вызывается с состоянием MDRIVER_INTR_ATTACH. На этом этапе минидрайвер должен выполнять все необходимые действия по очистке и отключать прерывание устройства. Затем обработчик минидрайвера может вернуть ненулевое значение, которое указывает, что минидрайвер завершает работу. Передача управления выполнена успешно, если:

Пример минидрайвера

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

Особенности реализации

Временные данные хранятся в общей памяти. В этом примере размер области данных составляет 64 Кбайт. Если переменной mdriver_max присваивается значение менее 16 Кбайт, может потребоваться область данных большего размера (например, 128 Кбайт), поскольку уменьшение значения mdriver_max приводит к увеличению количества внешних вызовов.

Рекомендуется использовать значение переменной mdriver_max по умолчанию (16 Кбайт), при котором размер области данных равен 64 Кбайт. Предполагается, что рассматриваемомум драйверу не требуется доступ к устройству.

Функция-обработчик минидрайвера

Прототип функции-обработчика минидрайвера имеет следующий вид:

int mdriver_handler( int state, void *data );

Определения переменной state и указателя data см. в описании функции mdriver_add(). В этом примере драйвера исходный код функции-обработчика выглядит следующим образом:

struct mini_data
{
uint16_t nstartup;
uint16_t nstartupp;
uint16_t nstartupf;
uint16_t nkernel;
uint16_t nprocess;
uint16_t data_len;
};
/*
* Пример функции-обработчика минидрайвера, предназначенного для отладки
*
* Подсчитывает количество вызовов для каждого состояния и записывает текущее состояние
* обработчика в область данных
*/
int mini_data( int state, void *data )
{
uint8_t *dptr;
struct mini_data *mdata;
mdata = (struct mini_data *)data;
dptr = (uint8_t *)(mdata + 1);
/* создание области данных в состоянии MDRIVER_INIT */
if ( state == MDRIVER_INIT )
{
mdata->nstartup = 0;
mdata->nstartupf = 0;
mdata->nstartupp = 0;
mdata->nkernel = 0;
mdata->nprocess = 0;
mdata->data_len = 0;
}
/* подсчет количества вызовов для каждого типа */
if ( state == MDRIVER_STARTUP ) mdata->nstartup = mdata->nstartup + 1;
else if ( state == MDRIVER_STARTUP_PREPARE ) mdata->nstartupp = mdata->nstartupp + 1;
else if ( state == MDRIVER_STARTUP_FINI ) mdata->nstartupf = mdata->nstartupf + 1;
else if ( state == MDRIVER_KERNEL ) mdata->nkernel = mdata->nkernel + 1;
else if ( state == MDRIVER_PROCESS ) mdata->nprocess = mdata->nprocess + 1;
else if ( state == MDRIVER_INTR_ATTACH ) return (1); /* обычное запрещение нашего прерывания */
/* запись информации о состоянии в область данных после структуры при наличии свободного места */
if (mdata->data_len < 60000 )
{
dptr[mdata->data_len] = (uint8_t)state;
mdata->data_len = mdata->data_len + 1;
}
return (0);
}

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

Мы предотвращаем возможность записи за пределы области данных, размер которой составляет 64 Кбайт. Попытка функции-обработчика выполнить запись вне области данных может приводить к сбою и невозможности дальнейшей загрузки операционной системы. Разработчику необходимо тщательно следить за соблюдением границ при чтении и записи в память.

В состоянии MDRIVER_INIT выполняется инициализация области данных. Обработчик входит в него один раз. В состоянии MDRIVER_INTR_ATTACH обработчик возвращает значение 1, запрашивая останов. Тем не менее, из-за асинхронного характера работы системы обработчик может быть вызван еще несколько раз после запроса на останов.

Добавление минидрайвера в систему

После написания функции-обработчика необходимо зарегистрировать ее в программе запуска и выделить требуемый объем RAM для области данных. Для этого используются функции:

paddr_t alloc_ram( phys_addr, size, alignment );
int mdriver_add( name, interrupt, handler, data_paddr, data_size );

Поскольку эти функции выделяют память и используют номер прерывания, перед их вызовом необходимо инициализировать оперативную память с помощью функции init_raminfo() и добавлять информацию о прерываниях на системную страницу с помощью функции init_intrinfo().

Функция main() в файле main.c программы запуска выглядит следующим образом:

...
paddr_t mdrvr_addr;
...
/* Получение информации обо всей свободной оперативной памяти системы. */
init_raminfo();
/* В виртуальной системе нам необходимо инициализировать таблицы страниц */
if ( shdr->flags1 & STARTUP_HDR_FLAGS1_VIRTUAL )
init_mmu();
/*
* Следующие процедуры могут иметь зависимости от оборудования или системы,
* которые требуется изменить
*/
init_intrinfo();
mdrvr_addr = alloc_ram( ~0L, 65535, 1 ); /* создание области данных размером 64 Кбайт */
mdriver_add( "mini-data", 0, mini_data, mdrvr_addr, 65535 );
...

В этом примере мы выделили 64 Кбайт памяти и зарегистрировали функцию-обработчика минидрайвера с именем mini-data.

Сборка программы запуска

После написания минидрайвера необходимо пересобрать код запуска и загрузочный образ. Чтобы проверить корректность работы минидрайвера, можно добавить отладочную информацию в функцию-обработчик или написать приложение, которое считывает область данных минидрайвера и отображает ее содержимое.

Тестовое приложение mini-peeker.c

В этом разделе содержится исходный код тестового приложения mini-peeker.c, которое отображает в свое адресное пространство область данных минидрайвера и выводит ее содержимое:

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <sys/mman.h>
#include <sys/neutrino.h>
#include <sys/syspage.h>
#include <hw/inout.h>
#include <inttypes.h>
struct mini_data
{
uint16_t nstartup;
uint16_t nstartupp;
uint16_t nstartupf;
uint16_t nkernel;
uint16_t nprocess;
uint16_t data_len;
};
int main( int argc, char *argv[] )
{
int i,
count,
dump_data = 0;
uint8_t *dptr;
struct mini_data *mdata;
if ( argv[1] )
dump_data = 1;
ThreadCtl( _NTO_TCTL_IO, 0 );
/* отображение области данных минидрайвера */
if ( (dptr = mmap_device_memory( 0, 65535, PROT_READ | PROT_WRITE | PROT_NOCACHE,
0, SYSPAGE_ENTRY( mdriver )->data_paddr )) == NULL )
{
fprintf( stderr, "Unable to get data pointer\n" );
return (-1);
}
mdata = (struct mini_data *)dptr;
dptr = dptr + sizeof( struct mini_data );
/* вывод данных минидрайвера */
printf( "---------------- MDRIVER DATA -------------------\n" );
printf( "\tMDRIVER_STARTUP calls = %d\n", mdata->nstartup );
printf( "\tMDRIVER_STARTUP_PREPARE calls = %d\n", mdata->nstartupp );
printf( "\tMDRIVER_STARTUP_FINI calls = %d\n", mdata->nstartupf );
printf( "\tMDRIVER_KERNEL calls = %d\n", mdata->nkernel );
printf( "\tMDRIVER_PROCESS calls = %d\n", mdata->nprocess );
printf( "\tData Length calls = %d\n", mdata->data_len );
count = mdata->data_len;
if ( dump_data )
{
printf( "State information:\n" );
for ( i = 0; i < count; i++ )
printf( "%d\n", dptr[i] );
}
printf( "\n---------------------------------\n" );
return (EXIT_SUCCESS);
}

Скомпилируйте этот код для целевой системы стандартным способом:

qcc -Vgcc_ntoppcbe mini-peeker.c -o mini-peeker

Передача управления от минидрайвера полноценному драйверу

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

Когда полнофункциональный драйвер обращается к функции InterruptAttach() или InterruptAttachEvent(), ядро вызывает минидрайвер с состоянием MDRIVER_INTR_ATTACH. Функция-обработчик минидрайвера должна выполнить все необходимые действия по очистке и завершить работу.

После подключения к прерыванию полнофункциональный драйвер может обрабатывать буферизованные данные и продолжать обслуживать устройство. Пример:

if ( (id == InterruptAttachEvent( intr, event, _NTO_INTR_FLAGS_TRK_MSK )) == -1 )
{
perror( "InterruptAttachEvent\n" );
return (-1);
}
if ( (dptr = mmap_device_memory( 0, data_size, PROT_READ | PROT_WRITE | PROT_NOCACHE,
0, SYSPAGE_ENTRY( mdriver )->data_paddr )) == NULL )
{
fprintf( stderr, "Unable to get data pointer\n" );
return (-1);
}
/* На этом этапе работа минидрайвера завершена, а полнофункциональный драйвер имеет доступ к прерыванию и области данных */
/* Включите прерывание устройства (intr) */

Для обеспечения безопасности в полнофункциональном драйвере следует всегда запрещать прерывание устройства перед вызовом функции InterruptAttach() или InterruptAttachEvent() и разрешать его после успешного завершения функции.

Особенности реализации минидрайвера

Подробнее рассмотрим этапы разработки, выполнения и отладки минидрайвера.

Разработка минидрайвера состоит из следующих основных этапов:

Этап передачи управления полнофункциональному драйверу не является обязательным. Функция-обработчик минидрайвера принимает прерывания даже после окончания загрузки ЗОСРВ «Нейтрино» до тех пор, пока функция присоединения обычного обработчика прерываний ( InterruptAttach*()) не отключает минидрайвер. Такое поведение может быть желательным для проектируемой системы.

Рассмотрим этапы разработки, а также применимые к ним методы и рекомендации.

Изменение программы запуска с кодом минидрайвера

Это ключевой этап разработки минидрайвера.

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

  1. Измените файл mdriver_max.c в библиотеке libstartup (этот файл находится на инструментальной системе в пакете поддержки аппаратной платформы в каталоге, имя которого заканчивается на libstartup).

    По умолчанию это значение составляет 16 Кбайт (в стандартном пакете поддержки аппаратной платформы для ЗОСРВ «Нейтрино»), что соответствует объему данных, которые одновременно копируются при передаче загрузочного образа из флеш-памяти в ОЗУ. После каждого копирования выполняется внешний вызов минидрайвера:

    внешний вызов минидрайвера копирование следующих 16 Кбайт внешний вызов минидрайвера копирование следующих 16 Кбайт и т.д.

    Иногда необходимо изменять это значение. Например, на микроконтроллере MPC5200 с процессором 396 МГц копирование 16 Кбайт занимает примерно 8 мс. Длительность копирования зависит от скорости процессора и флеш-накопителя. Если присвоить переменной mdriver_max значение 1 Кбайт, копирование займет менее 1 миллисекунды. Следует подбирать значение mdriver_max экспериментальным путем.

    После внесения изменений в файл mdriver_max.c необходимо повторно скомпилировать библиотеку libstartup.a и скомпоновать код запуска с новой библиотекой.

  2. Внесите необходимые изменения в файлы запуска и добавьте код минидрайвера.

    Все файлы, которые требуется изменять, находятся в том же каталоге BSP, что и код startup. Например, при сборке BSP платы Media5200b редактируются следующие файлы:

    Примеры см. в главе Примеры драйверов для быстрой активации устройств. Выполните следующие основные действия:

    main.c
    • задайте прототип функции внешнего вызова минидрайвера:

      extern int mini_data( int state, void *data );

    • выделите область памяти для данных, например:

      /* глобальная переменная */
      paddr_t mdriver_addr; /* выделение 64 Кбайт памяти для использования минидрайвером */
      mdriver_addr = alloc_ram( ~0L, 65536, 1 );

    • задайте функцию внешнего вызова минидрайвера после обращения к функции init_intrinfo():

      /* Пример добавления функции минидрайвера с именем mini-data для irq=81 */
      mdriver_add( "mini-data", 81, mini_data, mdrvr_addr, 65536 );

    cpu_mdriver.c
    • не изменяйте этот файл.
    • помещайте этот C-файл в каталог с кодом программы запуска.
    mdriver.c
    • не изменяйте этот файл.
    • включите этот C-файл в каталог с кодом запуска.
    mini-driver.c
    • в этом файле находится код минидрайвера. Этот C-файл может иметь любое имя. Необходимо, чтобы функция минидрайвера, которая задана в функции mdriver_add(), входила в состав кода запуска.
    • минидрайвер может включать в себя несколько C-файлов и заголовочных файлов

    Опробуйте примеры, которые входят в этот комплект, и создайте новую программу запуска (например, startup-mgt5200).

Создайте загрузочный образ с собственным минидрайвером

На этом этапе у вас имеется скомпилированная программа запуска с интегрированным минидрайвером. Теперь следует включить эту программу запуска в загрузочный образ ЗОСРВ «Нейтрино» и опробовать минидрайвер.

Несколько важных правил сборки загрузочного образа с минидрайвером:

Сжатие
Не следует сжимать загрузочный образ. Распаковка загрузочного образа влияет на временные характеристики, которые определяются объемом копируемых данных в соответствии с mdriver_max. Загрузочный образ должен иметь тип:

[virtual=ppcbe,binary] .bootstrap = {

Обратите внимание, что в этой строке отсутствует ключевое слово +compress. Замените параметры ppcbe или binary в соответствии с используемым оборудованием и форматом образа.

Программа запуска
После компиляции программы запуска с интегрированным минидрайвером не забывайте указывать ее в файле сборки.

Например, если программа запуска для платы Media5200b скомпилирована с именем startup-mgt5200, следует скопировать ее в каталог ${KPDA_TARGET}/ppcbe/boot/sys/startup-mgt5200-mdriver, а затем указать имя startup-mgt5200-mdriver в файле сборки.

Дополнительную информацию и примеры файлов сборки см. в главе Примеры драйверов для быстрой активации устройств.

Отладка минидрайвера

Для отладки минидрайвера применяются следующие методы:

kprintf()
Если в коде запуска можно выводить данные в последовательный порт или на другое отладочное устройство, функция kprintf() позволяет отображать значения любых интересующих переменных:

kprintf( "I am the minidriver!\n" );
kprintf( "Global variable mcounts=%d\n", mcounts );

Область памяти
Записывайте всю собираемую информацию в общедоступную область данных минидрайвера. После загрузки ядра можно анализировать ее содержимое. Пример использования области данных см. в программе mini-peeker.c.
JTAG или аппаратная индикация
Вы также можете использовать интерфейс JTAG при его наличии на аппаратной платформе. Если оборудование оснащено светодиодами или другими средствами диагностики, минидрайвер может использовать их в качестве индикаторов определенных состояний, записывая соответствующие значения в регистры устройств.

Отображение информации о состоянии минидрайвера (после загрузки ядра)

После загрузки ядра изучите содержимое общей памяти, которая была выделена для минидрайвера с помощью функции alloc_ram(). Передайте указатель paddr_t в функцию mdriver_add(), чтобы связать минидрайвер с областью общей памяти.

См. пример mini-peeker.c.

Передача управления полнофункциональному драйверу

Минидрайвер вызывается следующим образом:




Предыдущий раздел: перейти