| /**************************************************************************//** * @file     main.c
 * @version  V1.00
 * $Revision: 20 $
 * $Date: 14/10/28 6:11p $
 * @brief
 *           Show how to implement a USB Host with a file system to read/write a file on USB Mass Storage.
 *
 * @note
 * Copyright (C) 2013 Nuvoton Technology Corp. All rights reserved.
 *****************************************************************************/
 #include <stdio.h>
 #include <string.h>
 #include "M451Series.h"
 #include "diskio.h"
 #include "ff.h"
 #include "usbh_core.h"
 #include "usbh_umas.h"
 
 #define PLLCTL_SETTING      0x422e
 #define PLL_CLOCK           96000000
 
 FATFS FatFs[_VOLUMES];      /* File system object for logical drive */
 
 #ifdef __ICCARM__
 #pragma data_alignment=32
 BYTE Buff[4096] ;       /* Working buffer */
 #endif
 
 #ifdef __ARMCC_VERSION
 __align(32) BYTE Buff[4096] ;       /* Working buffer */
 #endif
 
 char GetChar(void);
 void Delay(uint32_t delayCnt)
 {
 while(delayCnt--)
 {
 __NOP();
 __NOP();
 }
 }
 
 void put_rc(FRESULT rc)
 {
 const TCHAR *p =
 _T("OK\0DISK_ERR\0INT_ERR\0NOT_READY\0NO_FILE\0NO_PATH\0INVALID_NAME\0")
 _T("DENIED\0EXIST\0INVALID_OBJECT\0WRITE_PROTECTED\0INVALID_DRIVE\0")
 _T("NOT_ENABLED\0NO_FILE_SYSTEM\0MKFS_ABORTED\0TIMEOUT\0LOCKED\0")
 _T("NOT_ENOUGH_CORE\0TOO_MANY_OPEN_FILES\0");
 //FRESULT i;
 uint32_t i;
 for(i = 0; (i != (UINT)rc) && *p; i++)
 {
 while(*p++) ;
 }
 printf(_T("rc=%u FR_%s\n"), (UINT)rc, p);
 }
 
 /*---------------------------------------------------------*/
 /* User Provided RTC Function for FatFs module             */
 /*---------------------------------------------------------*/
 /* This is a real time clock service to be called from     */
 /* FatFs module. Any valid time must be returned even if   */
 /* the system does not support an RTC.                     */
 /* This function is not required in read-only cfg.         */
 
 unsigned long get_fattime(void)
 {
 unsigned long tmr;
 
 tmr = 0x00000;
 
 return tmr;
 }
 
 
 void SYS_Init(void)
 {
 /*---------------------------------------------------------------------------------------------------------*/
 /* Init System Clock                                                                                       */
 /*---------------------------------------------------------------------------------------------------------*/
 
 /* Enable External XTAL (4~24 MHz) */
 CLK_EnableXtalRC(CLK_PWRCTL_HXTEN_Msk);
 
 /* Waiting for 12MHz clock ready */
 CLK_WaitClockReady(CLK_STATUS_HXTSTB_Msk);
 
 /* Switch HCLK clock source to XTAL */
 CLK_SetHCLK(CLK_CLKSEL0_HCLKSEL_HXT, CLK_CLKDIV0_HCLK(1));
 
 /* Set PLL to power down mode and PLL_STB bit in CLKSTATUS register will be cleared by hardware.*/
 CLK->PLLCTL |= CLK_PLLCTL_PD_Msk;
 
 /* Set PLL frequency */
 CLK->PLLCTL = PLLCTL_SETTING;
 
 /* Waiting for clock ready */
 CLK_WaitClockReady(CLK_STATUS_PLLSTB_Msk);
 
 /* Switch HCLK clock source to PLL */
 CLK->CLKSEL0 &= (~CLK_CLKSEL0_HCLKSEL_Msk);
 CLK->CLKSEL0 |= CLK_CLKSEL0_HCLKSEL_PLL;
 
 /* Enable IP clock */
 CLK_EnableModuleClock(UART0_MODULE);
 
 
 /* Select IP clock source */
 CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UARTSEL_HXT, CLK_CLKDIV0_UART(1));
 
 /* Update System Core Clock */
 /* User can use SystemCoreClockUpdate() to calculate PllClock, SystemCoreClock and CycylesPerUs automatically. */
 SystemCoreClockUpdate();
 PllClock        = PLL_CLOCK;            // PLL
 SystemCoreClock = PLL_CLOCK / 2;              // HCLK
 CyclesPerUs     = SystemCoreClock / 1000000;  // For SYS_SysTickDelay()
 /*---------------------------------------------------------------------------------------------------------*/
 /* Init I/O Multi-function                                                                                 */
 /*---------------------------------------------------------------------------------------------------------*/
 /* Set GPD multi-function pins for UART0 RXD and TXD */
 SYS->GPD_MFPL &= ~(SYS_GPD_MFPL_PD0MFP_Msk | SYS_GPD_MFPL_PD1MFP_Msk);
 SYS->GPD_MFPL |= (SYS_GPD_MFPL_PD0MFP_UART0_RXD | SYS_GPD_MFPL_PD1MFP_UART0_TXD);
 
 /*---------------------------------------------------------------------------------------------------------*/
 /* Init USB Host clock                                                                                     */
 /*---------------------------------------------------------------------------------------------------------*/
 // Configure OTG function as Host-Only
 SYS->USBPHY = 0x101;
 
 #ifdef AUTO_POWER_CONTROL
 /* Below settings is use power switch IC to enable/disable USB Host power.
 Set PC.4 is VBUS_EN function pin and PC.3 VBUS_ST function pin             */
 //SYS->GPC_MFPL &= ~(SYS_GPC_MFPL_PC4MFP_Msk | SYS_GPC_MFPL_PC3MFP_Msk);
 //SYS->GPC_MFPL |=  (SYS_GPC_MFPL_PC3MFP_USB_VBUS_ST | SYS_GPC_MFPL_PC4MFP_USB_VBUS_EN);
 
 /* Below settings is use power switch IC to enable/disable USB Host power.
 Set PA.2 is VBUS_EN function pin and PA.3 VBUS_ST function pin             */
 SYS->GPA_MFPL &= ~(SYS_GPA_MFPL_PA2MFP_Msk | SYS_GPA_MFPL_PA3MFP_Msk);
 SYS->GPA_MFPL |= (SYS_GPA_MFPL_PA3MFP_USB_VBUS_ST | SYS_GPA_MFPL_PA2MFP_USB_VBUS_EN);
 
 CLK->APBCLK0 |= CLK_APBCLK0_OTGCKEN_Msk;   //Enable OTG_EN clock
 #else
 /* Below settings is use GPIO to enable/disable USB Host power.
 Set PC.4 output high to enable USB power                               */
 
 SYS->GPC_MFPL &= ~SYS_GPC_MFPL_PC4MFP_Msk;
 PC->MODE = (PC->MODE & ~GPIO_MODE_MODE4_Msk) | (0x1 << GPIO_MODE_MODE4_Pos);
 PC->DOUT |= 0x10;
 #endif
 
 // USB clock divided by 2
 CLK->CLKDIV0 = (CLK->CLKDIV0 & ~CLK_CLKDIV0_USBDIV_Msk) | (1 << CLK_CLKDIV0_USBDIV_Pos);
 
 // Enable USB Host
 CLK->AHBCLK |= CLK_AHBCLK_USBHCKEN_Msk;
 }
 
 
 void UART0_Init(void)
 {
 /*---------------------------------------------------------------------------------------------------------*/
 /* Init UART                                                                                               */
 /*---------------------------------------------------------------------------------------------------------*/
 /* Reset UART IP */
 SYS->IPRST1 |=  SYS_IPRST1_UART0RST_Msk;
 SYS->IPRST1 &= ~SYS_IPRST1_UART0RST_Msk;
 
 /* Configure UART0 and set UART0 Baudrate */
 UART0->BAUD = UART_BAUD_MODE2 | UART_BAUD_MODE2_DIVIDER(__HXT, 115200);
 UART0->LINE = UART_WORD_LEN_8 | UART_PARITY_NONE | UART_STOP_BIT_1;
 }
 
 static FIL file1;        /* File objects */
 
 /*----------------------------------------------------------------------------
 MAIN function
 *----------------------------------------------------------------------------*/
 int32_t main(void)
 {
 FRESULT res;
 UINT s2, cnt;
 uint32_t i;
 
 /* Unlock protected registers */
 SYS_UnlockReg();
 
 /* Init System, IP clock and multi-function I/O */
 SYS_Init(); //In the end of SYS_Init() will issue SYS_LockReg() to lock protected register. If user want to write protected register, please issue SYS_UnlockReg() to unlock protected register.
 
 /* Lock protected registers */
 SYS_LockReg();
 
 /* Init UART0 for printf */
 UART0_Init();
 
 /* Init USB host and prepare a root hub*/
 USBH_Open();
 
 /* Set USB host to support USB mass storage device*/
 USBH_MassInit();
 
 /*Delay for power stable*/
 Delay(0x500000);
 
 printf("+-----------------------------------------------+\n");
 printf("|                                               |\n");
 printf("|  M451 USB Host Mass Storage sample program    |\n");
 printf("|                                               |\n");
 printf("+-----------------------------------------------+\n");
 
 printf("OTG->PHYCTL = 0x%x\n", OTG->PHYCTL);
 printf("OTG->STS = 0x%x\n", OTG->STATUS);
 printf("OTG->CTL = 0x%x\n", OTG->CTL);
 
 while(1)
 {
 
 /*USBH_ProcessHubEvents() must be executed at main loop*/
 if(USBH_ProcessHubEvents())//Check USB device status Change for plug-in and unplug
 {
 if(disk_status(0))//Check mass storage device status
 put_rc(f_mount(0, NULL));//unplug
 else
 put_rc(f_mount(0, &FatFs[0]));//plug-in
 }
 
 if(disk_status(0) == 0)//Check connection of USB mass storage
 {//USB mass storage is still connected to USB host
 putchar('\n');
 res = f_open(&file1, (TCHAR*)"Test.txt", FA_OPEN_EXISTING | FA_READ);// Open "Test.txt" file for read operation
 if(res)//Check the result of FatFs function
 {//Fail --> Maybe connection fail or Not find "Text.txt" file
 
 put_rc(res);//Print fail message
 
 res = f_open(&file1, (TCHAR*)"Test.txt", FA_CREATE_ALWAYS | FA_WRITE);// Open "Test.txt" file for write operation
 if(res)
 {//Fail
 put_rc(res);//Print fail message
 }else
 {//Pass
 cnt = 512;//Set data lenght
 for(i=0;i<cnt;i++)
 Buff = i;//Prepare data for write
 
 res = f_write(&file1, Buff, cnt, &s2);//Write data into file.
 if(res != FR_OK)
 {//Fail
 put_rc(res);//Print fail message
 }
 f_close(&file1);//Close "Test.txt" file
 printf("Data lenght:%d\n",s2);//Print how many wrote data
 }
 }else
 {//Pass
 cnt = 512;//Set data lenght
 res = f_read(&file1, Buff, cnt, &s2);//Read data from file.
 if(res != FR_OK)
 {//Fail
 put_rc(res);//Print fail message
 }else
 {//Pass
 printf("Data size:%d\n",s2);//Print how many read data
 for(i=0;i<s2;i++)
 {
 if((i%8) == 0 )
 printf("\n");
 printf("0x%2x ",Buff);//Print read data
 }
 }
 f_close(&file1);//Close "Test.txt" file
 printf("\nData lenght:%d\n",s2);//Print how many wrote data
 printf("Test finish.\n");//Print how many wrote data
 GetChar();
 }
 }
 }
 }
 
 
 /*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/
 
 |