Skip to content

Commit

Permalink
Merge branch 'bugfix-2.1.x' of github.com:MarlinFirmware/Marlin into …
Browse files Browse the repository at this point in the history
…leo_1S_S6_btt_mini
  • Loading branch information
JaxTheWolf committed Dec 21, 2024
2 parents ae034fa + 4eb8a87 commit 3af53bd
Show file tree
Hide file tree
Showing 57 changed files with 1,152 additions and 46,900 deletions.
12 changes: 6 additions & 6 deletions Marlin/Configuration.h
Original file line number Diff line number Diff line change
Expand Up @@ -1646,15 +1646,15 @@
// with NOZZLE_AS_PROBE this can be negative for a wider probing area.
#define PROBING_MARGIN 8

// X and Y axis travel speed (mm/min) between probes.
// X and Y axis travel speed between probes.
// Leave undefined to use the average of the current XY homing feedrate.
#define XY_PROBE_FEEDRATE (133*60)
#define XY_PROBE_FEEDRATE (133*60) // (mm/min)

// Feedrate (mm/min) for the first approach when double-probing (MULTIPLE_PROBING == 2)
#define Z_PROBE_FEEDRATE_FAST (3*60)
// Feedrate for the first approach when double-probing (MULTIPLE_PROBING == 2)
#define Z_PROBE_FEEDRATE_FAST (4*60) // (mm/min)

// Feedrate (mm/min) for the "accurate" probe of each point
#define Z_PROBE_FEEDRATE_SLOW (Z_PROBE_FEEDRATE_FAST / 2)
// Feedrate for the "accurate" probe of each point
#define Z_PROBE_FEEDRATE_SLOW (Z_PROBE_FEEDRATE_FAST / 2) // (mm/min)

/**
* Probe Activation Switch
Expand Down
2 changes: 1 addition & 1 deletion Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1020,7 +1020,7 @@

#endif // BLTOUCH

// @section calibration
// @section calibrate

/**
* Z Steppers Auto-Alignment
Expand Down
2 changes: 1 addition & 1 deletion Marlin/Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
* here we define this default string as the date where the latest release
* version was tagged.
*/
//#define STRING_DISTRIBUTION_DATE "2024-12-02"
//#define STRING_DISTRIBUTION_DATE "2024-12-18"

