Микроконтроллеры

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Микроконтроллеры » Архив » J-Link совместимый дебаггер на CH551


J-Link совместимый дебаггер на CH551

Сообщений 1 страница 8 из 8

1

Ну, точнее говоря, libjaylink совместимый - https://repo.or.cz/libjaylink.git
OpenOCD работает с j-link через libjaylink и принимает такой дебаггер за j-link
Протокол j-link опубликован - https://archive.org/details/segger-jlin … rotocol-r7
OpenOCD и libjaylink - open source
Жаль только, что openocd для j-link не настраивается на произвольные usb vid/pid, и приходится использовать segger-овские

Протоколы j-link и swd укладываются в 100 строчек кода

Код:
__xdata struct { uint8_t r [ 252 ], t [ 124 ]; } jay_buf;
        struct { uint8_t r,         t;         } jay_ind, jay_len;
uint16_t jay_numbits;

const uint8_t jay_caps     [ 4 ] = { 3, 8, 2 };         /* hw_ver free_mem sel_if */
const uint8_t jay_free_mem [ 4 ] = { 0xFC };            /* 252 */
const uint8_t jay_hw_stat  [ 8 ] = { 5, 0xD };          /* 3333 */
const uint8_t jay_hw_ver   [ 4 ] = { 0xD1, 0x2F, 1 };   /* 77777 */
const uint8_t jay_sel_if   [ 4 ] = { 2 };               /* mask */
const uint8_t jay_ver   [ 0x22 ] = "\x20\x00Jay CH55x";

void jay_init ( void ) {
    GPIO_SWCLOCK( 0 );
    GPIO_SWCLOCK_MODE();
    GPIO_SWDIN_MODE();
    jay_ind.r = jay_len.r = 0;
    jay_ind.t = jay_len.t = 0;
}

void jay_reply ( uint8_t *buf, uint8_t len ) {
    jay_ind.t = jay_len.t = 0;
    for( uint8_t i = 0; i < len; i++ ) jay_buf.t[ jay_len.t++ ] = buf[ i ];
}

uint8_t jay_protocol ( void ) {
    switch( jay_buf.r[ 0 ] ) {
        case 0x01 : jay_reply( jay_ver, sizeof( jay_ver ));
                    break;
        case 0x07 : jay_reply( jay_hw_stat, sizeof( jay_hw_stat ));
                    break;
        case 0xC7 : jay_reply( jay_sel_if, sizeof( jay_sel_if ));
                    if( jay_buf.r[ 1 ] != 0xFF ) jay_buf.t[ 0 ] = 1;
                    break;
        case 0xCF : jay_numbits = *(( uint16_t* ) &jay_buf.r[ 2 ] );
                    return 4 + 2 * (( jay_numbits + 7 ) >> 3 );
        case 0xD4 : jay_reply( jay_free_mem, sizeof( jay_free_mem ));
                    break;
        case 0xDC : GPIO_RESET( 0 );
                    break;
        case 0xDD : GPIO_RESET( 1 );
                    break;
        case 0xE8 : jay_reply( jay_caps, sizeof( jay_caps ));
                    break;
        case 0xF0 : jay_reply( jay_hw_ver, sizeof( jay_hw_ver ));
    }
    return 0;
}

void jay_swd ( void ) {
    uint8_t dir, in, mask, out;
    dir = in = mask = out = 0;
    jay_ind.r = 4;
    jay_len.r = 4 + (( jay_numbits + 7 ) >> 3 );
    jay_ind.t = jay_len.t = 0;
    while( jay_numbits-- ) {
        if( mask == 0 ) {
            mask = 1;
            dir = jay_buf.r[ jay_ind.r++ ];
            out = jay_buf.r[ jay_len.r++ ];
            in = 0;
        }
        if( dir & mask ) {
            GPIO_SWDOUT_MODE();
            GPIO_SWDOUT( out & mask );
        } else {
            GPIO_SWDIN_MODE();
        }
        GPIO_SWCLOCK( 0 ); GPIO_DELAY();
        GPIO_SWCLOCK( 1 ); GPIO_DELAY();
        in |= GPIO_SWDIN() ? mask : 0;
        mask <<= 1;
        if( mask == 0 ) jay_buf.t[ jay_len.t++ ] = in;
    }
    if( mask ) jay_buf.t[ jay_len.t++ ] = in;
    jay_buf.t[ jay_len.t++ ] = 0;
    GPIO_SWCLOCK( 0 );
}

