Итак я снова добрался до платы, точнее всего устройства в сборе.
Посмотрел его работу на Debian 5 убедился что драйвер для linux работает корректно и плата прошита.
Лог
pci -vvvClass = 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;
}
Я в тупике, написал программку тест, последовательно ввожу команды типа, разрешить прерывания, загрузить пороги, разрешить сравнение с порогом. После последней команды ребутаю СПишку((
