6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Fri Nov 22, 2024 10:30 pm

All times are UTC




Post new topic Reply to topic  [ 32 posts ]  Go to page Previous  1, 2, 3  Next
Author Message
PostPosted: Fri Feb 12, 2021 3:44 am 
Offline

Joined: Fri Apr 15, 2016 1:03 am
Posts: 140
at 403a: error -----------------------------------------------
403a & 403f don't wrap the same way as at 40f1 - it'll go to values that the interrupt handler can never get to.
The interrupt handler will keep retransmitting old bytes trying to get there.

at 4012: error ------------------------------------------------
4012 doesn't wrap the same way as at 40c1,

comment -------------------------------------------------------
Do nx_rx_get_a, nx_tx_get_a, nx_rx_put_a, nx_tx_put_a get initialized somewhere not shown?
If they have random values at startup, you'll get random characters received & transmitted when you start up.

at nx_irq: error? ---------------------------------------------
Interrupted routine's registers need to be saved before this code executes - is this just not shown?
It should be the reverse of the register restores at nx_irq_end: . )

at 4099: comment ------------------------------------------------
This doesn't match the stack contents here.
DP is 2byte.
Hardware pushes P (SR), then PBR, then PC.

; stack now contains
; +13 saved CPU status register
; +12 saved program bank
; +10 saved PC
; +09 saved data bank
; +07 saved DPR
; +05 saved A
; +03 saved X
; +01 saved Y


comment ---------------------------------------------------------------------
I think this UART has rx & tx FIFOs more than 1 byte deep. You could process multiple bytes in the interrupt routines if you want them to use less CPU time.


Top
 Profile  
Reply with quote  
PostPosted: Fri Feb 12, 2021 9:35 am 
Offline

Joined: Tue May 03, 2016 11:32 am
Posts: 41
Thank you for the feedback!

leepivonka wrote:
at 403a: error -----------------------------------------------
403a & 403f don't wrap the same way as at 40f1 - it'll go to values that the interrupt handler can never get to.
The interrupt handler will keep retransmitting old bytes trying to get there.

at 4012: error ------------------------------------------------
4012 doesn't wrap the same way as at 40c1,

I was already suspecting it had something to do with the index wrapping?

leepivonka wrote:
Do nx_rx_get_a, nx_tx_get_a, nx_rx_put_a, nx_tx_put_a get initialized somewhere not shown?
If they have random values at startup, you'll get random characters received & transmitted when you start up.

I set them to zero in the nx_init routine at $410b:
Code:
00410B  2  A2 00           ldx   #$00
00410D  2               @nextAddr:
00410D  2  74 20           stz   nx_zeropage, X
00410F  2  E8              inx
004110  2  E0 20           cpx   #$20         ; Reserve $20 (32) bytes and clear these
004112  2  D0 F9           bne   @nextAddr


leepivonka wrote:
at nx_irq: error? ---------------------------------------------
Interrupted routine's registers need to be saved before this code executes - is this just not shown?
It should be the reverse of the register restores at nx_irq_end: . )

The registers are pushed/saved in the IRQ routine higher in ROM
Code:
00FDB3  2               handler_nirq:
00FDB3  2  8B              phb            ; Save current DB
00FDB4  2  0B              phd            ; Save current DP
00FDB5  2  C2 30           longr            ; 16-bit registers
00FDB7  2  48              pha            ; Save .A, .X and .Y
00FDB8  2  DA              phx
00FDB9  2  5A              phy
00FDBA  2               ;-----------------------
00FDBA  2               ;   Contents of stack
00FDBA  2               ;
00FDBA  2               ;irq_yreg   = 1         ; 16 bit .Y
00FDBA  2               ;irq_xreg   = irq_yreg + s_word   ; 16 bit .X
00FDBA  2               ;irq_areg   = irq_xreg + s_word   ; 16 bit .A
00FDBA  2               ;irq_dpreg   = irq_areg + s_word   ; DP
00FDBA  2               ;irq_dbreg   = irq_dpreg + s_mpudpx   ; DBR
00FDBA  2               ; pushed by hardware
00FDBA  2               ;irq_srreg   = irq_dbreg + s_mpudbx   ; SR
00FDBA  2               ;irq_pcreg   = irq_srreg + s_mpusrx   ; PC
00FDBA  2               ;irq_pbreg   = irq_pcreg + s_mpupcx   ; PBR
00FDBA  2               ;-----------------------
00FDBA  2  6C D8 02        jmp   (VECTOR_INT)      ; Jump to (indirect) vector


