Wir übertakten den JTAG-Router


Wenn Sie plötzlich mehrere Mikrocontroller / Mikroprozessoren auf der Krim debuggen müssen, trinken Sie Smoothies aus einem stickigen Büro in Khimki. Befindet sich die Mikroprozessorplatine auf einem sich bewegenden Objekt und kann der JTAG-Debugger nicht erreicht werden (die Platine befindet sich auf einem Ballon / Quadrocopter). Wenn Sie plötzlich nur noch eine galvanische Trennung zwischen dem Host und der zu debuggenden Karte benötigen (z. B. ein Hochspannungsgerät). Und es ist gut, dass es für den Hersteller (STM, Broadcom, Xilinx usw.) oder die Architektur (ARM, MIPS, FPGA usw.) immer noch billig, gut gelaunt und universell ist. Dann brauchen Sie einen Router, ja, zum Beispiel nur einen Router.

Bild
Bild von sagemcom.ru

Schauen wir mal rein:

Bild
wiki.openwrt.org

Das ist also Sagem F @ ST2704 V2, das von Rostelecom im ganzen Land vertrieben wird. Wir haben einen SoC BCM6328 MIPS-Architekturkern mit 320 MHz und zwei gelöteten USB-Anschlüssen [1]. Es gibt WiFi und Ethernet. Und das Beste daran ist die Veröffentlichung von openwrt für dieses Modell. Alles, was von der Ausrüstung für die oben genannten Ziele benötigt wird.

Sofort entsteht die Idee, st-link aufzunehmen und zu versuchen, USB über das Netzwerk weiterzuleiten. Es sieht aus wie eine Krücke, verspricht höchstwahrscheinlich, nicht schnell und nicht sehr stabil zu arbeiten, der Overhead ist riesig. Wir schauen uns weiter an, was getan werden kann.

Sie können openocd auf openwrt portieren, einen st-link- oder ftdi-Chip abholen und den gdb-Server starten. Glücklicherweise wurde openocr bereits auf openwrt portiert. Es scheint genug zu sein, um über diese Option nachzudenken. Aber ich möchte sehen, welche anderen Optionen openocd uns bietet. Und hier in der Dokumentation stößt man auf die sysfsgpio-Oberfläche. Was Sie brauchen, ist es möglich, tck, tdi, tdo Signale, reguläre Mittel von OS Linux über / sys / class / gpio auf den gelöteten Pins des Chips zu steuern.

Wir versuchen es. Sammeln Sie zunächst openwrt (mithilfe des Zweigs chaos_calmer) zusammen mit openocd. Standardmäßig sind auf den gelöteten GPIOs Lichtanzeigefunktionen sowie Abfragetasten zum Ausführen einiger Befehle (rfkill, reset und wpsc) festgelegt. Damit sie nicht stören, habe ich sie ausgeschaltet, indem ich die entsprechenden Kernelmodule aus der Assembly entfernt habe.

$cat target/linux/brcm63xx/config-3.18 b/target/linux/brcm63xx/config-3.18 ... # CONFIG_NEW_LEDS is not set … $cat .config … # CONFIG_PACKAGE_kmod-input-gpio-keys-polled is not set ... # CONFIG_PACKAGE_kmod-input-polldev is not set ... CONFIG_PACKAGE_openocd=y 

Montage selbst:

 ./scripts/feeds update -a ./scripts/feeds install -a make V=s 

Firmware:

 mtd -q write openwrt-brcm63xx-generic-F@ST2704V2-squashfs-cfe.bin linux 

Für den sysfsgpio-Test kompilieren wir die Konfiguration:

 root@OpenWrt:~# cat sysfs.cfg.2.11 interface sysfsgpio transport select swd sysfsgpio_swclk_num 482 sysfsgpio_swdio_num 491 source [find target/stm32f1x.cfg] 

Verbinden Sie wie auf dem Foto:



