From c13abd3e00f2cfbb4267f9a6153ff69c38f4cecc Mon Sep 17 00:00:00 2001 From: sabas1080 Date: Sat, 29 Aug 2020 22:02:10 -0500 Subject: [PATCH] Added firmware for Electronic Cats hardware --- .gitignore | 8 + firmware/CMSIS_DAP.ino | 42 + firmware/src/CMSIS_DAPusb/DAP.c | 1048 +++++++++++++++++++++++ firmware/src/CMSIS_DAPusb/DAP.h | 222 +++++ firmware/src/CMSIS_DAPusb/SW_DP.c | 307 +++++++ firmware/src/CMSIS_DAPusb/USBHID.c | 37 + firmware/src/CMSIS_DAPusb/USBHID.h | 19 + firmware/src/CMSIS_DAPusb/USBconstant.c | 107 +++ firmware/src/CMSIS_DAPusb/USBconstant.h | 28 + firmware/src/CMSIS_DAPusb/USBhandler.c | 481 +++++++++++ firmware/src/CMSIS_DAPusb/USBhandler.h | 58 ++ 11 files changed, 2357 insertions(+) create mode 100644 firmware/CMSIS_DAP.ino create mode 100644 firmware/src/CMSIS_DAPusb/DAP.c create mode 100644 firmware/src/CMSIS_DAPusb/DAP.h create mode 100644 firmware/src/CMSIS_DAPusb/SW_DP.c create mode 100644 firmware/src/CMSIS_DAPusb/USBHID.c create mode 100644 firmware/src/CMSIS_DAPusb/USBHID.h create mode 100644 firmware/src/CMSIS_DAPusb/USBconstant.c create mode 100644 firmware/src/CMSIS_DAPusb/USBconstant.h create mode 100644 firmware/src/CMSIS_DAPusb/USBhandler.c create mode 100644 firmware/src/CMSIS_DAPusb/USBhandler.h diff --git a/.gitignore b/.gitignore index 853ee63..dc88843 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,11 @@ fp-info-cache # Exported BOM files *.xml *.csv + +.DS_Store + +hardware/fp-lib-table + +hardware/sym-lib-table + +*.dcm diff --git a/firmware/CMSIS_DAP.ino b/firmware/CMSIS_DAP.ino new file mode 100644 index 0000000..87e15bc --- /dev/null +++ b/firmware/CMSIS_DAP.ino @@ -0,0 +1,42 @@ +/* + CMSIS_DAP + + Modified form ljbfly's implementation, working but a lot to improve + RST -> P30 + SWCLK -> P31 + SWDIO -> P32 + These pins works in OC mode with pull-up resistor (70K). Should be safe to connect 3.3V part. + + created 2020 + by Deqing Sun for use with CH55xduino + + This example code is in the public domain. + +*/ + + +#ifndef USER_USB_RAM +#error "This example needs to be compiled with a USER USB setting" +#endif + +#include "src/CMSIS_DAPusb/DAP.h" + + +extern volatile __xdata uint8_t USBByteCountEP1; + + +void setup() { + USBInit(); +} + +void loop() { + 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 + } +} diff --git a/firmware/src/CMSIS_DAPusb/DAP.c b/firmware/src/CMSIS_DAPusb/DAP.c new file mode 100644 index 0000000..e303abf --- /dev/null +++ b/firmware/src/CMSIS_DAPusb/DAP.c @@ -0,0 +1,1048 @@ +/* + * 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 datas +// return: number of bytes in info datas +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 datas +// response: pointer to response datas +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +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 datas +// response: pointer to response datas +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +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 datas +// response: pointer to response datas +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +__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 = (uint8_t)port; + return 1; +} + +// Process Disconnect command and prepare response +// response: pointer to response datas +// 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 datas +// 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 datas +// response: pointer to response datas +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +static uint8_t DAP_SWJ_Pins(const uint8_t *req, uint8_t *res) +{ + uint8_t value; + uint8_t select; + uint16_t wait; + + value = (uint8_t) * (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 = (uint8_t)value; + + return 1; +} + +// Process SWJ Clock command and prepare response +// request: pointer to request datas +// response: pointer to response datas +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +__xdata uint32_t fast_clock; +__xdata uint8_t clock_delay; +static uint8_t DAP_SWJ_Clock(const uint8_t *req, uint8_t *res) +{ + /**/ + fast_clock = *((uint32_t *)req); + + clock_delay = 0; + + *res = DAP_OK; + return 1; +} + +// Process SWJ Sequence command and prepare response +// request: pointer to request datas +// response: pointer to response datas +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +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 datas +// response: pointer to response datas +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +__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 datas +// response: pointer to response datas +// 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 datas +// response: pointer to response datas +// 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 datas +// response: pointer to response datas +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) + +__xdata uint8_t datas[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 datas and post next AP read + do + { + response_value = SWD_Transfer(request_value, datas); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } + else + { + // Read previous AP datas + do + { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, datas); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + post_read = 0U; + } + if (response_value != DAP_TRANSFER_OK) + { + break; + } + // Store previous AP datas + *res++ = (uint8_t)datas[0]; + *res++ = (uint8_t)datas[1]; + *res++ = (uint8_t)datas[2]; + *res++ = (uint8_t)datas[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, datas); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) + { + break; + } + } + while (((datas[0] & match_mask[0]) != match_value[0] || + (datas[1] & match_mask[1]) != match_value[1] || + (datas[2] & match_mask[2]) != match_value[2] || + (datas[3] & match_mask[3]) != match_value[3]) && + match_retry-- && !DAP_TransferAbort); + if ((datas[0] & match_mask[0]) != match_value[0] || + (datas[1] & match_mask[1]) != match_value[1] || + (datas[2] & match_mask[2]) != match_value[2] || + (datas[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, datas); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) + { + break; + } + + // Store datas + *res++ = datas[0]; + *res++ = datas[1]; + *res++ = datas[2]; + *res++ = datas[3]; + } + } + check_write = 0U; + } + else + { + // Write register + if (post_read) + { + // Read previous datas + retry = retry_count; + do + { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, datas); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) + { + break; + } + // Store previous datas + *res++ = datas[0]; + *res++ = datas[1]; + *res++ = datas[2]; + *res++ = datas[3]; + post_read = 0U; + } + // Load datas + datas[0] = (uint8_t)(*(req + 0)); + datas[1] = (uint8_t)(*(req + 1)); + datas[2] = (uint8_t)(*(req + 2)); + datas[3] = (uint8_t)(*(req + 3)); + req += 4; + if ((request_value & DAP_TRANSFER_MATCH_MASK) != 0U) + { + // Write match mask + match_mask[0] = datas[0]; + match_mask[1] = datas[1]; + match_mask[2] = datas[2]; + match_mask[3] = datas[3]; + response_value = DAP_TRANSFER_OK; + } + else + { + // Write DP/AP register + retry = retry_count; + do + { + response_value = SWD_Transfer(request_value, datas); + } + 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 datas + retry = retry_count; + do + { + response_value = SWD_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, datas); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) + { + goto end; + } + // Store previous datas + *res++ = (uint8_t)datas[0]; + *res++ = (uint8_t)datas[1]; + *res++ = (uint8_t)datas[2]; + *res++ = (uint8_t)datas[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 datas +// response: pointer to response datas +// 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 datas +// response: pointer to response datas +// 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 datas +// response: pointer to response datas +// 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, datas); + } + while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) + { + goto end; + } + // Store datas + *res++ = (uint8_t)datas[0]; + *res++ = (uint8_t)datas[1]; + *res++ = (uint8_t)datas[2]; + *res++ = (uint8_t)datas[3]; + response_count++; + } + } + else + { + // Write register block + while (request_count--) + { + // Load datas + datas[0] = (uint8_t)(*(req + 0)); + datas[1] = (uint8_t)(*(req + 1)); + datas[2] = (uint8_t)(*(req + 2)); + datas[3] = (uint8_t)(*(req + 3)); + + req += 4; + // Write DP/AP register + retry = retry_count; + do + { + response_value = SWD_Transfer(request_value, datas); + } + 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) = (uint8_t)(response_count >> 0); + *(response_head + 1) = (uint8_t)(response_count >> 8); + *(response_head + 2) = (uint8_t)response_value; + + return ((uint8_t)(res - response_head)); +} + +// Process Transfer Block command and prepare response +// request: pointer to request datas +// response: pointer to response datas +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +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; + } + + if ((*(req + 3) & DAP_TRANSFER_RnW) != 0U) + { + // Read registers block + num |= 4U << 16; + } + else + { + // Write registers block + num |= (4U + (((uint8_t)(*(req + 1)) | (uint8_t)(*(req + 2) << 8)) * 4)) << 16; + } + + return (num); +} + +// Process SWD Write ABORT command and prepare response +// request: pointer to request datas +// response: pointer to response datas +// return: number of bytes in response +static uint8_t DAP_SWD_WriteAbort(const uint8_t *req, uint8_t *res) +{ + // Load datas (Ignore DAP index) + datas[0] = (uint8_t)(*(req + 1)); + datas[1] = (uint8_t)(*(req + 2)); + datas[2] = (uint8_t)(*(req + 3)); + datas[3] = (uint8_t)(*(req + 4)); + + // Write Abort register + SWD_Transfer(DP_ABORT, datas); + + *res = DAP_OK; + return (1U); +} + +// Process Write ABORT command and prepare response +// request: pointer to request datas +// response: pointer to response datas +// return: number of bytes in response (lower 16 bits) +// number of bytes in request (upper 16 bits) +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. +void DAP_Thread(void) +{ + uint8_t num; + + 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; + } + + Ep1Buffer[64] = num + 1; + } +} diff --git a/firmware/src/CMSIS_DAPusb/DAP.h b/firmware/src/CMSIS_DAPusb/DAP.h new file mode 100644 index 0000000..fd81720 --- /dev/null +++ b/firmware/src/CMSIS_DAPusb/DAP.h @@ -0,0 +1,222 @@ +/* + * 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 "include/ch554.h" +#include +#include +#include + +// DAP Firmware Version +#define DAP_FW_VER "1.0.0" + +// 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 4 +#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 void 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/firmware/src/CMSIS_DAPusb/SW_DP.c b/firmware/src/CMSIS_DAPusb/SW_DP.c new file mode 100644 index 0000000..37af6f9 --- /dev/null +++ b/firmware/src/CMSIS_DAPusb/SW_DP.c @@ -0,0 +1,307 @@ +/* + * 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" +#include + +#define SW_CLOCK_CYCLE() \ + SWK = 0; delayMicroseconds(1); \ + SWK = 1; delayMicroseconds(1); + +#define SW_WRITE_BIT(bits) \ + SWD = (bits)&1; \ + SWK = 0; delayMicroseconds(1); \ + SWK = 1; delayMicroseconds(1); + +#define SW_READ_BIT(bits) \ + SWK = 0; delayMicroseconds(1); \ + bits = SWD; \ + SWK = 1; delayMicroseconds(1); + +/** Setup SWD I/O pins: SWCLK, SWDIO, and nRESET. +Configures the DAP Hardware I/O pins for Serial Wire Debug (SWD) mode: + - SWCLK, SWDIO, nRESET to output mode and set to default high level. + - TDI, TMS, nTRST to HighZ mode (pins are unused in SWD mode). +*/ +void PORT_SWD_SETUP(void) +{ + // Set SWCLK HIGH + //推挽输出 + + //P3_MOD_OC = P3_MOD_OC & ~(1 << 1); + P3_MOD_OC = P3_MOD_OC | (1 << 1); + P3_DIR_PU = P3_DIR_PU | (1 << 1); + SWK = 1; + // Set SWDIO HIGH + //推挽输出 + //P3_MOD_OC = P3_MOD_OC & ~(1 << 2); + P3_MOD_OC = P3_MOD_OC | (1 << 2); + P3_DIR_PU = P3_DIR_PU | (1 << 2); + SWD = 1; + // Set RESET HIGH + //推挽输出 + //P3_MOD_OC = P3_MOD_OC & ~(1 << 0); + P3_MOD_OC = P3_MOD_OC | (1 << 0); + P3_DIR_PU = P3_DIR_PU | (1 << 0); + RST = 1; +} + +// 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; + } + SWK = 0; + delayMicroseconds(1); + SWK = 1; + 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; + uint8_t val; + uint8_t parity; + + uint8_t m, n; + + /* Packet req */ + parity = 0U; + SW_WRITE_BIT(1U); /* Start Bit */ + bits = req >> 0; + SW_WRITE_BIT(bits); /* APnDP Bit */ + parity += bits; + bits = req >> 1; + SW_WRITE_BIT(bits); /* RnW Bit */ + parity += bits; + bits = req >> 2; + SW_WRITE_BIT(bits); /* A2 Bit */ + parity += bits; + bits = req >> 3; + 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 */ + SWD = 1; + 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 (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/firmware/src/CMSIS_DAPusb/USBHID.c b/firmware/src/CMSIS_DAPusb/USBHID.c new file mode 100644 index 0000000..4e5be31 --- /dev/null +++ b/firmware/src/CMSIS_DAPusb/USBHID.c @@ -0,0 +1,37 @@ +#include +#include +#include "include/ch554.h" +#include "include/ch554_usb.h" +#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/firmware/src/CMSIS_DAPusb/USBHID.h b/firmware/src/CMSIS_DAPusb/USBHID.h new file mode 100644 index 0000000..7962a68 --- /dev/null +++ b/firmware/src/CMSIS_DAPusb/USBHID.h @@ -0,0 +1,19 @@ +#ifndef __USB_HID_H__ +#define __USB_HID_H__ + +#include +#include "include/ch554.h" +#include "include/ch554_usb.h" + +#ifdef __cplusplus +extern "C" { +#endif + +void USBInit(void); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif + diff --git a/firmware/src/CMSIS_DAPusb/USBconstant.c b/firmware/src/CMSIS_DAPusb/USBconstant.c new file mode 100644 index 0000000..21e81ff --- /dev/null +++ b/firmware/src/CMSIS_DAPusb/USBconstant.c @@ -0,0 +1,107 @@ +#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,0x50,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 + 0x14,0x03, + '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[]={ + 0x1E,0x03, + 'E',0x00,'l',0x00,'e',0x00,'c',0x00,'t',0x00,'r',0x00,'o',0x00,'n',0x00,'i',0x00,'c',0x00,'C',0x00,'a',0x00,'t',0x00,'s',0x00, +}; +__code uint16_t Manuf_DesLen = sizeof(Manuf_Des); diff --git a/firmware/src/CMSIS_DAPusb/USBconstant.h b/firmware/src/CMSIS_DAPusb/USBconstant.h new file mode 100644 index 0000000..fec2da9 --- /dev/null +++ b/firmware/src/CMSIS_DAPusb/USBconstant.h @@ -0,0 +1,28 @@ +#ifndef __CONST_DATA_H__ +#define __CONST_DATA_H__ + +#include +#include "include/ch554.h" +#include "include/ch554_usb.h" + +#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/firmware/src/CMSIS_DAPusb/USBhandler.c b/firmware/src/CMSIS_DAPusb/USBhandler.c new file mode 100644 index 0000000..650b36d --- /dev/null +++ b/firmware/src/CMSIS_DAPusb/USBhandler.c @@ -0,0 +1,481 @@ +#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 + +#if (EP1_ADDR+128) > USER_USB_RAM +#error "This example needs more USB ram. Increase this setting in menu." +#endif + +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: //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 + + //while ( XBUS_AUX & bUART0_TX ); //Wait till uart0 sending complete + //SAFE_MOD = 0x55; + //SAFE_MOD = 0xAA; + //WAKE_CTRL = bWAK_BY_USB | bWAK_RXD0_LO | bWAK_RXD1_LO; //wake up by USB or RXD0/1 signal + //PCON |= PD; //sleep + //SAFE_MOD = 0x55; + //SAFE_MOD = 0xAA; + //WAKE_CTRL = 0x00; + } + 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 "include/ch554.h" +#include "include/ch554_usb.h" +#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 + +#ifdef __cplusplus +extern "C" { +#endif + +void USBInterrupt(void); +void USBDeviceCfg(); +void USBDeviceIntCfg(); +void USBDeviceEndPointCfg(); + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif +