From efdb5c5f2bf079d45c29f30c6fa84f9de3d3a9b6 Mon Sep 17 00:00:00 2001 From: gussy Date: Sun, 31 Jan 2010 16:48:23 +0000 Subject: [PATCH] Added MSD library. Added PIOS_USB. Global improvements, see specific files for changes. git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@144 ebee16cc-31ac-478f-84a7-5cbb03baadba --- flight/Libraries/CMSIS/Core/CM3/stm32f10x.h | 4 +- flight/Libraries/FatFS/diskio.c | 2 +- flight/Libraries/msd/msd.c | 429 +++++++++++++++++ flight/Libraries/msd/msd.h | 78 ++++ flight/Libraries/msd/msd_bot.c | 334 ++++++++++++++ flight/Libraries/msd/msd_bot.h | 95 ++++ flight/Libraries/msd/msd_desc.c | 135 ++++++ flight/Libraries/msd/msd_desc.h | 48 ++ flight/Libraries/msd/msd_memory.c | 242 ++++++++++ flight/Libraries/msd/msd_memory.h | 43 ++ flight/Libraries/msd/msd_scsi.c | 430 +++++++++++++++++ flight/Libraries/msd/msd_scsi.h | 142 ++++++ flight/Libraries/msd/msd_scsi_data.c | 144 ++++++ flight/Makefile | 27 +- flight/PiOS/Common/pios_com.c | 2 +- flight/PiOS/Common/pios_sdcard.c | 2 +- flight/PiOS/STM32F10x/pios_delay.c | 6 +- flight/PiOS/STM32F10x/pios_irq.c | 2 +- flight/PiOS/STM32F10x/pios_pwm.c | 24 +- flight/PiOS/STM32F10x/pios_sys.c | 27 ++ flight/PiOS/STM32F10x/pios_usb.c | 484 ++++++++++++++++++++ flight/PiOS/inc/pios_board.h | 149 +++--- flight/PiOS/inc/pios_delay.h | 4 +- flight/PiOS/inc/pios_sys.h | 1 + flight/PiOS/inc/pios_usb.h | 79 ++++ flight/PiOS/pios.c | 65 ++- flight/PiOS/pios.h | 4 + 27 files changed, 2887 insertions(+), 115 deletions(-) create mode 100644 flight/Libraries/msd/msd.c create mode 100644 flight/Libraries/msd/msd.h create mode 100644 flight/Libraries/msd/msd_bot.c create mode 100644 flight/Libraries/msd/msd_bot.h create mode 100644 flight/Libraries/msd/msd_desc.c create mode 100644 flight/Libraries/msd/msd_desc.h create mode 100644 flight/Libraries/msd/msd_memory.c create mode 100644 flight/Libraries/msd/msd_memory.h create mode 100644 flight/Libraries/msd/msd_scsi.c create mode 100644 flight/Libraries/msd/msd_scsi.h create mode 100644 flight/Libraries/msd/msd_scsi_data.c create mode 100644 flight/PiOS/STM32F10x/pios_usb.c create mode 100644 flight/PiOS/inc/pios_usb.h diff --git a/flight/Libraries/CMSIS/Core/CM3/stm32f10x.h b/flight/Libraries/CMSIS/Core/CM3/stm32f10x.h index 48aeee335..556a0632d 100644 --- a/flight/Libraries/CMSIS/Core/CM3/stm32f10x.h +++ b/flight/Libraries/CMSIS/Core/CM3/stm32f10x.h @@ -47,8 +47,8 @@ #if !defined (STM32F10X_LD) && !defined (STM32F10X_MD) && !defined (STM32F10X_HD) && !defined (STM32F10X_CL) /* #define STM32F10X_LD */ /*!< STM32F10X_LD: STM32 Low density devices */ /* #define STM32F10X_MD */ /*!< STM32F10X_MD: STM32 Medium density devices */ - /* #define STM32F10X_HD */ /*!< STM32F10X_HD: STM32 High density devices */ - #define STM32F10X_CL /*!< STM32F10X_CL: STM32 Connectivity line devices */ + #define STM32F10X_HD /*!< STM32F10X_HD: STM32 High density devices */ + /* #define STM32F10X_CL */ /*!< STM32F10X_CL: STM32 Connectivity line devices */ #endif /* Tip: To avoid modifying this file each time you need to switch between these devices, you can define the device in your toolchain compiler preprocessor. diff --git a/flight/Libraries/FatFS/diskio.c b/flight/Libraries/FatFS/diskio.c index d0e99fa79..7883dee45 100644 --- a/flight/Libraries/FatFS/diskio.c +++ b/flight/Libraries/FatFS/diskio.c @@ -165,7 +165,7 @@ int32_t SDCARD_PowerOn(void) PIOS_SPI_RC_PinSet(PIOS_SDCARD_SPI, 0); /* spi, pin_value */ /* wait for 1 mS */ - PIOS_DELAY_Wait_uS(1000); + PIOS_DELAY_WaituS(1000); /* Send CMD0 to reset the media */ if((status = SDCARD_SendSDCCmd(SDCMD_GO_IDLE_STATE, 0, SDCMD_GO_IDLE_STATE_CRC)) < 0) { diff --git a/flight/Libraries/msd/msd.c b/flight/Libraries/msd/msd.c new file mode 100644 index 000000000..0501fedb7 --- /dev/null +++ b/flight/Libraries/msd/msd.c @@ -0,0 +1,429 @@ +/** + ****************************************************************************** + * + * @file msd.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2009. + * Parts by Thorsten Klose (tk@midibox.org) + * @brief USB Mass Storage Device Driver + * @see The GNU Public License (GPL) Version 3 + * @defgroup MSD MSD Functions + * @{ + * + *****************************************************************************/ +/* + * 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. + * + * This program 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 this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Include files */ +#include +#include + +#include + +#include "msd.h" +#include "msd_desc.h" +#include "msd_bot.h" +#include "msd_memory.h" + +/* Local definitions */ + +/* MASS Storage Requests */ +#define GET_MAX_LUN 0xFE +#define MASS_STORAGE_RESET 0xFF +#define LUN_DATA_LENGTH 1 + +/* ISTR events */ +/* IMR_MSK */ +/* mask defining which events has to be handled */ +/* by the device application software */ +#define MSD_IMR_MSK (CNTR_RESETM) + +/* Local prototypes */ +static void MSD_MASS_Reset(void); +static void MSD_Mass_Storage_SetConfiguration(void); +static void MSD_Mass_Storage_ClearFeature(void); +static void MSD_Mass_Storage_SetDeviceAddress(void); +static void MSD_MASS_Status_In(void); +static void MSD_MASS_Status_Out(void); +static RESULT MSD_MASS_Data_Setup(uint8_t); +static RESULT MSD_MASS_NoData_Setup(uint8_t); +static RESULT MSD_MASS_Get_Interface_Setting(uint8_t Interface, uint8_t AlternateSetting); +static uint8_t *MSD_MASS_GetDeviceDescriptor(uint16_t); +static uint8_t *MSD_MASS_GetConfigDescriptor(uint16_t); +static uint8_t *MSD_MASS_GetStringDescriptor(uint16_t); +static uint8_t *Get_Max_Lun(uint16_t Length); + +/* Local variables */ +static const DEVICE My_Device_Table = {MSD_EP_NUM, 1}; +static const DEVICE_PROP My_Device_Property = { + 0, // Init hook not used, done by PIOS_USB module! + MSD_MASS_Reset, MSD_MASS_Status_In, MSD_MASS_Status_Out, MSD_MASS_Data_Setup, MSD_MASS_NoData_Setup, MSD_MASS_Get_Interface_Setting, + MSD_MASS_GetDeviceDescriptor, MSD_MASS_GetConfigDescriptor, MSD_MASS_GetStringDescriptor, 0, 0x40 /*MAX PACKET SIZE*/ +}; +static const USER_STANDARD_REQUESTS My_User_Standard_Requests = {NOP_Process, MSD_Mass_Storage_SetConfiguration, NOP_Process, NOP_Process, NOP_Process, + MSD_Mass_Storage_ClearFeature, NOP_Process, NOP_Process, MSD_Mass_Storage_SetDeviceAddress}; +static ONE_DESCRIPTOR Device_Descriptor = {(uint8_t *) MSD_MASS_DeviceDescriptor, MSD_MASS_SIZ_DEVICE_DESC}; +static ONE_DESCRIPTOR Config_Descriptor = {(uint8_t *) MSD_MASS_ConfigDescriptor, MSD_MASS_SIZ_CONFIG_DESC}; +static ONE_DESCRIPTOR String_Descriptor[5] = { {(uint8_t *) MSD_MASS_StringLangID, MSD_MASS_SIZ_STRING_LANGID}, {(uint8_t *) MSD_MASS_StringVendor, + MSD_MASS_SIZ_STRING_VENDOR}, {(uint8_t *) MSD_MASS_StringProduct, MSD_MASS_SIZ_STRING_PRODUCT}, {(uint8_t *) MSD_MASS_StringSerial, + MSD_MASS_SIZ_STRING_SERIAL}, {(uint8_t *) MSD_MASS_StringInterface, MSD_MASS_SIZ_STRING_INTERFACE}, }; +static uint8_t lun_available; + +/** +* Initialises the USB Device Driver for a Mass Storage Device +* +* Should be called during runtime once a SD Card has been connected.
+* It is possible to switch back to the original device driver provided +* by calling PIOS_USB_Init(1) +* +* \param[in] mode currently only mode 0 supported +* \return < 0 if initialisation failed +*/ +int32_t MSD_Init(uint32_t mode) +{ + /* Update the serial number string descriptor with the data from the unique ID*/ + uint8_t serial_number_str[40]; + int i, len; + PIOS_SYS_SerialNumberGet((char *) serial_number_str); + for(i = 0, len = 0; serial_number_str[i] != '\0' && len < 25; ++i) { + MSD_MASS_StringSerial[len++] = serial_number_str[i]; + MSD_MASS_StringSerial[len++] = 0; + } + + lun_available = 0; + + /* All LUNs available after USB init */ + for(i = 0; i < MSD_NUM_LUN; ++i) { + MSD_LUN_AvailableSet(i, 1); + } + + PIOS_IRQ_Disable(); + + /* Clear all USB interrupt requests */ + _SetCNTR(0); /* Interrupt Mask */ + _SetISTR(0); /* clear pending requests */ + + /* Switch to MSD driver hooks */ + memcpy(&Device_Table, (DEVICE *) &My_Device_Table, sizeof(Device_Table)); + pProperty = (DEVICE_PROP *) &My_Device_Property; + pUser_Standard_Requests = (USER_STANDARD_REQUESTS *) &My_User_Standard_Requests; + + /* Change endpoints */ + pEpInt_IN[0] = MSD_Mass_Storage_In; + pEpInt_OUT[1] = MSD_Mass_Storage_Out; + + /* Force re-enumeration w/o overwriting PIOS hooks */ + PIOS_USB_Init(2); + + /* Clear pending interrupts (again) */ + _SetISTR(0); + + /* Set interrupts mask */ + _SetCNTR(MSD_IMR_MSK); + + PIOS_IRQ_Enable(); + + /* No error */ + return 0; +} + +/** +* Should be called periodically each millisecond so long this driver is +* active (and only then!) to handle USBtransfers. +* +* Take care that no other task accesses SD Card while this function is +* processed! +* +* Ensure that this function isn't called when a PIOS USB driver is running! +* +* \return < 0 on errors +*/ +int32_t MSD_Periodic_mS(void) +{ + /* Call endpoint handler of STM32 USB driver */ + CTR_LP(); + + /* No error */ + return 0; +} + +/** +* This function returns the connection status of the USB MIDI interface +* \return 1: interface available +* \return 0: interface not available +*/ +int32_t MSD_CheckAvailable(void) +{ + return pInformation->Current_Configuration ? 1 : 0; +} + +/** +* The logical unit is available whenever MSD_Init() is called, or the USB +* cable has been reconnected. +* +* It will be disabled when the host unmounts the file system (like if the +* SD Card would be removed. +* +* When this happens, the application can either call PIOS_USB_Init(1) +* again, e.g. to switch to USB MIDI, or it can make the LUN available +* again by calling MSD_LUN_AvailableSet(0, 1) +* \param[in] lun Logical Unit number (0) +* \param[in] available 0 or 1 +* \return < 0 on errors +*/ +int32_t MSD_LUN_AvailableSet(uint8_t lun, uint8_t available) +{ + if(lun >= MSD_NUM_LUN) { + return -1; + } + + if(available) { + lun_available |= (1 << lun); + } else { + lun_available &= ~(1 << lun); + } + + /* No error */ + return 0; +} + +/** +* \return 1 if device is mounted by host +* \return 0 if device is not mounted by host +*/ +int32_t MSD_LUN_AvailableGet(uint8_t lun) +{ + if(lun >= MSD_NUM_LUN) + return 0; + + return (lun_available & (1 << lun)) ? 1 : 0; +} + +/** +* Mass Storage reset routine. +*/ +static void MSD_MASS_Reset() +{ + /* Set the device as not configured */ + pInformation->Current_Configuration = 0; + + /* Current Feature initialization */ + pInformation->Current_Feature = MSD_MASS_ConfigDescriptor[7]; + + SetBTABLE(MSD_BTABLE_ADDRESS); + + /* Initialize Endpoint 0 */ + SetEPType(ENDP0, EP_CONTROL); + SetEPTxStatus(ENDP0, EP_TX_NAK); + SetEPRxAddr(ENDP0, MSD_ENDP0_RXADDR); + SetEPRxCount(ENDP0, pProperty->MaxPacketSize); + SetEPTxAddr(ENDP0, MSD_ENDP0_TXADDR); + Clear_Status_Out(ENDP0); + SetEPRxValid(ENDP0); + + /* Initialize Endpoint 1 */ + SetEPType(ENDP1, EP_BULK); + SetEPTxAddr(ENDP1, MSD_ENDP1_TXADDR); + SetEPTxStatus(ENDP1, EP_TX_NAK); + SetEPRxStatus(ENDP1, EP_RX_DIS); + + /* Initialize Endpoint 2 */ + SetEPType(ENDP2, EP_BULK); + SetEPRxAddr(ENDP2, MSD_ENDP2_RXADDR); + SetEPRxCount(ENDP2, pProperty->MaxPacketSize); + SetEPRxStatus(ENDP2, EP_RX_VALID); + SetEPTxStatus(ENDP2, EP_TX_DIS); + + SetEPRxCount(ENDP0, pProperty->MaxPacketSize); + SetEPRxValid(ENDP0); + + /* Set the device to response on default address */ + SetDeviceAddress(0); + + MSD_CBW.dSignature = BOT_CBW_SIGNATURE; + MSD_Bot_State = BOT_IDLE; +} + +/** +* Handle the SetConfiguration request. +*/ +static void MSD_Mass_Storage_SetConfiguration(void) +{ + if(pInformation->Current_Configuration != 0) { + ClearDTOG_TX(ENDP1); + ClearDTOG_RX(ENDP2); + MSD_Bot_State = BOT_IDLE; /* Set the Bot state machine to the IDLE state */ + + /* All LUNs available after USB (re-)connection */ + for(int i = 0; i < MSD_NUM_LUN; ++i) { + MSD_LUN_AvailableSet(i, 1); + } + } +} + +/** +* Handle the ClearFeature request. +*/ +static void MSD_Mass_Storage_ClearFeature(void) +{ + /* When the host send a CBW with invalid signature or invalid length the two */ + /* Endpoints (IN & OUT) shall stall until receiving a Mass Storage Reset */ + if(MSD_CBW.dSignature != BOT_CBW_SIGNATURE) { + MSD_Bot_Abort(BOTH_DIR); + } +} + +/** +* Udpade the device state to addressed. +*/ +static void MSD_Mass_Storage_SetDeviceAddress(void) +{ + +} + +/** +* Mass Storage Status IN routine. +*/ +static void MSD_MASS_Status_In(void) +{ + return; +} + +/******************************************************************************* +* Mass Storage Status OUT routine. +*/ +static void MSD_MASS_Status_Out(void) +{ + return; +} + +/******************************************************************************* +* Handle the data class specific requests.. +* \param[in] RequestNo +* \return RESULT +*/ +static RESULT MSD_MASS_Data_Setup(uint8_t RequestNo) +{ + uint8_t *(*CopyRoutine)( uint16_t); + + CopyRoutine = NULL; + if((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) && (RequestNo == GET_MAX_LUN) && (pInformation->USBwValue == 0) + && (pInformation->USBwIndex == 0) && (pInformation->USBwLength == 0x01)) { + CopyRoutine = Get_Max_Lun; + } else { + return USB_UNSUPPORT; + } + + if(CopyRoutine == NULL) { + return USB_UNSUPPORT; + } + + pInformation->Ctrl_Info.CopyData = CopyRoutine; + pInformation->Ctrl_Info.Usb_wOffset = 0; + (*CopyRoutine)(0); + + return USB_SUCCESS; +} + +/** +* Handle the no data class specific requests. +* \param[in] RequestNo +* \return RESULT +*/ +static RESULT MSD_MASS_NoData_Setup(uint8_t RequestNo) +{ + if((Type_Recipient == (CLASS_REQUEST | INTERFACE_RECIPIENT)) && (RequestNo == MASS_STORAGE_RESET) && (pInformation->USBwValue == 0) + && (pInformation->USBwIndex == 0) && (pInformation->USBwLength == 0x00)) { + /* Initialise Endpoint 1 */ + ClearDTOG_TX(ENDP1); + + /* Initialise Endpoint 2 */ + ClearDTOG_RX(ENDP2); + + /* Initialise the CBW signature to enable the clear feature*/ + MSD_CBW.dSignature = BOT_CBW_SIGNATURE; + MSD_Bot_State = BOT_IDLE; + + return USB_SUCCESS; + } + return USB_UNSUPPORT; +} + +/** +* Test the interface and the alternate setting according to the supported one. +* \param[in] Interface +* \param[in] AlternateSetting +* \return RESULT +*/ +static RESULT MSD_MASS_Get_Interface_Setting(uint8_t Interface, uint8_t AlternateSetting) +{ + if(AlternateSetting > 0) { + return USB_UNSUPPORT;/* In this application we don't have AlternateSetting*/ + } else if(Interface > 0) { + return USB_UNSUPPORT;/* In this application we have only 1 interfaces*/ + } + return USB_SUCCESS; +} + +/** +* Get the device descriptor. +* \param[in] Length +*/ +static uint8_t *MSD_MASS_GetDeviceDescriptor(uint16_t Length) +{ + return Standard_GetDescriptorData(Length, &Device_Descriptor); +} + +/** +* Get the configuration descriptor. +* \param[in] Length +*/ +static uint8_t *MSD_MASS_GetConfigDescriptor(uint16_t Length) +{ + return Standard_GetDescriptorData(Length, &Config_Descriptor); +} + +/** +* Get the string descriptors according to the needed index. +* \param[in] Length +*/ +static uint8_t *MSD_MASS_GetStringDescriptor(uint16_t Length) +{ + uint8_t wValue0 = pInformation->USBwValue0; + + if(wValue0 > 5) { + return NULL; + } else { + return Standard_GetDescriptorData(Length, &String_Descriptor[wValue0]); + } +} + +/** +* Handle the Get Max Lun request. +* \param[in] Length +*/ +static uint8_t *Get_Max_Lun(uint16_t Length) +{ + static uint32_t Max_Lun = MSD_NUM_LUN - 1; + + if(Length == 0) { + pInformation->Ctrl_Info.Usb_wLength = LUN_DATA_LENGTH; + return 0; + } else { + /* This copy concept requires statically allocated data... grr! */ + return ((uint8_t*) (&Max_Lun)); + } +} + diff --git a/flight/Libraries/msd/msd.h b/flight/Libraries/msd/msd.h new file mode 100644 index 000000000..613fdae1d --- /dev/null +++ b/flight/Libraries/msd/msd.h @@ -0,0 +1,78 @@ +/** + ****************************************************************************** + * + * @file msd.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2009. + * Parts by Thorsten Klose (tk@midibox.org) + * @brief MSD functions header. + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * 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. + * + * This program 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 this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +#ifndef _MSD_H +#define _MSD_H + +///////////////////////////////////////////////////////////////////////////// +// Global definitions +///////////////////////////////////////////////////////////////////////////// + +/* defines how many bytes are sent per packet */ +#define MSD_BULK_MAX_PACKET_SIZE 0x40 + +/* max. number of supported logical units */ +#define MSD_NUM_LUN 1 + +/* defines how many endpoints are used by the device */ +#define MSD_EP_NUM 3 + +/* buffer table base address */ + +#define MSD_BTABLE_ADDRESS (0x00) + +/* EP0 */ +/* rx/tx buffer base address */ +#define MSD_ENDP0_RXADDR (0x18) +#define MSD_ENDP0_TXADDR (0x58) + +/* EP1 */ +/* tx buffer base address */ +#define MSD_ENDP1_TXADDR (0x98) + +/* EP2 */ +/* Rx buffer base address */ +#define MSD_ENDP2_RXADDR (0xD8) + + + +///////////////////////////////////////////////////////////////////////////// +// Prototypes +///////////////////////////////////////////////////////////////////////////// + +extern s32 MSD_Init(u32 mode); +extern s32 MSD_Periodic_mS(void); + +extern s32 MSD_CheckAvailable(void); + +extern s32 MSD_LUN_AvailableSet(u8 lun, u8 available); +extern s32 MSD_LUN_AvailableGet(u8 lun); + +///////////////////////////////////////////////////////////////////////////// +// Export global variables +///////////////////////////////////////////////////////////////////////////// + + +#endif /* _MSD_H */ diff --git a/flight/Libraries/msd/msd_bot.c b/flight/Libraries/msd/msd_bot.c new file mode 100644 index 000000000..2ee50cf87 --- /dev/null +++ b/flight/Libraries/msd/msd_bot.c @@ -0,0 +1,334 @@ +/******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** +* File Name : usb_bot.c +* Author : MCD Application Team +* Version : V3.0.1 +* Date : 04/27/2009 +* Description : BOT State Machine management +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include +#include + +#include "msd.h" +#include "msd_scsi.h" +#include "msd_bot.h" +#include "msd_memory.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* Global variables ----------------------------------------------------------*/ +uint8_t MSD_Bot_State; +uint8_t MSD_Bulk_Data_Buff[MSD_BULK_MAX_PACKET_SIZE]; /* data buffer*/ +uint16_t MSD_Data_Len; +Bulk_Only_CBW MSD_CBW; +Bulk_Only_CSW MSD_CSW; + +/* Private variables ---------------------------------------------------------*/ +static uint32_t SCSI_LBA , SCSI_BlkLen; + +/* Extern variables ----------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Extern function prototypes ------------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/******************************************************************************* +* Function Name : MSD_Mass_Storage_In +* Description : Mass Storage IN transfer. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_Mass_Storage_In (void) +{ + switch (MSD_Bot_State) + { + case BOT_CSW_Send: + case BOT_ERROR: + MSD_Bot_State = BOT_IDLE; + SetEPRxStatus(ENDP2, EP_RX_VALID);/* enable the Endpoint to recive the next cmd*/ + break; + case BOT_DATA_IN: + switch (MSD_CBW.CB[0]) + { + case SCSI_READ10: + MSD_SCSI_Read10_Cmd(MSD_CBW.bLUN , SCSI_LBA , SCSI_BlkLen); + break; + } + break; + case BOT_DATA_IN_LAST: + MSD_Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE); + SetEPRxStatus(ENDP2, EP_RX_VALID); + break; + + default: + break; + } +} + +/******************************************************************************* +* Function Name : MSD_Mass_Storage_Out +* Description : Mass Storage OUT transfer. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_Mass_Storage_Out (void) +{ + uint8_t CMD; + CMD = MSD_CBW.CB[0]; + MSD_Data_Len = GetEPRxCount(ENDP2); + + PMAToUserBufferCopy(MSD_Bulk_Data_Buff, MSD_ENDP2_RXADDR, MSD_Data_Len); + + switch (MSD_Bot_State) + { + case BOT_IDLE: + MSD_CBW_Decode(); + break; + case BOT_DATA_OUT: + if (CMD == SCSI_WRITE10) + { + MSD_SCSI_Write10_Cmd(MSD_CBW.bLUN , SCSI_LBA , SCSI_BlkLen); + break; + } + MSD_Bot_Abort(DIR_OUT); + MSD_Set_Scsi_Sense_Data(MSD_CBW.bLUN, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + MSD_Set_CSW (CSW_PHASE_ERROR, SEND_CSW_DISABLE); + break; + default: + MSD_Bot_Abort(BOTH_DIR); + MSD_Set_Scsi_Sense_Data(MSD_CBW.bLUN, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + MSD_Set_CSW (CSW_PHASE_ERROR, SEND_CSW_DISABLE); + break; + } +} + +/******************************************************************************* +* Function Name : MSD_CBW_Decode +* Description : Decode the received CBW and call the related SCSI command +* routine. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_CBW_Decode(void) +{ + uint32_t Counter; + + for (Counter = 0; Counter < MSD_Data_Len; Counter++) + { + *((uint8_t *)&MSD_CBW + Counter) = MSD_Bulk_Data_Buff[Counter]; + } + MSD_CSW.dTag = MSD_CBW.dTag; + MSD_CSW.dDataResidue = MSD_CBW.dDataLength; + if (MSD_Data_Len != BOT_CBW_PACKET_LENGTH) + { + MSD_Bot_Abort(BOTH_DIR); + /* reset the MSD_CBW.dSignature to desible the clear feature until receiving a Mass storage reset*/ + MSD_CBW.dSignature = 0; + MSD_Set_Scsi_Sense_Data(MSD_CBW.bLUN, ILLEGAL_REQUEST, PARAMETER_LIST_LENGTH_ERROR); + MSD_Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); + return; + } + + if ((MSD_CBW.CB[0] == SCSI_READ10 ) || (MSD_CBW.CB[0] == SCSI_WRITE10 )) + { + /* Calculate Logical Block Address */ + SCSI_LBA = (MSD_CBW.CB[2] << 24) | (MSD_CBW.CB[3] << 16) | (MSD_CBW.CB[4] << 8) | MSD_CBW.CB[5]; + /* Calculate the Number of Blocks to transfer */ + SCSI_BlkLen = (MSD_CBW.CB[7] << 8) | MSD_CBW.CB[8]; + } + + if (MSD_CBW.dSignature == BOT_CBW_SIGNATURE) + { + /* Valid CBW */ + if ((MSD_CBW.bLUN >= MSD_NUM_LUN) || (MSD_CBW.bCBLength < 1) || (MSD_CBW.bCBLength > 16)) + { + MSD_Bot_Abort(BOTH_DIR); + MSD_Set_Scsi_Sense_Data(MSD_CBW.bLUN, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + MSD_Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); + } + else + { + switch (MSD_CBW.CB[0]) + { + case SCSI_REQUEST_SENSE: + MSD_SCSI_RequestSense_Cmd (MSD_CBW.bLUN); + break; + case SCSI_INQUIRY: + MSD_SCSI_Inquiry_Cmd(MSD_CBW.bLUN); + break; + case SCSI_START_STOP_UNIT: + MSD_SCSI_Start_Stop_Unit_Cmd(MSD_CBW.bLUN); + MSD_LUN_AvailableSet(MSD_CBW.bLUN, 0); + break; + case SCSI_ALLOW_MEDIUM_REMOVAL: + MSD_SCSI_Start_Stop_Unit_Cmd(MSD_CBW.bLUN); + break; + case SCSI_MODE_SENSE6: + MSD_SCSI_ModeSense6_Cmd (MSD_CBW.bLUN); + break; + case SCSI_MODE_SENSE10: + MSD_SCSI_ModeSense10_Cmd (MSD_CBW.bLUN); + break; + case SCSI_READ_FORMAT_CAPACITIES: + MSD_SCSI_ReadFormatCapacity_Cmd(MSD_CBW.bLUN); + break; + case SCSI_READ_CAPACITY10: + MSD_SCSI_ReadCapacity10_Cmd(MSD_CBW.bLUN); + break; + case SCSI_TEST_UNIT_READY: + MSD_SCSI_TestUnitReady_Cmd(MSD_CBW.bLUN); + break; + case SCSI_READ10: + MSD_SCSI_Read10_Cmd(MSD_CBW.bLUN, SCSI_LBA , SCSI_BlkLen); + break; + case SCSI_WRITE10: + MSD_SCSI_Write10_Cmd(MSD_CBW.bLUN, SCSI_LBA , SCSI_BlkLen); + break; + case SCSI_VERIFY10: + MSD_SCSI_Verify10_Cmd(MSD_CBW.bLUN); + break; + case SCSI_FORMAT_UNIT: + MSD_SCSI_Format_Cmd(MSD_CBW.bLUN); + break; + /*Unsupported command*/ + + case SCSI_MODE_SELECT10: + MSD_SCSI_Mode_Select10_Cmd(MSD_CBW.bLUN); + break; + case SCSI_MODE_SELECT6: + MSD_SCSI_Mode_Select6_Cmd(MSD_CBW.bLUN); + break; + + case SCSI_SEND_DIAGNOSTIC: + MSD_SCSI_Send_Diagnostic_Cmd(MSD_CBW.bLUN); + break; + case SCSI_READ6: + MSD_SCSI_Read6_Cmd(MSD_CBW.bLUN); + break; + case SCSI_READ12: + MSD_SCSI_Read12_Cmd(MSD_CBW.bLUN); + break; + case SCSI_READ16: + MSD_SCSI_Read16_Cmd(MSD_CBW.bLUN); + break; + case SCSI_READ_CAPACITY16: + MSD_SCSI_READ_CAPACITY16_Cmd(MSD_CBW.bLUN); + break; + case SCSI_WRITE6: + MSD_SCSI_Write6_Cmd(MSD_CBW.bLUN); + break; + case SCSI_WRITE12: + MSD_SCSI_Write12_Cmd(MSD_CBW.bLUN); + break; + case SCSI_WRITE16: + MSD_SCSI_Write16_Cmd(MSD_CBW.bLUN); + break; + case SCSI_VERIFY12: + MSD_SCSI_Verify12_Cmd(MSD_CBW.bLUN); + break; + case SCSI_VERIFY16: + MSD_SCSI_Verify16_Cmd(MSD_CBW.bLUN); + break; + + default: + { + MSD_Bot_Abort(BOTH_DIR); + MSD_Set_Scsi_Sense_Data(MSD_CBW.bLUN, ILLEGAL_REQUEST, INVALID_COMMAND); + MSD_Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); + } + } + } + } + else + { + /* Invalid CBW */ + MSD_Bot_Abort(BOTH_DIR); + MSD_Set_Scsi_Sense_Data(MSD_CBW.bLUN, ILLEGAL_REQUEST, INVALID_COMMAND); + MSD_Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); + } +} + +/******************************************************************************* +* Function Name : MSD_Transfer_Data_Request +* Description : Send the request response to the PC HOST. +* Input : uint8_t* Data_Address : point to the data to transfer. +* uint16_t Data_Length : the nember of Bytes to transfer. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_Transfer_Data_Request(uint8_t* Data_Pointer, uint16_t Data_Len) +{ + UserToPMABufferCopy(Data_Pointer, MSD_ENDP1_TXADDR, Data_Len); + + SetEPTxCount(ENDP1, Data_Len); + SetEPTxStatus(ENDP1, EP_TX_VALID); + MSD_Bot_State = BOT_DATA_IN_LAST; + MSD_CSW.dDataResidue -= Data_Len; + MSD_CSW.bStatus = CSW_CMD_PASSED; +} + +/******************************************************************************* +* Function Name : MSD_Set_CSW +* Description : Set the SCW with the needed fields. +* Input : uint8_t CSW_Status this filed can be CSW_CMD_PASSED,CSW_CMD_FAILED, +* or CSW_PHASE_ERROR. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_Set_CSW (uint8_t CSW_Status, uint8_t Send_Permission) +{ + MSD_CSW.dSignature = BOT_CSW_SIGNATURE; + MSD_CSW.bStatus = CSW_Status; + + UserToPMABufferCopy(((uint8_t *)& MSD_CSW), MSD_ENDP1_TXADDR, CSW_DATA_LENGTH); + + SetEPTxCount(ENDP1, CSW_DATA_LENGTH); + MSD_Bot_State = BOT_ERROR; + if (Send_Permission) + { + MSD_Bot_State = BOT_CSW_Send; + SetEPTxStatus(ENDP1, EP_TX_VALID); + } + +} + +/******************************************************************************* +* Function Name : MSD_Bot_Abort +* Description : Stall the needed Endpoint according to the selected direction. +* Input : Endpoint direction IN, OUT or both directions +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_Bot_Abort(uint8_t Direction) +{ + switch (Direction) + { + case DIR_IN : + SetEPTxStatus(ENDP1, EP_TX_STALL); + break; + case DIR_OUT : + SetEPRxStatus(ENDP2, EP_RX_STALL); + break; + case BOTH_DIR : + SetEPTxStatus(ENDP1, EP_TX_STALL); + SetEPRxStatus(ENDP2, EP_RX_STALL); + break; + default: + break; + } +} + +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ + diff --git a/flight/Libraries/msd/msd_bot.h b/flight/Libraries/msd/msd_bot.h new file mode 100644 index 000000000..4324c21b1 --- /dev/null +++ b/flight/Libraries/msd/msd_bot.h @@ -0,0 +1,95 @@ +/******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** +* File Name : usb_bot.h +* Author : MCD Application Team +* Version : V3.0.1 +* Date : 04/27/2009 +* Description : BOT State Machine management +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_BOT_H +#define __USB_BOT_H + +/* Includes ------------------------------------------------------------------*/ +/* Exported types ------------------------------------------------------------*/ +/* Bulk-only Command Block Wrapper */ + +typedef struct _Bulk_Only_CBW +{ + uint32_t dSignature; + uint32_t dTag; + uint32_t dDataLength; + uint8_t bmFlags; + uint8_t bLUN; + uint8_t bCBLength; + uint8_t CB[16]; +} +Bulk_Only_CBW; + +/* Bulk-only Command Status Wrapper */ +typedef struct _Bulk_Only_CSW +{ + uint32_t dSignature; + uint32_t dTag; + uint32_t dDataResidue; + uint8_t bStatus; +} +Bulk_Only_CSW; +/* Exported constants --------------------------------------------------------*/ + +/*****************************************************************************/ +/*********************** Bulk-Only Transfer State machine ********************/ +/*****************************************************************************/ +#define BOT_IDLE 0 /* Idle state */ +#define BOT_DATA_OUT 1 /* Data Out state */ +#define BOT_DATA_IN 2 /* Data In state */ +#define BOT_DATA_IN_LAST 3 /* Last Data In Last */ +#define BOT_CSW_Send 4 /* Command Status Wrapper */ +#define BOT_ERROR 5 /* error state */ + +#define BOT_CBW_SIGNATURE 0x43425355 +#define BOT_CSW_SIGNATURE 0x53425355 +#define BOT_CBW_PACKET_LENGTH 31 + +#define CSW_DATA_LENGTH 0x000D + +/* CSW Status Definitions */ +#define CSW_CMD_PASSED 0x00 +#define CSW_CMD_FAILED 0x01 +#define CSW_PHASE_ERROR 0x02 + +#define SEND_CSW_DISABLE 0 +#define SEND_CSW_ENABLE 1 + +#define DIR_IN 0 +#define DIR_OUT 1 +#define BOTH_DIR 2 + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +extern void MSD_Mass_Storage_In (void); +extern void MSD_Mass_Storage_Out (void); +extern void MSD_CBW_Decode(void); +extern void MSD_Transfer_Data_Request(uint8_t* Data_Pointer, uint16_t Data_Len); +extern void MSD_Set_CSW (uint8_t CSW_Status, uint8_t Send_Permission); +extern void MSD_Bot_Abort(uint8_t Direction); + + +/* Exported variables ------------------------------------------------------- */ +extern uint8_t MSD_Bot_State; +extern uint8_t MSD_Bulk_Data_Buff[MSD_BULK_MAX_PACKET_SIZE]; /* data buffer*/ +extern uint16_t MSD_Data_Len; +extern Bulk_Only_CBW MSD_CBW; +extern Bulk_Only_CSW MSD_CSW; + +#endif /* __USB_BOT_H */ + +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ + diff --git a/flight/Libraries/msd/msd_desc.c b/flight/Libraries/msd/msd_desc.c new file mode 100644 index 000000000..fe1c422c3 --- /dev/null +++ b/flight/Libraries/msd/msd_desc.c @@ -0,0 +1,135 @@ +/******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** +* File Name : usb_desc.c +* Author : MCD Application Team +* Version : V3.0.1 +* Date : 04/27/2009 +* Description : Descriptors for Mass Storage Device +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include "msd_desc.h" + +const uint8_t MSD_MASS_DeviceDescriptor[MSD_MASS_SIZ_DEVICE_DESC] = + { + 0x12, /* bLength */ + 0x01, /* bDescriptorType */ + 0x00, /* bcdUSB, version 2.00 */ + 0x02, + 0x00, /* bDeviceClass : each interface define the device class */ + 0x00, /* bDeviceSubClass */ + 0x00, /* bDeviceProtocol */ + 0x40, /* bMaxPacketSize0 0x40 = 64 */ + 0x83, /* idVendor (0483) */ + 0x04, + 0x20, /* idProduct */ + 0x57, + 0x00, /* bcdDevice 2.00*/ + 0x02, + 1, /* index of string Manufacturer */ + /**/ + 2, /* index of string descriptor of product*/ + /* */ + 3, /* */ + /* */ + /* */ + 0x01 /*bNumConfigurations */ + }; +const uint8_t MSD_MASS_ConfigDescriptor[MSD_MASS_SIZ_CONFIG_DESC] = + { + + 0x09, /* bLength: Configuation Descriptor size */ + 0x02, /* bDescriptorType: Configuration */ + MSD_MASS_SIZ_CONFIG_DESC, + + 0x00, + 0x01, /* bNumInterfaces: 1 interface */ + 0x01, /* bConfigurationValue: */ + /* Configuration value */ + 0x00, /* iConfiguration: */ + /* Index of string descriptor */ + /* describing the configuration */ + 0xC0, /* bmAttributes: */ + /* bus powered */ + 0x32, /* MaxPower 100 mA */ + + /******************** Descriptor of Mass Storage interface ********************/ + /* 09 */ + 0x09, /* bLength: Interface Descriptor size */ + 0x04, /* bDescriptorType: */ + /* Interface descriptor type */ + 0x00, /* bInterfaceNumber: Number of Interface */ + 0x00, /* bAlternateSetting: Alternate setting */ + 0x02, /* bNumEndpoints*/ + 0x08, /* bInterfaceClass: MASS STORAGE Class */ + 0x06, /* bInterfaceSubClass : SCSI transparent*/ + 0x50, /* nInterfaceProtocol */ + 4, /* iInterface: */ + /* 18 */ + 0x07, /*Endpoint descriptor length = 7*/ + 0x05, /*Endpoint descriptor type */ + 0x81, /*Endpoint address (IN, address 1) */ + 0x02, /*Bulk endpoint type */ + 0x40, /*Maximum packet size (64 bytes) */ + 0x00, + 0x00, /*Polling interval in milliseconds */ + /* 25 */ + 0x07, /*Endpoint descriptor length = 7 */ + 0x05, /*Endpoint descriptor type */ + 0x02, /*Endpoint address (OUT, address 2) */ + 0x02, /*Bulk endpoint type */ + 0x40, /*Maximum packet size (64 bytes) */ + 0x00, + 0x00 /*Polling interval in milliseconds*/ + /*32*/ + }; +const uint8_t MSD_MASS_StringLangID[MSD_MASS_SIZ_STRING_LANGID] = + { + MSD_MASS_SIZ_STRING_LANGID, + 0x03, + 0x09, + 0x04 + } + ; /* LangID = 0x0409: U.S. English */ +const uint8_t MSD_MASS_StringVendor[MSD_MASS_SIZ_STRING_VENDOR] = + { + MSD_MASS_SIZ_STRING_VENDOR, /* Size of manufaturer string */ + 0x03, /* bDescriptorType = String descriptor */ + /* Manufacturer */ + 'O', 0, 'p', 0, 'e', 0, 'n', 0, 'p', 0, 'i', 0, 'l', 0, 'o', 0, + 't', 0, + }; +const uint8_t MSD_MASS_StringProduct[MSD_MASS_SIZ_STRING_PRODUCT] = + { + MSD_MASS_SIZ_STRING_PRODUCT, + 0x03, + /* Product name */ + 'O', 0, 'p', 0, 'e', 0, 'n', 0, 'P', 0, 'i', 0, 'l', 0, 'o', 0, 't', 0, + ' ', 0, 'M', 0, 'a', 0, 's', 0, 's', 0, ' ', 0, 'S', 0, 't', 0, 'o', 0, + 'r', 0, 'a', 0, 'g', 0, 'e', 0 + + }; + +uint8_t MSD_MASS_StringSerial[MSD_MASS_SIZ_STRING_SERIAL] = + { + MSD_MASS_SIZ_STRING_SERIAL, + 0x03, + /* Serial number */ + '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0, '0', 0 + }; +const uint8_t MSD_MASS_StringInterface[MSD_MASS_SIZ_STRING_INTERFACE] = + { + MSD_MASS_SIZ_STRING_INTERFACE, + 0x03, + /* Interface 0: */ + 'S', 0, 'D', 0, ' ', 0, 'C', 0, 'a', 0, 'r', 0, 'd', 0 + }; + +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ + diff --git a/flight/Libraries/msd/msd_desc.h b/flight/Libraries/msd/msd_desc.h new file mode 100644 index 000000000..88d07b417 --- /dev/null +++ b/flight/Libraries/msd/msd_desc.h @@ -0,0 +1,48 @@ +/******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** +* File Name : usb_desc.h +* Author : MCD Application Team +* Version : V3.0.1 +* Date : 04/27/2009 +* Description : Descriptor Header for Mass Storage Device +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_DESC_H +#define __USB_DESC_H + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported define -----------------------------------------------------------*/ +#define MSD_MASS_SIZ_DEVICE_DESC 18 +#define MSD_MASS_SIZ_CONFIG_DESC 32 + +#define MSD_MASS_SIZ_STRING_LANGID 4 +#define MSD_MASS_SIZ_STRING_VENDOR 20 +#define MSD_MASS_SIZ_STRING_PRODUCT 46 +#define MSD_MASS_SIZ_STRING_SERIAL 26 +#define MSD_MASS_SIZ_STRING_INTERFACE 16 + +/* Exported functions ------------------------------------------------------- */ +extern const uint8_t MSD_MASS_DeviceDescriptor[MSD_MASS_SIZ_DEVICE_DESC]; +extern const uint8_t MSD_MASS_ConfigDescriptor[MSD_MASS_SIZ_CONFIG_DESC]; + +extern const uint8_t MSD_MASS_StringLangID[MSD_MASS_SIZ_STRING_LANGID]; +extern const uint8_t MSD_MASS_StringVendor[MSD_MASS_SIZ_STRING_VENDOR]; +extern const uint8_t MSD_MASS_StringProduct[MSD_MASS_SIZ_STRING_PRODUCT]; +extern uint8_t MSD_MASS_StringSerial[MSD_MASS_SIZ_STRING_SERIAL]; +extern const uint8_t MSD_MASS_StringInterface[MSD_MASS_SIZ_STRING_INTERFACE]; + +#endif /* __USB_DESC_H */ + +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ + diff --git a/flight/Libraries/msd/msd_memory.c b/flight/Libraries/msd/msd_memory.c new file mode 100644 index 000000000..1ea1d7b44 --- /dev/null +++ b/flight/Libraries/msd/msd_memory.c @@ -0,0 +1,242 @@ +/** + ****************************************************************************** + * + * @file msd_memory.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2009. + * Parts by Thorsten Klose (tk@midibox.org) + * @brief Memory Management Layer + * @see The GNU Public License (GPL) Version 3 + * @defgroup MSD MSD Functions + * @{ + * + *****************************************************************************/ +/* + * 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. + * + * This program 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 this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ +/******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** +* File Name : memory.c +* Author : MCD Application Team +* Version : V3.0.1 +* Date : 04/27/2009 +* Description : Memory management layer +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Includes ------------------------------------------------------------------*/ + +#include +#include + +#include "msd.h" +#include "msd_memory.h" +#include "msd_scsi.h" +#include "msd_bot.h" + + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ + +/* Global variables ----------------------------------------------------------*/ +uint32_t MSD_Mass_Memory_Size[MSD_NUM_LUN]; +uint32_t MSD_Mass_Block_Size[MSD_NUM_LUN]; +uint32_t MSD_Mass_Block_Count[MSD_NUM_LUN]; + + +/* Private variables ---------------------------------------------------------*/ +static __IO uint32_t Block_Read_count = 0; +static __IO uint32_t Block_offset; +static __IO uint32_t Counter = 0; +static uint32_t Idx; +static uint32_t Data_Buffer[MSD_BULK_MAX_PACKET_SIZE *2]; /* 512 bytes*/ +static uint8_t TransferState = TXFR_IDLE; + + +/* Extern variables ----------------------------------------------------------*/ + +/* Private function prototypes -----------------------------------------------*/ +/* Extern function prototypes ------------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + + +/******************************************************************************* +* Function Name : Read_Memory +* Description : Handle the Read operation from the microSD card. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_Read_Memory(uint8_t lun, uint32_t Memory_Offset, uint32_t Transfer_Length) +{ + static uint32_t Offset, Length; + + if (TransferState == TXFR_IDLE ) + { + Offset = Memory_Offset * MSD_Mass_Block_Size[lun]; + Length = Transfer_Length * MSD_Mass_Block_Size[lun]; + TransferState = TXFR_ONGOING; + } + + if (TransferState == TXFR_ONGOING ) + { + if (!Block_Read_count) + { + s32 status; + + switch( lun ) { + case 0: + if( MSD_Mass_Block_Size[lun] != 512 ) + break; + status = PIOS_SDCARD_SectorRead(Offset/512, (u8 *)Data_Buffer); + // TK: how to handle an error here? + break; + + default: + status = -1; + // TK: how to handle an error here? + } + + UserToPMABufferCopy((uint8_t *)Data_Buffer, MSD_ENDP1_TXADDR, MSD_BULK_MAX_PACKET_SIZE); + Block_Read_count = MSD_Mass_Block_Size[lun] - MSD_BULK_MAX_PACKET_SIZE; + Block_offset = MSD_BULK_MAX_PACKET_SIZE; + } + else + { + UserToPMABufferCopy((uint8_t *)Data_Buffer + Block_offset, MSD_ENDP1_TXADDR, MSD_BULK_MAX_PACKET_SIZE); + Block_Read_count -= MSD_BULK_MAX_PACKET_SIZE; + Block_offset += MSD_BULK_MAX_PACKET_SIZE; + } + + SetEPTxCount(ENDP1, MSD_BULK_MAX_PACKET_SIZE); + SetEPTxStatus(ENDP1, EP_TX_VALID); + Offset += MSD_BULK_MAX_PACKET_SIZE; + Length -= MSD_BULK_MAX_PACKET_SIZE; + + MSD_CSW.dDataResidue -= MSD_BULK_MAX_PACKET_SIZE; + } + if (Length == 0) + { + Block_Read_count = 0; + Block_offset = 0; + Offset = 0; + MSD_Bot_State = BOT_DATA_IN_LAST; + TransferState = TXFR_IDLE; + } +} + +/******************************************************************************* +* Function Name : Write_Memory +* Description : Handle the Write operation to the microSD card. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_Write_Memory (uint8_t lun, uint32_t Memory_Offset, uint32_t Transfer_Length) +{ + + static uint32_t W_Offset, W_Length; + + uint32_t temp = Counter + 64; + + if (TransferState == TXFR_IDLE ) + { + W_Offset = Memory_Offset * MSD_Mass_Block_Size[lun]; + W_Length = Transfer_Length * MSD_Mass_Block_Size[lun]; + TransferState = TXFR_ONGOING; + } + + if (TransferState == TXFR_ONGOING ) + { + + for (Idx = 0 ; Counter < temp; Counter++) + { + *((uint8_t *)Data_Buffer + Counter) = MSD_Bulk_Data_Buff[Idx++]; + } + + W_Offset += MSD_Data_Len; + W_Length -= MSD_Data_Len; + + if (!(W_Length % MSD_Mass_Block_Size[lun])) + { + Counter = 0; + + s32 status; + u32 Offset = W_Offset - MSD_Mass_Block_Size[lun]; + + switch( lun ) { + case 0: + if( MSD_Mass_Block_Size[lun] != 512 ) + break; + status = PIOS_SDCARD_SectorWrite(Offset/512, (u8 *)Data_Buffer); + // TK: how to handle an error here? + break; + + default: + status = -1; + // TK: how to handle an error here? + } + } + + MSD_CSW.dDataResidue -= MSD_Data_Len; + SetEPRxStatus(ENDP2, EP_RX_VALID); /* enable the next transaction*/ + } + + if ((W_Length == 0) || (MSD_Bot_State == BOT_CSW_Send)) + { + Counter = 0; + MSD_Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE); + TransferState = TXFR_IDLE; + } +} + + +/******************************************************************************* +* Function Name : MAL_GetStatus +* Description : Get status +* Input : None +* Output : None +* Return : None +*******************************************************************************/ +uint16_t MSD_MAL_GetStatus (uint8_t lun) +{ + // LUN removed or disabled? + if( !MSD_LUN_AvailableGet(lun) ) + return 1; + + if( lun == 0 ) { + SDCARDCsdTypeDef csd; + if( PIOS_SDCARD_CSDRead(&csd) < 0 ) + return 1; + + u32 DeviceSizeMul = csd.DeviceSizeMul + 2; + u32 temp_block_mul = (1 << csd.RdBlockLen)/ 512; + MSD_Mass_Block_Count[lun] = ((csd.DeviceSize + 1) * (1 << (DeviceSizeMul))) * temp_block_mul; + MSD_Mass_Block_Size[lun] = 512; + MSD_Mass_Memory_Size[lun] = (MSD_Mass_Block_Count[lun] * MSD_Mass_Block_Size[0]); + + return 0; + } + + return 1; +} + +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ + diff --git a/flight/Libraries/msd/msd_memory.h b/flight/Libraries/msd/msd_memory.h new file mode 100644 index 000000000..24d30d71d --- /dev/null +++ b/flight/Libraries/msd/msd_memory.h @@ -0,0 +1,43 @@ +/******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** +* File Name : memory.h +* Author : MCD Application Team +* Version : V3.0.1 +* Date : 04/27/2009 +* Description : Memory management layer +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __memory_H +#define __memory_H + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" +#include "msd.h" + +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ +#define TXFR_IDLE 0 +#define TXFR_ONGOING 1 + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +extern void MSD_Write_Memory (uint8_t lun, uint32_t Memory_Offset, uint32_t Transfer_Length); +extern void MSD_Read_Memory (uint8_t lun, uint32_t Memory_Offset, uint32_t Transfer_Length); +extern uint16_t MSD_MAL_GetStatus (uint8_t lun); + +/* Exported variables ------------------------------------------------------- */ +extern uint32_t MSD_Mass_Memory_Size[MSD_NUM_LUN]; +extern uint32_t MSD_Mass_Block_Size[MSD_NUM_LUN]; +extern uint32_t MSD_Mass_Block_Count[MSD_NUM_LUN]; + +#endif /* __memory_H */ + +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ + diff --git a/flight/Libraries/msd/msd_scsi.c b/flight/Libraries/msd/msd_scsi.c new file mode 100644 index 000000000..746ee2dda --- /dev/null +++ b/flight/Libraries/msd/msd_scsi.c @@ -0,0 +1,430 @@ +/******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** +* File Name : usb_scsi.c +* Author : MCD Application Team +* Version : V3.0.1 +* Date : 04/27/2009 +* Description : All processing related to the SCSI commands +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include +#include + +#include + +#include "msd.h" +#include "msd_scsi.h" +#include "msd_bot.h" +#include "msd_memory.h" +//#include "nand_if.h" +//#include "platform_config.h" + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* External variables --------------------------------------------------------*/ + +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/******************************************************************************* +* Function Name : SCSI_Inquiry_Cmd +* Description : SCSI Inquiry Command routine. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_SCSI_Inquiry_Cmd(uint8_t lun) +{ + uint8_t* Inquiry_Data; + uint16_t Inquiry_Data_Length; + + if (MSD_CBW.CB[1] & 0x01)/*Evpd is set*/ + { + Inquiry_Data = MSD_Page00_Inquiry_Data; + Inquiry_Data_Length = 5; + } + else + { + + if ( lun == 0) + { + Inquiry_Data = MSD_Standard_Inquiry_Data; + } + else + { + Inquiry_Data = MSD_Standard_Inquiry_Data2; + } + + if (MSD_CBW.CB[4] <= STANDARD_INQUIRY_DATA_LEN) + Inquiry_Data_Length = MSD_CBW.CB[4]; + else + Inquiry_Data_Length = STANDARD_INQUIRY_DATA_LEN; + + } + MSD_Transfer_Data_Request(Inquiry_Data, Inquiry_Data_Length); +} + +/******************************************************************************* +* Function Name : MSD_SCSI_ReadFormatCapacity_Cmd +* Description : SCSI ReadFormatCapacity Command routine. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_SCSI_ReadFormatCapacity_Cmd(uint8_t lun) +{ + + if (MSD_MAL_GetStatus(lun) != 0 ) + { + MSD_Set_Scsi_Sense_Data(MSD_CBW.bLUN, NOT_READY, MEDIUM_NOT_PRESENT); + MSD_Set_CSW (CSW_CMD_FAILED, SEND_CSW_ENABLE); + MSD_Bot_Abort(DIR_IN); + return; + } + MSD_ReadFormatCapacity_Data[4] = (uint8_t)(MSD_Mass_Block_Count[lun] >> 24); + MSD_ReadFormatCapacity_Data[5] = (uint8_t)(MSD_Mass_Block_Count[lun] >> 16); + MSD_ReadFormatCapacity_Data[6] = (uint8_t)(MSD_Mass_Block_Count[lun] >> 8); + MSD_ReadFormatCapacity_Data[7] = (uint8_t)(MSD_Mass_Block_Count[lun]); + + MSD_ReadFormatCapacity_Data[9] = (uint8_t)(MSD_Mass_Block_Size[lun] >> 16); + MSD_ReadFormatCapacity_Data[10] = (uint8_t)(MSD_Mass_Block_Size[lun] >> 8); + MSD_ReadFormatCapacity_Data[11] = (uint8_t)(MSD_Mass_Block_Size[lun]); + MSD_Transfer_Data_Request(MSD_ReadFormatCapacity_Data, READ_FORMAT_CAPACITY_DATA_LEN); +} + +/******************************************************************************* +* Function Name : MSD_SCSI_ReadCapacity10_Cmd +* Description : SCSI ReadCapacity10 Command routine. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_SCSI_ReadCapacity10_Cmd(uint8_t lun) +{ + + if (MSD_MAL_GetStatus(lun)) + { + MSD_Set_Scsi_Sense_Data(MSD_CBW.bLUN, NOT_READY, MEDIUM_NOT_PRESENT); + MSD_Set_CSW (CSW_CMD_FAILED, SEND_CSW_ENABLE); + MSD_Bot_Abort(DIR_IN); + return; + } + + MSD_ReadCapacity10_Data[0] = (uint8_t)((MSD_Mass_Block_Count[lun] - 1) >> 24); + MSD_ReadCapacity10_Data[1] = (uint8_t)((MSD_Mass_Block_Count[lun] - 1) >> 16); + MSD_ReadCapacity10_Data[2] = (uint8_t)((MSD_Mass_Block_Count[lun] - 1) >> 8); + MSD_ReadCapacity10_Data[3] = (uint8_t)((MSD_Mass_Block_Count[lun] - 1)); + + MSD_ReadCapacity10_Data[4] = (uint8_t)(MSD_Mass_Block_Size[lun] >> 24); + MSD_ReadCapacity10_Data[5] = (uint8_t)(MSD_Mass_Block_Size[lun] >> 16); + MSD_ReadCapacity10_Data[6] = (uint8_t)(MSD_Mass_Block_Size[lun] >> 8); + MSD_ReadCapacity10_Data[7] = (uint8_t)(MSD_Mass_Block_Size[lun]); + MSD_Transfer_Data_Request(MSD_ReadCapacity10_Data, READ_CAPACITY10_DATA_LEN); +} + +/******************************************************************************* +* Function Name : MSD_SCSI_ModeSense6_Cmd +* Description : SCSI ModeSense6 Command routine. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_SCSI_ModeSense6_Cmd (uint8_t lun) +{ + MSD_Transfer_Data_Request(MSD_Mode_Sense6_data, MODE_SENSE6_DATA_LEN); +} + +/******************************************************************************* +* Function Name : MSD_SCSI_ModeSense10_Cmd +* Description : SCSI ModeSense10 Command routine. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_SCSI_ModeSense10_Cmd (uint8_t lun) +{ + MSD_Transfer_Data_Request(MSD_Mode_Sense10_data, MODE_SENSE10_DATA_LEN); +} + +/******************************************************************************* +* Function Name : MSD_SCSI_RequestSense_Cmd +* Description : SCSI RequestSense Command routine. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_SCSI_RequestSense_Cmd (uint8_t lun) +{ + uint8_t Request_Sense_data_Length; + + if (MSD_CBW.CB[4] <= REQUEST_SENSE_DATA_LEN) + { + Request_Sense_data_Length = MSD_CBW.CB[4]; + } + else + { + Request_Sense_data_Length = REQUEST_SENSE_DATA_LEN; + } + MSD_Transfer_Data_Request(MSD_Scsi_Sense_Data, Request_Sense_data_Length); +} + +/******************************************************************************* +* Function Name : MSD_Set_Scsi_Sense_Data +* Description : Set Scsi Sense Data routine. +* Input : uint8_t Sens_Key + uint8_t Asc. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_Set_Scsi_Sense_Data(uint8_t lun, uint8_t Sens_Key, uint8_t Asc) +{ + MSD_Scsi_Sense_Data[2] = Sens_Key; + MSD_Scsi_Sense_Data[12] = Asc; +} + +/******************************************************************************* +* Function Name : MSD_SCSI_Start_Stop_Unit_Cmd +* Description : SCSI Start_Stop_Unit Command routine. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_SCSI_Start_Stop_Unit_Cmd(uint8_t lun) +{ + MSD_Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE); +} + +/******************************************************************************* +* Function Name : MSD_SCSI_Read10_Cmd +* Description : SCSI Read10 Command routine. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_SCSI_Read10_Cmd(uint8_t lun , uint32_t LBA , uint32_t BlockNbr) +{ + + if (MSD_Bot_State == BOT_IDLE) + { + if (!(MSD_SCSI_Address_Management(MSD_CBW.bLUN, SCSI_READ10, LBA, BlockNbr)))/*address out of range*/ + { + return; + } + + if ((MSD_CBW.bmFlags & 0x80) != 0) + { + MSD_Bot_State = BOT_DATA_IN; + MSD_Read_Memory(lun, LBA , BlockNbr); + } + else + { + MSD_Bot_Abort(BOTH_DIR); + MSD_Set_Scsi_Sense_Data(MSD_CBW.bLUN, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + MSD_Set_CSW (CSW_CMD_FAILED, SEND_CSW_ENABLE); + } + return; + } + else if (MSD_Bot_State == BOT_DATA_IN) + { + MSD_Read_Memory(lun , LBA , BlockNbr); + } +} + +/******************************************************************************* +* Function Name : MSD_SCSI_Write10_Cmd +* Description : SCSI Write10 Command routine. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_SCSI_Write10_Cmd(uint8_t lun , uint32_t LBA , uint32_t BlockNbr) +{ + + if (MSD_Bot_State == BOT_IDLE) + { + if (!(MSD_SCSI_Address_Management(MSD_CBW.bLUN, SCSI_WRITE10 , LBA, BlockNbr)))/*address out of range*/ + { + return; + } + + if ((MSD_CBW.bmFlags & 0x80) == 0) + { + MSD_Bot_State = BOT_DATA_OUT; + SetEPRxStatus(ENDP2, EP_RX_VALID); + } + else + { + MSD_Bot_Abort(DIR_IN); + MSD_Set_Scsi_Sense_Data(MSD_CBW.bLUN, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + MSD_Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); + } + return; + } + else if (MSD_Bot_State == BOT_DATA_OUT) + { + MSD_Write_Memory(lun , LBA , BlockNbr); + } +} + +/******************************************************************************* +* Function Name : MSD_SCSI_Verify10_Cmd +* Description : SCSI Verify10 Command routine. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_SCSI_Verify10_Cmd(uint8_t lun) +{ + if ((MSD_CBW.dDataLength == 0) && !(MSD_CBW.CB[1] & BLKVFY))/* BLKVFY not set*/ + { + MSD_Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE); + } + else + { + MSD_Bot_Abort(BOTH_DIR); + MSD_Set_Scsi_Sense_Data(MSD_CBW.bLUN, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + MSD_Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); + } +} +/******************************************************************************* +* Function Name : MSD_SCSI_Valid_Cmd +* Description : Valid Commands routine. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_SCSI_Valid_Cmd(uint8_t lun) +{ + if (MSD_CBW.dDataLength != 0) + { + MSD_Bot_Abort(BOTH_DIR); + MSD_Set_Scsi_Sense_Data(MSD_CBW.bLUN, ILLEGAL_REQUEST, INVALID_COMMAND); + MSD_Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); + } + else + MSD_Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE); +} +/******************************************************************************* +* Function Name : MSD_SCSI_Valid_Cmd +* Description : Valid Commands routine. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_SCSI_TestUnitReady_Cmd(uint8_t lun) +{ + if (MSD_MAL_GetStatus(lun)) + { + MSD_Set_Scsi_Sense_Data(MSD_CBW.bLUN, NOT_READY, MEDIUM_NOT_PRESENT); + MSD_Set_CSW (CSW_CMD_FAILED, SEND_CSW_ENABLE); + MSD_Bot_Abort(DIR_IN); + return; + } + else + { + MSD_Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE); + } +} +/******************************************************************************* +* Function Name : MSD_SCSI_Format_Cmd +* Description : Format Commands routine. +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_SCSI_Format_Cmd(uint8_t lun) +{ + if (MSD_MAL_GetStatus(lun)) + { + MSD_Set_Scsi_Sense_Data(MSD_CBW.bLUN, NOT_READY, MEDIUM_NOT_PRESENT); + MSD_Set_CSW (CSW_CMD_FAILED, SEND_CSW_ENABLE); + MSD_Bot_Abort(DIR_IN); + return; + } +#ifdef USE_STM3210E_EVAL + else + { + NAND_Format(); + MSD_Set_CSW (CSW_CMD_PASSED, SEND_CSW_ENABLE); + } +#endif + +} +/******************************************************************************* +* Function Name : MSD_SCSI_Invalid_Cmd +* Description : Invalid Commands routine +* Input : None. +* Output : None. +* Return : None. +*******************************************************************************/ +void MSD_SCSI_Invalid_Cmd(uint8_t lun) +{ + if (MSD_CBW.dDataLength == 0) + { + MSD_Bot_Abort(DIR_IN); + } + else + { + if ((MSD_CBW.bmFlags & 0x80) != 0) + { + MSD_Bot_Abort(DIR_IN); + } + else + { + MSD_Bot_Abort(BOTH_DIR); + } + } + MSD_Set_Scsi_Sense_Data(MSD_CBW.bLUN, ILLEGAL_REQUEST, INVALID_COMMAND); + MSD_Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); +} + +/******************************************************************************* +* Function Name : MSD_SCSI_Address_Management +* Description : Test the received address. +* Input : uint8_t Cmd : the command can be SCSI_READ10 or SCSI_WRITE10. +* Output : None. +* Return : Read\Write status (bool). +*******************************************************************************/ +bool MSD_SCSI_Address_Management(uint8_t lun , uint8_t Cmd , uint32_t LBA , uint32_t BlockNbr) +{ + + if ((LBA + BlockNbr) > MSD_Mass_Block_Count[lun] ) + { + if (Cmd == SCSI_WRITE10) + { + MSD_Bot_Abort(BOTH_DIR); + } + MSD_Bot_Abort(DIR_IN); + MSD_Set_Scsi_Sense_Data(lun, ILLEGAL_REQUEST, ADDRESS_OUT_OF_RANGE); + MSD_Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); + return (FALSE); + } + + + if (MSD_CBW.dDataLength != BlockNbr * MSD_Mass_Block_Size[lun]) + { + if (Cmd == SCSI_WRITE10) + { + MSD_Bot_Abort(BOTH_DIR); + } + else + { + MSD_Bot_Abort(DIR_IN); + } + MSD_Set_Scsi_Sense_Data(MSD_CBW.bLUN, ILLEGAL_REQUEST, INVALID_FIELED_IN_COMMAND); + MSD_Set_CSW (CSW_CMD_FAILED, SEND_CSW_DISABLE); + return (FALSE); + } + return (TRUE); +} +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ + diff --git a/flight/Libraries/msd/msd_scsi.h b/flight/Libraries/msd/msd_scsi.h new file mode 100644 index 000000000..45b0a28d6 --- /dev/null +++ b/flight/Libraries/msd/msd_scsi.h @@ -0,0 +1,142 @@ +/******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** +* File Name : usb_scsi.h +* Author : MCD Application Team +* Version : V3.0.1 +* Date : 04/27/2009 +* Description : All processing related to the SCSI commands +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef __USB_SCSI_H +#define __USB_SCSI_H + +/* Includes ------------------------------------------------------------------*/ +#include "stm32f10x.h" +/* Exported types ------------------------------------------------------------*/ +/* Exported constants --------------------------------------------------------*/ + +/* SCSI Commands */ +#define SCSI_FORMAT_UNIT 0x04 +#define SCSI_INQUIRY 0x12 +#define SCSI_MODE_SELECT6 0x15 +#define SCSI_MODE_SELECT10 0x55 +#define SCSI_MODE_SENSE6 0x1A +#define SCSI_MODE_SENSE10 0x5A +#define SCSI_ALLOW_MEDIUM_REMOVAL 0x1E +#define SCSI_READ6 0x08 +#define SCSI_READ10 0x28 +#define SCSI_READ12 0xA8 +#define SCSI_READ16 0x88 + +#define SCSI_READ_CAPACITY10 0x25 +#define SCSI_READ_CAPACITY16 0x9E + +#define SCSI_REQUEST_SENSE 0x03 +#define SCSI_START_STOP_UNIT 0x1B +#define SCSI_TEST_UNIT_READY 0x00 +#define SCSI_WRITE6 0x0A +#define SCSI_WRITE10 0x2A +#define SCSI_WRITE12 0xAA +#define SCSI_WRITE16 0x8A + +#define SCSI_VERIFY10 0x2F +#define SCSI_VERIFY12 0xAF +#define SCSI_VERIFY16 0x8F + +#define SCSI_SEND_DIAGNOSTIC 0x1D +#define SCSI_READ_FORMAT_CAPACITIES 0x23 + +#define NO_SENSE 0 +#define RECOVERED_ERROR 1 +#define NOT_READY 2 +#define MEDIUM_ERROR 3 +#define HARDWARE_ERROR 4 +#define ILLEGAL_REQUEST 5 +#define UNIT_ATTENTION 6 +#define DATA_PROTECT 7 +#define BLANK_CHECK 8 +#define VENDOR_SPECIFIC 9 +#define COPY_ABORTED 10 +#define ABORTED_COMMAND 11 +#define VOLUME_OVERFLOW 13 +#define MISCOMPARE 14 + + +#define INVALID_COMMAND 0x20 +#define INVALID_FIELED_IN_COMMAND 0x24 +#define PARAMETER_LIST_LENGTH_ERROR 0x1A +#define INVALID_FIELD_IN_PARAMETER_LIST 0x26 +#define ADDRESS_OUT_OF_RANGE 0x21 +#define MEDIUM_NOT_PRESENT 0x3A +#define MEDIUM_HAVE_CHANGED 0x28 + +#define READ_FORMAT_CAPACITY_DATA_LEN 0x0C +#define READ_CAPACITY10_DATA_LEN 0x08 +#define MODE_SENSE10_DATA_LEN 0x08 +#define MODE_SENSE6_DATA_LEN 0x04 +#define REQUEST_SENSE_DATA_LEN 0x12 +#define STANDARD_INQUIRY_DATA_LEN 0x24 +#define BLKVFY 0x04 + +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions ------------------------------------------------------- */ +extern void MSD_SCSI_Inquiry_Cmd(uint8_t lun); +extern void MSD_SCSI_ReadFormatCapacity_Cmd(uint8_t lun); +extern void MSD_SCSI_ReadCapacity10_Cmd(uint8_t lun); +extern void MSD_SCSI_RequestSense_Cmd (uint8_t lun); +extern void MSD_SCSI_Start_Stop_Unit_Cmd(uint8_t lun); +extern void MSD_SCSI_ModeSense6_Cmd (uint8_t lun); +extern void MSD_SCSI_ModeSense10_Cmd (uint8_t lun); +extern void MSD_SCSI_Write10_Cmd(uint8_t lun , uint32_t LBA , uint32_t BlockNbr); +extern void MSD_SCSI_Read10_Cmd(uint8_t lun , uint32_t LBA , uint32_t BlockNbr); +extern void MSD_SCSI_Verify10_Cmd(uint8_t lun); + +extern void MSD_SCSI_Invalid_Cmd(uint8_t lun); +extern void MSD_SCSI_Valid_Cmd(uint8_t lun); +extern bool MSD_SCSI_Address_Management(uint8_t lun , uint8_t Cmd , uint32_t LBA , uint32_t BlockNbr); + +extern void MSD_Set_Scsi_Sense_Data(uint8_t lun , uint8_t Sens_Key, uint8_t Asc); +extern void MSD_SCSI_TestUnitReady_Cmd (uint8_t lun); +extern void MSD_SCSI_Format_Cmd (uint8_t lun); + +//#define MSD_SCSI_TestUnitReady_Cmd MSD_SCSI_Valid_Cmd +#define MSD_SCSI_Prevent_Removal_Cmd MSD_SCSI_Valid_Cmd + +/* Invalid (Unsupported) commands */ +#define MSD_SCSI_READ_CAPACITY16_Cmd MSD_SCSI_Invalid_Cmd +//#define MSD_SCSI_FormatUnit_Cmd MSD_SCSI_Invalid_Cmd +#define MSD_SCSI_Write6_Cmd MSD_SCSI_Invalid_Cmd +#define MSD_SCSI_Write16_Cmd MSD_SCSI_Invalid_Cmd +#define MSD_SCSI_Write12_Cmd MSD_SCSI_Invalid_Cmd +#define MSD_SCSI_Read6_Cmd MSD_SCSI_Invalid_Cmd +#define MSD_SCSI_Read12_Cmd MSD_SCSI_Invalid_Cmd +#define MSD_SCSI_Read16_Cmd MSD_SCSI_Invalid_Cmd +#define MSD_SCSI_Send_Diagnostic_Cmd MSD_SCSI_Invalid_Cmd +#define MSD_SCSI_Mode_Select6_Cmd MSD_SCSI_Invalid_Cmd +#define MSD_SCSI_Mode_Select10_Cmd MSD_SCSI_Invalid_Cmd +#define MSD_SCSI_Verify12_Cmd MSD_SCSI_Invalid_Cmd +#define MSD_SCSI_Verify16_Cmd MSD_SCSI_Invalid_Cmd + + +/* Exported variables ------------------------------------------------------- */ +extern uint8_t MSD_Page00_Inquiry_Data[]; +extern uint8_t MSD_Standard_Inquiry_Data[]; +extern uint8_t MSD_Standard_Inquiry_Data2[]; +extern uint8_t MSD_Mode_Sense6_data[]; +extern uint8_t MSD_Mode_Sense10_data[]; +extern uint8_t MSD_Scsi_Sense_Data[]; +extern uint8_t MSD_ReadCapacity10_Data[]; +extern uint8_t MSD_ReadFormatCapacity_Data []; + + +#endif /* __USB_SCSI_H */ + +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ + diff --git a/flight/Libraries/msd/msd_scsi_data.c b/flight/Libraries/msd/msd_scsi_data.c new file mode 100644 index 000000000..a9522f936 --- /dev/null +++ b/flight/Libraries/msd/msd_scsi_data.c @@ -0,0 +1,144 @@ +/******************** (C) COPYRIGHT 2009 STMicroelectronics ******************** +* File Name : scsi_data.c +* Author : MCD Application Team +* Version : V3.0.1 +* Date : 04/27/2009 +* Description : Initialization of the SCSI data +******************************************************************************** +* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS +* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE TIME. +* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT, +* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE +* CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING +* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS. +*******************************************************************************/ + +/* Includes ------------------------------------------------------------------*/ +#include "msd_scsi.h" +#include "msd_memory.h" +uint8_t MSD_Page00_Inquiry_Data[] = + { + 0x00, /* PERIPHERAL QUALIFIER & PERIPHERAL DEVICE TYPE*/ + 0x00, + 0x00, + 0x00, + 0x00 /* Supported Pages 00*/ + }; +uint8_t MSD_Standard_Inquiry_Data[] = + { + 0x00, /* Direct Access Device */ + 0x80, /* RMB = 1: Removable Medium */ + 0x02, /* Version: No conformance claim to standard */ + 0x02, + + 36 - 4, /* Additional Length */ + 0x00, /* SCCS = 1: Storage Controller Component */ + 0x00, + 0x00, + /* Vendor Identification */ + 'G', 'e', 'n', 'e', 'r', 'i', 'c', ' ', + /* Product Identification */ + 'S', 'D', ' ', 'C', 'a', 'r', 'd', ' ', + 'R', 'e', 'a', 'd', 'e', 'r', ' ', ' ', + /* Product Revision Level */ + '1', '.', '0', ' ' + }; +uint8_t MSD_Standard_Inquiry_Data2[] = + { + 0x00, /* Direct Access Device */ + 0x80, /* RMB = 1: Removable Medium */ + 0x02, /* Version: No conformance claim to standard */ + 0x02, + + 36 - 4, /* Additional Length */ + 0x00, /* SCCS = 1: Storage Controller Component */ + 0x00, + 0x00, + /* Vendor Identification */ + 'S', 'T', 'M', ' ', ' ', ' ', ' ', ' ', + /* Product Identification */ + 'N', 'A', 'N', 'D', ' ', 'F', 'l', 'a', 's', 'h', ' ', + 'D', 'i', 's', 'k', ' ', + /* Product Revision Level */ + '1', '.', '0', ' ' + }; +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ +uint8_t MSD_Mode_Sense6_data[] = + { + 0x03, + 0x00, + 0x00, + 0x00, + }; + +/*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*/ + +uint8_t MSD_Mode_Sense10_data[] = + { + 0x00, + 0x06, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00 + }; +uint8_t MSD_Scsi_Sense_Data[] = + { + 0x70, /*RespCode*/ + 0x00, /*SegmentNumber*/ + NO_SENSE, /* Sens_Key*/ + 0x00, + 0x00, + 0x00, + 0x00, /*Information*/ + 0x0A, /*AdditionalSenseLength*/ + 0x00, + 0x00, + 0x00, + 0x00, /*CmdInformation*/ + NO_SENSE, /*Asc*/ + 0x00, /*ASCQ*/ + 0x00, /*FRUC*/ + 0x00, /*TBD*/ + 0x00, + 0x00 /*SenseKeySpecific*/ + }; +uint8_t MSD_ReadCapacity10_Data[] = + { + /* Last Logical Block */ + 0, + 0, + 0, + 0, + + /* Block Length */ + 0, + 0, + 0, + 0 + }; + +uint8_t MSD_ReadFormatCapacity_Data [] = + { + 0x00, + 0x00, + 0x00, + 0x08, /* Capacity List Length */ + + /* Block Count */ + 0, + 0, + 0, + 0, + + /* Block Length */ + 0x02,/* Descriptor Code: Formatted Media */ + 0, + 0, + 0 + }; + +/******************* (C) COPYRIGHT 2009 STMicroelectronics *****END OF FILE****/ + diff --git a/flight/Makefile b/flight/Makefile index 7ae0077b5..d700cbacf 100644 --- a/flight/Makefile +++ b/flight/Makefile @@ -33,9 +33,9 @@ CODE_SOURCERY=NO TCHAIN_PREFIX = arm-none-eabi- ifeq ($(CODE_SOURCERY), YES) -REMOVE_CMD=cs-rm +REMOVE_CMD = cs-rm else -REMOVE_CMD=rm +REMOVE_CMD = rm endif FLASH_TOOL = OPENOCD @@ -76,6 +76,7 @@ STMUSBSRCDIR = $(STMUSBDIR)/src STMUSBINCDIR = $(STMUSBDIR)/inc CMSISDIR = $(STMLIBDIR)/CMSIS/Core/CM3 DOSFSDIR = $(APPLIBDIR)/dosfs +MSDDIR = $(APPLIBDIR)/msd MININIDIR = $(APPLIBDIR)/minIni RTOSDIR = $(APPLIBDIR)/FreeRTOS RTOSSRCDIR = $(RTOSDIR)/Source @@ -103,6 +104,7 @@ SRC += $(PIOSSTM32F10X)/pios_servo.c SRC += $(PIOSSTM32F10X)/pios_i2c.c SRC += $(PIOSSTM32F10X)/pios_spi.c SRC += $(PIOSSTM32F10X)/pios_pwm.c +SRC += $(PIOSSTM32F10X)/pios_usb.c ## PIOS Hardware (Common) SRC += $(PIOSCOMMON)/pios_sdcard.c @@ -134,10 +136,11 @@ SRC += $(STMSPDSRCDIR)/stm32f10x_usart.c SRC += $(STMSPDSRCDIR)/misc.c ## STM32 USB Library -#SRC += $(STMUSBSRCDIR)/usb_core.c -#SRC += $(STMUSBSRCDIR)/usb_int.c -#SRC += $(STMUSBSRCDIR)/usb_mem.c -#SRC += $(STMUSBSRCDIR)/usb_regs.c +SRC += $(STMUSBSRCDIR)/usb_core.c +SRC += $(STMUSBSRCDIR)/usb_init.c +SRC += $(STMUSBSRCDIR)/usb_int.c +SRC += $(STMUSBSRCDIR)/usb_mem.c +SRC += $(STMUSBSRCDIR)/usb_regs.c ## RTOS SRC += $(RTOSSRCDIR)/list.c @@ -156,6 +159,14 @@ SRC += $(DOSFSDIR)/dfs_sdcard.c SRC += $(MININIDIR)/minIni.c SRC += $(MININIDIR)/minGlue.c +## Mass Storage Device +SRC += $(MSDDIR)/msd.c +SRC += $(MSDDIR)/msd_bot.c +SRC += $(MSDDIR)/msd_desc.c +SRC += $(MSDDIR)/msd_memory.c +SRC += $(MSDDIR)/msd_scsi.c +SRC += $(MSDDIR)/msd_scsi_data.c + # List C source files here which must be compiled in ARM-Mode (no -mthumb). # use file-extension c for "c-only"-files ## just for testing, timer.c could be compiled in thumb-mode too @@ -191,12 +202,13 @@ EXTRAINCDIRS += $(PIOSINC) EXTRAINCDIRS += $(PIOSSTM32F10X) EXTRAINCDIRS += $(PIOSCOMMON) EXTRAINCDIRS += $(STMSPDINCDIR) +EXTRAINCDIRS += $(STMUSBINCDIR) EXTRAINCDIRS += $(CMSISDIR) EXTRAINCDIRS += $(DOSFSDIR) +EXTRAINCDIRS += $(MSDDIR) EXTRAINCDIRS += $(MININIDIR) EXTRAINCDIRS += $(RTOSINCDIR) EXTRAINCDIRS += $(RTOSSRCDIR)/portable/GCC/ARM_CM3 -EXTRAINCDIRS += $(STMUSBINCDIR) # List any extra directories to look for library files here. @@ -241,7 +253,6 @@ DEBUGF = dwarf-2 CDEFS = -DSTM32F10X_$(MODEL) CDEFS += -DUSE_STDPERIPH_DRIVER CDEFS += -DUSE_$(BOARD) -CDEFS += -DSTM32_SD_USE_DMA # Place project-specific -D and/or -U options for # Assembler with preprocessor here. diff --git a/flight/PiOS/Common/pios_com.c b/flight/PiOS/Common/pios_com.c index 22c2efa0e..ad3937859 100644 --- a/flight/PiOS/Common/pios_com.c +++ b/flight/PiOS/Common/pios_com.c @@ -2,7 +2,7 @@ ****************************************************************************** * * @file pios_com.c - * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2009. + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2009. * @brief COM layer functions * @see The GNU Public License (GPL) Version 3 * @defgroup PIOS_COM COM layer functions diff --git a/flight/PiOS/Common/pios_sdcard.c b/flight/PiOS/Common/pios_sdcard.c index bbf03f7a8..cde71bef0 100644 --- a/flight/PiOS/Common/pios_sdcard.c +++ b/flight/PiOS/Common/pios_sdcard.c @@ -130,7 +130,7 @@ int32_t PIOS_SDCARD_PowerOn(void) PIOS_SPI_RC_PinSet(PIOS_SDCARD_SPI, 0); /* spi, pin_value */ /* wait for 1 mS */ - PIOS_DELAY_Wait_uS(1000); + PIOS_DELAY_WaituS(1000); /* Send CMD0 to reset the media */ if((status = PIOS_SDCARD_SendSDCCmd(SDCMD_GO_IDLE_STATE, 0, SDCMD_GO_IDLE_STATE_CRC)) < 0) { diff --git a/flight/PiOS/STM32F10x/pios_delay.c b/flight/PiOS/STM32F10x/pios_delay.c index 0b73c1da2..2972e4018 100644 --- a/flight/PiOS/STM32F10x/pios_delay.c +++ b/flight/PiOS/STM32F10x/pios_delay.c @@ -74,7 +74,7 @@ int32_t PIOS_DELAY_Init(void) * \param[in] uS delay (1..65535 microseconds) * \return < 0 on errors */ -int32_t PIOS_DELAY_Wait_uS(uint16_t uS) +int32_t PIOS_DELAY_WaituS(uint16_t uS) { uint16_t start = PIOS_DELAY_TIMER->CNT; @@ -96,10 +96,10 @@ int32_t PIOS_DELAY_Wait_uS(uint16_t uS) * \param[in] mS delay (1..65535 milliseconds) * \return < 0 on errors */ -int32_t PIOS_DELAY_Wait_mS(uint16_t mS) +int32_t PIOS_DELAY_WaitmS(uint16_t mS) { for(int i = 0; i < mS; i++) { - PIOS_DELAY_Wait_uS(1000); + PIOS_DELAY_WaituS(1000); } /* No error */ diff --git a/flight/PiOS/STM32F10x/pios_irq.c b/flight/PiOS/STM32F10x/pios_irq.c index c1f264e52..965d17dd3 100644 --- a/flight/PiOS/STM32F10x/pios_irq.c +++ b/flight/PiOS/STM32F10x/pios_irq.c @@ -55,7 +55,7 @@ int32_t PIOS_IRQ_Disable(void) ); } - /* disable interrupts */ + /* Disable interrupts */ __asm volatile ( \ " mov r0, #1 \n" \ " msr primask, r0\n" \ diff --git a/flight/PiOS/STM32F10x/pios_pwm.c b/flight/PiOS/STM32F10x/pios_pwm.c index b34d7a89a..f2a9f49f1 100644 --- a/flight/PiOS/STM32F10x/pios_pwm.c +++ b/flight/PiOS/STM32F10x/pios_pwm.c @@ -102,15 +102,17 @@ void TIM3_IRQHandler(void) /* Get the Input Capture value */ IC3Value = TIM_GetCapture3(TIM3); -// if (IC3Value != 0) -// { -// /* Duty cycle computation */ -// DutyCycle = (TIM_GetCapture1(TIM3) * 100) / IC3Value; -// -// /* Frequency computation */ -// Frequency = 72000000 / IC3Value; -// } else { -// DutyCycle = 0; -// Frequency = 0; -// } +#if 0 + if (IC3Value != 0) + { + /* Duty cycle computation */ + DutyCycle = (TIM_GetCapture1(TIM3) * 100) / IC3Value; + + /* Frequency computation */ + Frequency = 72000000 / IC3Value; + } else { + DutyCycle = 0; + Frequency = 0; + } +#endif } diff --git a/flight/PiOS/STM32F10x/pios_sys.c b/flight/PiOS/STM32F10x/pios_sys.c index fe6cc120e..d374cf5d5 100644 --- a/flight/PiOS/STM32F10x/pios_sys.c +++ b/flight/PiOS/STM32F10x/pios_sys.c @@ -33,6 +33,9 @@ void NVIC_Configuration(void); void SysTick_Handler(void); +/* Local Macros */ +#define MEM8(addr) (*((volatile uint8_t *)(addr))) + /** * Initializes all system peripherals */ @@ -75,6 +78,30 @@ void PIOS_SYS_Init(void) PIOS_LED_Init(); } +/** +* Returns the serial number as a string +* param[out] str pointer to a string which can store at least 32 digits + zero terminator! +* (24 digits returned for STM32) +* return < 0 if feature not supported +*/ +int32_t PIOS_SYS_SerialNumberGet(char *str) +{ + int i; + + /* Stored in the so called "electronic signature" */ + for(i=0; i<24; ++i) { + uint8_t b = MEM8(0x1ffff7e8 + (i/2)); + if( !(i & 1) ) + b >>= 4; + b &= 0x0f; + + str[i] = ((b > 9) ? ('A'-10) : '0') + b; + } + str[i] = 0; + + /* No error */ + return 0; +} /** * Configures Vector Table base location and SysTick diff --git a/flight/PiOS/STM32F10x/pios_usb.c b/flight/PiOS/STM32F10x/pios_usb.c new file mode 100644 index 000000000..b6e693f7c --- /dev/null +++ b/flight/PiOS/STM32F10x/pios_usb.c @@ -0,0 +1,484 @@ +/** + ****************************************************************************** + * + * @file pios_usb.c + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2009. + * Parts by Thorsten Klose (tk@midibox.org) + * @brief USB functions + * @see The GNU Public License (GPL) Version 3 + * @defgroup PIOS_USB USB Functions + * @{ + * + *****************************************************************************/ +/* + * 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. + * + * This program 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 this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +/* Project Includes */ +#include "pios.h" +#define PIOS_DONT_USE_USB_MIDI +#define PIOS_USE_USB_COM + +/* Private Function Prototypes */ + +/* Local Variables */ + +#include +#include + +/* Local definitions */ +#define DSCR_DEVICE 1 /* Descriptor type: Device */ +#define DSCR_CONFIG 2 /* Descriptor type: Configuration */ +#define DSCR_STRING 3 /* Descriptor type: String */ +#define DSCR_INTRFC 4 /* Descriptor type: Interface */ +#define DSCR_ENDPNT 5 /* Descriptor type: Endpoint */ +#define CS_INTERFACE 0x24 /* Class-specific type: Interface */ +#define CS_ENDPOINT 0x25 /* Class-specific type: Endpoint */ +/* ISTR events */ +/* mask defining which events has to be handled by the device application software */ +#define IMR_MSK (CNTR_CTRM | CNTR_RESETM) + +/* Local types */ +typedef enum _DEVICE_STATE { + UNCONNECTED, ATTACHED, POWERED, SUSPENDED, ADDRESSED, CONFIGURED +} DEVICE_STATE; + +/* Global Variables used by STM32 USB Driver */ +/* (unfortunately no unique names are used...) */ +/* Points to the DEVICE_INFO/DEVICE_PROP_USER_STANDARD_REQUESTS structure of current device */ +/* The purpose of this register is to speed up the execution */ +DEVICE_INFO *pInformation; +DEVICE Device_Table; +DEVICE_PROP *pProperty; +USER_STANDARD_REQUESTS *pUser_Standard_Requests; + +/* Stored in RAM, vectors can be changed on-the-fly */ +void (*pEpInt_IN[7])(void) = {NOP_Process, NOP_Process, NOP_Process, NOP_Process, NOP_Process, NOP_Process, NOP_Process}; +void (*pEpInt_OUT[7])(void) = {NOP_Process, NOP_Process, NOP_Process, NOP_Process, NOP_Process, NOP_Process, NOP_Process}; + +#define PIOS_USB_NUM_INTERFACES (0) +#define PIOS_USB_SIZ_CONFIG_DESC (9 + 0) + +/* USB Standard Device Descriptor */ +#define PIOS_USB_SIZ_DEVICE_DESC 18 +static const uint8_t PIOS_USB_DeviceDescriptor[PIOS_USB_SIZ_DEVICE_DESC] = {(uint8_t)(PIOS_USB_SIZ_DEVICE_DESC & 0xff), /* Device Descriptor length */ + DSCR_DEVICE, /* Descriptor type */ + (uint8_t)(0x0200 & 0xff), /* Specification Version (BCD, LSB) */ + (uint8_t)(0x0200 >> 8), /* Specification Version (BCD, MSB) */ +#if 1 + 0x02, /* Device class "Communication" -- required for MacOS to find the COM device. Audio Device works fine in parallel to this */ +#else + 0x00, /* Device class "Composite" */ +#endif + 0x00, /* Device sub-class */ + 0x00, /* Device sub-sub-class */ + 0x40, /* Maximum packet size */ + (uint8_t)((PIOS_USB_VENDOR_ID) & 0xff), /* Vendor ID (LSB) */ + (uint8_t)((PIOS_USB_VENDOR_ID) >> 8), /* Vendor ID (MSB) */ + (uint8_t)((PIOS_USB_PRODUCT_ID) & 0xff), /* Product ID (LSB) */ + (uint8_t)((PIOS_USB_PRODUCT_ID) >> 8), /* Product ID (MSB) */ + (uint8_t)((PIOS_USB_VERSION_ID) & 0xff), /* Product version ID (LSB) */ + (uint8_t)((PIOS_USB_VERSION_ID) >> 8), /* Product version ID (MSB) */ + 0x01, /* Manufacturer string index */ + 0x02, /* Product string index */ + 0x03, /* Serial number string index */ + 0x01 /* Number of configurations */ + }; + +/* USB Config Descriptor */ +static const uint8_t PIOS_USB_ConfigDescriptor[PIOS_USB_SIZ_CONFIG_DESC] = { + /* Configuration Descriptor */ + 9, /* Descriptor length */ + DSCR_CONFIG, // Descriptor type */ + (PIOS_USB_SIZ_CONFIG_DESC) & 0xff, /* Config + End Points length (LSB) */ + (PIOS_USB_SIZ_CONFIG_DESC) >> 8, /* Config + End Points length (LSB) */ + PIOS_USB_NUM_INTERFACES, /* Number of interfaces */ + 0x01, /* Configuration Value */ + 0x00, /* Configuration string */ + 0x80, /* Attributes (b7 - buspwr, b6 - selfpwr, b5 - rwu) */ + 0x32, /* Power requirement (div 2 ma) */ + + /* TODO:HID */ + + }; + +/* Local prototypes */ +static void PIOS_USB_CB_Reset(void); +static void PIOS_USB_CB_SetConfiguration(void); +static void PIOS_USB_CB_SetDeviceAddress(void); +static void PIOS_USB_CB_Status_In(void); +static void PIOS_USB_CB_Status_Out(void); +static RESULT PIOS_USB_CB_Data_Setup(uint8_t RequestNo); +static RESULT PIOS_USB_CB_NoData_Setup(uint8_t RequestNo); +static uint8_t *PIOS_USB_CB_GetDeviceDescriptor(uint16_t Length); +static uint8_t *PIOS_USB_CB_GetConfigDescriptor(uint16_t Length); +static uint8_t *PIOS_USB_CB_GetStringDescriptor(uint16_t Length); +static RESULT PIOS_USB_CB_Get_Interface_Setting(uint8_t Interface, uint8_t AlternateSetting); + +/* USB callback vectors */ +static const DEVICE My_Device_Table = {PIOS_USB_EP_NUM, 1}; +static const DEVICE_PROP My_Device_Property = { + 0, /* PIOS_USB_CB_Init, */ + PIOS_USB_CB_Reset, PIOS_USB_CB_Status_In, PIOS_USB_CB_Status_Out, PIOS_USB_CB_Data_Setup, PIOS_USB_CB_NoData_Setup, + PIOS_USB_CB_Get_Interface_Setting, PIOS_USB_CB_GetDeviceDescriptor, PIOS_USB_CB_GetConfigDescriptor, PIOS_USB_CB_GetStringDescriptor, 0, 0x40 /*MAX PACKET SIZE*/ +}; +static const USER_STANDARD_REQUESTS My_User_Standard_Requests = {NOP_Process, /* PIOS_USB_CB_GetConfiguration, */ + PIOS_USB_CB_SetConfiguration, NOP_Process, /* PIOS_USB_CB_GetInterface, */ + NOP_Process, /* PIOS_USB_CB_SetInterface, */ + NOP_Process, /* PIOS_USB_CB_GetStatus, */ + NOP_Process, /* PIOS_USB_CB_ClearFeature, */ + NOP_Process, /* PIOS_USB_CB_SetEndPointFeature, */ + NOP_Process, /* PIOS_USB_CB_SetDeviceFeature, */ + PIOS_USB_CB_SetDeviceAddress}; + +/* Local Variables */ +/* USB Device informations */ +static DEVICE_INFO My_Device_Info; +/* USB device status */ +static __IO uint32_t bDeviceState = UNCONNECTED; + +/** +* Initialises USB interface +* \param[in] mode +*
    +*
  • if 0, USB peripheral won't be initialised if this has already been done before +*
  • if 1, USB peripheral re-initialisation will be forced +*
  • if 2, USB peripheral re-initialisation will be forced, STM32 driver hooks won't be overwritten.
    +* This mode can be used for a local USB driver which installs it's own hooks during runtime.
    +* The application can switch back to MIOS32 drivers (e.g. PIOS_USB_MIDI) by calling PIOS_USB_Init(1) +*
