Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

USB Flash Drive support using native USB Host + MSC #20571

Merged
13 changes: 10 additions & 3 deletions Marlin/Configuration_adv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1323,9 +1323,6 @@
*/
//#define USB_FLASH_DRIVE_SUPPORT
#if ENABLED(USB_FLASH_DRIVE_SUPPORT)
#define USB_CS_PIN SDSS
#define USB_INTR_PIN SD_DETECT_PIN

/**
* USB Host Shield Library
*
Expand All @@ -1337,6 +1334,16 @@
* [1] This requires USB_INTR_PIN to be interrupt-capable.
*/
//#define USE_UHS3_USB

/**
* Native USB Host supported by some boards (USB OTG)
*/
//#define USE_OTG_USB_HOST

#if DISABLED(USE_OTG_USB_HOST)
#define USB_CS_PIN SDSS
#define USB_INTR_PIN SD_DETECT_PIN
#endif
#endif

/**
Expand Down
117 changes: 117 additions & 0 deletions Marlin/src/HAL/STM32/usb_host.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 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/>.
*
*/

#if defined(ARDUINO_ARCH_STM32) && !defined(STM32GENERIC)

#include "../../inc/MarlinConfig.h"

#if BOTH(USE_OTG_USB_HOST, USBHOST)

#include "usb_host.h"
#include "../shared/Marduino.h"
#include "usbh_core.h"
#include "usbh_msc.h"

USBH_HandleTypeDef hUsbHost;
USBHost usb;
BulkStorage bulk(&usb);

static void USBH_UserProcess(USBH_HandleTypeDef *phost, uint8_t id) {
switch(id) {
case HOST_USER_SELECT_CONFIGURATION:
//SERIAL_ECHOLN("APPLICATION_SELECT_CONFIGURATION");
break;
case HOST_USER_DISCONNECTION:
// SERIAL_ECHOLN("APPLICATION_DISCONNECT");
// usb.setUsbTaskState(USB_STATE_RUNNING);
break;
case HOST_USER_CLASS_ACTIVE:
// SERIAL_ECHOLN("APPLICATION_READY");
usb.setUsbTaskState(USB_STATE_RUNNING);
break;
case HOST_USER_CONNECTION:
break;
default:
break;
}
}

bool USBHost::start() {
if (USBH_Init(&hUsbHost, USBH_UserProcess, TERN(USE_USB_HS_IN_FS, HOST_HS, HOST_FS)) != USBH_OK) {
SERIAL_ECHOLN("Error: USBH_Init");
return false;
}
if (USBH_RegisterClass(&hUsbHost, USBH_MSC_CLASS) != USBH_OK) {
SERIAL_ECHOLN("Error: USBH_RegisterClass");
return false;
}
if (USBH_Start(&hUsbHost) != USBH_OK) {
SERIAL_ECHOLN("Error: USBH_Start");
return false;
}
return true;
}

void USBHost::Task() {
USBH_Process(&hUsbHost);
}

uint8_t USBHost::getUsbTaskState() {
return usb_task_state;
}

void USBHost::setUsbTaskState(uint8_t state) {
usb_task_state = state;
if (usb_task_state == USB_STATE_RUNNING) {
MSC_LUNTypeDef info;
USBH_MSC_GetLUNInfo(&hUsbHost, usb.lun, &info);
capacity = info.capacity.block_nbr / 2000;
block_size = info.capacity.block_size;
block_count = info.capacity.block_nbr;
// SERIAL_ECHOLNPAIR("info.capacity.block_nbr : %ld\n", info.capacity.block_nbr);
// SERIAL_ECHOLNPAIR("info.capacity.block_size: %d\n", info.capacity.block_size);
// SERIAL_ECHOLNPAIR("capacity : %d MB\n", capacity);
}
};

bool BulkStorage::LUNIsGood(uint8_t t) {
return USBH_MSC_IsReady(&hUsbHost) && USBH_MSC_UnitIsReady(&hUsbHost, t);
}

uint32_t BulkStorage::GetCapacity(uint8_t lun) {
return usb->block_count;
}

uint16_t BulkStorage::GetSectorSize(uint8_t lun) {
return usb->block_size;
}

uint8_t BulkStorage::Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf) {
return USBH_MSC_Read(&hUsbHost, lun, addr, buf, blocks) != USBH_OK;
}

uint8_t BulkStorage::Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf) {
return USBH_MSC_Write(&hUsbHost, lun, addr, const_cast <uint8_t*>(buf), blocks) != USBH_OK;
}

#endif // BOTH(USE_OTG_USB_HOST, USBHOST)
#endif // ARDUINO_ARCH_STM32 && !STM32GENERIC
60 changes: 60 additions & 0 deletions Marlin/src/HAL/STM32/usb_host.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* Marlin 3D Printer Firmware
* Copyright (c) 2020 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

#include <stdint.h>

typedef enum {
USB_STATE_INIT,
USB_STATE_ERROR,
USB_STATE_RUNNING,
} usb_state_t;

class USBHost {
public:
bool start();
void Task();
uint8_t getUsbTaskState();
void setUsbTaskState(uint8_t state);
uint8_t regRd(uint8_t reg) { return 0x0; };
uint8_t usb_task_state = USB_STATE_INIT;
uint8_t lun = 0;
uint32_t capacity = 0;
uint16_t block_size = 0;
uint32_t block_count = 0;
};

class BulkStorage {
public:
BulkStorage(USBHost *usb) : usb(usb) {};

bool LUNIsGood(uint8_t t);
uint32_t GetCapacity(uint8_t lun);
uint16_t GetSectorSize(uint8_t lun);
uint8_t Read(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, uint8_t *buf);
uint8_t Write(uint8_t lun, uint32_t addr, uint16_t bsize, uint8_t blocks, const uint8_t * buf);

USBHost *usb;
};

extern USBHost usb;
extern BulkStorage bulk;
6 changes: 5 additions & 1 deletion Marlin/src/inc/SanityCheck.h
Original file line number Diff line number Diff line change
Expand Up @@ -2913,10 +2913,14 @@ static_assert( _ARR_TEST(3,0) && _ARR_TEST(3,1) && _ARR_TEST(3,2)
#error "PRINTCOUNTER requires EEPROM_SETTINGS."
#endif

#if ENABLED(USB_FLASH_DRIVE_SUPPORT) && !PINS_EXIST(USB_CS, USB_INTR)
#if ENABLED(USB_FLASH_DRIVE_SUPPORT) && !PINS_EXIST(USB_CS, USB_INTR) && DISABLED(USE_OTG_USB_HOST)
#error "USB_CS_PIN and USB_INTR_PIN are required for USB_FLASH_DRIVE_SUPPORT."
#endif

#if ENABLED(USE_OTG_USB_HOST) && !defined(HAS_OTG_USB_HOST_SUPPORT)
#error "The current board does not support USE_OTG_USB_HOST."
#endif

#if ENABLED(SD_FIRMWARE_UPDATE) && !defined(__AVR_ATmega2560__)
#error "SD_FIRMWARE_UPDATE requires an ATmega2560-based (Arduino Mega) board."
#endif
Expand Down
2 changes: 2 additions & 0 deletions Marlin/src/pins/stm32f4/pins_BTT_GTR_V1_0.h
Original file line number Diff line number Diff line change
Expand Up @@ -453,3 +453,5 @@
#endif // HAS_WIRED_LCD

#undef TP

#define HAS_OTG_USB_HOST_SUPPORT
2 changes: 2 additions & 0 deletions Marlin/src/pins/stm32f4/pins_BTT_SKR_PRO_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -469,3 +469,5 @@
#define ESP_WIFI_MODULE_ENABLE_PIN PG1
#define ESP_WIFI_MODULE_GPIO0_PIN PF14
#define ESP_WIFI_MODULE_GPIO2_PIN PF15

#define HAS_OTG_USB_HOST_SUPPORT
2 changes: 2 additions & 0 deletions Marlin/src/pins/stm32f4/pins_MKS_ROBIN_PRO_V2.h
Original file line number Diff line number Diff line change
Expand Up @@ -362,3 +362,5 @@

#endif // !MKS_MINI_12864
#endif // HAS_SPI_LCD

#define HAS_OTG_USB_HOST_SUPPORT
19 changes: 16 additions & 3 deletions Marlin/src/sd/usb_flashdrive/Sd2Card_FlashDrive.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,10 @@
#include "../../core/serial.h"
#include "../../module/temperature.h"

static_assert(USB_CS_PIN != -1, "USB_CS_PIN must be defined");
static_assert(USB_INTR_PIN != -1, "USB_INTR_PIN must be defined");
#if DISABLED(USE_OTG_USB_HOST)
static_assert(USB_CS_PIN != -1, "USB_CS_PIN must be defined");
static_assert(USB_INTR_PIN != -1, "USB_INTR_PIN must be defined");
#endif

#if ENABLED(USE_UHS3_USB)
#define NO_AUTO_SPEED
Expand Down Expand Up @@ -81,6 +83,17 @@ static_assert(USB_INTR_PIN != -1, "USB_INTR_PIN must be defined");

#define UHS_START (usb.Init() == 0)
#define UHS_STATE(state) UHS_USB_HOST_STATE_##state
#elif ENABLED(USE_OTG_USB_HOST)

#if HAS_SD_HOST_DRIVE
#include HAL_PATH(../../HAL, msc_sd.h)
#endif

#include HAL_PATH(../../HAL, usb_host.h)

#define UHS_START usb.start()
#define rREVISION 0
#define UHS_STATE(state) USB_STATE_##state
#else
#include "lib-uhs2/Usb.h"
#include "lib-uhs2/masstorage.h"
Expand Down Expand Up @@ -250,7 +263,7 @@ bool Sd2Card::isInserted() {
return state == MEDIA_READY;
}

bool Sd2Card::ready() {
bool Sd2Card::isReady() {
return state > DO_STARTUP;
}

Expand Down
41 changes: 22 additions & 19 deletions Marlin/src/sd/usb_flashdrive/Sd2Card_FlashDrive.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,26 +23,27 @@

/**
* \file
* \brief Sd2Card class for V2 SD/SDHC cards
* \brief Sd2Card class for USB Flash Drive
*/

#include "../SdFatConfig.h"
#include "../SdInfo.h"

/**
* Define SOFTWARE_SPI to use bit-bang SPI
*/
#if EITHER(MEGA_SOFT_SPI, USE_SOFTWARE_SPI)
#define SOFTWARE_SPI
#endif
#if DISABLED(USE_OTG_USB_HOST)
/**
* Define SOFTWARE_SPI to use bit-bang SPI
*/
#if EITHER(MEGA_SOFT_SPI, USE_SOFTWARE_SPI)
#define SOFTWARE_SPI
#endif

// SPI pin definitions - do not edit here - change in SdFatConfig.h
#if ENABLED(SOFTWARE_SPI)
#warning "Auto-assigning '10' as the SD_CHIP_SELECT_PIN."
#define SD_CHIP_SELECT_PIN 10 // Software SPI chip select pin for the SD
#else
// hardware pin defs
#define SD_CHIP_SELECT_PIN SS_PIN // The default chip select pin for the SD card is SS.
// SPI pin definitions - do not edit here - change in SdFatConfig.h
#if ENABLED(SOFTWARE_SPI)
#warning "Auto-assigning '10' as the SD_CHIP_SELECT_PIN."
#define SD_CHIP_SELECT_PIN 10 // Software SPI chip select pin for the SD
#else
// hardware pin defs
#define SD_CHIP_SELECT_PIN SS_PIN // The default chip select pin for the SD card is SS.
#endif
#endif

class Sd2Card {
Expand All @@ -54,22 +55,24 @@ class Sd2Card {
public:
static bool usbStartup();

bool init(const uint8_t sckRateID=0, const pin_t chipSelectPin=SD_CHIP_SELECT_PIN);
bool init(const uint8_t sckRateID=0, const pin_t chipSelectPin=TERN(USE_OTG_USB_HOST, 0, SD_CHIP_SELECT_PIN));

static void idle();

inline bool readStart(const uint32_t block) { pos = block; return ready(); }
inline bool readStart(const uint32_t block) { pos = block; return isReady(); }
inline bool readData(uint8_t* dst) { return readBlock(pos++, dst); }
inline bool readStop() const { return true; }

inline bool writeStart(const uint32_t block, const uint32_t) { pos = block; return ready(); }
inline bool writeStart(const uint32_t block, const uint32_t) { pos = block; return isReady(); }
inline bool writeData(uint8_t* src) { return writeBlock(pos++, src); }
inline bool writeStop() const { return true; }

bool readBlock(uint32_t block, uint8_t* dst);
bool writeBlock(uint32_t blockNumber, const uint8_t* src);

bool readCSD(csd_t* csd) { return true; };

uint32_t cardSize();
static bool isInserted();
static bool ready();
bool isReady();
};
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
#undef HAL_IRDA_MODULE_ENABLED
#undef HAL_SMARTCARD_MODULE_ENABLED
#undef HAL_WWDG_MODULE_ENABLED
#undef HAL_HCD_MODULE_ENABLED
// #undef HAL_HCD_MODULE_ENABLED
#undef HAL_FMPI2C_MODULE_ENABLED
#undef HAL_SPDIFRX_MODULE_ENABLED
#undef HAL_DFSDM_MODULE_ENABLED
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
#undef HAL_IRDA_MODULE_ENABLED
#undef HAL_SMARTCARD_MODULE_ENABLED
#undef HAL_WWDG_MODULE_ENABLED
#undef HAL_HCD_MODULE_ENABLED
// #undef HAL_HCD_MODULE_ENABLED
#undef HAL_FMPI2C_MODULE_ENABLED
#undef HAL_SPDIFRX_MODULE_ENABLED
#undef HAL_DFSDM_MODULE_ENABLED
Expand Down
Loading