QNX.ORG.RU

Разработка => Программирование под QNX => Тема начата: denmor86 от Ноября 29, 2013, 12:47:58 pm



Название: Проблемы с in32 () или out32()
Отправлено: denmor86 от Ноября 29, 2013, 12:47:58 pm
Код:
static void Pci080ClearBit(uint32_t bitmask, uint32_t addr) {
uint32_t t = in32(addr); // читаю предыдущее значение
printf("clear bit t=%x mask=%x val=%x\n",t,bitmask,t & ~bitmask);
    out32(addr,(uint32_t)(t & ~bitmask)); // выставляю текущее
}
void Pci080PllSetup(uint32_t value, uint32_t pll_addr, Pci080DevT *dev) {
out32(pll_addr, value);
Pci080SetBit(1 << 29, dev->control); // Пытаюсь выставить 29 бит в 1
uint32_t ctrl = in32 (dev->control); // читаю результат
printf("Pci080PllSetup control = %x\n",ctrl);
}

29 (да и любой до 8 ) биты не записываются(или не читаются). Т.е если я ставлю
Код:
Pci080SetBit(1 << 7, dev->control);

то всё нормально 7 бит выставляется.

В чём может быть беда?

Возможно это связано с тем что я юзаю mmap_device_memory?
Код:
dev->base = (uint32_t) mmap_device_memory(0, info.BaseAddressSize[0],
PROT_READ | PROT_WRITE | PROT_NOCACHE, 0, info.CpuBaseAddress[0]);

dev->control = dev->base + 0x4;


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Ноября 29, 2013, 01:48:29 pm
Код:
#define pci080_in8(addr)   *(volatile uint8_t *)(addr);
#define pci080_in16(addr)  *(volatile uint16_t *)(addr);
#define pci080_in32(addr)  *(volatile uint32_t *)(addr);

#define pci080_out8(addr,val)  { *(volatile uint8_t*)(addr) = val; }
#define pci080_out16(addr,val) { *(volatile uint16_t *)(addr) = val; }
#define pci080_out32(addr,val) { *(volatile uint32_t *)(addr) = val; }
переписал функции на работу с указателем...

эффект тот же


Название: Re: Проблемы с in32 () или out32()
Отправлено: PoP от Ноября 30, 2013, 03:52:03 pm
Может плата пдоддерживает только побайтный доступ?


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Ноября 30, 2013, 10:05:25 pm
судя по коду этого же драйвера под Linux:

Код:
static void mmio32_clear_bit(u32 bitmask, u32 *reg)
{
u32 t = readl(reg);

writel(t & ~bitmask, reg);
}

должны работать запись и чтение по 4 байта...


Название: Re: Проблемы с in32 () или out32()
Отправлено: PoP от Ноября 30, 2013, 11:24:28 pm
Ну а readl и writel нигде не переопределены?
В описании платы указаны биты с номерами больше 7?
Получается хотябы прочитать из платы что-нибудь зарание точно известное целым двойным словом?


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Ноября 30, 2013, 11:42:25 pm
1. Не переопределены, стандартные линуксовые используются.
2. Да описание бьётся на на блоки по 4 байта (32).
3. В первых 4 байтах находится номер версии, он статичный, и его получается корректно прочитать (прочитанный совпадает с тем что указан в описании). Далее 4 байта, всяких настроек, вот тут и Опа с записью чего либо после 7 бита, а мне бы надо их юзать.


Название: Re: Проблемы с in32 () или out32()
Отправлено: PoP от Декабря 01, 2013, 01:14:29 am
Хотелось бы прочитать что-нибудь с не нулевым смещением :). Дефолтовые настрйки платы читаются правильно? Если нет - то, видимо просто попадаете нетуда.
Если читаются правильно, попробуйте писать побайтно(пословно), но обязательно проверяйте результат 32-х байтным чтением (если уж в описании всё по 32 бита), может ложиться очень по разному, далеко не все платы поддерживают все виды адресации.


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Декабря 01, 2013, 10:00:58 am
К сожалению, плату от меня на 1 неделю забрали, и попробовать почитать из неё у меня получится только через понедельник.

