[TP] Przerwanie coś szpunci... Bliżej nieokreślony konflikt.

0

Witam... w moim dość istotny projekcie, który wychodzi jak na razie bardzo ładnie wystąpił dziwny i niezrozumiały dla mnie konflikt przerwania 1Ch z resztą programu. W związku z tym Problem rozwiązałoby zatrzymanie przerwania na dosłownie moment. Mam tu na myśli zrobienie takiego czegoś, ze kiedy wykonywana jest moja procedura, wtedy przerwanie musi czekać aż sie skończy. Teoretycznie aby to się stało musiałoby wystąpić przerwanie o wyższym IRQ, jednak wtedy moja procedura przerwałaby to pierwsze przerwanie. Innymi słowy, żadna z procedur nie może przeciąć drugiej, a jedna z nich musi być przerwaniem. Problem dość dziwny... nienawidzę błędów które wyglądają na losowe. Zostawię kod, ale chyba nikt z tego nic nie wyduma...:

uses crt,dos,graph,jarek,okna,xms;
type tab=array[1..50,1..32]of byte;
const com=$0;
      lpt=$378;


var adres:integer;
    l1,l2,licznik:longint;
    okno1:okno;

    guzikkoniec,guzikwczytaj,guzikzapisz:guzik;
    guzikP,guzikL,guzikG,guzikD:guzik;
    guzikStop,GuzikKrok:guzik;

    suwakPL,suwakGD:suwak;
    suwakczasu:array[1..50]of suwak;
    ramka1:ramka;
    a,a1:byte;

    tablica:tab;

    FlagaCzytaj:boolean;

    bufor1,bufor2,bufor3,bufor4:tab;

    ilx,ily,tablicax,tablicay:longint;
    pozycjax,pozycjay,spozycjax,spozycjay:longint;
    pozycjapx,pozycjapy:longint;
    pozycjawx,pozycjawy:integer;
    polowka:boolean;

    nazwa:string;
    l:integer;
    startx,starty:integer;
    x,y,p:word;
    sxz,syz,xz,yz:integer;

    plik1,plik2:text;

    Handle:word;

    krok:longint;

    stareprzerwanie:pointer;
    czestosc:integer;




label dal,dal1;

function pstr(a:longint):string;
var s:string;
 begin
 str(a,s);
 pstr:=s;
 end;


function wczytaj(xt,yt:longint):byte;
var wartosc,w:byte;
begin
xmsmovefrom(handle,xt+((yt)*tablicax),2,@wartosc);
wczytaj:=wartosc;
end;

procedure zapisz(xt,yt:longint;wartosc:byte);
var bajty:array[1..2]of byte;
begin
bajty[1]:=wartosc;
bajty[2]:=wczytaj(xt+1,yt);
xmsmoveto(@bajty,2,handle,xt+((yt)*tablicax));
end;



procedure znacznik;
begin
sound(300);
delay(10);
nosound;
end;

procedure StartInterfejsuGraficznego;
var slowo:string;
begin
 okno1.ustaw(0,0,639,479,'Diody po Jarowemu',false);
 okno1.maluj;
 guzikkoniec.ustaw(624,4,635,15,'X',true);
 guzikkoniec.maluj;
 guzikL.ustaw(120,462,135,477,'<',true);
 guzikL.maluj;
 guzikP.ustaw(605,462,620,477,'>',true);
 guzikP.maluj;
 guzikG.ustaw(622,140,637,155,'^',true);
 guzikG.maluj;
 guzikD.ustaw(622,445,637,460,'V',true);
 guzikD.maluj;
 suwakPL.ustaw(136,462,604,477,0,ilx-50,0,true,false);
 suwakPL.maluj;
 suwakGD.ustaw(622,156,637,444,0,ily-32,0,true,true);
 suwakGD.maluj;
 for l1:=1 to 50 do begin suwakczasu[l1].ustaw(110+(10*l1),88,119+(10*l1),138,0,63,58,true,true);
                    suwakczasu[l1].maluj; end;
 setfillstyle(1,15);
 bar(120,140,620,460);
 setcolor(4);
  for l1:=0 to 50 do line(120+(l1*10),140,120+(l1*10),460);
  for l1:=0 to 32 do line(120,140+(l1*10),620,140+(l1*10));
 rectangle(119,139,621,461);
 setcolor(0);
  for l1:=1 to 32 do begin str(l1,slowo); outtextxy(118-(length(slowo))*8,131+(l1*10),slowo); end;
  settextstyle(1,vertdir,8);
  for l1:=1 to 50 do begin str(l1,slowo); outtextxy(120+(l1*10),87-(length(slowo))*8,slowo); end;