void jay_poll ( uint8_t *rbuf, uint8_t *rlen, uint8_t *tbuf, uint8_t *tlen ) {
    uint8_t i, len;
    if( jay_len.t ) {
        if( *tlen == 0 ) {
            len = jay_len.t - jay_ind.t;
            if( len > 64 ) len = 64; else if( len > 1 ) len--;
            for( i = 0; i < len; i++ ) tbuf[ i ] = jay_buf.t[ jay_ind.t++ ];
            if( jay_ind.t >= jay_len.t ) jay_ind.t = jay_len.t = 0;
            *tlen = len;
        }
    } else if( *rlen ) {
        len = *rlen;
        for( i = 0; i < len; i++ ) jay_buf.r[ jay_ind.r++ ] = rbuf[ i ];
        if( jay_len.r == 0 ) jay_len.r = jay_protocol();
        if( jay_ind.r >= jay_len.r ) {
            if( jay_buf.r[ 0 ] == 0xCF ) jay_swd();
            jay_ind.r = jay_len.r = 0;
        }
        *rlen = 0;
    }
}

Поскольку единственная привязка к мк там - это тип __xdata для xram в sdcc, то всё это легко переносится на любой мк
Для ch551 вся программа, использующая этот код, выглядит так:

Код:
#include <stdint.h>
#include <string.h>
#include <compiler.h>
#include <8051.h>
#include "timer.c"
#include "usb.c"
#include "gpio.c"
#include "jay.c"
void main ( void ) {
    timer_init();
    usb_init();
    jay_init();
loop:
    timer_poll();
    usb_poll();
    jay_poll( usb_buf1.r, &usb_len1.r, usb_buf1.t, &usb_len1.t );
    goto loop;
}

USB дескрипторы:

Код:
    ---------------------- Device Descriptor ----------------------
bLength                  : 0x12 (18 bytes)
bDescriptorType          : 0x01 (Device Descriptor)
bcdUSB                   : 0x110 (USB Version 1.10)
bDeviceClass             : 0x00 (defined by the interface descriptors)
bDeviceSubClass          : 0x00
bDeviceProtocol          : 0x00
bMaxPacketSize0          : 0x08 (8 bytes)
idVendor                 : 0x1366
idProduct                : 0x0104
bcdDevice                : 0x5504
iManufacturer            : 0x00 (No String Descriptor)
iProduct                 : 0x02 (String Descriptor 2)
 Language 0x0409         : "Jay"
iSerialNumber            : 0x03 (String Descriptor 3)
 Language 0x0409         : "12345"
bNumConfigurations       : 0x01 (1 Configuration)
Data (HexDump)           : 12 01 10 01 00 00 00 08 66 13 04 01 04 55 00 02
                           03 01                                          

    ------------------ Configuration Descriptor -------------------
bLength                  : 0x09 (9 bytes)
bDescriptorType          : 0x02 (Configuration Descriptor)
wTotalLength             : 0x0020 (32 bytes)
bNumInterfaces           : 0x01 (1 Interface)
bConfigurationValue      : 0x01 (Configuration 1)
iConfiguration           : 0x00 (No String Descriptor)
bmAttributes             : 0x80
 D7: Reserved, set 1     : 0x01
 D6: Self Powered        : 0x00 (no)
 D5: Remote Wakeup       : 0x00 (no)
 D4..0: Reserved, set 0  : 0x00
