Skip to content

Commit

Permalink
Atomically check transceiver mode and sequence before loop dispatch.
Browse files Browse the repository at this point in the history
This ensures that when one of the mode-specific loops starts, the choice
of loop and the sequence number passed to it are those set by the same
call to the set_transceiver_mode vendor request handler.

If the handler is called a second time during dispatch, the mode and
sequence numbers it sets will not yet take effect. The already selected
loop will begin running, and will return as soon as it notices the
sequence number has changed.

This avoids any race in which the vendor request handler is called in
between reading the two variables, causing the wrong loop to be started
or to fail to exit when needed.
  • Loading branch information
martinling committed Feb 2, 2022
1 parent e68ceca commit 2f5428d
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 13 deletions.
22 changes: 18 additions & 4 deletions firmware/hackrf_usb/hackrf_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -263,15 +263,29 @@ int main(void) {
operacake_init(operacake_allow_gpio);

while(true) {
switch (transceiver_mode()) {

// Briefly disable USB interrupt so that we can
// atomically retrieve both the transceiver mode
// and the mode change sequence number. They are
// changed together by the set_transceiver_mode
// vendor request handler.

nvic_disable_irq(NVIC_USB0_IRQ);

transceiver_mode_t mode = transceiver_mode();
uint32_t seq = transceiver_mode_seq();

nvic_enable_irq(NVIC_USB0_IRQ);

switch (mode) {
case TRANSCEIVER_MODE_RX:
rx_mode();
rx_mode(seq);
break;
case TRANSCEIVER_MODE_TX:
tx_mode();
tx_mode(seq);
break;
case TRANSCEIVER_MODE_RX_SWEEP:
sweep_mode();
sweep_mode(seq);
break;
case TRANSCEIVER_MODE_CPLD_UPDATE:
cpld_update();
Expand Down
3 changes: 1 addition & 2 deletions firmware/hackrf_usb/usb_api_sweep.c
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ usb_request_status_t usb_vendor_request_init_sweep(
return USB_REQUEST_STATUS_OK;
}

void sweep_mode(void) {
uint32_t seq = transceiver_mode_seq();
void sweep_mode(uint32_t seq) {
unsigned int blocks_queued = 0;
unsigned int phase = 1;
bool odd = true;
Expand Down
2 changes: 1 addition & 1 deletion firmware/hackrf_usb/usb_api_sweep.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ enum sweep_style {
usb_request_status_t usb_vendor_request_init_sweep(
usb_endpoint_t* const endpoint, const usb_transfer_stage_t stage);

void sweep_mode(void);
void sweep_mode(uint32_t seq);

#endif /* __USB_API_SWEEP_H__ */
6 changes: 2 additions & 4 deletions firmware/hackrf_usb/usb_api_transceiver.c
Original file line number Diff line number Diff line change
Expand Up @@ -330,8 +330,7 @@ usb_request_status_t usb_vendor_request_set_hw_sync_mode(
}
}

void rx_mode(void) {
uint32_t seq = _transceiver_mode_seq;
void rx_mode(uint32_t seq) {
unsigned int phase = 1;

baseband_streaming_enable(&sgpio_config);
Expand Down Expand Up @@ -360,8 +359,7 @@ void rx_mode(void) {
}
}

void tx_mode(void) {
uint32_t seq = _transceiver_mode_seq;
void tx_mode(uint32_t seq) {
unsigned int phase = 1;

memset(&usb_bulk_buffer[0x0000], 0, 0x8000);
Expand Down
4 changes: 2 additions & 2 deletions firmware/hackrf_usb/usb_api_transceiver.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ transceiver_mode_t transceiver_mode(void);
uint32_t transceiver_mode_seq(void);
void set_transceiver_mode(const transceiver_mode_t new_transceiver_mode);
void start_streaming_on_hw_sync();
void rx_mode(void);
void tx_mode(void);
void rx_mode(uint32_t seq);
void tx_mode(uint32_t seq);

#endif/*__USB_API_TRANSCEIVER_H__*/

0 comments on commit 2f5428d

Please sign in to comment.