Detour swd primitives.

This commit is contained in:
Uwe Bonnes 2020-04-16 17:27:26 +02:00
parent 1e10b96b03
commit e34a27f72c
14 changed files with 100 additions and 175 deletions

View File

@ -1,6 +1,6 @@
PROBE_HOST ?= native
PLATFORM_DIR = platforms/$(PROBE_HOST)
VPATH += $(PLATFORM_DIR) platforms/common target
VPATH += $(PLATFORM_DIR) target
ENABLE_DEBUG ?=
ifneq ($(V), 1)
@ -9,8 +9,8 @@ Q := @
endif
CFLAGS += -Wall -Wextra -Werror -Wno-char-subscripts \
-std=gnu99 -g3 -MD \
-I. -Iinclude -Iplatforms/common -I$(PLATFORM_DIR)
-std=gnu99 -g3 -MD -I./target \
-I. -Iinclude -I$(PLATFORM_DIR)
ifeq ($(ENABLE_DEBUG), 1)
CFLAGS += -DENABLE_DEBUG
@ -55,6 +55,7 @@ SRC = \
stm32h7.c \
stm32l0.c \
stm32l4.c \
swdptap.c \
target.c \
include $(PLATFORM_DIR)/Makefile.inc
@ -72,7 +73,7 @@ SRC += jtagtap_generic.c swdptap_generic.c
endif
ifndef OWN_HL
SRC += jtag_scan.c jtagtap.c swdptap.c
SRC += jtag_scan.c jtagtap.c
else
CFLAGS += -DOWN_HL
endif
@ -81,6 +82,8 @@ ifdef PC_HOSTED
CFLAGS += -DPC_HOSTED=1
else
CFLAGS += -DPC_HOSTED=0
VPATH += platforms/common
CFLAGS += -Iplatforms/common
endif
OBJ = $(patsubst %.S,%.o,$(patsubst %.c,%.o,$(SRC)))

View File

@ -20,20 +20,17 @@
#ifndef __SWDPTAP_H
#define __SWDPTAP_H
typedef struct swd_proc_s {
uint32_t (*swdptap_seq_in)(int ticks);
bool (*swdptap_seq_in_parity)(uint32_t *data, int ticks);
void (*swdptap_seq_out)(uint32_t MS, int ticks);
void (*swdptap_seq_out_parity)(uint32_t MS, int ticks);
} swd_proc_t;
extern swd_proc_t swd_proc;
# if PC_HOSTED == 1
int platform_swdptap_init(void);
# else
int swdptap_init(void);
/* Primitive functions */
bool swdptap_bit_in(void);
void swdptap_bit_out(bool val);
/* Low level functions, provided in swdptap_generic.c from the primitives
(indicate NO_OWN_LL in the Makefile.inc or libopencm specific in
platforms/common*/
uint32_t swdptap_seq_in(int ticks);
bool swdptap_seq_in_parity(uint32_t *data, int ticks);
void swdptap_seq_out(uint32_t MS, int ticks);
void swdptap_seq_out_parity(uint32_t MS, int ticks);
# endif
#endif

View File

@ -34,16 +34,13 @@ typedef struct target_s target;
typedef uint32_t target_addr;
struct target_controller;
#if defined(PC_HOSTED)
#if PC_HOSTED == 1
int platform_adiv5_swdp_scan(void);
int platform_jtag_scan(const uint8_t *lrlens);
#endif
int adiv5_swdp_scan(void);
int jtag_scan(const uint8_t *lrlens);
int adiv5_swdp_scan(void);
int jtag_scan(const uint8_t *lrlens);
bool target_foreach(void (*cb)(int i, target *t, void *context), void *context);
void target_list_free(void);

View File

