====== 9. Technické a organizační prostředky (vnější události, výjimky, reálný čas) ======
{{.:lekce09-irq-events.pdf|PDF}}
[[https://gitlab.fel.cvut.cz/b35apo/apo-slides/-/tree/main/09-irq-events|TeX]]
==== Další materiály ====
{{..:..:en:lectures:09:b35apo_lecture09-irq-events.pdf|External Events Processing}}
{{..:..:en:lectures:09:b35apo_lecture09-irq-events.odp|ODP}}
==== Pooling ====
Pooling - čtení seriového portu po odsunutí 1 na LED line:
_start:
lui t0, 0xffffc
ori t0, t0, 0x100
repeat:
addi t1, zero, 0
addi t2, zero, 0
la s0, n
lw s0,0(s0)
cykl1:
slli t1, t1, 1
ori t1, t1, 1
addi t2,t2,1
sw t1, 4(t0)
bne s0,t2, cykl1
move_left:
slli t1, t1, 1
sw t1, 4(t0)
bne t1, zero, move_left
lui t4, 0xffffc
rx_not_ready:
lw t1, 0(t4) # zjisti statu prijimaci fronty
andi t1, t1, 1 # vymaskuj bit READY
beq t1, zero, repeat # pokud neni znak UARTU cekej zkus to znovu
lw t1, 4(t4)
addi t1, t1, -0x30 # odecti acsii hodnotu '0'
la t4, n
sw t1, 0(t4)
j repeat
ebreak
.data
n:
.word 5
==== Využití přerušení ====
_start:
la t0, obsluha_preruseni
csrrw zero, mtvec, t0
la t0, task_control_block
csrrw zero, mscratch, t0
csrrsi zero,mstatus,8 //MIE=1
addi t0, zero, 16 // UART RX
addi t1, zero, 1
sll t1, t1, t0 // bit mask
csrrs zero, mie, t1
lui t0, 0xffffc
.equ SERP_RX_ST_REG_IE_m, 0x2 // Enable Rx ready interrupt
li t1, SERP_RX_ST_REG_IE_m
sw t1, 0(t0)
lui t0, 0xffffc
ori t0, t0, 0x100
repeat:
addi t1, zero, 0
addi t2, zero, 0
la s0, n
lw s0,0(s0)
cykl1:
slli t1, t1, 1
ori t1, t1, 1
addi t2,t2,1
sw t1, 4(t0)
bne s0,t2, cykl1
move_left:
slli t1, t1, 1
sw t1, 4(t0)
bne t1, zero, move_left
j repeat
obsluha_preruseni:
csrrw tp, mscratch, tp // kam si ukladat registry
sw t1, 0(tp) // uloz t1
sw t4, 4(tp) // uloz t4
csrr t1, mcause // is it Rx interrupt?
blt t1, zero, handle_irq // branch to interrupts processing
// ... obsluha jinych vyjimek
j konec_preruseni
handle_irq:
andi t4, t1, 16 // UART RX is the first platform irq
beq t4, zero, konec_preruseni // it is not UART RX
lui t4, 0xffffc
lw t1, 0(t4) # zjisti statu prijimaci fronty
andi t1, t1, 1 # vymaskuj bit READY
beq t1, zero, konec_preruseni # pokud neni znak UARTU chyba ukonci preurseni
lw t1, 4(t4)
addi t1, t1, -0x30 # odecti acsii hodnotu '0'
la t4, n
sw t1, 0(t4)
konec_preruseni:
lw t1, 0(tp) // restore rest of clobberable regs
lw t4, 4(tp)
csrrw tp, mscratch, tp // Swap back TCB to mscratch
mret // Return from exception pc <= mepc
.data
n:
.word 5
task_control_block:
.skip 64
==== Využití přerušení pro procesory MIPS ====
Program irq_test.S pro společnou obsluhu sériového portu a časovače
// Directives to make interresting windows visible
#pragma qtmips show terminal
#pragma qtmips show registers
#pragma qtmips show cop0dock
#pragma qtmips show peripherals
.set SERIAL_PORT_BASE, 0xffffc000
.set SERP_RX_ST_REG_o, 0x00
.set SERP_RX_ST_REG_READY_m, 0x1
.set SERP_RX_ST_REG_IE_m, 0x2
.set SERP_RX_DATA_REG_o, 0x04
.set SERP_TX_ST_REG_o, 0x08
.set SERP_TX_ST_REG_READY_m, 0x1
.set SERP_TX_ST_REG_IE_m, 0x2
.set SERP_TX_DATA_REG_o, 0x0c
.set FREQ_FAST, 0x0800
.set FREQ_SLOW, 0x2000
.set SLOW_CMD, 0x736c6f77
.set FAST_CMD, 0x66617374
.globl _start
.set noat
.set noreorder
.ent _start
.text
_start:
la $t0, irq_entry - 0x180
mtc0 $t0, $15, 1 // set EBase
mfc0 $t1, $9, 0
addi $t1, $0, 50
mtc0 $t1, $11, 0
la $t0, next_counter
sw $t1, 0($t0)
li $21, SERIAL_PORT_BASE
li $20, SERP_RX_ST_REG_IE_m
sw $20, SERP_RX_ST_REG_o($21)
li $20, 0x00008801
mtc0 $20, $12, 0 // set - status
loop:
la $8, rd_ptr
lw $9, 0($8)
lw $10, 4($8)
beq $9, $10, no_new_char
nop
addi $10, $9, 1
andi $10, $10, 0x3f
sw $10, 0($8)
add $8, $9, $8
lbu $9, 8($8)
la $8, received_cmd
lw $10, 0($8)
sll $10, $10, 8
or $10, $10, $9
sw $10, 0($8)
li $11, FAST_CMD
bne $10, $11, not_fast
nop
la $8, frequency
addi $9, $0, FREQ_FAST
sw $9, 0($8)
j no_new_char
nop
not_fast:
li $11, SLOW_CMD
bne $10, $11, no_new_char
nop
la $8, frequency
addi $9, $0, FREQ_SLOW
sw $9, 0($8)
no_new_char:
lui $8,0xffff
ori $8,$8,0xc110
lw $9,0x14($8)
sw $9,0($8)
j loop
nop
irq_entry:
la $26, save_regs
sw $8, 0($26)
sw $9, 4($26)
sw $10, 8($26)
sw $11, 12($26)
mfc0 $26, $13, 0 // Cause
andi $27, $26, 0x00000800
bne $27, $0, rs232_rx_irq
nop
test_timer:
andi $27, $26, 0x00008000
bne $27, $0, timer_irq
nop
irq_end:
la $26, save_regs
lw $8, 0($26)
lw $9, 4($26)
lw $10, 8($26)
lw $11, 12($26)
eret
rs232_rx_irq:
li $8, SERIAL_PORT_BASE
lw $9,0($8)
andi $9,$9,1
beq $9,$0, test_timer
nop
read_next_char:
la $8, rd_ptr
lw $10, 4($8)
addi $9, $10, 1
andi $9, $9, 0x3f
sw $9, 4($8)
lw $11, 0($8)
bne $9, $11, free_buffer
nop
addi $11, $11, 1
andi $11, $11, 0x3f
sw $11, 0($8)
free_buffer:
add $8, $8, $10
li $10, SERIAL_PORT_BASE
lw $9, SERP_RX_DATA_REG_o($10)
sb $9, 8($8) //131
lw $9,0($10)
andi $9,$9,1
bne $9,$0, read_next_char
nop
j test_timer
nop
timer_irq:
la $8, next_counter
lw $9, 0($8)
lw $10, 8($8) //frequency
add $9, $9, $10
sw $9, 0($8)
mtc0 $9, $11, 0
lw $9, 4($8)
xori $9, $9, 1
sw $9, 4($8)
add $10, $0, $0
beq $9, $0, turn_off
nop
addi $10, $0, 0xff
turn_off:
la $8, 0xffffc110
sw $10,4($8)
j irq_end
nop
.data
.org 0x40000
received_cmd:
.word 0
rd_ptr:
.word 0
wr_ptr:
.word 0
buffer:
.word 0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0
save_regs:
.word 0,0,0,0,0,0,0,0
.word 0,0,0,0,0,0,0,0
next_counter:
.word 0
turn_on:
.word 0
frequency:
.word FREQ_FAST