From dbea6f0022dcb805e4b57c8f5b8dc6dce5820344 Mon Sep 17 00:00:00 2001 From: Scott Lahteine Date: Sun, 8 Sep 2019 02:27:23 -0500 Subject: [PATCH] STM32F1 USB cdc/msc composite device (#15180) Co-Authored-By: bigtreetech <38851044+bigtreetech@users.noreply.github.com> --- Marlin/src/HAL/HAL_STM32F1/HAL.cpp | 23 +- Marlin/src/HAL/HAL_STM32F1/HAL.h | 17 +- .../maple_win_usb_driver/maple_serial.inf | 56 ++ Marlin/src/HAL/HAL_STM32F1/msc_sd.cpp | 64 ++ Marlin/src/HAL/HAL_STM32F1/msc_sd.h | 24 + Marlin/src/HAL/HAL_STM32F1/onboard_sd.cpp | 558 ++++++++++++++++++ Marlin/src/HAL/HAL_STM32F1/onboard_sd.h | 96 +++ .../lulzbot/ftdi_eve_lib/basic/commands.cpp | 6 +- .../src/pins/stm32/pins_BIGTREE_SKR_E3_DIP.h | 12 + .../src/pins/stm32/pins_BIGTREE_SKR_MINI_E3.h | 12 + .../pins/stm32/pins_BIGTREE_SKR_MINI_V1_1.h | 16 +- .../lib-uhs3/UHS_host/UHS_USB_IDs.h | 2 +- platformio.ini | 2 +- 13 files changed, 872 insertions(+), 16 deletions(-) create mode 100644 Marlin/src/HAL/HAL_STM32F1/maple_win_usb_driver/maple_serial.inf create mode 100644 Marlin/src/HAL/HAL_STM32F1/msc_sd.cpp create mode 100644 Marlin/src/HAL/HAL_STM32F1/msc_sd.h create mode 100644 Marlin/src/HAL/HAL_STM32F1/onboard_sd.cpp create mode 100644 Marlin/src/HAL/HAL_STM32F1/onboard_sd.h diff --git a/Marlin/src/HAL/HAL_STM32F1/HAL.cpp b/Marlin/src/HAL/HAL_STM32F1/HAL.cpp index 3dbcfa76aa..f3d0168342 100644 --- a/Marlin/src/HAL/HAL_STM32F1/HAL.cpp +++ b/Marlin/src/HAL/HAL_STM32F1/HAL.cpp @@ -82,7 +82,7 @@ // Public Variables // ------------------------ -#ifdef SERIAL_USB +#if (!defined(SERIAL_USB) && !defined(USE_USB_COMPOSITE)) USBSerial SerialUSB; #endif @@ -215,6 +215,9 @@ void HAL_init(void) { #if PIN_EXISTS(LED) OUT_WRITE(LED_PIN, LOW); #endif + #ifdef USE_USB_COMPOSITE + MSC_SD_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 @@ -222,6 +225,24 @@ void HAL_init(void) { #endif } +// HAL idle task +void HAL_idletask(void) { + #ifdef USE_USB_COMPOSITE + #if ENABLED(SHARED_SD_CARD) + // 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. Unfortuately there is currently no way + // to unmount the disk from the LCD menu. + // if (IS_SD_PRINTING() || IS_SD_FILE_OPEN()) + /* copy from lpc1768 framework, should be fixed later for process SHARED_SD_CARD*/ + #endif + // process USB mass storage device class loop + MarlinMSC.loop(); + #endif +} + /* VGPV Done with defines // disable interrupts void cli(void) { noInterrupts(); } diff --git a/Marlin/src/HAL/HAL_STM32F1/HAL.h b/Marlin/src/HAL/HAL_STM32F1/HAL.h index 08c79bc6de..c096fb0831 100644 --- a/Marlin/src/HAL/HAL_STM32F1/HAL.h +++ b/Marlin/src/HAL/HAL_STM32F1/HAL.h @@ -42,21 +42,30 @@ #include #include "../../inc/MarlinConfigPre.h" +#include "msc_sd.h" // ------------------------ // Defines // ------------------------ #ifdef SERIAL_USB - #define UsbSerial Serial + #ifndef USE_USB_COMPOSITE + #define UsbSerial Serial + #else + #define UsbSerial MarlinCompositeSerial + #endif #define MSerial1 Serial1 #define MSerial2 Serial2 #define MSerial3 Serial3 #define MSerial4 Serial4 #define MSerial5 Serial5 #else - extern USBSerial SerialUSB; - #define UsbSerial SerialUSB + #ifndef USE_USB_COMPOSITE + extern USBSerial SerialUSB; + #define UsbSerial SerialUSB + #else + #define UsbSerial MarlinCompositeSerial + #endif #define MSerial1 Serial #define MSerial2 Serial1 #define MSerial3 Serial2 @@ -111,6 +120,8 @@ // Set interrupt grouping for this MCU void HAL_init(void); +#define HAL_IDLETASK 1 +void HAL_idletask(void); /** * TODO: review this to return 1 for pins that are not analog input diff --git a/Marlin/src/HAL/HAL_STM32F1/maple_win_usb_driver/maple_serial.inf b/Marlin/src/HAL/HAL_STM32F1/maple_win_usb_driver/maple_serial.inf new file mode 100644 index 0000000000..c39f4ce0ed --- /dev/null +++ b/Marlin/src/HAL/HAL_STM32F1/maple_win_usb_driver/maple_serial.inf @@ -0,0 +1,56 @@ +; +; STMicroelectronics Communication Device Class driver installation file +; (C)2006 Copyright STMicroelectronics +; + +[Version] +Signature="$Windows NT$" +Class=Ports +ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318} +Provider=%STM% +LayoutFile=layout.inf + +[Manufacturer] +%MFGNAME%=VirComDevice,NT,NTamd64 + +[DestinationDirs] +DefaultDestDir = 12 + +[VirComDevice.NT] +%DESCRIPTION%=DriverInstall,USB\VID_1EAF&PID_0029&MI_01 +%DESCRIPTION%=DriverInstall,USB\VID_1EAF&PID_0029&MI_01 + +[VirComDevice.NTamd64] +%DESCRIPTION%=DriverInstall,USB\VID_1EAF&PID_0029&MI_01 +%DESCRIPTION%=DriverInstall,USB\VID_1EAF&PID_0029&MI_01 + +[DriverInstall.NT] +Include=mdmcpq.inf +CopyFiles=FakeModemCopyFileSection +AddReg=DriverInstall.NT.AddReg + +[DriverInstall.NT.AddReg] +HKR,,DevLoader,,*ntkern +HKR,,NTMPDriver,,usbser.sys +HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider" + +[DriverInstall.NT.Services] +AddService=usbser, 0x00000002, DriverServiceInst + +[DriverServiceInst] +DisplayName=%SERVICE% +ServiceType=1 +StartType=3 +ErrorControl=1 +ServiceBinary=%12%\usbser.sys + +;------------------------------------------------------------------------------ +; String Definitions +;------------------------------------------------------------------------------ + + +[Strings] +STM = "LeafLabs" +MFGNAME = "LeafLabs" +DESCRIPTION = "Maple R3" +SERVICE = "USB Virtual COM port" diff --git a/Marlin/src/HAL/HAL_STM32F1/msc_sd.cpp b/Marlin/src/HAL/HAL_STM32F1/msc_sd.cpp new file mode 100644 index 0000000000..81e430fa2a --- /dev/null +++ b/Marlin/src/HAL/HAL_STM32F1/msc_sd.cpp @@ -0,0 +1,64 @@ +/** + * Marlin 3D Printer Firmware + * + * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * Copyright (c) 2019 BigTreeTech [https://github.com/bigtreetech] + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ +#ifdef USE_USB_COMPOSITE + +#include "msc_sd.h" +#include "SPI.h" + +#define PRODUCT_ID 0x29 + +USBMassStorage MarlinMSC; +USBCompositeSerial MarlinCompositeSerial; + +#include "../../inc/MarlinConfig.h" + +#ifdef HAS_ONBOARD_SD + + #include "onboard_sd.h" + + static bool MSC_Write(const uint8_t *writebuff, uint32_t startSector, uint16_t numSectors) { + return (disk_write(0, writebuff, startSector, numSectors) == RES_OK); + } + static bool MSC_Read(uint8_t *readbuff, uint32_t startSector, uint16_t numSectors) { + return (disk_read(0, readbuff, startSector, numSectors) == RES_OK); + } + +#endif + +void MSC_SD_init() { + USBComposite.setProductId(PRODUCT_ID); + // Just set MarlinCompositeSerial enabled to true + // because when MarlinCompositeSerial.begin() is used in setup() + // it clears all USBComposite devices. + MarlinCompositeSerial.begin(); + USBComposite.end(); + USBComposite.clear(); + // Set api and register mass storage + #ifdef HAS_ONBOARD_SD + uint32_t cardSize; + if (disk_initialize(0) == RES_OK) { + if (disk_ioctl(0, GET_SECTOR_COUNT, (void *)(&cardSize)) == RES_OK) { + MarlinMSC.setDriveData(0, cardSize, MSC_Read, MSC_Write); + MarlinMSC.registerComponent(); + } + } + #endif + // Register composite Serial + MarlinCompositeSerial.registerComponent(); + USBComposite.begin(); +} + +#endif // USE_USB_COMPOSITE diff --git a/Marlin/src/HAL/HAL_STM32F1/msc_sd.h b/Marlin/src/HAL/HAL_STM32F1/msc_sd.h new file mode 100644 index 0000000000..825af8cdb0 --- /dev/null +++ b/Marlin/src/HAL/HAL_STM32F1/msc_sd.h @@ -0,0 +1,24 @@ +/** + * Marlin 3D Printer Firmware + * + * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] + * Copyright (c) 2019 BigTreeTech [https://github.com/bigtreetech] + * + * 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. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#pragma once + +#include + +extern USBMassStorage MarlinMSC; +extern USBCompositeSerial MarlinCompositeSerial; + +void MSC_SD_init(); diff --git a/Marlin/src/HAL/HAL_STM32F1/onboard_sd.cpp b/Marlin/src/HAL/HAL_STM32F1/onboard_sd.cpp new file mode 100644 index 0000000000..6a0420223a --- /dev/null +++ b/Marlin/src/HAL/HAL_STM32F1/onboard_sd.cpp @@ -0,0 +1,558 @@ +/*------------------------------------------------------------------------*/ +/* STM32F1: MMCv3/SDv1/SDv2 (SPI mode) control module */ +/*------------------------------------------------------------------------*/ +/* +/ * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] +/ * Copyright (c) 2019 BigTreeTech [https://github.com/bigtreetech] +/ * Copyright (C) 2015, ChaN, all right reserved. +/ +/ * This software is a free software and there is NO WARRANTY. +/ * No restriction on use. You can use, modify and redistribute it for +/ personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. +/ * Redistributions of source code must retain the above copyright notice. +/ +/-------------------------------------------------------------------------*/ +#include "../../inc/MarlinConfig.h" + +#ifdef HAS_ONBOARD_SD + +#include "onboard_sd.h" +#include "spi.h" +#include "fastio.h" + +#ifdef SHARED_SD_CARD + #ifndef ON_BOARD_SPI_DEVICE + #define ON_BOARD_SPI_DEVICE SPI_DEVICE + #endif + #define ONBOARD_SD_SPI SPI +#else + SPIClass OnBoardSPI(ON_BOARD_SPI_DEVICE) + #define ONBOARD_SD_SPI OnBoardSPI +#endif + +#if ON_BOARD_SPI_DEVICE == 1 + #define SPI_CLOCK_MAX SPI_BAUD_PCLK_DIV_4 +#else + #define SPI_CLOCK_MAX SPI_BAUD_PCLK_DIV_2 +#endif + +#define CS_LOW() {WRITE(ONBOARD_SD_CS_PIN, LOW);} /* Set OnBoardSPI cs low */ +#define CS_HIGH() {WRITE(ONBOARD_SD_CS_PIN, HIGH);} /* Set OnBoardSPI cs high */ + +#define FCLK_FAST() ONBOARD_SD_SPI.setClockDivider(SPI_CLOCK_MAX) +#define FCLK_SLOW() ONBOARD_SD_SPI.setClockDivider(SPI_BAUD_PCLK_DIV_256) + +/*-------------------------------------------------------------------------- + Module Private Functions +---------------------------------------------------------------------------*/ + +#include "onboard_sd.h" + +/* MMC/SD command */ +#define CMD0 (0) /* GO_IDLE_STATE */ +#define CMD1 (1) /* SEND_OP_COND (MMC) */ +#define ACMD41 (0x80+41) /* SEND_OP_COND (SDC) */ +#define CMD8 (8) /* SEND_IF_COND */ +#define CMD9 (9) /* SEND_CSD */ +#define CMD10 (10) /* SEND_CID */ +#define CMD12 (12) /* STOP_TRANSMISSION */ +#define ACMD13 (0x80+13) /* SD_STATUS (SDC) */ +#define CMD16 (16) /* SET_BLOCKLEN */ +#define CMD17 (17) /* READ_SINGLE_BLOCK */ +#define CMD18 (18) /* READ_MULTIPLE_BLOCK */ +#define CMD23 (23) /* SET_BLOCK_COUNT (MMC) */ +#define ACMD23 (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */ +#define CMD24 (24) /* WRITE_BLOCK */ +#define CMD25 (25) /* WRITE_MULTIPLE_BLOCK */ +#define CMD32 (32) /* ERASE_ER_BLK_START */ +#define CMD33 (33) /* ERASE_ER_BLK_END */ +#define CMD38 (38) /* ERASE */ +#define CMD48 (48) /* READ_EXTR_SINGLE */ +#define CMD49 (49) /* WRITE_EXTR_SINGLE */ +#define CMD55 (55) /* APP_CMD */ +#define CMD58 (58) /* READ_OCR */ + +static volatile DSTATUS Stat = STA_NOINIT; /* Physical drive status */ +static volatile UINT timeout; +static BYTE CardType; /* Card type flags */ + +/*-----------------------------------------------------------------------*/ +/* Send/Receive data to the MMC (Platform dependent) */ +/*-----------------------------------------------------------------------*/ + +/* Exchange a byte */ +static BYTE xchg_spi ( + BYTE dat /* Data to send */ +) { + BYTE returnByte = ONBOARD_SD_SPI.transfer(dat); + return returnByte; +} + +/* Receive multiple byte */ +static void rcvr_spi_multi ( + BYTE *buff, /* Pointer to data buffer */ + UINT btr /* Number of bytes to receive (16, 64 or 512) */ +) { + ONBOARD_SD_SPI.dmaTransfer(0, const_cast(buff), btr); +} + +#if _DISKIO_WRITE + + /* Send multiple bytes */ + static void xmit_spi_multi ( + const BYTE *buff, /* Pointer to the data */ + UINT btx /* Number of bytes to send (multiple of 16) */ + ) { + ONBOARD_SD_SPI.dmaSend(const_cast(buff), btx); + } + +#endif // _DISKIO_WRITE + +/*-----------------------------------------------------------------------*/ +/* Wait for card ready */ +/*-----------------------------------------------------------------------*/ + +static int wait_ready ( /* 1:Ready, 0:Timeout */ + UINT wt /* Timeout [ms] */ +) { + BYTE d; + + timeout = millis() + wt; + do { + d = xchg_spi(0xFF); + /* This loop takes a while. Insert rot_rdq() here for multitask environment. */ + } while (d != 0xFF && (timeout > millis())); /* Wait for card goes ready or timeout */ + + return (d == 0xFF) ? 1 : 0; +} + +/*-----------------------------------------------------------------------*/ +/* Deselect card and release SPI */ +/*-----------------------------------------------------------------------*/ + +static void deselect(void) { + CS_HIGH(); /* CS = H */ + xchg_spi(0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */ +} + +/*-----------------------------------------------------------------------*/ +/* Select card and wait for ready */ +/*-----------------------------------------------------------------------*/ + +static int select(void) { /* 1:OK, 0:Timeout */ + CS_LOW(); /* CS = L */ + xchg_spi(0xFF); /* Dummy clock (force DO enabled) */ + + if (wait_ready(500)) return 1; /* Leading busy check: Wait for card ready */ + + deselect(); /* Timeout */ + return 0; +} + +/*-----------------------------------------------------------------------*/ +/* Control SPI module (Platform dependent) */ +/*-----------------------------------------------------------------------*/ + +static void power_on(void) { /* Enable SSP module and attach it to I/O pads */ + ONBOARD_SD_SPI.setModule(ON_BOARD_SPI_DEVICE); + ONBOARD_SD_SPI.begin(); + ONBOARD_SD_SPI.setBitOrder(MSBFIRST); + ONBOARD_SD_SPI.setDataMode(SPI_MODE0); + OUT_WRITE(ONBOARD_SD_CS_PIN, HIGH); /* Set CS# high */ +} + +static void power_off(void) { /* Disable SPI function */ + select(); /* Wait for card ready */ + deselect(); +} + +/*-----------------------------------------------------------------------*/ +/* Receive a data packet from the MMC */ +/*-----------------------------------------------------------------------*/ + +static int rcvr_datablock ( /* 1:OK, 0:Error */ + BYTE *buff, /* Data buffer */ + UINT btr /* Data block length (byte) */ +) { + BYTE token; + + timeout = millis() + 200; + do { /* Wait for DataStart token in timeout of 200ms */ + token = xchg_spi(0xFF); + /* This loop will take a while. Insert rot_rdq() here for multitask environment. */ + } while ((token == 0xFF) && (timeout > millis())); + if (token != 0xFE) return 0; /* Function fails if invalid DataStart token or timeout */ + + rcvr_spi_multi(buff, btr); /* Store trailing data to the buffer */ + xchg_spi(0xFF); xchg_spi(0xFF); /* Discard CRC */ + + return 1; /* Function succeeded */ +} + +/*-----------------------------------------------------------------------*/ +/* Send a data packet to the MMC */ +/*-----------------------------------------------------------------------*/ + +#if _DISKIO_WRITE + + static int xmit_datablock ( /* 1:OK, 0:Failed */ + const BYTE *buff, /* Ponter to 512 byte data to be sent */ + BYTE token /* Token */ + ) { + BYTE resp; + + if (!wait_ready(500)) return 0; /* Leading busy check: Wait for card ready to accept data block */ + + xchg_spi(token); /* Send token */ + if (token == 0xFD) return 1; /* Do not send data if token is StopTran */ + + xmit_spi_multi(buff, 512); /* Data */ + xchg_spi(0xFF); xchg_spi(0xFF); /* Dummy CRC */ + + resp = xchg_spi(0xFF); /* Receive data resp */ + + return (resp & 0x1F) == 0x05 ? 1 : 0; /* Data was accepted or not */ + + /* Busy check is done at next transmission */ + } + +#endif // _DISKIO_WRITE + +/*-----------------------------------------------------------------------*/ +/* Send a command packet to the MMC */ +/*-----------------------------------------------------------------------*/ + +static BYTE send_cmd ( /* Return value: R1 resp (bit7==1:Failed to send) */ + BYTE cmd, /* Command index */ + DWORD arg /* Argument */ +) { + BYTE n, res; + + if (cmd & 0x80) { /* Send a CMD55 prior to ACMD */ + cmd &= 0x7F; + res = send_cmd(CMD55, 0); + if (res > 1) return res; + } + + /* Select the card and wait for ready except to stop multiple block read */ + if (cmd != CMD12) { + deselect(); + if (!select()) return 0xFF; + } + + /* Send command packet */ + xchg_spi(0x40 | cmd); /* Start + command index */ + xchg_spi((BYTE)(arg >> 24)); /* Argument[31..24] */ + xchg_spi((BYTE)(arg >> 16)); /* Argument[23..16] */ + xchg_spi((BYTE)(arg >> 8)); /* Argument[15..8] */ + xchg_spi((BYTE)arg); /* Argument[7..0] */ + n = 0x01; /* Dummy CRC + Stop */ + if (cmd == CMD0) n = 0x95; /* Valid CRC for CMD0(0) */ + if (cmd == CMD8) n = 0x87; /* Valid CRC for CMD8(0x1AA) */ + xchg_spi(n); + + /* Receive command resp */ + if (cmd == CMD12) xchg_spi(0xFF); /* Diacard following one byte when CMD12 */ + n = 10; /* Wait for response (10 bytes max) */ + do + res = xchg_spi(0xFF); + while ((res & 0x80) && --n); + + return res; /* Return received response */ +} + +/*-------------------------------------------------------------------------- + Public Functions +---------------------------------------------------------------------------*/ + +/*-----------------------------------------------------------------------*/ +/* Initialize disk drive */ +/*-----------------------------------------------------------------------*/ + +DSTATUS disk_initialize ( + BYTE drv /* Physical drive number (0) */ +) { + BYTE n, cmd, ty, ocr[4]; + + if (drv) return STA_NOINIT; /* Supports only drive 0 */ + power_on(); /* Initialize SPI */ + + if (Stat & STA_NODISK) return Stat; /* Is a card existing in the soket? */ + + FCLK_SLOW(); + for (n = 10; n; n--) xchg_spi(0xFF); /* Send 80 dummy clocks */ + + ty = 0; + if (send_cmd(CMD0, 0) == 1) { /* Put the card SPI state */ + timeout = millis() + 1000; /* Initialization timeout = 1 sec */ + if (send_cmd(CMD8, 0x1AA) == 1) { /* Is the catd SDv2? */ + for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); /* Get 32 bit return value of R7 resp */ + if (ocr[2] == 0x01 && ocr[3] == 0xAA) { /* Does the card support 2.7-3.6V? */ + while ((timeout > millis()) && send_cmd(ACMD41, 1UL << 30)) ; /* Wait for end of initialization with ACMD41(HCS) */ + if ((timeout > millis()) && send_cmd(CMD58, 0) == 0) { /* Check CCS bit in the OCR */ + for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF); + ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2; /* Check if the card is SDv2 */ + } + } + } else { /* Not an SDv2 card */ + if (send_cmd(ACMD41, 0) <= 1) { /* SDv1 or MMCv3? */ + ty = CT_SD1; cmd = ACMD41; /* SDv1 (ACMD41(0)) */ + } else { + ty = CT_MMC; cmd = CMD1; /* MMCv3 (CMD1(0)) */ + } + while ((timeout > millis()) && send_cmd(cmd, 0)) ; /* Wait for the card leaves idle state */ + if (!(timeout > millis()) || send_cmd(CMD16, 512) != 0) /* Set block length: 512 */ + ty = 0; + } + } + CardType = ty; /* Card type */ + deselect(); + + if (ty) { /* OK */ + FCLK_FAST(); /* Set fast clock */ + Stat &= ~STA_NOINIT; /* Clear STA_NOINIT flag */ + } else { /* Failed */ + power_off(); + Stat = STA_NOINIT; + } + + return Stat; +} + +/*-----------------------------------------------------------------------*/ +/* Get disk status */ +/*-----------------------------------------------------------------------*/ + +DSTATUS disk_status ( + BYTE drv /* Physical drive number (0) */ +) { + if (drv) return STA_NOINIT; /* Supports only drive 0 */ + return Stat; /* Return disk status */ +} + +/*-----------------------------------------------------------------------*/ +/* Read sector(s) */ +/*-----------------------------------------------------------------------*/ + +DRESULT disk_read ( + BYTE drv, /* Physical drive number (0) */ + BYTE *buff, /* Pointer to the data buffer to store read data */ + DWORD sector, /* Start sector number (LBA) */ + UINT count /* Number of sectors to read (1..128) */ +) { + BYTE cmd; + + if (drv || !count) return RES_PARERR; /* Check parameter */ + if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */ + if (!(CardType & CT_BLOCK)) sector *= 512; /* LBA ot BA conversion (byte addressing cards) */ + FCLK_FAST(); + cmd = count > 1 ? CMD18 : CMD17; /* READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */ + if (send_cmd(cmd, sector) == 0) { + do { + if (!rcvr_datablock(buff, 512)) break; + buff += 512; + } while (--count); + if (cmd == CMD18) send_cmd(CMD12, 0); /* STOP_TRANSMISSION */ + } + deselect(); + + return count ? RES_ERROR : RES_OK; /* Return result */ +} + +/*-----------------------------------------------------------------------*/ +/* Write sector(s) */ +/*-----------------------------------------------------------------------*/ + +#if _DISKIO_WRITE + + DRESULT disk_write( + BYTE drv, /* Physical drive number (0) */ + const BYTE *buff, /* Ponter to the data to write */ + DWORD sector, /* Start sector number (LBA) */ + UINT count /* Number of sectors to write (1..128) */ + ) { + if (drv || !count) return RES_PARERR; /* Check parameter */ + if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check drive status */ + if (Stat & STA_PROTECT) return RES_WRPRT; /* Check write protect */ + FCLK_FAST(); + if (!(CardType & CT_BLOCK)) sector *= 512; /* LBA ==> BA conversion (byte addressing cards) */ + + if (count == 1) { /* Single sector write */ + if ((send_cmd(CMD24, sector) == 0) /* WRITE_BLOCK */ + && xmit_datablock(buff, 0xFE)) { + count = 0; + } + } + else { /* Multiple sector write */ + if (CardType & CT_SDC) send_cmd(ACMD23, count); /* Predefine number of sectors */ + if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */ + do { + if (!xmit_datablock(buff, 0xFC)) break; + buff += 512; + } while (--count); + if (!xmit_datablock(0, 0xFD)) count = 1; /* STOP_TRAN token */ + } + } + deselect(); + + return count ? RES_ERROR : RES_OK; /* Return result */ + } + +#endif // _DISKIO_WRITE + +/*-----------------------------------------------------------------------*/ +/* Miscellaneous drive controls other than data read/write */ +/*-----------------------------------------------------------------------*/ + +#if _DISKIO_IOCTL + + DRESULT disk_ioctl ( + BYTE drv, /* Physical drive number (0) */ + BYTE cmd, /* Control command code */ + void *buff /* Pointer to the conrtol data */ + ) { + DRESULT res; + BYTE n, csd[16], *ptr = (BYTE *)buff; + DWORD *dp, st, ed, csize; + #if _DISKIO_ISDIO + SDIO_CMD *sdio = buff; + BYTE rc, *buf; + UINT dc; + #endif + + if (drv) return RES_PARERR; /* Check parameter */ + if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */ + + res = RES_ERROR; + FCLK_FAST(); + switch (cmd) { + case CTRL_SYNC: /* Wait for end of internal write process of the drive */ + if (select()) res = RES_OK; + break; + + case GET_SECTOR_COUNT: /* Get drive capacity in unit of sector (DWORD) */ + if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { + if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */ + csize = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1; + *(DWORD*)buff = csize << 10; + } else { /* SDC ver 1.XX or MMC ver 3 */ + n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2; + csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1; + *(DWORD*)buff = csize << (n - 9); + } + res = RES_OK; + } + break; + + case GET_BLOCK_SIZE: /* Get erase block size in unit of sector (DWORD) */ + if (CardType & CT_SD2) { /* SDC ver 2.00 */ + if (send_cmd(ACMD13, 0) == 0) { /* Read SD status */ + xchg_spi(0xFF); + if (rcvr_datablock(csd, 16)) { /* Read partial block */ + for (n = 64 - 16; n; n--) xchg_spi(0xFF); /* Purge trailing data */ + *(DWORD*)buff = 16UL << (csd[10] >> 4); + res = RES_OK; + } + } + } else { /* SDC ver 1.XX or MMC */ + if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) { /* Read CSD */ + if (CardType & CT_SD1) { /* SDC ver 1.XX */ + *(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1); + } else { /* MMC */ + *(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1); + } + res = RES_OK; + } + } + break; + + case CTRL_TRIM: /* Erase a block of sectors (used when _USE_TRIM in ffconf.h is 1) */ + if (!(CardType & CT_SDC)) break; /* Check if the card is SDC */ + if (disk_ioctl(drv, MMC_GET_CSD, csd)) break; /* Get CSD */ + if (!(csd[0] >> 6) && !(csd[10] & 0x40)) break; /* Check if sector erase can be applied to the card */ + dp = (DWORD *)buff; st = dp[0]; ed = dp[1]; /* Load sector block */ + if (!(CardType & CT_BLOCK)) { + st *= 512; ed *= 512; + } + if (send_cmd(CMD32, st) == 0 && send_cmd(CMD33, ed) == 0 && send_cmd(CMD38, 0) == 0 && wait_ready(30000)) { /* Erase sector block */ + res = RES_OK; /* FatFs does not check result of this command */ + } + break; + + /* Following commands are never used by FatFs module */ + + case MMC_GET_TYPE: /* Get MMC/SDC type (BYTE) */ + *ptr = CardType; + res = RES_OK; + break; + + case MMC_GET_CSD: /* Read CSD (16 bytes) */ + if (send_cmd(CMD9, 0) == 0 && rcvr_datablock(ptr, 16)) { /* READ_CSD */ + res = RES_OK; + } + break; + + case MMC_GET_CID: /* Read CID (16 bytes) */ + if (send_cmd(CMD10, 0) == 0 && rcvr_datablock(ptr, 16)) { /* READ_CID */ + res = RES_OK; + } + break; + + case MMC_GET_OCR: /* Read OCR (4 bytes) */ + if (send_cmd(CMD58, 0) == 0) { /* READ_OCR */ + for (n = 4; n; n--) *ptr++ = xchg_spi(0xFF); + res = RES_OK; + } + break; + + case MMC_GET_SDSTAT: /* Read SD status (64 bytes) */ + if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */ + xchg_spi(0xFF); + if (rcvr_datablock(ptr, 64)) res = RES_OK; + } + break; + + #if _DISKIO_ISDIO + + case ISDIO_READ: + sdio = buff; + if (send_cmd(CMD48, 0x80000000 | sdio->func << 28 | sdio->addr << 9 | ((sdio->ndata - 1) & 0x1FF)) == 0) { + for (Timer1 = 1000; (rc = xchg_spi(0xFF)) == 0xFF && Timer1; ) ; + if (rc == 0xFE) { + for (buf = sdio->data, dc = sdio->ndata; dc; dc--) *buf++ = xchg_spi(0xFF); + for (dc = 514 - sdio->ndata; dc; dc--) xchg_spi(0xFF); + res = RES_OK; + } + } + break; + case ISDIO_WRITE: + sdio = buff; + if (send_cmd(CMD49, 0x80000000 | sdio->func << 28 | sdio->addr << 9 | ((sdio->ndata - 1) & 0x1FF)) == 0) { + xchg_spi(0xFF); xchg_spi(0xFE); + for (buf = sdio->data, dc = sdio->ndata; dc; dc--) xchg_spi(*buf++); + for (dc = 514 - sdio->ndata; dc; dc--) xchg_spi(0xFF); + if ((xchg_spi(0xFF) & 0x1F) == 0x05) res = RES_OK; + } + break; + case ISDIO_MRITE: + sdio = buff; + if (send_cmd(CMD49, 0x84000000 | sdio->func << 28 | sdio->addr << 9 | sdio->ndata >> 8) == 0) { + xchg_spi(0xFF); xchg_spi(0xFE); + xchg_spi(sdio->ndata); + for (dc = 513; dc; dc--) xchg_spi(0xFF); + if ((xchg_spi(0xFF) & 0x1F) == 0x05) res = RES_OK; + } + break; + + #endif // _DISKIO_ISDIO + + default: res = RES_PARERR; + } + + deselect(); + return res; + } + +#endif // _DISKIO_IOCTL + +#endif // HAS_ONBOARD_SD diff --git a/Marlin/src/HAL/HAL_STM32F1/onboard_sd.h b/Marlin/src/HAL/HAL_STM32F1/onboard_sd.h new file mode 100644 index 0000000000..ec73162ba1 --- /dev/null +++ b/Marlin/src/HAL/HAL_STM32F1/onboard_sd.h @@ -0,0 +1,96 @@ +/*----------------------------------------------------------------------- +/ * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin] +/ * Copyright (c) 2019 BigTreeTech [https://github.com/bigtreetech] +/ * Low level disk interface module include file (C)ChaN, 2015 +/-----------------------------------------------------------------------*/ + +#pragma once + +#define _DISKIO_WRITE 1 /* 1: Enable disk_write function */ +#define _DISKIO_IOCTL 1 /* 1: Enable disk_ioctl fucntion */ +#define _DISKIO_ISDIO 0 /* 1: Enable iSDIO control fucntion */ + +typedef unsigned char BYTE; +typedef unsigned short WORD; +typedef unsigned long DWORD; +typedef unsigned int UINT; + +/* Status of Disk Functions */ +typedef BYTE DSTATUS; + +/* Results of Disk Functions */ +typedef enum { + RES_OK = 0, /* 0: Successful */ + RES_ERROR, /* 1: R/W Error */ + RES_WRPRT, /* 2: Write Protected */ + RES_NOTRDY, /* 3: Not Ready */ + RES_PARERR /* 4: Invalid Parameter */ +} DRESULT; + + +#if _DISKIO_ISDIO +/* Command structure for iSDIO ioctl command */ +typedef struct { + BYTE func; /* Function number: 0..7 */ + WORD ndata; /* Number of bytes to transfer: 1..512, or mask + data */ + DWORD addr; /* Register address: 0..0x1FFFF */ + void* data; /* Pointer to the data (to be written | read buffer) */ +} SDIO_CMD; +#endif + +/*---------------------------------------*/ +/* Prototypes for disk control functions */ + +DSTATUS disk_initialize(BYTE pdrv); +DSTATUS disk_status(BYTE pdrv); +DRESULT disk_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count); +#if _DISKIO_WRITE + DRESULT disk_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count); +#endif +#if _DISKIO_IOCTL + DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void* buff); +#endif + +/* Disk Status Bits (DSTATUS) */ +#define STA_NOINIT 0x01 /* Drive not initialized */ +#define STA_NODISK 0x02 /* No medium in the drive */ +#define STA_PROTECT 0x04 /* Write protected */ + +/* Command code for disk_ioctrl fucntion */ + +/* Generic command (Used by FatFs) */ +#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */ +#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */ +#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */ +#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */ +#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */ + +/* Generic command (Not used by FatFs) */ +#define CTRL_FORMAT 5 /* Create physical format on the media */ +#define CTRL_POWER_IDLE 6 /* Put the device idle state */ +#define CTRL_POWER_OFF 7 /* Put the device off state */ +#define CTRL_LOCK 8 /* Lock media removal */ +#define CTRL_UNLOCK 9 /* Unlock media removal */ +#define CTRL_EJECT 10 /* Eject media */ + +/* MMC/SDC specific ioctl command (Not used by FatFs) */ +#define MMC_GET_TYPE 50 /* Get card type */ +#define MMC_GET_CSD 51 /* Get CSD */ +#define MMC_GET_CID 52 /* Get CID */ +#define MMC_GET_OCR 53 /* Get OCR */ +#define MMC_GET_SDSTAT 54 /* Get SD status */ +#define ISDIO_READ 55 /* Read data form SD iSDIO register */ +#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */ +#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */ + +/* ATA/CF specific ioctl command (Not used by FatFs) */ +#define ATA_GET_REV 60 /* Get F/W revision */ +#define ATA_GET_MODEL 61 /* Get model name */ +#define ATA_GET_SN 62 /* Get serial number */ + +/* MMC card type flags (MMC_GET_TYPE) */ +#define CT_MMC 0x01 /* MMC ver 3 */ +#define CT_SD1 0x02 /* SD ver 1 */ +#define CT_SD2 0x04 /* SD ver 2 */ +#define CT_SDC (CT_SD1|CT_SD2) /* SD */ +#define CT_BLOCK 0x08 /* Block addressing */ diff --git a/Marlin/src/lcd/extensible_ui/lib/lulzbot/ftdi_eve_lib/basic/commands.cpp b/Marlin/src/lcd/extensible_ui/lib/lulzbot/ftdi_eve_lib/basic/commands.cpp index 83e23e6e0f..c7d1599451 100644 --- a/Marlin/src/lcd/extensible_ui/lib/lulzbot/ftdi_eve_lib/basic/commands.cpp +++ b/Marlin/src/lcd/extensible_ui/lib/lulzbot/ftdi_eve_lib/basic/commands.cpp @@ -1105,9 +1105,9 @@ void CLCD::init (void) { mem_write_8(REG::CSPREAD, FTDI::CSpread); /* write a basic display-list to get things started */ - mem_write_32(MAP::RAM_DL, DL::CLEAR_COLOR_RGB); - mem_write_32(MAP::RAM_DL + 4, (DL::CLEAR | 0x07)); /* clear color, stencil and tag buffer */ - mem_write_32(MAP::RAM_DL + 8, DL::DL_DISPLAY); /* end of display list */ + mem_write_32(MAP::RAM_DL, DL::CLEAR_COLOR_RGB); + mem_write_32(MAP::RAM_DL + 4, (DL::CLEAR | 0x07)); /* clear color, stencil and tag buffer */ + mem_write_32(MAP::RAM_DL + 8, DL::DL_DISPLAY); /* end of display list */ mem_write_8(REG::DLSWAP, 0x02); // activate display list, Bad Magic Cookie 2 = switch to new list after current frame is scanned out diff --git a/Marlin/src/pins/stm32/pins_BIGTREE_SKR_E3_DIP.h b/Marlin/src/pins/stm32/pins_BIGTREE_SKR_E3_DIP.h index 9206e2ebe5..1e8e605abb 100644 --- a/Marlin/src/pins/stm32/pins_BIGTREE_SKR_E3_DIP.h +++ b/Marlin/src/pins/stm32/pins_BIGTREE_SKR_E3_DIP.h @@ -187,3 +187,15 @@ #endif #endif // HAS_SPI_LCD + +// +// SD Support +// +#define HAS_ONBOARD_SD + +#ifndef SDCARD_CONNECTION + #define SDCARD_CONNECTION ONBOARD +#endif + +#define ON_BOARD_SPI_DEVICE 1 //SPI1 +#define ONBOARD_SD_CS_PIN PA4 // Chip select for "System" SD card diff --git a/Marlin/src/pins/stm32/pins_BIGTREE_SKR_MINI_E3.h b/Marlin/src/pins/stm32/pins_BIGTREE_SKR_MINI_E3.h index 852226eff3..b0039b109c 100644 --- a/Marlin/src/pins/stm32/pins_BIGTREE_SKR_MINI_E3.h +++ b/Marlin/src/pins/stm32/pins_BIGTREE_SKR_MINI_E3.h @@ -142,3 +142,15 @@ #endif #endif // HAS_SPI_LCD + +// +// SD Support +// +#define HAS_ONBOARD_SD + +#ifndef SDCARD_CONNECTION + #define SDCARD_CONNECTION ONBOARD +#endif + +#define ON_BOARD_SPI_DEVICE 1 //SPI1 +#define ONBOARD_SD_CS_PIN PA4 // Chip select for "System" SD card diff --git a/Marlin/src/pins/stm32/pins_BIGTREE_SKR_MINI_V1_1.h b/Marlin/src/pins/stm32/pins_BIGTREE_SKR_MINI_V1_1.h index 3d7f8d98d4..f82c215636 100644 --- a/Marlin/src/pins/stm32/pins_BIGTREE_SKR_MINI_V1_1.h +++ b/Marlin/src/pins/stm32/pins_BIGTREE_SKR_MINI_V1_1.h @@ -160,20 +160,20 @@ // // By default the onboard SD is enabled. -// To disable it and use an external SD (connected to LCD) -// enable STM32_SD_LCD. +// set SDCARD_CONNECTION form 'ONBOARD' to 'LCD' and use an external SD (connected to LCD) +#define HAS_ONBOARD_SD +#ifndef SDCARD_CONNECTION + #define SDCARD_CONNECTION ONBOARD +#endif -//#define STM32_SD_LCD - -#if ENABLED(STM32_SD_LCD) +#if SD_CONNECTION_IS(LCD) #define ENABLE_SPI3 #define SD_DETECT_PIN PB9 #define SCK_PIN PB3 #define MISO_PIN PB4 #define MOSI_PIN PB5 #define SS_PIN PA15 -#else - #define SDCARD_CONNECTION ONBOARD +#if SD_CONNECTION_IS(ONBOARD) #define ENABLE_SPI1 #define SD_DETECT_PIN PA3 #define SCK_PIN PA5 @@ -181,6 +181,8 @@ #define MOSI_PIN PA7 #define SS_PIN PA4 #endif +#define ON_BOARD_SPI_DEVICE 1 //SPI1 +#define ONBOARD_SD_CS_PIN PA4 // Chip select for "System" SD card #ifndef ST7920_DELAY_1 #define ST7920_DELAY_1 DELAY_NS(125) diff --git a/Marlin/src/sd/usb_flashdrive/lib-uhs3/UHS_host/UHS_USB_IDs.h b/Marlin/src/sd/usb_flashdrive/lib-uhs3/UHS_host/UHS_USB_IDs.h index 68d7885c6b..1a88d38e9b 100644 --- a/Marlin/src/sd/usb_flashdrive/lib-uhs3/UHS_host/UHS_USB_IDs.h +++ b/Marlin/src/sd/usb_flashdrive/lib-uhs3/UHS_host/UHS_USB_IDs.h @@ -77,7 +77,7 @@ #define UHS_VID_OPTI 0x03fbU // OPTi, Inc. #define UHS_VID_ELITEGROUP_COMPUTER_SYSTEMS 0x03fcU // Elitegroup Computer Systems #define UHS_VID_XILINX 0x03fdU // Xilinx, Inc. -#define UHS_VID_FARALLON_COMUNICATIONS 0x03feU // Farallon Comunications +#define UHS_VID_FARALLON_COMUNICATIONS 0x03feU // Farallon Communications #define UHS_VID_NATIONAL_SEMICONDUCTOR 0x0400U // National Semiconductor Corp. #define UHS_VID_NATIONAL_REGISTRY 0x0401U // National Registry, Inc. #define UHS_VID_ALI 0x0402U // ALi Corp. diff --git a/platformio.ini b/platformio.ini index a2df18720c..83019cd029 100644 --- a/platformio.ini +++ b/platformio.ini @@ -304,7 +304,7 @@ platform_packages = tool-stm32duino extra_scripts = buildroot/share/PlatformIO/scripts/STM32F1_SKR_MINI.py build_flags = !python Marlin/src/HAL/HAL_STM32F1/build_flags.py ${common.build_flags} -std=gnu++14 - -DDEBUG_LEVEL=0 + -DDEBUG_LEVEL=0 -DUSE_USB_COMPOSITE build_unflags = -std=gnu++11 lib_deps = ${common.lib_deps} lib_ignore = Adafruit NeoPixel, SPI