asix-sigma: download sample memory in multiple receive calls

The previous implementation ran the complete sample memory retrieval
in a single call to the receive callback. Which in combination with
slow USB communication and deep memory could block application logic
for rather long periods of time.

Rephrase the download_capture() routine such that it can spread its
workload across multiple invocations. Run the acquisition stop and
resource allocation for the download, the interpretation of a set of
DRAM lines, and the resource cleanup, as needed. And keep calling the
download routine until completion of the interpretation of the sample
memory region of interest. The workload size per invocation may need
more adjustment.

The previous implementation could stall UI progress for some 20-30s.
This change lets users perceive UI progress while sample memory gets
retrieved and interpreted.

This resolves bug #1005.
This commit is contained in:
Gerhard Sittig 2020-05-31 18:38:39 +02:00
parent 914f8160e7
commit debe1ff66d
1 changed files with 98 additions and 47 deletions

View File

@ -1494,6 +1494,7 @@ static void free_sample_buffer(struct dev_context *devc)
{ {
g_free(devc->interp.fetch.rcvd_lines); g_free(devc->interp.fetch.rcvd_lines);
devc->interp.fetch.rcvd_lines = NULL; devc->interp.fetch.rcvd_lines = NULL;
devc->interp.fetch.lines_per_read = 0;
} }
/* /*
@ -1870,26 +1871,35 @@ static int download_capture(struct sr_dev_inst *sdi)
uint32_t stoppos, triggerpos; uint32_t stoppos, triggerpos;
uint8_t modestatus; uint8_t modestatus;
int ret; int ret;
size_t chunks_per_receive_call;
devc = sdi->priv; devc = sdi->priv;
interp = &devc->interp; interp = &devc->interp;
sr_info("Downloading sample data.");
devc->state = SIGMA_DOWNLOAD;
/* /*
* Check the mode register. Force stop the current acquisition
* if it has not yet terminated before. Will block until the
* acquisition stops, assuming that this won't take long. Should
* execute exactly once, then keep finding its condition met.
*
* Ask the hardware to stop data acquisition. Reception of the * Ask the hardware to stop data acquisition. Reception of the
* FORCESTOP request makes the hardware "disable RLE" (store * FORCESTOP request makes the hardware "disable RLE" (store
* clusters to DRAM regardless of whether pin state changes) and * clusters to DRAM regardless of whether pin state changes) and
* raise the POSTTRIGGERED flag. * raise the POSTTRIGGERED flag.
*
* Then switch the hardware from DRAM write (data acquisition)
* to DRAM read (sample memory download).
*/ */
ret = sigma_get_register(devc, READ_MODE, &modestatus);
if (ret != SR_OK) {
sr_err("Could not determine current device state.");
return FALSE;
}
if (!(modestatus & RMR_POSTTRIGGERED)) {
sr_info("Downloading sample data.");
devc->state = SIGMA_DOWNLOAD;
modestatus = WMR_FORCESTOP | WMR_SDRAMWRITEEN; modestatus = WMR_FORCESTOP | WMR_SDRAMWRITEEN;
ret = sigma_set_register(devc, WRITE_MODE, modestatus); ret = sigma_set_register(devc, WRITE_MODE, modestatus);
if (ret != SR_OK) if (ret != SR_OK)
return ret; return FALSE;
do { do {
ret = sigma_get_register(devc, READ_MODE, &modestatus); ret = sigma_get_register(devc, READ_MODE, &modestatus);
if (ret != SR_OK) { if (ret != SR_OK) {
@ -1897,15 +1907,25 @@ static int download_capture(struct sr_dev_inst *sdi)
return FALSE; return FALSE;
} }
} while (!(modestatus & RMR_POSTTRIGGERED)); } while (!(modestatus & RMR_POSTTRIGGERED));
ret = sigma_set_register(devc, WRITE_MODE, WMR_SDRAMREADEN); }
if (ret != SR_OK)
return ret;
/* /*
* Switch the hardware from DRAM write (data acquisition) to
* DRAM read (sample memory download). Prepare resources for
* sample memory content retrieval. Should execute exactly once,
* then keep finding its condition met.
*
* Get the current positions (acquisition write pointer, and * Get the current positions (acquisition write pointer, and
* trigger match location). With disabled triggers, use a value * trigger match location). With disabled triggers, use a value
* for the location that will never match during interpretation. * for the location that will never match during interpretation.
* Determine which area of the sample memory to retrieve,
* allocate a receive buffer, and setup counters/pointers.
*/ */
if (!interp->fetch.lines_per_read) {
ret = sigma_set_register(devc, WRITE_MODE, WMR_SDRAMREADEN);
if (ret != SR_OK)
return FALSE;
ret = sigma_read_pos(devc, &stoppos, &triggerpos, &modestatus); ret = sigma_read_pos(devc, &stoppos, &triggerpos, &modestatus);
if (ret != SR_OK) { if (ret != SR_OK) {
sr_err("Could not query capture positions/state."); sr_err("Could not query capture positions/state.");
@ -1916,10 +1936,6 @@ static int download_capture(struct sr_dev_inst *sdi)
if (!(modestatus & RMR_TRIGGERED)) if (!(modestatus & RMR_TRIGGERED))
triggerpos = ~0; triggerpos = ~0;
/*
* Determine which area of the sample memory to retrieve,
* allocate a receive buffer, and setup counters/pointers.
*/
ret = alloc_sample_buffer(devc, stoppos, triggerpos, modestatus); ret = alloc_sample_buffer(devc, stoppos, triggerpos, modestatus);
if (ret != SR_OK) if (ret != SR_OK)
return FALSE; return FALSE;
@ -1930,6 +1946,18 @@ static int download_capture(struct sr_dev_inst *sdi)
ret = setup_submit_limit(devc); ret = setup_submit_limit(devc);
if (ret != SR_OK) if (ret != SR_OK)
return FALSE; return FALSE;
}
/*
* Get another set of sample memory rows, and interpret its
* content. Will execute as many times as it takes to complete
* the memory region that the recent acquisition spans.
*
* The size of a receive call's workload and the main loop's
* receive call poll period determine the UI responsiveness and
* the overall transfer time for the sample memory content.
*/
chunks_per_receive_call = 50;
while (interp->fetch.lines_done < interp->fetch.lines_total) { while (interp->fetch.lines_done < interp->fetch.lines_total) {
size_t dl_events_in_line; size_t dl_events_in_line;
@ -1949,15 +1977,35 @@ static int download_capture(struct sr_dev_inst *sdi)
interp->fetch.curr_line++; interp->fetch.curr_line++;
interp->fetch.lines_done++; interp->fetch.lines_done++;
} }
/* Keep returning to application code for large data sets. */
if (!--chunks_per_receive_call) {
ret = flush_submit_buffer(devc);
if (ret != SR_OK)
return FALSE;
break;
} }
flush_submit_buffer(devc); }
/*
* Release previously allocated resources, and adjust state when
* all of the sample memory was retrieved, and interpretation has
* completed. Should execute exactly once.
*/
if (interp->fetch.lines_done >= interp->fetch.lines_total) {
ret = flush_submit_buffer(devc);
if (ret != SR_OK)
return FALSE;
free_submit_buffer(devc); free_submit_buffer(devc);
free_sample_buffer(devc); free_sample_buffer(devc);
std_session_send_df_end(sdi); ret = std_session_send_df_end(sdi);
if (ret != SR_OK)
return FALSE;
devc->state = SIGMA_IDLE; devc->state = SIGMA_IDLE;
sr_dev_acquisition_stop(sdi); sr_dev_acquisition_stop(sdi);
}
return TRUE; return TRUE;
} }
@ -1994,12 +2042,15 @@ SR_PRIV int sigma_receive_data(int fd, int revents, void *cb_data)
/* /*
* When the application has requested to stop the acquisition, * When the application has requested to stop the acquisition,
* then immediately start downloading sample data. Otherwise * then immediately start downloading sample data. Continue a
* previously initiated download until completion. Otherwise
* keep checking configured limits which will terminate the * keep checking configured limits which will terminate the
* acquisition and initiate download. * acquisition and initiate download.
*/ */
if (devc->state == SIGMA_STOPPING) if (devc->state == SIGMA_STOPPING)
return download_capture(sdi); return download_capture(sdi);
if (devc->state == SIGMA_DOWNLOAD)
return download_capture(sdi);
if (devc->state == SIGMA_CAPTURE) if (devc->state == SIGMA_CAPTURE)
return sigma_capture_mode(sdi); return sigma_capture_mode(sdi);