[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

MIPS - Memory-mapped I/O question

Posted on 2006-05-15
7
Medium Priority
?
2,985 Views
Last Modified: 2011-09-20
Turn off branch and load delays for this program.  It will make it MUCH simpler…  Be sure to turn on memory-mapped I/O.

You may start with the "Test of memory mapped IO" example program.  Make sure you fully understand what it is doing before you start programming.  Remove all parts of the example program that are not being used by your program.

You cannot use syscall for input, because the program would then block on the input.  Instead, use an interrupt-driven input routine catch input.

Write a program that starts with two arrays of characters (.asciiz strings), of length 25, labeled 'source' and 'display'.  Initially, the two arrays are identical and contain 24- character strings.  You may start your program by copying the source array into the display array.  Use a subroutine to do this.  Then run repeatedly displaying the display array character-by-character with a terminating newline.  To make debugging easier, code a delay loop (perhaps 2 nested loops with 300 to 500 passes through each one, to make the total elapsed time approximately 1 second between each display of the display array.  Also, use a delay loop to slow down the printing of the elements in the array so you can watch what happens as keyboard interrupts occur.

Do the following tasks depending on the user's input:

'S' or 's': sort the display array using the ripple sort routine.

'T' or 't': toggle the case of every character (for example, 'T' becomes 't', 't' becomes 'T' and all non-alphabetic characters stay unchanged) .

'A' or 'a': replace the display array elements with the source elements once again.

'R' or 'r': reverse the elements in the display array.

'Q' or 'q': terminate program execution gracefully.

Note: an interrupt could happen in the middle of displaying the array, so the characters being displayed could change mid-line.

This program is obviously designed to build on previous assignments, so you should reuse code wherever possible.  The primary new feature is the interrupt-driven input.  Instead of reading until you have the entire string (up to NL or CR to stop), read and process each character as it arrives.

Here is the example code:

.data
prompt: .asciiz "SPIM IO Test.\nOnly runs with -mapped_io flag.\nPlease type 6 input lines:\n"
nl:      .asciiz "\n"

      .text
      .globl main
main:
      li $v0 4
      la $a0 prompt
      syscall


# Register usage:
#            s0            loop counter
#            t0            address of recv_ctrl
#            t1            address of recv_buffer
#            t2            address of trans_ctrl
#            t3            address of trans_buffer
#            t4, t5            temporaries
#            t6            char read from input
#            t7            1 => char in t6

      li      $s0, 3            # loop counter

      li       $t0, 0xffff0000      # recv ctrl
      li      $t1, 0xffff0004      # recv buf
      li       $t2, 0xffff0008      # trans ctrl
      li       $t3, 0xffff000c      # trans buf

# First, read and echo 3 lines of input by polling the IO registers, not through
# interrupts:

      mtc0      $0, $12            # Clear IE bit in Status reg to disable interrupts

l1:
      lw      $t4, 0($t0)      # Wait for receiver ready
      and       $t4, $t4, 1
      beq      $t4, 0, l1

      lw      $t6, 0($t1)      # Read character

l2:
      lw      $t4, 0($t2)      # Wait for transmitter ready
      and      $t4, $t4, 1
      beq      $t4, 0, l2

      sw      $t6, 0($t3)      # Write character

      beq      $t6, 0xa, decr      # New line (nl)
      bne      $t6, 0xd, l1      # Carriage return (cr)

decr:
      add      $s0, $s0, -1      # Decrement line counter
      bne      $s0, 0, l1      # If not zero, get another line

# Second, read and echo 3 lines of input by through interrupts:

      mfc0      $t4, $13
      and      $t4, 0xffff00ff      # Clear IP bits in Cause register
      mtc0      $t4, $13

      li      $s0, 3            # loop counter

      li      $t4, 0x2      # Enable device interrupts
      sw      $t4, 0($t0)
      sw      $t4, 0($t2)

      mfc0      $t4, $12      # Enable interrupts and mask in Status reg
      ori      $t4, $t4, 0xff01
      mtc0      $t4, $12


l3:      b      l3            # Loop waiting for interrupts


# Trap handler. Replaces the standard SPIM handler.

      .ktext 0x80000180
      mfc0      $t4, $13      # Get ExcCode field from Cause reg
      srl      $t5, $t4, 2
      and      $t5, $t5, 0x1f      # ExcCode field
      bne      $t5, 0, exception

# An interrupt:
      and      $t5, $t4, 0x800      # Check for IP3 (HW 1)
      beq      $t5, 0, check_trans

# Receiver interrupt:
      lw      $t5, 0($t0)      # Check receiver ready
      and      $t5, $t5, 1
      beq      $t5, 0, no_recv_ready      # Error if receiver is not ready

      lw      $t6, 0($t1)      # Read character
      li      $t7, 1

      beq      $t6, 0xa, decr2      # New line (nl)
      bne      $t6, 0xd, next      # Carriage return (cr)

decr2:
      add      $s0, $s0, -1      # Decrement line counter

next:
      mfc0      $t4, $13      # Get Cause register
      and      $t4, 0xfffff7ff      # Clear IP3 bit
      mtc0      $t4, $13

check_trans:
      beq      $t7, 0, ret_handler      # No char to write yet

      and      $t5, $t4, 0x400      # Check for IP2 (HW 0)
      beq      $t5, 0, check_loop

# Transmitter interrupt:
      lw      $t5, 0($t2)      # Check transmitter ready
      and      $t5, $t5, 1
      beq      $t5, 0, no_trans_ready

      sw      $t6, 0($t3)      # Write character
      li      $t7, 0

      mfc0      $t4, $13      # Get Cause register
      and      $t4, 0xfffffbff      # Clear IP2 bit
      mtc0      $t4, $13

check_loop:
      bne      $s0, 0, ret_handler      # If line counter not zero, get another line

# Done echoing, so terminate program.
      li      $v0, 10
      syscall                  # syscall 10 (exit)

# Return from handler.
ret_handler:
      mfc0      $t4, $12      # Enable interrupts and mask in Status reg
      ori      $t4, $t4, 0xff01
      mtc0      $t4, $12

      eret                  # return to interrupted instruction

exception:
      li      $v0, 4            # Non-interrupt exception
      la      $a0, other_str      # Print message and ignore
      syscall
      b      ret_handler

no_recv_ready:
      li      $v0, 4            # Receiver was not ready after interrupt
      la      $a0, no_recv_str      # Print message and ignore
      syscall
      b      ret_handler

bad_int:
      li      $v0, 4            # Interrupt was not from recv or trans
      la      $a0, bad_int_str      # Print message and ignore
      syscall
      b      ret_handler

no_trans_ready:
      li      $v0, 4            # Transmitter was not ready after interrupt
      la      $a0, no_trans_str      # Print message and ignore
      syscall
      b      ret_handler

      .data
other_str:
      .asciiz "Non-interrupt exception\n"
no_recv_str:
      .asciiz "Receiver not ready\n"
no_trans_str:
      .asciiz "Transmitter not ready\n"
bad_int_str:
      .asciiz "Unknown interrupt\n"
0
Comment
Question by:cyrus_bu
  • 2
4 Comments
 
LVL 16

Expert Comment

by:PaulCaswell
ID: 16702665
Hi cyrus_bu,

Would you please highlight the code that you have done so we can tell what was provided for you. That would make it easier to help you because we can then assume that the rest is correct. If that is not possible, please indicate where you think the problem is and what difficulties you are having with it.

Paul
0
 

Author Comment

by:cyrus_bu
ID: 16705906
i need people who can help me to set up this program!! Thanks.
0
 
LVL 3

Accepted Solution

by:
PeterdLo earned 2000 total points
ID: 16710182
Hi cyrus_bu,

Here is my hint.

Try to understand the following Porgramming definition language and then
write codes based on the description.

Good Luck!

The features of this program are:

1) In the Main Task, use the I/O polling scheme and the memory map I/O to
   transmit characters repeatly.

2) Use an interrupt service routine to receive any input character and also
   echo back this character. This routine will save the input in got_input_data
   and also set the flag of "got_input_flag" to TRUE in order to wake-up the
   Main Task to process the command (for example, 'T' or 't').