leepivonka wrote:
This doesn't match the stack contents here.
DP is 2byte.
Hardware pushes P (SR), then PBR, then PC.

; stack now contains
; +13 saved CPU status register
; +12 saved program bank
; +10 saved PC
; +09 saved data bank
; +07 saved DPR
; +05 saved A
; +03 saved X
; +01 saved Y

Doesn't the 65816 not first push the Program bank register, PC and last Processor Status register?

leepivonka wrote:
I think this UART has rx & tx FIFOs more than 1 byte deep. You could process multiple bytes in the interrupt routines if you want them to use less CPU time.

This is something I want to look into later on....


Top
 Profile  
Reply with quote  
PostPosted: Fri Feb 12, 2021 6:24 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8507
Location: Midwestern USA
leepivonka wrote:
Hardware pushes P (SR), then PBR, then PC.

You've got that backward. Following any interrupt, PB is the first register to be pushed, followed by PC high, PC low and lastly SR. After SR has been pushed the I bit in SR is set and the D bit in SR is cleared.

Reference:
Investigating 65C816 Interrupts

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Sat Feb 13, 2021 12:12 am 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8507
Location: Midwestern USA
xjmaas wrote:
It seems that when sending data, the send buffer will not wrap. First, when I had half page buffers, receiving seemed to fill the buffers like they should. But when trying to send data, it fills to the size of the buffer (I can see that when examining the buffers after a reset), but the routine will hang there....
(I have to say, I use a regular UART cable from my 6522 based card, but an Arduino as serial emulator (with RTS and CTS tied together) to the 28L92 based card))

In the following line of code:

Code:
buf_idx_mask   = s_e32_buf ^ %11111111   ; Buffer index wrap mask

change the equate to:

Code:
buf_idx_mask   = s_e32_buf -1            ; Buffer index wrap mask

and set s_e32_buf to 128. Re-assemble with index wrapping enabled and see what happens.

Also, attached is the listing output from the assembly of POC V1.2's firmware. The DUART channel interrupt code starts at line 3884. Illustrated are several concepts, one being how to handle multiple channels in a loop and how to work with the DUART's FIFOs. In particular, I use an array of direct page pointers to access the hardware, queues and a transmitter status bit field, using the channel number (0-3) as an index.

Attachment:
File comment: POC V1.2 Firmware Assembly Listing
aout.txt [594.52 KiB]
Downloaded 33 times

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Tue Feb 16, 2021 9:42 am 
Offline

Joined: Tue May 03, 2016 11:32 am
Posts: 41

Hmm, "index" wrapping" seems to work. When I try to send a string several times, I can see the index wraps. But when I try to send >128 bytes, it looks like a (new) interrupt interrupts the interrupt?
(Did I mention I use 19k2 8N1 for serial?)

Next step is looking at "easier/nicer" way to drive the 'L92 using ZP indexing :)

frontend routine
Code:
;-------------------------------------------------------------------------------
; Process Transmit Request
;
; Call the subroutine and the routine will try to "put" a datum into the
; corresponding TxQ. If this succeeds, the routine will return:
;   carry   - clear
;
; NOTE: Carry will be set, if the driver hasn't been initialized,
;   yet...
;-------------------------------------------------------------------------------
; nx_sioput_a - Process datum for channel A TxQ
;-----------------------
nx_sioput_a:
   shortr            ; 8 bit registers
   sec            ; Default, assume error
   bit   IOBASE + dr_misc   ; Read bit 7 of dr_misc, if set, driver
               ; has been initialized
   bpl   @done         ; No, error!