MaxPower                 : 0x64 (200 mA)
Data (HexDump)           : 09 02 20 00 01 01 00 80 64 09 04 00 00 02 FF FF
                           FF 00 07 05 01 02 40 00 00 07 05 81 02 40 00 00

        ---------------- Interface Descriptor -----------------
bLength                  : 0x09 (9 bytes)
bDescriptorType          : 0x04 (Interface Descriptor)
bInterfaceNumber         : 0x00
bAlternateSetting        : 0x00
bNumEndpoints            : 0x02 (2 Endpoints)
bInterfaceClass          : 0xFF (Vendor Specific)
bInterfaceSubClass       : 0xFF
bInterfaceProtocol       : 0xFF
iInterface               : 0x00 (No String Descriptor)
Data (HexDump)           : 09 04 00 00 02 FF FF FF 00                     

        ----------------- Endpoint Descriptor -----------------
bLength                  : 0x07 (7 bytes)
bDescriptorType          : 0x05 (Endpoint Descriptor)
bEndpointAddress         : 0x01 (Direction=OUT EndpointID=1)
bmAttributes             : 0x02 (TransferType=Bulk)
wMaxPacketSize           : 0x0040 (64 bytes)
bInterval                : 0x00 (ignored)
Data (HexDump)           : 07 05 01 02 40 00 00                           

        ----------------- Endpoint Descriptor -----------------
bLength                  : 0x07 (7 bytes)
bDescriptorType          : 0x05 (Endpoint Descriptor)
bEndpointAddress         : 0x81 (Direction=IN EndpointID=1)
bmAttributes             : 0x02 (TransferType=Bulk)
wMaxPacketSize           : 0x0040 (64 bytes)
bInterval                : 0x00 (ignored)
Data (HexDump)           : 07 05 81 02 40 00 00                           

      -------------------- String Descriptors -------------------
             ------ String Descriptor 0 ------
bLength                  : 0x04 (4 bytes)
bDescriptorType          : 0x03 (String Descriptor)
Language ID[0]           : 0x0409 (English - United States)
Data (HexDump)           : 04 03 09 04                                    
             ------ String Descriptor 2 ------
bLength                  : 0x08 (8 bytes)
bDescriptorType          : 0x03 (String Descriptor)
Language 0x0409          : "Jay"
Data (HexDump)           : 08 03 4A 00 61 00 79 00                        
             ------ String Descriptor 3 ------
bLength                  : 0x0C (12 bytes)
bDescriptorType          : 0x03 (String Descriptor)
Language 0x0409          : "12345"
Data (HexDump)           : 0C 03 31 00 32 00 33 00 34 00 35 00

           

Готовая прошивка для ch551 и ch552 - https://disk.yandex.ru/d/hchFImQVyT8WCA
Распиновка для этой прошивки:
P1.7 - SWCLK
P1.5 - SWDIO
P1.4 - RESET
P1.6 - LED

http://forumupload.ru/uploads/0018/26/8f/2/779136.png

Отредактировано vt (2021-01-02 15:37:01)

2

У меня 2 вопроса по дебаггеру.
Во первых, не могли бы вы привести командную строку запуска OpenOCD. Достаточно ли для interface указать jlink.cfg, а для target stm32f1x.cfg? Что-то типа этого:

Код:
sudo openocd -f interface/jlink.cfg \
             -c "transport select swd" \
             -c "adapter_khz 1000" \
             -f target/stm32f1x.cfg

И во вторых, решил декомпилировать HEX файл Jay CH55x.hex в ASM исходник для Keil С51, дизассемблер IDA PRO. Как известно при декомпиляции основная сложность в разделении кода и данных, и если какие-то данные зараннее известны, например дескрипторы USB, это может значительно облегчить задачу. Конвертитовал HEX в BIN, отрыл в HxD, найти и вырезать дескрипторы не проблемма. Начало таблицы по смещению 0x08FB, длина 0x4F. Перевел в код и озадачился, в таблице USB дескрипторов несоответствия и какой-то лишний мусор, таблица отличается от приведенной.
В конце концов добился бинарной идентичности, приведу декомпилированную таблицу в формате ASM Keil С51. Макрос RDW перед таблицей служит для конвертации ендианности.

