221 Commits

Author SHA1 Message Date
Yan
790de7f47b Cleaner fast exit
Interrupt the event handling thread instead of waiting for timeout.
2022-03-16 11:13:00 +00:00
Yan
7ff92b3b05 Ensure fast exit
transfer_threadproc has a timeout of half a second, so
when kill_transfer_thread tries to pthread_join, it often
has to wait until the timeout kicks in.

With this fix, we ensure that a final request is made after
request_exit has been called, so that transfer_threadproc can exit its
loop in a fast and clean manner.
2022-03-15 12:43:45 +00:00
Martin Ling
d755f7a5c8 Correct order of requested mode and flag. 2022-02-28 17:12:45 +00:00
Martin Ling
779483b9bd Make M0 state retrieval endian-safe. 2022-02-13 17:53:34 +00:00
Martin Ling
f3633e285f Replace direct setting of M0 mode with a request/ack mechanism.
This change avoids various possible races in which an autonomous mode
change by the M0 might clobber a mode change made from the M4, as well
as related races on other state fields that can be written by the M4.

The previous mode field is replaced by two separate ones:

- active_mode, which is written only by the M0, and indicates the
  current operating mode.

- requested_mode, which is written by the M4 to request a change.
  This field includes both the requested mode, and a flag bit. The M4
  writes the field with the flag bit set, and must then wait for the
  M0 to signal completion of the request by clearing the flag bit.

Whilst the M4 is blocked waiting for the flag bit to be cleared, the
M0 can safely make all the required changes to the state that are
needed for the transition to the requested mode. Once the transition
is complete, the M0 clears the flag bit and the M4 continues execution.

Request handling is implemented in the idle loop. To handle requests,
mode-specific loops simply need to check the request flag and branch to
idle if it is set.

A request from the M4 to change modes will always require passing
through the idle loop, and is not subject to timing guarantees. Only
transitions made autonomously by the M0 have guaranteed timing
constraints.

The work previously done in reset_counts is now implemented as part of
the request handling, so the tx_start, rx_start and wait_start labels
are no longer required.

An extra two cycles are required in the TX shortfall path because we
must now load the active mode to check whether we are in TX_START.

Two cycles are saved in the normal TX path because updating the active
mode to TX_RUN can now be done without checking the previous value.
2022-02-13 17:53:34 +00:00
Martin Ling
137f2481e5 Make an error code available when a shortfall limit is hit.
Previously, finding the M0 in IDLE mode was ambiguous; it could indicate
either a normal outcome, or a shortfall limit having being hit.

To disambiguate, we add an error field to the M0 state. The errors
currently possible are an RX timeout or a TX timeout, both of which
can be obtained efficiently from the current operating mode due to
the values used.

