Repostiory containing DAPLink source code with Reset Pin workaround for HANI_IOT board.

Upstream: https://github.com/ARMmbed/DAPLink

Committer:
Pawel Zarembski
Date:
Tue Apr 07 12:55:42 2020 +0200
Revision:
0:01f31e923fe2
hani: DAPLink with reset workaround

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Pawel Zarembski 0:01f31e923fe2 1 /**
Pawel Zarembski 0:01f31e923fe2 2 * @file swd_host.c
Pawel Zarembski 0:01f31e923fe2 3 * @brief Implementation of swd_host.h
Pawel Zarembski 0:01f31e923fe2 4 *
Pawel Zarembski 0:01f31e923fe2 5 * DAPLink Interface Firmware
Pawel Zarembski 0:01f31e923fe2 6 * Copyright (c) 2009-2019, ARM Limited, All Rights Reserved
Pawel Zarembski 0:01f31e923fe2 7 * Copyright 2019, Cypress Semiconductor Corporation
Pawel Zarembski 0:01f31e923fe2 8 * or a subsidiary of Cypress Semiconductor Corporation.
Pawel Zarembski 0:01f31e923fe2 9 * SPDX-License-Identifier: Apache-2.0
Pawel Zarembski 0:01f31e923fe2 10 *
Pawel Zarembski 0:01f31e923fe2 11 * Licensed under the Apache License, Version 2.0 (the "License"); you may
Pawel Zarembski 0:01f31e923fe2 12 * not use this file except in compliance with the License.
Pawel Zarembski 0:01f31e923fe2 13 * You may obtain a copy of the License at
Pawel Zarembski 0:01f31e923fe2 14 *
Pawel Zarembski 0:01f31e923fe2 15 * http://www.apache.org/licenses/LICENSE-2.0
Pawel Zarembski 0:01f31e923fe2 16 *
Pawel Zarembski 0:01f31e923fe2 17 * Unless required by applicable law or agreed to in writing, software
Pawel Zarembski 0:01f31e923fe2 18 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
Pawel Zarembski 0:01f31e923fe2 19 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Pawel Zarembski 0:01f31e923fe2 20 * See the License for the specific language governing permissions and
Pawel Zarembski 0:01f31e923fe2 21 * limitations under the License.
Pawel Zarembski 0:01f31e923fe2 22 */
Pawel Zarembski 0:01f31e923fe2 23
Pawel Zarembski 0:01f31e923fe2 24 #ifndef TARGET_MCU_CORTEX_A
Pawel Zarembski 0:01f31e923fe2 25 #include "cmsis_os2.h"
Pawel Zarembski 0:01f31e923fe2 26 #include "target_config.h"
Pawel Zarembski 0:01f31e923fe2 27 #include "swd_host.h"
Pawel Zarembski 0:01f31e923fe2 28 #include "debug_cm.h"
Pawel Zarembski 0:01f31e923fe2 29 #include "DAP_config.h"
Pawel Zarembski 0:01f31e923fe2 30 #include "DAP.h"
Pawel Zarembski 0:01f31e923fe2 31 #include "target_family.h"
Pawel Zarembski 0:01f31e923fe2 32 #include "device.h"
Pawel Zarembski 0:01f31e923fe2 33
Pawel Zarembski 0:01f31e923fe2 34 // Default NVIC and Core debug base addresses
Pawel Zarembski 0:01f31e923fe2 35 // TODO: Read these addresses from ROM.
Pawel Zarembski 0:01f31e923fe2 36 #define NVIC_Addr (0xe000e000)
Pawel Zarembski 0:01f31e923fe2 37 #define DBG_Addr (0xe000edf0)
Pawel Zarembski 0:01f31e923fe2 38
Pawel Zarembski 0:01f31e923fe2 39 // AP CSW register, base value
Pawel Zarembski 0:01f31e923fe2 40 #define CSW_VALUE (CSW_RESERVED | CSW_MSTRDBG | CSW_HPROT | CSW_DBGSTAT | CSW_SADDRINC)
Pawel Zarembski 0:01f31e923fe2 41
Pawel Zarembski 0:01f31e923fe2 42 #define DCRDR 0xE000EDF8
Pawel Zarembski 0:01f31e923fe2 43 #define DCRSR 0xE000EDF4
Pawel Zarembski 0:01f31e923fe2 44 #define DHCSR 0xE000EDF0
Pawel Zarembski 0:01f31e923fe2 45 #define REGWnR (1 << 16)
Pawel Zarembski 0:01f31e923fe2 46
Pawel Zarembski 0:01f31e923fe2 47 #define MAX_SWD_RETRY 100//10
Pawel Zarembski 0:01f31e923fe2 48 #define MAX_TIMEOUT 1000000 // Timeout for syscalls on target
Pawel Zarembski 0:01f31e923fe2 49
Pawel Zarembski 0:01f31e923fe2 50 // Use the CMSIS-Core definition if available.
Pawel Zarembski 0:01f31e923fe2 51 #if !defined(SCB_AIRCR_PRIGROUP_Pos)
Pawel Zarembski 0:01f31e923fe2 52 #define SCB_AIRCR_PRIGROUP_Pos 8U /*!< SCB AIRCR: PRIGROUP Position */
Pawel Zarembski 0:01f31e923fe2 53 #define SCB_AIRCR_PRIGROUP_Msk (7UL << SCB_AIRCR_PRIGROUP_Pos) /*!< SCB AIRCR: PRIGROUP Mask */
Pawel Zarembski 0:01f31e923fe2 54 #endif
Pawel Zarembski 0:01f31e923fe2 55
Pawel Zarembski 0:01f31e923fe2 56 typedef struct {
Pawel Zarembski 0:01f31e923fe2 57 uint32_t select;
Pawel Zarembski 0:01f31e923fe2 58 uint32_t csw;
Pawel Zarembski 0:01f31e923fe2 59 } DAP_STATE;
Pawel Zarembski 0:01f31e923fe2 60
Pawel Zarembski 0:01f31e923fe2 61 typedef struct {
Pawel Zarembski 0:01f31e923fe2 62 uint32_t r[16];
Pawel Zarembski 0:01f31e923fe2 63 uint32_t xpsr;
Pawel Zarembski 0:01f31e923fe2 64 } DEBUG_STATE;
Pawel Zarembski 0:01f31e923fe2 65
Pawel Zarembski 0:01f31e923fe2 66 static SWD_CONNECT_TYPE reset_connect = CONNECT_NORMAL;
Pawel Zarembski 0:01f31e923fe2 67
Pawel Zarembski 0:01f31e923fe2 68 static DAP_STATE dap_state;
Pawel Zarembski 0:01f31e923fe2 69 static uint32_t soft_reset = SYSRESETREQ;
Pawel Zarembski 0:01f31e923fe2 70
Pawel Zarembski 0:01f31e923fe2 71 static uint32_t swd_get_apsel(uint32_t adr)
Pawel Zarembski 0:01f31e923fe2 72 {
Pawel Zarembski 0:01f31e923fe2 73 uint32_t apsel = target_get_apsel();
Pawel Zarembski 0:01f31e923fe2 74 if (!apsel)
Pawel Zarembski 0:01f31e923fe2 75 return adr & 0xff000000;
Pawel Zarembski 0:01f31e923fe2 76 else
Pawel Zarembski 0:01f31e923fe2 77 return apsel;
Pawel Zarembski 0:01f31e923fe2 78 }
Pawel Zarembski 0:01f31e923fe2 79
Pawel Zarembski 0:01f31e923fe2 80 void swd_set_reset_connect(SWD_CONNECT_TYPE type)
Pawel Zarembski 0:01f31e923fe2 81 {
Pawel Zarembski 0:01f31e923fe2 82 reset_connect = type;
Pawel Zarembski 0:01f31e923fe2 83 }
Pawel Zarembski 0:01f31e923fe2 84
Pawel Zarembski 0:01f31e923fe2 85 void int2array(uint8_t *res, uint32_t data, uint8_t len)
Pawel Zarembski 0:01f31e923fe2 86 {
Pawel Zarembski 0:01f31e923fe2 87 uint8_t i = 0;
Pawel Zarembski 0:01f31e923fe2 88
Pawel Zarembski 0:01f31e923fe2 89 for (i = 0; i < len; i++) {
Pawel Zarembski 0:01f31e923fe2 90 res[i] = (data >> 8 * i) & 0xff;
Pawel Zarembski 0:01f31e923fe2 91 }
Pawel Zarembski 0:01f31e923fe2 92 }
Pawel Zarembski 0:01f31e923fe2 93
Pawel Zarembski 0:01f31e923fe2 94 uint8_t swd_transfer_retry(uint32_t req, uint32_t *data)
Pawel Zarembski 0:01f31e923fe2 95 {
Pawel Zarembski 0:01f31e923fe2 96 uint8_t i, ack;
Pawel Zarembski 0:01f31e923fe2 97
Pawel Zarembski 0:01f31e923fe2 98 for (i = 0; i < MAX_SWD_RETRY; i++) {
Pawel Zarembski 0:01f31e923fe2 99 ack = SWD_Transfer(req, data);
Pawel Zarembski 0:01f31e923fe2 100
Pawel Zarembski 0:01f31e923fe2 101 // if ack != WAIT
Pawel Zarembski 0:01f31e923fe2 102 if (ack != DAP_TRANSFER_WAIT) {
Pawel Zarembski 0:01f31e923fe2 103 return ack;
Pawel Zarembski 0:01f31e923fe2 104 }
Pawel Zarembski 0:01f31e923fe2 105 }
Pawel Zarembski 0:01f31e923fe2 106
Pawel Zarembski 0:01f31e923fe2 107 return ack;
Pawel Zarembski 0:01f31e923fe2 108 }
Pawel Zarembski 0:01f31e923fe2 109
Pawel Zarembski 0:01f31e923fe2 110 void swd_set_soft_reset(uint32_t soft_reset_type)
Pawel Zarembski 0:01f31e923fe2 111 {
Pawel Zarembski 0:01f31e923fe2 112 soft_reset = soft_reset_type;
Pawel Zarembski 0:01f31e923fe2 113 }
Pawel Zarembski 0:01f31e923fe2 114
Pawel Zarembski 0:01f31e923fe2 115 uint8_t swd_init(void)
Pawel Zarembski 0:01f31e923fe2 116 {
Pawel Zarembski 0:01f31e923fe2 117 //TODO - DAP_Setup puts GPIO pins in a hi-z state which can
Pawel Zarembski 0:01f31e923fe2 118 // cause problems on re-init. This needs to be investigated
Pawel Zarembski 0:01f31e923fe2 119 // and fixed.
Pawel Zarembski 0:01f31e923fe2 120 DAP_Setup();
Pawel Zarembski 0:01f31e923fe2 121 PORT_SWD_SETUP();
Pawel Zarembski 0:01f31e923fe2 122 return 1;
Pawel Zarembski 0:01f31e923fe2 123 }
Pawel Zarembski 0:01f31e923fe2 124
Pawel Zarembski 0:01f31e923fe2 125 uint8_t swd_off(void)
Pawel Zarembski 0:01f31e923fe2 126 {
Pawel Zarembski 0:01f31e923fe2 127 PORT_OFF();
Pawel Zarembski 0:01f31e923fe2 128 return 1;
Pawel Zarembski 0:01f31e923fe2 129 }
Pawel Zarembski 0:01f31e923fe2 130
Pawel Zarembski 0:01f31e923fe2 131 uint8_t swd_clear_errors(void)
Pawel Zarembski 0:01f31e923fe2 132 {
Pawel Zarembski 0:01f31e923fe2 133 if (!swd_write_dp(DP_ABORT, STKCMPCLR | STKERRCLR | WDERRCLR | ORUNERRCLR)) {
Pawel Zarembski 0:01f31e923fe2 134 return 0;
Pawel Zarembski 0:01f31e923fe2 135 }
Pawel Zarembski 0:01f31e923fe2 136 return 1;
Pawel Zarembski 0:01f31e923fe2 137 }
Pawel Zarembski 0:01f31e923fe2 138
Pawel Zarembski 0:01f31e923fe2 139 // Read debug port register.
Pawel Zarembski 0:01f31e923fe2 140 uint8_t swd_read_dp(uint8_t adr, uint32_t *val)
Pawel Zarembski 0:01f31e923fe2 141 {
Pawel Zarembski 0:01f31e923fe2 142 uint32_t tmp_in;
Pawel Zarembski 0:01f31e923fe2 143 uint8_t tmp_out[4];
Pawel Zarembski 0:01f31e923fe2 144 uint8_t ack;
Pawel Zarembski 0:01f31e923fe2 145 uint32_t tmp;
Pawel Zarembski 0:01f31e923fe2 146 tmp_in = SWD_REG_DP | SWD_REG_R | SWD_REG_ADR(adr);
Pawel Zarembski 0:01f31e923fe2 147 ack = swd_transfer_retry(tmp_in, (uint32_t *)tmp_out);
Pawel Zarembski 0:01f31e923fe2 148 *val = 0;
Pawel Zarembski 0:01f31e923fe2 149 tmp = tmp_out[3];
Pawel Zarembski 0:01f31e923fe2 150 *val |= (tmp << 24);
Pawel Zarembski 0:01f31e923fe2 151 tmp = tmp_out[2];
Pawel Zarembski 0:01f31e923fe2 152 *val |= (tmp << 16);
Pawel Zarembski 0:01f31e923fe2 153 tmp = tmp_out[1];
Pawel Zarembski 0:01f31e923fe2 154 *val |= (tmp << 8);
Pawel Zarembski 0:01f31e923fe2 155 tmp = tmp_out[0];
Pawel Zarembski 0:01f31e923fe2 156 *val |= (tmp << 0);
Pawel Zarembski 0:01f31e923fe2 157 return (ack == 0x01);
Pawel Zarembski 0:01f31e923fe2 158 }
Pawel Zarembski 0:01f31e923fe2 159
Pawel Zarembski 0:01f31e923fe2 160 // Write debug port register
Pawel Zarembski 0:01f31e923fe2 161 uint8_t swd_write_dp(uint8_t adr, uint32_t val)
Pawel Zarembski 0:01f31e923fe2 162 {
Pawel Zarembski 0:01f31e923fe2 163 uint32_t req;
Pawel Zarembski 0:01f31e923fe2 164 uint8_t data[4];
Pawel Zarembski 0:01f31e923fe2 165 uint8_t ack;
Pawel Zarembski 0:01f31e923fe2 166
Pawel Zarembski 0:01f31e923fe2 167 //check if the right bank is already selected
Pawel Zarembski 0:01f31e923fe2 168 if ((adr == DP_SELECT) && (dap_state.select == val)) {
Pawel Zarembski 0:01f31e923fe2 169 return 1;
Pawel Zarembski 0:01f31e923fe2 170 }
Pawel Zarembski 0:01f31e923fe2 171
Pawel Zarembski 0:01f31e923fe2 172 req = SWD_REG_DP | SWD_REG_W | SWD_REG_ADR(adr);
Pawel Zarembski 0:01f31e923fe2 173 int2array(data, val, 4);
Pawel Zarembski 0:01f31e923fe2 174 ack = swd_transfer_retry(req, (uint32_t *)data);
Pawel Zarembski 0:01f31e923fe2 175 if ((ack == DAP_TRANSFER_OK) && (adr == DP_SELECT)) {
Pawel Zarembski 0:01f31e923fe2 176 dap_state.select = val;
Pawel Zarembski 0:01f31e923fe2 177 }
Pawel Zarembski 0:01f31e923fe2 178 return (ack == 0x01);
Pawel Zarembski 0:01f31e923fe2 179 }
Pawel Zarembski 0:01f31e923fe2 180
Pawel Zarembski 0:01f31e923fe2 181 // Read access port register.
Pawel Zarembski 0:01f31e923fe2 182 uint8_t swd_read_ap(uint32_t adr, uint32_t *val)
Pawel Zarembski 0:01f31e923fe2 183 {
Pawel Zarembski 0:01f31e923fe2 184 uint8_t tmp_in, ack;
Pawel Zarembski 0:01f31e923fe2 185 uint8_t tmp_out[4];
Pawel Zarembski 0:01f31e923fe2 186 uint32_t tmp;
Pawel Zarembski 0:01f31e923fe2 187 uint32_t apsel = swd_get_apsel(adr);
Pawel Zarembski 0:01f31e923fe2 188 uint32_t bank_sel = adr & APBANKSEL;
Pawel Zarembski 0:01f31e923fe2 189
Pawel Zarembski 0:01f31e923fe2 190 if (!swd_write_dp(DP_SELECT, apsel | bank_sel)) {
Pawel Zarembski 0:01f31e923fe2 191 return 0;
Pawel Zarembski 0:01f31e923fe2 192 }
Pawel Zarembski 0:01f31e923fe2 193
Pawel Zarembski 0:01f31e923fe2 194 tmp_in = SWD_REG_AP | SWD_REG_R | SWD_REG_ADR(adr);
Pawel Zarembski 0:01f31e923fe2 195 // first dummy read
Pawel Zarembski 0:01f31e923fe2 196 swd_transfer_retry(tmp_in, (uint32_t *)tmp_out);
Pawel Zarembski 0:01f31e923fe2 197 ack = swd_transfer_retry(tmp_in, (uint32_t *)tmp_out);
Pawel Zarembski 0:01f31e923fe2 198 *val = 0;
Pawel Zarembski 0:01f31e923fe2 199 tmp = tmp_out[3];
Pawel Zarembski 0:01f31e923fe2 200 *val |= (tmp << 24);
Pawel Zarembski 0:01f31e923fe2 201 tmp = tmp_out[2];
Pawel Zarembski 0:01f31e923fe2 202 *val |= (tmp << 16);
Pawel Zarembski 0:01f31e923fe2 203 tmp = tmp_out[1];
Pawel Zarembski 0:01f31e923fe2 204 *val |= (tmp << 8);
Pawel Zarembski 0:01f31e923fe2 205 tmp = tmp_out[0];
Pawel Zarembski 0:01f31e923fe2 206 *val |= (tmp << 0);
Pawel Zarembski 0:01f31e923fe2 207 return (ack == 0x01);
Pawel Zarembski 0:01f31e923fe2 208 }
Pawel Zarembski 0:01f31e923fe2 209
Pawel Zarembski 0:01f31e923fe2 210 // Write access port register
Pawel Zarembski 0:01f31e923fe2 211 uint8_t swd_write_ap(uint32_t adr, uint32_t val)
Pawel Zarembski 0:01f31e923fe2 212 {
Pawel Zarembski 0:01f31e923fe2 213 uint8_t data[4];
Pawel Zarembski 0:01f31e923fe2 214 uint8_t req, ack;
Pawel Zarembski 0:01f31e923fe2 215 uint32_t apsel = swd_get_apsel(adr);
Pawel Zarembski 0:01f31e923fe2 216 uint32_t bank_sel = adr & APBANKSEL;
Pawel Zarembski 0:01f31e923fe2 217
Pawel Zarembski 0:01f31e923fe2 218 if (!swd_write_dp(DP_SELECT, apsel | bank_sel)) {
Pawel Zarembski 0:01f31e923fe2 219 return 0;
Pawel Zarembski 0:01f31e923fe2 220 }
Pawel Zarembski 0:01f31e923fe2 221
Pawel Zarembski 0:01f31e923fe2 222 switch (adr) {
Pawel Zarembski 0:01f31e923fe2 223 case AP_CSW:
Pawel Zarembski 0:01f31e923fe2 224 if (dap_state.csw == val) {
Pawel Zarembski 0:01f31e923fe2 225 return 1;
Pawel Zarembski 0:01f31e923fe2 226 }
Pawel Zarembski 0:01f31e923fe2 227
Pawel Zarembski 0:01f31e923fe2 228 dap_state.csw = val;
Pawel Zarembski 0:01f31e923fe2 229 break;
Pawel Zarembski 0:01f31e923fe2 230
Pawel Zarembski 0:01f31e923fe2 231 default:
Pawel Zarembski 0:01f31e923fe2 232 break;
Pawel Zarembski 0:01f31e923fe2 233 }
Pawel Zarembski 0:01f31e923fe2 234
Pawel Zarembski 0:01f31e923fe2 235 req = SWD_REG_AP | SWD_REG_W | SWD_REG_ADR(adr);
Pawel Zarembski 0:01f31e923fe2 236 int2array(data, val, 4);
Pawel Zarembski 0:01f31e923fe2 237
Pawel Zarembski 0:01f31e923fe2 238 if (swd_transfer_retry(req, (uint32_t *)data) != 0x01) {
Pawel Zarembski 0:01f31e923fe2 239 return 0;
Pawel Zarembski 0:01f31e923fe2 240 }
Pawel Zarembski 0:01f31e923fe2 241
Pawel Zarembski 0:01f31e923fe2 242 req = SWD_REG_DP | SWD_REG_R | SWD_REG_ADR(DP_RDBUFF);
Pawel Zarembski 0:01f31e923fe2 243 ack = swd_transfer_retry(req, NULL);
Pawel Zarembski 0:01f31e923fe2 244 return (ack == 0x01);
Pawel Zarembski 0:01f31e923fe2 245 }
Pawel Zarembski 0:01f31e923fe2 246
Pawel Zarembski 0:01f31e923fe2 247
Pawel Zarembski 0:01f31e923fe2 248 // Write 32-bit word aligned values to target memory using address auto-increment.
Pawel Zarembski 0:01f31e923fe2 249 // size is in bytes.
Pawel Zarembski 0:01f31e923fe2 250 static uint8_t swd_write_block(uint32_t address, uint8_t *data, uint32_t size)
Pawel Zarembski 0:01f31e923fe2 251 {
Pawel Zarembski 0:01f31e923fe2 252 uint8_t tmp_in[4], req;
Pawel Zarembski 0:01f31e923fe2 253 uint32_t size_in_words;
Pawel Zarembski 0:01f31e923fe2 254 uint32_t i, ack;
Pawel Zarembski 0:01f31e923fe2 255
Pawel Zarembski 0:01f31e923fe2 256 if (size == 0) {
Pawel Zarembski 0:01f31e923fe2 257 return 0;
Pawel Zarembski 0:01f31e923fe2 258 }
Pawel Zarembski 0:01f31e923fe2 259
Pawel Zarembski 0:01f31e923fe2 260 size_in_words = size / 4;
Pawel Zarembski 0:01f31e923fe2 261
Pawel Zarembski 0:01f31e923fe2 262 // CSW register
Pawel Zarembski 0:01f31e923fe2 263 if (!swd_write_ap(AP_CSW, CSW_VALUE | CSW_SIZE32)) {
Pawel Zarembski 0:01f31e923fe2 264 return 0;
Pawel Zarembski 0:01f31e923fe2 265 }
Pawel Zarembski 0:01f31e923fe2 266
Pawel Zarembski 0:01f31e923fe2 267 // TAR write
Pawel Zarembski 0:01f31e923fe2 268 req = SWD_REG_AP | SWD_REG_W | (1 << 2);
Pawel Zarembski 0:01f31e923fe2 269 int2array(tmp_in, address, 4);
Pawel Zarembski 0:01f31e923fe2 270
Pawel Zarembski 0:01f31e923fe2 271 if (swd_transfer_retry(req, (uint32_t *)tmp_in) != 0x01) {
Pawel Zarembski 0:01f31e923fe2 272 return 0;
Pawel Zarembski 0:01f31e923fe2 273 }
Pawel Zarembski 0:01f31e923fe2 274
Pawel Zarembski 0:01f31e923fe2 275 // DRW write
Pawel Zarembski 0:01f31e923fe2 276 req = SWD_REG_AP | SWD_REG_W | (3 << 2);
Pawel Zarembski 0:01f31e923fe2 277
Pawel Zarembski 0:01f31e923fe2 278 for (i = 0; i < size_in_words; i++) {
Pawel Zarembski 0:01f31e923fe2 279 if (swd_transfer_retry(req, (uint32_t *)data) != 0x01) {
Pawel Zarembski 0:01f31e923fe2 280 return 0;
Pawel Zarembski 0:01f31e923fe2 281 }
Pawel Zarembski 0:01f31e923fe2 282
Pawel Zarembski 0:01f31e923fe2 283 data += 4;
Pawel Zarembski 0:01f31e923fe2 284 }
Pawel Zarembski 0:01f31e923fe2 285
Pawel Zarembski 0:01f31e923fe2 286 // dummy read
Pawel Zarembski 0:01f31e923fe2 287 req = SWD_REG_DP | SWD_REG_R | SWD_REG_ADR(DP_RDBUFF);
Pawel Zarembski 0:01f31e923fe2 288 ack = swd_transfer_retry(req, NULL);
Pawel Zarembski 0:01f31e923fe2 289 return (ack == 0x01);
Pawel Zarembski 0:01f31e923fe2 290 }
Pawel Zarembski 0:01f31e923fe2 291
Pawel Zarembski 0:01f31e923fe2 292 // Read 32-bit word aligned values from target memory using address auto-increment.
Pawel Zarembski 0:01f31e923fe2 293 // size is in bytes.
Pawel Zarembski 0:01f31e923fe2 294 static uint8_t swd_read_block(uint32_t address, uint8_t *data, uint32_t size)
Pawel Zarembski 0:01f31e923fe2 295 {
Pawel Zarembski 0:01f31e923fe2 296 uint8_t tmp_in[4], req, ack;
Pawel Zarembski 0:01f31e923fe2 297 uint32_t size_in_words;
Pawel Zarembski 0:01f31e923fe2 298 uint32_t i;
Pawel Zarembski 0:01f31e923fe2 299
Pawel Zarembski 0:01f31e923fe2 300 if (size == 0) {
Pawel Zarembski 0:01f31e923fe2 301 return 0;
Pawel Zarembski 0:01f31e923fe2 302 }
Pawel Zarembski 0:01f31e923fe2 303
Pawel Zarembski 0:01f31e923fe2 304 size_in_words = size / 4;
Pawel Zarembski 0:01f31e923fe2 305
Pawel Zarembski 0:01f31e923fe2 306 if (!swd_write_ap(AP_CSW, CSW_VALUE | CSW_SIZE32)) {
Pawel Zarembski 0:01f31e923fe2 307 return 0;
Pawel Zarembski 0:01f31e923fe2 308 }
Pawel Zarembski 0:01f31e923fe2 309
Pawel Zarembski 0:01f31e923fe2 310 // TAR write
Pawel Zarembski 0:01f31e923fe2 311 req = SWD_REG_AP | SWD_REG_W | AP_TAR;
Pawel Zarembski 0:01f31e923fe2 312 int2array(tmp_in, address, 4);
Pawel Zarembski 0:01f31e923fe2 313
Pawel Zarembski 0:01f31e923fe2 314 if (swd_transfer_retry(req, (uint32_t *)tmp_in) != DAP_TRANSFER_OK) {
Pawel Zarembski 0:01f31e923fe2 315 return 0;
Pawel Zarembski 0:01f31e923fe2 316 }
Pawel Zarembski 0:01f31e923fe2 317
Pawel Zarembski 0:01f31e923fe2 318 // read data
Pawel Zarembski 0:01f31e923fe2 319 req = SWD_REG_AP | SWD_REG_R | AP_DRW;
Pawel Zarembski 0:01f31e923fe2 320
Pawel Zarembski 0:01f31e923fe2 321 // initiate first read, data comes back in next read
Pawel Zarembski 0:01f31e923fe2 322 if (swd_transfer_retry(req, NULL) != 0x01) {
Pawel Zarembski 0:01f31e923fe2 323 return 0;
Pawel Zarembski 0:01f31e923fe2 324 }
Pawel Zarembski 0:01f31e923fe2 325
Pawel Zarembski 0:01f31e923fe2 326 for (i = 0; i < (size_in_words - 1); i++) {
Pawel Zarembski 0:01f31e923fe2 327 if (swd_transfer_retry(req, (uint32_t *)data) != DAP_TRANSFER_OK) {
Pawel Zarembski 0:01f31e923fe2 328 return 0;
Pawel Zarembski 0:01f31e923fe2 329 }
Pawel Zarembski 0:01f31e923fe2 330
Pawel Zarembski 0:01f31e923fe2 331 data += 4;
Pawel Zarembski 0:01f31e923fe2 332 }
Pawel Zarembski 0:01f31e923fe2 333
Pawel Zarembski 0:01f31e923fe2 334 // read last word
Pawel Zarembski 0:01f31e923fe2 335 req = SWD_REG_DP | SWD_REG_R | SWD_REG_ADR(DP_RDBUFF);
Pawel Zarembski 0:01f31e923fe2 336 ack = swd_transfer_retry(req, (uint32_t *)data);
Pawel Zarembski 0:01f31e923fe2 337 return (ack == 0x01);
Pawel Zarembski 0:01f31e923fe2 338 }
Pawel Zarembski 0:01f31e923fe2 339
Pawel Zarembski 0:01f31e923fe2 340 // Read target memory.
Pawel Zarembski 0:01f31e923fe2 341 static uint8_t swd_read_data(uint32_t addr, uint32_t *val)
Pawel Zarembski 0:01f31e923fe2 342 {
Pawel Zarembski 0:01f31e923fe2 343 uint8_t tmp_in[4];
Pawel Zarembski 0:01f31e923fe2 344 uint8_t tmp_out[4];
Pawel Zarembski 0:01f31e923fe2 345 uint8_t req, ack;
Pawel Zarembski 0:01f31e923fe2 346 uint32_t tmp;
Pawel Zarembski 0:01f31e923fe2 347 // put addr in TAR register
Pawel Zarembski 0:01f31e923fe2 348 int2array(tmp_in, addr, 4);
Pawel Zarembski 0:01f31e923fe2 349 req = SWD_REG_AP | SWD_REG_W | (1 << 2);
Pawel Zarembski 0:01f31e923fe2 350
Pawel Zarembski 0:01f31e923fe2 351 if (swd_transfer_retry(req, (uint32_t *)tmp_in) != 0x01) {
Pawel Zarembski 0:01f31e923fe2 352 return 0;
Pawel Zarembski 0:01f31e923fe2 353 }
Pawel Zarembski 0:01f31e923fe2 354
Pawel Zarembski 0:01f31e923fe2 355 // read data
Pawel Zarembski 0:01f31e923fe2 356 req = SWD_REG_AP | SWD_REG_R | (3 << 2);
Pawel Zarembski 0:01f31e923fe2 357
Pawel Zarembski 0:01f31e923fe2 358 if (swd_transfer_retry(req, (uint32_t *)tmp_out) != 0x01) {
Pawel Zarembski 0:01f31e923fe2 359 return 0;
Pawel Zarembski 0:01f31e923fe2 360 }
Pawel Zarembski 0:01f31e923fe2 361
Pawel Zarembski 0:01f31e923fe2 362 // dummy read
Pawel Zarembski 0:01f31e923fe2 363 req = SWD_REG_DP | SWD_REG_R | SWD_REG_ADR(DP_RDBUFF);
Pawel Zarembski 0:01f31e923fe2 364 ack = swd_transfer_retry(req, (uint32_t *)tmp_out);
Pawel Zarembski 0:01f31e923fe2 365 *val = 0;
Pawel Zarembski 0:01f31e923fe2 366 tmp = tmp_out[3];
Pawel Zarembski 0:01f31e923fe2 367 *val |= (tmp << 24);
Pawel Zarembski 0:01f31e923fe2 368 tmp = tmp_out[2];
Pawel Zarembski 0:01f31e923fe2 369 *val |= (tmp << 16);
Pawel Zarembski 0:01f31e923fe2 370 tmp = tmp_out[1];
Pawel Zarembski 0:01f31e923fe2 371 *val |= (tmp << 8);
Pawel Zarembski 0:01f31e923fe2 372 tmp = tmp_out[0];
Pawel Zarembski 0:01f31e923fe2 373 *val |= (tmp << 0);
Pawel Zarembski 0:01f31e923fe2 374 return (ack == 0x01);
Pawel Zarembski 0:01f31e923fe2 375 }
Pawel Zarembski 0:01f31e923fe2 376
Pawel Zarembski 0:01f31e923fe2 377 // Write target memory.
Pawel Zarembski 0:01f31e923fe2 378 static uint8_t swd_write_data(uint32_t address, uint32_t data)
Pawel Zarembski 0:01f31e923fe2 379 {
Pawel Zarembski 0:01f31e923fe2 380 uint8_t tmp_in[4];
Pawel Zarembski 0:01f31e923fe2 381 uint8_t req, ack;
Pawel Zarembski 0:01f31e923fe2 382 // put addr in TAR register
Pawel Zarembski 0:01f31e923fe2 383 int2array(tmp_in, address, 4);
Pawel Zarembski 0:01f31e923fe2 384 req = SWD_REG_AP | SWD_REG_W | (1 << 2);
Pawel Zarembski 0:01f31e923fe2 385
Pawel Zarembski 0:01f31e923fe2 386 if (swd_transfer_retry(req, (uint32_t *)tmp_in) != 0x01) {
Pawel Zarembski 0:01f31e923fe2 387 return 0;
Pawel Zarembski 0:01f31e923fe2 388 }
Pawel Zarembski 0:01f31e923fe2 389
Pawel Zarembski 0:01f31e923fe2 390 // write data
Pawel Zarembski 0:01f31e923fe2 391 int2array(tmp_in, data, 4);
Pawel Zarembski 0:01f31e923fe2 392 req = SWD_REG_AP | SWD_REG_W | (3 << 2);
Pawel Zarembski 0:01f31e923fe2 393
Pawel Zarembski 0:01f31e923fe2 394 if (swd_transfer_retry(req, (uint32_t *)tmp_in) != 0x01) {
Pawel Zarembski 0:01f31e923fe2 395 return 0;
Pawel Zarembski 0:01f31e923fe2 396 }
Pawel Zarembski 0:01f31e923fe2 397
Pawel Zarembski 0:01f31e923fe2 398 // dummy read
Pawel Zarembski 0:01f31e923fe2 399 req = SWD_REG_DP | SWD_REG_R | SWD_REG_ADR(DP_RDBUFF);
Pawel Zarembski 0:01f31e923fe2 400 ack = swd_transfer_retry(req, NULL);
Pawel Zarembski 0:01f31e923fe2 401 return (ack == 0x01) ? 1 : 0;
Pawel Zarembski 0:01f31e923fe2 402 }
Pawel Zarembski 0:01f31e923fe2 403
Pawel Zarembski 0:01f31e923fe2 404 // Read 32-bit word from target memory.
Pawel Zarembski 0:01f31e923fe2 405 uint8_t swd_read_word(uint32_t addr, uint32_t *val)
Pawel Zarembski 0:01f31e923fe2 406 {
Pawel Zarembski 0:01f31e923fe2 407 if (!swd_write_ap(AP_CSW, CSW_VALUE | CSW_SIZE32)) {
Pawel Zarembski 0:01f31e923fe2 408 return 0;
Pawel Zarembski 0:01f31e923fe2 409 }
Pawel Zarembski 0:01f31e923fe2 410
Pawel Zarembski 0:01f31e923fe2 411 if (!swd_read_data(addr, val)) {
Pawel Zarembski 0:01f31e923fe2 412 return 0;
Pawel Zarembski 0:01f31e923fe2 413 }
Pawel Zarembski 0:01f31e923fe2 414
Pawel Zarembski 0:01f31e923fe2 415 return 1;
Pawel Zarembski 0:01f31e923fe2 416 }
Pawel Zarembski 0:01f31e923fe2 417
Pawel Zarembski 0:01f31e923fe2 418 // Write 32-bit word to target memory.
Pawel Zarembski 0:01f31e923fe2 419 uint8_t swd_write_word(uint32_t addr, uint32_t val)
Pawel Zarembski 0:01f31e923fe2 420 {
Pawel Zarembski 0:01f31e923fe2 421 if (!swd_write_ap(AP_CSW, CSW_VALUE | CSW_SIZE32)) {
Pawel Zarembski 0:01f31e923fe2 422 return 0;
Pawel Zarembski 0:01f31e923fe2 423 }
Pawel Zarembski 0:01f31e923fe2 424
Pawel Zarembski 0:01f31e923fe2 425 if (!swd_write_data(addr, val)) {
Pawel Zarembski 0:01f31e923fe2 426 return 0;
Pawel Zarembski 0:01f31e923fe2 427 }
Pawel Zarembski 0:01f31e923fe2 428
Pawel Zarembski 0:01f31e923fe2 429 return 1;
Pawel Zarembski 0:01f31e923fe2 430 }
Pawel Zarembski 0:01f31e923fe2 431
Pawel Zarembski 0:01f31e923fe2 432 // Read 8-bit byte from target memory.
Pawel Zarembski 0:01f31e923fe2 433 uint8_t swd_read_byte(uint32_t addr, uint8_t *val)
Pawel Zarembski 0:01f31e923fe2 434 {
Pawel Zarembski 0:01f31e923fe2 435 uint32_t tmp;
Pawel Zarembski 0:01f31e923fe2 436
Pawel Zarembski 0:01f31e923fe2 437 if (!swd_write_ap(AP_CSW, CSW_VALUE | CSW_SIZE8)) {
Pawel Zarembski 0:01f31e923fe2 438 return 0;
Pawel Zarembski 0:01f31e923fe2 439 }
Pawel Zarembski 0:01f31e923fe2 440
Pawel Zarembski 0:01f31e923fe2 441 if (!swd_read_data(addr, &tmp)) {
Pawel Zarembski 0:01f31e923fe2 442 return 0;
Pawel Zarembski 0:01f31e923fe2 443 }
Pawel Zarembski 0:01f31e923fe2 444
Pawel Zarembski 0:01f31e923fe2 445 *val = (uint8_t)(tmp >> ((addr & 0x03) << 3));
Pawel Zarembski 0:01f31e923fe2 446 return 1;
Pawel Zarembski 0:01f31e923fe2 447 }
Pawel Zarembski 0:01f31e923fe2 448
Pawel Zarembski 0:01f31e923fe2 449 // Write 8-bit byte to target memory.
Pawel Zarembski 0:01f31e923fe2 450 uint8_t swd_write_byte(uint32_t addr, uint8_t val)
Pawel Zarembski 0:01f31e923fe2 451 {
Pawel Zarembski 0:01f31e923fe2 452 uint32_t tmp;
Pawel Zarembski 0:01f31e923fe2 453
Pawel Zarembski 0:01f31e923fe2 454 if (!swd_write_ap(AP_CSW, CSW_VALUE | CSW_SIZE8)) {
Pawel Zarembski 0:01f31e923fe2 455 return 0;
Pawel Zarembski 0:01f31e923fe2 456 }
Pawel Zarembski 0:01f31e923fe2 457
Pawel Zarembski 0:01f31e923fe2 458 tmp = val << ((addr & 0x03) << 3);
Pawel Zarembski 0:01f31e923fe2 459
Pawel Zarembski 0:01f31e923fe2 460 if (!swd_write_data(addr, tmp)) {
Pawel Zarembski 0:01f31e923fe2 461 return 0;
Pawel Zarembski 0:01f31e923fe2 462 }
Pawel Zarembski 0:01f31e923fe2 463
Pawel Zarembski 0:01f31e923fe2 464 return 1;
Pawel Zarembski 0:01f31e923fe2 465 }
Pawel Zarembski 0:01f31e923fe2 466
Pawel Zarembski 0:01f31e923fe2 467 // Read unaligned data from target memory.
Pawel Zarembski 0:01f31e923fe2 468 // size is in bytes.
Pawel Zarembski 0:01f31e923fe2 469 uint8_t swd_read_memory(uint32_t address, uint8_t *data, uint32_t size)
Pawel Zarembski 0:01f31e923fe2 470 {
Pawel Zarembski 0:01f31e923fe2 471 uint32_t n;
Pawel Zarembski 0:01f31e923fe2 472
Pawel Zarembski 0:01f31e923fe2 473 // Read bytes until word aligned
Pawel Zarembski 0:01f31e923fe2 474 while ((size > 0) && (address & 0x3)) {
Pawel Zarembski 0:01f31e923fe2 475 if (!swd_read_byte(address, data)) {
Pawel Zarembski 0:01f31e923fe2 476 return 0;
Pawel Zarembski 0:01f31e923fe2 477 }
Pawel Zarembski 0:01f31e923fe2 478
Pawel Zarembski 0:01f31e923fe2 479 address++;
Pawel Zarembski 0:01f31e923fe2 480 data++;
Pawel Zarembski 0:01f31e923fe2 481 size--;
Pawel Zarembski 0:01f31e923fe2 482 }
Pawel Zarembski 0:01f31e923fe2 483
Pawel Zarembski 0:01f31e923fe2 484 // Read word aligned blocks
Pawel Zarembski 0:01f31e923fe2 485 while (size > 3) {
Pawel Zarembski 0:01f31e923fe2 486 // Limit to auto increment page size
Pawel Zarembski 0:01f31e923fe2 487 n = TARGET_AUTO_INCREMENT_PAGE_SIZE - (address & (TARGET_AUTO_INCREMENT_PAGE_SIZE - 1));
Pawel Zarembski 0:01f31e923fe2 488
Pawel Zarembski 0:01f31e923fe2 489 if (size < n) {
Pawel Zarembski 0:01f31e923fe2 490 n = size & 0xFFFFFFFC; // Only count complete words remaining
Pawel Zarembski 0:01f31e923fe2 491 }
Pawel Zarembski 0:01f31e923fe2 492
Pawel Zarembski 0:01f31e923fe2 493 if (!swd_read_block(address, data, n)) {
Pawel Zarembski 0:01f31e923fe2 494 return 0;
Pawel Zarembski 0:01f31e923fe2 495 }
Pawel Zarembski 0:01f31e923fe2 496
Pawel Zarembski 0:01f31e923fe2 497 address += n;
Pawel Zarembski 0:01f31e923fe2 498 data += n;
Pawel Zarembski 0:01f31e923fe2 499 size -= n;
Pawel Zarembski 0:01f31e923fe2 500 }
Pawel Zarembski 0:01f31e923fe2 501
Pawel Zarembski 0:01f31e923fe2 502 // Read remaining bytes
Pawel Zarembski 0:01f31e923fe2 503 while (size > 0) {
Pawel Zarembski 0:01f31e923fe2 504 if (!swd_read_byte(address, data)) {
Pawel Zarembski 0:01f31e923fe2 505 return 0;
Pawel Zarembski 0:01f31e923fe2 506 }
Pawel Zarembski 0:01f31e923fe2 507
Pawel Zarembski 0:01f31e923fe2 508 address++;
Pawel Zarembski 0:01f31e923fe2 509 data++;
Pawel Zarembski 0:01f31e923fe2 510 size--;
Pawel Zarembski 0:01f31e923fe2 511 }
Pawel Zarembski 0:01f31e923fe2 512
Pawel Zarembski 0:01f31e923fe2 513 return 1;
Pawel Zarembski 0:01f31e923fe2 514 }
Pawel Zarembski 0:01f31e923fe2 515
Pawel Zarembski 0:01f31e923fe2 516 // Write unaligned data to target memory.
Pawel Zarembski 0:01f31e923fe2 517 // size is in bytes.
Pawel Zarembski 0:01f31e923fe2 518 uint8_t swd_write_memory(uint32_t address, uint8_t *data, uint32_t size)
Pawel Zarembski 0:01f31e923fe2 519 {
Pawel Zarembski 0:01f31e923fe2 520 uint32_t n = 0;
Pawel Zarembski 0:01f31e923fe2 521
Pawel Zarembski 0:01f31e923fe2 522 // Write bytes until word aligned
Pawel Zarembski 0:01f31e923fe2 523 while ((size > 0) && (address & 0x3)) {
Pawel Zarembski 0:01f31e923fe2 524 if (!swd_write_byte(address, *data)) {
Pawel Zarembski 0:01f31e923fe2 525 return 0;
Pawel Zarembski 0:01f31e923fe2 526 }
Pawel Zarembski 0:01f31e923fe2 527
Pawel Zarembski 0:01f31e923fe2 528 address++;
Pawel Zarembski 0:01f31e923fe2 529 data++;
Pawel Zarembski 0:01f31e923fe2 530 size--;
Pawel Zarembski 0:01f31e923fe2 531 }
Pawel Zarembski 0:01f31e923fe2 532
Pawel Zarembski 0:01f31e923fe2 533 // Write word aligned blocks
Pawel Zarembski 0:01f31e923fe2 534 while (size > 3) {
Pawel Zarembski 0:01f31e923fe2 535 // Limit to auto increment page size
Pawel Zarembski 0:01f31e923fe2 536 n = TARGET_AUTO_INCREMENT_PAGE_SIZE - (address & (TARGET_AUTO_INCREMENT_PAGE_SIZE - 1));
Pawel Zarembski 0:01f31e923fe2 537
Pawel Zarembski 0:01f31e923fe2 538 if (size < n) {
Pawel Zarembski 0:01f31e923fe2 539 n = size & 0xFFFFFFFC; // Only count complete words remaining
Pawel Zarembski 0:01f31e923fe2 540 }
Pawel Zarembski 0:01f31e923fe2 541
Pawel Zarembski 0:01f31e923fe2 542 if (!swd_write_block(address, data, n)) {
Pawel Zarembski 0:01f31e923fe2 543 return 0;
Pawel Zarembski 0:01f31e923fe2 544 }
Pawel Zarembski 0:01f31e923fe2 545
Pawel Zarembski 0:01f31e923fe2 546 address += n;
Pawel Zarembski 0:01f31e923fe2 547 data += n;
Pawel Zarembski 0:01f31e923fe2 548 size -= n;
Pawel Zarembski 0:01f31e923fe2 549 }
Pawel Zarembski 0:01f31e923fe2 550
Pawel Zarembski 0:01f31e923fe2 551 // Write remaining bytes
Pawel Zarembski 0:01f31e923fe2 552 while (size > 0) {
Pawel Zarembski 0:01f31e923fe2 553 if (!swd_write_byte(address, *data)) {
Pawel Zarembski 0:01f31e923fe2 554 return 0;
Pawel Zarembski 0:01f31e923fe2 555 }
Pawel Zarembski 0:01f31e923fe2 556
Pawel Zarembski 0:01f31e923fe2 557 address++;
Pawel Zarembski 0:01f31e923fe2 558 data++;
Pawel Zarembski 0:01f31e923fe2 559 size--;
Pawel Zarembski 0:01f31e923fe2 560 }
Pawel Zarembski 0:01f31e923fe2 561
Pawel Zarembski 0:01f31e923fe2 562 return 1;
Pawel Zarembski 0:01f31e923fe2 563 }
Pawel Zarembski 0:01f31e923fe2 564
Pawel Zarembski 0:01f31e923fe2 565 // Execute system call.
Pawel Zarembski 0:01f31e923fe2 566 static uint8_t swd_write_debug_state(DEBUG_STATE *state)
Pawel Zarembski 0:01f31e923fe2 567 {
Pawel Zarembski 0:01f31e923fe2 568 uint32_t i, status;
Pawel Zarembski 0:01f31e923fe2 569
Pawel Zarembski 0:01f31e923fe2 570 if (!swd_write_dp(DP_SELECT, 0)) {
Pawel Zarembski 0:01f31e923fe2 571 return 0;
Pawel Zarembski 0:01f31e923fe2 572 }
Pawel Zarembski 0:01f31e923fe2 573
Pawel Zarembski 0:01f31e923fe2 574 // R0, R1, R2, R3
Pawel Zarembski 0:01f31e923fe2 575 for (i = 0; i < 4; i++) {
Pawel Zarembski 0:01f31e923fe2 576 if (!swd_write_core_register(i, state->r[i])) {
Pawel Zarembski 0:01f31e923fe2 577 return 0;
Pawel Zarembski 0:01f31e923fe2 578 }
Pawel Zarembski 0:01f31e923fe2 579 }
Pawel Zarembski 0:01f31e923fe2 580
Pawel Zarembski 0:01f31e923fe2 581 // R9
Pawel Zarembski 0:01f31e923fe2 582 if (!swd_write_core_register(9, state->r[9])) {
Pawel Zarembski 0:01f31e923fe2 583 return 0;
Pawel Zarembski 0:01f31e923fe2 584 }
Pawel Zarembski 0:01f31e923fe2 585
Pawel Zarembski 0:01f31e923fe2 586 // R13, R14, R15
Pawel Zarembski 0:01f31e923fe2 587 for (i = 13; i < 16; i++) {
Pawel Zarembski 0:01f31e923fe2 588 if (!swd_write_core_register(i, state->r[i])) {
Pawel Zarembski 0:01f31e923fe2 589 return 0;
Pawel Zarembski 0:01f31e923fe2 590 }
Pawel Zarembski 0:01f31e923fe2 591 }
Pawel Zarembski 0:01f31e923fe2 592
Pawel Zarembski 0:01f31e923fe2 593 // xPSR
Pawel Zarembski 0:01f31e923fe2 594 if (!swd_write_core_register(16, state->xpsr)) {
Pawel Zarembski 0:01f31e923fe2 595 return 0;
Pawel Zarembski 0:01f31e923fe2 596 }
Pawel Zarembski 0:01f31e923fe2 597
Pawel Zarembski 0:01f31e923fe2 598 if (!swd_write_word(DBG_HCSR, DBGKEY | C_DEBUGEN | C_MASKINTS | C_HALT)) {
Pawel Zarembski 0:01f31e923fe2 599 return 0;
Pawel Zarembski 0:01f31e923fe2 600 }
Pawel Zarembski 0:01f31e923fe2 601
Pawel Zarembski 0:01f31e923fe2 602 if (!swd_write_word(DBG_HCSR, DBGKEY | C_DEBUGEN | C_MASKINTS)) {
Pawel Zarembski 0:01f31e923fe2 603 return 0;
Pawel Zarembski 0:01f31e923fe2 604 }
Pawel Zarembski 0:01f31e923fe2 605
Pawel Zarembski 0:01f31e923fe2 606 // check status
Pawel Zarembski 0:01f31e923fe2 607 if (!swd_read_dp(DP_CTRL_STAT, &status)) {
Pawel Zarembski 0:01f31e923fe2 608 return 0;
Pawel Zarembski 0:01f31e923fe2 609 }
Pawel Zarembski 0:01f31e923fe2 610
Pawel Zarembski 0:01f31e923fe2 611 if (status & (STICKYERR | WDATAERR)) {
Pawel Zarembski 0:01f31e923fe2 612 return 0;
Pawel Zarembski 0:01f31e923fe2 613 }
Pawel Zarembski 0:01f31e923fe2 614
Pawel Zarembski 0:01f31e923fe2 615 return 1;
Pawel Zarembski 0:01f31e923fe2 616 }
Pawel Zarembski 0:01f31e923fe2 617
Pawel Zarembski 0:01f31e923fe2 618 uint8_t swd_read_core_register(uint32_t n, uint32_t *val)
Pawel Zarembski 0:01f31e923fe2 619 {
Pawel Zarembski 0:01f31e923fe2 620 int i = 0, timeout = 100;
Pawel Zarembski 0:01f31e923fe2 621
Pawel Zarembski 0:01f31e923fe2 622 if (!swd_write_word(DCRSR, n)) {
Pawel Zarembski 0:01f31e923fe2 623 return 0;
Pawel Zarembski 0:01f31e923fe2 624 }
Pawel Zarembski 0:01f31e923fe2 625
Pawel Zarembski 0:01f31e923fe2 626 // wait for S_REGRDY
Pawel Zarembski 0:01f31e923fe2 627 for (i = 0; i < timeout; i++) {
Pawel Zarembski 0:01f31e923fe2 628 if (!swd_read_word(DHCSR, val)) {
Pawel Zarembski 0:01f31e923fe2 629 return 0;
Pawel Zarembski 0:01f31e923fe2 630 }
Pawel Zarembski 0:01f31e923fe2 631
Pawel Zarembski 0:01f31e923fe2 632 if (*val & S_REGRDY) {
Pawel Zarembski 0:01f31e923fe2 633 break;
Pawel Zarembski 0:01f31e923fe2 634 }
Pawel Zarembski 0:01f31e923fe2 635 }
Pawel Zarembski 0:01f31e923fe2 636
Pawel Zarembski 0:01f31e923fe2 637 if (i == timeout) {
Pawel Zarembski 0:01f31e923fe2 638 return 0;
Pawel Zarembski 0:01f31e923fe2 639 }
Pawel Zarembski 0:01f31e923fe2 640
Pawel Zarembski 0:01f31e923fe2 641 if (!swd_read_word(DCRDR, val)) {
Pawel Zarembski 0:01f31e923fe2 642 return 0;
Pawel Zarembski 0:01f31e923fe2 643 }
Pawel Zarembski 0:01f31e923fe2 644
Pawel Zarembski 0:01f31e923fe2 645 return 1;
Pawel Zarembski 0:01f31e923fe2 646 }
Pawel Zarembski 0:01f31e923fe2 647
Pawel Zarembski 0:01f31e923fe2 648 uint8_t swd_write_core_register(uint32_t n, uint32_t val)
Pawel Zarembski 0:01f31e923fe2 649 {
Pawel Zarembski 0:01f31e923fe2 650 int i = 0, timeout = 100;
Pawel Zarembski 0:01f31e923fe2 651
Pawel Zarembski 0:01f31e923fe2 652 if (!swd_write_word(DCRDR, val)) {
Pawel Zarembski 0:01f31e923fe2 653 return 0;
Pawel Zarembski 0:01f31e923fe2 654 }
Pawel Zarembski 0:01f31e923fe2 655
Pawel Zarembski 0:01f31e923fe2 656 if (!swd_write_word(DCRSR, n | REGWnR)) {
Pawel Zarembski 0:01f31e923fe2 657 return 0;
Pawel Zarembski 0:01f31e923fe2 658 }
Pawel Zarembski 0:01f31e923fe2 659
Pawel Zarembski 0:01f31e923fe2 660 // wait for S_REGRDY
Pawel Zarembski 0:01f31e923fe2 661 for (i = 0; i < timeout; i++) {
Pawel Zarembski 0:01f31e923fe2 662 if (!swd_read_word(DHCSR, &val)) {
Pawel Zarembski 0:01f31e923fe2 663 return 0;
Pawel Zarembski 0:01f31e923fe2 664 }
Pawel Zarembski 0:01f31e923fe2 665
Pawel Zarembski 0:01f31e923fe2 666 if (val & S_REGRDY) {
Pawel Zarembski 0:01f31e923fe2 667 return 1;
Pawel Zarembski 0:01f31e923fe2 668 }
Pawel Zarembski 0:01f31e923fe2 669 }
Pawel Zarembski 0:01f31e923fe2 670
Pawel Zarembski 0:01f31e923fe2 671 return 0;
Pawel Zarembski 0:01f31e923fe2 672 }
Pawel Zarembski 0:01f31e923fe2 673
Pawel Zarembski 0:01f31e923fe2 674 static uint8_t swd_wait_until_halted(void)
Pawel Zarembski 0:01f31e923fe2 675 {
Pawel Zarembski 0:01f31e923fe2 676 // Wait for target to stop
Pawel Zarembski 0:01f31e923fe2 677 uint32_t val, i, timeout = MAX_TIMEOUT;
Pawel Zarembski 0:01f31e923fe2 678
Pawel Zarembski 0:01f31e923fe2 679 for (i = 0; i < timeout; i++) {
Pawel Zarembski 0:01f31e923fe2 680 if (!swd_read_word(DBG_HCSR, &val)) {
Pawel Zarembski 0:01f31e923fe2 681 return 0;
Pawel Zarembski 0:01f31e923fe2 682 }
Pawel Zarembski 0:01f31e923fe2 683
Pawel Zarembski 0:01f31e923fe2 684 if (val & S_HALT) {
Pawel Zarembski 0:01f31e923fe2 685 return 1;
Pawel Zarembski 0:01f31e923fe2 686 }
Pawel Zarembski 0:01f31e923fe2 687 }
Pawel Zarembski 0:01f31e923fe2 688
Pawel Zarembski 0:01f31e923fe2 689 return 0;
Pawel Zarembski 0:01f31e923fe2 690 }
Pawel Zarembski 0:01f31e923fe2 691
Pawel Zarembski 0:01f31e923fe2 692 uint8_t swd_flash_syscall_exec(const program_syscall_t *sysCallParam, uint32_t entry, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4, flash_algo_return_t return_type)
Pawel Zarembski 0:01f31e923fe2 693 {
Pawel Zarembski 0:01f31e923fe2 694 DEBUG_STATE state = {{0}, 0};
Pawel Zarembski 0:01f31e923fe2 695 // Call flash algorithm function on target and wait for result.
Pawel Zarembski 0:01f31e923fe2 696 state.r[0] = arg1; // R0: Argument 1
Pawel Zarembski 0:01f31e923fe2 697 state.r[1] = arg2; // R1: Argument 2
Pawel Zarembski 0:01f31e923fe2 698 state.r[2] = arg3; // R2: Argument 3
Pawel Zarembski 0:01f31e923fe2 699 state.r[3] = arg4; // R3: Argument 4
Pawel Zarembski 0:01f31e923fe2 700 state.r[9] = sysCallParam->static_base; // SB: Static Base
Pawel Zarembski 0:01f31e923fe2 701 state.r[13] = sysCallParam->stack_pointer; // SP: Stack Pointer
Pawel Zarembski 0:01f31e923fe2 702 state.r[14] = sysCallParam->breakpoint; // LR: Exit Point
Pawel Zarembski 0:01f31e923fe2 703 state.r[15] = entry; // PC: Entry Point
Pawel Zarembski 0:01f31e923fe2 704 state.xpsr = 0x01000000; // xPSR: T = 1, ISR = 0
Pawel Zarembski 0:01f31e923fe2 705
Pawel Zarembski 0:01f31e923fe2 706 if (!swd_write_debug_state(&state)) {
Pawel Zarembski 0:01f31e923fe2 707 return 0;
Pawel Zarembski 0:01f31e923fe2 708 }
Pawel Zarembski 0:01f31e923fe2 709
Pawel Zarembski 0:01f31e923fe2 710 if (!swd_wait_until_halted()) {
Pawel Zarembski 0:01f31e923fe2 711 return 0;
Pawel Zarembski 0:01f31e923fe2 712 }
Pawel Zarembski 0:01f31e923fe2 713
Pawel Zarembski 0:01f31e923fe2 714 if (!swd_read_core_register(0, &state.r[0])) {
Pawel Zarembski 0:01f31e923fe2 715 return 0;
Pawel Zarembski 0:01f31e923fe2 716 }
Pawel Zarembski 0:01f31e923fe2 717
Pawel Zarembski 0:01f31e923fe2 718 //remove the C_MASKINTS
Pawel Zarembski 0:01f31e923fe2 719 if (!swd_write_word(DBG_HCSR, DBGKEY | C_DEBUGEN | C_HALT)) {
Pawel Zarembski 0:01f31e923fe2 720 return 0;
Pawel Zarembski 0:01f31e923fe2 721 }
Pawel Zarembski 0:01f31e923fe2 722
Pawel Zarembski 0:01f31e923fe2 723 if ( return_type == FLASHALGO_RETURN_POINTER ) {
Pawel Zarembski 0:01f31e923fe2 724 // Flash verify functions return pointer to byte following the buffer if successful.
Pawel Zarembski 0:01f31e923fe2 725 if (state.r[0] != (arg1 + arg2)) {
Pawel Zarembski 0:01f31e923fe2 726 return 0;
Pawel Zarembski 0:01f31e923fe2 727 }
Pawel Zarembski 0:01f31e923fe2 728 }
Pawel Zarembski 0:01f31e923fe2 729 else {
Pawel Zarembski 0:01f31e923fe2 730 // Flash functions return 0 if successful.
Pawel Zarembski 0:01f31e923fe2 731 if (state.r[0] != 0) {
Pawel Zarembski 0:01f31e923fe2 732 return 0;
Pawel Zarembski 0:01f31e923fe2 733 }
Pawel Zarembski 0:01f31e923fe2 734 }
Pawel Zarembski 0:01f31e923fe2 735
Pawel Zarembski 0:01f31e923fe2 736 return 1;
Pawel Zarembski 0:01f31e923fe2 737 }
Pawel Zarembski 0:01f31e923fe2 738
Pawel Zarembski 0:01f31e923fe2 739 // SWD Reset
Pawel Zarembski 0:01f31e923fe2 740 static uint8_t swd_reset(void)
Pawel Zarembski 0:01f31e923fe2 741 {
Pawel Zarembski 0:01f31e923fe2 742 uint8_t tmp_in[8];
Pawel Zarembski 0:01f31e923fe2 743 uint8_t i = 0;
Pawel Zarembski 0:01f31e923fe2 744
Pawel Zarembski 0:01f31e923fe2 745 for (i = 0; i < 8; i++) {
Pawel Zarembski 0:01f31e923fe2 746 tmp_in[i] = 0xff;
Pawel Zarembski 0:01f31e923fe2 747 }
Pawel Zarembski 0:01f31e923fe2 748
Pawel Zarembski 0:01f31e923fe2 749 SWJ_Sequence(51, tmp_in);
Pawel Zarembski 0:01f31e923fe2 750 return 1;
Pawel Zarembski 0:01f31e923fe2 751 }
Pawel Zarembski 0:01f31e923fe2 752
Pawel Zarembski 0:01f31e923fe2 753 // SWD Switch
Pawel Zarembski 0:01f31e923fe2 754 static uint8_t swd_switch(uint16_t val)
Pawel Zarembski 0:01f31e923fe2 755 {
Pawel Zarembski 0:01f31e923fe2 756 uint8_t tmp_in[2];
Pawel Zarembski 0:01f31e923fe2 757 tmp_in[0] = val & 0xff;
Pawel Zarembski 0:01f31e923fe2 758 tmp_in[1] = (val >> 8) & 0xff;
Pawel Zarembski 0:01f31e923fe2 759 SWJ_Sequence(16, tmp_in);
Pawel Zarembski 0:01f31e923fe2 760 return 1;
Pawel Zarembski 0:01f31e923fe2 761 }
Pawel Zarembski 0:01f31e923fe2 762
Pawel Zarembski 0:01f31e923fe2 763 // SWD Read ID
Pawel Zarembski 0:01f31e923fe2 764 static uint8_t swd_read_idcode(uint32_t *id)
Pawel Zarembski 0:01f31e923fe2 765 {
Pawel Zarembski 0:01f31e923fe2 766 uint8_t tmp_in[1];
Pawel Zarembski 0:01f31e923fe2 767 uint8_t tmp_out[4];
Pawel Zarembski 0:01f31e923fe2 768 tmp_in[0] = 0x00;
Pawel Zarembski 0:01f31e923fe2 769 SWJ_Sequence(8, tmp_in);
Pawel Zarembski 0:01f31e923fe2 770
Pawel Zarembski 0:01f31e923fe2 771 if (swd_read_dp(0, (uint32_t *)tmp_out) != 0x01) {
Pawel Zarembski 0:01f31e923fe2 772 return 0;
Pawel Zarembski 0:01f31e923fe2 773 }
Pawel Zarembski 0:01f31e923fe2 774
Pawel Zarembski 0:01f31e923fe2 775 *id = (tmp_out[3] << 24) | (tmp_out[2] << 16) | (tmp_out[1] << 8) | tmp_out[0];
Pawel Zarembski 0:01f31e923fe2 776 return 1;
Pawel Zarembski 0:01f31e923fe2 777 }
Pawel Zarembski 0:01f31e923fe2 778
Pawel Zarembski 0:01f31e923fe2 779
Pawel Zarembski 0:01f31e923fe2 780 uint8_t JTAG2SWD()
Pawel Zarembski 0:01f31e923fe2 781 {
Pawel Zarembski 0:01f31e923fe2 782 uint32_t tmp = 0;
Pawel Zarembski 0:01f31e923fe2 783
Pawel Zarembski 0:01f31e923fe2 784 if (!swd_reset()) {
Pawel Zarembski 0:01f31e923fe2 785 return 0;
Pawel Zarembski 0:01f31e923fe2 786 }
Pawel Zarembski 0:01f31e923fe2 787
Pawel Zarembski 0:01f31e923fe2 788 if (!swd_switch(0xE79E)) {
Pawel Zarembski 0:01f31e923fe2 789 return 0;
Pawel Zarembski 0:01f31e923fe2 790 }
Pawel Zarembski 0:01f31e923fe2 791
Pawel Zarembski 0:01f31e923fe2 792 if (!swd_reset()) {
Pawel Zarembski 0:01f31e923fe2 793 return 0;
Pawel Zarembski 0:01f31e923fe2 794 }
Pawel Zarembski 0:01f31e923fe2 795
Pawel Zarembski 0:01f31e923fe2 796 if (!swd_read_idcode(&tmp)) {
Pawel Zarembski 0:01f31e923fe2 797 return 0;
Pawel Zarembski 0:01f31e923fe2 798 }
Pawel Zarembski 0:01f31e923fe2 799
Pawel Zarembski 0:01f31e923fe2 800 return 1;
Pawel Zarembski 0:01f31e923fe2 801 }
Pawel Zarembski 0:01f31e923fe2 802
Pawel Zarembski 0:01f31e923fe2 803 uint8_t swd_init_debug(void)
Pawel Zarembski 0:01f31e923fe2 804 {
Pawel Zarembski 0:01f31e923fe2 805 uint32_t tmp = 0;
Pawel Zarembski 0:01f31e923fe2 806 int i = 0;
Pawel Zarembski 0:01f31e923fe2 807 int timeout = 100;
Pawel Zarembski 0:01f31e923fe2 808 // init dap state with fake values
Pawel Zarembski 0:01f31e923fe2 809 dap_state.select = 0xffffffff;
Pawel Zarembski 0:01f31e923fe2 810 dap_state.csw = 0xffffffff;
Pawel Zarembski 0:01f31e923fe2 811
Pawel Zarembski 0:01f31e923fe2 812 int8_t retries = 4;
Pawel Zarembski 0:01f31e923fe2 813 int8_t do_abort = 0;
Pawel Zarembski 0:01f31e923fe2 814 do {
Pawel Zarembski 0:01f31e923fe2 815 if (do_abort) {
Pawel Zarembski 0:01f31e923fe2 816 //do an abort on stale target, then reset the device
Pawel Zarembski 0:01f31e923fe2 817 swd_write_dp(DP_ABORT, DAPABORT);
Pawel Zarembski 0:01f31e923fe2 818 swd_set_target_reset(1);
Pawel Zarembski 0:01f31e923fe2 819 osDelay(2);
Pawel Zarembski 0:01f31e923fe2 820 swd_set_target_reset(0);
Pawel Zarembski 0:01f31e923fe2 821 osDelay(2);
Pawel Zarembski 0:01f31e923fe2 822 do_abort = 0;
Pawel Zarembski 0:01f31e923fe2 823 }
Pawel Zarembski 0:01f31e923fe2 824 swd_init();
Pawel Zarembski 0:01f31e923fe2 825 // call a target dependant function
Pawel Zarembski 0:01f31e923fe2 826 // this function can do several stuff before really
Pawel Zarembski 0:01f31e923fe2 827 // initing the debug
Pawel Zarembski 0:01f31e923fe2 828 if (g_target_family && g_target_family->target_before_init_debug) {
Pawel Zarembski 0:01f31e923fe2 829 g_target_family->target_before_init_debug();
Pawel Zarembski 0:01f31e923fe2 830 }
Pawel Zarembski 0:01f31e923fe2 831
Pawel Zarembski 0:01f31e923fe2 832 if (!JTAG2SWD()) {
Pawel Zarembski 0:01f31e923fe2 833 do_abort = 1;
Pawel Zarembski 0:01f31e923fe2 834 continue;
Pawel Zarembski 0:01f31e923fe2 835 }
Pawel Zarembski 0:01f31e923fe2 836
Pawel Zarembski 0:01f31e923fe2 837 if (!swd_clear_errors()) {
Pawel Zarembski 0:01f31e923fe2 838 do_abort = 1;
Pawel Zarembski 0:01f31e923fe2 839 continue;
Pawel Zarembski 0:01f31e923fe2 840 }
Pawel Zarembski 0:01f31e923fe2 841
Pawel Zarembski 0:01f31e923fe2 842 if (!swd_write_dp(DP_SELECT, 0)) {
Pawel Zarembski 0:01f31e923fe2 843 do_abort = 1;
Pawel Zarembski 0:01f31e923fe2 844 continue;
Pawel Zarembski 0:01f31e923fe2 845
Pawel Zarembski 0:01f31e923fe2 846 }
Pawel Zarembski 0:01f31e923fe2 847
Pawel Zarembski 0:01f31e923fe2 848 // Power up
Pawel Zarembski 0:01f31e923fe2 849 if (!swd_write_dp(DP_CTRL_STAT, CSYSPWRUPREQ | CDBGPWRUPREQ)) {
Pawel Zarembski 0:01f31e923fe2 850 do_abort = 1;
Pawel Zarembski 0:01f31e923fe2 851 continue;
Pawel Zarembski 0:01f31e923fe2 852 }
Pawel Zarembski 0:01f31e923fe2 853
Pawel Zarembski 0:01f31e923fe2 854 for (i = 0; i < timeout; i++) {
Pawel Zarembski 0:01f31e923fe2 855 if (!swd_read_dp(DP_CTRL_STAT, &tmp)) {
Pawel Zarembski 0:01f31e923fe2 856 do_abort = 1;
Pawel Zarembski 0:01f31e923fe2 857 break;
Pawel Zarembski 0:01f31e923fe2 858 }
Pawel Zarembski 0:01f31e923fe2 859 if ((tmp & (CDBGPWRUPACK | CSYSPWRUPACK)) == (CDBGPWRUPACK | CSYSPWRUPACK)) {
Pawel Zarembski 0:01f31e923fe2 860 // Break from loop if powerup is complete
Pawel Zarembski 0:01f31e923fe2 861 break;
Pawel Zarembski 0:01f31e923fe2 862 }
Pawel Zarembski 0:01f31e923fe2 863 }
Pawel Zarembski 0:01f31e923fe2 864 if ((i == timeout) || (do_abort == 1)) {
Pawel Zarembski 0:01f31e923fe2 865 // Unable to powerup DP
Pawel Zarembski 0:01f31e923fe2 866 do_abort = 1;
Pawel Zarembski 0:01f31e923fe2 867 continue;
Pawel Zarembski 0:01f31e923fe2 868 }
Pawel Zarembski 0:01f31e923fe2 869
Pawel Zarembski 0:01f31e923fe2 870 if (!swd_write_dp(DP_CTRL_STAT, CSYSPWRUPREQ | CDBGPWRUPREQ | TRNNORMAL | MASKLANE)) {
Pawel Zarembski 0:01f31e923fe2 871 do_abort = 1;
Pawel Zarembski 0:01f31e923fe2 872 continue;
Pawel Zarembski 0:01f31e923fe2 873 }
Pawel Zarembski 0:01f31e923fe2 874
Pawel Zarembski 0:01f31e923fe2 875 // call a target dependant function:
Pawel Zarembski 0:01f31e923fe2 876 // some target can enter in a lock state
Pawel Zarembski 0:01f31e923fe2 877 // this function can unlock these targets
Pawel Zarembski 0:01f31e923fe2 878 if (g_target_family && g_target_family->target_unlock_sequence) {
Pawel Zarembski 0:01f31e923fe2 879 g_target_family->target_unlock_sequence();
Pawel Zarembski 0:01f31e923fe2 880 }
Pawel Zarembski 0:01f31e923fe2 881
Pawel Zarembski 0:01f31e923fe2 882 if (!swd_write_dp(DP_SELECT, 0)) {
Pawel Zarembski 0:01f31e923fe2 883 do_abort = 1;
Pawel Zarembski 0:01f31e923fe2 884 continue;
Pawel Zarembski 0:01f31e923fe2 885 }
Pawel Zarembski 0:01f31e923fe2 886
Pawel Zarembski 0:01f31e923fe2 887 return 1;
Pawel Zarembski 0:01f31e923fe2 888
Pawel Zarembski 0:01f31e923fe2 889 } while (--retries > 0);
Pawel Zarembski 0:01f31e923fe2 890
Pawel Zarembski 0:01f31e923fe2 891 return 0;
Pawel Zarembski 0:01f31e923fe2 892 }
Pawel Zarembski 0:01f31e923fe2 893
Pawel Zarembski 0:01f31e923fe2 894 uint8_t swd_set_target_state_hw(target_state_t state)
Pawel Zarembski 0:01f31e923fe2 895 {
Pawel Zarembski 0:01f31e923fe2 896 uint32_t val;
Pawel Zarembski 0:01f31e923fe2 897 int8_t ap_retries = 2;
Pawel Zarembski 0:01f31e923fe2 898 /* Calling swd_init prior to entering RUN state causes operations to fail. */
Pawel Zarembski 0:01f31e923fe2 899 if (state != RUN) {
Pawel Zarembski 0:01f31e923fe2 900 swd_init();
Pawel Zarembski 0:01f31e923fe2 901 }
Pawel Zarembski 0:01f31e923fe2 902
Pawel Zarembski 0:01f31e923fe2 903 switch (state) {
Pawel Zarembski 0:01f31e923fe2 904 case RESET_HOLD:
Pawel Zarembski 0:01f31e923fe2 905 swd_set_target_reset(1);
Pawel Zarembski 0:01f31e923fe2 906 break;
Pawel Zarembski 0:01f31e923fe2 907
Pawel Zarembski 0:01f31e923fe2 908 case RESET_RUN:
Pawel Zarembski 0:01f31e923fe2 909 swd_set_target_reset(1);
Pawel Zarembski 0:01f31e923fe2 910 osDelay(2);
Pawel Zarembski 0:01f31e923fe2 911 swd_set_target_reset(0);
Pawel Zarembski 0:01f31e923fe2 912 osDelay(2);
Pawel Zarembski 0:01f31e923fe2 913 swd_off();
Pawel Zarembski 0:01f31e923fe2 914 break;
Pawel Zarembski 0:01f31e923fe2 915
Pawel Zarembski 0:01f31e923fe2 916 case RESET_PROGRAM:
Pawel Zarembski 0:01f31e923fe2 917 if (!swd_init_debug()) {
Pawel Zarembski 0:01f31e923fe2 918 return 0;
Pawel Zarembski 0:01f31e923fe2 919 }
Pawel Zarembski 0:01f31e923fe2 920
Pawel Zarembski 0:01f31e923fe2 921 if (reset_connect == CONNECT_UNDER_RESET) {
Pawel Zarembski 0:01f31e923fe2 922 // Assert reset
Pawel Zarembski 0:01f31e923fe2 923 swd_set_target_reset(1);
Pawel Zarembski 0:01f31e923fe2 924 osDelay(2);
Pawel Zarembski 0:01f31e923fe2 925 }
Pawel Zarembski 0:01f31e923fe2 926
Pawel Zarembski 0:01f31e923fe2 927 // Enable debug
Pawel Zarembski 0:01f31e923fe2 928 while(swd_write_word(DBG_HCSR, DBGKEY | C_DEBUGEN) == 0) {
Pawel Zarembski 0:01f31e923fe2 929 if( --ap_retries <=0 )
Pawel Zarembski 0:01f31e923fe2 930 return 0;
Pawel Zarembski 0:01f31e923fe2 931 // Target is in invalid state?
Pawel Zarembski 0:01f31e923fe2 932 swd_set_target_reset(1);
Pawel Zarembski 0:01f31e923fe2 933 osDelay(2);
Pawel Zarembski 0:01f31e923fe2 934 swd_set_target_reset(0);
Pawel Zarembski 0:01f31e923fe2 935 osDelay(2);
Pawel Zarembski 0:01f31e923fe2 936 }
Pawel Zarembski 0:01f31e923fe2 937
Pawel Zarembski 0:01f31e923fe2 938 // Enable halt on reset
Pawel Zarembski 0:01f31e923fe2 939 if (!swd_write_word(DBG_EMCR, VC_CORERESET)) {
Pawel Zarembski 0:01f31e923fe2 940 return 0;
Pawel Zarembski 0:01f31e923fe2 941 }
Pawel Zarembski 0:01f31e923fe2 942
Pawel Zarembski 0:01f31e923fe2 943 if (reset_connect == CONNECT_NORMAL) {
Pawel Zarembski 0:01f31e923fe2 944 // Assert reset
Pawel Zarembski 0:01f31e923fe2 945 swd_set_target_reset(1);
Pawel Zarembski 0:01f31e923fe2 946 osDelay(2);
Pawel Zarembski 0:01f31e923fe2 947 }
Pawel Zarembski 0:01f31e923fe2 948
Pawel Zarembski 0:01f31e923fe2 949 // Deassert reset
Pawel Zarembski 0:01f31e923fe2 950 swd_set_target_reset(0);
Pawel Zarembski 0:01f31e923fe2 951 osDelay(2);
Pawel Zarembski 0:01f31e923fe2 952
Pawel Zarembski 0:01f31e923fe2 953 do {
Pawel Zarembski 0:01f31e923fe2 954 if (!swd_read_word(DBG_HCSR, &val)) {
Pawel Zarembski 0:01f31e923fe2 955 return 0;
Pawel Zarembski 0:01f31e923fe2 956 }
Pawel Zarembski 0:01f31e923fe2 957 } while ((val & S_HALT) == 0);
Pawel Zarembski 0:01f31e923fe2 958
Pawel Zarembski 0:01f31e923fe2 959 // Disable halt on reset
Pawel Zarembski 0:01f31e923fe2 960 if (!swd_write_word(DBG_EMCR, 0)) {
Pawel Zarembski 0:01f31e923fe2 961 return 0;
Pawel Zarembski 0:01f31e923fe2 962 }
Pawel Zarembski 0:01f31e923fe2 963
Pawel Zarembski 0:01f31e923fe2 964 break;
Pawel Zarembski 0:01f31e923fe2 965
Pawel Zarembski 0:01f31e923fe2 966 case NO_DEBUG:
Pawel Zarembski 0:01f31e923fe2 967 if (!swd_write_word(DBG_HCSR, DBGKEY)) {
Pawel Zarembski 0:01f31e923fe2 968 return 0;
Pawel Zarembski 0:01f31e923fe2 969 }
Pawel Zarembski 0:01f31e923fe2 970
Pawel Zarembski 0:01f31e923fe2 971 break;
Pawel Zarembski 0:01f31e923fe2 972
Pawel Zarembski 0:01f31e923fe2 973 case DEBUG:
Pawel Zarembski 0:01f31e923fe2 974 if (!JTAG2SWD()) {
Pawel Zarembski 0:01f31e923fe2 975 return 0;
Pawel Zarembski 0:01f31e923fe2 976 }
Pawel Zarembski 0:01f31e923fe2 977
Pawel Zarembski 0:01f31e923fe2 978 if (!swd_clear_errors()) {
Pawel Zarembski 0:01f31e923fe2 979 return 0;
Pawel Zarembski 0:01f31e923fe2 980 }
Pawel Zarembski 0:01f31e923fe2 981
Pawel Zarembski 0:01f31e923fe2 982 // Ensure CTRL/STAT register selected in DPBANKSEL
Pawel Zarembski 0:01f31e923fe2 983 if (!swd_write_dp(DP_SELECT, 0)) {
Pawel Zarembski 0:01f31e923fe2 984 return 0;
Pawel Zarembski 0:01f31e923fe2 985 }
Pawel Zarembski 0:01f31e923fe2 986
Pawel Zarembski 0:01f31e923fe2 987 // Power up
Pawel Zarembski 0:01f31e923fe2 988 if (!swd_write_dp(DP_CTRL_STAT, CSYSPWRUPREQ | CDBGPWRUPREQ)) {
Pawel Zarembski 0:01f31e923fe2 989 return 0;
Pawel Zarembski 0:01f31e923fe2 990 }
Pawel Zarembski 0:01f31e923fe2 991
Pawel Zarembski 0:01f31e923fe2 992 // Enable debug
Pawel Zarembski 0:01f31e923fe2 993 if (!swd_write_word(DBG_HCSR, DBGKEY | C_DEBUGEN)) {
Pawel Zarembski 0:01f31e923fe2 994 return 0;
Pawel Zarembski 0:01f31e923fe2 995 }
Pawel Zarembski 0:01f31e923fe2 996
Pawel Zarembski 0:01f31e923fe2 997 break;
Pawel Zarembski 0:01f31e923fe2 998
Pawel Zarembski 0:01f31e923fe2 999 case HALT:
Pawel Zarembski 0:01f31e923fe2 1000 if (!swd_init_debug()) {
Pawel Zarembski 0:01f31e923fe2 1001 return 0;
Pawel Zarembski 0:01f31e923fe2 1002 }
Pawel Zarembski 0:01f31e923fe2 1003
Pawel Zarembski 0:01f31e923fe2 1004 // Enable debug and halt the core (DHCSR <- 0xA05F0003)
Pawel Zarembski 0:01f31e923fe2 1005 if (!swd_write_word(DBG_HCSR, DBGKEY | C_DEBUGEN | C_HALT)) {
Pawel Zarembski 0:01f31e923fe2 1006 return 0;
Pawel Zarembski 0:01f31e923fe2 1007 }
Pawel Zarembski 0:01f31e923fe2 1008
Pawel Zarembski 0:01f31e923fe2 1009 // Wait until core is halted
Pawel Zarembski 0:01f31e923fe2 1010 do {
Pawel Zarembski 0:01f31e923fe2 1011 if (!swd_read_word(DBG_HCSR, &val)) {
Pawel Zarembski 0:01f31e923fe2 1012 return 0;
Pawel Zarembski 0:01f31e923fe2 1013 }
Pawel Zarembski 0:01f31e923fe2 1014 } while ((val & S_HALT) == 0);
Pawel Zarembski 0:01f31e923fe2 1015 break;
Pawel Zarembski 0:01f31e923fe2 1016
Pawel Zarembski 0:01f31e923fe2 1017 case RUN:
Pawel Zarembski 0:01f31e923fe2 1018 if (!swd_write_word(DBG_HCSR, DBGKEY)) {
Pawel Zarembski 0:01f31e923fe2 1019 return 0;
Pawel Zarembski 0:01f31e923fe2 1020 }
Pawel Zarembski 0:01f31e923fe2 1021 swd_off();
Pawel Zarembski 0:01f31e923fe2 1022 break;
Pawel Zarembski 0:01f31e923fe2 1023
Pawel Zarembski 0:01f31e923fe2 1024 case POST_FLASH_RESET:
Pawel Zarembski 0:01f31e923fe2 1025 // This state should be handled in target_reset.c, nothing needs to be done here.
Pawel Zarembski 0:01f31e923fe2 1026 break;
Pawel Zarembski 0:01f31e923fe2 1027
Pawel Zarembski 0:01f31e923fe2 1028 default:
Pawel Zarembski 0:01f31e923fe2 1029 return 0;
Pawel Zarembski 0:01f31e923fe2 1030 }
Pawel Zarembski 0:01f31e923fe2 1031
Pawel Zarembski 0:01f31e923fe2 1032 return 1;
Pawel Zarembski 0:01f31e923fe2 1033 }
Pawel Zarembski 0:01f31e923fe2 1034
Pawel Zarembski 0:01f31e923fe2 1035 uint8_t swd_set_target_state_sw(target_state_t state)
Pawel Zarembski 0:01f31e923fe2 1036 {
Pawel Zarembski 0:01f31e923fe2 1037 uint32_t val;
Pawel Zarembski 0:01f31e923fe2 1038 int8_t ap_retries = 2;
Pawel Zarembski 0:01f31e923fe2 1039 /* Calling swd_init prior to enterring RUN state causes operations to fail. */
Pawel Zarembski 0:01f31e923fe2 1040 if (state != RUN) {
Pawel Zarembski 0:01f31e923fe2 1041 swd_init();
Pawel Zarembski 0:01f31e923fe2 1042 }
Pawel Zarembski 0:01f31e923fe2 1043
Pawel Zarembski 0:01f31e923fe2 1044 switch (state) {
Pawel Zarembski 0:01f31e923fe2 1045 case RESET_HOLD:
Pawel Zarembski 0:01f31e923fe2 1046 swd_set_target_reset(1);
Pawel Zarembski 0:01f31e923fe2 1047 break;
Pawel Zarembski 0:01f31e923fe2 1048
Pawel Zarembski 0:01f31e923fe2 1049 case RESET_RUN:
Pawel Zarembski 0:01f31e923fe2 1050 swd_set_target_reset(1);
Pawel Zarembski 0:01f31e923fe2 1051 osDelay(2);
Pawel Zarembski 0:01f31e923fe2 1052 swd_set_target_reset(0);
Pawel Zarembski 0:01f31e923fe2 1053 osDelay(2);
Pawel Zarembski 0:01f31e923fe2 1054 swd_off();
Pawel Zarembski 0:01f31e923fe2 1055 break;
Pawel Zarembski 0:01f31e923fe2 1056
Pawel Zarembski 0:01f31e923fe2 1057 case RESET_PROGRAM:
Pawel Zarembski 0:01f31e923fe2 1058 if (!swd_init_debug()) {
Pawel Zarembski 0:01f31e923fe2 1059 return 0;
Pawel Zarembski 0:01f31e923fe2 1060 }
Pawel Zarembski 0:01f31e923fe2 1061
Pawel Zarembski 0:01f31e923fe2 1062 // Enable debug and halt the core (DHCSR <- 0xA05F0003)
Pawel Zarembski 0:01f31e923fe2 1063 while (swd_write_word(DBG_HCSR, DBGKEY | C_DEBUGEN | C_HALT) == 0) {
Pawel Zarembski 0:01f31e923fe2 1064 if ( --ap_retries <=0 ) {
Pawel Zarembski 0:01f31e923fe2 1065 return 0;
Pawel Zarembski 0:01f31e923fe2 1066 }
Pawel Zarembski 0:01f31e923fe2 1067 // Target is in invalid state?
Pawel Zarembski 0:01f31e923fe2 1068 swd_set_target_reset(1);
Pawel Zarembski 0:01f31e923fe2 1069 osDelay(2);
Pawel Zarembski 0:01f31e923fe2 1070 swd_set_target_reset(0);
Pawel Zarembski 0:01f31e923fe2 1071 osDelay(2);
Pawel Zarembski 0:01f31e923fe2 1072 }
Pawel Zarembski 0:01f31e923fe2 1073
Pawel Zarembski 0:01f31e923fe2 1074 // Wait until core is halted
Pawel Zarembski 0:01f31e923fe2 1075 do {
Pawel Zarembski 0:01f31e923fe2 1076 if (!swd_read_word(DBG_HCSR, &val)) {
Pawel Zarembski 0:01f31e923fe2 1077 return 0;
Pawel Zarembski 0:01f31e923fe2 1078 }
Pawel Zarembski 0:01f31e923fe2 1079 } while ((val & S_HALT) == 0);
Pawel Zarembski 0:01f31e923fe2 1080
Pawel Zarembski 0:01f31e923fe2 1081 // Enable halt on reset
Pawel Zarembski 0:01f31e923fe2 1082 if (!swd_write_word(DBG_EMCR, VC_CORERESET)) {
Pawel Zarembski 0:01f31e923fe2 1083 return 0;
Pawel Zarembski 0:01f31e923fe2 1084 }
Pawel Zarembski 0:01f31e923fe2 1085
Pawel Zarembski 0:01f31e923fe2 1086 // Perform a soft reset
Pawel Zarembski 0:01f31e923fe2 1087 if (!swd_read_word(NVIC_AIRCR, &val)) {
Pawel Zarembski 0:01f31e923fe2 1088 return 0;
Pawel Zarembski 0:01f31e923fe2 1089 }
Pawel Zarembski 0:01f31e923fe2 1090
Pawel Zarembski 0:01f31e923fe2 1091 if (!swd_write_word(NVIC_AIRCR, VECTKEY | (val & SCB_AIRCR_PRIGROUP_Msk) | soft_reset)) {
Pawel Zarembski 0:01f31e923fe2 1092 return 0;
Pawel Zarembski 0:01f31e923fe2 1093 }
Pawel Zarembski 0:01f31e923fe2 1094
Pawel Zarembski 0:01f31e923fe2 1095 osDelay(2);
Pawel Zarembski 0:01f31e923fe2 1096
Pawel Zarembski 0:01f31e923fe2 1097 do {
Pawel Zarembski 0:01f31e923fe2 1098 if (!swd_read_word(DBG_HCSR, &val)) {
Pawel Zarembski 0:01f31e923fe2 1099 return 0;
Pawel Zarembski 0:01f31e923fe2 1100 }
Pawel Zarembski 0:01f31e923fe2 1101 } while ((val & S_HALT) == 0);
Pawel Zarembski 0:01f31e923fe2 1102
Pawel Zarembski 0:01f31e923fe2 1103 // Disable halt on reset
Pawel Zarembski 0:01f31e923fe2 1104 if (!swd_write_word(DBG_EMCR, 0)) {
Pawel Zarembski 0:01f31e923fe2 1105 return 0;
Pawel Zarembski 0:01f31e923fe2 1106 }
Pawel Zarembski 0:01f31e923fe2 1107
Pawel Zarembski 0:01f31e923fe2 1108 break;
Pawel Zarembski 0:01f31e923fe2 1109
Pawel Zarembski 0:01f31e923fe2 1110 case NO_DEBUG:
Pawel Zarembski 0:01f31e923fe2 1111 if (!swd_write_word(DBG_HCSR, DBGKEY)) {
Pawel Zarembski 0:01f31e923fe2 1112 return 0;
Pawel Zarembski 0:01f31e923fe2 1113 }
Pawel Zarembski 0:01f31e923fe2 1114
Pawel Zarembski 0:01f31e923fe2 1115 break;
Pawel Zarembski 0:01f31e923fe2 1116
Pawel Zarembski 0:01f31e923fe2 1117 case DEBUG:
Pawel Zarembski 0:01f31e923fe2 1118 if (!JTAG2SWD()) {
Pawel Zarembski 0:01f31e923fe2 1119 return 0;
Pawel Zarembski 0:01f31e923fe2 1120 }
Pawel Zarembski 0:01f31e923fe2 1121
Pawel Zarembski 0:01f31e923fe2 1122 if (!swd_clear_errors()) {
Pawel Zarembski 0:01f31e923fe2 1123 return 0;
Pawel Zarembski 0:01f31e923fe2 1124 }
Pawel Zarembski 0:01f31e923fe2 1125
Pawel Zarembski 0:01f31e923fe2 1126 // Ensure CTRL/STAT register selected in DPBANKSEL
Pawel Zarembski 0:01f31e923fe2 1127 if (!swd_write_dp(DP_SELECT, 0)) {
Pawel Zarembski 0:01f31e923fe2 1128 return 0;
Pawel Zarembski 0:01f31e923fe2 1129 }
Pawel Zarembski 0:01f31e923fe2 1130
Pawel Zarembski 0:01f31e923fe2 1131 // Power up
Pawel Zarembski 0:01f31e923fe2 1132 if (!swd_write_dp(DP_CTRL_STAT, CSYSPWRUPREQ | CDBGPWRUPREQ)) {
Pawel Zarembski 0:01f31e923fe2 1133 return 0;
Pawel Zarembski 0:01f31e923fe2 1134 }
Pawel Zarembski 0:01f31e923fe2 1135
Pawel Zarembski 0:01f31e923fe2 1136 // Enable debug
Pawel Zarembski 0:01f31e923fe2 1137 if (!swd_write_word(DBG_HCSR, DBGKEY | C_DEBUGEN)) {
Pawel Zarembski 0:01f31e923fe2 1138 return 0;
Pawel Zarembski 0:01f31e923fe2 1139 }
Pawel Zarembski 0:01f31e923fe2 1140
Pawel Zarembski 0:01f31e923fe2 1141 break;
Pawel Zarembski 0:01f31e923fe2 1142
Pawel Zarembski 0:01f31e923fe2 1143 case HALT:
Pawel Zarembski 0:01f31e923fe2 1144 if (!swd_init_debug()) {
Pawel Zarembski 0:01f31e923fe2 1145 return 0;
Pawel Zarembski 0:01f31e923fe2 1146 }
Pawel Zarembski 0:01f31e923fe2 1147
Pawel Zarembski 0:01f31e923fe2 1148 // Enable debug and halt the core (DHCSR <- 0xA05F0003)
Pawel Zarembski 0:01f31e923fe2 1149 if (!swd_write_word(DBG_HCSR, DBGKEY | C_DEBUGEN | C_HALT)) {
Pawel Zarembski 0:01f31e923fe2 1150 return 0;
Pawel Zarembski 0:01f31e923fe2 1151 }
Pawel Zarembski 0:01f31e923fe2 1152
Pawel Zarembski 0:01f31e923fe2 1153 // Wait until core is halted
Pawel Zarembski 0:01f31e923fe2 1154 do {
Pawel Zarembski 0:01f31e923fe2 1155 if (!swd_read_word(DBG_HCSR, &val)) {
Pawel Zarembski 0:01f31e923fe2 1156 return 0;
Pawel Zarembski 0:01f31e923fe2 1157 }
Pawel Zarembski 0:01f31e923fe2 1158 } while ((val & S_HALT) == 0);
Pawel Zarembski 0:01f31e923fe2 1159 break;
Pawel Zarembski 0:01f31e923fe2 1160
Pawel Zarembski 0:01f31e923fe2 1161 case RUN:
Pawel Zarembski 0:01f31e923fe2 1162 if (!swd_write_word(DBG_HCSR, DBGKEY)) {
Pawel Zarembski 0:01f31e923fe2 1163 return 0;
Pawel Zarembski 0:01f31e923fe2 1164 }
Pawel Zarembski 0:01f31e923fe2 1165 swd_off();
Pawel Zarembski 0:01f31e923fe2 1166 break;
Pawel Zarembski 0:01f31e923fe2 1167
Pawel Zarembski 0:01f31e923fe2 1168 case POST_FLASH_RESET:
Pawel Zarembski 0:01f31e923fe2 1169 // This state should be handled in target_reset.c, nothing needs to be done here.
Pawel Zarembski 0:01f31e923fe2 1170 break;
Pawel Zarembski 0:01f31e923fe2 1171
Pawel Zarembski 0:01f31e923fe2 1172 default:
Pawel Zarembski 0:01f31e923fe2 1173 return 0;
Pawel Zarembski 0:01f31e923fe2 1174 }
Pawel Zarembski 0:01f31e923fe2 1175
Pawel Zarembski 0:01f31e923fe2 1176 return 1;
Pawel Zarembski 0:01f31e923fe2 1177 }
Pawel Zarembski 0:01f31e923fe2 1178 #endif