xmclib/XMCLib/examples/XMC4500_series/USBH/USBH_MS/main.c
2024-10-17 17:09:59 +02:00

403 lines
12 KiB
C

/******************************************************************************
* Software License Agreement
*
* Copyright (c) 2015-2016, Infineon Technologies AG
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the copyright holders nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* To improve the quality of the software, users are encouraged to share
* modifications, enhancements or bug fixes with Infineon Technologies AG
* (dave@infineon.com).
*
*****************************************************************************/
/**
* @file main.c
* @date 30 July, 2016
* @version 1.0.0
*
* @brief Implements an example of USB host mass storage <br>
*
* <b>Detailed description of file</b> <br>
* The file implements the main function where it initializes USB peripheral, FatFS file system,
* LUFA stack and executes the device enumeration and file, folder creation application.
*
* History
*
* 01 Jul 2014 Version 1.0.0 <br>
* Initial version
*/
#include <xmc_common.h>
#include "xmc_rtc.h"
#include "FatFs/ff.h"
#include "USB/GLUE/USB_Glue.h"
#include "USBH_BLOCK/USBBL.h"
void ClockSetup(void);
/*FAT file access demonstration function*/
void FATFS_TestDemo(void);
/*USB port event callback function*/
void MS_USB_PortCb(uint8_t port, uint32_t event);
/*FAT related buffer for file IO*/
char read_buff[1000];
uint32_t read_index, loc_index;
/*RTC configuration*/
const XMC_RTC_CONFIG_t rtc_config =
{
.prescaler = 0x7FFFU,
.time = {
.year = 2016,
.month = 6,
.days = 6,
.hours = 0,
.minutes = 0,
.seconds = 0,
},
};
#if (defined (XMC4500_E144x1024) || defined (XMC4500_F144x1024) || defined (XMC4500_F100x1024) || \
defined (XMC4500_F144x768) || defined (XMC4500_F100x768) || defined (XMC4502_F100x768) || \
defined (XMC4504_F100x512) || defined (XMC4504_F144x512))
/* Data structure for initializing the clock functional block */
const XMC_SCU_CLOCK_CONFIG_t CLOCK_XMC4_0_CONFIG =
{
.syspll_config.n_div = 80U,
.syspll_config.p_div = 2U,
.syspll_config.k_div = 4U,
.syspll_config.mode = XMC_SCU_CLOCK_SYSPLL_MODE_NORMAL,
.syspll_config.clksrc = XMC_SCU_CLOCK_SYSPLLCLKSRC_OSCHP,
.enable_oschp = true,
.enable_osculp = false,
.calibration_mode = XMC_SCU_CLOCK_FOFI_CALIBRATION_MODE_FACTORY,
.fstdby_clksrc = XMC_SCU_HIB_STDBYCLKSRC_OSI,
.fsys_clksrc = XMC_SCU_CLOCK_SYSCLKSRC_PLL,
.fsys_clkdiv = 1U,
.fcpu_clkdiv = 1U,
.fperipheral_clkdiv = 1U
};
#else
#error "Clock configuration has to be updated for the device selected. You may use CLOCK_XMC4 APP to derive the required configuration."
#endif
/* File pointer */
FIL fp ;
/* File System Object Structure variable */
FATFS myfsObject ;
/*Callback functions to be called from USB glue layer*/
USBH_GLUE_APP_IF_t MS_CB =
{
.PortEventHandler = MS_USB_PortCb
};
/* Variable to access the current USB host state */
uint8_t USBHostState;
/*Flag to identify remote wakeup event*/
volatile uint32_t USBH_RemoteWkUp_Detected = 0U;
/**
* @brief main() - Application entry point
*
* <b>Details of function</b><br>
* This routine is the application entry point. It is invoked by the device startup code.
* The application enumerates a USB device and executes a demonstration of FAT file access example function.
*/
int main(void)
{
/*Configure USB and CPU clocks*/
ClockSetup();
/*Select VBUS pin as P3.2*/
XMC_USBH_Select_VBUS(XMC_GPIO_PORT3, 2U);
/* Initializes the USB host driver. */
USB_Init_Host(&MS_CB);
/*LED pin to indicate USB status*/
XMC_GPIO_SetMode(XMC_GPIO_PORT3, 9, XMC_GPIO_MODE_OUTPUT_PUSH_PULL);
XMC_GPIO_SetOutputHigh(XMC_GPIO_PORT3, 9);
/*Initialize RTC used for FAT get time API*/
XMC_RTC_Enable();
XMC_RTC_Init(&rtc_config);
XMC_RTC_Start();
/* Infinite loop */
while (1)
{
/*Check if remote wakeup is detected and clear the resume
* bit after 20ms delay*/
if (USBH_RemoteWkUp_Detected)
{
(void)XMC_USBH_osDelay(20U);
XMC_USBH_TurnOffResumeBit();
USBH_RemoteWkUp_Detected = 0;
}
/* Get the USB Host status. */
USB_GetHostState(&USBHostState);
/* To Enumerate the attached mass storage device
* after it is addressed. */
USBBL_Process();
if(USBHostState == HOST_STATE_Configured)
{
/* Call MassStorageHost demo function */
XMC_GPIO_SetOutputLow(XMC_GPIO_PORT3, 9);
FATFS_TestDemo();
XMC_GPIO_SetOutputHigh(XMC_GPIO_PORT3, 9);
(void)XMC_USBH_osDelay(200U);
}
else
{
/*Keep the LED switched Off as long as it is not
* enumerated*/
XMC_GPIO_SetOutputHigh(XMC_GPIO_PORT3, 9);
}
/* Keep calling this function for USB management.
* This function handles the USB host states till it gets
* addressed */
USB_USBTask();
}
}
/*Function to demonstrate FAT file access.
* Creates a folder with the name ABSTEP, writes 3 files each with 1KB, 2KB and 3KB
* of data, reads the content of the same files and compares with written data.
* A LED connected on P3.9 glows when the enumeration is complete and contiunues to glow
* when the file access is ongoing. When the file access is done, the LED starts blinking.*/
void FATFS_TestDemo(void)
{
volatile FRESULT DResult;
uint32_t data_index;
/* Mount USB device */
DResult = f_mount(&myfsObject, "0:", 0);
/* Make directory */
DResult = f_mkdir("ABSTEP");
if ((DResult == FR_OK) || (DResult == FR_EXIST))
{
/*Directory already exists!!*/
}
/* Create File */
DResult = f_open( &fp, "ABSTEP/readme1.txt", (FA_CREATE_NEW | FA_WRITE | FA_READ));
if (DResult == FR_OK)
{
for(data_index = 0; data_index < 1000; data_index++)
{
f_printf( &fp,"%d", 1);
}
}
else if (DResult == FR_EXIST )
{
/* File already exists!! */
}
/* Close File */
DResult = f_close(&fp);
DResult = f_open( &fp, "ABSTEP/readme1.txt", (FA_READ));
read_index = 0;
while(read_index < 1000)
{
f_read(&fp, read_buff, 1000, (UINT*)&loc_index);
read_index += loc_index;
for(data_index = 0; data_index < loc_index; data_index++)
{
if(read_buff[data_index] != '1')
{
/*TODO: Error management */
while(1);
}
}
if(read_index < 1000)
{
f_lseek(&fp, read_index);
}
USB_GetHostState(&USBHostState);
if(USBHostState == HOST_STATE_WaitForDevice)
{
break;
}
}
/* Close File */
DResult = f_close(&fp);
/* Create File */
DResult = f_open( &fp, "ABSTEP/readme2.txt", (FA_CREATE_NEW | FA_WRITE | FA_READ));
if (DResult == FR_OK)
{
for(data_index = 0; data_index < 2000; data_index++)
{
f_printf( &fp,"%d", 2);
}
}
else if (DResult == FR_EXIST )
{
/* File already exists!! */
}
/* Close File */
DResult = f_close(&fp);
DResult = f_open( &fp, "ABSTEP/readme2.txt", (FA_READ));
read_index = 0;
while(read_index < 2000)
{
f_read(&fp, read_buff, 1000, (UINT*)&loc_index);
read_index += loc_index;
for(data_index = 0; data_index < loc_index; data_index++)
{
if(read_buff[data_index] != '2')
{
/*TODO: Error management */
while(1);
}
}
if(read_index < 2000)
{
f_lseek(&fp, read_index);
}
USB_GetHostState(&USBHostState);
if(USBHostState == HOST_STATE_WaitForDevice)
{
break;
}
}
/* Close File */
DResult = f_close(&fp);
/* Create File */
DResult = f_open( &fp, "ABSTEP/readme3.txt", (FA_CREATE_NEW | FA_WRITE | FA_READ));
if (DResult == FR_OK)
{
for(data_index = 0; data_index < 3000; data_index++)
{
f_printf( &fp,"%d", 3);
}
}
else if (DResult == FR_EXIST )
{
/* File already exists!! */
}
/* Close File */
DResult = f_close(&fp);
DResult = f_open( &fp, "ABSTEP/readme3.txt", (FA_READ));
read_index = 0;
while(read_index < 3000)
{
f_read(&fp, read_buff, 1000, (UINT*)&loc_index);
read_index += loc_index;
for(data_index = 0; data_index < loc_index; data_index++)
{
if(read_buff[data_index] != '3')
{
/*TODO: Error management */
while(1);
}
}
if(read_index < 3000)
{
f_lseek(&fp, read_index);
}
USB_GetHostState(&USBHostState);
if(USBHostState == HOST_STATE_WaitForDevice)
{
break;
}
}
/* Close File */
DResult = f_close(&fp);
}
/*USB port event callback function*/
void MS_USB_PortCb(uint8_t port, uint32_t event)
{
if(event & XMC_USBH_EVENT_DISCONNECT)
{
/*Switch off the LED when device is disconnected*/
XMC_GPIO_SetOutputHigh(XMC_GPIO_PORT3, 9);
Driver_USBH0.PipeDelete(USBHost_Pipe_State[0].pipe_handle);
Driver_USBH0.PipeDelete(USBHost_Pipe_State[1].pipe_handle);
Driver_USBH0.PipeDelete(USBHost_Pipe_State[2].pipe_handle);
}
if(event & XMC_USBH_EVENT_REMOTE_WAKEUP)
{
/*This flag is set to remember the occurrence of remote wakeup event and
* to return from ISR immediately. This helps to time a 20ms delay in
* the context of the application main loop rather than inside the ISR context.
* The reason for this is that the example uses a timer interrupt whose priority is
* lower than the USB interrupt and therefore would result in a deadlock.*/
USBH_RemoteWkUp_Detected = 1;
}
}
/*Implementation of FAT get time API for completeness.
* This implementation can be modified to use any other interface or DAVE APP.*/
DWORD get_fattime(void)
{
XMC_RTC_TIME_t cur_time;
XMC_RTC_GetTime(&cur_time);
/* Pack date and time into a DWORD variable */
return (((DWORD)(cur_time.year - 1980UL) << 25UL) | (((DWORD)cur_time.month+1U) << 21UL) | (((DWORD)cur_time.days+1U) << 16UL)
| ((DWORD)cur_time.hours << 11UL)
| ((DWORD)cur_time.minutes << 5UL)
| ((DWORD)cur_time.seconds >> 1UL));
}
/*Function to initialize CPU clock and USB clock*/
void ClockSetup(void)
{
/* Initialize the SCU clock */
XMC_SCU_CLOCK_Init(&CLOCK_XMC4_0_CONFIG);
/* RTC source clock */
XMC_SCU_HIB_SetRtcClockSource(XMC_SCU_HIB_RTCCLKSRC_OSI);
/*CLOCK_XMC4_USBCLK_ENABLED*/
/* USB/SDMMC source clock */
XMC_SCU_CLOCK_SetUsbClockSource(XMC_SCU_CLOCK_USBCLKSRC_USBPLL);
/* USB/SDMMC divider setting */
XMC_SCU_CLOCK_SetUsbClockDivider(4U);
/* Start USB PLL */
XMC_SCU_CLOCK_StartUsbPll(1U, 32U);
}