Merge branch 'bugfix-2.1.x' into ParseSafetyCommandsEvenWithEParser

This commit is contained in:
InsanityAutomation
2025-05-13 16:17:41 -04:00
committed by GitHub
271 changed files with 4024 additions and 2914 deletions
+6 -2
View File
@@ -260,6 +260,7 @@
#define SWITCHING_NOZZLE_SERVO_ANGLES { 0, 90 } // A pair of angles for { E0, E1 }.
// For Dual Servo use two pairs: { { lower, raise }, { lower, raise } }
#define SWITCHING_NOZZLE_SERVO_DWELL 2500 // Dwell time to wait for servo to make physical move
#define SWITCHING_NOZZLE_LIFT_TO_PROBE // Lift toolheads out of the way while probing
#endif
// Switch nozzles by bumping the toolhead. Requires EVENT_GCODE_TOOLCHANGE_#.
@@ -2036,8 +2037,11 @@
//#define FILAMENT_MOTION_SENSOR
#if ENABLED(FILAMENT_MOTION_SENSOR)
//#define FILAMENT_SWITCH_AND_MOTION
//#define FILAMENT_SWITCH_AND_MOTION // Define separate pins below to sense motion
#if ENABLED(FILAMENT_SWITCH_AND_MOTION)
#define FILAMENT_MOTION_DISTANCE_MM 3.0 // (mm) Missing distance required to trigger runout
#define NUM_MOTION_SENSORS 1 // Number of sensors, up to one per extruder. Define a FIL_MOTION#_PIN for each.
//#define FIL_MOTION1_PIN -1
@@ -2073,7 +2077,7 @@
//#define FIL_MOTION8_STATE LOW
//#define FIL_MOTION8_PULLUP
//#define FIL_MOTION8_PULLDOWN
#endif
#endif // FILAMENT_SWITCH_AND_MOTION
#endif // FILAMENT_MOTION_SENSOR
#endif // FILAMENT_RUNOUT_DISTANCE_MM
#endif // FILAMENT_RUNOUT_SENSOR
+23 -2
View File
@@ -1938,6 +1938,9 @@
//#define CUSTOM_FIRMWARE_UPLOAD
#endif
// "Over-the-air" Firmware Update with M936 - Required to set EEPROM flag
//#define OTA_FIRMWARE_UPDATE
/**
* Set this option to one of the following (or the board's defaults apply):
*
@@ -1960,8 +1963,8 @@
#if ENABLED(MULTI_VOLUME)
#define VOLUME_SD_ONBOARD
#define VOLUME_USB_FLASH_DRIVE
#define DEFAULT_VOLUME SV_SD_ONBOARD
#define DEFAULT_SHARED_VOLUME SV_USB_FLASH_DRIVE
#define DEFAULT_VOLUME SD_ONBOARD // :[ 'SD_ONBOARD', 'USB_FLASH_DRIVE' ]
#define DEFAULT_SHARED_VOLUME USB_FLASH_DRIVE // :[ 'SD_ONBOARD', 'USB_FLASH_DRIVE' ]
#endif
#endif // HAS_MEDIA
@@ -2352,6 +2355,24 @@
//#define ADVANCE_K_EXTRA // Add a second linear advance constant, configurable with M900 L.
//#define LA_DEBUG // Print debug information to serial during operation. Disable for production use.
//#define EXPERIMENTAL_I2S_LA // Allow I2S_STEPPER_STREAM to be used with LA. Performance degrades as the LA step rate reaches ~20kHz.
//#define SMOOTH_LIN_ADVANCE // Remove limits on acceleration by gradual increase of nozzle pressure
#if ENABLED(SMOOTH_LIN_ADVANCE)
/**
* ADVANCE_TAU is also the time ahead that the smoother needs to look
* into the planner, so the planner needs to have enough blocks loaded.
* For k=0.04 at 10k acceleration and an "Orbiter 2" extruder it can be as low as 0.0075.
* Adjust by lowering the value until you observe the extruder skipping, then raise slightly.
* Higher k and higher XY acceleration may require larger ADVANCE_TAU to avoid skipping steps.
*/
#if ENABLED(DISTINCT_E_FACTORS)
#define ADVANCE_TAU { 0.01 } // (s) Smoothing time to reduce extruder acceleration, per extruder
#else
#define ADVANCE_TAU 0.01 // (s) Smoothing time to reduce extruder acceleration
#endif
#define SMOOTH_LIN_ADV_HZ 5000 // (Hz) How often to update extruder speed
#define INPUT_SHAPING_E_SYNC // Synchronize the extruder-shaped XY axes (to increase precision)
#endif
#endif
/**
+1 -1
View File
@@ -41,7 +41,7 @@
* here we define this default string as the date where the latest release
* version was tagged.
*/
//#define STRING_DISTRIBUTION_DATE "2025-04-18"
//#define STRING_DISTRIBUTION_DATE "2025-05-10"
/**
* The protocol for communication to the host. Protocol indicates communication
+1 -1
View File
@@ -204,7 +204,7 @@ public:
static void isr_on() { sei(); }
static void isr_off() { cli(); }
static void delay_ms(const int ms) { _delay_ms(ms); }
static void delay_ms(const int ms) { delay(ms); }
// Tasks, called from idle()
static void idletask() {}
+6 -6
View File
@@ -363,8 +363,11 @@
#define AIO7_PWM 0
#define AIO7_DDR DDRF
//-- Begin not supported by Teensyduino
//-- don't use Arduino functions on these pins pinMode/digitalWrite/etc
//-- 46-47 are not supported by Teensyduino
//-- Don't use Arduino functions (pinMode, digitalWrite, etc.) on these pins
#define PIN_E2 46
#define PIN_E3 47
#define DIO46_PIN PINE2
#define DIO46_RPORT PINE
#define DIO46_WPORT PORTE
@@ -377,10 +380,7 @@
#define DIO47_PWM 0
#define DIO47_DDR DDRE
#define TEENSY_E2 46
#define TEENSY_E3 47
//-- end not supported by Teensyduino
//--
#undef PA0
#define PA0_PIN PINA0
+4 -4
View File
@@ -377,16 +377,16 @@ void printPinPort(const pin_t pin) { // print port number
uint8_t x;
SERIAL_ECHOPGM(" Port: ");
#if AVR_AT90USB1286_FAMILY
x = (pin == 46 || pin == 47) ? 'E' : digitalPinToPort_DEBUG(pin) + 64;
x = (pin == PIN_E2 || pin == PIN_E3) ? 'E' : 'A' + digitalPinToPort_DEBUG(pin) - 1;
#else
x = digitalPinToPort_DEBUG(pin) + 64;
x = 'A' + digitalPinToPort_DEBUG(pin) - 1;
#endif
SERIAL_CHAR(x);
#if AVR_AT90USB1286_FAMILY
if (pin == 46)
if (pin == PIN_E2)
x = '2';
else if (pin == 47)
else if (pin == PIN_E3)
x = '3';
else {
uint8_t temp = digitalPinToBitMask_DEBUG(pin);
+14 -9
View File
@@ -102,6 +102,10 @@ void watchdogSetup() {
#if ENABLED(USE_WATCHDOG)
#ifndef WATCHDOG_PIO_RESET
#define WATCHDOG_PIO_RESET
#endif
// 4 seconds timeout
uint32_t timeout = TERN(WATCHDOG_DURATION_8S, 8000, 4000);
@@ -115,15 +119,16 @@ void watchdogSetup() {
timeout = 0xFFF;
// We want to enable the watchdog with the specified timeout
uint32_t value =
WDT_MR_WDV(timeout) | // With the specified timeout
WDT_MR_WDD(timeout) | // and no invalid write window
#if !(SAMV70 || SAMV71 || SAME70 || SAMS70)
WDT_MR_WDRPROC | // WDT fault resets processor only - We want
// to keep PIO controller state
#endif
WDT_MR_WDDBGHLT | // WDT stops in debug state.
WDT_MR_WDIDLEHLT; // WDT stops in idle state.
uint32_t value = (0
| WDT_MR_WDV(timeout) // With the specified timeout
| WDT_MR_WDD(timeout) // and no invalid write window
#if NONE(WATCHDOG_PIO_RESET, SAMV70, SAMV71, SAME70, SAMS70)
| WDT_MR_WDRPROC // WDT fault resets processor only with this flag.
// Omit to also reset the PIO controller.
#endif
| WDT_MR_WDDBGHLT // WDT stops in debug state.
| WDT_MR_WDIDLEHLT // WDT stops in idle state.
);
#if ENABLED(WATCHDOG_RESET_MANUAL)
// We enable the watchdog timer, but only for the interrupt.
@@ -21,7 +21,7 @@
*/
#ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(FLASH_EEPROM_EMULATION)
@@ -132,7 +132,7 @@ static uint8_t buffer[256] = {0}, // The RAM buffer to accumulate writes
curGroup = 0xFF; // Current FLASH group
#define DEBUG_OUT ENABLED(EE_EMU_DEBUG)
#include "../../core/debug_out.h"
#include "../../../core/debug_out.h"
static void ee_Dump(const int page, const void *data) {
@@ -953,7 +953,7 @@ static void ee_Init() {
/* PersistentStore -----------------------------------------------------------*/
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#define MARLIN_EEPROM_SIZE 0x1000 // 4KB
@@ -21,7 +21,7 @@
*/
#ifdef ARDUINO_ARCH_SAM
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
@@ -30,8 +30,8 @@
* with simple implementations supplied by Marlin.
*/
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#error "MARLIN_EEPROM_SIZE is required for I2C / SPI EEPROM."
+2 -1
View File
@@ -40,11 +40,12 @@
* Some jitter in the Vref signal is OK so the interrupt priority is left at its default value.
*/
#include "../../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfigPre.h"
#if MB(PRINTRBOARD_G2)
#include "G2_PWM.h"
#include "../../../module/stepper.h"
#if PIN_EXISTS(MOTOR_CURRENT_PWM_X)
#define G2_PWM_X 1
+1 -4
View File
@@ -26,10 +26,7 @@
* PR #7500. It is hardwired for the PRINTRBOARD_G2 Motor Current needs.
*/
#include "../../../inc/MarlinConfigPre.h"
#include "../../../module/stepper.h"
//C:\Users\bobku\Documents\GitHub\Marlin-Bob-2\Marlin\src\module\stepper.h
//C:\Users\bobku\Documents\GitHub\Marlin-Bob-2\Marlin\src\HAL\HAL_DUE\G2_PWM.h
#include <stdint.h>
#define PWM_PERIOD_US 100 // base repetition rate in micro seconds
+2 -2
View File
@@ -63,8 +63,8 @@
#include "compiler.h"
#include "preprocessor.h"
#ifdef FREERTOS_USED
#include "FreeRTOS.h"
#include "semphr.h"
#include <FreeRTOS.h>
#include <semphr.h>
#endif
#include "ctrl_access.h"
+7 -6
View File
@@ -19,7 +19,7 @@ void sd_mmc_spi_mem_init() {
}
inline bool media_ready() {
return IS_SD_MOUNTED() && IS_SD_INSERTED() && !IS_SD_FILE_OPEN() && !IS_SD_PRINTING();
return card.isMounted() && card.isInserted() && !card.isFileOpen() && !card.isStillPrinting();
}
bool sd_mmc_spi_unload(bool) { return true; }
@@ -29,11 +29,10 @@ bool sd_mmc_spi_wr_protect() { return false; }
bool sd_mmc_spi_removal() { return !media_ready(); }
Ctrl_status sd_mmc_spi_test_unit_ready() {
#ifdef DISABLE_DUE_SD_MMC
#if ENABLED(DISABLE_DUE_SD_MMC)
return CTRL_NO_PRESENT;
#endif
if (sd_mmc_spi_removal()) return CTRL_NO_PRESENT;
return CTRL_GOOD;
return sd_mmc_spi_removal() ? CTRL_NO_PRESENT : CTRL_GOOD;
}
// NOTE: This function is defined as returning the address of the last block
@@ -58,9 +57,10 @@ uint8_t sector_buf[SD_MMC_BLOCK_SIZE];
// #define DEBUG_MMC
Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) {
#ifdef DISABLE_DUE_SD_MMC
#if ENABLED(DISABLE_DUE_SD_MMC)
return CTRL_NO_PRESENT;
#endif
if (sd_mmc_spi_removal()) return CTRL_NO_PRESENT;
#ifdef DEBUG_MMC
@@ -97,9 +97,10 @@ Ctrl_status sd_mmc_spi_usb_read_10(uint32_t addr, uint16_t nb_sector) {
}
Ctrl_status sd_mmc_spi_usb_write_10(uint32_t addr, uint16_t nb_sector) {
#ifdef DISABLE_DUE_SD_MMC
#if ENABLED(DISABLE_DUE_SD_MMC)
return CTRL_NO_PRESENT;
#endif
if (sd_mmc_spi_removal()) return CTRL_NO_PRESENT;
#ifdef DEBUG_MMC
+4 -6
View File
@@ -34,13 +34,13 @@
#if ENABLED(WIFISUPPORT)
#include <ESPAsyncWebServer.h>
#include "wifi.h"
#include "wifi/wifi.h"
#if ENABLED(OTASUPPORT)
#include "ota.h"
#include "wifi/ota.h"
#endif
#if ENABLED(WEBSUPPORT)
#include "spiffs.h"
#include "web.h"
#include "wifi/spiffs.h"
#include "wifi/web.h"
#endif
#endif
@@ -175,8 +175,6 @@ uint8_t MarlinHAL::get_reset_source() { return rtc_get_reset_reason(1); }
void MarlinHAL::reboot() { ESP.restart(); }
void _delay_ms(const int ms) { delay(ms); }
// return free memory between end of heap (or end bss) and whatever is current
int MarlinHAL::freeMemory() { return ESP.getFreeHeap(); }
+3 -5
View File
@@ -37,11 +37,11 @@
#include "i2s.h"
#if ENABLED(WIFISUPPORT)
#include "WebSocketSerial.h"
#include "wifi/WebSocketSerial.h"
#endif
#if ENABLED(ESP3D_WIFISUPPORT)
#include "esp3dlib.h"
#include <esp3dlib.h>
#endif
#include "FlushableHardwareSerial.h"
@@ -165,8 +165,6 @@ int freeMemory();
#pragma GCC diagnostic pop
void _delay_ms(const int ms);
// ------------------------
// MarlinHAL Class
// ------------------------
@@ -194,7 +192,7 @@ public:
static void isr_on() { if (spinlock.owner != portMUX_FREE_VAL) portEXIT_CRITICAL(&spinlock); }
static void isr_off() { portENTER_CRITICAL(&spinlock); }
static void delay_ms(const int ms) { _delay_ms(ms); }
static void delay_ms(const int ms) { delay(ms); }
// Tasks, called from idle()
static void idletask();
+1 -1
View File
@@ -35,7 +35,7 @@
#if HAS_MEDIA
#include "../../sd/cardreader.h"
#if ENABLED(ESP3D_WIFISUPPORT)
#include "sd_ESP32.h"
#include <sd_ESP32.h>
#endif
#endif
@@ -21,7 +21,7 @@
*/
#ifdef ARDUINO_ARCH_ESP32
#include "../../inc/MarlinConfigPre.h"
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(WIFISUPPORT)
@@ -21,8 +21,8 @@
*/
#pragma once
#include "../../inc/MarlinConfig.h"
#include "../../core/serial_hook.h"
#include "../../../inc/MarlinConfig.h"
#include "../../../core/serial_hook.h"
#include <Stream.h>
@@ -27,7 +27,7 @@
#undef ENABLED
#undef DISABLED
#include "../../inc/MarlinConfigPre.h"
#include "../../../inc/MarlinConfigPre.h"
#if ALL(WIFISUPPORT, OTASUPPORT)
@@ -21,11 +21,11 @@
*/
#ifdef ARDUINO_ARCH_ESP32
#include "../../inc/MarlinConfigPre.h"
#include "../../../inc/MarlinConfigPre.h"
#if ALL(WIFISUPPORT, WEBSUPPORT)
#include "../../core/serial.h"
#include "../../../core/serial.h"
#include <FS.h>
#include <SPIFFS.h>
@@ -21,11 +21,11 @@
*/
#ifdef ARDUINO_ARCH_ESP32
#include "../../inc/MarlinConfigPre.h"
#include "../../../inc/MarlinConfigPre.h"
#if ALL(WIFISUPPORT, WEBSUPPORT)
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#undef DISABLED // esp32-hal-gpio.h
#include <SPIFFS.h>
@@ -21,11 +21,11 @@
*/
#ifdef ARDUINO_ARCH_ESP32
#include "../../inc/MarlinConfigPre.h"
#include "../../../inc/MarlinConfigPre.h"
#if ENABLED(WIFISUPPORT)
#include "../../core/serial.h"
#include "../../../core/serial.h"
#include <WiFi.h>
#include <ESPmDNS.h>
+1 -1
View File
@@ -105,7 +105,7 @@ extern "C" char* dtostrf(double val, signed char width, unsigned char prec, char
class MarlinHAL {
public:
// Before setup()
MarlinHAL() {}
MarlinHAL() = default;
// Watchdog
static void watchdog_init() IF_DISABLED(USE_WATCHDOG, {});
+12 -16
View File
@@ -33,8 +33,8 @@
using namespace arduino;
MarlinSerial& MarlinSerial::get_instance(usart::USART_Base Base, pin_size_t rxPin, pin_size_t txPin) {
UsartSerial& serial = UsartSerial::get_instance(Base, rxPin, txPin);
auto MarlinSerial::get_instance(usart::USART_Base Base, pin_size_t rxPin, pin_size_t txPin) -> MarlinSerial& {
auto& serial = UsartSerial::get_instance(Base, rxPin, txPin);
return *reinterpret_cast<MarlinSerial*>(&serial);
}
@@ -60,10 +60,9 @@ MarlinSerial& MarlinSerial::get_instance(usart::USART_Base Base, pin_size_t rxPi
static MarlinSerial* current_serial_instance = nullptr;
static void emergency_callback() {
if (current_serial_instance) {
uint8_t last_data = current_serial_instance->get_last_data();
emergency_parser.update(current_serial_instance->emergency_state, last_data);
}
if (!current_serial_instance) return;
const auto last_data = current_serial_instance->get_last_data();
emergency_parser.update(current_serial_instance->emergency_state, last_data);
}
void MarlinSerial::register_emergency_callback(void (*callback)()) {
@@ -72,26 +71,23 @@ MarlinSerial& MarlinSerial::get_instance(usart::USART_Base Base, pin_size_t rxPi
#endif
void MarlinSerial::begin(unsigned long baudrate, uint16_t config) {
UsartSerial::begin(baudrate, config);
#if DISABLED(SERIAL_DMA)
#if ENABLED(EMERGENCY_PARSER)
current_serial_instance = this;
register_emergency_callback(emergency_callback);
#endif
UsartSerial::begin(baudrate, config, ENABLED(SERIAL_DMA));
#if ENABLED(EMERGENCY_PARSER) && DISABLED(SERIAL_DMA)
current_serial_instance = this;
register_emergency_callback(emergency_callback);
#endif
}
void MarlinSerial::updateRxDmaBuffer() {
#if ENABLED(EMERGENCY_PARSER)
// Get the number of bytes available in the receive buffer
size_t available_bytes = usart_.available_for_read(true);
uint8_t data;
const size_t available_bytes = usart_.available_for_read(true);
// Process only the available data
for (size_t i = 0; i < available_bytes; ++i) {
if (usart_.read_rx_buffer(data)) {
uint8_t data;
if (usart_.read_rx_buffer(data))
emergency_parser.update(emergency_state, data);
}
}
#endif
// Call the base class implementation to handle any additional updates
+2 -2
View File
@@ -43,7 +43,7 @@
using namespace arduino;
struct MarlinSerial : public UsartSerial {
static MarlinSerial& get_instance(usart::USART_Base Base, pin_size_t rxPin = NO_PIN, pin_size_t txPin = NO_PIN);
static auto get_instance(usart::USART_Base Base, pin_size_t rxPin = NO_PIN, pin_size_t txPin = NO_PIN) -> MarlinSerial&;
void begin(unsigned long baudrate, uint16_t config);
inline void begin(unsigned long baudrate) { begin(baudrate, SERIAL_8N1); }
@@ -57,7 +57,7 @@ struct MarlinSerial : public UsartSerial {
EmergencyParser::State emergency_state;
// Accessor method to get the last received byte
uint8_t get_last_data() { return usart_.get_last_data(); }
auto get_last_data() -> uint8_t { return usart_.get_last_data(); }
// Register the emergency callback
void register_emergency_callback(void (*callback)());
-214
View File
@@ -1,214 +0,0 @@
//
// MFL gd32f30x SDCARD using DMA through SDIO in C++
//
// Copyright (C) 2025 B. Mourit <bnmguy@gmail.com>
//
// This software is free software: you can redistribute it and/or modify it under the terms of the
// GNU Lesser General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// This software 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License along with this software.
// If not, see <https://www.gnu.org/licenses/>.
//
#pragma once
#include "../../inc/MarlinConfig.h"
#include "SDIO.hpp"
namespace sdio {
class DMA;
class CardDMA {
public:
static CardDMA& get_instance();
SDIO_Error_Type init();
SDIO_Error_Type card_init();
SDIO_Error_Type begin_startup_procedure();
void begin_shutdown_procedure();
// Configuration
SDIO_Error_Type set_hardware_bus_width(Bus_Width width);
// Main read/write functions for single and multiblock transfers
SDIO_Error_Type read(uint8_t* buf, uint32_t address, uint32_t count);
SDIO_Error_Type write(uint8_t* buf, uint32_t address, uint32_t count);
// DMA transfers
// Other card functions
SDIO_Error_Type erase(uint32_t address_start, uint32_t address_end);
// Interrupt handler
void handle_interrupts();
// Card select
SDIO_Error_Type select_deselect();
SDIO_Error_Type get_card_interface_status(uint32_t* status);
SDIO_Error_Type get_sdcard_status(uint32_t* status);
void check_dma_complete();
SDIO_Error_Type stop_transfer();
Transfer_State get_transfer_state();
uint32_t get_card_capacity() const;
SDIO_Error_Type send_bus_width_command(uint32_t width_value);
SDIO_Error_Type get_card_specific_data(Card_Info* info);
constexpr Block_Size get_data_block_size_index(uint16_t size);
SDIO_Error_Type get_card_state(Card_State* card_state);
SDIO_Error_Type check_sdio_status(Command_Index index = Command_Index::INVALID, bool check_index = false, bool ignore_crc = false);
// DMA configuration
void set_dma_parameters(uint8_t* buf, uint32_t count, bool is_write);
// SDIO configuration
void sdio_configure(const SDIO_Config config) { sdio_.init(config); }
// Varaible stored parameters
SDIO_Error_Type get_scr(uint16_t rca, uint32_t* scr);
SDIO_Error_Type store_cid();
SDIO_Error_Type store_csd();
// Accessor methods
SDIO_Config& get_config() { return config_; }
dma::DMA& get_dma_instance() { return dma_; }
void set_data_end_interrupt() { sdio_.set_interrupt_enable(Interrupt_Type::DTENDIE, true); }
void set_sdio_dma_enable(bool enable) { sdio_.set_dma_enable(enable); }
bool get_is_sdio_rx() { return is_rx_; }
void clear_sdio_data_flags() { sdio_.clear_multiple_interrupt_flags(clear_data_flags); }
void clear_sdio_cmd_flags() { sdio_.clear_multiple_interrupt_flags(clear_command_flags); }
void clear_sdio_common_flags() { sdio_.clear_multiple_interrupt_flags(clear_common_flags); }
Operational_State get_state() { return current_state_; }
void set_state(Operational_State state) { current_state_ = state; }
void set_transfer_end(bool value) { transfer_end_ = value; }
void set_transfer_error(SDIO_Error_Type error) { transfer_error_ = error; }
inline SDIO_Error_Type set_desired_clock(uint32_t desired_clock, bool wide_bus, bool low_power) {
sdio_.init({
desired_clock,
Clock_Edge::RISING_EDGE,
wide_bus ? Bus_Width::WIDTH_4BIT : Bus_Width::WIDTH_1BIT,
false,
low_power,
false
});
sync_domains();
desired_clock_ = desired_clock;
return SDIO_Error_Type::OK;
}
private:
CardDMA();
// Prevent copying or assigning
CardDMA(const CardDMA&) = delete;
CardDMA& operator=(const CardDMA&) = delete;
// Helper function
SDIO_Error_Type wait_for_card_ready();
// Member variables
alignas(4) uint32_t sdcard_csd_[4];
alignas(4) uint32_t sdcard_cid_[4];
alignas(4) uint32_t sdcard_scr_[2];
uint32_t desired_clock_;
uint32_t stop_condition_;
uint32_t total_bytes_;
uint32_t count_;
SDIO& sdio_;
SDIO_Config& config_;
const dma::DMA_Base dmaBase_;
const dma::DMA_Channel dmaChannel_;
dma::DMA& dma_;
uint16_t sdcard_rca_;
SDIO_Error_Type transfer_error_;
Interface_Version interface_version_;
Card_Type card_type_;
volatile bool transfer_end_;
volatile bool is_rx_;
volatile bool multiblock_;
volatile Operational_State current_state_;
// Private helper methods
SDIO_Error_Type validate_voltage();
SDIO_Error_Type get_r1_result(Command_Index index);
//SDIO_Error_Type get_r2_r3_result();
SDIO_Error_Type get_r6_result(Command_Index index, uint16_t* rca);
SDIO_Error_Type get_r7_result();
//SDIO_Error_Type get_r1_error_type(uint32_t response);
SDIO_Error_Type get_command_sent_result();
inline void sync_domains() {
delayMicroseconds(8);
}
inline bool validate_transfer_params(uint32_t* buf, uint16_t size) {
if (buf == nullptr) return false;
// Size must be > 0, <= 2048 and power of 2
if ((size == 0U) || (size > 2048U) || (size & (size - 1U))) {
return false;
}
return true;
}
void process_sdsc_specific_csd(Card_Info* info, const uint8_t* csd_bytes) {
info->csd.device_size = (static_cast<uint32_t>(csd_bytes[6] & 0x03U) << 10U) |
(static_cast<uint32_t>(csd_bytes[7]) << 2U) |
(static_cast<uint32_t>((csd_bytes[8] & 0xC0U) >> 6U));
info->csd.device_size_multiplier = static_cast<uint8_t>((csd_bytes[9] & 0x03U) << 1U |
(csd_bytes[10] & 0x80U) >> 7U);
info->block_size = static_cast<uint32_t>(1 << info->csd.read_block_length);
info->capacity = static_cast<uint32_t>((info->csd.device_size + 1U) *
(1U << (info->csd.device_size_multiplier + 2U)) *
info->block_size);
}
void process_sdhc_specific_csd(Card_Info* info, const uint8_t* csd_bytes) {
info->csd.device_size = static_cast<uint32_t>((csd_bytes[7] & 0x3FU) << 16U) |
static_cast<uint32_t>((csd_bytes[8]) << 8U) |
static_cast<uint32_t>(csd_bytes[9]);
info->block_size = BLOCK_SIZE;
info->capacity = static_cast<uint32_t>((info->csd.device_size + 1U) *
BLOCK_SIZE * KILOBYTE);
}
void process_common_csd_tail(Card_Info* info, const uint8_t* csd_bytes) {
info->csd.sector_size = static_cast<uint8_t>(((csd_bytes[9] & 0x3FU) << 1U) |
(csd_bytes[10] & 0x80U) >> 7U);
info->csd.speed_factor = static_cast<uint8_t>((csd_bytes[11] & 0x1CU) >> 2U);
info->csd.write_block_length = static_cast<uint8_t>(((csd_bytes[11] & 0x03U) << 2U) |
((csd_bytes[12] & 0xC0U) >> 6U));
info->csd.checksum = static_cast<uint8_t>((csd_bytes[15] & 0xFEU) >> 1U);
}
inline void disable_all_interrupts() {
sdio_.set_interrupt_enable(Interrupt_Type::DTCRCERRIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::DTTMOUTIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::DTENDIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::STBITEIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::TFHIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::RFHIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::TXUREIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::RXOREIE, false);
}
template <typename CheckFunc>
inline SDIO_Error_Type send_command_and_check(Command_Index command, uint32_t argument,
Command_Response response, Wait_Type type, CheckFunc check_result) {
sdio_.set_command_state_machine(command, argument, response, type);
sync_domains();
sdio_.set_command_state_machine_enable(true);
return check_result();
}
};
} // namespace sdio
extern sdio::CardDMA& CardDMA_I;
@@ -25,16 +25,16 @@
* with simple implementations supplied by Marlin.
*/
#include "../platforms.h"
#include "../../platforms.h"
#ifdef ARDUINO_ARCH_MFL
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(IIC_BL24CXX_EEPROM)
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#error "MARLIN_EEPROM_SIZE is required for IIC_BL24CXX_EEPROM."
@@ -62,7 +62,7 @@ bool PersistentStore::write_data(int &pos, const uint8_t *value, size_t size, ui
// so only write bytes that have changed!
if (v != eeprom_read_byte(p)) {
eeprom_write_byte(p, v);
if (++written & 0x7F) delay(4); else safe_delay(4);
if (++written & 0x7F) delay(2); else safe_delay(2);
if (eeprom_read_byte(p) != v) {
SERIAL_ECHO_MSG(STR_ERR_EEPROM_WRITE);
return true;
@@ -25,16 +25,16 @@
* Enable USE_SHARED_EEPROM if not supplied by the framework.
*/
#include "../platforms.h"
#include "../../platforms.h"
#ifdef ARDUINO_ARCH_MFL
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(IIC_BL24CXX_EEPROM)
#include "../../libs/BL24CXX.h"
#include "../shared/eeprom_if.h"
#include "../../../libs/BL24CXX.h"
#include "../../shared/eeprom_if.h"
void eeprom_init() {
BL24CXX::init();
@@ -19,11 +19,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../platforms.h"
#include "../../platforms.h"
#ifdef ARDUINO_ARCH_MFL
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
@@ -32,8 +32,8 @@
* with simple implementations supplied by Marlin.
*/
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#define MARLIN_EEPROM_SIZE size_t(E2END + 1)
+12 -8
View File
@@ -21,23 +21,27 @@
*/
#pragma once
// Fast I/O interfaces for GD32F303RE
// Fast I/O interfaces for GD32
#include <GPIO.hpp>
#include <variant.h>
#include <PinOps.hpp>
#include <PinOpsMap.hpp>
static inline void fast_write_pin_wrapper(pin_size_t IO, bool V) {
if (V) gpio::fast_set_pin(getPortFromPin(IO), getPinInPort(IO));
else gpio::fast_clear_pin(getPortFromPin(IO), getPinInPort(IO));
template<typename T>
FORCE_INLINE static void fast_write_pin_wrapper(pin_size_t IO, T V) {
const PortPinPair& pp = port_pin_map[IO];
gpio::fast_write_pin(pp.port, pp.pin, static_cast<bool>(V));
}
static inline bool fast_read_pin_wrapper(pin_size_t IO) {
return gpio::fast_read_pin(getPortFromPin(IO), getPinInPort(IO));
FORCE_INLINE static auto fast_read_pin_wrapper(pin_size_t IO) -> bool {
const PortPinPair& pp = port_pin_map[IO];
return gpio::fast_read_pin(pp.port, pp.pin);
}
static inline void fast_toggle_pin_wrapper(pin_size_t IO) {
gpio::fast_toggle_pin(getPortFromPin(IO), getPinInPort(IO));
FORCE_INLINE static void fast_toggle_pin_wrapper(pin_size_t IO) {
const PortPinPair& pp = port_pin_map[IO];
gpio::fast_toggle_pin(pp.port, pp.pin);
}
// ------------------------
+6 -4
View File
@@ -70,8 +70,9 @@ bool isAnalogPin(const pin_t pin) {
if (!isValidPin(pin)) return false;
if (getAdcChannel(pin) != adc::ADC_Channel::INVALID) {
auto& instance = gpio::GPIO::get_instance(getPortFromPin(pin)).value();
return instance.get_pin_mode(getPinInPort(pin)) == gpio::Pin_Mode::ANALOG && !M43_NEVER_TOUCH(pin);
const PortPinPair& pp = port_pin_map[pin];
auto& instance = gpio::GPIO::get_instance(pp.port).value();
return instance.get_pin_mode(pp.pin) == gpio::Pin_Mode::ANALOG && !M43_NEVER_TOUCH(pin);
}
return false;
@@ -80,8 +81,9 @@ bool isAnalogPin(const pin_t pin) {
bool getValidPinMode(const pin_t pin) {
if (!isValidPin(pin)) return false;
auto& instance = gpio::GPIO::get_instance(getPortFromPin(pin)).value();
gpio::Pin_Mode mode = instance.get_pin_mode(getPinInPort(pin));
const PortPinPair& pp = port_pin_map[pin];
auto& instance = gpio::GPIO::get_instance(pp.port).value();
gpio::Pin_Mode mode = instance.get_pin_mode(pp.pin);
return mode != gpio::Pin_Mode::ANALOG && mode != gpio::Pin_Mode::INPUT_FLOATING &&
mode != gpio::Pin_Mode::INPUT_PULLUP && mode != gpio::Pin_Mode::INPUT_PULLDOWN;
@@ -15,12 +15,12 @@
// If not, see <https://www.gnu.org/licenses/>.
//
#include "../platforms.h"
#include "../../platforms.h"
#ifdef ARDUINO_ARCH_MFL
#include "../../inc/MarlinConfig.h"
#include "../shared/Delay.h"
#include "../../../inc/MarlinConfig.h"
#include "../../shared/Delay.h"
#include "SDCard.h"
#include <string.h>
@@ -28,7 +28,7 @@
namespace sdio {
CardDMA& CardDMA::get_instance() {
auto CardDMA::get_instance() -> CardDMA& {
static CardDMA instance;
return instance;
}
@@ -38,9 +38,7 @@ CardDMA::CardDMA() :
sdcard_cid_{0U, 0U, 0U, 0U},
sdcard_scr_{0U, 0U},
desired_clock_(Default_Desired_Clock),
stop_condition_(0U),
total_bytes_(0U),
count_(0U),
sdio_(SDIO::get_instance()),
config_(sdio_.get_config()),
dmaBase_(dma::DMA_Base::DMA1_BASE),
@@ -50,15 +48,15 @@ CardDMA::CardDMA() :
transfer_error_(SDIO_Error_Type::OK),
interface_version_(Interface_Version::UNKNOWN),
card_type_(Card_Type::UNKNOWN),
current_state_(Operational_State::READY),
transfer_end_(false),
is_rx_(false),
multiblock_(false),
current_state_(Operational_State::READY)
is_rx_(false)
{
}
// Initialize card and put in standby state
SDIO_Error_Type CardDMA::init() {
auto CardDMA::init() -> SDIO_Error_Type {
// Reset SDIO peripheral
sdio_.reset();
sync_domains();
@@ -79,7 +77,7 @@ SDIO_Error_Type CardDMA::init() {
}
// Startup command procedure according to SDIO specification
SDIO_Error_Type CardDMA::begin_startup_procedure() {
auto CardDMA::begin_startup_procedure() -> SDIO_Error_Type {
sdio_.set_power_mode(Power_Control::POWER_ON);
sdio_.set_clock_enable(true);
sync_domains();
@@ -124,12 +122,12 @@ SDIO_Error_Type CardDMA::begin_startup_procedure() {
}
// Voltage validation
SDIO_Error_Type CardDMA::validate_voltage() {
auto CardDMA::validate_voltage() -> SDIO_Error_Type {
uint32_t response = 0U;
uint32_t count = 0U;
bool valid_voltage = false;
while ((count < Max_Voltage_Checks) && (valid_voltage == false)) {
while (count < Max_Voltage_Checks && valid_voltage == false) {
if (send_command_and_check(Command_Index::CMD55, 0, Command_Response::RSP_SHORT,
Wait_Type::WT_NONE, [this, cmd = Command_Index::CMD55]() {
return get_r1_result(cmd);
@@ -144,7 +142,7 @@ SDIO_Error_Type CardDMA::validate_voltage() {
return SDIO_Error_Type::ACMD41_FAILED;
}
response = sdio_.get_response(Response_Type::RESPONSE0);
valid_voltage = (((response >> 31U) == 1U) ? true : false);
valid_voltage = ((response >> 31U) == 1U);
count++;
}
@@ -171,7 +169,7 @@ void CardDMA::begin_shutdown_procedure() {
}
// Initialize card
SDIO_Error_Type CardDMA::card_init() {
auto CardDMA::card_init() -> SDIO_Error_Type {
if (sdio_.get_power_mode() == static_cast<uint32_t>(Power_Control::POWER_OFF)) {
return SDIO_Error_Type::INVALID_OPERATION;
}
@@ -221,7 +219,7 @@ SDIO_Error_Type CardDMA::card_init() {
return SDIO_Error_Type::OK;
}
SDIO_Error_Type CardDMA::store_cid() {
auto CardDMA::store_cid() -> SDIO_Error_Type {
// Store the CID register values
sdcard_cid_[0] = sdio_.get_response(Response_Type::RESPONSE0);
sdcard_cid_[1] = sdio_.get_response(Response_Type::RESPONSE1);
@@ -231,7 +229,7 @@ SDIO_Error_Type CardDMA::store_cid() {
return SDIO_Error_Type::OK;
}
SDIO_Error_Type CardDMA::store_csd() {
auto CardDMA::store_csd() -> SDIO_Error_Type {
// Store the CSD register values
sdcard_csd_[0] = sdio_.get_response(Response_Type::RESPONSE0);
sdcard_csd_[1] = sdio_.get_response(Response_Type::RESPONSE1);
@@ -241,7 +239,7 @@ SDIO_Error_Type CardDMA::store_csd() {
return SDIO_Error_Type::OK;
}
SDIO_Error_Type CardDMA::set_hardware_bus_width(Bus_Width width) {
auto CardDMA::set_hardware_bus_width(Bus_Width width) -> SDIO_Error_Type {
if (card_type_ == Card_Type::SD_MMC || width == Bus_Width::WIDTH_8BIT) {
return SDIO_Error_Type::UNSUPPORTED_FUNCTION;
}
@@ -283,7 +281,7 @@ SDIO_Error_Type CardDMA::set_hardware_bus_width(Bus_Width width) {
return SDIO_Error_Type::UNSUPPORTED_FUNCTION;
}
SDIO_Error_Type CardDMA::read(uint8_t* buf, uint32_t address, uint32_t count) {
auto CardDMA::read(uint8_t* buf, uint32_t address, uint32_t count) -> SDIO_Error_Type {
if (current_state_ == Operational_State::READY) {
transfer_error_ = SDIO_Error_Type::OK;
current_state_ = Operational_State::BUSY;
@@ -340,7 +338,7 @@ SDIO_Error_Type CardDMA::read(uint8_t* buf, uint32_t address, uint32_t count) {
}
}
SDIO_Error_Type CardDMA::write(uint8_t* buf, uint32_t address, uint32_t count) {
auto CardDMA::write(uint8_t* buf, uint32_t address, uint32_t count) -> SDIO_Error_Type {
// Enable the interrupts
sdio_.set_interrupt_enable(Interrupt_Type::DTCRCERRIE, true);
sdio_.set_interrupt_enable(Interrupt_Type::DTTMOUTIE, true);
@@ -363,7 +361,7 @@ SDIO_Error_Type CardDMA::write(uint8_t* buf, uint32_t address, uint32_t count) {
// CMD25/CMD24 (WRITE_MULTIPLE_BLOCK/WRITE_BLOCK) send write command
Command_Index write_cmd = (count > 1U) ? Command_Index::CMD25 : Command_Index::CMD24;
if (send_command_and_check(write_cmd, address, Command_Response::RSP_SHORT,
Wait_Type::WT_NONE, [this, cmd = write_cmd]() {
Wait_Type::WT_NONE, [this, cmd = write_cmd]() {
return get_r1_result(cmd);
}) != SDIO_Error_Type::OK) {
sdio_.clear_multiple_interrupt_flags(clear_common_flags);
@@ -379,16 +377,16 @@ SDIO_Error_Type CardDMA::write(uint8_t* buf, uint32_t address, uint32_t count) {
Block_Size block_size = get_data_block_size_index(total_bytes_);
sdio_.set_data_state_machine_and_send(Data_Timeout, total_bytes_, block_size,
Transfer_Mode::BLOCK, Transfer_Direction::SDIO_TO_CARD, true);
Transfer_Mode::BLOCK, Transfer_Direction::SDIO_TO_CARD, true);
while ((dma_.get_flag(dma::Status_Flags::FLAG_FTFIF)) || (dma_.get_flag(dma::Status_Flags::FLAG_ERRIF))) {
while (dma_.get_flag(dma::Status_Flags::FLAG_FTFIF) || dma_.get_flag(dma::Status_Flags::FLAG_ERRIF)) {
// Wait for the IRQ handler to clear
}
return SDIO_Error_Type::OK;
}
SDIO_Error_Type CardDMA::erase(uint32_t address_start, uint32_t address_end) {
auto CardDMA::erase(uint32_t address_start, uint32_t address_end) -> SDIO_Error_Type {
SDIO_Error_Type result = SDIO_Error_Type::OK;
// Card command classes CSD
@@ -459,9 +457,11 @@ void CardDMA::handle_interrupts() {
disable_all_interrupts();
sdio_.set_data_state_machine_enable(false);
if ((multiblock_) && (!is_rx_)) {
if (multiblock_ && !is_rx_) {
transfer_error_ = stop_transfer();
if (transfer_error_ != SDIO_Error_Type::OK) {}
if (transfer_error_ != SDIO_Error_Type::OK) {
return;
}
}
if (!is_rx_) {
@@ -497,7 +497,7 @@ void CardDMA::handle_interrupts() {
}
}
SDIO_Error_Type CardDMA::select_deselect() {
auto CardDMA::select_deselect() -> SDIO_Error_Type {
// CMD7 (SELECT/DESELECT_CARD)
if (send_command_and_check(Command_Index::CMD7, static_cast<uint32_t>(sdcard_rca_ << RCA_Shift),
Command_Response::RSP_SHORT, Wait_Type::WT_NONE, [this, cmd = Command_Index::CMD7]() {
@@ -508,7 +508,7 @@ SDIO_Error_Type CardDMA::select_deselect() {
return SDIO_Error_Type::OK;
}
SDIO_Error_Type CardDMA::get_card_interface_status(uint32_t* status) {
auto CardDMA::get_card_interface_status(uint32_t* status) -> SDIO_Error_Type {
if (status == nullptr) return SDIO_Error_Type::INVALID_PARAMETER;
// CMD13 (SEND_STATUS)
@@ -524,7 +524,7 @@ SDIO_Error_Type CardDMA::get_card_interface_status(uint32_t* status) {
return SDIO_Error_Type::OK;
}
SDIO_Error_Type CardDMA::get_sdcard_status(uint32_t* status) {
auto CardDMA::get_sdcard_status(uint32_t* status) -> SDIO_Error_Type {
uint32_t count = 0U;
// CMD16 (SET_BLOCKLEN)
@@ -599,7 +599,7 @@ void CardDMA::check_dma_complete() {
}
}
SDIO_Error_Type CardDMA::stop_transfer() {
auto CardDMA::stop_transfer() -> SDIO_Error_Type {
// CMD12 (STOP_TRANSMISSION)
if (send_command_and_check(Command_Index::CMD12, 0, Command_Response::RSP_SHORT, Wait_Type::WT_NONE, [this, cmd = Command_Index::CMD12]() {
return get_r1_result(cmd);
@@ -609,7 +609,7 @@ SDIO_Error_Type CardDMA::stop_transfer() {
return SDIO_Error_Type::OK;
}
Transfer_State CardDMA::get_transfer_state() {
auto CardDMA::get_transfer_state() -> Transfer_State {
Transfer_State transfer_state = Transfer_State::IDLE;
if (sdio_.get_flag(Status_Flags::FLAG_TXRUN) | sdio_.get_flag(Status_Flags::FLAG_RXRUN)) {
transfer_state = Transfer_State::BUSY;
@@ -618,7 +618,7 @@ Transfer_State CardDMA::get_transfer_state() {
return transfer_state;
}
uint32_t CardDMA::get_card_capacity() const {
[[nodiscard]] auto CardDMA::get_card_capacity() const -> uint32_t {
auto extract_bits = [](uint32_t value, uint8_t start_bit, uint8_t length) -> uint32_t {
return (value >> start_bit) & ((1U << length) - 1U);
};
@@ -665,7 +665,7 @@ uint32_t CardDMA::get_card_capacity() const {
return capacity;
}
SDIO_Error_Type CardDMA::get_card_specific_data(Card_Info* info) {
auto CardDMA::get_card_specific_data(Card_Info* info) -> SDIO_Error_Type {
if (info == nullptr) return SDIO_Error_Type::INVALID_PARAMETER;
// Store basic card information
@@ -735,28 +735,20 @@ SDIO_Error_Type CardDMA::get_card_specific_data(Card_Info* info) {
return SDIO_Error_Type::OK;
}
constexpr Block_Size CardDMA::get_data_block_size_index(uint16_t size) {
switch (size) {
case 1: return Block_Size::BYTES_1;
case 2: return Block_Size::BYTES_2;
case 4: return Block_Size::BYTES_4;
case 8: return Block_Size::BYTES_8;
case 16: return Block_Size::BYTES_16;
case 32: return Block_Size::BYTES_32;
case 64: return Block_Size::BYTES_64;
case 128: return Block_Size::BYTES_128;
case 256: return Block_Size::BYTES_256;
case 512: return Block_Size::BYTES_512;
case 1024: return Block_Size::BYTES_1024;
case 2048: return Block_Size::BYTES_2048;
case 4096: return Block_Size::BYTES_4096;
case 8192: return Block_Size::BYTES_8192;
case 16384: return Block_Size::BYTES_16384;
default: return Block_Size::BYTES_1;
}
constexpr auto CardDMA::get_data_block_size_index(uint16_t size) -> Block_Size {
if (size < 1 || size > 16384) return Block_Size::BYTES_1;
// Check if size is a power of two
if ((size & (size - 1)) != 0) return Block_Size::BYTES_1;
// Count trailing zeros to find the index
uint16_t index = 0;
while ((size >>= 1) != 0) ++index;
return static_cast<Block_Size>(index);
}
SDIO_Error_Type CardDMA::get_card_state(Card_State* card_state) {
auto CardDMA::get_card_state(Card_State* card_state) -> SDIO_Error_Type {
// CMD13 (SEND_STATUS)
if (send_command_and_check(Command_Index::CMD13, static_cast<uint32_t>(sdcard_rca_ << RCA_Shift),
Command_Response::RSP_SHORT, Wait_Type::WT_NONE, [this, cmd = Command_Index::CMD13]() {
@@ -773,7 +765,7 @@ SDIO_Error_Type CardDMA::get_card_state(Card_State* card_state) {
if (response & All_R1_Error_Bits) {
for (const auto& entry : errorTableR1) {
if (response & entry.mask) {
if (TEST(response, entry.bit_position)) {
return entry.errorType;
}
}
@@ -783,23 +775,28 @@ SDIO_Error_Type CardDMA::get_card_state(Card_State* card_state) {
return SDIO_Error_Type::OK;
}
SDIO_Error_Type CardDMA::get_command_sent_result() {
volatile uint32_t timeout = 0x00FFFFFFU;
auto CardDMA::get_command_sent_result() -> SDIO_Error_Type {
constexpr uint32_t MAX_TIMEOUT = 0x00FFFFFFU;
uint32_t timeout = MAX_TIMEOUT;
while ((sdio_.get_flag(Status_Flags::FLAG_CMDSEND) == false) && (timeout != 0U)) {
timeout = timeout - 1U;
// Wait for command sent flag or timeout
while (!sdio_.get_flag(Status_Flags::FLAG_CMDSEND) && timeout) {
--timeout;
}
if (timeout == 0U) return SDIO_Error_Type::RESPONSE_TIMEOUT;
sdio_.clear_multiple_interrupt_flags(clear_command_flags);
// Check if timeout occurred
if (timeout == 0U) {
return SDIO_Error_Type::RESPONSE_TIMEOUT;
}
// Clear command flags and return success
sdio_.clear_multiple_interrupt_flags(clear_command_flags);
return SDIO_Error_Type::OK;
}
SDIO_Error_Type CardDMA::check_sdio_status(Command_Index index, bool check_index, bool ignore_crc) {
auto CardDMA::check_sdio_status(Command_Index index, bool check_index, bool ignore_crc) -> SDIO_Error_Type {
// Wait until one of the relevant flags is set
bool flag_set = sdio_.wait_cmd_flags();
if (!flag_set) {
if (!sdio_.wait_cmd_flags()) {
return SDIO_Error_Type::RESPONSE_TIMEOUT;
}
@@ -810,56 +807,55 @@ SDIO_Error_Type CardDMA::check_sdio_status(Command_Index index, bool check_index
// If cmd was received, check the index
// Responses that dont do an index check will send an invalid cmd index
if (check_index && (index != Command_Index::INVALID)) {
uint8_t idx = sdio_.get_command_index();
if (idx != static_cast<uint8_t>(index)) {
uint8_t received_idx = sdio_.get_command_index();
if (received_idx != static_cast<uint8_t>(index)) {
sdio_.clear_multiple_interrupt_flags(clear_command_flags);
return SDIO_Error_Type::ILLEGAL_COMMAND;
}
}
// Clear all flags before returning
// Command received successfully
sdio_.clear_multiple_interrupt_flags(clear_command_flags);
return SDIO_Error_Type::OK;
}
// Timeout check
// Check for timeout
if (sdio_.get_flag(Status_Flags::FLAG_CMDTMOUT)) {
sdio_.clear_flag(Clear_Flags::FLAG_CMDTMOUTC);
return SDIO_Error_Type::RESPONSE_TIMEOUT;
}
// CRC check
if (!ignore_crc) {
if (sdio_.get_flag(Status_Flags::FLAG_CCRCERR)) {
sdio_.clear_flag(Clear_Flags::FLAG_CCRCERRC);
return SDIO_Error_Type::COMMAND_CRC_ERROR;
}
// Check for CRC error if not ignored
if (!ignore_crc && sdio_.get_flag(Status_Flags::FLAG_CCRCERR)) {
sdio_.clear_flag(Clear_Flags::FLAG_CCRCERRC);
return SDIO_Error_Type::COMMAND_CRC_ERROR;
}
// Responses that dont do an index check will send an invalid cmd index
// Final index check (redundant with the first check, but keeping for safety)
// This code path should rarely be taken due to the earlier checks
if (check_index && (index != Command_Index::INVALID)) {
uint8_t idx = sdio_.get_command_index();
if (idx != static_cast<uint8_t>(index)) {
uint8_t received_idx = sdio_.get_command_index();
if (received_idx != static_cast<uint8_t>(index)) {
sdio_.clear_multiple_interrupt_flags(clear_command_flags);
return SDIO_Error_Type::ILLEGAL_COMMAND;
}
}
// Clear all flags before returning
// Clear all flags and return success
sdio_.clear_multiple_interrupt_flags(clear_command_flags);
return SDIO_Error_Type::OK;
}
SDIO_Error_Type CardDMA::get_r1_result(Command_Index index) {
auto CardDMA::get_r1_result(Command_Index index) -> SDIO_Error_Type {
SDIO_Error_Type result = check_sdio_status(index, true, false);
if (result != SDIO_Error_Type::OK) {
return result;
}
if (result != SDIO_Error_Type::OK) return result;
// Get the R1 response and check for errors
uint32_t response = sdio_.get_response(Response_Type::RESPONSE0);
if (response & All_R1_Error_Bits) {
for (const auto& entry : errorTableR1) {
if (response & entry.mask) {
if (TEST(response, entry.bit_position)) {
return entry.errorType;
}
}
@@ -869,7 +865,7 @@ SDIO_Error_Type CardDMA::get_r1_result(Command_Index index) {
return SDIO_Error_Type::OK;
}
SDIO_Error_Type CardDMA::get_r6_result(Command_Index index, uint16_t* rca) {
auto CardDMA::get_r6_result(Command_Index index, uint16_t* rca) -> SDIO_Error_Type {
SDIO_Error_Type result = check_sdio_status(index, true, false);
if (result != SDIO_Error_Type::OK) return result;
@@ -877,7 +873,7 @@ SDIO_Error_Type CardDMA::get_r6_result(Command_Index index, uint16_t* rca) {
if (response & R6_Error_Bits) {
for (const auto& entry : errorTableR6) {
if (response & entry.mask) {
if (TEST(response, entry.bit_position)) {
return entry.errorType;
}
}
@@ -888,18 +884,13 @@ SDIO_Error_Type CardDMA::get_r6_result(Command_Index index, uint16_t* rca) {
return SDIO_Error_Type::OK;
}
SDIO_Error_Type CardDMA::get_r7_result() {
return check_sdio_status(Command_Index::INVALID, false, false);
}
SDIO_Error_Type CardDMA::get_scr(uint16_t rca, uint32_t* scr) {
auto CardDMA::get_scr(uint16_t rca, uint32_t* scr) -> SDIO_Error_Type {
uint32_t temp_scr[2] = {0U, 0U};
uint32_t index_scr = 0U;
uint32_t* src_data = scr;
// CMD16 (SET_BLOCKLEN)
if (send_command_and_check(Command_Index::CMD16, 8U, Command_Response::RSP_SHORT,
Wait_Type::WT_NONE, [this, cmd = Command_Index::CMD16]() {
Wait_Type::WT_NONE, [this, cmd = Command_Index::CMD16]() {
return get_r1_result(cmd);
}) != SDIO_Error_Type::OK) {
return SDIO_Error_Type::CMD16_FAILED;
@@ -907,7 +898,7 @@ SDIO_Error_Type CardDMA::get_scr(uint16_t rca, uint32_t* scr) {
// CMD55 (APP_CMD)
if (send_command_and_check(Command_Index::CMD55, static_cast<uint32_t>(sdcard_rca_ << RCA_Shift),
Command_Response::RSP_SHORT, Wait_Type::WT_NONE, [this, cmd = Command_Index::CMD55]() {
Command_Response::RSP_SHORT, Wait_Type::WT_NONE, [this, cmd = Command_Index::CMD55]() {
return get_r1_result(cmd);
}) != SDIO_Error_Type::OK) {
return SDIO_Error_Type::CMD55_FAILED;
@@ -919,7 +910,7 @@ SDIO_Error_Type CardDMA::get_scr(uint16_t rca, uint32_t* scr) {
// ACMD51 (SEND_SCR)
if (send_command_and_check(Command_Index::ACMD51, 0U, Command_Response::RSP_SHORT,
Wait_Type::WT_NONE, [this, cmd = Command_Index::ACMD51]() {
Wait_Type::WT_NONE, [this, cmd = Command_Index::ACMD51]() {
return get_r1_result(cmd);
}) != SDIO_Error_Type::OK) {
return SDIO_Error_Type::ACMD51_FAILED;
@@ -928,36 +919,41 @@ SDIO_Error_Type CardDMA::get_scr(uint16_t rca, uint32_t* scr) {
// Store SCR
while (!sdio_.check_scr_flags()) {
if (sdio_.get_flag(Status_Flags::FLAG_RXDTVAL)) {
*(temp_scr + index_scr) = sdio_.read_fifo_word();
++index_scr;
temp_scr[index_scr++] = sdio_.read_fifo_word();
}
}
// Check for errors
if (sdio_.get_flag(Status_Flags::FLAG_DTTMOUT)) {
sdio_.clear_flag(Clear_Flags::FLAG_DTTMOUTC);
return SDIO_Error_Type::DATA_TIMEOUT;
} else if (sdio_.get_flag(Status_Flags::FLAG_DTCRCERR)) {
}
else if (sdio_.get_flag(Status_Flags::FLAG_DTCRCERR)) {
sdio_.clear_flag(Clear_Flags::FLAG_DTCRCERRC);
return SDIO_Error_Type::DATA_CRC_ERROR;
} else if (sdio_.get_flag(Status_Flags::FLAG_RXORE)) {
}
else if (sdio_.get_flag(Status_Flags::FLAG_RXORE)) {
sdio_.clear_flag(Clear_Flags::FLAG_RXOREC);
return SDIO_Error_Type::RX_FIFO_OVERRUN;
}
sdio_.clear_multiple_interrupt_flags(clear_data_flags);
constexpr uint32_t Zero_Seven = (0xFFU << 0U);
constexpr uint32_t Eight_Fifteen = (0xFFU << 8U);
constexpr uint32_t Sixteen_Twentythree = (0xFFU << 16U);
constexpr uint32_t TwentyFour_Thirtyone = (0xFFU << 24U);
constexpr uint32_t BYTE0_MASK = 0xFFU;
constexpr uint32_t BYTE1_MASK = 0xFF00U;
constexpr uint32_t BYTE2_MASK = 0xFF0000U;
constexpr uint32_t BYTE3_MASK = 0xFF000000U;
// adjust SCR value
*src_data = ((temp_scr[1] & Zero_Seven) << 24U) | ((temp_scr[1] & Eight_Fifteen) << 8U) |
((temp_scr[1] & Sixteen_Twentythree) >> 8U) | ((temp_scr[1] & TwentyFour_Thirtyone) >> 24U);
// Byte-swap the SCR values (convert from big-endian to little-endian)
scr[0] = ((temp_scr[1] & BYTE0_MASK) << 24) |
((temp_scr[1] & BYTE1_MASK) << 8) |
((temp_scr[1] & BYTE2_MASK) >> 8) |
((temp_scr[1] & BYTE3_MASK) >> 24);
src_data = src_data + 1U;
*src_data = ((temp_scr[0] & Zero_Seven) << 24U) | ((temp_scr[0] & Eight_Fifteen) << 8U) |
((temp_scr[0] & Sixteen_Twentythree) >> 8U) | ((temp_scr[0] & TwentyFour_Thirtyone) >> 24U);
scr[1] = ((temp_scr[0] & BYTE0_MASK) << 24) |
((temp_scr[0] & BYTE1_MASK) << 8) |
((temp_scr[0] & BYTE2_MASK) >> 8) |
((temp_scr[0] & BYTE3_MASK) >> 24);
return SDIO_Error_Type::OK;
}
@@ -965,23 +961,22 @@ SDIO_Error_Type CardDMA::get_scr(uint16_t rca, uint32_t* scr) {
// DMA for rx/tx is always DMA1 channel 3
void CardDMA::set_dma_parameters(uint8_t* buf, uint32_t count, bool is_write) {
constexpr uint32_t flag_bits = (1U << static_cast<uint32_t>(dma::INTF_Bits::GIF3));
dma_.clear_flags(flag_bits);
// Disable and reset DMA
dma_.set_channel_enable(false);
dma_.clear_channel();
dma_.init({
count,
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(buf)),
static_cast<uint32_t>(reinterpret_cast<uintptr_t>(sdio_.reg_address(SDIO_Regs::FIFO))),
dma::Bit_Width::WIDTH_32BIT,
dma::Bit_Width::WIDTH_32BIT,
dma::Increase_Mode::INCREASE_DISABLE,
dma::Increase_Mode::INCREASE_ENABLE,
dma::Channel_Priority::MEDIUM_PRIORITY,
is_write ? dma::Transfer_Direction::M2P : dma::Transfer_Direction::P2M
dma_.init(dma::DMA_Config{
.count = count,
.memory_address = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(buf)),
.peripheral_address = static_cast<uint32_t>(reinterpret_cast<uintptr_t>(sdio_.reg_address(SDIO_Regs::FIFO))),
.peripheral_bit_width = dma::Bit_Width::WIDTH_32BIT,
.memory_bit_width = dma::Bit_Width::WIDTH_32BIT,
.peripheral_increase = dma::Increase_Mode::INCREASE_DISABLE,
.memory_increase = dma::Increase_Mode::INCREASE_ENABLE,
.channel_priority = dma::Channel_Priority::MEDIUM_PRIORITY,
.direction = is_write ? dma::Transfer_Direction::M2P : dma::Transfer_Direction::P2M
});
dma_.set_memory_to_memory_enable(false);
@@ -995,24 +990,29 @@ void CardDMA::set_dma_parameters(uint8_t* buf, uint32_t count, bool is_write) {
dma_.set_channel_enable(true);
}
SDIO_Error_Type CardDMA::wait_for_card_ready() {
volatile uint32_t timeout = 0x00FFFFFFU;
auto CardDMA::wait_for_card_ready() -> SDIO_Error_Type {
constexpr uint32_t MAX_TIMEOUT = 0x00FFFFFFU;
uint32_t timeout = MAX_TIMEOUT;
uint32_t response = sdio_.get_response(Response_Type::RESPONSE0);
while (((response & static_cast<uint32_t>(R1_Status::READY_FOR_DATA)) == 0U) && (timeout != 0U)) {
// Continue to send CMD13 to poll the state of card until buffer empty or timeout
timeout = timeout - 1U;
// Poll until card is ready for data or timeout occurs
while (((response & static_cast<uint32_t>(R1_Status::READY_FOR_DATA)) == 0U) && timeout) {
--timeout;
// CMD13 (SEND_STATUS)
if (send_command_and_check(Command_Index::CMD13, static_cast<uint32_t>(sdcard_rca_ << RCA_Shift),
Command_Response::RSP_SHORT, Wait_Type::WT_NONE, [this, cmd = Command_Index::CMD13]() {
Command_Response::RSP_SHORT, Wait_Type::WT_NONE, [this, cmd = Command_Index::CMD13]() {
return get_r1_result(cmd);
}) != SDIO_Error_Type::OK) {
return SDIO_Error_Type::CMD13_FAILED;
}
// Get updated response
response = sdio_.get_response(Response_Type::RESPONSE0);
}
return (timeout == 0U) ? SDIO_Error_Type::ERROR : SDIO_Error_Type::OK;
// Return error if timeout occurred, otherwise success
return timeout ? SDIO_Error_Type::OK : SDIO_Error_Type::ERROR;
}
} // namespace sdio
+222
View File
@@ -0,0 +1,222 @@
//
// MFL gd32f30x SDCARD using DMA through SDIO in C++
//
// Copyright (C) 2025 B. Mourit <bnmguy@gmail.com>
//
// This software is free software: you can redistribute it and/or modify it under the terms of the
// GNU Lesser General Public License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any later version.
//
// This software 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 Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License along with this software.
// If not, see <https://www.gnu.org/licenses/>.
//
#pragma once
#include "../../../inc/MarlinConfig.h"
#include <SDIO.hpp>
namespace sdio {
class DMA;
class CardDMA {
public:
static auto get_instance() -> CardDMA&;
// Initialization
auto init() -> SDIO_Error_Type;
auto card_init() -> SDIO_Error_Type;
// Startup and shutdown procedures
auto begin_startup_procedure() -> SDIO_Error_Type;
void begin_shutdown_procedure();
// Configuration
auto set_hardware_bus_width(Bus_Width width) -> SDIO_Error_Type;
auto send_bus_width_command(uint32_t width_value) -> SDIO_Error_Type;
// Main read/write/erase functions
auto read(uint8_t* buf, uint32_t address, uint32_t count) -> SDIO_Error_Type;
auto write(uint8_t* buf, uint32_t address, uint32_t count) -> SDIO_Error_Type;
auto erase(uint32_t address_start, uint32_t address_end) -> SDIO_Error_Type;
// Card select
auto select_deselect() -> SDIO_Error_Type;
// Status and state
auto get_card_interface_status(uint32_t* status) -> SDIO_Error_Type;
auto get_sdcard_status(uint32_t* status) -> SDIO_Error_Type;
auto get_transfer_state() -> Transfer_State;
auto get_card_state(Card_State* card_state) -> SDIO_Error_Type;
auto check_sdio_status(Command_Index index = Command_Index::INVALID, bool check_index = false, bool ignore_crc = false) -> SDIO_Error_Type;
// DMA
void set_dma_parameters(uint8_t* buf, uint32_t count, bool is_write);
void check_dma_complete();
// Stop transfer
auto stop_transfer() -> SDIO_Error_Type;
// Card information
auto get_card_specific_data(Card_Info* info) -> SDIO_Error_Type;
constexpr auto get_data_block_size_index(uint16_t size) -> Block_Size;
[[nodiscard]] auto get_card_capacity() const -> uint32_t;
// SDIO configuration
void sdio_configure(const SDIO_Config config) { sdio_.init(config); }
// Interrupt handler
void handle_interrupts();
// Varaible stored parameters
auto get_scr(uint16_t rca, uint32_t* scr) -> SDIO_Error_Type;
auto store_cid() -> SDIO_Error_Type;
auto store_csd() -> SDIO_Error_Type;
// Inlined accessor methods
auto get_config() -> SDIO_Config& { return config_; }
auto get_dma_instance() -> dma::DMA& { return dma_; }
void set_data_end_interrupt() { sdio_.set_interrupt_enable(Interrupt_Type::DTENDIE, true); }
void set_sdio_dma_enable(bool enable) { sdio_.set_dma_enable(enable); }
auto get_is_sdio_rx() -> bool { return is_rx_; }
void clear_sdio_data_flags() { sdio_.clear_multiple_interrupt_flags(clear_data_flags); }
void clear_sdio_cmd_flags() { sdio_.clear_multiple_interrupt_flags(clear_command_flags); }
void clear_sdio_common_flags() { sdio_.clear_multiple_interrupt_flags(clear_common_flags); }
auto get_state() -> Operational_State { return current_state_; }
void set_state(Operational_State state) { current_state_ = state; }
void set_transfer_error(SDIO_Error_Type error) { transfer_error_ = error; }
void set_transfer_end(bool end) { transfer_end_ = end; };
auto set_desired_clock(uint32_t desired_clock, bool wide_bus, bool low_power) -> SDIO_Error_Type {
sdio_.init(SDIO_Config{
.desired_clock = desired_clock,
.enable_bypass = false,
.enable_powersave = low_power,
.enable_hwclock = false,
.clock_edge = Clock_Edge::RISING_EDGE,
.width = wide_bus ? Bus_Width::WIDTH_4BIT : Bus_Width::WIDTH_1BIT
});
sync_domains();
desired_clock_ = desired_clock;
return SDIO_Error_Type::OK;
}
private:
CardDMA();
// Prevent copying or assigning
CardDMA(const CardDMA&) = delete;
auto operator=(const CardDMA&) -> CardDMA& = delete;
// Helper function
auto wait_for_card_ready() -> SDIO_Error_Type;
// Member variables
alignas(4) uint32_t sdcard_csd_[4];
alignas(4) uint32_t sdcard_cid_[4];
alignas(4) uint32_t sdcard_scr_[2];
uint32_t desired_clock_;
uint32_t total_bytes_;
SDIO& sdio_;
SDIO_Config& config_;
const dma::DMA_Base dmaBase_;
const dma::DMA_Channel dmaChannel_;
dma::DMA& dma_;
uint16_t sdcard_rca_;
SDIO_Error_Type transfer_error_;
Interface_Version interface_version_;
Card_Type card_type_;
Operational_State current_state_;
bool transfer_end_;
bool multiblock_;
bool is_rx_;
// Private helper methods
auto validate_voltage() -> SDIO_Error_Type;
auto get_command_sent_result() -> SDIO_Error_Type;
auto get_r1_result(Command_Index index) -> SDIO_Error_Type;
auto get_r6_result(Command_Index index, uint16_t* rca) -> SDIO_Error_Type;
auto get_r7_result() -> SDIO_Error_Type { return check_sdio_status(Command_Index::INVALID, false, false); };
void sync_domains() { delayMicroseconds(8); }
auto validate_transfer_params(uint32_t* buf, uint16_t size) -> bool {
if (buf == nullptr) return false;
// Size must be > 0, <= 2048 and power of 2
return size > 0U && size <= 2048U && !(size & (size - 1U));
}
void process_sdsc_specific_csd(Card_Info* info, const uint8_t* csd_bytes) {
const uint32_t device_size = ((csd_bytes[6] & 0x3U) << 10) |
(csd_bytes[7] << 2) |
((csd_bytes[8] >> 6) & 0x3U);
const uint8_t device_size_multiplier = ((csd_bytes[9] & 0x3U) << 1) |
((csd_bytes[10] >> 7) & 0x1U);
// Store calculated values
info->csd.device_size = device_size;
info->csd.device_size_multiplier = device_size_multiplier;
// Calculate block size and capacity
info->block_size = 1U << info->csd.read_block_length;
info->capacity = (device_size + 1U) *
(1U << (device_size_multiplier + 2U)) *
info->block_size;
}
void process_sdhc_specific_csd(Card_Info* info, const uint8_t* csd_bytes) {
info->csd.device_size = static_cast<uint32_t>((csd_bytes[7] & 0x3FU) << 16) |
static_cast<uint32_t>((csd_bytes[8]) << 8) |
static_cast<uint32_t>(csd_bytes[9]);
// Set block size and calculate capacity
info->block_size = BLOCK_SIZE;
info->capacity = static_cast<uint32_t>((info->csd.device_size + 1U) *
BLOCK_SIZE * KILOBYTE);
}
void process_common_csd_tail(Card_Info* info, const uint8_t* csd_bytes) {
// Calculate sector_size
info->csd.sector_size = static_cast<uint8_t>(((csd_bytes[9] & 0x3FU) << 1) |
(csd_bytes[10] & 0x80U) >> 7);
// Calculate speed_factor and write_block_length
info->csd.speed_factor = static_cast<uint8_t>((csd_bytes[11] & 0x1CU) >> 2);
info->csd.write_block_length = static_cast<uint8_t>(((csd_bytes[11] & 0x3U) << 2) |
((csd_bytes[12] & 0xC0U) >> 6));
// Calculate checksum
info->csd.checksum = static_cast<uint8_t>((csd_bytes[15] & 0xFEU) >> 1);
}
void disable_all_interrupts() {
sdio_.set_interrupt_enable(Interrupt_Type::DTCRCERRIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::DTTMOUTIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::DTENDIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::STBITEIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::TFHIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::RFHIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::TXUREIE, false);
sdio_.set_interrupt_enable(Interrupt_Type::RXOREIE, false);
}
template <typename CheckFunc>
auto send_command_and_check(Command_Index command, uint32_t argument,
Command_Response response, Wait_Type type, CheckFunc check_result) -> SDIO_Error_Type {
sdio_.set_command_state_machine(command, argument, response, type);
sync_domains();
sdio_.set_command_state_machine_enable(true);
return check_result();
}
};
} // namespace sdio
extern sdio::CardDMA& CardDMA_I;
@@ -20,11 +20,11 @@
*
*/
#include "../platforms.h"
#include "../../platforms.h"
#ifdef ARDUINO_ARCH_MFL
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(ONBOARD_SDIO)
@@ -47,7 +47,7 @@ inline constexpr uint8_t SDIO_READ_RETRIES = READ_RETRIES;
Card_State cardState = Card_State::READY;
bool SDIO_SetBusWidth(Bus_Width width) {
auto SDIO_SetBusWidth(Bus_Width width) -> bool {
return (CardDMA_I.set_hardware_bus_width(width) == SDIO_Error_Type::OK);
}
@@ -215,7 +215,6 @@ void DMA1_IRQHandler() {
}
}
extern "C" {
void SDIO_IRQHandler(void) {
@@ -228,6 +227,5 @@ extern "C" {
} // extern "C"
#endif // ONBOARD_SDIO
#endif // ARDUINO_ARCH_MFL
@@ -32,5 +32,5 @@
#define SDIO_CMD_PIN PD2
void sdio_mfl_init();
bool SDIO_SetBusWidth(sdio::Bus_Width width);
auto SDIO_SetBusWidth(sdio::Bus_Width width) -> bool;
void DMA1_IRQHandler(dma::DMA_Channel channel);
+8 -1
View File
@@ -92,7 +92,9 @@ bool is_temp_timer_initialized = false;
// Retrieves the clock frequency of the stepper timer
uint32_t GetStepperTimerClkFreq() {
return Step_Timer.getTimerClockFrequency();
// Cache result
static uint32_t clkFreq = Step_Timer.getTimerClockFrequency();
return clkFreq;
}
/**
@@ -191,10 +193,12 @@ void SetTimerInterruptPriorities() {
// Detect timer conflicts
// ------------------------
TERN_(HAS_TMC_SW_SERIAL, static constexpr timer::TIMER_Base timer_serial[] = {static_cast<timer::TIMER_Base>(TIMER_SERIAL)});
TERN_(SPEAKER, static constexpr timer::TIMER_Base timer_tone[] = {static_cast<timer::TIMER_Base>(TIMER_TONE)});
TERN_(HAS_SERVOS, static constexpr timer::TIMER_Base timer_servo[] = {static_cast<timer::TIMER_Base>(TIMER_SERVO)});
enum TimerPurpose {
PURPOSE_SERIAL,
PURPOSE_TONE,
PURPOSE_SERVO,
PURPOSE_STEP,
@@ -205,6 +209,9 @@ enum TimerPurpose {
// Includes the timer purpose to ease debugging when evaluating at build-time
// This cannot yet account for timers used for PWM output, such as for fans
static constexpr struct { TimerPurpose p; int t; } timers_in_use[] = {
#if HAS_TMC_SW_SERIAL
{ PURPOSE_SERIAL, timer_base_to_index(timer_serial[0]) }, // Set in variant.h
#endif
#if ENABLED(SPEAKER)
{ PURPOSE_TONE, timer_base_to_index(timer_tone[0]) }, // Set in variant.h
#endif
+2 -2
View File
@@ -89,7 +89,7 @@ static inline constexpr struct {timer::TIMER_Base base; uint8_t timer_number;} b
};
// Converts a timer base to an integer timer index.
constexpr int timer_base_to_index(timer::TIMER_Base base) {
constexpr auto timer_base_to_index(timer::TIMER_Base base) -> int {
for (const auto& timer : base_to_index) {
if (timer.base == base) {
return static_cast<int>(timer.timer_number);
@@ -131,7 +131,7 @@ FORCE_INLINE static hal_timer_t HAL_timer_get_count(const uint8_t timer_number)
FORCE_INLINE static void HAL_timer_set_compare(const uint8_t timer_number, const hal_timer_t value) {
if (!HAL_timer_initialized(timer_number)) return;
const uint32_t new_value = static_cast<uint32_t>(value + 1U);
const auto new_value = static_cast<uint32_t>(value + 1U);
GeneralTimer& timer = (timer_number == MF_TIMER_STEP) ? Step_Timer : Temp_Timer;
if (timer_number == MF_TIMER_STEP || timer_number == MF_TIMER_TEMP) {
+1 -1
View File
@@ -27,7 +27,7 @@
#define GCC_VERSION (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__)
#endif
#include HAL_PATH(..,HAL.h)
#include HAL_PATH(.., HAL.h)
extern MarlinHAL hal;
#define HAL_ADC_RANGE _BV(HAL_ADC_RESOLUTION)
@@ -26,12 +26,12 @@
*/
#ifdef ARDUINO_ARCH_HC32
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(IIC_BL24CXX_EEPROM)
#include "../shared/eeprom_api.h"
#include "../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#ifndef MARLIN_EEPROM_SIZE
#error "MARLIN_EEPROM_SIZE is required for IIC_BL24CXX_EEPROM."
@@ -26,12 +26,12 @@
*/
#ifdef ARDUINO_ARCH_HC32
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(IIC_BL24CXX_EEPROM)
#include "../../libs/BL24CXX.h"
#include "../shared/eeprom_if.h"
#include "../../../libs/BL24CXX.h"
#include "../../shared/eeprom_if.h"
void eeprom_init() {
BL24CXX::init();
@@ -25,12 +25,12 @@
*/
#ifdef ARDUINO_ARCH_HC32
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(SDCARD_EEPROM_EMULATION)
#include "../shared/eeprom_api.h"
#include "../../sd/cardreader.h"
#include "../../shared/eeprom_api.h"
#include "../../../sd/cardreader.h"
#define EEPROM_FILENAME "eeprom.dat"
@@ -21,7 +21,7 @@
*/
#ifdef ARDUINO_ARCH_HC32
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
@@ -32,8 +32,8 @@
* with simple implementations supplied by Marlin.
*/
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#error "MARLIN_EEPROM_SIZE is required for I2C / SPI EEPROM."
+1 -1
View File
@@ -124,7 +124,7 @@ public:
static void isr_on() {}
static void isr_off() {}
static void delay_ms(const int ms) { _delay_ms(ms); }
static void delay_ms(const int ms) { delay(ms); }
// Tasks, called from idle()
static void idletask() {}
-2
View File
@@ -31,8 +31,6 @@ void cli() { } // Disable
void sei() { } // Enable
// Time functions
void _delay_ms(const int ms) { delay(ms); }
unsigned long millis() {
return (unsigned long)Clock::millis();
}
-1
View File
@@ -74,7 +74,6 @@ extern "C" {
// Time functions
extern "C" void delay(const int ms);
void _delay_ms(const int ms);
void delayMicroseconds(unsigned long);
unsigned long millis();
+2 -7
View File
@@ -173,13 +173,8 @@ void MarlinHAL::init() {
// HAL idle task
void MarlinHAL::idletask() {
#if HAS_SHARED_MEDIA
// If Marlin is using the SD card we need to lock it to prevent access from
// a PC via USB.
// Other HALs use IS_SD_PRINTING() and IS_SD_FILE_OPEN() to check for access but
// this will not reliably detect delete operations. To be safe we will lock
// the disk if Marlin has it mounted. Unfortunately there is currently no way
// to unmount the disk from the LCD menu.
// if (IS_SD_PRINTING() || IS_SD_FILE_OPEN())
// When Marlin is using the SD Card it must be locked to prevent PC access via USB.
// For maximum safety we lock the disk if Marlin has it mounted for any reason.
if (card.isMounted())
MSC_Aquire_Lock();
else
@@ -36,11 +36,11 @@
* 16Kb I/O buffers (intended to hold DMA USB and Ethernet data, but currently
* unused).
*/
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(FLASH_EEPROM_EMULATION)
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_api.h"
extern "C" {
#include <lpc17xx_iap.h>
@@ -26,13 +26,13 @@
#ifdef TARGET_LPC1768
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(SDCARD_EEPROM_EMULATION)
//#define DEBUG_SD_EEPROM_EMULATION
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_api.h"
#include <chanfs/diskio.h>
#include <chanfs/ff.h>
@@ -52,7 +52,6 @@ bool eeprom_file_open = false;
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE - eeprom_exclude_size; }
bool PersistentStore::access_start() {
const char eeprom_erase_value = 0xFF;
MSC_Aquire_Lock();
if (f_mount(&fat_fs, "", 1)) {
MSC_Release_Lock();
@@ -65,6 +64,7 @@ bool PersistentStore::access_start() {
UINT bytes_written;
FSIZE_t file_size = f_size(&eeprom_file);
f_lseek(&eeprom_file, file_size);
const char eeprom_erase_value = 0xFF;
while (file_size < capacity() && res == FR_OK) {
res = f_write(&eeprom_file, &eeprom_erase_value, 1, &bytes_written);
file_size++;
@@ -21,7 +21,7 @@
*/
#ifdef TARGET_LPC1768
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
@@ -30,8 +30,8 @@
* with implementations supplied by the framework.
*/
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#define MARLIN_EEPROM_SIZE 0x8000 // 32K
+8 -4
View File
@@ -52,7 +52,9 @@ uint8_t _getc();
// ------------------------
#define CPU_32_BIT
#define SHARED_SERVOS HAS_SERVOS // Use shared/servos.cpp
class Servo;
typedef Servo hal_servo_t;
#define F_CPU 100000000
#define SystemCoreClock F_CPU
@@ -193,7 +195,7 @@ public:
static void isr_on() {}
static void isr_off() {}
static void delay_ms(const int ms) { _delay_ms(ms); }
static void delay_ms(const int ms) { delay(ms); }
// Tasks, called from idle()
static void idletask();
@@ -232,8 +234,10 @@ public:
* No option to invert the duty cycle [default = false]
* No option to change the scale of the provided value to enable finer PWM duty control [default = 255]
*/
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t=255, const bool=false) {
analogWrite(pin, v);
static void set_pwm_duty(const pin_t pin, const uint16_t v, const uint16_t v_size=255, const bool invert=false) {
auto value = map(v, 0, v_size, 0, UINT16_MAX);
value = invert ? UINT16_MAX - value : value;
analogWrite(pin, value);
}
static void set_pwm_frequency(const pin_t, int) {}
+104
View File
@@ -0,0 +1,104 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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 <https://www.gnu.org/licenses/>.
*
*/
#include "../platforms.h"
#ifdef __PLAT_NATIVE_SIM__
#include "../../inc/MarlinConfig.h"
#if HAS_SERVOS
#include "Servo.h"
//#define DEBUG_SERVOS
#define DEBUG_OUT ENABLED(DEBUG_SERVOS)
#include "../../../core/debug_out.h"
uint8_t ServoCount = 0; // the total number of attached servos
Servo::Servo() {
// Constructor stub
DEBUG_ECHOLNPGM("Debug Servo: constructor");
this->servoIndex = ServoCount++; // assign a servo index to this instance
}
uint8_t Servo::attach(int pin) {
// Attach stub
DEBUG_ECHOLNPGM("Debug Servo: attach to pin ", pin, " servo index ", this->servoIndex);
return attach(pin, MIN_PULSE_WIDTH, MAX_PULSE_WIDTH);
}
uint8_t Servo::attach(int pin, int min, int max) {
// Attach with min and max stub
DEBUG_ECHOLNPGM("Debug Servo: attach to pin ", pin, " with min ", min, " and max ", max);
if (pin > 0) servo_pin = pin;
return this->servoIndex;
}
void Servo::detach() {
// Detach stub
DEBUG_ECHOLNPGM("Debug Servo: detach");
}
// If value is < 200 it is treated as an angle, otherwise as pulse width in microseconds
void Servo::write(int value) {
if (value < MIN_PULSE_WIDTH) { // treat values less than 544 as angles in degrees (valid values in microseconds are handled as microseconds)
value = map(constrain(value, 0, 180), 0, 180, SERVO_MIN_US(min), SERVO_MAX_US(max));
}
writeMicroseconds(value);
DEBUG_ECHOLNPGM("Debug Servo: write ", value);
}
void Servo::writeMicroseconds(int value) {
// Simulate the servo movement
this->value = value;
hal.set_pwm_duty(pin_t(this->servo_pin), (float(value) / 20000) * UINT16_MAX, UINT16_MAX);
DEBUG_ECHOLNPGM("Debug Servo: write microseconds ", value);
}
int Servo::read() {
// Read stub
DEBUG_ECHOLNPGM("Debug Servo: read ", this->value);
return this->value;
}
int Servo::readMicroseconds() {
// Read microseconds stub
DEBUG_ECHOLNPGM("Debug Servo: read microseconds");
return 0;
}
bool Servo::attached() {
// Attached stub
DEBUG_ECHOLNPGM("Debug Servo: attached");
return false;
}
int Servo::move(const unsigned char cmd) {
// Move stub
DEBUG_ECHOLNPGM("Debug Servo: move ", cmd);
write(cmd);
return 0;
}
#endif // HAS_SERVOS
#endif // __PLAT_NATIVE_SIM__
+48
View File
@@ -0,0 +1,48 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
#define SERVO_MIN_US(v) (MIN_PULSE_WIDTH - (v) * 4) // minimum value in uS for this servo
#define SERVO_MAX_US(v) (MAX_PULSE_WIDTH - (v) * 4) // maximum value in uS for this servo
class Servo {
public:
Servo();
uint8_t attach(int pin); // Attach the given pin to the next free channel, set pinMode, return channel number or INVALID_SERVO if failure
uint8_t attach(int pin, int min, int max); // As above but also set min and max values for writes.
void detach();
void write(int value); // If value is < 200 it's treated as an angle, otherwise as pulse width in microseconds
void writeMicroseconds(int value); // Write pulse width in microseconds
int read(); // Return current pulse width as an angle between 0 and 180 degrees
int readMicroseconds(); // Return current pulse width in microseconds for this servo
bool attached(); // Return true if this servo is attached, otherwise false
int move (const unsigned char cmd);
private:
uint8_t servoIndex; // Index into the channel data for this servo
int8_t min; // Minimum is this value times 4 added to MIN_PULSE_WIDTH
int8_t max; // Maximum is this value times 4 added to MAX_PULSE_WIDTH
int value; // Pulse width in microseconds for this servo
int servo_pin = 0; // pin number for this servo
};
@@ -0,0 +1,30 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2025 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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
#error "ENDSTOP_INTERRUPTS_FEATURE is not supported in this simulation environment."
void setup_endstop_interrupts() {
// This function is a stub for setting up endstop interrupts.
// Since this is a simulation environment, actual hardware interrupts
// are not applicable. Add any necessary simulation-specific logic here.
}
-79
View File
@@ -1,79 +0,0 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2021 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 <https://www.gnu.org/licenses/>.
*
*/
#pragma once
/**
* servo.h - Interrupt driven Servo library for Arduino using 16 bit timers- Version 2
* Copyright (c) 2009 Michael Margolis. All right reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* Based on "servo.h - Interrupt driven Servo library for Arduino using 16 bit timers -
* Version 2 Copyright (c) 2009 Michael Margolis. All right reserved.
*
* The only modification was to update/delete macros to match the LPC176x.
*
*/
#include <stdint.h>
// Macros
//values in microseconds
#define MIN_PULSE_WIDTH 544 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2400 // the longest pulse sent to a servo
#define DEFAULT_PULSE_WIDTH 1500 // default pulse width when servo is attached
#define REFRESH_INTERVAL 20000 // minimum time to refresh servos in microseconds
#define MAX_SERVOS 4
#define INVALID_SERVO 255 // flag indicating an invalid servo index
// Types
typedef struct {
uint8_t nbr : 8 ; // a pin number from 0 to 254 (255 signals invalid pin)
uint8_t isActive : 1 ; // true if this channel is enabled, pin not pulsed if false
} ServoPin_t;
typedef struct {
ServoPin_t Pin;
unsigned int pulse_width; // pulse width in microseconds
} ServoInfo_t;
// Global variables
extern uint8_t ServoCount;
extern ServoInfo_t servo_info[MAX_SERVOS];
+2 -2
View File
@@ -77,7 +77,7 @@ void MarlinHAL::init() {
HAL_timer_init();
#if ENABLED(EMERGENCY_PARSER) && USBD_USE_CDC
#if ALL(EMERGENCY_PARSER, USBD_USE_CDC)
USB_Hook_init();
#endif
@@ -87,7 +87,7 @@ void MarlinHAL::init() {
#if PIN_EXISTS(USB_CONNECT)
OUT_WRITE(USB_CONNECT_PIN, !USB_CONNECT_INVERTING); // USB clear connection
delay_ms(1000); // Give OS time to notice
delay_ms(1000); // Give OS time to notice
WRITE(USB_CONNECT_PIN, USB_CONNECT_INVERTING);
#endif
}
+5 -5
View File
@@ -29,16 +29,16 @@
#include "arduino_extras.h"
#include "../../core/macros.h"
#include "../shared/Marduino.h"
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "fastio.h"
//#include "Servo.h"
#include "watchdog.h"
#include "../../inc/MarlinConfigPre.h"
#include <stdint.h>
#if HAS_SD_HOST_DRIVE
#include "msc_sd.h"
#endif
//
// Serial Ports
@@ -139,10 +139,10 @@ public:
static void isr_on() { __enable_irq(); }
static void isr_off() { __disable_irq(); }
static void delay_ms(const int ms) { ::delay(ms); }
static void delay_ms(const int ms) { delay(ms); }
// Tasks, called from idle()
static void idletask() {}
static void idletask() { TERN_(HAS_SD_HOST_DRIVE, tuh_task()); }
// Reset
static uint8_t get_reset_source();
-1
View File
@@ -29,7 +29,6 @@
#include "../shared/HAL_MinSerial.h"
static void TXBegin() {
#if !WITHIN(SERIAL_PORT, -1, 2)
#warning "Using POSTMORTEM_DEBUGGING requires a physical U(S)ART hardware in case of severe error."
@@ -19,15 +19,15 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../platforms.h"
#include "../../platforms.h"
#ifdef __PLAT_RP2040__
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(FLASH_EEPROM_EMULATION)
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_api.h"
// NOTE: The Bigtreetech SKR Pico has an onboard W25Q16 flash module
@@ -19,11 +19,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../platforms.h"
#include "../../platforms.h"
#ifdef __PLAT_RP2040__
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
@@ -32,8 +32,8 @@
* with simple implementations supplied by Marlin.
*/
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#define MARLIN_EEPROM_SIZE size_t(E2END + 1)
+1 -1
View File
@@ -21,7 +21,7 @@
*/
#pragma once
#if ALL(SDSUPPORT, USBD_USE_CDC_MSC) && DISABLED(NO_SD_HOST_DRIVE)
#if HAS_MEDIA && DISABLED(NO_SD_HOST_DRIVE)
#define HAS_SD_HOST_DRIVE 1
#endif
+58 -90
View File
@@ -27,109 +27,77 @@
#if HAS_SD_HOST_DRIVE
#include "../shared/Marduino.h"
#include "msc_sd.h"
#include "usbd_core.h"
#include "../../sd/cardreader.h"
#include <USB.h>
#include <USBMscHandler.h>
#include <tusb.h> // TinyUSB device stack
#define BLOCK_SIZE 512
#define PRODUCT_ID 0x29
#define SD_MULTIBLOCK_RETRY_CNT 1
class Sd2CardUSBMscHandler : public USBMscHandler {
public:
DiskIODriver* diskIODriver() {
#if HAS_MULTI_VOLUME
#if SHARED_VOLUME_IS(SD_ONBOARD)
return &card.media_driver_sdcard;
#elif SHARED_VOLUME_IS(USB_FLASH_DRIVE)
return &card.media_driver_usbFlash;
#endif
#else
return card.diskIODriver();
DiskIODriver* diskIODriver() {
#if HAS_MULTI_VOLUME
#if SHARED_VOLUME_IS(SD_ONBOARD)
return &card.media_driver_sdcard;
#elif SHARED_VOLUME_IS(USB_FLASH_DRIVE)
return &card.media_driver_usbFlash;
#endif
}
#else
return card.diskIODriver();
#endif
}
bool GetCapacity(uint32_t *pBlockNum, uint16_t *pBlockSize) {
*pBlockNum = diskIODriver()->cardSize();
*pBlockSize = BLOCK_SIZE;
return true;
}
/** Callbacks used by TinyUSB MSC **/
bool Write(uint8_t *pBuf, uint32_t blkAddr, uint16_t blkLen) {
auto sd2card = diskIODriver();
// single block
if (blkLen == 1) {
watchdog_refresh();
sd2card->writeBlock(blkAddr, pBuf);
return true;
extern "C" {
bool tud_msc_ready_cb(uint8_t lun) {
return diskIODriver()->isReady();
}
int32_t tud_msc_read10_cb(uint8_t lun, uint32_t lba, void* buffer, uint32_t bufsize) {
const uint32_t blocks = bufsize / BLOCK_SIZE;
for (uint16_t rcount = SD_MULTIBLOCK_RETRY_CNT; rcount--; ) {
if (diskIODriver()->readBlocks(lba, (uint8_t*)buffer, blocks))
return bufsize; // Success
}
return -1; // Failure after retries
}
int32_t tud_msc_write10_cb(uint8_t lun, uint32_t lba, uint8_t const* buffer, uint32_t bufsize) {
const uint32_t blocks = bufsize / BLOCK_SIZE;
for (uint16_t rcount = SD_MULTIBLOCK_RETRY_CNT; rcount--; ) {
if (diskIODriver()->writeBlocks(lba, buffer, blocks))
return bufsize; // Success
}
return -1; // Failure after retries
}
void tud_msc_inquiry_cb(uint8_t lun, uint8_t vendor_id[8], uint8_t product_id[16], uint8_t product_rev[4]) {
memcpy(vendor_id, "MARLIN ", 8);
memcpy(product_id, "Product ", 16);
memcpy(product_rev, "0.01", 4);
}
void tud_msc_capacity_cb(uint8_t lun, uint32_t* block_count, uint16_t* block_size) {
*block_count = diskIODriver()->cardSize();
*block_size = BLOCK_SIZE;
}
void tud_msc_start_stop_cb(uint8_t lun, uint8_t power_condition, bool start, bool load_eject) {
if (load_eject) {
if (start) {
// Handle media load
} else {
// Handle media eject
}
// multi block optimization
sd2card->writeStart(blkAddr, blkLen);
while (blkLen--) {
watchdog_refresh();
sd2card->writeData(pBuf);
pBuf += BLOCK_SIZE;
}
sd2card->writeStop();
return true;
}
}
bool Read(uint8_t *pBuf, uint32_t blkAddr, uint16_t blkLen) {
auto sd2card = diskIODriver();
// single block
if (blkLen == 1) {
watchdog_refresh();
sd2card->readBlock(blkAddr, pBuf);
return true;
}
// multi block optimization
sd2card->readStart(blkAddr);
while (blkLen--) {
watchdog_refresh();
sd2card->readData(pBuf);
pBuf += BLOCK_SIZE;
}
sd2card->readStop();
return true;
}
bool IsReady() {
return diskIODriver()->isReady();
}
};
Sd2CardUSBMscHandler usbMscHandler;
/* USB Mass storage Standard Inquiry Data */
uint8_t Marlin_STORAGE_Inquirydata[] = { /* 36 */
/* LUN 0 */
0x00,
0x80,
0x02,
0x02,
(STANDARD_INQUIRY_DATA_LEN - 5),
0x00,
0x00,
0x00,
'M', 'A', 'R', 'L', 'I', 'N', ' ', ' ', /* Manufacturer : 8 bytes */
'P', 'r', 'o', 'd', 'u', 'c', 't', ' ', /* Product : 16 Bytes */
' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',
'0', '.', '0', '1', /* Version : 4 Bytes */
};
USBMscHandler *pSingleMscHandler = &usbMscHandler;
} // extern "C"
void MSC_SD_init() {
USBDevice.end();
delay(200);
USBDevice.registerMscHandlers(1, &pSingleMscHandler, Marlin_STORAGE_Inquirydata);
USBDevice.begin();
tusb_init();
// Add USB reinitialization logic if needed
}
#endif // HAS_SD_HOST_DRIVE
@@ -24,7 +24,7 @@
* SAMD21 HAL developed by Bart Meijer (brupje)
* Based on SAMD51 HAL by Giuliano Zaro (AKA GMagician)
*/
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(QSPI_EEPROM)
@@ -26,7 +26,7 @@
*/
#ifdef __SAMD21__
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(FLASH_EEPROM_EMULATION)
@@ -35,7 +35,7 @@
/* reserve flash memory */
static const uint8_t flashdata[TOTAL_FLASH_SIZE] __attribute__((__aligned__(256))) { }; \
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_api.h"
size_t PersistentStore::capacity() { return MARLIN_EEPROM_SIZE - eeprom_exclude_size; }
@@ -26,13 +26,13 @@
*/
#ifdef __SAMD21__
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(QSPI_EEPROM)
#error "QSPI_EEPROM emulation Not implemented on SAMD21"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_api.h"
#include "QSPIFlash.h"
@@ -26,7 +26,7 @@
*/
#ifdef __SAMD21__
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
@@ -36,8 +36,8 @@
* with simple implementations supplied by Marlin.
*/
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#error "MARLIN_EEPROM_SIZE is required for I2C / SPI EEPROM."
@@ -20,7 +20,7 @@
*
*/
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(QSPI_EEPROM)
@@ -25,11 +25,11 @@
*/
#ifdef __SAMD51__
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(FLASH_EEPROM_EMULATION)
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_api.h"
#define NVMCTRL_CMD(c) do{ \
SYNC(!NVMCTRL->STATUS.bit.READY); \
@@ -25,11 +25,11 @@
*/
#ifdef __SAMD51__
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(QSPI_EEPROM)
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_api.h"
#include "QSPIFlash.h"
@@ -25,7 +25,7 @@
*/
#ifdef __SAMD51__
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
@@ -34,8 +34,8 @@
* with simple implementations supplied by Marlin.
*/
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#error "MARLIN_EEPROM_SIZE is required for I2C / SPI EEPROM."
+4 -4
View File
@@ -43,8 +43,8 @@
#endif
#if HAS_SD_HOST_DRIVE
#include "msc_sd.h"
#include "usbd_cdc_if.h"
#include "sd/msc_sd.h"
#include <usbd_cdc_if.h>
#endif
// ------------------------
@@ -87,7 +87,7 @@ void MarlinHAL::init() {
SetTimerInterruptPriorities();
#if ENABLED(EMERGENCY_PARSER) && (USBD_USE_CDC || USBD_USE_CDC_MSC)
#if ENABLED(EMERGENCY_PARSER) && ANY(USBD_USE_CDC, USBD_USE_CDC_MSC)
USB_Hook_init();
#endif
@@ -97,7 +97,7 @@ void MarlinHAL::init() {
#if PIN_EXISTS(USB_CONNECT)
OUT_WRITE(USB_CONNECT_PIN, !USB_CONNECT_INVERTING); // USB clear connection
delay(1000); // Give OS time to notice
delay_ms(1000); // Give OS time to notice
WRITE(USB_CONNECT_PIN, USB_CONNECT_INVERTING);
#endif
}
+2 -6
View File
@@ -23,18 +23,14 @@
#define CPU_32_BIT
#include "../../core/macros.h"
#include "../shared/Marduino.h"
#include "../../inc/MarlinConfigPre.h"
#include "../shared/math_32bit.h"
#include "../shared/HAL_SPI.h"
#include "temp_soc.h"
#include "fastio.h"
#include "Servo.h"
#include "../../inc/MarlinConfigPre.h"
#include <stdint.h>
//
// Default graphical display delays
//
@@ -20,7 +20,7 @@
*
*/
#include "../platforms.h"
#include "../../platforms.h"
#ifdef HAL_STM32
@@ -29,12 +29,12 @@
* with simple implementations supplied by Marlin.
*/
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(IIC_BL24CXX_EEPROM)
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
//
// PersistentStore
@@ -19,15 +19,15 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../platforms.h"
#include "../../platforms.h"
#ifdef HAL_STM32
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(FLASH_EEPROM_EMULATION)
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_api.h"
// Better: "utility/stm32_eeprom.h", but only after updating stm32duino to 2.0.0
// Use EEPROM.h for compatibility, for now.
@@ -50,10 +50,10 @@
#if ENABLED(FLASH_EEPROM_LEVELING)
#include "stm32_def.h"
#include <stm32_def.h>
#define DEBUG_OUT ENABLED(EEPROM_CHITCHAT)
#include "../../core/debug_out.h"
#include "../../../core/debug_out.h"
#ifndef MARLIN_EEPROM_SIZE
#define MARLIN_EEPROM_SIZE 0x1000 // 4KB
@@ -20,7 +20,7 @@
*
*/
#include "../platforms.h"
#include "../../platforms.h"
#ifdef HAL_STM32
@@ -29,12 +29,12 @@
* Enable USE_SHARED_EEPROM if not supplied by the framework.
*/
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(IIC_BL24CXX_EEPROM)
#include "../../libs/BL24CXX.h"
#include "../shared/eeprom_if.h"
#include "../../../libs/BL24CXX.h"
#include "../../shared/eeprom_if.h"
void eeprom_init() { BL24CXX::init(); }
@@ -20,7 +20,7 @@
*
*/
#include "../platforms.h"
#include "../../platforms.h"
#ifdef HAL_STM32
@@ -28,12 +28,12 @@
* Implementation of EEPROM settings in SD Card
*/
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(SDCARD_EEPROM_EMULATION)
#include "../shared/eeprom_api.h"
#include "../../sd/cardreader.h"
#include "../../shared/eeprom_api.h"
#include "../../../sd/cardreader.h"
#define EEPROM_FILENAME "eeprom.dat"
@@ -19,16 +19,16 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../platforms.h"
#include "../../platforms.h"
#ifdef HAL_STM32
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(SRAM_EEPROM_EMULATION)
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#define MARLIN_EEPROM_SIZE 0x1000 // 4KB
@@ -19,11 +19,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../platforms.h"
#include "../../platforms.h"
#ifdef HAL_STM32
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
@@ -32,8 +32,8 @@
* with simple implementations supplied by Marlin.
*/
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#define MARLIN_EEPROM_SIZE size_t(E2END + 1)
@@ -20,20 +20,19 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "../platforms.h"
#include "../../platforms.h"
#ifdef HAL_STM32
#include "../../inc/MarlinConfigPre.h"
#include "../../../inc/MarlinConfigPre.h"
#if HAS_SD_HOST_DRIVE
#include "../shared/Marduino.h"
#include "../../../sd/cardreader.h"
#include "msc_sd.h"
#include "usbd_core.h"
#include "../../sd/cardreader.h"
#include <usbd_core.h>
#include <USB.h>
#include <USBMscHandler.h>
@@ -49,6 +48,7 @@
class Sd2CardUSBMscHandler : public USBMscHandler {
public:
DiskIODriver* diskIODriver() {
// TODO: Explore a variable shared volume, or auto share the un-mounted volume(s)
#if HAS_MULTI_VOLUME
#if SHARED_VOLUME_IS(SD_ONBOARD)
return &card.media_driver_sdcard;
@@ -20,18 +20,17 @@
*
*/
#include "../platforms.h"
#include "../../platforms.h"
#ifdef HAL_STM32
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ALL(USE_OTG_USB_HOST, USBHOST)
#include "usb_host.h"
#include "../shared/Marduino.h"
#include "usbh_core.h"
#include "usbh_msc.h"
#include <usbh_core.h>
#include <usbh_msc.h>
USBH_HandleTypeDef hUsbHost;
USBHost usb;
+2 -2
View File
@@ -26,7 +26,7 @@
#include "../../inc/MarlinConfigPre.h"
#if ENABLED(EMERGENCY_PARSER) && (USBD_USE_CDC || USBD_USE_CDC_MSC)
#if ENABLED(EMERGENCY_PARSER) && ANY(USBD_USE_CDC, USBD_USE_CDC_MSC)
#include "usb_serial.h"
#include "../../feature/e_parser.h"
@@ -56,5 +56,5 @@ void USB_Hook_init() {
USBD_CDC_fops.Receive = USBD_CDC_Receive_hook;
}
#endif // EMERGENCY_PARSER && USBD_USE_CDC
#endif // EMERGENCY_PARSER && (USBD_USE_CDC || USBD_USE_CDC_MSC)
#endif // HAL_STM32
+4 -3
View File
@@ -65,7 +65,8 @@ uint16_t adc_results[ADC_COUNT];
emergency_parser.update(MSerial0.emergency_state, buf[i + total - len]);
}
#endif
#endif
#endif // SERIAL_USB && !HAS_SD_HOST_DRIVE
// ------------------------
// Watchdog Timer
@@ -252,7 +253,7 @@ void MarlinHAL::init() {
#endif
#if PIN_EXISTS(USB_CONNECT)
OUT_WRITE(USB_CONNECT_PIN, !USB_CONNECT_INVERTING); // USB clear connection
delay(1000); // Give OS time to notice
delay_ms(1000); // Give OS time to notice
WRITE(USB_CONNECT_PIN, USB_CONNECT_INVERTING);
#endif
TERN_(POSTMORTEM_DEBUGGING, install_min_serial()); // Install the minimal serial handler
@@ -264,7 +265,7 @@ void MarlinHAL::idletask() {
/**
* When Marlin is using the SD card it should be locked to prevent it being
* accessed from a PC over USB.
* Other HALs use (IS_SD_PRINTING() || IS_SD_FILE_OPEN()) to check for access
* Other HALs use (card.isStillPrinting() || card.isFileOpen()) to check for access
* but this won't reliably detect other file operations. To be safe we just lock
* the drive whenever Marlin has it mounted. LCDs should include an Unmount
* command so drives can be released as needed.
+1 -1
View File
@@ -40,7 +40,7 @@
#include "../../inc/MarlinConfigPre.h"
#if HAS_SD_HOST_DRIVE
#include "msc_sd.h"
#include "sd/msc_sd.h"
#endif
// ------------------------
@@ -26,12 +26,12 @@
* with simple implementations supplied by Marlin.
*/
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(IIC_BL24CXX_EEPROM)
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
//
// PersistentStore
@@ -28,11 +28,11 @@
#ifdef __STM32F1__
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(FLASH_EEPROM_EMULATION)
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_api.h"
#include <flash_stm32.h>
#include <EEPROM.h>
@@ -27,12 +27,12 @@
#ifdef __STM32F1__
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(IIC_BL24CXX_EEPROM)
#include "../../libs/BL24CXX.h"
#include "../shared/eeprom_if.h"
#include "../../../libs/BL24CXX.h"
#include "../../shared/eeprom_if.h"
void eeprom_init() { BL24CXX::init(); }
@@ -27,12 +27,12 @@
#ifdef __STM32F1__
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if ENABLED(SDCARD_EEPROM_EMULATION)
#include "../shared/eeprom_api.h"
#include "../../sd/cardreader.h"
#include "../../shared/eeprom_api.h"
#include "../../../sd/cardreader.h"
#define EEPROM_FILENAME "eeprom.dat"
@@ -26,12 +26,12 @@
#ifdef __STM32F1__
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if USE_WIRED_EEPROM
#include "../shared/eeprom_if.h"
#include "../shared/eeprom_api.h"
#include "../../shared/eeprom_if.h"
#include "../../shared/eeprom_api.h"
#ifndef MARLIN_EEPROM_SIZE
#error "MARLIN_EEPROM_SIZE is required for I2C / SPI EEPROM."
@@ -22,20 +22,21 @@
*/
#ifdef __STM32F1__
#include "../../inc/MarlinConfigPre.h"
#include "../../../inc/MarlinConfigPre.h"
#if HAS_SD_HOST_DRIVE
#include "msc_sd.h"
#include "SPI.h"
#include "usb_reg_map.h"
#include "../SPI.h"
#include <usb_reg_map.h>
#define PRODUCT_ID 0x29
USBMassStorage MarlinMSC;
Serial1Class<USBCompositeSerial> MarlinCompositeSerial(true);
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if SD_CONNECTION_IS(ONBOARD)
@@ -24,8 +24,8 @@
#include <USBComposite.h>
#include "../../inc/MarlinConfigPre.h"
#include "../../core/serial_hook.h"
#include "../../../inc/MarlinConfigPre.h"
#include "../../../core/serial_hook.h"
extern USBMassStorage MarlinMSC;
extern Serial1Class<USBCompositeSerial> MarlinCompositeSerial;
@@ -13,13 +13,13 @@
#ifdef __STM32F1__
#include "../../inc/MarlinConfig.h"
#include "../../../inc/MarlinConfig.h"
#if SD_CONNECTION_IS(ONBOARD)
#include "onboard_sd.h"
#include "SPI.h"
#include "fastio.h"
#include "../SPI.h"
#include "../fastio.h"
#ifndef ONBOARD_SPI_DEVICE
#define ONBOARD_SPI_DEVICE SPI_DEVICE
@@ -19,11 +19,11 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifdef ARDUINO_ARCH_STM32F1
#ifdef __STM32F1__
#include <libmaple/stm32.h>
#include "../../inc/MarlinConfig.h" // Allow pins/pins.h to set density
#include "../../../inc/MarlinConfig.h" // Allow pins/pins.h to set density
#if ANY(STM32_HIGH_DENSITY, STM32_XL_DENSITY)
@@ -308,4 +308,4 @@ bool SDIO_GetCmdResp7() {
}
#endif // STM32_HIGH_DENSITY || STM32_XL_DENSITY
#endif // ARDUINO_ARCH_STM32F1
#endif // __STM32F1__

Some files were not shown because too many files have changed in this diff Show More