diff --git a/DAP.c b/DAP.c new file mode 100644 index 0000000..860c2b5 --- /dev/null +++ b/DAP.c @@ -0,0 +1,1363 @@ +/* CMSIS-DAP Interface Firmware + * Copyright (c) 2009-2013 ARM Limited + * + * 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 + * + * http://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. + */ + +#include +#include "DAP_config.h" +#include "DAP.h" +#include "semihost.h" + + +#define DAP_FW_VER "1.0" // Firmware Version + + +#if (DAP_PACKET_SIZE < 64) +#error "Minimum Packet Size is 64" +#endif +#if (DAP_PACKET_SIZE > 32768) +#error "Maximum Packet Size is 32768" +#endif +#if (DAP_PACKET_COUNT < 1) +#error "Minimum Packet Count is 1" +#endif +#if (DAP_PACKET_COUNT > 255) +#error "Maximum Packet Count is 255" +#endif + + +// Clock Macros + +#define MAX_SWJ_CLOCK(delay_cycles) \ + (CPU_CLOCK/2 / (IO_PORT_WRITE_CYCLES + delay_cycles)) + +#define CLOCK_DELAY(swj_clock) \ + ((CPU_CLOCK/2 / swj_clock) - IO_PORT_WRITE_CYCLES) + + + DAP_Data_t DAP_Data; // DAP Data +volatile uint8_t DAP_TransferAbort; // Trasfer Abort Flag + + +#ifdef DAP_VENDOR +const char DAP_Vendor [] = DAP_VENDOR; +#endif +#ifdef DAP_PRODUCT +const char DAP_Product[] = DAP_PRODUCT; +#endif +#ifdef DAP_SER_NUM +const char DAP_SerNum [] = DAP_SER_NUM; +#endif +const char DAP_FW_Ver [] = DAP_FW_VER; + +#if TARGET_DEVICE_FIXED +const char TargetDeviceVendor [] = TARGET_DEVICE_VENDOR; +const char TargetDeviceName [] = TARGET_DEVICE_NAME; +#endif + + +// 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 = 0; + + switch (id) { + case DAP_ID_VENDOR: +#ifdef DAP_VENDOR + memcpy(info, DAP_Vendor, sizeof(DAP_Vendor)); + length = sizeof(DAP_Vendor); +#endif + break; + case DAP_ID_PRODUCT: +#ifdef DAP_PRODUCT + memcpy(info, DAP_Product, sizeof(DAP_Product)); + length = sizeof(DAP_Product); +#endif + break; + case DAP_ID_SER_NUM: +#ifdef DAP_SER_NUM + memcpy(info, DAP_SerNum, sizeof(DAP_SerNum)); + length = sizeof(DAP_SerNum); +#endif + break; + case DAP_ID_FW_VER: + memcpy(info, DAP_FW_Ver, sizeof(DAP_FW_Ver)); + length = sizeof(DAP_FW_Ver); + break; + case DAP_ID_DEVICE_VENDOR: +#if TARGET_DEVICE_FIXED + memcpy(info, TargetDeviceVendor, sizeof(TargetDeviceVendor)); + length = sizeof(TargetDeviceVendor); +#endif + break; + case DAP_ID_DEVICE_NAME: +#if TARGET_DEVICE_FIXED + memcpy(info, TargetDeviceName, sizeof(TargetDeviceName)); + length = sizeof(TargetDeviceName); +#endif + break; + case DAP_ID_CAPABILITIES: + info[0] = ((DAP_SWD != 0) ? (1 << 0) : 0) | + ((DAP_JTAG != 0) ? (1 << 1) : 0); + length = 1; + break; + case DAP_ID_PACKET_SIZE: + info[0] = (uint8_t)(DAP_PACKET_SIZE >> 0); + info[1] = (uint8_t)(DAP_PACKET_SIZE >> 8); + length = 2; + break; + case DAP_ID_PACKET_COUNT: + info[0] = DAP_PACKET_COUNT; + length = 1; + break; + } + + return (length); +} + + +// Timer Functions + +#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) + +// Start Timer +static __inline void TIMER_START (uint32_t usec) { + SysTick->VAL = 0; + SysTick->LOAD = usec * CPU_CLOCK/1000000; + SysTick->CTRL = (1 << SysTick_CTRL_ENABLE_Pos) | + (1 << SysTick_CTRL_CLKSOURCE_Pos); +} + +// Stop Timer +static __inline void TIMER_STOP (void) { + SysTick->CTRL = 0; +} + +// Check if Timer expired +static __inline uint32_t TIMER_EXPIRED (void) { + return ((SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk) ? 1 : 0); +} + +#endif + + +// Delay for specified time +// delay: delay time in ms +void Delayms(uint32_t delay) { + delay *= (CPU_CLOCK/1000 + (DELAY_SLOW_CYCLES-1)) / DELAY_SLOW_CYCLES; + PIN_DELAY_SLOW(delay); +} + + +// Process Delay command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint32_t DAP_Delay(uint8_t *request, uint8_t *response) { + uint32_t delay; + + delay = *(request+0) | (*(request+1) << 8); + delay *= (CPU_CLOCK/1000000 + (DELAY_SLOW_CYCLES-1)) / DELAY_SLOW_CYCLES; + + PIN_DELAY_SLOW(delay); + + *response = 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 uint32_t DAP_HostStatus(uint8_t *request, uint8_t *response) { + + switch (*request) { + case DAP_DEBUGGER_CONNECTED: + LED_CONNECTED_OUT((*(request+1) & 1)); + break; + case DAP_TARGET_RUNNING: + LED_RUNNING_OUT((*(request+1) & 1)); + break; + default: + *response = DAP_ERROR; + return (1); + } + + *response = 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 +static uint32_t DAP_Connect(uint8_t *request, uint8_t *response) { + uint32_t port; + + if (*request == DAP_PORT_AUTODETECT) { + port = DAP_DEFAULT_PORT; + } else { + port = *request; + } + + semihost_disable(); + + switch (port) { +#if (DAP_SWD != 0) + case DAP_PORT_SWD: + DAP_Data.debug_port = DAP_PORT_SWD; + PORT_SWD_SETUP(); + break; +#endif +#if (DAP_JTAG != 0) + case DAP_PORT_JTAG: + DAP_Data.debug_port = DAP_PORT_JTAG; + PORT_JTAG_SETUP(); + break; +#endif + default: + *response = DAP_PORT_DISABLED; + return (1); + } + + *response = port; + return (1); +} + + +// Process Disconnect command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint32_t DAP_Disconnect(uint8_t *response) { + + DAP_Data.debug_port = DAP_PORT_DISABLED; + PORT_OFF(); + + semihost_enable(); + + *response = DAP_OK; + return (1); +} + + +// Process Reset Target command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint32_t DAP_ResetTarget(uint8_t *response) { + + *(response+1) = RESET_TARGET(); + *(response+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 +#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) +static uint32_t DAP_SWJ_Pins(uint8_t *request, uint8_t *response) { + uint32_t value; + uint32_t select; + uint32_t wait; + + value = *(request+0); + select = *(request+1); + wait = (*(request+2) << 0) | + (*(request+3) << 8) | + (*(request+4) << 16) | + (*(request+5) << 24); + + if (select & (1 << DAP_SWJ_SWCLK_TCK)) { + if (value & (1 << DAP_SWJ_SWCLK_TCK)) { + PIN_SWCLK_TCK_SET(); + } else { + PIN_SWCLK_TCK_CLR(); + } + } + if (select & (1 << DAP_SWJ_SWDIO_TMS)) { + if (value & (1 << DAP_SWJ_SWDIO_TMS)) { + PIN_SWDIO_TMS_SET(); + } else { + PIN_SWDIO_TMS_CLR(); + } + } + if (select & (1 << DAP_SWJ_TDI)) { + PIN_TDI_OUT(value >> DAP_SWJ_TDI); + } + if (select & (1 << DAP_SWJ_nTRST)) { + PIN_nTRST_OUT(value >> DAP_SWJ_nTRST); + } + if (select & (1 << DAP_SWJ_nRESET)) { + PIN_nRESET_OUT(value >> DAP_SWJ_nRESET); + } + + if (wait) { + if (wait > 3000000) wait = 3000000; + TIMER_START(wait); + do { + if (select & (1 << DAP_SWJ_SWCLK_TCK)) { + if ((value >> DAP_SWJ_SWCLK_TCK) ^ PIN_SWCLK_TCK_IN()) continue; + } + if (select & (1 << DAP_SWJ_SWDIO_TMS)) { + if ((value >> DAP_SWJ_SWDIO_TMS) ^ PIN_SWDIO_TMS_IN()) continue; + } + if (select & (1 << DAP_SWJ_TDI)) { + if ((value >> DAP_SWJ_TDI) ^ PIN_TDI_IN()) continue; + } + if (select & (1 << DAP_SWJ_nTRST)) { + if ((value >> DAP_SWJ_nTRST) ^ PIN_nTRST_IN()) continue; + } + if (select & (1 << DAP_SWJ_nRESET)) { + if ((value >> DAP_SWJ_nRESET) ^ PIN_nRESET_IN()) continue; + } + break; + } while (!TIMER_EXPIRED()); + TIMER_STOP(); + } + + value = (PIN_SWCLK_TCK_IN() << DAP_SWJ_SWCLK_TCK) | + (PIN_SWDIO_TMS_IN() << DAP_SWJ_SWDIO_TMS) | + (PIN_TDI_IN() << DAP_SWJ_TDI) | + (PIN_TDO_IN() << DAP_SWJ_TDO) | + (PIN_nTRST_IN() << DAP_SWJ_nTRST) | + (PIN_nRESET_IN() << DAP_SWJ_nRESET); + + *response = (uint8_t)value; + return (1); +} +#endif + + +// Process SWJ Clock command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) +static uint32_t DAP_SWJ_Clock(uint8_t *request, uint8_t *response) { + uint32_t clock; + uint32_t delay; + + clock = (*(request+0) << 0) | + (*(request+1) << 8) | + (*(request+2) << 16) | + (*(request+3) << 24); + + if (clock == 0) { + *response = DAP_ERROR; + return (1); + } + + if (clock >= MAX_SWJ_CLOCK(DELAY_FAST_CYCLES)) { + DAP_Data.fast_clock = 1; + DAP_Data.clock_delay = 1; + } else { + DAP_Data.fast_clock = 0; + + delay = (CPU_CLOCK/2 + (clock - 1)) / clock; + if (delay > IO_PORT_WRITE_CYCLES) { + delay -= IO_PORT_WRITE_CYCLES; + delay = (delay + (DELAY_SLOW_CYCLES - 1)) / DELAY_SLOW_CYCLES; + } else { + delay = 1; + } + + DAP_Data.clock_delay = delay; + } + + *response = DAP_OK; + return (1); +} +#endif + + +// Process SWJ Sequence command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) +static uint32_t DAP_SWJ_Sequence(uint8_t *request, uint8_t *response) { + uint32_t count; + + count = *request++; + if (count == 0) count = 256; + + SWJ_Sequence(count, request); + + *response = DAP_OK; + return (1); +} +#endif + + +// Process SWD Configure command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_SWD != 0) +static uint32_t DAP_SWD_Configure(uint8_t *request, uint8_t *response) { + uint8_t value; + + value = *request; + DAP_Data.swd_conf.turnaround = (value & 0x03) + 1; + DAP_Data.swd_conf.data_phase = (value & 0x04) ? 1 : 0; + + *response = DAP_OK; + + return (1); +} +#endif + + +// Process SWD Abort command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_SWD != 0) +static uint32_t DAP_SWD_Abort(uint8_t *request, uint8_t *response) { + uint32_t data; + + if (DAP_Data.debug_port != DAP_PORT_SWD) { + *response = DAP_ERROR; + return (1); + } + + // Load data (Ignore DAP index) + data = (*(request+1) << 0) | + (*(request+2) << 8) | + (*(request+3) << 16) | + (*(request+4) << 24); + + // Write Abort register + SWD_Transfer(DP_ABORT, &data); + *response = DAP_OK; + + return (1); +} +#endif + + +// Process JTAG Sequence command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_JTAG != 0) +static uint32_t DAP_JTAG_Sequence(uint8_t *request, uint8_t *response) { + uint32_t sequence_info; + uint32_t sequence_count; + uint32_t response_count; + uint32_t count; + + *response++ = DAP_OK; + response_count = 1; + + sequence_count = *request++; + while (sequence_count--) { + sequence_info = *request++; + JTAG_Sequence(sequence_info, request, response); + count = sequence_info & JTAG_SEQUENCE_TCK; + if (count == 0) count = 64; + count = (count + 7) / 8; + request += count; + if (sequence_info & JTAG_SEQUENCE_TDO) { + response += count; + response_count += count; + } + } + + return (response_count); +} +#endif + + +// Process JTAG Configure command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_JTAG != 0) +static uint32_t DAP_JTAG_Configure(uint8_t *request, uint8_t *response) { + uint32_t count; + uint32_t length; + uint32_t bits; + uint32_t n; + + count = *request++; + DAP_Data.jtag_dev.count = count; + + bits = 0; + for (n = 0; n < count; n++) { + length = *request++; + DAP_Data.jtag_dev.ir_length[n] = length; + DAP_Data.jtag_dev.ir_before[n] = bits; + bits += length; + } + for (n = 0; n < count; n++) { + bits -= DAP_Data.jtag_dev.ir_length[n]; + DAP_Data.jtag_dev.ir_after[n] = bits; + } + + *response = DAP_OK; + return (1); +} +#endif + + +// Process JTAG IDCODE command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_JTAG != 0) +static uint32_t DAP_JTAG_IDCode(uint8_t *request, uint8_t *response) { + uint32_t data; + + if (DAP_Data.debug_port != DAP_PORT_JTAG) { +err:*response = DAP_ERROR; + return (1); + } + + // Device index (JTAP TAP) + DAP_Data.jtag_dev.index = *request; + if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto err; + + // Select JTAG chain + JTAG_IR(JTAG_IDCODE); + + // Read IDCODE register + data = JTAG_ReadIDCode(); + + // Store Data + *(response+0) = DAP_OK; + *(response+1) = (uint8_t)(data >> 0); + *(response+2) = (uint8_t)(data >> 8); + *(response+3) = (uint8_t)(data >> 16); + *(response+4) = (uint8_t)(data >> 24); + + return (1+4); +} +#endif + + +// Process JTAG Abort command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_JTAG != 0) +static uint32_t DAP_JTAG_Abort(uint8_t *request, uint8_t *response) { + uint32_t data; + + if (DAP_Data.debug_port != DAP_PORT_JTAG) { +err:*response = DAP_ERROR; + return (1); + } + + // Device index (JTAP TAP) + DAP_Data.jtag_dev.index = *request; + if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto err; + + // Select JTAG chain + JTAG_IR(JTAG_ABORT); + + // Load data + data = (*(request+1) << 0) | + (*(request+2) << 8) | + (*(request+3) << 16) | + (*(request+4) << 24); + + // Write Abort register + JTAG_WriteAbort(data); + *response = DAP_OK; + + return (1); +} +#endif + + +// Process Transfer Configure command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +static uint32_t DAP_TransferConfigure(uint8_t *request, uint8_t *response) { + + DAP_Data.transfer.idle_cycles = *(request+0); + DAP_Data.transfer.retry_count = *(request+1) | (*(request+2) << 8); + DAP_Data.transfer.match_retry = *(request+3) | (*(request+4) << 8); + + *response = 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 +#if (DAP_SWD != 0) +static uint32_t DAP_SWD_Transfer(uint8_t *request, uint8_t *response) { + uint32_t request_count; + uint32_t request_value; + uint32_t response_count; + uint32_t response_value; + uint8_t *response_head; + uint32_t post_read; + uint32_t check_write; + uint32_t match_value; + uint32_t match_retry; + uint32_t retry; + uint32_t data; + + response_count = 0; + response_value = 0; + response_head = response; + response += 2; + + DAP_TransferAbort = 0; + + post_read = 0; + check_write = 0; + + request++; // Ignore DAP index + + request_count = *request++; + while (request_count--) { + request_value = *request++; + if (request_value & DAP_TRANSFER_RnW) { + // Read register + if (post_read) { + // Read was posted before + retry = DAP_Data.transfer.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 = 0; + } + if (response_value != DAP_TRANSFER_OK) break; + // Store previous AP data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + } + if (request_value & DAP_TRANSFER_MATCH_VALUE) { + // Read with value match + match_value = (*(request+0) << 0) | + (*(request+1) << 8) | + (*(request+2) << 16) | + (*(request+3) << 24); + request += 4; + match_retry = DAP_Data.transfer.match_retry; + if (request_value & DAP_TRANSFER_APnDP) { + // Post AP read + retry = DAP_Data.transfer.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 register until its value matches or retry counter expires + retry = DAP_Data.transfer.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 & DAP_Data.transfer.match_mask) != match_value) && match_retry-- && !DAP_TransferAbort); + if ((data & DAP_Data.transfer.match_mask) != match_value) { + response_value |= DAP_TRANSFER_MISMATCH; + } + if (response_value != DAP_TRANSFER_OK) break; + } else { + // Normal read + retry = DAP_Data.transfer.retry_count; + if (request_value & DAP_TRANSFER_APnDP) { + // Read AP register + if (post_read == 0) { + // 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 = 1; + } + } 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 + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + } + } + check_write = 0; + } else { + // Write register + if (post_read) { + // Read previous data + retry = DAP_Data.transfer.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 + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + post_read = 0; + } + // Load data + data = (*(request+0) << 0) | + (*(request+1) << 8) | + (*(request+2) << 16) | + (*(request+3) << 24); + request += 4; + if (request_value & DAP_TRANSFER_MATCH_MASK) { + // Write match mask + DAP_Data.transfer.match_mask = data; + response_value = DAP_TRANSFER_OK; + } else { + // Write DP/AP register + retry = DAP_Data.transfer.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 = 1; + } + } + response_count++; + if (DAP_TransferAbort) break; + } + + if (response_value == DAP_TRANSFER_OK) { + if (post_read) { + // Read previous data + retry = DAP_Data.transfer.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 + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + } else if (check_write) { + // Check last write + retry = DAP_Data.transfer.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 (response - response_head); +} +#endif + + +// Process JTAG Transfer command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_JTAG != 0) +static uint32_t DAP_JTAG_Transfer(uint8_t *request, uint8_t *response) { + uint32_t request_count; + uint32_t request_value; + uint32_t request_ir; + uint32_t response_count; + uint32_t response_value; + uint8_t *response_head; + uint32_t post_read; + uint32_t match_value; + uint32_t match_retry; + uint32_t retry; + uint32_t data; + uint32_t ir; + + response_count = 0; + response_value = 0; + response_head = response; + response += 2; + + DAP_TransferAbort = 0; + + ir = 0; + post_read = 0; + + // Device index (JTAP TAP) + DAP_Data.jtag_dev.index = *request++; + if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto end; + + request_count = *request++; + while (request_count--) { + request_value = *request++; + request_ir = (request_value & DAP_TRANSFER_APnDP) ? JTAG_APACC : JTAG_DPACC; + if (request_value & DAP_TRANSFER_RnW) { + // Read register + if (post_read) { + // Read was posted before + retry = DAP_Data.transfer.retry_count; + if ((ir == request_ir) && ((request_value & DAP_TRANSFER_MATCH_VALUE) == 0)) { + // Read previous data and post next read + do { + response_value = JTAG_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + } else { + // Select JTAG chain + if (ir != JTAG_DPACC) { + ir = JTAG_DPACC; + JTAG_IR(ir); + } + // Read previous data + do { + response_value = JTAG_Transfer(DP_RDBUFF | DAP_TRANSFER_RnW, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + post_read = 0; + } + if (response_value != DAP_TRANSFER_OK) break; + // Store previous data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + } + if (request_value & DAP_TRANSFER_MATCH_VALUE) { + // Read with value match + match_value = (*(request+0) << 0) | + (*(request+1) << 8) | + (*(request+2) << 16) | + (*(request+3) << 24); + request += 4; + match_retry = DAP_Data.transfer.match_retry; + // Select JTAG chain + if (ir != request_ir) { + ir = request_ir; + JTAG_IR(ir); + } + // Post DP/AP read + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) break; + do { + // Read register until its value matches or retry counter expires + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) break; + } while (((data & DAP_Data.transfer.match_mask) != match_value) && match_retry-- && !DAP_TransferAbort); + if ((data & DAP_Data.transfer.match_mask) != match_value) { + response_value |= DAP_TRANSFER_MISMATCH; + } + if (response_value != DAP_TRANSFER_OK) break; + } else { + // Normal read + if (post_read == 0) { + // Select JTAG chain + if (ir != request_ir) { + ir = request_ir; + JTAG_IR(ir); + } + // Post DP/AP read + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) break; + post_read = 1; + } + } + } else { + // Write register + if (post_read) { + // Select JTAG chain + if (ir != JTAG_DPACC) { + ir = JTAG_DPACC; + JTAG_IR(ir); + } + // Read previous data + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_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 + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + post_read = 0; + } + // Load data + data = (*(request+0) << 0) | + (*(request+1) << 8) | + (*(request+2) << 16) | + (*(request+3) << 24); + request += 4; + if (request_value & DAP_TRANSFER_MATCH_MASK) { + // Write match mask + DAP_Data.transfer.match_mask = data; + response_value = DAP_TRANSFER_OK; + } else { + // Select JTAG chain + if (ir != request_ir) { + ir = request_ir; + JTAG_IR(ir); + } + // Write DP/AP register + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) break; + } + } + response_count++; + if (DAP_TransferAbort) break; + } + + if (response_value == DAP_TRANSFER_OK) { + // Select JTAG chain + if (ir != JTAG_DPACC) { + ir = JTAG_DPACC; + JTAG_IR(ir); + } + if (post_read) { + // Read previous data + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_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 + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + } else { + // Check last write + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_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 (response - response_head); +} +#endif + + +// Process SWD Transfer Block command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_SWD != 0) +static uint32_t DAP_SWD_TransferBlock(uint8_t *request, uint8_t *response) { + uint32_t request_count; + uint32_t request_value; + uint32_t response_count; + uint32_t response_value; + uint8_t *response_head; + uint32_t retry; + uint32_t data; + + response_count = 0; + response_value = 0; + response_head = response; + response += 3; + + DAP_TransferAbort = 0; + + request++; // Ignore DAP index + + request_count = *request | (*(request+1) << 8); + request += 2; + if (request_count == 0) goto end; + + request_value = *request++; + if (request_value & DAP_TRANSFER_RnW) { + // Read register block + if (request_value & DAP_TRANSFER_APnDP) { + // Post AP read + retry = DAP_Data.transfer.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 == 0) && (request_value & DAP_TRANSFER_APnDP)) { + // Last AP read + request_value = DP_RDBUFF | DAP_TRANSFER_RnW; + } + retry = DAP_Data.transfer.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 + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + response_count++; + } + } else { + // Write register block + while (request_count--) { + // Load data + data = (*(request+0) << 0) | + (*(request+1) << 8) | + (*(request+2) << 16) | + (*(request+3) << 24); + request += 4; + // Write DP/AP register + retry = DAP_Data.transfer.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 = DAP_Data.transfer.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 (response - response_head); +} +#endif + + +// Process JTAG Transfer Block command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +#if (DAP_JTAG != 0) +static uint32_t DAP_JTAG_TransferBlock(uint8_t *request, uint8_t *response) { + uint32_t request_count; + uint32_t request_value; + uint32_t response_count; + uint32_t response_value; + uint8_t *response_head; + uint32_t retry; + uint32_t data; + uint32_t ir; + + response_count = 0; + response_value = 0; + response_head = response; + response += 3; + + DAP_TransferAbort = 0; + + // Device index (JTAP TAP) + DAP_Data.jtag_dev.index = *request++; + if (DAP_Data.jtag_dev.index >= DAP_Data.jtag_dev.count) goto end; + + request_count = *request | (*(request+1) << 8); + request += 2; + if (request_count == 0) goto end; + + request_value = *request++; + + // Select JTAG chain + ir = (request_value & DAP_TRANSFER_APnDP) ? JTAG_APACC : JTAG_DPACC; + JTAG_IR(ir); + + if (request_value & DAP_TRANSFER_RnW) { + // Post read + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, NULL); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) goto end; + // Read register block + while (request_count--) { + // Read DP/AP register + if (request_count == 0) { + // Last read + if (ir != JTAG_DPACC) { + JTAG_IR(JTAG_DPACC); + } + request_value = DP_RDBUFF | DAP_TRANSFER_RnW; + } + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_Transfer(request_value, &data); + } while ((response_value == DAP_TRANSFER_WAIT) && retry-- && !DAP_TransferAbort); + if (response_value != DAP_TRANSFER_OK) goto end; + // Store data + *response++ = (uint8_t) data; + *response++ = (uint8_t)(data >> 8); + *response++ = (uint8_t)(data >> 16); + *response++ = (uint8_t)(data >> 24); + response_count++; + } + } else { + // Write register block + while (request_count--) { + // Load data + data = (*(request+0) << 0) | + (*(request+1) << 8) | + (*(request+2) << 16) | + (*(request+3) << 24); + request += 4; + // Write DP/AP register + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_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 + if (ir != JTAG_DPACC) { + JTAG_IR(JTAG_DPACC); + } + retry = DAP_Data.transfer.retry_count; + do { + response_value = JTAG_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 (response - response_head); +} +#endif + + +// Process DAP Vendor command and prepare response +// Default function (can be overridden) +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +__weak uint32_t DAP_ProcessVendorCommand(uint8_t *request, uint8_t *response) { + *response = ID_DAP_Invalid; + return (1); +} + + +// Process DAP command and prepare response +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +uint32_t DAP_ProcessCommand(uint8_t *request, uint8_t *response) { + uint32_t num; + + if ((*request >= ID_DAP_Vendor0) && (*request <= ID_DAP_Vendor31)) { + return DAP_ProcessVendorCommand(request, response); + } + + *response++ = *request; + + switch (*request++) { + case ID_DAP_Info: + num = DAP_Info(*request, response+1); + *response = num; + return (2 + num); + case ID_DAP_HostStatus: + num = DAP_HostStatus(request, response); + break; + case ID_DAP_Connect: + num = DAP_Connect(request, response); + break; + case ID_DAP_Disconnect: + num = DAP_Disconnect(response); + break; + case ID_DAP_Delay: + num = DAP_Delay(request, response); + break; + case ID_DAP_ResetTarget: + num = DAP_ResetTarget(response); + break; + +#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) + case ID_DAP_SWJ_Pins: + num = DAP_SWJ_Pins(request, response); + break; + case ID_DAP_SWJ_Clock: + num = DAP_SWJ_Clock(request, response); + break; + case ID_DAP_SWJ_Sequence: + num = DAP_SWJ_Sequence(request, response); + break; +#else + case ID_DAP_SWJ_Pins: + case ID_DAP_SWJ_Clock: + case ID_DAP_SWJ_Sequence: + *response = DAP_ERROR; + return (2); +#endif + +#if (DAP_SWD != 0) + case ID_DAP_SWD_Configure: + num = DAP_SWD_Configure(request, response); + break; +#else + case ID_DAP_SWD_Configure: + *response = DAP_ERROR; + return (2); +#endif + +#if (DAP_JTAG != 0) + case ID_DAP_JTAG_Sequence: + num = DAP_JTAG_Sequence(request, response); + break; + case ID_DAP_JTAG_Configure: + num = DAP_JTAG_Configure(request, response); + break; + case ID_DAP_JTAG_IDCODE: + num = DAP_JTAG_IDCode(request, response); + break; +#else + case ID_DAP_JTAG_Sequence: + case ID_DAP_JTAG_Configure: + case ID_DAP_JTAG_IDCODE: + *response = DAP_ERROR; + return (2); +#endif + + case ID_DAP_TransferConfigure: + num = DAP_TransferConfigure(request, response); + break; + + case ID_DAP_Transfer: + switch (DAP_Data.debug_port) { +#if (DAP_SWD != 0) + case DAP_PORT_SWD: + num = DAP_SWD_Transfer (request, response); + break; +#endif +#if (DAP_JTAG != 0) + case DAP_PORT_JTAG: + num = DAP_JTAG_Transfer(request, response); + break; +#endif + default: + *(response+0) = 0; // Response count + *(response+1) = 0; // Response value + num = 2; + } + break; + + case ID_DAP_TransferBlock: + switch (DAP_Data.debug_port) { +#if (DAP_SWD != 0) + case DAP_PORT_SWD: + num = DAP_SWD_TransferBlock (request, response); + break; +#endif +#if (DAP_JTAG != 0) + case DAP_PORT_JTAG: + num = DAP_JTAG_TransferBlock(request, response); + break; +#endif + default: + *(response+0) = 0; // Response count [7:0] + *(response+1) = 0; // Response count[15:8] + *(response+2) = 0; // Response value + num = 3; + } + break; + + case ID_DAP_WriteABORT: + switch (DAP_Data.debug_port) { +#if (DAP_SWD != 0) + case DAP_PORT_SWD: + num = DAP_SWD_Abort (request, response); + break; +#endif +#if (DAP_JTAG != 0) + case DAP_PORT_JTAG: + num = DAP_JTAG_Abort(request, response); + break; +#endif + default: + *response = DAP_ERROR; + return (2); + } + break; + + default: + *(response-1) = ID_DAP_Invalid; + return (1); + } + + return (1 + num); +} + + +// Setup DAP +void DAP_Setup(void) { + + // Default settings (only non-zero values) +//DAP_Data.debug_port = 0; +//DAP_Data.fast_clock = 0; + DAP_Data.clock_delay = CLOCK_DELAY(DAP_DEFAULT_SWJ_CLOCK); +//DAP_Data.transfer.idle_cycles = 0; + DAP_Data.transfer.retry_count = 100; +//DAP_Data.transfer.match_retry = 0; +//DAP_Data.transfer.match_mask = 0x000000; +#if (DAP_SWD != 0) + DAP_Data.swd_conf.turnaround = 1; +//DAP_Data.swd_conf.data_phase = 0; +#endif +#if (DAP_JTAG != 0) +//DAP_Data.jtag_dev.count = 0; +#endif + + DAP_SETUP(); // Device specific setup +} diff --git a/DAP.h b/DAP.h new file mode 100644 index 0000000..e7b6ab4 --- /dev/null +++ b/DAP.h @@ -0,0 +1,229 @@ +/* CMSIS-DAP Interface Firmware + * Copyright (c) 2009-2013 ARM Limited + * + * 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 + * + * http://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. + */ + +#ifndef __DAP_H__ +#define __DAP_H__ + + +// DAP Command IDs +#define ID_DAP_Info 0x00 +#define ID_DAP_HostStatus 0x01 +#define ID_DAP_Connect 0x02 +#define ID_DAP_Disconnect 0x03 +#define ID_DAP_TransferConfigure 0x04 +#define ID_DAP_Transfer 0x05 +#define ID_DAP_TransferBlock 0x06 +#define ID_DAP_TransferAbort 0x07 +#define ID_DAP_WriteABORT 0x08 +#define ID_DAP_Delay 0x09 +#define ID_DAP_ResetTarget 0x0A +#define ID_DAP_SWJ_Pins 0x10 +#define ID_DAP_SWJ_Clock 0x11 +#define ID_DAP_SWJ_Sequence 0x12 +#define ID_DAP_SWD_Configure 0x13 +#define ID_DAP_JTAG_Sequence 0x14 +#define ID_DAP_JTAG_Configure 0x15 +#define ID_DAP_JTAG_IDCODE 0x16 + +// DAP Vendor Command IDs +#define ID_DAP_Vendor0 0x80 +#define ID_DAP_Vendor1 0x81 +#define ID_DAP_Vendor2 0x82 +#define ID_DAP_Vendor3 0x83 +#define ID_DAP_Vendor4 0x84 +#define ID_DAP_Vendor5 0x85 +#define ID_DAP_Vendor6 0x86 +#define ID_DAP_Vendor7 0x87 +#define ID_DAP_Vendor8 0x88 +#define ID_DAP_Vendor9 0x89 +#define ID_DAP_Vendor10 0x8A +#define ID_DAP_Vendor11 0x8B +#define ID_DAP_Vendor12 0x8C +#define ID_DAP_Vendor13 0x8D +#define ID_DAP_Vendor14 0x8E +#define ID_DAP_Vendor15 0x8F +#define ID_DAP_Vendor16 0x90 +#define ID_DAP_Vendor17 0x91 +#define ID_DAP_Vendor18 0x92 +#define ID_DAP_Vendor19 0x93 +#define ID_DAP_Vendor20 0x94 +#define ID_DAP_Vendor21 0x95 +#define ID_DAP_Vendor22 0x96 +#define ID_DAP_Vendor23 0x97 +#define ID_DAP_Vendor24 0x98 +#define ID_DAP_Vendor25 0x99 +#define ID_DAP_Vendor26 0x9A +#define ID_DAP_Vendor27 0x9B +#define ID_DAP_Vendor28 0x9C +#define ID_DAP_Vendor29 0x9D +#define ID_DAP_Vendor30 0x9E +#define ID_DAP_Vendor31 0x9F + +#define ID_DAP_Invalid 0xFF + +// DAP Status Code +#define DAP_OK 0 +#define DAP_ERROR 0xFF + +// DAP ID +#define DAP_ID_VENDOR 1 +#define DAP_ID_PRODUCT 2 +#define DAP_ID_SER_NUM 3 +#define DAP_ID_FW_VER 4 +#define DAP_ID_DEVICE_VENDOR 5 +#define DAP_ID_DEVICE_NAME 6 +#define DAP_ID_CAPABILITIES 0xF0 +#define DAP_ID_PACKET_COUNT 0xFE +#define DAP_ID_PACKET_SIZE 0xFF + +// DAP Host Status +#define DAP_DEBUGGER_CONNECTED 0 +#define DAP_TARGET_RUNNING 1 + +// DAP Port +#define DAP_PORT_AUTODETECT 0 // Autodetect Port +#define DAP_PORT_DISABLED 0 // Port Disabled (I/O pins in High-Z) +#define DAP_PORT_SWD 1 // SWD Port (SWCLK, SWDIO) + nRESET +#define DAP_PORT_JTAG 2 // 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 + +// DAP Transfer Request +#define DAP_TRANSFER_APnDP (1<<0) +#define DAP_TRANSFER_RnW (1<<1) +#define DAP_TRANSFER_A2 (1<<2) +#define DAP_TRANSFER_A3 (1<<3) +#define DAP_TRANSFER_MATCH_VALUE (1<<4) +#define DAP_TRANSFER_MATCH_MASK (1<<5) + +// DAP Transfer Response +#define DAP_TRANSFER_OK (1<<0) +#define DAP_TRANSFER_WAIT (1<<1) +#define DAP_TRANSFER_FAULT (1<<2) +#define DAP_TRANSFER_ERROR (1<<3) +#define DAP_TRANSFER_MISMATCH (1<<4) + + +// Debug Port Register Addresses +#define DP_IDCODE 0x00 // IDCODE Register (SW Read only) +#define DP_ABORT 0x00 // Abort Register (SW Write only) +#define DP_CTRL_STAT 0x04 // Control & Status +#define DP_WCR 0x04 // Wire Control Register (SW Only) +#define DP_SELECT 0x08 // Select Register (JTAG R/W & SW W) +#define DP_RESEND 0x08 // Resend (SW Read Only) +#define DP_RDBUFF 0x0C // Read Buffer (Read Only) + +// JTAG IR Codes +#define JTAG_ABORT 0x08 +#define JTAG_DPACC 0x0A +#define JTAG_APACC 0x0B +#define JTAG_IDCODE 0x0E +#define JTAG_BYPASS 0x0F + +// JTAG Sequence Info +#define JTAG_SEQUENCE_TCK 0x3F // TCK count +#define JTAG_SEQUENCE_TMS 0x40 // TMS value +#define JTAG_SEQUENCE_TDO 0x80 // TDO capture + + +#include +#include + +// DAP Data structure +typedef struct { + uint8_t debug_port; // Debug Port + uint8_t fast_clock; // Fast Clock Flag + uint32_t clock_delay; // Clock Delay + struct { // Transfer Configuration + uint8_t idle_cycles; // Idle cycles after transfer + uint16_t retry_count; // Number of retries after WAIT response + uint16_t match_retry; // Number of retries if read value does not match + uint32_t match_mask; // Match Mask + } transfer; +#if (DAP_SWD != 0) + struct { // SWD Configuration + uint8_t turnaround; // Turnaround period + uint8_t data_phase; // Always generate Data Phase + } swd_conf; +#endif +#if (DAP_JTAG != 0) + struct { // JTAG Device Chain + uint8_t count; // Number of devices + uint8_t index; // Device index (device at TDO has index 0) +#if (DAP_JTAG_DEV_CNT != 0) + uint8_t ir_length[DAP_JTAG_DEV_CNT]; // IR Length in bits + uint16_t ir_before[DAP_JTAG_DEV_CNT]; // Bits before IR + uint16_t ir_after [DAP_JTAG_DEV_CNT]; // Bits after IR +#endif + } jtag_dev; +#endif +} DAP_Data_t; + +extern DAP_Data_t DAP_Data; // DAP Data +extern volatile uint8_t DAP_TransferAbort; // Transfer Abort Flag + + +// Functions +extern void SWJ_Sequence (uint32_t count, uint8_t *data); +extern void JTAG_Sequence (uint32_t info, uint8_t *tdi, uint8_t *tdo); +extern void JTAG_IR (uint32_t ir); +extern uint32_t JTAG_ReadIDCode (void); +extern void JTAG_WriteAbort (uint32_t data); +extern uint8_t JTAG_Transfer (uint32_t request, uint32_t *data); +extern uint8_t SWD_Transfer (uint32_t request, uint32_t *data); + +extern void Delayms (uint32_t delay); + +extern uint32_t DAP_ProcessVendorCommand (uint8_t *request, uint8_t *response); + +extern uint32_t DAP_ProcessCommand (uint8_t *request, uint8_t *response); +extern void DAP_Setup (void); + +// Configurable delay for clock generation +#ifndef DELAY_SLOW_CYCLES +#define DELAY_SLOW_CYCLES 3 // Number of cycles for one iteration +#endif +static __forceinline void PIN_DELAY_SLOW (uint32_t delay) { + int32_t count; + + count = delay; + while (--count); +} + +// Fixed delay for fast clock generation +#ifndef DELAY_FAST_CYCLES +#define DELAY_FAST_CYCLES 0 // Number of cycles: 0..3 +#endif +static __forceinline void PIN_DELAY_FAST (void) { +#if (DELAY_FAST_CYCLES >= 1) + __nop(); +#endif +#if (DELAY_FAST_CYCLES >= 2) + __nop(); +#endif +#if (DELAY_FAST_CYCLES >= 3) + __nop(); +#endif +} + + +#endif /* __DAP_H__ */ diff --git a/JTAG_DP.c b/JTAG_DP.c new file mode 100755 index 0000000..cfc459f --- /dev/null +++ b/JTAG_DP.c @@ -0,0 +1,352 @@ +/* CMSIS-DAP Interface Firmware + * Copyright (c) 2009-2013 ARM Limited + * + * 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 + * + * http://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. + */ + +#include "DAP_config.h" +#include "DAP.h" + + +// JTAG Macros + +#define PIN_TCK_SET PIN_SWCLK_TCK_SET +#define PIN_TCK_CLR PIN_SWCLK_TCK_CLR +#define PIN_TMS_SET PIN_SWDIO_TMS_SET +#define PIN_TMS_CLR PIN_SWDIO_TMS_CLR + +#define JTAG_CYCLE_TCK() \ + PIN_TCK_CLR(); \ + PIN_DELAY(); \ + PIN_TCK_SET(); \ + PIN_DELAY() + +#define JTAG_CYCLE_TDI(tdi) \ + PIN_TDI_OUT(tdi); \ + PIN_TCK_CLR(); \ + PIN_DELAY(); \ + PIN_TCK_SET(); \ + PIN_DELAY() + +#define JTAG_CYCLE_TDO(tdo) \ + PIN_TCK_CLR(); \ + PIN_DELAY(); \ + tdo = PIN_TDO_IN(); \ + PIN_TCK_SET(); \ + PIN_DELAY() + +#define JTAG_CYCLE_TDIO(tdi,tdo) \ + PIN_TDI_OUT(tdi); \ + PIN_TCK_CLR(); \ + PIN_DELAY(); \ + tdo = PIN_TDO_IN(); \ + PIN_TCK_SET(); \ + PIN_DELAY() + +#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) + + +#if (DAP_JTAG != 0) + + +// Generate JTAG Sequence +// info: sequence information +// tdi: pointer to TDI generated data +// tdo: pointer to TDO captured data +// return: none +void JTAG_Sequence (uint32_t info, uint8_t *tdi, uint8_t *tdo) { + uint32_t i_val; + uint32_t o_val; + uint32_t bit; + uint32_t n, k; + + n = info & JTAG_SEQUENCE_TCK; + if (n == 0) n = 64; + + if (info & JTAG_SEQUENCE_TMS) { + PIN_TMS_SET(); + } else { + PIN_TMS_CLR(); + } + + while (n) { + i_val = *tdi++; + o_val = 0; + for (k = 8; k && n; k--, n--) { + JTAG_CYCLE_TDIO(i_val, bit); + i_val >>= 1; + o_val >>= 1; + o_val |= bit << 7; + } + o_val >>= k; + if (info & JTAG_SEQUENCE_TDO) { + *tdo++ = o_val; + } + } +} + + +// JTAG Set IR +// ir: IR value +// return: none +#define JTAG_IR_Function(speed) /**/ \ +void JTAG_IR_##speed (uint32_t ir) { \ + uint32_t n; \ + \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Select-DR-Scan */ \ + JTAG_CYCLE_TCK(); /* Select-IR-Scan */ \ + PIN_TMS_CLR(); \ + JTAG_CYCLE_TCK(); /* Capture-IR */ \ + JTAG_CYCLE_TCK(); /* Shift-IR */ \ + \ + PIN_TDI_OUT(1); \ + for (n = DAP_Data.jtag_dev.ir_before[DAP_Data.jtag_dev.index]; n; n--) { \ + JTAG_CYCLE_TCK(); /* Bypass before data */ \ + } \ + for (n = DAP_Data.jtag_dev.ir_length[DAP_Data.jtag_dev.index] - 1; n; n--) { \ + JTAG_CYCLE_TDI(ir); /* Set IR bits (except last) */ \ + ir >>= 1; \ + } \ + n = DAP_Data.jtag_dev.ir_after[DAP_Data.jtag_dev.index]; \ + if (n) { \ + JTAG_CYCLE_TDI(ir); /* Set last IR bit */ \ + PIN_TDI_OUT(1); \ + for (--n; n; n--) { \ + JTAG_CYCLE_TCK(); /* Bypass after data */ \ + } \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Bypass & Exit1-IR */ \ + } else { \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TDI(ir); /* Set last IR bit & Exit1-IR */ \ + } \ + \ + JTAG_CYCLE_TCK(); /* Update-IR */ \ + PIN_TMS_CLR(); \ + JTAG_CYCLE_TCK(); /* Idle */ \ + PIN_TDI_OUT(1); \ +} + + +// JTAG Transfer I/O +// request: A[3:2] RnW APnDP +// data: DATA[31:0] +// return: ACK[2:0] +#define JTAG_TransferFunction(speed) /**/ \ +uint8_t JTAG_Transfer##speed (uint32_t request, uint32_t *data) { \ + uint32_t ack; \ + uint32_t bit; \ + uint32_t val; \ + uint32_t n; \ + \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Select-DR-Scan */ \ + PIN_TMS_CLR(); \ + JTAG_CYCLE_TCK(); /* Capture-DR */ \ + JTAG_CYCLE_TCK(); /* Shift-DR */ \ + \ + for (n = DAP_Data.jtag_dev.index; n; n--) { \ + JTAG_CYCLE_TCK(); /* Bypass before data */ \ + } \ + \ + JTAG_CYCLE_TDIO(request >> 1, bit); /* Set RnW, Get ACK.0 */ \ + ack = bit << 1; \ + JTAG_CYCLE_TDIO(request >> 2, bit); /* Set A2, Get ACK.1 */ \ + ack |= bit << 0; \ + JTAG_CYCLE_TDIO(request >> 3, bit); /* Set A3, Get ACK.2 */ \ + ack |= bit << 2; \ + \ + if (ack != DAP_TRANSFER_OK) { \ + /* Exit on error */ \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Exit1-DR */ \ + goto exit; \ + } \ + \ + if (request & DAP_TRANSFER_RnW) { \ + /* Read Transfer */ \ + val = 0; \ + for (n = 31; n; n--) { \ + JTAG_CYCLE_TDO(bit); /* Get D0..D30 */ \ + val |= bit << 31; \ + val >>= 1; \ + } \ + n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1; \ + if (n) { \ + JTAG_CYCLE_TDO(bit); /* Get D31 */ \ + for (--n; n; n--) { \ + JTAG_CYCLE_TCK(); /* Bypass after data */ \ + } \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ \ + } else { \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TDO(bit); /* Get D31 & Exit1-DR */ \ + } \ + val |= bit << 31; \ + if (data) *data = val; \ + } else { \ + /* Write Transfer */ \ + val = *data; \ + for (n = 31; n; n--) { \ + JTAG_CYCLE_TDI(val); /* Set D0..D30 */ \ + val >>= 1; \ + } \ + n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1; \ + if (n) { \ + JTAG_CYCLE_TDI(val); /* Set D31 */ \ + for (--n; n; n--) { \ + JTAG_CYCLE_TCK(); /* Bypass after data */ \ + } \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ \ + } else { \ + PIN_TMS_SET(); \ + JTAG_CYCLE_TDI(val); /* Set D31 & Exit1-DR */ \ + } \ + } \ + \ +exit: \ + JTAG_CYCLE_TCK(); /* Update-DR */ \ + PIN_TMS_CLR(); \ + JTAG_CYCLE_TCK(); /* Idle */ \ + PIN_TDI_OUT(1); \ + \ + /* Idle cycles */ \ + n = DAP_Data.transfer.idle_cycles; \ + while (n--) { \ + JTAG_CYCLE_TCK(); /* Idle */ \ + } \ + \ + return (ack); \ +} + + +#undef PIN_DELAY +#define PIN_DELAY() PIN_DELAY_FAST() +JTAG_IR_Function(Fast); +JTAG_TransferFunction(Fast); + +#undef PIN_DELAY +#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) +JTAG_IR_Function(Slow); +JTAG_TransferFunction(Slow); + + +// JTAG Read IDCODE register +// return: value read +uint32_t JTAG_ReadIDCode (void) { + uint32_t bit; + uint32_t val; + uint32_t n; + + PIN_TMS_SET(); + JTAG_CYCLE_TCK(); /* Select-DR-Scan */ + PIN_TMS_CLR(); + JTAG_CYCLE_TCK(); /* Capture-DR */ + JTAG_CYCLE_TCK(); /* Shift-DR */ + + for (n = DAP_Data.jtag_dev.index; n; n--) { + JTAG_CYCLE_TCK(); /* Bypass before data */ + } + + val = 0; + for (n = 31; n; n--) { + JTAG_CYCLE_TDO(bit); /* Get D0..D30 */ + val |= bit << 31; + val >>= 1; + } + PIN_TMS_SET(); + JTAG_CYCLE_TDO(bit); /* Get D31 & Exit1-DR */ + val |= bit << 31; + + JTAG_CYCLE_TCK(); /* Update-DR */ + PIN_TMS_CLR(); + JTAG_CYCLE_TCK(); /* Idle */ + + return (val); +} + + +// JTAG Write ABORT register +// data: value to write +// return: none +void JTAG_WriteAbort (uint32_t data) { + uint32_t n; + + PIN_TMS_SET(); + JTAG_CYCLE_TCK(); /* Select-DR-Scan */ + PIN_TMS_CLR(); + JTAG_CYCLE_TCK(); /* Capture-DR */ + JTAG_CYCLE_TCK(); /* Shift-DR */ + + for (n = DAP_Data.jtag_dev.index; n; n--) { + JTAG_CYCLE_TCK(); /* Bypass before data */ + } + + PIN_TDI_OUT(0); + JTAG_CYCLE_TCK(); /* Set RnW=0 (Write) */ + JTAG_CYCLE_TCK(); /* Set A2=0 */ + JTAG_CYCLE_TCK(); /* Set A3=0 */ + + for (n = 31; n; n--) { + JTAG_CYCLE_TDI(data); /* Set D0..D30 */ + data >>= 1; + } + n = DAP_Data.jtag_dev.count - DAP_Data.jtag_dev.index - 1; + if (n) { + JTAG_CYCLE_TDI(data); /* Set D31 */ + for (--n; n; n--) { + JTAG_CYCLE_TCK(); /* Bypass after data */ + } + PIN_TMS_SET(); + JTAG_CYCLE_TCK(); /* Bypass & Exit1-DR */ + } else { + PIN_TMS_SET(); + JTAG_CYCLE_TDI(data); /* Set D31 & Exit1-DR */ + } + + JTAG_CYCLE_TCK(); /* Update-DR */ + PIN_TMS_CLR(); + JTAG_CYCLE_TCK(); /* Idle */ + PIN_TDI_OUT(1); +} + + +// JTAG Set IR +// ir: IR value +// return: none +void JTAG_IR (uint32_t ir) { + if (DAP_Data.fast_clock) { + JTAG_IR_Fast(ir); + } else { + JTAG_IR_Slow(ir); + } +} + + +// JTAG Transfer I/O +// request: A[3:2] RnW APnDP +// data: DATA[31:0] +// return: ACK[2:0] +uint8_t JTAG_Transfer(uint32_t request, uint32_t *data) { + if (DAP_Data.fast_clock) { + return JTAG_TransferFast(request, data); + } else { + return JTAG_TransferSlow(request, data); + } +} + + +#endif /* (DAP_JTAG != 0) */ diff --git a/SW_DP.c b/SW_DP.c new file mode 100644 index 0000000..abb2276 --- /dev/null +++ b/SW_DP.c @@ -0,0 +1,230 @@ +/* CMSIS-DAP Interface Firmware + * Copyright (c) 2009-2013 ARM Limited + * + * 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 + * + * http://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. + */ + +#include "DAP_config.h" +#include "DAP.h" + + +// SW Macros + +#define PIN_SWCLK_SET PIN_SWCLK_TCK_SET +#define PIN_SWCLK_CLR PIN_SWCLK_TCK_CLR + +#define SW_CLOCK_CYCLE() \ + PIN_SWCLK_CLR(); \ + PIN_DELAY(); \ + PIN_SWCLK_SET(); \ + PIN_DELAY() + +#define SW_WRITE_BIT(bit) \ + PIN_SWDIO_OUT(bit); \ + PIN_SWCLK_CLR(); \ + PIN_DELAY(); \ + PIN_SWCLK_SET(); \ + PIN_DELAY() + +#define SW_READ_BIT(bit) \ + PIN_SWCLK_CLR(); \ + PIN_DELAY(); \ + bit = PIN_SWDIO_IN(); \ + PIN_SWCLK_SET(); \ + PIN_DELAY() + +#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) + + +// Generate SWJ Sequence +// count: sequence bit count +// data: pointer to sequence bit data +// return: none +#if ((DAP_SWD != 0) || (DAP_JTAG != 0)) +void SWJ_Sequence (uint32_t count, uint8_t *data) { + uint32_t val; + uint32_t n; + + val = 0; + n = 0; + while (count--) { + if (n == 0) { + val = *data++; + n = 8; + } + if (val & 1) { + PIN_SWDIO_TMS_SET(); + } else { + PIN_SWDIO_TMS_CLR(); + } + SW_CLOCK_CYCLE(); + val >>= 1; + n--; + } +} +#endif + + +#if (DAP_SWD != 0) + + +// SWD Transfer I/O +// request: A[3:2] RnW APnDP +// data: DATA[31:0] +// return: ACK[2:0] +#define SWD_TransferFunction(speed) /**/ \ +uint8_t SWD_Transfer##speed (uint32_t request, uint32_t *data) { \ + uint32_t ack; \ + uint32_t bit; \ + uint32_t val; \ + uint32_t parity; \ + \ + uint32_t n; \ + \ + /* Packet Request */ \ + parity = 0; \ + SW_WRITE_BIT(1); /* Start Bit */ \ + bit = request >> 0; \ + SW_WRITE_BIT(bit); /* APnDP Bit */ \ + parity += bit; \ + bit = request >> 1; \ + SW_WRITE_BIT(bit); /* RnW Bit */ \ + parity += bit; \ + bit = request >> 2; \ + SW_WRITE_BIT(bit); /* A2 Bit */ \ + parity += bit; \ + bit = request >> 3; \ + SW_WRITE_BIT(bit); /* A3 Bit */ \ + parity += bit; \ + SW_WRITE_BIT(parity); /* Parity Bit */ \ + SW_WRITE_BIT(0); /* Stop Bit */ \ + SW_WRITE_BIT(1); /* Park Bit */ \ + \ + /* Turnaround */ \ + PIN_SWDIO_OUT_DISABLE(); \ + for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ + SW_CLOCK_CYCLE(); \ + } \ + \ + /* Acknowledge response */ \ + SW_READ_BIT(bit); \ + ack = bit << 0; \ + SW_READ_BIT(bit); \ + ack |= bit << 1; \ + SW_READ_BIT(bit); \ + ack |= bit << 2; \ + \ + if (ack == DAP_TRANSFER_OK) { /* OK response */ \ + /* Data transfer */ \ + if (request & DAP_TRANSFER_RnW) { \ + /* Read data */ \ + val = 0; \ + parity = 0; \ + for (n = 32; n; n--) { \ + SW_READ_BIT(bit); /* Read RDATA[0:31] */ \ + parity += bit; \ + val >>= 1; \ + val |= bit << 31; \ + } \ + SW_READ_BIT(bit); /* Read Parity */ \ + if ((parity ^ bit) & 1) { \ + ack = DAP_TRANSFER_ERROR; \ + } \ + if (data) *data = val; \ + /* Turnaround */ \ + for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ + SW_CLOCK_CYCLE(); \ + } \ + PIN_SWDIO_OUT_ENABLE(); \ + } else { \ + /* Turnaround */ \ + for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ + SW_CLOCK_CYCLE(); \ + } \ + PIN_SWDIO_OUT_ENABLE(); \ + /* Write data */ \ + val = *data; \ + parity = 0; \ + for (n = 32; n; n--) { \ + SW_WRITE_BIT(val); /* Write WDATA[0:31] */ \ + parity += val; \ + val >>= 1; \ + } \ + SW_WRITE_BIT(parity); /* Write Parity Bit */ \ + } \ + /* Idle cycles */ \ + n = DAP_Data.transfer.idle_cycles; \ + if (n) { \ + PIN_SWDIO_OUT(0); \ + for (; n; n--) { \ + SW_CLOCK_CYCLE(); \ + } \ + } \ + PIN_SWDIO_OUT(1); \ + return (ack); \ + } \ + \ + if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) { \ + /* WAIT or FAULT response */ \ + if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) != 0)) { \ + for (n = 32+1; n; n--) { \ + SW_CLOCK_CYCLE(); /* Dummy Read RDATA[0:31] + Parity */ \ + } \ + } \ + /* Turnaround */ \ + for (n = DAP_Data.swd_conf.turnaround; n; n--) { \ + SW_CLOCK_CYCLE(); \ + } \ + PIN_SWDIO_OUT_ENABLE(); \ + if (DAP_Data.swd_conf.data_phase && ((request & DAP_TRANSFER_RnW) == 0)) { \ + PIN_SWDIO_OUT(0); \ + for (n = 32+1; n; n--) { \ + SW_CLOCK_CYCLE(); /* Dummy Write WDATA[0:31] + Parity */ \ + } \ + } \ + PIN_SWDIO_OUT(1); \ + return (ack); \ + } \ + \ + /* Protocol error */ \ + for (n = DAP_Data.swd_conf.turnaround + 32 + 1; n; n--) { \ + SW_CLOCK_CYCLE(); /* Back off data phase */ \ + } \ + PIN_SWDIO_OUT(1); \ + return (ack); \ +} + + +#undef PIN_DELAY +#define PIN_DELAY() PIN_DELAY_FAST() +SWD_TransferFunction(Fast); + +#undef PIN_DELAY +#define PIN_DELAY() PIN_DELAY_SLOW(DAP_Data.clock_delay) +SWD_TransferFunction(Slow); + + +// SWD Transfer I/O +// request: A[3:2] RnW APnDP +// data: DATA[31:0] +// return: ACK[2:0] +uint8_t SWD_Transfer(uint32_t request, uint32_t *data) { + if (DAP_Data.fast_clock) { + return SWD_TransferFast(request, data); + } else { + return SWD_TransferSlow(request, data); + } +} + + +#endif /* (DAP_SWD != 0) */ diff --git a/board.c b/board.c new file mode 100644 index 0000000..b7b0105 --- /dev/null +++ b/board.c @@ -0,0 +1,111 @@ +/* CMSIS-DAP Interface Firmware + * Copyright (c) 2009-2013 ARM Limited + * + * 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 + * + * http://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. + */ +#include "board.h" + +/* Each board should have a unique ID and secret. For information + * about obtaining a secret contact support@mbed.org + */ +#if defined (BOARD_FRDM_KL25Z) || defined (BOARD_TWR_KL25Z48M) +#define BOARD_ID "0200" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_FRDM_KL05Z) +#define BOARD_ID "0210" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_FRDM_KL46Z) +#define BOARD_ID "0220" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_FRDM_K20D50M) +#define BOARD_ID "0230" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_FRDM_K22F) +#define BOARD_ID "0231" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_FRDM_K64F) +#define BOARD_ID "0240" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_FRDM_KL02Z) +#define BOARD_ID "0250" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_FRDM_KL26Z) +#define BOARD_ID "0260" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_FRDM_KE02Z) +#define BOARD_ID "0270" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_TWR_K24F) +#define BOARD_ID "0280" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_LPC812_MAX) +#define BOARD_ID "1050" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_SEEED_ARCH_PRO) +#define BOARD_ID "9004" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_UBLOX_C027) +#define BOARD_ID "1234" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_LPC1114) +#define BOARD_ID "1114" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_BAMBINO_210) +#define BOARD_ID "1600" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_BAMBINO_210E) +#define BOARD_ID "1605" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_LPC1549) +#define BOARD_ID "1549" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_LPC11U68) +#define BOARD_ID "1168" +#define BOARD_SECRET "xxxxxxxx" + +#elif defined (BOARD_LPC4337) +#define BOARD_ID "1062" +#define BOARD_SECRET "xxxxxxxx" + +#endif + +#if !defined(BOARD_SECRET) || !defined(BOARD_ID) +// TODO: how to check a string value using the preprocessor... +#error contact support@mbed.org to obtain a secret and board ID +#endif + +BOARD board = { + BOARD_ID, // board id + BOARD_SECRET // board secret +}; + +/* Weak declaration of the board_init function for boards that don't use it */ +__weak void board_init(void) { +} diff --git a/board.h b/board.h new file mode 100644 index 0000000..9994bf6 --- /dev/null +++ b/board.h @@ -0,0 +1,31 @@ +/* CMSIS-DAP Interface Firmware + * Copyright (c) 2009-2013 ARM Limited + * + * 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 + * + * http://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. + */ +#ifndef BOARD_H +#define BOARD_H + +#include + +typedef struct { + const uint8_t id[4]; + const uint8_t secret[9]; +} BOARD; + +extern BOARD board; + +// Init function called in main() before the main task is started +void board_init(void); + +#endif diff --git a/dap_vendor_command.c b/dap_vendor_command.c new file mode 100644 index 0000000..994a97d --- /dev/null +++ b/dap_vendor_command.c @@ -0,0 +1,49 @@ +/* CMSIS-DAP Interface Firmware + * Copyright (c) 2009-2013 ARM Limited + * + * 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 + * + * http://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. + */ +#include +#include +#include + +#include "rl_usb.h" +#include "version.h" +#include "DAP_config.h" +#include "uart.h" +#include "DAP.h" + +// Process DAP Vendor command and prepare response +// Default function (can be overridden) +// request: pointer to request data +// response: pointer to response data +// return: number of bytes in response +// this function is declared as __weak in DAP.c +uint32_t DAP_ProcessVendorCommand(uint8_t *request, uint8_t *response) { + + // get unique ID command + if (*request == ID_DAP_Vendor0) { + uint8_t * id_str = get_uid_string(); + uint8_t len = strlen((const char *)(id_str + 4)); + *response = ID_DAP_Vendor0; + *(response + 1) = len; + memcpy(response + 2, id_str + 4, len); + return (len + 2); + } + + // else return invalid command + else { + *response = ID_DAP_Invalid; + } + return (1); +} diff --git a/debug_cm.h b/debug_cm.h new file mode 100644 index 0000000..3644366 --- /dev/null +++ b/debug_cm.h @@ -0,0 +1,160 @@ +/* CMSIS-DAP Interface Firmware + * Copyright (c) 2009-2013 ARM Limited + * + * 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 + * + * http://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. + */ +#ifndef DEBUG_CM_H +#define DEBUG_CM_H + +// Debug Port Register Addresses +#define DP_IDCODE 0x00 // IDCODE Register (Read only) +#define DP_ABORT 0x00 // Abort Register (Write only) +#define DP_CTRL_STAT 0x04 // Control & Status +#define DP_WCR 0x04 // Wire Control Register (SW Only) +#define DP_DLCR 0x04 // Data Link Control Register (Renamed WCR) +#define DP_SELECT 0x08 // Select Register (JTAG R/W & SW W) +#define DP_RESEND 0x08 // Resend (SW Read Only) +#define DP_RDBUFF 0x0C // Read Buffer (Read Only) + +// Abort Register definitions +#define DAPABORT 0x00000001 // DAP Abort +#define STKCMPCLR 0x00000002 // Clear STICKYCMP Flag (SW Only) +#define STKERRCLR 0x00000004 // Clear STICKYERR Flag (SW Only) +#define WDERRCLR 0x00000008 // Clear WDATAERR Flag (SW Only) +#define ORUNERRCLR 0x00000010 // Clear STICKYORUN Flag (SW Only) + +// Debug Control and Status definitions +#define ORUNDETECT 0x00000001 // Overrun Detect +#define STICKYORUN 0x00000002 // Sticky Overrun +#define TRNMODE 0x0000000C // Transfer Mode Mask +#define TRNNORMAL 0x00000000 // Transfer Mode: Normal +#define TRNVERIFY 0x00000004 // Transfer Mode: Pushed Verify +#define TRNCOMPARE 0x00000008 // Transfer Mode: Pushed Compare +#define STICKYCMP 0x00000010 // Sticky Compare +#define STICKYERR 0x00000020 // Sticky Error +#define READOK 0x00000040 // Read OK (SW Only) +#define WDATAERR 0x00000080 // Write Data Error (SW Only) +#define MASKLANE 0x00000F00 // Mask Lane Mask +#define MASKLANE0 0x00000100 // Mask Lane 0 +#define MASKLANE1 0x00000200 // Mask Lane 1 +#define MASKLANE2 0x00000400 // Mask Lane 2 +#define MASKLANE3 0x00000800 // Mask Lane 3 +#define TRNCNT 0x001FF000 // Transaction Counter Mask +#define CDBGRSTREQ 0x04000000 // Debug Reset Request +#define CDBGRSTACK 0x08000000 // Debug Reset Acknowledge +#define CDBGPWRUPREQ 0x10000000 // Debug Power-up Request +#define CDBGPWRUPACK 0x20000000 // Debug Power-up Acknowledge +#define CSYSPWRUPREQ 0x40000000 // System Power-up Request +#define CSYSPWRUPACK 0x80000000 // System Power-up Acknowledge + +// Debug Select Register definitions +#define CTRLSEL 0x00000001 // CTRLSEL (SW Only) +#define APBANKSEL 0x000000F0 // APBANKSEL Mask +#define APSEL 0xFF000000 // APSEL Mask + +// Access Port Register Addresses +#define AP_CSW 0x00 // Control and Status Word +#define AP_TAR 0x04 // Transfer Address +#define AP_DRW 0x0C // Data Read/Write +#define AP_BD0 0x10 // Banked Data 0 +#define AP_BD1 0x14 // Banked Data 1 +#define AP_BD2 0x18 // Banked Data 2 +#define AP_BD3 0x1C // Banked Data 3 +#define AP_ROM 0xF8 // Debug ROM Address +#define AP_IDR 0xFC // Identification Register + +// AP Control and Status Word definitions +#define CSW_SIZE 0x00000007 // Access Size: Selection Mask +#define CSW_SIZE8 0x00000000 // Access Size: 8-bit +#define CSW_SIZE16 0x00000001 // Access Size: 16-bit +#define CSW_SIZE32 0x00000002 // Access Size: 32-bit +#define CSW_ADDRINC 0x00000030 // Auto Address Increment Mask +#define CSW_NADDRINC 0x00000000 // No Address Increment +#define CSW_SADDRINC 0x00000010 // Single Address Increment +#define CSW_PADDRINC 0x00000020 // Packed Address Increment +#define CSW_DBGSTAT 0x00000040 // Debug Status +#define CSW_TINPROG 0x00000080 // Transfer in progress +#define CSW_HPROT 0x02000000 // User/Privilege Control +#define CSW_MSTRTYPE 0x20000000 // Master Type Mask +#define CSW_MSTRCORE 0x00000000 // Master Type: Core +#define CSW_MSTRDBG 0x20000000 // Master Type: Debug +#define CSW_RESERVED 0x01000000 // Reserved Value + +// Core Debug Register Address Offsets +#define DBG_OFS 0x0DF0 // Debug Register Offset inside NVIC +#define DBG_HCSR_OFS 0x00 // Debug Halting Control & Status Register +#define DBG_CRSR_OFS 0x04 // Debug Core Register Selector Register +#define DBG_CRDR_OFS 0x08 // Debug Core Register Data Register +#define DBG_EMCR_OFS 0x0C // Debug Exception & Monitor Control Register + +// Core Debug Register Addresses +#define DBG_HCSR (DBG_Addr + DBG_HCSR_OFS) +#define DBG_CRSR (DBG_Addr + DBG_CRSR_OFS) +#define DBG_CRDR (DBG_Addr + DBG_CRDR_OFS) +#define DBG_EMCR (DBG_Addr + DBG_EMCR_OFS) + +// Debug Halting Control and Status Register definitions +#define C_DEBUGEN 0x00000001 // Debug Enable +#define C_HALT 0x00000002 // Halt +#define C_STEP 0x00000004 // Step +#define C_MASKINTS 0x00000008 // Mask Interrupts +#define C_SNAPSTALL 0x00000020 // Snap Stall +#define S_REGRDY 0x00010000 // Register R/W Ready Flag +#define S_HALT 0x00020000 // Halt Flag +#define S_SLEEP 0x00040000 // Sleep Flag +#define S_LOCKUP 0x00080000 // Lockup Flag +#define S_RETIRE_ST 0x01000000 // Sticky Retire Flag +#define S_RESET_ST 0x02000000 // Sticky Reset Flag +#define DBGKEY 0xA05F0000 // Debug Key + +// Debug Exception and Monitor Control Register definitions +#define VC_CORERESET 0x00000001 // Reset Vector Catch +#define VC_MMERR 0x00000010 // Debug Trap on MMU Fault +#define VC_NOCPERR 0x00000020 // Debug Trap on No Coprocessor Fault +#define VC_CHKERR 0x00000040 // Debug Trap on Checking Error Fault +#define VC_STATERR 0x00000080 // Debug Trap on State Error Fault +#define VC_BUSERR 0x00000100 // Debug Trap on Bus Error Fault +#define VC_INTERR 0x00000200 // Debug Trap on Interrupt Error Fault +#define VC_HARDERR 0x00000400 // Debug Trap on Hard Fault +#define MON_EN 0x00010000 // Monitor Enable +#define MON_PEND 0x00020000 // Monitor Pend +#define MON_STEP 0x00040000 // Monitor Step +#define MON_REQ 0x00080000 // Monitor Request +#define TRCENA 0x01000000 // Trace Enable (DWT, ITM, ETM, TPIU) + +// NVIC: Interrupt Controller Type Register +#define NVIC_ICT (NVIC_Addr + 0x0004) +#define INTLINESNUM 0x0000001F // Interrupt Line Numbers + +// NVIC: CPUID Base Register +#define NVIC_CPUID (NVIC_Addr + 0x0D00) +#define CPUID_PARTNO 0x0000FFF0 // Part Number Mask +#define CPUID_REVISION 0x0000000F // Revision Mask +#define CPUID_VARIANT 0x00F00000 // Variant Mask + +// NVIC: Application Interrupt/Reset Control Register +#define NVIC_AIRCR (NVIC_Addr + 0x0D0C) +#define VECTRESET 0x00000001 // Reset Cortex-M (except Debug) +#define VECTCLRACTIVE 0x00000002 // Clear Active Vector Bit +#define SYSRESETREQ 0x00000004 // Reset System (except Debug) +#define VECTKEY 0x05FA0000 // Write Key + +// NVIC: Debug Fault Status Register +#define NVIC_DFSR (NVIC_Addr + 0x0D30) +#define HALTED 0x00000001 // Halt Flag +#define BKPT 0x00000002 // BKPT Flag +#define DWTTRAP 0x00000004 // DWT Match +#define VCATCH 0x00000008 // Vector Catch Flag +#define EXTERNAL 0x00000010 // External Debug Request + +#endif diff --git a/gpio.h b/gpio.h new file mode 100644 index 0000000..45b6b56 --- /dev/null +++ b/gpio.h @@ -0,0 +1,25 @@ +/* CMSIS-DAP Interface Firmware + * Copyright (c) 2009-2013 ARM Limited + * + * 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 + * + * http://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. + */ +#ifndef GPIO_H +#define GPIO_H + +void gpio_init(void); +void gpio_enable_button_flag(OS_TID task, uint16_t flag); +void gpio_set_dap_led(uint8_t state); +void gpio_set_cdc_led(uint8_t state); +void gpio_set_msd_led(uint8_t state); + +#endif diff --git a/read_uid.h b/read_uid.h new file mode 100644 index 0000000..f8c0a9b --- /dev/null +++ b/read_uid.h @@ -0,0 +1,27 @@ +/* CMSIS-DAP Interface Firmware + * Copyright (c) 2009-2013 ARM Limited + * + * 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 + * + * http://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. + */ +#ifndef READ_UID_H +#define READ_UID_H + +#include + +void read_unique_id(uint32_t * id); + +#ifdef BOARD_UBLOX_C027 +void __svc(2) enter_isp(void); +#endif + +#endif diff --git a/semihost.c b/semihost.c new file mode 100644 index 0000000..e8cab67 --- /dev/null +++ b/semihost.c @@ -0,0 +1,230 @@ +/* CMSIS-DAP Interface Firmware + * Copyright (c) 2009-2013 ARM Limited + * + * 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 + * + * http://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. + */ +#ifdef SEMIHOST + +#include +#include + +#include "tasks.h" +#include "main.h" + +#include "target_reset.h" +#include "version.h" +#include "swd_host.h" +#include "semihost.h" + +#define RESERVED_FOR_USER_APPLICATIONS (0x100) /* 0x100 - 0x1ff */ +#define USR_UID (RESERVED_FOR_USER_APPLICATIONS + 1) +#define USR_RESET (RESERVED_FOR_USER_APPLICATIONS + 2) +#define USR_POWERDOWN (RESERVED_FOR_USER_APPLICATIONS + 4) +#define USR_DISABLEDEBUG (RESERVED_FOR_USER_APPLICATIONS + 5) +#define angel_SWIreason_ReportException (0x18) + +#define FLAGS_SH_START (1) +#define FLAGS_SH_STOP (2) + +static OS_TID semihostTask; +static OS_SEM semihostStoppedSem; +static uint8_t semihostEnabled; +static uint32_t r0, r1; + +static int shReadWord(uint32_t address, uint32_t *ptr) { + return swd_read_memory(address, (uint8_t *)ptr, sizeof(uint32_t)); +} + +static int shWriteBytes(uint32_t address, uint8_t *ptr, uint32_t count) { + return swd_write_memory(address, ptr, count); +} + +static int sh_usr_uid(uint32_t *r0, uint32_t r1) { + uint32_t p1, p2; + uint32_t uidSize; + uint32_t i; + uint8_t null = '\0'; + uint8_t * id_str; + + // Read parameter block + if (!shReadWord(r1, &p1)) + return 0; + + if (!shReadWord(r1+4, &p2)) + return 0; + + id_str = get_uid_string(); + uidSize = strlen((const char *)id_str) - 4; + + // Validate parameters + if (p1 == NULL) return 1; + if (p2 != (uidSize+1)) return 1; // +1 for null string terminator + + // skip " $ $ $ length" + id_str += 4; + + // Write data to target + for (i = 0; i < uidSize; i++) { + if (!shWriteBytes(p1++, id_str, 1)) + return 0; + id_str++; + } + // Write null terminator to target + if (!shWriteBytes(p1, &null, 1)) + return 0; + + *r0 = 0; // Successful + return 1; +} + +static int sh_usr_reset(uint32_t *r0, uint32_t r1) { + main_reset_target(0); + + // Don't restart target as the target will be resetted + return 0; +} + +static int sh_report_exception(uint32_t *r0, uint32_t r1) { + uint32_t p1; + + // Read paramter block + if (!shReadWord(r1, &p1)) return 0; + + // TODO: r1 does not appear to be set a to a useful value, contrary to the ARM documentation? See: + // DUI0205G_rvct_compiler_and_libraries_guide.pdf 7.4.2 angel_SWIreason_ReportException (0x18) + return 1; +} + + +static int sh_usr_powerdown(uint32_t *r0, uint32_t r1) { + main_powerdown_event(); + + // successful + *r0 = 0; + return 1; +} + +static int sh_usr_disabledebug(uint32_t *r0, uint32_t r1) { + main_disable_debug_event(); + + // successful + *r0 = 0; + return 1; +} + +static int process_event(void) { + // Returns TRUE if successful, FALSE if an error occurs + uint32_t svc; + + svc = r0; + + // Set default return value + r0 = 0xffffffff; + + switch(svc) { + case USR_UID: + if (!sh_usr_uid(&r0,r1)) return 0; + break; + case USR_RESET: + if (!sh_usr_reset(&r0,r1)) return 0; + break; + case USR_POWERDOWN: + if (!sh_usr_powerdown(&r0,r1)) return 0; + break; + case USR_DISABLEDEBUG: + if (!sh_usr_disabledebug(&r0,r1)) return 0; + break; + case angel_SWIreason_ReportException: + if (!sh_report_exception(&r0,r1)) return 0; + break; + default: + break; + } + + return 1; +} + +static void sh_main(void) { + while(1) { + // Wait for start flag + os_evt_wait_or(FLAGS_SH_START, NO_TIMEOUT); + + do { + if (swd_is_semihost_event(&r0, &r1)) { + if (process_event()) { + swd_semihost_restart(r0); + } + } else { + // Wait for 2 scheduler tick; the serial task may run at this point + os_dly_wait(2); + } + // Loop until stop flag is set + } while (os_evt_wait_or(FLAGS_SH_STOP, 0 )==OS_R_TMO); + + // Stopped + os_sem_send(semihostStoppedSem); + } +} + +void semihost_init(void) { + // Called from main task + + semihostEnabled = 0; + os_sem_init(semihostStoppedSem,0); + + // Create semihost task + semihostTask = os_tsk_create(sh_main, SEMIHOST_TASK_PRIORITY); + return; +} + +void semihost_enable(void) { + // Called from: + // - main task when the interface firmware starts + // - cmsis-dap when a debugger closes the swd port + // - drag n drop when a binary has been flashed + + if (semihostEnabled) return; + if (semihostTask==0) return; + + // enable debug + target_set_state(DEBUG); + + os_evt_set(FLAGS_SH_START, semihostTask); + + semihostEnabled = 1; + + return; +} + +void semihost_disable(void) { + // Called from: + // - main task when the the interface receives the POWERDOWN semihost call + // - cmsis-dap when a debugger opens the swd port + // - drag n drop when a binary will be flashed + + if (!semihostEnabled) return; + if (semihostTask==0) return; + + os_evt_set(FLAGS_SH_STOP, semihostTask); + + // Wait for semihost task to stop + os_sem_wait(semihostStoppedSem, NO_TIMEOUT); + semihostEnabled = 0; + return; +} + +#else /* #ifndef SEMIHOST */ +void semihost_init(void) { } +void semihost_enable(void) { } +void semihost_disable(void){ } +#endif diff --git a/semihost.h b/semihost.h new file mode 100644 index 0000000..4fb876b --- /dev/null +++ b/semihost.h @@ -0,0 +1,23 @@ +/* CMSIS-DAP Interface Firmware + * Copyright (c) 2009-2013 ARM Limited + * + * 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 + * + * http://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. + */ +#ifndef SEMIHOST_H +#define SEMIHOST_H + +void semihost_init(void); +void semihost_enable(void); +void semihost_disable(void); + +#endif diff --git a/target_reset.h b/target_reset.h new file mode 100644 index 0000000..38a75b0 --- /dev/null +++ b/target_reset.h @@ -0,0 +1,25 @@ +/* CMSIS-DAP Interface Firmware + * Copyright (c) 2009-2013 ARM Limited + * + * 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 + * + * http://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. + */ +#ifndef TARGET_RESET_H +#define TARGET_RESET_H + +#include "target_struct.h" + +void target_before_init_debug(void); +uint8_t target_unlock_sequence(void); +uint8_t target_set_state(TARGET_RESET_STATE state); + +#endif diff --git a/target_struct.h b/target_struct.h new file mode 100644 index 0000000..71eac42 --- /dev/null +++ b/target_struct.h @@ -0,0 +1,55 @@ +/* CMSIS-DAP Interface Firmware + * Copyright (c) 2009-2013 ARM Limited + * + * 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 + * + * http://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. + */ +#ifndef TARGET_H +#define TARGET_H + +#include + +typedef struct { + uint32_t breakpoint; + uint32_t static_base; + uint32_t stack_pointer; +} FLASH_SYSCALL; + +typedef struct { + + uint32_t init; + uint32_t uninit; + uint32_t erase_chip; + uint32_t erase_sector; + uint32_t program_page; + + FLASH_SYSCALL sys_call_param; + + uint32_t program_buffer; + uint32_t algo_start; + uint32_t algo_size; + const uint32_t * image; + + uint32_t ram_to_flash_bytes_to_be_written; + +} TARGET_FLASH; + +typedef enum { + RESET_HOLD, // Hold target in reset + RESET_PROGRAM, // Reset target and setup for flash programming. + RESET_RUN, // Reset target and run normally + RESET_RUN_WITH_DEBUG, // Reset target and run with debug enabled (required for semihost) + NO_DEBUG, // Disable debug on running target + DEBUG // Enable debug on running target +} TARGET_RESET_STATE; + +#endif diff --git a/tasks.h b/tasks.h new file mode 100644 index 0000000..4b0a564 --- /dev/null +++ b/tasks.h @@ -0,0 +1,38 @@ +/* CMSIS-DAP Interface Firmware + * Copyright (c) 2009-2013 ARM Limited + * + * 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 + * + * http://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. + */ +#ifndef TASK_H +#define TASK_H + +#define NO_TIMEOUT (0xffff) + +#define LOWEST_PRIORITY (1) /* Priority 0 is reserved for the RTX idle task */ +#define HIGHEST_PRIORITY (254) /* Priority 255 is reserved by RTX */ + +#define MAIN_TASK_PRIORITY (8) +#define SERIAL_TASK_PRIORITY (1) +#define TIMER_TASK_PRIORITY (11) +#define DAP_TASK_PRIORITY (15) +#define MSC_TASK_PRIORITY (5) +#define TIMER_TASK_30_PRIORITY (TIMER_TASK_PRIORITY) +#define SEMIHOST_TASK_PRIORITY (2) + +#define TIMER_TASK_30_STACK (100) +#define DAP_TASK_STACK (400) +#define SERIAL_TASK_STACK (400) +#define MSC_TASK_STACK (200) +#define MAIN_TASK_STACK (200) + +#endif diff --git a/uart.h b/uart.h new file mode 100644 index 0000000..c759d13 --- /dev/null +++ b/uart.h @@ -0,0 +1,76 @@ +/* CMSIS-DAP Interface Firmware + * Copyright (c) 2009-2013 ARM Limited + * + * 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 + * + * http://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. + */ +#ifndef UART_H +#define UART_H + +#include + +/* Parity enumerator */ +typedef enum { + UART_PARITY_NONE = 0, + UART_PARITY_ODD = 1, + UART_PARITY_EVEN = 2, + UART_PARITY_MARK = 3, + UART_PARITY_SPACE = 4 +} UART_Parity; + +/* Stop Bits enumerator */ +typedef enum { + UART_STOP_BITS_1 = 0, + UART_STOP_BITS_1_5 = 1, + UART_STOP_BITS_2 = 2 +} UART_StopBits; + +/* Data Bits enumerator */ +typedef enum { + UART_DATA_BITS_5 = 5, + UART_DATA_BITS_6 = 6, + UART_DATA_BITS_7 = 7, + UART_DATA_BITS_8 = 8, + UART_DATA_BITS_16 = 16 +} UART_DataBits; + +/* Flow control enumerator */ +typedef enum { + UART_FLOW_CONTROL_NONE = 0, + UART_FLOW_CONTROL_RTS_CTS = 1, + UART_FLOW_CONTROL_XON_XOFF = 2 +} UART_FlowControl; + +/* UART Port Properties structure */ +typedef struct { + uint32_t Baudrate; + UART_DataBits DataBits; + UART_Parity Parity; + UART_StopBits StopBits; + UART_FlowControl FlowControl; +} UART_Configuration; + +/*----------------------------------------------------------------------------- + * FUNCTION PROTOTYPES + *----------------------------------------------------------------------------*/ + +/* UART driver function prototypes */ +extern int32_t uart_initialize (void); +extern int32_t uart_uninitialize (void); +extern int32_t uart_reset (void); +extern int32_t uart_set_configuration (UART_Configuration *config); +extern int32_t uart_get_configuration (UART_Configuration *config); +extern int32_t uart_write_free (void); +extern int32_t uart_write_data (uint8_t *data, uint16_t size); +extern int32_t uart_read_data (uint8_t *data, uint16_t size); + +#endif /* __UART_H */