Indeks English versionEnglish version

Jak odczytać wewnętrzną pamięć ROM mikroprocesora HD6305Y1

Niezbyt szczegółowy opis końcówki NUM zacytowany z dokumentacji:

To wyprowadzenie nie jest przeznaczone do wykorzystania przez użytkownika. W przypadku układu HD6305Y1 (posiadającego wewnętrzną pamięć ROM) powinno być podłączone do Vcc przez opornik 10 kΩ. W przypadku układu HD6305Y2 (bez wewnętrznej pamięci ROM) powinno być podłączone do Vss.

Okazało się, że mikroprocesor HD6305Y1 z końcówką NUM połączoną z Vss zachowuje się tak samo jak HD6305Y2, tzn. zaczyna wykonywać kod z zewnętrznej pamięci zamiast z wewnętrznej. Niestety program nie uzyska dostępu do wewnętrznej pamięci ROM przez zmianę stanu końcówki NUM (ponieważ jest on odczytywany tylko przy resecie a potem ignorowany), ale odczyt nieudokumentowanego rejestru pod adresem $001F lub zapis czegokolwiek do niego również przynosi pożądany efekt.

Jedyna dotychczas znaleziona informacja na temat rejestru $001F:

Nie wolno używać obszaru $13 do $1F, ponieważ jest on przeznaczony do testowania układu. Zapis lub odczyt tych adresów powoduje katastrofę.

Schemat układu

mikroprocesor HD6305Y1 z zewnętrzną pamięcią programu

Software

Program zapisany w pamięci EPROM przesyła zawartość wewnętrznej pamięci ROM (zakres adresów $0140 do $1FFF) przez port szeregowy. Fragmenty kodu, które zawierają w komentarzu liczbę taktów, muszą być wykonane w ściśle określonym czasie. Trzeba zwrócić na to uwagę przy ewentualnej modyfikacji.

Ustawienia portu szeregowego:

plik 6305y1.zip - zawartość pamięci EPROM

portc   equ     $02
ddrc    equ     $06
ram     equ     $40             ;adres początku pamięci RAM

; bity portu C
TXD     equ     0               ;wyjście szeregowe, nie zmieniać!

        org     $1F00
reset:  sei
        rsp

; kopiowanie programu do pamięci RAM oraz wykonanie go
        clr     x
loop1:  lda     progr,x
        sta     ram,x
        inc     x
        bpl     loop1           ;kopiowane jest 128 bajtów
        jmp     ram

; kod kopiowany do RAM
progr:  lda     #$01            ;1<<TXD
        sta     ddrc            ;TXD = wyjście
        sta     portc           ;TXD = stan wysoki
; opóźnienie ok. 500 ms
        clr     x
loop2:  dec     a
        bne     loop2
        dec     x
        bne     loop2

; przełączenie trybu pracy procesora
        clr     $1F

; pętla wysyłająca bajty
loop4:  bclr    TXD,portc       ;bit startu
ldacmd: lda     $0140           ;4 takty, argument modyfikowany
        sec                     ;1 takt, bit stopu
; pętla wysyłająca bity
; wymagana długość pętli = 2.4576MHz / 4 / 9600Hz = 64 takty
loop5:  ldx     #10             ;2 takty
loop6:  dec     x               ;2 takty
        bne     loop6           ;3 takty
        ror     a               ;2 takty
        rol     portc           ;5 taktów, Carry idzie na TXD
        cmp     #0              ;2 takty, kasuje Carry
        bne     loop5           ;3 takty, następny bit
; bity stopu, ilość taktów niekrytyczna, ale co najmniej 59 stąd do loop4
        ldx     #30
loop7:  dec     x
        bne     loop7
; następny adres
        inc     ldacmd+2+ram-progr
        bne     loop4
        inc     ldacmd+1+ram-progr
        brclr   5,ldacmd+1+ram-progr,loop4
; koniec
        bra     *

; wektor RESET
        org     $1FFE
        db      high reset, low reset