;
   pha            ; Preserve .A
   phx            ; Preserve .X
;
   xba            ; Save datum to .B
;   
   lda   nx_tx_put_a      ; Get TxD "put" index
   ina            ; Increment "put" index
   and   #buf_idx_mask      ; Deal with wrap
;
@full:               ; Loop here until there is space in TxQ
   cmp   nx_tx_get_a      ; TxQ "get" index
   beq   @full         ; TxQ is full, block...
;
   ldx   nx_tx_put_a
   xba            ; Restore datum in .A, save new "put"
   sta   nx_tx_qa, X      ; Put datum into TxQ
   xba            ; Retrieve new "put" index from .B
   sta   nx_tx_put_a
;---------------
;   Manage transmitter
;---------------
   lda   #nx_txa_dis      ; Transmitter disabled flag
   trb   IOBASE + dr_misc   ; is transmitter disabled?
   beq   @cleanup      ; No

   lda   #nx_cr_tx_ena      ; Yes, enable transmitter
   sta   IOBASE + dr_cra
;
@cleanup:
   plx
   pla
   clc
;
@done:
   rts

interrupt excerpt handling TxQ
Code:
;-----------------------   
; Test for channel A THR IRQ
;-----------------------
test_thr_a:
   lda   irq_isrx, S      ; Get ISR from stack
;
   bit   #msk_irq_txa      ; Did Xmitter A request interrupt?
   beq   test_thr_b      ; Nope, try Xmitter B
;-----------------------   
; Process channel A THR IRQ
;-----------------------   
@handle_thr_a:
   ldx   nx_tx_get_a      ; Buffer "get" index
   cpx   nx_tx_put_a      ; Compare with buffer "put" index
   bne   @get_datum
;
   lda   #nx_cr_tx_dis      ; Disable TxD to suppress ...
   sta   IOBASE + dr_cra      ; ... interrupts
   lda   #nx_txa_dis      ; Set xmitter disabled flag in
   tsb   IOBASE + dr_misc   ; - MISC register
   tsb   nx_tx_status      ; - ZP (for debug)
   bra   test_thr_b      ; Buffer is empty, so we can continue
;
@get_datum:
   lda   nx_tx_qa, X      ; Get datum from buffer
   sta   IOBASE + dr_txfifoa   ; Write to THR
   txa            ; Current position
   ina            ; New buffer position
   and   #buf_idx_mask      ; Deal with wrap of index
   sta   nx_tx_get_a      ; Set new "get" index



Top
 Profile  
Reply with quote  
PostPosted: Tue Feb 16, 2021 6:27 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8507
Location: Midwestern USA
xjmaas wrote:
Hmm, "index" wrapping" seems to work. When I try to send a string several times, I can see the index wraps. But when I try to send >128 bytes, it looks like a (new) interrupt interrupts the interrupt?

Assuming that new IRQ is coming from the DUART, it is likely because you are not completely filling the THR on each IRQ. Each time the transmitter interrupts you need to "stuff" the THR to at least the level configured by MR0 bits 3, 4 and 5 in order to clear the TxD IRQ. Writing one datum and moving on isn't how to do it, as the TxD IRQ will keep coming until you satisfy the FIFO fill level or disable the transmitter.

Please review the material in Driving the NXP 28L91 (attached), starting at page 31. If you follow the flow chart and code example it should work.

Attachment:
File comment: Driving the NXP 28L91 UART—also applicable to the 28L92
28l91_driving.pdf [573.32 KiB]
Downloaded 57 times

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Wed Feb 17, 2021 11:52 am 
Offline

Joined: Tue May 03, 2016 11:32 am
Posts: 41
Did a few extra testing and found that when I:
  • try to send <= 256 bytes, it works as expected
  • try to send > 256 bytes, the "@handle_thr_a" keeps looping somewhere...

