Skip to content

Commit

Permalink
Bugfix/swd sometimes work fail (#17)
Browse files Browse the repository at this point in the history
* projects: hpm5301evklite: fixed some issue

* projects: hslink-pro: fixed the problem of low-rate programming error

- the ack response should keep the lower three bits valid for swd
- trn should be variable length, 1 to 4 clock cycles for SPI_SWD_Transfer API
- idle_cycles should be valid for read and write operations for SPI_SWD_Transfer API

* projects: hslink-pro: improve CLK clock output accuracy

- in SPI mode, SWD can be adjusted from 80M to 100Khz
- in single SPI mode, jtag clk can be adjusted from 80 to 100 khz
- remove IO mode
  • Loading branch information
RCSN authored Sep 21, 2024
1 parent 3425a00 commit cacc36f
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 121 deletions.
2 changes: 1 addition & 1 deletion projects/HSLink-Pro/src/SW_DP/SW_DP.c
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#include "SW_DP.h"

PORT_Mode_t SWD_Port_Mode;
PORT_Mode_t SWD_Port_Mode = PORT_MODE_SPI;

void PORT_SWD_SETUP(void)
{
Expand Down
43 changes: 22 additions & 21 deletions projects/HSLink-Pro/src/SW_DP/SW_DP_SPI.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,13 +197,13 @@ uint8_t SPI_SWD_Transfer(uint32_t request, uint32_t *data)
spi_set_transfer_mode(SWD_SPI_BASE, spi_trans_write_only);
if (request & DAP_TRANSFER_RnW) {
spi_set_data_bits(SWD_SPI_BASE, 8);
ack_width = 4;
ack_width = 3 + DAP_Data.swd_conf.turnaround; /* trn max 4 periods */
} else {
for (i = 0; i < 32; i++) {
parity += (((*data) >> i) & 0x01);
}
spi_set_data_bits(SWD_SPI_BASE, 8);
ack_width = 5;
ack_width = DAP_Data.swd_conf.turnaround + 3 + DAP_Data.swd_conf.turnaround; /* trn + ack + trn*/
}
SWD_SPI_BASE->CMD = 0xFF;
SWD_SPI_BASE->DATA = host_data;
Expand All @@ -218,7 +218,8 @@ uint8_t SPI_SWD_Transfer(uint32_t request, uint32_t *data)
ack = SWD_SPI_BASE->DATA;
while (SWD_SPI_BASE->STATUS & SPI_STATUS_SPIACTIVE_MASK) {
};
ack >>= 1;
ack >>= DAP_Data.swd_conf.turnaround;
ack = ack & 0x07;
if (ack == DAP_TRANSFER_OK) { /* OK response */
/* Data transfer */
if (request & DAP_TRANSFER_RnW) {
Expand Down Expand Up @@ -274,31 +275,31 @@ uint8_t SPI_SWD_Transfer(uint32_t request, uint32_t *data)
SWD_SPI_BASE->DATA = parity;
while (SWD_SPI_BASE->STATUS & SPI_STATUS_SPIACTIVE_MASK) {
};
/* Capture Timestamp */
if (request & DAP_TRANSFER_TIMESTAMP) {
DAP_Data.timestamp = TIMESTAMP_GET();
}
if (DAP_Data.transfer.idle_cycles > 0) {
gpio_write_pin(PIN_SWDIO_DIR_GPIO, GPIO_GET_PORT_INDEX(SWDIO_DIR), GPIO_GET_PIN_INDEX(SWDIO_DIR), 1);
SWD_SPI_BASE->TRANSCTRL = 0x01000000; /* only write mode*/
SWD_SPI_BASE->TRANSFMT = 0x0018; /* datalen = 1bit, mosibidir = 1, lsb=1 */
spi_set_write_data_count(SWD_SPI_BASE, DAP_Data.transfer.idle_cycles);
SWD_SPI_BASE->CMD = 0xFF;
for (int i = 0; i < DAP_Data.transfer.idle_cycles; i++) {
SWD_SPI_BASE->DATA = 0;
while ((SWD_SPI_BASE->STATUS & SPI_STATUS_TXFULL_MASK) == SPI_STATUS_TXFULL_MASK) {
};
}
}
gpio_write_pin(PIN_SWDIO_DIR_GPIO, GPIO_GET_PORT_INDEX(SWDIO_DIR), GPIO_GET_PIN_INDEX(SWDIO_DIR), 1);
/* Capture Timestamp */
if (request & DAP_TRANSFER_TIMESTAMP) {
DAP_Data.timestamp = TIMESTAMP_GET();
}
if (DAP_Data.transfer.idle_cycles > 0) {
gpio_write_pin(PIN_SWDIO_DIR_GPIO, GPIO_GET_PORT_INDEX(SWDIO_DIR), GPIO_GET_PIN_INDEX(SWDIO_DIR), 1);
SWD_SPI_BASE->TRANSCTRL = 0x01000000; /* only write mode*/
SWD_SPI_BASE->TRANSFMT = 0x0018; /* datalen = 1bit, mosibidir = 1, lsb=1 */
spi_set_write_data_count(SWD_SPI_BASE, DAP_Data.transfer.idle_cycles);
SWD_SPI_BASE->CMD = 0xFF;
for (int i = 0; i < DAP_Data.transfer.idle_cycles; i++) {
SWD_SPI_BASE->DATA = 0;
while ((SWD_SPI_BASE->STATUS & SPI_STATUS_TXFULL_MASK) == SPI_STATUS_TXFULL_MASK) {
};
while (SWD_SPI_BASE->STATUS & SPI_STATUS_SPIACTIVE_MASK) {
};
}
while ((SWD_SPI_BASE->STATUS & SPI_STATUS_TXFULL_MASK) == SPI_STATUS_TXFULL_MASK) {
};
while (SWD_SPI_BASE->STATUS & SPI_STATUS_SPIACTIVE_MASK) {
};
}
gpio_write_pin(PIN_SWDIO_DIR_GPIO, GPIO_GET_PORT_INDEX(SWDIO_DIR), GPIO_GET_PIN_INDEX(SWDIO_DIR), 0);
return ack;
}

/* WAIT or FAULT response */
if ((ack == DAP_TRANSFER_WAIT) || (ack == DAP_TRANSFER_FAULT)) {
gpio_write_pin(PIN_SWDIO_DIR_GPIO, GPIO_GET_PORT_INDEX(SWDIO_DIR), GPIO_GET_PIN_INDEX(SWDIO_DIR), 0);
Expand Down
100 changes: 58 additions & 42 deletions projects/HSLink-Pro/src/dp_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,68 +7,84 @@
#include "DAP_config.h"
#include "DAP.h"
#include "hpm_spi_drv.h"
#include "hpm_clock_drv.h"
#include <stdlib.h>

#define SPI_MAX_SRC_CLOCK 80000000
#define SPI_MIN_SRC_CLOCK 60000000

#define SPI_MAX_SRC_CLOCK (80000000U)
#define SPI_MID_SRC_CLOCK (60000000U)
#define SPI_MIN_SRC_CLOCK (50000000U)
#define SPI_MIN_SCLK_CLOCK (20000000U)
void set_swj_clock_frequency(uint32_t clock)
{
uint8_t div, sclk_div;
int freq_list[clock_source_general_source_end] = {0};
uint32_t div, sclk_div;
uint32_t sclk_freq_in_hz;
sclk_freq_in_hz = clock;
SPI_Type *spi_base = NULL;
clock_name_t clock_name;
clock_source_t clock_source;
uint32_t pll_clk = 0;
int min_diff_freq;
int current_diff_freq;
int best_freq;
uint8_t i;
int _freq = sclk_freq_in_hz;
clk_src_t src_clock = clk_src_pll1_clk0; /* 800M */
if (BOOST_KEIL_SWD_FREQ == 1) {
sclk_freq_in_hz *= 10;
}
PORT_Mode_t mode;
if (DAP_Data.debug_port == DAP_PORT_SWD) {
if (sclk_freq_in_hz < 1000000) {
mode = PORT_MODE_GPIO;
} else {
mode = PORT_MODE_SPI;
}

// 判断是否需要切换模式
if (SWD_Port_Mode != mode) {
SWD_Port_Mode = mode;
PORT_SWD_SETUP();
}

spi_base = SWD_SPI_BASE;
clock_name = SWD_SPI_BASE_CLOCK_NAME;
} else {
if (sclk_freq_in_hz < 1000000) {
mode = PORT_MODE_GPIO;
} else {
mode = PORT_MODE_SPI;
}

// 判断是否需要切换模式
if (JTAG_Port_Mode != mode) {
JTAG_Port_Mode = mode;
PORT_JTAG_SETUP();
}

spi_base = JTAG_SPI_BASE;
clock_name = JTAG_SPI_BASE_CLOCK_NAME;
}

if (mode == PORT_MODE_GPIO) {
Set_Clock_Delay(sclk_freq_in_hz);
return;
}

sclk_div = ((SPI_MAX_SRC_CLOCK / sclk_freq_in_hz) / 2) - 1; /* SCLK = SPI_SRC_CLOK / ((SCLK_DIV + 1) * 2)*/
if (sclk_div <= 0xFE) {
div = 10;
} else {
src_clock = clk_src_pll0_clk1; /* 600M */
sclk_div = ((SPI_MIN_SRC_CLOCK / sclk_freq_in_hz) / 2) - 1; /* SCLK = SPI_SRC_CLOK / ((SCLK_DIV + 1) * 2)*/
if (sclk_freq_in_hz <= SPI_MIN_SCLK_CLOCK) {
sclk_div = ((SPI_MAX_SRC_CLOCK / sclk_freq_in_hz) / 2) - 1; /* SCLK = SPI_SRC_CLOK / ((SCLK_DIV + 1) * 2)*/
if (sclk_div <= 0xFE) {
div = 10;
sclk_div = 0xFE; /* The minimum sclk clock allowed is 117KHz */
} else {
div = 10;
src_clock = clk_src_pll0_clk1; /* 600M */
sclk_div = ((SPI_MID_SRC_CLOCK / sclk_freq_in_hz) / 2) - 1; /* SCLK = SPI_SRC_CLOK / ((SCLK_DIV + 1) * 2)*/
if (sclk_div >= 0xFE) {
div = 10;
src_clock = clk_src_pll1_clk2; /* 500M */
sclk_div = ((SPI_MIN_SRC_CLOCK / sclk_freq_in_hz) / 2) - 1;
if (sclk_div >= 0xFE) {
sclk_div = 0xFE; /* The minimum sclk clock allowed is 98KHz */
}
}
}
} else {
sclk_div = 0xFF;
for (clock_source = (clock_source_t)0; clock_source < clock_source_general_source_end; clock_source++) {
pll_clk = get_frequency_for_source(clock_source);
div = pll_clk / sclk_freq_in_hz;
/* The division factor ranges from 1 to 256 as any integer */
if ((div > 0) && (div <= 0x100)) {
freq_list[clock_source] = pll_clk / div;
}
}
/* Find the best sclk frequency */
min_diff_freq = abs(freq_list[0] - _freq);
best_freq = freq_list[0];
for (i = 1; i < clock_source_general_source_end; i++) {
current_diff_freq = abs(freq_list[i] - _freq);
if (current_diff_freq < min_diff_freq) {
min_diff_freq = current_diff_freq;
best_freq = freq_list[i];
}
}
/* Find the best spi clock frequency */
for (i = 0; i < clock_source_general_source_end; i++) {
if (best_freq == freq_list[i]) {
pll_clk = get_frequency_for_source((clock_source_t)i);
src_clock = MAKE_CLK_SRC(CLK_SRC_GROUP_COMMON, i);
div = pll_clk / best_freq;
break;
}
}
}
spi_master_set_sclk_div(spi_base, sclk_div);
Expand Down
13 changes: 9 additions & 4 deletions projects/hpm5301evklite/JTAG_DP_SPI.c
Original file line number Diff line number Diff line change
Expand Up @@ -401,7 +401,7 @@ static void jtag_spi_ir_fast(uint32_t ir, uint16_t ir_before, uint8_t ir_length,
}
if (ir_length) {
jtag_ir(ir, ir_length - 1); /* Set IR bits (except last) */
ir >>= (ir_length - 2);
ir >>= (ir_length - 1);
}
if (ir_after) {
/* Set last IR bit */
Expand Down Expand Up @@ -454,13 +454,13 @@ static uint8_t jtag_spi_transfer_fast(uint32_t request, uint32_t *data, uint8_t
spi_set_read_data_count(JTAG_SPI_BASE, 1);
spi_set_write_data_count(JTAG_SPI_BASE, 1);
JTAG_SPI_BASE->CMD = 0xFF; /* Write a dummy byte */
JTAG_SPI_BASE->DATA = request;
JTAG_SPI_BASE->DATA = request >> 0x01;
while ((JTAG_SPI_BASE->STATUS & SPI_STATUS_RXEMPTY_MASK) == SPI_STATUS_RXEMPTY_MASK) {
};
bit = JTAG_SPI_BASE->DATA;
while (JTAG_SPI_BASE->STATUS & SPI_STATUS_SPIACTIVE_MASK) {
};
ack = ((bit & 0x01) << 1) | ((bit & 0x02) >> 0) | (bit & 0x04);
ack = ((bit & 0x01) << 1) | ((bit & 0x02) >> 1) | (bit & 0x04);
if (ack != DAP_TRANSFER_OK) {
gpio_write_pin(PIN_JTAG_GPIO, GPIO_GET_PORT_INDEX(PIN_SINGLE_SPI_JTAG_TMS), GPIO_GET_PIN_INDEX(PIN_SINGLE_SPI_JTAG_TMS), true);
jtag_less_than_32bit_size_for_tck(1, 0xFFFFFFFF);
Expand All @@ -472,7 +472,7 @@ static uint8_t jtag_spi_transfer_fast(uint32_t request, uint32_t *data, uint8_t
val = 0;
/* Get D0..D30 */
spi_set_transfer_mode(JTAG_SPI_BASE, spi_trans_read_only);
spi_set_data_bits(JTAG_SPI_BASE, 32);
spi_set_data_bits(JTAG_SPI_BASE, 31);
spi_set_read_data_count(JTAG_SPI_BASE, 1);
spi_set_write_data_count(JTAG_SPI_BASE, 1);
JTAG_SPI_BASE->CMD = 0xFF; /* Write a dummy byte */
Expand Down Expand Up @@ -545,9 +545,11 @@ static uint8_t jtag_spi_transfer_fast(uint32_t request, uint32_t *data, uint8_t
}
}
exit:
gpio_write_pin(PIN_JTAG_GPIO, GPIO_GET_PORT_INDEX(PIN_SINGLE_SPI_JTAG_TMS), GPIO_GET_PIN_INDEX(PIN_SINGLE_SPI_JTAG_TMS), 1);
/* Update-DR */
jtag_less_than_32bit_size_for_tck(1, 0);
board_write_spi_cs(BOARD_SPI_CS_PIN, false);
gpio_write_pin(PIN_JTAG_GPIO, GPIO_GET_PORT_INDEX(PIN_SINGLE_SPI_JTAG_TMS), GPIO_GET_PIN_INDEX(PIN_SINGLE_SPI_JTAG_TMS), 0);
/* Idle */
jtag_less_than_32bit_size_for_tck(1, 0xFFFFFFFF);

Expand All @@ -556,6 +558,7 @@ static uint8_t jtag_spi_transfer_fast(uint32_t request, uint32_t *data, uint8_t
// DAP_Data.timestamp = TIMESTAMP_GET();
}

gpio_write_pin(PIN_JTAG_GPIO, GPIO_GET_PORT_INDEX(PIN_SINGLE_SPI_JTAG_TMS), GPIO_GET_PIN_INDEX(PIN_SINGLE_SPI_JTAG_TMS), 0);
/* Idle cycles */
jtag_less_than_32bit_size_for_tck(idle_cycles, 0xFFFFFFFF);
return ((uint8_t)ack);
Expand Down Expand Up @@ -606,9 +609,11 @@ static uint32_t jtag_spi_read_idcode (uint8_t index)
while (JTAG_SPI_BASE->STATUS & SPI_STATUS_SPIACTIVE_MASK) {
};
val |= bit << 31;
gpio_write_pin(PIN_JTAG_GPIO, GPIO_GET_PORT_INDEX(PIN_SINGLE_SPI_JTAG_TMS), GPIO_GET_PIN_INDEX(PIN_SINGLE_SPI_JTAG_TMS), 1);
/* Update-DR */
jtag_less_than_32bit_size_for_tck(1, 0);
board_write_spi_cs(BOARD_SPI_CS_PIN, false);
gpio_write_pin(PIN_JTAG_GPIO, GPIO_GET_PORT_INDEX(PIN_SINGLE_SPI_JTAG_TMS), GPIO_GET_PIN_INDEX(PIN_SINGLE_SPI_JTAG_TMS), 0);
/* Idle */
jtag_less_than_32bit_size_for_tck(1, 0xFFFFFFFF);
return (val);
Expand Down
23 changes: 16 additions & 7 deletions projects/hpm5301evklite/SW_DP_SPI.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,13 +58,18 @@ void SWJ_Sequence (uint32_t count, const uint8_t *data)
SWD_SPI_BASE->CTRL |= SPI_CTRL_RXFIFORST_MASK | SPI_CTRL_TXFIFORST_MASK;
while (SWD_SPI_BASE->STATUS & (SPI_CTRL_RXFIFORST_MASK | SPI_CTRL_TXFIFORST_MASK)) {
};
spi_set_write_data_count(SWD_SPI_BASE, integer_val);
SWD_SPI_BASE->CMD = 0xFF;
for (n = 0; n < integer_val; n++) {
SWD_SPI_BASE->DATA = *(data + n);
if (integer_val > 0)
{
spi_set_data_bits(SWD_SPI_BASE, 8);
spi_set_write_data_count(SWD_SPI_BASE, integer_val);
SWD_SPI_BASE->CMD = 0xFF;
for (n = 0; n < integer_val; n++) {
SWD_SPI_BASE->DATA = *(data + n);
}
while (SWD_SPI_BASE->STATUS & SPI_STATUS_SPIACTIVE_MASK) {
}
}
while (SWD_SPI_BASE->STATUS & SPI_STATUS_SPIACTIVE_MASK) {
};

if (remaind_val > 0) {
spi_set_write_data_count(SWD_SPI_BASE, 1);
spi_set_data_bits(SWD_SPI_BASE, remaind_val);
Expand Down Expand Up @@ -260,7 +265,11 @@ uint8_t SWD_Transfer(uint32_t request, uint32_t *data)
SWD_SPI_BASE->TRANSFMT = 0x0018; /* datalen = 1bit, mosibidir = 1, lsb=1 */
spi_set_write_data_count(SWD_SPI_BASE, DAP_Data.transfer.idle_cycles);
SWD_SPI_BASE->CMD = 0xFF;
SWD_SPI_BASE->DATA = 0;
for (int i = 0; i < DAP_Data.transfer.idle_cycles; i++) {
SWD_SPI_BASE->DATA = 0;
while ((SWD_SPI_BASE->STATUS & SPI_STATUS_TXFULL_MASK) == SPI_STATUS_TXFULL_MASK) {
};
}
while ((SWD_SPI_BASE->STATUS & SPI_STATUS_TXFULL_MASK) == SPI_STATUS_TXFULL_MASK) {
};
while (SWD_SPI_BASE->STATUS & SPI_STATUS_SPIACTIVE_MASK) {
Expand Down
Loading

0 comments on commit cacc36f

Please sign in to comment.