[#1] Amiga i przerwania !!!
Oto maksymalnie uproszczony przykład podpinania własnej procedury
pod określone przerwanie komputera Amiga

W tym przypadku chodzi o przewanie wywoływane w chwili kiedy
bufor portu serial (RS232) otrzymał nowy bajt danej.

Problem:

Ten przykładowy programik nie działa czemu???


Oto program:

;-------------------------------------------------------

;CPU: MC 68000
;System: Amiga 500 OS v1.3 Kickstart (v34)
;Assembler: DevPac v3.02 (HiSoft)



Exec: equ 4
AddIntServer: equ -168
RemIntServer: equ -174


;Lista przerwań

INTB_TBE = 0
INTB_DSKBLK = 1
INTB_SOFTINT = 2
INTB_PORTS = 3
INTB_COPER = 4
INTB_VERTB = 5
INTB_BLIT = 6
INTB_AUD2 = 7
INTB_AUD0 = 8
INTB_AUD3 = 9
INTB_AUD1 = 10
INTB_RBF = 11
INTB_DSKSYNC = 12
INTB_EXTER = 13
INTB_INTEN = 14




;Teraz podpinamy procedure obsługi przerwania i oczekujemy
;na klawisz 'Esc' po którym usuwamy dodaną procedurę i wychodzimy.

Start: move.l 4,a6
move.l #INTB_RBF,d0
move.l #Interrupt_RBF,a1
jsr AddIntServer(a6)

Wait_Key_Esc: cmp.b #$75,$BFEC01 ;Sprawdzamy stan klawisza 'ESC'
bne.s Wait_Key_Esc

move.l 4,a6
move.l #INTB_RBF,d0
move.l #Interrupt_RBF,a1
jsr RemIntServer(a6)
moveq #0,d0
rts



;Struktura "Interrupt" definująca dodawaną procedurę.

Interrupt_RBF: dc.l 0 ;ln_Succ
dc.l 0 ;ln_Pred
dc.b 2 ;ln_Type - dla Node typu Intterupt
dc.b 0 ;ln_Pri
dc.l Int_RBF_NAME ;ln_Name - adres do nazwy naszej procedury
dc.l 0 ;is_Data
dc.l Int_RBF_CODE ;is_Code - adres do procedury przerwania

Int_RBF_NAME: dc.b 'Test przerwania RS232',0

;Tutaj procedura wykonywana w chwili przyjęcia przerwania.

Int_RBF_CODE: movem.l d0-a6,-(sp)

bchg.b #1,$BFE001 ;Zmieniamy stan diody PowerLED na przeciwny.

movem.l (sp)+,d0-a6
rts ;z takiej systemowej procedury przerwania
;wychodzimy zwykłym rozkazem RTS

;---------------------------------------------------------
[#2] Re: Amiga i przerwania !!!

@68k_tester, post #1

Nie jestem pewien, ale może chodzi o to, że kod procedury obsługi przerwania zaczyna się od nieparzystego adresu, choć w Asm-One wyskoczyłby błąd. Najlepiej użyć Asm-One i wpisać
section int_RBF_CODE,code_p
tuż przed procedurą przerwania.

[#3] Re: Amiga i przerwania !!!

@68k_tester, post #1

Przerwanie RBF ma handler zamiast serwera, więc dla niego AddIntServer() nie zadziała. Trzeba przełączyć handler na swój wywołując SetIntVector(). Proponuję przeczytanie działu o przerwaniach w ROM Kernel Manuals.

[#4] Re: Amiga i przerwania !!!

@Grzegorz Kraszewski, post #3

A czym się różni handler od servera?

[#5] Re: Amiga i przerwania !!!

@Grzegorz Kraszewski, post #3



Poprawiłem ten przykładowy program zgodnie z zaleceniami ale mimo ustawionego wektora przerwanie dalej nie jest uaktywniane......
Ten przykład dodatkowo powinien odebrać bajt z bufora portu RS232 i wysłać go tam ponownie co na terminalu da widoczny efekt echa jednak
nic takiego nie zachodzi.......

Gdzie problem????

Oto kod:
;-----------------------------------------------------------------------




;CPU: MC 68000
;System: Amiga 500 OS v1.3 Kickstart (v34)
;Assembler: DevPac v3.02 (HiSoft)



Exec: equ 4
SetIntVector: equ -162
RawPutChar: equ -516 ;wysyła bajt z rej.D0 do RS232
RawMayGetChar: equ -510 ;odczytuje bajt z RS232 do rej.D0

INTB_TBE = 0
INTB_DSKBLK = 1
INTB_SOFTINT = 2
INTB_PORTS = 3
INTB_COPER = 4
INTB_VERTB = 5
INTB_BLIT = 6
INTB_AUD2 = 7
INTB_AUD0 = 8
INTB_AUD3 = 9
INTB_AUD1 = 10
INTB_RBF = 11
INTB_DSKSYNC = 12
INTB_EXTER = 13
INTB_INTEN = 14




;Teraz podpinamy procedure obsługi przerwania i oczekujemy
;na klawisz 'Esc' po którym usuwamy dodaną procedurę i wychodzimy.




SECTION Program,CODE_F

Start: move.l 4.w,a6
moveq #INTB_RBF,d0
lea Interrupt_RBF(pc),a1
jsr SetIntVector(a6)
move.l d0,Old_Vector_Buf

Wait_Key_Esc: cmp.b #$75,$BFEC01 ;Sprawdzamy czy wcisnieto klawisz 'ESC'
bne.s Wait_Key_Esc ;jeśli tak wychodzimy z programu.

move.l 4.w,a6
moveq #INTB_RBF,d0
move.l Old_Vector_Buf,a1
jsr SetIntVector(a6)
moveq #0,d0
rts

Old_Vector_Buf: dc.l 0

;Struktura "Interrupt" definująca dodawaną procedurę.

Interrupt_RBF: dc.l 0 ;ln_Succ
dc.l 0 ;ln_Pred
dc.b 2 ;ln_Type
dc.b 0 ;ln_Pri
dc.l Int_RBF_NAME ;ln_Name - adres do nazwy naszej procedury
dc.l 0 ;is_Data
dc.l Int_RBF_CODE ;is_Code - adres do procedury przerwania

Int_RBF_NAME: dc.b 'Test przerwania RS232',0

;Tutaj procedura wykonywana w chwili przyjęcia przerwania.

Int_RBF_CODE: movem.l d0-a6,-(sp)

bchg.b #1,$BFE001 ;Zmieniamy stan diody PowerLED na przeciwny.

move.l Exec.w,a6
jsr RawMayGetChar(a6) ;Odbieramy bajt z portu RS232.
cmp.b #-1,d0
beq.s NotReadChar

move.l Exec.w,a6
jsr RawPutChar(a6) ;Wysyłamy bajt do portu RS232.
NotReadChar:
movem.l (sp)+,d0-a6
rts
[#6] Re: Amiga i przerwania !!!

@68k_tester, post #5

A próbowałeś przenieść kod przerwania w inne miejsce tj. przed sekcją danych lub stworzyć dodatkową sekcję? W Twoim przykładzie kod przerwania znajduje się za sekcją danych i może leżeć pod nieparzystym adresem.

Innymi słowy podziel kod na trzy częśći:

SECTION Program,CODE_F ;(istniejąca)

SECTION Data,DATA_F

SECTION Interrupt,CODE_F

Może to coś pomoże.

[#7] Re: Amiga i przerwania !!!

@Minniat, post #4

Handler jest procedurą "wyłączną", więc można jedynie usunąć systemowy handler i zastąpić go własnym. Serwery natomiast są przez system dopisywane do listy i wywoływane po kolei.

[#8] Re: Amiga i przerwania !!!

@68k_tester, post #5

Podejrzewam, że RawMayGetChar() bazuje na systemowym handlerze przerwania RBF. W momencie, gdy zostanie on przestawiony na własny, funkcja nie będzie działać.

Czy nie prościej zamiast takich kombinacji po prostu skorzystać z serial.device?

[#9] Re: Amiga i przerwania !!!

@Grzegorz Kraszewski, post #8

Nie potrafie pod systemem Kickstart (v34) czyli na OS 1.3 napisać kodu
do komunikacji z serial.device ani nawet prostego odbierania klawiszy poprzez keyboard.device w Amiga Reference Manual przykłady są pod conajmniej (v37) czyli OS 2.0
Szukałem w necie przykładów assemblerowych do Amigi500 ale nic wszystko jest pod OS 2.0
OS 1.3 nie ma połowy zastosowanych tam funkcji bibliotecznych!!!
[#10] Re: Amiga i przerwania !!!

@68k_tester, post #9

Właściwie to potrzebny mi prosty działający przykład.... na os 1.3
[#11] Re: Amiga i przerwania !!!

@68k_tester, post #10

Jutro podeślę Ci archiwum z procedurami w asemblerze, na pewno są tam rzeczy pod kick 1.3. W ogóle jest tam masa ciekawych rzeczy.

[#12] Re: Amiga i przerwania !!!

@68k_tester, post #5

http://aminet.net/dev/src/RKMCompanion.lha
Przykład handlera komunikującego się z serial.device z rkm 1.3
(dysk1, katalog exec/interrupts/rbf)
[#13] Re: Amiga i przerwania !!!

@cholok, post #12

Zrobiłem to tak:


Przykład z języka C przerobiłem na assembler 68000 jednak oba programy nie działają identycznie a dokładniej assemblerowy blokuje się na funkcji DoIO
czemu?


To przykład w C z pomocy Commodore Amiga Reference






#include
#include
#include
#include
#include
#include
#include


VOID main(int argc, char *argv[])
{
struct IOStdReq *keyRequest;
struct MsgPort *keyPort;
struct InputEvent *keyEvent;


if (keyPort=CreatePort(NULL,NULL))
{
if (keyRequest=(struct IOStdReq *)CreateExtIO(keyPort,
sizeof(struct IOStdReq)))
{
if (!OpenDevice("keyboard.device",NULL,
(struct IORequest *)keyRequest,NULL))
{
if (keyEvent=AllocMem(sizeof(struct InputEvent),MEMF_PUBLIC))
{


}
CloseDevice((struct IORequest *)keyRequest);
}
DeleteExtIO((struct IORequest *)keyRequest);
}
DeletePort(keyPort);
}
}






A to moje wypociny assemblerowe:





;Testy "Keyboard Device"
;Nie działa....!!!


Exec: equ 4
AddPort: equ -354
RemPort: equ -360
OpenDevice: equ -444
CloseDevice: equ -450
DoIO: equ -456


ln_Type = 8
ln_Name = 10 ;offset do wskaźnika nazwy portu publicznego..
io_Command = 28 ;offset do pola Command struktury IOStdReq
io_Data = 40
io_Length = 36


NT_MSGPORT = 4


KBD_READEVENT = 9 ;polecenie wysyłane do urządzenia



Start: move.l Exec.w,a6
move.l #StructIOStdReq,a1
move.b #NT_MSGPORT,ln_Type(a1)
move.l #NazwaPortu,ln_Name(a1)
jsr AddPort(a6)
move.l Exec.w,a6
move.l #DeviceName,a0
moveq #0,d0
move.l #StructIOStdReq,a1
moveq #0,d1
jsr OpenDevice(a6)
tst.l d0
bne Error_001



move.l #StructIOStdReq,a0
move.l #KBD_READEVENT,d0
move.w d0,io_Command(a0)
move.l #StructInputEvent,d0
move.l d0,io_Data(a0)
move.l #22,d0 ;tu podajemy rozmiar struktury InputEvent
move.l d0,io_Length(a0)

move.l #StructIOStdReq,a1
move.l Exec.w,a6
jsr DoIO(a6) ;czekamy na komunikat z urządzenia!!!!
tst.l d0


move.l #StructIOStdReq,a1
move.l Exec.w,a6
jsr CloseDevice(a6)
move.l Exec.w,a6
move.l #StructIOStdReq,a1
jsr RemPort(a6)
clr.l d0
rts



Error_001: moveq #-1,d0
rts



NazwaPortu: dc.b "Publiczny Nr.1",0


StructIOStdReq: dcb.b 48,0


StructInputEvent: dcb.b 22,0



DeviceName: dc.b "keyboard.device",0
[#14] Re: Amiga i przerwania !!!

@68k_tester, post #13

Może dlatego, że AddPort() i CreatePort() to zupełnie co innego? AddPort() nie jest w ogóle potrzebne. Port używany do komunikacji z device nie musi być publiczny.

[#15] Re: Amiga i przerwania !!!

@Grzegorz Kraszewski, post #14

Funkcja CreatePort() nie istnieje w bibliotece exec.library systemu (v34) więc jak mam
utworzyć port? Ponadto funkcji CreateExIo() tak samo ma na liście funkcji biblioteki exec (v34).


W przykładie z języka C nie rozumiem znaczenia:


keyRequest=(struct IOStdReq *)CreateExtIO(keyPort,
sizeof(struct IOStdReq))


skoro "keyPort" jest wskaźnikiem do struktury MsgPort a IoStdReq to tylko
powiekszona o dodatkowe pola struktura Message ???



Dekompilacja tego przykładu w C nic mi nie dała kod wynikowy SAS C ma 6 kb i jest tak pogmatwany ,ze nie ma szans na dokładniejszą analizę....



Ostatnia modyfikacja: 02.05.2009 23:04:57
[#16] Re: Amiga i przerwania !!!

@68k_tester, post #15

Funkcja CreatePort() nie istnieje w bibliotece exec.library systemu

Wszystko się zgadza, to nie jest funkcja z exec.library, tylko z amiga.lib, biblioteki linkowalnej dołączanej do kompilatorów C. Odpowiednia funkcja w exec.library to CreateMsgPort() i pojawiła się dopiero w v39. Trzeba w asemblerze ją zastąpić ręczną inicjalizacją struktury MsgPort. Niestety po detale mogę wyłącznie odesłać do RKRM, bo dla mnie system 1.3 to już historia... Spodziewam się jedynie, że ważną rzeczą będzie zainicjalizowanie listy wiadomości i ustawienie typu sygnalizacji. Funkcję CreateExtIO() też trzeba będzie zaimplementować na piechotę, jej głównym zadaniem jest inicjalizacja odpowiednich pól requesta, w szczególności ustawienie adresu portu, do którego request zostaje odesłany po wykonaniu (stąd adres MsgPortu jako parametr).

[#17] Re: Amiga i przerwania !!!

@68k_tester, post #15

/* Example only, please use the amiga.lib version where possible */

struct MsgPort *CreatePort(name, pri)
char *name;
LONG pri;
{
int sigBit;
struct MsgPort *port;

if ((sigBit = AllocSignal(-1L)) == -1)
return(NULL);

port = (struct MsgPort *)
AllocMem((ULONG)sizeof(struct MsgPort),(ULONG)MEMF_CLEAR|MEMF_PUBLIC);

if (!port)
{
FreeSignal(sigBit);
return(NULL);
}

port-> mp_Node.ln_Name = name;
port-> mp_Node.ln_Pri = pri;
port-> mp_Node.ln_Type = NT_MSGPORT;

port-> mp_Flags = PA_SIGNAL;
port-> mp_SigBit = sigBit;
port-> mp_SigTask = (struct Task *)FindTask(0L); /* find THIS task */

if (name)
AddPort(port);
else
NewList(&(port-> mp_MsgList)); /* init message list */

return(port);
}

/****** amiga.lib/CreateExtIO *****/

struct IORequest *CreateExtIO( ioReplyPort, size )
struct MsgPort *ioReplyPort;
ULONG size;
{
struct IORequest *ioReq;

if(! ioReplyPort )
return(NULL);

ioReq =
(struct IORequest *)AllocMem( size, (ULONG)MEMF_CLEAR|MEMF_PUBLIC );

if(!ioReq)
return(NULL);

ioReq->io_Message.mn_Node.ln_Type = NT_MESSAGE;
ioReq->io_Message.mn_Length = size; /* save for later */
ioReq->io_Message.mn_ReplyPort = ioReplyPort;

return( ioReq );
}
[#18] Re: Amiga i przerwania !!!

@cholok, post #17

Napisałem w assemblerze testując wielokrotnie ....
Jest to dokładny odpowiednik kodu z języka C tylko w mojej wersji
Wszystkie struktury i adresy wywołań funkcji oraz parametry
stałych są prawidłowe.... do zawieszenia dochodzi na funkcji exec'a DoIO()

jeśli ktoś ma jakiś pomysł....?????

Co do problemu poruszonego przez pana Grzegorza .... moja obserwacja funkcji AddPort() wykazała,że otwierany port bez podanego wskaźnika do jego nazwy czyli z parametrem (NULL) nie jest widoczny na liście portów publicznych....Parametr ten pozostaje jednak bez wpływu na przydzielany temu portowi bit sygnałowy co sugeruje praktycznie identyczną funkcjonalność tych portów.


Exec: equ 4
AllocSignal: equ -330
FreeSignal: equ -336
AddPort: equ -354
RemPort: equ -360
FindPort: equ -390
FindTask: equ -294
DoIO: equ -456



ln_Name = 10
ln_Pri = 9
ln_Type = 8
mp_Flags = 14
mp_SigBit = 15
mp_SigTask = 16

NT_MSGPORT = 4 ;identyfikator typu struktury
PA_SIGNAL = 0 ;wiadomość ma otrzymać Task nie Przerwanie

mn_Node = 0
mn_Length = 18
mn_ReplyPort = 14

NT_MESSAGE = 5

KBD_READEVENT = 9 ;polecenie wysyłane do urządzenia

io_Command = 28 ;offset do pola Command struktury IOStdReq
io_Data = 40
io_Length = 36

ie_Code = 7 ;offset do pola struktury InputEvent
ie_Qualifier = 9


Start: clr.l d0 ;priorytet portu na 0
move.l d0,a0 ;brak nazwy portu
lea StrukturaMsgPort,a1
bsr CreatePort
tst.l d0 ;teraz rej.A1 zawiera wskaźnik do (MsgPort)
bne.s Error_001
lea StrukturaIOStdReq,a0
move.w #48,d0
bsr CreateExtIO
move.w #KBD_READEVENT,io_Command(a0)
move.l #StrukturaInputEvent,io_Data(a0)
move.l #22,io_Length(a0) ;Rozmiar struktury (InputEvent)
move.l a0,a1
move.l Exec.w,a6
jsr DoIO(a6) ;czekamy na komunikat z urządzenia!!!!
tst.l d0
bne.s Error_002


;----------------------------------------------------------
;UWAGA: teraz w polu (ie_Code) struktury (InputEvent) mamy
;kod odebranego klawisza natomiast pole (ie_Qualifier) zawiera
;maskę klawiszy funkcyjnych oba pola są typu (WORD)

clr.l d0
clr.l d1
lea StrukturaInputEvent,a1
move.w ie_Code(a1),d0 ;odczytany kod klawisza
move.w ie_Qualifier(a1),d1 ;stan klawiszy specjalnych
;----------------------------------------------------------



Error_002: lea StrukturaMsgPort,a1
bsr DeletePort

moveq #0,d0
Error_001: rts




StrukturaMsgPort: dcb.b 34,0
StrukturaIOStdReq: dcb.b 48,0
StrukturaInputEvent: dcb.b 22,0
DeviceName: dc.b "keyboard.device",0

;----------------------------------------------------------------------
;[D0.b] = CreatePort([A0.l],[A1.l],[D0.b])
;
;Funkcja tworzy port komunikacyjny o podanych parametrach na jej
;wyjściu pod adresem wskazywanym rej.A1 uzyskujemy przygotowaną
;strukturę (MsgPort) przydzielonego portu.
;UWAGA: Wcześniej rezerwujemy pamięć (struktura MsgPort = 34 bajty.)
;
;wejście: A0.l = Wskaźnik do nazwy tworzonego portu.
; A1.l = Wskaźnik do obszaru pamięci przydzielonego
; wcześniej na bufor dla kreowanej struktury (MsgPort).
; D0.b = Priorytet elementu (struktury) używany do
; sortowania elementów do których przynależy (struktura)
; zakres od najwiekszego (127) do najmniejszego (-128).
; Zwykle jako priorytet podajemy wartość 0.
;
;wyjście: D0.b = Zawiera 0 jeśli wszystko OK czyli przydzielono
; bit sygnałowy i dodano port publiczny o podanej nazie
; lub -1 jeśli Error.


CreatePort: move.b d0,ln_Pri(a1)
move.l a0,ln_Name(a1)
move.b #NT_MSGPORT,ln_Type(a1)
move.b #PA_SIGNAL,mp_Flags(a1)
move.l Exec.w,a6
moveq #-1,d0 ;-1 = dowolny wolny bit sygnałowy.
movem.l a1,-(SP)
jsr AllocSignal(a6)
move.l (SP)+,a1
tst.l d0
bmi.s CP_Error_00 ;wartość ujemna to błąd!
move.b d0,mp_SigBit(a1)
move.l Exec.w,a6
movem.l a1,-(SP)
move.l #0,a1 ;wartość 0 oznacza aktualny Task
jsr FindTask(a6)
movem.l (SP)+,a1
move.l d0,mp_SigTask(a1)
move.l Exec.w,a6
jsr AddPort(a6)
moveq #0,d0
rts
CP_Error_00: moveq #-1,d0
rts

;-------------------------------------------------------------------
;DeletePort([A1.l])
;
;wejście: A1.l = Wskaźnik do obszaru pamięci struktury (MsgPort) która
; została wcześniej utworzona poprzez funkcję CreatePort()

DeletePort: move.l Exec.w,a6
movem.l a1,-(SP)
jsr RemPort(a6)
move.l (SP)+,a1
move.b mp_SigBit(a1),d0
move.l Exec.w,a6
jsr FreeSignal(a6)
rts
;-------------------------------------------------------------------
;CreateExtIO([A0.l],[A1.l],[D0.b])
;
;wejście: A0.l = Wskaźnik do przydzielonego wcześniej obszaru
; struktury wynikowej, która podlega inicjalizacji
; chodzi o struktury typu (IOReuest) lub (IOStdReq)
; A1.l = Wskaźnik do struktury (MsgPort)
; D0.w = Rozmiar nowej struktury.(wartość typu WORD)
; UWAGA: Funkcja nie allokuje samodzielnie obszaru
; który modyfikuje więc nie wymaga istnienia jej
; odpowiednika zamykającego czyli funkcji DeleteExtIO()

;Funkcja inicjalizuje strukturę do której wskaźnik przekazujemy w
;rej.A0 a w rej.D0 podajemy jej rozmiar!!!

CreateExtIO: cmp.w #20,d0 ;rozmiar minimum 20
blt.s CEI_Error_00
move.b #NT_MESSAGE,ln_Type(a0)
move.w d0,mn_Length(a0)
move.l a1,mn_ReplyPort(a0)
CEI_Error_00: rts



Ostatnia modyfikacja: 06.05.2009 13:12:18



Ostatnia modyfikacja: 06.05.2009 13:14:49
[#19] Re: Amiga i przerwania !!!

@68k_tester, post #18

moja obserwacja funkcji AddPort() wykazała,że otwierany port bez podanego wskaźnika do jego nazwy czyli z parametrem (NULL) nie jest widoczny na liście portów publicznych....Parametr ten pozostaje jednak bez wpływu na przydzielany temu portowi bit sygnałowy co sugeruje praktycznie identyczną funkcjonalność tych portów.

Wszystko się zgadza, ale AddPort() nie tworzy portu, jedynie dodaje go do listy portów publicznych. Z punktu widzenia użycia portu do obsługi device'ów, jest to działanie zupełnie zbędne.

Drugie pytanie - co znajduje się w rejestrze A0 w momencie wywołania AddPort()?

Na koniec sugestia - potestowałbym ten kod na jakimś prostszym urządzeniu, np. timer.device. Jak zadziała, wtedy przeszedłbym do keyboard.device.

[#20] Re: Amiga i przerwania !!!

@Grzegorz Kraszewski, post #19

To co pisze wymaga "keyboard.device" i "serial.device"
Co do zastosowania "AddPort" wykonałem tylko assemblerowy odpowiednik funkcji CreateProc()... tej z biblioteki amiga.lib ,której nie ma DevPac .
Oczywiście wszytko to tylko dzięki przykładowi kodu w C podesłanemu przez "cholok'a"

Funkcja AddPort() z "exec.library" nie wymaga rej.A0 w chwili wywołania!
[#21] Re: Amiga i przerwania !!!

@68k_tester, post #18

68k_tester napisał(a):

> Wszystkie struktury i adresy wywołań funkcji oraz parametry
> stałych są prawidłowe.... do zawieszenia dochodzi na funkcji
> exec'a DoIO()
>
> jeśli ktoś ma jakiś pomysł....?????

Wiesz, DoIO() slabo dziala bez wczesniejszego otwarcia urzadzenia (za pomoca OpenDevice()) :)

[#22] Re: Amiga i przerwania !!!

@szuler, post #21

faktycznie... jak to się stało???
chyba zbyt wiele tych zmian i modyfikacji..
w efekcie po drodze coś zaginęło w akcji...
a było jeszcze w poprzednich testach...

postawiłem na błędy wypełniania struktur!

Dzięki... przeglądałem to tyle razy ,że gdyby nie Pan Michał ,pewnie nigdy tego „detalu” bym już nie dostrzegł...

poprawie i zobaczymy co teraz przywoła Guru???
[#23] Re: Amiga i przerwania !!!

@68k_tester, post #22

Oto finał!!!

Gotowy działający przykład dla zainteresowanych.

Dzieki wszystkim za pomoc i wszelkie uwagi.
Krok po kroku dało to efekt końcowy.


kolej na serial.device

Pozdrawiam.





;-------------------------------------------------------------------
;Przykładowy program synchronicznego odczytu stanu klawiatury
;poprzez urządzenie 'keyboard.device'


;System: Amiga 500 (OS 1.3) Kickstart (v34)
;Procesor: MC68000
;Assembler: DevPac 3.02 (HiSoft)
;Data: 07.05.2009


;Testy: OK Działa!!!


;wektory skoków do funkcji biblioteki 'exec.library'

Exec: equ 4
AllocSignal: equ -330
FreeSignal: equ -336
AddPort: equ -354
RemPort: equ -360
FindTask: equ -294
OpenDevice: equ -444
CloseDevice: equ -450
DoIO: equ -456

;stałe i offsety do struktur programu

ln_Name = 10 ;(DWORD) offset do pola ln_Name struktury Node
ln_Pri = 9 ;(BYTE) offset do pola ln_Pri struktury Node
ln_Type = 8 ;(BYTE) offset do pola ln_Type struktury Node

mp_Flags = 14 ;(BYTE) offset do pola mp_Flag struktury MsgPort
mp_SigBit = 15 ;(BYTE) offset do pola mp_SigBit struktury MsgPort
mp_SigTask = 16 ;(DWORD) offset do pola mp_SigTask struktury MsgPort

NT_MSGPORT = 4 ;identyfikator typu struktury
PA_SIGNAL = 0 ;wiadomość ma otrzymać Task nie Przerwanie

mn_ReplyPort = 14 ;(DWORD) offset do pola mn_ReplyPort struktury Message
mn_Length = 18 ;(WORD) offset do pola mn_Length struktury Message

NT_MESSAGE = 5 ;oznacza stan: wysyłanie wiadomości......
;UWAGA: Gdy wiadomość zostaje odesłana pole to
;zmieni się na wartość NT_REPLYMSG i jeśli wtedy
;z tym parametrem ponownie ją wyślemy będzie Guru...

KBD_READEVENT = 9 ;polecenie wysyłane do urządzenia (odczyt klawiatury)

io_Command = 28 ;(WORD) offset do pola io_Command struktury IOStdReq
io_Length = 36 ;(DWORD) offset do pola io_Length struktury IOStdReq
io_Data = 40 ;(DWORD) offset do pola io_Data struktury IOStdReq

ie_Code = 6 ;(WORD) offset do pola ie_Code struktury InputEvent
ie_Qualifier = 8 ;(WORD) offset do pola ie_Qualifier struktury InputEvent




;Ta dyrektywa assemblacji umieszcza kod programu w pamięci CHIP_RAM

SECTION Program,CODE_C



Start: clr.l d0 ;priorytet portu na 0
move.l d0,a0 ;brak nazy portu
lea StrukturaMsgPort,a1
bsr CreatePort
tst.l d0 ;teraz rej.A1 zawiera wskaźnik do (MsgPort)
bne Error_001

lea StrukturaIOStdReq,a0
move.w #48,d0
bsr CreateExtIO

move.l Exec.w,a6
move.l #DeviceNameKeyboard,a0
moveq #0,d0
move.l #StrukturaIOStdReq,a1
moveq #0,d1
jsr OpenDevice(a6)
tst.l d0
bne.s Error_003

KeyLoopRead: lea StrukturaIOStdReq,a0
move.w #KBD_READEVENT,io_Command(a0)
move.l #StrukturaInputEvent,io_Data(a0)
move.l #22,io_Length(a0) ;Rozmiar struktury (InputEvent)
move.l a0,a1
move.l Exec.w,a6
jsr DoIO(a6) ;czekamy na komunikat z urządzenia!!!!
tst.l d0
bne.s Error_002


;Tutaj odbieramy stan klawiatury
;----------------------------------------------------------
;UWAGA: teraz w polu (ie_Code) struktury (InputEvent) mamy
;kod odebranego klawisza natomiast pole (ie_Qualifier) zawiera
;maskę klawiszy specjalnych oba pola są typu (WORD)

clr.l d0
clr.l d1
lea StrukturaInputEvent,a1
move.w ie_Code(a1),d0 ;rej.D0.w = odczytany kod klawisza
move.w ie_Qualifier(a1),d1 ;rej.D1.w = stan klawiszy specjalnych
;----------------------------------------------------------
;Aby oczekiwać na kolejną zmianę stanu klawiatury
;wykonujemy tu skok do etykiety: KeyLoopRead


Error_002: move.l #StrukturaIOStdReq,a1
move.l Exec.w,a6
jsr CloseDevice(a6)

Error_003: lea StrukturaMsgPort,a1
bsr DeletePort

moveq #0,d0
Error_001: rts


;Ta dyrektywa DevPac'a umieszcza struktury w osobnym
;HUNK'u i zapewnia dodatkowo wyrównanie adresu w pamięci.

SECTION StrukturyProgramu,DATA_C

StrukturaMsgPort: dcb.b 34,0
StrukturaIOStdReq: dcb.b 48,0
StrukturaInputEvent: dcb.b 22,0
DeviceNameKeyboard: dc.b "keyboard.device",0


;Ta dyrektywa assemblacji umieszcza dalszy kod programu w pamięci CHIP_RAM

SECTION Program,CODE_C

;----------------------------------------------------------------------
;[D0.b] = CreatePort([A0.l],[A1.l],[D0.b])
;
;Funkcja tworzy port komunikacyjny o podanych parametrach na jej
;wyjściu pod adresem wskazywanym rej.A1 uzyskujemy przygotowaną
;strukturę (MsgPort) przydzielonego portu.
;UWAGA: Wcześniej rezerwujemy pamięć (struktura MsgPort rozmiar = 34 bajty.)
;
;wejście: A0.l = Wskaźnik do nazwy tworzonego portu lub 0.
; A1.l = Wskaźnik do obszaru pamięci przydzielonego
; wcześniej na bufor dla kreowanej struktury (MsgPort).
; D0.b = Priorytet elementu (struktury) używany do
; sortowania elementów do których przynależy (struktura)
; zakres od najwiekszego (127) do najmniejszego (-128).
; Zwykle jako priorytet podajemy wartość 0.
;
;wyjście: D0.b = Zawiera 0 jeśli wszystko OK czyli przydzielono
; bit sygnałowy i utworzono port lub -1 jeśli Error.
; A1.l = Jeśli rej.D0.b = 0 to rej.A1.l wskazuje na
; aktywną strukturę (MsgPort) przydzielonego portu!


CreatePort: move.b d0,ln_Pri(a1)
move.l a0,ln_Name(a1)
move.b #NT_MSGPORT,ln_Type(a1)
move.b #PA_SIGNAL,mp_Flags(a1)
move.l Exec.w,a6
moveq #-1,d0 ;-1 = dowolny wolny bit sygnałowy.
movem.l a1,-(SP)
jsr AllocSignal(a6)
move.l (SP)+,a1
tst.l d0
bmi.s CP_Error_00 ;wartość ujemna to błąd!
move.b d0,mp_SigBit(a1)
move.l Exec.w,a6
movem.l a1,-(SP)
move.l #0,a1 ;wartość 0 oznacza aktualny Task
jsr FindTask(a6)
movem.l (SP)+,a1
move.l d0,mp_SigTask(a1)
move.l Exec.w,a6
jsr AddPort(a6)
moveq #0,d0
rts
CP_Error_00: moveq #-1,d0
rts

;-------------------------------------------------------------------
;DeletePort([A1.l])
;
;wejście: A1.l = Wskaźnik do obszaru pamięci struktury (MsgPort) która
; została wcześniej utworzona poprzez funkcję CreatePort()

DeletePort: move.l Exec.w,a6
movem.l a1,-(SP)
jsr RemPort(a6)
move.l (SP)+,a1
move.b mp_SigBit(a1),d0
move.l Exec.w,a6
jsr FreeSignal(a6)
rts
;-------------------------------------------------------------------
;CreateExtIO([A0.l],[A1.l],[D0.b])
;
;wejście: A0.l = Wskaźnik do przydzielonego wcześniej obszaru
; struktury wynikowej, która podlega inicjalizacji
; chodzi o struktury typu (IOReuest) lub (IOStdReq)
; A1.l = Wskaźnik do struktury (MsgPort)
; D0.w = Rozmiar nowej struktury.(wartość typu WORD)
; UWAGA: Funkcja nie allokuje samodzielnie obszaru
; który modyfikuje więc nie wymaga istnienia jej
; odpowiednika zamykającego czyli funkcji DeleteExtIO()

;Funkcja inicjalizuje strukturę do której wskaźnik przekazujemy w
;rej.A0 a w rej.D0 podajemy jej rozmiar!!!

CreateExtIO: cmp.w #20,d0 ;rozmiar minimum 20
blt.s CEI_Error_00
move.b #NT_MESSAGE,ln_Type(a0)
move.w d0,mn_Length(a0)
move.l a1,mn_ReplyPort(a0)
CEI_Error_00: rts
;-------------------------------------------------------------------
Na stronie www.PPA.pl, podobnie jak na wielu innych stronach internetowych, wykorzystywane są tzw. cookies (ciasteczka). Służą ona m.in. do tego, aby zalogować się na swoje konto, czy brać udział w ankietach. Ze względu na nowe regulacje prawne jesteśmy zobowiązani do poinformowania Cię o tym w wyraźniejszy niż dotychczas sposób. Dalsze korzystanie z naszej strony bez zmiany ustawień przeglądarki internetowej będzie oznaczać, że zgadzasz się na ich wykorzystywanie.
OK, rozumiem