end;


{procedure ustawczestotliwosc(cz:integer);
var dz:word;
begin
if cz=0 then exit;
dz:=1193181 div 19;
 asm
  mov al,36h
  out 43h,al
  mov ax,dz
  out 40h,al
  mov al,ah
  out 40h,al
 end;
end;}


procedure wgore;
begin
if pozycjay>0 then pozycjay:=pozycjay-1 else exit;
end;

procedure wdol;
begin
if (pozycjay+32<ily) then pozycjay:=pozycjay+1 else exit;
end;

procedure wprawo;
begin
if (pozycjax+50<ilx) then pozycjax:=pozycjax+1 else exit;

end;

procedure wlewo;
begin
if (pozycjax>0) then pozycjax:=pozycjax-1 else exit;
end;

procedure liczby;
begin
if spozycjax<>pozycjax then
    begin
     settextstyle(1,vertdir,8);
     setcolor(0);
     setfillstyle(1,7);
     bar(120,86-8*length(pstr(ilx)),620,87);
     schowajmyche;
     for l1:=1 to 50 do outtextxy(120+(l1*10),87-(length(pstr(l1+pozycjax)))*8,pstr(l1+pozycjax));
     pokazmyche;



    end;
   if spozycjay<>pozycjay then
    begin
     settextstyle(1,horizdir,8);
     setcolor(0);
     setfillstyle(1,7);
     schowajmyche;
     bar(118-8*length(pstr(ily)),140,118,460);
     for l1:=1 to 32 do outtextxy(118-(length(pstr(l1+pozycjay))*8),131+(l1*10),pstr(pozycjay+l1));
     pokazmyche;
    end;
   spozycjax:=pozycjax;
   spozycjay:=pozycjay;

end;


procedure tabela;
begin
pobierzmyche(x,y,p);
if (p=1)and(x>120)and(x<620)and(y>140)and(y<460) then
  begin
   l1:=trunc((x-110)/10);
   l2:=trunc((y-130)/10);
   zapisz(l1+pozycjax-1,l2+pozycjay-1,255);
  end;
if (p=2)and(x>120)and(x<620)and(y>140)and(y<460) then
  begin
   l1:=trunc((x-110)/10);
   l2:=trunc((y-130)/10);
   zapisz(l1+pozycjax-1,l2+pozycjay-1,0);
  end;


for l2:=1 to 32 do for l1:=1 to 50 do if tablica[l1,l2]<>wczytaj(l1+pozycjax-1,l2+pozycjay-1) then
  begin
   tablica[l1,l2]:=wczytaj(l1+pozycjax-1,l2+pozycjay-1);
   if tablica[l1,l2]=255 then setfillstyle(1,2) else setfillstyle(1,15);
   schowajmyche;
   bar(111+(l1*10),131+(l2*10),119+(l1*10),139+(l2*10));
   pokazmyche;
  end;
end;


function getczestosc(num:longint):byte;
var wartosc:byte;
begin
xmsmovefrom(handle,(tablicax+1)*(tablicay+1)+num,2,@wartosc);
getczestosc:=wartosc;
end;


procedure setczestosc(num:longint;cz:byte);
var bajty:array[1..2]of byte;
begin
bajty[1]:=cz;
bajty[2]:=getczestosc(num+1);
xmsmoveto(@bajty,2,handle,(tablicax+1)*(tablicay+1)+num);
end;




procedure przerwanie; interrupt;
var lp:longint;
begin 
inc(licznik,1);
if licznik<getczestosc(krok) then exit;
licznik:=0;
for lp:=0 to round(ily/8)-1 do
       begin
        a:=0;
        if wczytaj(krok,(lp*8))=255 then a:=1;
        if wczytaj(krok,(lp*8)+1)=255 then a:=a+2;
        if wczytaj(krok,(lp*8)+2)=255 then a:=a+4;
        if wczytaj(krok,(lp*8)+3)=255 then a:=a+8;
        if wczytaj(krok,(lp*8)+4)=255 then a:=a+16;
        if wczytaj(krok,(lp*8)+5)=255 then a:=a+32;
        if wczytaj(krok,(lp*8)+6)=255 then a:=a+64;
        if wczytaj(krok,(lp*8)+7)=255 then a:=a+128;
        port[lpt]:=a;
       end;
krok:=krok+1;
if krok=ilx then krok:=0;
end;