Wir starten:

 root@OpenWrt:~# openocd -f sysfs.cfg.2.11 Open On-Chip Debugger 0.10.0+dev-00085-gfced6ac6-dirty (2017-03-xx-21:49) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html SysfsGPIO num: swclk = 482 SysfsGPIO num: swdio = 491 SysfsGPIO num: trst = 481 adapter speed: 1000 kHz adapter_nsrst_delay: 100 none separate cortex_m reset_config sysresetreq Info : SysfsGPIO JTAG/SWD bitbang driver Info : SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode) Warn : gpio 482 is already exported Warn : gpio 491 is already exported Info : This adapter doesn't support configurable speed Info : SWD DPIDR 0x1ba01477 Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints 

Führen Sie das Debug in der IDE aus, alles funktioniert.



Nur sehr langsam.

Wir versuchen die Geschwindigkeit zu quantifizieren, gehen zum Telnet Router:

 telnet 10.65.9.239 4444 

Wir machen einen Speicherauszug.

 > dump_image dump.bin 0x08000000 0x1ffff dumped 131071 bytes in 55.013523s (2.327 KiB/s) 

Hmm, zum Beispiel gibt st-linkv2 auf meinem Host eine Geschwindigkeit von ungefähr 45 KiB / s an. 20 mal der Unterschied!



Der Punkt ist natürlich auf die langsame Arbeit mit Dateien in / sys / class / gpio zurückzuführen. In openocd herumstöbern. Suchen Sie den Schnittstellentreiber für RaspberryPi (src / jtag / drivers / bcm2835gpio.c). Nach den Tests [5] sollte es eine ähnliche Geschwindigkeit wie st-link haben. Dies wird zum großen Teil durch den direkten Zugriff auf die GPIO-Register erreicht. Wir werden dasselbe für unseren SoC tun, und dies gilt auch für die gesamte bcm63xx-Chipfamilie.

