Products > Programming

x86 assembly, uart-16450, simple putch

(1/6) > >>

DiTBho:

--- Code: ---; Serial Port 16450 IO
; ====================

;base DLAB access Abbreviation  Register Nam
; +0   0   Write      THR **    Transmitter Holding Buffer
; +0   0   Read       RBR **    Receiver Buffer
; +0   1   Read/Write DLL **    Divisor Latch Low Byte
; +1   1   Read/Write DLM **    Divisor Latch High Byte
; +1   0   Read/Write IER       Interrupt Enable Registe
; +2   x   Read       IIR       Interrupt Identification Register
; +3   x   Read/Write LCR **    Line Control Register
; +4   x   Read/Write MCR **    Modem Control Register
; +5   x   Read       LSR       Line Status Register
; +6   x   Read       MSR       Modem Status Register

; baud rate setting
; latch low byte
; 0x00 0x01 = 115200 bps
; 0x00 0x02 =  56700 bps
; 0x00 0x03 =  38400 bps
; 0x00 0x06 =  19200 bps
; 0x00 0x0C =   9600 bps
; 0x00 0x18 =   4800 bps
; 0x00 0x30 =   2400 bps

serial_base     equ (0x3f8)
serial_cmd0     equ (serial_base + 0)
serial_cmd1     equ (serial_base + 1)
serial_cmd2     equ (serial_base + 2)
serial_cmd3     equ (serial_base + 3)
serial_cmd4     equ (serial_base + 4)
serial_status   equ (serial_base + 5)

console_init:
                push   dx
                push   ax
                                         ; Settings
                mov    dx, serial_cmd3
                mov    al, 0x80          ; DLAB ON
                out    dx, al            ; get it on its way.

                mov    dx, serial_cmd0   ; 115200 bps
                mov    al, 0x01          ; baud rate - Divisor Latch low byte
                out    dx, al            ; get it on its way.

                mov    dx, serial_cmd1
                mov    al, 0x00          ; baud rate - divisor latch high byte
                out    dx, al            ; get it on its way.

                mov    dx, serial_cmd3
                mov    al, 0x03          ; 8 bits, No parity, 1 stop bit
                out    dx, al            ; get it on its way.

                mov    dx, serial_cmd2
                mov    al, 0xC7          ; FIFO control register
                out    dx, al            ; get it on its way.

                mov    dx, serial_cmd4
                mov    al, 0x0B          ; turn on DTR, RTS, and OUT2
                out    dx, al            ; get it on its way.

; clear the Divisor Latch Access Bit
; in order to use the Transmitter Holding Register

                mov    dx, serial_cmd3   ; Line Control Register
                in     al, dx
                and    al, 0x7f          ; 0111_1111b, Set DLAB=0, DLAP is bit7
                out    dx, al

                pop    ax
                pop    dx
                ret

; reg al: received character
ch_get:
                ; to be implemented
                mov    al, 0x00
                ret

; reg al: char to transmit
ch_put:
                push   dx
                push   ax
                push   cx
ch_put_wait:
                mov dx, serial_status    ; Line Status Register
                mov cx, ax
                in al, dx
                test cx, 0x20            ; 0010_0000b, use bit 5 to see if THR is empty
                jz ch_put_wait

                mov ax, cx
                mov dx, serial_cmd0      ; Transmitter Holding Register
                out dx, al

                pop    cx
                pop    ax
                pop    dx
                ret

--- End code ---
(serial.s)


--- Code: ---            cli                        ; disable interrupts

            mov bp, 0x9000
            mov sp, bp

            call console_init

main:
            mov al, 'h'
            call ch_put
            mov al, 'a'
            call ch_put
            mov al, 'l'
            call ch_put
            mov al, 'l'
            call ch_put
            mov al, 'o'
            call ch_put

            jmp main

--- End code ---
(main.s)

do you see any error with this simple code?
The serial doesn't correctly show chars  :o :o :o

edit:
nasm syntax

Andy Watson:
I'm not familiar with the 16450, however, one common problem is not waiting for the character flag of the transmit register. Once the character is put into the Tx register the tx-full flag will be set, BUT usually this is a state controlled operation that is operating at the speed of the UART clock. Hence it is possible to put a character into tx reg, return from the subroutine, and then re-enter with the next character before the flag is set. The solution, is to use interupts or to wait for the flag to be set after putting the character in the Tx reg. If using the non-interrupt version, you might want to bracket the tx insertion and subsequent wait loop with disabled interupts - so that you don't miss the flag setting completely.

DiTBho:

--- Code: ---ch_put_wait:
                mov dx, serial_status    ; Line Status Register
                mov cx, ax
                in al, dx
                test cx, 0x20            ; 0010_0000b, use bit 5 to see if THR is empty
                jz ch_put_wait

--- End code ---

this part? it waits and loops until the status register reports "THR is empty"

Andy Watson:
You still need the empty check.

Consider what happens when you have multiple characters to transmit. Your present code is:

Loop until Tx empty - fill Tx 1 - go away and fetch next character - Loop until Tx empty - fill Tx 2 - etc..

The problem is that the setting of the UART flags is asynchronos and can be much slower than the "go away and fetch next charater" such that when the code returns with the second character it can find the Tx is still being flagged as empty.
The non-interrupt solution is:
Loop until Tx empty - (disable interrupts) - fill Tx 1 -  Loop until Tx full - (re-eneable interrupts) - go away to fetch nect character - etc..
You need the fill tx and loop until full to be atomic, hence the disabling/enabling of interrupts - if they are being used.

DiTBho:
but interrupts are always disabled in that code.

Navigation

[0] Message Index

[#] Next page

There was an error while thanking
Thanking...
Go to full version
Powered by SMFPacks Advanced Attachments Uploader Mod