sipeed-slogic-analyzer: Add Support for Sipeed SLogic Series, including SLogic16U3 5Gbps#262
sipeed-slogic-analyzer: Add Support for Sipeed SLogic Series, including SLogic16U3 5Gbps#262taorye wants to merge 0 commit intosigrokproject:masterfrom
Conversation
|
We are preparing to send a batch of patches to the sigrok mailing list. This PR serves as a record for tracking purposes. After the patches are merged upstream, we will proactively close this PR and notify everyone. Of course, before merging, everyone is welcome to pull and test these changes. We will promptly respond to any questions or issues raised. |
|
Thanks. May I ask when will SlogicBasic16U3 be available? |
|
It will open preorder in the last week of April, and start ship before June. |
|
| do { | ||
| struct libusb_transfer *transfer = libusb_alloc_transfer(0); | ||
| if (!transfer) { | ||
| sr_err("Failed to allocate libusb transfer!"); | ||
| return SR_ERR_IO; | ||
| } | ||
| do { | ||
| devc->per_transfer_nbytes = (devc->per_transfer_nbytes + (2*16*1024-1)) & ~(2*16*1024-1); | ||
| devc->per_transfer_duration = devc->per_transfer_nbytes * SR_KHZ(1) * 8 / (devc->cur_samplerate * devc->cur_samplechannel); | ||
| sr_dbg("Plan to receive %u bytes per %ums...", devc->per_transfer_nbytes, devc->per_transfer_duration); | ||
|
|
||
| uint8_t *dev_buf = g_malloc(devc->per_transfer_nbytes); | ||
| if (!dev_buf) { | ||
| sr_dbg("Failed to allocate memory: %u bytes! Half .", devc->per_transfer_nbytes); | ||
| devc->per_transfer_nbytes >>= 1; | ||
| continue; | ||
| } | ||
|
|
||
| libusb_fill_bulk_transfer(transfer, usb->devhdl, devc->model->ep_in, | ||
| dev_buf, devc->per_transfer_nbytes, NULL, | ||
| NULL, 0); | ||
|
|
||
| ret = libusb_submit_transfer(transfer); | ||
| if (ret) { | ||
| g_free(transfer->buffer); | ||
| if (ret == LIBUSB_ERROR_NO_MEM) { | ||
| sr_dbg("Failed to submit transfer: %s!", libusb_error_name(ret)); | ||
| devc->per_transfer_nbytes >>= 1; | ||
| continue; | ||
| } else { | ||
| sr_err("Failed to submit transfer: %s!", libusb_error_name(ret)); | ||
| libusb_free_transfer(transfer); | ||
| return SR_ERR_IO; | ||
| } | ||
| } else { | ||
| ret = libusb_cancel_transfer(transfer); | ||
| if (ret) { | ||
| sr_dbg("Failed to cancel transfer: %s!", libusb_error_name(ret)); | ||
| } | ||
| libusb_handle_events_timeout_completed(drvc->sr_ctx->libusb_ctx, &(struct timeval){3, 0}, NULL); | ||
| g_free(transfer->buffer); | ||
|
|
||
| devc->per_transfer_nbytes >>= 1; | ||
| devc->per_transfer_duration = devc->per_transfer_nbytes / (devc->cur_samplerate / SR_KHZ(1) * devc->cur_samplechannel / 8); | ||
| break; | ||
| } | ||
| } while (devc->per_transfer_nbytes > 32*1024); // 32kiB > 125ms * 1MHZ * 2ch | ||
| libusb_free_transfer(transfer); | ||
| sr_info("Nice plan! :) => %u bytes per %ums.", devc->per_transfer_nbytes, devc->per_transfer_duration); | ||
| } while (0); | ||
|
|
There was a problem hiding this comment.
Should go into a separate function, with a name telling what this code block is doing (i.e. probe the maximum transfer size).
There was a problem hiding this comment.
Got it, I will refactor them soon.
THANK YOU for your advise!
| sr_dbg("Failed to cancel transfer: %s!", libusb_error_name(ret)); | ||
| } | ||
| libusb_handle_events_timeout_completed(drvc->sr_ctx->libusb_ctx, &(struct timeval){3, 0}, NULL); |
There was a problem hiding this comment.
I should remember to format them first then.
Thanks!
| static inline void clear_ep(const struct sr_dev_inst *sdi) { | ||
| struct dev_context *devc = sdi->priv; | ||
| struct sr_usb_dev_inst *usb = sdi->conn; | ||
| uint8_t ep = devc->model->ep_in; | ||
|
|
||
| size_t tmp_size = 4 * 1024 * 1024; | ||
| uint8_t *tmp = malloc(tmp_size); | ||
| int actual_length = 0; | ||
| do { | ||
| libusb_bulk_transfer(usb->devhdl, ep, | ||
| tmp, tmp_size, &actual_length, 100); | ||
| } while (actual_length); | ||
| free(tmp); | ||
| sr_dbg("Cleared EP: 0x%02x", ep); | ||
| } |
There was a problem hiding this comment.
Should be moved to the api.c file.
| #define TRANSFERS_DURATION_TOLERANCE 0.05f | ||
|
|
||
| enum { | ||
| PATTERN_MODE_NOMAL, |
| if (devc->num_transfers_used) { | ||
| for (size_t i = 0; i < NUM_MAX_TRANSFERS; ++i) { | ||
| struct libusb_transfer *transfer = devc->transfers[i]; | ||
| if (transfer) { | ||
| libusb_cancel_transfer(transfer); | ||
| } | ||
| } |
There was a problem hiding this comment.
This branch leaks all uncompleted transfers.
There was a problem hiding this comment.
Yeah, if (devc->raw_data_queue == NULL) is not enough to ensure transfers to be freed.
I'll add some restrictive conditions to guarantee cleanup.
| #define GEN_PATTERN(P) [P] = #P | ||
| GEN_PATTERN(PATTERN_MODE_NOMAL), | ||
| GEN_PATTERN(PATTERN_MODE_TEST_MAX_SPEED), | ||
| #undef GEN_PATTERN |
There was a problem hiding this comment.
| #define GEN_PATTERN(P) [P] = #P | |
| GEN_PATTERN(PATTERN_MODE_NOMAL), | |
| GEN_PATTERN(PATTERN_MODE_TEST_MAX_SPEED), | |
| #undef GEN_PATTERN | |
| [PATTERN_MODE_NORMAL] = "Normal", | |
| [PATTERN_MODE_TEST_MAX_SPEED] = "Test_Max_Speed", |
| { | ||
| size_t retry = 0; | ||
| memset(cmd_aux, 0, sizeof(cmd_aux)); | ||
| *(uint32_t*)(cmd_aux) = 0x00000001; |
|
|
||
| slogic_usb_control_write(sdi, SLOGIC16U3_CONTROL_OUT_REQ_REG_WRITE, SLOGIC16U3_R32_CTRL, 0x0000, ARRAY_AND_SIZE(cmd_derst), 500); | ||
|
|
||
| { |
There was a problem hiding this comment.
Split into separate function.
| } | ||
|
|
||
|
|
||
| { |
There was a problem hiding this comment.
Split into separate function.
| if (!data && len) { | ||
| sr_warn("%s: Nothing to write although len(%u)>0!", __func__, len); | ||
| len = 0; | ||
| } else if (len & 0x3) { |
There was a problem hiding this comment.
Nope, this has to be a hard error, you will do an out-of-bounds read (or even write below).
|
Please add Trigger function |
Building upon the foundation established in #212, this PR delivers:
Legacy Hardware Maintenance (Slogic Combo 8)
New Hardware Support (Slogic16U3: USB3.2 Gen1 5Gbps)
Initial Slogic16U3 driver implementation
200MHz/16ch mode based on max 430MiB/s throughput