1155 lines
40 KiB
C
1155 lines
40 KiB
C
/*----------------------------------------------------------------------------
|
|
* ATMEL Microcontroller Software Support
|
|
* ----------------------------------------------------------------------------
|
|
* Copyright (c) 2008, Atmel Corporation
|
|
*
|
|
* 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 disclaimer below.
|
|
*
|
|
* Atmel's name may not be used to endorse or promote products derived from
|
|
* this software without specific prior written permission.
|
|
*
|
|
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
|
* DISCLAIMED. IN NO EVENT SHALL ATMEL 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.
|
|
* ----------------------------------------------------------------------------
|
|
*/
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/// \dir "USB Device Mass Storage Project"
|
|
///
|
|
/// !!!Purpose
|
|
///
|
|
/// The USB Massstorage Project will help you to get familiar with the
|
|
/// USB Device Port(UDP) on AT91SAM microcontrollers. Also
|
|
/// it can help you to be familiar with the USB Framework that is used for
|
|
/// rapid development of USB-compliant class drivers such as USB Mass
|
|
/// Storage class (MSD).
|
|
///
|
|
/// You can find following information depends on your needs:
|
|
/// - Sample usage of USB MSD driver.
|
|
/// - USB MSD driver development based on the AT91 USB Framework.
|
|
/// - USB enumerate sequence, the standard and class-specific descriptors and
|
|
/// requests handling.
|
|
/// - The initialize sequence and usage of UDP interface.
|
|
///
|
|
/// !See
|
|
/// - memories: Storage Media interface for MSD
|
|
/// - usb: USB Framework, USB MSD driver and UDP interface driver
|
|
/// - "AT91 USB device framework"
|
|
/// - "USBD API"
|
|
/// - "massstorage"
|
|
/// - "USB MSD Driver"
|
|
///
|
|
/// !!!Requirements
|
|
///
|
|
/// This package can be used with all Atmel evaluation kits that have USB interface
|
|
///
|
|
/// !!!Description
|
|
///
|
|
/// When an EK running this program connected to a host (PC for example), with
|
|
/// USB cable, the EK appears as a USB Disk for the host. Then the host can
|
|
/// format/read/write on the disk.
|
|
///
|
|
/// If there is SDRAM on the EK, the disk can be up to 10M so that read/write
|
|
/// speed can be tested.
|
|
///
|
|
/// If there is no SDRAM but only internal flash, the disk is about 30K and
|
|
/// only small file can be tested.
|
|
///
|
|
/// !!!Usage
|
|
///
|
|
/// -# Build the program and download it inside the evaluation board. Please
|
|
/// refer to the
|
|
/// <a href="http://www.atmel.com/dyn/resources/prod_documents/doc6224.pdf">
|
|
/// SAM-BA User Guide</a>, the
|
|
/// <a href="http://www.atmel.com/dyn/resources/prod_documents/doc6310.pdf">
|
|
/// GNU-Based Software Development</a> application note or to the
|
|
/// <a href="ftp://ftp.iar.se/WWWfiles/arm/Guides/EWARM_UserGuide.ENU.pdf">
|
|
/// IAR EWARM User Guide</a>, depending on your chosen solution.
|
|
/// -# On the computer, open and configure a terminal application
|
|
/// (e.g. HyperTerminal on Microsoft Windows) with these settings:
|
|
/// - 115200 bauds
|
|
/// - 8 bits of data
|
|
/// - No parity
|
|
/// - 1 stop bit
|
|
/// - No flow control
|
|
/// -# Start the application.
|
|
/// -# In the terminal window, the following text should appear:
|
|
/// \code
|
|
/// -- USB Device Mass Storage Project xxx --
|
|
/// -- AT91xxxxxx-xx
|
|
/// -- Compiled: xxx xx xxxx xx:xx:xx --
|
|
/// \endcode
|
|
/// -# When connecting USB cable to windows, the LED blinks, and the host
|
|
/// reports a new USB %device attachment and Disk installation.
|
|
/// . Then new "USB Mass Storage Device" and
|
|
/// "ATMEL Mass Storage MSD USB Device" and "Generic volume" appear in
|
|
/// hardware %device list.
|
|
/// -# You can find the new disk on host, and to create/write file to it.
|
|
///
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------------
|
|
/// \unit
|
|
///
|
|
/// !Purpose
|
|
///
|
|
/// This file contains all the specific code for the
|
|
/// usb-device-massstorage-project
|
|
///
|
|
/// !Contents
|
|
///
|
|
/// The code can be roughly broken down as follows:
|
|
/// - Configuration functions
|
|
/// - VBus_Configure
|
|
/// - ConfigurePit
|
|
/// - ConfigureWakeUp
|
|
/// - PIO & Timer configurations in start of main
|
|
/// - Interrupt handlers
|
|
/// - ISR_Vbus
|
|
/// - ISR_Pit
|
|
/// - WakeUpHandler
|
|
/// - ISR_Media
|
|
/// - The main function, which implements the program behavior
|
|
///
|
|
/// Please refer to the list of functions in the #Overview# tab of this unit
|
|
/// for more detailed information.
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Headers
|
|
//------------------------------------------------------------------------------
|
|
|
|
#include <board.h>
|
|
#include <board_lowlevel.h>
|
|
#include <board_memories.h>
|
|
#include <pio/pio.h>
|
|
#include <pio/pio_it.h>
|
|
#ifdef AT91C_BASE_PITC
|
|
#include <pit/pit.h>
|
|
#endif
|
|
#include <irq/irq.h>
|
|
#include <tc/tc.h>
|
|
#include <dbgu/dbgu.h>
|
|
#include <utility/trace.h>
|
|
#include <utility/assert.h>
|
|
#include <utility/led.h>
|
|
#include <usb/common/core/USBConfigurationDescriptor.h>
|
|
#include <usb/device/core/USBD.h>
|
|
#include <usb/device/massstorage/MSDDriver.h>
|
|
#include <usb/device/massstorage/MSDLun.h>
|
|
#include <usb/device/core/USBDCallbacks.h>
|
|
#include <memories/Media.h>
|
|
#if defined(AT91C_EBI_SDRAM)
|
|
#include <memories/MEDSdram.h>
|
|
#endif
|
|
#if defined(AT91C_BASE_DDR2C)
|
|
#include <memories/MEDDdram.h>
|
|
#endif
|
|
#if defined(BOARD_SD_MCI_BASE)
|
|
#include <memories/MEDSdcard.h>
|
|
#endif
|
|
#if defined(CHIP_FLASH_EFC) || defined(CHIP_FLASH_EEFC) && !defined(cortexm3)
|
|
#include <memories/MEDFlash.h>
|
|
#endif
|
|
#if defined(at91sam3uek)
|
|
#include <memories/MEDRamDisk.h>
|
|
#endif
|
|
#if 0
|
|
#include <memories/MEDNandFlash.h>
|
|
#include <memories/nandflash/RawNandFlash.h>
|
|
#include <memories/nandflash/TranslatedNandFlash.h>
|
|
#endif
|
|
|
|
#include <pmc/pmc.h>
|
|
|
|
#include <string.h>
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Internal definitions
|
|
//------------------------------------------------------------------------------
|
|
|
|
/// Maximum number of LUNs which can be defined.
|
|
#define MAX_LUNS 3
|
|
|
|
/// Media index for different disks
|
|
#define DRV_RAMDISK 0 /// RAM disk
|
|
#define DRV_IFLASH 0 /// Internal flash, if no RAM disk
|
|
#define DRV_SDMMC 1 /// SD card, if there is
|
|
#define DRV_NAND 2 /// Nand flash, if there is
|
|
|
|
/// Delay for pushbutton debouncing (ms)
|
|
#define DEBOUNCE_TIME 10
|
|
|
|
/// PIT period value (seconds)
|
|
#define PIT_PERIOD 1000
|
|
|
|
/// Delay for display view update (*250ms)
|
|
#define UPDATE_DELAY 4
|
|
|
|
/// Delay for waiting DBGU input (*250ms)
|
|
#define INPUT_DELAY 20
|
|
|
|
#if defined(at91sam3uek)
|
|
/// No reserved space for code in PSRAM
|
|
#define CODE_SIZE (0)
|
|
/// Size of the RAM disk in bytes (512K).
|
|
#define RAMDISK_SIZE (512*1024)
|
|
#else
|
|
/// Maximum code size 100K reserved for running in SDRAM and FLASH
|
|
#define CODE_SIZE (100*1024)
|
|
/// Size of the RAM disk in bytes (10M).
|
|
#define RAMDISK_SIZE (10*1024*1024)
|
|
#endif
|
|
|
|
/// Size of the reserved Nand Flash (4M)
|
|
#define NF_RESERVE_SIZE (4*1024*1024)
|
|
|
|
/// Size of the managed Nand Flash (128M)
|
|
#define NF_MANAGED_SIZE (128*1024*1024)
|
|
|
|
/// Size of one block in bytes.
|
|
#define BLOCK_SIZE 512
|
|
|
|
/// Size of the MSD IO buffer in bytes (2K, more the better).
|
|
#define MSD_BUFFER_SIZE (12*BLOCK_SIZE)
|
|
|
|
/// Use for power management
|
|
#define STATE_IDLE 0
|
|
/// The USB device is in suspend state
|
|
#define STATE_SUSPEND 4
|
|
/// The USB device is in resume state
|
|
#define STATE_RESUME 5
|
|
|
|
/// Retry 3 times when SD is inserted
|
|
#define SD_INIT_RETRY 3
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Global variables
|
|
//------------------------------------------------------------------------------
|
|
|
|
/// Available medias.
|
|
Media medias[MAX_LUNS];
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Internal variables
|
|
//------------------------------------------------------------------------------
|
|
|
|
/// Device LUNs.
|
|
MSDLun luns[MAX_LUNS];
|
|
|
|
/// LUN read/write buffer.
|
|
unsigned char msdBuffer[MSD_BUFFER_SIZE];
|
|
|
|
/// Total data read/write by MSD
|
|
unsigned int msdReadTotal = 0;
|
|
unsigned int msdWriteTotal = 0;
|
|
unsigned short msdFullCnt = 0;
|
|
unsigned short msdNullCnt = 0;
|
|
|
|
/// Update delay counter, tick is 250ms
|
|
unsigned int updateDelay = UPDATE_DELAY;
|
|
|
|
/// Flag to update Display View
|
|
unsigned char updateView = 0;
|
|
|
|
/// State of USB, for suspend and resume
|
|
unsigned char USBState = STATE_IDLE;
|
|
|
|
#if 0//#ifdef PINS_NANDFLASH
|
|
/// Pins used to access to nandflash.
|
|
static const Pin pPinsNf[] = {PINS_NANDFLASH};
|
|
/// Nandflash device structure.
|
|
static struct TranslatedNandFlash translatedNf;
|
|
/// Address for transferring command bytes to the nandflash.
|
|
static unsigned int cmdBytesAddr = BOARD_NF_COMMAND_ADDR;
|
|
/// Address for transferring address bytes to the nandflash.
|
|
static unsigned int addrBytesAddr = BOARD_NF_ADDRESS_ADDR;
|
|
/// Address for transferring data bytes to the nandflash.
|
|
static unsigned int dataBytesAddr = BOARD_NF_DATA_ADDR;
|
|
/// Nandflash chip enable pin.
|
|
static const Pin nfCePin = BOARD_NF_CE_PIN;
|
|
/// Nandflash ready/busy pin.
|
|
static const Pin nfRbPin = BOARD_NF_RB_PIN;
|
|
#endif
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Remote wake-up support (optional)
|
|
//------------------------------------------------------------------------------
|
|
#if (BOARD_USB_BMATTRIBUTES == USBConfigurationDescriptor_BUSPOWERED_RWAKEUP) \
|
|
|| (BOARD_USB_BMATTRIBUTES == USBConfigurationDescriptor_SELFPOWERED_RWAKEUP)
|
|
|
|
#define WAKEUP_CONFIGURE() ConfigureWakeUp()
|
|
|
|
/// Button for Wake-UP the USB device.
|
|
static const Pin pinWakeUp = PIN_PUSHBUTTON_1;
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Interrupt service routine for the PIT. Debounces the wake-up pin input.
|
|
//------------------------------------------------------------------------------
|
|
#if defined (AT91C_BASE_PITC)
|
|
static void ISR_Pit(void)
|
|
{
|
|
static unsigned long debounceCounter = DEBOUNCE_TIME;
|
|
unsigned long pisr = 0;
|
|
|
|
// Read the PISR
|
|
pisr = PIT_GetStatus() & AT91C_PITC_PITS;
|
|
|
|
if (pisr != 0) {
|
|
|
|
// Read the PIVR. It acknowledges the IT
|
|
PIT_GetPIVR();
|
|
}
|
|
|
|
// Button released
|
|
if (PIO_Get(&pinWakeUp)) {
|
|
|
|
debounceCounter = DEBOUNCE_TIME;
|
|
}
|
|
// Button still pressed
|
|
else {
|
|
|
|
debounceCounter--;
|
|
}
|
|
|
|
// End of debounce time
|
|
if (debounceCounter == 0) {
|
|
|
|
debounceCounter = DEBOUNCE_TIME;
|
|
PIT_DisableIT();
|
|
AT91C_BASE_PITC->PITC_PIMR &= ~AT91C_PITC_PITEN;
|
|
MSDDriver_RemoteWakeUp();
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Configures the PIT to generate 1ms ticks.
|
|
//------------------------------------------------------------------------------
|
|
static void ConfigurePit(void)
|
|
{
|
|
// Initialize and enable the PIT
|
|
PIT_Init(PIT_PERIOD, BOARD_MCK / 1000000);
|
|
|
|
// Disable the interrupt on the interrupt controller
|
|
IRQ_DisableIT(AT91C_ID_SYS);
|
|
|
|
// Configure the AIC for PIT interrupts
|
|
IRQ_ConfigureIT(AT91C_ID_SYS, 0, ISR_Pit);
|
|
|
|
// Enable the interrupt on the interrupt controller
|
|
IRQ_EnableIT(AT91C_ID_SYS);
|
|
|
|
// Enable the interrupt on the pit
|
|
PIT_EnableIT();
|
|
|
|
// Enable the pit
|
|
PIT_Enable();
|
|
}
|
|
#endif // AT91C_BASE_PITC
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Interrupt service routine for the remote wake-up pin. Starts the debouncing
|
|
/// sequence.
|
|
//------------------------------------------------------------------------------
|
|
static void WakeUpHandler(const Pin *pin)
|
|
{
|
|
TRACE_DEBUG("Wake-up handler\n\r");
|
|
|
|
// Check current level on the remote wake-up pin
|
|
if (!PIO_Get(&pinWakeUp)) {
|
|
#ifdef AT91C_BASE_PITC
|
|
ConfigurePit();
|
|
#endif // AT91C_BASE_PITC
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Configures the wake-up pin to generate interrupts.
|
|
//------------------------------------------------------------------------------
|
|
static void ConfigureWakeUp(void)
|
|
{
|
|
TRACE_INFO("Wake-up configuration\n\r");
|
|
|
|
// Configure PIO
|
|
PIO_Configure(&pinWakeUp, 1);
|
|
PIO_ConfigureIt(&pinWakeUp, WakeUpHandler);
|
|
PIO_EnableIt(&pinWakeUp);
|
|
}
|
|
|
|
#else
|
|
#define WAKEUP_CONFIGURE()
|
|
#endif
|
|
|
|
//------------------------------------------------------------------------------
|
|
// VBus monitoring (optional)
|
|
//------------------------------------------------------------------------------
|
|
#if defined(PIN_USB_VBUS)
|
|
|
|
#define VBUS_CONFIGURE() VBus_Configure()
|
|
|
|
/// VBus pin instance.
|
|
static const Pin pinVbus = PIN_USB_VBUS;
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Handles interrupts coming from PIO controllers.
|
|
//------------------------------------------------------------------------------
|
|
void ISR_Vbus(const Pin *pPin)
|
|
{
|
|
// Check current level on VBus
|
|
if (PIO_Get(&pinVbus)) {
|
|
|
|
TRACE_INFO("VBUS conn\n\r");
|
|
USBD_Connect();
|
|
}
|
|
else {
|
|
|
|
TRACE_INFO("VBUS discon\n\r");
|
|
USBD_Disconnect();
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Configures the VBus pin to trigger an interrupt when the level on that pin
|
|
/// changes.
|
|
//------------------------------------------------------------------------------
|
|
static void VBus_Configure( void )
|
|
{
|
|
TRACE_INFO("VBus configuration\n\r");
|
|
|
|
// Configure PIO
|
|
PIO_Configure(&pinVbus, 1);
|
|
PIO_ConfigureIt(&pinVbus, ISR_Vbus);
|
|
PIO_EnableIt(&pinVbus);
|
|
|
|
// Check current level on VBus
|
|
if (PIO_Get(&pinVbus)) {
|
|
|
|
// if VBUS present, force the connect
|
|
TRACE_INFO("conn\n\r");
|
|
USBD_Connect();
|
|
}
|
|
else {
|
|
USBD_Disconnect();
|
|
}
|
|
}
|
|
|
|
#else
|
|
#define VBUS_CONFIGURE() USBD_Connect()
|
|
#endif //#if defined(PIN_USB_VBUS)
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Callbacks (re)-implementation
|
|
//------------------------------------------------------------------------------
|
|
//------------------------------------------------------------------------------
|
|
/// Invoked when the USB device leaves the Suspended state. By default,
|
|
/// configures the LEDs.
|
|
//------------------------------------------------------------------------------
|
|
void USBDCallbacks_Resumed(void)
|
|
{
|
|
// Initialize LEDs
|
|
LED_Configure(USBD_LEDPOWER);
|
|
LED_Set(USBD_LEDPOWER);
|
|
LED_Configure(USBD_LEDUSB);
|
|
LED_Clear(USBD_LEDUSB);
|
|
USBState = STATE_RESUME;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Invoked when the USB device gets suspended. By default, turns off all LEDs.
|
|
//------------------------------------------------------------------------------
|
|
void USBDCallbacks_Suspended(void)
|
|
{
|
|
// Turn off LEDs
|
|
LED_Clear(USBD_LEDPOWER);
|
|
LED_Clear(USBD_LEDUSB);
|
|
USBState = STATE_SUSPEND;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Invoked when the MSD finish a READ/WRITE.
|
|
/// \param flowDirection 1 - device to host (READ10)
|
|
/// 0 - host to device (WRITE10)
|
|
/// \param dataLength Length of data transferred in bytes.
|
|
/// \param fifoNullCount Times that FIFO is NULL to wait
|
|
/// \param fifoFullCount Times that FIFO is filled to wait
|
|
//------------------------------------------------------------------------------
|
|
void MSDCallbacks_Data(unsigned char flowDirection,
|
|
unsigned int dataLength,
|
|
unsigned int fifoNullCount,
|
|
unsigned int fifoFullCount)
|
|
{
|
|
if (flowDirection) {
|
|
|
|
msdReadTotal += dataLength;
|
|
}
|
|
else {
|
|
|
|
msdWriteTotal += dataLength;
|
|
}
|
|
|
|
msdFullCnt += fifoFullCount;
|
|
msdNullCnt += fifoNullCount;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Internal functions
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Interrupt handler for timer.
|
|
//------------------------------------------------------------------------------
|
|
void TC0_IrqHandler(void)
|
|
{
|
|
volatile unsigned int dummy;
|
|
// Clear status bit to acknowledge interrupt
|
|
dummy = AT91C_BASE_TC0->TC_SR;
|
|
|
|
if (-- updateDelay == 0) {
|
|
|
|
updateDelay = UPDATE_DELAY;
|
|
updateView = 1;
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Configure Timer Counter 0 to generate an interrupt every 250ms.
|
|
//------------------------------------------------------------------------------
|
|
void ConfigureTc0(void)
|
|
{
|
|
unsigned int div;
|
|
unsigned int tcclks;
|
|
|
|
// Enable peripheral clock
|
|
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_TC0;
|
|
|
|
// Configure TC for a 4Hz frequency and trigger on RC compare
|
|
TC_FindMckDivisor(4, BOARD_MCK, &div, &tcclks);
|
|
TC_Configure(AT91C_BASE_TC0, tcclks | AT91C_TC_CPCTRG);
|
|
AT91C_BASE_TC0->TC_RC = (BOARD_MCK / div) / 4; // timerFreq / desiredFreq
|
|
|
|
// Configure and enable interrupt on RC compare
|
|
IRQ_ConfigureIT(AT91C_ID_TC0, 3, TC0_IrqHandler);
|
|
AT91C_BASE_TC0->TC_IER = AT91C_TC_CPCS;
|
|
IRQ_EnableIT(AT91C_ID_TC0);
|
|
|
|
TC_Start(AT91C_BASE_TC0);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Interrupt handler for all media types.
|
|
//------------------------------------------------------------------------------
|
|
void ISR_Media(void)
|
|
{
|
|
MED_HandleAll(medias, numMedias);
|
|
}
|
|
|
|
#if defined(BOARD_SD_MCI_BASE)
|
|
//------------------------------------------------------------------------------
|
|
/// SD card connection/disconnection handler, to initialize and link SD Media
|
|
/// to corresponding LUN or unlink it.
|
|
/// \param inserted SD card is inserted/ejected.
|
|
//------------------------------------------------------------------------------
|
|
static unsigned char SDConnectionUpdate(unsigned char inserted)
|
|
{
|
|
unsigned char rc;
|
|
if (inserted) {
|
|
#if 1
|
|
// Faster, non-blocked SD access function
|
|
rc = MEDSdusb_Initialize(&(medias[DRV_SDMMC]), 0);
|
|
#else
|
|
// Blocked SD access function
|
|
rc = MEDSdcard_Initialize(&(medias[DRV_SDMMC]), 0);
|
|
#endif
|
|
if(rc) {
|
|
LUN_Init(&(luns[DRV_SDMMC]), &(medias[DRV_SDMMC]),
|
|
msdBuffer, MSD_BUFFER_SIZE,
|
|
0, 0, 0, 0,
|
|
MSDCallbacks_Data);
|
|
return 1;
|
|
}
|
|
}
|
|
else {
|
|
LUN_Eject(&luns[DRV_SDMMC]);
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#if 0//defined(PINS_NANDFLASH)
|
|
#define NandFlash_Configure(nfBusWidth) BOARD_ConfigureNandFlash(nfBusWidth)
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Initialize Nand Flash for LUN
|
|
//------------------------------------------------------------------------------
|
|
static void NandFlashInitialize(void)
|
|
{
|
|
unsigned char nfBusWidth = 16, nfRc;
|
|
unsigned short nfBaseBlock = 0;
|
|
struct RawNandFlash *pRaw = (struct RawNandFlash*)&translatedNf;
|
|
struct NandFlashModel *pModel = (struct NandFlashModel*)&translatedNf;
|
|
unsigned int nfMamagedSize;
|
|
|
|
// Configure SMC for NandFlash
|
|
NandFlash_Configure(nfBusWidth);
|
|
// Configure PIO for Nand Flash
|
|
PIO_Configure(pPinsNf, PIO_LISTSIZE(pPinsNf));
|
|
|
|
// Nand Flash Initialize (ALL flash mapped)
|
|
nfRc = RawNandFlash_Initialize(pRaw,
|
|
0,
|
|
cmdBytesAddr,
|
|
addrBytesAddr,
|
|
dataBytesAddr,
|
|
nfCePin,
|
|
nfRbPin);
|
|
if (nfRc) {
|
|
printf("Nand not found\n\r");
|
|
return;
|
|
}
|
|
else {
|
|
printf("NF\tNb Blocks %d\n\r",
|
|
NandFlashModel_GetDeviceSizeInBlocks(pModel));
|
|
printf("\tBlock Size %dK\n\r",
|
|
NandFlashModel_GetBlockSizeInBytes(pModel)/1024);
|
|
printf("\tPage Size %d\n\r",
|
|
NandFlashModel_GetPageDataSize(pModel));
|
|
nfBaseBlock =
|
|
NF_RESERVE_SIZE / NandFlashModel_GetBlockSizeInBytes(pModel);
|
|
}
|
|
printf("NF disk will use area from %dM(B%d)\n\r",
|
|
NF_RESERVE_SIZE/1024/1024, nfBaseBlock);
|
|
printf("!! Erase the NF Disk? (y/n):");
|
|
updateDelay = INPUT_DELAY;
|
|
updateView = 0;
|
|
while(1) {
|
|
if(DBGU_IsRxReady()) {
|
|
char key = DBGU_GetChar();
|
|
DBGU_PutChar(key);
|
|
if (key == 'y') {
|
|
if (nfRc == 0) {
|
|
unsigned int block;
|
|
printf(" Erase from %d ... ", nfBaseBlock);
|
|
for (block = nfBaseBlock;
|
|
block < NandFlashModel_GetDeviceSizeInBlocks(pModel);
|
|
block ++) {
|
|
RawNandFlash_EraseBlock(pRaw, block);
|
|
}
|
|
printf("OK");
|
|
}
|
|
}
|
|
printf("\n\r");
|
|
break;
|
|
}
|
|
if (updateView) {
|
|
printf("No\n\r");
|
|
break;
|
|
}
|
|
}
|
|
nfMamagedSize = ((NandFlashModel_GetDeviceSizeInMBytes(pModel) - NF_RESERVE_SIZE/1024/1024) > NF_MANAGED_SIZE/1024/1024) ? \
|
|
NF_MANAGED_SIZE/1024/1024 : (NandFlashModel_GetDeviceSizeInMBytes(pModel) - NF_RESERVE_SIZE/1024/1024);
|
|
if (TranslatedNandFlash_Initialize(&translatedNf,
|
|
0,
|
|
cmdBytesAddr,
|
|
addrBytesAddr,
|
|
dataBytesAddr,
|
|
nfCePin,
|
|
nfRbPin,
|
|
nfBaseBlock, nfMamagedSize * 1024 * 1024/NandFlashModel_GetBlockSizeInBytes(pModel))) {
|
|
printf("Nand init error\n\r");
|
|
return;
|
|
}
|
|
// Check the data bus width of the NandFlash
|
|
nfBusWidth =
|
|
NandFlashModel_GetDataBusWidth(pModel);
|
|
NandFlash_Configure(nfBusWidth);
|
|
|
|
// Media initialize
|
|
MEDNandFlash_Initialize(&medias[DRV_NAND], &translatedNf);
|
|
|
|
// Initialize LUN
|
|
LUN_Init(&(luns[DRV_NAND]), &(medias[DRV_NAND]),
|
|
msdBuffer, MSD_BUFFER_SIZE,
|
|
0, 0, 0, 0,
|
|
MSDCallbacks_Data);
|
|
|
|
numMedias ++;
|
|
}
|
|
#endif
|
|
|
|
#if !defined(cortexm3)
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Initialize memory for LUN
|
|
//------------------------------------------------------------------------------
|
|
static void MemoryInitialization(void)
|
|
{
|
|
unsigned int i;
|
|
for (i = 0; i < MAX_LUNS; i ++)
|
|
LUN_Init(&luns[i], 0, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
// Memory initialization
|
|
#if defined(AT91C_BASE_DDR2C)
|
|
TRACE_INFO("MEM: DDR2\n\r");
|
|
BOARD_ConfigureDdram(0, BOARD_DDRAM_BUSWIDTH); // Micron, 16 bit data bus size
|
|
|
|
MEDDdram_Initialize(&(medias[DRV_RAMDISK]),
|
|
BLOCK_SIZE,
|
|
(unsigned int)(AT91C_DDR2 + CODE_SIZE) / BLOCK_SIZE,
|
|
RAMDISK_SIZE / BLOCK_SIZE);
|
|
LUN_Init(&(luns[DRV_RAMDISK]), &(medias[DRV_RAMDISK]),
|
|
msdBuffer, MSD_BUFFER_SIZE,
|
|
0, 0, 0, 0,
|
|
MSDCallbacks_Data);
|
|
numMedias = 1;
|
|
|
|
#elif defined(AT91C_EBI_SDRAM)
|
|
|
|
TRACE_INFO("MEM: SDRAM\n\r");
|
|
#if !defined(sdram)
|
|
BOARD_ConfigureSdram(BOARD_SDRAM_BUSWIDTH);
|
|
#endif
|
|
|
|
MEDSdram_Initialize(&(medias[DRV_RAMDISK]),
|
|
BLOCK_SIZE,
|
|
(unsigned int)(AT91C_EBI_SDRAM + CODE_SIZE)/BLOCK_SIZE,
|
|
RAMDISK_SIZE / BLOCK_SIZE);
|
|
LUN_Init(&(luns[DRV_RAMDISK]),
|
|
&(medias[DRV_RAMDISK]),
|
|
msdBuffer, MSD_BUFFER_SIZE,
|
|
0, 0, 0, 0,
|
|
MSDCallbacks_Data);
|
|
numMedias = 1;
|
|
|
|
#endif // AT91C_EBI_SDRAM
|
|
|
|
// SD Card
|
|
#if defined(BOARD_SD_MCI_BASE)
|
|
TRACE_DEBUG("MEM: SD Card\n\r");
|
|
SDConnectionUpdate(1);
|
|
numMedias = 2;
|
|
#endif
|
|
|
|
// Flash
|
|
#if defined(CHIP_FLASH_EFC) || defined(CHIP_FLASH_EEFC)
|
|
TRACE_INFO("MEM: Flash\n\r");
|
|
if (numMedias == 0) {
|
|
|
|
FLA_Initialize(&(medias[DRV_IFLASH]), AT91C_BASE_EFC);
|
|
LUN_Init(&(luns[DRV_IFLASH]),
|
|
&(medias[DRV_IFLASH]),
|
|
msdBuffer, MSD_BUFFER_SIZE,
|
|
CODE_SIZE,
|
|
AT91C_IFLASH_SIZE - CODE_SIZE,
|
|
BLOCK_SIZE,
|
|
0,
|
|
MSDCallbacks_Data);
|
|
numMedias = 1;
|
|
}
|
|
#endif // #if defined(CHIP_FLASH_EFC) || defined(CHIP_FLASH_EEFC)
|
|
}
|
|
#else
|
|
static void MemoryInitialization(void)
|
|
{
|
|
unsigned int i;
|
|
for (i = 0; i < MAX_LUNS; i ++)
|
|
LUN_Init(&luns[i], 0, 0, 0, 0, 0, 0, 0, 0);
|
|
|
|
#if defined(AT91C_EBI_PSRAM)
|
|
// Currently working on Sam3u-PSRAM
|
|
BOARD_ConfigurePsram();
|
|
|
|
// Initialize 10M for ram disk & code.
|
|
if (1 != MEDRamDisk_Initialize(&(medias[DRV_RAMDISK]),
|
|
BLOCK_SIZE,
|
|
(AT91C_EBI_PSRAM + CODE_SIZE) / BLOCK_SIZE,
|
|
RAMDISK_SIZE / BLOCK_SIZE)) {
|
|
TRACE_ERROR("FAIL!\n\r");
|
|
return;
|
|
}
|
|
// 512k Disk
|
|
LUN_Init(&(luns[DRV_RAMDISK]), &(medias[DRV_RAMDISK]), msdBuffer,
|
|
MSD_BUFFER_SIZE, 0, 0, 0, 0 , MSDCallbacks_Data);
|
|
#endif
|
|
|
|
// SD Disk
|
|
// SDConnectionUpdate(1);
|
|
numMedias = 2;
|
|
|
|
// Nand flash
|
|
//NandFlashInitialize();
|
|
}
|
|
#endif
|
|
|
|
#if defined (CP15_PRESENT)
|
|
//------------------------------------------------------------------------------
|
|
/// Put the CPU in 32kHz, disable PLL, main oscillator
|
|
/// Put voltage regulator in standby mode
|
|
//------------------------------------------------------------------------------
|
|
static void LowPowerMode(void)
|
|
{
|
|
PMC_CPUInIdleMode();
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/// Put voltage regulator in normal mode
|
|
/// Return the CPU to normal speed 48MHz, enable PLL, main oscillator
|
|
//------------------------------------------------------------------------------
|
|
static void NormalPowerMode(void)
|
|
{
|
|
}
|
|
|
|
#elif defined(at91sam7a3)
|
|
//------------------------------------------------------------------------------
|
|
/// Put the CPU in 32kHz, disable PLL, main oscillator
|
|
//------------------------------------------------------------------------------
|
|
static void LowPowerMode(void)
|
|
{
|
|
// MCK=48MHz to MCK=32kHz
|
|
// MCK = SLCK/2 : change source first from 48 000 000 to 18. / 2 = 9M
|
|
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
// MCK=SLCK : then change prescaler
|
|
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_SLOW_CLK;
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
// disable PLL
|
|
AT91C_BASE_PMC->PMC_PLLR = 0;
|
|
// Disable Main Oscillator
|
|
AT91C_BASE_PMC->PMC_MOR = 0;
|
|
|
|
PMC_DisableProcessorClock();
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/// Return the CPU to normal speed 48MHz, enable PLL, main oscillator
|
|
//------------------------------------------------------------------------------
|
|
static void NormalPowerMode(void)
|
|
{
|
|
// MCK=32kHz to MCK=48MHz
|
|
// enable Main Oscillator
|
|
AT91C_BASE_PMC->PMC_MOR = (( (AT91C_CKGR_OSCOUNT & (0x06 <<8)) | AT91C_CKGR_MOSCEN ));
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS ) );
|
|
|
|
// enable PLL@96MHz
|
|
AT91C_BASE_PMC->PMC_PLLR = ((AT91C_CKGR_DIV & 0x0E) |
|
|
(AT91C_CKGR_PLLCOUNT & (28<<8)) |
|
|
(AT91C_CKGR_MUL & (0x48<<16)));
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK ) );
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;
|
|
// MCK=SLCK/2 : change prescaler first
|
|
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
// MCK=PLLCK/2 : then change source
|
|
AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK ;
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
}
|
|
|
|
#elif defined (at91sam7se)
|
|
//------------------------------------------------------------------------------
|
|
/// Put the CPU in 32kHz, disable PLL, main oscillator
|
|
/// Put voltage regulator in standby mode
|
|
//------------------------------------------------------------------------------
|
|
static void LowPowerMode(void)
|
|
{
|
|
// MCK=48MHz to MCK=32kHz
|
|
// MCK = SLCK/2 : change source first from 48 000 000 to 18. / 2 = 9M
|
|
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
// MCK=SLCK : then change prescaler
|
|
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_SLOW_CLK;
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
// disable PLL
|
|
AT91C_BASE_PMC->PMC_PLLR = 0;
|
|
// Disable Main Oscillator
|
|
AT91C_BASE_PMC->PMC_MOR = 0;
|
|
|
|
// Voltage regulator in standby mode : Enable VREG Low Power Mode
|
|
AT91C_BASE_VREG->VREG_MR |= AT91C_VREG_PSTDBY;
|
|
|
|
PMC_DisableProcessorClock();
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/// Put voltage regulator in normal mode
|
|
/// Return the CPU to normal speed 48MHz, enable PLL, main oscillator
|
|
//------------------------------------------------------------------------------
|
|
static void NormalPowerMode(void)
|
|
{
|
|
// Voltage regulator in normal mode : Disable VREG Low Power Mode
|
|
AT91C_BASE_VREG->VREG_MR &= ~AT91C_VREG_PSTDBY;
|
|
|
|
// MCK=32kHz to MCK=48MHz
|
|
// enable Main Oscillator
|
|
AT91C_BASE_PMC->PMC_MOR = (( (AT91C_CKGR_OSCOUNT & (0x06 <<8)) | AT91C_CKGR_MOSCEN ));
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS ) );
|
|
|
|
// enable PLL@96MHz
|
|
AT91C_BASE_PMC->PMC_PLLR = ((AT91C_CKGR_DIV & 0x0E) |
|
|
(AT91C_CKGR_PLLCOUNT & (28<<8)) |
|
|
(AT91C_CKGR_MUL & (0x48<<16)));
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK ) );
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;
|
|
// MCK=SLCK/2 : change prescaler first
|
|
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
// MCK=PLLCK/2 : then change source
|
|
AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK ;
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
}
|
|
|
|
#elif defined (at91sam7s)
|
|
//------------------------------------------------------------------------------
|
|
/// Put the CPU in 32kHz, disable PLL, main oscillator
|
|
/// Put voltage regulator in standby mode
|
|
//------------------------------------------------------------------------------
|
|
static void LowPowerMode(void)
|
|
{
|
|
// MCK=48MHz to MCK=32kHz
|
|
// MCK = SLCK/2 : change source first from 48 000 000 to 18. / 2 = 9M
|
|
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
// MCK=SLCK : then change prescaler
|
|
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_SLOW_CLK;
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
// disable PLL
|
|
AT91C_BASE_PMC->PMC_PLLR = 0;
|
|
// Disable Main Oscillator
|
|
AT91C_BASE_PMC->PMC_MOR = 0;
|
|
|
|
// Voltage regulator in standby mode : Enable VREG Low Power Mode
|
|
AT91C_BASE_VREG->VREG_MR |= AT91C_VREG_PSTDBY;
|
|
|
|
PMC_DisableProcessorClock();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Put voltage regulator in normal mode
|
|
/// Return the CPU to normal speed 48MHz, enable PLL, main oscillator
|
|
//------------------------------------------------------------------------------
|
|
static void NormalPowerMode(void)
|
|
{
|
|
// Voltage regulator in normal mode : Disable VREG Low Power Mode
|
|
AT91C_BASE_VREG->VREG_MR &= ~AT91C_VREG_PSTDBY;
|
|
|
|
// MCK=32kHz to MCK=48MHz
|
|
// enable Main Oscillator
|
|
AT91C_BASE_PMC->PMC_MOR = (( (AT91C_CKGR_OSCOUNT & (0x06 <<8)) | AT91C_CKGR_MOSCEN ));
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS ) );
|
|
|
|
// enable PLL@96MHz
|
|
AT91C_BASE_PMC->PMC_PLLR = ((AT91C_CKGR_DIV & 0x0E) |
|
|
(AT91C_CKGR_PLLCOUNT & (28<<8)) |
|
|
(AT91C_CKGR_MUL & (0x48<<16)));
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK ) );
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;
|
|
// MCK=SLCK/2 : change prescaler first
|
|
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
// MCK=PLLCK/2 : then change source
|
|
AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK ;
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
|
|
}
|
|
|
|
#elif defined (at91sam7x) || defined (at91sam7xc)
|
|
//------------------------------------------------------------------------------
|
|
/// Put the CPU in 32kHz, disable PLL, main oscillator
|
|
/// Put voltage regulator in standby mode
|
|
//------------------------------------------------------------------------------
|
|
static void LowPowerMode(void)
|
|
{
|
|
// MCK=48MHz to MCK=32kHz
|
|
// MCK = SLCK/2 : change source first from 48 000 000 to 18. / 2 = 9M
|
|
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
// MCK=SLCK : then change prescaler
|
|
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_SLOW_CLK;
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
// disable PLL
|
|
AT91C_BASE_PMC->PMC_PLLR = 0;
|
|
// Disable Main Oscillator
|
|
AT91C_BASE_PMC->PMC_MOR = 0;
|
|
|
|
// Voltage regulator in standby mode : Enable VREG Low Power Mode
|
|
AT91C_BASE_VREG->VREG_MR |= AT91C_VREG_PSTDBY;
|
|
|
|
PMC_DisableProcessorClock();
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Put voltage regulator in normal mode
|
|
/// Return the CPU to normal speed 48MHz, enable PLL, main oscillator
|
|
//------------------------------------------------------------------------------
|
|
static void NormalPowerMode(void)
|
|
{
|
|
// Voltage regulator in normal mode : Disable VREG Low Power Mode
|
|
AT91C_BASE_VREG->VREG_MR &= ~AT91C_VREG_PSTDBY;
|
|
|
|
// MCK=32kHz to MCK=48MHz
|
|
// enable Main Oscillator
|
|
AT91C_BASE_PMC->PMC_MOR = (( (AT91C_CKGR_OSCOUNT & (0x06 <<8)) | AT91C_CKGR_MOSCEN ));
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS ) );
|
|
|
|
// enable PLL@96MHz
|
|
AT91C_BASE_PMC->PMC_PLLR = ((AT91C_CKGR_DIV & 0x0E) |
|
|
(AT91C_CKGR_PLLCOUNT & (28<<8)) |
|
|
(AT91C_CKGR_MUL & (0x48<<16)));
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK ) );
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ;
|
|
// MCK=SLCK/2 : change prescaler first
|
|
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
// MCK=PLLCK/2 : then change source
|
|
AT91C_BASE_PMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK ;
|
|
while( !( AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY ) );
|
|
}
|
|
#else
|
|
//------------------------------------------------------------------------------
|
|
/// Put the CPU in low power mode (for customer)
|
|
//------------------------------------------------------------------------------
|
|
static void LowPowerMode(void)
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Return the CPU to normal speed (for customer)
|
|
//------------------------------------------------------------------------------
|
|
static void NormalPowerMode(void)
|
|
{
|
|
}
|
|
#endif
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Initializes the Mass Storage driver and runs it.
|
|
//------------------------------------------------------------------------------
|
|
int main(void)
|
|
{
|
|
unsigned char sdConnected = 0;
|
|
unsigned char sdInitErrorCnt = 0, sdInitExecDelay = 0;
|
|
|
|
TRACE_CONFIGURE(DBGU_STANDARD, 115200, BOARD_MCK);
|
|
printf("-- USB Device Mass Storage Project %s --\n\r", SOFTPACK_VERSION);
|
|
printf("-- %s\n\r", BOARD_NAME);
|
|
printf("-- Compiled: %s %s --\n\r", __DATE__, __TIME__);
|
|
|
|
// If they are present, configure Vbus & Wake-up pins
|
|
PIO_InitializeInterrupts(0);
|
|
|
|
// If there is on board power, switch it off
|
|
#ifdef PIN_USB_POWER_ENB
|
|
{ const Pin pinUsbPwr = PIN_USB_POWER_ENB;
|
|
PIO_Configure(&pinUsbPwr, 1);
|
|
}
|
|
#endif
|
|
|
|
WAKEUP_CONFIGURE();
|
|
|
|
// Start TC for timing & status update
|
|
ConfigureTc0();
|
|
|
|
MemoryInitialization();
|
|
|
|
ASSERT(numMedias > 0, "Error: No media defined.\n\r");
|
|
TRACE_INFO("%u medias defined\n\r", numMedias);
|
|
|
|
// BOT driver initialization
|
|
MSDDriver_Initialize(luns, numMedias);
|
|
|
|
// connect if needed
|
|
VBUS_CONFIGURE();
|
|
|
|
while (USBD_GetState() < USBD_STATE_CONFIGURED);
|
|
|
|
|
|
// Infinite loop
|
|
updateDelay = UPDATE_DELAY;
|
|
updateView = 0;
|
|
while (1) {
|
|
|
|
#if defined(BOARD_SD_MCI_BASE)
|
|
// SD Card disconnection
|
|
if (MEDSdcard_Detect(&medias[DRV_SDMMC], 0)) {
|
|
if (sdConnected == 0) {
|
|
// Try several times
|
|
if (sdInitExecDelay == 0) {
|
|
sdInitExecDelay = sdInitErrorCnt + 1;
|
|
}
|
|
}
|
|
}
|
|
else if (sdConnected) {
|
|
sdConnected = 0;
|
|
sdInitErrorCnt = 0;
|
|
SDConnectionUpdate(0);
|
|
printf("\n\r** SD removed!\n\r");
|
|
}
|
|
#endif
|
|
|
|
// Mass storage state machine
|
|
if (USBD_GetState() < USBD_STATE_CONFIGURED){}
|
|
else MSDDriver_StateMachine();
|
|
|
|
if( USBState == STATE_SUSPEND ) {
|
|
TRACE_DEBUG("suspend !\n\r");
|
|
LowPowerMode();
|
|
USBState = STATE_IDLE;
|
|
}
|
|
if( USBState == STATE_RESUME ) {
|
|
// Return in normal MODE
|
|
TRACE_DEBUG("resume !\n\r");
|
|
NormalPowerMode();
|
|
USBState = STATE_IDLE;
|
|
}
|
|
|
|
// Update status view
|
|
if (updateView) {
|
|
|
|
updateView = 0;
|
|
#if 0
|
|
if (msdWriteTotal < 50 * 1000)
|
|
MED_Flush(&medias[DRV_NAND]);
|
|
#endif
|
|
|
|
printf("Read %5dK, Write %5dK, IO %5dK; Null %4d, Full %4d\r",
|
|
msdReadTotal/(UPDATE_DELAY*250),
|
|
msdWriteTotal/(UPDATE_DELAY*250),
|
|
(msdReadTotal+msdWriteTotal)/(UPDATE_DELAY*250),
|
|
msdNullCnt, msdFullCnt);
|
|
|
|
msdReadTotal = 0;
|
|
msdWriteTotal = 0;
|
|
msdNullCnt = 0;
|
|
msdFullCnt = 0;
|
|
|
|
#if defined(BOARD_SD_MCI_BASE)
|
|
if (sdInitExecDelay) {
|
|
if (0 == --sdInitExecDelay) {
|
|
sdConnected = SDConnectionUpdate(1);
|
|
if (!sdConnected) {
|
|
if (SD_INIT_RETRY <= sdInitErrorCnt++) {
|
|
printf("\n\r** SD inserted but init fail!\n\r");
|
|
sdConnected = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
}
|
|
|