@ -27,4 +27,3 @@ struct platform_timeout {
uint32_t platform_time_ms(void);
#endif /* __TIMING_H */

View File

@ -28,11 +28,6 @@ enum {
SWDIO_STATUS_DRIVE
};
int swdptap_init(void)
{
return 0;
}
static void swdptap_turnaround(int dir)
{
static int olddir = SWDIO_STATUS_FLOAT;
@ -54,26 +49,7 @@ static void swdptap_turnaround(int dir)
SWDIO_MODE_DRIVE();
}
bool swdptap_bit_in(void)
{
uint16_t ret;
swdptap_turnaround(SWDIO_STATUS_FLOAT);
ret = gpio_get(SWDIO_PORT, SWDIO_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_clear(SWCLK_PORT, SWCLK_PIN);
#ifdef DEBUG_SWD_BITS
DEBUG("%d", ret?1:0);
#endif
return ret != 0;
}
uint32_t
swdptap_seq_in(int ticks)
static uint32_t swdptap_seq_in(int ticks)
{
uint32_t index = 1;
uint32_t ret = 0;
@ -97,8 +73,7 @@ swdptap_seq_in(int ticks)
return ret;
}
bool
swdptap_seq_in_parity(uint32_t *ret, int ticks)
static bool swdptap_seq_in_parity(uint32_t *ret, int ticks)
{
uint32_t index = 1;
uint8_t parity = 0;
@ -130,22 +105,7 @@ swdptap_seq_in_parity(uint32_t *ret, int ticks)
return parity;
}
void swdptap_bit_out(bool val)
{
#ifdef DEBUG_SWD_BITS
DEBUG("%d", val);
#endif
swdptap_turnaround(SWDIO_STATUS_DRIVE);
gpio_set_val(SWDIO_PORT, SWDIO_PIN, val);
gpio_clear(SWCLK_PORT, SWCLK_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_clear(SWCLK_PORT, SWCLK_PIN);
}
void
swdptap_seq_out(uint32_t MS, int ticks)
static void swdptap_seq_out(uint32_t MS, int ticks)
{
int data = MS & 1;
#ifdef DEBUG_SWD_BITS
@ -163,8 +123,7 @@ swdptap_seq_out(uint32_t MS, int ticks)
}
}
void
swdptap_seq_out_parity(uint32_t MS, int ticks)
static void swdptap_seq_out_parity(uint32_t MS, int ticks)
{
uint8_t parity = 0;
int data = MS & 1;
@ -188,3 +147,15 @@ swdptap_seq_out_parity(uint32_t MS, int ticks)
gpio_set(SWCLK_PORT, SWCLK_PIN);
gpio_clear(SWCLK_PORT, SWCLK_PIN);
}
swd_proc_t swd_proc;
int swdptap_init(void)
{
swd_proc.swdptap_seq_in = swdptap_seq_in;
swd_proc.swdptap_seq_in_parity = swdptap_seq_in_parity;
swd_proc.swdptap_seq_out = swdptap_seq_out;
swd_proc.swdptap_seq_out_parity = swdptap_seq_out_parity;
return 0;
}

View File

@ -35,7 +35,14 @@ static uint8_t olddir = 0;
#define MPSSE_TMS_SHIFT (MPSSE_WRITE_TMS | MPSSE_LSB |\
MPSSE_BITMODE | MPSSE_WRITE_NEG)
int swdptap_init(void)
static bool swdptap_seq_in_parity(uint32_t *res, int ticks);
static uint32_t swdptap_seq_in(int ticks);
static void swdptap_seq_out(uint32_t MS, int ticks);
static void swdptap_seq_out_parity(uint32_t MS, int ticks);
swd_proc_t swd_proc;
int platform_swdptap_init(void)
{
if (!active_cable->bitbang_tms_in_pin) {
DEBUG("SWD not possible or missing item in cable description.\n");
@ -70,6 +77,11 @@ int swdptap_init(void)
platform_buffer_write(ftdi_init, 9);
platform_buffer_flush();
swd_proc.swdptap_seq_in = swdptap_seq_in;
swd_proc.swdptap_seq_in_parity = swdptap_seq_in_parity;
swd_proc.swdptap_seq_out = swdptap_seq_out;
swd_proc.swdptap_seq_out_parity = swdptap_seq_out_parity;
return 0;
}
@ -102,34 +114,7 @@ static void swdptap_turnaround(uint8_t dir)
platform_buffer_write(cmd, index);
}
bool swdptap_bit_in(void)
{
swdptap_turnaround(1);
uint8_t cmd[4];
int index = 0;
cmd[index++] = active_cable->bitbang_tms_in_port_cmd;
cmd[index++] = MPSSE_TMS_SHIFT;
cmd[index++] = 0;
cmd[index++] = 0;
platform_buffer_write(cmd, index);
uint8_t data[1];
platform_buffer_read(data, 1);
return (data[0] &= active_cable->bitbang_tms_in_pin);
}
void swdptap_bit_out(bool val)
{
swdptap_turnaround(0);
uint8_t cmd[3];
cmd[0] = MPSSE_TMS_SHIFT;
cmd[1] = 0;
cmd[2] = (val)? 1 : 0;
platform_buffer_write(cmd, 3);
}
bool swdptap_seq_in_parity(uint32_t *res, int ticks)
static bool swdptap_seq_in_parity(uint32_t *res, int ticks)
{
int index = ticks + 1;
uint8_t cmd[4];
@ -158,7 +143,7 @@ bool swdptap_seq_in_parity(uint32_t *res, int ticks)
return parity;
}
uint32_t swdptap_seq_in(int ticks)
static uint32_t swdptap_seq_in(int ticks)
{
int index = ticks;
uint8_t cmd[4];
@ -182,7 +167,7 @@ uint32_t swdptap_seq_in(int ticks)
return ret;
}
void swdptap_seq_out(uint32_t MS, int ticks)
static void swdptap_seq_out(uint32_t MS, int ticks)
{
uint8_t cmd[15];
unsigned int index = 0;
@ -203,7 +188,7 @@ void swdptap_seq_out(uint32_t MS, int ticks)
platform_buffer_write(cmd, index);
}
void swdptap_seq_out_parity(uint32_t MS, int ticks)
static void swdptap_seq_out_parity(uint32_t MS, int ticks)
{
uint8_t parity = 0;
int steps = ticks;

View File

@ -30,7 +30,14 @@
#include "swdptap.h"
#include "remote.h"
int swdptap_init(void)
static bool swdptap_seq_in_parity(uint32_t *res, int ticks);
static uint32_t swdptap_seq_in(int ticks);
static void swdptap_seq_out(uint32_t MS, int ticks);
static void swdptap_seq_out_parity(uint32_t MS, int ticks);
swd_proc_t swd_proc;
int platform_swdptap_init(void)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
@ -46,11 +53,15 @@ int swdptap_init(void)
exit(-1);
}
swd_proc.swdptap_seq_in = swdptap_seq_in;
swd_proc.swdptap_seq_in_parity = swdptap_seq_in_parity;
swd_proc.swdptap_seq_out = swdptap_seq_out;
swd_proc.swdptap_seq_out_parity = swdptap_seq_out_parity;
return 0;
}
bool swdptap_seq_in_parity(uint32_t *res, int ticks)
static bool swdptap_seq_in_parity(uint32_t *res, int ticks)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
@ -70,8 +81,7 @@ bool swdptap_seq_in_parity(uint32_t *res, int ticks)
return (construct[0]!=REMOTE_RESP_OK);
}
uint32_t swdptap_seq_in(int ticks)
static uint32_t swdptap_seq_in(int ticks)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
@ -89,7 +99,7 @@ uint32_t swdptap_seq_in(int ticks)
return remotehston(-1,(char *)&construct[1]);
}
void swdptap_seq_out(uint32_t MS, int ticks)
static void swdptap_seq_out(uint32_t MS, int ticks)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;
@ -106,7 +116,7 @@ void swdptap_seq_out(uint32_t MS, int ticks)
}
void swdptap_seq_out_parity(uint32_t MS, int ticks)
static void swdptap_seq_out_parity(uint32_t MS, int ticks)
{
uint8_t construct[PLATFORM_MAX_MSG_SIZE];
int s;

View File

@ -1,49 +0,0 @@
/*
* This file is part of the Black Magic Debug project.
*
* Copyright (C) 2011 Black Sphere Technologies Ltd.
* Written by Gareth McMullin <gareth@blacksphere.co.nz>
* Copyright (C) 2019 Uwe Bonnes (bon@elektron.ikp.physik.tu-darmstadt.de)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/* This file implements the SW-DP specific functions of the
* ARM Debug Interface v5 Architecure Specification, ARM doc IHI0031A.
*/
#include "general.h"
#include "target.h"
#include "target_internal.h"
#include "adiv5.h"
#include "stlinkv2.h"
int adiv5_swdp_scan(void)
{
target_list_free();
ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp));
if (stlink_enter_debug_swd())
return 0;
dp->idcode = stlink_read_coreid();
dp->dp_read = stlink_dp_read;
dp->error = stlink_dp_error;
dp->low_access = stlink_dp_low_access;
dp->abort = stlink_dp_abort;
stlink_dp_error(dp);
adiv5_dp_init(dp);
return target_list?1:0;
return 0;
}

