569 lines
22 KiB
C
569 lines
22 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 CCID project with AT91SAM Microcontrollers"
|
|
///
|
|
/// !!!Purpose
|
|
///
|
|
/// This example demonstrates the CCID (USB Chip/Smart Card Interface Devices) on AT91
|
|
/// microcontrollers.
|
|
///
|
|
/// !!!Requirements
|
|
///
|
|
/// This example can be used on AT91SAM9260-EK, AT91SAM9263-EK, AT91SAM9G20-EK,
|
|
/// AT91SAM9XE-EK.
|
|
///
|
|
/// !!!Description
|
|
///
|
|
/// This application implement a CCID driver.<BR>
|
|
/// Different tests can be done with the Windows(c) software Smart Access(c).<BR>
|
|
/// Smart Access: a powerful scripting tool to write sequences of commands.
|
|
///
|
|
/// !!!Usage
|
|
///
|
|
/// -# Install Smart Access(c) software.
|
|
/// -# 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 data bits
|
|
/// - No parity
|
|
/// - 1 stop bit
|
|
/// - Hardware flow control (RTS/CTS)
|
|
/// -# Start the application. The following traces shall appear on the terminal:
|
|
/// \code
|
|
/// -- USB Device CCID Project xxx --
|
|
/// -- AT91xxxxxx-xx
|
|
/// -- Compiled: xxx xx xxxx xx:xx:xx --
|
|
/// \endcode
|
|
/// -# Connect the USB cable to the board. Traces should start to appear on the terminal.<BR>
|
|
/// If this is the first time the device is connected to the PC,
|
|
/// the operating system may take some time to install it.
|
|
/// -# The device is enumerated as a Smart Card Device implementing CCID class.<BR>
|
|
/// -# The host use the CCID device driver (usbccid.sys) as the functionnal driver.
|
|
/// -# Launch Smart Access and connect it to the Card Reader Atmel.<BR>
|
|
/// Use Smart Access for launch instruction command.<BR>
|
|
/// Note that instruction command case one, two and three are implemanted.
|
|
///
|
|
/// !!!Contents
|
|
///
|
|
/// The definitions and functions provided are dispatched inside a number of
|
|
/// files:
|
|
/// - main.c main software
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
/// \unit
|
|
///
|
|
/// !Purpose
|
|
/// Implementation of the USB CCID.
|
|
///
|
|
/// !Contents
|
|
/// The code can be roughly broken down as follows:
|
|
/// - Configuration functions
|
|
/// - Interrupt handlers
|
|
/// - Utility functions
|
|
/// - The main() function, which implements the program behavior
|
|
/// - Use ICC insertion event() and CCID_SmartCardRequest() CCID functions
|
|
///
|
|
/// Please refer to the list of functions in the #Overview# tab of this unit
|
|
/// for more detailed information.
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Headers
|
|
//------------------------------------------------------------------------------
|
|
|
|
#include <board.h>
|
|
#include <aic/aic.h>
|
|
#include <pio/pio.h>
|
|
#include <pio/pio_it.h>
|
|
#include <utility/trace.h>
|
|
#include <utility/assert.h>
|
|
#include <utility/led.h>
|
|
#include <usb/device/core/USBD.h>
|
|
#include <dbgu/dbgu.h>
|
|
#include <usb/device/ccid/cciddriver.h>
|
|
#include <iso7816/iso7816_4.h>
|
|
#include <pmc/pmc.h>
|
|
|
|
#include <string.h>
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Local Define
|
|
//-----------------------------------------------------------------------------
|
|
/// 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
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Local variables
|
|
//-----------------------------------------------------------------------------
|
|
/// State of USB, for suspend and resume
|
|
unsigned char USBState = STATE_IDLE;
|
|
|
|
/// List of pins that must be configured for use by the application.
|
|
static const Pin pinsISO7816[] = {PINS_ISO7816};
|
|
static const Pin pinIso7816RstMC = PIN_ISO7816_RSTMC;
|
|
|
|
static const Pin pinsPower[] = {
|
|
/* Swlf Power (LDO): low = off */
|
|
{1 << 5, AT91C_BASE_PIOA, AT91C_ID_PIOA, PIO_OUTPUT_0, PIO_DEFAULT},
|
|
/* Phone pass-through power: high = off */
|
|
{1 << 26, AT91C_BASE_PIOA, AT91C_ID_PIOA, PIO_OUTPUT_1, PIO_DEFAULT},
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Optional smartcard detection
|
|
//------------------------------------------------------------------------------
|
|
#ifdef PIN_SMARTCARD_CONNECT
|
|
|
|
/// Smartcard detection pin.
|
|
static const Pin pinSmartCard = PIN_SMARTCARD_CONNECT;
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// PIO interrupt service routine. Checks if the smartcard has been connected
|
|
/// or disconnected.
|
|
//------------------------------------------------------------------------------
|
|
static void ISR_PioSmartCard(const Pin *pPin)
|
|
{
|
|
// Check current level on pin
|
|
if (PIO_Get(&pinSmartCard) == 0) {
|
|
printf("-H- Insert\n\r");
|
|
CCID_Insertion();
|
|
} else {
|
|
printf("-H- Removal\n\r");
|
|
CCID_Removal();
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Configures the smartcard detection pin to trigger an interrupt.
|
|
//------------------------------------------------------------------------------
|
|
static void ConfigureCardDetection(void)
|
|
{
|
|
PIO_Configure(&pinSmartCard, 1);
|
|
PIO_ConfigureIt(&pinSmartCard, ISR_PioSmartCard);
|
|
PIO_EnableIt(&pinSmartCard);
|
|
}
|
|
|
|
#else
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Dummy implementation.
|
|
//------------------------------------------------------------------------------
|
|
static void ConfigureCardDetection(void)
|
|
{
|
|
printf("-I- Smartcard detection not supported.\n\r");
|
|
}
|
|
|
|
#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.
|
|
//------------------------------------------------------------------------------
|
|
static 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("VBUS conn\n\r");
|
|
USBD_Connect();
|
|
}
|
|
else {
|
|
USBD_Disconnect();
|
|
}
|
|
}
|
|
|
|
#else
|
|
#define VBUS_CONFIGURE() USBD_Connect()
|
|
#endif //#if defined(PIN_USB_VBUS)
|
|
|
|
#if defined (CP15_PRESENT)
|
|
//------------------------------------------------------------------------------
|
|
/// Put the CPU in 32kHz, disable PLL, main oscillator
|
|
/// Put voltage regulator in standby mode
|
|
//------------------------------------------------------------------------------
|
|
void LowPowerMode(void)
|
|
{
|
|
PMC_CPUInIdleMode();
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
/// Put voltage regulator in normal mode
|
|
/// Return the CPU to normal speed 48MHz, enable PLL, main oscillator
|
|
//------------------------------------------------------------------------------
|
|
void NormalPowerMode(void)
|
|
{
|
|
}
|
|
|
|
#elif defined(at91sam7a3)
|
|
//------------------------------------------------------------------------------
|
|
/// Put the CPU in 32kHz, disable PLL, main oscillator
|
|
//------------------------------------------------------------------------------
|
|
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
|
|
//------------------------------------------------------------------------------
|
|
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
|
|
//------------------------------------------------------------------------------
|
|
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
|
|
//------------------------------------------------------------------------------
|
|
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
|
|
//------------------------------------------------------------------------------
|
|
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
|
|
//------------------------------------------------------------------------------
|
|
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
|
|
//------------------------------------------------------------------------------
|
|
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
|
|
//------------------------------------------------------------------------------
|
|
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 ) );
|
|
}
|
|
|
|
#endif
|
|
|
|
//------------------------------------------------------------------------------
|
|
// 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;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Exported functions
|
|
//------------------------------------------------------------------------------
|
|
|
|
//------------------------------------------------------------------------------
|
|
/// Initializes the CCID driver and runs it.
|
|
/// \return Unused (ANSI-C compatibility)
|
|
//------------------------------------------------------------------------------
|
|
int main( void )
|
|
{
|
|
// Initialize traces
|
|
TRACE_CONFIGURE(DBGU_STANDARD, 115200, BOARD_MCK);
|
|
printf("-- USB Device CCID 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);
|
|
|
|
// Configure IT on Smart Card
|
|
ConfigureCardDetection();
|
|
|
|
// Configure ISO7816 driver
|
|
PIO_Configure(pinsISO7816, PIO_LISTSIZE(pinsISO7816));
|
|
PIO_Configure(pinsPower, PIO_LISTSIZE(pinsPower));
|
|
|
|
/* power up the card */
|
|
PIO_Set(&pinsPower[0]);
|
|
|
|
ISO7816_Init( pinIso7816RstMC );
|
|
|
|
// USB audio driver initialization
|
|
CCIDDriver_Initialize();
|
|
|
|
// connect if needed
|
|
VBUS_CONFIGURE();
|
|
while (USBD_GetState() < USBD_STATE_CONFIGURED);
|
|
|
|
CCID_Insertion();
|
|
|
|
// Infinite loop
|
|
while (1) {
|
|
|
|
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;
|
|
}
|
|
CCID_SmartCardRequest();
|
|
}
|
|
return 0;
|
|
}
|
|
|