Browse Source

STM32F1 USB cdc/msc composite device (#15180)

Co-Authored-By: bigtreetech <38851044+bigtreetech@users.noreply.github.com>
Scott Lahteine 4 years ago
parent
commit
dbea6f0022

+ 22
- 1
Marlin/src/HAL/HAL_STM32F1/HAL.cpp View File

@@ -82,7 +82,7 @@
82 82
 // Public Variables
83 83
 // ------------------------
84 84
 
85
-#ifdef SERIAL_USB
85
+#if (!defined(SERIAL_USB) && !defined(USE_USB_COMPOSITE))
86 86
   USBSerial SerialUSB;
87 87
 #endif
88 88
 
@@ -215,6 +215,9 @@ void HAL_init(void) {
215 215
   #if PIN_EXISTS(LED)
216 216
     OUT_WRITE(LED_PIN, LOW);
217 217
   #endif
218
+  #ifdef USE_USB_COMPOSITE
219
+    MSC_SD_init();
220
+  #endif
218 221
   #if PIN_EXISTS(USB_CONNECT)
219 222
     OUT_WRITE(USB_CONNECT_PIN, !USB_CONNECT_INVERTING);  // USB clear connection
220 223
     delay(1000);                                         // Give OS time to notice
@@ -222,6 +225,24 @@ void HAL_init(void) {
222 225
   #endif
223 226
 }
224 227
 
228
+// HAL idle task
229
+void HAL_idletask(void) {
230
+  #ifdef USE_USB_COMPOSITE
231
+    #if ENABLED(SHARED_SD_CARD)
232
+      // If Marlin is using the SD card we need to lock it to prevent access from
233
+      // a PC via USB.
234
+      // Other HALs use IS_SD_PRINTING() and IS_SD_FILE_OPEN() to check for access but
235
+      // this will not reliably detect delete operations. To be safe we will lock
236
+      // the disk if Marlin has it mounted. Unfortuately there is currently no way
237
+      // to unmount the disk from the LCD menu.
238
+      // if (IS_SD_PRINTING() || IS_SD_FILE_OPEN())
239
+      /* copy from lpc1768 framework, should be fixed later for process SHARED_SD_CARD*/
240
+    #endif
241
+    // process USB mass storage device class loop
242
+    MarlinMSC.loop();
243
+  #endif
244
+}
245
+
225 246
 /* VGPV Done with defines
226 247
 // disable interrupts
227 248
 void cli(void) { noInterrupts(); }

+ 14
- 3
Marlin/src/HAL/HAL_STM32F1/HAL.h View File

@@ -42,21 +42,30 @@
42 42
 #include <util/atomic.h>
43 43
 
44 44
 #include "../../inc/MarlinConfigPre.h"
45
+#include "msc_sd.h"
45 46
 
46 47
 // ------------------------
47 48
 // Defines
48 49
 // ------------------------
49 50
 
50 51
 #ifdef SERIAL_USB
51
-  #define UsbSerial Serial
52
+  #ifndef USE_USB_COMPOSITE
53
+    #define UsbSerial Serial
54
+  #else
55
+    #define UsbSerial MarlinCompositeSerial
56
+  #endif
52 57
   #define MSerial1  Serial1
53 58
   #define MSerial2  Serial2
54 59
   #define MSerial3  Serial3
55 60
   #define MSerial4  Serial4
56 61
   #define MSerial5  Serial5
57 62
 #else
58
-  extern USBSerial SerialUSB;
59
-  #define UsbSerial SerialUSB
63
+  #ifndef USE_USB_COMPOSITE
64
+    extern USBSerial SerialUSB;
65
+    #define UsbSerial SerialUSB
66
+  #else
67
+    #define UsbSerial MarlinCompositeSerial
68
+  #endif
60 69
   #define MSerial1  Serial
61 70
   #define MSerial2  Serial1
62 71
   #define MSerial3  Serial2
@@ -111,6 +120,8 @@
111 120
 
112 121
 // Set interrupt grouping for this MCU
113 122
 void HAL_init(void);
123
+#define HAL_IDLETASK 1
124
+void HAL_idletask(void);
114 125
 
115 126
 /**
116 127
  * TODO: review this to return 1 for pins that are not analog input

+ 56
- 0
Marlin/src/HAL/HAL_STM32F1/maple_win_usb_driver/maple_serial.inf View File

@@ -0,0 +1,56 @@
1
+;
2
+; STMicroelectronics Communication Device Class driver installation file
3
+; (C)2006 Copyright STMicroelectronics
4
+;
5
+
6
+[Version]
7
+Signature="$Windows NT$"
8
+Class=Ports
9
+ClassGuid={4D36E978-E325-11CE-BFC1-08002BE10318}
10
+Provider=%STM%
11
+LayoutFile=layout.inf
12
+
13
+[Manufacturer]
14
+%MFGNAME%=VirComDevice,NT,NTamd64
15
+
16
+[DestinationDirs]
17
+DefaultDestDir = 12
18
+
19
+[VirComDevice.NT]
20
+%DESCRIPTION%=DriverInstall,USB\VID_1EAF&PID_0029&MI_01
21
+%DESCRIPTION%=DriverInstall,USB\VID_1EAF&PID_0029&MI_01
22
+
23
+[VirComDevice.NTamd64]
24
+%DESCRIPTION%=DriverInstall,USB\VID_1EAF&PID_0029&MI_01
25
+%DESCRIPTION%=DriverInstall,USB\VID_1EAF&PID_0029&MI_01
26
+
27
+[DriverInstall.NT]
28
+Include=mdmcpq.inf
29
+CopyFiles=FakeModemCopyFileSection
30
+AddReg=DriverInstall.NT.AddReg
31
+
32
+[DriverInstall.NT.AddReg]
33
+HKR,,DevLoader,,*ntkern
34
+HKR,,NTMPDriver,,usbser.sys
35
+HKR,,EnumPropPages32,,"MsPorts.dll,SerialPortPropPageProvider"
36
+
37
+[DriverInstall.NT.Services]
38
+AddService=usbser, 0x00000002, DriverServiceInst
39
+
40
+[DriverServiceInst]
41
+DisplayName=%SERVICE%
42
+ServiceType=1
43
+StartType=3
44
+ErrorControl=1
45
+ServiceBinary=%12%\usbser.sys
46
+
47
+;------------------------------------------------------------------------------
48
+;  String Definitions
49
+;------------------------------------------------------------------------------
50
+
51
+
52
+[Strings]
53
+STM         = "LeafLabs"
54
+MFGNAME     = "LeafLabs"
55
+DESCRIPTION = "Maple R3"
56
+SERVICE     = "USB Virtual COM port"

+ 64
- 0
Marlin/src/HAL/HAL_STM32F1/msc_sd.cpp View File

@@ -0,0 +1,64 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ *
4
+ * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
5
+ * Copyright (c) 2019 BigTreeTech [https://github.com/bigtreetech]
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * You should have received a copy of the GNU General Public License
13
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
14
+ *
15
+ */
16
+#ifdef USE_USB_COMPOSITE
17
+
18
+#include "msc_sd.h"
19
+#include "SPI.h"
20
+
21
+#define PRODUCT_ID 0x29
22
+
23
+USBMassStorage MarlinMSC;
24
+USBCompositeSerial MarlinCompositeSerial;
25
+
26
+#include "../../inc/MarlinConfig.h"
27
+
28
+#ifdef HAS_ONBOARD_SD
29
+
30
+  #include "onboard_sd.h"
31
+
32
+  static bool MSC_Write(const uint8_t *writebuff, uint32_t startSector, uint16_t numSectors) {
33
+    return (disk_write(0, writebuff, startSector, numSectors) == RES_OK);
34
+  }
35
+  static bool MSC_Read(uint8_t *readbuff, uint32_t startSector, uint16_t numSectors) {
36
+    return (disk_read(0, readbuff, startSector, numSectors) == RES_OK);
37
+  }
38
+
39
+#endif
40
+
41
+void MSC_SD_init() {
42
+  USBComposite.setProductId(PRODUCT_ID);
43
+  // Just set MarlinCompositeSerial enabled to true
44
+  // because when MarlinCompositeSerial.begin() is used in setup()
45
+  // it clears all USBComposite devices.
46
+  MarlinCompositeSerial.begin();
47
+  USBComposite.end();
48
+  USBComposite.clear();
49
+  // Set api and register mass storage
50
+  #ifdef HAS_ONBOARD_SD
51
+    uint32_t cardSize;
52
+    if (disk_initialize(0) == RES_OK) {
53
+      if (disk_ioctl(0, GET_SECTOR_COUNT, (void *)(&cardSize)) == RES_OK) {
54
+        MarlinMSC.setDriveData(0, cardSize, MSC_Read, MSC_Write);
55
+        MarlinMSC.registerComponent();
56
+      }
57
+    }
58
+  #endif
59
+  // Register composite Serial
60
+  MarlinCompositeSerial.registerComponent();
61
+  USBComposite.begin();
62
+}
63
+
64
+#endif // USE_USB_COMPOSITE

+ 24
- 0
Marlin/src/HAL/HAL_STM32F1/msc_sd.h View File

@@ -0,0 +1,24 @@
1
+/**
2
+ * Marlin 3D Printer Firmware
3
+ *
4
+ * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
5
+ * Copyright (c) 2019 BigTreeTech [https://github.com/bigtreetech]
6
+ *
7
+ * This program is free software: you can redistribute it and/or modify
8
+ * it under the terms of the GNU General Public License as published by
9
+ * the Free Software Foundation, either version 3 of the License, or
10
+ * (at your option) any later version.
11
+ *
12
+ * You should have received a copy of the GNU General Public License
13
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
14
+ *
15
+ */
16
+
17
+#pragma once
18
+
19
+#include <USBComposite.h>
20
+
21
+extern USBMassStorage MarlinMSC;
22
+extern USBCompositeSerial MarlinCompositeSerial;
23
+
24
+void MSC_SD_init();

+ 558
- 0
Marlin/src/HAL/HAL_STM32F1/onboard_sd.cpp View File

@@ -0,0 +1,558 @@
1
+/*------------------------------------------------------------------------*/
2
+/* STM32F1: MMCv3/SDv1/SDv2 (SPI mode) control module                     */
3
+/*------------------------------------------------------------------------*/
4
+/*
5
+/ * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
6
+/ * Copyright (c) 2019 BigTreeTech [https://github.com/bigtreetech]
7
+/ * Copyright (C) 2015, ChaN, all right reserved.
8
+/
9
+/ * This software is a free software and there is NO WARRANTY.
10
+/ * No restriction on use. You can use, modify and redistribute it for
11
+/   personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY.
12
+/ * Redistributions of source code must retain the above copyright notice.
13
+/
14
+/-------------------------------------------------------------------------*/
15
+#include "../../inc/MarlinConfig.h"
16
+
17
+#ifdef HAS_ONBOARD_SD
18
+
19
+#include "onboard_sd.h"
20
+#include "spi.h"
21
+#include "fastio.h"
22
+
23
+#ifdef SHARED_SD_CARD
24
+  #ifndef ON_BOARD_SPI_DEVICE
25
+    #define ON_BOARD_SPI_DEVICE SPI_DEVICE
26
+  #endif
27
+  #define ONBOARD_SD_SPI SPI
28
+#else
29
+  SPIClass OnBoardSPI(ON_BOARD_SPI_DEVICE)
30
+  #define ONBOARD_SD_SPI OnBoardSPI
31
+#endif
32
+
33
+#if ON_BOARD_SPI_DEVICE == 1
34
+  #define SPI_CLOCK_MAX SPI_BAUD_PCLK_DIV_4
35
+#else
36
+  #define SPI_CLOCK_MAX SPI_BAUD_PCLK_DIV_2
37
+#endif
38
+
39
+#define CS_LOW()  {WRITE(ONBOARD_SD_CS_PIN, LOW);}  /* Set OnBoardSPI cs low */
40
+#define CS_HIGH() {WRITE(ONBOARD_SD_CS_PIN, HIGH);} /* Set OnBoardSPI cs high */
41
+
42
+#define FCLK_FAST() ONBOARD_SD_SPI.setClockDivider(SPI_CLOCK_MAX)
43
+#define FCLK_SLOW() ONBOARD_SD_SPI.setClockDivider(SPI_BAUD_PCLK_DIV_256)
44
+
45
+/*--------------------------------------------------------------------------
46
+   Module Private Functions
47
+---------------------------------------------------------------------------*/
48
+
49
+#include "onboard_sd.h"
50
+
51
+/* MMC/SD command */
52
+#define CMD0  (0)     /* GO_IDLE_STATE */
53
+#define CMD1  (1)     /* SEND_OP_COND (MMC) */
54
+#define ACMD41  (0x80+41) /* SEND_OP_COND (SDC) */
55
+#define CMD8  (8)     /* SEND_IF_COND */
56
+#define CMD9  (9)     /* SEND_CSD */
57
+#define CMD10 (10)    /* SEND_CID */
58
+#define CMD12 (12)    /* STOP_TRANSMISSION */
59
+#define ACMD13  (0x80+13) /* SD_STATUS (SDC) */
60
+#define CMD16 (16)    /* SET_BLOCKLEN */
61
+#define CMD17 (17)    /* READ_SINGLE_BLOCK */
62
+#define CMD18 (18)    /* READ_MULTIPLE_BLOCK */
63
+#define CMD23 (23)    /* SET_BLOCK_COUNT (MMC) */
64
+#define ACMD23  (0x80+23) /* SET_WR_BLK_ERASE_COUNT (SDC) */
65
+#define CMD24 (24)    /* WRITE_BLOCK */
66
+#define CMD25 (25)    /* WRITE_MULTIPLE_BLOCK */
67
+#define CMD32 (32)    /* ERASE_ER_BLK_START */
68
+#define CMD33 (33)    /* ERASE_ER_BLK_END */
69
+#define CMD38 (38)    /* ERASE */
70
+#define CMD48 (48)    /* READ_EXTR_SINGLE */
71
+#define CMD49 (49)    /* WRITE_EXTR_SINGLE */
72
+#define CMD55 (55)    /* APP_CMD */
73
+#define CMD58 (58)    /* READ_OCR */
74
+
75
+static volatile DSTATUS Stat = STA_NOINIT;  /* Physical drive status */
76
+static volatile UINT timeout;
77
+static BYTE CardType;      /* Card type flags */
78
+
79
+/*-----------------------------------------------------------------------*/
80
+/* Send/Receive data to the MMC  (Platform dependent)                    */
81
+/*-----------------------------------------------------------------------*/
82
+
83
+/* Exchange a byte */
84
+static BYTE xchg_spi (
85
+  BYTE dat  /* Data to send */
86
+) {
87
+  BYTE returnByte = ONBOARD_SD_SPI.transfer(dat);
88
+  return returnByte;
89
+}
90
+
91
+/* Receive multiple byte */
92
+static void rcvr_spi_multi (
93
+  BYTE *buff,   /* Pointer to data buffer */
94
+  UINT btr    /* Number of bytes to receive (16, 64 or 512) */
95
+) {
96
+  ONBOARD_SD_SPI.dmaTransfer(0, const_cast<uint8_t*>(buff), btr);
97
+}
98
+
99
+#if _DISKIO_WRITE
100
+
101
+  /* Send multiple bytes */
102
+  static void xmit_spi_multi (
103
+    const BYTE *buff, /* Pointer to the data */
104
+    UINT btx      /* Number of bytes to send (multiple of 16) */
105
+  ) {
106
+    ONBOARD_SD_SPI.dmaSend(const_cast<uint8_t*>(buff), btx);
107
+  }
108
+
109
+#endif // _DISKIO_WRITE
110
+
111
+/*-----------------------------------------------------------------------*/
112
+/* Wait for card ready                                                   */
113
+/*-----------------------------------------------------------------------*/
114
+
115
+static int wait_ready (  /* 1:Ready, 0:Timeout */
116
+  UINT wt     /* Timeout [ms] */
117
+) {
118
+  BYTE d;
119
+
120
+  timeout = millis() + wt;
121
+  do {
122
+    d = xchg_spi(0xFF);
123
+    /* This loop takes a while. Insert rot_rdq() here for multitask environment. */
124
+  } while (d != 0xFF && (timeout > millis()));  /* Wait for card goes ready or timeout */
125
+
126
+  return (d == 0xFF) ? 1 : 0;
127
+}
128
+
129
+/*-----------------------------------------------------------------------*/
130
+/* Deselect card and release SPI                                         */
131
+/*-----------------------------------------------------------------------*/
132
+
133
+static void deselect(void) {
134
+  CS_HIGH();    /* CS = H */
135
+  xchg_spi(0xFF); /* Dummy clock (force DO hi-z for multiple slave SPI) */
136
+}
137
+
138
+/*-----------------------------------------------------------------------*/
139
+/* Select card and wait for ready                                        */
140
+/*-----------------------------------------------------------------------*/
141
+
142
+static int select(void) { /* 1:OK, 0:Timeout */
143
+  CS_LOW();   /* CS = L */
144
+  xchg_spi(0xFF); /* Dummy clock (force DO enabled) */
145
+
146
+  if (wait_ready(500)) return 1;  /* Leading busy check: Wait for card ready */
147
+
148
+  deselect();   /* Timeout */
149
+  return 0;
150
+}
151
+
152
+/*-----------------------------------------------------------------------*/
153
+/* Control SPI module (Platform dependent)                               */
154
+/*-----------------------------------------------------------------------*/
155
+
156
+static void power_on(void) {  /* Enable SSP module and attach it to I/O pads */
157
+  ONBOARD_SD_SPI.setModule(ON_BOARD_SPI_DEVICE);
158
+  ONBOARD_SD_SPI.begin();
159
+  ONBOARD_SD_SPI.setBitOrder(MSBFIRST);
160
+  ONBOARD_SD_SPI.setDataMode(SPI_MODE0);
161
+  OUT_WRITE(ONBOARD_SD_CS_PIN, HIGH); /* Set CS# high */
162
+}
163
+
164
+static void power_off(void) {   /* Disable SPI function */
165
+  select();       /* Wait for card ready */
166
+  deselect();
167
+}
168
+
169
+/*-----------------------------------------------------------------------*/
170
+/* Receive a data packet from the MMC                                    */
171
+/*-----------------------------------------------------------------------*/
172
+
173
+static int rcvr_datablock (  /* 1:OK, 0:Error */
174
+  BYTE *buff,     /* Data buffer */
175
+  UINT btr      /* Data block length (byte) */
176
+) {
177
+  BYTE token;
178
+
179
+  timeout = millis() + 200;
180
+  do {              /* Wait for DataStart token in timeout of 200ms */
181
+    token = xchg_spi(0xFF);
182
+    /* This loop will take a while. Insert rot_rdq() here for multitask environment. */
183
+  } while ((token == 0xFF) && (timeout > millis()));
184
+  if (token != 0xFE) return 0;   /* Function fails if invalid DataStart token or timeout */
185
+
186
+  rcvr_spi_multi(buff, btr);    /* Store trailing data to the buffer */
187
+  xchg_spi(0xFF); xchg_spi(0xFF); /* Discard CRC */
188
+
189
+  return 1;           /* Function succeeded */
190
+}
191
+
192
+/*-----------------------------------------------------------------------*/
193
+/* Send a data packet to the MMC                                         */
194
+/*-----------------------------------------------------------------------*/
195
+
196
+#if _DISKIO_WRITE
197
+
198
+  static int xmit_datablock (  /* 1:OK, 0:Failed */
199
+    const BYTE *buff, /* Ponter to 512 byte data to be sent */
200
+    BYTE token      /* Token */
201
+  ) {
202
+    BYTE resp;
203
+
204
+    if (!wait_ready(500)) return 0;   /* Leading busy check: Wait for card ready to accept data block */
205
+
206
+    xchg_spi(token);          /* Send token */
207
+    if (token == 0xFD) return 1;    /* Do not send data if token is StopTran */
208
+
209
+    xmit_spi_multi(buff, 512);      /* Data */
210
+    xchg_spi(0xFF); xchg_spi(0xFF);   /* Dummy CRC */
211
+
212
+    resp = xchg_spi(0xFF);        /* Receive data resp */
213
+
214
+    return (resp & 0x1F) == 0x05 ? 1 : 0; /* Data was accepted or not */
215
+
216
+    /* Busy check is done at next transmission */
217
+  }
218
+
219
+#endif // _DISKIO_WRITE
220
+
221
+/*-----------------------------------------------------------------------*/
222
+/* Send a command packet to the MMC                                      */
223
+/*-----------------------------------------------------------------------*/
224
+
225
+static BYTE send_cmd (   /* Return value: R1 resp (bit7==1:Failed to send) */
226
+  BYTE cmd,   /* Command index */
227
+  DWORD arg   /* Argument */
228
+) {
229
+  BYTE n, res;
230
+
231
+  if (cmd & 0x80) { /* Send a CMD55 prior to ACMD<n> */
232
+    cmd &= 0x7F;
233
+    res = send_cmd(CMD55, 0);
234
+    if (res > 1) return res;
235
+  }
236
+
237
+  /* Select the card and wait for ready except to stop multiple block read */
238
+  if (cmd != CMD12) {
239
+    deselect();
240
+    if (!select()) return 0xFF;
241
+  }
242
+
243
+  /* Send command packet */
244
+  xchg_spi(0x40 | cmd);       /* Start + command index */
245
+  xchg_spi((BYTE)(arg >> 24));    /* Argument[31..24] */
246
+  xchg_spi((BYTE)(arg >> 16));    /* Argument[23..16] */
247
+  xchg_spi((BYTE)(arg >> 8));     /* Argument[15..8] */
248
+  xchg_spi((BYTE)arg);        /* Argument[7..0] */
249
+  n = 0x01;             /* Dummy CRC + Stop */
250
+  if (cmd == CMD0) n = 0x95;      /* Valid CRC for CMD0(0) */
251
+  if (cmd == CMD8) n = 0x87;      /* Valid CRC for CMD8(0x1AA) */
252
+  xchg_spi(n);
253
+
254
+  /* Receive command resp */
255
+  if (cmd == CMD12) xchg_spi(0xFF); /* Diacard following one byte when CMD12 */
256
+  n = 10;               /* Wait for response (10 bytes max) */
257
+  do
258
+    res = xchg_spi(0xFF);
259
+  while ((res & 0x80) && --n);
260
+
261
+  return res;             /* Return received response */
262
+}
263
+
264
+/*--------------------------------------------------------------------------
265
+   Public Functions
266
+---------------------------------------------------------------------------*/
267
+
268
+/*-----------------------------------------------------------------------*/
269
+/* Initialize disk drive                                                 */
270
+/*-----------------------------------------------------------------------*/
271
+
272
+DSTATUS disk_initialize (
273
+  BYTE drv    /* Physical drive number (0) */
274
+) {
275
+  BYTE n, cmd, ty, ocr[4];
276
+
277
+  if (drv) return STA_NOINIT;     /* Supports only drive 0 */
278
+  power_on();             /* Initialize SPI */
279
+
280
+  if (Stat & STA_NODISK) return Stat; /* Is a card existing in the soket? */
281
+
282
+  FCLK_SLOW();
283
+  for (n = 10; n; n--) xchg_spi(0xFF);  /* Send 80 dummy clocks */
284
+
285
+  ty = 0;
286
+  if (send_cmd(CMD0, 0) == 1) {     /* Put the card SPI state */
287
+    timeout = millis() + 1000;            /* Initialization timeout = 1 sec */
288
+    if (send_cmd(CMD8, 0x1AA) == 1) { /* Is the catd SDv2? */
289
+      for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);  /* Get 32 bit return value of R7 resp */
290
+      if (ocr[2] == 0x01 && ocr[3] == 0xAA) {       /* Does the card support 2.7-3.6V? */
291
+        while ((timeout > millis()) && send_cmd(ACMD41, 1UL << 30)) ; /* Wait for end of initialization with ACMD41(HCS) */
292
+        if ((timeout > millis()) && send_cmd(CMD58, 0) == 0) {    /* Check CCS bit in the OCR */
293
+          for (n = 0; n < 4; n++) ocr[n] = xchg_spi(0xFF);
294
+          ty = (ocr[0] & 0x40) ? CT_SD2 | CT_BLOCK : CT_SD2;  /* Check if the card is SDv2 */
295
+        }
296
+      }
297
+    } else {  /* Not an SDv2 card */
298
+      if (send_cmd(ACMD41, 0) <= 1)   { /* SDv1 or MMCv3? */
299
+        ty = CT_SD1; cmd = ACMD41;  /* SDv1 (ACMD41(0)) */
300
+      } else {
301
+        ty = CT_MMC; cmd = CMD1;  /* MMCv3 (CMD1(0)) */
302
+      }
303
+      while ((timeout > millis()) && send_cmd(cmd, 0)) ;    /* Wait for the card leaves idle state */
304
+      if (!(timeout > millis()) || send_cmd(CMD16, 512) != 0) /* Set block length: 512 */
305
+        ty = 0;
306
+    }
307
+  }
308
+  CardType = ty;  /* Card type */
309
+  deselect();
310
+
311
+  if (ty) {   /* OK */
312
+    FCLK_FAST();      /* Set fast clock */
313
+    Stat &= ~STA_NOINIT;  /* Clear STA_NOINIT flag */
314
+  } else {    /* Failed */
315
+    power_off();
316
+    Stat = STA_NOINIT;
317
+  }
318
+
319
+  return Stat;
320
+}
321
+
322
+/*-----------------------------------------------------------------------*/
323
+/* Get disk status                                                       */
324
+/*-----------------------------------------------------------------------*/
325
+
326
+DSTATUS disk_status (
327
+  BYTE drv    /* Physical drive number (0) */
328
+) {
329
+  if (drv) return STA_NOINIT;   /* Supports only drive 0 */
330
+  return Stat;  /* Return disk status */
331
+}
332
+
333
+/*-----------------------------------------------------------------------*/
334
+/* Read sector(s)                                                        */
335
+/*-----------------------------------------------------------------------*/
336
+
337
+DRESULT disk_read (
338
+  BYTE drv,   /* Physical drive number (0) */
339
+  BYTE *buff,   /* Pointer to the data buffer to store read data */
340
+  DWORD sector, /* Start sector number (LBA) */
341
+  UINT count    /* Number of sectors to read (1..128) */
342
+) {
343
+  BYTE cmd;
344
+
345
+  if (drv || !count) return RES_PARERR;   /* Check parameter */
346
+  if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */
347
+  if (!(CardType & CT_BLOCK)) sector *= 512;  /* LBA ot BA conversion (byte addressing cards) */
348
+  FCLK_FAST();
349
+  cmd = count > 1 ? CMD18 : CMD17;      /*  READ_MULTIPLE_BLOCK : READ_SINGLE_BLOCK */
350
+  if (send_cmd(cmd, sector) == 0) {
351
+    do {
352
+      if (!rcvr_datablock(buff, 512)) break;
353
+      buff += 512;
354
+    } while (--count);
355
+    if (cmd == CMD18) send_cmd(CMD12, 0); /* STOP_TRANSMISSION */
356
+  }
357
+  deselect();
358
+
359
+  return count ? RES_ERROR : RES_OK;  /* Return result */
360
+}
361
+
362
+/*-----------------------------------------------------------------------*/
363
+/* Write sector(s)                                                       */
364
+/*-----------------------------------------------------------------------*/
365
+
366
+#if _DISKIO_WRITE
367
+
368
+  DRESULT disk_write(
369
+    BYTE drv,     /* Physical drive number (0) */
370
+    const BYTE *buff, /* Ponter to the data to write */
371
+    DWORD sector,   /* Start sector number (LBA) */
372
+    UINT count      /* Number of sectors to write (1..128) */
373
+  ) {
374
+    if (drv || !count) return RES_PARERR;   /* Check parameter */
375
+    if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check drive status */
376
+    if (Stat & STA_PROTECT) return RES_WRPRT; /* Check write protect */
377
+    FCLK_FAST();
378
+    if (!(CardType & CT_BLOCK)) sector *= 512;  /* LBA ==> BA conversion (byte addressing cards) */
379
+
380
+    if (count == 1) { /* Single sector write */
381
+      if ((send_cmd(CMD24, sector) == 0)  /* WRITE_BLOCK */
382
+        && xmit_datablock(buff, 0xFE)) {
383
+        count = 0;
384
+      }
385
+    }
386
+    else {        /* Multiple sector write */
387
+      if (CardType & CT_SDC) send_cmd(ACMD23, count); /* Predefine number of sectors */
388
+      if (send_cmd(CMD25, sector) == 0) { /* WRITE_MULTIPLE_BLOCK */
389
+        do {
390
+          if (!xmit_datablock(buff, 0xFC)) break;
391
+          buff += 512;
392
+        } while (--count);
393
+        if (!xmit_datablock(0, 0xFD)) count = 1;  /* STOP_TRAN token */
394
+      }
395
+    }
396
+    deselect();
397
+
398
+    return count ? RES_ERROR : RES_OK;  /* Return result */
399
+  }
400
+
401
+#endif // _DISKIO_WRITE
402
+
403
+/*-----------------------------------------------------------------------*/
404
+/* Miscellaneous drive controls other than data read/write               */
405
+/*-----------------------------------------------------------------------*/
406
+
407
+#if _DISKIO_IOCTL
408
+
409
+  DRESULT disk_ioctl (
410
+    BYTE drv,   /* Physical drive number (0) */
411
+    BYTE cmd,   /* Control command code */
412
+    void *buff    /* Pointer to the conrtol data */
413
+  ) {
414
+    DRESULT res;
415
+    BYTE n, csd[16], *ptr = (BYTE *)buff;
416
+    DWORD *dp, st, ed, csize;
417
+    #if _DISKIO_ISDIO
418
+      SDIO_CMD *sdio = buff;
419
+      BYTE rc, *buf;
420
+      UINT dc;
421
+    #endif
422
+
423
+    if (drv) return RES_PARERR;         /* Check parameter */
424
+    if (Stat & STA_NOINIT) return RES_NOTRDY; /* Check if drive is ready */
425
+
426
+    res = RES_ERROR;
427
+    FCLK_FAST();
428
+    switch (cmd) {
429
+      case CTRL_SYNC:     /* Wait for end of internal write process of the drive */
430
+        if (select()) res = RES_OK;
431
+        break;
432
+
433
+      case GET_SECTOR_COUNT:  /* Get drive capacity in unit of sector (DWORD) */
434
+        if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {
435
+          if ((csd[0] >> 6) == 1) { /* SDC ver 2.00 */
436
+            csize = csd[9] + ((WORD)csd[8] << 8) + ((DWORD)(csd[7] & 63) << 16) + 1;
437
+            *(DWORD*)buff = csize << 10;
438
+          } else {          /* SDC ver 1.XX or MMC ver 3 */
439
+            n = (csd[5] & 15) + ((csd[10] & 128) >> 7) + ((csd[9] & 3) << 1) + 2;
440
+            csize = (csd[8] >> 6) + ((WORD)csd[7] << 2) + ((WORD)(csd[6] & 3) << 10) + 1;
441
+            *(DWORD*)buff = csize << (n - 9);
442
+          }
443
+          res = RES_OK;
444
+        }
445
+        break;
446
+
447
+      case GET_BLOCK_SIZE:  /* Get erase block size in unit of sector (DWORD) */
448
+        if (CardType & CT_SD2) {  /* SDC ver 2.00 */
449
+          if (send_cmd(ACMD13, 0) == 0) { /* Read SD status */
450
+            xchg_spi(0xFF);
451
+            if (rcvr_datablock(csd, 16)) {        /* Read partial block */
452
+              for (n = 64 - 16; n; n--) xchg_spi(0xFF); /* Purge trailing data */
453
+              *(DWORD*)buff = 16UL << (csd[10] >> 4);
454
+              res = RES_OK;
455
+            }
456
+          }
457
+        } else {          /* SDC ver 1.XX or MMC */
458
+          if ((send_cmd(CMD9, 0) == 0) && rcvr_datablock(csd, 16)) {  /* Read CSD */
459
+            if (CardType & CT_SD1) {  /* SDC ver 1.XX */
460
+              *(DWORD*)buff = (((csd[10] & 63) << 1) + ((WORD)(csd[11] & 128) >> 7) + 1) << ((csd[13] >> 6) - 1);
461
+            } else {          /* MMC */
462
+              *(DWORD*)buff = ((WORD)((csd[10] & 124) >> 2) + 1) * (((csd[11] & 3) << 3) + ((csd[11] & 224) >> 5) + 1);
463
+            }
464
+            res = RES_OK;
465
+          }
466
+        }
467
+        break;
468
+
469
+      case CTRL_TRIM:   /* Erase a block of sectors (used when _USE_TRIM in ffconf.h is 1) */
470
+        if (!(CardType & CT_SDC)) break;        /* Check if the card is SDC */
471
+        if (disk_ioctl(drv, MMC_GET_CSD, csd)) break; /* Get CSD */
472
+        if (!(csd[0] >> 6) && !(csd[10] & 0x40)) break; /* Check if sector erase can be applied to the card */
473
+        dp = (DWORD *)buff; st = dp[0]; ed = dp[1];       /* Load sector block */
474
+        if (!(CardType & CT_BLOCK)) {
475
+          st *= 512; ed *= 512;
476
+        }
477
+        if (send_cmd(CMD32, st) == 0 && send_cmd(CMD33, ed) == 0 && send_cmd(CMD38, 0) == 0 && wait_ready(30000)) { /* Erase sector block */
478
+          res = RES_OK; /* FatFs does not check result of this command */
479
+        }
480
+        break;
481
+
482
+      /* Following commands are never used by FatFs module */
483
+
484
+      case MMC_GET_TYPE:    /* Get MMC/SDC type (BYTE) */
485
+        *ptr = CardType;
486
+        res = RES_OK;
487
+        break;
488
+
489
+      case MMC_GET_CSD:   /* Read CSD (16 bytes) */
490
+        if (send_cmd(CMD9, 0) == 0 && rcvr_datablock(ptr, 16)) {  /* READ_CSD */
491
+          res = RES_OK;
492
+        }
493
+        break;
494
+
495
+      case MMC_GET_CID:   /* Read CID (16 bytes) */
496
+        if (send_cmd(CMD10, 0) == 0 && rcvr_datablock(ptr, 16)) { /* READ_CID */
497
+          res = RES_OK;
498
+        }
499
+        break;
500
+
501
+      case MMC_GET_OCR:   /* Read OCR (4 bytes) */
502
+        if (send_cmd(CMD58, 0) == 0) {  /* READ_OCR */
503
+          for (n = 4; n; n--) *ptr++ = xchg_spi(0xFF);
504
+          res = RES_OK;
505
+        }
506
+        break;
507
+
508
+      case MMC_GET_SDSTAT:  /* Read SD status (64 bytes) */
509
+        if (send_cmd(ACMD13, 0) == 0) { /* SD_STATUS */
510
+          xchg_spi(0xFF);
511
+          if (rcvr_datablock(ptr, 64)) res = RES_OK;
512
+        }
513
+        break;
514
+
515
+      #if _DISKIO_ISDIO
516
+
517
+        case ISDIO_READ:
518
+          sdio = buff;
519
+          if (send_cmd(CMD48, 0x80000000 | sdio->func << 28 | sdio->addr << 9 | ((sdio->ndata - 1) & 0x1FF)) == 0) {
520
+            for (Timer1 = 1000; (rc = xchg_spi(0xFF)) == 0xFF && Timer1; ) ;
521
+            if (rc == 0xFE) {
522
+              for (buf = sdio->data, dc = sdio->ndata; dc; dc--) *buf++ = xchg_spi(0xFF);
523
+              for (dc = 514 - sdio->ndata; dc; dc--) xchg_spi(0xFF);
524
+              res = RES_OK;
525
+            }
526
+          }
527
+          break;
528
+        case ISDIO_WRITE:
529
+          sdio = buff;
530
+          if (send_cmd(CMD49, 0x80000000 | sdio->func << 28 | sdio->addr << 9 | ((sdio->ndata - 1) & 0x1FF)) == 0) {
531
+            xchg_spi(0xFF); xchg_spi(0xFE);
532
+            for (buf = sdio->data, dc = sdio->ndata; dc; dc--) xchg_spi(*buf++);
533
+            for (dc = 514 - sdio->ndata; dc; dc--) xchg_spi(0xFF);
534
+            if ((xchg_spi(0xFF) & 0x1F) == 0x05) res = RES_OK;
535
+          }
536
+          break;
537
+        case ISDIO_MRITE:
538
+          sdio = buff;
539
+          if (send_cmd(CMD49, 0x84000000 | sdio->func << 28 | sdio->addr << 9 | sdio->ndata >> 8) == 0) {
540
+            xchg_spi(0xFF); xchg_spi(0xFE);
541
+            xchg_spi(sdio->ndata);
542
+            for (dc = 513; dc; dc--) xchg_spi(0xFF);
543
+            if ((xchg_spi(0xFF) & 0x1F) == 0x05) res = RES_OK;
544
+          }
545
+          break;
546
+
547
+      #endif // _DISKIO_ISDIO
548
+
549
+      default: res = RES_PARERR;
550
+    }
551
+
552
+    deselect();
553
+    return res;
554
+  }
555
+
556
+#endif // _DISKIO_IOCTL
557
+
558
+#endif // HAS_ONBOARD_SD

+ 96
- 0
Marlin/src/HAL/HAL_STM32F1/onboard_sd.h View File

@@ -0,0 +1,96 @@
1
+/*-----------------------------------------------------------------------
2
+/ * Copyright (c) 2019 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
3
+/ * Copyright (c) 2019 BigTreeTech [https://github.com/bigtreetech]
4
+/ * Low level disk interface module include file   (C)ChaN, 2015
5
+/-----------------------------------------------------------------------*/
6
+
7
+#pragma once
8
+
9
+#define _DISKIO_WRITE   1   /* 1: Enable disk_write function */
10
+#define _DISKIO_IOCTL   1   /* 1: Enable disk_ioctl fucntion */
11
+#define _DISKIO_ISDIO   0   /* 1: Enable iSDIO control fucntion */
12
+
13
+typedef unsigned char BYTE;
14
+typedef unsigned short WORD;
15
+typedef unsigned long DWORD;
16
+typedef unsigned int UINT;
17
+
18
+/* Status of Disk Functions */
19
+typedef BYTE    DSTATUS;
20
+
21
+/* Results of Disk Functions */
22
+typedef enum {
23
+  RES_OK = 0,     /* 0: Successful */
24
+  RES_ERROR,      /* 1: R/W Error */
25
+  RES_WRPRT,      /* 2: Write Protected */
26
+  RES_NOTRDY,     /* 3: Not Ready */
27
+  RES_PARERR      /* 4: Invalid Parameter */
28
+} DRESULT;
29
+
30
+
31
+#if _DISKIO_ISDIO
32
+/* Command structure for iSDIO ioctl command */
33
+typedef struct {
34
+ BYTE    func;   /* Function number: 0..7 */
35
+ WORD    ndata;  /* Number of bytes to transfer: 1..512, or mask + data */
36
+ DWORD   addr;   /* Register address: 0..0x1FFFF */
37
+ void*   data;   /* Pointer to the data (to be written | read buffer) */
38
+} SDIO_CMD;
39
+#endif
40
+
41
+/*---------------------------------------*/
42
+/* Prototypes for disk control functions */
43
+
44
+DSTATUS disk_initialize(BYTE pdrv);
45
+DSTATUS disk_status(BYTE pdrv);
46
+DRESULT disk_read(BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
47
+#if _DISKIO_WRITE
48
+  DRESULT disk_write(BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
49
+#endif
50
+#if _DISKIO_IOCTL
51
+  DRESULT disk_ioctl(BYTE pdrv, BYTE cmd, void* buff);
52
+#endif
53
+
54
+/* Disk Status Bits (DSTATUS) */
55
+#define STA_NOINIT      0x01    /* Drive not initialized */
56
+#define STA_NODISK      0x02    /* No medium in the drive */
57
+#define STA_PROTECT     0x04    /* Write protected */
58
+
59
+/* Command code for disk_ioctrl fucntion */
60
+
61
+/* Generic command (Used by FatFs) */
62
+#define CTRL_SYNC        0  /* Complete pending write process (needed at _FS_READONLY == 0) */
63
+#define GET_SECTOR_COUNT 1  /* Get media size (needed at _USE_MKFS == 1) */
64
+#define GET_SECTOR_SIZE  2  /* Get sector size (needed at _MAX_SS != _MIN_SS) */
65
+#define GET_BLOCK_SIZE   3  /* Get erase block size (needed at _USE_MKFS == 1) */
66
+#define CTRL_TRIM        4  /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */
67
+
68
+/* Generic command (Not used by FatFs) */
69
+#define CTRL_FORMAT      5  /* Create physical format on the media */
70
+#define CTRL_POWER_IDLE  6  /* Put the device idle state */
71
+#define CTRL_POWER_OFF   7  /* Put the device off state */
72
+#define CTRL_LOCK        8  /* Lock media removal */
73
+#define CTRL_UNLOCK      9  /* Unlock media removal */
74
+#define CTRL_EJECT      10  /* Eject media */
75
+
76
+/* MMC/SDC specific ioctl command (Not used by FatFs) */
77
+#define MMC_GET_TYPE    50  /* Get card type */
78
+#define MMC_GET_CSD     51  /* Get CSD */
79
+#define MMC_GET_CID     52  /* Get CID */
80
+#define MMC_GET_OCR     53  /* Get OCR */
81
+#define MMC_GET_SDSTAT  54  /* Get SD status */
82
+#define ISDIO_READ      55  /* Read data form SD iSDIO register */
83
+#define ISDIO_WRITE     56  /* Write data to SD iSDIO register */
84
+#define ISDIO_MRITE     57  /* Masked write data to SD iSDIO register */
85
+
86
+/* ATA/CF specific ioctl command (Not used by FatFs) */
87
+#define ATA_GET_REV     60  /* Get F/W revision */
88
+#define ATA_GET_MODEL   61  /* Get model name */
89
+#define ATA_GET_SN      62  /* Get serial number */
90
+
91
+/* MMC card type flags (MMC_GET_TYPE) */
92
+#define CT_MMC      0x01        /* MMC ver 3 */
93
+#define CT_SD1      0x02        /* SD ver 1 */
94
+#define CT_SD2      0x04        /* SD ver 2 */
95
+#define CT_SDC      (CT_SD1|CT_SD2) /* SD */
96
+#define CT_BLOCK    0x08        /* Block addressing */

+ 3
- 3
Marlin/src/lcd/extensible_ui/lib/lulzbot/ftdi_eve_lib/basic/commands.cpp View File

@@ -1105,9 +1105,9 @@ void CLCD::init (void) {
1105 1105
   mem_write_8(REG::CSPREAD,  FTDI::CSpread);
1106 1106
 
1107 1107
   /* write a basic display-list to get things started */
1108
-	mem_write_32(MAP::RAM_DL,      DL::CLEAR_COLOR_RGB);
1109
-	mem_write_32(MAP::RAM_DL + 4, (DL::CLEAR | 0x07)); /* clear color, stencil and tag buffer */
1110
-	mem_write_32(MAP::RAM_DL + 8,  DL::DL_DISPLAY);	/* end of display list */
1108
+  mem_write_32(MAP::RAM_DL,      DL::CLEAR_COLOR_RGB);
1109
+  mem_write_32(MAP::RAM_DL + 4, (DL::CLEAR | 0x07)); /* clear color, stencil and tag buffer */
1110
+  mem_write_32(MAP::RAM_DL + 8,  DL::DL_DISPLAY);    /* end of display list */
1111 1111
 
1112 1112
   mem_write_8(REG::DLSWAP, 0x02); // activate display list, Bad Magic Cookie 2 = switch to new list after current frame is scanned out
1113 1113
 

+ 12
- 0
Marlin/src/pins/stm32/pins_BIGTREE_SKR_E3_DIP.h View File

@@ -187,3 +187,15 @@
187 187
   #endif
188 188
 
189 189
 #endif // HAS_SPI_LCD
190
+
191
+//
192
+// SD Support
193
+//
194
+#define HAS_ONBOARD_SD
195
+
196
+#ifndef SDCARD_CONNECTION
197
+  #define SDCARD_CONNECTION ONBOARD
198
+#endif
199
+
200
+#define ON_BOARD_SPI_DEVICE 1    //SPI1
201
+#define ONBOARD_SD_CS_PIN  PA4   // Chip select for "System" SD card

+ 12
- 0
Marlin/src/pins/stm32/pins_BIGTREE_SKR_MINI_E3.h View File

@@ -142,3 +142,15 @@
142 142
   #endif
143 143
 
144 144
 #endif // HAS_SPI_LCD
145
+
146
+//
147
+// SD Support
148
+//
149
+#define HAS_ONBOARD_SD
150
+
151
+#ifndef SDCARD_CONNECTION
152
+  #define SDCARD_CONNECTION ONBOARD
153
+#endif
154
+
155
+#define ON_BOARD_SPI_DEVICE 1    //SPI1
156
+#define ONBOARD_SD_CS_PIN  PA4   // Chip select for "System" SD card

+ 9
- 7
Marlin/src/pins/stm32/pins_BIGTREE_SKR_MINI_V1_1.h View File

@@ -160,20 +160,20 @@
160 160
 //
161 161
 
162 162
 // By default the onboard SD is enabled.
163
-// To disable it and use an external SD (connected to LCD)
164
-// enable STM32_SD_LCD.
165
-
166
-//#define STM32_SD_LCD
163
+// set SDCARD_CONNECTION form 'ONBOARD' to 'LCD' and use an external SD (connected to LCD)
164
+#define HAS_ONBOARD_SD
165
+#ifndef SDCARD_CONNECTION
166
+  #define SDCARD_CONNECTION ONBOARD
167
+#endif
167 168
 
168
-#if ENABLED(STM32_SD_LCD)
169
+#if SD_CONNECTION_IS(LCD)
169 170
   #define ENABLE_SPI3
170 171
   #define SD_DETECT_PIN    PB9
171 172
   #define SCK_PIN          PB3
172 173
   #define MISO_PIN         PB4
173 174
   #define MOSI_PIN         PB5
174 175
   #define SS_PIN           PA15
175
-#else
176
-  #define SDCARD_CONNECTION ONBOARD
176
+#if SD_CONNECTION_IS(ONBOARD)
177 177
   #define ENABLE_SPI1
178 178
   #define SD_DETECT_PIN    PA3
179 179
   #define SCK_PIN          PA5
@@ -181,6 +181,8 @@
181 181
   #define MOSI_PIN         PA7
182 182
   #define SS_PIN           PA4
183 183
 #endif
184
+#define ON_BOARD_SPI_DEVICE 1    //SPI1
185
+#define ONBOARD_SD_CS_PIN  PA4   // Chip select for "System" SD card
184 186
 
185 187
 #ifndef ST7920_DELAY_1
186 188
   #define ST7920_DELAY_1 DELAY_NS(125)

+ 1
- 1
Marlin/src/sd/usb_flashdrive/lib-uhs3/UHS_host/UHS_USB_IDs.h View File

@@ -77,7 +77,7 @@
77 77
 #define UHS_VID_OPTI 0x03fbU // OPTi, Inc.
78 78
 #define UHS_VID_ELITEGROUP_COMPUTER_SYSTEMS 0x03fcU // Elitegroup Computer Systems
79 79
 #define UHS_VID_XILINX 0x03fdU // Xilinx, Inc.
80
-#define UHS_VID_FARALLON_COMUNICATIONS 0x03feU // Farallon Comunications
80
+#define UHS_VID_FARALLON_COMUNICATIONS 0x03feU // Farallon Communications
81 81
 #define UHS_VID_NATIONAL_SEMICONDUCTOR 0x0400U // National Semiconductor Corp.
82 82
 #define UHS_VID_NATIONAL_REGISTRY 0x0401U // National Registry, Inc.
83 83
 #define UHS_VID_ALI 0x0402U // ALi Corp.

+ 1
- 1
platformio.ini View File

@@ -304,7 +304,7 @@ platform_packages = tool-stm32duino
304 304
 extra_scripts     = buildroot/share/PlatformIO/scripts/STM32F1_SKR_MINI.py
305 305
 build_flags       = !python Marlin/src/HAL/HAL_STM32F1/build_flags.py
306 306
   ${common.build_flags} -std=gnu++14
307
-  -DDEBUG_LEVEL=0
307
+  -DDEBUG_LEVEL=0 -DUSE_USB_COMPOSITE
308 308
 build_unflags     = -std=gnu++11
309 309
 lib_deps          = ${common.lib_deps}
310 310
 lib_ignore        = Adafruit NeoPixel, SPI

Loading…
Cancel
Save