Вот код как мапится память этой платы под Linux

Код:
p = ioremap_nocache(pci_resource_start(pdev, 0),
    pci_resource_len(pdev, 0));
if (!p)
BAIL_OUT_VERBOSELY(err_exit, -EIO,
                   "can't remap %ldK from 0x%lx\n",
                   (unsigned long)pci_resource_len(pdev, 0) >> 10,
                   (unsigned long)pci_resource_start(pdev, 0));
dev->mapped_bar0 = p;
        dev->cregs = (struct mm080_cregs *)p;

Далее все смещение идут через структуру mm080_cregs
Код:
struct mm080_cregs {
u32 ident; // Идентификационный номер ячейки(0x37550047)(ro).
u32 control; // Регистр управления(rw) имеет следующие битов.
// поля:
// 0 - разрешение прерывания по событию превышения
// установленного порога(готовность данных)
// '0' - запрещены, '1' - разрешены.
// 1 - резерв.
// 2 - ZBT_MODE_SELECT управление мультиплексором
// обращения к ZBT памяти.
// '0' - работа прошивки, '1' - загрузка/чтение.
// 3 - резерв.
// 4 - разрешение эмуляции данных с АЦП1 в память
// синус 1МГц.
// 5 - разрешение эмуляции данных с АЦП2 в память
// синус 1МГц.
// 6 - разрешение эмуляции данных с АЦП3 в память
// синус 1МГц.
// 7 - разрешение эмуляции данных с АЦП4 в память
// синус 1МГц.
// 8 - разрешение работы компоратора и рег-ции данных
// в память по всем каналам.
// 9..28 - резерв.
// 29 - запуск загрузки конф-ции PLL. Для запуска
// надо установить в '1' .
// 30 - подтверждение прерывания по событию превы-
// шения установленного порога(готовность
// данных). Для подтверждения надо записать '1'.
// 31 - программный сброс прошивки.
// Разряды 24..31 сбрасываются автоматически.
// Внимание: именно 24..31, просто используются
// только 29..31 . В прошивке автоматический сброс
// сделан для резервных разрядов(24..28) на будущее.

u32 status; // Регистр состояния(ro) имеет след. битовые поля:
// 0 - проверка наличие качества частоты PLL1.
// 1 - проверка наличие качества частоты PLL2.
// Для битов '0' и '1' состояние "1" частота
// в норме, "0" - не в норме.
// 2..3 - резерв
// 4 - флаг превышения порога в канале 1.
// 5 - флаг превышения порога в канале 2.
// 6 - флаг превышения порога в канале 3.
// 7 - флаг превышения порога в канале 4.
// Для битов '4..7' состояние "1" - событие
// превышения, "0" - нет превышения.
// 8..29 - резерв.
// 30 - флаг прерывания по событию готовности данных
// '0' - нет события, '1' - есть событие.
// 31 - состояние линии прерывания на шине PCI
// '0' - линия в прерывании, '1' - нет прерывания.
// Прерывание снимается, когда все прерывания
// подтверждены.

u32 version; // Версия прошивки(ro).
u32 serial_num; // Серийный номер ячейки(rw), прописывается программно.
u16 threshold[4]; // Значения порога по каналам(rw).
// Разряды 0..11 - значение порога.
// Разряды 12..15 - резерв.

u32 pll_1_ctrl, pll_2_ctrl; // Регистр управления для PLL60 и PLL250(rw):
// разряды 0..6 - число M
// разряды 7,8 - число N
// разряды 9..11 - число T
};

например так
Код:
static void mmio32_set_bit(u32 bitmask, u32 *reg)
{
u32 t = readl(reg);

writel(t | bitmask, reg);
}
static void mmio32_clear_bit(u32 bitmask, u32 *reg)
{
u32 t = readl(reg);

writel(t & ~bitmask, reg);
}

