/** * Marlin 3D Printer Firmware * Copyright (c) 2024 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 . * */ #include "../platforms.h" #ifdef __PLAT_RP2040__ #include "HAL.h" //#include "usb_serial.h" #include "../../inc/MarlinConfig.h" #include "../shared/Delay.h" extern "C" { #include "pico/bootrom.h" #include "hardware/watchdog.h" } #if HAS_SD_HOST_DRIVE #include "msc_sd.h" #include "usbd_cdc_if.h" #endif // ------------------------ // Public Variables // ------------------------ volatile uint16_t adc_result; // ------------------------ // Public functions // ------------------------ TERN_(POSTMORTEM_DEBUGGING, extern void install_min_serial()); // HAL initialization task void MarlinHAL::init() { // Ensure F_CPU is a constant expression. // If the compiler breaks here, it means that delay code that should compute at compile time will not work. // So better safe than sorry here. constexpr int cpuFreq = F_CPU; UNUSED(cpuFreq); #undef SDSS #define SDSS 2 #define PIN_EXISTS_(P1,P2) (defined(P1##P2) && P1##P2 >= 0) #if HAS_MEDIA && DISABLED(SDIO_SUPPORT) && PIN_EXISTS_(SDSS,) OUT_WRITE(SDSS, HIGH); // Try to set SDSS inactive before any other SPI users start up #endif #if PIN_EXISTS(LED) OUT_WRITE(LED_PIN, LOW); #endif #if ENABLED(SRAM_EEPROM_EMULATION) // __HAL_RCC_PWR_CLK_ENABLE(); // HAL_PWR_EnableBkUpAccess(); // Enable access to backup SRAM // __HAL_RCC_BKPSRAM_CLK_ENABLE(); // LL_PWR_EnableBkUpRegulator(); // Enable backup regulator // while (!LL_PWR_IsActiveFlag_BRR()); // Wait until backup regulator is initialized #endif HAL_timer_init(); #if ENABLED(EMERGENCY_PARSER) && USBD_USE_CDC USB_Hook_init(); #endif TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the min serial handler TERN_(HAS_SD_HOST_DRIVE, MSC_SD_init()); // Enable USB SD card access #if PIN_EXISTS(USB_CONNECT) OUT_WRITE(USB_CONNECT_PIN, !USB_CONNECT_INVERTING); // USB clear connection delay_ms(1000); // Give OS time to notice WRITE(USB_CONNECT_PIN, USB_CONNECT_INVERTING); #endif } uint8_t MarlinHAL::get_reset_source() { return watchdog_enable_caused_reboot() ? RST_WATCHDOG : 0; } void MarlinHAL::reboot() { watchdog_reboot(0, 0, 1); } // ------------------------ // Watchdog Timer // ------------------------ #if ENABLED(USE_WATCHDOG) #define WDT_TIMEOUT_US TERN(WATCHDOG_DURATION_8S, 8000000, 4000000) // 4 or 8 second timeout extern "C" { #include "hardware/watchdog.h" } void MarlinHAL::watchdog_init() { #if DISABLED(DISABLE_WATCHDOG_INIT) static_assert(WDT_TIMEOUT_US > 1000, "WDT Timout is too small, aborting"); watchdog_enable(WDT_TIMEOUT_US/1000, true); #endif } void MarlinHAL::watchdog_refresh() { watchdog_update(); #if DISABLED(PINS_DEBUGGING) && PIN_EXISTS(LED) TOGGLE(LED_PIN); // heartbeat indicator #endif } #endif // ------------------------ // ADC // ------------------------ volatile bool MarlinHAL::adc_has_result = false; void MarlinHAL::adc_init() { analogReadResolution(HAL_ADC_RESOLUTION); ::adc_init(); adc_fifo_setup(true, false, 1, false, false); irq_set_exclusive_handler(ADC_IRQ_FIFO, adc_exclusive_handler); irq_set_enabled(ADC_IRQ_FIFO, true); adc_irq_set_enabled(true); } void MarlinHAL::adc_enable(const pin_t pin) { if (pin >= A0 && pin <= A3) adc_gpio_init(pin); else if (pin == HAL_ADC_MCU_TEMP_DUMMY_PIN) adc_set_temp_sensor_enabled(true); } void MarlinHAL::adc_start(const pin_t pin) { adc_has_result = false; // Select an ADC input. 0...3 are GPIOs 26...29 respectively. adc_select_input(pin == HAL_ADC_MCU_TEMP_DUMMY_PIN ? 4 : pin - A0); adc_run(true); } void MarlinHAL::adc_exclusive_handler() { adc_run(false); // Disable since we only want one result irq_clear(ADC_IRQ_FIFO); // Clear the IRQ if (adc_fifo_get_level() >= 1) { adc_result = adc_fifo_get(); // Pop the result adc_fifo_drain(); adc_has_result = true; // Signal the end of the conversion } } uint16_t MarlinHAL::adc_value() { return adc_result; } // Reset the system to initiate a firmware flash void flashFirmware(const int16_t) { hal.reboot(); } extern "C" { void * _sbrk(int incr); extern unsigned int __bss_end__; // end of bss section } // Return free memory between end of heap (or end bss) and whatever is current int freeMemory() { int free_memory, heap_end = (int)_sbrk(0); return (int)&free_memory - (heap_end ?: (int)&__bss_end__); } #endif // __PLAT_RP2040__