----------------------------------------------------------------------------

Main Task

initialization includes

   copy source array element to display array
   set got_input_flag to FALSE
   set the xmit pointer to the 1st element of display array
   enable the receiver and disable the transmitter
   enable the interrupt and turn on the mask
   
do forever loop
   delay 1 sec
   if got_input_flag is TRUE then
      set got_input_flag to FALSE
      select on the got_input_data
         case 'S' or 's'
            Sort the display array
         endcase
         
         case 'T' or 't'
            Toggle the case of every characters in the display array
         endcase
         
         case 'A' or 'a'
            Copy the source array to the display array
         endcase
         
         case 'R' or 'r'
            Reverse the display array elements
         endcase
         
         case 'Q' or 'q'
            Call syscall to terminate this program
         endcase
         
      endselect
   endif
   
   xmit the next char from display array
   if reaches the end of display array then
      reset xmit pointer back to the beginning of display array
   endif
enddo
---------------------------------------------------------------------------------------
Interrupt Service Routine at .ktext 0x80000180

Read the Cause Register

Fetch the exception code from it

if exception code <> 0 then
   enable interrupt and turn on mask (via the Status Register)
   return from interrupt
endif

if the receive interrupt pending bit is set in the Cause Register then
   if the receiver control register shows RECV_READY then
      read receiver data register to got_input_data
      set got_input_flag to TRUE
      poke the transmitter control register for XMIT_READY
      write (echo) the got_input_data to the transmitter data register
      clear the receiver interrupt pending bit
   endif
endif
enable interrupt and turn on mask (via the Status Register)
return from interrupt
---------------------------------------------------------------------------------------

     
0
 

Author Comment

by:cyrus_bu
ID: 16713196
Hi PeterdLo:
    Thanks your comment.
    As the first one: 'S' or 's': sort the display array using the ripple sort routine.
    Could you write this piece of code that i can fully understand the program? I think i will follow your code to finish the
program!! Thanks.
0

Featured Post

Hire Technology Freelancers with Gigs

Work with freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely, and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Moore’s Law has proven itself time and time again since it was first introduced. So what’s next? Will Moore’s law continue to remain relevant, or will new technology take over and bring us the next big advancement in computing?
Exchange administrators are always vigilant about Exchange crashes and disasters that are possible any time. It is quite essential to identify the symptoms of a possible Exchange issue and be prepared with a proper recovery plan. There are multiple…
this video summaries big data hadoop online training demo (http://onlineitguru.com/big-data-hadoop-online-training-placement.html) , and covers basics in big data hadoop .
Despite its rising prevalence in the business world, "the cloud" is still misunderstood. Some companies still believe common misconceptions about lack of security in cloud solutions and many misuses of cloud storage options still occur every day. …
Suggested Courses

873 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question