Commit c67b6164 authored by Roberto Hexsel's avatar Roberto Hexsel

improved UART_rx_irq handler

parent 0def435e
Pipeline #4256 skipped
......@@ -95,34 +95,36 @@ Ud: .comm rx_queue 16 # reception queue and pointers
# [4]=$ra, [5]=$a0, [6]=$a1, [7]=$a2, [8]=$a3
UARTinterr:
lui $k0, %hi(HW_uart_addr)
ori $k0, $k0, %lo(HW_uart_addr)
lw $k1, 0($k0) # Read status, remove interrupt request
lui $k0, %hi(_uart_buff)
lui $k0, %hi(_uart_buff) # get buffer's address
ori $k0, $k0, %lo(_uart_buff)
sw $k1, 0*4($k0) # and save UART status to memory
sw $a0, 5*4($k0) # save registers $a0,$a1, others?
sw $a1, 6*4($k0)
lui $a0, %hi(HW_uart_addr)# get device's address
ori $a0, $a0, %lo(HW_uart_addr)
lw $k1, 0($a0) # Read status, remove interrupt request
nop
sw $k1, 0*4($k0) # and save UART status to memory
#----------------------------------
# while you are developing the complete handler,
# uncomment the line below and comment out lines up to UARTret
# .include "../tests/handlerUART.s"
#----------------------------------
andi $a0, $k1, UART_rx_irq # Is this reception?
beq $a0, $zero, UARTret # no, ignore it and return
andi $a1, $k1, UART_rx_irq # Is this reception?
beq $a1, $zero, UARTret # no, ignore it and return
nop
lui $a0, %hi(HW_uart_addr)
ori $a0, $a0, %lo(HW_uart_addr)
lw $a1, 4($a0) # Read data
# handle reception
lw $a1, 4($a0) # Read data from device
nop # and store it to UART's buffer
sw $a1, 4($k0) # and return from interrupt
sw $a1, 2*4($k0) # and return from interrupt
addiu $a1, $zero, 1
sw $a1, 8($k0) # Signal new arrival
sw $a1, 3*4($k0) # Signal new arrival
UARTret:
lw $a1, 6*4($k0) # restore registers $a0,$a1, others?
lw $a0, 5*4($k0)
......
......@@ -64,27 +64,25 @@ int main(void) { // receive a string through the UART serial interface
ctrl.rts = 0; // make RTS=0 to hold remote unit
ctrl.intTX = 0;
ctrl.intRX = 0;
ctrl.speed = 1; // operate at 1/2 of the highest data rate
ctrl.speed = 2; // operate at 1/4 of the highest data rate
uart->cs.ctl = ctrl; // initizlize UART
// handler sets flag=bfr[3] to 1 after new character is received;
// this program resets the flag on fetching a new character from buffer
bfr[3] = 0; // reset flag
ctrl.ign = 0;
ctrl.rts = 1; // make RTS=1 so RemoteUnit starts its transmission
ctrl.intTX = 0;
ctrl.intRX = 1; // do generate interrupts on RXbuffer full
ctrl.speed = 1; // operate at 1/2 of the highest data rate
ctrl.speed = 2; // operate at 1/4 of the highest data rate
uart->cs.ctl = ctrl;
// handler sets flag=bfr[2] to 1 after new character is received;
// this program resets the flag on fetching a new character from buffer
c = (char)bfr[2]; // interrupt handler's flag
do {
while ( (c = (char)bfr[2]) == 0 )
while ( (c = (char)bfr[3]) == 0 )
{}; // nothing new
c = (char)bfr[1]; // get new character
bfr[2] = 0; // and reset flag
c = (char)bfr[2]; // get new character
bfr[3] = 0; // and reset flag
to_stdout( (int)c );
} while (c != '\0'); // end of string?
......
......@@ -1967,6 +1967,9 @@ begin
i_stall := '0'; -- do not stall
i_nullify := TRUE; -- nullify instructions in IF,RF
-- when processor goes into exception-level, IRQs are ignored,
-- hence disabled
when exSYSCALL | exBREAK => -- SYSCALL, BREAK
i_stall := '0';
......@@ -1977,7 +1980,6 @@ begin
end if;
newSTATUS(STATUS_EXL) := '1'; -- at exception level
newSTATUS(STATUS_UM) := '0'; -- enter kernel mode
-- newSTATUS(STATUS_IE) := '0'; -- disable interrupts
i_update := '1';
i_update_r := cop0reg_STATUS;
i_stall := '0'; -- do not stall
......@@ -1996,7 +1998,6 @@ begin
ExcCode <= cop0code_Tr;
newSTATUS(STATUS_EXL) := '1'; -- at exception level
newSTATUS(STATUS_UM) := '0'; -- enter kernel mode
-- newSTATUS(STATUS_IE) := '0'; -- disable interrupts
i_update := '1';
i_update_r := cop0reg_STATUS;
i_stall := '0';
......@@ -2026,7 +2027,6 @@ begin
when exOvfl => -- OVERFLOW happened one cycle earlier
newSTATUS(STATUS_EXL) := '1'; -- at exception level
-- newSTATUS(STATUS_IE) := '0'; -- disable interrupts
exception_taken <= '1';
i_update := '1';
i_update_r := cop0reg_STATUS;
......@@ -2044,7 +2044,6 @@ begin
when IFaddressError => -- fetch from UNALIGNED ADDRESS
newSTATUS(STATUS_EXL) := '1'; -- at exception level
newSTATUS(STATUS_IE) := '0'; -- disable interrupts
exception_taken <= '1';
i_update := '1';
i_update_r := cop0reg_STATUS;
......@@ -2058,7 +2057,6 @@ begin
when MMaddressErrorLD | MMaddressErrorST =>
-- load/store from/to UNALIGNED ADDRESS
newSTATUS(STATUS_EXL) := '1'; -- at exception level
newSTATUS(STATUS_IE) := '0'; -- disable interrupts
exception_taken <= '1';
i_update := '1';
i_update_r := cop0reg_STATUS;
......@@ -2096,7 +2094,6 @@ begin
is_delayslot <= '0';
end if;
newSTATUS(STATUS_EXL) := '1'; -- at exception level
-- newSTATUS(STATUS_IE) := '0'; -- disable interrupts
i_update := '1';
i_update_r := cop0reg_STATUS;
i_epc_update := '0';
......@@ -2119,7 +2116,6 @@ begin
is_delayslot <= MM_is_delayslot;
end if;
newSTATUS(STATUS_EXL) := '1'; -- at exception level
-- newSTATUS(STATUS_IE) := '0'; -- disable interrupts
i_update := '1';
i_update_r := cop0reg_STATUS;
i_epc_update := '0';
......@@ -2135,7 +2131,6 @@ begin
is_delayslot <= '0';
end if;
newSTATUS(STATUS_EXL) := '1'; -- at exception level
-- newSTATUS(STATUS_IE) := '0'; -- disable interrupts
i_update := '1';
i_update_r := cop0reg_STATUS;
i_epc_update := '0';
......@@ -2161,7 +2156,6 @@ begin
is_delayslot <= MM_is_delayslot;
end if;
newSTATUS(STATUS_EXL) := '1'; -- at exception level
-- newSTATUS(STATUS_IE) := '0'; -- disable interrupts
i_update := '1';
i_update_r := cop0reg_STATUS;
i_epc_update := '0';
......@@ -2175,7 +2169,6 @@ begin
ExcCode <= cop0code_DBE;
end if;
newSTATUS(STATUS_EXL) := '1'; -- at exception level
newSTATUS(STATUS_IE) := '0'; -- disable interrupts
i_update := '1';
i_update_r := cop0reg_STATUS;
i_nullify := TRUE; -- nullify instructions in IF,RF,EX
......@@ -2187,7 +2180,6 @@ begin
interrupt_taken <= '1';
newSTATUS(STATUS_UM) := '0'; -- enter kernel mode
newSTATUS(STATUS_EXL) := '1'; -- at exception level
newSTATUS(STATUS_IE) := '0'; -- disable interrupts
ExcCode <= cop0code_Int;
i_update := '1';
i_update_r := cop0reg_STATUS;
......@@ -2239,9 +2231,9 @@ begin
update_reg <= i_update_r;
if is_exception = exMTC0 and MM_cop0_reg = cop0reg_EPC then
epc_update <= i_epc_update;
epc_update <= i_epc_update;
else
epc_update <= i_epc_update OR STATUS(STATUS_EXL);
epc_update <= i_epc_update OR STATUS(STATUS_EXL);
end if;
epc_source <= i_epc_source;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment