From 32c725dd618ceb06433186ed3c8a7993945db791 Mon Sep 17 00:00:00 2001 From: Martin Ling Date: Fri, 24 Dec 2021 08:27:34 +0000 Subject: [PATCH] Add an idle mode for the M0. In the idle mode, the M0 simply waits for a different mode to be set. No SGPIO access is done. One extra cycle is added to both TX code paths, to check whether the M0 should return to the idle loop based on the mode setting. The RX paths are unaffected as the branch to RX is handled first. --- firmware/hackrf_usb/m0_state.h | 5 +++-- firmware/hackrf_usb/sgpio_m0.s | 19 ++++++++++++++----- host/hackrf-tools/src/hackrf_debug.c | 2 +- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/firmware/hackrf_usb/m0_state.h b/firmware/hackrf_usb/m0_state.h index 497f4323..7928dd3f 100644 --- a/firmware/hackrf_usb/m0_state.h +++ b/firmware/hackrf_usb/m0_state.h @@ -32,8 +32,9 @@ struct m0_state { }; enum m0_mode { - M0_MODE_RX = 0, - M0_MODE_TX = 1, + M0_MODE_IDLE = 0, + M0_MODE_RX = 1, + M0_MODE_TX = 2, }; /* Address of m0_state is set in ldscripts. If you change the name of this diff --git a/firmware/hackrf_usb/sgpio_m0.s b/firmware/hackrf_usb/sgpio_m0.s index 5d60bb6c..8df257c3 100644 --- a/firmware/hackrf_usb/sgpio_m0.s +++ b/firmware/hackrf_usb/sgpio_m0.s @@ -68,8 +68,8 @@ There are four key code paths, with the following worst-case timings: RX, normal: 146 cycles RX, overrun: 52 cycles -TX, normal: 131 cycles -TX, underrun: 118 cycles +TX, normal: 132 cycles +TX, underrun: 119 cycles Design ====== @@ -113,8 +113,9 @@ registers and fixed memory addresses. .equ M4_COUNT, 0x08 // Operating modes. -.equ MODE_RX, 0 -.equ MODE_TX, 1 +.equ MODE_IDLE, 0 +.equ MODE_RX, 1 +.equ MODE_TX, 2 // Our slice chain is set up as follows (ascending data age; arrows are reversed for flow): // L -> F -> K -> C -> J -> E -> I -> A @@ -167,6 +168,13 @@ main: str zero, [state, #M0_COUNT] // state.m0_count = zero // 2 str zero, [state, #M4_COUNT] // state.m4_count = zero // 2 +idle: + // Wait for RX or TX mode to be set. + mode .req r0 + ldr mode, [state, #MODE] // mode = state.mode // 2 + cmp mode, #MODE_IDLE // if mode == IDLE: // 1 + beq idle // goto idle // 1 thru, 3 taken + loop: // The worst case timing is assumed to occur when reading the interrupt // status register *just* misses the flag being set - so we include the @@ -208,9 +216,10 @@ loop: mode .req r0 ldr mode, [state, #MODE] // mode = state.mode // 2 - // TX? + // Branch according to mode setting. cmp mode, #MODE_RX // if mode == RX: // 1 beq direction_rx // goto direction_rx // 1 thru, 3 taken + blt idle // elif mode < RX: goto idle // 1 thru, 3 taken direction_tx: diff --git a/host/hackrf-tools/src/hackrf_debug.c b/host/hackrf-tools/src/hackrf_debug.c index 40fa89e4..a36120b3 100644 --- a/host/hackrf-tools/src/hackrf_debug.c +++ b/host/hackrf-tools/src/hackrf_debug.c @@ -378,7 +378,7 @@ int write_register(hackrf_device* device, uint8_t part, } static void print_state(hackrf_m0_state *state) { - const char *mode_names[] = {"RX", "TX"}; + const char *mode_names[] = {"IDLE", "RX", "TX"}; const uint32_t num_modes = sizeof(mode_names) / sizeof(mode_names[0]); printf("M0 state:\n"); printf("Mode: %u (%s)\n",