Код
Код:
;    ----------------------USB descriptors -------------------------
RDW MACRO DWVAL ; convert Big-Endian <-> Little-Endian
    IF NUL DWVAL
        EXITM
    ENDIF
    DB LOW DWVAL
    DB HIGH DWVAL
ENDM
;    ----------------------------------------------------------------
DB  0x12    	; ???
;    ---------------------- Device Descriptor ----------------------
DB  0x12    	; bLength, 18 bytes
DB  0x01    	; bDescriptorType
RDW 0x0110  	; bcdUSB, USB Version 1.10
DB  0x00    	; bDeviceClass
DB  0x00    	; bDeviceSubClass
DB  0x00    	; bDeviceProtocol
DB  0x08    	; bMaxPacketSize0, 8 bytes
RDW 0x1366  	; idVendor (Segger J-Link)
RDW 0x0104  	; idProduct (Segger J-Link)
RDW 0x5505  	; bcdDevice (!!! 0x5504 origin)
DB  0x00    	; iManufacturer
DB  0x02    	; iProduct
DB  0x03    	; iSerialNumber
DB  0x01    	; bNumConfigurations, 1 Configuration
;    ----------------------------------------------------------------
DB  0x20    	; ???
;    ------------------ Configuration Descriptor -------------------
DB  0x09    	; bLength, 9 bytes
DB  0x02    	; bDescriptorType
RDW 0x0020  	; wTotalLength, 32 bytes
DB  0x01    	; bNumInterfaces, 1 Interface
DB  0x01    	; bConfigurationValue, Configuration 1
DB  0x00    	; iConfiguration
DB  0x80    	; bmAttributes
; D7: 0x01  	; Reserved, set 1	
; D6: 0x00  	; Self Powered (no)
; D5: 0x00  	; Remote Wakeup (no)
; D4..0: 0x00	; Reserved, set 0
DB  0x64    	; MaxPower, 200 mA    
;    ------------------ Interface Descriptor -----------------------
DB  0x09    	; bLength, 9 bytes
DB  0x04    	; bDescriptorType
DB  0x00    	; bInterfaceNumber
DB  0x00    	; bAlternateSetting
DB  0x02    	; bNumEndpoints, 2 Endpoints
DB  0xFF    	; bInterfaceClass, Vendor Specific
DB  0xFF    	; bInterfaceSubClass, Vendor Specific
DB  0xFF    	; bInterfaceProtocol, Vendor Specific
DB  0x00    	; iInterface  
;    ------------------- Endpoint Descriptor ------------------------
DB  0x07    	; bLength, 7 bytes
DB  0x05    	; bDescriptorType
DB  0x01    	; bEndpointAddress, Direction=OUT, EndpointID=1
DB  0x02    	; bmAttributes, TransferType=Bulk
RDW 0x0040  	; wMaxPacketSize, 64 bytes
DB  0x00    	; bInterval, ignored
;    ------------------- Endpoint Descriptor ------------------------
DB  0x07    	; bLength, 7 bytes
DB  0x05    	; bDescriptorType
DB  0x81    	; bEndpointAddress, Direction=IN, EndpointID=1
DB  0x02    	; bmAttributes, TransferType=Bulk
RDW 0x0040  	; wMaxPacketSize, 64 bytes
DB  0x00    	; bInterval, ignored
;    ----------------------------------------------------------------
DB  0x04    	; ???
;    ------------------- Language String Descriptors ----------------
DB  0x04    	; bLength, 4 bytes
DB  0x03    	; bDescriptorType, String
RDW 0x0409  	; Language ID, English - United States
;    ----------------------------------------------------------------
DB  0x08    	; ???
;    ------------------- String Descriptor 1 ------------------------
DB  0x08    	; bLength, 8 bytes
DB  0x03    	; bDescriptorType, String
;    ------------------- 'Jay' --------------------------------------
DB  'J', 0, 'a', 0, 'y', 0 
;    ----------------------------------------------------------------
DB  0x0C    	; ???
;    ------------------- String Descriptor 2 ------------------------
DB  0x0C    	; bLength, 12 bytes
DB  0x03    	; bDescriptorType, String
;    ------------------- '12345' ------------------------------------
DB  '1', 0, '2', 0, '3', 0, '4', 0, '5', 0
;    ----------------------------------------------------------------

1. Перед Device Descriptor стоит лишний байт, копирующий размер записи Device Descriptor. Ну ладно, возможно я тут ошибся, принял код за данные, пока пропустим.
2. Поле bcdDevice записи Device Descriptor отличается, ладно, это Device Version Number, на рабоспособность не повлияет.
3. В полях iProduct и iSerialNumber прописаны строки 'Jay' и '12345'. Зачем, если на самом деле их там нет, эти строки прописаны ниже в строковых дескрипторах?
   Про индексы строковых дескрипторов, дескриптор языка имеет Index[0], а значит дескриптор iProduct должен иметь Index[1], дескриптор iSerialNumber должен иметь Index[2]. Здесь же они имеют индексы 2 и 3 соответственно. Непонятно.
3. Между записями Device Descriptor и Configuration Descriptor стоит лишний байт 0x20, в коде ASCII это пробел. Зачем?
4. Перед записями Language String Descriptors, String Descriptor 1, String Descriptor 2 стоит по байту копирующему размер соответствующей записи. Зачем?
  Насколько точен приведенный код С программы, или он приблизителен? Если соответствует знаете ли вы какой компилятор, какие ключи запуска?

В BIN файле после USB десрипторов невооруженным взлядом видна строка 'Jay CH55x' по смещению 0x0967 длина 9 байт (ASCII). Т.к. она присутствует в выводе консоли OpenOCD, наверное это вывод команды EMU_CMD_VERSION протокола Segger. Всего судя по сырцам С дебагер может обрабатывать следующие Segger команды:

Код:
0x01 - EMU_CMD_VERSION - получить версию прошивки.
0x07 - EMU_CMD_GET_STATE - получить напряжение и состояния выводов JTAG.
0xC7 - EMU_CMD_SELECT_IF - выбрать целевой интерфейс или извлечь текущий настроенный целевой интерфейс.
0xCF - EMU_CMD_HW_JTAG3 - обработать соединение JTAG с передачей данных с выравниванием по словам и возвращаемым значением.
0xD4 - EMU_CMD_GET_MAX_MEM_BLOCK - получить максимальный размер блока памяти.
0xDC - EMU_CMD_HW_RESET0 - активировать сброс устройства.
0xDD - EMU_CMD_HW_RESET1 - деактивировать сброс устройства.
0xE8 - EMU_CMD_GET_CAPS - получить возможности эмулятора.
0xF0 - EMU_CMD_GET_HW_VERSION - получить аппаратную версию эмулятора.

Отредактировано anakost (2021-01-24 09:07:05)

3

Про строчку запуска
openocd -c "adapter driver jlink" -c "transport select swd" -f target/stm32f1x.cfg

Про декомпиляцию
вот архив с исходниками и батником для сборки - https://yadi.sk/d/gq1-TiKIPVQ5wQ

4

Есть еще вопрос, какой программой можно сделать upload c СР552 находящегося в режиме DFU?

5

В смысле вычитать прошивку из мк?
Никакой, у загрузчика в мк нет функциональности чтения, только запись и верификация записи
Теоретически возможно подбором с помощью команд верификации, в топике про ch55 dosikus давал ссылки и цитаты с немецкого форума где этим развлекались, если эту возможность не прикрыли с тех пор

6

Я почему спросил, есть программатор Minpro I, желательно считать с него прошивку перед перепрошитием, чтобы можно было восстановить.
И так понимаю никакого отладочного иньерфейса у ch55x тоже нет? Печалька.

Хотя не все потеряно, WCHISPTool особенности

  1. Обеспечьте программирование нескольких микросхем и загрузите локальные данные микросхемы

  2. Поддержка редактирования DataFlash, и вы можете добавлять новые данные.

  3. Поддержка загрузки необходимого контента через режим USB и заполнение данных в DataFlash.

  4. Поддержка чтения чипа, вы можете читать и записывать данные на интерфейсе DataFlash.

  5. Поддержка 8-битного и 16-битного отображения данных

  6. Flash также можно загрузить в виде программного обеспечения, вы можете выбрать одну загрузку, вы можете загружать ее партиями.

  7. Обеспечьте функцию проверки обучения, загруженный контент можно проверить, проверив результат

  8. Поддержка значения SHA1 сгенерированного файла, правая кнопка мыши может скопировать значение SHA1 в буфер обмена.

Осталось найти заголовочный файл к WCH55xISP.DLL

Отредактировано anakost (2021-02-08 20:36:06)

7

Data flash это не программа

http://forumupload.ru/uploads/0018/26/8f/2/243944.png

8

Спасибо за наводку, upload сделал.
Считыватель firmware через загрузчик написал участник немецкого форума Thomas. Их там 2 варианта, для загрузчика старой версии 1.1 (freader.zip, с исходниками), и для новой 2.31 (freader2.zip, один ехешник). Оба работают через 5 функций из ch375dll.dll. Чтобы не возиться с путями просто скопировал Флеш-дампер freader.exe в папку установленного WCHISPTool, подключил программатор в режиме DFU, запустил, после отработки он создал 2 файла firmware.hex и firmware.bin.

Microsoft Windows [Version 6.1.7601]
(c) Корпорация Майкрософт (Microsoft Corp.), 2009. Все права защищены.

C:\WinSoft\WCHISPTool>freader.exe
CH552 Flash Dumper
... Bootloader V2.3 found.
... starting point found at 0x3FE4
... now reading the flash. This may take some time. If bored cancel with ESC
................................................................................
................................................................................
................................................................................
................
C:\WinSoft\WCHISPTool>

Снимается полный дамп 16-килобайтной области Flash, считывание начинается с конца. Затем перебором 0..255 по нисходящей идет попытка считывания каждого байта. В программе есть ошибка, последний байт (адрес 0х0000) всегда считывается как 0хFF. Учитывая что это адрес вектора сброса, и там почти всегда стоит команда LJMP, байт 0хFF надо поменять на 0х02.
Т.к. моя цель была получить и сохранить на будущее только прошивку программатора, нужно открыть firmware.bin в HEX-редакторе HxD. Код разделен на 2 части , прошивка (firmware, начало 0x0000) и загрузчик (bootlouder, начало 0x3800), между ними 0xFF. По адресу 0x0000 заменил байт 0хFF на 0х02, выделил весь код до начала блока 0хFF и сохранил как MinPro_I.bin.
Осталось проверить, подключаем программатор в режиме DFU, загружаем WCHISPTool, в качестве User-файла указываем свежесозданный MinPro_I.bin, запускаем верификацию, отчет:

Device#0  UID:B9-64-4D-43-00-00-00-00, BTVER:02.31
** User file name:D:\TEMP\MINPRO_I.BIN
** Download bytes:10432 B
User file HASH: 9B16D6FF3303C0F029074C4E1E5E7E4E18938872
Via usb download CH552 firmware
Device No.90700408 is started to download
BTVER:02.31
Verifying...
complete
1#device device download is complete
Total verified:1, 1 succeed, 0 failed
time used:0.405s


Вы здесь » Микроконтроллеры » Архив » J-Link совместимый дебаггер на CH551