static inline void flush_pci_txns(struct mm080_sysdev *dev)
{
readl(&dev->cregs->ident);
}
void interrupt_enable(struct mm080_sysdev *dev)
{
mmio32_set_bit(1 << 0, &dev->cregs->control);
flush_pci_txns(dev);
}
void hw_compare_enable(struct mm080_sysdev *dev)
{
mmio32_set_bit(1 << 8, &dev->cregs->control);
flush_pci_txns(dev);
}

а вот мои функции
Код:
static void Pci080SetBit(uint32_t bitmask, uint32_t addr) {
uint32_t t = in32(addr);
printf("set bit t=%x mask=%x val=%x\n",t,bitmask,t | bitmask);
out32(addr,(uint32_t)(t | bitmask));
}
static void Pci080ClearBit(uint32_t bitmask, uint32_t addr) {
uint32_t t = in32(addr);
printf("clear bit t=%x mask=%x val=%x\n",t,bitmask,t & ~bitmask);
    out32(addr,(uint32_t)(t & ~bitmask));
}
void Pci080InterruptEnable(Pci080DevT *dev) {
Pci080SetBit(1 << 0, dev->control);
pci080_in32(dev->base);
uint32_t ctrl = pci080_in32 (dev->control);
printf("Pci080InterruptEnable control = %x\n",ctrl);
}
Вообщем не пойму что я делаю не так((


Название: Re: Проблемы с in32 () или out32()
Отправлено: ed1k от Декабря 02, 2013, 10:02:51 am
Еще когда плата будет наберите в консоли 'pci -vvv' и все касаемое вашей платы скопипасте сюда.


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Декабря 02, 2013, 10:54:32 am
К сожалению доступ к плате будет только в следующий вторник.
Но я много раз смотрел вывод этой команды, какое поле вам интересно там?


Название: Re: Проблемы с in32 () или out32()
Отправлено: vshemm от Декабря 02, 2013, 06:32:22 pm
Код:
// 9..28 - резерв.
// Разряды 24..31 сбрасываются автоматически.

Наверное, там и должны читаться нули, не?


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Декабря 02, 2013, 07:47:52 pm
Код:
Разряды 24..31 сбрасываются автоматически.
// Внимание: именно 24..31, просто используются
// только 29..31 .
написано что 29 используется...


Название: Re: Проблемы с in32 () или out32()
Отправлено: ed1k от Декабря 02, 2013, 07:51:46 pm
Ну я все же надеюсь, что ожидаемого действа не происходит. Странно читать назад самосбрасывающиеся биты. Хотя похоже автор это и делает, но думается это вторично, ведь надо чтото делать если оно не работает.  

По поводу вывода pci -vvv интересует все, включая хексдамп конгифспейса.

Мне все же не понятно, устройство имеет доступ через порты ввода-ввывода или через память. Может иметь и оба режима одновременно, но адреса доступа обычно будут разные. В ваших функциях вверху жуткий микс. Set/clear используют порты, enable interrupts использует set (порт) и плюс самостоятельно лезет по памяти (указатель).

Младшие биты базового регистра адреса говорят о том это ввод-вывод или память (см соответствующие макросы в pci.h), соответсвенно надо сделать mmap_device_memory() или mmap_device_io() и использовать полученный адрес для выбранного метода доступа. И лучше не чередовать/смешивать методы доступа одного и того же железа.



Название: Re: Проблемы с in32 () или out32()
Отправлено: ed1k от Декабря 02, 2013, 07:58:59 pm
Код:
Разряды 24..31 сбрасываются автоматически.
// Внимание: именно 24..31, просто используются
// только 29..31 .
написано что 29 используется...
Это шутка? Вам же по-русски написали что бит 29 используется и запускает загрузку конфигурации ФАПЧ при записи туда 1. Потом этот бит самостоятельно сбрасывается. (и читается как 0).  Иначе для повторного запуска вам приходилось бы руками его сбрасывать в ноль, потом через задержку устанавливать в один.


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Декабря 02, 2013, 08:12:53 pm
Начну по порядку.
1. Устройство однозначно имеет доступ типа память (MEMORY) это было видно через pci -vvv. Соответственно мои потуги работать через порт IO ошибочно, и сделаны от безысходности.
2. Микс работы с IO/MEMORY так же из за того что игрался с разными функциями в надежде на положительный результат.
3. На счёт 29 бита возможно вы правы, но я пробовал и другие биты начиная с 8, наблюдал одинаковую картину. Бит не устанавливался.

А вообще извините меня за мой тупизм, первая моя работа с платой и вообще с драйверами.


Название: Re: Проблемы с in32 () или out32()
Отправлено: ed1k от Декабря 02, 2013, 08:52:02 pm
1. Странный ход для инженера. Лучше выпить или курнуть. От безысходности.
2. Я бы изменил линуксовый код, там где они указатель памяти получают, и функции writel/readl определил бы через волатайл указатели, т е менял бы минимум. Чем меньше самодеятельности, тем лучше.
3. Про бит 8 ничего не могу сказать. Нужно документацию читать, возможно другие биты конфига могут запрещать его изменение. Биты 29 и выше - четко написано, нужно писать единицу для старта действия. И судить произошла ли запись по тому, запустилось ли действие, т е сконфигурировался ли PLL и т д.

Ну а в остальном не отчаивайтесь. Все когда-то начинали.


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Декабря 02, 2013, 09:21:49 pm
1. Спасибо, жаль что я не пью и не курю, просто очень расстроился, плата в Москве, а я в Питере, приходится мотаться чтобы отлаживать драйвер.
2. Да думаю так и сделаю.
3. Беда в том что, документации то собственно и нету... Плату прошивали в Белоруссии, разработчиков давно уже нету. Имеется только старый драйвер под Debian 5, и карта памяти устройства в pdf.

А в целом спасибо огромное за поддержку.


Название: Re: Проблемы с in32 () или out32()
Отправлено: ed1k от Декабря 02, 2013, 09:43:19 pm
У вас код очень подробный, с комментариями. Для проверки ваших функций установки/сброса битов у вас есть u32 serial_num (rw). Идеально подходит для теста функций доступа. Что вписали, то и должны прочитать.


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Декабря 02, 2013, 09:47:34 pm
Во вторник буду пробовать ещё читать и писать, надеюсь что дело было только в моей не внимательности.

Спасибо, во вторник отпишусь ещё.


Название: Re: Проблемы с in32 () или out32()
Отправлено: ed1k от Декабря 02, 2013, 10:20:04 pm
Да всегда пожалуйста. А что до Питер-Москва, так наверно потому что рядом и расслабляет. Я, например, в Торонто, а железки, если повезет в Калифорнии, а если не повезет, в другую сторону лететь не меньше 13 часов. Разработчиков и документации чаще нет, чем есть, в эпоху этого застоявшегося кризиса. Ну или если есть документация, то на таком ломаном английском, что лучше б и не было ее.
Пишите. Удачи.


Название: Re: Проблемы с in32 () или out32()
Отправлено: PoP от Декабря 03, 2013, 12:23:06 pm
Добавлю про биты 8....23 - никто не обещял, что плата запомнит, что вы туда пишете. Они вполене могут быть никуда в самой плате не отмаплены.


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Декабря 03, 2013, 07:01:57 pm
Главное что я теперь понял как мне через serial_num проверить свои функции, ну не доверяю я своему коду)


Название: Re: Проблемы с in32 () или out32()
Отправлено: Kas1781 от Декабря 06, 2013, 03:47:40 pm
Кстати при использовании info.CpuBaseAddress[0] для получения адреса нужно базовый адрес включить в макрос:
PCI_MEM_ADDR(info.CpuBaseAddress[0]), а потом его мапить.

Еще в моей практике бывала ситуация когда из регистра нельзя было прочитать то, что записал. Скорее всего следует проанализировать исходный драйвер на предмет вообще использования 8-го бита на чтение.



Название: Re: Проблемы с in32 () или out32()
Отправлено: Basil-64 от Декабря 08, 2013, 09:39:06 pm
Во первых, поддерживаю ораторов, указывающих на то что аппаратные регистры далеко не всегда зеркальны по записи/чтению. Обычно в описании платы это указывается явно. А во вторых, хоть и тривиально до жути, но с учетом первого опыта автора, стоит напомнить о необходимости использования ThreadCtl(_NTO_TCTL_IO, 0).


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Декабря 11, 2013, 07:36:06 pm
Итак, краткий отчёт.

Сделал всё как вы все мне советовали. Читать, писать получается во все области памяти.

Теперь образовалась проблема, когда выставляю биты 1(разрешаю прерывания) и 8 (разрешаю сравнение с порогом)
комп виснет намертво (даже мышка не работает), спасает только резет по питанию...
чувствую дело в прошивке плисины(тут как всегда никакой инфы)... или может у меня в драйвере фигня какая...
Ни у кого мыслей на этот счёт нету?


Название: Re: Проблемы с in32 () или out32()
Отправлено: ed1k от Декабря 11, 2013, 09:12:49 pm
Мысли есть. Скорее всего контроллер ПДП настроен не верно и данные с каналов АЦП пишутся не туда, куда следует.

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

И еще вопрос, а работает ли эмуляция данных (биты 4-7) с АЦП в память?


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Декабря 11, 2013, 09:27:08 pm
Плата http://www.cifronik.ru/ADSP-3U.html (http://www.cifronik.ru/ADSP-3U.html)
Платформа http://emea.kontron.com/products/boards+and+mezzanines/3u+compactpci/x86+processor/cp307.html (http://emea.kontron.com/products/boards+and+mezzanines/3u+compactpci/x86+processor/cp307.html) ОС QNX 6.5
Регистры читаются и записываются (пробовал менять и снова читать всё норм)
Эмуляцию отдельно думаю не проверить, так как не включен блок сравнения с порогом и данные не формируются...
А вот как определить контролер DMA я пока не знаю)


