SAMV71 Xplained Ultra Software Package 1.5

main.c

Go to the documentation of this file.
00001 /* ---------------------------------------------------------------------------- */
00002 /*                  Atmel Microcontroller Software Support                      */
00003 /*                       SAM Software Package License                           */
00004 /* ---------------------------------------------------------------------------- */
00005 /* Copyright (c) 2015, Atmel Corporation                                        */
00006 /*                                                                              */
00007 /* All rights reserved.                                                         */
00008 /*                                                                              */
00009 /* Redistribution and use in source and binary forms, with or without           */
00010 /* modification, are permitted provided that the following condition is met:    */
00011 /*                                                                              */
00012 /* - Redistributions of source code must retain the above copyright notice,     */
00013 /* this list of conditions and the disclaimer below.                            */
00014 /*                                                                              */
00015 /* Atmel's name may not be used to endorse or promote products derived from     */
00016 /* this software without specific prior written permission.                     */
00017 /*                                                                              */
00018 /* DISCLAIMER:  THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR   */
00019 /* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF */
00020 /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE   */
00021 /* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,      */
00022 /* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT */
00023 /* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,  */
00024 /* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF    */
00025 /* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING         */
00026 /* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
00027 /* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                           */
00028 /* ---------------------------------------------------------------------------- */
00029 
00030 /** \cond usb_hid_msd
00031  * \page usb_hid_msd USB HID(Keyboard)+MSD Example
00032  *
00033  * \section Purpose
00034  *
00035  * The USB COMPOSITE Project will help you to get familiar with the
00036  * USB Device Port(UDP)interface and also some of the other interfaces in
00037  * SAMV7/E7 Microcontrollers. Also it can help you to be familiar with the USB
00038  * Framework that is used for rapid development of USB-compliant class
00039  * drivers such as USB Communication Device class (CDC), and how to combine
00040  * two USB functions to a single composite device (such as CDC + MSD).
00041  *
00042  * \section Requirements
00043  *
00044  * This package can be used with SAMV71 Xplained Ultra board or SAME70 Xplained board
00045  * that have UDP interface, depending on the functions included.
00046  *
00047  *  \section win_drv_update Windows Driver Update
00048  *
00049  * The composite device is generally supported by Microsoft windows, but some
00050  * patches are needed for muti-interface functions such as CDC & Audio.
00051  *
00052  * \section Description
00053  *
00054  * The demo simulates a USB composite device with HID Keyboard function and
00055  * USB Disk function integrated.
00056  *
00057  * When an board running this program connected to a host (PC for example),
00058  * with USB cable, host will notice the attachment of a USB device. No device
00059  * driver offered for the device now.
00060  *
00061  * \section Usage
00062  *
00063  *  -# Build the program and download it inside the board.
00064  *     Please refer to the Getting Started with SAM V71/E70 Microcontrollers.pdf
00065  * -# On the computer, open and configure a terminal application
00066  *    (e.g. HyperTerminal on Microsoft Windows) with these settings:
00067  *   - 115200 baud rate
00068  *   - 8 bits of data
00069  *   - No parity
00070  *   - 1 stop bit
00071  *   - No flow control
00072  * -# Start the application.
00073  * -# In the terminal window, the following text should appear:
00074  *     \code
00075  *     -- USB HIDMSD Device Project xxx --
00076  *     -- SAMxxxxx-xx
00077  *     -- Compiled: xxx xx xxxx xx:xx:xx --
00078  *     \endcode
00079  * -# When connecting USB cable to windows, the LED blinks, and the host
00080  *    reports a new USB device attachment.
00081  * -# For the windows driver installation and the test functions, please
00082  *      refer to "USB HID Keyboard Project" &
00083  *      "USB Device Mass Storage Project".
00084  *
00085  * \section References
00086  * - usb_hid_msd/main.c
00087  * - pio: Pin configurations and peripheral configure.
00088  * - memories: Storage Media interface for MSD
00089  * - usb: USB Device Framework, USB CDC driver and UDP interface driver
00090  *    - \ref usbd_framework
00091  *        - \ref usbd_api
00092  *    - \ref usbd_composite "composite"
00093  *       - \ref usbd_composite_drv
00094  *    - \ref usbd_hid "hid" \\ \ref usbd_hid_key "hid-keyboard"
00095  *       - \ref usbd_hid_kbd_drv
00096  *    - \ref usbd_msd "massstorage"
00097  *       - \ref usbd_msd_drv
00098  * - projects:
00099  *    - \ref usb_hid_keyboard
00100  *    - \ref usb_massstorage
00101  *
00102  */
00103 
00104 /**
00105  * \file
00106  *
00107  * This file contains all the specific code for the
00108  * usb_hid_msd
00109  *
00110  * \section Contents
00111  *
00112  * The code can be roughly broken down as follows:
00113  *    - Configuration functions
00114  *       - VBus_Configure
00115  *       - PIO configurations in start of main
00116  *    - Interrupt handlers
00117  *       - ISR_Vbus
00118  *    - Callback functions
00119  *       - USBDCallbacks_RequestReceived
00120  *    - The main function, which implements the program behaviour
00121  */
00122 
00123 /*----------------------------------------------------------------------------
00124  *        Headers
00125  *----------------------------------------------------------------------------*/
00126 
00127 #include "board.h"
00128 
00129 #include "libstoragemedia.h"
00130 
00131 #include <USBD_Config.h>
00132 #include <USBD_LEDs.h>
00133 
00134 #include <HIDMSDDriver.h>
00135 #include <HIDDKeyboard.h>
00136 #include <MSDFunction.h>
00137 
00138 #include <string.h>
00139 #include <stdbool.h>
00140 #include <stdint.h>
00141 #include <stdio.h>
00142 
00143 /*---------------------------------------------------------------------------
00144  *      Definitions
00145  *---------------------------------------------------------------------------*/
00146 
00147 #define NO_PUSHBUTTON
00148 
00149 /** Master clock frequency in Hz */
00150 #define MCK                         BOARD_MCK
00151 
00152 /** Number of keys used in the example. */
00153 #define NUM_KEYS                    2
00154 
00155 /** Number of non-modifiers keys. */
00156 #define NUM_NORMAL_KEYS             1
00157 
00158 /** Number of modifier keys. */
00159 #define NUM_MODIFIER_KEYS           (NUM_KEYS - NUM_NORMAL_KEYS)
00160 
00161 /** Num lock LED index. */
00162 #define LED_NUMLOCK                 USBD_LEDOTHER
00163 
00164 
00165 /** Maximum number of LUNs which can be defined. */
00166 #define MAX_LUNS            1
00167 /** Media index for different disks */
00168 #define DRV_RAMDISK         0    /**< RAM disk */
00169 #define DRV_SDMMC           1    /**< SD card */
00170 #define DRV_NAND            2    /**< Nand flash */
00171 
00172 /** Size of one block in bytes. */
00173 #define BLOCK_SIZE          512
00174 
00175 /** Size of the MSD IO buffer in bytes (6K, more the better). */
00176 #define MSD_BUFFER_SIZE     (12*BLOCK_SIZE)
00177 
00178 /** Ramdisk size: 20K (WinXP can not format the disk if lower than 20K) */
00179 #define RAMDISK_SIZE        128*1024
00180 
00181 COMPILER_SECTION("ramdisk_region") static uint8_t
00182 ramdisk_reserved[RAMDISK_SIZE];
00183 #define RAMDISK_BASE_ADDR ((uint32_t)ramdisk_reserved)
00184 
00185 /** Delay loop for MSD refresh */
00186 #define MSD_REFRESH_LOOP    0
00187 
00188 
00189 /*----------------------------------------------------------------------------
00190  *        External variables
00191  *----------------------------------------------------------------------------*/
00192 
00193 /** Descriptor list for device enumeration */
00194 extern const USBDDriverDescriptors hidmsddDriverDescriptors;
00195 
00196 /*----------------------------------------------------------------------------
00197  *        Global variables
00198  *----------------------------------------------------------------------------*/
00199 
00200 /*- HID */
00201 
00202 #ifdef NO_PUSHBUTTON
00203 #else
00204 /** List of pinsPushButtons to configure for the application. */
00205 static Pin pinsPushButtons[] = {PINS_PUSHBUTTONS};
00206 #endif
00207 
00208 /** Array of key codes produced by each button. */
00209 static uint8_t keyCodes[NUM_KEYS] = {
00210     HIDKeypad_A,
00211     HIDKeypad_NUMLOCK,
00212 };
00213 
00214 /** Current status (pressed or not) for each key. */
00215 static uint8_t keyStatus[NUM_KEYS];
00216 
00217 /*- MSD */
00218 /** Available media. */
00219 sMedia medias[MAX_LUNS];
00220 
00221 /** Device LUNs. */
00222 MSDLun luns[MAX_LUNS];
00223 
00224 /** LUN read/write buffer. */
00225 COMPILER_ALIGNED(32) uint8_t msdBuffer[MSD_BUFFER_SIZE];
00226 
00227 /** Total data write to disk */
00228 uint32_t msdWriteTotal = 0;
00229 /** Delay for data write refresh */
00230 uint32_t msdRefreshDelay = MSD_REFRESH_LOOP;
00231 
00232 /*-----------------------------------------------------------------------------
00233  *         Callback re-implementation
00234  *----------------------------------------------------------------------------*/
00235 /**
00236  * Invoked when the configuration of the device changes. Parse used endpoints.
00237  * \param cfgnum New configuration number.
00238  */
00239 void USBDDriverCallbacks_ConfigurationChanged(uint8_t cfgnum)
00240 {
00241     HIDMSDDriver_ConfigurationChangedHandler(cfgnum);
00242 }
00243 
00244 /**
00245  * Invoked when a new SETUP request is received from the host. Forwards the
00246  * request to the Mass Storage device driver handler function.
00247  * \param request  Pointer to a USBGenericRequest instance.
00248  */
00249 void USBDCallbacks_RequestReceived(const USBGenericRequest *request)
00250 {
00251     HIDMSDDriver_RequestHandler(request);
00252 }
00253 
00254 /*----------------------------------------------------------------------------
00255  *         Callbacks
00256  *----------------------------------------------------------------------------*/
00257 
00258 /**
00259  * Invoked when the MSD finish a READ/WRITE.
00260  * \param flowDirection 1 - device to host (READ10)
00261  *                      0 - host to device (WRITE10)
00262  * \param dataLength Length of data transferred in bytes.
00263  * \param fifoNullCount Times that FIFO is NULL to wait
00264  * \param fifoFullCount Times that FIFO is filled to wait
00265  */
00266 static void MSDCallbacks_Data(uint8_t flowDirection,
00267                               uint32_t dataLength,
00268                               uint32_t fifoNullCount,
00269                               uint32_t fifoFullCount)
00270 {
00271     fifoNullCount = fifoNullCount; /*dummy */
00272     fifoFullCount = fifoFullCount; /*dummy */
00273 
00274     if (!flowDirection)
00275         msdWriteTotal += dataLength;
00276 }
00277 
00278 /*---------------------------------------------------------------------------
00279  *         Internal functions
00280  *---------------------------------------------------------------------------*/
00281 /**
00282  * Configure USB settings for USB device
00283  */
00284 static void _ConfigureUotghs(void)
00285 {
00286     /* UTMI parallel mode, High/Full/Low Speed */
00287     /* UUSBCK not used in this configuration (High Speed) */
00288     PMC->PMC_SCDR = PMC_SCDR_USBCLK;
00289     /* USB clock register: USB Clock Input is UTMI PLL */
00290     PMC->PMC_USB = PMC_USB_USBS;
00291     /* Enable peripheral clock for USBHS */
00292     PMC_EnablePeripheral(ID_USBHS);
00293     USBHS->USBHS_CTRL = USBHS_CTRL_UIMOD_DEVICE;
00294     /* Enable PLL 480 MHz */
00295     PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0xF);
00296 
00297     /* Wait that PLL is considered locked by the PMC */
00298     while (!(PMC->PMC_SR & PMC_SR_LOCKU));
00299 
00300     /* IRQ */
00301     NVIC_EnableIRQ(USBHS_IRQn);
00302 }
00303 /**
00304  * Invoked when the status of the keyboard LEDs changes. Turns the num. lock
00305  * LED on or off.
00306  * \param numLockStatus Indicates the current status of the num. lock key.
00307  * \param capsLockStatus Indicates the current status of the caps lock key.
00308  * \param scrollLockStatus Indicates the current status of the scroll lock key
00309  */
00310 void HIDDKeyboardCallbacks_LedsChanged(
00311     uint8_t numLockStatus,
00312     uint8_t capsLockStatus,
00313     uint8_t scrollLockStatus)
00314 {
00315     capsLockStatus = capsLockStatus; /*dummy */
00316     scrollLockStatus = scrollLockStatus; /*dummy */
00317 
00318     /* Num. lock */
00319     if (numLockStatus)
00320         LED_Set(LED_NUMLOCK);
00321     else
00322         LED_Clear(LED_NUMLOCK);
00323 }
00324 
00325 /*---------------------------------------------------------------------------
00326  *         Internal functions
00327  *---------------------------------------------------------------------------*/
00328 
00329 /**
00330  * Monitor keyboard buttons & Update key status in HID driver
00331  */
00332 static void HIDDKeyboardProcessKeys(void)
00333 {
00334     uint32_t i;
00335     uint8_t pressedKeys[NUM_KEYS];
00336     uint8_t pressedKeysSize = 0;
00337     uint8_t releasedKeys[NUM_KEYS];
00338     uint8_t releasedKeysSize = 0;
00339 
00340     /* Monitor buttons */
00341 #ifdef NO_PUSHBUTTON
00342 
00343     if (DBG_IsRxReady()) {
00344         uint8_t key = DBG_GetChar();
00345 
00346         switch (key) {
00347         case '1': case '2':
00348             i = key - '1';
00349 
00350             if (keyStatus[i]) {
00351                 /* Key press simulation */
00352                 TRACE_INFO("Key %u pressed\n\r", (unsigned int)i);
00353                 keyStatus[i] = 0;
00354                 pressedKeys[pressedKeysSize] = keyCodes[i];
00355                 pressedKeysSize ++;
00356                 HIDDKeyboard_RemoteWakeUp();
00357             } else {
00358                 /* Key release simulation */
00359                 TRACE_INFO("Key %u released\n\r", (unsigned int)i);
00360                 keyStatus[i] = 1;
00361                 releasedKeys[releasedKeysSize] = keyCodes[i];
00362                 releasedKeysSize++;
00363             }
00364 
00365             break;
00366 
00367         default: DBG_PutChar(key);
00368         }
00369     }
00370 
00371 #else
00372 
00373     for (i = 0; i < PIO_LISTSIZE(pinsPushButtons); i++) {
00374         /* Check if button state has changed */
00375         uint8_t isButtonPressed = PIO_Get(&(pinsPushButtons[i]));
00376 
00377         if (isButtonPressed != keyStatus[i]) {
00378             /* Update button state */
00379             if (!isButtonPressed) {
00380                 /* Key has been pressed */
00381                 TRACE_INFO("Key %u has been pressed\n\r", i);
00382                 keyStatus[i] = 0;
00383                 pressedKeys[pressedKeysSize] = keyCodes[i];
00384                 pressedKeysSize++;
00385                 HIDDKeyboard_RemoteWakeUp();
00386             } else {
00387                 /* Key has been released */
00388                 TRACE_INFO("Key %u has been released\n\r", i);
00389                 keyStatus[i] = 1;
00390                 releasedKeys[releasedKeysSize] = keyCodes[i];
00391                 releasedKeysSize++;
00392             }
00393         }
00394     }
00395 
00396 #endif
00397 
00398     /* Update key status in the HID driver if necessary */
00399     if ((pressedKeysSize != 0) || (releasedKeysSize != 0)) {
00400         uint8_t status;
00401 
00402         do {
00403             status = HIDDKeyboard_ChangeKeys(pressedKeys,
00404                                              pressedKeysSize,
00405                                              releasedKeys,
00406                                              releasedKeysSize);
00407         } while (status != USBD_STATUS_SUCCESS);
00408     }
00409 }
00410 
00411 /**
00412  * Initialize SDRAM to assign ramdisk block
00413  */
00414 static void RamDiskInit(void)
00415 {
00416     printf("RamDisk @ %x, size %d\n\r", (unsigned int)RAMDISK_BASE_ADDR , RAMDISK_SIZE);
00417 
00418     BOARD_ConfigureSdram();
00419     MEDRamDisk_Initialize(&(medias[DRV_RAMDISK]),
00420                           BLOCK_SIZE,
00421                           RAMDISK_BASE_ADDR  / BLOCK_SIZE,
00422                           RAMDISK_SIZE / BLOCK_SIZE,
00423                           1);
00424     LUN_Init(&(luns[DRV_RAMDISK]),
00425              &(medias[DRV_RAMDISK]),
00426              msdBuffer, MSD_BUFFER_SIZE,
00427              0, 0, 0, 0,
00428              MSDCallbacks_Data);
00429     gNbMedias = 1;
00430 }
00431 
00432 /**
00433  * Initialize MSD Media & LUNs
00434  */
00435 static void _MemoriesInitialize(void)
00436 {
00437     uint32_t i;
00438 
00439     /* Reset all LUNs */
00440     for (i = 0; i < MAX_LUNS; i ++)
00441         LUN_Init(&luns[i], 0, 0, 0, 0, 0, 0, 0, 0);
00442 
00443     /* TODO: Add LUN Init here */
00444 
00445     /* RAM disk initialize */
00446     RamDiskInit();
00447     /* Nand Flash Init */
00448     /* SD Card Init */
00449 }
00450 
00451 /*---------------------------------------------------------------------------
00452  *          Main
00453  *---------------------------------------------------------------------------*/
00454 
00455 /**
00456  * Initializes drivers and start the USB composite device.
00457  */
00458 int main(void)
00459 {
00460     uint8_t usbConnected = 0;
00461 
00462     /* Disable watchdog */
00463     WDT_Disable(WDT);
00464 
00465     SCB_EnableICache();
00466     SCB_EnableDCache();
00467 
00468     printf("-- USB HIDMSD Device Project %s --\n\r", SOFTPACK_VERSION);
00469     printf("-- %s\n\r", BOARD_NAME);
00470     printf("-- Compiled: %s %s With %s--\n\r", __DATE__, __TIME__ ,
00471             COMPILER_NAME);
00472 
00473 
00474     /* If they are present, configure Vbus & Wake-up pins */
00475     PIO_InitializeInterrupts(0);
00476 
00477     /* Initialize all USB power (off) */
00478     _ConfigureUotghs();
00479 
00480     /* ----- HID Function Initialize */
00481 #ifdef NO_PUSHBUTTON
00482     printf("-- : DBG key 1 2 used as buttons\n\r");
00483     printf("-- : 1st press to push, 2nd press to release\n\r");
00484 #else
00485     /* Initialize key statuses and configure push buttons */
00486     PIO_Configure(pinsPushButtons, PIO_LISTSIZE(pinsPushButtons));
00487 #endif
00488     memset(keyStatus, 1, NUM_KEYS);
00489 
00490     /* Configure LEDs */
00491     LED_Configure(LED_NUMLOCK);
00492 
00493     _MemoriesInitialize();
00494 
00495     /* USB COMPOSITE driver initialization */
00496     HIDMSDDriver_Initialize(&hidmsddDriverDescriptors, luns, MAX_LUNS);
00497 
00498     /* connect if needed */
00499     USBD_Connect();
00500 
00501     /* Driver loop */
00502     while (1) {
00503         /* Device is not configured */
00504         if (USBD_GetState() < USBD_STATE_CONFIGURED) {
00505             if (usbConnected) {
00506                 printf("-I- USB Disconnect/Suspend\n\r");
00507                 usbConnected = 0;
00508             }
00509         } else {
00510             if (usbConnected == 0) {
00511                 printf("-I- USB Connect\n\r");
00512                 usbConnected = 1;
00513             }
00514 
00515             HIDDKeyboardProcessKeys();
00516             MSDFunction_StateMachine();
00517 
00518             if (msdRefreshDelay -- > 0) {
00519                 msdRefreshDelay = MSD_REFRESH_LOOP;
00520 
00521                 if (msdWriteTotal < 5 * 1024) {
00522                     // Flush Disk Media
00523                 }
00524 
00525                 msdWriteTotal = 0;
00526             }
00527         }
00528     }
00529 }
00530 /** \endcond */
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Defines