Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Зависание платы PCI  (Прочитано 18697 раз)
0 Пользователей и 1 Гость смотрят эту тему.
ashot
Гость
« : 17-03-2006 08:01 » 

Есть плата PCI. Для работы с ней драйвер выделяет буфер (AllocateCommonBuffer()). Буфер я сделалала 28К байт, чтобы он разместился на 8 страницах ( мне выделяется 8 map registers). В плату записывается адрес буфера и размер, и она начинает писать (Burst Master Memory Writes по 8 DWORDов) в буфер значения последовательного  32-х разрядного счетчика , заполнив буфер до конца продолжает писать с начала, при переполнении счетчик обнуляется. Прерывания не используются. Переодически я просматриваю содержимое буфера . Плата отлично работает, если я на компе больше ничего не делаю. Но когда запускаю какое-нибудь приложение плата зависает: пытается писать данные, но пересылок нет.  Такая картина если моя сетевая карта отключена. Если я подключаю сетевую карту, то тоже какое-то время пересылки идут нормально, но потом вместе с платой уже весь комп виснит.
Буду очень рада, если  поможете советом.
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #1 : 17-03-2006 12:38 » 

Возможно, вам не дают захватить шину PCI на время пересылки 8 слов.
там помоему фича была... когда требуется произвести запись 8 слов в шину - возможно, что вам не дадут записать все 8 слов и прервут транзакцию по шине раньше, где нибудь по середине. учитывать надо... если не ошибаюсь в Burst режиме эт обычное дело.
на софтовую ошибку не похоже.
что за плата? 100% работоспособная или в отладке?

память выделяем так:Не понял
Код:
    //выделение памяти под DMA-------------------------------------------------------
    //такс..теперь память под Buff... это гораздо показательей, так как вероятность НЕвыделения такой памяти ВЫШЕ!
    //заполняем структуру под все это дело...
    RtlZeroMemory(&devDescr,sizeof(DEVICE_DESCRIPTION)); //обнуляем лишнее (по рекомендации)

    devDescr.Version = DEVICE_DESCRIPTION_VERSION; //перавя версия, нулевая исползуется только при IgnoreCounter = FALSE
    devDescr.Master = TRUE;
    devDescr.ScatterGather = FALSE;
    //devDescr.DemandMode = Not Used
    //devDescr.AutoInitialize = Not Used
    devDescr.Dma32BitAddresses = TRUE;
    devDescr.IgnoreCount = TRUE;
    //devDescr.Reserved1 = 0;
    devDescr.Dma64BitAddresses = FALSE;
    //devDescr.DoNotUse2 = 0; //=devDescr.BusNumber - NotUsed in WDM
    //devDescr.DmaChannel = 0; //только для Slave устройств
    devDescr.InterfaceType = PCIBus;
    //devDescr.DmaWidth -
    //devDescr.DmaSpeed - не для мастера? (только если value only if the machine's ACPI BIOS supports it)... ничего не понял
    //devDescr.MaximumLength = ROUND_TO_PAGES(SYSTEM_MEMORY_FOR_BOARD/2);   
    devDescr.MaximumLength = PAGE_SIZE;    //че тут ставить я не знаю... пока - не знаю!(может один мегобайт? вроде у нас такие передачи...
    //в любом случае они просили округлить до PAGE_SIZE, да на здоровье!
    //devDescr.DmaPort = 0;   //говорят, что это устаревший параметр. но нужен для совместимости... для Legacy...

    devExt->NumberOfMapRegisters = 2; //мои изыски - вряд ли нужно

    devExt->DMAAdapter = IoGetDmaAdapter(    devExt->PhysicalDeviceObject,
    &devDescr,
    &devExt->NumberOfMapRegisters);

    if (!devExt->DMAAdapter)
    {
//не удалось получить DMA Adapter.
KdPrint((" Error: not get DMA Adapter \n"));

ReleaseResPCI(devExt);
//вываливаемся по ошибке
return STATUS_INSUFFICIENT_RESOURCES; //тип ошибки - нет памяти, впрочем с этим я позже разберусь
    };

    //devExt->LengthBuffDataDW = ROUND_TO_PAGES(SYSTEM_MEMORY_FOR_BOARD)/4;
    devExt->LengthBuffDataDW = (devExt->LengthBuffPages_Pages<<(PAGE_SHIFT-2));

    devExt->h0_BuffData =
devExt->DMAAdapter->DmaOperations->
    AllocateCommonBuffer(   devExt->DMAAdapter,
    devExt->LengthBuffDataDW<<2,//ROUND_TO_PAGES(SYSTEM_MEMORY_FOR_BOARD),
    &devExt->lpPhisAddrBuffData,
    FALSE);
