
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.97.9.171] |
![]() |
|
Сообщ.
#1
,
|
|
|
Хаюшки.
Вобщем тема такая - есть старая добрая программа написанная на Borland C++ 3.1, есть компьютер на котором это все чудно работает под DOS, и появляется новое железо (а конкретно PCI плата ЦАП Advantech PCI-1724) и сразу же появляется вопрос : Описание говорит что "эта плата специально разработана для легкого использования с помощью 32 бит комманд" ![]() ![]() И возник тупик ![]() Если все таки реально подскажите как? |
Сообщ.
#2
,
|
|
|
32-битные типы в BC++ 3.1 вроде никто не отменял. Есть библиотека-то какая-нибудь для работы с этой платой?
|
Сообщ.
#3
,
|
|
|
Типы то есть, но во внешний порт, коим является PCI - плата как их засунуть?
На диске шли сишный файлик для работы с PCI, примеры для DOS и Вынь, и dll-ки для винды. В примерах для доса этой платы нету ![]() |
Сообщ.
#4
,
|
|
|
Цитата vadymko @ "эта плата специально разработана для легкого использования с помощью 32 бит комманд" А конкретнее? Цитата vadymko @ Типы то есть, но во внешний порт, коим является PCI - плата как их засунуть? Это не вопрос. Адреса и порты платы можешь узнать с помощью PCI-BIOS. Цитата vadymko @ На диске шли сишный файлик для работы с PCI, примеры для DOS Примеры в какую тему? |
Сообщ.
#5
,
|
|
|
В вставках компилятор не узнаёт EAX, но сам tasm от BC3.1 м расширенными регистрами работает.
Не проверял в работе, но компилируется и линкуется и должно прокатить ![]() ![]() ; FILE 'port32.asm' ;32bit input/output function .386p PORT32_TEXT segment byte public use16 'CODE' assume cs:PORT32_TEXT _inpdw proc far push bp mov bp, sp mov dx, word ptr [bp+6] in eax, dx shld edx, eax, 16 ;исправлена ошибка - возвращаться должно через dx:ax - спасибо [b]cppasm[/b] ret _inpdw endp _outpdw proc far push bp mov bp, sp mov dx, word ptr [bp+6] mov eax, dword ptr [bp+8] out dx, eax pop bp ret _outpdw endp PORT32_TEXT ends public _outpdw public _inpdw end ![]() ![]() extern "C" { unsigned long __cdecl inpdw(unsigned int port); void __cdecl outpdw(unsigned int port, unsigned long value); } unsigned long i = inpdw(25); outpdw(25, i); |
Сообщ.
#6
,
|
|
|
Цитата AndNot @ А конкретнее? The PCI-1724U is delivered with an easy-to-use 32-bit device driver for user programming under the Windows 2000/95/98/ME/XP operating sys- tems. We advise users to program the PCI-1724U using the 32-bit device drivers provided by Advantech to avoid the complexity of low-level reg- istry programming. Вот примеры в инете (500кб), такие же и на диске, но именно на эту плату нет ![]() http://taiwan.advantech.com.tw/unzipfunc/unzipfile.asp?File_Id=1%2BFW%2B2428 Базовый адрес естественно я получу от биоса, но по этому адресу мне надо записать 32-разрядное слово, в два смыка (2 ворда со смещением) естественно сразу попробовал - не катит Цитата Adil @ В вставках компилятор не узнаёт EAX, но сам tasm от BC3.1 м расширенными регистрами работает. Не проверял в работе, но компилируется и линкуется и должно прокатить А вот это уже интересно, спасибо, попробую... |
Сообщ.
#7
,
|
|
|
Цитата vadymko @ Вот примеры в инете (500кб), такие же и на диске, но именно на эту плату нет Можно подобрать. Например ясно что девайс опознается так: ![]() ![]() iErrCode = find_pci_device( 0x1724, 0x13fe, 0, &ucBusNumber, &ucDevAndFunc ); if (iErrCode == NOT_SUCCESSFUL ) { printf("\nPCI-1724 search fail.\n"); exit(1); } // //Get base address, from PCI base address range 2 // iErrCode = read_configuration_dword( ucBusNumber, ucDevAndFunc, PCI_CS_BASE_ADDRESS_2, &dwData); if (iErrCode == NOT_SUCCESSFUL) { printf("\nPCI-1724 gets base address fail.\n"); exit(1); } else dwBaseAddr = dwData & 0xfffffffc; Это уже не мало. Далее можешь попытаться сделать как и для модели 1720. Скорее всего разница у них не очень большая, можно и в кон попасть. Или дизассмить VxD дрова на твою плату. |
Сообщ.
#8
,
|
|
|
Цитата vadymko @ В вставках компилятор не узнаёт EAX, но сам tasm от BC3.1 м расширенными регистрами работает. Не проверял в работе, но компилируется и линкуется и должно прокатить С сожалением приходится констатировать - не прокатило ![]() ![]() Цитата AndNot @ Можно подобрать. Например ясно что девайс опознается так: Ну это то как раз единственное что и работает.. Так как относится скорее не к самой плате а к PCI вообще... а дальше уже идет конкретика платы.... Вот оттуда же из руководства - команда выглядит так: Offset___________PCI-1724U Register Format Address____D31~D24_____D23~D16_____D15__D14__D13~D0 0x00_________N/A____Group/Channel___REG1_REG0___DAC ______________________Select Bit________________Data ______________________________________________Code Это все надо загнать одним смыком.... |
Сообщ.
#9
,
|
|
|
Кстати может кто поможет бедному
![]() Назовем ее типа "Вывод INT32 в порт в DOSе" ![]() |
Сообщ.
#10
,
|
|
|
Можно. Только уточни какие функции и с какими параметрами нужны. Кстати, а почему бы на ватком Си не попробовать?
|
Сообщ.
#11
,
|
|
|
Функции всего две - ввод/вывод 32 битного слова из/в внешнюю шину.
В принципе все это реализовано в приведенном примере. Все красиво реализовано - и передача и обработка 32 бит, единственно меня терзают смутные сомнения, что TASM в строке Цитата Adil @ out dx, eax сгенерирует процессору опкод вывода 32-разрядного слова, а не любимого 16-битного ![]() ![]() Watcom не применял только изза неприменения ранее ![]() ![]() З.Ы. Кстати не судите строго (или обьясните-не спец в ассемблере под ПК), но вот команда --- outport (dwBaseAddr,v_int); --- в сгенеренном ассемблере выглядит: ?debug L 11 mov dx,word ptr [bp-8] mov ax,word ptr [bp-4] out dx,ax то есть стек идет в минуса, а в вышеприведенном примере в плюса... |
Сообщ.
#12
,
|
|
|
Цитата vadymko @ то есть стек идет в минуса, а в вышеприведенном примере в плюса... Ну это кому как нравится. Просто всё зависит от того куда указывает bp. А по поводу темы в общем - приведённые выше процедуры 100% рабочие. И tasm всё нормально откомпилирует. Проблема не в том что не работает 32-битный ввод/вывод, а в том что ты не знаеш протокола общения с устройством. Цитата vadymko @ Offset___________PCI-1724U Register Format Address____D31~D24_____D23~D16_____D15__D14__D13~D0 0x00_________N/A____Group/Channel___REG1_REG0___DAC ______________________Select Bit________________Data ______________________________________________Code Вот это не сильно понял, это таблица? |
Сообщ.
#13
,
|
|
|
Цитата vadymko @ сгенерирует процессору опкод вывода 32-разрядного слова, а не любимого 16-битного , хотя вроде по написанию должен Ясно. Для режима 16-бит перед коммандами ставится опкод 66h. Например так: ![]() ![]() dword inportd (port: word) { asm { mov dx, [port] db 66h in ax, dx } } outportd (port: word; num: dword) { asm { db 66h mov ax, word ptr [num] mov dx, [port] db 66h out dx ,ax И так далее, таким макаром. Так что внешние модули не нужны. Другой вопрос если само железо не поддерживает 32-х битные операции с портами. |
Сообщ.
#14
,
|
|
|
Цитата cppasm @ Проблема не в том что не работает 32-битный ввод/вывод, а в том что ты не знаеш протокола общения с устройством. Протокол состоит в банальной низкоуровневой записи в регистр платы по базовому адресу выдаваемому биосом для данной PCI платы. Адрес чудненько получается, а вот реакции на запись не происходит. Цитата cppasm @ Вот это не сильно понял, это таблица? нет это побитовая раскладка команды (это то мне как микроконтрольщику и понятнее всего ![]() то есть младшие 14 бит - это значение для ЦАПа потом 2 бита - задают режим его работы следующие 8 бит задают номер канала (их на плате 32 штуки) ну и старшие 8 бит не используются. Значение Offset задает местонахождение этого регистра относительно базового адреса платы (в данном случае 0x00 ) Сформированная по этому образу команда и загоняется в этот регистр. |
![]() |
Сообщ.
#15
,
|
|
Цитата vadymko @ адрес небось далеко за мегабайтом лежит? а ты в него ещё записывать чего-то пытаешься Адрес чудненько получается, ![]() |
Сообщ.
#16
,
|
|
|
Цитата archimed7592 @ адрес небось далеко за мегабайтом лежит? а ты в него ещё записывать чего-то пытаешься Вот это на мысли наводит ![]() А плата использует Port IO или Memory Mapped IO? И какой адрес получается при чтении из конфигурационного пространства PCI? |
![]() |
Сообщ.
#17
,
|
|
ну раз чудненько получается адрес, то наверное Memory Mapped IO
![]() |
Сообщ.
#18
,
|
|
|
Цитата AndNot @ Другой вопрос если само железо не поддерживает 32-х битные операции с портами. Ну железо - промышленный комп с гигагерцовым пеньком. И естественно из под винды адвантековскими тестовыми утилитками плата чудненько управляется. Я раньше работал с их платами в досе - все чудно шло, но с вордовыми обменами. А с 32 битами вот с первой платой столкнулся... Добавлено Цитата cppasm @ И какой адрес получается при чтении из конфигурационного пространства PCI? Сейчас точно не скажу - но адрес недалеко, где то что то типа 0x0C00 Я говорил, что уже работал с этими платами, и с 16 разрядами все работало |
Сообщ.
#19
,
|
|
|
Вот уточнил - базовые адреса плат идут 0xC100, 0xC200 и т.д....
|
![]() |
Сообщ.
#20
,
|
|
Цитата vadymko @ насколько я понял из примеров на которые ты дал ссылку, под базовым адресом понимается порт в который ты должен писать значения, а не адрес в памяти Вот уточнил - базовые адреса плат идут 0xC100, 0xC200 и т.д.... ![]() ![]() |
Сообщ.
#21
,
|
|
|
Цитата archimed7592 @ ну раз чудненько получается адрес, то наверное Memory Mapped IO Это откуда такие выводы? Базовый адрес - это базовый адрес. Просто адрес относительно которого отсчитываются все адреса регистров устройства. Может быть как Port IO, так и Memory Mapped IO. Цитата vadymko @ Вот уточнил - базовые адреса плат идут 0xC100, 0xC200 и т.д.... Уточнил как? Это в PCI conf прописано или ты другими путями какими-то смотрел? Вообще дамп конфигурационного пространства PCI этой платы очень бы помог - многое бы прояснилось... Снять можно скажем этой утилитой: http://members.datafast.net.au/dft0802/downloads/pci32.zip Запускать из консоли как-то так: ![]() ![]() PCI32.EXE -D>pci.txt Отчёт будет в pci.txt, запости сюда, а лучше приаттач. |
![]() |
Сообщ.
#22
,
|
|
Цитата cppasm @ Это откуда такие выводы? Базовый адрес - это базовый адрес. ![]() ![]() |
Сообщ.
#23
,
|
|
|
Базовый адрес - это базовый адрес порта
![]() |
Сообщ.
#24
,
|
|
|
Цитата archimed7592 @ просто в моём понимание адрес - это адрес, а никак не порт... Ну у тя ж тоже адрес есть, хоть ты и не в памяти живёш ![]() |
Сообщ.
#25
,
|
|
|
Цитата cppasm @ Уточнил как? Это в PCI conf прописано или ты другими путями какими-то смотрел? Уточнил собственной программой ![]() Еще раз уточню чтоб вопросов в эту сторону не было - с другими платами этой серии (с теми же платами цифрового ввода/вывода) все работает, то есть и получение адреса, и вывод значений. Цитата cppasm @ Снять можно скажем этой утилитой: Как попаду к железу сниму и скину ![]() |
Сообщ.
#26
,
|
|
|
Вот кусок рабочего кода, который я использую при работе с нашими PCI-устройствами. Именно BC31, DOS.
ВАЖНО! В настройках проекта поставить Option | Compiler | Advanced code generation | Instruction set -> 80386. ![]() ![]() typedef signed char schar; typedef unsigned char byte; typedef unsigned short word; typedef unsigned long dword; dword devid = 0x11112222; // Vendor ID, Device ID dword devno = 0; // Номер устройства (если несколько) #define outportv(addr,data) _DX = (addr); _EAX = (dword)(data); asm db 0x66; asm out dx,ax; #define _inportd(addr) _DX = (addr); asm db 0x66; asm in ax,dx; #define inportv(addr,v) _DX = (addr); asm db 0x66; asm in ax,dx; v = _EAX; dword inportd(word addr) { _DX = (addr); asm db 0x66; asm in ax,dx; return _EAX; } void outportd(word addr, dword data) { _DX = addr; _EAX = data; asm db 0x66; asm out dx,ax; } //------------------------------------------------------------- // Инициализация устройства //------------------------------------------------------------- void FindDev(void) { _SI = (word) devno; _DX = (word) (devid >> 16); _CX = (word) devid; _AX = 0xB102; asm int 0x1A; if (_AH != 0) { _SI = (word) devno; _DX = (word) (devid1 >> 16); _CX = (word) devid1; _AX = 0xB102; asm int 0x1A; if (_AH != 0) { printf("Ошибка поиска устройства\n"); exit(4); } } bx = _BX; _DI = 0x10; _BX = bx; _AX = 0xB108 + 2; asm int 0x1A; if (_AH != 0) { printf("Ошибка чтения устройства\n"); exit(4); } bar10 = _ECX; base = bar10 & 0xFFFC; _DI = 0x3C; _BX = bx; _AX = 0xB108 + 0; asm int 0x1A; irq = _CL; if (irq < 8) intno = irq + 0x08; else intno = irq - 8 + 0x70; printf("BAR10 = %08lX, Base = %04X, IRQ = %d\n", bar10, base, irq); if (base == 0) exit(4); } |
Сообщ.
#27
,
|
|
|
Цитата vmp @ Сильно...typedef signed char schar; Внушает. |
Сообщ.
#28
,
|
|
|
Цитата Adil @ Цитата (vmp @ Сегодня, 12:14) typedef signed char schar; Сильно... Внушает. А что делать, если приходится писать и таскать тексты программ между 5 процессорами разных архитектур и с разной длиной слова? И у 4 разных производителей компиляторов разные понятия о типе char - где знаковый, где беззнаковый, где настраивается ключем компилятора. |
Сообщ.
#29
,
|
|
|
![]() ![]() ![]() Не подумайте чего плохого ![]() vmp шаман ![]() Отцу русской демократии помогло Цитата vmp @ ![]() ![]() #define outportv(addr,data) _DX = (addr); _EAX = (dword)(data); asm db 0x66; asm out dx,ax; #define _inportd(addr) _DX = (addr); asm db 0x66; asm in ax,dx; #define inportv(addr,v) _DX = (addr); asm db 0x66; asm in ax,dx; v = _EAX; Не знаю что не так с предыдущими примерами, или что с ними не так делал я, но прокатил только последний вариант. Код х386 стоял в принципе везде, так что на это кивать вроде нечего... Спасибо всем!!! |
Сообщ.
#30
,
|
|
|
Ну это реально мистика
![]() Вот это ![]() ![]() asm db 0x66; asm out dx,ax; ![]() ![]() asm out dx,eax; Возможно правда с моделью памяти косяк в первом варианте - она на large рассчитана (far вызов). И в чтении порта там ошибка - результат в eax возвращается, а надо dx:ax |
Сообщ.
#31
,
|
|
|
Цитата cppasm @ Ну это реально мистика ![]() Просто я умнел на глазах с каждым примером ![]() Программы везде под large писаны, да и пользовал я тока вывод... Кстати позже я и второй пример запустил, уже вот в таком немного отредактированном виде, ну в принципе они практически не отличаются (ни от исходного ни от примеров vmp) ![]() ![]() dword inportd (word port) { asm { mov dx, [port] db 66h in ax, dx } } outportd (word port, dword num) { asm { db 66h mov ax, dword ptr [num] mov dx, [port] db 66h out dx ,ax } } |
Сообщ.
#32
,
|
|
|
Цитата vadymko @ Здесь такая же ошибка, что и у меня. Только у меня поправить проще - просто добавлением строки![]() ![]() dword inportd (word port) { asm { mov dx, [port] db 66h in ax, dx } } ![]() ![]() shld edx,eax,16 ![]() |
Сообщ.
#33
,
|
|
|
Цитата Adil @ Здесь такая же ошибка, что и у меня. Только у меня поправить проще - просто добавлением строки shld edx,eax,16 после инструкции in ![]() Спасибо учтем. Просто инпорт я не пользовал. Мне нужен просто вывод..вот и упустил.. ![]() |
Сообщ.
#34
,
|
|
|
Vadymko, можешь дать исходники, которые получились. А то такая же проблемма возникла (тоже с PCI-1724U), а насчет работы с регистрами и асемблера я ни в зуб ногой. Буду очень благодарен.
|
Сообщ.
#35
,
|
|
|
Вобщем выкладываю сборную солянку, собранную здесь общим коллективом, на всеобщее обозрение...
Главное ее достоинство - РАБОТАЕТ !! ![]() ![]() ![]() #include <dos.h> #include <stdio.h> #include <conio.h> #include <stdlib.h> #include "..\hardware\PCI.H" /************ * Global variable declare ************/ //typedef signed char schar; //typedef unsigned char byte; //typedef unsigned short word; //typedef unsigned long dword; #define outportv(addr,data) _DX = (addr); _EAX = (dword)(data); asm db 0x66; asm out dx,ax; #define inportv(addr,v) _DX = (addr); asm db 0x66; asm in ax,dx; v = _EAX; dword dwDACBaseAddr; //Base address union wrdstr { int wrd[2]; dword lng; } dat; int Init1724(void) { int wVendorId, wDeviceId, wIndex; int iErrCode; byte ucBusNumber, ucDevAndFunc; dword dwData; wIndex = 0; wVendorId = 0x13fe; wDeviceId = 0x1724; /*************************** * Get 1724's resource ***************************/ // // Search PCI-1724 // iErrCode = find_pci_device( wDeviceId, wVendorId, wIndex, &ucBusNumber, &ucDevAndFunc ); if (iErrCode == NOT_SUCCESSFUL ) { //printf("\nPCI-1724 search fail\n"); return -1; } // //Get base address, from PCI base address range 2 // iErrCode = read_configuration_dword( ucBusNumber, ucDevAndFunc, PCI_CS_BASE_ADDRESS_2, &dwData); if (iErrCode == NOT_SUCCESSFUL) { //printf("\nPCI-1724 gets base address fail\n"); return -2; } else dwDACBaseAddr = dwData & 0xfffffffc; // printf("\n\n\n\n\tPCI-1724 BaseAddress: %lx\r\n\n",dwDACBaseAddr); return 0; } int AnalogOutput(unsigned int wChannel, unsigned int wValue) { // MAX= 2^14 = 16383 = 0x3fff // Middle = 8191 = 0x1fff int GroupGX,ChannelCX; if (wValue > 0x3fff) wValue = 0x3fff; GroupGX = 0x0001 << (wChannel/8); ChannelCX = wChannel%8; dat.wrd[1] = (GroupGX << 4)+ ChannelCX; dat.wrd[0] = wValue + 0xC000; if (dwDACBaseAddr==0) return(1); outportv(dwDACBaseAddr, dat.lng); return(0); } void main(void) { int wChannel; int wValue,ch,i; Init1724(); wChannel=0; clrscr(); // простой тестик - выдает по кругу значение на ЦАП... do { if (wValue>=0x3fff) {wValue =0;clrscr();} else wValue+=1; gotoxy(20,2); AnalogOutput(wChannel,wValue); putch('\n'); for (i=0;i<wValue/205;i++) if (i<0x3fff/410) putch ('_'); else putch('-'); putch('\r'); delay(1); } while (!kbhit()); } /* ////////////////////////////////// // Из вольт в данные переводила вот такая простенькая процедурка... // Analog OUTPUT 14 bit = 0 - 8192 - 16384 -/+ 10V // РАБОТАЕМ С МИЛИВОЛЬТАМИ void SetU(double val) { // значения max,min в принципе подбирал по вольтметру на каждый канал // ну это по желанию... unsigned int max = 16260; // +10V ( 9.999) unsigned int min = 270; // -10V (-9.999) double delta=20000.0/(max-min); unsigned int wValue=(val+10000.0)/delta+min; AnalogOutput(chan0, wValue); // } */ |
Сообщ.
#36
,
|
|
|
Цитата vadymko @ Вобщем выкладываю сборную солянку, собранную здесь общим коллективом, на всеобщее обозрение... Главное ее достоинство - РАБОТАЕТ !! ![]() ![]() ![]() #include <dos.h> #include <stdio.h> #include <conio.h> #include <stdlib.h> #include "..\hardware\PCI.H" /************ * Global variable declare ************/ //typedef signed char schar; //typedef unsigned char byte; //typedef unsigned short word; //typedef unsigned long dword; #define outportv(addr,data) _DX = (addr); _EAX = (dword)(data); asm db 0x66; asm out dx,ax; #define inportv(addr,v) _DX = (addr); asm db 0x66; asm in ax,dx; v = _EAX; dword dwDACBaseAddr; //Base address union wrdstr { int wrd[2]; dword lng; } dat; int Init1724(void) { int wVendorId, wDeviceId, wIndex; int iErrCode; byte ucBusNumber, ucDevAndFunc; dword dwData; wIndex = 0; wVendorId = 0x13fe; wDeviceId = 0x1724; /*************************** * Get 1724's resource ***************************/ // // Search PCI-1724 // iErrCode = find_pci_device( wDeviceId, wVendorId, wIndex, &ucBusNumber, &ucDevAndFunc ); if (iErrCode == NOT_SUCCESSFUL ) { //printf("\nPCI-1724 search fail\n"); return -1; } // //Get base address, from PCI base address range 2 // iErrCode = read_configuration_dword( ucBusNumber, ucDevAndFunc, PCI_CS_BASE_ADDRESS_2, &dwData); if (iErrCode == NOT_SUCCESSFUL) { //printf("\nPCI-1724 gets base address fail\n"); return -2; } else dwDACBaseAddr = dwData & 0xfffffffc; // printf("\n\n\n\n\tPCI-1724 BaseAddress: %lx\r\n\n",dwDACBaseAddr); return 0; } int AnalogOutput(unsigned int wChannel, unsigned int wValue) { // MAX= 2^14 = 16383 = 0x3fff // Middle = 8191 = 0x1fff int GroupGX,ChannelCX; if (wValue > 0x3fff) wValue = 0x3fff; GroupGX = 0x0001 << (wChannel/8); ChannelCX = wChannel%8; dat.wrd[1] = (GroupGX << 4)+ ChannelCX; dat.wrd[0] = wValue + 0xC000; if (dwDACBaseAddr==0) return(1); outportv(dwDACBaseAddr, dat.lng); return(0); } void main(void) { int wChannel; int wValue,ch,i; Init1724(); wChannel=0; clrscr(); // простой тестик - выдает по кругу значение на ЦАП... do { if (wValue>=0x3fff) {wValue =0;clrscr();} else wValue+=1; gotoxy(20,2); AnalogOutput(wChannel,wValue); putch('\n'); for (i=0;i<wValue/205;i++) if (i<0x3fff/410) putch ('_'); else putch('-'); putch('\r'); delay(1); } while (!kbhit()); } /* ////////////////////////////////// // Из вольт в данные переводила вот такая простенькая процедурка... // Analog OUTPUT 14 bit = 0 - 8192 - 16384 -/+ 10V // РАБОТАЕМ С МИЛИВОЛЬТАМИ void SetU(double val) { // значения max,min в принципе подбирал по вольтметру на каждый канал // ну это по желанию... unsigned int max = 16260; // +10V ( 9.999) unsigned int min = 270; // -10V (-9.999) double delta=20000.0/(max-min); unsigned int wValue=(val+10000.0)/delta+min; AnalogOutput(chan0, wValue); // } */ Здравcтвуйте. Можете выложить этот файлик? #include "..\hardware\PCI.H" |