This is an automated email from Gerrit. "Name of user not set <r.nooteb...@gmail.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/7987
-- gerrit commit 49a14e06ac924ceb71a0627acba7e07004367ddb Author: RolfNoot <r.nooteb...@gmail.com> Date: Sat Dec 16 16:17:53 2023 +0100 src/flash/nor/psoc6.c update changes Change-Id: I18c2d7aaf9fee53cc346dcc69eb52570f05c20dd Signed-off-by: RolfNoot <r.nooteb...@gmail.com> diff --git a/src/flash/nor/psoc6.c b/src/flash/nor/psoc6.c index 7923178139..41f34c874c 100644 --- a/src/flash/nor/psoc6.c +++ b/src/flash/nor/psoc6.c @@ -21,7 +21,6 @@ #include "target/image.h" #include "target/register.h" #include "target/target.h" -#include "rtos/rtos.h" /************************************************************************************************** * PSoC6 device definitions @@ -154,7 +153,6 @@ struct sflash_region { struct psoc6_bank_info { bool is_probed; bool ppu_read_protected; - bool has_erase_subsector_bug; uint32_t size_override; uint32_t page_size; size_t program_algo_size; @@ -530,9 +528,7 @@ static int ipc_acquire(struct flash_bank *bank) /* Workaround for double-buffered PPU */ if (info->regs->ppu_flush) { - //enum log_levels level = change_debug_level(LOG_LVL_USER); hr = target_read_u32(target, info->regs->ppu_flush, ®_val); - //change_debug_level(level); info->ppu_read_protected = (hr != ERROR_OK); } @@ -590,7 +586,6 @@ static uint32_t psoc6_probe_mem_area(struct target *target, target_addr_t start_ uint32_t dummy; int steps = 0; - //enum log_levels old_lvl = change_debug_level(LOG_LVL_USER); while (true) { steps++; hr = target_read_u32(target, start_addr + offset, &dummy); @@ -606,8 +601,7 @@ static uint32_t psoc6_probe_mem_area(struct target *target, target_addr_t start_ hr = target_read_u32(target, start_addr + offset, &dummy); offset = (hr != ERROR_OK) ? offset - step : offset + step; } - //change_debug_level(old_lvl); - + const uint32_t area_size = offset + step; LOG_INFO("Probed Flash Bank @" TARGET_ADDR_FMT ", size %u.%u KiB (in %d steps)", start_addr, area_size >> 10, area_size % 1024, steps); @@ -619,7 +613,7 @@ static uint32_t psoc6_probe_mem_area(struct target *target, target_addr_t start_ * @brief Invokes SROM API functions which are responsible for Flash operations * * @param bank current flash bank - * @param req_and_params requect id of the function to invoke + * @param req_and_params request id of the function to invoke * @param working_area address of memory buffer in target's memory space for SROM API parameters * @param check_errors true if error check and reporting should be performed * @param data_out pointer to variable which will be populated with execution status @@ -628,7 +622,7 @@ static uint32_t psoc6_probe_mem_area(struct target *target, target_addr_t start_ static int psoc6_call_sromapi_inner(struct flash_bank *bank, uint32_t req_and_params, uint32_t working_area, bool check_errors, uint32_t *data_out) { - LOG_DEBUG("Executing SROM API #0x%08X", req_and_params); + LOG_DEBUG("Executing SROM API #0x%08" PRIX32, req_and_params); struct target *target = bank->target; @@ -675,7 +669,7 @@ static int psoc6_call_sromapi_inner(struct flash_bank *bank, uint32_t req_and_pa bool is_error = (*data_out & SROMAPI_STATUS_MSK) != SROMAPI_STAT_SUCCESS; if (check_errors && is_error) { - LOG_ERROR("SROM API execution failed. Status: 0x%08X", (uint32_t)*data_out); + LOG_ERROR("SROM API execution failed. Status: 0x%08" PRIX32, *data_out); return ERROR_TARGET_FAILURE; } @@ -817,7 +811,7 @@ static int psoc6_get_info(struct flash_bank *bank, struct command_invocation *cm if (hr != ERROR_OK) return hr; - command_print_sameline(cmd, "Silicon ID: 0x%08X\nProtection: %s", + command_print_sameline(cmd, "Silicon ID: 0x%08" PRIX32 "\nProtection: %s", silicon_id, protection_to_str(protection)); return ERROR_OK; @@ -843,9 +837,9 @@ static bool psoc6_is_safe_sflash_page(struct psoc6_bank_info *info, uint32_t add if (addr >= region_start && addr < region_start + region_size) { if (op == ERASE) { - return (info->sflash_regions[i].flags & (1u << (g_sflash_restrictions + 0))); + return info->sflash_regions[i].flags & BIT(g_sflash_restrictions + 0); } else { /* op == PROGRAM */ - return (info->sflash_regions[i].flags & (1u << (g_sflash_restrictions + 4))); + return info->sflash_regions[i].flags & BIT(g_sflash_restrictions + 4); } } } @@ -1015,18 +1009,16 @@ static int psoc6_erase_sflash(struct flash_bank *bank, int first, int last) if (hr != ERROR_OK) goto exit; - //progress_init(count / info->page_size, ERASING); for (size_t i = 0; i < count / info->page_size; i++) { const uint32_t row_addr = bank->base + offset + i * info->page_size; if (psoc6_is_safe_sflash_page(info, row_addr, ERASE)) { hr = psoc6_program_row(bank, row_addr, buffer, is_sflash); if (hr != ERROR_OK) - LOG_ERROR("Failed to program Flash at address 0x%08X", row_addr); + LOG_ERROR("Failed to program Flash at address 0x%08" PRIX32, row_addr); } else { erase_skipped = true; } - //progress_sofar(i + 1); buffer += info->page_size; } hr = ERROR_OK; @@ -1034,8 +1026,7 @@ static int psoc6_erase_sflash(struct flash_bank *bank, int first, int last) exit: free(const_buffer); psoc6_sromalgo_release(target); - //progress_done(hr); - + if (erase_skipped) LOG_WARNING("Some SFlash rows were skipped during erase, see 'sflash_restrictions' command"); @@ -1064,7 +1055,6 @@ static size_t psoc6_erase_builder(struct flash_bank *bank, int first, int last, /* Number of rows in single sector */ const int rows_in_sector = sector_size / info->page_size; - const int rows_in_sub_sector = 8; size_t sector_count = 0; while (last >= first) { @@ -1073,11 +1063,6 @@ static size_t psoc6_erase_builder(struct flash_bank *bank, int first, int last, /* Erase Sector if we are on sector boundary and erase size covers whole sector */ address_buffer[sector_count++] = address | 1u; first += rows_in_sector; - } else if (!info->has_erase_subsector_bug && - (first % rows_in_sub_sector) == 0 && (last - first + 1) >= rows_in_sub_sector) { - /* Erase Sub-Sector if we are on sub-sector boundary and erase size covers whole sub-sector */ - address_buffer[sector_count++] = address | 2u; - first += rows_in_sub_sector; } else { /* Erase Row otherwise */ address_buffer[sector_count++] = address; @@ -1123,7 +1108,6 @@ static int psoc6_erase(struct flash_bank *bank, unsigned int first, unsigned int /* Number of rows in single sector */ const unsigned int rows_in_sector = sector_size / info->page_size; - //progress_init(last - first + 1, ERASING); while (last >= first) { const uint32_t address = bank->base + first * info->page_size; /* Erase Sector if we are on sector boundary and erase size covers whole sector */ @@ -1141,12 +1125,10 @@ static int psoc6_erase(struct flash_bank *bank, unsigned int first, unsigned int first += 1; } - //progress_left(last - first + 1); } exit: psoc6_sromalgo_release(target); - //progress_done(hr); return hr; } @@ -1216,7 +1198,6 @@ static int psoc6_erase_with_algo(struct flash_bank *bank, int first, int last, e buf_set_u32(reg_params[2].value, 0, 32, num_addresses_in_buffer); buf_set_u32(reg_params[3].value, 0, 32, wa_stack->address + wa_stack->size); - //progress_init(0, ERASING); hr = target_run_flash_async_algorithm(target, (const uint8_t *)address_buffer, num_addresses_in_buffer, sizeof(uint32_t), 0, NULL, ARRAY_SIZE(reg_params), reg_params, wa_buffer->address, wa_buffer->size, @@ -1225,7 +1206,7 @@ static int psoc6_erase_with_algo(struct flash_bank *bank, int first, int last, e if (hr != ERROR_OK) { uint32_t srom_result = buf_get_u32(reg_params[0].value, 0, 32); if ((srom_result & SROMAPI_STATUS_MSK) != SROMAPI_STAT_SUCCESS) { - LOG_ERROR("SROM API execution failed. Status: 0x%08X", srom_result); + LOG_ERROR("SROM API execution failed. Status: 0x%08" PRIX32, srom_result); hr = ERROR_FAIL; } } @@ -1266,11 +1247,11 @@ static int psoc6_program_row_inner(struct flash_bank *bank, uint32_t addr, const struct target *target = bank->target; struct working_area *wa; const uint32_t sromapi_req = use_writerow ? SROMAPI_WRITEROW_REQ : program_row_req; - const size_t num_bytes = (1u << data_size); + const size_t num_bytes = BIT(data_size); uint32_t data_out; int hr; - LOG_DEBUG("PSoC6 platform: programming row @%08X", addr); + LOG_DEBUG("PSoC6 platform: programming row @0x%08" PRIX32, addr); uint8_t srom_params[4 * sizeof(uint32_t)]; hr = target_alloc_working_area(target, sizeof(srom_params) + num_bytes, &wa); @@ -1343,7 +1324,6 @@ static int psoc6_program(struct flash_bank *bank, const uint8_t *buffer, uint32_ if (hr != ERROR_OK) goto exit; - //progress_init(count / info->page_size, PROGRAMMING); for (size_t i = 0; i < count / info->page_size; i++) { const uint32_t page_addr = bank->base + offset + i * info->page_size; const bool is_safe_sflash_page = psoc6_is_safe_sflash_page(info, page_addr, PROGRAM); @@ -1351,9 +1331,9 @@ static int psoc6_program(struct flash_bank *bank, const uint8_t *buffer, uint32_ if (!is_sflash || is_safe_sflash_page) { hr = psoc6_program_row(bank, page_addr, buffer, is_sflash); if (hr != ERROR_OK) { - LOG_ERROR("Failed to program Flash at address 0x%08X", page_addr); + LOG_ERROR("Failed to program Flash at address 0x%08" PRIX32, page_addr); - /* Ignore possigle errors in case we are dealing with SFlash */ + /* Ignore possible errors in case we are dealing with SFlash */ if (!is_sflash) goto exit; } @@ -1361,13 +1341,11 @@ static int psoc6_program(struct flash_bank *bank, const uint8_t *buffer, uint32_ if (is_sflash) program_skipped = true; } - //progress_sofar(i + 1); buffer += info->page_size; } exit: psoc6_sromalgo_release(target); - //progress_done(hr); if (program_skipped) LOG_WARNING("Some SFlash rows were skipped during programming, see 'sflash_restrictions' command"); @@ -1457,7 +1435,7 @@ static int psoc6_program_with_algo(struct flash_bank *bank, const uint8_t *buffe if (hr != ERROR_OK) { uint32_t srom_result = buf_get_u32(reg_params[0].value, 0, 32); if ((srom_result & SROMAPI_STATUS_MSK) != SROMAPI_STAT_SUCCESS) { - LOG_ERROR("SROM API execution failed. Status: 0x%08X", srom_result); + LOG_ERROR("SROM API execution failed. Status: 0x%08" PRIX32, srom_result); hr = ERROR_FAIL; } } @@ -1535,7 +1513,7 @@ static int psoc6_reset_halt(struct target *target, enum reset_halt_mode mode) continue; if (target->coreid == 0 && (vt_base & 0xFFFF0000) == 0xFFFF0000) { - LOG_INFO("%s: Application is invalid (VTOR = 0x%08X), reset_halt skipped", + LOG_INFO("%s: Application is invalid (VTOR = 0x%08" PRIX32 "), reset_halt skipped", target_name(target), vt_base); goto exit_halt_cpu; } @@ -1561,7 +1539,7 @@ static int psoc6_reset_halt(struct target *target, enum reset_halt_mode mode) goto exit_halt_cpu; } - LOG_INFO("%s: Vector Table found at 0x%08X", target_name(target), vt_base); + LOG_INFO("%s: Vector Table found at 0x%08" PRIX32, target_name(target), vt_base); /* Set breakpoint at User Application entry point */ hr = breakpoint_add(target, reset_addr, 2, BKPT_HARD); @@ -1586,16 +1564,12 @@ static int psoc6_reset_halt(struct target *target, enum reset_halt_mode mode) } /* Reset the CM0 by asserting SYSRESETREQ. This will also reset CM4 */ - LOG_INFO("%s: bkpt @0x%08X, issuing %s", target_name(target), reset_addr, mode_str); + LOG_INFO("%s: bkpt @0x%08" PRIX32 ", issuing %s", target_name(target), reset_addr, mode_str); /* Workaround for PT-2019, both cores enter LOCKUP state with slow JTAG clock * This happens probably because JTAG pins gets disconnected momentarily when * SYSRESETREQ bit is written causing invalid JTAG state when pins gets connected * back to the DAP by the boot code. */ -#if (0) - mem_ap_write_atomic_u32(armv7m->debug_ap, NVIC_AIRCR, - AIRCR_VECTKEY | rst_mask); -#else mem_ap_write_u32(armv7m->debug_ap, NVIC_AIRCR, AIRCR_VECTKEY | rst_mask); struct adiv5_dap *dap = armv7m->debug_ap->dap; if (dap->ops->sync) { @@ -1604,7 +1578,6 @@ static int psoc6_reset_halt(struct target *target, enum reset_halt_mode mode) /* SWD DAP does not support sync() method, use run() instead */ dap->ops->run(dap); } -#endif jtag_sleep(jtag_get_nsrst_delay() * 1000u); @@ -1630,10 +1603,6 @@ static int psoc6_reset_halt(struct target *target, enum reset_halt_mode mode) /* Remove the break point */ breakpoint_remove(target, reset_addr); - /* Wipe-out previous RTOS state, if any */ - //if (target->rtos_wipe_on_reset_halt) - // rtos_wipe(target); - return ERROR_OK; exit_halt_cpu: @@ -1713,7 +1682,7 @@ COMMAND_HANDLER(psoc6_handle_sflash_restrictions) COMMAND_PARSE_NUMBER(uint, CMD_ARGV[0], restrictions); if (restrictions > 3) { - LOG_ERROR("SFlash restriction level should be in range 0...3"); + command_print(CMD, "SFlash restriction level should be in range 0...3"); return ERROR_COMMAND_ARGUMENT_INVALID; } @@ -1750,8 +1719,8 @@ COMMAND_HANDLER(psoc6_handle_set_region_size) struct flash_bank *bank = get_flash_bank_by_name_noprobe(CMD_ARGV[0]); if (!bank) { - LOG_ERROR("Invalid Flash Bank for psoc6_handle_set_region_size: %s", CMD_ARGV[0]); - return ERROR_COMMAND_SYNTAX_ERROR; + command_print(CMD, "Invalid Flash Bank for psoc6_handle_set_region_size: %s", CMD_ARGV[0]); + return ERROR_COMMAND_ARGUMENT_INVALID; } struct psoc6_bank_info *info = bank->driver_priv; @@ -1790,21 +1759,20 @@ COMMAND_HANDLER(psoc6_handle_sromcall_prepare) COMMAND_HANDLER(psoc6_handle_sromcall) { - if (!CMD_ARGC) { - LOG_ERROR("At least one argument required"); + if (!CMD_ARGC) return ERROR_COMMAND_SYNTAX_ERROR; - } uint32_t sromapi_params[CMD_ARGC]; - for (size_t i = 0; i < CMD_ARGC; i++) { - COMMAND_PARSE_NUMBER(u32, CMD_ARGV[i], sromapi_params[i]); - if (i == 0 && (sromapi_params[i] & 0x01) && CMD_ARGC > 1) { - LOG_ERROR("Additional SROM API parameters can be passed via RAM buffer only, " - "check bit #0 of your SROM API request."); - return ERROR_COMMAND_SYNTAX_ERROR; - } + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], sromapi_params[0]); + if ((sromapi_params[0] & 0x01) && CMD_ARGC > 1) { + LOG_ERROR("Additional SROM API parameters can be passed via RAM buffer only, " + "check bit #0 of your SROM API request."); + return ERROR_COMMAND_SYNTAX_ERROR; } + + for (size_t i = 1; i < CMD_ARGC; i++) + COMMAND_PARSE_NUMBER(u32, CMD_ARGV[i], sromapi_params[i]); struct target *target = get_current_target(CMD_CTX); struct working_area *wa = NULL; @@ -1831,7 +1799,7 @@ COMMAND_HANDLER(psoc6_handle_sromcall) uint32_t data_out; hr = psoc6_call_sromapi(bank, sromapi_params[0], wa ? wa->address : 0, &data_out); if (hr == ERROR_OK && data_out != 0xA0000000) - command_print(CMD, "0x%08X", data_out); + command_print(CMD, "0x%08" PRIX32, data_out); exit_free_wa: if (data_in_ram) @@ -1859,8 +1827,6 @@ COMMAND_HANDLER(psoc6_handle_sromcall_release) *************************************************************************************************/ static int dummy_protect(struct flash_bank *bank, int set, unsigned int first, unsigned int last) { - (void)bank; (void)set; (void)first; (void)last; - LOG_WARNING("Device does not support flash bank protection"); return ERROR_OK; } @@ -1958,7 +1924,6 @@ COMMAND_HANDLER(psoc6_handle_secure_acquire) LOG_INFO("Waiting up to %d.%d sec for the bootloader to open AP #%d...", timeout / 1000u, timeout % 1000u, ap); - //const enum log_levels old_level = change_debug_level(LOG_LVL_USER); psoc6_timeout_init(&to, timeout); const char *error_msg = ""; @@ -1984,7 +1949,6 @@ COMMAND_HANDLER(psoc6_handle_secure_acquire) error_msg = ""; break; }; - //change_debug_level(old_level); if (psoc6_timeout_expired(&to)) { LOG_ERROR("AP #%d is still not opened: %s, giving up", ap, error_msg); @@ -1996,7 +1960,6 @@ COMMAND_HANDLER(psoc6_handle_secure_acquire) LOG_INFO("Waiting up to %d.%d sec for the handshake from the target...", timeout / 1000u, timeout % 1000u); - //change_debug_level(LOG_LVL_USER); psoc6_timeout_init(&to, timeout); while (!psoc6_timeout_expired(&to)) { keep_alive(); @@ -2008,7 +1971,6 @@ COMMAND_HANDLER(psoc6_handle_secure_acquire) if (ipc_data == 0x12344321) break; }; - //change_debug_level(old_level); if (psoc6_timeout_expired(&to)) LOG_WARNING("No handshake from the target, continuing anyway"); diff --git a/src/jtag/drivers/cmsis_dap_usb_bulk.c b/src/jtag/drivers/cmsis_dap_usb_bulk.c deleted file mode 100644 index 17e490f05a..0000000000 --- a/src/jtag/drivers/cmsis_dap_usb_bulk.c +++ /dev/null @@ -1,680 +0,0 @@ -// SPDX-License-Identifier: GPL-2.0-or-later - -/*************************************************************************** - * Copyright (C) 2018 by Mickaël Thomas * - * micka...@gmail.com * - * * - * Copyright (C) 2016 by Maksym Hilliaka * - * o...@frozen-team.com * - * * - * Copyright (C) 2016 by Phillip Pearson * - * p...@myelin.co.nz * - * * - * Copyright (C) 2014 by Paul Fertser * - * fercer...@gmail.com * - * * - * Copyright (C) 2013 by mike brown * - * m...@theshedworks.org.uk * - * * - * Copyright (C) 2013 by Spencer Oliver * - * s...@spen-soft.co.uk * - ***************************************************************************/ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include <helper/system.h> -#include <libusb.h> -#include <helper/log.h> -#include <helper/replacements.h> -#include <jtag/jtag.h> /* ERROR_JTAG_DEVICE_ERROR only */ - -#include "cmsis_dap.h" -#include "libusb_helper.h" - -#if !defined(LIBUSB_API_VERSION) || (LIBUSB_API_VERSION < 0x01000105) \ - || defined(_WIN32) || defined(__CYGWIN__) - #define libusb_dev_mem_alloc(dev, sz) malloc(sz) - #define libusb_dev_mem_free(dev, buffer, sz) free(buffer) -#endif - -enum { - CMSIS_DAP_TRANSFER_PENDING = 0, /* must be 0, used in libusb_handle_events_completed */ - CMSIS_DAP_TRANSFER_IDLE, - CMSIS_DAP_TRANSFER_COMPLETED -}; - -struct cmsis_dap_bulk_transfer { - struct libusb_transfer *transfer; - uint8_t *buffer; - int status; /* either CMSIS_DAP_TRANSFER_ enum or error code */ - int transferred; -}; - -struct cmsis_dap_backend_data { - struct libusb_context *usb_ctx; - struct libusb_device_handle *dev_handle; - unsigned int ep_out; - unsigned int ep_in; - int interface; - - struct cmsis_dap_bulk_transfer command_transfers[MAX_PENDING_REQUESTS]; - struct cmsis_dap_bulk_transfer response_transfers[MAX_PENDING_REQUESTS]; -}; - -static int cmsis_dap_usb_interface = -1; - -static void cmsis_dap_usb_close(struct cmsis_dap *dap); -static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz); -static void cmsis_dap_usb_free(struct cmsis_dap *dap); - -static int cmsis_dap_usb_open(struct cmsis_dap *dap, uint16_t vids[], uint16_t pids[], const char *serial) -{ - int err; - struct libusb_context *ctx; - struct libusb_device **device_list; - - err = libusb_init(&ctx); - if (err) { - LOG_ERROR("libusb initialization failed: %s", libusb_strerror(err)); - return ERROR_FAIL; - } - - int num_devices = libusb_get_device_list(ctx, &device_list); - if (num_devices < 0) { - LOG_ERROR("could not enumerate USB devices: %s", libusb_strerror(num_devices)); - libusb_exit(ctx); - return ERROR_FAIL; - } - - for (int i = 0; i < num_devices; i++) { - struct libusb_device *dev = device_list[i]; - struct libusb_device_descriptor dev_desc; - - err = libusb_get_device_descriptor(dev, &dev_desc); - if (err) { - LOG_ERROR("could not get device descriptor for device %d: %s", i, libusb_strerror(err)); - continue; - } - - /* Match VID/PID */ - - bool id_match = false; - bool id_filter = vids[0] || pids[0]; - for (int id = 0; vids[id] || pids[id]; id++) { - id_match = !vids[id] || dev_desc.idVendor == vids[id]; - id_match &= !pids[id] || dev_desc.idProduct == pids[id]; - - if (id_match) - break; - } - - if (id_filter && !id_match) - continue; - - /* Don't continue if we asked for a serial number and the device doesn't have one */ - if (dev_desc.iSerialNumber == 0 && serial && serial[0]) - continue; - - struct libusb_device_handle *dev_handle = NULL; - err = libusb_open(dev, &dev_handle); - if (err) { - /* It's to be expected that most USB devices can't be opened - * so only report an error if it was explicitly selected - */ - if (id_filter) { - LOG_ERROR("could not open device 0x%04x:0x%04x: %s", - dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err)); - } else { - LOG_DEBUG("could not open device 0x%04x:0x%04x: %s", - dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err)); - } - continue; - } - - /* Match serial number */ - - bool serial_match = false; - char dev_serial[256] = {0}; - if (dev_desc.iSerialNumber > 0) { - err = libusb_get_string_descriptor_ascii( - dev_handle, dev_desc.iSerialNumber, - (uint8_t *)dev_serial, sizeof(dev_serial)); - - if (err < 0) { - const char *msg = "could not read serial number for device 0x%04x:0x%04x: %s"; - if (serial) - LOG_WARNING(msg, dev_desc.idVendor, dev_desc.idProduct, - libusb_strerror(err)); - else - LOG_DEBUG(msg, dev_desc.idVendor, dev_desc.idProduct, - libusb_strerror(err)); - } else if (serial && strncmp(dev_serial, serial, sizeof(dev_serial)) == 0) { - serial_match = true; - } - } - - if (serial && !serial_match) { - libusb_close(dev_handle); - continue; - } - - /* Find the CMSIS-DAP string in product string */ - - bool cmsis_dap_in_product_str = false; - char product_string[256] = {0}; - if (dev_desc.iProduct > 0) { - err = libusb_get_string_descriptor_ascii( - dev_handle, dev_desc.iProduct, - (uint8_t *)product_string, sizeof(product_string)); - if (err < 0) { - LOG_WARNING("could not read product string for device 0x%04x:0x%04x: %s", - dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err)); - } else if (strstr(product_string, "CMSIS-DAP")) { - LOG_DEBUG("found product string of 0x%04x:0x%04x '%s'", - dev_desc.idVendor, dev_desc.idProduct, product_string); - cmsis_dap_in_product_str = true; - } - } - - bool device_identified_reliably = cmsis_dap_in_product_str - || serial_match || id_match; - - /* Find the CMSIS-DAP interface */ - - for (int config = 0; config < dev_desc.bNumConfigurations; config++) { - struct libusb_config_descriptor *config_desc; - err = libusb_get_config_descriptor(dev, config, &config_desc); - if (err) { - LOG_ERROR("could not get configuration descriptor %d for device 0x%04x:0x%04x: %s", - config, dev_desc.idVendor, dev_desc.idProduct, libusb_strerror(err)); - continue; - } - - LOG_DEBUG("enumerating interfaces of 0x%04x:0x%04x", - dev_desc.idVendor, dev_desc.idProduct); - int config_num = config_desc->bConfigurationValue; - const struct libusb_interface_descriptor *intf_desc_candidate = NULL; - const struct libusb_interface_descriptor *intf_desc_found = NULL; - - for (int interface = 0; interface < config_desc->bNumInterfaces; interface++) { - const struct libusb_interface_descriptor *intf_desc = &config_desc->interface[interface].altsetting[0]; - int interface_num = intf_desc->bInterfaceNumber; - - /* Skip this interface if another one was requested explicitly */ - if (cmsis_dap_usb_interface != -1 && cmsis_dap_usb_interface != interface_num) - continue; - - /* CMSIS-DAP v2 spec says: - * - * CMSIS-DAP with default V2 configuration uses WinUSB and is therefore faster. - * Optionally support for streaming SWO trace is provided via an additional USB endpoint. - * - * The WinUSB configuration requires custom class support with the interface setting - * Class Code: 0xFF (Vendor specific) - * Subclass: 0x00 - * Protocol code: 0x00 - * - * Depending on the configuration it uses the following USB endpoints which should be configured - * in the interface descriptor in this order: - * - Endpoint 1: Bulk Out – used for commands received from host PC. - * - Endpoint 2: Bulk In – used for responses send to host PC. - * - Endpoint 3: Bulk In (optional) – used for streaming SWO trace (if enabled with SWO_STREAM). - */ - - /* Search for "CMSIS-DAP" in the interface string */ - bool cmsis_dap_in_interface_str = false; - if (intf_desc->iInterface != 0) { - - char interface_str[256] = {0}; - - err = libusb_get_string_descriptor_ascii( - dev_handle, intf_desc->iInterface, - (uint8_t *)interface_str, sizeof(interface_str)); - if (err < 0) { - LOG_DEBUG("could not read interface string %d for device 0x%04x:0x%04x: %s", - intf_desc->iInterface, - dev_desc.idVendor, dev_desc.idProduct, - libusb_strerror(err)); - } else if (strstr(interface_str, "CMSIS-DAP")) { - cmsis_dap_in_interface_str = true; - LOG_DEBUG("found interface %d string '%s'", - interface_num, interface_str); - } - } - - /* Bypass the following check if this interface was explicitly requested. */ - if (cmsis_dap_usb_interface == -1) { - if (!cmsis_dap_in_product_str && !cmsis_dap_in_interface_str) - continue; - } - - /* check endpoints */ - if (intf_desc->bNumEndpoints < 2) { - LOG_DEBUG("skipping interface %d, has only %d endpoints", - interface_num, intf_desc->bNumEndpoints); - continue; - } - - if ((intf_desc->endpoint[0].bmAttributes & 3) != LIBUSB_TRANSFER_TYPE_BULK || - (intf_desc->endpoint[0].bEndpointAddress & 0x80) != LIBUSB_ENDPOINT_OUT) { - LOG_DEBUG("skipping interface %d, endpoint[0] is not bulk out", - interface_num); - continue; - } - - if ((intf_desc->endpoint[1].bmAttributes & 3) != LIBUSB_TRANSFER_TYPE_BULK || - (intf_desc->endpoint[1].bEndpointAddress & 0x80) != LIBUSB_ENDPOINT_IN) { - LOG_DEBUG("skipping interface %d, endpoint[1] is not bulk in", - interface_num); - continue; - } - - /* We can rely on the interface is really CMSIS-DAP if - * - we've seen CMSIS-DAP in the interface string - * - config asked explicitly for an interface number - * - the device has only one interface - * The later two cases should be honored only if we know - * we are on the right device */ - bool intf_identified_reliably = cmsis_dap_in_interface_str - || (device_identified_reliably && - (cmsis_dap_usb_interface != -1 - || config_desc->bNumInterfaces == 1)); - - if (intf_desc->bInterfaceClass != LIBUSB_CLASS_VENDOR_SPEC || - intf_desc->bInterfaceSubClass != 0 || intf_desc->bInterfaceProtocol != 0) { - /* If the interface is reliably identified - * then we need not insist on setting USB class, subclass and protocol - * exactly as the specification requires. - * Just filter out the well known classes, mainly CDC and MSC. - * At least KitProg3 uses class 0 contrary to the specification */ - if (intf_identified_reliably && - (intf_desc->bInterfaceClass == 0 || intf_desc->bInterfaceClass > 0x12)) { - LOG_WARNING("Using CMSIS-DAPv2 interface %d with wrong class %" PRId8 - " subclass %" PRId8 " or protocol %" PRId8, - interface_num, - intf_desc->bInterfaceClass, - intf_desc->bInterfaceSubClass, - intf_desc->bInterfaceProtocol); - } else { - LOG_DEBUG("skipping interface %d, class %" PRId8 - " subclass %" PRId8 " protocol %" PRId8, - interface_num, - intf_desc->bInterfaceClass, - intf_desc->bInterfaceSubClass, - intf_desc->bInterfaceProtocol); - continue; - - } - } - - if (intf_identified_reliably) { - /* That's the one! */ - intf_desc_found = intf_desc; - break; - } - - if (!intf_desc_candidate && device_identified_reliably) { - /* This interface looks suitable for CMSIS-DAP. Store the pointer to it - * and keep searching for another one with CMSIS-DAP in interface string */ - intf_desc_candidate = intf_desc; - } - } - - if (!intf_desc_found) { - /* We were not able to identify reliably which interface is CMSIS-DAP. - * Let's use the first suitable if we found one */ - intf_desc_found = intf_desc_candidate; - } - - if (!intf_desc_found) { - libusb_free_config_descriptor(config_desc); - continue; - } - - /* We've chosen an interface, connect to it */ - int interface_num = intf_desc_found->bInterfaceNumber; - int packet_size = intf_desc_found->endpoint[0].wMaxPacketSize; - int ep_out = intf_desc_found->endpoint[0].bEndpointAddress; - int ep_in = intf_desc_found->endpoint[1].bEndpointAddress; - - libusb_free_config_descriptor(config_desc); - libusb_free_device_list(device_list, true); - - LOG_INFO("Using CMSIS-DAPv2 interface with VID:PID=0x%04x:0x%04x, serial=%s", - dev_desc.idVendor, dev_desc.idProduct, dev_serial); - - int current_config; - err = libusb_get_configuration(dev_handle, ¤t_config); - if (err) { - LOG_ERROR("could not find current configuration: %s", libusb_strerror(err)); - libusb_close(dev_handle); - libusb_exit(ctx); - return ERROR_FAIL; - } - - if (config_num != current_config) { - err = libusb_set_configuration(dev_handle, config_num); - if (err) { - LOG_ERROR("could not set configuration: %s", libusb_strerror(err)); - libusb_close(dev_handle); - libusb_exit(ctx); - return ERROR_FAIL; - } - } - - err = libusb_claim_interface(dev_handle, interface_num); - if (err) - LOG_WARNING("could not claim interface: %s", libusb_strerror(err)); - - dap->bdata = malloc(sizeof(struct cmsis_dap_backend_data)); - if (!dap->bdata) { - LOG_ERROR("unable to allocate memory"); - libusb_release_interface(dev_handle, interface_num); - libusb_close(dev_handle); - libusb_exit(ctx); - return ERROR_FAIL; - } - - dap->bdata->usb_ctx = ctx; - dap->bdata->dev_handle = dev_handle; - dap->bdata->ep_out = ep_out; - dap->bdata->ep_in = ep_in; - dap->bdata->interface = interface_num; - - for (unsigned int idx = 0; idx < MAX_PENDING_REQUESTS; idx++) { - dap->bdata->command_transfers[idx].status = CMSIS_DAP_TRANSFER_IDLE; - dap->bdata->command_transfers[idx].transfer = libusb_alloc_transfer(0); - if (!dap->bdata->command_transfers[idx].transfer) { - LOG_ERROR("unable to allocate USB transfer"); - cmsis_dap_usb_close(dap); - return ERROR_FAIL; - } - - dap->bdata->response_transfers[idx].status = CMSIS_DAP_TRANSFER_IDLE; - dap->bdata->response_transfers[idx].transfer = libusb_alloc_transfer(0); - if (!dap->bdata->response_transfers[idx].transfer) { - LOG_ERROR("unable to allocate USB transfer"); - cmsis_dap_usb_close(dap); - return ERROR_FAIL; - } - } - - err = cmsis_dap_usb_alloc(dap, packet_size); - if (err != ERROR_OK) - cmsis_dap_usb_close(dap); - - return err; - } - - libusb_close(dev_handle); - } - - libusb_free_device_list(device_list, true); - - libusb_exit(ctx); - return ERROR_FAIL; -} - -static void cmsis_dap_usb_close(struct cmsis_dap *dap) -{ - for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) { - libusb_free_transfer(dap->bdata->command_transfers[i].transfer); - libusb_free_transfer(dap->bdata->response_transfers[i].transfer); - } - cmsis_dap_usb_free(dap); - libusb_release_interface(dap->bdata->dev_handle, dap->bdata->interface); - libusb_close(dap->bdata->dev_handle); - libusb_exit(dap->bdata->usb_ctx); - free(dap->bdata); - dap->bdata = NULL; -} - -static void LIBUSB_CALL cmsis_dap_usb_callback(struct libusb_transfer *transfer) -{ - struct cmsis_dap_bulk_transfer *tr; - - tr = (struct cmsis_dap_bulk_transfer *)transfer->user_data; - if (transfer->status == LIBUSB_TRANSFER_COMPLETED) { - tr->status = CMSIS_DAP_TRANSFER_COMPLETED; - tr->transferred = transfer->actual_length; - } else if (transfer->status == LIBUSB_TRANSFER_TIMED_OUT) { - tr->status = ERROR_TIMEOUT_REACHED; - } else { - tr->status = ERROR_JTAG_DEVICE_ERROR; - } -} - -static int cmsis_dap_usb_read(struct cmsis_dap *dap, int transfer_timeout_ms, - struct timeval *wait_timeout) -{ - int transferred = 0; - int err; - struct cmsis_dap_bulk_transfer *tr; - tr = &dap->bdata->response_transfers[dap->pending_fifo_get_idx]; - - if (tr->status == CMSIS_DAP_TRANSFER_IDLE) { - libusb_fill_bulk_transfer(tr->transfer, - dap->bdata->dev_handle, dap->bdata->ep_in, - tr->buffer, dap->packet_size, - &cmsis_dap_usb_callback, tr, - transfer_timeout_ms); - LOG_DEBUG_IO("submit read @ %u", dap->pending_fifo_get_idx); - tr->status = CMSIS_DAP_TRANSFER_PENDING; - err = libusb_submit_transfer(tr->transfer); - if (err) { - tr->status = CMSIS_DAP_TRANSFER_IDLE; - LOG_ERROR("error submitting USB read: %s", libusb_strerror(err)); - return ERROR_FAIL; - } - } - - struct timeval tv = { - .tv_sec = transfer_timeout_ms / 1000, - .tv_usec = transfer_timeout_ms % 1000 * 1000 - }; - - while (tr->status == CMSIS_DAP_TRANSFER_PENDING) { - err = libusb_handle_events_timeout_completed(dap->bdata->usb_ctx, - wait_timeout ? wait_timeout : &tv, - &tr->status); - if (err) { - LOG_ERROR("error handling USB events: %s", libusb_strerror(err)); - return ERROR_FAIL; - } - if (wait_timeout) - break; - } - - if (tr->status < 0 || tr->status == CMSIS_DAP_TRANSFER_COMPLETED) { - /* Check related command request for an error */ - struct cmsis_dap_bulk_transfer *tr_cmd; - tr_cmd = &dap->bdata->command_transfers[dap->pending_fifo_get_idx]; - if (tr_cmd->status < 0) { - err = tr_cmd->status; - tr_cmd->status = CMSIS_DAP_TRANSFER_IDLE; - if (err != ERROR_TIMEOUT_REACHED) - LOG_ERROR("error writing USB data"); - else - LOG_DEBUG("command write USB timeout @ %u", dap->pending_fifo_get_idx); - - return err; - } - if (tr_cmd->status == CMSIS_DAP_TRANSFER_COMPLETED) - tr_cmd->status = CMSIS_DAP_TRANSFER_IDLE; - } - - if (tr->status < 0) { - err = tr->status; - tr->status = CMSIS_DAP_TRANSFER_IDLE; - if (err != ERROR_TIMEOUT_REACHED) - LOG_ERROR("error reading USB data"); - else - LOG_DEBUG("USB timeout @ %u", dap->pending_fifo_get_idx); - - return err; - } - - if (tr->status == CMSIS_DAP_TRANSFER_COMPLETED) { - transferred = tr->transferred; - LOG_DEBUG_IO("completed read @ %u, transferred %i", - dap->pending_fifo_get_idx, transferred); - memcpy(dap->packet_buffer, tr->buffer, transferred); - memset(&dap->packet_buffer[transferred], 0, dap->packet_buffer_size - transferred); - tr->status = CMSIS_DAP_TRANSFER_IDLE; - } - - return transferred; -} - -static int cmsis_dap_usb_write(struct cmsis_dap *dap, int txlen, int timeout_ms) -{ - int err; - struct cmsis_dap_bulk_transfer *tr; - tr = &dap->bdata->command_transfers[dap->pending_fifo_put_idx]; - - if (tr->status == CMSIS_DAP_TRANSFER_PENDING) { - LOG_ERROR("busy command USB transfer at %u", dap->pending_fifo_put_idx); - struct timeval tv = { - .tv_sec = timeout_ms / 1000, - .tv_usec = timeout_ms % 1000 * 1000 - }; - libusb_handle_events_timeout_completed(dap->bdata->usb_ctx, &tv, &tr->status); - } - if (tr->status < 0) { - if (tr->status != ERROR_TIMEOUT_REACHED) - LOG_ERROR("error writing USB data, late detect"); - else - LOG_DEBUG("USB write timeout @ %u, late detect", dap->pending_fifo_get_idx); - tr->status = CMSIS_DAP_TRANSFER_IDLE; - } - if (tr->status == CMSIS_DAP_TRANSFER_COMPLETED) { - LOG_ERROR("USB write: late transfer competed"); - tr->status = CMSIS_DAP_TRANSFER_IDLE; - } - if (tr->status != CMSIS_DAP_TRANSFER_IDLE) { - libusb_cancel_transfer(tr->transfer); - /* TODO: switch to less verbose errors and wait for USB working again */ - return ERROR_JTAG_DEVICE_ERROR; - } - - memcpy(tr->buffer, dap->packet_buffer, txlen); - - libusb_fill_bulk_transfer(tr->transfer, - dap->bdata->dev_handle, dap->bdata->ep_out, - tr->buffer, txlen, - &cmsis_dap_usb_callback, tr, - timeout_ms); - - LOG_DEBUG_IO("submit write @ %u", dap->pending_fifo_put_idx); - tr->status = CMSIS_DAP_TRANSFER_PENDING; - err = libusb_submit_transfer(tr->transfer); - if (err) { - if (err == LIBUSB_ERROR_BUSY) - libusb_cancel_transfer(tr->transfer); - else - tr->status = CMSIS_DAP_TRANSFER_IDLE; - - LOG_ERROR("error submitting USB write: %s", libusb_strerror(err)); - return ERROR_FAIL; - } - - return ERROR_OK; -} - -static int cmsis_dap_usb_alloc(struct cmsis_dap *dap, unsigned int pkt_sz) -{ - dap->packet_buffer = malloc(pkt_sz); - if (!dap->packet_buffer) { - LOG_ERROR("unable to allocate CMSIS-DAP packet buffer"); - return ERROR_FAIL; - } - - dap->packet_size = pkt_sz; - dap->packet_buffer_size = pkt_sz; - /* Prevent sending zero size USB packets */ - dap->packet_usable_size = pkt_sz - 1; - - dap->command = dap->packet_buffer; - dap->response = dap->packet_buffer; - - for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) { - dap->bdata->command_transfers[i].buffer = - libusb_dev_mem_alloc(dap->bdata->dev_handle, pkt_sz); - if (!dap->bdata->command_transfers[i].buffer) { - LOG_ERROR("unable to allocate CMSIS-DAP packet buffer"); - return ERROR_FAIL; - } - dap->bdata->response_transfers[i].buffer = - libusb_dev_mem_alloc(dap->bdata->dev_handle, pkt_sz); - if (!dap->bdata->response_transfers[i].buffer) { - LOG_ERROR("unable to allocate CMSIS-DAP packet buffer"); - return ERROR_FAIL; - } - } - - return ERROR_OK; -} - -static void cmsis_dap_usb_free(struct cmsis_dap *dap) -{ - for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) { - libusb_dev_mem_free(dap->bdata->dev_handle, - dap->bdata->command_transfers[i].buffer, dap->packet_size); - dap->bdata->command_transfers[i].buffer = NULL; - libusb_dev_mem_free(dap->bdata->dev_handle, - dap->bdata->response_transfers[i].buffer, dap->packet_size); - dap->bdata->response_transfers[i].buffer = NULL; - } - - free(dap->packet_buffer); - dap->packet_buffer = NULL; - dap->command = NULL; - dap->response = NULL; -} - -static void cmsis_dap_usb_cancel_all(struct cmsis_dap *dap) -{ - for (unsigned int i = 0; i < MAX_PENDING_REQUESTS; i++) { - if (dap->bdata->command_transfers[i].status == CMSIS_DAP_TRANSFER_PENDING) - libusb_cancel_transfer(dap->bdata->command_transfers[i].transfer); - if (dap->bdata->response_transfers[i].status == CMSIS_DAP_TRANSFER_PENDING) - libusb_cancel_transfer(dap->bdata->response_transfers[i].transfer); - - dap->bdata->command_transfers[i].status = CMSIS_DAP_TRANSFER_IDLE; - dap->bdata->response_transfers[i].status = CMSIS_DAP_TRANSFER_IDLE; - } -} - -COMMAND_HANDLER(cmsis_dap_handle_usb_interface_command) -{ - if (CMD_ARGC == 1) - COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], cmsis_dap_usb_interface); - else - LOG_ERROR("expected exactly one argument to cmsis_dap_usb_interface <interface_number>"); - - return ERROR_OK; -} - -const struct command_registration cmsis_dap_usb_subcommand_handlers[] = { - { - .name = "interface", - .handler = &cmsis_dap_handle_usb_interface_command, - .mode = COMMAND_CONFIG, - .help = "set the USB interface number to use (for USB bulk backend only)", - .usage = "<interface_number>", - }, - COMMAND_REGISTRATION_DONE -}; - -const struct cmsis_dap_backend cmsis_dap_usb_backend = { - .name = "usb_bulk", - .open = cmsis_dap_usb_open, - .close = cmsis_dap_usb_close, - .read = cmsis_dap_usb_read, - .write = cmsis_dap_usb_write, - .packet_buffer_alloc = cmsis_dap_usb_alloc, - .packet_buffer_free = cmsis_dap_usb_free, - .cancel_all = cmsis_dap_usb_cancel_all, -}; --