Merge pull request #1510 from martinling/sgpio-deadline-check

SGPIO deadline check
This commit is contained in:
Michael Ossmann
2024-12-05 11:30:06 -05:00
committed by GitHub
3 changed files with 58 additions and 17 deletions

View File

@ -100,10 +100,10 @@ shadow registers.
There are four key code paths, with the following worst-case timings:
RX, normal: 152 cycles
RX, overrun: 76 cycles
TX, normal: 140 cycles
TX, underrun: 145 cycles
RX, normal: 150 cycles
RX, overrun: 74 cycles
TX, normal: 138 cycles
TX, underrun: 143 cycles
Design
======
@ -239,6 +239,7 @@ The rest of this file is organised as follows:
.equ ERROR_NONE, 0
.equ ERROR_RX_TIMEOUT, 1
.equ ERROR_TX_TIMEOUT, 2
.equ ERROR_MISSED_DEADLINE, 3
// Our slice chain is set up as follows (ascending data age; arrows are reversed for flow):
// L -> F -> K -> C -> J -> E -> I -> A
@ -289,11 +290,17 @@ buf_ptr .req r4
// relying on any assumptions about the timing details of a read over
// the SGPIO to AHB bridge.
// Test the exchange interrupt status, shifting the slice A flag to the carry flag.
// If the flag is already set, we missed our deadline.
ldr int_status, [sgpio_int, #INT_STATUS] // int_status = SGPIO_STATUS_1 // 10
lsr scratch, int_status, #1 // scratch = int_status >> 1 // 1
bcs missed_deadline // if carry: goto missed_deadline // 1
\name\()_int_wait:
// Spin on the exchange interrupt status, shifting the slice A flag to the carry flag.
ldr int_status, [sgpio_int, #INT_STATUS] // int_status = SGPIO_STATUS_1 // 10, twice
lsr scratch, int_status, #1 // scratch = int_status >> 1 // 1, twice
bcc \name\()_int_wait // if !carry: goto int_wait // 3, then 1
// Test the flag again, and if it's still unset, repeat until it's set.
ldr int_status, [sgpio_int, #INT_STATUS] // int_status = SGPIO_STATUS_1 // 10
lsr scratch, int_status, #1 // scratch = int_status >> 1 // 1
bcc \name\()_int_wait // if !carry: goto int_wait // 1
// Clear the interrupt pending bits that were set.
str int_status, [sgpio_int, #INT_CLEAR] // SGPIO_CLR_STATUS_1 = int_status // 8
@ -430,12 +437,31 @@ as follows:
Routine: Uses conditional branches to:
idle tx_loop, wait_loop
idle tx_loop
wait_loop
tx_zeros tx_loop
checked_rollback idle
tx_loop tx_zeros, checked_rollback, rx_loop, wait_loop
wait_loop rx_loop, tx_loop
rx_loop rx_shortfall, checked_rollback, tx_loop, wait_loop
tx_loop tx_zeros
checked_rollback
wait_loop
missed_deadline
rx_loop
wait_loop tx_loop
missed_deadline
rx_loop
missed_deadline <none>
rx_loop checked_rollback
tx_loop
wait_loop
missed_deadline
rx_shortfall
rx_shortfall rx_loop
If any of these routines are reordered, or made longer, you may get an error
@ -578,7 +604,7 @@ checked_rollback:
tx_loop:
// Wait for and clear SGPIO interrupt.
await_sgpio tx // await_sgpio() // 34
await_sgpio tx // await_sgpio() // 32
// Check if there is a mode change request.
// If so, we may need to roll back shortfall stats.
@ -628,7 +654,7 @@ tx_loop:
wait_loop:
// Wait for and clear SGPIO interrupt.
await_sgpio wait // await_sgpio() // 34
await_sgpio wait // await_sgpio() // 32
// Check if there is a mode change request.
// If so, return to idle.
@ -640,10 +666,21 @@ wait_loop:
// Jump to next mode if threshold reached, or back to wait loop start.
jump_next_mode wait // jump_next_mode() // 15
missed_deadline:
// The deadline was missed. Record an error and return to idle state.
error .req r2
mode .req r3
mov error, #ERROR_MISSED_DEADLINE // error = ERROR_MISSED_DEADLINE // 1
mov mode, #MODE_IDLE // mode = MODE_IDLE // 1
str error, [state, #ERROR] // state.error = error // 2
str mode, [state, #ACTIVE_MODE] // state.active_mode = mode // 2
b idle // goto idle // 3
rx_loop:
// Wait for and clear SGPIO interrupt.
await_sgpio rx // await_sgpio() // 34
await_sgpio rx // await_sgpio() // 32
// Check if there is a mode change request.
// If so, we may need to roll back shortfall stats.

View File

@ -428,7 +428,11 @@ static const char* mode_name(uint32_t mode)
static const char* error_name(uint32_t error)
{
const char* error_names[] = {"NONE", "RX_TIMEOUT", "TX_TIMEOUT"};
const char* error_names[] = {
"NONE",
"RX_TIMEOUT",
"TX_TIMEOUT",
"MISSED_DEADLINE"};
const uint32_t num_errors = sizeof(error_names) / sizeof(error_names[0]);
if (error < num_errors) {
return error_names[error];

View File

@ -975,7 +975,7 @@ typedef struct {
uint32_t threshold;
/** Mode which will be switched to when threshold is reached. Possible values are the same as in @ref hackrf_m0_state.requested_mode */
uint32_t next_mode;
/** Error, if any, that caused the M0 to revert to IDLE mode. Possible values are 0 (NONE), 1 (RX_TIMEOUT) and 2(TX_TIMEOUT)*/
/** Error, if any, that caused the M0 to revert to IDLE mode. Possible values are 0 (NONE), 1 (RX_TIMEOUT) 2 (TX_TIMEOUT) or 3 (MISSED_DEADLINE) */
uint32_t error;
} hackrf_m0_state;