View File

View File

@ -22,6 +22,7 @@
#include "platform.h"
#include "target.h"
#include "target_internal.h"
#include "swdptap.h"
#include <assert.h>
#include <unistd.h>
@ -41,6 +42,13 @@ const char *platform_target_voltage(void)
return stlink_target_voltage();
}
int platform_swdptap_init(void)
{
return 0;
}
swd_proc_t swd_proc;
static int adiv5_swdp_scan_stlinkv2(void)
{
target_list_free();

View File

View File

@ -115,27 +115,27 @@ void remotePacketProcessSWD(uint8_t i, char *packet)
case REMOTE_IN_PAR: /* = In parity ================================== */
ticks=remotehston(2,&packet[2]);
badParity=swdptap_seq_in_parity(&param, ticks);
badParity = swd_proc.swdptap_seq_in_parity(&param, ticks);
_respond(badParity?REMOTE_RESP_PARERR:REMOTE_RESP_OK,param);
break;
case REMOTE_IN: /* = In ========================================= */
ticks=remotehston(2,&packet[2]);
param=swdptap_seq_in(ticks);
param = swd_proc.swdptap_seq_in(ticks);
_respond(REMOTE_RESP_OK,param);
break;
case REMOTE_OUT: /* = Out ======================================== */
ticks=remotehston(2,&packet[2]);
param=remotehston(-1, &packet[4]);
swdptap_seq_out(param, ticks);
swd_proc.swdptap_seq_out(param, ticks);
_respond(REMOTE_RESP_OK, 0);
break;
case REMOTE_OUT_PAR: /* = Out parity ================================= */
ticks=remotehston(2,&packet[2]);
param=remotehston(-1, &packet[4]);
swdptap_seq_out_parity(param, ticks);
swd_proc.swdptap_seq_out_parity(param, ticks);
_respond(REMOTE_RESP_OK, 0);
break;

View File

@ -53,24 +53,28 @@ int adiv5_swdp_scan(void)
return -1;
}
#if PC_HOSTED == 1
if (platform_swdptap_init())
#else
if (swdptap_init())
#endif
return -1;
/* Switch from JTAG to SWD mode */
swdptap_seq_out(0xFFFFFFFF, 16);
swdptap_seq_out(0xFFFFFFFF, 32);
swdptap_seq_out(0xFFFFFFFF, 18);
swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */
swdptap_seq_out(0xFFFFFFFF, 32);
swdptap_seq_out(0xFFFFFFFF, 18);
swdptap_seq_out(0, 16);
swd_proc.swdptap_seq_out(0xFFFFFFFF, 16);
swd_proc.swdptap_seq_out(0xFFFFFFFF, 32);
swd_proc.swdptap_seq_out(0xFFFFFFFF, 18);
swd_proc.swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */
swd_proc.swdptap_seq_out(0xFFFFFFFF, 32);
swd_proc.swdptap_seq_out(0xFFFFFFFF, 18);
swd_proc.swdptap_seq_out(0, 16);
/* Read the SW-DP IDCODE register to syncronise */
/* This could be done with adiv_swdp_low_access(), but this doesn't
* allow the ack to be checked here. */
swdptap_seq_out(0xA5, 8);
ack = swdptap_seq_in(3);
if((ack != SWDP_ACK_OK) || swdptap_seq_in_parity(&dp->idcode, 32)) {
swd_proc.swdptap_seq_out(0xA5, 8);
ack = swd_proc.swdptap_seq_in(3);
if((ack != SWDP_ACK_OK) || swd_proc.swdptap_seq_in_parity(&dp->idcode, 32)) {
DEBUG("\n");
free(dp);
return -1;
@ -143,8 +147,8 @@ static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
platform_timeout_set(&timeout, 2000);
do {
swdptap_seq_out(request, 8);
ack = swdptap_seq_in(3);
swd_proc.swdptap_seq_out(request, 8);
ack = swd_proc.swdptap_seq_in(3);
} while (ack == SWDP_ACK_WAIT && !platform_timeout_is_expired(&timeout));
if (ack == SWDP_ACK_WAIT)
@ -159,10 +163,10 @@ static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
raise_exception(EXCEPTION_ERROR, "SWDP invalid ACK");
if(RnW) {
if(swdptap_seq_in_parity(&response, 32)) /* Give up on parity error */
if(swd_proc.swdptap_seq_in_parity(&response, 32)) /* Give up on parity error */
raise_exception(EXCEPTION_ERROR, "SWDP Parity error");
} else {
swdptap_seq_out_parity(value, 32);
swd_proc.swdptap_seq_out_parity(value, 32);
/* RM0377 Rev. 8 Chapter 27.5.4 for STM32L0x1 states:
* Because of the asynchronous clock domains SWCLK and HCLK,
* two extra SWCLK cycles are needed after a write transaction
@ -173,7 +177,7 @@ static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW,
* for a power-up request. If the next transaction (requiring
* a power-up) occurs immediately, it will fail.
*/
swdptap_seq_out(0, 2);
swd_proc.swdptap_seq_out(0, 2);
}
return response;