This tells me that I have some bit in the SR set, but should be cleared? Which affects one or two branch conditions?


Code:
0040E7  2               ;-----------------------
0040E7  2               ; Process channel A THR IRQ
0040E7  2               ;-----------------------
0040E7  2               @handle_thr_a:
0040E7  2               ;   ldx   nx_tx_get_a      ; Buffer "get" index
0040E7  2               ;   cpx   nx_tx_put_a      ; Compare with buffer "put" index
0040E7  2               ;   bne   @get_datum
0040E7  2               ;
0040E7  2               ;   lda   #nx_cr_tx_dis      ; Disable TxD to suppress ...
0040E7  2               ;   sta   IOBASE + dr_cra      ; ... interrupts
0040E7  2               ;   lda   #nx_txa_dis      ; Set xmitter disabled flag in
0040E7  2               ;   tsb   IOBASE + dr_misc   ; - MISC register
0040E7  2               ;   tsb   nx_tx_status      ; - ZP (for debug)
0040E7  2               ;   bra   test_thr_b      ; Buffer is empty, so we can continue
0040E7  2               ;
0040E7  2               ;@get_datum:
0040E7  2               ;   lda   nx_tx_qa, X      ; Get datum from buffer
0040E7  2               ;   sta   IOBASE + dr_txfifoa   ; Write to THR
0040E7  2               ;   txa            ; Current position
0040E7  2               ;   ina            ; New buffer position
0040E7  2               ;   and   #buf_idx_mask      ; Deal with wrap of index
0040E7  2               ;   sta   nx_tx_get_a      ; Set new "get" index
0040E7  2               ;
0040E7  2               ; vvvv  THIS WAS BASED ON PDF BY BDD  vvv
0040E7  2  A6 26           ldx   nx_tx_get_a      ; Get current TxQ "get" index
0040E9  2  A0 04           ldy   #msk_sr_tx_rdy      ; THR status mask
0040EB  2               ;-----------------------
0040EB  2               ; Enter the loop to service the THR interrupt. This loop will continue until
0040EB  2               ; the THR is full or TxQ is empty
0040EB  2               ;-----------------------
0040EB  2               @next_datum:
0040EB  2  E4 28           cpx   nx_tx_put_a      ; Any (new) datums in TxQ?
0040ED  2  F0 13           beq   @tx_off         ; Nope, shutdown Xmitter and go to B
0040EF  2               ;
0040EF  2  98              tya            ; YES ...
0040F0  2  2C 01 C4        bit   IOBASE + dr_sra      ; Any space left in THR
0040F3  2  F0 19           beq   @done         ; no, done for now...
0040F5  2               ;-----------------------
0040F5  2               ; If the THR is full, the transmitter IRQ processing is done for now...
0040F5  2               ; Later on, when the THR's level has been reduced, another IRQ will occur and
0040F5  2               ; more datums can be processed
0040F5  2               ;-----------------------
0040F5  2  BD 80 20        lda   nx_tx_qa, X      ; Get datum from queue and ...
0040F8  2  8D 03 C4        sta   IOBASE + dr_txfifoa   ; ... write to THR (FIFO)
0040FB  2               ;   inx            ; Increment "get" index
0040FB  2  8A              txa            ; Move .X to .A
0040FC  2  1A              inc   a         ; Increment "get" index
0040FD  2  29 7F           and   #buf_idx_mask      ; Deal with wrap?
0040FF  2  AA              tax            ; move .A back to .X
004100  2  80 E9           bra   @next_datum      ; And process next
004102  2               ;
004102  2               @tx_off:
004102  2  A9 08           lda   #nx_cr_tx_dis      ; Shutdown Xmitter A to suppress ...
004104  2  8D 02 C4        sta   IOBASE + dr_cra      ; ... IRQs
004107  2  A9 40           lda   #nx_txa_dis      ; Set Xmitter A disabled flag
004109  2  0C 0C C4        tsb   IOBASE + dr_misc   ; Do in MISC register!
00410C  2  04 2D           tsb   nx_tx_status      ; And in ZP (for debug)
00410E  2               ;
00410E  2               @done:
00410E  2  86 26           stx   nx_tx_get_a      ; Save final TxQ "get" index
004110  2               ; ^^^  THIS WAS BASED ON PDF BY BDD  ^^^