eine solche Schnittstelle stellte sich heraus
 /** * @file * This driver implements a bitbang jtag interface using gpio lines via * router ob BCM63XX SoC. * The aim of this driver implementation is use system GPIOs but avoid the * need for a additional kernel driver. * (Note memory mapped IO is another option, however it doesn't mix well with * the kernel gpiolib driver - which makes sense I guess.) * * A gpio is required for tck, tms, tdi and tdo. One or both of srst and trst * must be also be specified. The required jtag gpios are specified via the * bcm63xx_gpio_jtag_nums command or the relevant bcm63xx_gpio_XXX_num commang. * The srst and trst gpios are set via the bcm63xx_gpio_srst_num and * bcm63xx_gpio_trst_num respectively. GPIO numbering follows the kernel * convention of starting from 0. * * The gpios should not be in use by another entity, and must not be requested * by a kernel driver without also being exported by it (otherwise they can't * be exported by bcm63xx_). * * The bcm63xx gpio interface can only manipulate one gpio at a time, so the * bitbang write handler remembers the last state for tck, tms, tdi to avoid * superfluous writes. * For speed the bcm63xx "value" entry is opened at init and held open. * This results in considerable gains over open-write-close (45s vs 900s) * * Further work could address: * -srst and trst open drain/ push pull * -configurable active high/low for srst & trst */ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include <jtag/interface.h> #include "bitbang.h" #include <sys/mman.h> /* * Helper func to determine if gpio number valid * * Assume here that there will be less than 1000 gpios on a system */ static int is_gpio_valid(int gpio) { return gpio >= 0 && gpio < 32; } off_t address_dir = NULL; off_t address_val = NULL; static int dev_mem_fd = -1; static volatile uint32_t *pio_base = NULL; static volatile uint32_t *pval_base = NULL; static volatile uint32_t *pads_base = NULL; static unsigned int jtag_delay = 0; static void set_dir_gpio(const int gpio, const int direction) { if(direction) *pio_base |= 1 << gpio; else *pio_base &= ~(1 << gpio); } static void set_value_gpio(const int gpio, const int value) { if(value) *pval_base |= 1 << gpio; else *pval_base &= ~(1 << gpio); for (unsigned int i = 0; i < jtag_delay; i++) asm volatile (""); } static int read_gpio(const int gpio) { uint32_t val = *pval_base & (1 << gpio); val = val ? 1 : 0; return val; } static int setup_bcm63xx_gpio(int gpio, int is_output, int init_high) { char buf[40]; char gpiostr[4]; int ret; if (!is_gpio_valid(gpio)) return ERROR_OK; if((address_dir == NULL) || (address_val == NULL)){ perror("address of gpio register don't set"); return ERROR_FAIL; } if( dev_mem_fd < 0 ) { dev_mem_fd = open("/dev/mem", O_RDWR | O_SYNC); if (dev_mem_fd < 0) { perror("open"); return ERROR_FAIL; } const uint32_t mapped_size = getpagesize(); const off_t target_mmap = address_dir & ~(off_t)(mapped_size - 1); pads_base = mmap(NULL, mapped_size, PROT_READ | PROT_WRITE, MAP_SHARED, dev_mem_fd, target_mmap); if (pads_base == MAP_FAILED) { perror("mmap. Check correct register address."); close(dev_mem_fd); return ERROR_FAIL; } pio_base = (char*)pads_base + (unsigned)(address_dir - target_mmap); pval_base = (char*)pads_base + (unsigned)(address_val - target_mmap); } set_dir_gpio(gpio, is_output); set_value_gpio(gpio, init_high); return 0; } /* gpio numbers for each gpio. Negative values are invalid */ static int tck_gpio = -1; static int tms_gpio = -1; static int tdi_gpio = -1; static int tdo_gpio = -1; static int trst_gpio = -1; static int srst_gpio = -1; static int swclk_gpio = -1; static int swdio_gpio = -1; /* * file descriptors for /sys/class/gpio/gpioXX/value * Set up during init. */ static int tck_fd = -1; static int tms_fd = -1; static int tdi_fd = -1; static int tdo_fd = -1; static int trst_fd = -1; static int srst_fd = -1; static int swclk_fd = -1; static int swdio_fd = -1; static int last_swclk; static int last_swdio; static bool last_stored; static bool swdio_input; static void bcm63xx_gpio_swdio_drive(bool is_output) { set_dir_gpio(swdio_gpio, is_output ? 1 : 0); last_stored = false; swdio_input = !is_output; } static int bcm63xx_gpio_swdio_read(void) { return read_gpio(swdio_gpio); } static void bcm63xx_gpio_swdio_write(int swclk, int swdio) { const char one[] = "1"; const char zero[] = "0"; size_t bytes_written; if (!swdio_input) { if (!last_stored || (swdio != last_swdio)) { set_value_gpio(swdio_gpio, swdio ? 1 : 0); } } /* write swclk last */ if (!last_stored || (swclk != last_swclk)) { set_value_gpio(swclk_gpio, swclk ? 1 : 0); } last_swdio = swdio; last_swclk = swclk; last_stored = true; } /* * Bitbang interface read of TDO * * The bcm63xx value will read back either '0' or '1'. The trick here is to call * lseek to bypass buffering in the bcm63xx kernel driver. */ static int bcm63xx_gpio_read(void) { return read_gpio(tdo_gpio); } /* * Bitbang interface write of TCK, TMS, TDI * * Seeing as this is the only function where the outputs are changed, * we can cache the old value to avoid needlessly writing it. */ static void bcm63xx_gpio_write(int tck, int tms, int tdi) { if (swd_mode) { bcm63xx_gpio_swdio_write(tck, tdi); return; } const char one[] = "1"; const char zero[] = "0"; static int last_tck; static int last_tms; static int last_tdi; static int first_time; size_t bytes_written; if (!first_time) { last_tck = !tck; last_tms = !tms; last_tdi = !tdi; first_time = 1; } if (tdi != last_tdi) { set_value_gpio(tdi_gpio,tdi); } if (tms != last_tms) { set_value_gpio(tms_gpio,tms); } /* write clk last */ if (tck != last_tck) { set_value_gpio(tck_gpio,tck); } last_tdi = tdi; last_tms = tms; last_tck = tck; } /* * Bitbang interface to manipulate reset lines SRST and TRST * * (1) assert or (0) deassert reset lines */ static void bcm63xx_gpio_reset(int trst, int srst) { LOG_DEBUG("bcm63xx_gpio_reset"); const char one[] = "1"; const char zero[] = "0"; size_t bytes_written; /* assume active low */ if (srst_fd >= 0) { set_value_gpio(srst_gpio,srst); } /* assume active low */ if (trst_fd >= 0) { set_value_gpio(trst_gpio,trst); } } COMMAND_HANDLER(bcm63xx_gpio_handle_jtag_gpionums) { if (CMD_ARGC == 4) { COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio); COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], tms_gpio); COMMAND_PARSE_NUMBER(int, CMD_ARGV[2], tdi_gpio); COMMAND_PARSE_NUMBER(int, CMD_ARGV[3], tdo_gpio); } else if (CMD_ARGC != 0) { return ERROR_COMMAND_SYNTAX_ERROR; } command_print(CMD_CTX, "bcm63xx_GPIO nums: tck = %d, tms = %d, tdi = %d, tdo = %d", tck_gpio, tms_gpio, tdi_gpio, tdo_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm63xx_gpio_handle_jtag_gpionum_tck) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tck_gpio); command_print(CMD_CTX, "bcm63xx_GPIO num: tck = %d", tck_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm63xx_gpio_handle_jtag_gpionum_tms) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tms_gpio); command_print(CMD_CTX, "bcm63xx_GPIO num: tms = %d", tms_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm63xx_gpio_handle_jtag_gpionum_tdo) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdo_gpio); command_print(CMD_CTX, "bcm63xx_GPIO num: tdo = %d", tdo_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm63xx_gpio_handle_jtag_gpionum_tdi) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], tdi_gpio); command_print(CMD_CTX, "bcm63xx_GPIO num: tdi = %d", tdi_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm63xx_gpio_handle_jtag_gpionum_srst) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], srst_gpio); command_print(CMD_CTX, "bcm63xx_GPIO num: srst = %d", srst_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm63xx_gpio_handle_jtag_gpionum_trst) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], trst_gpio); command_print(CMD_CTX, "bcm63xx_GPIO num: trst = %d", trst_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm63xx_gpio_handle_swd_gpionums) { if (CMD_ARGC == 2) { COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio); COMMAND_PARSE_NUMBER(int, CMD_ARGV[1], swdio_gpio); } else if (CMD_ARGC != 0) { return ERROR_COMMAND_SYNTAX_ERROR; } command_print(CMD_CTX, "bcm63xx_GPIO nums: swclk = %d, swdio = %d", swclk_gpio, swdio_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm63xx_gpio_handle_swd_gpionum_swclk) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swclk_gpio); command_print(CMD_CTX, "bcm63xx_GPIO num: swclk = %d", swclk_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm63xx_gpio_handle_swd_gpionum_swdio) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], swdio_gpio); command_print(CMD_CTX, "bcm63xx_GPIO num: swdio = %d", swdio_gpio); return ERROR_OK; } COMMAND_HANDLER(bcm63xx_gpio_jtag_delay) { if (CMD_ARGC == 1) COMMAND_PARSE_NUMBER(int, CMD_ARGV[0], jtag_delay); command_print(CMD_CTX, "bcm63xx_GPIO jtag_delay:= %d tics", jtag_delay); return ERROR_OK; } COMMAND_HANDLER(bcm63xx_gpio_adresses) { if (CMD_ARGC == 2) { COMMAND_PARSE_NUMBER(u32, CMD_ARGV[0], address_dir); COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], address_val); } else if (CMD_ARGC != 0) { return ERROR_COMMAND_SYNTAX_ERROR; } command_print(CMD_CTX, "bcm63xx_GPIO address: direction = %x, value = %x", address_dir, address_val); return ERROR_OK; } static const struct command_registration bcm63xx_gpio_command_handlers[] = { { .name = "bcm63xx_gpio_jtag_nums", .handler = &bcm63xx_gpio_handle_jtag_gpionums, .mode = COMMAND_CONFIG, .help = "gpio numbers for tck, tms, tdi, tdo. (in that order)", .usage = "(tck tms tdi tdo)* ", }, { .name = "bcm63xx_gpio_tck_num", .handler = &bcm63xx_gpio_handle_jtag_gpionum_tck, .mode = COMMAND_CONFIG, .help = "gpio number for tck.", }, { .name = "bcm63xx_gpio_tms_num", .handler = &bcm63xx_gpio_handle_jtag_gpionum_tms, .mode = COMMAND_CONFIG, .help = "gpio number for tms.", }, { .name = "bcm63xx_gpio_tdo_num", .handler = &bcm63xx_gpio_handle_jtag_gpionum_tdo, .mode = COMMAND_CONFIG, .help = "gpio number for tdo.", }, { .name = "bcm63xx_gpio_tdi_num", .handler = &bcm63xx_gpio_handle_jtag_gpionum_tdi, .mode = COMMAND_CONFIG, .help = "gpio number for tdi.", }, { .name = "bcm63xx_gpio_srst_num", .handler = &bcm63xx_gpio_handle_jtag_gpionum_srst, .mode = COMMAND_CONFIG, .help = "gpio number for srst.", }, { .name = "bcm63xx_gpio_trst_num", .handler = &bcm63xx_gpio_handle_jtag_gpionum_trst, .mode = COMMAND_CONFIG, .help = "gpio number for trst.", }, { .name = "bcm63xx_gpio_swd_nums", .handler = &bcm63xx_gpio_handle_swd_gpionums, .mode = COMMAND_CONFIG, .help = "gpio numbers for swclk, swdio. (in that order)", .usage = "(swclk swdio)* ", }, { .name = "bcm63xx_gpio_swclk_num", .handler = &bcm63xx_gpio_handle_swd_gpionum_swclk, .mode = COMMAND_CONFIG, .help = "gpio number for swclk.", }, { .name = "bcm63xx_gpio_swdio_num", .handler = &bcm63xx_gpio_handle_swd_gpionum_swdio, .mode = COMMAND_CONFIG, .help = "gpio number for swdio.", }, { .name = "bcm63xx_gpio_jtag_delay", .handler = &bcm63xx_gpio_jtag_delay, .mode = COMMAND_CONFIG, .help = "qty tics gpio delay.", }, { .name = "bcm63xx_gpio_adresses", .handler = &bcm63xx_gpio_adresses, .mode = COMMAND_CONFIG, .help = "addresses for direction and value setup. (in that order)", .usage = "(address_dir address_val)* ", }, COMMAND_REGISTRATION_DONE }; static int bcm63xx_gpio_init(void); static int bcm63xx_gpio_quit(void); static const char * const bcm63xx_gpio_transports[] = { "jtag", "swd", NULL }; struct jtag_interface bcm63xxgpio_interface = { .name = "bcm63xxgpio", .supported = DEBUG_CAP_TMS_SEQ, .execute_queue = bitbang_execute_queue, .transports = bcm63xx_gpio_transports, .swd = &bitbang_swd, .commands = bcm63xx_gpio_command_handlers, .init = bcm63xx_gpio_init, .quit = bcm63xx_gpio_quit, }; static struct bitbang_interface bcm63xx_gpio_bitbang = { .read = bcm63xx_gpio_read, .write = bcm63xx_gpio_write, .reset = bcm63xx_gpio_reset, .swdio_read = bcm63xx_gpio_swdio_read, .swdio_drive = bcm63xx_gpio_swdio_drive, .blink = 0 }; static void unusing_all_gpio(void) { munmap(pads_base, sysconf(_SC_PAGE_SIZE)); close(dev_mem_fd); LOG_INFO("unusing_all_gpio\n"); } static bool bcm63xx_gpio_jtag_mode_possible(void) { if (!is_gpio_valid(tck_gpio)) return 0; if (!is_gpio_valid(tms_gpio)) return 0; if (!is_gpio_valid(tdi_gpio)) return 0; if (!is_gpio_valid(tdo_gpio)) return 0; return 1; } static bool bcm63xx_gpio_swd_mode_possible(void) { if (!is_gpio_valid(swclk_gpio)) return 0; if (!is_gpio_valid(swdio_gpio)) return 0; return 1; } static int bcm63xx_gpio_init(void) { bitbang_interface = &bcm63xx_gpio_bitbang; LOG_INFO("bcm63xx_gpio JTAG/SWD bitbang driver"); if (bcm63xx_gpio_jtag_mode_possible()) { if (bcm63xx_gpio_swd_mode_possible()) LOG_INFO("JTAG and SWD modes enabled"); else LOG_INFO("JTAG only mode enabled (specify swclk and swdio gpio to add SWD mode)"); if (!is_gpio_valid(trst_gpio) && !is_gpio_valid(srst_gpio)) { LOG_ERROR("Require at least one of trst or srst gpios to be specified"); return ERROR_JTAG_INIT_FAILED; } } else if (bcm63xx_gpio_swd_mode_possible()) { LOG_INFO("SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode)"); } else { LOG_ERROR("Require tck, tms, tdi and tdo gpios for JTAG mode and/or swclk and swdio gpio for SWD mode"); return ERROR_JTAG_INIT_FAILED; } /* * Configure TDO as an input, and TDI, TCK, TMS, TRST, SRST * as outputs. Drive TDI and TCK low, and TMS/TRST/SRST high. * For SWD, SWCLK and SWDIO are configures as output high. */ if (tck_gpio >= 0) { tck_fd = setup_bcm63xx_gpio(tck_gpio, 1, 0); if (tck_fd < 0) goto out_error; } if (tms_gpio >= 0) { tms_fd = setup_bcm63xx_gpio(tms_gpio, 1, 1); if (tms_fd < 0) goto out_error; } if (tdi_gpio >= 0) { tdi_fd = setup_bcm63xx_gpio(tdi_gpio, 1, 0); if (tdi_fd < 0) goto out_error; } if (tdo_gpio >= 0) { tdo_fd = setup_bcm63xx_gpio(tdo_gpio, 0, 0); if (tdo_fd < 0) goto out_error; } /* assume active low*/ if (trst_gpio >= 0) { trst_fd = setup_bcm63xx_gpio(trst_gpio, 1, 1); if (trst_fd < 0) goto out_error; } /* assume active low*/ if (srst_gpio >= 0) { srst_fd = setup_bcm63xx_gpio(srst_gpio, 1, 1); if (srst_fd < 0) goto out_error; } if (swclk_gpio >= 0) { swclk_fd = setup_bcm63xx_gpio(swclk_gpio, 1, 0); if (swclk_fd < 0) goto out_error; } if (swdio_gpio >= 0) { swdio_fd = setup_bcm63xx_gpio(swdio_gpio, 1, 0); if (swdio_fd < 0) goto out_error; } if (bcm63xx_gpio_swd_mode_possible()) { if (swd_mode) bitbang_swd_switch_seq(JTAG_TO_SWD); else bitbang_swd_switch_seq(SWD_TO_JTAG); } return ERROR_OK; out_error: unusing_all_gpio(); return ERROR_JTAG_INIT_FAILED; } static int bcm63xx_gpio_quit(void) { unusing_all_gpio(); return ERROR_OK; } 


