Прерывания и DMA
- Прерывание — сигнал, сообщающий процессору о наступлении какого-либо внешнего события.
- асинхронны
- позволяют освободить cpu от активного ожидания.
- Проблемы возникающие при обработке прерываний:
- распознавание природы прерывания
- прерывания важны
- прерывания нужно быстро обработать
- Маскирование прерываний.
- Прерывания, в зависимости от возможности запрета, делятся на:
- маскируемые — прерывания, которые можно запрещать установкой соответствующих битов в регистре маскирования прерываний;
- немаскируемые — обрабатываются всегда, независимо от запретов на другие прерывания.
- Прерывания, в зависимости от возможности запрета, делятся на:
- Приоритеты обслуживания прерываний.
- Прерывания в Mars.
- Микропроцессор имеет входы прерывания.
- Каждый запрос прерывания может индивидуально маскироваться(включаются при 1) соответствующими разрядами поля Int Mask в регистре Status. Все запросы прерываний маскируются при установке значения бита IЕ=1 в регистра Status.
Все прерывания обнаруживаются процессором. При поступлении сигналов прерывания процессор сбрасывает(0) биты поля ExcCode регистра Cause. При этом содержимое поля IP регистра Cause будет показывать, на какие входы поступили сигналы прерывания. При поступлении нескольких запросов прерывания приоритет их обслуживания должен задаваться программой-обработчиком.
- Сигнал прерывания продолжает восприниматься процессором после начала обработки прерывания. Чтобы избежать повторного обслуживания запроса, программа-обработчик должна выдать сообщение соответствующему внешнему устройству на снятие запроса прерывания или произвести маскирование запроса путем сброса в 0 соответствующего бита IMx регистре Status.
- Пример:
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"
- DMA - прямой доступ к памяти.