Название: Re: Проблемы с in32 () или out32()
Отправлено: ed1k от Декабря 11, 2013, 10:57:28 pm
Отставить. У вас там сложнее, чем я думал. По 8Мб на канал на борту. И пишут, что эта память быстро доступна виртексу, т.е. вряд ли мепится в память также как эти ваши регистры статуса/управления. Надо читать доки и смотреть линуксовый драйвер как там этот виртекс напрограммирован чтобы данные ацп прочитать черес РСI или обрабатывать виртексом, если вам нужна обработка. Возможно и нету ПДП, если на борту столько памяти. А все же, что говорит pci -vvv?


Название: Re: Проблемы с in32 () или out32()
Отправлено: ed1k от Декабря 11, 2013, 11:03:52 pm
Еще вопрос. А что вы делаете в обработчике прерывания? Ведь если вы разрешаете прерывания (бит 1), то вы установили свой ISR handler.


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Декабря 12, 2013, 08:52:34 am
Обработка идёт на самой плисине, мне необходимо управлять её с помощью регистров управления и установки порогов ,а также читать с неё полученные значения по событию превышения порога.

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

В обработчике прерывания я выставляю флаги превышения порога в нужном канале, затем через poll проверяю их.


Название: Re: Проблемы с in32 () или out32()
Отправлено: @nger от Декабря 12, 2013, 11:42:32 am
В обработчике прерывания я выставляю флаги превышения порога в нужном канале, затем через poll проверяю их.