Im Vergleich zu sysfsgpio wurden einige Optionen hinzugefügt:

  • bcm63xx_gpio_jtag_delay
  • bcm63xx_gpio_adresses

Die erste Einstellung legt die Verzögerung zwischen den Schaltstiften fest. Sie ist ein indirektes Analogon von bcm2835gpio_speed_coeffs für den RaspberryPi-Treiber, der die jtag-Frequenz festlegt. Bei einer Verzögerung von Null betrug die Schaltfrequenz beispielsweise etwa einen Megahertz, alles funktionierte recht stabil, aber aus Gründen der Zuverlässigkeit ist es besser, diesen Parameter einstellen zu können.

Und die zweite Option ist ein Analogon von bcm2835gpio_peripheral_base. Nur dafür müssen Sie zwei Adressen für das Register registrieren, das die Eingabe- / Ausgabefunktion der Pins festlegt, und das Register, das für den logischen Eingabe- / Ausgabewert auf gpio verantwortlich ist. Am Anfang wurden Registerwerte aus den Kernel-Header-Dateien übernommen. Aber mit diesen Werten hat nichts funktioniert. Es stellte sich heraus, dass auf Peripherieregister nicht direkt vom Benutzerraum aus zugegriffen werden kann, d. H. Eine Neuzuordnung muss im Kernel vorgenommen werden. Es ist gut, dass der GPIO-Treiber dies bereits für mich implementiert hat und die erforderlichen Werte aus / proc / iomem entnommen werden können.

Fügen Sie unsere Schnittstelle zur openocd-Assembly hinzu

Denken Sie daran, CONFIGURE_ARGS in der Datei feeds / packages / utils / openocd / Makefile --enable-bcm63xxgpio hinzuzufügen.

Wir bauen den Router neu auf, installieren ihn und führen ihn aus:

 root@OpenWrt:~# openocd -f interface/bcm63xx-swd.cfg -f target/stm32f1x.cfg Open On-Chip Debugger 0.10.0+dev-00085-gfced6ac6-dirty (2017-03-xx-21:49) Licensed under GNU GPL v2 For bug reports, read http://openocd.org/doc/doxygen/bugs.html bcm63xx_GPIO num: swclk = 2 bcm63xx_GPIO num: swdio = 11 bcm63xx_GPIO jtag_delay:= 10 tics bcm63xx_GPIO address: direction = 10000084, value = 1000008c adapter speed: 1000 kHz adapter_nsrst_delay: 100 none separate cortex_m reset_config sysresetreq Info : bcm63xx_gpio JTAG/SWD bitbang driver Info : SWD only mode enabled (specify tck, tms, tdi and tdo gpios to add JTAG mode) Info : This adapter doesn't support configurable speed Info : SWD DPIDR 0x1ba01477 Info : stm32f1x.cpu: hardware has 6 breakpoints, 4 watchpoints 

