Ну, точнее говоря, libjaylink совместимый - https://github.com/syntacore/libjaylink
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)
