Различия между версиями 3 и 4
Версия 3 от 2016-03-22 22:14:24
Размер: 3127
Редактор: ali
Комментарий:
Версия 4 от 2016-03-24 03:55:23
Размер: 5132
Редактор: ali
Комментарий:
Удаления помечены так. Добавления помечены так.
Строка 20: Строка 20:
   {{{#!highlight nasm

.text
 .globl main
main:
 mfc0 $a0, $12 # read from the status register
 ori $a0, 0xff11 # enable all interrupts
 mtc0 $a0, $12 # write back to the status register

 lui $t0, 0xFFFF # $t0 = 0xFFFF0000;
 ori $a0, $0, 2 # enable keyboard interrupt
 sw $a0, 0($t0) # write back to 0xFFFF0000;
  
here:
 j here # stay here forever
 nop
 li $v0, 10 # exit,if it ever comes here
 syscall


.ktext 0x80000180 # kernel code starts here
 
 .set noat # tell the assembler not to use $at, not needed here actually, just to illustrae the use of the .set noat
 move $k1, $at # save $at. User prorams are not supposed to touch $k0 and $k1
 .set at # tell the assembler okay to use $at
 
 sw $v0, s1 # We need to use these registers
 sw $a0, s2 # not using the stack because the interrupt might be triggered by a memory reference
     # using a bad value of the stack pointer

 mfc0 $k0, $13 # Cause register
 srl $a0, $k0, 2 # Extract ExcCode Field
 andi $a0, $a0, 0x1f

    bne $a0, $zero, kdone # Exception Code 0 is I/O. Only processing I/O here
    nop
    
 lui $v0, 0xFFFF # $t0 = 0xFFFF0000;
 lw $a0, 4($v0) # get the input key
 li $v0,1 # print it here.
     # Note: interrupt routine should return very fast, so doing something like
     # print is NOT a good practice, actually!
 syscall

 li $v0,4 # print the new line
 la $a0, new_line
 syscall

kdone:
 mtc0 $0, $13 # Clear Cause register
 mfc0 $k0, $12 # Set Status register
 andi $k0, 0xfffd # clear EXL bit
 ori $k0, 0x01 # Interrupts enabled
 mtc0 $k0, $12 # write back to status
    
    lw $v0, s1 # Restore other registers
 lw $a0, s2

 .set noat # tell the assembler not to use $at
 move $at, $k1 # Restore $at
 .set at # tell the assembler okay to use $at

 eret # return to EPC
    nop

.kdata # kernel data
s1: .word 10
s2: .word 11
new_line:
 .asciiz "\n"

}}}

Прерывания и DMA

  1. Прерывание — сигнал, сообщающий процессору о наступлении какого-либо внешнего события.
    • асинхронны
    • позволяют освободить cpu от активного ожидания.
  2. Проблемы возникающие при обработке прерываний:
    • распознавание природы прерывания
    • прерывания важны
    • прерывания нужно быстро обработать
  3. Маскирование прерываний.
    • Прерывания, в зависимости от возможности запрета, делятся на:
      • маскируемые — прерывания, которые можно запрещать установкой соответствующих битов в регистре маскирования прерываний;
      • немаскируемые — обрабатываются всегда, независимо от запретов на другие прерывания.
  4. Приоритеты обслуживания прерываний.
  5. Прерывания в Mars.
    1. Микропроцессор имеет входы прерывания.
    2. Каждый запрос прерывания может индивидуально маскироваться(включаются при 1) соответствующими разрядами поля Int Mask в регистре Status. Все запросы прерываний маскируются при установке значения бита IЕ=1 в регистра Status.
    3. Все прерывания обнаруживаются процессором. При поступлении сигналов прерывания процессор сбрасывает(0) биты поля ExcCode регистра Cause. При этом содержимое поля IP регистра Cause будет показывать, на какие входы поступили сигналы прерывания. При поступлении нескольких запросов прерывания приоритет их обслуживания должен задаваться программой-обработчиком.

    4. Сигнал прерывания продолжает восприниматься процессором после начала обработки прерывания. Чтобы избежать повторного обслуживания запроса, программа-обработчик должна выдать сообщение соответствующему внешнему устройству на снятие запроса прерывания или произвести маскирование запроса путем сброса в 0 соответствующего бита IMx регистре Status.
  6. Пример:
       1 .text
       2         .globl main
       3 main:
       4         mfc0 $a0, $12                   # read from the status register
       5         ori $a0, 0xff11                 # enable all interrupts
       6         mtc0 $a0, $12                   # write back to the status register
       7 
       8         lui $t0, 0xFFFF                 # $t0 = 0xFFFF0000;
       9         ori $a0, $0, 2                          # enable keyboard interrupt
      10         sw $a0, 0($t0)                  # write back to 0xFFFF0000;
      11                 
      12 here: 
      13         j here                          # stay here forever
      14         nop
      15         li $v0, 10                              # exit,if it ever comes here
      16         syscall
      17 
      18 
      19 .ktext 0x80000180                               # kernel code starts here
      20         
      21         .set noat                               # tell the assembler not to use $at, not needed here actually, just to illustrae the use of the .set noat
      22         move $k1, $at                   # save $at. User prorams are not supposed to touch $k0 and $k1 
      23         .set at                         # tell the assembler okay to use $at
      24         
      25         sw $v0, s1                              # We need to use these registers
      26         sw $a0, s2                              # not using the stack because the interrupt might be triggered by a memory reference 
      27                                         # using a bad value of the stack pointer
      28 
      29         mfc0 $k0, $13                   # Cause register
      30         srl $a0, $k0, 2                         # Extract ExcCode Field
      31         andi $a0, $a0, 0x1f
      32 
      33     bne $a0, $zero, kdone                       # Exception Code 0 is I/O. Only processing I/O here
      34     nop
      35     
      36         lui $v0, 0xFFFF                 # $t0 = 0xFFFF0000;
      37         lw $a0, 4($v0)                  # get the input key
      38         li $v0,1                                # print it here. 
      39                                         # Note: interrupt routine should return very fast, so doing something like 
      40                                         # print is NOT a good practice, actually!
      41         syscall
      42 
      43         li $v0,4                                # print the new line
      44         la $a0, new_line
      45         syscall
      46 
      47 kdone:
      48         mtc0 $0, $13                            # Clear Cause register
      49         mfc0 $k0, $12                   # Set Status register
      50         andi $k0, 0xfffd                        # clear EXL bit
      51         ori  $k0, 0x01                          # Interrupts enabled
      52         mtc0 $k0, $12                   # write back to status
      53     
      54     lw $v0, s1                          # Restore other registers
      55         lw $a0, s2
      56 
      57         .set noat                               # tell the assembler not to use $at
      58         move $at, $k1                   # Restore $at
      59         .set at                                 # tell the assembler okay to use $at
      60 
      61         eret                                    # return to EPC
      62     nop
      63 
      64 .kdata                                  # kernel data
      65 s1:     .word 10
      66 s2:     .word 11
      67 new_line: 
      68         .asciiz "\n"
    
  7. DMA - прямой доступ к памяти.

ArchitectureAssembler/18_InterruptsDMA (последним исправлял пользователь ali 2016-03-24 03:55:23)