Commit 038df431 authored by Damien George's avatar Damien George
Browse files

stmhal: Implement selector for USB device mode; improve boot up.

Can now choose at boot up whether the USB device is CDC+MSC or CDC+HID.
Choice is made by an option in boot.py, with default being CDC+MSC.
HID+MSC is not currently supported, but should be easy to implement.

Boot up now has ability to change the reset mode: hold down USR switch
while booting and LEDs will count from 1 to 7 to indicate the boot mode.
Release USR when correct mode is selected.  Current modes are 1 (normal
boot), 2 (safe mode), 3 (reset FS mode).
parent d40d8f1e
......@@ -21,7 +21,7 @@ INC += -I$(PY_SRC)
INC += -I$(CMSIS_DIR)/inc
INC += -I$(CMSIS_DIR)/devinc
INC += -I$(HAL_DIR)/inc
INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/cdc_msc/inc
INC += -I$(USBDEV_DIR)/core/inc -I$(USBDEV_DIR)/class/cdc_msc_hid/inc
#INC += -I$(USBHOST_DIR)
INC += -I$(FATFS_DIR)/src
#INC += -I$(CC3K_DIR)
......@@ -135,10 +135,10 @@ SRC_USBDEV = $(addprefix $(USBDEV_DIR)/,\
core/src/usbd_core.c \
core/src/usbd_ctlreq.c \
core/src/usbd_ioreq.c \
class/cdc_msc/src/usbd_cdc_msc.c \
class/cdc_msc/src/usbd_msc_bot.c \
class/cdc_msc/src/usbd_msc_scsi.c \
class/cdc_msc/src/usbd_msc_data.c \
class/cdc_msc_hid/src/usbd_cdc_msc_hid.c \
class/cdc_msc_hid/src/usbd_msc_bot.c \
class/cdc_msc_hid/src/usbd_msc_scsi.c \
class/cdc_msc_hid/src/usbd_msc_data.c \
)
# class/cdc/src/usbd_cdc.c \
......
#include <stdio.h>
#include <stm32f4xx_hal.h>
#include "usbd_cdc_msc.h"
#include "usbd_cdc_msc_hid.h"
#include "usbd_cdc_interface.h"
#include "nlr.h"
......
......@@ -75,6 +75,7 @@ void __fatal_error(const char *msg) {
STATIC mp_obj_t pyb_config_source_dir = MP_OBJ_NULL;
STATIC mp_obj_t pyb_config_main = MP_OBJ_NULL;
STATIC mp_obj_t pyb_config_usb_mode = MP_OBJ_NULL;
STATIC mp_obj_t pyb_source_dir(mp_obj_t source_dir) {
if (MP_OBJ_IS_STR(source_dir)) {
......@@ -94,6 +95,15 @@ STATIC mp_obj_t pyb_main(mp_obj_t main) {
MP_DEFINE_CONST_FUN_OBJ_1(pyb_main_obj, pyb_main);
STATIC mp_obj_t pyb_usb_mode(mp_obj_t usb_mode) {
if (MP_OBJ_IS_STR(usb_mode)) {
pyb_config_usb_mode = usb_mode;
}
return mp_const_none;
}
MP_DEFINE_CONST_FUN_OBJ_1(pyb_usb_mode_obj, pyb_usb_mode);
void fatality(void) {
led_state(PYB_LED_R1, 1);
led_state(PYB_LED_G1, 1);
......@@ -109,12 +119,9 @@ static const char fresh_boot_py[] =
"# can run arbitrary Python, but best to keep it minimal\n"
"\n"
"import pyb\n"
"pyb.source_dir('/src')\n"
"pyb.main('main.py')\n"
"#pyb.usb_usr('VCP')\n"
"#pyb.usb_msd(True, 'dual partition')\n"
"#pyb.flush_cache(False)\n"
"#pyb.error_log('error.txt')\n"
"#pyb.source_dir('/src')\n"
"#pyb.main('main.py')\n"
"#pyb.usb_mode('CDC+MSC') # one of: 'CDC+MSC', 'CDC+HID'\n"
;
static const char fresh_main_py[] =
......@@ -171,23 +178,64 @@ int main(void) {
// basic sub-system init
pendsv_init();
led_init();
switch_init0();
// turn on LED to indicate bootup
led_state(PYB_LED_GREEN, 1);
int first_soft_reset = true;
uint reset_mode;
soft_reset:
// check if user switch held to select the reset mode
reset_mode = 1;
led_state(1, 0);
led_state(2, 1);
led_state(3, 0);
led_state(4, 0);
#if MICROPY_HW_HAS_SWITCH
if (switch_get()) {
for (uint i = 0; i < 3000; i++) {
if (!switch_get()) {
break;
}
HAL_Delay(20);
if (i % 30 == 29) {
reset_mode = (reset_mode + 1) & 7;
led_state(2, reset_mode & 1);
led_state(3, reset_mode & 2);
led_state(4, reset_mode & 4);
}
}
// flash the selected reset mode
for (uint i = 0; i < 6; i++) {
led_state(2, 0);
led_state(3, 0);
led_state(4, 0);
HAL_Delay(50);
led_state(2, reset_mode & 1);
led_state(3, reset_mode & 2);
led_state(4, reset_mode & 4);
HAL_Delay(50);
}
HAL_Delay(400);
}
#endif
#if MICROPY_HW_ENABLE_RTC
rtc_init();
if (first_soft_reset) {
rtc_init();
}
#endif
// more sub-system init
#if MICROPY_HW_HAS_SDCARD
sdcard_init();
if (first_soft_reset) {
sdcard_init();
}
#endif
storage_init();
int first_soft_reset = true;
soft_reset:
if (first_soft_reset) {
storage_init();
}
// GC init
gc_init(&_heap_start, &_heap_end);
......@@ -215,6 +263,7 @@ soft_reset:
exti_init();
#if MICROPY_HW_HAS_SWITCH
// must come after exti_init
switch_init();
#endif
......@@ -225,29 +274,12 @@ soft_reset:
pin_map_init();
// check if user switch held (initiates reset of filesystem)
bool reset_filesystem = false;
#if MICROPY_HW_HAS_SWITCH
if (switch_get()) {
reset_filesystem = true;
for (int i = 0; i < 50; i++) {
if (!switch_get()) {
reset_filesystem = false;
break;
}
HAL_Delay(10);
}
}
#endif
// local filesystem init
{
// try to mount the flash
FRESULT res = f_mount(&fatfs0, "0:", 1);
if (!reset_filesystem && res == FR_OK) {
// mount sucessful
} else if (reset_filesystem || res == FR_NO_FILESYSTEM) {
// no filesystem, so create a fresh one
// TODO doesn't seem to work correctly when reset_filesystem is true...
if (reset_mode == 3 || res == FR_NO_FILESYSTEM) {
// no filesystem, or asked to reset it, so create a fresh one
// LED on to indicate creation of LFS
led_state(PYB_LED_R2, 1);
......@@ -275,6 +307,8 @@ soft_reset:
// keep LED on for at least 200ms
sys_tick_wait_at_least(start_tick, 200);
led_state(PYB_LED_R2, 0);
} else if (res == FR_OK) {
// mount sucessful
} else {
__fatal_error("could not access LFS");
}
......@@ -317,20 +351,24 @@ soft_reset:
}
// run /boot.py
if (!pyexec_file("0:/boot.py")) {
flash_error(4);
if (reset_mode == 1) {
if (!pyexec_file("0:/boot.py")) {
flash_error(4);
}
}
// turn boot-up LED off
led_state(PYB_LED_GREEN, 0);
// turn boot-up LEDs off
led_state(2, 0);
led_state(3, 0);
led_state(4, 0);
#if defined(USE_DEVICE_MODE)
usbd_storage_medium_kind_t usbd_medium_kind = USBD_STORAGE_MEDIUM_FLASH;
usb_storage_medium_t usb_medium = USB_STORAGE_MEDIUM_FLASH;
#endif
#if MICROPY_HW_HAS_SDCARD
// if an SD card is present then mount it on 1:/
if (sdcard_is_present()) {
if (reset_mode == 1 && sdcard_is_present()) {
FRESULT res = f_mount(&fatfs1, "1:", 1);
if (res != FR_OK) {
printf("[SD] could not mount SD card\n");
......@@ -338,7 +376,7 @@ soft_reset:
if (first_soft_reset) {
// use SD card as medium for the USB MSD
#if defined(USE_DEVICE_MODE)
usbd_medium_kind = USBD_STORAGE_MEDIUM_SDCARD;
usb_medium = USB_STORAGE_MEDIUM_SDCARD;
#endif
}
}
......@@ -353,7 +391,17 @@ soft_reset:
pyb_usb_host_init();
#elif defined(USE_DEVICE_MODE)
// USB device
pyb_usb_dev_init(USBD_DEVICE_CDC_MSC, usbd_medium_kind);
if (reset_mode == 1) {
usb_device_mode_t usb_mode = USB_DEVICE_MODE_CDC_MSC;
if (pyb_config_usb_mode != MP_OBJ_NULL) {
if (strcmp(mp_obj_str_get_str(pyb_config_usb_mode), "CDC+HID") == 0) {
usb_mode = USB_DEVICE_MODE_CDC_HID;
}
}
pyb_usb_dev_init(usb_mode, usb_medium);
} else {
pyb_usb_dev_init(USB_DEVICE_MODE_CDC_MSC, usb_medium);
}
#endif
#if MICROPY_HW_ENABLE_RNG
......@@ -387,7 +435,7 @@ soft_reset:
#endif
// run main script
{
if (reset_mode == 1) {
vstr_t *vstr = vstr_new();
vstr_add_str(vstr, "0:/");
if (pyb_config_source_dir == MP_OBJ_NULL) {
......@@ -408,41 +456,6 @@ soft_reset:
}
#if 0
#if MICROPY_HW_HAS_MMA7660
// HID example
if (0) {
uint8_t data[4];
data[0] = 0;
data[1] = 1;
data[2] = -2;
data[3] = 0;
for (;;) {
#if MICROPY_HW_HAS_SWITCH
if (switch_get()) {
data[0] = 0x01; // 0x04 is middle, 0x02 is right
} else {
data[0] = 0x00;
}
#else
data[0] = 0x00;
#endif
accel_start(0x4c /* ACCEL_ADDR */, 1);
accel_send_byte(0);
accel_restart(0x4c /* ACCEL_ADDR */, 0);
for (int i = 0; i <= 1; i++) {
int v = accel_read_ack() & 0x3f;
if (v & 0x20) {
v |= ~0x1f;
}
data[1 + i] = v;
}
accel_read_nack();
usb_hid_send_report(data);
HAL_Delay(15);
}
}
#endif
#if MICROPY_HW_HAS_WLAN
// wifi
pyb_wlan_init();
......
......@@ -208,6 +208,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(pyb_input_obj, pyb_input);
MP_DECLARE_CONST_FUN_OBJ(pyb_source_dir_obj); // defined in main.c
MP_DECLARE_CONST_FUN_OBJ(pyb_main_obj); // defined in main.c
MP_DECLARE_CONST_FUN_OBJ(pyb_usb_mode_obj); // defined in main.c
STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR___name__), MP_OBJ_NEW_QSTR(MP_QSTR_pyb) },
......@@ -220,6 +221,7 @@ STATIC const mp_map_elem_t pyb_module_globals_table[] = {
{ MP_OBJ_NEW_QSTR(MP_QSTR_standby), (mp_obj_t)&pyb_standby_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_source_dir), (mp_obj_t)&pyb_source_dir_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_main), (mp_obj_t)&pyb_main_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_usb_mode), (mp_obj_t)&pyb_usb_mode_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_millis), (mp_obj_t)&pyb_millis_obj },
{ MP_OBJ_NEW_QSTR(MP_QSTR_delay), (mp_obj_t)&pyb_delay_obj },
......
......@@ -10,6 +10,7 @@ Q(stop)
Q(standby)
Q(source_dir)
Q(main)
Q(usb_mode)
Q(sync)
Q(gc)
Q(repl_info)
......
......@@ -38,7 +38,7 @@
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#include "usbd_cdc_msc.h"
#include "usbd_cdc_msc_hid.h"
#include "usbd_cdc_interface.h"
#include "misc.h"
......
......@@ -42,7 +42,7 @@
#include "stm32f4xx_it.h"
#include "stm32f4xx_hal.h"
#include "usbd_cdc_msc.h"
#include "usbd_cdc_msc_hid.h"
#include "usbd_cdc_interface.h"
#include "misc.h"
......
......@@ -2,7 +2,7 @@
#include "usbd_core.h"
#include "usbd_desc.h"
#include "usbd_cdc_msc.h"
#include "usbd_cdc_msc_hid.h"
#include "usbd_cdc_interface.h"
#include "usbd_msc_storage.h"
......@@ -19,28 +19,24 @@ USBD_HandleTypeDef hUSBDDevice;
static int dev_is_enabled = 0;
mp_obj_t mp_const_vcp_interrupt = MP_OBJ_NULL;
void pyb_usb_dev_init(usbd_device_kind_t device_kind, usbd_storage_medium_kind_t medium_kind) {
void pyb_usb_dev_init(usb_device_mode_t mode, usb_storage_medium_t medium) {
#ifdef USE_DEVICE_MODE
if (!dev_is_enabled) {
// only init USB once in the device's power-lifetime
switch (device_kind) {
case USBD_DEVICE_CDC_MSC:
USBD_Init(&hUSBDDevice, &VCP_Desc, 0);
USBD_RegisterClass(&hUSBDDevice, &USBD_CDC_MSC);
USBD_CDC_RegisterInterface(&hUSBDDevice, (USBD_CDC_ItfTypeDef*)&USBD_CDC_fops);
if (medium_kind == USBD_STORAGE_MEDIUM_FLASH) {
USBD_MSC_RegisterStorage(&hUSBDDevice, (USBD_StorageTypeDef*)&USBD_FLASH_STORAGE_fops);
} else {
USBD_MSC_RegisterStorage(&hUSBDDevice, (USBD_StorageTypeDef*)&USBD_SDCARD_STORAGE_fops);
}
USBD_Start(&hUSBDDevice);
break;
case USBD_DEVICE_HID:
//USBD_Init(&USB_OTG_Core, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_PYB_HID_cb, &USR_cb);
// TODO
break;
if (mode == USB_DEVICE_MODE_CDC_MSC) {
USBD_SelectMode(USBD_MODE_CDC_MSC);
} else {
USBD_SelectMode(USBD_MODE_CDC_HID);
}
USBD_Init(&hUSBDDevice, &VCP_Desc, 0);
USBD_RegisterClass(&hUSBDDevice, &USBD_CDC_MSC_HID);
USBD_CDC_RegisterInterface(&hUSBDDevice, (USBD_CDC_ItfTypeDef*)&USBD_CDC_fops);
if (medium == USB_STORAGE_MEDIUM_FLASH) {
USBD_MSC_RegisterStorage(&hUSBDDevice, (USBD_StorageTypeDef*)&USBD_FLASH_STORAGE_fops);
} else {
USBD_MSC_RegisterStorage(&hUSBDDevice, (USBD_StorageTypeDef*)&USBD_SDCARD_STORAGE_fops);
}
USBD_Start(&hUSBDDevice);
}
dev_is_enabled = 1;
......
......@@ -5,16 +5,16 @@
#define VCP_CHAR_CTRL_D (4)
typedef enum {
USBD_DEVICE_CDC_MSC,
USBD_DEVICE_HID,
} usbd_device_kind_t;
USB_DEVICE_MODE_CDC_MSC,
USB_DEVICE_MODE_CDC_HID,
} usb_device_mode_t;
typedef enum {
USBD_STORAGE_MEDIUM_FLASH,
USBD_STORAGE_MEDIUM_SDCARD,
} usbd_storage_medium_kind_t;
USB_STORAGE_MEDIUM_FLASH,
USB_STORAGE_MEDIUM_SDCARD,
} usb_storage_medium_t;
void pyb_usb_dev_init(usbd_device_kind_t device_kind, usbd_storage_medium_kind_t medium_kind);
void pyb_usb_dev_init(usb_device_mode_t mode, usb_storage_medium_t medium);
bool usb_vcp_is_enabled(void);
bool usb_vcp_is_connected(void);
void usb_vcp_set_interrupt_char(int c);
......
......@@ -28,7 +28,7 @@
/* Includes ------------------------------------------------------------------*/
#include <stdbool.h>
#include "stm32f4xx_hal.h"
#include "usbd_cdc_msc.h"
#include "usbd_cdc_msc_hid.h"
#include "usbd_cdc_interface.h"
#include "pendsv.h"
#include "usb.h"
......
#ifndef _USB_CDC_MSC_CORE_H_
#define _USB_CDC_MSC_CORE_H_
#include "usbd_msc_bot.h"
#include "usbd_msc_scsi.h"
#include "usbd_ioreq.h"
// CDC and MSC packet sizes
#define CDC_DATA_FS_MAX_PACKET_SIZE (64) // endpoint IN & OUT packet size
#define MSC_MEDIA_PACKET (2048) // was 8192; how low can it go whilst still working?
// Need to define here for BOT and SCSI layers
#define MSC_IN_EP (0x81)
#define MSC_OUT_EP (0x01)
// only CDC_MSC and CDC_HID are available
#define USBD_MODE_CDC (0x01)
#define USBD_MODE_MSC (0x02)
#define USBD_MODE_HID (0x04)
#define USBD_MODE_CDC_MSC (USBD_MODE_CDC | USBD_MODE_MSC)
#define USBD_MODE_CDC_HID (USBD_MODE_CDC | USBD_MODE_HID)
#define USBD_MODE_MSC_HID (USBD_MODE_MSC | USBD_MODE_HID)
typedef struct {
uint32_t bitrate;
uint8_t format;
uint8_t paritytype;
uint8_t datatype;
} USBD_CDC_LineCodingTypeDef;
typedef struct _USBD_CDC_Itf {
int8_t (* Init) (void);
int8_t (* DeInit) (void);
int8_t (* Control) (uint8_t, uint8_t * , uint16_t);
int8_t (* Receive) (uint8_t *, uint32_t *);
} USBD_CDC_ItfTypeDef;
typedef struct {
uint32_t data[CDC_DATA_FS_MAX_PACKET_SIZE/4]; /* Force 32bits alignment */
uint8_t CmdOpCode;
uint8_t CmdLength;
uint8_t *RxBuffer;
uint8_t *TxBuffer;
uint32_t RxLength;
uint32_t TxLength;
__IO uint32_t TxState;
__IO uint32_t RxState;
} USBD_CDC_HandleTypeDef;
typedef struct _USBD_STORAGE {
int8_t (* Init) (uint8_t lun);
int8_t (* GetCapacity) (uint8_t lun, uint32_t *block_num, uint16_t *block_size);
int8_t (* IsReady) (uint8_t lun);
int8_t (* IsWriteProtected) (uint8_t lun);
int8_t (* Read) (uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
int8_t (* Write)(uint8_t lun, uint8_t *buf, uint32_t blk_addr, uint16_t blk_len);
int8_t (* GetMaxLun)(void);
int8_t *pInquiry;
} USBD_StorageTypeDef;
typedef struct {
uint32_t max_lun;
uint32_t interface;
uint8_t bot_state;
uint8_t bot_status;
uint16_t bot_data_length;
uint8_t bot_data[MSC_MEDIA_PACKET];
USBD_MSC_BOT_CBWTypeDef cbw;
USBD_MSC_BOT_CSWTypeDef csw;
USBD_SCSI_SenseTypeDef scsi_sense [SENSE_LIST_DEEPTH];
uint8_t scsi_sense_head;
uint8_t scsi_sense_tail;
uint16_t scsi_blk_size;
uint32_t scsi_blk_nbr;
uint32_t scsi_blk_addr;
uint32_t scsi_blk_len;
} USBD_MSC_BOT_HandleTypeDef;
extern USBD_ClassTypeDef USBD_CDC_MSC_HID;
void USBD_SelectMode(uint32_t mode);
uint8_t USBD_CDC_RegisterInterface (USBD_HandleTypeDef *pdev, USBD_CDC_ItfTypeDef *fops);
uint8_t USBD_CDC_SetTxBuffer (USBD_HandleTypeDef *pdev, uint8_t *pbuff, uint16_t length);
uint8_t USBD_CDC_SetRxBuffer (USBD_HandleTypeDef *pdev, uint8_t *pbuff);
uint8_t USBD_CDC_ReceivePacket (USBD_HandleTypeDef *pdev);
uint8_t USBD_CDC_TransmitPacket (USBD_HandleTypeDef *pdev);
uint8_t USBD_MSC_RegisterStorage(USBD_HandleTypeDef *pdev, USBD_StorageTypeDef *fops);
uint8_t USBD_HID_SendReport(USBD_HandleTypeDef *pdev, uint8_t *report, uint16_t len);
#endif // _USB_CDC_MSC_CORE_H_
/**
******************************************************************************
* @file usbd_msc_bot.h
* @author MCD Application Team
* @version V2.0.0
* @date 18-February-2014
* @brief header for the usbd_msc_bot.c file
******************************************************************************
* @attention
*
* <h2><center>&copy; COPYRIGHT 2014 STMicroelectronics</center></h2>
*
* Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/software_license_agreement_liberty_v2
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************
*/
/* Define to prevent recursive inclusion -------------------------------------*/
#include "usbd_core.h"
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __USBD_MSC_BOT_H
#define __USBD_MSC_BOT_H
/** @addtogroup STM32_USB_OTG_DEVICE_LIBRARY
* @{
*/
/** @defgroup MSC_BOT
* @brief This file is the Header file for usbd_bot.c
* @{
*/
/** @defgroup USBD_CORE_Exported_Defines
* @{
*/
#define USBD_BOT_IDLE 0 /* Idle state */
#define USBD_BOT_DATA_OUT 1 /* Data Out state */
#define USBD_BOT_DATA_IN 2 /* Data In state */
#define USBD_BOT_LAST_DATA_IN 3 /* Last Data In Last */
#define USBD_BOT_SEND_DATA 4 /* Send Immediate data */
#define USBD_BOT_NO_DATA 5 /* No data Stage */
#define USBD_BOT_CBW_SIGNATURE 0x43425355
#define USBD_BOT_CSW_SIGNATURE 0x53425355
#define USBD_BOT_CBW_LENGTH 31
#define USBD_BOT_CSW_LENGTH 13
#define USBD_BOT_MAX_DATA 256
/* CSW Status Definitions */
#define USBD_CSW_CMD_PASSED 0x00
#define USBD_CSW_CMD_FAILED 0x01
#define USBD_CSW_PHASE_ERROR 0x02
/* BOT Status */
#define USBD_BOT_STATUS_NORMAL 0
#define USBD_BOT_STATUS_RECOVERY 1
#define USBD_BOT_STATUS_ERROR 2
#define USBD_DIR_IN 0
#define USBD_DIR_OUT 1
#define USBD_BOTH_DIR 2
/**
* @}
*/
/** @defgroup MSC_CORE_Private_TypesDefinitions
* @{
*/
typedef struct
{
uint32_t dSignature;
uint32_t dTag;
uint32_t dDataLength;
uint8_t bmFlags;
uint8_t bLUN;
uint8_t bCBLength;
uint8_t CB[16];
uint8_t ReservedForAlign;
}
USBD_MSC_BOT_CBWTypeDef;