Top
 Profile  
Reply with quote  
PostPosted: Wed Feb 17, 2021 6:47 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8507
Location: Midwestern USA
xjmaas wrote:
Did a few extra testing and found that when I:
  • try to send <= 256 bytes, it works as expected
  • try to send > 256 bytes, the "@handle_thr_a" keeps looping somewhere...

This tells me that I have some bit in the SR set, but should be cleared? Which affects one or two branch conditions?

Code:
0040E7  2               ;-----------------------
0040E7  2               ; Process channel A THR IRQ
0040E7  2               ;-----------------------
0040E7  2               @handle_thr_a:
0040E7  2  A6 26                ldx nx_tx_get_a             ; Get current TxQ "get" index
0040E9  2  A0 04                ldy #msk_sr_tx_rdy          ; THR status mask
0040EB  2               ;-----------------------
0040EB  2               ; Enter the loop to service the THR interrupt. This loop will continue until
0040EB  2               ; the THR is full or TxQ is empty
0040EB  2               ;-----------------------
0040EB  2               @next_datum:
0040EB  2  E4 28                cpx nx_tx_put_a             ; Any (new) datums in TxQ?
0040ED  2  F0 13                beq @tx_off                 ; Nope, shutdown Xmitter and go to B
0040EF  2               ;
0040EF  2  98                   tya                         ; YES ...
0040F0  2  2C 01 C4             bit IOBASE + dr_sra         ; Any space left in THR
0040F3  2  F0 19                beq @done                   ; no, done for now...
0040F5  2               ;-----------------------
0040F5  2               ; If the THR is full, the transmitter IRQ processing is done for now...
0040F5  2               ; Later on, when the THR's level has been reduced, another IRQ will occur and
0040F5  2               ; more datums can be processed
0040F5  2               ;-----------------------
0040F5  2  BD 80 20             lda nx_tx_qa, X             ; Get datum from queue and ...
0040F8  2  8D 03 C4             sta IOBASE + dr_txfifoa     ; ... write to THR (FIFO)
0040FB  2  8A                   txa                         ; Move .X to .A
0040FC  2  1A                   inc a                       ; Increment "get" index
0040FD  2  29 7F                and #buf_idx_mask           ; Deal with wrap?
0040FF  2  AA                   tax                         ; move .A back to .X
004100  2  80 E9                bra @next_datum             ; And process next
004102  2               ;
004102  2               @tx_off:
004102  2  A9 08                lda #nx_cr_tx_dis           ; Shutdown Xmitter A to suppress ...
004104  2  8D 02 C4             sta IOBASE + dr_cra         ; ... IRQs
004107  2  A9 40                lda #nx_txa_dis             ; Set Xmitter A disabled flag
004109  2  0C 0C C4             tsb IOBASE + dr_misc        ; Do in MISC register!
00410C  2  04 2D                tsb nx_tx_status            ; And in ZP (for debug)
00410E  2               ;
00410E  2               @done:
00410E  2  86 26                stx nx_tx_get_a             ; Save final TxQ "get" index

For legibility purposes, I removed the commented-out code and extra whitespace between mnemonics and operands, and reduced text size. BTW, all datums in TxQ are "new." :D

I'm not seeing anything here that would cause a loop on handle_thr_a. You said it's "looping somewhere." Any idea where "where" might be? It would be useful if you posted the entire ISR as a text file, with commented-out code removed and tabs converted to spaces. Debugging code fragments often isn't productive in this environment.

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Wed Feb 17, 2021 7:30 pm 
Offline