This adds 3 cycles to both shortfall paths, in order to shift down
the mode to obtain the error code, and store it to the M0 state.
2022-02-13 17:53:34 +00:00
Martin Ling
3618a5352f Add a counter threshold at which the M0 will change to a new mode.
This lays the groundwork for implementing timed operations (#86). The M0
can be configured to automatically change modes when its byte count
reaches a specific value.

Checking the counter against the threshold and dispatching to the next
mode is handled by a new `jump_next_mode` macro, which replaces the
unconditional branches back to the start of the TX and RX loops.

Making this change work requires some rearrangement of the code, such
that the destinations of all conditional branch instructions are within
reach. These branch instructions (`b[cond] label`) have a range of -256
to +254 bytes from the current program counter.

For this reason, the TX shortfall handling is moved earlier in the file,
and branches in the idle loop are restructured to use an unconditional
branch to rx_start, which is furthest away.

The additional code for switching modes adds 9 cycles to the normal RX
path, and 10 to the TX path (the difference is because the dispatch in
`jump_next_mode` is optimised for the longer RX path).
2022-02-13 16:46:12 +00:00
Martin Ling
5abc39c53a Add USB requests and host support to set TX/RX shortfall limits.
This adds `-T` and `-R` options to `hackrf_debug`, which set the TX
underrun and RX overrun limits in bytes.
2022-02-13 16:46:12 +00:00
Martin Ling
f0bc6eda30 Add a shortfall length limit.
This limit allows implementing a timeout: if a TX underrun or RX overrun
continues for the specified number of bytes, the M0 will revert to idle.

A setting of zero disables the limit.

This change adds 5 cycles to the TX & RX shortfall paths, to check if a
limit is set and to check the shortfall length against the limit.
2022-02-13 16:46:12 +00:00
Martin Ling
2c86f493d9 Keep track of longest shortfall.
This adds six cycles to the TX and RX shortfall paths.
2022-02-13 16:46:12 +00:00
Martin Ling
a7bd1e3ede Keep count of number of shortfalls.
To enable this, we keep a count of the current shortfall length. Each
time an SGPIO read/write cannot be completed due to a shortfall, we
increase this length. Each time an SGPIO read/write is completed
successfully, we reset the shortfall length to zero.

When a shortfall occurs and the existing shortfall length is zero, this
indicates a new shortfall, and the shortfall count is incremented.

This change adds one cycle to the normal RX & TX paths, to zero the
shortfall count. To enable this to be done in a single cycle, we keep a
zero handy in a high register.

The extra accounting adds 10 cycles to the TX and RX shortfall paths,
plus an additional 3 cycles to the RX shortfall path since there are
now two branches involved: one to the shortfall handler, and another
back to the main loop.
2022-02-13 16:46:12 +00:00
Martin Ling
5b50b2dfac Replace TX flag with a mode setting.
This is to let us start adding new operatin modes for the M0.
2022-02-13 16:46:12 +00:00
Martin Ling
79853d2b28 Add a second counter to keep track of bytes transferred by the M4.
With both counters in place, the number of bytes in the buffer is now
indicated by the difference between the M0 and M4 counts.

The M4 count needs to be increased whenever the M4 produces or consumes
data in the USB bulk buffer, so that the two counts remain correctly
synchronised.

There are three places where this is done:

1. When a USB bulk transfer in or out of the buffer completes, the count
   is increased by the number of bytes transferred. This is the most
   common case.

2. At TX startup, the M4 effectively sends the M0 16K of zeroes to
   transmit, before the first host-provided data.

   This is done by zeroing the whole 32K buffer area, and then setting
   up the first bulk transfer to write to the second 16K, whilst the M0
   begins transmission of the first 16K.

   The count is therefore increased by 16K during TX startup, to account
   for the initial 16K of zeros.

3. In sweep mode, some data is discarded. When this is done, the count
   is incremented by the size of the discarded data.

   The USB IRQ is masked whilst doing this, since a read-modify-write is
   required, and the bulk transfer completion callback may be called at
   any point, which also increases the count.
2022-02-13 16:46:12 +00:00
Martin Ling
21dabc920f 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.
2022-02-13 16:46:12 +00:00
Martin Ling
fd073e391f Add USB vendor request to read M0 state, and host support for doing so.
This adds a `hackrf_debug [-S|--state]` option, and the necessary
plumbing to libhackrf and the M4 firmware to support it.

The USB API and libhackrf versions are bumped to reflect the changes.
2022-02-13 16:46:12 +00:00
Martin Ling
4c9fcf8665 After cancelling transfers, wait for all handling to complete.
Calling libusb_cancel_transfer only starts the cancellation of a
transfer. The process is not complete until the transfer callback
has been called with status LIBUSB_TRANSFER_CANCELLED.

If hackrf_start_rx() is called soon after hackrf_stop_rx(),
prepare_transfers() may be called before the previous cancellations
are completed, resulting in a LIBUSB_ERROR_BUSY when a transfer is
reused with libusb_submit_transfer().

To prevent this happening, we keep track of which transfers have
finished (either by completion, or cancellation), and make
cancel_transfers() wait until all transfers are finished.

This is implemented using a pthread condition variable which is
signalled from the transfer thread.
2022-02-03 06:44:20 +00:00
Martin Ling
837b5ee9c8 Use a lock to prevent transfers being restarted during cancellation.
Fixes bug #916.

Previously, there was a race which could lead to a transfer being left
active after cancel_transfers() completed. This would then cause the
next prepare_transfers() call to fail, because libusb_submit_transfer()
would return an error due to the transfer already being in use.

The sequence of events that could cause this was:

1. Main thread calls hackrf_stop_rx(), which calls cancel_transfers(),
   which iterates through the 4 transfers in use and cancels them one
   by one with libusb_cancel_transfer().

2. During this time, a transfer is completed. The transfer thread calls
   hackrf_libusb_transfer_callback(), which handles the data and then
   calls libusb_submit_transfer() to resubmit that transfer.

3. Now, cancel_transfers() and hackrf_stop_rx() are completed but one
   transfer is still active.

4. The next hackrf_start_rx() call fails, because prepare_transfers()
   tries to submit a transfer which is already in use.

To fix this, we add a lock which must be held to either cancel transfers
or restart them. This ensures that only one of these actions can happen
for a given transfer; it's no longer possible for a transfer to be
cancelled and then immediately restarted.
2022-02-03 06:44:19 +00:00
Michael Ossmann
e25096b17a firmware: add operacake_activate_ports()
Fixes frequency mode which had been broken by operacake_set_ports() only
activating the selected ports when in manual mode (at my suggestion).
2021-12-12 11:56:57 -07:00
Michael Ossmann
aa0485d4df Revert "Cleanup of host software CMake build system (#664)"
This reverts commit d60fb83320cea49fd20305f22838f948557f1b81.
2021-12-08 16:59:05 -07:00
Jamie Smith
d60fb83320 Cleanup of host software CMake build system (#664)
* Clean up the CMake build system and improve the FindFFTW3 module.

* Fixes for Linux build

* Include winsock.h to get struct timeval

* Couple more fixes for MSVC, also add new FindMath module

* Update host build README for new CMake changes (esp. Windows)

* Try to fix Travis OS X build error

* Add docs about pthread-win32

* Whoops, AppVeyor caught a bug in FindFFTW where the includes not being found weren't generating a fatal error.

* Travis rebuild bump

* One more fix: replace hardcoded include paths with a PATH_SUFFIX to standard include paths

* Invert Windows preprocessor flag so it's only needed when using a static build.  This preserves compatibility with the previous system.

* Fix copy-paste error

* Update cmake modules from amber-cmake upstream, incorporate TryLinkLibrary into FindUSB1

* Fix missing include
2021-12-03 14:11:04 -05:00
Michael Ossmann
0f4f1addd1 libhackrf: document hackrf_transfer struct 2021-11-17 18:38:00 -07:00
Mike Walters
38ed075437 operacake: replace hackrf_set_operacake_ranges with hackrf_set_operacake_freq_ranges 2021-10-15 14:45:38 +01:00
Mike Walters
e41314f130 operacake: add API function to set port dwell times 2021-10-14 14:41:52 +01:00
Mike Walters
c50ebb1a36 operacake: add time switching mode 2021-10-14 14:41:52 +01:00
Mike Walters
790b5d35cf operacake: add get/set switching mode functions 2021-10-14 14:36:18 +01:00
Mike Walters
0293cf23db Opera Cake: use 0-7 instead of I2C addresses & bump USB API version 2021-07-14 18:35:31 +01:00
Michael Ossmann
2a8ed4ec59 increment .so/.pc version number to 0.6 2021-03-17 21:44:34 -06:00
adrian chadd
61a06b904d Handle hackrf_close() being called without TX or RX being started.
My previous commits didn't handle the specific case of hackrf_close()
being called without the transfers being active.

In this instance the transfers haven't been setup, so calling
cancel_transfers() returned an error.

Instead:

* refactor out the tx/rx stop command from canceling transfers
* send the tx/rx stop command without canceling transfers, since ..
* ... we can then destroy the transfer thread.

I may also need to put an explicit cancel_transfers() before the
call to send the tx/rx stop commands; I'll look at doing that
in a subsequent commit.
2020-12-10 15:57:54 -08:00
Adrian Chadd
b4ea51a36b add 10ms sleep after stop
This seems to stop consumers that are doing quick back to back stop/start
(eg gqrx changing decode mode / filter bandwidth) from hanging the
device.

I now don't have any weird hangs on hackrf with gqrx/freebsd/libusb!

When things hang it isn't erroring out in any way; it just doesn't
start receive.  It doesn't look like a libusb issue; I'd have to get
some USB bus sniffing to see what's going on behind the scenes.
2020-11-09 10:40:44 -08:00
Adrian Chadd
9a278d267a Fix streaming hangs in consumers
* Update device->streaming to reflect whether we're streaming data,
  rather than just whether the streaming thread is active.
  The streaming thread is now always active!
2020-11-09 09:42:34 -08:00
Adrian Chadd
0961a76f26 Fix libusb usage for at least freebsd around the worker thread and transfer cancellation
On at least freebsd-13 trying to cancel a transfer whilst the libusb thread
is not running results in the transfers not completing cancellation.
The next time they're attempted to be re-added the libusb code thinks
they're still active, and returns BUSY on the buffers.

This causes gqrx to error out when one makes DSP changes or stops/starts it.
You have to restart gqrx to fix it.

After digging into it a bit, the libusb code expects that you're actively
running the main loop in order to have some deferred actions run in the
context of said main loop thread.  This includes processing cancelled
transfers - the callbacks have to be run (if they exist) before the
buffers are properly cancelled and have their tracking metadata (a couple of
private pointers and state) removed from inside of libusb.

This patch does the following:

* separate out adding and cancelling transfers from the libusb worker thread
  create/destroy path
* create the libusb worker thread when opening the device
* destroy the libusb worker thread when closing the device
* only add and cancel transfers when starting and stopping tx/rx
* handle cancelled transfers gracefully in the USB callback

Whilst here, also make the libusb device memory zeroed by using
calloc instead of malloc.

This fixes all of the weird libusb related buffer management problems
on FreeBSD.
2020-11-08 21:38:39 -08:00
Mike Walters
1c091a10bf libhackrf: Zero-out initial transfer buffers 2020-02-12 18:53:59 +00:00
Michael Ossmann
c0aed2edb7 firmware: clean up transceiver modes 2020-02-11 16:59:59 +00:00
Mike Walters
4aac303480 Add option to disable HackRF UI
Fixes #608
2020-01-22 21:23:30 +00:00
Michael Ossmann
ecd82e81c1 remove specific sample rate recommendations
HackRF One supports arbitrary sample rates from 2 Msps to 20 Msps.  In
early development we had ideas about preferred sample rates that we no
longer consider valid.
2020-01-22 06:39:08 -07:00
Matioupi
1442014a80 Modified hackrf_stop_tx and hackrf_stop_rx to first join the transfer thread
before setting the receiver to OFF mode (cf. issue #650)
2020-01-06 16:37:05 -07:00
Jared Boone
ef5b907295 CPLD: Remove checksum function from libhackrf and hackrf_info.
The checksum calculation process was causing the CPLD configuration to reload from flash. With the new SRAM loading mechanism, flash contents may not be up to date, so the CPLD bitstream may regress to the point of not working or not working correctly. This commit is a short-term fix for mossmann/hackrf issue #609.
2019-03-27 12:16:39 -07:00
Jared Boone
fa2a9acd1a USB: initial CPLD checksum API support. 2019-01-31 21:19:21 +00:00
Jared Boone
8721fe606a Host: Add USB request ordinal for WCID 2019-01-09 15:07:08 -08:00
Dominic Spill
847d00d770 Fix typo in still in use error message 2018-12-18 14:42:41 -07:00
Michael Ossmann
74ef45a0dd Merge pull request #558 from dominicgs/multiple_hackrf_stop_rx_issue_463
Fix multiple hackrf stop rx
2018-12-06 15:48:53 -07:00
Dominic Spill
82656b8f14 HackRF Opera Cake - GPIO test mode 2018-11-09 22:10:16 -07:00
Michael Ossmann
5fbd75ef94 Merge pull request #468 from dominicgs/appveyor
Appveyor
2018-03-28 09:15:11 -06:00
Dominic Spill
bde5ca9f58 DFU serial number - avoid reading serial from flash chip
Set a DFU mode specific serial number
2018-03-27 18:08:49 -06:00
Dominic Spill
bfa9f65f4e Try another work around for strdup() 2018-03-26 23:25:31 -06:00
Dominic Spill
936da52169 Third time lucky with definition to remove warning about strdup() 2018-03-26 21:31:56 -06:00
Dominic Spill
e0e02bcd7a Fix bad define (maybe) 2018-03-26 21:16:23 -06:00
Dominic Spill
c8e8d33a59 Silence warning about strdup() being deprecated 2018-03-26 20:59:55 -06:00
Dominic Spill
bb585e40a4 libhackrf: Fix Windows type warnings
MSVC compalins when we mix int and ssize_t
Declaration of hackrf_set_sample_rate_manual differed between .h and .c
2018-03-26 20:35:44 -06:00
Dominic Spill
bac06167f1 Merge branch 'mossmann-master' into multiple_hackrf_stop_rx_issue_463 2018-03-21 16:44:07 -06:00