/**
* The protocol for communication to the host. Protocol indicates communication
Expand Down
2 changes: 1 addition & 1 deletion Marlin/src/HAL/HC32/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The HC32F460 HAL is designed to be generic enough for any HC32F460-based board.
- Examine the board's main processor. (Refer the naming key in `hc32.ini`.)
- Extend the `HC32F460C_common` base env for 256K, or `HC32F460E_common` for 512K.
3. Determine your board's application start address (see [below](#finding-the-application-start-address))
4. Set `board_build.ld_args.flash_start` to the app start address once you've found it. If your board doesn't use a bootloader, you may be able to use the "ICSP" header or DFU. This document will be updated once we have more information about flashing without a bootloader.
4. Set `board_upload.offset_address` to the app start address once you've found it. If your board doesn't use a bootloader, you may be able to use the "ICSP" header or DFU. This document will be updated once we have more information about flashing without a bootloader.

### Finding the application start address

Expand Down
11 changes: 4 additions & 7 deletions Marlin/src/HAL/HC32/app_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#define _HC32_APP_CONFIG_H_

#include "../../inc/MarlinConfigPre.h"
#include "sysclock.h"

//
// dev mode
Expand Down Expand Up @@ -64,12 +65,8 @@
// redirect printf to host serial
#define REDIRECT_PRINTF_TO_SERIAL 1

// F_CPU must be known at compile time, but on HC32F460 it's not.
// Thus we assume HCLK to be 200MHz, as that's what is configured in
// 'core_hook_sysclock_init' in 'sysclock.cpp'.
// If you face issues with this assumption, please double-check with the values
// printed by 'MarlinHAL::HAL_clock_frequencies_dump'.
// see also: HAL_TIMER_RATE in timers.h
#define F_CPU 200000000 // 200MHz HCLK
// F_CPU is F_HCLK, as that's the main CPU core's clock.
// see 'sysclock.h' for more information.
#define F_CPU F_HCLK

#endif // _HC32_APP_CONFIG_H_
237 changes: 170 additions & 67 deletions Marlin/src/HAL/HC32/sysclock.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,94 +26,201 @@

#ifdef ARDUINO_ARCH_HC32

// Get BOARD_XTAL_FREQUENCY from configuration / pins
#include "../../inc/MarlinConfig.h"
#include "sysclock.h"

#include <core_hooks.h>
#include <drivers/sysclock/sysclock_util.h>

/***
* @brief Automatically calculate M, N, P values for the MPLL to reach a target frequency.
* @param input_frequency The input frequency.
* @param target_frequency The target frequency.
* @return The MPLL configuration structure. Q and R are not set.
*
* @note
* Simplified MPLL block diagram, with intermediary clocks (1) = VCO_in, (2) = VCO_out:
*
* INPUT -> [/ M] -(1)-> [* N] -(2)-|-> [/ P] -> MPLL-P
*/
constexpr stc_clk_mpll_cfg_t get_mpll_config(double input_frequency, double target_frequency) {
// PLL input clock divider: M in [1, 24]
for (uint32_t M = 1; M <= 24; M++) {
double f_vco_in = input_frequency / M;

// 1 <= VCO_in <= 25 MHz
if (f_vco_in < 1e6 || f_vco_in > 25e6) continue;

// VCO multiplier: N in [20, 480]
for (uint32_t N = 20; N <= 480; N++) {
double f_vco_out = f_vco_in * N;

// 240 <= VCO_out <= 480 MHz
if (f_vco_out < 240e6 || f_vco_out > 480e6) continue;

// Output "P" divider: P in [2, 16]
for (uint32_t P = 2; P <= 16; P++) {
double f_calculated_out = f_vco_out / P;
if (f_calculated_out == target_frequency) {
// Found a match, return it
return {
.PllpDiv = P,
.PllqDiv = P, // Don't care for Q and R
.PllrDiv = P, // "
.plln = N,
.pllmDiv = M
};
}
}
}
}

// If no valid M, N, P found, return invalid config
return { 0, 0, 0, 0, 0 };
}

/**
* @brief Get the division factor required to get the target frequency from the input frequency.
* @tparam input_freq The input frequency.
* @tparam target_freq The target frequency.
* @return The division factor.
*/
template <uint32_t input_freq, uint32_t target_freq>
constexpr en_clk_sysclk_div_factor_t get_division_factor() {
// Calculate the divider to get the target frequency
constexpr float fdivider = static_cast<float>(input_freq) / static_cast<float>(target_freq);
constexpr int divider = static_cast<int>(fdivider);

// divider must be an integer
static_assert(fdivider == divider, "Target frequency not achievable, divider must be an integer");

// divider must be between 1 and 64 (enum range), and must be a power of 2
static_assert(divider >= 1 && divider <= 64, "Invalid divider, out of range");
static_assert((divider & (divider - 1)) == 0, "Invalid divider, not a power of 2");

// return the divider
switch (divider) {
case 1: return ClkSysclkDiv1;
case 2: return ClkSysclkDiv2;
case 4: return ClkSysclkDiv4;
case 8: return ClkSysclkDiv8;
case 16: return ClkSysclkDiv16;
case 32: return ClkSysclkDiv32;
case 64: return ClkSysclkDiv64;
}
}