Joined: Tue May 03, 2016 11:32 am
Posts: 41
BigDumbDinosaur wrote:
For legibility purposes, I removed the commented-out code and extra whitespace between mnemonics and operands, and reduced text size. BTW, all datums in TxQ are "new." :D
I will change this comment ;)

BigDumbDinosaur wrote:
I'm not seeing anything here that would cause a loop on handle_thr_a. You said it's "looping somewhere." Any idea where "where" might be? It would be useful if you posted the entire ISR as a text file, with commented-out code removed and tabs converted to spaces. Debugging code fragments often isn't productive in this environment.
I have the source for the ISR, the frontend, the assembly listing and a "test" program added.
In the test program, after uploading using the HEX loader, I change the address from which the test is loaded, manually for testing. (The $3100 is just a placeholder)


Attachments:
File comment: ISR, frontend, assembly listing and "test" program
nxp28l9x.zip [16.18 KiB]
Downloaded 39 times
Top
 Profile  
Reply with quote  
PostPosted: Wed Feb 17, 2021 7:51 pm 
Offline

Joined: Tue May 03, 2016 11:32 am
Posts: 41
Oh, I think i May have found the issue with (longer) strings! Going to try to rewrite your (BDD) sprint routine for the DUART


Top
 Profile  
Reply with quote  
PostPosted: Wed Feb 17, 2021 8:11 pm 
Offline

Joined: Tue May 03, 2016 11:32 am
Posts: 41
I created a new debug.asm, in which I implemented the sprint functionality, but pointing to the DUART routine(s). Up to 256 bytes are sent correctly, but when I want to send > 256 bytes, the routine doesn't seem to return...


Code:
        .org    $3000
        .p816

; macros
        .macro  longi                   ; Set .X and .Y to 16-bit
        rep     #%00010000
        .i16
        .endmacro
       
        .macro  shorti                  ; Set .X and .Y to 8-bit
        sep     #%00010000
        .i8
        .endmacro
       
        .macro  longa                   ; Set .A to 16-bit
        rep     #%00100000             
        .a16
        .endmacro
       
        .macro  shorta                  ; Set .A to 8-bit
        sep     #%00100000
        .a8
        .endmacro
       
        .macro  longr                   ; Set all registers to 16-bit
        rep     #%00110000              ; Set 16-bit .A, .X and .Y
        .a16
        .i16
        .endmacro
       
        .macro  shortr                  ; Set all registers to 8-bit
        sep     #%00110000              ; Set 8-bit .A, .X and .Y
        .a8
        .i8
        .endmacro
;
; Equates
nx_sioput_a     = $402e
;
; Actual code start
start:
        shortr
        pea     large                   ; Push pointer to sting to stack
        jsr     sprint                  ; print string @ pointer on stack
@end:
        rts                             ; And.... The END...

; For a description of the routine, see source of Adria (or Supermon 816)
sprint:
        shorta
        longi
;-------
@retadd = 1                             ; Return address
@src    = @retadd + 2                   ; String address (= return address + 2)
;-------       
        ldy     #$0000
        clc                             ; Initial no error
@next:
        lda     (@src, S), Y            ; Get a byte from the string, where:
                                        ; stack pointer + 2, indexed with Y
        beq     @done                   ; If $00, we reached EOL (End-Of-Line)
;
        jsr     nx_sioput_a             ; Print character to DUART channel A
        iny                             ; increment index
        bpl     @next                   ; Continue if .Y < ($ffff + 1)
;       
        sec                             ; String is too long
;
@done:
        plx                             ; Pull return address from stack
        ply                             ; Pull string pointer from stack
        phx                             ; Push return address (in effect to
                                        ; clear string pointer)
        shorti
        rts                             ; Done
;
; small large string (16 bytes)
small:
        .byte   "Dit is een strng"
        .byte   $0a, $0d, $00   
;
; large string (128 bytes)
large:
        .byte   "Dit is een strng"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abc"
        .byte   $0a, $0d, $00   
;
; even larger string (256 bytes)
larger:
        .byte   "Dit is een strng"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abc"
        .byte   $0a, $0d, $00   
