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> #include <usb_request.h>
struct m0_state { struct m0_state {
uint32_t offset; uint32_t m0_count;
uint32_t tx; uint32_t tx;
}; };

View File

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

View File

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

View File

@ -296,7 +296,7 @@ void transceiver_startup(const transceiver_mode_t mode) {
activate_best_clock_source(); activate_best_clock_source();
hw_sync_enable(_hw_sync_mode); 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( 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); baseband_streaming_enable(&sgpio_config);
while (transceiver_request.seq == seq) { while (transceiver_request.seq == seq) {
uint32_t m0_offset = m0_state.m0_count & USB_BULK_BUFFER_MASK;
// Set up IN transfer of buffer 0. // 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_transfer_schedule_block(
&usb_endpoint_bulk_in, &usb_endpoint_bulk_in,
&usb_bulk_buffer[0x0000], &usb_bulk_buffer[0x0000],
@ -353,7 +354,7 @@ void rx_mode(uint32_t seq) {
phase = 0; phase = 0;
} }
// Set up IN transfer of buffer 1. // 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_transfer_schedule_block(
&usb_endpoint_bulk_in, &usb_endpoint_bulk_in,
&usb_bulk_buffer[0x4000], &usb_bulk_buffer[0x4000],
@ -384,8 +385,9 @@ void tx_mode(uint32_t seq) {
baseband_streaming_enable(&sgpio_config); baseband_streaming_enable(&sgpio_config);
while (transceiver_request.seq == seq) { while (transceiver_request.seq == seq) {
uint32_t m0_offset = m0_state.m0_count & USB_BULK_BUFFER_MASK;
// Set up OUT transfer of buffer 0. // 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_transfer_schedule_block(
&usb_endpoint_bulk_out, &usb_endpoint_bulk_out,
&usb_bulk_buffer[0x0000], &usb_bulk_buffer[0x0000],
@ -395,7 +397,7 @@ void tx_mode(uint32_t seq) {
phase = 0; phase = 0;
} }
// Set up OUT transfer of buffer 1. // 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_transfer_schedule_block(
&usb_endpoint_bulk_out, &usb_endpoint_bulk_out,
&usb_bulk_buffer[0x4000], &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) { static void print_state(hackrf_m0_state *state) {
printf("M0 state:\n"); 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); printf("TX: %u\n", state->tx);
} }

View File

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