/** * Marlin 3D Printer Firmware * Copyright (c) 2023 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] * * Based on Sprinter and grbl. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm * * 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 . * */ /** * HAL for HC32F460, based heavily on the legacy implementation and STM32F1 */ #ifdef ARDUINO_ARCH_HC32 #include "../../inc/MarlinConfig.h" #include "HAL.h" // Includes MarlinHAL.h #include #include #if TEMP_SENSOR_SOC #include #endif extern "C" char *_sbrk(int incr); #if ENABLED(POSTMORTEM_DEBUGGING) // From MinSerial.cpp extern void install_min_serial(); #endif #if ENABLED(MARLIN_DEV_MODE) inline void HAL_clock_frequencies_dump() { // 1. dump all clock frequencies update_system_clock_frequencies(); SERIAL_ECHOPGM( "-- clocks dump -- \nSYS=", SYSTEM_CLOCK_FREQUENCIES.system, "\nHCLK=", SYSTEM_CLOCK_FREQUENCIES.hclk, "\nPCLK0=", SYSTEM_CLOCK_FREQUENCIES.pclk0, "\nPCLK1=", SYSTEM_CLOCK_FREQUENCIES.pclk1, "\nPCLK2=", SYSTEM_CLOCK_FREQUENCIES.pclk2, "\nPCLK3=", SYSTEM_CLOCK_FREQUENCIES.pclk3, "\nPCLK4=", SYSTEM_CLOCK_FREQUENCIES.pclk4, "\nEXCLK=", SYSTEM_CLOCK_FREQUENCIES.exclk, "\nF_CPU=", F_CPU ); // 2. dump current system clock source en_clk_sys_source_t clkSrc = CLK_GetSysClkSource(); SERIAL_ECHOPGM("\nSYSCLK="); switch (clkSrc) { case ClkSysSrcHRC: SERIAL_ECHOPGM("HRC"); break; case ClkSysSrcMRC: SERIAL_ECHOPGM("MRC"); break; case ClkSysSrcLRC: SERIAL_ECHOPGM("LRC"); break; case ClkSysSrcXTAL: SERIAL_ECHOPGM("XTAL"); break; case ClkSysSrcXTAL32: SERIAL_ECHOPGM("XTAL32"); break; case CLKSysSrcMPLL: SERIAL_ECHOPGM("MPLL"); // 3. if MPLL is used, dump MPLL settings: // (derived from CLK_SetPllSource and CLK_MpllConfig) // source switch (M4_SYSREG->CMU_PLLCFGR_f.PLLSRC) { case ClkPllSrcXTAL: SERIAL_ECHOPGM(",XTAL"); break; case ClkPllSrcHRC: SERIAL_ECHOPGM(",HRC"); break; default: break; } // PLL multipliers and dividers SERIAL_ECHOPGM( "\nP=", M4_SYSREG->CMU_PLLCFGR_f.MPLLP + 1UL, "\nQ=", M4_SYSREG->CMU_PLLCFGR_f.MPLLQ + 1UL, "\nR=", M4_SYSREG->CMU_PLLCFGR_f.MPLLR + 1UL, "\nN=", M4_SYSREG->CMU_PLLCFGR_f.MPLLN + 1UL, "\nM=", M4_SYSREG->CMU_PLLCFGR_f.MPLLM + 1UL ); break; default: break; } // Done SERIAL_ECHOPGM("\n--\n"); } #endif // MARLIN_DEV_MODE // // MarlinHAL class implementation // pin_t MarlinHAL::last_adc_pin; #if TEMP_SENSOR_SOC float MarlinHAL::soc_temp = 0; #endif MarlinHAL::MarlinHAL() {} void MarlinHAL::watchdog_init() { TERN_(USE_WATCHDOG, WDT.begin(5000)); // Reset on 5 second timeout } void MarlinHAL::watchdog_refresh() { TERN_(USE_WATCHDOG, WDT.reload()); } void MarlinHAL::init() { NVIC_SetPriorityGrouping(0x3); // Print clock frequencies to host serial TERN_(MARLIN_DEV_MODE, HAL_clock_frequencies_dump()); // Register min serial TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); } void MarlinHAL::init_board() {} void MarlinHAL::reboot() { NVIC_SystemReset(); } bool MarlinHAL::isr_state() { return !__get_PRIMASK(); } void MarlinHAL::isr_on() { __enable_irq(); } void MarlinHAL::isr_off() { __disable_irq(); } void MarlinHAL::delay_ms(const int ms) { delay(ms); } void MarlinHAL::idletask() {} uint8_t MarlinHAL::get_reset_source() { // Query reset cause from RMU stc_rmu_rstcause_t rstCause; RMU_GetResetCause(&rstCause); // Map reset cause code to those expected by Marlin // - Reset causes are flags, so multiple can be set TERN_(MARLIN_DEV_MODE, printf("-- Reset Cause -- \n")); uint8_t cause = 0; #define MAP_CAUSE(from, to) \ if (rstCause.from == Set) { \ TERN_(MARLIN_DEV_MODE, printf(" - " STRINGIFY(from) "\n")); \ cause |= to; \ } // Power on MAP_CAUSE(enPowerOn, RST_POWER_ON) // Power on reset // External MAP_CAUSE(enRstPin, RST_EXTERNAL) // Reset pin MAP_CAUSE(enPvd1, RST_EXTERNAL) // Program voltage detection reset MAP_CAUSE(enPvd2, RST_EXTERNAL) // " // Brown out MAP_CAUSE(enBrownOut, RST_BROWN_OUT) // Brown out reset // Wdt MAP_CAUSE(enWdt, RST_WATCHDOG) // Watchdog reset MAP_CAUSE(enSwdt, RST_WATCHDOG) // Special WDT reset // Software MAP_CAUSE(enPowerDown, RST_SOFTWARE) // MCU power down (?) MAP_CAUSE(enSoftware, RST_SOFTWARE) // Software reset (e.g. NVIC_SystemReset()) // Misc. MAP_CAUSE(enMpuErr, RST_BACKUP) // MPU error MAP_CAUSE(enRamParityErr, RST_BACKUP) // RAM parity error MAP_CAUSE(enRamEcc, RST_BACKUP) // RAM ecc error MAP_CAUSE(enClkFreqErr, RST_BACKUP) // Clock frequency failure MAP_CAUSE(enXtalErr, RST_BACKUP) // XTAL failure #undef MAP_CAUSE return cause; } void MarlinHAL::clear_reset_source() { RMU_ClrResetFlag(); } int MarlinHAL::freeMemory() { volatile char top; return &top - _sbrk(0); } void MarlinHAL::adc_init() {} void MarlinHAL::adc_enable(const pin_t pin) { #if TEMP_SENSOR_SOC if (pin == TEMP_SOC_PIN) { // Start OTS, min. 1s between reads ChipTemperature.begin(); ChipTemperature.setMinimumReadDeltaMillis(1000); return; } #endif // Just set pin mode to analog pinMode(pin, INPUT_ANALOG); } void MarlinHAL::adc_start(const pin_t pin) { MarlinHAL::last_adc_pin = pin; #if TEMP_SENSOR_SOC if (pin == TEMP_SOC_PIN) { // Read OTS float temp; if (ChipTemperature.read(temp)) MarlinHAL::soc_temp = temp; return; } #endif CORE_ASSERT(IS_GPIO_PIN(pin), "adc_start: invalid pin") analogReadAsync(pin); } bool MarlinHAL::adc_ready() { #if TEMP_SENSOR_SOC if (MarlinHAL::last_adc_pin == TEMP_SOC_PIN) return true; #endif CORE_ASSERT(IS_GPIO_PIN(MarlinHAL::last_adc_pin), "adc_ready: invalid pin") return getAnalogReadComplete(MarlinHAL::last_adc_pin); } uint16_t MarlinHAL::adc_value() { #if TEMP_SENSOR_SOC if (MarlinHAL::last_adc_pin == TEMP_SOC_PIN) return OTS_FLOAT_TO_ADC_READING(MarlinHAL::soc_temp); #endif // Read conversion result CORE_ASSERT(IS_GPIO_PIN(MarlinHAL::last_adc_pin), "adc_value: invalid pin") return getAnalogReadValue(MarlinHAL::last_adc_pin); } void MarlinHAL::set_pwm_duty(const pin_t pin, const uint16_t value, const uint16_t scale, const bool invert) { // Invert value if requested const uint16_t val = invert ? scale - value : value; // AnalogWrite the value, core handles the rest // Pin mode should be set by Marlin by calling SET_PWM() before calling this function analogWriteScaled(pin, val, scale); } void MarlinHAL::set_pwm_frequency(const pin_t pin, const uint16_t f_desired) { // TODO set_pwm_frequency is not implemented yet panic("set_pwm_frequency is not implemented yet\n"); } void flashFirmware(const int16_t) { MarlinHAL::reboot(); } #endif // ARDUINO_ARCH_HC32