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 m4_count;
|
||||||
uint32_t num_shortfalls;
|
uint32_t num_shortfalls;
|
||||||
uint32_t longest_shortfall;
|
uint32_t longest_shortfall;
|
||||||
|
uint32_t shortfall_limit;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum m0_mode {
|
enum m0_mode {
|
||||||
|
@ -67,9 +67,9 @@ shadow registers.
|
|||||||
There are four key code paths, with the following worst-case timings:
|
There are four key code paths, with the following worst-case timings:
|
||||||
|
|
||||||
RX, normal: 147 cycles
|
RX, normal: 147 cycles
|
||||||
RX, overrun: 71 cycles
|
RX, overrun: 76 cycles
|
||||||
TX, normal: 133 cycles
|
TX, normal: 133 cycles
|
||||||
TX, underrun: 135 cycles
|
TX, underrun: 140 cycles
|
||||||
|
|
||||||
Design
|
Design
|
||||||
======
|
======
|
||||||
@ -113,6 +113,7 @@ registers and fixed memory addresses.
|
|||||||
.equ M4_COUNT, 0x08
|
.equ M4_COUNT, 0x08
|
||||||
.equ NUM_SHORTFALLS, 0x0C
|
.equ NUM_SHORTFALLS, 0x0C
|
||||||
.equ LONGEST_SHORTFALL, 0x10
|
.equ LONGEST_SHORTFALL, 0x10
|
||||||
|
.equ SHORTFALL_LIMIT, 0x14
|
||||||
|
|
||||||
// Operating modes.
|
// Operating modes.
|
||||||
.equ MODE_IDLE, 0
|
.equ MODE_IDLE, 0
|
||||||
@ -174,6 +175,7 @@ main:
|
|||||||
str zero, [state, #M4_COUNT] // state.m4_count = zero // 2
|
str zero, [state, #M4_COUNT] // state.m4_count = zero // 2
|
||||||
str zero, [state, #NUM_SHORTFALLS] // state.num_shortfalls = 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, #LONGEST_SHORTFALL] // state.longest_shortfall = zero // 2
|
||||||
|
str zero, [state, #SHORTFALL_LIMIT] // state.shortfall_limit = zero // 2
|
||||||
|
|
||||||
idle:
|
idle:
|
||||||
// Wait for RX or TX mode to be set.
|
// Wait for RX or TX mode to be set.
|
||||||
@ -309,8 +311,19 @@ extend_shortfall:
|
|||||||
blt loop // goto loop // 1 thru, 3 taken
|
blt loop // goto loop // 1 thru, 3 taken
|
||||||
str length, [state, #LONGEST_SHORTFALL] // state.longest_shortfall = length // 2
|
str length, [state, #LONGEST_SHORTFALL] // state.longest_shortfall = length // 2
|
||||||
|
|
||||||
// Return to main loop.
|
// Is this shortfall long enough to trigger a timeout?
|
||||||
b loop // goto loop // 3
|
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:
|
direction_rx:
|
||||||
|
|
||||||
|
@ -390,6 +390,7 @@ static void print_state(hackrf_m0_state *state) {
|
|||||||
printf("M4 count: %u bytes\n", state->m4_count);
|
printf("M4 count: %u bytes\n", state->m4_count);
|
||||||
printf("Number of shortfalls: %u\n", state->num_shortfalls);
|
printf("Number of shortfalls: %u\n", state->num_shortfalls);
|
||||||
printf("Longest shortfall: %u bytes\n", state->longest_shortfall);
|
printf("Longest shortfall: %u bytes\n", state->longest_shortfall);
|
||||||
|
printf("Shortfall limit: %u bytes\n", state->shortfall_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void usage() {
|
static void usage() {
|
||||||
|
@ -167,6 +167,8 @@ typedef struct {
|
|||||||
uint32_t num_shortfalls;
|
uint32_t num_shortfalls;
|
||||||
/** Longest shortfall. */
|
/** Longest shortfall. */
|
||||||
uint32_t longest_shortfall;
|
uint32_t longest_shortfall;
|
||||||
|
/** Shortfall limit in bytes. */
|
||||||
|
uint32_t shortfall_limit;
|
||||||
} hackrf_m0_state;
|
} hackrf_m0_state;
|
||||||
|
|
||||||
struct hackrf_device_list {
|
struct hackrf_device_list {
|
||||||
|
Reference in New Issue
Block a user