Add a shortfall length limit.
This limit allows implementing a timeout: if a TX underrun or RX overrun continues for the specified number of bytes, the M0 will revert to idle. A setting of zero disables the limit. This change adds 5 cycles to the TX & RX shortfall paths, to check if a limit is set and to check the shortfall length against the limit.
This commit is contained in:
@ -31,6 +31,7 @@ struct m0_state {
|
||||
uint32_t m4_count;
|
||||
uint32_t num_shortfalls;
|
||||
uint32_t longest_shortfall;
|
||||
uint32_t shortfall_limit;
|
||||
};
|
||||
|
||||
enum m0_mode {
|
||||
|
@ -67,9 +67,9 @@ shadow registers.
|
||||
There are four key code paths, with the following worst-case timings:
|
||||
|
||||
RX, normal: 147 cycles
|
||||
RX, overrun: 71 cycles
|
||||
RX, overrun: 76 cycles
|
||||
TX, normal: 133 cycles
|
||||
TX, underrun: 135 cycles
|
||||
TX, underrun: 140 cycles
|
||||
|
||||
Design
|
||||
======
|
||||
@ -113,6 +113,7 @@ registers and fixed memory addresses.
|
||||
.equ M4_COUNT, 0x08
|
||||
.equ NUM_SHORTFALLS, 0x0C
|
||||
.equ LONGEST_SHORTFALL, 0x10
|
||||
.equ SHORTFALL_LIMIT, 0x14
|
||||
|
||||
// Operating modes.
|
||||
.equ MODE_IDLE, 0
|
||||
@ -174,6 +175,7 @@ main:
|
||||
str zero, [state, #M4_COUNT] // state.m4_count = zero // 2
|
||||
str zero, [state, #NUM_SHORTFALLS] // state.num_shortfalls = zero // 2
|
||||
str zero, [state, #LONGEST_SHORTFALL] // state.longest_shortfall = zero // 2
|
||||
str zero, [state, #SHORTFALL_LIMIT] // state.shortfall_limit = zero // 2
|
||||
|
||||
idle:
|
||||
// Wait for RX or TX mode to be set.
|
||||
@ -309,8 +311,19 @@ extend_shortfall:
|
||||
blt loop // goto loop // 1 thru, 3 taken
|
||||
str length, [state, #LONGEST_SHORTFALL] // state.longest_shortfall = length // 2
|
||||
|
||||
// Return to main loop.
|
||||
b loop // goto loop // 3
|
||||
// Is this shortfall long enough to trigger a timeout?
|
||||
limit .req r1
|
||||
ldr limit, [state, #SHORTFALL_LIMIT] // limit = state.shortfall_limit // 2
|
||||
cmp limit, #0 // if limit == 0: // 1
|
||||
beq loop // goto loop // 1 thru, 3 taken
|
||||
cmp length, limit // if length < limit: // 1
|
||||
blt loop // goto loop // 1 thru, 3 taken
|
||||
|
||||
// If so, reset mode to idle and return to idle loop.
|
||||
mode .req r3
|
||||
mov mode, #MODE_IDLE // mode = MODE_IDLE // 1
|
||||
str mode, [state, #MODE] // state.mode = mode // 2
|
||||
b idle // goto idle // 3
|
||||
|
||||
direction_rx:
|
||||
|
||||
|
@ -390,6 +390,7 @@ static void print_state(hackrf_m0_state *state) {
|
||||
printf("M4 count: %u bytes\n", state->m4_count);
|
||||
printf("Number of shortfalls: %u\n", state->num_shortfalls);
|
||||
printf("Longest shortfall: %u bytes\n", state->longest_shortfall);
|
||||
printf("Shortfall limit: %u bytes\n", state->shortfall_limit);
|
||||
}
|
||||
|
||||
static void usage() {
|
||||
|
@ -167,6 +167,8 @@ typedef struct {
|
||||
uint32_t num_shortfalls;
|
||||
/** Longest shortfall. */
|
||||
uint32_t longest_shortfall;
|
||||
/** Shortfall limit in bytes. */
|
||||
uint32_t shortfall_limit;
|
||||
} hackrf_m0_state;
|
||||
|
||||
struct hackrf_device_list {
|
||||
|
Reference in New Issue
Block a user