PS у мя буфер 8 МБ был. (SYSTEM_MEMORY_FOR_BOARD)
« Последнее редактирование: 20-12-2007 15:14 от Алексей1153++ » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
ashot
Гость
« Ответ #2 : 20-03-2006 08:57 » 

Ochkarik, спасибо.
Плата в отладке . DMA настраиваю также. Тоже подозреваю что проблемы в прошивке платы.
Только еще вопрос: может ли передача затыкаться при переходе на новую страницу если в физ памяти страницы не непрерывны(т.е. возникать какие- нибудь проблемы с использованием map registers)?
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #3 : 20-03-2006 10:38 » 

в том и суть, чтобы выделенная память в непрерывном физ адресном пространстве находилась. в общем для современных объемов памяти это легко выполнимо даже для моих 8 мегобайт) ну разве что десять раз подряд их не выделить... но при старте - всегда пожалуйста. у меня - как раз так, кусок кода - ниже, наша железка поддерживает ТОЛЬКО физически непрерывную память. зуб даю)

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

а вобоще это дело на мой взгляд - ненужное и хлопотное. с точки зрения железа. тем более при таких смешных объемах. если код как у меня - вы используете непрерывную память!
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
ashot
Гость
« Ответ #4 : 20-03-2006 13:51 » 

Насколько я поняла читая документацию DDK при организации DMA есть пространство физических адресов в котором буфер может занимать не непрерывные страницы, и logical address прострастранство в которое буфер отображается непрерывно и по этим адресам устройство общается с памятью. Для отображения физических адресов в логические Hal использует map registers. Еще в документации написано, что размер буфера передаваемый в функцию AllocateCommonBuffer() определяет кол-во  map registers которое будет использоваться, советуется функцией BYTES_TO_PAGES() определить сколько страниц занимает буфер и это число не должно превышать NumberOfMapRegisters возвращаемое IoGetDmaAdapter.
Однако сейчас я назначила размер буфера 1М, NumberOfMapRegisters возвращается равное 8, BYTES_TO_PAGES() возвращает 0х100, и передача нормально идет(пока комп больше ничем не нагружен).
Так значит AllocateCommonBuffer() выделяет непрерывный в физической памяти и НАL никаких map registers не использует. Тогда какой максимальный размер буфера можно указать?
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #5 : 20-03-2006 14:45 » 

все так.
BYTES_TO_PAGES - не функция а макрос. в архитектуре винды одна страница равна 4кБ. макрос это и выдает тупо. почему 4к? - это один из двух вариантов размера сегмента памяти. который в виндах и используется.
функция AllocateCommonBuffer (если указать тот самый ScatterGather= false) память размещает в непрерывном пространстве физических адресов. впрочем другого варианта я никогда не испытывал....
а размер буфера вы должны сами определить.
например исходя из своих задач для скоростей порядка 40МБ/сек, период опроса ~20мс. я выделял 8Мб, мне хватало.
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
V-ctor
Гость
« Ответ #6 : 16-05-2006 08:48 » 

Ха! Ну ничо се!
Так же ж низя! Зацапать PCI шину в монопольное использование!
Другие устройства тож хотят по ней данные гонять! Та же сетевушка, IDE-контроллер тож по мойму через PCI заведен.
И потом что значит выражение плата зависает? Зависает драйвер? Зависает ПО на плате?
Максимальный размер AllocateCommonBuffer() будет зависеть от нескольких факторов, где самый очевидный объем имеющийся физической памяти.
Если надо большой кусок памяти зацапать, да еще и не раз, то придеца все же работать с разрывной памятью, это заморочней, но вполне реализуемо, хорошо если есть поддержка в PCI-контроллере, тогда грубо гря можно ему отдать список адресов этих кусков и их длины и тогда доработка не так сложна со стороны драйвера, а вот если нет такой поддержки, то можно тоже выкрутица но чуток сложней, придеца по окончании обработки каждого куска данных указывать контроллеру новый адрес, через прерывания все работает, проверено.
Записан
urock
Участник

ru
Offline Offline

« Ответ #7 : 16-03-2009 11:41 » 

