From 37542bd961d0da0f006a8664a664533189063124 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Thu, 8 Oct 2020 21:08:10 -0300 Subject: [PATCH 01/54] add port output mode function --- examples/blink/main.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/examples/blink/main.c b/examples/blink/main.c index a7232a9..03476db 100644 --- a/examples/blink/main.c +++ b/examples/blink/main.c @@ -1,18 +1,25 @@ -// Blink an LED connected to pin 1.7 +// Blink an LED connected to pin 1.4 #include #include -#define LED_PIN 7 -SBIT(LED, 0x90, LED_PIN); +// 0x90-0x97 are P1 bit addresses, 0xB0-0xB7 are P3 bit addresses +#define LED_ADDR 0x94 +__sbit __at (LED_ADDR) LED; + +// set GPIO to push-pull mode +inline void pushPull(uint8_t pinaddr) +{ + if (pinaddr >= 0xB0 && pinaddr < 0xB8) + P3_MOD_OC &= ~(1 << (pinaddr - 0xB0)); + else if (pinaddr >= 0x90 && pinaddr < 0x98) + P3_MOD_OC &= ~(1 << (pinaddr - 0x90)); +} void main() { CfgFsys(); - // Configure pin 1.7 as GPIO output - P1_DIR_PU &= 0x0C; - P1_MOD_OC = P1_MOD_OC & ~(1< Date: Sun, 11 Oct 2020 23:01:42 -0300 Subject: [PATCH 02/54] use USB_DEV_DESCR struct for DevDesc --- examples/usb_device_cdc/main.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/examples/usb_device_cdc/main.c b/examples/usb_device_cdc/main.c index d10dbec..1c0fabc 100644 --- a/examples/usb_device_cdc/main.c +++ b/examples/usb_device_cdc/main.c @@ -19,7 +19,8 @@ __xdata __at (0x0080) uint8_t Ep2Buffer[2*MAX_PACKET_SIZE]; //Endpoint 2 uint16_t SetupLen; uint8_t SetupReq,Count,UsbConfig; -const uint8_t * pDescr; //USB configuration flag +const uint8_t * pDescr; + USB_SETUP_REQ SetupReqBuf; //Temporary Setup package #define UsbSetupBuf ((PUSB_SETUP_REQ)Ep0Buffer) @@ -29,10 +30,32 @@ USB_SETUP_REQ SetupReqBuf; / /*设备描述符*/ +/* __code uint8_t DevDesc[] = {0x12,0x01,0x10,0x01,0x02,0x00,0x00,DEFAULT_ENDP0_SIZE, 0x86,0x1a,0x22,0x57,0x00,0x01,0x01,0x02, 0x03,0x01 }; +*/ + +// device descriptor + +__code USB_DEV_DESCR DevDesc = { + .bLength = 18, + .bDescriptorType = USB_DESCR_TYP_DEVICE, + .bcdUSBH = 0x01, .bcdUSBL = 0x10, + .bDeviceClass = USB_DEV_CLASS_COMMUNIC, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = DEFAULT_ENDP0_SIZE, + .idVendorH = 0x1a, .idVendorL = 0x86, + .idProductH = 0x57, .idProductL = 0x22, + .bcdDeviceH = 0x01, .bcdDeviceL = 0x00, + .iManufacturer = 1, // string descriptors + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 1 +}; + __code uint8_t CfgDesc[] ={ 0x09,0x02,0x43,0x00,0x02,0x01,0x00,0xa0,0x32, //Configuration descriptor (two interfaces) // The following is the interface 0 (CDC interface) descriptor @@ -220,8 +243,9 @@ void DeviceInterrupt(void) __interrupt (INT_NO_USB) //USB case USB_GET_DESCRIPTOR: switch(UsbSetupBuf->wValueH) { - case 1: //设备描述符 - pDescr = DevDesc; //把设备描述符送到要发送的缓冲区 + case USB_DESCR_TYP_DEVICE: + //pDescr = DevDesc; + pDescr = (uint8_t *)&DevDesc; len = sizeof(DevDesc); break; case 2: //配置描述符 From f3be6c37ac8b2c3f46c7ca9d4114cdb44f48e7e4 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Wed, 14 Oct 2020 09:51:11 -0300 Subject: [PATCH 03/54] cleanup string descriptors --- examples/usb_device_cdc/main.c | 53 ++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/examples/usb_device_cdc/main.c b/examples/usb_device_cdc/main.c index 1c0fabc..70bfdb3 100644 --- a/examples/usb_device_cdc/main.c +++ b/examples/usb_device_cdc/main.c @@ -52,7 +52,7 @@ __code USB_DEV_DESCR DevDesc = { .bcdDeviceH = 0x01, .bcdDeviceL = 0x00, .iManufacturer = 1, // string descriptors .iProduct = 2, - .iSerialNumber = 3, + .iSerialNumber = 0, .bNumConfigurations = 1 }; @@ -73,21 +73,44 @@ __code uint8_t CfgDesc[] ={ }; /*字符串描述符*/ unsigned char __code LangDes[]={0x04,0x03,0x09,0x04}; //Language descriptor -unsigned char __code SerDes[]={ //Serial number string descriptor - 0x14,0x03, - 0x32,0x00,0x30,0x00,0x31,0x00,0x37,0x00,0x2D,0x00, - 0x32,0x00,0x2D,0x00, - 0x32,0x00,0x35,0x00 - }; -unsigned char __code Prod_Des[]={ //Product string descriptor + +/* +unsigned char __code Prod_Des[]={ 0x14,0x03, 0x43,0x00,0x48,0x00,0x35,0x00,0x35,0x00,0x34,0x00,0x5F,0x00, 0x43,0x00,0x44,0x00,0x43,0x00, }; + +*/ + +#define PROD_DESC (u"CH55x_CDC") +// don't use sizeof(DESC/2): It will put a copy of the string in CSEG +#define PDESC_LEN 9 + +//Product string descriptor +__code struct {uint8_t bLength; uint8_t bDscType; uint16_t string[PDESC_LEN];} Prod_Des = { + .bLength = sizeof(Prod_Des), + .bDscType = USB_DESCR_TYP_STRING, + .string = PROD_DESC +}; + +/* unsigned char __code Manuf_Des[]={ 0x0A,0x03, 0x5F,0x6c,0xCF,0x82,0x81,0x6c,0x52,0x60, }; +*/ + +#define MANUF_DESC (u"WCH") +// don't use sizeof(DESC/2): It will put a copy of the string in CSEG +#define MDESC_LEN 3 + +//Product string descriptor +__code struct {uint8_t bLength; uint8_t bDscType; uint16_t string[MDESC_LEN];} Manuf_Des = { + .bLength = sizeof(Manuf_Des), + .bDscType = USB_DESCR_TYP_STRING, + .string = MANUF_DESC +}; //cdc参数 __xdata uint8_t LineCoding[7]={0x00,0xe1,0x00,0x00,0x00,0x00,0x08}; //The initial baud rate is 57600, 1 stop bit, no parity, 8 data bits. @@ -252,7 +275,7 @@ void DeviceInterrupt(void) __interrupt (INT_NO_USB) //USB pDescr = CfgDesc; //把设备描述符送到要发送的缓冲区 len = sizeof(CfgDesc); break; - case 3: + case USB_DESCR_TYP_STRING: if(UsbSetupBuf->wValueL == 0) { pDescr = LangDes; @@ -260,19 +283,16 @@ void DeviceInterrupt(void) __interrupt (INT_NO_USB) //USB } else if(UsbSetupBuf->wValueL == 1) { - pDescr = Manuf_Des; + //pDescr = Manuf_Des; + pDescr = (uint8_t *)Manuf_Des; len = sizeof(Manuf_Des); } else if(UsbSetupBuf->wValueL == 2) { - pDescr = Prod_Des; + //pDescr = (uint8_t *)&Prod_Des; + pDescr = (uint8_t *)Prod_Des; len = sizeof(Prod_Des); } - else - { - pDescr = SerDes; - len = sizeof(SerDes); - } break; default: len = 0xff; //Unsupported command or error @@ -569,6 +589,7 @@ void Uart1_ISR(void) __interrupt (INT_NO_UART1) } } + //主函数 main() { From 4f6295f1a0e24ba67e628f11676b04eecef55f44 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Wed, 14 Oct 2020 10:00:59 -0300 Subject: [PATCH 04/54] rm single-use string #defines --- examples/usb_device_cdc/main.c | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/examples/usb_device_cdc/main.c b/examples/usb_device_cdc/main.c index 70bfdb3..983ee0a 100644 --- a/examples/usb_device_cdc/main.c +++ b/examples/usb_device_cdc/main.c @@ -83,15 +83,11 @@ unsigned char __code Prod_Des[]={ */ -#define PROD_DESC (u"CH55x_CDC") -// don't use sizeof(DESC/2): It will put a copy of the string in CSEG #define PDESC_LEN 9 - -//Product string descriptor __code struct {uint8_t bLength; uint8_t bDscType; uint16_t string[PDESC_LEN];} Prod_Des = { .bLength = sizeof(Prod_Des), .bDscType = USB_DESCR_TYP_STRING, - .string = PROD_DESC + .string = u"CH55x_CDC" }; /* @@ -101,15 +97,11 @@ unsigned char __code Manuf_Des[]={ }; */ -#define MANUF_DESC (u"WCH") -// don't use sizeof(DESC/2): It will put a copy of the string in CSEG #define MDESC_LEN 3 - -//Product string descriptor __code struct {uint8_t bLength; uint8_t bDscType; uint16_t string[MDESC_LEN];} Manuf_Des = { .bLength = sizeof(Manuf_Des), .bDscType = USB_DESCR_TYP_STRING, - .string = MANUF_DESC + .string = u"WCH" }; //cdc参数 From 79cdfb3c1bb36348ef4213b9dd0bcd40ed142a16 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Sat, 14 Nov 2020 21:33:28 -0400 Subject: [PATCH 05/54] make CfgFsys() inline --- include/debug.c | 38 ------------------------------- include/debug.h | 60 ++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 50 insertions(+), 48 deletions(-) diff --git a/include/debug.c b/include/debug.c index 4328123..9198718 100644 --- a/include/debug.c +++ b/include/debug.c @@ -15,44 +15,6 @@ #include "ch554.h" #include "debug.h" -/******************************************************************************* -* Function Name : CfgFsys( ) -* Description : CH554 clock selection and configuration function, Fsys 6MHz is used by default, FREQ_SYS can be passed -                 CLOCK_CFG configuration, the formula is as follows: -                 Fsys = (Fosc * 4 / (CLOCK_CFG & MASK_SYS_CK_SEL); the specific clock needs to be configured by yourself -*******************************************************************************/ -void CfgFsys( ) -{ - SAFE_MOD = 0x55; - SAFE_MOD = 0xAA; -// CLOCK_CFG |= bOSC_EN_XT; // Enable external crystal -// CLOCK_CFG & = ~ bOSC_EN_INT; // Turn off the internal crystal - -#if FREQ_SYS == 32000000 - CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x07; // 32MHz -#elif FREQ_SYS == 24000000 - CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x06; // 24MHz -#elif FREQ_SYS == 16000000 - CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x05; // 16MHz -#elif FREQ_SYS == 12000000 - CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x04; // 12MHz -#elif FREQ_SYS == 6000000 - CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x03; // 6MHz -#elif FREQ_SYS == 3000000 - CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x02; // 3MHz -#elif FREQ_SYS == 750000 - CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x01; // 750KHz -#elif FREQ_SYS == 187500 - CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x00; // 187.5MHz -#else - #warning FREQ_SYS invalid or not set -#endif - - SAFE_MOD = 0x00; -} - - - /******************************************************************************* * Function Name : mDelayus(UNIT16 n) * Description : us delay function diff --git a/include/debug.h b/include/debug.h index fc4ae39..94513cd 100644 --- a/include/debug.h +++ b/include/debug.h @@ -1,4 +1,3 @@ - /* Debug */ /* Provide printf subroutine and delay function */ @@ -14,11 +13,47 @@ #define UART1_BAUD 9600 #endif -void CfgFsys( ); // CH554 clock selection and configuration - void mDelayuS (uint16_t n); // Delay in units of uS void mDelaymS (uint16_t n); // Delay in mS + +/******************************************************************************* +* Function Name : CfgFsys( ) +* Description : CH554 clock selection and configuration function, Fsys 6MHz is used by default, FREQ_SYS can be passed +CLOCK_CFG configuration, the formula is as follows: +Fsys = (Fosc * 4 / (CLOCK_CFG & MASK_SYS_CK_SEL); the specific clock needs to be configured by yourself +*******************************************************************************/ +inline void CfgFsys( ) +{ + SAFE_MOD = 0x55; + SAFE_MOD = 0xAA; +// CLOCK_CFG |= bOSC_EN_XT; // Enable external crystal +// CLOCK_CFG & = ~ bOSC_EN_INT; // Turn off the internal crystal + +#if FREQ_SYS == 32000000 + CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x07; // 32MHz +#elif FREQ_SYS == 24000000 + CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x06; // 24MHz +#elif FREQ_SYS == 16000000 + CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x05; // 16MHz +#elif FREQ_SYS == 12000000 + CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x04; // 12MHz +#elif FREQ_SYS == 6000000 + CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x03; // 6MHz +#elif FREQ_SYS == 3000000 + CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x02; // 3MHz +#elif FREQ_SYS == 750000 + CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x01; // 750KHz +#elif FREQ_SYS == 187500 + CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x00; // 187.5MHz +#else + #warning FREQ_SYS invalid or not set +#endif + + SAFE_MOD = 0x00; +} + + /******************************************************************************* * Function Name : CH554UART0Alter() * Description : CH554 serial port 0 pin mapping, serial port mapping to P0.2 and P0.3 @@ -39,13 +74,17 @@ inline void mInitSTDIO( ) uint32_t x; uint8_t x2; - SM0 = 0; + // set UART0 to mode 1: 81N + //SM0 = 0; SM1 = 1; - SM2 = 0; //Serial port 0 usage mode 1 - //Use Timer1 as a baud rate generator - RCLK = 0; //UART0 receive clock - TCLK = 0; //UART0 transmit clock - PCON |= SMOD; + //SM2 = 0; + + // UART0 receive clock default = T1 + // RCLK = 0; + // UART0 transmit clock default = T1 + // TCLK = 0; + + PCON = SMOD; x = 10 * FREQ_SYS / UART0_BAUD / 16; //If you change the main frequency, be careful not to overflow the value of x x2 = x % 10; x /= 10; @@ -53,7 +92,8 @@ inline void mInitSTDIO( ) TMOD = TMOD & ~ bT1_GATE & ~ bT1_CT & ~ MASK_T1_MOD | bT1_M1; //0X20, Timer1 as 8-bit auto-reload timer T2MOD = T2MOD | bTMR_CLK | bT1_CLK; //Timer1 clock selection - TH1 = 0-x; //12MHz crystal oscillator, buad / 12 is the actual need to set the baud rate + TH1 = 256-x; + TR1 = 1; //Start timer 1 TI = 1; REN = 1; //Serial 0 receive enable From 0ca0cc36772742353e0b6ac31f1e6f62cec61435 Mon Sep 17 00:00:00 2001 From: Ralph Doncaster Date: Sat, 14 Nov 2020 22:27:18 -0400 Subject: [PATCH 06/54] used ubuntu-20.04 --- .github/workflows/linux.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml index 8ee610a..95893ab 100644 --- a/.github/workflows/linux.yml +++ b/.github/workflows/linux.yml @@ -14,7 +14,8 @@ on: jobs: build: - runs-on: ubuntu-latest + # need ubuntu 20 for sdcc-3.8 package since ubuntu 18 has old sdcc-3.5 + runs-on: ubuntu-20.04 steps: - name: Check out From 3357b13d30dfe15005fed78b21a3316be585bd5c Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Sat, 14 Nov 2020 23:20:03 -0400 Subject: [PATCH 07/54] implement putchar/getchar in asm --- include/debug.c | 45 +++++++++++++++++++++++++++------------------ include/debug.h | 5 ----- 2 files changed, 27 insertions(+), 23 deletions(-) diff --git a/include/debug.c b/include/debug.c index 9198718..c0fd5d7 100644 --- a/include/debug.c +++ b/include/debug.c @@ -93,32 +93,41 @@ void mDelaymS( uint16_t n ) // } } -#if SDCC < 370 -void putchar(char c) -{ - while (!TI); /* assumes UART is initialized */ - TI = 0; - SBUF = c; -} - -char getchar() { - while(!RI); /* assumes UART is initialized */ - RI = 0; - return SBUF; -} -#else +#pragma callee_saves putchar int putchar(int c) { - while (!TI); /* assumes UART is initialized */ + /* + while (!TI); // assumes UART is initialized TI = 0; SBUF = c & 0xFF; + return c; + */ + __asm + 1$: + jnb _TI, 1$ + clr _TI + mov _SBUF, dpl + __endasm; + return c; } -int getchar() { - while(!RI); /* assumes UART is initialized */ +#pragma callee_saves getchar +int getchar() __naked +{ + /* + while(!RI); // assumes UART is initialized RI = 0; return SBUF; + */ + __asm + 1$: + jnb _RI, 1$ + clr _RI + + mov dpl, _SBUF + mov dph, #0 + ret + __endasm; } -#endif diff --git a/include/debug.h b/include/debug.h index 94513cd..fffd2ef 100644 --- a/include/debug.h +++ b/include/debug.h @@ -170,13 +170,8 @@ inline void CH554UART1SendByte(uint8_t SendDat) U1TI = 0; } -#if SDCC < 370 -void putchar(char c); -char getchar(); -#else int putchar(int c); int getchar(void); -#endif /******************************************************************************* * Function Name : CH554WDTModeSelect(uint8_t mode) From 482e8ea3d9a38d2af4e1f2afc1dffdcc015fda64 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Sun, 15 Nov 2020 00:01:03 -0400 Subject: [PATCH 08/54] make putchar/getchar compatible with sdcc < 3.7.0 --- include/debug.c | 15 ++++++++++----- include/debug.h | 3 --- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/debug.c b/include/debug.c index c0fd5d7..1ea635b 100644 --- a/include/debug.c +++ b/include/debug.c @@ -93,8 +93,12 @@ void mDelaymS( uint16_t n ) // } } +// printf will use putchar function #pragma callee_saves putchar -int putchar(int c) +// putchar takes a single argument: +// char, or int for sdcc version 3.7.0 and later +// in both cases, only one byte, DPL, is copied to SBUF +void putchar() { /* while (!TI); // assumes UART is initialized @@ -107,14 +111,15 @@ int putchar(int c) 1$: jnb _TI, 1$ clr _TI + mov _SBUF, dpl __endasm; - - return c; } #pragma callee_saves getchar -int getchar() __naked +// getchar returns char or int depending on the sdcc version +// lie to sdcc and declare it as void but return in DPL +void getchar() { /* while(!RI); // assumes UART is initialized @@ -128,6 +133,6 @@ int getchar() __naked mov dpl, _SBUF mov dph, #0 - ret __endasm; } + diff --git a/include/debug.h b/include/debug.h index fffd2ef..aab6d02 100644 --- a/include/debug.h +++ b/include/debug.h @@ -170,9 +170,6 @@ inline void CH554UART1SendByte(uint8_t SendDat) U1TI = 0; } -int putchar(int c); -int getchar(void); - /******************************************************************************* * Function Name : CH554WDTModeSelect(uint8_t mode) * Description : CH554 watchdog mode selection From 74da08f0baaf8cb49cf1f73f43ec0f0140f656a3 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Thu, 17 Dec 2020 17:34:57 -0400 Subject: [PATCH 09/54] round baud rate instead of truncate --- examples/usb_device_cdc/main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/examples/usb_device_cdc/main.c b/examples/usb_device_cdc/main.c index 983ee0a..a5a4389 100644 --- a/examples/usb_device_cdc/main.c +++ b/examples/usb_device_cdc/main.c @@ -176,6 +176,7 @@ void USBDeviceEndPointCfg() UEP4_1_MOD = 0X40; //Endpoint 1 upload buffer; endpoint 0 single 64-byte send and receive buffer UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; //Manual flip, OUT transaction returns ACK, IN transaction returns NAK } + /******************************************************************************* * Function Name : Config_Uart1(uint8_t *cfg_uart) * Description : Configure serial port 1 parameters @@ -183,16 +184,20 @@ void USBDeviceEndPointCfg() * Output : None * Return : None *******************************************************************************/ -void Config_Uart1(uint8_t *cfg_uart) +inline void Config_Uart1(uint8_t *cfg_uart) { uint32_t uart1_buad = 0; + // why not: uint32_t uart1_buad = *(uint32_t *)cfg_uart; *((uint8_t *)&uart1_buad) = cfg_uart[0]; *((uint8_t *)&uart1_buad+1) = cfg_uart[1]; *((uint8_t *)&uart1_buad+2) = cfg_uart[2]; *((uint8_t *)&uart1_buad+3) = cfg_uart[3]; - SBAUD1 = 256 - FREQ_SYS/16/uart1_buad; // SBAUD1 = 256 - Fsys / 16 / baud rate + + // SBAUD1 = 256 - Fsys / 16 / baud rate, rounded to int + SBAUD1 = 256 - ((FREQ_SYS/8/uart1_buad) + 1) /2; IE_UART1 = 1; } + /******************************************************************************* * Function Name : DeviceInterrupt() * Description : CH559USB interrupt processing function From 9bb2deb3e7b32fc3e4f9f752c2ae96281a6461d6 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Wed, 13 Jan 2021 17:52:29 -0400 Subject: [PATCH 10/54] working backport from ch55xduino --- examples/CMSIS_DAP/DAP.c | 1026 ++++++++++++++++++++++++++++++ examples/CMSIS_DAP/DAP.h | 223 +++++++ examples/CMSIS_DAP/Makefile | 14 + examples/CMSIS_DAP/SW_DP.c | 319 ++++++++++ examples/CMSIS_DAP/USBHID.c | 36 ++ examples/CMSIS_DAP/USBHID.h | 9 + examples/CMSIS_DAP/USBconstant.c | 112 ++++ examples/CMSIS_DAP/USBconstant.h | 26 + examples/CMSIS_DAP/USBhandler.c | 458 +++++++++++++ examples/CMSIS_DAP/USBhandler.h | 48 ++ examples/CMSIS_DAP/main.c | 41 ++ 11 files changed, 2312 insertions(+) create mode 100644 examples/CMSIS_DAP/DAP.c create mode 100644 examples/CMSIS_DAP/DAP.h create mode 100644 examples/CMSIS_DAP/Makefile create mode 100644 examples/CMSIS_DAP/SW_DP.c create mode 100644 examples/CMSIS_DAP/USBHID.c create mode 100644 examples/CMSIS_DAP/USBHID.h create mode 100644 examples/CMSIS_DAP/USBconstant.c create mode 100644 examples/CMSIS_DAP/USBconstant.h create mode 100644 examples/CMSIS_DAP/USBhandler.c create mode 100644 examples/CMSIS_DAP/USBhandler.h create mode 100644 examples/CMSIS_DAP/main.c diff --git a/examples/CMSIS_DAP/DAP.c b/examples/CMSIS_DAP/DAP.c new file mode 100644 index 0000000..8bff304 --- /dev/null +++ b/examples/CMSIS_DAP/DAP.c @@ -0,0 +1,1026 @@ +/* + * Copyright (c) 2013-2017 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ---------------------------------------------------------------------- + * + * $Date: 1. December 2017 + * $Revision: V2.0.0 + * + * Project: CMSIS-DAP Source + * Title: DAP.c CMSIS-DAP Commands + * + *---------------------------------------------------------------------------*/ + +#include "DAP.h" + +// Get DAP Information +// id: info identifier +// info: pointer to info data +// return: number of bytes in info data +static uint8_t DAP_Info(uint8_t id, uint8_t *info) +{ + uint8_t length = 0U; + + switch (id) + { + case DAP_ID_VENDOR: + length = 0; + break; + case DAP_ID_PRODUCT: + length = 0; + break; + case DAP_ID_SER_NUM: + length = 0; + break; + case DAP_ID_FW_VER: + length = (uint8_t)sizeof(DAP_FW_VER); + memcpy(info, DAP_FW_VER, length); + break; + case DAP_ID_DEVICE_VENDOR: + + break; + case DAP_ID_DEVICE_NAME: + + break; + case DAP_ID_CAPABILITIES: + info[0] = DAP_PORT_SWD; + length = 1U; + break; + case DAP_ID_TIMESTAMP_CLOCK: + + break; + case DAP_ID_SWO_BUFFER_SIZE: + + break; + case DAP_ID_PACKET_SIZE: + info[0] = (uint8_t)(DAP_PACKET_SIZE >> 0); + info[1] = (uint8_t)(DAP_PACKET_SIZE >> 8); + length = 2U; + break; + case DAP_ID_PACKET_COUNT: + info[0] = DAP_PACKET_COUNT; + length = 1U; + break; + default: + break; + } + + return (length); +} + +// Process Delay command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint8_t DAP_Delay(const uint8_t *req, uint8_t *res) +{ + uint16_t delay; + + delay = (uint16_t)(*(req + 0)) | + (uint16_t)(*(req + 1) << 8); + + while (--delay) + { + }; + + *res = DAP_OK; + return 1; +} + +// Process Host Status command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint8_t DAP_HostStatus(const uint8_t *req, uint8_t *res) +{ + + switch (*req) + { + case DAP_DEBUGGER_CONNECTED: + LED = ((*(req + 1) & 1U)); + break; + case DAP_TARGET_RUNNING: + LED = ((*(req + 1) & 1U)); + break; + default: + *res = DAP_ERROR; + return 1; + } + + *res = DAP_OK; + return 1; +} + +// Process Connect command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +__idata uint8_t debug_port; +static uint8_t DAP_Connect(const uint8_t *req, uint8_t *res) +{ + uint8_t port; + + if (*req == DAP_PORT_AUTODETECT) + { + port = DAP_DEFAULT_PORT; + } + else + { + port = *req; + } + + switch (port) + { + case DAP_PORT_SWD: + debug_port = DAP_PORT_SWD; + PORT_SWD_SETUP(); + break; + default: + port = DAP_PORT_DISABLED; + break; + } + + *res = port; + return 1; +} + +// Process Disconnect command and prepare response +// response: pointer to response data +// return: number of bytes in response +#define PORT_OFF() PORT_SWD_SETUP() +static uint8_t DAP_Disconnect(uint8_t *res) +{ + + debug_port = DAP_PORT_DISABLED; + PORT_OFF(); + + *res = DAP_OK; + return (1U); +} + +// Process Reset Target command and prepare response +// response: pointer to response data +// return: number of bytes in response +static uint8_t DAP_ResetTarget(uint8_t *res) +{ + *(res + 1) = 0; //RESET_TARGET(); + *(res + 0) = DAP_OK; + return 2; +} + +// Process SWJ Pins command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint8_t DAP_SWJ_Pins(const uint8_t *req, uint8_t *res) +{ + uint8_t value; + uint8_t select; + uint16_t wait; + + value = * (req + 0); + select = (uint8_t) * (req + 1); + wait = (uint16_t)(*(req + 2) << 0) | (uint16_t)(*(req + 3) << 8); + if ((uint8_t)(*(req + 4)) || (uint8_t)(*(req + 5))) + wait |= 0x8000; + + if ((select & DAP_SWJ_SWCLK_TCK_BIT) != 0U) + { + if ((value & DAP_SWJ_SWCLK_TCK_BIT) != 0U) + { + SWK = 1; + } + else + { + SWK = 0; + } + } + if ((select & DAP_SWJ_SWDIO_TMS_BIT) != 0U) + { + if ((value & DAP_SWJ_SWDIO_TMS_BIT) != 0U) + { + SWD = 1; + } + else + { + SWD = 0; + } + } + if ((select & DAP_SWJ_nRESET_BIT) != 0U) + { + RST = value >> DAP_SWJ_nRESET; + } + + if (wait != 0U) + { + + do + { + if ((select & DAP_SWJ_SWCLK_TCK_BIT) != 0U) + { + if ((value >> DAP_SWJ_SWCLK_TCK) ^ SWK) + { + continue; + } + } + if ((select & DAP_SWJ_SWDIO_TMS_BIT) != 0U) + { + if ((value >> DAP_SWJ_SWDIO_TMS) ^ SWD) + { + continue; + } + } + if ((select & DAP_SWJ_nRESET_BIT) != 0U) + { + if ((value >> DAP_SWJ_nRESET) ^ RST) + { + continue; + } + } + break; + } + while (wait--); + } + + value = ((uint8_t)SWK << DAP_SWJ_SWCLK_TCK) | + ((uint8_t)SWD << DAP_SWJ_SWDIO_TMS) | + (0 << DAP_SWJ_TDI) | + (0 << DAP_SWJ_TDO) | + (0 << DAP_SWJ_nTRST) | + ((uint8_t)RST << DAP_SWJ_nRESET); + + *res = value; + + return 1; +} + +// Process SWJ Clock command +// command ignored - fast ~1mbps clock always used +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint8_t DAP_SWJ_Clock(const uint8_t *req, uint8_t *res) +{ + req; + *res = DAP_OK; + return 1; +} + +// Process SWJ Sequence command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint8_t DAP_SWJ_Sequence(const uint8_t *req, uint8_t *res) +{ + uint8_t count; + + count = *req++; + if (count == 0U) + { + count = 255U; + } + + SWJ_Sequence(count, req); + *res = DAP_OK; + + return 1; +} + +// Process SWD Configure command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +__idata uint8_t turnaround; +__idata uint8_t data_phase; +static uint8_t DAP_SWD_Configure(const uint8_t *req, uint8_t *res) +{ + uint8_t value; + + value = *req; + turnaround = (value & 0x03U) + 1U; + data_phase = (value & 0x04U) ? 1U : 0U; + + *res = DAP_OK; + return 1; +} + +// Process SWD Sequence command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint8_t DAP_SWD_Sequence(const uint8_t *req, uint8_t *res) +{ + uint8_t sequence_info; + uint8_t sequence_count; + uint8_t request_count; + uint8_t response_count; + uint8_t count; + + *res++ = DAP_OK; + + request_count = 1U; + response_count = 1U; + + sequence_count = *req++; + while (sequence_count--) + { + sequence_info = *req++; + count = sequence_info & SWD_SEQUENCE_CLK; + if (count == 0U) + { + count = 64U; + } + count = (count + 7U) / 8U; + if ((sequence_info & SWD_SEQUENCE_DIN) != 0U) + { + SWD = 1; + } + else + { + SWD = 1; + } + SWD_Sequence(sequence_info, req, res); + if (sequence_count == 0U) + { + SWD = 1; + } + if ((sequence_info & SWD_SEQUENCE_DIN) != 0U) + { + request_count++; + res += count; + response_count += count; + } + else + { + req += count; + request_count += count + 1U; + } + } + + return response_count; +} + +// Process Transfer Configure command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +__idata uint8_t idle_cycles; +__idata uint16_t retry_count; +__idata uint16_t match_retry; +static uint8_t DAP_TransferConfigure(const uint8_t *req, uint8_t *res) +{ + + idle_cycles = *(req + 0); + retry_count = (uint16_t) * (req + 1) | + (uint16_t)(*(req + 2) << 8); + match_retry = (uint16_t) * (req + 3) | + (uint16_t)(*(req + 4) << 8); + + *res = DAP_OK; + return 1; +} + +// Process SWD Transfer command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) + +__xdata uint8_t data[4]; +__idata uint8_t match_mask[4]; +__idata uint8_t match_value[4]; +__idata uint8_t DAP_TransferAbort = 0U; +__idata uint8_t request_count; +__idata uint8_t request_value; +__idata uint8_t response_count; +__idata uint8_t response_value; +__idata uint16_t retry; +static uint8_t DAP_SWD_Transfer(const uint8_t *req, uint8_t *res) +{ + const uint8_t *request_head; + uint8_t *response_head; + + uint8_t post_read; + uint8_t check_write; + + request_head = req; + + response_count = 0U; + response_value = 0U; + response_head = res; + res += 2; + + DAP_TransferAbort = 0U; + + post_read = 0U; + check_write = 0U; + + req++; // Ignore DAP index + + request_count = *req++; + for (; request_count != 0U; request_count--) + { + request_value = *req++; + if ((request_value & DAP_TRANSFER_RnW) != 0U) + { + // Read registers + if (post_read) + { + // Read was posted before + retry = retry_count; + if ((request_value & (DAP_TRANSFER_APnDP | DAP_TRANSFER_MATCH_VALUE)) == DAP_TRANSFER_APnDP) + { + // Read previous AP data and post next AP read + do + { + response_value = SWD_Transfer(request_value, data); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } + else + { + // Read previous AP data + do + { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, data); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + post_read = 0U; + } + if (response_value != DAP_TRANSFER_OK) + { + break; + } + // Store previous AP data + *res++ = (uint8_t)data[0]; + *res++ = (uint8_t)data[1]; + *res++ = (uint8_t)data[2]; + *res++ = (uint8_t)data[3]; + } + if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) + { + // Read with value match + match_value[0] = (uint8_t)(*(req + 0)); + match_value[1] = (uint8_t)(*(req + 1)); + match_value[2] = (uint8_t)(*(req + 2)); + match_value[3] = (uint8_t)(*(req + 3)); + req += 4; + match_retry = match_retry; + if ((request_value & DAP_TRANSFER_APnDP) != 0U) + { + // Post AP read + retry = retry_count; + do + { + response_value = SWD_Transfer(request_value, NULL); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) + { + break; + } + } + do + { + // Read registers until its value matches or retry counter expires + retry = retry_count; + do + { + response_value = SWD_Transfer(request_value, data); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) + { + break; + } + } + while (((data[0] & match_mask[0]) != match_value[0] || + (data[1] & match_mask[1]) != match_value[1] || + (data[2] & match_mask[2]) != match_value[2] || + (data[3] & match_mask[3]) != match_value[3]) && + match_retry-- && !DAP_TransferAbort); + if ((data[0] & match_mask[0]) != match_value[0] || + (data[1] & match_mask[1]) != match_value[1] || + (data[2] & match_mask[2]) != match_value[2] || + (data[3] & match_mask[3]) != match_value[3]) + { + response_value |= DAP_TRANSFER_MISMATCH; + } + if (response_value != DAP_TRANSFER_OK) + { + break; + } + } + else + { + // Normal read + retry = retry_count; + if ((request_value & DAP_TRANSFER_APnDP) != 0U) + { + // Read AP registers + if (post_read == 0U) + { + // Post AP read + do + { + response_value = SWD_Transfer(request_value, NULL); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) + { + break; + } + post_read = 1U; + } + } + else + { + // Read DP register + do + { + response_value = SWD_Transfer(request_value, data); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) + { + break; + } + + // Store data + *res++ = data[0]; + *res++ = data[1]; + *res++ = data[2]; + *res++ = data[3]; + } + } + check_write = 0U; + } + else + { + // Write register + if (post_read) + { + // Read previous data + retry = retry_count; + do + { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, data); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) + { + break; + } + // Store previous data + *res++ = data[0]; + *res++ = data[1]; + *res++ = data[2]; + *res++ = data[3]; + post_read = 0U; + } + // Load data + data[0] = (uint8_t)(*(req + 0)); + data[1] = (uint8_t)(*(req + 1)); + data[2] = (uint8_t)(*(req + 2)); + data[3] = (uint8_t)(*(req + 3)); + req += 4; + if ((request_value & DAP_TRANSFER_MATCH_MASK) != 0U) + { + // Write match mask + match_mask[0] = data[0]; + match_mask[1] = data[1]; + match_mask[2] = data[2]; + match_mask[3] = data[3]; + response_value = DAP_TRANSFER_OK; + } + else + { + // Write DP/AP register + retry = retry_count; + do + { + response_value = SWD_Transfer(request_value, data); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) + { + break; + } + + check_write = 1U; + } + } + response_count++; + if (DAP_TransferAbort) + { + break; + } + } + + for (; request_count != 0U; request_count--) + { + // Process canceled requests + request_value = *req++; + if ((request_value & DAP_TRANSFER_RnW) != 0U) + { + // Read register + if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) + { + // Read with value match + req += 4; + } + } + else + { + // Write register + req += 4; + } + } + + if (response_value == DAP_TRANSFER_OK) + { + if (post_read) + { + // Read previous data + retry = retry_count; + do + { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, data); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) + { + goto end; + } + // Store previous data + *res++ = (uint8_t)data[0]; + *res++ = (uint8_t)data[1]; + *res++ = (uint8_t)data[2]; + *res++ = (uint8_t)data[3]; + } + else if (check_write) + { + // Check last write + retry = retry_count; + do + { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } + } + +end: + *(response_head + 0) = (uint8_t)response_count; + *(response_head + 1) = (uint8_t)response_value; + + return ((uint8_t)(res - response_head)); +} + +// Process Dummy Transfer command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +//static uint8_t DAP_Dummy_Transfer(const uint8_t *req, uint8_t *res) +//{ +// uint8_t *request_head; +// uint8_t request_count; +// uint8_t request_value; + +// request_head = req; + +// req++; // Ignore DAP index + +// request_count = *req++; + +// for (; request_count != 0U; request_count--) +// { +// // Process dummy requests +// request_value = *req++; +// if ((request_value & DAP_TRANSFER_RnW) != 0U) +// { +// // Read registers +// if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) +// { +// // Read with value match +// req += 4; +// } +// } +// else +// { +// // Write registers +// req += 4; +// } +// } + +// *(res + 0) = 0U; // res count +// *(res + 1) = 0U; // res value + +// return 2; +//} + +// Process Transfer command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint8_t DAP_Transfer(const uint8_t *req, uint8_t *res) +{ + uint8_t num = 0; + +// switch (debug_port) +// { +// case DAP_PORT_SWD: + num = DAP_SWD_Transfer(req, res); +// break; +// default: +// num = DAP_Dummy_Transfer(req, res); +// break; +// } + + return (num); +} + +// Process SWD Transfer Block command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint8_t DAP_SWD_TransferBlock(const uint8_t *req, uint8_t *res) +{ + + uint8_t *response_head; + response_count = 0U; + response_value = 0U; + response_head = res; + res += 3; + + DAP_TransferAbort = 0U; + + req++; // Ignore DAP index + + request_count = (uint16_t)(*(req + 0) << 0) | + (uint16_t)(*(req + 1) << 8); + req += 2; + if (request_count == 0U) + { + goto end; + } + + request_value = *req++; + if ((request_value & DAP_TRANSFER_RnW) != 0U) + { + // Read register block + if ((request_value & DAP_TRANSFER_APnDP) != 0U) + { + // Post AP read + retry = retry_count; + do + { + response_value = SWD_Transfer(request_value, NULL); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) + { + goto end; + } + } + while (request_count--) + { + // Read DP/AP register + if ((request_count == 0U) && ((request_value & DAP_TRANSFER_APnDP) != 0U)) + { + // Last AP read + request_value = DP_RDBUFF | DAP_TRANSFER_RnW; + } + retry = retry_count; + do + { + response_value = SWD_Transfer(request_value, data); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) + { + goto end; + } + // Store data + *res++ = (uint8_t)data[0]; + *res++ = (uint8_t)data[1]; + *res++ = (uint8_t)data[2]; + *res++ = (uint8_t)data[3]; + response_count++; + } + } + else + { + // Write register block + while (request_count--) + { + // Load data + data[0] = (uint8_t)(*(req + 0)); + data[1] = (uint8_t)(*(req + 1)); + data[2] = (uint8_t)(*(req + 2)); + data[3] = (uint8_t)(*(req + 3)); + + req += 4; + // Write DP/AP register + retry = retry_count; + do + { + response_value = SWD_Transfer(request_value, data); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) + { + goto end; + } + response_count++; + } + // Check last write + retry = retry_count; + do + { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, NULL); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } + +end: + *(response_head + 0) = response_count; + *(response_head + 1) = 0; + *(response_head + 2) = response_value; + + return ((uint8_t)(res - response_head)); +} + +// Process SWD Transfer Block command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint8_t DAP_TransferBlock(const uint8_t *req, uint8_t *res) +{ + uint8_t num; + + switch (debug_port) + { + case DAP_PORT_SWD: + num = DAP_SWD_TransferBlock(req, res); + break; + + default: + *(res + 0) = 0U; // res count [7:0] + *(res + 1) = 0U; // res count[15:8] + *(res + 2) = 0U; // res value + num = 3U; + break; + } + + return (num); +} + +// Process SWD Write ABORT command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint8_t DAP_SWD_WriteAbort(const uint8_t *req, uint8_t *res) +{ + // Load data (Ignore DAP index) + data[0] = (uint8_t)(*(req + 1)); + data[1] = (uint8_t)(*(req + 2)); + data[2] = (uint8_t)(*(req + 3)); + data[3] = (uint8_t)(*(req + 4)); + + // Write Abort register + SWD_Transfer(DP_ABORT, data); + + *res = DAP_OK; + return (1U); +} + +// Process Write ABORT command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint8_t DAP_WriteAbort(const uint8_t *req, uint8_t *res) +{ + uint8_t num; + + switch (debug_port) + { + case DAP_PORT_SWD: + num = DAP_SWD_WriteAbort(req, res); + break; + + default: + *res = DAP_ERROR; + num = 1U; + break; + } + return num; +} + +// DAP Thread. +uint8_t DAP_Thread(void) +{ + uint8_t num; + uint8_t returnVal = 0; + + if (1) + { + uint8_t __xdata *req = &Ep1Buffer[0]; + uint8_t __xdata *res = &Ep1Buffer[64]; + + *res++ = *req; + switch (*req++) + { + case ID_DAP_Transfer: + num = DAP_Transfer(req, res); + break; + + case ID_DAP_TransferBlock: + num = DAP_TransferBlock(req, res); + break; + + case ID_DAP_Info: + num = DAP_Info(*req, res + 1); + *res = (uint8_t)num; + num++; + break; + + case ID_DAP_HostStatus: + num = DAP_HostStatus(req, res); + break; + + case ID_DAP_Connect: + num = DAP_Connect(req, res); + break; + + case ID_DAP_Disconnect: + num = DAP_Disconnect(res); + break; + + case ID_DAP_Delay: + num = DAP_Delay(req, res); + break; + + case ID_DAP_ResetTarget: + num = DAP_ResetTarget(res); + break; + + case ID_DAP_SWJ_Pins: + num = DAP_SWJ_Pins(req, res); + break; + + case ID_DAP_SWJ_Clock: + num = DAP_SWJ_Clock(req, res); + break; + + case ID_DAP_SWJ_Sequence: + num = DAP_SWJ_Sequence(req, res); + break; + + case ID_DAP_SWD_Configure: + num = DAP_SWD_Configure(req, res); + break; + + case ID_DAP_SWD_Sequence: + num = DAP_SWD_Sequence(req, res); + break; + + case ID_DAP_TransferConfigure: + num = DAP_TransferConfigure(req, res); + break; + + case ID_DAP_WriteABORT: + num = DAP_WriteAbort(req, res); + break; + + case ID_DAP_ExecuteCommands: + case ID_DAP_QueueCommands: + default: + *(res - 1) = ID_DAP_Invalid; + num = 1; + break; + } + + returnVal = num + 1; + } + + return returnVal; +} diff --git a/examples/CMSIS_DAP/DAP.h b/examples/CMSIS_DAP/DAP.h new file mode 100644 index 0000000..c38eadc --- /dev/null +++ b/examples/CMSIS_DAP/DAP.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2013-2017 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ---------------------------------------------------------------------- + * + * $Date: 1. December 2017 + * $Revision: V2.0.0 + * + * Project: CMSIS-DAP Include + * Title: DAP.h Definitions + * + *---------------------------------------------------------------------------*/ + +#ifndef __DAP_H__ +#define __DAP_H__ + +#include <8052.h> +#include +#include +#include +#include + +// DAP Firmware Version +#define DAP_FW_VER "1.2.1" + +// DAP Command IDs +#define ID_DAP_Info 0x00U +#define ID_DAP_HostStatus 0x01U +#define ID_DAP_Connect 0x02U +#define ID_DAP_Disconnect 0x03U +#define ID_DAP_TransferConfigure 0x04U +#define ID_DAP_Transfer 0x05U +#define ID_DAP_TransferBlock 0x06U +#define ID_DAP_TransferAbort 0x07U +#define ID_DAP_WriteABORT 0x08U +#define ID_DAP_Delay 0x09U +#define ID_DAP_ResetTarget 0x0AU +#define ID_DAP_SWJ_Pins 0x10U +#define ID_DAP_SWJ_Clock 0x11U +#define ID_DAP_SWJ_Sequence 0x12U +#define ID_DAP_SWD_Configure 0x13U +#define ID_DAP_SWD_Sequence 0x1DU +#define ID_DAP_JTAG_Sequence 0x14U +#define ID_DAP_JTAG_Configure 0x15U +#define ID_DAP_JTAG_IDCODE 0x16U +#define ID_DAP_SWO_Transport 0x17U +#define ID_DAP_SWO_Mode 0x18U +#define ID_DAP_SWO_Baudrate 0x19U +#define ID_DAP_SWO_Control 0x1AU +#define ID_DAP_SWO_Status 0x1BU +#define ID_DAP_SWO_ExtendedStatus 0x1EU +#define ID_DAP_SWO_Data 0x1CU + +#define ID_DAP_QueueCommands 0x7EU +#define ID_DAP_ExecuteCommands 0x7FU + +// DAP Vendor Command IDs +#define ID_DAP_Vendor0 0x80U +#define ID_DAP_Vendor1 0x81U +#define ID_DAP_Vendor2 0x82U +#define ID_DAP_Vendor3 0x83U +#define ID_DAP_Vendor4 0x84U +#define ID_DAP_Vendor5 0x85U +#define ID_DAP_Vendor6 0x86U +#define ID_DAP_Vendor7 0x87U +#define ID_DAP_Vendor8 0x88U +#define ID_DAP_Vendor9 0x89U +#define ID_DAP_Vendor10 0x8AU +#define ID_DAP_Vendor11 0x8BU +#define ID_DAP_Vendor12 0x8CU +#define ID_DAP_Vendor13 0x8DU +#define ID_DAP_Vendor14 0x8EU +#define ID_DAP_Vendor15 0x8FU +#define ID_DAP_Vendor16 0x90U +#define ID_DAP_Vendor17 0x91U +#define ID_DAP_Vendor18 0x92U +#define ID_DAP_Vendor19 0x93U +#define ID_DAP_Vendor20 0x94U +#define ID_DAP_Vendor21 0x95U +#define ID_DAP_Vendor22 0x96U +#define ID_DAP_Vendor23 0x97U +#define ID_DAP_Vendor24 0x98U +#define ID_DAP_Vendor25 0x99U +#define ID_DAP_Vendor26 0x9AU +#define ID_DAP_Vendor27 0x9BU +#define ID_DAP_Vendor28 0x9CU +#define ID_DAP_Vendor29 0x9DU +#define ID_DAP_Vendor30 0x9EU +#define ID_DAP_Vendor31 0x9FU + +#define ID_DAP_Invalid 0xFFU + +// DAP Status Code +#define DAP_OK 0U +#define DAP_ERROR 0xFFU + +// DAP ID +#define DAP_ID_VENDOR 1U +#define DAP_ID_PRODUCT 2U +#define DAP_ID_SER_NUM 3U +#define DAP_ID_FW_VER 4U +#define DAP_ID_DEVICE_VENDOR 5U +#define DAP_ID_DEVICE_NAME 6U +#define DAP_ID_CAPABILITIES 0xF0U +#define DAP_ID_TIMESTAMP_CLOCK 0xF1U +#define DAP_ID_SWO_BUFFER_SIZE 0xFDU +#define DAP_ID_PACKET_COUNT 0xFEU +#define DAP_ID_PACKET_SIZE 0xFFU + +// DAP Host Status +#define DAP_DEBUGGER_CONNECTED 0U +#define DAP_TARGET_RUNNING 1U + +// DAP Port +#define DAP_PORT_AUTODETECT 0U // Autodetect Port +#define DAP_PORT_DISABLED 0U // Port Disabled (I/O pins in High-Z) +#define DAP_PORT_SWD 1U // SWD Port (SWCLK, SWDIO) + nRESET +#define DAP_PORT_JTAG 2U // JTAG Port (TCK, TMS, TDI, TDO, nTRST) + nRESET + +// DAP SWJ Pins +#define DAP_SWJ_SWCLK_TCK 0 // SWCLK/TCK +#define DAP_SWJ_SWDIO_TMS 1 // SWDIO/TMS +#define DAP_SWJ_TDI 2 // TDI +#define DAP_SWJ_TDO 3 // TDO +#define DAP_SWJ_nTRST 5 // nTRST +#define DAP_SWJ_nRESET 7 // nRESET + +#define DAP_SWJ_SWCLK_TCK_BIT 0x01 // SWCLK/TCK +#define DAP_SWJ_SWDIO_TMS_BIT 0x02 // SWDIO/TMS +#define DAP_SWJ_TDI_BIT 0x04 // TDI +#define DAP_SWJ_TDO_BIT 0x08 // TDO +#define DAP_SWJ_nTRST_BIT 0x20 // nTRST +#define DAP_SWJ_nRESET_BIT 0x80 // nRESET + +// DAP Transfer Request +#define DAP_TRANSFER_APnDP (1U << 0) +#define DAP_TRANSFER_RnW (1U << 1) +#define DAP_TRANSFER_A2 (1U << 2) +#define DAP_TRANSFER_A3 (1U << 3) +#define DAP_TRANSFER_MATCH_VALUE (1U << 4) +#define DAP_TRANSFER_MATCH_MASK (1U << 5) +#define DAP_TRANSFER_TIMESTAMP (1U << 7) + +// DAP Transfer Response +#define DAP_TRANSFER_OK (1U << 0) +#define DAP_TRANSFER_WAIT (1U << 1) +#define DAP_TRANSFER_FAULT (1U << 2) +#define DAP_TRANSFER_ERROR (1U << 3) +#define DAP_TRANSFER_MISMATCH (1U << 4) + +// DAP SWO Trace Mode +#define DAP_SWO_OFF 0U +#define DAP_SWO_UART 1U +#define DAP_SWO_MANCHESTER 2U + +// DAP SWO Trace Status +#define DAP_SWO_CAPTURE_ACTIVE (1U << 0) +#define DAP_SWO_CAPTURE_PAUSED (1U << 1) +#define DAP_SWO_STREAM_ERROR (1U << 6) +#define DAP_SWO_BUFFER_OVERRUN (1U << 7) + +// Debug Port Register Addresses +#define DP_IDCODE 0x00U // IDCODE Register (SW Read only) +#define DP_ABORT 0x00U // Abort Register (SW Write only) +#define DP_CTRL_STAT 0x04U // Control & Status +#define DP_WCR 0x04U // Wire Control Register (SW Only) +#define DP_SELECT 0x08U // Select Register (JTAG R/W & SW W) +#define DP_RESEND 0x08U // Resend (SW Read Only) +#define DP_RDBUFF 0x0CU // Read Buffer (Read Only) + +// JTAG IR Codes +#define JTAG_ABORT 0x08U +#define JTAG_DPACC 0x0AU +#define JTAG_APACC 0x0BU +#define JTAG_IDCODE 0x0EU +#define JTAG_BYPASS 0x0FU + +// JTAG Sequence Info +#define JTAG_SEQUENCE_TCK 0x3FU // TCK count +#define JTAG_SEQUENCE_TMS 0x40U // TMS value +#define JTAG_SEQUENCE_TDO 0x80U // TDO capture + +// SWD Sequence Info +#define SWD_SEQUENCE_CLK 0x3FU // SWCLK count +#define SWD_SEQUENCE_DIN 0x80U // SWDIO capture + +#define DAP_PACKET_COUNT 1 +#define DAP_PACKET_SIZE 64 //THIS_ENDP0_SIZE +#define DAP_DEFAULT_PORT DAP_PORT_SWD + +#define RST P3_0 +#define SWK P3_1 +#define SWD P3_2 +#define LED P3_3 + +extern __xdata uint8_t Ep0Buffer[]; +extern __xdata uint8_t Ep1Buffer[]; + +extern __idata uint8_t turnaround; +extern __idata uint8_t data_phase; +extern __idata uint8_t idle_cycles; + +extern uint8_t DAP_Thread(void); +extern void PORT_SWD_SETUP(void); +extern uint8_t SWD_Transfer(uint8_t reqI, uint8_t __xdata *datas); +extern void SWJ_Sequence(uint8_t count, const uint8_t *datas); +extern void SWD_Sequence(uint8_t info, const uint8_t *swdo, uint8_t *swdi); + +#endif /* __DAP_H__ */ diff --git a/examples/CMSIS_DAP/Makefile b/examples/CMSIS_DAP/Makefile new file mode 100644 index 0000000..f233369 --- /dev/null +++ b/examples/CMSIS_DAP/Makefile @@ -0,0 +1,14 @@ +TARGET = daplink + +# reserve 256 bytes for USB DMA buffers +XRAM_SIZE = 0x0300 +XRAM_LOC = 0x0100 + +C_FILES = \ + $(wildcard *.c) \ + ../../include/debug.c + +pre-flash: + + +include ../Makefile.include diff --git a/examples/CMSIS_DAP/SW_DP.c b/examples/CMSIS_DAP/SW_DP.c new file mode 100644 index 0000000..302bbc7 --- /dev/null +++ b/examples/CMSIS_DAP/SW_DP.c @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2013-2017 ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the License); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an AS IS BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * ---------------------------------------------------------------------- + * + * $Date: 1. December 2017 + * $Revision: V2.0.0 + * + * Project: CMSIS-DAP Source + * Title: SW_DP.c CMSIS-DAP SW DP I/O + * + *---------------------------------------------------------------------------*/ + +#include "DAP.h" + +#if 0 +#define SW_CLOCK_CYCLE() \ + while(!TF2); SWK = 1; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; \ + while(!TF2); SWK = 0; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; +#endif +#define SW_CLOCK_CYCLE() \ + SWK = 0; SWK = 1; + +#if 0 +#define SW_WRITE_BIT(bits) \ + SWD = (bits)&1; \ + while(!TF2); SWK = 1; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1;\ + while(!TF2); SWK = 0; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; +#endif +#define SW_WRITE_BIT(bits) \ + SWD = (bits)&1; SWK = 0; SWK = 1; + +#if 0 + data from target was clocked out on last SWK rising edge +#define SW_READ_BIT(bits) \ + bits = SWD; \ + while(!TF2); SWK = 1; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1;\ + while(!TF2); SWK = 0; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; +#endif +#define SW_READ_BIT(bits) \ + SWK = 0; bits = SWD; SWK = 1; + +/** Setup SWD I/O pins: SWCLK, SWDIO, and nRESET. +Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode: + - SWCLK low, SWDIO, nRESET high. +*/ +void PORT_SWD_SETUP(void) +{ + // P3_MOD_OC & P3_DIR_PU = 0xFF at reset + + // set P3.1 to push-pull + P3_MOD_OC &= ~(1 << 1); + //P3_MOD_OC = P3_MOD_OC | (1 << 1); + //P3_DIR_PU = P3_DIR_PU | (1 << 1); + SWK = 0; + + //P3_MOD_OC = P3_MOD_OC | (1 << 2); + //P3_DIR_PU = P3_DIR_PU | (1 << 2); + SWD = 1; + + //P3_MOD_OC = P3_MOD_OC | (1 << 0); + //P3_DIR_PU = P3_DIR_PU | (1 << 0); + RST = 1; +} + +// todo: look at difference between SWJ & SWD sequence +// use SW_WRITE_BIT macro? +// Generate SWJ Sequence +// count: sequence bits count +// datas: pointer to sequence bits datas +// return: none +void SWJ_Sequence(uint8_t count, const uint8_t *datas) +{ + uint8_t val; + uint8_t n; + + val = 0U; + n = 0U; + while (count--) + { + if (n == 0U) + { + val = *datas++; + n = 8U; + } +/* + if (val & 1U) + { + SWD = 1; + } + else + { + SWD = 0; + } + while(!TF2); + + SWK = 1; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; + while(!TF2); SWK = 0; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; +*/ + SW_WRITE_BIT(val); + val >>= 1; + n--; + } +} + +// Generate SWD Sequence +// info: sequence information +// swdo: pointer to SWDIO generated datas +// swdi: pointer to SWDIO captured datas +// return: none +void SWD_Sequence(uint8_t info, const uint8_t *swdo, uint8_t *swdi) +{ + uint8_t val; + uint8_t bits; + uint8_t n, k; + + n = info & SWD_SEQUENCE_CLK; + if (n == 0U) + { + n = 64U; + } + + if (info & SWD_SEQUENCE_DIN) + { + while (n) + { + val = 0U; + for (k = 8U; k && n; k--, n--) + { + SW_READ_BIT(bits); + val >>= 1; + val |= bits << 7; + } + val >>= k; + *swdi++ = (uint8_t)val; + } + } + else + { + while (n) + { + val = *swdo++; + for (k = 8U; k && n; k--, n--) + { + SW_WRITE_BIT(val); + val >>= 1; + } + } + } +} + +// SWD Transfer I/O +// request: A[3:2] RnW APnDP +// datas: DATA[31:0] +// return: ACK[2:0] +uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) +{ + uint8_t ack; + uint8_t bits = req; + uint8_t val; + uint8_t parity; + + uint8_t m, n; + + /* Packet req */ + parity = 0U; + SW_WRITE_BIT(1U); /* Start Bit */ + SW_WRITE_BIT(bits); /* APnDP Bit */ + parity += bits; + bits >>= 1; + SW_WRITE_BIT(bits); /* RnW Bit */ + parity += bits; + bits >>= 1; + SW_WRITE_BIT(bits); /* A2 Bit */ + parity += bits; + bits >>= 1; + SW_WRITE_BIT(bits); /* A3 Bit */ + parity += bits; + SW_WRITE_BIT(parity); /* Parity Bit */ + SW_WRITE_BIT(0U); /* Stop Bit */ + SW_WRITE_BIT(1U); /* Park Bit */ + + /* Turnaround */ + for (n = turnaround; n; n--) + { + SW_CLOCK_CYCLE(); + } + + /* Acknowledge res */ + SW_READ_BIT(bits); + ack = bits << 0; + SW_READ_BIT(bits); + ack |= bits << 1; + SW_READ_BIT(bits); + ack |= bits << 2; + + if (ack == DAP_TRANSFER_OK) + { + /* OK res */ + /* Data transfer */ + if (req & DAP_TRANSFER_RnW) + { + /* Read datas */ + val = 0U; + parity = 0U; + for (m = 0; m < 4; m++) + { + for (n = 8U; n; n--) + { + SW_READ_BIT(bits); /* Read RDATA[0:31] */ + parity += bits; + val >>= 1; + //val |= bits << 7; + if (bits) val |= 0x80; + } + if (datas) + { + datas[m] = val; + } + } + SW_READ_BIT(bits); /* Read Parity */ + if ((parity ^ bits) & 1U) + { + ack = DAP_TRANSFER_ERROR; + } + + /* Turnaround */ + for (n = turnaround; n; n--) + { + SW_CLOCK_CYCLE(); + } + SWD = 1; + } + else + { + /* Turnaround */ + for (n = turnaround; n; n--) + { + SW_CLOCK_CYCLE(); + } + SWD = 1; + /* Write datas */ + parity = 0U; + for (m = 0; m < 4; m++) + { + val = datas[m]; + for (n = 8U; n; n--) + { + SW_WRITE_BIT(val); /* Write WDATA[0:31] */ + parity += val; + val >>= 1; + } + } + SW_WRITE_BIT(parity); /* Write Parity Bit */ + } + /* Idle cycles */ + n = idle_cycles; + if (n) + { + SWD = 0; + for (; n; n--) + { + SW_CLOCK_CYCLE(); + } + } + SWD = 1; + return ((uint8_t)ack); + } + + if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) + { + /* WAIT or FAULT res */ + if (data_phase && ((req & DAP_TRANSFER_RnW) != 0U)) + { + for (n = 32U + 1U; n; n--) + { + SW_CLOCK_CYCLE(); /* Dummy Read RDATA[0:31] + Parity */ + } + } + /* Turnaround */ + for (n = turnaround; n; n--) + { + SW_CLOCK_CYCLE(); + } + SWD = 1; + if (data_phase && ((req & DAP_TRANSFER_RnW) == 0U)) + { + SWD = 0; + for (n = 32U + 1U; n; n--) + { + SW_CLOCK_CYCLE(); /* Dummy Write WDATA[0:31] + Parity */ + } + } + SWD = 1; + return ((uint8_t)ack); + } + + /* Protocol error */ + for (n = turnaround + 32U + 1U; n; n--) + { + SW_CLOCK_CYCLE(); /* Back off datas phase */ + } + SWD = 1; + return ((uint8_t)ack); +} diff --git a/examples/CMSIS_DAP/USBHID.c b/examples/CMSIS_DAP/USBHID.c new file mode 100644 index 0000000..a14f419 --- /dev/null +++ b/examples/CMSIS_DAP/USBHID.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include +#include "USBconstant.h" +#include "USBhandler.h" + +extern __xdata uint8_t Ep0Buffer[]; +extern __xdata uint8_t Ep1Buffer[]; + +volatile __xdata uint8_t USBByteCountEP1 = 0; //Bytes of received data on USB endpoint + +void USBInit(){ + USBDeviceCfg(); //Device mode configuration + USBDeviceEndPointCfg(); //Endpoint configuration + USBDeviceIntCfg(); //Interrupt configuration + UEP0_T_LEN = 0; + UEP1_T_LEN = 0; //Pre-use send length must be cleared + UEP2_T_LEN = 0; +} + +void USB_EP1_IN(){ + UEP1_T_LEN = 0; // No data to send anymore + UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_NAK; //Respond NAK by default + +} + +void USB_EP1_OUT(){ + if ( U_TOG_OK ){ // Discard unsynchronized packets + USBByteCountEP1 = USB_RX_LEN; + if (USBByteCountEP1){ + UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_NAK; //Respond NAK after a packet. Let main code change response after handling. + } + } +} + diff --git a/examples/CMSIS_DAP/USBHID.h b/examples/CMSIS_DAP/USBHID.h new file mode 100644 index 0000000..efe31ec --- /dev/null +++ b/examples/CMSIS_DAP/USBHID.h @@ -0,0 +1,9 @@ +#ifndef __USB_HID_H__ +#define __USB_HID_H__ + +#include + +void USBInit(void); + +#endif + diff --git a/examples/CMSIS_DAP/USBconstant.c b/examples/CMSIS_DAP/USBconstant.c new file mode 100644 index 0000000..2a3d06c --- /dev/null +++ b/examples/CMSIS_DAP/USBconstant.c @@ -0,0 +1,112 @@ +// Descriptors for CMSIS_DAP + +#include +#include +#include "USBconstant.h" + + +//Device descriptor +__code uint8_t DevDesc[] = { + 0x12,0x01, + 0x10,0x01, //USB spec release number in BCD format, USB1.1 (0x10, 0x01). + 0x00,0x00,0x00, //bDeviceClass, bDeviceSubClass, bDeviceProtocol + DEFAULT_ENDP0_SIZE, //PACKET_SIZE + 0x09,0x12,0x5D,0xC5, // VID PID + 0x00,0x01, //version + 0x01,0x02,0x03, //bString + 0x01 //bNumConfigurations +}; + +__code uint16_t DevDescLen = sizeof(DevDesc); + +__code uint8_t CfgDesc[] ={ + 0x09,0x02,sizeof(CfgDesc) & 0xff,sizeof(CfgDesc) >> 8, + 0x01, /* bNumInterfaces */ + 0x01, /* bConfigurationValue */ + 0x00, /* iConfiguration */ + 0x80, /* bmAttributes */ + 0x64, /* MaxPower */ + + + /* I/F descr: HID */ + 0x09, /* bLength */ + 0x04, /* bDescriptorType */ + 0x00, /* bInterfaceNumber */ + 0x00, /* bAlternateSetting */ + 0x02, /* bNumEndpoints */ + 0x03, /* bInterfaceClass */ + 0x00, /* bInterfaceSubClass */ + 0x00, /* bInterfaceProtocol */ + 0x00, /* iInterface */ + + /* HID Descriptor */ + 0x09, /* Size of this descriptor in UINT8s. */ + 0x21, /* HID descriptor type. */ + 0x10, 0x01, /* HID Class Spec. release number. */ + 0x00, /* H/W target country. */ + 0x01, /* Number of HID class descriptors to follow. */ + 0x22, /* Descriptor type. */ + sizeof(ReportDesc) & 0xff,sizeof(ReportDesc) >> 8, /* Total length of report descriptor. */ + + /* EP Descriptor: interrupt in. */ + 0x07, /* bLength */ + 0x05, /* bDescriptorType */ + 0x01, /* bEndpointAddress */ + 0x03, /* bmAttributes */ + 0x40, 0x00, /* wMaxPacketSize */ + 1, /* bInterval */ + + /* EP Descriptor: interrupt out. */ + 0x07, /* bLength */ + 0x05, /* bDescriptorType */ + 0x81, /* bEndpointAddress */ + 0x03, /* bmAttributes */ + 0x40, 0x00, /* wMaxPacketSize */ + 1 /* bInterval */ + + +}; + + +__code uint16_t ReportDescLen = sizeof(ReportDesc); + +__code uint8_t ReportDesc[] ={ + 0x06, 0x00, 0xFF, // Usage Page = 0xFF00 (Vendor Defined Page 1) + 0x09, 0x01, // Usage (Vendor Usage 1) + 0xA1, 0x01, // Collection (Application) + 0x19, 0x01, // Usage Minimum + 0x29, 0x40, // Usage Maximum //64 input usages total (0x01 to 0x40) + 0x15, 0x00, // Logical Minimum (data bytes in the report may have minimum value = 0x00) + 0x26, 0xFF, 0x00, // Logical Maximum (data bytes in the report may have maximum value = 0x00FF = unsigned 255) + 0x75, 0x08, // Report Size: 8-bit field size + 0x95, 0x40, // Report Count: Make sixty-four 8-bit fields (the next time the parser hits an "Input", "Output", or "Feature" item) + 0x81, 0x00, // Input (Data, Array, Abs): Instantiates input packet fields based on the above report size, count, logical min/max, and usage. + 0x19, 0x01, // Usage Minimum + 0x29, 0x40, // Usage Maximum //64 output usages total (0x01 to 0x40) + 0x91, 0x00, // Output (Data, Array, Abs): Instantiates output packet fields. Uses same report size and count as "Input" fields, since nothing new/different was specified to the parser since the "Input" item. + 0xC0 // End Collection +}; + +__code uint16_t CfgDescLen = sizeof(CfgDesc); + +//String Descriptors +__code uint8_t LangDes[]={0x04,0x03,0x09,0x04}; //Language Descriptor +__code uint16_t LangDesLen = sizeof(LangDes); +__code uint8_t SerDes[]={ //Serial String Descriptor + 0x0C,0x03, + 'C',0x00,'H',0x00,'5',0x00,'5',0x00,'x',0x00 +}; +__code uint16_t SerDesLen = sizeof(SerDes); +__code uint8_t Prod_Des[]={ //Produce String Descriptor + 0x20,0x03, + 'C',0x00,'H',0x00,'5',0x00,'5',0x00,'x',0x00,' ',0x00, + 'C',0x00,'M',0x00,'S',0x00,'I',0x00,'S',0x00,'-',0x00 + ,'D',0x00,'A',0x00, 'P',0x00 +}; +__code uint16_t Prod_DesLen = sizeof(Prod_Des); + +__code uint8_t Manuf_Des[]={ + 0x0E,0x03, + 'D',0x00,'e',0x00,'q',0x00,'i',0x00,'n',0x00,'g',0x00, +}; +__code uint16_t Manuf_DesLen = sizeof(Manuf_Des); diff --git a/examples/CMSIS_DAP/USBconstant.h b/examples/CMSIS_DAP/USBconstant.h new file mode 100644 index 0000000..82f91ed --- /dev/null +++ b/examples/CMSIS_DAP/USBconstant.h @@ -0,0 +1,26 @@ +#ifndef __CONST_DATA_H__ +#define __CONST_DATA_H__ + +#include + +#define EP0_ADDR 0 +#define EP1_ADDR 10 +#define EP2_ADDR 20 + +extern __code uint8_t DevDesc[]; +extern __code uint8_t CfgDesc[]; +extern __code uint8_t LangDes[]; +extern __code uint8_t ReportDesc[]; +extern __code uint8_t SerDes[]; +extern __code uint8_t Prod_Des[]; +extern __code uint8_t Manuf_Des[]; + +extern __code uint16_t DevDescLen; +extern __code uint16_t CfgDescLen; +extern __code uint16_t LangDesLen; +extern __code uint16_t ReportDescLen; +extern __code uint16_t SerDesLen; +extern __code uint16_t Prod_DesLen; +extern __code uint16_t Manuf_DesLen; + +#endif diff --git a/examples/CMSIS_DAP/USBhandler.c b/examples/CMSIS_DAP/USBhandler.c new file mode 100644 index 0000000..a833202 --- /dev/null +++ b/examples/CMSIS_DAP/USBhandler.c @@ -0,0 +1,458 @@ + +#include +#include +#include "USBhandler.h" +#include "USBconstant.h" + +//HID functions: +void USB_EP1_IN(); +void USB_EP1_OUT(); + +__xdata __at (EP0_ADDR) uint8_t Ep0Buffer[8]; +__xdata __at (EP1_ADDR) uint8_t Ep1Buffer[128]; //on page 47 of data sheet, the receive buffer need to be min(possible packet size+2,64) //IN and OUT buffer, must be even address + +uint16_t SetupLen; +uint8_t SetupReq,UsbConfig; + +__code uint8_t *pDescr; + +volatile uint8_t usbMsgFlags=0; // uint8_t usbMsgFlags copied from VUSB + +inline void NOP_Process(void) {} + +void USB_EP0_SETUP(){ + uint8_t len = USB_RX_LEN; + if(len == (sizeof(USB_SETUP_REQ))) + { + SetupLen = ((uint16_t)UsbSetupBuf->wLengthH<<8) | (UsbSetupBuf->wLengthL); + len = 0; // Default is success and upload 0 length + SetupReq = UsbSetupBuf->bRequest; + usbMsgFlags = 0; + if ( ( UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD )//Not standard request + { + + //here is the commnunication starts, refer to usbFunctionSetup of USBtiny + //or usb_setup in usbtiny + + switch( ( UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK )) + { + case USB_REQ_TYP_VENDOR: + { + switch( SetupReq ) + { + default: + len = 0xFF; //command not supported + break; + } + break; + } + case USB_REQ_TYP_CLASS: + { + switch( SetupReq ) + { + default: + len = 0xFF; //command not supported + break; + } + break; + } + default: + len = 0xFF; //command not supported + break; + } + + } + else //Standard request + { + switch(SetupReq) //Request ccfType + { + case USB_GET_DESCRIPTOR: + switch(UsbSetupBuf->wValueH) + { + case 1: //Device Descriptor + pDescr = DevDesc; //Put Device Descriptor into outgoing buffer + len = DevDescLen; + break; + case 2: //Configure Descriptor + pDescr = CfgDesc; + len = CfgDescLen; + break; + case 3: + if(UsbSetupBuf->wValueL == 0) + { + pDescr = LangDes; + len = LangDesLen; + } + else if(UsbSetupBuf->wValueL == 1) + { + pDescr = Manuf_Des; + len = Manuf_DesLen; + } + else if(UsbSetupBuf->wValueL == 2) + { + pDescr = Prod_Des; + len = Prod_DesLen; + } + else if(UsbSetupBuf->wValueL == 3) + { + pDescr = SerDes; + len = SerDesLen; + } + else + { + pDescr = SerDes; + len = SerDesLen; + } + break; + case 0x22: + if(UsbSetupBuf->wValueL == 0){ + pDescr = ReportDesc; + len = ReportDescLen; + } + else + { + len = 0xff; + } + break; + default: + len = 0xff; // Unsupported descriptors or error + break; + } + if (len != 0xff){ + if ( SetupLen > len ) + { + SetupLen = len; // Limit length + } + len = SetupLen >= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupLen; //transmit length for this packet + for (uint8_t i=0;iwValueL; // Save the assigned address + break; + case USB_GET_CONFIGURATION: + Ep0Buffer[0] = UsbConfig; + if ( SetupLen >= 1 ) + { + len = 1; + } + break; + case USB_SET_CONFIGURATION: + UsbConfig = UsbSetupBuf->wValueL; + break; + case USB_GET_INTERFACE: + break; + case USB_SET_INTERFACE: + break; + case USB_CLEAR_FEATURE: + if( ( UsbSetupBuf->bRequestType & 0x1F ) == USB_REQ_RECIP_DEVICE ) // Clear the device featuee. + { + if( ( ( ( uint16_t )UsbSetupBuf->wValueH << 8 ) | UsbSetupBuf->wValueL ) == 0x01 ) + { + if( CfgDesc[ 7 ] & 0x20 ) + { + // wake up + } + else + { + len = 0xFF; //Failed + } + } + else + { + len = 0xFF; //Failed + } + } + else if ( ( UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK ) == USB_REQ_RECIP_ENDP )// endpoint + { + switch( UsbSetupBuf->wIndexL ) + { + case 0x84: + UEP4_CTRL = UEP4_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK; + break; + case 0x04: + UEP4_CTRL = UEP4_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK; + break; + case 0x83: + UEP3_CTRL = UEP3_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK; + break; + case 0x03: + UEP3_CTRL = UEP3_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK; + break; + case 0x82: + UEP2_CTRL = UEP2_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK; + break; + case 0x02: + UEP2_CTRL = UEP2_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK; + break; + case 0x81: + UEP1_CTRL = UEP1_CTRL & ~ ( bUEP_T_TOG | MASK_UEP_T_RES ) | UEP_T_RES_NAK; + break; + case 0x01: + UEP1_CTRL = UEP1_CTRL & ~ ( bUEP_R_TOG | MASK_UEP_R_RES ) | UEP_R_RES_ACK; + break; + default: + len = 0xFF; // Unsupported endpoint + break; + } + } + else + { + len = 0xFF; // Unsupported for non-endpoint + } + break; + case USB_SET_FEATURE: // Set Feature + if( ( UsbSetupBuf->bRequestType & 0x1F ) == USB_REQ_RECIP_DEVICE ) // Set the device featuee. + { + if( ( ( ( uint16_t )UsbSetupBuf->wValueH << 8 ) | UsbSetupBuf->wValueL ) == 0x01 ) + { + if( CfgDesc[ 7 ] & 0x20 ) + { + // suspend not supported + } + else + { + len = 0xFF; // Failed + } + } + else + { + len = 0xFF; // Failed + } + } + else if( ( UsbSetupBuf->bRequestType & 0x1F ) == USB_REQ_RECIP_ENDP ) //endpoint + { + if( ( ( ( uint16_t )UsbSetupBuf->wValueH << 8 ) | UsbSetupBuf->wValueL ) == 0x00 ) + { + switch( ( ( uint16_t )UsbSetupBuf->wIndexH << 8 ) | UsbSetupBuf->wIndexL ) + { + case 0x84: + UEP4_CTRL = UEP4_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;// Set endpoint4 IN STALL + break; + case 0x04: + UEP4_CTRL = UEP4_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;// Set endpoint4 OUT Stall + break; + case 0x83: + UEP3_CTRL = UEP3_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;// Set endpoint3 IN STALL + break; + case 0x03: + UEP3_CTRL = UEP3_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;// Set endpoint3 OUT Stall + break; + case 0x82: + UEP2_CTRL = UEP2_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;// Set endpoint2 IN STALL + break; + case 0x02: + UEP2_CTRL = UEP2_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;// Set endpoint2 OUT Stall + break; + case 0x81: + UEP1_CTRL = UEP1_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL;// Set endpoint1 IN STALL + break; + case 0x01: + UEP1_CTRL = UEP1_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL;// Set endpoint1 OUT Stall + default: + len = 0xFF; // Failed + break; + } + } + else + { + len = 0xFF; // Failed + } + } + else + { + len = 0xFF; // Failed + } + break; + case USB_GET_STATUS: + Ep0Buffer[0] = 0x00; + Ep0Buffer[1] = 0x00; + if ( SetupLen >= 2 ) + { + len = 2; + } + else + { + len = SetupLen; + } + break; + default: + len = 0xff; // Failed + break; + } + } + } + else + { + len = 0xff; //Wrong packet length + } + if(len == 0xff) + { + SetupReq = 0xFF; + UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_STALL | UEP_T_RES_STALL;//STALL + } + else if(len <= DEFAULT_ENDP0_SIZE) // Tx data to host or send 0-length packet + { + UEP0_T_LEN = len; + UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK;//Expect DATA1, Answer ACK + } + else + { + UEP0_T_LEN = 0; // Tx data to host or send 0-length packet + UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK;//Expect DATA1, Answer ACK + } +} + +void USB_EP0_IN(){ + switch(SetupReq) + { + case USB_GET_DESCRIPTOR: + { + uint8_t len = SetupLen >= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupLen; //send length + for (uint8_t i=0;i +#include "USBconstant.h" + +extern uint16_t SetupLen; +extern uint8_t SetupReq,UsbConfig; +extern const __code uint8_t *pDescr; + + +#define UsbSetupBuf ((PUSB_SETUP_REQ)Ep0Buffer) + +// Out +#define EP0_OUT_Callback USB_EP0_OUT +#define EP1_OUT_Callback USB_EP1_OUT +#define EP2_OUT_Callback NOP_Process +#define EP3_OUT_Callback NOP_Process +#define EP4_OUT_Callback NOP_Process + +// SOF +#define EP0_SOF_Callback NOP_Process +#define EP1_SOF_Callback NOP_Process +#define EP2_SOF_Callback NOP_Process +#define EP3_SOF_Callback NOP_Process +#define EP4_SOF_Callback NOP_Process + +// IN +#define EP0_IN_Callback USB_EP0_IN +#define EP1_IN_Callback USB_EP1_IN +#define EP2_IN_Callback NOP_Process +#define EP3_IN_Callback NOP_Process +#define EP4_IN_Callback NOP_Process + +// SETUP +#define EP0_SETUP_Callback USB_EP0_SETUP +#define EP1_SETUP_Callback NOP_Process +#define EP2_SETUP_Callback NOP_Process +#define EP3_SETUP_Callback NOP_Process +#define EP4_SETUP_Callback NOP_Process + +void USBInterrupt(void); +void USBDeviceCfg(); +void USBDeviceIntCfg(); +void USBDeviceEndPointCfg(); + +#endif + diff --git a/examples/CMSIS_DAP/main.c b/examples/CMSIS_DAP/main.c new file mode 100644 index 0000000..36bb02b --- /dev/null +++ b/examples/CMSIS_DAP/main.c @@ -0,0 +1,41 @@ +/* + CMSIS_DAP + Based on DAPLink and Deqing Sun's CH55xduino port + https://github.com/ARMmbed/DAPLink + + DAP.h defaults: + RST = P30 + SWCLK = P31 + SWDIO = P32 + LED = P33 +*/ + +#include +#include "DAP.h" +#include "USBHID.h" +#include "USBhandler.h" + +void DeviceUSBInterrupt(void) __interrupt (INT_NO_USB) +{ + USBInterrupt(); +} + + +extern volatile __xdata uint8_t USBByteCountEP1; + + +void main() { + CfgFsys(); + USBInit(); + while (1) { + if (USBByteCountEP1) { + DAP_Thread(); + USBByteCountEP1 = 0 ; + + UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_ACK; //enable receive + + UEP1_T_LEN = 64; + UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_ACK; //enable send + } + } +} From 8fab4c27bb7cea6cbe722b62de6bcc1f04f848bf Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Wed, 13 Jan 2021 19:45:14 -0400 Subject: [PATCH 11/54] include stdint --- include/ch554_usb.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/ch554_usb.h b/include/ch554_usb.h index 34d0d25..e510cc1 100644 --- a/include/ch554_usb.h +++ b/include/ch554_usb.h @@ -1,16 +1,17 @@ /*-------------------------------------------------------------------------- -CH554.H -Header file for CH554 microcontrollers. +CH554.H Header file for CH554 microcontrollers. **************************************** ** Copyright (C) W.ch 1999-2014 ** ** Web: http://wch.cn ** **************************************** +** 2021 changes Ralph Doncaster http://nerdralph.blogspot.ca/ --------------------------------------------------------------------------*/ - #ifndef __USB_DEF__ #define __USB_DEF__ +#include + /*----- USB constant and structure define --------------------------------*/ /* USB PID */ From 08b7e7eb1feb23cd4373366b9d86a5091bce90fc Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Wed, 13 Jan 2021 19:46:46 -0400 Subject: [PATCH 12/54] include ch554 --- include/debug.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/debug.h b/include/debug.h index aab6d02..d662be0 100644 --- a/include/debug.h +++ b/include/debug.h @@ -4,6 +4,7 @@ #pragma once #include +#include "ch554.h" #ifndef UART0_BAUD #define UART0_BAUD 9600 From f27bd64dc454b8595761b7258702aa3aaa6f31c2 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Thu, 14 Jan 2021 14:23:37 -0400 Subject: [PATCH 13/54] cleanup and optimize --- examples/CMSIS_DAP/SW_DP.c | 55 +++++++------------------------------- 1 file changed, 10 insertions(+), 45 deletions(-) diff --git a/examples/CMSIS_DAP/SW_DP.c b/examples/CMSIS_DAP/SW_DP.c index 302bbc7..805128a 100644 --- a/examples/CMSIS_DAP/SW_DP.c +++ b/examples/CMSIS_DAP/SW_DP.c @@ -27,32 +27,15 @@ #include "DAP.h" -#if 0 #define SW_CLOCK_CYCLE() \ - while(!TF2); SWK = 1; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; \ - while(!TF2); SWK = 0; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; -#endif -#define SW_CLOCK_CYCLE() \ - SWK = 0; SWK = 1; + SWK = 1; SWK = 0; -#if 0 -#define SW_WRITE_BIT(bits) \ - SWD = (bits)&1; \ - while(!TF2); SWK = 1; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1;\ - while(!TF2); SWK = 0; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; -#endif #define SW_WRITE_BIT(bits) \ - SWD = (bits)&1; SWK = 0; SWK = 1; + SWD = (bits)&1; SWK = 1; SWK = 0; -#if 0 - data from target was clocked out on last SWK rising edge +// data from target was clocked out on last SWK rising edge #define SW_READ_BIT(bits) \ - bits = SWD; \ - while(!TF2); SWK = 1; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1;\ - while(!TF2); SWK = 0; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; -#endif -#define SW_READ_BIT(bits) \ - SWK = 0; bits = SWD; SWK = 1; + bits = SWD; SWK = 1; SWK = 0; /** Setup SWD I/O pins: SWCLK, SWDIO, and nRESET. Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode: @@ -97,20 +80,6 @@ void SWJ_Sequence(uint8_t count, const uint8_t *datas) val = *datas++; n = 8U; } -/* - if (val & 1U) - { - SWD = 1; - } - else - { - SWD = 0; - } - while(!TF2); - - SWK = 1; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; - while(!TF2); SWK = 0; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; -*/ SW_WRITE_BIT(val); val >>= 1; n--; @@ -214,7 +183,7 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) /* Data transfer */ if (req & DAP_TRANSFER_RnW) { - /* Read datas */ + /* Read data */ val = 0U; parity = 0U; for (m = 0; m < 4; m++) @@ -222,15 +191,11 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) for (n = 8U; n; n--) { SW_READ_BIT(bits); /* Read RDATA[0:31] */ - parity += bits; + //parity += bits; val >>= 1; - //val |= bits << 7; if (bits) val |= 0x80; } - if (datas) - { - datas[m] = val; - } + *datas++ = val; } SW_READ_BIT(bits); /* Read Parity */ if ((parity ^ bits) & 1U) @@ -278,7 +243,7 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) } } SWD = 1; - return ((uint8_t)ack); + return ack; } if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) @@ -306,7 +271,7 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) } } SWD = 1; - return ((uint8_t)ack); + return ack; } /* Protocol error */ @@ -315,5 +280,5 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) SW_CLOCK_CYCLE(); /* Back off datas phase */ } SWD = 1; - return ((uint8_t)ack); + return ack; } From 8b79b002e9d9c0b603a01b41c7f8c361d9d1379a Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Thu, 14 Jan 2021 14:25:26 -0400 Subject: [PATCH 14/54] cleanup USB descriptors --- examples/CMSIS_DAP/Makefile | 3 ++ examples/CMSIS_DAP/USBHID.c | 3 +- examples/CMSIS_DAP/USBHID.h | 2 ++ examples/CMSIS_DAP/USBconstant.c | 59 ++++++++++++++++---------------- examples/CMSIS_DAP/USBconstant.h | 20 +++++------ examples/CMSIS_DAP/USBhandler.c | 16 ++------- examples/CMSIS_DAP/main.c | 6 ++-- 7 files changed, 51 insertions(+), 58 deletions(-) diff --git a/examples/CMSIS_DAP/Makefile b/examples/CMSIS_DAP/Makefile index f233369..1d90436 100644 --- a/examples/CMSIS_DAP/Makefile +++ b/examples/CMSIS_DAP/Makefile @@ -1,5 +1,8 @@ TARGET = daplink +# 24M not stable if VCC = 3V3 +FREQ_SYS = 16000000 + # reserve 256 bytes for USB DMA buffers XRAM_SIZE = 0x0300 XRAM_LOC = 0x0100 diff --git a/examples/CMSIS_DAP/USBHID.c b/examples/CMSIS_DAP/USBHID.c index a14f419..b087ada 100644 --- a/examples/CMSIS_DAP/USBHID.c +++ b/examples/CMSIS_DAP/USBHID.c @@ -8,7 +8,8 @@ extern __xdata uint8_t Ep0Buffer[]; extern __xdata uint8_t Ep1Buffer[]; -volatile __xdata uint8_t USBByteCountEP1 = 0; //Bytes of received data on USB endpoint +//Bytes of received data on USB endpoint +volatile uint8_t USBByteCountEP1 = 0; void USBInit(){ USBDeviceCfg(); //Device mode configuration diff --git a/examples/CMSIS_DAP/USBHID.h b/examples/CMSIS_DAP/USBHID.h index efe31ec..f622a6f 100644 --- a/examples/CMSIS_DAP/USBHID.h +++ b/examples/CMSIS_DAP/USBHID.h @@ -3,6 +3,8 @@ #include +extern volatile uint8_t USBByteCountEP1; + void USBInit(void); #endif diff --git a/examples/CMSIS_DAP/USBconstant.c b/examples/CMSIS_DAP/USBconstant.c index 2a3d06c..1522a9f 100644 --- a/examples/CMSIS_DAP/USBconstant.c +++ b/examples/CMSIS_DAP/USBconstant.c @@ -6,19 +6,23 @@ //Device descriptor -__code uint8_t DevDesc[] = { - 0x12,0x01, - 0x10,0x01, //USB spec release number in BCD format, USB1.1 (0x10, 0x01). - 0x00,0x00,0x00, //bDeviceClass, bDeviceSubClass, bDeviceProtocol - DEFAULT_ENDP0_SIZE, //PACKET_SIZE - 0x09,0x12,0x5D,0xC5, // VID PID - 0x00,0x01, //version - 0x01,0x02,0x03, //bString - 0x01 //bNumConfigurations +__code USB_DEV_DESCR DevDesc = { + .bLength = 18, + .bDescriptorType = USB_DESCR_TYP_DEVICE, + .bcdUSBH = 0x01, .bcdUSBL = 0x10, + .bDeviceClass = 0, // interface will define class + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = DEFAULT_ENDP0_SIZE, + .idVendorH = 0x12, .idVendorL = 0x09, + .idProductH = 0xC5, .idProductL = 0x5D, + .bcdDeviceH = 0x01, .bcdDeviceL = 0x00, + .iManufacturer = 1, // string descriptors + .iProduct = 2, + .iSerialNumber = 0, // no serial number string + .bNumConfigurations = 1 }; -__code uint16_t DevDescLen = sizeof(DevDesc); - __code uint8_t CfgDesc[] ={ 0x09,0x02,sizeof(CfgDesc) & 0xff,sizeof(CfgDesc) >> 8, 0x01, /* bNumInterfaces */ @@ -68,7 +72,7 @@ __code uint8_t CfgDesc[] ={ }; -__code uint16_t ReportDescLen = sizeof(ReportDesc); +__code uint8_t ReportDescLen = sizeof(ReportDesc); __code uint8_t ReportDesc[] ={ 0x06, 0x00, 0xFF, // Usage Page = 0xFF00 (Vendor Defined Page 1) @@ -87,26 +91,23 @@ __code uint8_t ReportDesc[] ={ 0xC0 // End Collection }; -__code uint16_t CfgDescLen = sizeof(CfgDesc); +__code uint8_t CfgDescLen = sizeof(CfgDesc); //String Descriptors __code uint8_t LangDes[]={0x04,0x03,0x09,0x04}; //Language Descriptor -__code uint16_t LangDesLen = sizeof(LangDes); -__code uint8_t SerDes[]={ //Serial String Descriptor - 0x0C,0x03, - 'C',0x00,'H',0x00,'5',0x00,'5',0x00,'x',0x00 -}; -__code uint16_t SerDesLen = sizeof(SerDes); -__code uint8_t Prod_Des[]={ //Produce String Descriptor - 0x20,0x03, - 'C',0x00,'H',0x00,'5',0x00,'5',0x00,'x',0x00,' ',0x00, - 'C',0x00,'M',0x00,'S',0x00,'I',0x00,'S',0x00,'-',0x00 - ,'D',0x00,'A',0x00, 'P',0x00 +__code uint8_t LangDesLen = sizeof(LangDes); + +//Product String Descriptor +__code uint16_t Prod_Des[]={ + 0x0320, // type and length + // u"CH55x CMSIS-DAP" + 'C','H','5','5','x',' ', + 'C','M','S','I','S','-','D','A','P' }; -__code uint16_t Prod_DesLen = sizeof(Prod_Des); +__code uint8_t Prod_DesLen = sizeof(Prod_Des); -__code uint8_t Manuf_Des[]={ - 0x0E,0x03, - 'D',0x00,'e',0x00,'q',0x00,'i',0x00,'n',0x00,'g',0x00, +__code uint16_t Manuf_Des[]={ + 0x0308, // type and length + 'W','C','H' }; -__code uint16_t Manuf_DesLen = sizeof(Manuf_Des); +__code uint8_t Manuf_DesLen = sizeof(Manuf_Des); diff --git a/examples/CMSIS_DAP/USBconstant.h b/examples/CMSIS_DAP/USBconstant.h index 82f91ed..d7f4c16 100644 --- a/examples/CMSIS_DAP/USBconstant.h +++ b/examples/CMSIS_DAP/USBconstant.h @@ -2,25 +2,23 @@ #define __CONST_DATA_H__ #include +#include #define EP0_ADDR 0 #define EP1_ADDR 10 #define EP2_ADDR 20 -extern __code uint8_t DevDesc[]; +extern __code USB_DEV_DESCR DevDesc; extern __code uint8_t CfgDesc[]; extern __code uint8_t LangDes[]; extern __code uint8_t ReportDesc[]; -extern __code uint8_t SerDes[]; -extern __code uint8_t Prod_Des[]; -extern __code uint8_t Manuf_Des[]; +extern __code uint16_t Prod_Des[]; +extern __code uint16_t Manuf_Des[]; -extern __code uint16_t DevDescLen; -extern __code uint16_t CfgDescLen; -extern __code uint16_t LangDesLen; -extern __code uint16_t ReportDescLen; -extern __code uint16_t SerDesLen; -extern __code uint16_t Prod_DesLen; -extern __code uint16_t Manuf_DesLen; +extern __code uint8_t CfgDescLen; +extern __code uint8_t LangDesLen; +extern __code uint8_t ReportDescLen; +extern __code uint8_t Prod_DesLen; +extern __code uint8_t Manuf_DesLen; #endif diff --git a/examples/CMSIS_DAP/USBhandler.c b/examples/CMSIS_DAP/USBhandler.c index a833202..bd89735 100644 --- a/examples/CMSIS_DAP/USBhandler.c +++ b/examples/CMSIS_DAP/USBhandler.c @@ -70,10 +70,10 @@ void USB_EP0_SETUP(){ switch(UsbSetupBuf->wValueH) { case 1: //Device Descriptor - pDescr = DevDesc; //Put Device Descriptor into outgoing buffer - len = DevDescLen; + pDescr = (uint8_t *)&DevDesc; + len = sizeof(DevDesc); break; - case 2: //Configure Descriptor + case 2: //Configuration Descriptor pDescr = CfgDesc; len = CfgDescLen; break; @@ -93,16 +93,6 @@ void USB_EP0_SETUP(){ pDescr = Prod_Des; len = Prod_DesLen; } - else if(UsbSetupBuf->wValueL == 3) - { - pDescr = SerDes; - len = SerDesLen; - } - else - { - pDescr = SerDes; - len = SerDesLen; - } break; case 0x22: if(UsbSetupBuf->wValueL == 0){ diff --git a/examples/CMSIS_DAP/main.c b/examples/CMSIS_DAP/main.c index 36bb02b..5623ed4 100644 --- a/examples/CMSIS_DAP/main.c +++ b/examples/CMSIS_DAP/main.c @@ -3,6 +3,8 @@ Based on DAPLink and Deqing Sun's CH55xduino port https://github.com/ARMmbed/DAPLink + Code cleanup and optimization by Ralph Doncaster + DAP.h defaults: RST = P30 SWCLK = P31 @@ -20,10 +22,6 @@ void DeviceUSBInterrupt(void) __interrupt (INT_NO_USB) USBInterrupt(); } - -extern volatile __xdata uint8_t USBByteCountEP1; - - void main() { CfgFsys(); USBInit(); From bca5417dc53163f7fde073f1b00e7bfaa63a88b6 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Tue, 26 Jan 2021 19:24:18 -0400 Subject: [PATCH 15/54] fix pushPull for P1 --- examples/blink/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/blink/main.c b/examples/blink/main.c index 03476db..44c330b 100644 --- a/examples/blink/main.c +++ b/examples/blink/main.c @@ -13,7 +13,7 @@ inline void pushPull(uint8_t pinaddr) if (pinaddr >= 0xB0 && pinaddr < 0xB8) P3_MOD_OC &= ~(1 << (pinaddr - 0xB0)); else if (pinaddr >= 0x90 && pinaddr < 0x98) - P3_MOD_OC &= ~(1 << (pinaddr - 0x90)); + P1_MOD_OC &= ~(1 << (pinaddr - 0x90)); } void main() { @@ -22,7 +22,7 @@ void main() { pushPull(LED_ADDR); while (1) { - mDelaymS(100); + mDelaymS(250); LED = !LED; } } From a6ae7e691307601ac5ecb7a4e36bc6403ce3dbea Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Thu, 11 Feb 2021 19:51:46 -0400 Subject: [PATCH 16/54] working with P1.7/P1.6 --- examples/CMSIS_DAP/DAP.c | 2 +- examples/CMSIS_DAP/DAP.h | 34 ++++++++++-- examples/CMSIS_DAP/SW_DP.c | 96 ++++++++++++++++++++------------- examples/CMSIS_DAP/USBHID.c | 3 +- examples/CMSIS_DAP/USBHID.h | 1 - examples/CMSIS_DAP/USBhandler.c | 18 ++++++- examples/CMSIS_DAP/main.c | 20 ++++--- 7 files changed, 120 insertions(+), 54 deletions(-) diff --git a/examples/CMSIS_DAP/DAP.c b/examples/CMSIS_DAP/DAP.c index 8bff304..1164a9a 100644 --- a/examples/CMSIS_DAP/DAP.c +++ b/examples/CMSIS_DAP/DAP.c @@ -114,7 +114,7 @@ static uint8_t DAP_HostStatus(const uint8_t *req, uint8_t *res) LED = ((*(req + 1) & 1U)); break; case DAP_TARGET_RUNNING: - LED = ((*(req + 1) & 1U)); + //LED = ((*(req + 1) & 1U)); break; default: *res = DAP_ERROR; diff --git a/examples/CMSIS_DAP/DAP.h b/examples/CMSIS_DAP/DAP.h index c38eadc..946ab6f 100644 --- a/examples/CMSIS_DAP/DAP.h +++ b/examples/CMSIS_DAP/DAP.h @@ -202,10 +202,36 @@ #define DAP_PACKET_SIZE 64 //THIS_ENDP0_SIZE #define DAP_DEFAULT_PORT DAP_PORT_SWD +// if port defines are changed, also modify MOD_OC and DIR_PU settings #define RST P3_0 -#define SWK P3_1 -#define SWD P3_2 -#define LED P3_3 +#define SWK P1_7 +#define SWD P1_6 +#define LED P1_4 + +inline void PORT_SWD_SETUP(void) +{ + // P1_MOD_OC & P1_DIR_PU = 0xFF at reset + + SWK = 0; + // set SWK P1.7 to push-pull + P1_MOD_OC &= ~(1 << 7); + + // set SWD P1.6 to push-pull + P1_MOD_OC &= ~(1 << 6); + + SWD = 1; + RST = 1; +} + +inline void SWD_OUT_ENABLE() +{ + P1_DIR_PU |= (1 << 6); +} + +inline void SWD_OUT_DISABLE() +{ + P1_DIR_PU &= ~(1 << 6); +} extern __xdata uint8_t Ep0Buffer[]; extern __xdata uint8_t Ep1Buffer[]; @@ -215,7 +241,7 @@ extern __idata uint8_t data_phase; extern __idata uint8_t idle_cycles; extern uint8_t DAP_Thread(void); -extern void PORT_SWD_SETUP(void); +//extern void PORT_SWD_SETUP(void); extern uint8_t SWD_Transfer(uint8_t reqI, uint8_t __xdata *datas); extern void SWJ_Sequence(uint8_t count, const uint8_t *datas); extern void SWD_Sequence(uint8_t info, const uint8_t *swdo, uint8_t *swdi); diff --git a/examples/CMSIS_DAP/SW_DP.c b/examples/CMSIS_DAP/SW_DP.c index 805128a..e5c806b 100644 --- a/examples/CMSIS_DAP/SW_DP.c +++ b/examples/CMSIS_DAP/SW_DP.c @@ -27,38 +27,34 @@ #include "DAP.h" +volatile uint8_t swdelay; + +#if 0 +#define SW_CLOCK_CYCLE() \ + while(!TF2); SWK = 1; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; \ + while(!TF2); SWK = 0; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; +#endif #define SW_CLOCK_CYCLE() \ - SWK = 1; SWK = 0; + SWK = 1; swdelay = 1; while (--swdelay); SWK = 0; +#if 0 #define SW_WRITE_BIT(bits) \ - SWD = (bits)&1; SWK = 1; SWK = 0; + SWD = (bits)&1; \ + while(!TF2); SWK = 1; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1;\ + while(!TF2); SWK = 0; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; +#endif +#define SW_WRITE_BIT(bits) \ + SWD = (bits)&1; SWK = 1; swdelay = 1; while (--swdelay); SWK = 0; -// data from target was clocked out on last SWK rising edge +#if 0 + data from target was clocked out on last SWK rising edge #define SW_READ_BIT(bits) \ - bits = SWD; SWK = 1; SWK = 0; - -/** Setup SWD I/O pins: SWCLK, SWDIO, and nRESET. -Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode: - - SWCLK low, SWDIO, nRESET high. -*/ -void PORT_SWD_SETUP(void) -{ - // P3_MOD_OC & P3_DIR_PU = 0xFF at reset - - // set P3.1 to push-pull - P3_MOD_OC &= ~(1 << 1); - //P3_MOD_OC = P3_MOD_OC | (1 << 1); - //P3_DIR_PU = P3_DIR_PU | (1 << 1); - SWK = 0; - - //P3_MOD_OC = P3_MOD_OC | (1 << 2); - //P3_DIR_PU = P3_DIR_PU | (1 << 2); - SWD = 1; - - //P3_MOD_OC = P3_MOD_OC | (1 << 0); - //P3_DIR_PU = P3_DIR_PU | (1 << 0); - RST = 1; -} + bits = SWD; \ + while(!TF2); SWK = 1; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1;\ + while(!TF2); SWK = 0; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; +#endif +#define SW_READ_BIT(bits) \ + bits = SWD; SWK = 1; swdelay = 1; while (--swdelay); SWK = 0; // todo: look at difference between SWJ & SWD sequence // use SW_WRITE_BIT macro? @@ -80,6 +76,20 @@ void SWJ_Sequence(uint8_t count, const uint8_t *datas) val = *datas++; n = 8U; } +/* + if (val & 1U) + { + SWD = 1; + } + else + { + SWD = 0; + } + while(!TF2); + + SWK = 1; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; + while(!TF2); SWK = 0; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; +*/ SW_WRITE_BIT(val); val >>= 1; n--; @@ -164,10 +174,14 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) SW_WRITE_BIT(1U); /* Park Bit */ /* Turnaround */ + SWD_OUT_DISABLE(); + SW_CLOCK_CYCLE(); + /* for (n = turnaround; n; n--) { SW_CLOCK_CYCLE(); } + */ /* Acknowledge res */ SW_READ_BIT(bits); @@ -183,7 +197,7 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) /* Data transfer */ if (req & DAP_TRANSFER_RnW) { - /* Read data */ + /* Read datas */ val = 0U; parity = 0U; for (m = 0; m < 4; m++) @@ -191,11 +205,15 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) for (n = 8U; n; n--) { SW_READ_BIT(bits); /* Read RDATA[0:31] */ - //parity += bits; + parity += bits; val >>= 1; + //val |= bits << 7; if (bits) val |= 0x80; } - *datas++ = val; + if (datas) + { + datas[m] = val; + } } SW_READ_BIT(bits); /* Read Parity */ if ((parity ^ bits) & 1U) @@ -204,11 +222,14 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) } /* Turnaround */ + /* for (n = turnaround; n; n--) { SW_CLOCK_CYCLE(); } - SWD = 1; + */ + SW_CLOCK_CYCLE(); + SWD_OUT_ENABLE(); } else { @@ -217,7 +238,7 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) { SW_CLOCK_CYCLE(); } - SWD = 1; + SWD_OUT_ENABLE(); /* Write datas */ parity = 0U; for (m = 0; m < 4; m++) @@ -233,17 +254,17 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) SW_WRITE_BIT(parity); /* Write Parity Bit */ } /* Idle cycles */ + SWD = 0; n = idle_cycles; if (n) { - SWD = 0; for (; n; n--) { SW_CLOCK_CYCLE(); } } SWD = 1; - return ack; + return ((uint8_t)ack); } if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) @@ -261,7 +282,7 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) { SW_CLOCK_CYCLE(); } - SWD = 1; + SWD_OUT_ENABLE(); if (data_phase && ((req & DAP_TRANSFER_RnW) == 0U)) { SWD = 0; @@ -271,7 +292,7 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) } } SWD = 1; - return ack; + return ((uint8_t)ack); } /* Protocol error */ @@ -279,6 +300,7 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) { SW_CLOCK_CYCLE(); /* Back off datas phase */ } + SWD_OUT_ENABLE(); SWD = 1; - return ack; + return ((uint8_t)ack); } diff --git a/examples/CMSIS_DAP/USBHID.c b/examples/CMSIS_DAP/USBHID.c index b087ada..0590af3 100644 --- a/examples/CMSIS_DAP/USBHID.c +++ b/examples/CMSIS_DAP/USBHID.c @@ -8,8 +8,7 @@ extern __xdata uint8_t Ep0Buffer[]; extern __xdata uint8_t Ep1Buffer[]; -//Bytes of received data on USB endpoint -volatile uint8_t USBByteCountEP1 = 0; +volatile uint8_t USBByteCountEP1 = 0; //Bytes of received data on USB endpoint void USBInit(){ USBDeviceCfg(); //Device mode configuration diff --git a/examples/CMSIS_DAP/USBHID.h b/examples/CMSIS_DAP/USBHID.h index f622a6f..502e535 100644 --- a/examples/CMSIS_DAP/USBHID.h +++ b/examples/CMSIS_DAP/USBHID.h @@ -4,7 +4,6 @@ #include extern volatile uint8_t USBByteCountEP1; - void USBInit(void); #endif diff --git a/examples/CMSIS_DAP/USBhandler.c b/examples/CMSIS_DAP/USBhandler.c index bd89735..3851e7e 100644 --- a/examples/CMSIS_DAP/USBhandler.c +++ b/examples/CMSIS_DAP/USBhandler.c @@ -70,10 +70,12 @@ void USB_EP0_SETUP(){ switch(UsbSetupBuf->wValueH) { case 1: //Device Descriptor - pDescr = (uint8_t *)&DevDesc; + // pDescr = DevDesc; //Put Device Descriptor into outgoing buffer + // len = DevDescLen; + pDescr = (uint8_t*)&DevDesc; len = sizeof(DevDesc); break; - case 2: //Configuration Descriptor + case 2: //Configure Descriptor pDescr = CfgDesc; len = CfgDescLen; break; @@ -93,6 +95,18 @@ void USB_EP0_SETUP(){ pDescr = Prod_Des; len = Prod_DesLen; } + /* + else if(UsbSetupBuf->wValueL == 3) + { + pDescr = SerDes; + len = SerDesLen; + } + else + { + pDescr = SerDes; + len = SerDesLen; + } + */ break; case 0x22: if(UsbSetupBuf->wValueL == 0){ diff --git a/examples/CMSIS_DAP/main.c b/examples/CMSIS_DAP/main.c index 5623ed4..4bbce9a 100644 --- a/examples/CMSIS_DAP/main.c +++ b/examples/CMSIS_DAP/main.c @@ -3,13 +3,7 @@ Based on DAPLink and Deqing Sun's CH55xduino port https://github.com/ARMmbed/DAPLink - Code cleanup and optimization by Ralph Doncaster - - DAP.h defaults: - RST = P30 - SWCLK = P31 - SWDIO = P32 - LED = P33 + see DAP.h for RST, SWCLK, & SWDIO pin defines */ #include @@ -22,7 +16,19 @@ void DeviceUSBInterrupt(void) __interrupt (INT_NO_USB) USBInterrupt(); } +// perform USB bus reset/disconnect +// set UDP to GPIO mode and hold low for device disconnect +void resetUSB() +{ + PIN_FUNC &= ~(bUSB_IO_EN); + UDP = 0; + mDelaymS(50); + UDP = 1; + PIN_FUNC |= bUSB_IO_EN; +} + void main() { + resetUSB(); CfgFsys(); USBInit(); while (1) { From 8416341971dc2516967df8f68818494c959f2a27 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Thu, 11 Feb 2021 20:02:07 -0400 Subject: [PATCH 17/54] document wiring and speeds --- examples/CMSIS_DAP/README.txt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 examples/CMSIS_DAP/README.txt diff --git a/examples/CMSIS_DAP/README.txt b/examples/CMSIS_DAP/README.txt new file mode 100644 index 0000000..c3dd732 --- /dev/null +++ b/examples/CMSIS_DAP/README.txt @@ -0,0 +1,6 @@ +CMSIS-DAP debug probe implementation + +Recommended hardware setup is with VCC=3V3 and 68-100Ohm series resistors on SWDIO & SWCLK. + +Performance is partially optimized, with SWCLK running at less than 1Mhz. Overall throughput flashing a STM32F103 with pyocd is about 6kB/s. With optimization of the bit-banged SWD code and the USB packet handling, 20kB/s programming speeds should be possible + From c479928f55974ef43eee4c90cea0892059c45d96 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Fri, 12 Feb 2021 11:06:29 -0400 Subject: [PATCH 18/54] rm unused code --- examples/CMSIS_DAP/USBHID.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/CMSIS_DAP/USBHID.c b/examples/CMSIS_DAP/USBHID.c index 0590af3..210fe95 100644 --- a/examples/CMSIS_DAP/USBHID.c +++ b/examples/CMSIS_DAP/USBHID.c @@ -5,9 +5,6 @@ #include "USBconstant.h" #include "USBhandler.h" -extern __xdata uint8_t Ep0Buffer[]; -extern __xdata uint8_t Ep1Buffer[]; - volatile uint8_t USBByteCountEP1 = 0; //Bytes of received data on USB endpoint void USBInit(){ From 0a668479e481ba8f8f3a765ba4bdfd5632756bd7 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Fri, 12 Feb 2021 11:07:22 -0400 Subject: [PATCH 19/54] --no-xinit-opt saves 70B --- examples/CMSIS_DAP/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/examples/CMSIS_DAP/Makefile b/examples/CMSIS_DAP/Makefile index 1d90436..fbe5f9e 100644 --- a/examples/CMSIS_DAP/Makefile +++ b/examples/CMSIS_DAP/Makefile @@ -7,6 +7,8 @@ FREQ_SYS = 16000000 XRAM_SIZE = 0x0300 XRAM_LOC = 0x0100 +EXTRA_FLAGS = --no-xinit-opt + C_FILES = \ $(wildcard *.c) \ ../../include/debug.c From fc7352f6bae5c08eed1fe23170aa6d4b9bf78928 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Sat, 13 Feb 2021 16:40:14 -0400 Subject: [PATCH 20/54] provide dummy serial descriptor for CMSIS-DAP unique ID --- examples/CMSIS_DAP/USBconstant.c | 9 ++++++++- examples/CMSIS_DAP/USBconstant.h | 3 ++- examples/CMSIS_DAP/USBhandler.c | 6 +++--- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/examples/CMSIS_DAP/USBconstant.c b/examples/CMSIS_DAP/USBconstant.c index 1522a9f..762d440 100644 --- a/examples/CMSIS_DAP/USBconstant.c +++ b/examples/CMSIS_DAP/USBconstant.c @@ -19,7 +19,7 @@ __code USB_DEV_DESCR DevDesc = { .bcdDeviceH = 0x01, .bcdDeviceL = 0x00, .iManufacturer = 1, // string descriptors .iProduct = 2, - .iSerialNumber = 0, // no serial number string + .iSerialNumber = 3, .bNumConfigurations = 1 }; @@ -111,3 +111,10 @@ __code uint16_t Manuf_Des[]={ 'W','C','H' }; __code uint8_t Manuf_DesLen = sizeof(Manuf_Des); + +// Serial string descriptor - CMSIS-DAP unique ID +__code uint16_t Ser_Des[]={ + 0x0308, // type and length + '1','2','3' +}; +__code uint8_t Ser_DesLen = sizeof(Manuf_Des); diff --git a/examples/CMSIS_DAP/USBconstant.h b/examples/CMSIS_DAP/USBconstant.h index d7f4c16..9ac6cbb 100644 --- a/examples/CMSIS_DAP/USBconstant.h +++ b/examples/CMSIS_DAP/USBconstant.h @@ -6,7 +6,6 @@ #define EP0_ADDR 0 #define EP1_ADDR 10 -#define EP2_ADDR 20 extern __code USB_DEV_DESCR DevDesc; extern __code uint8_t CfgDesc[]; @@ -14,11 +13,13 @@ extern __code uint8_t LangDes[]; extern __code uint8_t ReportDesc[]; extern __code uint16_t Prod_Des[]; extern __code uint16_t Manuf_Des[]; +extern __code uint16_t Ser_Des[]; extern __code uint8_t CfgDescLen; extern __code uint8_t LangDesLen; extern __code uint8_t ReportDescLen; extern __code uint8_t Prod_DesLen; extern __code uint8_t Manuf_DesLen; +extern __code uint8_t Ser_DesLen; #endif diff --git a/examples/CMSIS_DAP/USBhandler.c b/examples/CMSIS_DAP/USBhandler.c index 3851e7e..79f365c 100644 --- a/examples/CMSIS_DAP/USBhandler.c +++ b/examples/CMSIS_DAP/USBhandler.c @@ -101,12 +101,12 @@ void USB_EP0_SETUP(){ pDescr = SerDes; len = SerDesLen; } + */ else { - pDescr = SerDes; - len = SerDesLen; + pDescr = Ser_Des; + len = Ser_DesLen; } - */ break; case 0x22: if(UsbSetupBuf->wValueL == 0){ From 28f94620d25bb3ac91c23e320ddbc9306f136720 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Sat, 13 Feb 2021 18:56:38 -0400 Subject: [PATCH 21/54] use reqponse size from DAP_Thread --- examples/CMSIS_DAP/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/CMSIS_DAP/main.c b/examples/CMSIS_DAP/main.c index 4bbce9a..5afdbd3 100644 --- a/examples/CMSIS_DAP/main.c +++ b/examples/CMSIS_DAP/main.c @@ -32,13 +32,14 @@ void main() { CfgFsys(); USBInit(); while (1) { + uint8_t response_len; if (USBByteCountEP1) { - DAP_Thread(); + response_len = DAP_Thread(); USBByteCountEP1 = 0 ; UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_ACK; //enable receive - UEP1_T_LEN = 64; + UEP1_T_LEN = response_len; UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_ACK; //enable send } } From 8544db369be78f800bac9cc3ab89fa584139561d Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Sun, 14 Feb 2021 00:11:53 -0400 Subject: [PATCH 22/54] cleanup comments --- examples/CMSIS_DAP/DAP.c | 60 +++++----------------------------------- 1 file changed, 7 insertions(+), 53 deletions(-) diff --git a/examples/CMSIS_DAP/DAP.c b/examples/CMSIS_DAP/DAP.c index 1164a9a..1094c45 100644 --- a/examples/CMSIS_DAP/DAP.c +++ b/examples/CMSIS_DAP/DAP.c @@ -321,8 +321,7 @@ static uint8_t DAP_SWD_Configure(const uint8_t *req, uint8_t *res) // Process SWD Sequence command and prepare response // request: pointer to request data // response: pointer to response data -// return: number of bytes in response (lower 16 bits) -// number of bytes in request (upper 16 bits) +// return: number of bytes in response static uint8_t DAP_SWD_Sequence(const uint8_t *req, uint8_t *res) { uint8_t sequence_info; @@ -378,8 +377,7 @@ static uint8_t DAP_SWD_Sequence(const uint8_t *req, uint8_t *res) // Process Transfer Configure command and prepare response // request: pointer to request data // response: pointer to response data -// return: number of bytes in response (lower 16 bits) -// number of bytes in request (upper 16 bits) +// return: number of bytes in response __idata uint8_t idle_cycles; __idata uint16_t retry_count; __idata uint16_t match_retry; @@ -399,8 +397,7 @@ static uint8_t DAP_TransferConfigure(const uint8_t *req, uint8_t *res) // Process SWD Transfer command and prepare response // request: pointer to request data // response: pointer to response data -// return: number of bytes in response (lower 16 bits) -// number of bytes in request (upper 16 bits) +// return: number of bytes in response __xdata uint8_t data[4]; __idata uint8_t match_mask[4]; @@ -437,7 +434,8 @@ static uint8_t DAP_SWD_Transfer(const uint8_t *req, uint8_t *res) for (; request_count != 0U; request_count--) { request_value = *req++; - if ((request_value & DAP_TRANSFER_RnW) != 0U) + // RnW == 1 for read, 0 for write + if (request_value & DAP_TRANSFER_RnW) { // Read registers if (post_read) @@ -571,7 +569,7 @@ static uint8_t DAP_SWD_Transfer(const uint8_t *req, uint8_t *res) } check_write = 0U; } - else + else // RnW == 0 { // Write register if (post_read) @@ -693,54 +691,10 @@ static uint8_t DAP_SWD_Transfer(const uint8_t *req, uint8_t *res) return ((uint8_t)(res - response_head)); } -// Process Dummy Transfer command and prepare response -// request: pointer to request data -// response: pointer to response data -// return: number of bytes in response (lower 16 bits) -// number of bytes in request (upper 16 bits) -//static uint8_t DAP_Dummy_Transfer(const uint8_t *req, uint8_t *res) -//{ -// uint8_t *request_head; -// uint8_t request_count; -// uint8_t request_value; - -// request_head = req; - -// req++; // Ignore DAP index - -// request_count = *req++; - -// for (; request_count != 0U; request_count--) -// { -// // Process dummy requests -// request_value = *req++; -// if ((request_value & DAP_TRANSFER_RnW) != 0U) -// { -// // Read registers -// if ((request_value & DAP_TRANSFER_MATCH_VALUE) != 0U) -// { -// // Read with value match -// req += 4; -// } -// } -// else -// { -// // Write registers -// req += 4; -// } -// } - -// *(res + 0) = 0U; // res count -// *(res + 1) = 0U; // res value - -// return 2; -//} - // Process Transfer command and prepare response // request: pointer to request data // response: pointer to response data -// return: number of bytes in response (lower 16 bits) -// number of bytes in request (upper 16 bits) +// return: number of bytes in response static uint8_t DAP_Transfer(const uint8_t *req, uint8_t *res) { uint8_t num = 0; From 0b57150df264e2ce8f0d9d2bd424820c507ce4cd Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Sun, 14 Feb 2021 00:14:16 -0400 Subject: [PATCH 23/54] trailing space? --- examples/CMSIS_DAP/USBhandler.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/CMSIS_DAP/USBhandler.c b/examples/CMSIS_DAP/USBhandler.c index 3851e7e..acedd33 100644 --- a/examples/CMSIS_DAP/USBhandler.c +++ b/examples/CMSIS_DAP/USBhandler.c @@ -8,7 +8,7 @@ void USB_EP1_IN(); void USB_EP1_OUT(); -__xdata __at (EP0_ADDR) uint8_t Ep0Buffer[8]; +__xdata __at (EP0_ADDR) uint8_t Ep0Buffer[8]; __xdata __at (EP1_ADDR) uint8_t Ep1Buffer[128]; //on page 47 of data sheet, the receive buffer need to be min(possible packet size+2,64) //IN and OUT buffer, must be even address uint16_t SetupLen; From e6c259bffd9477b85c2281f7898549375a4312fa Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Sun, 14 Feb 2021 10:50:17 -0400 Subject: [PATCH 24/54] revert to 64-byte responses due to Windoze bug --- examples/CMSIS_DAP/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/examples/CMSIS_DAP/main.c b/examples/CMSIS_DAP/main.c index 5afdbd3..a3ba0bd 100644 --- a/examples/CMSIS_DAP/main.c +++ b/examples/CMSIS_DAP/main.c @@ -39,7 +39,8 @@ void main() { UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_ACK; //enable receive - UEP1_T_LEN = response_len; + //UEP1_T_LEN = response_len; + UEP1_T_LEN = 64; // hangs on Windoze < 64 UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_ACK; //enable send } } From 8adb7cd80cae58253530bab92c873fe500f21d00 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Sun, 14 Feb 2021 10:51:34 -0400 Subject: [PATCH 25/54] rm unused code --- examples/CMSIS_DAP/USBhandler.c | 24 +++++------------------- examples/CMSIS_DAP/USBhandler.h | 14 -------------- 2 files changed, 5 insertions(+), 33 deletions(-) diff --git a/examples/CMSIS_DAP/USBhandler.c b/examples/CMSIS_DAP/USBhandler.c index 4b4d197..98816ac 100644 --- a/examples/CMSIS_DAP/USBhandler.c +++ b/examples/CMSIS_DAP/USBhandler.c @@ -20,7 +20,7 @@ volatile uint8_t usbMsgFlags=0; // uint8_t usbMsgFlags copied from VUSB inline void NOP_Process(void) {} -void USB_EP0_SETUP(){ +void USB_EP0_Setup(){ uint8_t len = USB_RX_LEN; if(len == (sizeof(USB_SETUP_REQ))) { @@ -362,18 +362,6 @@ void USBInterrupt(void) { //inline not really working in multiple files in SDC } } break; - case UIS_TOKEN_SOF: - {//SDCC will take IRAM if array of function pointer is used. - switch (callIndex) { - case 0: EP0_SOF_Callback(); break; - case 1: EP1_SOF_Callback(); break; - case 2: EP2_SOF_Callback(); break; - case 3: EP3_SOF_Callback(); break; - case 4: EP4_SOF_Callback(); break; - default: break; - } - } - break; case UIS_TOKEN_IN: {//SDCC will take IRAM if array of function pointer is used. switch (callIndex) { @@ -387,17 +375,15 @@ void USBInterrupt(void) { //inline not really working in multiple files in SDC } break; case UIS_TOKEN_SETUP: - {//SDCC will take IRAM if array of function pointer is used. + { switch (callIndex) { - case 0: EP0_SETUP_Callback(); break; - case 1: EP1_SETUP_Callback(); break; - case 2: EP2_SETUP_Callback(); break; - case 3: EP3_SETUP_Callback(); break; - case 4: EP4_SETUP_Callback(); break; + case 0: USB_EP0_Setup(); break; default: break; } } break; + default: + break; } UIF_TRANSFER = 0; // Clear interrupt flag diff --git a/examples/CMSIS_DAP/USBhandler.h b/examples/CMSIS_DAP/USBhandler.h index 8c5368f..eebe6d0 100644 --- a/examples/CMSIS_DAP/USBhandler.h +++ b/examples/CMSIS_DAP/USBhandler.h @@ -18,13 +18,6 @@ extern const __code uint8_t *pDescr; #define EP3_OUT_Callback NOP_Process #define EP4_OUT_Callback NOP_Process -// SOF -#define EP0_SOF_Callback NOP_Process -#define EP1_SOF_Callback NOP_Process -#define EP2_SOF_Callback NOP_Process -#define EP3_SOF_Callback NOP_Process -#define EP4_SOF_Callback NOP_Process - // IN #define EP0_IN_Callback USB_EP0_IN #define EP1_IN_Callback USB_EP1_IN @@ -32,13 +25,6 @@ extern const __code uint8_t *pDescr; #define EP3_IN_Callback NOP_Process #define EP4_IN_Callback NOP_Process -// SETUP -#define EP0_SETUP_Callback USB_EP0_SETUP -#define EP1_SETUP_Callback NOP_Process -#define EP2_SETUP_Callback NOP_Process -#define EP3_SETUP_Callback NOP_Process -#define EP4_SETUP_Callback NOP_Process - void USBInterrupt(void); void USBDeviceCfg(); void USBDeviceIntCfg(); From 9a75cb24516d48f4626b9f2326dd5125851b0a6a Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Mon, 15 Feb 2021 09:58:29 -0400 Subject: [PATCH 26/54] cleanup + speedup --- examples/CMSIS_DAP/DAP.c | 6 +-- examples/CMSIS_DAP/DAP.h | 5 +- examples/CMSIS_DAP/SW_DP.c | 106 +++++++++++-------------------------- 3 files changed, 37 insertions(+), 80 deletions(-) diff --git a/examples/CMSIS_DAP/DAP.c b/examples/CMSIS_DAP/DAP.c index 1094c45..b29b831 100644 --- a/examples/CMSIS_DAP/DAP.c +++ b/examples/CMSIS_DAP/DAP.c @@ -38,13 +38,13 @@ static uint8_t DAP_Info(uint8_t id, uint8_t *info) switch (id) { case DAP_ID_VENDOR: - length = 0; + break; case DAP_ID_PRODUCT: - length = 0; + break; case DAP_ID_SER_NUM: - length = 0; + break; case DAP_ID_FW_VER: length = (uint8_t)sizeof(DAP_FW_VER); diff --git a/examples/CMSIS_DAP/DAP.h b/examples/CMSIS_DAP/DAP.h index 946ab6f..090044c 100644 --- a/examples/CMSIS_DAP/DAP.h +++ b/examples/CMSIS_DAP/DAP.h @@ -241,9 +241,8 @@ extern __idata uint8_t data_phase; extern __idata uint8_t idle_cycles; extern uint8_t DAP_Thread(void); -//extern void PORT_SWD_SETUP(void); -extern uint8_t SWD_Transfer(uint8_t reqI, uint8_t __xdata *datas); -extern void SWJ_Sequence(uint8_t count, const uint8_t *datas); +extern uint8_t SWD_Transfer(uint8_t reqI, __xdata uint8_t *data); +extern void SWJ_Sequence(uint8_t count, const uint8_t *data); extern void SWD_Sequence(uint8_t info, const uint8_t *swdo, uint8_t *swdi); #endif /* __DAP_H__ */ diff --git a/examples/CMSIS_DAP/SW_DP.c b/examples/CMSIS_DAP/SW_DP.c index e5c806b..c503981 100644 --- a/examples/CMSIS_DAP/SW_DP.c +++ b/examples/CMSIS_DAP/SW_DP.c @@ -24,45 +24,31 @@ * Title: SW_DP.c CMSIS-DAP SW DP I/O * *---------------------------------------------------------------------------*/ +// SDCC/8051 optimizations by Ralph Doncaster 2021 #include "DAP.h" volatile uint8_t swdelay; -#if 0 #define SW_CLOCK_CYCLE() \ - while(!TF2); SWK = 1; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; \ - while(!TF2); SWK = 0; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; -#endif -#define SW_CLOCK_CYCLE() \ - SWK = 1; swdelay = 1; while (--swdelay); SWK = 0; + SWK = 1; SWK = 0; +// SWK = 1; swdelay = 1; while (--swdelay); SWK = 0; -#if 0 -#define SW_WRITE_BIT(bits) \ - SWD = (bits)&1; \ - while(!TF2); SWK = 1; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1;\ - while(!TF2); SWK = 0; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; -#endif #define SW_WRITE_BIT(bits) \ - SWD = (bits)&1; SWK = 1; swdelay = 1; while (--swdelay); SWK = 0; + SWD = (bits)&1; SWK = 1; SWK = 0; +// SWD = (bits)&1; SWK = 1; swdelay = 1; while (--swdelay); SWK = 0; -#if 0 - data from target was clocked out on last SWK rising edge #define SW_READ_BIT(bits) \ - bits = SWD; \ - while(!TF2); SWK = 1; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1;\ - while(!TF2); SWK = 0; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; -#endif -#define SW_READ_BIT(bits) \ - bits = SWD; SWK = 1; swdelay = 1; while (--swdelay); SWK = 0; + bits = SWD; SWK = 1; SWK = 0; +// bits = SWD; SWK = 1; swdelay = 1; while (--swdelay); SWK = 0; // todo: look at difference between SWJ & SWD sequence // use SW_WRITE_BIT macro? // Generate SWJ Sequence // count: sequence bits count -// datas: pointer to sequence bits datas +// data: pointer to sequence bits data // return: none -void SWJ_Sequence(uint8_t count, const uint8_t *datas) +void SWJ_Sequence(uint8_t count, const uint8_t *data) { uint8_t val; uint8_t n; @@ -73,23 +59,10 @@ void SWJ_Sequence(uint8_t count, const uint8_t *datas) { if (n == 0U) { - val = *datas++; + val = *data++; n = 8U; } -/* - if (val & 1U) - { - SWD = 1; - } - else - { - SWD = 0; - } - while(!TF2); - - SWK = 1; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; - while(!TF2); SWK = 0; TR2=0;TL2=RCAP2L;TH2=RCAP2H;TF2=0;TR2=1; -*/ + SW_WRITE_BIT(val); val >>= 1; n--; @@ -98,8 +71,8 @@ void SWJ_Sequence(uint8_t count, const uint8_t *datas) // Generate SWD Sequence // info: sequence information -// swdo: pointer to SWDIO generated datas -// swdi: pointer to SWDIO captured datas +// swdo: pointer to SWDIO generated data +// swdi: pointer to SWDIO captured data // return: none void SWD_Sequence(uint8_t info, const uint8_t *swdo, uint8_t *swdi) { @@ -144,9 +117,9 @@ void SWD_Sequence(uint8_t info, const uint8_t *swdo, uint8_t *swdi) // SWD Transfer I/O // request: A[3:2] RnW APnDP -// datas: DATA[31:0] +// data: DATA[31:0] // return: ACK[2:0] -uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) +uint8_t SWD_Transfer(uint8_t req, __xdata uint8_t *data) { uint8_t ack; uint8_t bits = req; @@ -173,15 +146,9 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) SW_WRITE_BIT(0U); /* Stop Bit */ SW_WRITE_BIT(1U); /* Park Bit */ - /* Turnaround */ + /* Turnaround is always 1 cycle */ SWD_OUT_DISABLE(); SW_CLOCK_CYCLE(); - /* - for (n = turnaround; n; n--) - { - SW_CLOCK_CYCLE(); - } - */ /* Acknowledge res */ SW_READ_BIT(bits); @@ -197,7 +164,7 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) /* Data transfer */ if (req & DAP_TRANSFER_RnW) { - /* Read datas */ + /* Read data */ val = 0U; parity = 0U; for (m = 0; m < 4; m++) @@ -210,9 +177,9 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) //val |= bits << 7; if (bits) val |= 0x80; } - if (datas) + if (data) { - datas[m] = val; + data[m] = val; } } SW_READ_BIT(bits); /* Read Parity */ @@ -222,28 +189,20 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) } /* Turnaround */ - /* - for (n = turnaround; n; n--) - { - SW_CLOCK_CYCLE(); - } - */ SW_CLOCK_CYCLE(); SWD_OUT_ENABLE(); } - else + else // write data { /* Turnaround */ - for (n = turnaround; n; n--) - { - SW_CLOCK_CYCLE(); - } + SW_CLOCK_CYCLE(); SWD_OUT_ENABLE(); - /* Write datas */ + + /* Write data */ parity = 0U; for (m = 0; m < 4; m++) { - val = datas[m]; + val = data[m]; for (n = 8U; n; n--) { SW_WRITE_BIT(val); /* Write WDATA[0:31] */ @@ -278,11 +237,9 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) } } /* Turnaround */ - for (n = turnaround; n; n--) - { - SW_CLOCK_CYCLE(); - } + SW_CLOCK_CYCLE(); SWD_OUT_ENABLE(); + if (data_phase && ((req & DAP_TRANSFER_RnW) == 0U)) { SWD = 0; @@ -295,11 +252,12 @@ uint8_t SWD_Transfer(uint8_t req, uint8_t __xdata *datas) return ((uint8_t)ack); } - /* Protocol error */ - for (n = turnaround + 32U + 1U; n; n--) - { - SW_CLOCK_CYCLE(); /* Back off datas phase */ - } + /* Protocol error - clock out 32bits + parity + turnaround */ + n = 32U + 1U + 1U; + do { + SW_CLOCK_CYCLE(); // back off data phase + } while (--n); + SWD_OUT_ENABLE(); SWD = 1; return ((uint8_t)ack); From cf683a96f7d287b9e609db637fac1c3d871ae0ce Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Mon, 15 Feb 2021 14:35:29 -0400 Subject: [PATCH 27/54] use hardware parity for write WDATA --- examples/CMSIS_DAP/SW_DP.c | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/examples/CMSIS_DAP/SW_DP.c b/examples/CMSIS_DAP/SW_DP.c index c503981..f5d1ea6 100644 --- a/examples/CMSIS_DAP/SW_DP.c +++ b/examples/CMSIS_DAP/SW_DP.c @@ -32,15 +32,12 @@ volatile uint8_t swdelay; #define SW_CLOCK_CYCLE() \ SWK = 1; SWK = 0; -// SWK = 1; swdelay = 1; while (--swdelay); SWK = 0; #define SW_WRITE_BIT(bits) \ SWD = (bits)&1; SWK = 1; SWK = 0; -// SWD = (bits)&1; SWK = 1; swdelay = 1; while (--swdelay); SWK = 0; #define SW_READ_BIT(bits) \ bits = SWD; SWK = 1; SWK = 0; -// bits = SWD; SWK = 1; swdelay = 1; while (--swdelay); SWK = 0; // todo: look at difference between SWJ & SWD sequence // use SW_WRITE_BIT macro? @@ -198,17 +195,31 @@ uint8_t SWD_Transfer(uint8_t req, __xdata uint8_t *data) SW_CLOCK_CYCLE(); SWD_OUT_ENABLE(); - /* Write data */ + // Write WDATA[0:31] parity = 0U; for (m = 0; m < 4; m++) { val = data[m]; + ACC = val; + //parity += P; + if (P) parity++; for (n = 8U; n; n--) { - SW_WRITE_BIT(val); /* Write WDATA[0:31] */ - parity += val; + SW_WRITE_BIT(val); val >>= 1; } + /* + __asm + mov r2, #8 + 1$: + rrc A + mov P1.6, C + setb P1.7 + clr P1.7 + djnz r2, 1$ + __endasm; + */ + } SW_WRITE_BIT(parity); /* Write Parity Bit */ } From 4568717dfaadb612821a32bc1e242319e5516703 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Fri, 19 Feb 2021 22:52:28 -0400 Subject: [PATCH 28/54] using separate endpoints for INT IN & OUT --- examples/CMSIS_DAP/DAP.c | 2 +- examples/CMSIS_DAP/DAP.h | 1 + examples/CMSIS_DAP/USBHID.c | 10 ++++---- examples/CMSIS_DAP/USBconstant.c | 39 ++++++++++++++++---------------- examples/CMSIS_DAP/USBconstant.h | 1 + examples/CMSIS_DAP/USBhandler.c | 32 ++++++++++++++------------ examples/CMSIS_DAP/USBhandler.h | 8 ------- examples/CMSIS_DAP/main.c | 8 +++---- 8 files changed, 48 insertions(+), 53 deletions(-) diff --git a/examples/CMSIS_DAP/DAP.c b/examples/CMSIS_DAP/DAP.c index b29b831..b7cbd8e 100644 --- a/examples/CMSIS_DAP/DAP.c +++ b/examples/CMSIS_DAP/DAP.c @@ -898,7 +898,7 @@ uint8_t DAP_Thread(void) if (1) { uint8_t __xdata *req = &Ep1Buffer[0]; - uint8_t __xdata *res = &Ep1Buffer[64]; + uint8_t __xdata *res = &Ep2Buffer[0]; *res++ = *req; switch (*req++) diff --git a/examples/CMSIS_DAP/DAP.h b/examples/CMSIS_DAP/DAP.h index 090044c..3d7f827 100644 --- a/examples/CMSIS_DAP/DAP.h +++ b/examples/CMSIS_DAP/DAP.h @@ -235,6 +235,7 @@ inline void SWD_OUT_DISABLE() extern __xdata uint8_t Ep0Buffer[]; extern __xdata uint8_t Ep1Buffer[]; +extern __xdata uint8_t Ep2Buffer[]; extern __idata uint8_t turnaround; extern __idata uint8_t data_phase; diff --git a/examples/CMSIS_DAP/USBHID.c b/examples/CMSIS_DAP/USBHID.c index 210fe95..16bd3c2 100644 --- a/examples/CMSIS_DAP/USBHID.c +++ b/examples/CMSIS_DAP/USBHID.c @@ -16,17 +16,17 @@ void USBInit(){ UEP2_T_LEN = 0; } -void USB_EP1_IN(){ - UEP1_T_LEN = 0; // No data to send anymore - UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_NAK; //Respond NAK by default - +void USB_EP2_IN(){ + UEP2_T_LEN = 0; // No data to send anymore + UEP2_CTRL = UEP2_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_NAK; //Respond NAK by default } void USB_EP1_OUT(){ if ( U_TOG_OK ){ // Discard unsynchronized packets USBByteCountEP1 = USB_RX_LEN; if (USBByteCountEP1){ - UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_NAK; //Respond NAK after a packet. Let main code change response after handling. + //Respond NAK after a packet. Let main code change response after handling. + UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_NAK; } } } diff --git a/examples/CMSIS_DAP/USBconstant.c b/examples/CMSIS_DAP/USBconstant.c index 762d440..d79fad9 100644 --- a/examples/CMSIS_DAP/USBconstant.c +++ b/examples/CMSIS_DAP/USBconstant.c @@ -44,31 +44,30 @@ __code uint8_t CfgDesc[] ={ 0x00, /* iInterface */ /* HID Descriptor */ - 0x09, /* Size of this descriptor in UINT8s. */ - 0x21, /* HID descriptor type. */ + 0x09, /* Size of this descriptor in UINT8s. */ + USB_DESCR_TYP_HID, // bDescriptorType 0x10, 0x01, /* HID Class Spec. release number. */ 0x00, /* H/W target country. */ 0x01, /* Number of HID class descriptors to follow. */ - 0x22, /* Descriptor type. */ + USB_DESCR_TYP_REPORT, // bDescriptorType sizeof(ReportDesc) & 0xff,sizeof(ReportDesc) >> 8, /* Total length of report descriptor. */ - /* EP Descriptor: interrupt in. */ - 0x07, /* bLength */ - 0x05, /* bDescriptorType */ - 0x01, /* bEndpointAddress */ - 0x03, /* bmAttributes */ - 0x40, 0x00, /* wMaxPacketSize */ - 1, /* bInterval */ - - /* EP Descriptor: interrupt out. */ - 0x07, /* bLength */ - 0x05, /* bDescriptorType */ - 0x81, /* bEndpointAddress */ - 0x03, /* bmAttributes */ - 0x40, 0x00, /* wMaxPacketSize */ - 1 /* bInterval */ - - + // EP Descriptor + sizeof(USB_ENDP_DESCR), // bLength + USB_DESCR_TYP_ENDP, // bDescriptorType + 0x82, // bEndpointAddress EP2 IN + USB_ENDP_TYPE_INTER, // bmAttributes + 0x40, 0x00, // wMaxPacketSize + 1, // bInterval + + // EP Descriptor + sizeof(USB_ENDP_DESCR), // bLength + USB_DESCR_TYP_ENDP, // bDescriptorType + 0x01, // bEndpointAddress EP1 OUT + USB_ENDP_TYPE_INTER, // bmAttributes + 0x40, 0x00, // wMaxPacketSize + 1, // bInterval + }; diff --git a/examples/CMSIS_DAP/USBconstant.h b/examples/CMSIS_DAP/USBconstant.h index 9ac6cbb..5b87a38 100644 --- a/examples/CMSIS_DAP/USBconstant.h +++ b/examples/CMSIS_DAP/USBconstant.h @@ -6,6 +6,7 @@ #define EP0_ADDR 0 #define EP1_ADDR 10 +#define EP2_ADDR 138 extern __code USB_DEV_DESCR DevDesc; extern __code uint8_t CfgDesc[]; diff --git a/examples/CMSIS_DAP/USBhandler.c b/examples/CMSIS_DAP/USBhandler.c index 98816ac..bf8d80d 100644 --- a/examples/CMSIS_DAP/USBhandler.c +++ b/examples/CMSIS_DAP/USBhandler.c @@ -5,11 +5,13 @@ #include "USBconstant.h" //HID functions: -void USB_EP1_IN(); +void USB_EP2_IN(); void USB_EP1_OUT(); +//on page 47 of data sheet, the receive buffer need to be min(possible packet size+2,64) __xdata __at (EP0_ADDR) uint8_t Ep0Buffer[8]; -__xdata __at (EP1_ADDR) uint8_t Ep1Buffer[128]; //on page 47 of data sheet, the receive buffer need to be min(possible packet size+2,64) //IN and OUT buffer, must be even address +__xdata __at (EP1_ADDR) uint8_t Ep1Buffer[128]; // EP1 OUT*2 +__xdata __at (EP2_ADDR) uint8_t Ep2Buffer[64]; uint16_t SetupLen; uint8_t SetupReq,UsbConfig; @@ -30,10 +32,6 @@ void USB_EP0_Setup(){ usbMsgFlags = 0; if ( ( UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK ) != USB_REQ_TYP_STANDARD )//Not standard request { - - //here is the commnunication starts, refer to usbFunctionSetup of USBtiny - //or usb_setup in usbtiny - switch( ( UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK )) { case USB_REQ_TYP_VENDOR: @@ -306,6 +304,7 @@ void USB_EP0_Setup(){ } else { + // TODO: remove unreachable code here UEP0_T_LEN = 0; // Tx data to host or send 0-length packet UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK;//Expect DATA1, Answer ACK } @@ -354,10 +353,10 @@ void USBInterrupt(void) { //inline not really working in multiple files in SDC {//SDCC will take IRAM if array of function pointer is used. switch (callIndex) { case 0: EP0_OUT_Callback(); break; - case 1: EP1_OUT_Callback(); break; - case 2: EP2_OUT_Callback(); break; - case 3: EP3_OUT_Callback(); break; - case 4: EP4_OUT_Callback(); break; + case 1: USB_EP1_OUT(); break; + case 2: break; + case 3: break; + case 4: break; default: break; } } @@ -366,10 +365,10 @@ void USBInterrupt(void) { //inline not really working in multiple files in SDC {//SDCC will take IRAM if array of function pointer is used. switch (callIndex) { case 0: EP0_IN_Callback(); break; - case 1: EP1_IN_Callback(); break; - case 2: EP2_IN_Callback(); break; - case 3: EP3_IN_Callback(); break; - case 4: EP4_IN_Callback(); break; + case 1: break; + case 2: USB_EP2_IN(); break; + case 3: break; + case 4: break; default: break; } } @@ -439,10 +438,13 @@ void USBDeviceIntCfg() void USBDeviceEndPointCfg() { UEP1_DMA = (uint16_t) Ep1Buffer; //Endpoint 1 data transfer address + UEP2_DMA = (uint16_t) Ep2Buffer; //Endpoint 1 data transfer address UEP1_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK; //Endpoint 1 automatically flips the sync flag, IN transaction returns NAK, OUT returns ACK + UEP2_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_NAK; //Endpoint 2 automatically flips the sync flag, IN & OUT transaction returns NAK UEP0_DMA = (uint16_t) Ep0Buffer; //Endpoint 0 data transfer address - UEP4_1_MOD = 0XC0; //endpoint1 TX RX enable + UEP4_1_MOD = bUEP1_RX_EN; + UEP2_3_MOD = bUEP2_TX_EN; UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; //Manual flip, OUT transaction returns ACK, IN transaction returns NAK } diff --git a/examples/CMSIS_DAP/USBhandler.h b/examples/CMSIS_DAP/USBhandler.h index eebe6d0..2c94863 100644 --- a/examples/CMSIS_DAP/USBhandler.h +++ b/examples/CMSIS_DAP/USBhandler.h @@ -13,17 +13,9 @@ extern const __code uint8_t *pDescr; // Out #define EP0_OUT_Callback USB_EP0_OUT -#define EP1_OUT_Callback USB_EP1_OUT -#define EP2_OUT_Callback NOP_Process -#define EP3_OUT_Callback NOP_Process -#define EP4_OUT_Callback NOP_Process // IN #define EP0_IN_Callback USB_EP0_IN -#define EP1_IN_Callback USB_EP1_IN -#define EP2_IN_Callback NOP_Process -#define EP3_IN_Callback NOP_Process -#define EP4_IN_Callback NOP_Process void USBInterrupt(void); void USBDeviceCfg(); diff --git a/examples/CMSIS_DAP/main.c b/examples/CMSIS_DAP/main.c index a3ba0bd..d8f7da1 100644 --- a/examples/CMSIS_DAP/main.c +++ b/examples/CMSIS_DAP/main.c @@ -37,11 +37,11 @@ void main() { response_len = DAP_Thread(); USBByteCountEP1 = 0 ; - UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_ACK; //enable receive + //UEP2_T_LEN = response_len; + UEP2_T_LEN = 64; // hangs on Windoze < 64 + UEP2_CTRL = UEP2_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_ACK; //enable send - //UEP1_T_LEN = response_len; - UEP1_T_LEN = 64; // hangs on Windoze < 64 - UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_ACK; //enable send + UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_ACK; //enable receive } } } From 62ca5e608a36f4f27886a41761561cedbf5751c3 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Sun, 21 Feb 2021 10:47:35 -0400 Subject: [PATCH 29/54] move code into main --- examples/CMSIS_DAP/USBHID.c | 33 --------------------------------- examples/CMSIS_DAP/USBHID.h | 10 ---------- 2 files changed, 43 deletions(-) delete mode 100644 examples/CMSIS_DAP/USBHID.c delete mode 100644 examples/CMSIS_DAP/USBHID.h diff --git a/examples/CMSIS_DAP/USBHID.c b/examples/CMSIS_DAP/USBHID.c deleted file mode 100644 index 16bd3c2..0000000 --- a/examples/CMSIS_DAP/USBHID.c +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include "USBconstant.h" -#include "USBhandler.h" - -volatile uint8_t USBByteCountEP1 = 0; //Bytes of received data on USB endpoint - -void USBInit(){ - USBDeviceCfg(); //Device mode configuration - USBDeviceEndPointCfg(); //Endpoint configuration - USBDeviceIntCfg(); //Interrupt configuration - UEP0_T_LEN = 0; - UEP1_T_LEN = 0; //Pre-use send length must be cleared - UEP2_T_LEN = 0; -} - -void USB_EP2_IN(){ - UEP2_T_LEN = 0; // No data to send anymore - UEP2_CTRL = UEP2_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_NAK; //Respond NAK by default -} - -void USB_EP1_OUT(){ - if ( U_TOG_OK ){ // Discard unsynchronized packets - USBByteCountEP1 = USB_RX_LEN; - if (USBByteCountEP1){ - //Respond NAK after a packet. Let main code change response after handling. - UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_NAK; - } - } -} - diff --git a/examples/CMSIS_DAP/USBHID.h b/examples/CMSIS_DAP/USBHID.h deleted file mode 100644 index 502e535..0000000 --- a/examples/CMSIS_DAP/USBHID.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef __USB_HID_H__ -#define __USB_HID_H__ - -#include - -extern volatile uint8_t USBByteCountEP1; -void USBInit(void); - -#endif - From 08dbda9eb49e0e22aa8d48b9abe6a369bb236dc8 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Sun, 21 Feb 2021 11:49:44 -0400 Subject: [PATCH 30/54] EP1 OUT double-buffering working with DAP_PACKET_COUNT=1 --- examples/CMSIS_DAP/DAP.c | 9 +++-- examples/CMSIS_DAP/DAP.h | 3 ++ examples/CMSIS_DAP/USBconstant.c | 21 ++++++------ examples/CMSIS_DAP/main.c | 59 +++++++++++++++++++++++++++++--- 4 files changed, 75 insertions(+), 17 deletions(-) diff --git a/examples/CMSIS_DAP/DAP.c b/examples/CMSIS_DAP/DAP.c index b7cbd8e..db7a296 100644 --- a/examples/CMSIS_DAP/DAP.c +++ b/examples/CMSIS_DAP/DAP.c @@ -27,6 +27,9 @@ #include "DAP.h" +__xdata uint8_t* DAP_RxBuf; +__xdata uint8_t* DAP_TxBuf; + // Get DAP Information // id: info identifier // info: pointer to info data @@ -897,8 +900,10 @@ uint8_t DAP_Thread(void) if (1) { - uint8_t __xdata *req = &Ep1Buffer[0]; - uint8_t __xdata *res = &Ep2Buffer[0]; + // uint8_t __xdata *req = &Ep1Buffer[0]; + // uint8_t __xdata *res = &Ep2Buffer[0]; + uint8_t __xdata *req = DAP_RxBuf; + uint8_t __xdata *res = DAP_TxBuf; *res++ = *req; switch (*req++) diff --git a/examples/CMSIS_DAP/DAP.h b/examples/CMSIS_DAP/DAP.h index 3d7f827..2d13ac8 100644 --- a/examples/CMSIS_DAP/DAP.h +++ b/examples/CMSIS_DAP/DAP.h @@ -237,6 +237,9 @@ extern __xdata uint8_t Ep0Buffer[]; extern __xdata uint8_t Ep1Buffer[]; extern __xdata uint8_t Ep2Buffer[]; +extern __xdata uint8_t* DAP_RxBuf; +extern __xdata uint8_t* DAP_TxBuf; + extern __idata uint8_t turnaround; extern __idata uint8_t data_phase; extern __idata uint8_t idle_cycles; diff --git a/examples/CMSIS_DAP/USBconstant.c b/examples/CMSIS_DAP/USBconstant.c index d79fad9..dbc31da 100644 --- a/examples/CMSIS_DAP/USBconstant.c +++ b/examples/CMSIS_DAP/USBconstant.c @@ -31,17 +31,16 @@ __code uint8_t CfgDesc[] ={ 0x80, /* bmAttributes */ 0x64, /* MaxPower */ - - /* I/F descr: HID */ - 0x09, /* bLength */ - 0x04, /* bDescriptorType */ - 0x00, /* bInterfaceNumber */ - 0x00, /* bAlternateSetting */ - 0x02, /* bNumEndpoints */ - 0x03, /* bInterfaceClass */ - 0x00, /* bInterfaceSubClass */ - 0x00, /* bInterfaceProtocol */ - 0x00, /* iInterface */ + // HID interface descriptor + 0x09, // bLength + USB_DESCR_TYP_INTERF, // bDescriptorType + 0x00, // bInterfaceNumber + 0x00, // bAlternateSetting + 0x02, // bNumEndpoints + USB_DEV_CLASS_HID, // bInterfaceClass + 0x00, // bInterfaceSubClass + 0x00, // bInterfaceProtocol + 0x00, // iInterface /* HID Descriptor */ 0x09, /* Size of this descriptor in UINT8s. */ diff --git a/examples/CMSIS_DAP/main.c b/examples/CMSIS_DAP/main.c index d8f7da1..7f18c01 100644 --- a/examples/CMSIS_DAP/main.c +++ b/examples/CMSIS_DAP/main.c @@ -2,13 +2,18 @@ CMSIS_DAP Based on DAPLink and Deqing Sun's CH55xduino port https://github.com/ARMmbed/DAPLink + Ralph Doncaster 2020, 2021 see DAP.h for RST, SWCLK, & SWDIO pin defines */ +#include + +#include +#include #include + #include "DAP.h" -#include "USBHID.h" #include "USBhandler.h" void DeviceUSBInterrupt(void) __interrupt (INT_NO_USB) @@ -16,9 +21,52 @@ void DeviceUSBInterrupt(void) __interrupt (INT_NO_USB) USBInterrupt(); } +//Bytes of received data on USB endpoint +volatile uint8_t USBByteCountEP1 = 0; + +// for EP1 OUT double-buffering +volatile uint8_t EP1_buffs_avail = 2; +__bit EP1_buf_toggle = 0; + +void USBInit(){ + USBDeviceCfg(); //Device mode configuration + USBDeviceEndPointCfg(); //Endpoint configuration + USBDeviceIntCfg(); //Interrupt configuration + UEP0_T_LEN = 0; + UEP1_T_LEN = 0; + UEP2_T_LEN = 0; + // single Tx buffer for DAP replies + DAP_TxBuf = (__xdata uint8_t*) UEP2_DMA; +} + +void USB_EP2_IN(){ + UEP2_T_LEN = 0; // No data to send anymore + UEP2_CTRL = UEP2_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_NAK; //Respond NAK by default +} + +void USB_EP1_OUT(){ + if ( U_TOG_OK ){ // Discard unsynchronized packets + USBByteCountEP1 = USB_RX_LEN; + if (USBByteCountEP1){ + if (--EP1_buffs_avail == 0) { + //Respond NAK. Let main change response after handling. + UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_NAK; + } + + DAP_RxBuf = (__xdata uint8_t*) UEP1_DMA; + EP1_buf_toggle = !EP1_buf_toggle; + if (EP1_buf_toggle) + UEP1_DMA = (uint16_t) Ep1Buffer + 64; + else + UEP1_DMA = (uint16_t) Ep1Buffer; + + } + } +} + // perform USB bus reset/disconnect // set UDP to GPIO mode and hold low for device disconnect -void resetUSB() +inline void resetUSB() { PIN_FUNC &= ~(bUSB_IO_EN); UDP = 0; @@ -36,12 +84,15 @@ void main() { if (USBByteCountEP1) { response_len = DAP_Thread(); USBByteCountEP1 = 0 ; + // enable receive + EP1_buffs_avail++; + UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_ACK; //UEP2_T_LEN = response_len; + // enable interrupt IN response UEP2_T_LEN = 64; // hangs on Windoze < 64 - UEP2_CTRL = UEP2_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_ACK; //enable send + UEP2_CTRL = UEP2_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_ACK; - UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_ACK; //enable receive } } } From a4bb9853aa7b08fc00cd612b860b0124f7a81076 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Sun, 21 Feb 2021 19:02:06 -0400 Subject: [PATCH 31/54] now working with DAP_PACKET_COUNT=2 --- examples/CMSIS_DAP/DAP.c | 8 +------- examples/CMSIS_DAP/DAP.h | 4 ++-- examples/CMSIS_DAP/main.c | 27 +++++++++++++++++---------- 3 files changed, 20 insertions(+), 19 deletions(-) diff --git a/examples/CMSIS_DAP/DAP.c b/examples/CMSIS_DAP/DAP.c index db7a296..9034a27 100644 --- a/examples/CMSIS_DAP/DAP.c +++ b/examples/CMSIS_DAP/DAP.c @@ -893,16 +893,11 @@ static uint8_t DAP_WriteAbort(const uint8_t *req, uint8_t *res) } // DAP Thread. -uint8_t DAP_Thread(void) +uint8_t DAP_Thread(uint8_t __xdata *req) { uint8_t num; uint8_t returnVal = 0; - if (1) - { - // uint8_t __xdata *req = &Ep1Buffer[0]; - // uint8_t __xdata *res = &Ep2Buffer[0]; - uint8_t __xdata *req = DAP_RxBuf; uint8_t __xdata *res = DAP_TxBuf; *res++ = *req; @@ -979,7 +974,6 @@ uint8_t DAP_Thread(void) } returnVal = num + 1; - } return returnVal; } diff --git a/examples/CMSIS_DAP/DAP.h b/examples/CMSIS_DAP/DAP.h index 2d13ac8..65e9c1b 100644 --- a/examples/CMSIS_DAP/DAP.h +++ b/examples/CMSIS_DAP/DAP.h @@ -198,7 +198,7 @@ #define SWD_SEQUENCE_CLK 0x3FU // SWCLK count #define SWD_SEQUENCE_DIN 0x80U // SWDIO capture -#define DAP_PACKET_COUNT 1 +#define DAP_PACKET_COUNT 2 #define DAP_PACKET_SIZE 64 //THIS_ENDP0_SIZE #define DAP_DEFAULT_PORT DAP_PORT_SWD @@ -244,7 +244,7 @@ extern __idata uint8_t turnaround; extern __idata uint8_t data_phase; extern __idata uint8_t idle_cycles; -extern uint8_t DAP_Thread(void); +extern uint8_t DAP_Thread(__xdata uint8_t* req); extern uint8_t SWD_Transfer(uint8_t reqI, __xdata uint8_t *data); extern void SWJ_Sequence(uint8_t count, const uint8_t *data); extern void SWD_Sequence(uint8_t info, const uint8_t *swdo, uint8_t *swdi); diff --git a/examples/CMSIS_DAP/main.c b/examples/CMSIS_DAP/main.c index 7f18c01..9c9429f 100644 --- a/examples/CMSIS_DAP/main.c +++ b/examples/CMSIS_DAP/main.c @@ -48,11 +48,10 @@ void USB_EP1_OUT(){ if ( U_TOG_OK ){ // Discard unsynchronized packets USBByteCountEP1 = USB_RX_LEN; if (USBByteCountEP1){ - if (--EP1_buffs_avail == 0) { - //Respond NAK. Let main change response after handling. - UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_NAK; - } + //Respond NAK. Let main change response after handling. + UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_NAK; + // double-buffering of DAP request packets DAP_RxBuf = (__xdata uint8_t*) UEP1_DMA; EP1_buf_toggle = !EP1_buf_toggle; if (EP1_buf_toggle) @@ -81,18 +80,26 @@ void main() { USBInit(); while (1) { uint8_t response_len; - if (USBByteCountEP1) { - response_len = DAP_Thread(); - USBByteCountEP1 = 0 ; - // enable receive - EP1_buffs_avail++; - UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_ACK; + // process if a DAP packet is received, and TxBuf is empty + // save ByteCountEP1? + if (USBByteCountEP1 && !UEP2_T_LEN) { + __xdata uint8_t* RxPkt = DAP_RxBuf; + if (--EP1_buffs_avail) { + USBByteCountEP1 = 0 ; + // Rx another packet while DAP_Thread runs + UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_ACK; + } + + response_len = DAP_Thread(RxPkt); //UEP2_T_LEN = response_len; // enable interrupt IN response UEP2_T_LEN = 64; // hangs on Windoze < 64 UEP2_CTRL = UEP2_CTRL & ~ MASK_UEP_T_RES | UEP_T_RES_ACK; + // enable receive + EP1_buffs_avail++; + UEP1_CTRL = UEP1_CTRL & ~ MASK_UEP_R_RES | UEP_R_RES_ACK; } } } From 782f41ed46380fd13fc58a607c6a41ca00879530 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Sun, 21 Feb 2021 19:13:06 -0400 Subject: [PATCH 32/54] update openocd & pyOCD info --- examples/CMSIS_DAP/README.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/CMSIS_DAP/README.txt b/examples/CMSIS_DAP/README.txt index c3dd732..f76e49d 100644 --- a/examples/CMSIS_DAP/README.txt +++ b/examples/CMSIS_DAP/README.txt @@ -2,5 +2,5 @@ CMSIS-DAP debug probe implementation Recommended hardware setup is with VCC=3V3 and 68-100Ohm series resistors on SWDIO & SWCLK. -Performance is partially optimized, with SWCLK running at less than 1Mhz. Overall throughput flashing a STM32F103 with pyocd is about 6kB/s. With optimization of the bit-banged SWD code and the USB packet handling, 20kB/s programming speeds should be possible +Performance is partially optimized, with SWCLK running at less than 1Mhz. Overall throughput flashing a STM32F103 with openocd is 9kB/s. pyOCD, being an interpreted python program, is usually slower. From a91fa6d3c9089cc92182bb4f2183a080ed84f6fc Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Sun, 21 Feb 2021 19:15:16 -0400 Subject: [PATCH 33/54] document default SWDIO & SWCLK pins --- examples/CMSIS_DAP/README.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/CMSIS_DAP/README.txt b/examples/CMSIS_DAP/README.txt index f76e49d..f4fd632 100644 --- a/examples/CMSIS_DAP/README.txt +++ b/examples/CMSIS_DAP/README.txt @@ -1,6 +1,6 @@ CMSIS-DAP debug probe implementation -Recommended hardware setup is with VCC=3V3 and 68-100Ohm series resistors on SWDIO & SWCLK. +Recommended hardware setup is with VCC=3V3 and 68-100Ohm series resistors on SWDIO(P1.6) & SWCLK(P1.7). Performance is partially optimized, with SWCLK running at less than 1Mhz. Overall throughput flashing a STM32F103 with openocd is 9kB/s. pyOCD, being an interpreted python program, is usually slower. From 968084790ff3c6c42996225636d74791f87c23b2 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Mon, 22 Feb 2021 13:36:34 -0400 Subject: [PATCH 34/54] string descriptor cleanup --- examples/CMSIS_DAP/USBconstant.c | 14 ++++++++------ examples/CMSIS_DAP/USBhandler.c | 5 ++++- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/examples/CMSIS_DAP/USBconstant.c b/examples/CMSIS_DAP/USBconstant.c index dbc31da..ac3f16b 100644 --- a/examples/CMSIS_DAP/USBconstant.c +++ b/examples/CMSIS_DAP/USBconstant.c @@ -97,22 +97,24 @@ __code uint8_t LangDesLen = sizeof(LangDes); //Product String Descriptor __code uint16_t Prod_Des[]={ - 0x0320, // type and length - // u"CH55x CMSIS-DAP" - 'C','H','5','5','x',' ', - 'C','M','S','I','S','-','D','A','P' + 0x0300 + sizeof(Prod_Des), // type and length + // compound literals not supported in SDCC as of v4.0.3 + // (__code uint16_t[]) { u"CH55x CMSIS-DAP" } + 'C','H','5','5','x',' ', 'C','M','S','I','S','-','D','A','P' }; __code uint8_t Prod_DesLen = sizeof(Prod_Des); +__sfr __at(sizeof(Prod_Des)) PDLen; + __code uint16_t Manuf_Des[]={ - 0x0308, // type and length + 0x0300 + sizeof(Manuf_Des), // type and length 'W','C','H' }; __code uint8_t Manuf_DesLen = sizeof(Manuf_Des); // Serial string descriptor - CMSIS-DAP unique ID __code uint16_t Ser_Des[]={ - 0x0308, // type and length + 0x0300 + sizeof(Ser_Des), // type and length '1','2','3' }; __code uint8_t Ser_DesLen = sizeof(Manuf_Des); diff --git a/examples/CMSIS_DAP/USBhandler.c b/examples/CMSIS_DAP/USBhandler.c index bf8d80d..1d6db59 100644 --- a/examples/CMSIS_DAP/USBhandler.c +++ b/examples/CMSIS_DAP/USBhandler.c @@ -13,6 +13,8 @@ __xdata __at (EP0_ADDR) uint8_t Ep0Buffer[8]; __xdata __at (EP1_ADDR) uint8_t Ep1Buffer[128]; // EP1 OUT*2 __xdata __at (EP2_ADDR) uint8_t Ep2Buffer[64]; +extern __sfr PDLen; + uint16_t SetupLen; uint8_t SetupReq,UsbConfig; @@ -91,7 +93,8 @@ void USB_EP0_Setup(){ else if(UsbSetupBuf->wValueL == 2) { pDescr = Prod_Des; - len = Prod_DesLen; + //len = Prod_DesLen; + len = (uint8_t)&PDLen; } /* else if(UsbSetupBuf->wValueL == 3) From 8b56686a65960df65e5fc21e9d122e320dd9ac70 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Mon, 22 Feb 2021 20:49:25 -0400 Subject: [PATCH 35/54] cleanup string descriptors --- examples/CMSIS_DAP/USBconstant.c | 24 +++++++++++------------- examples/CMSIS_DAP/USBconstant.h | 6 +----- examples/CMSIS_DAP/USBhandler.c | 24 ++++++++---------------- 3 files changed, 20 insertions(+), 34 deletions(-) diff --git a/examples/CMSIS_DAP/USBconstant.c b/examples/CMSIS_DAP/USBconstant.c index dbc31da..4fd3ea9 100644 --- a/examples/CMSIS_DAP/USBconstant.c +++ b/examples/CMSIS_DAP/USBconstant.c @@ -68,9 +68,7 @@ __code uint8_t CfgDesc[] ={ 1, // bInterval }; - - -__code uint8_t ReportDescLen = sizeof(ReportDesc); +__code uint8_t CfgDescLen = sizeof(CfgDesc); __code uint8_t ReportDesc[] ={ 0x06, 0x00, 0xFF, // Usage Page = 0xFF00 (Vendor Defined Page 1) @@ -88,31 +86,31 @@ __code uint8_t ReportDesc[] ={ 0x91, 0x00, // Output (Data, Array, Abs): Instantiates output packet fields. Uses same report size and count as "Input" fields, since nothing new/different was specified to the parser since the "Input" item. 0xC0 // End Collection }; - -__code uint8_t CfgDescLen = sizeof(CfgDesc); +__code uint8_t ReportDescLen = sizeof(ReportDesc); //String Descriptors -__code uint8_t LangDes[]={0x04,0x03,0x09,0x04}; //Language Descriptor -__code uint8_t LangDesLen = sizeof(LangDes); +//Language Descriptor +__code uint16_t LangDes[]={ + 0x0300 + sizeof(LangDes), // type and length + 0x0409 // 0x0409 = US English language code +}; //Product String Descriptor __code uint16_t Prod_Des[]={ - 0x0320, // type and length + 0x0300 + sizeof(Prod_Des), // type and length // u"CH55x CMSIS-DAP" 'C','H','5','5','x',' ', 'C','M','S','I','S','-','D','A','P' }; -__code uint8_t Prod_DesLen = sizeof(Prod_Des); __code uint16_t Manuf_Des[]={ - 0x0308, // type and length + 0x0300 + sizeof(Manuf_Des), // type and length 'W','C','H' }; -__code uint8_t Manuf_DesLen = sizeof(Manuf_Des); // Serial string descriptor - CMSIS-DAP unique ID __code uint16_t Ser_Des[]={ - 0x0308, // type and length + 0x0300 + sizeof(Ser_Des), // type and length '1','2','3' }; -__code uint8_t Ser_DesLen = sizeof(Manuf_Des); + diff --git a/examples/CMSIS_DAP/USBconstant.h b/examples/CMSIS_DAP/USBconstant.h index 5b87a38..43f3414 100644 --- a/examples/CMSIS_DAP/USBconstant.h +++ b/examples/CMSIS_DAP/USBconstant.h @@ -10,17 +10,13 @@ extern __code USB_DEV_DESCR DevDesc; extern __code uint8_t CfgDesc[]; -extern __code uint8_t LangDes[]; extern __code uint8_t ReportDesc[]; +extern __code uint16_t LangDes[]; extern __code uint16_t Prod_Des[]; extern __code uint16_t Manuf_Des[]; extern __code uint16_t Ser_Des[]; extern __code uint8_t CfgDescLen; -extern __code uint8_t LangDesLen; extern __code uint8_t ReportDescLen; -extern __code uint8_t Prod_DesLen; -extern __code uint8_t Manuf_DesLen; -extern __code uint8_t Ser_DesLen; #endif diff --git a/examples/CMSIS_DAP/USBhandler.c b/examples/CMSIS_DAP/USBhandler.c index bf8d80d..092cbcc 100644 --- a/examples/CMSIS_DAP/USBhandler.c +++ b/examples/CMSIS_DAP/USBhandler.c @@ -67,44 +67,36 @@ void USB_EP0_Setup(){ case USB_GET_DESCRIPTOR: switch(UsbSetupBuf->wValueH) { - case 1: //Device Descriptor - // pDescr = DevDesc; //Put Device Descriptor into outgoing buffer - // len = DevDescLen; + case 1: // Device Descriptor pDescr = (uint8_t*)&DevDesc; len = sizeof(DevDesc); break; - case 2: //Configure Descriptor + case 2: // configureation descriptor pDescr = CfgDesc; len = CfgDescLen; break; - case 3: + case 3: // string descriptor if(UsbSetupBuf->wValueL == 0) { pDescr = LangDes; - len = LangDesLen; + // len = LangDesLen; } else if(UsbSetupBuf->wValueL == 1) { pDescr = Manuf_Des; - len = Manuf_DesLen; + //len = Manuf_DesLen; } else if(UsbSetupBuf->wValueL == 2) { pDescr = Prod_Des; - len = Prod_DesLen; + //len = Prod_DesLen; } - /* - else if(UsbSetupBuf->wValueL == 3) - { - pDescr = SerDes; - len = SerDesLen; - } - */ else { pDescr = Ser_Des; - len = Ser_DesLen; + //len = Ser_DesLen; } + len = pDescr[0]; break; case 0x22: if(UsbSetupBuf->wValueL == 0){ From 051beb3790a3d55df76cf0848ed3f6098b4576f5 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Mon, 22 Feb 2021 23:19:42 -0400 Subject: [PATCH 36/54] asm descriptor copy function --- examples/CMSIS_DAP/USBhandler.c | 48 ++++++++++++++++++++++++++++----- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/examples/CMSIS_DAP/USBhandler.c b/examples/CMSIS_DAP/USBhandler.c index 092cbcc..85333ee 100644 --- a/examples/CMSIS_DAP/USBhandler.c +++ b/examples/CMSIS_DAP/USBhandler.c @@ -1,3 +1,4 @@ +#include #include #include @@ -22,6 +23,42 @@ volatile uint8_t usbMsgFlags=0; // uint8_t usbMsgFlags copied from VUSB inline void NOP_Process(void) {} +// copy descriptor *pDescr to Ep0 +#pragma callee_saves cpy_desc_Ep0 +void cpy_desc_Ep0(uint8_t len) __naked +{ + len; // stop unused arg warning + __asm + xch A, _DPL ; ACC = len + inc _XBUS_AUX + mov DPL, #_Ep0Buffer + mov DPH, #(_Ep0Buffer >> 8) + dec _XBUS_AUX + mov DPL, _pDescr + mov DPH, (_pDescr + 1) + sjmp _ccpyx + __endasm; +} + +// copy code to xram +// *dest in DPTR1, len in A +#pragma callee_saves ccpyx +void ccpyx(__code char* src) +{ + src; // stop unused arg warning + __asm + push ar7 + xch A, R7 + 01$: + clr A + movc A, @A+DPTR + inc DPTR + .DB 0xA5 ;MOVX @DPTR1,A & INC DPTR1 + djnz R7, 01$ + pop ar7 + __endasm; +} + void USB_EP0_Setup(){ uint8_t len = USB_RX_LEN; if(len == (sizeof(USB_SETUP_REQ))) @@ -118,9 +155,8 @@ void USB_EP0_Setup(){ SetupLen = len; // Limit length } len = SetupLen >= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupLen; //transmit length for this packet - for (uint8_t i=0;i= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupLen; //send length - for (uint8_t i=0;i Date: Mon, 22 Feb 2021 23:42:46 -0400 Subject: [PATCH 37/54] change SetupLen to u8 from u16 --- examples/CMSIS_DAP/USBhandler.c | 7 +++++-- examples/CMSIS_DAP/USBhandler.h | 5 ----- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/examples/CMSIS_DAP/USBhandler.c b/examples/CMSIS_DAP/USBhandler.c index 85333ee..c858a83 100644 --- a/examples/CMSIS_DAP/USBhandler.c +++ b/examples/CMSIS_DAP/USBhandler.c @@ -14,7 +14,7 @@ __xdata __at (EP0_ADDR) uint8_t Ep0Buffer[8]; __xdata __at (EP1_ADDR) uint8_t Ep1Buffer[128]; // EP1 OUT*2 __xdata __at (EP2_ADDR) uint8_t Ep2Buffer[64]; -uint16_t SetupLen; +uint8_t SetupLen; uint8_t SetupReq,UsbConfig; __code uint8_t *pDescr; @@ -63,7 +63,10 @@ void USB_EP0_Setup(){ uint8_t len = USB_RX_LEN; if(len == (sizeof(USB_SETUP_REQ))) { - SetupLen = ((uint16_t)UsbSetupBuf->wLengthH<<8) | (UsbSetupBuf->wLengthL); + uint16_t wLength = ((uint16_t)UsbSetupBuf->wLengthH<<8) | (UsbSetupBuf->wLengthL); + SetupLen = wLength; + // maximum supported reply size is 254 bytes + if (wLength > 254) SetupLen = 254; len = 0; // Default is success and upload 0 length SetupReq = UsbSetupBuf->bRequest; usbMsgFlags = 0; diff --git a/examples/CMSIS_DAP/USBhandler.h b/examples/CMSIS_DAP/USBhandler.h index 2c94863..17d0e06 100644 --- a/examples/CMSIS_DAP/USBhandler.h +++ b/examples/CMSIS_DAP/USBhandler.h @@ -4,11 +4,6 @@ #include #include "USBconstant.h" -extern uint16_t SetupLen; -extern uint8_t SetupReq,UsbConfig; -extern const __code uint8_t *pDescr; - - #define UsbSetupBuf ((PUSB_SETUP_REQ)Ep0Buffer) // Out From a75e58d8eda9b7aac8d0369f80de7310d1b964aa Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Tue, 23 Feb 2021 00:01:41 -0400 Subject: [PATCH 38/54] use strcpy instead of memcpy --- examples/CMSIS_DAP/DAP.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/examples/CMSIS_DAP/DAP.c b/examples/CMSIS_DAP/DAP.c index 9034a27..b631935 100644 --- a/examples/CMSIS_DAP/DAP.c +++ b/examples/CMSIS_DAP/DAP.c @@ -25,16 +25,19 @@ * *---------------------------------------------------------------------------*/ +#include #include "DAP.h" __xdata uint8_t* DAP_RxBuf; __xdata uint8_t* DAP_TxBuf; +// TODO: change all uint8_t* to __xdata + // Get DAP Information // id: info identifier // info: pointer to info data // return: number of bytes in info data -static uint8_t DAP_Info(uint8_t id, uint8_t *info) +static uint8_t DAP_Info(uint8_t id, __xdata uint8_t *info) { uint8_t length = 0U; @@ -51,7 +54,7 @@ static uint8_t DAP_Info(uint8_t id, uint8_t *info) break; case DAP_ID_FW_VER: length = (uint8_t)sizeof(DAP_FW_VER); - memcpy(info, DAP_FW_VER, length); + strcpy(info, DAP_FW_VER ); break; case DAP_ID_DEVICE_VENDOR: From 828dc97f43a7989cfd1a2aa8dbb03d5e491afbc8 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Tue, 23 Feb 2021 00:11:12 -0400 Subject: [PATCH 39/54] use xdata pointers instead of generic --- examples/CMSIS_DAP/DAP.c | 40 ++++++++++++++++++++-------------------- examples/CMSIS_DAP/DAP.h | 2 -- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/examples/CMSIS_DAP/DAP.c b/examples/CMSIS_DAP/DAP.c index b631935..6ddb02d 100644 --- a/examples/CMSIS_DAP/DAP.c +++ b/examples/CMSIS_DAP/DAP.c @@ -92,7 +92,7 @@ static uint8_t DAP_Info(uint8_t id, __xdata uint8_t *info) // request: pointer to request data // response: pointer to response data // return: number of bytes in response -static uint8_t DAP_Delay(const uint8_t *req, uint8_t *res) +static uint8_t DAP_Delay(const __xdata uint8_t *req, __xdata uint8_t *res) { uint16_t delay; @@ -111,7 +111,7 @@ static uint8_t DAP_Delay(const uint8_t *req, uint8_t *res) // request: pointer to request data // response: pointer to response data // return: number of bytes in response -static uint8_t DAP_HostStatus(const uint8_t *req, uint8_t *res) +static uint8_t DAP_HostStatus(const __xdata uint8_t *req, __xdata uint8_t *res) { switch (*req) @@ -136,7 +136,7 @@ static uint8_t DAP_HostStatus(const uint8_t *req, uint8_t *res) // response: pointer to response data // return: number of bytes in response __idata uint8_t debug_port; -static uint8_t DAP_Connect(const uint8_t *req, uint8_t *res) +static uint8_t DAP_Connect(const __xdata uint8_t *req, __xdata uint8_t *res) { uint8_t port; @@ -168,7 +168,7 @@ static uint8_t DAP_Connect(const uint8_t *req, uint8_t *res) // response: pointer to response data // return: number of bytes in response #define PORT_OFF() PORT_SWD_SETUP() -static uint8_t DAP_Disconnect(uint8_t *res) +static uint8_t DAP_Disconnect(__xdata uint8_t *res) { debug_port = DAP_PORT_DISABLED; @@ -181,7 +181,7 @@ static uint8_t DAP_Disconnect(uint8_t *res) // Process Reset Target command and prepare response // response: pointer to response data // return: number of bytes in response -static uint8_t DAP_ResetTarget(uint8_t *res) +static uint8_t DAP_ResetTarget(__xdata uint8_t *res) { *(res + 1) = 0; //RESET_TARGET(); *(res + 0) = DAP_OK; @@ -192,7 +192,7 @@ static uint8_t DAP_ResetTarget(uint8_t *res) // request: pointer to request data // response: pointer to response data // return: number of bytes in response -static uint8_t DAP_SWJ_Pins(const uint8_t *req, uint8_t *res) +static uint8_t DAP_SWJ_Pins(const __xdata uint8_t *req, __xdata uint8_t *res) { uint8_t value; uint8_t select; @@ -279,7 +279,7 @@ static uint8_t DAP_SWJ_Pins(const uint8_t *req, uint8_t *res) // request: pointer to request data // response: pointer to response data // return: number of bytes in response -static uint8_t DAP_SWJ_Clock(const uint8_t *req, uint8_t *res) +static uint8_t DAP_SWJ_Clock(const __xdata uint8_t *req, __xdata uint8_t *res) { req; *res = DAP_OK; @@ -290,7 +290,7 @@ static uint8_t DAP_SWJ_Clock(const uint8_t *req, uint8_t *res) // request: pointer to request data // response: pointer to response data // return: number of bytes in response -static uint8_t DAP_SWJ_Sequence(const uint8_t *req, uint8_t *res) +static uint8_t DAP_SWJ_Sequence(const __xdata uint8_t *req, __xdata uint8_t *res) { uint8_t count; @@ -312,7 +312,7 @@ static uint8_t DAP_SWJ_Sequence(const uint8_t *req, uint8_t *res) // return: number of bytes in response __idata uint8_t turnaround; __idata uint8_t data_phase; -static uint8_t DAP_SWD_Configure(const uint8_t *req, uint8_t *res) +static uint8_t DAP_SWD_Configure(const __xdata uint8_t *req, __xdata uint8_t *res) { uint8_t value; @@ -328,7 +328,7 @@ static uint8_t DAP_SWD_Configure(const uint8_t *req, uint8_t *res) // request: pointer to request data // response: pointer to response data // return: number of bytes in response -static uint8_t DAP_SWD_Sequence(const uint8_t *req, uint8_t *res) +static uint8_t DAP_SWD_Sequence(const __xdata uint8_t *req, __xdata uint8_t *res) { uint8_t sequence_info; uint8_t sequence_count; @@ -387,7 +387,7 @@ static uint8_t DAP_SWD_Sequence(const uint8_t *req, uint8_t *res) __idata uint8_t idle_cycles; __idata uint16_t retry_count; __idata uint16_t match_retry; -static uint8_t DAP_TransferConfigure(const uint8_t *req, uint8_t *res) +static uint8_t DAP_TransferConfigure(const __xdata uint8_t *req, __xdata uint8_t *res) { idle_cycles = *(req + 0); @@ -414,10 +414,10 @@ __idata uint8_t request_value; __idata uint8_t response_count; __idata uint8_t response_value; __idata uint16_t retry; -static uint8_t DAP_SWD_Transfer(const uint8_t *req, uint8_t *res) +static uint8_t DAP_SWD_Transfer(const __xdata uint8_t *req, __xdata uint8_t *res) { - const uint8_t *request_head; - uint8_t *response_head; + const __xdata uint8_t *request_head; + __xdata uint8_t *response_head; uint8_t post_read; uint8_t check_write; @@ -701,7 +701,7 @@ static uint8_t DAP_SWD_Transfer(const uint8_t *req, uint8_t *res) // request: pointer to request data // response: pointer to response data // return: number of bytes in response -static uint8_t DAP_Transfer(const uint8_t *req, uint8_t *res) +static uint8_t DAP_Transfer(const __xdata uint8_t *req, __xdata uint8_t *res) { uint8_t num = 0; @@ -722,10 +722,10 @@ static uint8_t DAP_Transfer(const uint8_t *req, uint8_t *res) // request: pointer to request data // response: pointer to response data // return: number of bytes in response -static uint8_t DAP_SWD_TransferBlock(const uint8_t *req, uint8_t *res) +static uint8_t DAP_SWD_TransferBlock(const __xdata uint8_t *req, __xdata uint8_t *res) { - uint8_t *response_head; + __xdata uint8_t *response_head; response_count = 0U; response_value = 0U; response_head = res; @@ -833,7 +833,7 @@ static uint8_t DAP_SWD_TransferBlock(const uint8_t *req, uint8_t *res) // request: pointer to request data // response: pointer to response data // return: number of bytes in response -static uint8_t DAP_TransferBlock(const uint8_t *req, uint8_t *res) +static uint8_t DAP_TransferBlock(const __xdata uint8_t *req, __xdata uint8_t *res) { uint8_t num; @@ -858,7 +858,7 @@ static uint8_t DAP_TransferBlock(const uint8_t *req, uint8_t *res) // request: pointer to request data // response: pointer to response data // return: number of bytes in response -static uint8_t DAP_SWD_WriteAbort(const uint8_t *req, uint8_t *res) +static uint8_t DAP_SWD_WriteAbort(const __xdata uint8_t *req, __xdata uint8_t *res) { // Load data (Ignore DAP index) data[0] = (uint8_t)(*(req + 1)); @@ -877,7 +877,7 @@ static uint8_t DAP_SWD_WriteAbort(const uint8_t *req, uint8_t *res) // request: pointer to request data // response: pointer to response data // return: number of bytes in response -static uint8_t DAP_WriteAbort(const uint8_t *req, uint8_t *res) +static uint8_t DAP_WriteAbort(const __xdata uint8_t *req, __xdata uint8_t *res) { uint8_t num; diff --git a/examples/CMSIS_DAP/DAP.h b/examples/CMSIS_DAP/DAP.h index 65e9c1b..39027db 100644 --- a/examples/CMSIS_DAP/DAP.h +++ b/examples/CMSIS_DAP/DAP.h @@ -30,9 +30,7 @@ #include <8052.h> #include -#include #include -#include // DAP Firmware Version #define DAP_FW_VER "1.2.1" From 91e99594e725708760e22051382e4119ef65e416 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Tue, 23 Feb 2021 00:15:54 -0400 Subject: [PATCH 40/54] use xdata pointers --- examples/CMSIS_DAP/DAP.h | 4 ++-- examples/CMSIS_DAP/SW_DP.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/CMSIS_DAP/DAP.h b/examples/CMSIS_DAP/DAP.h index 39027db..b1b7740 100644 --- a/examples/CMSIS_DAP/DAP.h +++ b/examples/CMSIS_DAP/DAP.h @@ -244,7 +244,7 @@ extern __idata uint8_t idle_cycles; extern uint8_t DAP_Thread(__xdata uint8_t* req); extern uint8_t SWD_Transfer(uint8_t reqI, __xdata uint8_t *data); -extern void SWJ_Sequence(uint8_t count, const uint8_t *data); -extern void SWD_Sequence(uint8_t info, const uint8_t *swdo, uint8_t *swdi); +extern void SWJ_Sequence(uint8_t count, const __xdata uint8_t *data); +extern void SWD_Sequence(uint8_t info, const __xdata uint8_t *swdo, __xdata uint8_t *swdi); #endif /* __DAP_H__ */ diff --git a/examples/CMSIS_DAP/SW_DP.c b/examples/CMSIS_DAP/SW_DP.c index f5d1ea6..fa5ec52 100644 --- a/examples/CMSIS_DAP/SW_DP.c +++ b/examples/CMSIS_DAP/SW_DP.c @@ -45,7 +45,7 @@ volatile uint8_t swdelay; // count: sequence bits count // data: pointer to sequence bits data // return: none -void SWJ_Sequence(uint8_t count, const uint8_t *data) +void SWJ_Sequence(uint8_t count, const __xdata uint8_t *data) { uint8_t val; uint8_t n; @@ -71,7 +71,7 @@ void SWJ_Sequence(uint8_t count, const uint8_t *data) // swdo: pointer to SWDIO generated data // swdi: pointer to SWDIO captured data // return: none -void SWD_Sequence(uint8_t info, const uint8_t *swdo, uint8_t *swdi) +void SWD_Sequence(uint8_t info, const __xdata uint8_t *swdo, __xdata uint8_t *swdi) { uint8_t val; uint8_t bits; From 520fda06804c1bbc0ce4758dfbe87b2133d1ee42 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Tue, 23 Feb 2021 08:59:24 -0400 Subject: [PATCH 41/54] rm unused PDLen --- examples/CMSIS_DAP/USBconstant.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/examples/CMSIS_DAP/USBconstant.c b/examples/CMSIS_DAP/USBconstant.c index 8b922a7..6ea1744 100644 --- a/examples/CMSIS_DAP/USBconstant.c +++ b/examples/CMSIS_DAP/USBconstant.c @@ -104,8 +104,6 @@ __code uint16_t Prod_Des[]={ 'C','H','5','5','x',' ', 'C','M','S','I','S','-','D','A','P' }; -__sfr __at(sizeof(Prod_Des)) PDLen; - __code uint16_t Manuf_Des[]={ 0x0300 + sizeof(Manuf_Des), // type and length 'W','C','H' From be6af9b35c7df2021c09f9bd590d8b329eabe1fa Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Tue, 23 Feb 2021 21:04:55 -0400 Subject: [PATCH 42/54] simplified HID report descriptor --- examples/CMSIS_DAP/USBconstant.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/examples/CMSIS_DAP/USBconstant.c b/examples/CMSIS_DAP/USBconstant.c index 6ea1744..dc6a46f 100644 --- a/examples/CMSIS_DAP/USBconstant.c +++ b/examples/CMSIS_DAP/USBconstant.c @@ -74,16 +74,10 @@ __code uint8_t ReportDesc[] ={ 0x06, 0x00, 0xFF, // Usage Page = 0xFF00 (Vendor Defined Page 1) 0x09, 0x01, // Usage (Vendor Usage 1) 0xA1, 0x01, // Collection (Application) - 0x19, 0x01, // Usage Minimum - 0x29, 0x40, // Usage Maximum //64 input usages total (0x01 to 0x40) - 0x15, 0x00, // Logical Minimum (data bytes in the report may have minimum value = 0x00) - 0x26, 0xFF, 0x00, // Logical Maximum (data bytes in the report may have maximum value = 0x00FF = unsigned 255) 0x75, 0x08, // Report Size: 8-bit field size - 0x95, 0x40, // Report Count: Make sixty-four 8-bit fields (the next time the parser hits an "Input", "Output", or "Feature" item) - 0x81, 0x00, // Input (Data, Array, Abs): Instantiates input packet fields based on the above report size, count, logical min/max, and usage. - 0x19, 0x01, // Usage Minimum - 0x29, 0x40, // Usage Maximum //64 output usages total (0x01 to 0x40) - 0x91, 0x00, // Output (Data, Array, Abs): Instantiates output packet fields. Uses same report size and count as "Input" fields, since nothing new/different was specified to the parser since the "Input" item. + 0x95, 0x40, // Report Count: Make sixty-four fields + 0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear) + 0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear) 0xC0 // End Collection }; __code uint8_t ReportDescLen = sizeof(ReportDesc); From b917743573dc5a719b5c4aec5ed53142abcabe1b Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Wed, 24 Feb 2021 16:09:42 -0400 Subject: [PATCH 43/54] comment code not needed for CMSIS-DAP v1 --- examples/CMSIS_DAP/DAP.c | 53 +++++++++++++++++++++++++--------------- examples/CMSIS_DAP/DAP.h | 3 +-- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/examples/CMSIS_DAP/DAP.c b/examples/CMSIS_DAP/DAP.c index 6ddb02d..098b76e 100644 --- a/examples/CMSIS_DAP/DAP.c +++ b/examples/CMSIS_DAP/DAP.c @@ -31,8 +31,6 @@ __xdata uint8_t* DAP_RxBuf; __xdata uint8_t* DAP_TxBuf; -// TODO: change all uint8_t* to __xdata - // Get DAP Information // id: info identifier // info: pointer to info data @@ -43,38 +41,37 @@ static uint8_t DAP_Info(uint8_t id, __xdata uint8_t *info) switch (id) { + /* case DAP_ID_VENDOR: - break; case DAP_ID_PRODUCT: - break; case DAP_ID_SER_NUM: - break; + */ case DAP_ID_FW_VER: length = (uint8_t)sizeof(DAP_FW_VER); strcpy(info, DAP_FW_VER ); break; + /* case DAP_ID_DEVICE_VENDOR: - break; case DAP_ID_DEVICE_NAME: - break; + */ case DAP_ID_CAPABILITIES: info[0] = DAP_PORT_SWD; length = 1U; break; + /* case DAP_ID_TIMESTAMP_CLOCK: - break; case DAP_ID_SWO_BUFFER_SIZE: - break; + */ case DAP_ID_PACKET_SIZE: - info[0] = (uint8_t)(DAP_PACKET_SIZE >> 0); - info[1] = (uint8_t)(DAP_PACKET_SIZE >> 8); + info[0] = DAP_PACKET_SIZE; + info[1] = 0; length = 2U; break; case DAP_ID_PACKET_COUNT: @@ -92,6 +89,7 @@ static uint8_t DAP_Info(uint8_t id, __xdata uint8_t *info) // request: pointer to request data // response: pointer to response data // return: number of bytes in response +#if 0 static uint8_t DAP_Delay(const __xdata uint8_t *req, __xdata uint8_t *res) { uint16_t delay; @@ -106,6 +104,7 @@ static uint8_t DAP_Delay(const __xdata uint8_t *req, __xdata uint8_t *res) *res = DAP_OK; return 1; } +#endif // Process Host Status command and prepare response // request: pointer to request data @@ -113,6 +112,7 @@ static uint8_t DAP_Delay(const __xdata uint8_t *req, __xdata uint8_t *res) // return: number of bytes in response static uint8_t DAP_HostStatus(const __xdata uint8_t *req, __xdata uint8_t *res) { + *res = DAP_OK; switch (*req) { @@ -124,10 +124,8 @@ static uint8_t DAP_HostStatus(const __xdata uint8_t *req, __xdata uint8_t *res) break; default: *res = DAP_ERROR; - return 1; } - *res = DAP_OK; return 1; } @@ -170,23 +168,25 @@ static uint8_t DAP_Connect(const __xdata uint8_t *req, __xdata uint8_t *res) #define PORT_OFF() PORT_SWD_SETUP() static uint8_t DAP_Disconnect(__xdata uint8_t *res) { + *res = DAP_OK; debug_port = DAP_PORT_DISABLED; PORT_OFF(); - *res = DAP_OK; return (1U); } // Process Reset Target command and prepare response // response: pointer to response data // return: number of bytes in response +#if 0 static uint8_t DAP_ResetTarget(__xdata uint8_t *res) { - *(res + 1) = 0; //RESET_TARGET(); - *(res + 0) = DAP_OK; + *res++ = DAP_OK; + *res = 0; // target-specific reset unimplmented return 2; } +#endif // Process SWJ Pins command and prepare response // request: pointer to request data @@ -301,8 +301,8 @@ static uint8_t DAP_SWJ_Sequence(const __xdata uint8_t *req, __xdata uint8_t *res } SWJ_Sequence(count, req); - *res = DAP_OK; + *res = DAP_OK; return 1; } @@ -310,6 +310,8 @@ static uint8_t DAP_SWJ_Sequence(const __xdata uint8_t *req, __xdata uint8_t *res // request: pointer to request data // response: pointer to response data // return: number of bytes in response +// turnaround is always 1, dataphase default false +#if 0 __idata uint8_t turnaround; __idata uint8_t data_phase; static uint8_t DAP_SWD_Configure(const __xdata uint8_t *req, __xdata uint8_t *res) @@ -323,6 +325,7 @@ static uint8_t DAP_SWD_Configure(const __xdata uint8_t *req, __xdata uint8_t *re *res = DAP_OK; return 1; } +#endif // Process SWD Sequence command and prepare response // request: pointer to request data @@ -858,6 +861,7 @@ static uint8_t DAP_TransferBlock(const __xdata uint8_t *req, __xdata uint8_t *re // request: pointer to request data // response: pointer to response data // return: number of bytes in response +#if 0 static uint8_t DAP_SWD_WriteAbort(const __xdata uint8_t *req, __xdata uint8_t *res) { // Load data (Ignore DAP index) @@ -872,11 +876,14 @@ static uint8_t DAP_SWD_WriteAbort(const __xdata uint8_t *req, __xdata uint8_t *r *res = DAP_OK; return (1U); } +#endif // Process Write ABORT command and prepare response // request: pointer to request data // response: pointer to response data // return: number of bytes in response +// unused by pyOCD and openocd - not required in CMSIS-DAP v1? +#if 0 static uint8_t DAP_WriteAbort(const __xdata uint8_t *req, __xdata uint8_t *res) { uint8_t num; @@ -894,10 +901,12 @@ static uint8_t DAP_WriteAbort(const __xdata uint8_t *req, __xdata uint8_t *res) } return num; } +#endif // DAP Thread. uint8_t DAP_Thread(uint8_t __xdata *req) { +#define DAP_Res_OK() *res = DAP_OK; num = 1 uint8_t num; uint8_t returnVal = 0; @@ -931,7 +940,8 @@ uint8_t DAP_Thread(uint8_t __xdata *req) case ID_DAP_Disconnect: num = DAP_Disconnect(res); break; - +#if 0 + // DAP_Delay not required in CMSIS-DAP v1 case ID_DAP_Delay: num = DAP_Delay(req, res); break; @@ -939,6 +949,7 @@ uint8_t DAP_Thread(uint8_t __xdata *req) case ID_DAP_ResetTarget: num = DAP_ResetTarget(res); break; +#endif case ID_DAP_SWJ_Pins: num = DAP_SWJ_Pins(req, res); @@ -953,7 +964,8 @@ uint8_t DAP_Thread(uint8_t __xdata *req) break; case ID_DAP_SWD_Configure: - num = DAP_SWD_Configure(req, res); + // no-op + DAP_Res_OK(); break; case ID_DAP_SWD_Sequence: @@ -965,7 +977,8 @@ uint8_t DAP_Thread(uint8_t __xdata *req) break; case ID_DAP_WriteABORT: - num = DAP_WriteAbort(req, res); + // no-op + DAP_Res_OK(); break; case ID_DAP_ExecuteCommands: diff --git a/examples/CMSIS_DAP/DAP.h b/examples/CMSIS_DAP/DAP.h index b1b7740..b4007f2 100644 --- a/examples/CMSIS_DAP/DAP.h +++ b/examples/CMSIS_DAP/DAP.h @@ -238,8 +238,7 @@ extern __xdata uint8_t Ep2Buffer[]; extern __xdata uint8_t* DAP_RxBuf; extern __xdata uint8_t* DAP_TxBuf; -extern __idata uint8_t turnaround; -extern __idata uint8_t data_phase; +#define data_phase 0 extern __idata uint8_t idle_cycles; extern uint8_t DAP_Thread(__xdata uint8_t* req); From f04b5d9b7d7cbfc76fd3c001ea6c2877dd9f7811 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Wed, 24 Feb 2021 17:55:38 -0400 Subject: [PATCH 44/54] rm more unused code --- examples/CMSIS_DAP/DAP.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/examples/CMSIS_DAP/DAP.c b/examples/CMSIS_DAP/DAP.c index 098b76e..93b3652 100644 --- a/examples/CMSIS_DAP/DAP.c +++ b/examples/CMSIS_DAP/DAP.c @@ -106,7 +106,7 @@ static uint8_t DAP_Delay(const __xdata uint8_t *req, __xdata uint8_t *res) } #endif -// Process Host Status command and prepare response +// Process Host Status AKA DAP_LED command and prepare response // request: pointer to request data // response: pointer to response data // return: number of bytes in response @@ -279,12 +279,14 @@ static uint8_t DAP_SWJ_Pins(const __xdata uint8_t *req, __xdata uint8_t *res) // request: pointer to request data // response: pointer to response data // return: number of bytes in response +#if 0 static uint8_t DAP_SWJ_Clock(const __xdata uint8_t *req, __xdata uint8_t *res) { req; *res = DAP_OK; return 1; } +#endif // Process SWJ Sequence command and prepare response // request: pointer to request data @@ -704,6 +706,7 @@ static uint8_t DAP_SWD_Transfer(const __xdata uint8_t *req, __xdata uint8_t *res // request: pointer to request data // response: pointer to response data // return: number of bytes in response +#if 0 static uint8_t DAP_Transfer(const __xdata uint8_t *req, __xdata uint8_t *res) { uint8_t num = 0; @@ -720,6 +723,7 @@ static uint8_t DAP_Transfer(const __xdata uint8_t *req, __xdata uint8_t *res) return (num); } +#endif // Process SWD Transfer Block command and prepare response // request: pointer to request data @@ -916,7 +920,8 @@ uint8_t DAP_Thread(uint8_t __xdata *req) switch (*req++) { case ID_DAP_Transfer: - num = DAP_Transfer(req, res); + // num = DAP_Transfer(req, res); + num = DAP_SWD_Transfer(req, res); break; case ID_DAP_TransferBlock: @@ -956,7 +961,8 @@ uint8_t DAP_Thread(uint8_t __xdata *req) break; case ID_DAP_SWJ_Clock: - num = DAP_SWJ_Clock(req, res); + // no-op + DAP_Res_OK(); break; case ID_DAP_SWJ_Sequence: From b668c6c9e4752ad56acb7047cd2537b87a4cfc7d Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Mon, 1 Mar 2021 15:24:28 -0400 Subject: [PATCH 45/54] let SDCC allocate xram data --- examples/CMSIS_DAP/Makefile | 1 + examples/CMSIS_DAP/USBconstant.h | 4 ---- examples/CMSIS_DAP/USBhandler.c | 8 ++++---- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/examples/CMSIS_DAP/Makefile b/examples/CMSIS_DAP/Makefile index fbe5f9e..6db2780 100644 --- a/examples/CMSIS_DAP/Makefile +++ b/examples/CMSIS_DAP/Makefile @@ -7,6 +7,7 @@ FREQ_SYS = 16000000 XRAM_SIZE = 0x0300 XRAM_LOC = 0x0100 +# no initialized data in xram EXTRA_FLAGS = --no-xinit-opt C_FILES = \ diff --git a/examples/CMSIS_DAP/USBconstant.h b/examples/CMSIS_DAP/USBconstant.h index 43f3414..4da43d4 100644 --- a/examples/CMSIS_DAP/USBconstant.h +++ b/examples/CMSIS_DAP/USBconstant.h @@ -4,10 +4,6 @@ #include #include -#define EP0_ADDR 0 -#define EP1_ADDR 10 -#define EP2_ADDR 138 - extern __code USB_DEV_DESCR DevDesc; extern __code uint8_t CfgDesc[]; extern __code uint8_t ReportDesc[]; diff --git a/examples/CMSIS_DAP/USBhandler.c b/examples/CMSIS_DAP/USBhandler.c index c858a83..bc0869c 100644 --- a/examples/CMSIS_DAP/USBhandler.c +++ b/examples/CMSIS_DAP/USBhandler.c @@ -10,9 +10,9 @@ void USB_EP2_IN(); void USB_EP1_OUT(); //on page 47 of data sheet, the receive buffer need to be min(possible packet size+2,64) -__xdata __at (EP0_ADDR) uint8_t Ep0Buffer[8]; -__xdata __at (EP1_ADDR) uint8_t Ep1Buffer[128]; // EP1 OUT*2 -__xdata __at (EP2_ADDR) uint8_t Ep2Buffer[64]; +__xdata uint8_t Ep0Buffer[DEFAULT_ENDP0_SIZE + 2]; +__xdata uint8_t Ep1Buffer[128]; // EP1 OUT*2 +__xdata uint8_t Ep2Buffer[64]; uint8_t SetupLen; uint8_t SetupReq,UsbConfig; @@ -138,7 +138,7 @@ void USB_EP0_Setup(){ } len = pDescr[0]; break; - case 0x22: + case USB_DESCR_TYP_REPORT: if(UsbSetupBuf->wValueL == 0){ pDescr = ReportDesc; len = ReportDescLen; From f7e6dd02fe7d49154b93bfd2e97d79b173454167 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Mon, 1 Mar 2021 15:28:58 -0400 Subject: [PATCH 46/54] rm unused data_phase --- examples/CMSIS_DAP/SW_DP.c | 22 +++------------------- 1 file changed, 3 insertions(+), 19 deletions(-) diff --git a/examples/CMSIS_DAP/SW_DP.c b/examples/CMSIS_DAP/SW_DP.c index fa5ec52..2288586 100644 --- a/examples/CMSIS_DAP/SW_DP.c +++ b/examples/CMSIS_DAP/SW_DP.c @@ -234,33 +234,17 @@ uint8_t SWD_Transfer(uint8_t req, __xdata uint8_t *data) } } SWD = 1; - return ((uint8_t)ack); + return (ack); } if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { - /* WAIT or FAULT res */ - if (data_phase && ((req & DAP_TRANSFER_RnW) != 0U)) - { - for (n = 32U + 1U; n; n--) - { - SW_CLOCK_CYCLE(); /* Dummy Read RDATA[0:31] + Parity */ - } - } /* Turnaround */ SW_CLOCK_CYCLE(); SWD_OUT_ENABLE(); - if (data_phase && ((req & DAP_TRANSFER_RnW) == 0U)) - { - SWD = 0; - for (n = 32U + 1U; n; n--) - { - SW_CLOCK_CYCLE(); /* Dummy Write WDATA[0:31] + Parity */ - } - } SWD = 1; - return ((uint8_t)ack); + return (ack); } /* Protocol error - clock out 32bits + parity + turnaround */ @@ -271,5 +255,5 @@ uint8_t SWD_Transfer(uint8_t req, __xdata uint8_t *data) SWD_OUT_ENABLE(); SWD = 1; - return ((uint8_t)ack); + return (ack); } From 4ca46bd128cddb585189e1c153a46059ae70b55f Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Mon, 1 Mar 2021 19:49:18 -0400 Subject: [PATCH 47/54] expand report descriptor for better Windows compatibility --- examples/CMSIS_DAP/USBconstant.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/examples/CMSIS_DAP/USBconstant.c b/examples/CMSIS_DAP/USBconstant.c index dc6a46f..7702335 100644 --- a/examples/CMSIS_DAP/USBconstant.c +++ b/examples/CMSIS_DAP/USBconstant.c @@ -66,18 +66,33 @@ __code uint8_t CfgDesc[] ={ USB_ENDP_TYPE_INTER, // bmAttributes 0x40, 0x00, // wMaxPacketSize 1, // bInterval - }; __code uint8_t CfgDescLen = sizeof(CfgDesc); +#if 0 +__code struct { + USB_CFG_DESCR config; +} ConfigDescriptor; +#endif + __code uint8_t ReportDesc[] ={ 0x06, 0x00, 0xFF, // Usage Page = 0xFF00 (Vendor Defined Page 1) + // USB-IF HID tool says vendor usage not required, but Win7 needs it 0x09, 0x01, // Usage (Vendor Usage 1) 0xA1, 0x01, // Collection (Application) - 0x75, 0x08, // Report Size: 8-bit field size - 0x95, 0x40, // Report Count: Make sixty-four fields - 0x81, 0x01, // Input (Const,Array,Abs,No Wrap,Linear) - 0x91, 0x01, // Output (Const,Array,Abs,No Wrap,Linear) + 0x25, 0x00, // Logical minimum + 0x25, 64, // Logical maximum + 0x75, 0x08, // Report Size: 8-bit field size + 0x95, 64, // Report Count: Make 64 fields + + // Input Report + 0x09, 0x01, // Usage (Vendor Usage 1) + 0x81, 0x02, // Input (Data,Var,Abs,No Wrap,Linear) + + // Output Report + 0x09, 0x01, // Usage (Vendor Usage 1) + 0x91, 0x02, // Output (Data,Var,Abs,No Wrap,Linear) + 0xC0 // End Collection }; __code uint8_t ReportDescLen = sizeof(ReportDesc); @@ -106,6 +121,6 @@ __code uint16_t Manuf_Des[]={ // Serial string descriptor - CMSIS-DAP unique ID __code uint16_t Ser_Des[]={ 0x0300 + sizeof(Ser_Des), // type and length - '1','2','3' + 'N','R' }; From c5816a0554b3f81d7bf98026f68a9333ec1a4a60 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Tue, 2 Mar 2021 16:37:57 -0400 Subject: [PATCH 48/54] cleanup USB init --- examples/CMSIS_DAP/USBconstant.c | 2 +- examples/CMSIS_DAP/USBhandler.c | 36 +++++++++++++++----------------- examples/CMSIS_DAP/USBhandler.h | 4 +--- examples/CMSIS_DAP/main.c | 13 +++++------- 4 files changed, 24 insertions(+), 31 deletions(-) diff --git a/examples/CMSIS_DAP/USBconstant.c b/examples/CMSIS_DAP/USBconstant.c index 7702335..c7d3a79 100644 --- a/examples/CMSIS_DAP/USBconstant.c +++ b/examples/CMSIS_DAP/USBconstant.c @@ -29,7 +29,7 @@ __code uint8_t CfgDesc[] ={ 0x01, /* bConfigurationValue */ 0x00, /* iConfiguration */ 0x80, /* bmAttributes */ - 0x64, /* MaxPower */ + 50, /* MaxPower in 2mA units */ // HID interface descriptor 0x09, // bLength diff --git a/examples/CMSIS_DAP/USBhandler.c b/examples/CMSIS_DAP/USBhandler.c index bc0869c..068d618 100644 --- a/examples/CMSIS_DAP/USBhandler.c +++ b/examples/CMSIS_DAP/USBhandler.c @@ -414,7 +414,7 @@ void USBInterrupt(void) { //inline not really working in multiple files in SDC break; } - UIF_TRANSFER = 0; // Clear interrupt flag + UIF_TRANSFER = 0; // Clear interrupt flag } // Device mode USB bus reset @@ -424,7 +424,7 @@ void USBInterrupt(void) { //inline not really working in multiple files in SDC UEP2_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK; //Endpoint 2 automatically flips the sync flag, IN transaction returns NAK, OUT returns ACK //UEP4_CTRL = UEP_T_RES_NAK | UEP_R_RES_ACK; //bUEP_AUTO_TOG only work for endpoint 1,2,3 - USB_DEV_AD = 0x00; + USB_DEV_AD = 0; UIF_SUSPEND = 0; UIF_TRANSFER = 0; UIF_BUS_RST = 0; // Clear interrupt flag @@ -443,31 +443,25 @@ void USBInterrupt(void) { //inline not really working in multiple files in SDC } #pragma restore -void USBDeviceCfg() +void USBDeviceSetup() { - USB_CTRL = 0x00; //Clear USB control register - USB_CTRL &= ~bUC_HOST_MODE; //This bit is the device selection mode - USB_CTRL |= bUC_DEV_PU_EN | bUC_INT_BUSY | bUC_DMA_EN; //USB device and internal pull-up enable, automatically return to NAK before interrupt flag is cleared during interrupt - USB_DEV_AD = 0x00; //Device address initialization - UDEV_CTRL &= ~bUD_LOW_SPEED; //Select full speed 12M mode, default mode - UDEV_CTRL = bUD_PD_DIS; // Disable DP/DM pull-down resistor - UDEV_CTRL |= bUD_PORT_EN; //Enable physical port -} + //USB internal pull-up enable, return NAK if USB INT flag not clear + USB_CTRL = bUC_DEV_PU_EN | bUC_INT_BUSY | bUC_DMA_EN; -void USBDeviceIntCfg() -{ - USB_INT_EN |= bUIE_SUSPEND; //Enable device hang interrupt + // enable port, full-speed, disable UDP/UDM pulldown resistor + UDEV_CTRL = bUD_PD_DIS | bUD_PORT_EN; + + // configure interrupts + // USB_INT_EN |= bUIE_SUSPEND; //Enable device hang interrupt USB_INT_EN |= bUIE_TRANSFER; //Enable USB transfer completion interrupt USB_INT_EN |= bUIE_BUS_RST; //Enable device mode USB bus reset interrupt USB_INT_FG |= 0x1F; //Clear interrupt flag IE_USB = 1; //Enable USB interrupt EA = 1; //Enable global interrupts -} -void USBDeviceEndPointCfg() -{ - UEP1_DMA = (uint16_t) Ep1Buffer; //Endpoint 1 data transfer address - UEP2_DMA = (uint16_t) Ep2Buffer; //Endpoint 1 data transfer address + // configure endpoints + UEP1_DMA = (uint16_t) Ep1Buffer; //Endpoint data transfer address + UEP2_DMA = (uint16_t) Ep2Buffer; //Endpoint data transfer address UEP1_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_ACK; //Endpoint 1 automatically flips the sync flag, IN transaction returns NAK, OUT returns ACK UEP2_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK | UEP_R_RES_NAK; //Endpoint 2 automatically flips the sync flag, IN & OUT transaction returns NAK @@ -476,4 +470,8 @@ void USBDeviceEndPointCfg() UEP4_1_MOD = bUEP1_RX_EN; UEP2_3_MOD = bUEP2_TX_EN; UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; //Manual flip, OUT transaction returns ACK, IN transaction returns NAK + + UEP0_T_LEN = 0; + UEP1_T_LEN = 0; + UEP2_T_LEN = 0; } diff --git a/examples/CMSIS_DAP/USBhandler.h b/examples/CMSIS_DAP/USBhandler.h index 17d0e06..a9d1e12 100644 --- a/examples/CMSIS_DAP/USBhandler.h +++ b/examples/CMSIS_DAP/USBhandler.h @@ -13,9 +13,7 @@ #define EP0_IN_Callback USB_EP0_IN void USBInterrupt(void); -void USBDeviceCfg(); -void USBDeviceIntCfg(); -void USBDeviceEndPointCfg(); +void USBDeviceSetup(); #endif diff --git a/examples/CMSIS_DAP/main.c b/examples/CMSIS_DAP/main.c index 9c9429f..7a9ab04 100644 --- a/examples/CMSIS_DAP/main.c +++ b/examples/CMSIS_DAP/main.c @@ -29,12 +29,8 @@ volatile uint8_t EP1_buffs_avail = 2; __bit EP1_buf_toggle = 0; void USBInit(){ - USBDeviceCfg(); //Device mode configuration - USBDeviceEndPointCfg(); //Endpoint configuration - USBDeviceIntCfg(); //Interrupt configuration - UEP0_T_LEN = 0; - UEP1_T_LEN = 0; - UEP2_T_LEN = 0; + USBDeviceSetup(); + // single Tx buffer for DAP replies DAP_TxBuf = (__xdata uint8_t*) UEP2_DMA; } @@ -65,7 +61,7 @@ void USB_EP1_OUT(){ // perform USB bus reset/disconnect // set UDP to GPIO mode and hold low for device disconnect -inline void resetUSB() +inline void disconnectUSB() { PIN_FUNC &= ~(bUSB_IO_EN); UDP = 0; @@ -75,9 +71,10 @@ inline void resetUSB() } void main() { - resetUSB(); CfgFsys(); + disconnectUSB(); USBInit(); + LED = 0; while (1) { uint8_t response_len; // process if a DAP packet is received, and TxBuf is empty From 9f6e1fd7b60502d56fcbdbc7c0e1f5b7c7dfced4 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Tue, 2 Mar 2021 17:45:38 -0400 Subject: [PATCH 49/54] add disconnectUSB() --- include/debug.h | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/include/debug.h b/include/debug.h index d662be0..c5efe30 100644 --- a/include/debug.h +++ b/include/debug.h @@ -210,3 +210,14 @@ inline void CH554WDTFeed(uint8_t tim) WDOG_COUNT = tim; // Watchdog counter assignment } + +// perform USB bus reset/disconnect +// set UDP to GPIO mode and hold low for device disconnect +inline void disconnectUSB() +{ + PIN_FUNC &= ~(bUSB_IO_EN); + UDP = 0; + mDelaymS(50); + UDP = 1; + PIN_FUNC |= bUSB_IO_EN; +} From a80809374641813d1d0778f5f2b6aa12bd37220a Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Tue, 2 Mar 2021 17:49:40 -0400 Subject: [PATCH 50/54] move disconnectUSB() to debug.h --- examples/CMSIS_DAP/main.c | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/examples/CMSIS_DAP/main.c b/examples/CMSIS_DAP/main.c index 7a9ab04..3d4dd4a 100644 --- a/examples/CMSIS_DAP/main.c +++ b/examples/CMSIS_DAP/main.c @@ -59,17 +59,6 @@ void USB_EP1_OUT(){ } } -// perform USB bus reset/disconnect -// set UDP to GPIO mode and hold low for device disconnect -inline void disconnectUSB() -{ - PIN_FUNC &= ~(bUSB_IO_EN); - UDP = 0; - mDelaymS(50); - UDP = 1; - PIN_FUNC |= bUSB_IO_EN; -} - void main() { CfgFsys(); disconnectUSB(); From ef8ba42083fa7aff83429265d84aa7e455825365 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Wed, 3 Mar 2021 21:32:32 -0400 Subject: [PATCH 51/54] cleanup config descriptor --- examples/CMSIS_DAP/DAP.h | 2 +- examples/CMSIS_DAP/USBconstant.c | 70 +++++++++++++++++++++++++++++--- examples/CMSIS_DAP/USBhandler.c | 11 ++--- 3 files changed, 69 insertions(+), 14 deletions(-) diff --git a/examples/CMSIS_DAP/DAP.h b/examples/CMSIS_DAP/DAP.h index b4007f2..bc9ffd5 100644 --- a/examples/CMSIS_DAP/DAP.h +++ b/examples/CMSIS_DAP/DAP.h @@ -197,7 +197,7 @@ #define SWD_SEQUENCE_DIN 0x80U // SWDIO capture #define DAP_PACKET_COUNT 2 -#define DAP_PACKET_SIZE 64 //THIS_ENDP0_SIZE +#define DAP_PACKET_SIZE 64 // THIS ENDP SIZE #define DAP_DEFAULT_PORT DAP_PORT_SWD // if port defines are changed, also modify MOD_OC and DIR_PU settings diff --git a/examples/CMSIS_DAP/USBconstant.c b/examples/CMSIS_DAP/USBconstant.c index c7d3a79..3a881a7 100644 --- a/examples/CMSIS_DAP/USBconstant.c +++ b/examples/CMSIS_DAP/USBconstant.c @@ -2,7 +2,7 @@ #include #include -#include "USBconstant.h" +#include "config.h" //Device descriptor @@ -23,6 +23,7 @@ __code USB_DEV_DESCR DevDesc = { .bNumConfigurations = 1 }; +#if 0 __code uint8_t CfgDesc[] ={ 0x09,0x02,sizeof(CfgDesc) & 0xff,sizeof(CfgDesc) >> 8, 0x01, /* bNumInterfaces */ @@ -67,13 +68,70 @@ __code uint8_t CfgDesc[] ={ 0x40, 0x00, // wMaxPacketSize 1, // bInterval }; +#endif + __code uint8_t CfgDescLen = sizeof(CfgDesc); -#if 0 __code struct { USB_CFG_DESCR config; -} ConfigDescriptor; -#endif + USB_ITF_DESCR interface; + USB_HID_DESCR hid; + USB_ENDP_DESCR ep2IN; + USB_ENDP_DESCR ep1OUT; +} CfgDesc = { + .config = { + .bLength = sizeof(USB_CFG_DESCR), + .bDescriptorType = USB_DESCR_TYP_CONFIG, + .wTotalLengthL = sizeof(CfgDesc), + .wTotalLengthH = 0, + .bNumInterfaces = 1, + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = 0x80, + .MaxPower = 50 // 2mA units + }, + .interface = { + .bLength = sizeof(USB_ITF_DESCR), + .bDescriptorType = USB_DESCR_TYP_INTERF, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_DEV_CLASS_HID, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0, // no interface string + + }, + .hid = { + .bLength = sizeof(USB_HID_DESCR), + .bDescriptorType = USB_DESCR_TYP_HID, + .bcdHIDH = 0x01, // HID class version + .bcdHIDL = 0x10, + .bCountryCode = 0, + .bNumDescriptors = 1, + .bDescriptorTypeX = USB_DESCR_TYP_REPORT, + .wDescriptorLengthL = sizeof(ReportDesc), + .wDescriptorLengthH = 0, + }, + .ep2IN = { + .bLength = sizeof(USB_ENDP_DESCR), + .bDescriptorType = USB_DESCR_TYP_ENDP, + .bEndpointAddress = 0x82, // EP2 IN + .bmAttributes = USB_ENDP_TYPE_INTER, + .wMaxPacketSizeL = HID_PKT_SIZ, + .wMaxPacketSizeH = 0, + .bInterval = 1, // poll every 1 ms + }, + .ep1OUT = { + .bLength = sizeof(USB_ENDP_DESCR), + .bDescriptorType = USB_DESCR_TYP_ENDP, + .bEndpointAddress = 0x01, // EP1 IN + .bmAttributes = USB_ENDP_TYPE_INTER, + .wMaxPacketSizeL = HID_PKT_SIZ, + .wMaxPacketSizeH = 0, + .bInterval = 1, // poll every 1 ms + } +}; __code uint8_t ReportDesc[] ={ 0x06, 0x00, 0xFF, // Usage Page = 0xFF00 (Vendor Defined Page 1) @@ -81,9 +139,9 @@ __code uint8_t ReportDesc[] ={ 0x09, 0x01, // Usage (Vendor Usage 1) 0xA1, 0x01, // Collection (Application) 0x25, 0x00, // Logical minimum - 0x25, 64, // Logical maximum + 0x25, HID_PKT_SIZ, // Logical maximum 0x75, 0x08, // Report Size: 8-bit field size - 0x95, 64, // Report Count: Make 64 fields + 0x95, HID_PKT_SIZ, // Report Count: Make 64 fields // Input Report 0x09, 0x01, // Usage (Vendor Usage 1) diff --git a/examples/CMSIS_DAP/USBhandler.c b/examples/CMSIS_DAP/USBhandler.c index 068d618..c48018f 100644 --- a/examples/CMSIS_DAP/USBhandler.c +++ b/examples/CMSIS_DAP/USBhandler.c @@ -4,6 +4,7 @@ #include #include "USBhandler.h" #include "USBconstant.h" +#include "config.h" //HID functions: void USB_EP2_IN(); @@ -11,8 +12,8 @@ void USB_EP1_OUT(); //on page 47 of data sheet, the receive buffer need to be min(possible packet size+2,64) __xdata uint8_t Ep0Buffer[DEFAULT_ENDP0_SIZE + 2]; -__xdata uint8_t Ep1Buffer[128]; // EP1 OUT*2 -__xdata uint8_t Ep2Buffer[64]; +__xdata uint8_t Ep1Buffer[HID_PKT_SIZ * 2]; // EP1 OUT*2 +__xdata uint8_t Ep2Buffer[HID_PKT_SIZ]; uint8_t SetupLen; uint8_t SetupReq,UsbConfig; @@ -119,24 +120,20 @@ void USB_EP0_Setup(){ if(UsbSetupBuf->wValueL == 0) { pDescr = LangDes; - // len = LangDesLen; } else if(UsbSetupBuf->wValueL == 1) { pDescr = Manuf_Des; - //len = Manuf_DesLen; } else if(UsbSetupBuf->wValueL == 2) { pDescr = Prod_Des; - //len = Prod_DesLen; } else { pDescr = Ser_Des; - //len = Ser_DesLen; } - len = pDescr[0]; + len = pDescr[0]; // bLength break; case USB_DESCR_TYP_REPORT: if(UsbSetupBuf->wValueL == 0){ From 62bf72826170c903f3636ba6af52c41e72c6b813 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Wed, 3 Mar 2021 21:58:57 -0400 Subject: [PATCH 52/54] global config --- examples/CMSIS_DAP/config.h | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 examples/CMSIS_DAP/config.h diff --git a/examples/CMSIS_DAP/config.h b/examples/CMSIS_DAP/config.h new file mode 100644 index 0000000..ba6a050 --- /dev/null +++ b/examples/CMSIS_DAP/config.h @@ -0,0 +1,3 @@ + +#define HID_PKT_SIZ 64 + From fbae536c0ffbfde9ce6e22eedc7c125a35c3a8cd Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Thu, 4 Mar 2021 09:24:59 -0400 Subject: [PATCH 53/54] correct logical maximum to 255 --- examples/CMSIS_DAP/USBconstant.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/CMSIS_DAP/USBconstant.c b/examples/CMSIS_DAP/USBconstant.c index 3a881a7..0a1fad9 100644 --- a/examples/CMSIS_DAP/USBconstant.c +++ b/examples/CMSIS_DAP/USBconstant.c @@ -138,8 +138,8 @@ __code uint8_t ReportDesc[] ={ // USB-IF HID tool says vendor usage not required, but Win7 needs it 0x09, 0x01, // Usage (Vendor Usage 1) 0xA1, 0x01, // Collection (Application) - 0x25, 0x00, // Logical minimum - 0x25, HID_PKT_SIZ, // Logical maximum + 0x25, 0x00, // Logical minimum value 0 + 0x25, 0xFF, // Logical maximum value 255 0x75, 0x08, // Report Size: 8-bit field size 0x95, HID_PKT_SIZ, // Report Count: Make 64 fields From 145ec7f4e7aa3fc3ccdb4b1697caa6c3d74219a1 Mon Sep 17 00:00:00 2001 From: Nerd Ralph Date: Sat, 6 Mar 2021 23:20:40 -0400 Subject: [PATCH 54/54] fix logical minimum ID --- examples/CMSIS_DAP/USBconstant.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/CMSIS_DAP/USBconstant.c b/examples/CMSIS_DAP/USBconstant.c index 0a1fad9..e709cc6 100644 --- a/examples/CMSIS_DAP/USBconstant.c +++ b/examples/CMSIS_DAP/USBconstant.c @@ -86,7 +86,7 @@ __code struct { .wTotalLengthH = 0, .bNumInterfaces = 1, .bConfigurationValue = 1, - .iConfiguration = 0, + .iConfiguration = 0, // string index .bmAttributes = 0x80, .MaxPower = 50 // 2mA units }, @@ -138,7 +138,7 @@ __code uint8_t ReportDesc[] ={ // USB-IF HID tool says vendor usage not required, but Win7 needs it 0x09, 0x01, // Usage (Vendor Usage 1) 0xA1, 0x01, // Collection (Application) - 0x25, 0x00, // Logical minimum value 0 + 0x15, 0x00, // Logical minimum value 0 0x25, 0xFF, // Logical maximum value 255 0x75, 0x08, // Report Size: 8-bit field size 0x95, HID_PKT_SIZ, // Report Count: Make 64 fields