Polling I/O (MIPS)

≯℡__Kan透↙ 提交于 2020-01-02 17:15:07

问题


I am attempting to write a program in MIPS that uses polling to read a character from the keyboard and then displays it using the builtin Keyboard and Display MMIO Simulator. Unfortunately, I am having trouble grasping the concept behind the registers used and the control bits, but have been trying to figure it out from examples online.

Here is what I have written so far:

            .data

            .text
            .globl main

main:
            .eqv    RCR 0xffff0000      # Receiver Control Register     (Ready Bit)
            .eqv    RDR 0xffff0004      # Receiver Data Register        (Key Pressed - ASCII)
            .eqv    TCR 0xffff0008      # Transmitter Control Register  (Ready Bit)
            .eqv    TDR 0xffff000c      # Transmitter Data Register     (Key Displayed- ASCII)

keyWait:    lw      $t0, RCR
            andi    $t0, $t0, 1
            beq     $t0, $zero, keyWait

            lb      $a0, RDR

What I believe is happening here is that keyWait continues to loop until the ready bit is set to 1 (*), and then the ASCII value of the key is stored in $a0. Is this correct?

If this is correct, how can I then print the character on the display using the same polling technique with the TCR and TDR?

*I don't understand why this is needed to be checked with the andi operation - if $t0 is 1 (or 0), it is anded with 1, which equals 1 (or 0), which is then stored in $t0? So the value of $t0 stays as it was prior to this operation regardless?

EDIT

Here is my attempt at passing the key pressed data to the display.

                .data

                .text
                .globl main

main:
                .eqv    RCR 0xffff0000      # Receiver Control Register     (Ready Bit)
                .eqv    RDR 0xffff0004      # Receiver Data Register    (Key Pressed - ASCII)
                .eqv    TCR 0xffff0008      # Transmitter Control Register  (Ready Bit)
                .eqv    TDR 0xffff000c      # Transmitter Data Register (Key Displayed- ASCII)

keyWait:        lw      $t0, RCR
                andi    $t0, $t0, 1
                beq     $t0, $zero, keyWait

                lbu     $a0, RDR

displayWait:    lw      $t1, TCR
                andi    $t1, $t1, 1
                beq     $t1, $zero, displayWait

                sb      $a1, TDR

                li      $v0, 11
                syscall 

                j       keyWait

This is just a test program which should print the character on the MMIO Display Simulator, and also in the console within MIPS. It is doing the latter, but not on the display simulator. In the display simulator, Cursor: is incrementing each time a key is pressed, but nothing is being printed. What am I missing?


回答1:


You probably didn't click "Connect to MIPS".

See this answer: How to print to the screen from MIPS assembly

When I was testing I've found that if you stop simulation, reload your program, you probably have to click on "Disconnect from MIPS" and then "Connect to MIPS" again (i.e. toggle it a bit)

Also, a bug: The data from RDR is in $a0, but you are storing into TDR from $a1

From the link, notice that the style is slightly different than yours. In the link, they use offsets from a base register rather than hardwiring the addresses. This is much more usual for devices [in device drivers in the real world], particularly if the base address of the device could be configured/changed.

Also, in mars, if you look at the actual low level instructions generated from the pseudo-ops in the hardwired vs. base register versions, the base register version is more compact (i.e. fewer injected lui insts)

So, I've restyled your code to use a base register:

    .data

    .eqv    MMIOBASE    0xffff0000

    # Receiver Control Register (Ready Bit)
    .eqv    RCR_        0x0000
    .eqv    RCR         RCR_($s0)

    # Receiver Data Register (Key Pressed - ASCII)
    .eqv    RDR_        0x0004
    .eqv    RDR         RDR_($s0)

    # Transmitter Control Register (Ready Bit)
    .eqv    TCR_        0x0008
    .eqv    TCR         TCR_($s0)

    # Transmitter Data Register (Key Displayed- ASCII)
    .eqv    TDR_        0x000c
    .eqv    TDR         TDR_($s0)

    .text
    .globl  main
main:
    li      $s0,MMIOBASE            # get base address of MMIO area

keyWait:
    lw      $t0,RCR                 # get control reg
    andi    $t0,$t0,1               # isolate ready bit
    beq     $t0,$zero,keyWait       # is key available? if no, loop

    lbu     $a0,RDR                 # get key value

displayWait:
    lw      $t1,TCR                 # get control reg
    andi    $t1,$t1,1               # isolate ready bit
    beq     $t1,$zero,displayWait   # is display ready? if no, loop

    sb      $a0,TDR                 # send key to display

    li      $v0,11
    syscall

    j       keyWait

I did a little "fancy footwork" with the .eqv above. In the general case, even though it's a bit more verbose, it may be clearer to do:

    .eqv    RCR         0x0000

    lw      $t0,RCR($s0)            # get control reg


来源:https://stackoverflow.com/questions/40051870/polling-i-o-mips

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!