Еще в документации написано, что размер буфера передаваемый в функцию AllocateCommonBuffer() определяет кол-во  map registers которое будет использоваться, советуется функцией BYTES_TO_PAGES() определить сколько страниц занимает буфер и это число не должно превышать NumberOfMapRegisters возвращаемое IoGetDmaAdapter.
Однако сейчас я назначила размер буфера 1М, NumberOfMapRegisters возвращается равное 8, BYTES_TO_PAGES() возвращает 0х100, и передача нормально идет(пока комп больше ничем не нагружен).
Так значит AllocateCommonBuffer() выделяет непрерывный в физической памяти и НАL никаких map registers не использует. Тогда какой максимальный размер буфера можно указать?

1. нет ли здесь противоречия, что с одной стороны размер буфера не может превышать значения PAGE_SIZE * NumberOfMapRegisters = 4 kb * 8 = 32 kb, а с другой стороны система допускает выделения буфера размером 1 MB (как у ashot) или 8 MB (как у Ochkarik)?

2. Поясните, пожалуйста, как правильно использовать этот Common Buffer. Если я использую DIRECT_IO (при обработке запросов IRP_MJ_READ/WRITE я работаю с MDL), то прежде чем начинать транзакцию передачи данных с устройством, сначала надо скопировать данные, описываемые этим MDL, в Common Buffer? Как лучше это сделать? Циклом типа
for (i=0; i<Buffer_Size; i++, MdlVirtualAddress++, CommonBufferVirtualAddress++)
{
         *CommonBufferVirtualAddress = *MdlVirtualAddress;
}
Записан
PredatorAlpha
Помогающий

us
Offline Offline

« Ответ #8 : 16-03-2009 14:43 » 

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

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

Размер страницы виртуальной памяти может быть равным как 4К, так и 8М (по крайней мере аппаратные средства процессоров начиная с Пентиума позволяют это, но как это реализовано в Винде - не знаю.)
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #9 : 16-03-2009 19:41 » 



PredatorAlpha,
DMAAdapter->DmaOperations->AllocateCommonBuffer() как раз для этого и предназначена. это один из способов.

urock, ограничение PAGE_SIZE * NumberOfMapRegisters  - эт ересь, и это не про то речь шла...
а по поводу метода использования  - это от вашей железки зависит)
вместо цикла - как минимум rep movsd.  то есть memcpy().
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
urock
Участник

ru
Offline Offline

« Ответ #10 : 17-03-2009 07:21 » 

спасибо
Записан
Рыжий Тигра
Гость
« Ответ #11 : 27-04-2009 09:32 » 

PredatorAlpha > Размер страницы виртуальной памяти может быть равным как 4К, так и 8М (по крайней мере аппаратные средства процессоров начиная с Пентиума позволяют это
Делись подробностями?!!
Записан
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #12 : 27-04-2009 10:02 » 

ток не в винде повидимому. в дефайнах забито 4к. сомневаюсь что можно менять. там слишком много не нее завязано...
Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #13 : 27-04-2009 11:41 » 

PredatorAlpha > Размер страницы виртуальной памяти может быть равным как 4К, так и 8М (по крайней мере аппаратные средства процессоров начиная с Пентиума позволяют это
Делись подробностями?!!

Не 8М, а 4М.
Суть простая:
1. Страница 4к (12 бит) получается трансляцией виртуального адреса через каталог страниц (старшие 10 бит адреса) и таблицы страниц (след. 10 бит).
2. Страница 4М (22 бита) адресуется напрямую из каталога первого уровня.

Сложность применения в том, что такая физическая страница должна быть выровнена по 4М границам.
В Linux есть фишка для предварительного резервирования, когда скрипты загрузки просят систему создать нужное количество 4М страниц и попридержать их.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Рыжий Тигра
Гость
« Ответ #14 : 27-04-2009 11:57 » 

RXL > В Linux есть фишка для предварительного резервирования
В windows есть возможность заюзать при загрузке не всё ОЗУ. Но на кой это может понадобиться и как незанятый кусок поюзать - нигде не нашёл. Жаль
Записан
RXL
Технический
Администратор

ru
Offline Offline
Пол: Мужской

WWW
« Ответ #15 : 27-04-2009 12:00 » 

Рыжий Тигра, возможно это механизм PAE - аппаратное мапирование средствами контроллера памяти. Страничный механизм аналогичный досовскому EMS.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Ochkarik
Модератор

ru
Offline Offline
Пол: Мужской

« Ответ #16 : 27-04-2009 12:03 » 

помоему это для совместимости кривого софта) PS то есть для отладки)
PAE там отдельно было.
http://support.microsoft.com/kb/833721/ru
« Последнее редактирование: 27-04-2009 12:05 от Ochkarik » Записан

RTFM уже хоть раз наконец!  RTFM :[ ну или хотя бы STFW...
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines