Nós fazemos overclock no roteador JTAG


Se você precisar depurar vários microcontroladores / microprocessadores na Crimeia, beba batidos em um escritório abafado em Khimki. Se a placa do microprocessador estiver localizada em um objeto em movimento e não houver maneira de alcançar o depurador JTAG (a placa está localizada em um balão / quadrocóptero). Se você precisar repentinamente de isolamento galvânico entre o host e a placa que está sendo depurada (por exemplo, um dispositivo de alta tensão). E é bom que ainda seja barato, alegre e universal para o fabricante (STM, Broadcom, Xilinx, etc) ou arquitetura (ARM, MIPS, FPGA, etc.). Então você precisa de um roteador, sim, apenas um roteador, por exemplo, assim.

imagem
Imagem de sagemcom.ru

Vamos olhar para dentro:

imagem
wiki.openwrt.org

Portanto, este é o Sagem F @ ST2704 V2, distribuído pela Rostelecom em todo o país. Temos o núcleo da arquitetura SoC BCM6328 MIPS, 320 MHz, um par de portas USB soldadas [1]. Há wi-fi e ethernet. E a melhor parte é o lançamento do openwrt para este modelo. Tudo o que é necessário do equipamento para os objetivos acima.

Imediatamente surge a idéia de pegar o st-link e tentar encaminhar o USB pela rede. Parece uma muleta, provavelmente promete trabalhar não rápido e não é muito estável, a sobrecarga é enorme. Analisamos mais o que pode ser feito.

Você pode portar o openocd para o openwrt, pegar um chip st-link ou ftdi e iniciar o servidor gdb. O benefício no openwrt já portou o openocd. Parece o suficiente para me debruçar sobre esta opção. Mas quero ver quais outras opções o openocd nos oferece. E aqui na documentação a interface sysfsgpio aparece. O que você precisa é possível controlar os sinais tck, tdi, tdo, ferramentas Linux regulares do sistema operacional via / sys / class / gpio nos pinos soldados do chip.

Nós tentamos. Para começar, colete o openwrt (usando a ramificação chaos_calmer) junto com o openocd. Por padrão, nos GPIOs soldados, as funções de indicação de luz são fixas, bem como os botões de pesquisa para executar alguns comandos (rfkill, reset e wpsc). Para que eles não interfiram, eu os desativei removendo os módulos correspondentes do kernel do assembly.

$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 

próprio conjunto:

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

Firmware:

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

Para o teste sysfsgpio, compilamos a configuração:

 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] 

Conecte como na foto:



Lançamos:

 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 

Execute a depuração no IDE, tudo funciona.



Só muito devagar.

Tentamos quantificar a velocidade, acesse o roteador telnet:

 telnet 10.65.9.239 4444 

Nós fazemos um despejo de memória.

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

Hmm, por exemplo, o st-linkv2 no meu host oferece uma velocidade de aproximadamente 45 KiB / s. 20 vezes a diferença!



O ponto, é claro, é devido ao trabalho lento com arquivos em / sys / class / gpio. Bisbilhotando no openocd. Encontre o driver de interface para o RaspberryPi (src / jtag / drivers / bcm2835gpio.c). A julgar pelos testes [5], deve ter uma velocidade semelhante à do st-link. Isso é alcançado, em grande parte, devido ao acesso direto aos registros GPIO. Faremos o mesmo para o nosso SoC, e isso também será válido para toda a família de chips bcm63xx.

essa interface acabou
 /** * @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; } 


Comparado ao sysfsgpio, ele adicionou algumas opções:

  • bcm63xx_gpio_jtag_delay
  • bcm63xx_gpio_adresses

A primeira configuração define o atraso entre a troca de pinos, é um análogo indireto de bcm2835gpio_speed_coeffs para o driver RaspberryPi, que define a frequência jtag. Por exemplo, com um atraso zero, a frequência de comutação era de cerca de um megahertz, tudo funcionava de maneira estável, mas, para a confiabilidade, é melhor poder definir esse parâmetro.

E a segunda opção é um análogo de bcm2835gpio_peripheral_base, apenas para isso é necessário registrar dois endereços para o registrador, que define a função de entrada / saída dos pinos, e o registrador, responsável pelo valor lógico de entrada / saída no gpio. No início, foram obtidos valores de registro dos arquivos de cabeçalho do kernel. Mas nada funcionou com esses valores. Verificou-se que os registros periféricos não podem ser acessados ​​diretamente do espaço do usuário, ou seja, um remapeamento deve ser feito de volta no kernel. É bom que o driver gpio já tenha implementado isso para mim e os valores necessários possam ser obtidos em / proc / iomem.

Adicione nossa interface ao assembly openocd

Lembre-se de adicionar --enable-bcm63xxgpio a CONFIGURE_ARGS no arquivo feeds / packages / utils / openocd / Makefile.

Reconstruímos, instalamos e executamos no roteador:

 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 

Verifique a velocidade do despejo.

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

Muito bom, perdemos duas vezes em algum lugar st-link e framboesa, mas, a olho nu, a diferença não é perceptível. Não há frisos durante a depuração, bem, e espere alguns segundos para piscar durante o firmware - "mostrar".

Todos os testes foram realizados no microcontrolador STM32F103C8T6 e, infelizmente, não havia jtag na placa depurada apenas na interface SWD, na placa depurada. Portanto, não posso garantir o trabalho completo no jtag. Além disso, não devemos esquecer a coordenação dos níveis de sinal (em particular para o MK AVR).

O roteador em si foi retirado de uma pilha de lixo, entre os quais estavam cheios os Sagem F @ st 2704V2 e V7. Infelizmente, todos os dispositivos estavam com defeito. Mas foi possível restaurar a placa sem problemas (consulte [2]).

Se alguém estiver pronto para criar um depurador / programador com esse construtor, ele estará pronto para compartilhar suas ações com o público, sem nenhum custo, assumindo toda a responsabilidade e fundos para o envio (da cidade padrão).

Firmware atualizado aqui .
Eu aviso que as configurações padrão de rede e firewall foram alteradas.

Isso é tudo, boa depuração!

Lista de recursos úteis


  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/pt402233/


All Articles