2 * This file is part of Cleanflight and Betaflight.
4 * Cleanflight and Betaflight are free software. You can redistribute
5 * this software and/or modify this software under the terms of the
6 * GNU General Public License as published by the Free Software
7 * Foundation, either version 3 of the License, or (at your option)
10 * Cleanflight and Betaflight are distributed in the hope that they
11 * will be useful, but WITHOUT ANY WARRANTY; without even the implied
12 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this software.
18 * If not, see <http://www.gnu.org/licenses/>.
22 * Author: Chris Hockuba (https://github.com/conkerkh)
32 #if defined(USE_USB_MSC)
34 #include "build/build_config.h"
36 #include "common/utils.h"
38 #include "blackbox/blackbox.h"
39 #include "blackbox/blackbox_io.h"
41 #include "drivers/io.h"
42 #include "drivers/light_led.h"
43 #include "drivers/nvic.h"
44 #include "drivers/persistent.h"
45 #include "drivers/sdcard/sdmmc_sdio.h"
46 #include "drivers/time.h"
47 #include "drivers/usb_msc.h"
52 #include "msc_class.h"
56 #define DEBOUNCE_TIME_MS 20
58 extern otg_core_type otg_core_struct
;
61 #if defined(MSC_USE_BUTTON)
62 static IO_t mscButton
;
67 #if defined(MSC_USE_BUTTON)
68 if (usbDevConfig()->mscButtonPin
) {
69 mscButton
= IOGetByTag(usbDevConfig()->mscButtonPin
);
70 IOInit(mscButton
, OWNER_USB_MSC_PIN
, 0);
71 if (usbDevConfig()->mscButtonUsePullup
) {
72 IOConfigGPIO(mscButton
, IOCFG_IPU
);
74 IOConfigGPIO(mscButton
, IOCFG_IPD
);
82 * @brief this function config gpio.
86 void msc_usb_gpio_config(void)
88 gpio_init_type gpio_init_struct
;
90 crm_periph_clock_enable(OTG_PIN_GPIO_CLOCK
, TRUE
);
91 gpio_default_para_init(&gpio_init_struct
);
93 gpio_init_struct
.gpio_drive_strength
= GPIO_DRIVE_STRENGTH_STRONGER
;
94 gpio_init_struct
.gpio_out_type
= GPIO_OUTPUT_PUSH_PULL
;
95 gpio_init_struct
.gpio_mode
= GPIO_MODE_MUX
;
96 gpio_init_struct
.gpio_pull
= GPIO_PULL_NONE
;
99 gpio_init_struct
.gpio_pins
= OTG_PIN_DP
| OTG_PIN_DM
;
100 gpio_init(OTG_PIN_GPIO
, &gpio_init_struct
);
102 gpio_pin_mux_config(OTG_PIN_GPIO
, OTG_PIN_DP_SOURCE
, OTG_PIN_MUX
);
103 gpio_pin_mux_config(OTG_PIN_GPIO
, OTG_PIN_DM_SOURCE
, OTG_PIN_MUX
);
105 #ifdef USB_SOF_OUTPUT_ENABLE
106 crm_periph_clock_enable(OTG_PIN_SOF_GPIO_CLOCK
, TRUE
);
107 gpio_init_struct
.gpio_pins
= OTG_PIN_SOF
;
108 gpio_init(OTG_PIN_SOF_GPIO
, &gpio_init_struct
);
109 gpio_pin_mux_config(OTG_PIN_GPIO
, OTG_PIN_SOF_SOURCE
, OTG_PIN_MUX
);
112 /* otgfs use vbus pin */
113 #ifndef USB_VBUS_IGNORE
114 gpio_init_struct
.gpio_pins
= OTG_PIN_VBUS
;
115 gpio_init_struct
.gpio_pull
= GPIO_PULL_DOWN
;
116 gpio_pin_mux_config(OTG_PIN_GPIO
, OTG_PIN_VBUS_SOURCE
, OTG_PIN_MUX
);
117 gpio_init(OTG_PIN_GPIO
, &gpio_init_struct
);
124 * @brief usb 48M clock select
125 * @param clk_s:USB_CLK_HICK, USB_CLK_HEXT
128 void msc_usb_clock48m_select(usb_clk48_s clk_s
)
130 if(clk_s
== USB_CLK_HICK
)
132 crm_usb_clock_source_select(CRM_USB_CLOCK_SOURCE_HICK
);
134 /* enable the acc calibration ready interrupt */
135 crm_periph_clock_enable(CRM_ACC_PERIPH_CLOCK
, TRUE
);
137 /* update the c1\c2\c3 value */
142 acc_sof_select(ACC_SOF_OTG1
);
144 acc_sof_select(ACC_SOF_OTG2
);
146 /* open acc calibration */
147 acc_calibration_mode_enable(ACC_CAL_HICKTRIM
, TRUE
);
151 switch(system_core_clock
)
155 crm_usb_clock_div_set(CRM_USB_DIV_1
);
160 crm_usb_clock_div_set(CRM_USB_DIV_1_5
);
165 crm_usb_clock_div_set(CRM_USB_DIV_2
);
170 crm_usb_clock_div_set(CRM_USB_DIV_2_5
);
175 crm_usb_clock_div_set(CRM_USB_DIV_3
);
180 crm_usb_clock_div_set(CRM_USB_DIV_3_5
);
185 crm_usb_clock_div_set(CRM_USB_DIV_4
);
190 crm_usb_clock_div_set(CRM_USB_DIV_4_5
);
195 crm_usb_clock_div_set(CRM_USB_DIV_5
);
200 crm_usb_clock_div_set(CRM_USB_DIV_5_5
);
205 crm_usb_clock_div_set(CRM_USB_DIV_6
);
216 uint8_t mscStart(void)
221 usbGenerateDisconnectPulse();
223 IOInit(IOGetByTag(IO_TAG(PA11
)), OWNER_USB
, 0, 0);
224 IOInit(IOGetByTag(IO_TAG(PA12
)), OWNER_USB
, 0, 0);
226 // The SD card is not supported
227 /* switch (blackboxConfig()->device) {
229 case BLACKBOX_DEVICE_SDCARD:
230 USBD_STORAGE_fops = &USBD_MSC_MICRO_SDIO_fops;
235 case BLACKBOX_DEVICE_FLASH:
236 USBD_STORAGE_fops = &USBD_MSC_EMFAT_fops;
245 /* usb gpio config */
246 msc_usb_gpio_config();
248 /* enable otgfs clock */
249 crm_periph_clock_enable(OTG_CLOCK
, TRUE
);
251 /* select usb 48m clcok source */
252 msc_usb_clock48m_select(USB_CLK_HEXT
);
254 /* enable otgfs irq,Priority NVIC_PRIO_USB must be used */
255 nvic_irq_enable(OTG_IRQ
, NVIC_PRIO_USB
, 0);
257 usbd_init(&otg_core_struct
,
258 USB_FULL_SPEED_CORE_ID
,
263 // NVIC configuration for SYSTick
264 nvic_irq_disable(SysTick_IRQn
);
266 nvic_irq_enable(SysTick_IRQn
, 0, 0);
270 bool mscCheckButton(void)
273 #if defined(MSC_USE_BUTTON)
275 uint8_t state
= IORead(mscButton
);
276 if (usbDevConfig()->mscButtonUsePullup
) {
286 void mscWaitForButton(void)
288 // In order to exit MSC mode simply disconnect the board, or push the button again.
289 while (mscCheckButton());
290 delay(DEBOUNCE_TIME_MS
);
293 if (mscCheckButton()) {