Überprüfen Sie die Geschwindigkeit des Dumps.

 > dump_image dump.bin 0x08000000 0x1ffff dumped 131071 bytes in 4.729815s (27.062 KiB/s) 

Sehr gut, wir verlieren zweimal irgendwo St-Link und Himbeere, aber mit dem Auge ist der Unterschied nicht spürbar. Während des Debuggens treten keine Friese auf, und warten Sie einige Sekunden, bis sie während der Firmware blinken - "Angeberei".

Alle Tests wurden auf dem Mikrocontroller STM32F103C8T6 durchgeführt, und leider gab es auf der debuggten Karte nur auf der SWD-Schnittstelle und auf der debuggten Karte kein jtag. Dementsprechend kann ich daher keine vollständige Arbeit an jtag garantieren. Darüber hinaus dürfen wir die Koordination der Signalpegel (insbesondere für MK AVR) nicht vergessen.

Der Router selbst wurde von einem Müllhaufen genommen, unter dem sich Sagem F @ st 2704V2 und V7 befanden. Leider waren alle Geräte außer Betrieb. Die Karte konnte jedoch problemlos wiederhergestellt werden (siehe [2]).

Wenn jemand bereit ist, aus diesem Konstruktor einen Debugger / Programmierer zu machen, ist er bereit, seine Vorräte kostenlos an die Öffentlichkeit zu teilen, wobei er alle Verantwortung und Mittel für die Weiterleitung (von der Standardstadt) übernimmt.

Firmware hier aktualisiert.
Ich warne Sie, dass die Standardeinstellungen für Netzwerk und Firewall geändert wurden.

Das ist alles, gutes Debuggen!

Liste nützlicher Ressourcen


  1. wiki.openwrt.org/toh/sagem/fast2704
  2. radiohlam.ru/forum/viewtopic.php?f=54&t=3749
  3. openocd.org
  4. developer.mbed.org/handbook/CMSIS-DAP
  5. github.com/rogerclarkmelbourne/Arduino_STM32/wiki/Programming-an-STM32F103XXX-with-a-generic-ST-Link-V2-programmer-from-Linux

Source: https://habr.com/ru/post/de402233/


All Articles