Skip to content

Commit

Permalink
projects: hslink-pro: improve CLK clock output accuracy
Browse files Browse the repository at this point in the history
- 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 committed Sep 19, 2024
1 parent 8cdeb21 commit eafba82
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 43 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
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

0 comments on commit eafba82

Please sign in to comment.