Источник очищаете? Если работа идет по уровню, как раз и подвесите систему.


Название: Re: Проблемы с in32 () или out32()
Отправлено: ed1k от Декабря 12, 2013, 07:37:28 pm
Плата на РС шине, поэтому прерывания по уровню. Без опций.

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


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Декабря 12, 2013, 11:20:55 pm
Код:
static irqreturn_t mm080_interrupt(int irq, void *sysdev, struct pt_regs *regs)
{
int i, do_wake = 0;
struct mm080_sysdev *dev = sysdev;
u32 channel = 0;
irqreturn_t ret = IRQ_NONE;

spin_lock(&dev->lock);
channel =  hw_interrupt_ready_flags(dev);
if (channel) {
// Выставляем флаг POLLIN для всех каналов устройства и флаг POLLPRI для
// того канала, в котором произошло превышение. Флаг POLLIN сообщает о
// том, что данные готовы для вычитывания, т.к. по превышению порога
// хотя бы в одном канале, данные сливаются со всех каналов и анализи-
// руются.
for (i = 0; i < NUM_CHANNELS; i++) {
dev->adc_poll_flags[i] |= POLLIN;
if (channel & (1 << i))
dev->adc_poll_flags[i] |= POLLPRI;
}
// dev->adc_poll_flags[0] |= POLLPRI;
hw_interrupt_acknowledge(dev);
do_wake = 1;
ret = IRQ_HANDLED;
// hw_compare_disable(dev);
// interrupt_disable(dev);
}
spin_unlock(&dev->lock);
if (do_wake)
for (i = 0; i < NUM_CHANNELS; i++)
wake_up_interruptible(&dev->adc_waitq[i]);

return ret;
}
да вроде тут нет никакого сброса прерывания...


