-
11. Data: 2020-08-21 14:57:42
Temat: Re: 74HCT245 jako port wejściowy - nie działa, choć powinien
Od: Piotr Gałka <p...@c...pl>
W dniu 2020-08-20 o 20:08, Atlantis pisze:
> Wymiana układy 74HCT138 też nie pomogła. Tym samym wymieniłem wszystkie
> układy współpracujące z 74HCT245. W akcie desperacji podmieniłem też
> wszystkie "mostki" z kynaru, jakie miałem na płytce - w razie gdyby
> któryś nie łączył. Też nic.
>
> Sprawdziłem też, czy przypadkiem winy nie ponosi kod w funkcjach
> obsługujących naciśnięcie przycisku. Podmieniłem go na proste zapalanie
> i gaszenie diody. Pomimo tego problem ciągle występuje. Znika dopiero
> wtedy, gdy zakomentuję w pętli głównej funkcje sprawdzające stan przycisków.
>
> Tak więc albo problem jest programowy i biblioteka do obsługi przycisków
> coś miesza (co byłoby dziwne, bo na innym urządzeniu działa), albo coś
> jest nie tak ze stosem, albo faktycznie chodzi o kierunek transmisji
> 74HCT245. Tyle tylko, że zanim zabiorę się za przeprojektowywanie
> modułu, wolałbym wykluczyć przyczyny programowe.
>
W czasach, gdy stosowaliśmy scalaki THT i nie najlepiej projektowaliśmy
płytki (GND pociągnięte ścieżkami) kilka razy zdarzyło nam się walczyć z
jakimś problemem którego przyczyną w końcu okazywała się zbyt duża
długość ścieżek podłączających kondensatory blokujące (też THT) do
któregoś scalaka.
P.G.
-
12. Data: 2020-08-22 10:37:50
Temat: Re: 74HCT245 jako port wejściowy - nie działa, choć powinien
Od: Atlantis <m...@w...pl>
On 21.08.2020 09:54, J.F. wrote:
> Byc moze, ale ... mozliwe tez, ze wtedy program uzywa niekolidujacych
> adresow ...
Co masz na myśli? Zarówno w funkcji sprawdzania stanu przycisku, jak i
przy odczytywaniu portu bezpośrednio, korzystam z tej samej definicji:
#define BTNS (*(volatile uint8_t*)0x6300)
Sprawdziłem jeszcze raz i faktycznie samo odczytanie portu nie powoduje
żadnych problemów. Zakomentowałem problematyczne funkcje key_update().
Zamiast tego w pętli co sekundę odczytuję>= wartość portu i wyświetlam ją
na wyświetlaczu hd44780. W takiej wersji układ działa prawidłowo -
wciskanie poszczególnych przycisków powoduję zmianę wyświetlanej
wartości, układ działa stabilnie i się nie resetuje.
Kod funkcji sprawdzającej przycisku znajduje się tutaj:
https://pastebin.com/E5PU9uPN
> Daj 500kHz czy 250kHz i sie zobaczy czy to w tym problem.
>
> Po tylu systemach powinienes miec juz taki generatorek gotowy do
> podpiecia :-)
Chwilowo nie mam, ale spróbuję coś wykombinować. ;)
-
13. Data: 2020-08-23 15:38:45
Temat: Re: 74HCT245 jako port wejściowy - nie działa, choć powinien
Od: Atlantis <m...@w...pl>
Z ciekawości wykonałem nową wersje modułu, w którym układ 74HCT245 jest
podłączony dokładnie tak samo, jak w tym drugim, działającym urządzeniu.
Przy okazji poprawiłem trochę sposób prowadzenia ścieżki zasilania i
pola masy. Okazało się jednak, że to nie tutaj leżała przyczyna.
Zacząłem jeszcze raz analizować sytuację i nagle mnie olśniło - byłem w
stanie odczytywać wartość portu i to nie powodowało problemów. Jednak
gdy tylko stosowałem swoją bibliotekę (która również czyta z tego portu)
urządzenie zaczęło działać niestabilnie i resetować się. Istniała jednak
jeszcze jedna różnica - testowa funkcja odczytująca wartość portu była
wywoływana raz na sekundę. Natomiast funkcja sprawdzająca wartość
przycisku jest wywoływana w każdym przebiegu pętli.
Zrobiłem więc eksperyment - ustawiłem programowy timer, powodujący
wywoływanie funkcji key_update() co jakiś 40 ms. Okazuje się, że problem
przestał występować. Nie pojawiają się też "fałszywe" wciśnięcia
przycisków. Na dobrą sprawę mógłbym to tak zostawić, nawet upraszczając
bibliotekę, bo to opóźnienie załatwia sprawę debouncingu.
Tyle tylko, że sprawa nie daje mi spokoju. Dlaczego tak się dzieje?
Dlaczego w drugim urządzeniu, opartym na tej samej architekturze, mogę
wywoływać funkcję key_update() z pętli głównej i nic się nie dzieje, a w
drugim występują takie problemy i trzeba stosować timer?
Mogę od razu obalić teorię, która w pierwszym momencie przychodzi do
głowy - to działające urządzenie ma jeszcze mniej "zajętą" pętlę główną,
więc nie ma tam niczego, co mogłoby robić za naturalne opóźnienie.
I jeszcze jedno: funkcja key_update jest wywoływana kilkukrotne - za
każdym razem przyjmując jako argument adres do struktury odnoszącej się
do jednego z przycisków. Przy każdym wywołaniu sprawdzany jest port.
Jednak wielokrotne wywołania nie są najwyraźniej problemem same w sobie,
bo wspomniany wcześniej timer programowy również wywołuje funkcję
trzykrotnie.
-
14. Data: 2020-08-23 16:09:26
Temat: Re: 74HCT245 jako port wejściowy - nie działa, choć powinien
Od: Atlantis <m...@w...pl>
Chyba trochę się pospieszyłem. Wprowadzona zmiana poprawiła sytuację,
ale jej nie naprawiła. Urządzenia pracuje stabilniej. Pierwszy reset
wystąpił po jakichś 10 minutach, a nie kilkunastu-kilkudziesięciu
sekundach...
-
15. Data: 2020-08-23 18:43:37
Temat: Re: 74HCT245 jako port wejściowy - nie działa, choć powinien
Od: Atlantis <m...@w...pl>
I jeszcze jeden update.
Wygląda na to, że:
1) Przyczyną niestabilnego zachowania układu nie są częste odczyty stanu
wejść 74HCT245. Umieściłem w pętli głównej kilka następujących sobie
instrukcji przypisania stanu tego portu zmiennej. Instrukcje te są
wywoływane przy każdym przebiegu pętli. Do zmiennej trafia zawartość
portu. Nic się nie wiesza ani nie resetuje.
2) Przyczyną nie jest raczej zbyt szybki zegar. Gdyby tak było,
doświadczałbym ogólnego braku stabilności systemu. Tymczasem do momentu
wykorzystania funkcji key_update() wszystko jest w porządku. Nie wygląda
więc na to, żeby problem był sprzętowy.
3) Niemniej na innym urządzeniu funkcja key_update() działa poprawnie...
-
16. Data: 2020-08-25 18:00:46
Temat: Re: 74HCT245 jako port wejściowy - nie działa, choć powinien
Od: Atlantis <m...@w...pl>
Ok, wygląda to tak, jakby faktycznie winę za niestabilne działanie
układu ponosiło przepełnienie stosu. Zamiast wywoływać funkcję
key_update() z pętli głównej, umieściłem tam odpowiadający jej fragment
kodu (cc65 na chwilę obecną jest dość ubogim kompilatorem, wśród jego
ograniczeń znajduje się m.in. brak funkcji inline). Wszystko zaczęło
działać.
Trochę mnie to dziwi, bo:
- Nie mam w tym kodzie głęboko zagnieżdżonych funkcji. Funkcje
key_update() była wywoływana bezpośrednio z pętli głównej, ona sama
wywołuje tylko funkcję millis() - wzorowaną na Arduino funkcję
zwracającą ilość taktów systemowych generowanych w przerwaniu (ze
względu na niskie taktowanie są one zwiększane co 20 ms, a nie 1 ms).
- Sprzętowy stos 6502 jest co prawda niewielki, ale cc65 generuje
własny, programowy stos.
- Pamięci jest sporo jak na taki układ (8kB) i jak na razie zbyt mocno
jej nie wykorzystuję. Najwięcej zużywają chyba bufory dla UART-a (2x 256
bajtów). Jest też kilka pomniejszych buforów i trochę zmiennych. Aż
sprawdziłem, czy przypadkiem łańcuch tekstowe podawane jako argumenty
funkcji nie trafiają przypadkiem do RAM-u, ale w generowanym przez
kompilator kodzie asemblerowym są oznaczone jako .rodata.
Gdyby kogoś szczególnie interesowała ta zagadka, to wrzuciłem kody
źródłowe na githuba,
To jest ten problematyczny:
https://github.com/marekw1986/RetroEG
A tutaj działający:
https://github.com/marekw1986/TalkingClock
(Definicja key_update w io.c)
-
17. Data: 2020-08-25 18:42:05
Temat: Re: 74HCT245 jako port wejściowy - nie działa, choć powinien
Od: "J.F." <j...@p...onet.pl>
Użytkownik "Atlantis" napisał w wiadomości grup
dyskusyjnych:5f4535af$0$536$6...@n...neostrada.
pl...
>Ok, wygląda to tak, jakby faktycznie winę za niestabilne działanie
>układu ponosiło przepełnienie stosu. Zamiast wywoływać funkcję
Mowilem - wpisz w stos jakies znane wartosci i sprawdzaj ile ich sie
ostalo.
>key_update() z pętli głównej, umieściłem tam odpowiadający jej
>fragment
>kodu (cc65 na chwilę obecną jest dość ubogim kompilatorem, wśród jego
>ograniczeń znajduje się m.in. brak funkcji inline). Wszystko zaczęło
>działać.
>Trochę mnie to dziwi, bo:
>- Nie mam w tym kodzie głęboko zagnieżdżonych funkcji. Funkcje
>key_update() była wywoływana bezpośrednio z pętli głównej, ona sama
>wywołuje tylko funkcję millis() - wzorowaną na Arduino funkcję
>zwracającą ilość taktów systemowych generowanych w przerwaniu (ze
>względu na niskie taktowanie są one zwiększane co 20 ms, a nie 1 ms).
>- Sprzętowy stos 6502 jest co prawda niewielki, ale cc65 generuje
>własny, programowy stos.
Sprzetowy chyba tez uzywa.
>- Pamięci jest sporo jak na taki układ (8kB) i jak na razie zbyt
>mocno
>jej nie wykorzystuję.
Ale Ty stosu sprzetowego potrzebujesz ... chyba
>Gdyby kogoś szczególnie interesowała ta zagadka, to wrzuciłem kody
>źródłowe na githuba,
>To jest ten problematyczny:
>https://github.com/marekw1986/RetroEG
Ten jest chyba dobry - bo juz nie wołasz key_update().
>A tutaj działający:
>https://github.com/marekw1986/TalkingClock
>(Definicja key_update w io.c)
A mozesz wrzucic assembler do funkcji key_update ?
Moze ma tam troche wewnetrznych zmiennych tymczasowych.
No i wolasz z niej te key_func, prepare_disp, update_disp jak sie
domyslam.
J.
-
18. Data: 2020-08-25 20:36:41
Temat: Re: 74HCT245 jako port wejściowy - nie działa, choć powinien
Od: Atlantis <m...@w...pl>
On 25.08.2020 18:42, J.F. wrote:
> Mowilem - wpisz w stos jakies znane wartosci i sprawdzaj ile ich sie
> ostalo.
Na razie wstrzymałem się z tym testem, bo jego przeprowadzenie jest
trochę uciążliwe ma tak antycznej platformie, gdy nie ma się dostępu do
sprzętowego debuggera i nie można tak po prostu ustawić pułapki i
podejrzeć zawartości pamięci.
Na chwilę obecną obserwacje zdają się wskazywać właśnie na problem ze
stosem...
> Sprzetowy chyba tez uzywa.
Tak, oczywiście. Miałem na myśli to, że używa go w ograniczonym
zakresie. Bodajże m.in. wartości zwracane przez funkcje są odkładane na
tym stosie. I to chyba tylko wtedy, gdy są one za duże, żeby dało się je
przekazać przez rejestry.
> Ale Ty stosu sprzetowego potrzebujesz ... chyba
Wydaje mi się, że sam w części kodu napisanej w asemblerze użyłem
instrukcji PHA i PLA tylko kilka razy. Na pewno występuj one w części
odpowiadającej za wykonanie przerwania (zrzucenie na stos i przywrócenie
kontekstu) oraz w jednej z procedur opóźniających. Widzę, że w kodzie
generowanym przez kompilator też czasem się pojawiają, gdy np. chwilowo
trzeba zwolnić rejestr albo akumulator.
> Ten jest chyba dobry - bo juz nie wołasz key_update().
Tak, to jest aktualna wersja kodu, w której wywaliłem wywołania tej
funkcji. Jednak to właśnie ten projekt buł problematyczny. Drugi, pomimo
wywołań kay_update() zawsze działał całkowicie poprawnie.
> A mozesz wrzucic assembler do funkcji key_update ?
> Moze ma tam troche wewnetrznych zmiennych tymczasowych.
Kompiluje się do następującego kodu asemblerowego:
; ----------------------------------------------------
-----------
; void __near__ key_update (__near__ struct key *)
; ----------------------------------------------------
-----------
.segment "CODE"
.proc _key_update: near
.segment "BSS"
L001E:
.res 1,$00
.segment "CODE"
jsr pushax
lda $6600
jsr pusha0
ldy #$03
jsr ldaxysp
sta ptr1
stx ptr1+1
lda (ptr1)
jsr tosanda0
jsr bnega
sta L001E
lda L001E
jsr pusha0
ldy #$03
jsr ldaxysp
sta ptr1
stx ptr1+1
ldy #$01
lda (ptr1),y
jsr tosicmp0
beq L0023
lda L001E
beq L0026
jsr pushw0sp
jsr _millis
ldy #$02
jsr staspidx
bra L002F
L0026: jsr _millis
jsr pushax
ldy #$03
jsr ldaxysp
sta ptr1
stx ptr1+1
ldy #$02
lda (ptr1),y
jsr tossuba0
cmp #$03
bcc L002F
jsr ldax0sp
ldy #$03
sta ptr1
stx ptr1+1
lda (ptr1),y
iny
ora (ptr1),y
beq L002F
jsr ldax0sp
ldy #$04
jsr ldaxidx
jsr callax
L002F: jsr ldax0sp
sta ptr1
stx ptr1+1
lda L001E
ldy #$01
sta (ptr1),y
L0023: jmp incsp2
.endproc
> No i wolasz z niej te key_func, prepare_disp, update_disp jak sie domyslam.
A tak, faktycznie. Te funkcje są wywoływane. Funkcja key_func przez
wskaźnik na funkcję zapisany w strukturze, a z niej jeszcze po kolei
prepare_disp i update_disp.
-
19. Data: 2020-08-28 11:03:51
Temat: Re: 74HCT245 jako port wejściowy - nie działa, choć powinien
Od: "J.F." <j...@p...onet.pl>
Użytkownik "Atlantis" napisał w wiadomości grup
dyskusyjnych:5f455a39$0$551$6...@n...neostrada.
pl...
On 25.08.2020 18:42, J.F. wrote:
>> Mowilem - wpisz w stos jakies znane wartosci i sprawdzaj ile ich
>> sie
>> ostalo.
>Na razie wstrzymałem się z tym testem, bo jego przeprowadzenie jest
>trochę uciążliwe ma tak antycznej platformie, gdy nie ma się dostępu
>do
>sprzętowego debuggera i nie można tak po prostu ustawić pułapki i
>podejrzeć zawartości pamięci.
W C moze byc problem, ale mialem na mysli wpisanie w obszar stosu np
55 gdzies na początku programu, a potem w petli glownej zliczenie ile
ich zostalo i wyswietlanie ...
>Na chwilę obecną obserwacje zdają się wskazywać właśnie na problem ze
>stosem...
>> Sprzetowy chyba tez uzywa.
>Tak, oczywiście. Miałem na myśli to, że używa go w ograniczonym
>zakresie. Bodajże m.in. wartości zwracane przez funkcje są odkładane
>na
>tym stosie. I to chyba tylko wtedy, gdy są one za duże, żeby dało się
>je
>przekazać przez rejestry.
>> Ale Ty stosu sprzetowego potrzebujesz ... chyba
>Wydaje mi się, że sam w części kodu napisanej w asemblerze użyłem
>instrukcji PHA i PLA tylko kilka razy. Na pewno występuj one w części
>odpowiadającej za wykonanie przerwania (zrzucenie na stos i
>przywrócenie
>kontekstu) oraz w jednej z procedur opóźniających. Widzę, że w kodzie
>generowanym przez kompilator też czasem się pojawiają, gdy np.
>chwilowo
>trzeba zwolnić rejestr albo akumulator.
Raczej podejrzewam ten kawalek w C, co on tam wyprawia, jak mu
wskaznik na strukture przekazesz.
>> A mozesz wrzucic assembler do funkcji key_update ?
>> Moze ma tam troche wewnetrznych zmiennych tymczasowych.
>Kompiluje się do następującego kodu asemblerowego:
; ----------------------------------------------------
-----------
; void __near__ key_update (__near__ struct key *)
; ----------------------------------------------------
-----------
.segment "CODE"
.proc _key_update: near
.segment "BSS"
L001E:
.res 1,$00
.segment "CODE"
jsr pushax
lda $6600
jsr pusha0
; jesli te pushax, pusha0 dotycza programowego stosu CC, to istotnie
az tak bardzo "sprzetowego" stosu nie obciaza.
ldy #$03
jsr ldaxysp
sta ptr1
stx ptr1+1
lda (ptr1)
jsr tosanda0
jsr bnega
sta L001E
lda L001E
jsr pusha0
ldy #$03
jsr ldaxysp
sta ptr1
stx ptr1+1
ldy #$01
lda (ptr1),y
jsr tosicmp0
beq L0023
lda L001E
beq L0026
jsr pushw0sp
jsr _millis
ldy #$02
jsr staspidx
bra L002F
L0026: jsr _millis
jsr pushax
ldy #$03
jsr ldaxysp
sta ptr1
stx ptr1+1
ldy #$02
lda (ptr1),y
jsr tossuba0
cmp #$03
bcc L002F
jsr ldax0sp
ldy #$03
sta ptr1
stx ptr1+1
lda (ptr1),y
iny
ora (ptr1),y
beq L002F
jsr ldax0sp
ldy #$04
jsr ldaxidx
jsr callax
L002F: jsr ldax0sp
sta ptr1
stx ptr1+1
lda L001E
ldy #$01
sta (ptr1),y
L0023: jmp incsp2
.endproc
J.