;
; Exceed even larger string (259 bytes!)
huge:
        .byte   "Dit is een strng"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   "0123456789abcdef"
        .byte   $0a, $0d, $00   



Top
 Profile  
Reply with quote  
PostPosted: Wed Feb 17, 2021 8:35 pm 
Offline

Joined: Tue May 03, 2016 11:32 am
Posts: 41
xjmaas wrote:
I created a new debug.asm, in which I implemented the sprint functionality, but pointing to the DUART routine(s). Up to 256 bytes are sent correctly, but when I want to send > 256 bytes, the routine doesn't seem to return...

I think I found the issue. Has nothing to do with the ISR or frontend code.... It was the calling code (the sprint routine)!

As we call the front end to send the byte(s), the registers are all set to 8 bit. But the index .Y for the string in sprint expects 16-bit width. What I have done, is add a PHY before and a PLY after the JSR to the frontend. Also I force the register widths just before the PLY.


Code:
        beq     @done                   ; If $00, we reached EOL (End-Of-Line)
;
        phy
;
        jsr     nx_sioput_a             ; Print character to DUART channel A
        longi                           ; Force proper register widths
        shorta
        ply
        iny                             ; increment index
        bpl     @next                   ; Continue if .Y < ($ffff + 1)
       


Next step: implement into ROM and say goodbye (for now) to the 6551 ;)


Top
 Profile  
Reply with quote  
PostPosted: Fri Feb 19, 2021 12:39 pm 
Offline

Joined: Tue May 03, 2016 11:32 am
Posts: 41
For those interested, I have attached the driver that is currently working for my board, for only one channel (as I need only on right now)
Please read the comment in NXP28L92.asm.

I use a cc65 build-environment and use the following commands:
Code:
$path_to/cc65 -l driver.lst -o driver.o NXP28L92.asm
$path_to/ld65 -C $path_to_used_config -o driver.bin driver.o


I used the ca65/ld65 approach as using cl65 directly gives me PETSCII instead of ASCII?

Next step is to get my Intel Hex Uploader working again, as I don;t have a proper blocking uart_input right now?


Attachments:
NXP28L92.zip [22.8 KiB]
Downloaded 37 times
Top
 Profile  
Reply with quote  
PostPosted: Fri Feb 19, 2021 5:52 pm 
Offline
User avatar

Joined: Thu May 28, 2009 9:46 pm
Posts: 8507
Location: Midwestern USA
xjmaas wrote:
For those interested, I have attached the driver that is currently working for my board, for only one channel (as I need only on right now)

In your foreground and interrupt code (ISR) for handling the transmitter I see you are wrapping the TxD queue at 128 bytes and have also defined TXQ at that size. I don't see wrapping occurring in the receiver's foreground and ISR. However, you are also defining RXQ as being 128 bytes.

Also, in foreground code in which you are waiting for a datum to become available (receive), or waiting for queue space to become available (transmit), you can gain a little interrupt performance by using the WAI instruction to stall the MPU instead of spinning in a loop. With the MPU WAIting in that fashion there will be no hardware interrupt latency when the DUART reports in—response time to an IRQ will not be more than one Ø2 cycle. Here's a code excerpt from my POC V1.2 BIOS that illustrates using WAI to block until TXQ space becomes available:


Code:
;================================================================================
;
;putchcom: WRITE DATUM TO TIA-232 CHANNEL (common to all channels)
;
;   ————————————————————————————————————————————————————————————————————————
;   Do not directly call this function, as the stack will become unbalanced.
;   Only use the PUTCHx functions, where x is the comm port ID.
;   ————————————————————————————————————————————————————————————————————————
;
putchcom phy                   ;preserve...
         pha                   ;remaining registers
         phd
         pea #kerneldp
         pld                   ;set kernel direct page
         shortr
         xba                   ;protect datum
         txa                   ;channel index...
         asl                   ;becomes...
         tax                   ;channel offset
         lda tiaputtx,x        ;queue "put" index
         ina                   ;bump it &...
         and #m_tiaptr         ;mask to queue size
         ora tiaqpmsk,x        ;align to queue base addr