BEGIN
clrscr;
writeln('podaj nazwe pliku ktory chcesz otworzyc lub wpisz "spadaj" w celu utworzenia nowego: ');
readln(nazwa);
if nazwa<>'spadaj' then goto dal;
write('Podaj liczbe kolumn: ');
readln(ilx);
write('Podaj liczbe bajtow: ');
readln(ily);
ily:=ily*8;
tablicax:=50+50*(trunc(ilx/50));
writeln('tablicax=',tablicax);
tablicay:=32+32*(trunc(ily/32));
writeln('tablicay=',tablicay);
delay(500);
if not xmsdriver then begin writeln('Brak sterownika XMS, sprawdz czy zainstalowany zostal sterownik Himem.sys'); halt; end;

dal:
if nazwa<>'spadaj' then
  begin
   assign(plik1,nazwa);
   reset(plik1);
   readln(plik1,ilx);
   readln(plik1,ily);
   readln(plik1,tablicax);
   readln(plik1,tablicay);

  end;
Handle:=XMSAllocate(2+trunc(tablicax*tablicay/1024)+tablicax);

clrscr;
for l2:=1 to 32 do for l1:=1 to 50 do tablica[l1,l2]:=0;
writeln('Czyszczenie Tablicy...');
for l2:=0 to tablicay do
begin
for l1:=0 to tablicax do zapisz(l1,l2,0);
gotoxy(2,1); writeln('wykonano: ',l2,' / ',tablicay);
end;
for l1:=1 to tablicax do setczestosc(l1,5);

writeln('Utworzono tablice w pamiec RAM (',1+trunc(tablicax*tablicay/1024),'kB), ladowanie interfejsu graficznego...');

if nazwa<>'spadaj' then
  begin
   for l2:=0 to ily do
    begin
     for l1:=0 to ilx do
      begin
      readln(plik1,a);
      zapisz(l1,l2,a);
      end;
      clrscr;
      write('Nieefektywne wczytywanie z dysku, wybaczcie. Post©p: ',l2,'/',ily);
    end;
   close(plik1);
  end;

 initvga;
 logo;
 StartInterfejsuGraficznego;

 ustawmyche(0,0,635,475);
 pokazmyche;

pozycjax:=0;
pozycjay:=0;
l1:=0;
l2:=0;
krok:=0;
licznik:=0;


{uruchamianie przerwania}
getintvec($1C,stareprzerwanie);
setintvec($1C,@przerwanie);


   REPEAT
    tabela;
    if guzikP.nacisniety then wprawo;
    if guzikL.nacisniety then wlewo;
    if guzikD.nacisniety then wdol;
    if guzikG.nacisniety then wgore;
    suwakpl.war:=pozycjax;
    suwakgd.war:=pozycjay;
    suwakPL.przestaw;
    suwakGD.przestaw;
    suwakPL.dzialaj;
    suwakGD.dzialaj;
    pozycjax:=round(suwakpl.war);
    pozycjay:=round(suwakgd.war);
    suwakPL.przestaw;
    suwakGD.przestaw;


    for l1:=1 to 50 do
    begin
     if pozycjax<>spozycjax then 
     suwakczasu[l1].war:=63-getczestosc(l1+pozycjax); {ta linia wpada w konflikt z przerwaniem!! kiedy usunę przerwanie lub zawartość procedury przerwania albo tez tę właśnie linię to problem znika...}
     suwakczasu[l1].dzialaj;
     suwakczasu[l1].przestaw;
     setczestosc(pozycjax+l1,63-round(suwakczasu[l1].war));
     end;
    liczby;

   UNTIL guzikkoniec.nacisniety;

 schowajmyche;
 setintvec($1C,stareprzerwanie);
 closegraph;
 clrscr;
 Write('Zapisac? spadaj/nazwa :');
 readln(nazwa);
 if nazwa='spadaj' then goto dal1;
 assign(plik1,nazwa);
 rewrite(plik1);
 writeln(plik1,ilx);
 writeln(plik1,ily);
 writeln(plik1,tablicax);
 writeln(plik1,tablicay);
 for l2:=0 to ily do for l1:=0 to ilx do writeln(plik1,wczytaj(l1,l2));
 dal1:
 XMSrelease(handle);
END.

EDIT:

dodałem komentarz w miejscu z błędem, około 26 linijka od dolu

0
chemik143 napisał(a)