+* \return < 0 if initialisation failed +* \note Applications shouldn't call this function directly, instead please use \ref PIOS_COM layer functions +*/ +int32_t PIOS_USB_Init(uint32_t mode) +{ + /* Currently only mode 0..2 supported */ + if(mode >= 3) { + /* Unsupported mode */ + return -1; + } + + /* Clear all USB interrupt requests */ + PIOS_IRQ_Disable(); + _SetCNTR(0); /* Interrupt Mask */ + PIOS_IRQ_Enable(); + + /* if mode != 2: install PIOS hooks */ + /* a local driver can install it's own hooks and call PIOS_USB_Init(2) to force re-enumeration */ + if(mode != 2) { + pInformation = &My_Device_Info; /* Note: usually no need to duplicate this for external drivers */ + + /* Following hooks/pointers should be replaced by external drivers */ + memcpy(&Device_Table, (DEVICE *) &My_Device_Table, sizeof(Device_Table)); + pProperty = (DEVICE_PROP *) &My_Device_Property; + pUser_Standard_Requests = (USER_STANDARD_REQUESTS *) &My_User_Standard_Requests; + } + + pInformation->ControlState = 2; + pInformation->Current_Configuration = 0; + + /* if mode == 0: don't initialise USB if not required (important for BSL) */ + if(mode == 0 && PIOS_USB_IsInitialized()) { + pInformation->Current_Feature = PIOS_USB_ConfigDescriptor[7]; + pInformation->Current_Configuration = 1; + pUser_Standard_Requests->User_SetConfiguration(); + + } else { + /* Force USB reset and power-down (this will also release the USB pins for direct GPIO control) */ + _SetCNTR(CNTR_FRES | CNTR_PDWN); + +#if 0 + /* Disabled because it doesn't work, hardware needs to be looked into */ + /* Configure USB disconnect pin */ + /* first we hold it low for ca. 50 mS to force a re-enumeration */ + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_StructInit(&GPIO_InitStructure); + GPIO_InitStructure.GPIO_Pin = USB_PULLUP_PIN; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(USB_ACC_GPIO_PORT, &GPIO_InitStructure); + + GPIO_SetBits(USB_ACC_GPIO_PORT, USB_PULLUP_PIN); + PIOS_DELAY_WaitmS(50); + + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; + GPIO_Init(USB_ACC_GPIO_PORT, &GPIO_InitStructure); +#endif + + /* Using a "dirty" method to force a re-enumeration: */ + /* Force DPM (Pin PA12) low for ca. 10 mS before USB Tranceiver will be enabled */ + /* This overrules the external Pull-Up at PA12, and at least Windows & MacOS will enumerate again */ + GPIO_InitTypeDef GPIO_InitStructure; + GPIO_StructInit(&GPIO_InitStructure); + GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; + GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; + GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; + GPIO_Init(GPIOA, &GPIO_InitStructure); + + GPIO_ResetBits(USB_ACC_GPIO_PORT, USB_PULLUP_PIN); + + PIOS_DELAY_WaitmS(50); + + /* Release power-down, still hold reset */ + _SetCNTR(CNTR_PDWN); + + PIOS_DELAY_WaituS(5); + + /* CNTR_FRES = 0 */ + _SetCNTR(0); + + /* Clear pending interrupts */ + _SetISTR(0); + + /* Configure USB clock */ + /* USBCLK = PLLCLK / 1.5 */ + RCC_USBCLKConfig(RCC_USBCLKSource_PLLCLK_1Div5); + /* Enable USB clock */ + RCC_APB1PeriphClockCmd(RCC_APB1Periph_USB, ENABLE); + } + + /* Don't set interrupt mask on custom driver installation */ + if(mode != 2) { + /* Clear pending interrupts (again) */ + _SetISTR(0); + + /* Set interrupts mask */ + _SetCNTR(IMR_MSK); /* Interrupt mask */ + } + + bDeviceState = UNCONNECTED; + + /* Enable USB interrupts (unfortunately shared with CAN Rx0, as either CAN or USB can be used, but not at the same time) */ + NVIC_InitTypeDef NVIC_InitStructure; + NVIC_InitStructure.NVIC_IRQChannel = USB_LP_CAN1_RX0_IRQn; + NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_USB_PRIORITY; + NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; + NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; + NVIC_Init(&NVIC_InitStructure); + + /* No error */ + return 0; +} + +/** +* Interrupt handler for USB +* \note Applications shouldn't call this function directly, instead please use \ref PIOS_COM layer functions +*/ +void USB_LP_CAN1_RX0_IRQHandler(void) +{ + uint16_t wIstr = _GetISTR(); + + if(wIstr & ISTR_RESET) { + _SetISTR((uint16_t)CLR_RESET); + pProperty->Reset(); + } + + if(wIstr & ISTR_SOF) { + _SetISTR((uint16_t)CLR_SOF); + } + + if(wIstr & ISTR_CTR) { + /* Servicing of the endpoint correct transfer interrupt */ + /* Clear of the CTR flag into the sub */ + CTR_LP(); + } +} + +/** +* Allows to query, if the USB interface has already been initialised.
+* This function is used by the bootloader to avoid a reconnection, it isn't +* relevant for typical applications! +* \return 1 if USB already initialised, 0 if not initialised +*/ +int32_t PIOS_USB_IsInitialized(void) +{ + /* We assume that initialisation has been done when endpoint 0 contains a value */ + return GetEPType(ENDP0) ? 1 : 0; +} + + +/* +* Hooks of STM32 USB library +* \note Applications shouldn't call this function directly, instead please use \ref PIOS_COM layer functions +*/ +/** +* Reset Routine +*/ +static void PIOS_USB_CB_Reset(void) +{ + /* Set MIOS32 Device as not configured */ + pInformation->Current_Configuration = 0; + + /* Current Feature initialization */ + pInformation->Current_Feature = PIOS_USB_ConfigDescriptor[7]; + + /* Set PIOS Device with the default Interface */ + pInformation->Current_Interface = 0; + SetBTABLE(PIOS_USB_BTABLE_ADDRESS); + + /* Initialize Endpoint 0 */ + SetEPType(ENDP0, EP_CONTROL); + SetEPTxStatus(ENDP0, EP_TX_STALL); + SetEPRxAddr(ENDP0, PIOS_USB_ENDP0_RXADDR); + SetEPTxAddr(ENDP0, PIOS_USB_ENDP0_TXADDR); + Clear_Status_Out(ENDP0); + SetEPRxCount(ENDP0, pProperty->MaxPacketSize); + SetEPRxValid(ENDP0); + + /* Set this device to response on default address */ + SetDeviceAddress(0); + + bDeviceState = ATTACHED; +} + +/** +* Update the device state to configured +*/ +static void PIOS_USB_CB_SetConfiguration(void) +{ + if(pInformation->Current_Configuration != 0) { + bDeviceState = CONFIGURED; + } +} + +/** +* Update the device state to addressed +*/ +static void PIOS_USB_CB_SetDeviceAddress(void) +{ + bDeviceState = ADDRESSED; +} + +/** +* Status IN routine +*/ +static void PIOS_USB_CB_Status_In(void) +{ + +} + +/** +* Status OUT routine +*/ +static void PIOS_USB_CB_Status_Out(void) +{ + +} + +/** +* Data setup routine +*/ +static RESULT PIOS_USB_CB_Data_Setup(uint8_t RequestNo) +{ + return USB_UNSUPPORT; +} + +/** +* Handles the non data class specific requests +*/ +static RESULT PIOS_USB_CB_NoData_Setup(uint8_t RequestNo) +{ + return USB_UNSUPPORT; +} + +/** +* Gets the device descriptor +*/ +static uint8_t *PIOS_USB_CB_GetDeviceDescriptor(uint16_t Length) +{ + ONE_DESCRIPTOR desc = {(uint8_t *) PIOS_USB_DeviceDescriptor, PIOS_USB_SIZ_DEVICE_DESC}; + return Standard_GetDescriptorData(Length, &desc); +} + +/** +* Gets the configuration descriptor +*/ +static uint8_t *PIOS_USB_CB_GetConfigDescriptor(uint16_t Length) +{ + ONE_DESCRIPTOR desc = {(uint8_t *) PIOS_USB_ConfigDescriptor, PIOS_USB_SIZ_CONFIG_DESC}; + return Standard_GetDescriptorData(Length, &desc); +} + +/** +* Gets the string descriptors according to the needed index +*/ +static uint8_t *PIOS_USB_CB_GetStringDescriptor(uint16_t Length) +{ + const uint8_t vendor_str[] = PIOS_USB_VENDOR_STR; + const uint8_t product_str[] = PIOS_USB_PRODUCT_STR; + + uint8_t buffer[200]; + uint16_t len; + int i; + + switch(pInformation->USBwValue0) { + case 0: /* Language */ + /* buffer[0] and [1] initialized below */ + buffer[2] = 0x09; // CharSet + buffer[3] = 0x04; // U.S. + len = 4; + break; + + case 1: /* Vendor */ + /* buffer[0] and [1] initialized below */ + for(i = 0, len = 2; vendor_str[i] != '\0' && len < 200; ++i) { + buffer[len++] = vendor_str[i]; + buffer[len++] = 0; + } + break; + + case 2: /* Product */ + /* buffer[0] and [1] initialized below */ + for(i = 0, len = 2; product_str[i] != '\0' && len < 200; ++i) { + buffer[len++] = product_str[i]; + buffer[len++] = 0; + } + break; + + case 3: { /* Serial Number */ + uint8_t serial_number_str[40]; + if(PIOS_SYS_SerialNumberGet((char *) serial_number_str) >= 0) { + for(i = 0, len = 2; serial_number_str[i] != '\0' && len < 200; ++i) { + buffer[len++] = serial_number_str[i]; + buffer[len++] = 0; + } + } else + return NULL; + } + break; + default: /* string ID not supported */ + return NULL; + } + + buffer[0] = len; /* Descriptor Length */ + buffer[1] = DSCR_STRING; /* Descriptor Type */ + ONE_DESCRIPTOR desc = {(uint8_t *) buffer, len}; + return Standard_GetDescriptorData(Length, &desc); +} + +/** +* Test the interface and the alternate setting according to the supported one. +*/ +static RESULT PIOS_USB_CB_Get_Interface_Setting(uint8_t Interface, uint8_t AlternateSetting) +{ + if(AlternateSetting > 0) { + return USB_UNSUPPORT; + } else if(Interface >= PIOS_USB_NUM_INTERFACES) { + return USB_UNSUPPORT; + } + + return USB_SUCCESS; +} + diff --git a/flight/PiOS/inc/pios_board.h b/flight/PiOS/inc/pios_board.h index 1f65ca89f..302c776cf 100644 --- a/flight/PiOS/inc/pios_board.h +++ b/flight/PiOS/inc/pios_board.h @@ -32,10 +32,10 @@ // DMA Channels Used //------------------------ /* Channel 1 - */ -/* Channel 2 - SPI1 RX */ -/* Channel 3 - SPI1 TX */ -/* Channel 4 - SPI2 RX */ -/* Channel 5 - SPI2 TX */ +/* Channel 2 - SPI1 RX */ +/* Channel 3 - SPI1 TX */ +/* Channel 4 - SPI2 RX */ +/* Channel 5 - SPI2 TX */ /* Channel 6 - */ /* Channel 7 - */ /* Channel 8 - */ @@ -47,49 +47,49 @@ //------------------------ // Leds Definition //------------------------ -#define LED1_GPIO_PORT GPIOC -#define LED1_GPIO_PIN GPIO_Pin_12 -#define LED1_GPIO_CLK RCC_APB2Periph_GPIOC -#define LED2_GPIO_PORT GPIOC -#define LED2_GPIO_PIN GPIO_Pin_13 -#define LED2_GPIO_CLK RCC_APB2Periph_GPIOC +#define LED1_GPIO_PORT GPIOC +#define LED1_GPIO_PIN GPIO_Pin_12 +#define LED1_GPIO_CLK RCC_APB2Periph_GPIOC +#define LED2_GPIO_PORT GPIOC +#define LED2_GPIO_PIN GPIO_Pin_13 +#define LED2_GPIO_CLK RCC_APB2Periph_GPIOC #define NUM_LED 2 //------------------------ // I2C //------------------------ -#define I2C_GPIO_PORT GPIOB +#define I2C_GPIO_PORT GPIOB #define I2C_SDA_PIN GPIO_Pin_11 #define I2C_SCL_PIN GPIO_Pin_10 -#define I2C_DUTY_CYCLE I2C_DutyCycle_2 -#define I2C_BUS_FREQUENCY 400000 -#define I2C_TIMEOUT_VALUE 5000 -#define IRQ_I2C_EV_PRIORITY 2 -#define IRQ_I2C_ER_PRIORITY 2 +#define I2C_DUTY_CYCLE I2C_DutyCycle_2 +#define I2C_BUS_FREQUENCY 400000 +#define I2C_TIMEOUT_VALUE 5000 +#define IRQ_I2C_EV_PRIORITY 2 +#define IRQ_I2C_ER_PRIORITY 2 //------------------------ // Onboard Pressure sensor //------------------------ -#define BMP085_EOC_GPIO_PORT GPIOC -#define BMP085_EOC_GPIO_PIN GPIO_Pin_15 -#define BMP085_EOC_PORT_SOURCE GPIO_PortSourceGPIOG -#define BMP085_EOC_PIN_SOURCE GPIO_PinSource8 -#define BMP085_EOC_CLK RCC_APB2Periph_GPIOC -#define BMP085_EOC_EXTI_LINE EXTI_Line15 -#define BMP085_EOC_IRQn EXTI15_10_IRQn +#define BMP085_EOC_GPIO_PORT GPIOC +#define BMP085_EOC_GPIO_PIN GPIO_Pin_15 +#define BMP085_EOC_PORT_SOURCE GPIO_PortSourceGPIOG +#define BMP085_EOC_PIN_SOURCE GPIO_PinSource8 +#define BMP085_EOC_CLK RCC_APB2Periph_GPIOC +#define BMP085_EOC_EXTI_LINE EXTI_Line15 +#define BMP085_EOC_IRQn EXTI15_10_IRQn /* Unused, repurpose PA1 as another ADC input? -#define BMP085_XCLR_GPIO_PORT GPIOA -#define BMP085_XCLR_GPIO_PIN GPIO_Pin_1 +#define BMP085_XCLR_GPIO_PORT GPIOA +#define BMP085_XCLR_GPIO_PIN GPIO_Pin_1 */ //------------------------- // GPS USART //------------------------- -#define GPS_USART USART2 +#define GPS_USART USART2 #define GPS_GPIO_PORT GPIOA -#define GPS_RX_PIN GPIO_Pin_3 -#define GPS_TX_PIN GPIO_Pin_2 +#define GPS_RX_PIN GPIO_Pin_3 +#define GPS_TX_PIN GPIO_Pin_2 #define GPS_REMAP_FUNC { } #define GPS_IRQ_CHANNEL USART2_IRQn #define GPS_IRQHANDLER_FUNC void USART2_IRQHandler(void) @@ -105,7 +105,7 @@ #define TELEM_TX_PIN GPIO_Pin_10 #define TELEM_REMAP_FUNC { GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE); } #define TELEM_IRQ_CHANNEL USART3_IRQn -#define TELEM_IRQHANDLER_FUNC void USART3_IRQHandler(void) +#define TELEM_IRQHANDLER_FUNC void USART3_IRQHandler(void) #define TELEM_CLK_FUNC RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE) #define TELEM_NVIC_PRIO IRQ_PRIO_HIGHEST @@ -116,52 +116,52 @@ #define AUX_USART_GPIO_PORT GPIOA #define AUX_USART_RX_PIN GPIO_Pin_10 #define AUX_USART_TX_PIN GPIO_Pin_9 -#define AUX_USART_REMAP_FUNC { } -#define AUX_USART_IRQ_CHANNEL USART1_IRQn -#define AUX_USART_IRQHANDLER_FUNC void USART1_IRQHandler(void) +#define AUX_USART_REMAP_FUNC { } +#define AUX_USART_IRQ_CHANNEL USART1_IRQn +#define AUX_USART_IRQHANDLER_FUNC void USART1_IRQHandler(void) #define AUX_USART_CLK_FUNC RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE) #define AUX_USART_NVIC_PRIO IRQ_PRIO_HIGH //------------------------- // USART Serial Ports //------------------------- -#define USART_NUM 3 -#define USART_RX_BUFFER_SIZE 1024 -#define USART_TX_BUFFER_SIZE 256 +#define USART_NUM 3 +#define USART_RX_BUFFER_SIZE 1024 +#define USART_TX_BUFFER_SIZE 256 #define COM_DEBUG_PORT GPS //------------------------- // SPI //------------------------- -#define PIOS_IRQ_SPI_DMA_PRIORITY IRQ_PRIO_HIGH -#define PIOS_SPI0_PTR SPI1 -#define PIOS_SPI0_DMA_RX_PTR DMA1_Channel2 -#define PIOS_SPI0_DMA_TX_PTR DMA1_Channel3 -#define PIOS_SPI0_DMA_RX_IRQ_FLAGS (DMA1_FLAG_TC2 | DMA1_FLAG_TE2 | DMA1_FLAG_HT2 | DMA1_FLAG_GL2) -#define PIOS_SPI0_DMA_IRQ_CHANNEL DMA1_Channel2_IRQn +#define PIOS_IRQ_SPI_DMA_PRIORITY IRQ_PRIO_HIGH +#define PIOS_SPI0_PTR SPI1 +#define PIOS_SPI0_DMA_RX_PTR DMA1_Channel2 +#define PIOS_SPI0_DMA_TX_PTR DMA1_Channel3 +#define PIOS_SPI0_DMA_RX_IRQ_FLAGS (DMA1_FLAG_TC2 | DMA1_FLAG_TE2 | DMA1_FLAG_HT2 | DMA1_FLAG_GL2) +#define PIOS_SPI0_DMA_IRQ_CHANNEL DMA1_Channel2_IRQn #define PIOS_SPI0_DMA_IRQHANDLER_FUNC void DMA1_Channel2_IRQHandler(void) -#define PIOS_SPI0_RCLK1_PORT GPIOA -#define PIOS_SPI0_RCLK1_PIN GPIO_Pin_4 -#define PIOS_SPI0_SCLK_PORT GPIOA -#define PIOS_SPI0_SCLK_PIN GPIO_Pin_5 -#define PIOS_SPI0_MISO_PORT GPIOA -#define PIOS_SPI0_MISO_PIN GPIO_Pin_6 -#define PIOS_SPI0_MOSI_PORT GPIOA -#define PIOS_SPI0_MOSI_PIN GPIO_Pin_7 -#define PIOS_SPI1_PTR SPI2 -#define PIOS_SPI1_DMA_RX_PTR DMA1_Channel4 -#define PIOS_SPI1_DMA_TX_PTR DMA1_Channel5 -#define PIOS_SPI1_DMA_RX_IRQ_FLAGS (DMA1_FLAG_TC4 | DMA1_FLAG_TE4 | DMA1_FLAG_HT4 | DMA1_FLAG_GL4) -#define PIOS_SPI1_DMA_IRQ_CHANNEL DMA1_Channel4_IRQn +#define PIOS_SPI0_RCLK1_PORT GPIOA +#define PIOS_SPI0_RCLK1_PIN GPIO_Pin_4 +#define PIOS_SPI0_SCLK_PORT GPIOA +#define PIOS_SPI0_SCLK_PIN GPIO_Pin_5 +#define PIOS_SPI0_MISO_PORT GPIOA +#define PIOS_SPI0_MISO_PIN GPIO_Pin_6 +#define PIOS_SPI0_MOSI_PORT GPIOA +#define PIOS_SPI0_MOSI_PIN GPIO_Pin_7 +#define PIOS_SPI1_PTR SPI2 +#define PIOS_SPI1_DMA_RX_PTR DMA1_Channel4 +#define PIOS_SPI1_DMA_TX_PTR DMA1_Channel5 +#define PIOS_SPI1_DMA_RX_IRQ_FLAGS (DMA1_FLAG_TC4 | DMA1_FLAG_TE4 | DMA1_FLAG_HT4 | DMA1_FLAG_GL4) +#define PIOS_SPI1_DMA_IRQ_CHANNEL DMA1_Channel4_IRQn #define PIOS_SPI1_DMA_IRQHANDLER_FUNC void DMA1_Channel4_IRQHandler(void) -#define PIOS_SPI1_RCLK1_PORT GPIOB -#define PIOS_SPI1_RCLK1_PIN GPIO_Pin_12 -#define PIOS_SPI1_SCLK_PORT GPIOB -#define PIOS_SPI1_SCLK_PIN GPIO_Pin_13 -#define PIOS_SPI1_MISO_PORT GPIOB -#define PIOS_SPI1_MISO_PIN GPIO_Pin_14 -#define PIOS_SPI1_MOSI_PORT GPIOB -#define PIOS_SPI1_MOSI_PIN GPIO_Pin_15 +#define PIOS_SPI1_RCLK1_PORT GPIOB +#define PIOS_SPI1_RCLK1_PIN GPIO_Pin_12 +#define PIOS_SPI1_SCLK_PORT GPIOB +#define PIOS_SPI1_SCLK_PIN GPIO_Pin_13 +#define PIOS_SPI1_MISO_PORT GPIOB +#define PIOS_SPI1_MISO_PIN GPIO_Pin_14 +#define PIOS_SPI1_MOSI_PORT GPIOB +#define PIOS_SPI1_MOSI_PIN GPIO_Pin_15 //------------------------- // SDCard @@ -213,24 +213,24 @@ // Servo outputs //------------------------- #define SERVO1TO4_PORT GPIOB -#define SERVO1_PIN GPIO_Pin_6 -#define SERVO2_PIN GPIO_Pin_7 -#define SERVO3_PIN GPIO_Pin_8 -#define SERVO4_PIN GPIO_Pin_9 +#define SERVO1_PIN GPIO_Pin_6 +#define SERVO2_PIN GPIO_Pin_7 +#define SERVO3_PIN GPIO_Pin_8 +#define SERVO4_PIN GPIO_Pin_9 #define SERVO5TO8_PORT GPIOC -#define SERVO5_PIN GPIO_Pin_6 -#define SERVO6_PIN GPIO_Pin_7 -#define SERVO7_PIN GPIO_Pin_8 -#define SERVO8_PIN GPIO_Pin_9 +#define SERVO5_PIN GPIO_Pin_6 +#define SERVO6_PIN GPIO_Pin_7 +#define SERVO7_PIN GPIO_Pin_8 +#define SERVO8_PIN GPIO_Pin_9 #define NUM_SERVO_OUTPUTS 8 //------------------------- // ADC //------------------------- #define ADC_GPIO_PORT GPIOC -#define ADC_Z_PIN GPIO_Pin_0 // ADC123_IN10 -#define ADC_A_PIN GPIO_Pin_1 // ADC123_IN11 -#define ADC_B_PIN GPIO_Pin_2 // ADC123_IN12 +#define ADC_Z_PIN GPIO_Pin_0 // ADC123_IN10 +#define ADC_A_PIN GPIO_Pin_1 // ADC123_IN11 +#define ADC_B_PIN GPIO_Pin_2 // ADC123_IN12 #define ADC_Z_CHANNEL ADC_Channel_10 #define ADC_A_CHANNEL ADC_Channel_11 #define ADC_B_CHANNEL ADC_Channel_12 @@ -243,12 +243,13 @@ #define USB_ACC_GPIO_PORT GPIOC #define USB_DETECT_PIN GPIO_Pin_4 #define USB_PULLUP_PIN GPIO_Pin_14 +#define PIOS_IRQ_USB_PRIORITY IRQ_PRIO_MID //------------------------- // Delay Timer //------------------------- #define PIOS_DELAY_TIMER TIM2 -#define PIOS_DELAY_TIMER_RCC RCC_APB1Periph_TIM2 +#define PIOS_DELAY_TIMER_RCC RCC_APB1Periph_TIM2 //------------------------- // Master Clock diff --git a/flight/PiOS/inc/pios_delay.h b/flight/PiOS/inc/pios_delay.h index d630c0a2d..8920b4c02 100644 --- a/flight/PiOS/inc/pios_delay.h +++ b/flight/PiOS/inc/pios_delay.h @@ -29,8 +29,8 @@ /* Public Functions */ extern int32_t PIOS_DELAY_Init(void); -extern int32_t PIOS_DELAY_Wait_uS(uint16_t uS); -extern int32_t PIOS_DELAY_Wait_mS(uint16_t mS); +extern int32_t PIOS_DELAY_WaituS(uint16_t uS); +extern int32_t PIOS_DELAY_WaitmS(uint16_t mS); #endif /* PIOS_DELAY_H */ diff --git a/flight/PiOS/inc/pios_sys.h b/flight/PiOS/inc/pios_sys.h index 1fa0cdb70..659e7c616 100644 --- a/flight/PiOS/inc/pios_sys.h +++ b/flight/PiOS/inc/pios_sys.h @@ -28,5 +28,6 @@ /* Public Functions */ extern void PIOS_SYS_Init(void); +extern int32_t PIOS_SYS_SerialNumberGet(char *str); #endif /* PIOS_SYS_H */ diff --git a/flight/PiOS/inc/pios_usb.h b/flight/PiOS/inc/pios_usb.h new file mode 100644 index 000000000..bbdf94553 --- /dev/null +++ b/flight/PiOS/inc/pios_usb.h @@ -0,0 +1,79 @@ +/** + ****************************************************************************** + * + * @file pios_usb.h + * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2009. + * @brief USB functions header. + * @see The GNU Public License (GPL) Version 3 + * + *****************************************************************************/ +/* + * 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. + * + * This program 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 this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef PIOS_USB_H +#define PIOS_USB_H + +/* Local defines */ +/* Following settings allow to customise the USB device descriptor */ +#ifndef PIOS_USB_VENDOR_ID +#define PIOS_USB_VENDOR_ID 0x16c0 // sponsored by voti.nl! see http://www.voti.nl/pids +#endif + +#ifndef PIOS_USB_VENDOR_STR +#define PIOS_USB_VENDOR_STR "midibox.org" // you will see this in the USB device description +#endif + +#ifndef PIOS_USB_PRODUCT_STR +#define PIOS_USB_PRODUCT_STR "MIOS32" /* You will see this in the USB device list */ +#endif + +#ifndef PIOS_USB_PRODUCT_ID +#define PIOS_USB_PRODUCT_ID 0x03ff /* ==1023; 1020-1029 reserved for T.Klose, 1000 - 1009 free for lab use */ +#endif + +#ifndef PIOS_USB_VERSION_ID +#define PIOS_USB_VERSION_ID 0x0100 /* v1.00 */ +#endif + +/* Internal defines which are used by MIOS32 USB MIDI/COM (don't touch) */ +#define PIOS_USB_EP_NUM 5 + +/* Buffer table base address */ +#define PIOS_USB_BTABLE_ADDRESS 0x000 + +/* EP0 rx/tx buffer base address */ +#define PIOS_USB_ENDP0_RXADDR 0x040 +#define PIOS_USB_ENDP0_TXADDR 0x080 + +/* EP1 Rx/Tx buffer base address for MIDI driver */ +#define PIOS_USB_ENDP1_TXADDR 0x0c0 +#define PIOS_USB_ENDP1_RXADDR 0x100 + +/* EP2/3/4 buffer base addresses for COM driver */ +#define PIOS_USB_ENDP2_TXADDR 0x140 +#define PIOS_USB_ENDP3_RXADDR 0x180 +#define PIOS_USB_ENDP4_TXADDR 0x1c0 + + +/* Global Variables */ +extern void (*pEpInt_IN[7])(void); +extern void (*pEpInt_OUT[7])(void); + +/* Public Functions */ +extern int32_t PIOS_USB_Init(uint32_t mode); +extern int32_t PIOS_USB_IsInitialized(void); + +#endif /* PIOS_USB_H */ diff --git a/flight/PiOS/pios.c b/flight/PiOS/pios.c index b67db9f28..b91a5bf19 100644 --- a/flight/PiOS/pios.c +++ b/flight/PiOS/pios.c @@ -40,19 +40,20 @@ #define STRING_MAX 1024 static uint8_t line_buffer[STRING_MAX]; static uint16_t line_ix; +static uint8_t sdcard_available; /* Function Prototypes */ static void TaskTick(void *pvParameters); static void TaskHooks(void *pvParameters); int32_t CONSOLE_Parse(COMPortTypeDef port, char c); void OP_ADC_NotifyChange(uint32_t pin, uint32_t pin_value); +static void TaskSDCard(void *pvParameters); /** * Main function */ int main() { - /* Brings up System using CMSIS functions, enables the LEDs. */ PIOS_SYS_Init(); @@ -79,7 +80,7 @@ int main() PIOS_LED_On(LED2); for(uint32_t i = 0; i < 10; i++) { PIOS_LED_Toggle(LED2); - PIOS_DELAY_Wait_mS(100); + PIOS_DELAY_WaitmS(100); } } @@ -93,18 +94,21 @@ int main() PIOS_Servo_Init(); /* Analog to digital converter initialise */ - PIOS_ADC_Init(); + //PIOS_ADC_Init(); //PIOS_PWM_Init(); + PIOS_USB_Init(0); + PIOS_COM_ReceiveCallbackInit(CONSOLE_Parse); /* Initialise OpenPilot application */ // OpenPilotInit(); /* Create a FreeRTOS task */ - xTaskCreate(TaskTick, (signed portCHAR *)"Test", configMINIMAL_STACK_SIZE , NULL, 3, NULL); - xTaskCreate(TaskHooks, (signed portCHAR *)"Hooks", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_HOOKS, NULL); + //xTaskCreate(TaskTick, (signed portCHAR *)"Test", configMINIMAL_STACK_SIZE , NULL, 1, NULL); + //xTaskCreate(TaskHooks, (signed portCHAR *)"Hooks", configMINIMAL_STACK_SIZE, NULL, PRIORITY_TASK_HOOKS, NULL); + xTaskCreate(TaskSDCard, (signed portCHAR *)"SDCard", configMINIMAL_STACK_SIZE, NULL, (tskIDLE_PRIORITY + 2), NULL); /* Start the FreeRTOS scheduler */ vTaskStartScheduler(); @@ -147,7 +151,7 @@ void OP_ADC_NotifyChange(uint32_t pin, uint32_t pin_value) void TaskTick(void *pvParameters) { - const portTickType xDelay = 500 / portTICK_RATE_MS; + portTickType xLastExecutionTime; /* Setup the LEDs to Alternate */ PIOS_LED_On(LED1); @@ -156,12 +160,11 @@ void TaskTick(void *pvParameters) for(;;) { PIOS_LED_Toggle(LED1); - //PIOS_LED_Toggle(LED2); - //PIOS_DELAY_Wait_mS(250); - vTaskDelay(xDelay); + vTaskDelayUntil(&xLastExecutionTime, 500 / portTICK_RATE_MS); } - /* +#if 0 + /* For testing servo outputs */ const portTickType xDelay = 1 / portTICK_RATE_MS; Used to test servos, cycles all servos from one side to the other @@ -189,7 +192,7 @@ void TaskTick(void *pvParameters) vTaskDelay(xDelay); } } - */ +#endif } static void TaskHooks(void *pvParameters) @@ -216,6 +219,46 @@ static void TaskHooks(void *pvParameters) } } +static void TaskSDCard(void *pvParameters) +{ + uint16_t second_delay_ctr = 0; + portTickType xLastExecutionTime; + + /* Initialise the xLastExecutionTime variable on task entry */ + xLastExecutionTime = xTaskGetTickCount(); + + for(;;) { + vTaskDelayUntil(&xLastExecutionTime, 1 / portTICK_RATE_MS); + + /* Each second: */ + /* Check if SD card is available */ + /* High-speed access if SD card was previously available */ + if(++second_delay_ctr >= 1000) { + second_delay_ctr = 0; + + uint8_t prev_sdcard_available = sdcard_available; + sdcard_available = PIOS_SDCARD_CheckAvailable(prev_sdcard_available); + + if(sdcard_available && !prev_sdcard_available) { + /* SD Card has been connected! */ + /* Switch to mass storage device */ + MSD_Init(0); + } else if(!sdcard_available && prev_sdcard_available) { + /* Re-init USB for MIDI */ + PIOS_USB_Init(1); + /* SD Card disconnected! */ + + } + } + + /* Each millisecond: */ + /* Handle USB access if device is available */ + if(sdcard_available) { + MSD_Periodic_mS(); + } + } +} + /** * Idle hook function */ diff --git a/flight/PiOS/pios.h b/flight/PiOS/pios.h index ed4d08b70..84b6f4509 100644 --- a/flight/PiOS/pios.h +++ b/flight/PiOS/pios.h @@ -49,6 +49,9 @@ /* minIni Includes */ #include +/* Mass Storage Device Includes */ +#include + /* PIOS Hardware Includes (STM32F10x) */ #include #include @@ -62,6 +65,7 @@ #include #include #include +#include /* PIOS Hardware Includes (Common) */ #include