[usb] add usb-storage for apogee SD logger

[usb] fix usb-storage when mounting before starting log
This commit is contained in:
Gautier Hattenberger
2014-02-06 14:32:31 +01:00
parent 6dd439ee07
commit 8af1bdac4e
10 changed files with 1470 additions and 23 deletions
+2 -1
View File
@@ -42,6 +42,7 @@ CHIBIOS_BOARD_DIR = $(PAPARAZZI_SRC)/sw/airborne/boards/$(BOARD)/chibios-libopen
CHIBIOS_LIB_DIR = $(PAPARAZZI_SRC)/sw/airborne/subsystems/chibios-libopencm3
CHIBIOS_EXT = $(PAPARAZZI_SRC)/sw/ext/chibios
OPENCM3_EXT = $(PAPARAZZI_SRC)/sw/ext/libopencm3
PPRZ_GENERATED = $(PAPARAZZI_SRC)/var/$(AIRCRAFT)/generated
# Launch with "make Q=''" to get full command display
Q=@
@@ -216,7 +217,7 @@ INCDIR = $(PORTINC) $(KERNINC) $(TESTINC) \
$(HALINC) $(PLATFORMINC) $(BOARDINC) \
$(CHIBIOS)/os/various $(OPENCM3_INC) \
$(CHIBIOS_BOARD_DIR) $(CHIBIOS_LIB_DIR) \
$(FATFSINC)
$(PPRZ_GENERATED) $(FATFSINC)
BUILDDIR := $(OBJDIR)
#
+11 -9
View File
@@ -1,10 +1,12 @@
# List of all the board related files.
CHIBIOSLIBSRC = ${CHIBIOS_LIB_DIR}/ringBuffer.c \
${CHIBIOS_LIB_DIR}/chibios_stub.c \
${CHIBIOS_LIB_DIR}/pprz_stub.c \
${CHIBIOS_LIB_DIR}/varLengthMsgQ.c \
${CHIBIOS_LIB_DIR}/rtcAccess.c \
${CHIBIOS_LIB_DIR}/sdLog.c \
${CHIBIOS_LIB_DIR}/chibios_sdlog.c \
${CHIBIOS_LIB_DIR}/sdio.c \
${CHIBIOS_LIB_DIR}/printf.c
CHIBIOSLIBSRC = ${CHIBIOS_LIB_DIR}/ringBuffer.c \
${CHIBIOS_LIB_DIR}/chibios_stub.c \
${CHIBIOS_LIB_DIR}/pprz_stub.c \
${CHIBIOS_LIB_DIR}/varLengthMsgQ.c \
${CHIBIOS_LIB_DIR}/rtcAccess.c \
${CHIBIOS_LIB_DIR}/sdLog.c \
${CHIBIOS_LIB_DIR}/chibios_sdlog.c \
${CHIBIOS_LIB_DIR}/sdio.c \
${CHIBIOS_LIB_DIR}/printf.c \
${CHIBIOS_LIB_DIR}/usb_msd.c \
${CHIBIOS_LIB_DIR}/usbStorage.c
@@ -157,7 +157,7 @@
* @brief Enables the USB subsystem.
*/
#if !defined(HAL_USE_USB) || defined(__DOXYGEN__)
#define HAL_USE_USB FALSE
#define HAL_USE_USB TRUE
#endif
/*===========================================================================*/
@@ -243,14 +243,14 @@
/*
* USB driver system settings.
*/
#define STM32_USB_USE_OTG1 FALSE // FS, DFU_BOOT
#define STM32_USB_USE_OTG1 TRUE // FS, DFU_BOOT
#define STM32_USB_USE_OTG2 FALSE // HS
#define STM32_USB_OTG1_IRQ_PRIORITY 14
#define STM32_USB_OTG2_IRQ_PRIORITY 14
#define STM32_USB_OTG1_RX_FIFO_SIZE 512
#define STM32_USB_OTG2_RX_FIFO_SIZE 512
#define STM32_USB_OTG_THREAD_PRIO LOWPRIO
#define STM32_USB_OTG_THREAD_STACK_SIZE 128
#define STM32_USB_OTG_THREAD_STACK_SIZE 256
#define STM32_USB_OTGFIFO_FILL_BASEPRI 0
@@ -310,7 +310,7 @@
[NVIC_USART3_IRQ] = NVIC_USART3_IRQ_VEC_OPENCM3, \
[NVIC_EXTI15_10_IRQ] = NVIC_EXTI15_10_IRQ_VEC_OPENCM3, \
[NVIC_RTC_ALARM_IRQ] = NVIC_RTC_ALARM_IRQ_VEC_CHIBIOS, \
[NVIC_USB_FS_WKUP_IRQ] = NVIC_USB_FS_WKUP_IRQ_VEC_OPENCM3, \
[NVIC_USB_FS_WKUP_IRQ] = NVIC_USB_FS_WKUP_IRQ_VEC_CHIBIOS, \
[NVIC_TIM8_BRK_TIM12_IRQ] = NVIC_TIM8_BRK_TIM12_IRQ_VEC_OPENCM3, \
[NVIC_TIM8_UP_TIM13_IRQ] = NVIC_TIM8_UP_TIM13_IRQ_VEC_OPENCM3, \
[NVIC_TIM8_TRG_COM_TIM14_IRQ] = NVIC_TIM8_TRG_COM_TIM14_IRQ_VEC_OPENCM3, \
@@ -335,7 +335,7 @@
[NVIC_CAN2_RX0_IRQ] = NVIC_CAN2_RX0_IRQ_VEC_OPENCM3, \
[NVIC_CAN2_RX1_IRQ] = NVIC_CAN2_RX1_IRQ_VEC_OPENCM3, \
[NVIC_CAN2_SCE_IRQ] = NVIC_CAN2_SCE_IRQ_VEC_OPENCM3, \
[NVIC_OTG_FS_IRQ] = NVIC_OTG_FS_IRQ_VEC_OPENCM3, \
[NVIC_OTG_FS_IRQ] = NVIC_OTG_FS_IRQ_VEC_CHIBIOS, \
[NVIC_DMA2_STREAM5_IRQ] = NVIC_DMA2_STREAM5_IRQ_VEC_OPENCM3, \
[NVIC_DMA2_STREAM6_IRQ] = NVIC_DMA2_STREAM6_IRQ_VEC_OPENCM3, \
[NVIC_DMA2_STREAM7_IRQ] = NVIC_DMA2_STREAM7_IRQ_VEC_OPENCM3, \
@@ -28,8 +28,15 @@
#include <hal.h>
#include "subsystems/chibios-libopencm3/chibios_sdlog.h"
#include "sdLog.h"
#include "usbStorage.h"
#include "pprz_stub.h"
#include "rtcAccess.h"
#include "airframe.h"
// Delay before starting SD log
#ifndef SDLOG_START_DELAY
#define SDLOG_START_DELAY 30
#endif
#ifndef SYS_TIME_FREQUENCY
@@ -62,12 +69,11 @@ bool_t chibios_init(void) {
PWR->CSR &= ~PWR_CSR_BRE;
DBGMCU->APB1FZ |= DBGMCU_APB1_FZ_DBG_IWDG_STOP;
chThdSleepMilliseconds (100);
sdOk = chibios_logInit(true);
chThdCreateStatic(wa_thd_heartbeat, sizeof(wa_thd_heartbeat),
NORMALPRIO, thd_heartbeat, NULL);
return sdOk;
usbStorageStartPolling ();
return RDY_OK;
}
static WORKING_AREA(pprzThd, 4096);
@@ -85,6 +91,9 @@ static __attribute__((noreturn)) msg_t thd_heartbeat(void *arg)
(void) arg;
chRegSetThreadName("pprz heartbeat");
chThdSleepSeconds (SDLOG_START_DELAY);
sdOk = chibios_logInit(true);
while (TRUE) {
palTogglePad (GPIOC, GPIOC_LED3);
chThdSleepMilliseconds (sdOk == TRUE ? 1000 : 200);
@@ -92,12 +92,15 @@ error:
void chibios_logFinish(void)
{
sdLogStopThread ();
sdLogCloseLog (&pprzLogFile);
if (pprzLogFile.fs != NULL) {
sdLogStopThread ();
sdLogCloseLog (&pprzLogFile);
#if LOG_PROCESS_STATE
sdLogCloseLog (&processLogFile);
sdLogCloseLog (&processLogFile);
#endif
sdLogFinish ();
sdLogFinish ();
pprzLogFile.fs = NULL;
}
}
@@ -0,0 +1,333 @@
/*
* Copyright (C) 2014 Gautier Hattenberger, Alexandre Bustico
*
* This file is part of paparazzi.
*
* paparazzi 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 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* @file subsystems/chibios-libopencm3/usbStorage.c
*
*/
#include "ch.h"
#include "hal.h"
#include "usb_msd.h"
#include "usbStorage.h"
#include "chibios_sdlog.h"
#include <stdio.h>
#include <string.h>
#include <sdio.h>
static msg_t thdUsbStorage(void *arg);
static Thread* usbStorageThreadPtr=NULL;
/* USB mass storage driver */
static USBMassStorageDriver UMSD1;
/* endpoint index */
#define USB_MS_DATA_EP 1
// cortex_m4 specific
#define MCU_RESTART() {*((unsigned long *)0x0E000ED0C) = 0x05FA0004;}
/* USB device descriptor */
static const uint8_t deviceDescriptorData[] =
{
USB_DESC_DEVICE
(
0x0200, /* supported USB version (2.0) */
0x00, /* device class (none, specified in interface) */
0x00, /* device sub-class (none, specified in interface) */
0x00, /* device protocol (none, specified in interface) */
64, /* max packet size of control end-point */
0x0483, /* vendor ID (STMicroelectronics!) */
0x5740, /* product ID (STM32F407) */
0x0100, /* device release number */
1, /* index of manufacturer string descriptor */
2, /* index of product string descriptor */
3, /* index of serial number string descriptor */
1 /* number of possible configurations */
)
};
static const USBDescriptor deviceDescriptor =
{
sizeof(deviceDescriptorData),
deviceDescriptorData
};
/* configuration descriptor */
static const uint8_t configurationDescriptorData[] =
{
/* configuration descriptor */
USB_DESC_CONFIGURATION
(
32, /* total length */
1, /* number of interfaces */
1, /* value that selects this configuration */
0, /* index of string descriptor describing this configuration */
0xC0, /* attributes (self-powered) */
50 /* max power (100 mA) */
),
/* interface descriptor */
USB_DESC_INTERFACE
(
0, /* interface number */
0, /* value used to select alternative setting */
2, /* number of end-points used by this interface */
0x08, /* interface class (Mass Storage) */
0x06, /* interface sub-class (SCSI Transparent Storage) */
0x50, /* interface protocol (Bulk Only) */
0 /* index of string descriptor describing this interface */
),
/* end-point descriptor */
USB_DESC_ENDPOINT
(
USB_MS_DATA_EP | 0x80, /* address (end point index | OUT direction) */
USB_EP_MODE_TYPE_BULK, /* attributes (bulk) */
64, /* max packet size */
0x05 /* polling interval (ignored for bulk end-points) */
),
/* end-point descriptor */
USB_DESC_ENDPOINT
(
USB_MS_DATA_EP | 0x00, /* address (end point index | IN direction) */
USB_EP_MODE_TYPE_BULK, /* attributes (bulk) */
64, /* max packet size */
0x05 /* polling interval (ignored for bulk end-points) */
)
};
static const USBDescriptor configurationDescriptor =
{
sizeof(configurationDescriptorData),
configurationDescriptorData
};
/* Language descriptor */
static const uint8_t languageDescriptorData[] =
{
USB_DESC_BYTE(4),
USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
USB_DESC_WORD(0x0409) /* U.S. english */
};
static const USBDescriptor languageDescriptor =
{
sizeof(languageDescriptorData),
languageDescriptorData
};
/* Vendor descriptor */
static const uint8_t vendorDescriptorData[] =
{
USB_DESC_BYTE(20),
USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
'P', 0, 'a', 0, 'p', 0, 'a', 0, 'r', 0, 'a', 0, 'z', 0, 'z', 0, 'i', 0
};
static const USBDescriptor vendorDescriptor =
{
sizeof(vendorDescriptorData),
vendorDescriptorData
};
/* Product descriptor */
static const uint8_t productDescriptorData[] =
{
USB_DESC_BYTE(24),
USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
'A', 0, 'p', 0, 'o', 0, 'g', 0, 'e', 0, 'e', 0, ' ', 0, 'V', 0, '1', 0, '0', 0, '0', 0
};
static const USBDescriptor productDescriptor =
{
sizeof(productDescriptorData),
productDescriptorData
};
/* Serial number descriptor */
static const uint8_t serialNumberDescriptorData[] =
{
USB_DESC_BYTE(24),
USB_DESC_BYTE(USB_DESCRIPTOR_STRING),
'0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '1', 0, '.', 0, '0', 0, '0', 0
};
static const USBDescriptor serialNumberDescriptor =
{
sizeof(serialNumberDescriptorData),
serialNumberDescriptorData
};
/* Handles GET_DESCRIPTOR requests from the USB host */
static const USBDescriptor* getDescriptor(USBDriver* usbp, uint8_t type, uint8_t index, uint16_t lang)
{
(void)usbp;
(void)lang;
switch (type)
{
case USB_DESCRIPTOR_DEVICE:
return &deviceDescriptor;
case USB_DESCRIPTOR_CONFIGURATION:
return &configurationDescriptor;
case USB_DESCRIPTOR_STRING:
switch (index)
{
case 0: return &languageDescriptor;
case 1: return &vendorDescriptor;
case 2: return &productDescriptor;
case 3: return &serialNumberDescriptor;
}
}
return 0;
}
/* Handles global events of the USB driver */
static void usbEvent(USBDriver* usbp, usbevent_t event)
{
(void) usbp;
switch (event)
{
case USB_EVENT_CONFIGURED:
chSysLockFromIsr();
msdConfigureHookI(&UMSD1);
chSysUnlockFromIsr();
break;
case USB_EVENT_RESET:
case USB_EVENT_ADDRESS:
case USB_EVENT_SUSPEND:
case USB_EVENT_WAKEUP:
case USB_EVENT_STALLED:
default:
break;
}
}
/* Configuration of the USB driver */
const USBConfig usbConfig =
{
usbEvent,
getDescriptor,
msdRequestsHook,
0
};
/* Turns on a LED when there is I/O activity on the USB port */
static void usbActivity(bool_t active)
{
if (active)
palSetPad(GPIOC, GPIOC_LED4);
else
palClearPad(GPIOC, GPIOC_LED4);
}
/* USB mass storage configuration */
static USBMassStorageConfig msdConfig =
{
&USBD1,
(BaseBlockDevice*)&SDCD1,
USB_MS_DATA_EP,
&usbActivity,
"DPprz_sd",
"DApogee",
"0.1"
};
static WORKING_AREA(waThsUsbStorage, 1024);
void usbStorageStartPolling (void)
{
usbStorageThreadPtr = chThdCreateStatic (waThsUsbStorage, sizeof(waThsUsbStorage),
NORMALPRIO, thdUsbStorage, NULL);
}
void usbStorageWaitForDeconnexion (void)
{
if (usbStorageThreadPtr != NULL)
chThdWait (usbStorageThreadPtr);
usbStorageThreadPtr = NULL;
}
void usbStorageStop (void)
{
if (usbStorageThreadPtr != NULL) {
chThdTerminate (usbStorageThreadPtr);
}
}
static msg_t thdUsbStorage(void *arg)
{
(void) arg; // unused
chRegSetThreadName("UsbStorage:polling");
uint antiBounce=5;
// Should use EXTI interrupt instead of active polling,
// but in the chibios_opencm3 implementation, since EXTI is
// used via libopencm3, ISR are routed on pprz/opencm3 and cannot
// be used concurrently by chibios api
// Should be fixed when using chibios-rt branch
while (!chThdShouldTerminate() && antiBounce) {
const bool_t usbConnected = palReadPad (GPIOA, GPIOA_OTG_FS_VBUS);
if (usbConnected)
antiBounce--;
else
antiBounce=5;
chThdSleepMilliseconds(20);
}
chRegSetThreadName("UsbStorage:connected");
chibios_logFinish ();
/* connect sdcard sdc interface sdio */
if (sdioConnect () == false)
chThdExit (RDY_TIMEOUT);
/* initialize the USB mass storage driver */
msdInit(&UMSD1);
/* start the USB mass storage service */
msdStart(&UMSD1, &msdConfig);
/* start the USB driver */
usbDisconnectBus(&USBD1);
chThdSleepMilliseconds(1000);
usbStart(&USBD1, &usbConfig);
usbConnectBus(&USBD1);
/* watch the mass storage events */
while (!chThdShouldTerminate() && palReadPad (GPIOA, GPIOA_OTG_FS_VBUS)) {
chThdSleepMilliseconds(10);
}
usbDisconnectBus(&USBD1);
chThdSleepMilliseconds(500);
msdStop(&UMSD1);
sdioDisconnect ();
MCU_RESTART();
return RDY_OK;
}
@@ -0,0 +1,30 @@
/*
* Copyright (C) 2014 Gautier Hattenberger, Alexandre Bustico
*
* This file is part of paparazzi.
*
* paparazzi 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 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* @file subsystems/chibios-libopencm3/usbStorage.h
*
*/
#pragma once
void usbStorageStartPolling (void);
void usbStorageStop (void);
void usbStorageWaitForDeconnexion (void);
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,209 @@
/*
* Copyright (C) 2014 Gautier Hattenberger, Alexandre Bustico
*
* This file is part of paparazzi.
*
* paparazzi 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 2, or (at your option)
* any later version.
*
* paparazzi is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/*
* @file subsystems/chibios-libopencm3/usb_msd.h
*
*/
#pragma once
#include "ch.h"
#include "hal.h"
/**
* @brief Command Block Wrapper structure
*/
PACK_STRUCT_BEGIN typedef struct {
uint32_t signature;
uint32_t tag;
uint32_t data_len;
uint8_t flags;
uint8_t lun;
uint8_t scsi_cmd_len;
uint8_t scsi_cmd_data[16];
} PACK_STRUCT_STRUCT msd_cbw_t PACK_STRUCT_END;
/**
* @brief Command Status Wrapper structure
*/
PACK_STRUCT_BEGIN typedef struct {
uint32_t signature;
uint32_t tag;
uint32_t data_residue;
uint8_t status;
} PACK_STRUCT_STRUCT msd_csw_t PACK_STRUCT_END;
/**
* @brief Structure holding sense data (status/error information)
*/
PACK_STRUCT_BEGIN typedef struct {
uint8_t byte[18];
} PACK_STRUCT_STRUCT msd_scsi_sense_response_t PACK_STRUCT_END;
/**
* @brief structure holding the data to reply to an INQUIRY SCSI command
*/
PACK_STRUCT_BEGIN typedef struct
{
uint8_t peripheral;
uint8_t removable;
uint8_t version;
uint8_t response_data_format;
uint8_t additional_length;
uint8_t sccstp;
uint8_t bqueetc;
uint8_t cmdque;
uint8_t vendor_id[8];
uint8_t product_id[16];
uint8_t product_rev[4];
} PACK_STRUCT_STRUCT msd_scsi_inquiry_response_t PACK_STRUCT_END;
/**
* @brief Possible states for the USB mass storage driver
*/
typedef enum {
MSD_IDLE,
MSD_READ_COMMAND_BLOCK,
MSD_EJECTED
} msd_state_t;
/**
* @brief Driver configuration structure
*/
typedef struct {
/**
* @brief USB driver to use for communication
*/
USBDriver *usbp;
/**
* @brief Block device to use for storage
*/
BaseBlockDevice *bbdp;
/**
* @brief Index of the USB endpoint to use for transfers
*/
usbep_t bulk_ep;
/**
* @brief Optional callback that will be called whenever there is
* read/write activity
* @note The callback is called with argument TRUE when activity starts,
* and FALSE when activity stops.
*/
void (*rw_activity_callback)(bool_t);
/**
* @brief Short vendor identification
* @note ASCII characters only, maximum 8 characters (pad with zeroes).
*/
uint8_t short_vendor_id[8];
/**
* @brief Short product identification
* @note ASCII characters only, maximum 16 characters (pad with zeroes).
*/
uint8_t short_product_id[16];
/**
* @brief Short product revision
* @note ASCII characters only, maximum 4 characters (pad with zeroes).
*/
uint8_t short_product_version[4];
} USBMassStorageConfig;
/**
* @brief USB mass storage driver structure.
* @details This structure holds all the states and members of a USB mass
* storage driver.
*/
typedef struct {
const USBMassStorageConfig* config;
BinarySemaphore bsem;
Thread* thread;
EventSource evt_connected, evt_ejected;
BlockDeviceInfo block_dev_info;
msd_state_t state;
msd_cbw_t cbw;
msd_csw_t csw;
msd_scsi_sense_response_t sense;
msd_scsi_inquiry_response_t inquiry;
bool_t result;
} USBMassStorageDriver;
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief Initializes a USB mass storage driver.
*/
void msdInit(USBMassStorageDriver *msdp);
/**
* @brief Starts a USB mass storage driver.
* @details This function is sufficient to have USB mass storage running, it internally
* runs a thread that handles USB requests and transfers.
* The block device must be connected but no file system must be mounted,
* everything is handled by the host system.
*/
void msdStart(USBMassStorageDriver *msdp, const USBMassStorageConfig *config);
/**
* @brief Stops a USB mass storage driver.
* @details This function waits for current tasks to be finished, if any, and then
* stops the mass storage thread.
*/
void msdStop(USBMassStorageDriver *msdp);
/**
* @brief USB device configured handler.
*
* @param[in] msdp pointer to the @p USBMassStorageDriver object
*
* @iclass
*/
void msdConfigureHookI(USBMassStorageDriver *msdp);
/**
* @brief Default requests hook.
* @details Applications wanting to use the Mass Storage over USB driver can use
* this function as requests hook in the USB configuration.
* The following requests are emulated:
* - MSD_REQ_RESET.
* - MSD_GET_MAX_LUN.
* .
*
* @param[in] usbp pointer to the @p USBDriver object
* @return The hook status.
* @retval TRUE Message handled internally.
* @retval FALSE Message not handled.
*/
bool_t msdRequestsHook(USBDriver *usbp);
#ifdef __cplusplus
}
#endif