/**
* @brief Validate the runtime clocks match the expected values.
*/
void validate_system_clocks() {
#define CLOCK_ASSERT(expected, actual) \
if (expected != actual) { \
SERIAL_ECHOPGM( \
"Clock Mismatch for " #expected ": " \
"expected ", expected, \
", got ", actual \
); \
CORE_ASSERT_FAIL("Clock Mismatch: " #expected); \
}

update_system_clock_frequencies();

CLOCK_ASSERT(F_SYSTEM_CLOCK, SYSTEM_CLOCK_FREQUENCIES.system);
CLOCK_ASSERT(F_HCLK, SYSTEM_CLOCK_FREQUENCIES.hclk);
CLOCK_ASSERT(F_EXCLK, SYSTEM_CLOCK_FREQUENCIES.exclk);
CLOCK_ASSERT(F_PCLK0, SYSTEM_CLOCK_FREQUENCIES.pclk0);
CLOCK_ASSERT(F_PCLK1, SYSTEM_CLOCK_FREQUENCIES.pclk1);
CLOCK_ASSERT(F_PCLK2, SYSTEM_CLOCK_FREQUENCIES.pclk2);
CLOCK_ASSERT(F_PCLK3, SYSTEM_CLOCK_FREQUENCIES.pclk3);
CLOCK_ASSERT(F_PCLK4, SYSTEM_CLOCK_FREQUENCIES.pclk4);
}

/**
* @brief Configure HC32 system clocks.
*
* This function is called by the Arduino core early in the startup process, before setup() is called.
* It is used to configure the system clocks to the desired state.
*
* See https://github.com/MarlinFirmware/Marlin/pull/27099 for more information.
*/
void core_hook_sysclock_init() {
// Set wait cycles, as we are about to switch to 200 MHz HCLK
sysclock_configure_flash_wait_cycles();
sysclock_configure_sram_wait_cycles();

// Configure MPLLp to 200 MHz output, with different settings depending on XTAL availability
#if BOARD_XTAL_FREQUENCY == 8000000 // 8 MHz XTAL
// - M = 1 => 8 MHz / 1 = 8 MHz
// - N = 50 => 8 MHz * 50 = 400 MHz
// - P = 2 => 400 MHz / 2 = 200 MHz (sysclk)
// - Q,R = 4 => 400 MHz / 4 = 100 MHz (dont care)
stc_clk_mpll_cfg_t pllConf = {
.PllpDiv = 2u, // P
.PllqDiv = 4u, // Q
.PllrDiv = 4u, // R
.plln = 50u, // N
.pllmDiv = 1u, // M
};
sysclock_configure_xtal();
sysclock_configure_mpll(ClkPllSrcXTAL, &pllConf);

#elif BOARD_XTAL_FREQUENCY == 16000000 // 16 MHz XTAL
// - M = 1 => 16 MHz / 1 = 16 MHz
// - N = 50 => 16 MHz * 25 = 400 MHz
// - P = 2 => 400 MHz / 2 = 200 MHz (sysclk)
// - Q,R = 4 => 400 MHz / 4 = 100 MHz (dont care)
stc_clk_mpll_cfg_t pllConf = {
.PllpDiv = 2u, // P
.PllqDiv = 4u, // Q
.PllrDiv = 4u, // R
.plln = 50u, // N
.pllmDiv = 1u, // M
};
// Select MPLL input frequency based on clock availability
#if BOARD_XTAL_FREQUENCY == 8000000 || BOARD_XTAL_FREQUENCY == 16000000 // 8 MHz or 16 MHz XTAL
constexpr uint32_t mpll_input_clock = BOARD_XTAL_FREQUENCY;

sysclock_configure_xtal();
sysclock_configure_mpll(ClkPllSrcXTAL, &pllConf);

#warning "HC32F460 with 16 MHz XTAL has not been tested."
#if BOARD_XTAL_FREQUENCY == 16000000
#warning "HC32F460 with 16 MHz XTAL has not been tested."
#endif

#else // HRC (16 MHz)
// - M = 1 => 16 MHz / 1 = 16 MHz
// - N = 25 => 16 MHz * 25 = 400 MHz
// - P = 2 => 400 MHz / 2 = 200 MHz (sysclk)
// - Q,R = 4 => 400 MHz / 4 = 100 MHz (dont care)
stc_clk_mpll_cfg_t pllConf = {
.PllpDiv = 2u, // P
.PllqDiv = 4u, // Q
.PllrDiv = 4u, // R
.plln = 25u, // N
.pllmDiv = 1u, // M
};

constexpr uint32_t mpll_input_clock = 16000000;

sysclock_configure_hrc();
sysclock_configure_mpll(ClkPllSrcHRC, &pllConf);

// HRC could have been configured by ICG to 20 MHz
// TODO: handle gracefully if HRC is not 16 MHz
if (1UL != (HRC_FREQ_MON() & 1UL)) {
panic("HRC is not 16 MHz");
}

#ifdef BOARD_XTAL_FREQUENCY
#if defined(BOARD_XTAL_FREQUENCY)
#warning "No valid XTAL frequency defined, falling back to HRC."
#endif

#endif

// sysclk is now configured according to F_CPU (i.e., 200MHz PLL output)
const uint32_t sysclock = F_CPU;
// Automagically calculate MPLL configuration
constexpr stc_clk_mpll_cfg_t pllConf = get_mpll_config(mpll_input_clock, F_SYSTEM_CLOCK);
static_assert(pllConf.pllmDiv != 0 && pllConf.plln != 0 && pllConf.PllpDiv != 0, "MPLL auto-configuration failed");
sysclock_configure_mpll(ClkPllSrcXTAL, &pllConf);

// Setup clock divisors for sysclk = 200 MHz
// Note: PCLK1 is used for step+temp timers, and need to be kept at 50 MHz (until there is a better solution)
// Setup clock divisors
constexpr stc_clk_sysclk_cfg_t sysClkConf = {
.enHclkDiv = ClkSysclkDiv1, // HCLK = 200 MHz (CPU)
.enExclkDiv = ClkSysclkDiv2, // EXCLK = 100 MHz (SDIO)
.enPclk0Div = ClkSysclkDiv2, // PCLK0 = 100 MHz (Timer6 (not used))
.enPclk1Div = ClkSysclkDiv4, // PCLK1 = 50 MHz (USART, SPI, I2S, Timer0 (step+temp), TimerA (Servo))
.enPclk2Div = ClkSysclkDiv8, // PCLK2 = 25 MHz (ADC)
.enPclk3Div = ClkSysclkDiv8, // PCLK3 = 25 MHz (I2C, WDT)
.enPclk4Div = ClkSysclkDiv2, // PCLK4 = 100 MHz (ADC ctl)
.enHclkDiv = get_division_factor<F_SYSTEM_CLOCK, F_HCLK>(),
.enExclkDiv = get_division_factor<F_SYSTEM_CLOCK, F_EXCLK>(),
.enPclk0Div = get_division_factor<F_SYSTEM_CLOCK, F_PCLK0>(),
.enPclk1Div = get_division_factor<F_SYSTEM_CLOCK, F_PCLK1>(),
.enPclk2Div = get_division_factor<F_SYSTEM_CLOCK, F_PCLK2>(),
.enPclk3Div = get_division_factor<F_SYSTEM_CLOCK, F_PCLK3>(),
.enPclk4Div = get_division_factor<F_SYSTEM_CLOCK, F_PCLK4>(),
};
sysclock_set_clock_dividers(&sysClkConf);

// Set power mode, before switch
power_mode_update_pre(F_SYSTEM_CLOCK);

// Switch to MPLL-P as system clock source
CLK_SetSysClkSource(CLKSysSrcMPLL);

// Set power mode, after switch
power_mode_update_post(F_SYSTEM_CLOCK);

// Verify clocks match expected values (at runtime)
#if ENABLED(MARLIN_DEV_MODE) || ENABLED(ALWAYS_VALIDATE_CLOCKS)
validate_system_clocks();
#endif

// Verify clock configuration (at compile time)
#if ARDUINO_CORE_VERSION_INT >= GET_VERSION_INT(1, 2, 0)
assert_mpll_config_valid<
mpll_input_clock,
pllConf.pllmDiv,
pllConf.plln,
pllConf.PllpDiv,
pllConf.PllqDiv,
pllConf.PllrDiv
>();

assert_system_clocks_valid<
sysclock,
F_SYSTEM_CLOCK,
sysClkConf.enHclkDiv,
sysClkConf.enPclk0Div,
sysClkConf.enPclk1Div,
Expand All @@ -122,18 +229,14 @@ void core_hook_sysclock_init() {
sysClkConf.enPclk4Div,
sysClkConf.enExclkDiv
>();
#endif

sysclock_set_clock_dividers(&sysClkConf);

// Set power mode
power_mode_update_pre(sysclock);

// Switch to MPLL as sysclk source
CLK_SetSysClkSource(CLKSysSrcMPLL);

// Set power mode
power_mode_update_post(sysclock);
static_assert(get_mpll_output_clock(
mpll_input_clock,
pllConf.pllmDiv,
pllConf.plln,
pllConf.PllpDiv
) == F_SYSTEM_CLOCK, "actual MPLL output clock does not match F_SYSTEM_CLOCK");
#endif
}

#endif // ARDUINO_ARCH_HC32
Loading

0 comments on commit 3af53bd

Please sign in to comment.