Replace M0 state offset field with a byte count.

Instead of this count wrapping at the buffer size, it now increments
continuously. The offset within the buffer is now obtained from the
lower bits of the count.

This makes it possible to keep track of the total number of bytes
transferred by the M0 core.

The count will wrap at 2^32 bytes, which at 20Msps will occur every
107 seconds.
This commit is contained in:
Martin Ling
2021-12-22 02:29:41 +00:00
parent be060ab753
commit 21dabc920f
6 changed files with 27 additions and 24 deletions

View File

@ -26,7 +26,7 @@
#include <usb_request.h>
struct m0_state {
uint32_t offset;
uint32_t m0_count;
uint32_t tx;
};

View File

@ -66,8 +66,8 @@ shadow registers.
There are two key code paths, with the following worst-case timings:
RX: 140 cycles
TX: 125 cycles
RX: 141 cycles
TX: 126 cycles
Design
======
@ -105,7 +105,7 @@ registers and fixed memory addresses.
.equ STATE_BASE, 0x20007000
// Offsets into the state structure.
.equ OFFSET, 0x00
.equ M0_COUNT, 0x00
.equ TX, 0x04
// Our slice chain is set up as follows (ascending data age; arrows are reversed for flow):
@ -128,7 +128,8 @@ buf_base .req r12
buf_mask .req r11
sgpio_data .req r7
sgpio_int .req r6
buf_ptr .req r5
count .req r5
buf_ptr .req r4
// Entry point. At this point, the libopencm3 startup code has set things up as
// normal; .data and .bss are initialised, the stack is set up, etc. However,
@ -151,7 +152,7 @@ main:
// Initialise state.
zero .req r0
mov zero, #0 // zero = 0 // 1
str zero, [state, #OFFSET] // state.offset = zero // 2
str zero, [state, #M0_COUNT] // state.m0_count = zero // 2
str zero, [state, #TX] // state.tx = zero // 2
loop:
@ -186,7 +187,9 @@ loop:
str int_status, [sgpio_int, #INT_CLEAR] // SGPIO_CLR_STATUS_1 = int_status // 8
// ... and grab the address of the buffer segment we want to write to / read from.
ldr buf_ptr, [state, #OFFSET] // buf_ptr = state.offset // 2
ldr count, [state, #M0_COUNT] // count = state.m0_count // 2
mov buf_ptr, buf_mask // buf_ptr = buf_mask // 1
and buf_ptr, count // buf_ptr &= count // 1
add buf_ptr, buf_base // buf_ptr += buf_base // 1
tx .req r0
@ -229,14 +232,11 @@ direction_rx:
stm buf_ptr!, {r0-r3} // buf_ptr[0:16] = r0-r3; buf_ptr += 16 // 5
done:
offset .req r0
// Finally, update the count...
add count, #32 // count += 32 // 1
// Finally, update the buffer location...
mov offset, buf_mask // offset = buf_mask // 1
and offset, buf_ptr // offset &= buf_ptr // 1
// ... and store the new position.
str offset, [state, #OFFSET] // state.offset = offset // 2
// ... and store the new count.
str count, [state, #M0_COUNT] // state.m0_count = count // 2
b loop // goto loop // 3

View File

@ -101,8 +101,9 @@ void sweep_mode(uint32_t seq) {
baseband_streaming_enable(&sgpio_config);
while (transceiver_request.seq == seq) {
uint32_t m0_offset = m0_state.m0_count & USB_BULK_BUFFER_MASK;
// Set up IN transfer of buffer 0.
if ( m0_state.offset >= 16384 && phase == 1) {
if ( m0_offset >= 16384 && phase == 1) {
transfer = true;
buffer = &usb_bulk_buffer[0x0000];
phase = 0;
@ -110,7 +111,7 @@ void sweep_mode(uint32_t seq) {
}
// Set up IN transfer of buffer 1.
if ( m0_state.offset < 16384 && phase == 0) {
if ( m0_offset < 16384 && phase == 0) {
transfer = true;
buffer = &usb_bulk_buffer[0x4000];
phase = 1;

View File

@ -296,7 +296,7 @@ void transceiver_startup(const transceiver_mode_t mode) {
activate_best_clock_source();
hw_sync_enable(_hw_sync_mode);
m0_state.offset = 0;
m0_state.m0_count = 0;
}
usb_request_status_t usb_vendor_request_set_transceiver_mode(
@ -342,8 +342,9 @@ void rx_mode(uint32_t seq) {
baseband_streaming_enable(&sgpio_config);
while (transceiver_request.seq == seq) {
uint32_t m0_offset = m0_state.m0_count & USB_BULK_BUFFER_MASK;
// Set up IN transfer of buffer 0.
if (16384 <= m0_state.offset && 1 == phase) {
if (16384 <= m0_offset && 1 == phase) {
usb_transfer_schedule_block(
&usb_endpoint_bulk_in,
&usb_bulk_buffer[0x0000],
@ -353,7 +354,7 @@ void rx_mode(uint32_t seq) {
phase = 0;
}
// Set up IN transfer of buffer 1.
if (16384 > m0_state.offset && 0 == phase) {
if (16384 > m0_offset && 0 == phase) {
usb_transfer_schedule_block(
&usb_endpoint_bulk_in,
&usb_bulk_buffer[0x4000],
@ -384,8 +385,9 @@ void tx_mode(uint32_t seq) {
baseband_streaming_enable(&sgpio_config);
while (transceiver_request.seq == seq) {
uint32_t m0_offset = m0_state.m0_count & USB_BULK_BUFFER_MASK;
// Set up OUT transfer of buffer 0.
if (16384 <= m0_state.offset && 1 == phase) {
if (16384 <= m0_offset && 1 == phase) {
usb_transfer_schedule_block(
&usb_endpoint_bulk_out,
&usb_bulk_buffer[0x0000],
@ -395,7 +397,7 @@ void tx_mode(uint32_t seq) {
phase = 0;
}
// Set up OUT transfer of buffer 1.
if (16384 > m0_state.offset && 0 == phase) {
if (16384 > m0_offset && 0 == phase) {
usb_transfer_schedule_block(
&usb_endpoint_bulk_out,
&usb_bulk_buffer[0x4000],

View File

@ -379,7 +379,7 @@ int write_register(hackrf_device* device, uint8_t part,
static void print_state(hackrf_m0_state *state) {
printf("M0 state:\n");
printf("Offset: %u bytes\n", state->offset);
printf("M0 count: %u bytes\n", state->m0_count);
printf("TX: %u\n", state->tx);
}

View File

@ -157,8 +157,8 @@ typedef struct {
/** State of the SGPIO loop running on the M0 core. */
typedef struct {
/** Current offset in the buffer. */
uint32_t offset;
/** Number of bytes transferred by the M0. */
uint32_t m0_count;
/** TX flag. */
uint32_t tx;
} hackrf_m0_state;