Witam... w moim dość istotny projekcie, który wychodzi jak na razie bardzo ładnie wystąpił dziwny i niezrozumiały dla mnie konflikt przerwania 1Ch z resztą programu. W związku z tym Problem rozwiązałoby zatrzymanie przerwania na dosłownie moment. Mam tu na myśli zrobienie takiego czegoś, ze kiedy wykonywana jest moja procedura, wtedy przerwanie musi czekać aż sie skończy. Teoretycznie aby to się stało musiałoby wystąpić przerwanie o wyższym IRQ, jednak wtedy moja procedura przerwałaby to pierwsze przerwanie. Innymi słowy, żadna z procedur nie może przeciąć drugiej, a jedna z nich musi być przerwaniem. Problem dość dziwny... nienawidzę błędów które wyglądają na losowe. Zostawię kod, ale chyba nikt z tego nic nie wyduma...:

przyznam, że nie analizowałem kodu, ale może pomogłoby odpowiednie ustawienie flagi IF procesora (instrukcje CLI oraz STI).

http://en.wikipedia.org/wiki/CLI_(x86_instruction)

0

trochę bardziej poszperałem w swoim kodzie i wnioski są takie: Tylko wtedy kiedy jest wykonywana wskazana wcześniej prze zemnie linia i jednocześnie w przerwaniu wykonywane są linie czytające z XMS wtedy występuje ów problem. Podejrzewam, że wtedy kiedy następuje czytanie z tej pamięci a wystąpi przerwanie w którym także jest czytanie to wtedy następuje problem... ALE!! Dlaczego w takim razie w innych miejscach programu gdzie jest czytanie(z 5 takich miejsc na pewno jest...) program nie sypie błędami??

Na żywca zrobiłem tak, że wyłączam całkowicie przerwanie przed wykonaniem felernej lini i włączam po a jednak program dalej wariuje... Takiego dziwnego błędu jeszcze nie miałem:/ Z IFami zaraz sie popatrzę co mogę zrobić:)

0

nasunęly mi sie takie dwa niezwiązane ze sobą spostrzeżenia:

  1. w procedurze przerwania nie wywolujesz poprzedniej procedury przerwania, czy tam na pewno nic nie wisi?

  2. w procedurze przerwania wywolujesz funkcje getczestosc w której wywolujesz xmsmovefrom podając adres do bajtu, oraz przekazując procedurze wartość '2'. jeśli ta dwójka to liczba sprowadzanych bajtów z xms to czy nie mażesz niechcący po sąsiedniej zmiennej lub (co gorsza) po odłożonych na stosie rejestrach? nie znam deklaracji xmsmovefrom, więc może jednak wszystko jest ok. ale może nie zawadzi sprawdzić, czy zmieni coś korekta kodu na

xmsmovefrom(handle,(tablicax+1)*(tablicay+1)+num, SizeOf(wartosc), @wartosc);
0

Co do pierwszej odpowiedzi. Fakt nie wywołuje starego przerwania... Jednak jaki to miałoby mieć wpływ...

Co d 2. puntu to wiem o co chodzi:D też miałem z tym problem.. Wada tego modułu XMS jest taka że trzeba czytać i zapisywać co najmniej 2 bajty... Sam sposób zapisu i odczytu na pewno jest poprawny. Wyłuskiwanie tych pojedynczych bajtów może nie jest efektywne, ale działa. Cała ogromna tablica, czasem na kilka MB na tym chodzi bez zarzutu...

ALE JUŻ MAM POSTĘP
Robię tak:
Przed wywołaniem felernej procedury ustawiam wektor przerwania na stare przerwanie, a po zakończeniu przywracam wektor wskazujący na moja procedurę. Ten sposób ma jedną wadę którą muszę wyeliminować... Tracę po drodze niektóre przerwania... przydałoby sie to ominąć, i właśnie pomogą w tym flagi... Jednak nie mam bladego pojęcia jak je sie w pascalu ustawia. Jeśli nie uda sie mi tego zrobić, to najwyżej zrobię jeszcze jedną procedurę przerwania (ustawiana zamiast tej mojej głównej na czas wykonywania felernej procedury), która w razie wystąpienia wpisze do jakiejś zmiennej wartość true, co będzie oznaczać że podczas wykonywania felernej procedury wystąpiło przerwanie... i mnie ominęło. Następnie procedura przerwania zostanie wywołana ręcznie... (może trochę namieszałem ale kichał pies...)

Nawet zaraz tak zrobię i dam nać jak działa... Ehh...

EDIT:

Zrobiłem to z dodatkowym przerwaniem i działa wyśmienice.. porostu śliczny efekt:)
Wiem ze to trochę łatanie programu jest ale cóż... :D czasem trzeba:) Teraz czas na zabawę z plikami... coś czuję, że przejdę przez piekło:)