Название: Re: Проблемы с in32 () или out32()
Отправлено: ed1k от Декабря 12, 2013, 11:54:03 pm
what is hw_interrupt_acknowledge(dev)?


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Декабря 13, 2013, 08:49:35 am
Установка 30 бита в 1

Код:
// 30 - подтверждение прерывания по событию превы-
// шения установленного порога(готовность
// данных). Для подтверждения надо записать '1'.
в своём драйвере я так же дергаю эту функцию.

Единственно что в в обработчик прерывания я попадаю только 1 раз при вызове InterruptAttach...


Название: Re: Проблемы с in32 () или out32()
Отправлено: ed1k от Декабря 13, 2013, 10:00:39 am
При вызове InterruptAttach() вы устанавливаете свой обработчик. Попадать в него вы должны по выставлению сигнала прерывания от платы. Честно, я не очень представляю что вы делаете. В документации qnx есть целая глава посвященная написанию обработчиков прерываний и как это работает. Я надеюсь вы ее читали.


Название: Re: Проблемы с in32 () или out32()
Отправлено: ed1k от Декабря 13, 2013, 10:04:17 am
Вы вызываете InterruptAttach() _до_ _того_, как ставите биты в регистре управления разрешающие работу и прерывания, верно?


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Декабря 13, 2013, 10:21:39 pm
Верно, InterruptAttach я делаю до того как разрешаю прерывания. Аттач делается в инициализации драйвера после инициализации ресурменеджера. Я понимаю, что привязываю прерывания платы к своей функции-обработчику.
Прерывания я разрешаю уже из своей программы, командой драйверу "включить прерывания"

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


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Января 21, 2014, 06:59:20 pm
Итак я снова добрался до платы, точнее всего устройства в сборе.

Посмотрел его работу на Debian 5 убедился что драйвер для linux работает корректно и плата прошита.

Лог pci -vvv
Код:
Class          = Communication (Other)
Vendor ID      = 3755h, Unknown
Device ID      = 47h, Unknown Unknown
PCI index      = 0h
Class Codes    = 078000h
Revision ID    = 1h
Bus number     = 3
Device number  = 10
Function num   = 0
Status Reg     = 200h
Command Reg    = bh
I/O space access enabled
Memory space access enabled
Bus Master disabled
Special Cycle operations monitor
Memory Write and Invalidate disabled
Palette Snooping disabled
Parity Error Response disabled
Data/Address stepping disabled
SERR# driver disabled
Fast back-to-back transactions to different agents disabled
PCI INTx enabled
Header type    = 0h Single-function
BIST           = 0h Build-in-self-test not supported
Latency Timer  = 0h
Cache Line Size= 0h
BAR - 0 [Mem]  = f0000000h 32bit length 134217728 enabled
Subsystem Vendor ID = 3755h
Subsystem ID        = 4h
Max Lat        = 0ns
Min Gnt        = 0ns
PCI Int Pin    = INT A
Interrupt line = 11
CPU Interrupt  = bh
Device Dependent Registers:
0x040:  0000 0000 0b00 0002   0000 0000 0000 0000
0x050:  0000 00f0 0000 0000   0000 0000 0000 0000
0x060:  0000 0000 0000 0000   0000 0000 0000 0000
0x070:  0000 0000 0000 0000   0000 0000 0b00 0000
0x080:  0000 0000 0b00 0002   0000 0000 0000 0000
0x090:  0000 00f0 0000 0000   0000 0000 0000 0000
0x0a0:  0000 0000 0000 0000   0000 0000 0000 0000
0x0b0:  0000 0000 0000 0000   0000 0000 0b00 0000
0x0c0:  0000 0000 0b00 0002   0000 0000 0000 0000
0x0d0:  0000 00f0 0000 0000   0000 0000 0000 0000
0x0e0:  0000 0000 0000 0000   0000 0000 0000 0000
0x0f0:  0000 0000 0000 0000   0000 0000 0b00 0000


