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:
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
@ -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],
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
Reference in New Issue
Block a user