Skip to content

Commit b33bd77

Browse files
committed
Change rx interrupt implementation to avoid deadlocks
1 parent 5d195ef commit b33bd77

File tree

1 file changed

+37
-33
lines changed

1 file changed

+37
-33
lines changed

src/cpu/controller.mlog.jinja

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,8 @@ end_slow_init:
167167

168168
# UARTs
169169
set uart_flags 0
170-
set uart_rx_was_non_empty 0
171-
set uart_tx_empty_ptrs 0xffffffff
170+
set uart_rx_interrupt_ptrs 0xffffffff
171+
set uart_tx_interrupt_ptrs 0xffffffff
172172

173173
op add ret @counter 1
174174
jump update_uart_flags always
@@ -383,56 +383,60 @@ update_uart_flags__loop:
383383
read _tx_write _uart {{UART_TX_WRITE}}
384384

385385
op shl _interrupt_mask 1 _uart_shift
386-
op not _interrupt_mask_inv _interrupt_mask
386+
387+
op mul _ptr_shift _uart_shift 8
388+
389+
op shl _clear_ptr_mask 0xff _ptr_shift
390+
op not _clear_ptr_mask _clear_ptr_mask
387391

388392
# RX FIFO became non-empty
389393

390394
# don't generate interrupt if rx is empty
391-
op notEqual _rx_is_non_empty _rx_read _rx_write
392-
jump update_uart_flags__no_rx_interrupt equal _rx_is_non_empty 0
395+
# in that case, set ptr to an invalid value so we don't mask a later interrupt here
396+
set _new_ptr 0xff
397+
jump update_uart_flags__set_rx_ptr equal _rx_read _rx_write
393398

394-
# don't generate interrupt if rx wasn't empty last time we checked
395-
op and _rx_was_non_empty uart_rx_was_non_empty _interrupt_mask
396-
jump update_uart_flags__no_rx_interrupt notEqual _rx_was_non_empty 0
399+
# don't generate interrupt if this is the last ptr we generated one at
400+
set _new_ptr _rx_read
401+
402+
op shr _prev_ptr uart_rx_interrupt_ptrs _ptr_shift
403+
op and _prev_ptr _prev_ptr 0xff
404+
405+
jump update_uart_flags__done_rx equal _prev_ptr _new_ptr
397406

398407
# generate interrupt
399408
op or uart_flags uart_flags _interrupt_mask
400409

401-
update_uart_flags__no_rx_interrupt:
402-
op shl _rx_is_non_empty _rx_is_non_empty _uart_shift
403-
op and uart_rx_was_non_empty uart_rx_was_non_empty _interrupt_mask_inv
404-
op or uart_rx_was_non_empty uart_rx_was_non_empty _rx_is_non_empty
410+
update_uart_flags__set_rx_ptr:
411+
op shl _new_ptr _new_ptr _ptr_shift
405412

406-
# TX FIFO became empty
413+
op and uart_rx_interrupt_ptrs uart_rx_interrupt_ptrs _clear_ptr_mask
414+
op or uart_rx_interrupt_ptrs uart_rx_interrupt_ptrs _new_ptr
415+
update_uart_flags__done_rx:
407416

408-
op mul _ptr_shift _uart_shift 8
417+
# TX FIFO became empty
409418

410419
# don't generate interrupt if tx is not empty
411-
jump update_uart_flags__no_tx_interrupt notEqual _tx_read _tx_write
420+
# in that case, set ptr to an invalid value so we don't mask a later interrupt here
421+
set _new_ptr 0xff
422+
jump update_uart_flags__set_tx_ptr notEqual _tx_read _tx_write
412423

413-
# don't generate interrupt if this is the last wptr we generated one at
414-
op shr _last_tx_write uart_tx_empty_ptrs _ptr_shift
415-
op and _last_tx_write _last_tx_write 0xff
416-
jump update_uart_flags__done_tx equal _last_tx_write _tx_write
424+
# don't generate interrupt if this is the last ptr we generated one at
425+
set _new_ptr _tx_write
417426

418-
# generate interrupt
419-
op or uart_flags uart_flags _interrupt_mask
427+
op shr _prev_ptr uart_tx_interrupt_ptrs _ptr_shift
428+
op and _prev_ptr _prev_ptr 0xff
420429

421-
# save this wptr
422-
set _last_tx_write _tx_write
423-
jump update_uart_flags__set_tx_empty_ptr always
430+
jump update_uart_flags__done_tx equal _prev_ptr _new_ptr
424431

425-
update_uart_flags__no_tx_interrupt:
426-
# if not empty, set to an invalid value so we don't mask the interrupt when it becomes empty
427-
set _last_tx_write 0xff
432+
# generate interrupt
433+
op or uart_flags uart_flags _interrupt_mask
428434

429-
update_uart_flags__set_tx_empty_ptr:
430-
op shl _mask 0xff _ptr_shift
431-
op not _mask _mask
432-
op and uart_tx_empty_ptrs uart_tx_empty_ptrs _mask
435+
update_uart_flags__set_tx_ptr:
436+
op shl _new_ptr _new_ptr _ptr_shift
433437

434-
op shl _last_tx_write _last_tx_write _ptr_shift
435-
op or uart_tx_empty_ptrs uart_tx_empty_ptrs _last_tx_write
438+
op and uart_tx_interrupt_ptrs uart_tx_interrupt_ptrs _clear_ptr_mask
439+
op or uart_tx_interrupt_ptrs uart_tx_interrupt_ptrs _new_ptr
436440
update_uart_flags__done_tx:
437441

438442
# next UART

0 commit comments

Comments
 (0)