Проблема моя сохранилась, после установке разрешения плате делать сравнение с порогом, плата вешает всю систему.
Функции коннекта к плате.
Код:
/**
 @fn int Pci080Open( mm080_sysdev *dev)
 @brief Инициализация устройства

 Инициализация и поиск устройства на шине
 @param dev    - Дескриптор устройства
 @return 0 - успех, -1 - ошибка
 */
int Pci080Open(struct mm080_sysdev *dev) {
pthread_attr_t attr;
int ret = 0;

if (g_pDevice)
return (-1);

if (Pci080Connect(PCI_VENDOR_ID_ADVANTECH, PCI_DEVICE_ID_PCI080, dev) == -1)
return (-1);

if (dev->attached != 1)
return (-1);

pthread_attr_init(&attr);

dev->iid = InterruptAttach( (int)dev->irq, IrqHandler, (const void *)dev, sizeof( struct mm080_sysdev * ), _NTO_INTR_FLAGS_END );
if ( dev->iid < 0 )
  return (-1);
else
  printf("[DRV_080_EMI] Interrupt %d is atteched in %d IRQ.\n",dev->iid,dev->irq);

g_pDevice = dev;
ret = ResmgrInit(dev);
if (ret != 0)
return (ret);
pthread_create(&dev->resmgr_thread, &attr, &ResmgrProcess, (void *) dev);

printf("[DRV_080_EMI] Driver is open.\n");

return (0);
}
int Pci080Connect(uint16_t vid, uint16_t did, struct mm080_sysdev *dev) {
struct pci_dev_info info;
void *pDevice = NULL;
void *p = NULL;
int i = 0;

if ((g_pciServer = pci_attach(0)) == -1)
return (-1);

/* Enable I/O-ports access */
ThreadCtl(_NTO_TCTL_IO, 0);

memset(&info, 0, sizeof(info));
memset(dev, 0, sizeof(struct mm080_sysdev));

info.VendorId = vid;
info.DeviceId = did;
  pDevice = pci_attach_device(NULL, PCI_SEARCH_VENDEV, 0, &info);
if (!pDevice) {
printf("[DRV_080_EMI] Error pci attach device. Exit. \n");
pci_detach(g_pciServer);
g_pciServer = 0;
return (-1);
}

p = mmap_device_memory(0, info.BaseAddressSize[0],
PROT_READ | PROT_WRITE | PROT_NOCACHE, 0, PCI_MEM_ADDR(info.PciBaseAddress[0]));
if( !p ) {
printf("[DRV_080_EMI] Error mmap device memory. Exit. \n");
pci_detach(g_pciServer);
g_pciServer = 0;
return(-1);

}
dev->device = pDevice;
dev->vid = vid;
dev->did = did;
dev->irq = info.Irq;
dev->cregs = (struct mm080_cregs *)p;
dev->ver = readl(&dev->cregs->version);

dev->mapped_bar0 = p;
dev->bar0_area_len = info.BaseAddressSize[0];

// Задаём доступ прошивки к ZBT.
hwctl_set_zbt_access_sw(dev, FW_ZBT_ACCESS);
// Настраиваем PLL.
// 0x99 - 100MHz; 0x19 - 200MHz; 0x1f - 248MHz.
hw_pll_setup(0x19, &dev->cregs->pll_1_ctrl, dev);
// Запрещаем прерывания. Прерывания будут разрешаться программой.
interrupt_disable(dev);

for (i = 0; i < NUM_CHANNELS; i++)
dev->adc_poll_flags[i] = 0;

strcpy(dev->name, PCI_DEVICE_NAME_PCI080 );
dev->attached = 1;


#ifdef _DEBUG_
printf("[DRV_080_EMI] Device found:\n");
printf("[DRV_080_EMI] did:vid: %04x:%04x\n", dev->vid, dev->did);
printf("[DRV_080_EMI] name: %s\n", dev->name);
printf("[DRV_080_EMI] version: %#x\n", dev->ver);
printf("[DRV_080_EMI] control reg = %#x\n", mmio32_read(&dev->cregs->control));
#endif
return (0);
}

