Прерывания и 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 - прямой доступ к памяти.

ArchitectureAssembler2015/18_InterruptsDMA (последним исправлял пользователь FrBrGeorge 2024-06-17 12:52:25)