;
.main    cmp tiagettx,x        ;room in the queue?
         beq .qfull            ;no, wait
;
         xba                   ;swap queue pointer w/datum
         sta (tiaputtx,x)      ;put datum in queue
         xba                   ;new queue pointer
         sta tiaputtx,x        ;save it
         lda tiatstab,x        ;channel's TxD status mask
         trb tiatxst           ;transmitter running?
         bne .enabltx          ;no, enable it
;
.done    longr
         pld                   ;restore MPU status
         pla
         ply
         plx
         plp
         clc
         rts
;
;
;   block for TXQ space...
;
.qfull   wai                   ;wait for interrupt &...
         bra .main             ;try again
;
;
;   enable transmitter...
;
.enabltx lda #nxpcrtxe
         sta (tiacr,x)
         bra .done
;

_________________
x86?  We ain't got no x86.  We don't NEED no stinking x86!


Top
 Profile  
Reply with quote  
PostPosted: Mon Feb 22, 2021 7:58 am 
Offline

Joined: Tue May 03, 2016 11:32 am
Posts: 41
BigDumbDinosaur wrote:
In your foreground and interrupt code (ISR) for handling the transmitter I see you are wrapping the TxD queue at 128 bytes and have also defined TXQ at that size. I don't see wrapping occurring in the receiver's foreground and ISR. However, you are also defining RXQ as being 128 bytes.

Thank you for the extra eyes! That was something I missed and fixed some unexpected input (from the TxQ)

BigDumbDinosaur wrote:
Also, in foreground code in which you are waiting for a datum to become available (receive), or waiting for queue space to become available (transmit), you can gain a little interrupt performance by using the WAI instruction to stall the MPU instead of spinning in a loop. With the MPU WAIting in that fashion there will be no hardware interrupt latency when the DUART reports in—response time to an IRQ will not be more than one Ø2 cycle. Here's a code excerpt from my POC V1.2 BIOS that illustrates using WAI to block until TXQ space becomes available:[/color]

Code:
;================================================================================
;
;putchcom: WRITE DATUM TO TIA-232 CHANNEL (common to all channels)
;
;   ————————————————————————————————————————————————————————————————————————
;   Do not directly call this function, as the stack will become unbalanced.
;   Only use the PUTCHx functions, where x is the comm port ID.
;   ————————————————————————————————————————————————————————————————————————
;
putchcom phy                   ;preserve...
         pha                   ;remaining registers
         phd
         pea #kerneldp
         pld                   ;set kernel direct page
         shortr
         xba                   ;protect datum
         txa                   ;channel index...
         asl                   ;becomes...
         tax                   ;channel offset
         lda tiaputtx,x        ;queue "put" index
         ina                   ;bump it &...
         and #m_tiaptr         ;mask to queue size
         ora tiaqpmsk,x        ;align to queue base addr
;
.main    cmp tiagettx,x        ;room in the queue?
         beq .qfull            ;no, wait
;
         xba                   ;swap queue pointer w/datum
         sta (tiaputtx,x)      ;put datum in queue
         xba                   ;new queue pointer
         sta tiaputtx,x        ;save it
         lda tiatstab,x        ;channel's TxD status mask
         trb tiatxst           ;transmitter running?
         bne .enabltx          ;no, enable it
;
.done    longr
         pld                   ;restore MPU status
         pla
         ply
         plx
         plp
         clc
         rts
;
;
;   block for TXQ space...
;
.qfull   wai                   ;wait for interrupt &...
         bra .main             ;try again
;
;
;   enable transmitter...
;
.enabltx lda #nxpcrtxe
         sta (tiacr,x)
         bra .done
;

This is something I am going totry in a newer spin of the ROM....


Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 32 posts ]  Go to page Previous  1, 2, 3  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 30 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: