Ну, точнее говоря, 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
Отредактировано vt (2021-01-02 15:37:01)