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
_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
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