Функция обработчик прерывания:
Код:
const struct sigevent * IrqHandler(void *area, int id) {
int i;
struct mm080_sysdev *dev = (struct mm080_sysdev *) area;
uint32_t channel = 0;

pthread_spin_lock(&dev->lock);
channel = hw_interrupt_ready_flags(dev);

if (channel) {
// Выставляем флаг POLLIN для всех каналов устройства и флаг POLLPRI для
// того канала, в котором произошло превышение. Флаг POLLIN сообщает о
// том, что данные готовы для вычитывания, т.к. по превышению порога
// хотя бы в одном канале, данные сливаются со всех каналов и анализи-
// руются.
#ifdef _DEBUG_
printf("Interrupt in %d channel \n", channel);
#endif
for (i = 0; i < NUM_CHANNELS; i++) {
dev->adc_poll_flags[i] |= POLLIN;
if (channel & (1 << i))
dev->adc_poll_flags[i] |= POLLPRI;
}
hw_interrupt_acknowledge(dev);
}
pthread_spin_unlock(&dev->lock);
return 0;
}

Я в тупике, написал программку тест, последовательно ввожу команды типа, разрешить прерывания, загрузить пороги, разрешить сравнение с порогом. После последней команды ребутаю СПишку(( :'(


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Января 22, 2014, 10:29:54 am
Ларчик открывался просто, нельзя использовать printf(...) в функции обработчике прерывания...

Разбираюсь с поллингом...

Забавно всё делать в первый раз, столько всего узнаёшь  :)


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Января 22, 2014, 12:51:14 pm
Возник вопрос, как правильно и легче организовать приём статуса от платы?
Плата по прерыванию понимает в каком из 4 каналов произошло превышение порога, клиент это должен понять и прочитать информацию с платы.
Нашёл 3 функции похожие друг на друга:
poll(...)
select(...)
ionotify(...)

Какую правильно использовать и как правильно реализовать установку флагов превышения в функции обработчике прерывания в драйвере?


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Января 22, 2014, 06:50:45 pm
Итак с select я разобрался, почти... не понял как получить разные ответы... ну думаю разберусь...

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

Существует ли способ узнать правильно ли я маплю память устройства?

я маплю так:
Код:
p = mmap_device_memory(0, info.BaseAddressSize[0],
PROT_READ | PROT_WRITE | PROT_NOCACHE, 0, PCI_MEM_ADDR(info.PciBaseAddress[0]));

далее использую конструкции типа:
Код:
void *addres = pDev->mapped_bar0 + mem_areas[inode].offset + mem_areas[inode].shift;
где
Код:
dev->mapped_bar0 = p;

в linux-драйвере память мапится

Код:
p = ioremap_nocache(pci_resource_start(pdev, 0),
    pci_resource_len(pdev, 0));


Название: Re: Проблемы с in32 () или out32()
Отправлено: denmor86 от Января 30, 2014, 09:36:17 pm
Всем спасибо за ответы, тему можно закрыть. Разобрался сам.