0
chemik143 napisał(a)

Co d 2. puntu to wiem o co chodzi:D też miałem z tym problem.. Wada tego modułu XMS jest taka że trzeba czytać i zapisywać co najmniej 2 bajty... Sam sposób zapisu i odczytu na pewno jest poprawny. Wyłuskiwanie tych pojedynczych bajtów może nie jest efektywne, ale działa. Cała ogromna tablica, czasem na kilka MB na tym chodzi bez zarzutu...

widzę tu jednak pewien problem. jeżeli przeznacza się na odczyt miejsce w pamięci o rozmiarze 1 bajt a procedura odczytuje, jak mówisz, minimum 2 bajty, to sąsiedni bajt zostanie zmamzany. zważywszy, że zmienne lokalne (takie jak zmienna wartosc) alokowane są na stosie, skutki mogą być opłakane... ale przecież można to przerobić na wzór procedury setczestosc:

function getczestosc(num:longint):byte;
var wartosc:array[1..2] of byte;
begin
  xmsmovefrom(handle,(tablicax+1)*(tablicay+1)+num,SizeOf(Wartosc){teraz SizeOf(wartosc)==2}, @wartosc);  
  getczestosc:=wartosc[1];
end;
chemik143 napisał(a)

Co do pierwszej odpowiedzi. Fakt nie wywołuje starego przerwania... Jednak jaki to miałoby mieć wpływ...

nie mam wielkiego doświadczenia w obsłudze przerwań, ale afaik zasada jest taka, że obok wykonaia własnego kodu należy wywołać 'zastaną' procedurę, bo ma pewności, czy na tym przerwaniu nie 'wiszą' jakieś procedury sytemowe. brak wywołania może spowodować niestabilność systemu

0

co do wywołania starej procedury to sie zgodzę.. i dodam...

Co do tego pierwszego...hmmm... już wiem w czym problem. i masz świętą rację. Teraz dziwię się że ten program w ogóle działa. Nie wiem czy to rozwiąże ten konflikt, ale zrobię tak dla bezpieczeństwa. Sugerowałem się tym, że to tylko odczyt i co tam sie może stać... a on przecież w miejsce ojej jedno bajtowej wartości wpisuje 2 bajty... Lece to poprawić..

EDIT:

no... dziwne dość.. zrobiłem jak mówisz i jest zmiana ale zbyt mała... Wcześniej suwaki lądowały w 4 różnych pozycjach: na samym dole, trochę wyżej w środku i na max. Teraz lądują tylko albo na max albo na min. Ale zazwyczaj na max...

Oznacza to że dziobnąłem właśnie w problem... W tym coś siedzi...

EDIT2

Dodałem wywołanie starej procedury przerwania. Spowodowało to, że program wiesza sie po par sekundach po załadowaniu danych.. najdalej 3 sekundy i stop... Przed procedurę przerwania dodałem dyrektywy $F+ $S- i $W-, a po dałem $F-, $S+

Niebawem wrzucę gdzieś wszystkie kody wszystkich używanych modułów, żeby każdy mógł zobaczyć co sie dzieje...

0
chemik143 napisał(a)

Dodałem wywołanie starej procedury przerwania. Spowodowało to, że program wiesza sie po par sekundach po załadowaniu danych.. najdalej 3 sekundy i stop...

czy przed wywołaniem starej obsługi przerwania odkładasz na stos rejestr Flags? jeśli nie, to pewie jest to żródło problemu. każda obsługa przerwania kończy się rozkazem IRET, która tym różni się od standardowego rozkazu powrotu z procedury RET, że oprócz adresu powrotu wczytuje ze stosu również rejestr Flags. żeby więc było co zdjąć trzeba to tam po prostu wrzucić. Ogólnie rzecz biorąc powinno to wyglądać jakoś tak

  var
     ZastanaObsPrz1C: procedure

procedure MojaObsPrz1C; interrupt;
begin
  asm PUSHF end;      
  ZastanaObsPrz1C;
  //...
  //mój kod obsługi 1c
  //...
end;

begin
   //...
   GetIntVec( $1c , @ZastanaObsPrz1C );
   //...
end.

0

nie wrzucałem flag na stos... Myślałem że samo wywołanie procedury poprzez call to załatwia za mnie;) ale widzę ze w asm nima lekko:) Niebawem dopisze ten fragment i dam znać jaki efekt, ale czuję, że to właśnie to co mówisz...

0

no i fakt.. teraz program sie nie wykrzacza:)

1 użytkowników online, w tym zalogowanych: 0, gości: 1