Add FreeRTOS-Plus directory.

This commit is contained in:
Richard Barry 2012-08-11 21:34:11 +00:00
parent 7bd5f21ad5
commit f508a5f653
6798 changed files with 134949 additions and 19 deletions

View file

@ -0,0 +1,679 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "ac97c.h"
#include <board.h>
#include <aic/aic.h>
#include <utility/assert.h>
#include <utility/trace.h>
#include <utility/math.h>
//------------------------------------------------------------------------------
// Local constants
//------------------------------------------------------------------------------
/// Maximum size of one PDC buffer (in bytes).
#define MAX_PDC_COUNTER 65535
//------------------------------------------------------------------------------
// Local types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// AC97 transfer descriptor. Tracks the status and parameters of a transfer
/// on the AC97 bus.
//------------------------------------------------------------------------------
typedef struct _Ac97Transfer {
/// Buffer containing the slots to send.
unsigned char *pBuffer;
/// Total number of samples to send.
volatile unsigned int numSamples;
/// Optional callback function.
Ac97Callback callback;
/// Optional argument to the callback function.
void *pArg;
} Ac97Transfer;
//------------------------------------------------------------------------------
/// AC97 controller driver structure. Monitors the status of transfers on all
/// AC97 channels.
//------------------------------------------------------------------------------
typedef struct _Ac97c {
/// List of transfers occuring on each channel.
Ac97Transfer transfers[5];
} Ac97c;
//------------------------------------------------------------------------------
// Local variables
//------------------------------------------------------------------------------
/// Global AC97 controller instance.
static Ac97c ac97c;
//------------------------------------------------------------------------------
// Local functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Returns the size of one sample (in bytes) on the given channel.
/// \param channel Channel number.
//------------------------------------------------------------------------------
static unsigned char GetSampleSize(unsigned char channel)
{
unsigned int size = 0;
SANITY_CHECK((channel == AC97C_CHANNEL_A)
|| (channel == AC97C_CHANNEL_B)
|| (channel == AC97C_CHANNEL_CODEC));
// Check selected channel
switch (channel) {
case AC97C_CHANNEL_CODEC: return 2;
case AC97C_CHANNEL_A: size = (AT91C_BASE_AC97C->AC97C_CAMR & AT91C_AC97C_SIZE) >> 16; break;
case AC97C_CHANNEL_B: size = (AT91C_BASE_AC97C->AC97C_CBMR & AT91C_AC97C_SIZE) >> 16; break;
}
// Compute size in bytes given SIZE field
if ((size & 2) != 0) {
return 2;
}
else {
return 4;
}
}
//------------------------------------------------------------------------------
/// Interrupt service routine for Codec, is invoked by AC97C_Handler.
//------------------------------------------------------------------------------
static void CodecHandler(void)
{
unsigned int status;
unsigned int data;
Ac97Transfer *pTransfer = &(ac97c.transfers[AC97C_CODEC_TRANSFER]);
// Read CODEC status register
status = AT91C_BASE_AC97C->AC97C_COSR;
status &= AT91C_BASE_AC97C->AC97C_COMR;
// A sample has been transmitted
if (status & AT91C_AC97C_TXRDY) {
pTransfer->numSamples--;
// If there are remaining samples, transmit one
if (pTransfer->numSamples > 0) {
data = *((unsigned int *) pTransfer->pBuffer);
AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_TXRDY);
AT91C_BASE_AC97C->AC97C_COTHR = data;
// Check if transfer is read or write
if ((data & AT91C_AC97C_READ) != 0) {
AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_RXRDY;
}
else {
pTransfer->pBuffer += sizeof(unsigned int);
AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_TXRDY;
}
}
// Transfer finished
else {
AT91C_BASE_AC97C->AC97C_IDR = AT91C_AC97C_COEVT;
AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_TXRDY);
if (pTransfer->callback) {
pTransfer->callback(pTransfer->pArg, 0, 0);
}
}
}
// A sample has been received
if (status & AT91C_AC97C_RXRDY) {
// Store sample
data = AT91C_BASE_AC97C->AC97C_CORHR;
*((unsigned int *) pTransfer->pBuffer) = data;
pTransfer->pBuffer += sizeof(unsigned int);
pTransfer->numSamples--;
// Transfer finished
if (pTransfer->numSamples > 0) {
data = *((unsigned int *) pTransfer->pBuffer);
AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_RXRDY);
AT91C_BASE_AC97C->AC97C_COTHR = data;
// Check if transfer is read or write
if ((data & AT91C_AC97C_READ) != 0) {
AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_RXRDY;
}
else {
pTransfer->pBuffer += sizeof(unsigned int);
AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_TXRDY;
}
}
else {
AT91C_BASE_AC97C->AC97C_IDR = AT91C_AC97C_COEVT;
AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_RXRDY);
if (pTransfer->callback) {
pTransfer->callback(pTransfer->pArg, 0, 0);
}
}
}
}
//------------------------------------------------------------------------------
/// Interrupt service routine for channel A, is invoked by AC97C_Handler.
//------------------------------------------------------------------------------
static void ChannelAHandler(void)
{
unsigned int status;
Ac97Transfer *pTransmit = &(ac97c.transfers[AC97C_CHANNEL_A_TRANSMIT]);
Ac97Transfer *pReceive = &(ac97c.transfers[AC97C_CHANNEL_A_RECEIVE]);
// Read channel A status register
status = AT91C_BASE_AC97C->AC97C_CASR;
// A buffer has been transmitted
if ((status & AT91C_AC97C_ENDTX) != 0) {
// Update transfer information
if (pTransmit->numSamples > MAX_PDC_COUNTER) {
pTransmit->numSamples -= MAX_PDC_COUNTER;
}
else {
pTransmit->numSamples = 0;
}
// Transmit new buffers if necessary
if (pTransmit->numSamples > MAX_PDC_COUNTER) {
// Fill next PDC
AT91C_BASE_AC97C->AC97C_TNPR = (unsigned int) pTransmit->pBuffer;
if (pTransmit->numSamples > 2 * MAX_PDC_COUNTER) {
AT91C_BASE_AC97C->AC97C_TNCR = MAX_PDC_COUNTER;
pTransmit->pBuffer += MAX_PDC_COUNTER * GetSampleSize(AC97C_CHANNEL_A);
}
else {
AT91C_BASE_AC97C->AC97C_TNCR = pTransmit->numSamples - MAX_PDC_COUNTER;
}
}
// Only one buffer remaining
else {
AT91C_BASE_AC97C->AC97C_CAMR &= ~AT91C_AC97C_ENDTX;
AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_TXBUFE;
}
}
// Transmit completed
if ((status & AT91C_AC97C_TXBUFE) != 0) {
pTransmit->numSamples = 0;
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS;
AT91C_BASE_AC97C->AC97C_CAMR &= ~AT91C_AC97C_TXBUFE;
if (pTransmit->callback) {
pTransmit->callback(pTransmit->pArg, 0, 0);
}
}
// A buffer has been received
if (status & AT91C_AC97C_ENDRX) {
if (pReceive->numSamples > MAX_PDC_COUNTER) {
pReceive->numSamples -= MAX_PDC_COUNTER;
}
else {
pReceive->numSamples = 0;
}
// Transfer remaining samples
if (pReceive->numSamples > MAX_PDC_COUNTER) {
AT91C_BASE_AC97C->AC97C_RNPR = (unsigned int) pReceive->pBuffer;
if (pReceive->numSamples > 2 * MAX_PDC_COUNTER) {
AT91C_BASE_AC97C->AC97C_RNCR = MAX_PDC_COUNTER;
pReceive->pBuffer += MAX_PDC_COUNTER * GetSampleSize(AC97C_CHANNEL_A);
}
else {
AT91C_BASE_AC97C->AC97C_RNCR = pReceive->numSamples - MAX_PDC_COUNTER;
}
}
// Only one buffer remaining
else {
AT91C_BASE_AC97C->AC97C_CAMR &= ~(AT91C_AC97C_ENDRX);
AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_RXBUFF;
}
}
// Receive complete
if ((status & AT91C_AC97C_RXBUFF) != 0) {
pReceive->numSamples = 0;
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTDIS;
AT91C_BASE_AC97C->AC97C_CAMR &= ~AT91C_AC97C_RXBUFF;
if (pReceive->callback) {
pReceive->callback(pReceive->pArg, 0, 0);
}
}
}
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// This handler function must be called by the AC97C interrupt service routine.
/// Identifies which event was activated and calls the associated function.
//------------------------------------------------------------------------------
void AC97C_Handler(void)
{
unsigned int status;
// Get the real interrupt source
status = AT91C_BASE_AC97C->AC97C_SR;
status &= AT91C_BASE_AC97C->AC97C_IMR;
// Check if an event on the codec channel is active
if ((status & AT91C_AC97C_COEVT) != 0) {
CodecHandler();
}
// Check if an event on channel A is active
if ((status & AT91C_AC97C_CAEVT) != 0) {
ChannelAHandler();
}
}
//------------------------------------------------------------------------------
/// Starts a read or write transfer on the given channel
/// \param channel particular channel (AC97C_CHANNEL_A or AC97C_CHANNEL_B).
/// \param pBuffer buffer containing the slots to send.
/// \param numSamples total number of samples to send.
/// \param callback optional callback function.
/// \param pArg optional argument to the callback function.
//------------------------------------------------------------------------------
unsigned char AC97C_Transfer(
unsigned char channel,
unsigned char *pBuffer,
unsigned int numSamples,
Ac97Callback callback,
void *pArg)
{
unsigned int size;
unsigned int data;
Ac97Transfer *pTransfer;
SANITY_CHECK(channel <= 5);
SANITY_CHECK(pBuffer);
SANITY_CHECK(numSamples > 0);
// Check that no transfer is pending on the channel
pTransfer = &(ac97c.transfers[channel]);
if (pTransfer->numSamples > 0) {
trace_LOG(trace_WARNING, "-W- AC97C_Transfer: Channel %d is busy\n\r", channel);
return AC97C_ERROR_BUSY;
}
// Fill transfer information
pTransfer->pBuffer = pBuffer;
pTransfer->numSamples = numSamples;
pTransfer->callback = callback;
pTransfer->pArg = pArg;
// Transmit or receive over codec channel
if (channel == AC97C_CODEC_TRANSFER) {
// Send command
data = *((unsigned int *) pTransfer->pBuffer);
AT91C_BASE_AC97C->AC97C_COTHR = data;
// Check if transfer is read or write
if ((data & AT91C_AC97C_READ) != 0) {
AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_RXRDY;
}
else {
pTransfer->pBuffer += sizeof(unsigned int);
AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_TXRDY;
}
// Enable interrupts
AT91C_BASE_AC97C->AC97C_IER |= AT91C_AC97C_COEVT;
}
// Transmit over channel A
else if (channel == AC97C_CHANNEL_A_TRANSMIT) {
// Disable PDC
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS;
// Fill PDC buffers
size = min(pTransfer->numSamples, MAX_PDC_COUNTER);
AT91C_BASE_AC97C->AC97C_TPR = (unsigned int) pTransfer->pBuffer;
AT91C_BASE_AC97C->AC97C_TCR = size;
pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
size = min(pTransfer->numSamples - size, MAX_PDC_COUNTER);
if (size > 0) {
AT91C_BASE_AC97C->AC97C_TNPR = (unsigned int) pTransfer->pBuffer;
AT91C_BASE_AC97C->AC97C_TNCR = size;
pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
}
// Enable interrupts
AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_PDCEN | AT91C_AC97C_ENDTX;
AT91C_BASE_AC97C->AC97C_IER |= AT91C_AC97C_CAEVT;
// Start transfer
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTEN;
}
// Receive over channel A
else if (channel == AC97C_CHANNEL_A_RECEIVE) {
// Disable PDC
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTDIS;
// Fill PDC buffers
size = min(pTransfer->numSamples, MAX_PDC_COUNTER);
AT91C_BASE_AC97C->AC97C_RPR = (unsigned int) pTransfer->pBuffer;
AT91C_BASE_AC97C->AC97C_RCR = size;
pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
size = min(pTransfer->numSamples - size, MAX_PDC_COUNTER);
if (size > 0) {
AT91C_BASE_AC97C->AC97C_RNPR = (unsigned int) pTransfer->pBuffer;
AT91C_BASE_AC97C->AC97C_RNCR = size;
pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
}
// Enable interrupts
AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_PDCEN | AT91C_AC97C_ENDRX;
AT91C_BASE_AC97C->AC97C_IER |= AT91C_AC97C_CAEVT;
// Start transfer
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTEN;
}
return 0;
}
//------------------------------------------------------------------------------
/// Stop read or write transfer on the given channel.
/// \param channel Channel number.
//------------------------------------------------------------------------------
void AC97C_CancelTransfer(unsigned char channel)
{
unsigned int size = 0;
Ac97Transfer *pTransfer;
SANITY_CHECK(channel <= AC97C_CHANNEL_B_TRANSMIT);
// Save remaining size
pTransfer = &(ac97c.transfers[channel]);
size = pTransfer->numSamples;
pTransfer->numSamples = 0;
// Stop PDC
if (channel == AC97C_CHANNEL_A_TRANSMIT) {
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS;
size -= min(size, MAX_PDC_COUNTER) - AT91C_BASE_AC97C->AC97C_TCR;
}
if (channel == AC97C_CHANNEL_A_RECEIVE) {
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTDIS;
size -= min(size, MAX_PDC_COUNTER) - AT91C_BASE_AC97C->AC97C_RCR;
}
// Invoke callback if provided
if (pTransfer->callback) {
pTransfer->callback(pTransfer->pArg, AC97C_ERROR_STOPPED, size);
}
}
//------------------------------------------------------------------------------
/// Initializes the AC97 controller.
//------------------------------------------------------------------------------
void AC97C_Configure(void)
{
unsigned char channel;
// Enable the AC97 controller peripheral clock
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_AC97C);
// Enable the peripheral and variable rate adjustment
AT91C_BASE_AC97C->AC97C_MR = AT91C_AC97C_ENA | AT91C_AC97C_VRA;
// Unassigns all input & output slots
AC97C_AssignInputSlots(0, 0xFFFF);
AC97C_AssignOutputSlots(0, 0xFFFF);
// Install the AC97C interrupt handler
AT91C_BASE_AC97C->AC97C_IDR = 0xFFFFFFFF;
AIC_ConfigureIT(AT91C_ID_AC97C, 0, AC97C_Handler);
AIC_EnableIT(AT91C_ID_AC97C);
// Disable PDC transfers
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS;
// Clear channel transfers
for (channel = 0; channel < AC97C_CHANNEL_B_TRANSMIT; channel++) {
ac97c.transfers[channel].numSamples = 0;
}
}
//------------------------------------------------------------------------------
/// Configures the desired channel with the given value.
/// \param channel Channel number.
/// \param cfg Configuration value.
//------------------------------------------------------------------------------
void AC97C_ConfigureChannel(unsigned char channel, unsigned int cfg)
{
SANITY_CHECK((channel == AC97C_CHANNEL_A) || (channel == AC97C_CHANNEL_B));
if (channel == AC97C_CHANNEL_A) {
AT91C_BASE_AC97C->AC97C_CAMR = cfg;
}
else {
AT91C_BASE_AC97C->AC97C_CBMR = cfg;
}
}
//------------------------------------------------------------------------------
/// Assigns the desired input slots to a particular channel.
/// \param channel Channel number (or 0 to unassign slots).
/// \param slots Bitfield value of slots to assign.
//------------------------------------------------------------------------------
void AC97C_AssignInputSlots(unsigned char channel, unsigned int slots)
{
unsigned int value;
unsigned int i;
SANITY_CHECK(channel <= AC97C_CHANNEL_B);
// Assign all slots
slots >>= 3;
for (i = 3; i < 15; i++) {
// Check if slots is selected
if (slots & 1) {
value = AT91C_BASE_AC97C->AC97C_ICA;
value &= ~(0x07 << ((i - 3) * 3));
value |= channel << ((i - 3) * 3);
AT91C_BASE_AC97C->AC97C_ICA = value;
}
slots >>= 1;
}
}
//------------------------------------------------------------------------------
/// Assigns the desired output slots to a particular channel.
/// \param channel Channel number (or 0 to unassign slots).
/// \param slots Bitfield value of slots to assign.
//------------------------------------------------------------------------------
void AC97C_AssignOutputSlots(unsigned char channel, unsigned int slots)
{
unsigned int value;
unsigned int i;
SANITY_CHECK(channel <= AC97C_CHANNEL_B);
// Assign all slots
slots >>= 3;
for (i = 3; i < 15; i++) {
// Check if slots is selected
if (slots & 1) {
value = AT91C_BASE_AC97C->AC97C_OCA;
value &= ~(0x07 << ((i - 3) * 3));
value |= channel << ((i - 3) * 3);
AT91C_BASE_AC97C->AC97C_OCA = value;
}
slots >>= 1;
}
}
//------------------------------------------------------------------------------
/// Returns 1 if no transfer is currently pending on the given channel;
/// otherwise, returns 0.
/// \param channel Channel number.
//------------------------------------------------------------------------------
unsigned char AC97C_IsFinished(unsigned char channel)
{
SANITY_CHECK(channel <= AC97C_CHANNEL_B_TRANSMIT);
if (ac97c.transfers[channel].numSamples > 0) {
return 0;
}
else {
return 1;
}
}
//------------------------------------------------------------------------------
/// Convenience function for synchronously sending commands to the codec.
/// \param address Register address.
/// \param data Command data.
//------------------------------------------------------------------------------
void AC97C_WriteCodec(unsigned char address, unsigned short data)
{
unsigned int sample;
sample = (address << 16) | data;
AC97C_Transfer(AC97C_CODEC_TRANSFER, (unsigned char *) &sample, 1, 0, 0);
while (!AC97C_IsFinished(AC97C_CODEC_TRANSFER));
}
//------------------------------------------------------------------------------
/// Convenience function for receiving data from the AC97 codec.
/// \param address Register address.
//------------------------------------------------------------------------------
unsigned short AC97C_ReadCodec(unsigned char address)
{
unsigned int sample;
sample = AT91C_AC97C_READ | (address << 16);
AC97C_Transfer(AC97C_CODEC_TRANSFER, (unsigned char *) &sample, 1, 0, 0);
while (!AC97C_IsFinished(AC97C_CODEC_TRANSFER));
return sample;
}
//------------------------------------------------------------------------------
/// Sets the size in bits of one sample on the given channel.
/// \param channel Channel number.
/// \param size Size of one sample in bits (10, 16, 18 or 24).
//------------------------------------------------------------------------------
void AC97C_SetChannelSize(unsigned char channel, unsigned char size)
{
unsigned int bits = 0;
SANITY_CHECK((size == 10) || (size == 16) || (size == 18) || (size == 24));
SANITY_CHECK((channel == AC97C_CHANNEL_A) || (channel == AC97C_CHANNEL_B));
switch (size) {
case 10 : bits = AT91C_AC97C_SIZE_10_BITS; break;
case 16 : bits = AT91C_AC97C_SIZE_16_BITS; break;
case 18 : bits = AT91C_AC97C_SIZE_18_BITS; break;
case 20 : bits = AT91C_AC97C_SIZE_20_BITS; break;
}
if (channel == AC97C_CHANNEL_A) {
AT91C_BASE_AC97C->AC97C_CAMR &= ~(AT91C_AC97C_SIZE);
AT91C_BASE_AC97C->AC97C_CAMR |= bits;
}
else {
AT91C_BASE_AC97C->AC97C_CBMR &= ~(AT91C_AC97C_SIZE);
AT91C_BASE_AC97C->AC97C_CBMR |= bits;
}
}

View file

@ -0,0 +1,100 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef AC97C_H
#define AC97C_H
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
/// The channel is already busy with a transfer.
#define AC97C_ERROR_BUSY 1
/// The transfer has been stopped by the user.
#define AC97C_ERROR_STOPPED 2
/// Codec channel index.
#define AC97C_CHANNEL_CODEC 0
/// Channel A index.
#define AC97C_CHANNEL_A 1
/// Channel B index.
#define AC97C_CHANNEL_B 2
/// Codec transmit/receive transfer index.
#define AC97C_CODEC_TRANSFER 0
/// Channel A receive transfer index.
#define AC97C_CHANNEL_A_RECEIVE 1
/// Channel A transmit transfer index.
#define AC97C_CHANNEL_A_TRANSMIT 2
/// Channel B receive transfer index.
#define AC97C_CHANNEL_B_RECEIVE 3
/// Channel B transmit transfer index.
#define AC97C_CHANNEL_B_TRANSMIT 4
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
/// AC97C transfer callback function.
typedef void (*Ac97Callback)(void *pArg,
unsigned char status,
unsigned int remaining);
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void AC97C_Configure();
extern void AC97C_ConfigureChannel(unsigned char channel, unsigned int cfg);
extern void AC97C_AssignInputSlots(unsigned char channel, unsigned int slots);
extern void AC97C_AssignOutputSlots(unsigned char channel, unsigned int slots);
extern unsigned char AC97C_Transfer(
unsigned char channel,
unsigned char *pBuffer,
unsigned int numSamples,
Ac97Callback callback,
void *pArg);
extern unsigned char AC97C_IsFinished(unsigned char channel);
extern void AC97C_WriteCodec(unsigned char address, unsigned short data);
extern unsigned short AC97C_ReadCodec(unsigned char address);
extern void AC97C_SetChannelSize(unsigned char channel, unsigned char size);
extern void AC97C_CancelTransfer(unsigned char channel);
#endif //#ifndef AC97C_H

View file

@ -0,0 +1,196 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef trace_LEVEL
#define trace_LEVEL 1
#endif
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "aes.h"
#include <board.h>
#include <utility/trace.h>
#include <utility/assert.h>
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures the AES peripheral to encrypt/decrypt, start mode (manual, auto,
/// PDC) and operating mode (ECB, CBC, OFB, CFB, CTR).
/// \param cipher Indicates if the peripheral should encrypt or decrypt data.
/// \param smode Start mode.
/// \param opmode Operating mode.
//------------------------------------------------------------------------------
void AES_Configure(
unsigned char cipher,
unsigned int smode,
unsigned int opmode)
{
trace_LOG(trace_DEBUG, "-D- AES_Configure()\n\r");
SANITY_CHECK((cipher & 0xFFFFFFFE) == 0);
SANITY_CHECK((smode & 0xFFFFFCFF) == 0);
SANITY_CHECK((opmode & 0xFFFF8FFF) == 0);
// Reset the peripheral first
AT91C_BASE_AES->AES_CR = AT91C_AES_SWRST;
// Configure mode register
AT91C_BASE_AES->AES_MR = cipher | smode | opmode;
}
//------------------------------------------------------------------------------
/// Sets the key used by the AES algorithm to cipher the plain text or
/// decipher the encrypted text.
/// \param pKey Pointer to a 16-bytes cipher key.
//------------------------------------------------------------------------------
void AES_SetKey(const unsigned int *pKey)
{
trace_LOG(trace_DEBUG, "-D- AES_SetKey()\n\r");
SANITY_CHECK(pKey);
AT91C_BASE_AES->AES_KEYWxR[0] = pKey[0];
AT91C_BASE_AES->AES_KEYWxR[1] = pKey[1];
AT91C_BASE_AES->AES_KEYWxR[2] = pKey[2];
AT91C_BASE_AES->AES_KEYWxR[3] = pKey[3];
}
//------------------------------------------------------------------------------
/// Sets the initialization vector that is used to encrypt the plain text or
/// decrypt the cipher text in chained block modes (CBC, CFB, OFB & CTR).
/// \param pVector Pointer to a 16-bytes initialization vector.
//------------------------------------------------------------------------------
void AES_SetVector(const unsigned int *pVector)
{
trace_LOG(trace_DEBUG, "-D- AES_SetVector()\n\r");
SANITY_CHECK(pVector);
AT91C_BASE_AES->AES_IVxR[0] = pVector[0];
AT91C_BASE_AES->AES_IVxR[1] = pVector[1];
AT91C_BASE_AES->AES_IVxR[2] = pVector[2];
AT91C_BASE_AES->AES_IVxR[3] = pVector[3];
}
//------------------------------------------------------------------------------
/// Sets the input data of the AES algorithm (i.e. plain text in cipher mode,
/// ciphered text in decipher mode). If auto mode is active, the encryption is
/// started automatically after writing the last word.
/// \param pData Pointer to the 16-bytes data to cipher/decipher.
//------------------------------------------------------------------------------
void AES_SetInputData(const unsigned int *pData)
{
trace_LOG(trace_DEBUG, "-D- AES_SetInputData()\n\r");
SANITY_CHECK(pData);
AT91C_BASE_AES->AES_IDATAxR[0] = pData[0];
AT91C_BASE_AES->AES_IDATAxR[1] = pData[1];
AT91C_BASE_AES->AES_IDATAxR[2] = pData[2];
AT91C_BASE_AES->AES_IDATAxR[3] = pData[3];
}
//------------------------------------------------------------------------------
/// Stores the result of the last AES operation (encrypt/decrypt) in the
/// provided buffer.
/// \param pData Pointer to a 16-bytes buffer.
//------------------------------------------------------------------------------
void AES_GetOutputData(unsigned int *pData)
{
trace_LOG(trace_DEBUG, "-D- AES_GetOutputData()\n\r");
SANITY_CHECK(pData);
pData[0] = AT91C_BASE_AES->AES_ODATAxR[0];
pData[1] = AT91C_BASE_AES->AES_ODATAxR[1];
pData[2] = AT91C_BASE_AES->AES_ODATAxR[2];
pData[3] = AT91C_BASE_AES->AES_ODATAxR[3];
}
//------------------------------------------------------------------------------
/// Sets the input buffer to use when in PDC mode.
/// \param pInput Pointer to the input buffer.
//------------------------------------------------------------------------------
void AES_SetInputBuffer(const unsigned int *pInput)
{
trace_LOG(trace_DEBUG, "-D- AES_SetInputBuffer()\n\r");
SANITY_CHECK(pInput);
AT91C_BASE_AES->AES_TPR = (unsigned int) pInput;
AT91C_BASE_AES->AES_TCR = 4;
}
//------------------------------------------------------------------------------
/// Sets the output buffer to use when in PDC mode.
/// \param pOutput Pointer to the output buffer.
//------------------------------------------------------------------------------
void AES_SetOutputBuffer(unsigned int *pOutput)
{
trace_LOG(trace_DEBUG, "-D- AES_SetOutputBuffer()\n\r");
SANITY_CHECK(pOutput);
AT91C_BASE_AES->AES_RPR = (unsigned int) pOutput;
AT91C_BASE_AES->AES_RCR = 4;
}
//------------------------------------------------------------------------------
/// Starts the encryption/decryption process when in manual or PDC mode. In
/// manual mode, the key and input data must have been entered using
/// AES_SetKey() and AES_SetInputData(). In PDC mode, the key, input & output
/// buffer must have been set using AES_SetKey(), AES_SetInputBuffer() and
/// AES_SetOutputBuffer().
//------------------------------------------------------------------------------
void AES_Start(void)
{
trace_LOG(trace_DEBUG, "AES_Start()\n\r");
SANITY_CHECK(((AT91C_BASE_AES->AES_MR & AT91C_AES_SMOD) == AT91C_AES_SMOD_MANUAL)
|| ((AT91C_BASE_AES->AES_MR & AT91C_AES_SMOD) == AT91C_AES_SMOD_PDC));
// Manual mode
if ((AT91C_BASE_AES->AES_MR & AT91C_AES_SMOD) == AT91C_AES_SMOD_MANUAL) {
AT91C_BASE_AES->AES_CR = AT91C_AES_START;
}
// PDC
else {
AT91C_BASE_AES->AES_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
}
}
//------------------------------------------------------------------------------
/// Returns the current value of the AES interrupt status register.
//------------------------------------------------------------------------------
unsigned int AES_GetStatus(void)
{
trace_LOG(trace_DEBUG, "-D- AES_GetStatus()\n\r");
return AT91C_BASE_AES->AES_ISR;
}

View file

@ -0,0 +1,59 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef AES_H
#define AES_H
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void AES_Configure(
unsigned char cipher,
unsigned int smode,
unsigned int opmode);
extern void AES_SetKey(const unsigned int *pKey);
extern void AES_SetVector(const unsigned int *pVector);
extern void AES_SetInputData(const unsigned int *pData);
extern void AES_GetOutputData(unsigned int *pData);
extern void AES_SetInputBuffer(const unsigned int *pInput);
extern void AES_SetOutputBuffer(unsigned int *pOutput);
extern void AES_Start(void);
extern unsigned int AES_GetStatus(void);
#endif //#ifndef AES_H

View file

@ -0,0 +1,80 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "aic.h"
#include <board.h>
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures the interrupt associated with the given source, using the
/// specified mode and interrupt handler.
/// \param source Interrupt source to configure.
/// \param mode Triggering mode of the interrupt.
/// \param handler Interrupt handler function.
//------------------------------------------------------------------------------
void AIC_ConfigureIT(unsigned int source,
unsigned int mode,
void (*handler)( void ))
{
// Disable the interrupt first
AT91C_BASE_AIC->AIC_IDCR = 1 << source;
// Configure mode and handler
AT91C_BASE_AIC->AIC_SMR[source] = mode;
AT91C_BASE_AIC->AIC_SVR[source] = (unsigned int) handler;
// Clear interrupt
AT91C_BASE_AIC->AIC_ICCR = 1 << source;
}
//------------------------------------------------------------------------------
/// Enables interrupts coming from the given (unique) source.
/// \param source Interrupt source to enable.
//------------------------------------------------------------------------------
void AIC_EnableIT(unsigned int source)
{
AT91C_BASE_AIC->AIC_IECR = 1 << source;
}
//------------------------------------------------------------------------------
/// Disables interrupts coming from the given (unique) source.
/// \param source Interrupt source to enable.
//------------------------------------------------------------------------------
void AIC_DisableIT(unsigned int source)
{
AT91C_BASE_AIC->AIC_IDCR = 1 << source;
}

View file

@ -0,0 +1,74 @@
/* ----------------------------------------------------------------------------
* 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
/// !Purpose
///
/// Methods and definitions for configuring interrupts using the Advanced
/// Interrupt Controller (AIC).
///
/// !Usage
/// -# Configure an interrupt source using AIC_ConfigureIT
/// -# Enable or disable interrupt generation of a particular source with
/// AIC_EnableIT and AIC_DisableIT.
//------------------------------------------------------------------------------
#ifndef AIC_H
#define AIC_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
#ifndef AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL
/// Redefinition of missing constant.
#define AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE
#endif
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void AIC_ConfigureIT(unsigned int source,
unsigned int mode,
void (*handler)( void ));
extern void AIC_EnableIT(unsigned int source);
extern void AIC_DisableIT(unsigned int source);
#endif //#ifndef AIC_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,113 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef _CAN_H
#define _CAN_H
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
#define AT91C_CAN_TIMEOUT 100000
#define AT91C_TEST_NOK 0
#define AT91C_TEST_OK 1
#define CAN_STATUS_SUCCESS 0
#define CAN_STATUS_LOCKED 1
#define CAN_STATUS_ABORTED 2
#define CAN_STATUS_RESET 3
#if defined (AT91C_BASE_CAN)
#define AT91C_BASE_CAN0 AT91C_BASE_CAN
#endif
#if defined (AT91C_ID_CAN)
#define AT91C_ID_CAN0 AT91C_ID_CAN
#endif
#if defined (AT91C_BASE_CAN_MB0)
#define AT91C_BASE_CAN0_MB0 AT91C_BASE_CAN_MB0
#define AT91C_BASE_CAN0_MB1 AT91C_BASE_CAN_MB1
#define AT91C_BASE_CAN0_MB2 AT91C_BASE_CAN_MB2
#define AT91C_BASE_CAN0_MB3 AT91C_BASE_CAN_MB3
#define AT91C_BASE_CAN0_MB4 AT91C_BASE_CAN_MB4
#define AT91C_BASE_CAN0_MB5 AT91C_BASE_CAN_MB5
#define AT91C_BASE_CAN0_MB6 AT91C_BASE_CAN_MB6
#define AT91C_BASE_CAN0_MB7 AT91C_BASE_CAN_MB7
#endif
#if defined (AT91C_BASE_CAN_MB8)
#define AT91C_BASE_CAN0_MB8 AT91C_BASE_CAN_MB8
#define AT91C_BASE_CAN0_MB9 AT91C_BASE_CAN_MB9
#define AT91C_BASE_CAN0_MB10 AT91C_BASE_CAN_MB10
#define AT91C_BASE_CAN0_MB11 AT91C_BASE_CAN_MB11
#define AT91C_BASE_CAN0_MB12 AT91C_BASE_CAN_MB12
#define AT91C_BASE_CAN0_MB13 AT91C_BASE_CAN_MB13
#define AT91C_BASE_CAN0_MB14 AT91C_BASE_CAN_MB14
#define AT91C_BASE_CAN0_MB15 AT91C_BASE_CAN_MB15
#endif
#define NUM_MAILBOX_MAX 16
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
typedef struct
{
volatile unsigned char state;
volatile unsigned char can_number;
volatile unsigned char mailbox_number;
volatile unsigned char test_can;
volatile unsigned int mode_reg;
volatile unsigned int acceptance_mask_reg;
volatile unsigned int identifier;
volatile unsigned int data_low_reg;
volatile unsigned int data_high_reg;
volatile unsigned int control_reg;
volatile unsigned int mailbox_in_use;
volatile int size;
} CanTransfer;
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern unsigned char CAN_Init( unsigned int baudrate,
CanTransfer *canTransferRead,
CanTransfer *canTransferWrite );
extern void CAN_BasicTestSuite(void);
extern void CAN_disable( void );
extern void CAN_ResetAllMailbox( void );
extern void CAN_ResetTransfer( CanTransfer *pTransfer );
extern void CAN_InitMailboxRegisters( CanTransfer *pTransfer );
extern unsigned char CAN_IsInIdle( CanTransfer *pTransfer );
extern unsigned char CAN_Write( CanTransfer *pTransfer );
extern unsigned char CAN_Read( CanTransfer *pTransfer );
extern void CAN_BasicTestSuiteWithoutInterrupt( void );
extern unsigned char CAN_IsInIdle( CanTransfer *pTransfer );
#endif // _CAN_H

View file

@ -0,0 +1,156 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "dbgu.h"
#include <stdarg.h>
#include <board.h>
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Initializes the DBGU with the given parameters, and enables both the
/// transmitter and the receiver.
/// \param mode Operating mode to configure (see <Modes>).
/// \param baudrate Desired baudrate.
/// \param mck Frequency of the system master clock.
//------------------------------------------------------------------------------
void DBGU_Configure(unsigned int mode,
unsigned int baudrate,
unsigned int mck)
{
// Reset & disable receiver and transmitter, disable interrupts
AT91C_BASE_DBGU->DBGU_CR = AT91C_US_RSTRX | AT91C_US_RSTTX;
AT91C_BASE_DBGU->DBGU_IDR = 0xFFFFFFFF;
// Configure baud rate
AT91C_BASE_DBGU->DBGU_BRGR = mck / (baudrate * 16);
// Configure mode register
AT91C_BASE_DBGU->DBGU_MR = mode;
// Disable DMA channel
AT91C_BASE_DBGU->DBGU_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
// Enable receiver and transmitter
AT91C_BASE_DBGU->DBGU_CR = AT91C_US_RXEN | AT91C_US_TXEN;
}
//------------------------------------------------------------------------------
/// Outputs a character on the DBGU line.
/// \param c Character to send.
//------------------------------------------------------------------------------
static void DBGU_PutChar(unsigned char c)
{
// Wait for the transmitter to be ready
while ((AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXEMPTY) == 0);
// Send character
AT91C_BASE_DBGU->DBGU_THR = c;
// Wait for the transfer to complete
while ((AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXEMPTY) == 0);
}
//------------------------------------------------------------------------------
/// Reads and returns a character from the DBGU.
//------------------------------------------------------------------------------
unsigned char DBGU_GetChar()
{
while ((AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_RXRDY) == 0);
return AT91C_BASE_DBGU->DBGU_RHR;
}
#ifndef NOFPUT
#include <stdio.h>
//------------------------------------------------------------------------------
/// Implementation of fputc using the DBGU as the standard output. Required
/// for printf().
/// Returns the character written if successful, or -1 if the output stream is
/// not stdout or stderr.
/// \param c Character to write.
/// \param pStream Output stream.
//------------------------------------------------------------------------------
signed int fputc(signed int c, FILE *pStream)
{
if ((pStream == stdout) || (pStream == stderr)) {
DBGU_PutChar(c);
return c;
}
else {
return EOF;
}
}
//------------------------------------------------------------------------------
/// Implementation of fputs using the DBGU as the standard output. Required
/// for printf(). Does NOT currently use the PDC.
/// Returns the number of characters written if successful, or -1 if the output
/// stream is not stdout or stderr.
/// \param pStr String to write.
/// \param pStream Output stream.
//------------------------------------------------------------------------------
signed int fputs(const char *pStr, FILE *pStream)
{
signed int num = 0;
while (*pStr != 0) {
if (fputc(*pStr, pStream) == -1) {
return -1;
}
num++;
pStr++;
}
return num;
}
#undef putchar
//------------------------------------------------------------------------------
/// Outputs a character on the DBGU. Returns the character itself.
/// \param c Character to output.
//------------------------------------------------------------------------------
signed int putchar(signed int c)
{
return fputc(c, stdout);
}
#endif //#ifndef NOFPUT

View file

@ -0,0 +1,72 @@
/* ----------------------------------------------------------------------------
* 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
/// !Purpose
///
/// This module provides definitions and functions for using the DBGU.
///
/// !Usage
///
/// -# Enable the DBGU pins (see pio.h).
/// -# Configure the DBGU using DBGU_Configure.
///
/// \note Unless specified, all the functions defined here operate synchronously;
/// i.e. they all wait the data is sent/received before returning.
//------------------------------------------------------------------------------
#ifndef DBGU_H
#define DBGU_H
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page Modes
/// This page lists several common operating modes for the DBGU.
/// !Modes
/// - DBGU_STANDARD
/// Standard operating mode (asynchronous, 8bit, no parity)
#define DBGU_STANDARD AT91C_US_PAR_NONE
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void DBGU_Configure(unsigned int mode,
unsigned int baudrate,
unsigned int mck);
extern unsigned char DBGU_GetChar();
#endif //#ifndef DBGU_H

View file

@ -0,0 +1,228 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef trace_LEVEL
#define trace_LEVEL trace_INFO
#endif
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "eefc.h"
#ifdef BOARD_FLASH_EEFC
#include <utility/assert.h>
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Enables the flash ready interrupt source on the EEFC peripheral.
//------------------------------------------------------------------------------
void EFC_EnableFrdyIt(void)
{
AT91C_BASE_EFC->EFC_FMR |= AT91C_EFC_FRDY;
}
//------------------------------------------------------------------------------
/// Disables the flash ready interrupt source on the EEFC peripheral.
//------------------------------------------------------------------------------
void EFC_DisableFrdyIt(void)
{
AT91C_BASE_EFC->EFC_FMR &= ~AT91C_EFC_FRDY;
}
//------------------------------------------------------------------------------
/// Translates the given address page and offset values. The resulting
/// values are stored in the provided variables if they are not null.
/// \param address Address to translate.
/// \param pPage First page accessed.
/// \param pOffset Byte offset in first page.
//------------------------------------------------------------------------------
void EFC_TranslateAddress(
unsigned int address,
unsigned short *pPage,
unsigned short *pOffset)
{
unsigned short page;
unsigned short offset;
SANITY_CHECK(address >= AT91C_IFLASH);
SANITY_CHECK(address <= (AT91C_IFLASH + AT91C_IFLASH_SIZE));
// Calculate page & offset
page = (address - AT91C_IFLASH) / AT91C_IFLASH_PAGE_SIZE;
offset = (address - AT91C_IFLASH) % AT91C_IFLASH_PAGE_SIZE;
trace_LOG(trace_DEBUG,
"-D- Translated 0x%08X to page=%d and offset=%d\n\r",
address, page, offset);
// Store values
if (pPage) {
*pPage = page;
}
if (pOffset) {
*pOffset = offset;
}
}
//------------------------------------------------------------------------------
/// Computes the address of a flash access given the page and offset.
/// \param page Page number.
/// \param offset Byte offset inside page.
/// \param pAddress Computed address (optional).
//------------------------------------------------------------------------------
void EFC_ComputeAddress(
unsigned short page,
unsigned short offset,
unsigned int *pAddress)
{
unsigned int address;
SANITY_CHECK(page <= AT91C_IFLASH_NB_OF_PAGES);
SANITY_CHECK(offset < AT91C_IFLASH_PAGE_SIZE);
// Compute address
address = AT91C_IFLASH + page * AT91C_IFLASH_PAGE_SIZE + offset;
// Store result
if (pAddress) {
*pAddress = address;
}
}
//------------------------------------------------------------------------------
/// Starts the executing the given command on the EEFC. This function returns
/// as soon as the command is started. It does NOT set the FMCN field automatically.
/// \param command Command to execute.
/// \param argument Command argument (should be 0 if not used).
//------------------------------------------------------------------------------
void EFC_StartCommand(unsigned char command, unsigned short argument)
{
// Check command & argument
switch (command) {
case AT91C_EFC_FCMD_WP:
case AT91C_EFC_FCMD_WPL:
case AT91C_EFC_FCMD_EWP:
case AT91C_EFC_FCMD_EWPL:
case AT91C_EFC_FCMD_EPL:
case AT91C_EFC_FCMD_EPA:
case AT91C_EFC_FCMD_SLB:
case AT91C_EFC_FCMD_CLB:
ASSERT(argument < AT91C_IFLASH_NB_OF_PAGES,
"-F- Embedded flash has only %d pages\n\r",
AT91C_IFLASH_NB_OF_PAGES);
break;
case AT91C_EFC_FCMD_SFB:
case AT91C_EFC_FCMD_CFB:
ASSERT(argument < EFC_NUM_GPNVMS, "-F- Embedded flash has only %d GPNVMs\n\r", EFC_NUM_GPNVMS);
break;
case AT91C_EFC_FCMD_GETD:
case AT91C_EFC_FCMD_EA:
case AT91C_EFC_FCMD_GLB:
case AT91C_EFC_FCMD_GFB:
ASSERT(argument == 0, "-F- Argument is meaningless for the given command.\n\r");
break;
default: ASSERT(0, "-F- Unknown command %d\n\r", command);
}
// Start commandEmbedded flash
ASSERT((AT91C_BASE_EFC->EFC_FSR & AT91C_EFC_FRDY) == AT91C_EFC_FRDY, "-F- EEFC is not ready\n\r");
AT91C_BASE_EFC->EFC_FCR = (0x5A << 24) | (argument << 8) | command;
}
//------------------------------------------------------------------------------
/// Performs the given command and wait until its completion (or an error).
/// Returns 0 if successful; otherwise returns an error code.
/// \param command Command to perform.
/// \param argument Optional command argument.
//------------------------------------------------------------------------------
#ifdef __ICCARM__
__ramfunc
#else
__attribute__ ((section (".ramfunc")))
#endif
unsigned char EFC_PerformCommand(unsigned char command, unsigned short argument)
{
unsigned int status;
#ifdef BOARD_FLASH_IAP_ADDRESS
// Pointer on IAP function in ROM
static void (*IAP_PerformCommand)(unsigned int);
IAP_PerformCommand = (void (*)(unsigned int)) *((unsigned int *) BOARD_FLASH_IAP_ADDRESS);
// Check if IAP function is implemented (opcode in SWI != 'b' or 'ldr') */
if ((((((unsigned long) IAP_PerformCommand >> 24) & 0xFF) != 0xEA) &&
(((unsigned long) IAP_PerformCommand >> 24) & 0xFF) != 0xE5)) {
IAP_PerformCommand((0x5A << 24) | (argument << 8) | command);
return (AT91C_BASE_EFC->EFC_FSR & (AT91C_EFC_LOCKE | AT91C_EFC_FCMDE));
}
#endif
AT91C_BASE_EFC->EFC_FCR = (0x5A << 24) | (argument << 8) | command;
do {
status = AT91C_BASE_EFC->EFC_FSR;
}
while ((status & AT91C_EFC_FRDY) != AT91C_EFC_FRDY);
return (status & (AT91C_EFC_LOCKE | AT91C_EFC_FCMDE));
}
//------------------------------------------------------------------------------
/// Returns the current status of the EEFC. Keep in mind that this function clears
/// the value of some status bits (LOCKE, PROGE).
//------------------------------------------------------------------------------
unsigned int EFC_GetStatus(void)
{
return AT91C_BASE_EFC->EFC_FSR;
}
//------------------------------------------------------------------------------
/// Returns the result of the last executed command.
//------------------------------------------------------------------------------
unsigned int EFC_GetResult(void) {
return AT91C_BASE_EFC->EFC_FRR;
}
#endif //#ifdef BOARD_FLASH_EEFC

View file

@ -0,0 +1,133 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef EEFC_H
#define EEFC_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#ifdef BOARD_FLASH_EEFC
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
/// Number of GPNVMs available on each chip.
#if defined(at91sam7l64) || defined(at91sam7l128)
#define EFC_NUM_GPNVMS 2
#elif defined(at91sam9xe128) || defined(at91sam9xe256) || defined(at91sam9xe512)
#define EFC_NUM_GPNVMS 17
#endif
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
// Needed when EEFC is integrated in MC.
#if !defined(AT91C_BASE_EFC) && defined(AT91C_BASE_MC)
typedef struct _AT91S_EFC {
AT91_REG EFC_FMR; // EFC Flash Mode Register
AT91_REG EFC_FCR; // EFC Flash Command Register
AT91_REG EFC_FSR; // EFC Flash Status Register
AT91_REG EFC_FRR; // EFC Flash Result Register
AT91_REG EFC_FVR; // EFC Flash Version Register
} AT91S_EFC, *AT91PS_EFC;
#define AT91C_EFC_FRDY AT91C_MC_FRDY
#define AT91C_EFC_FWS AT91C_MC_FWS
#define AT91C_EFC_FWS_0WS AT91C_MC_FWS_0WS
#define AT91C_EFC_FWS_1WS AT91C_MC_FWS_1WS
#define AT91C_EFC_FWS_2WS AT91C_MC_FWS_2WS
#define AT91C_EFC_FWS_3WS AT91C_MC_FWS_3WS
#define AT91C_EFC_FCMD AT91C_MC_FCMD
#define AT91C_EFC_FCMD_GETD AT91C_MC_FCMD_GETD
#define AT91C_EFC_FCMD_WP AT91C_MC_FCMD_WP
#define AT91C_EFC_FCMD_WPL AT91C_MC_FCMD_WPL
#define AT91C_EFC_FCMD_EWP AT91C_MC_FCMD_EWP
#define AT91C_EFC_FCMD_EWPL AT91C_MC_FCMD_EWPL
#define AT91C_EFC_FCMD_EA AT91C_MC_FCMD_EA
#define AT91C_EFC_FCMD_EPL AT91C_MC_FCMD_EPL
#define AT91C_EFC_FCMD_EPA AT91C_MC_FCMD_EPA
#define AT91C_EFC_FCMD_SLB AT91C_MC_FCMD_SLB
#define AT91C_EFC_FCMD_CLB AT91C_MC_FCMD_CLB
#define AT91C_EFC_FCMD_GLB AT91C_MC_FCMD_GLB
#define AT91C_EFC_FCMD_SFB AT91C_MC_FCMD_SFB
#define AT91C_EFC_FCMD_CFB AT91C_MC_FCMD_CFB
#define AT91C_EFC_FCMD_GFB AT91C_MC_FCMD_GFB
#define AT91C_EFC_FARG AT91C_MC_FARG
#define AT91C_EFC_FKEY AT91C_MC_FKEY
#define AT91C_EFC_FRDY_S AT91C_MC_FRDY_S
#define AT91C_EFC_FCMDE AT91C_MC_FCMDE
#define AT91C_EFC_LOCKE AT91C_MC_LOCKE
#define AT91C_EFC_FVALUE AT91C_MC_FVALUE
#define AT91C_BASE_EFC (AT91_CAST(AT91PS_EFC) 0xFFFFFF60)
#endif //#if !defined(AT91C_BASE_EFC) && defined(AT91C_BASE_MC)
//------------------------------------------------------------------------------
// Functions
//------------------------------------------------------------------------------
extern void EFC_EnableFrdyIt(void);
extern void EFC_DisableFrdyIt(void);
extern void EFC_TranslateAddress(
unsigned int address,
unsigned short *pPage,
unsigned short *pOffset);
extern void EFC_ComputeAddress(
unsigned short page,
unsigned short offset,
unsigned int *pAddress);
extern void EFC_StartCommand(
unsigned char command,
unsigned short argument);
extern unsigned char EFC_PerformCommand(
unsigned char command,
unsigned short argument);
extern unsigned int EFC_GetStatus(void);
extern unsigned int EFC_GetResult(void);
#endif //#ifdef BOARD_FLASH_EEFC
#endif //#ifndef EEFC_H

View file

@ -0,0 +1,387 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef trace_LEVEL
#define trace_LEVEL trace_INFO
#endif
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "efc.h"
#ifdef BOARD_FLASH_EFC
#include <utility/assert.h>
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Local definitions
//------------------------------------------------------------------------------
// Round a number to the nearest integral value (number must have been
// multiplied by 10, e.g. to round 10.3 enter 103).
#define ROUND(n) ((((n) % 10) >= 5) ? (((n) / 10) + 1) : ((n) / 10))
// Returns the FMCN field value when manipulating lock bits, given MCK.
#if defined(at91sam7a3)
#define FMCN_BITS(mck) (ROUND((mck) / 100000) << 16) // <- Not correct according to the datasheet but it works
#else
#define FMCN_BITS(mck) (ROUND((mck) / 100000) << 16)
#endif
// Returns the FMCN field value when manipulating the rest of the flash.
#define FMCN_FLASH(mck) ((((mck) / 2000000) * 3) << 16)
//------------------------------------------------------------------------------
// Local functions
//------------------------------------------------------------------------------
/// Master clock frequency, used to infer the value of the FMCN field.
static unsigned int lMck;
/// Calculated value of the FMCN field base on Master clock frequency.
static unsigned int lMckFMCN;
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Sets the system master clock so the FMCN field of the EFC(s) can be
/// programmed properly.
/// \param mck Master clock frequency in Hz.
//------------------------------------------------------------------------------
void EFC_SetMasterClock(unsigned int mck)
{
lMck = mck;
lMckFMCN = FMCN_BITS(lMck);
}
//------------------------------------------------------------------------------
/// Enables the given interrupt sources on an EFC peripheral.
/// \param pEfc Pointer to an AT91S_EFC structure.
/// \param sources Interrupt sources to enable.
//------------------------------------------------------------------------------
void EFC_EnableIt(AT91S_EFC *pEfc, unsigned int sources)
{
SANITY_CHECK(pEfc);
SANITY_CHECK((sources & ~0x0000000D) == 0);
pEfc->EFC_FMR |= sources;
}
//------------------------------------------------------------------------------
/// Disables the given interrupt sources on an EFC peripheral.
/// \param pEfc Pointer to an AT91S_EFC structure.
/// \param sources Interrupt sources to disable.
//------------------------------------------------------------------------------
void EFC_DisableIt(AT91S_EFC *pEfc, unsigned int sources)
{
SANITY_CHECK(pEfc);
SANITY_CHECK((sources & ~(AT91C_MC_FRDY | AT91C_MC_LOCKE | AT91C_MC_PROGE)) == 0);
pEfc->EFC_FMR &= ~sources;
}
//------------------------------------------------------------------------------
/// Enables or disable the "Erase before programming" feature of an EFC.
/// \param pEfc Pointer to an AT91S_EFC structure.
/// \param enable If 1, the feature is enabled; otherwise it is disabled.
//------------------------------------------------------------------------------
void EFC_SetEraseBeforeProgramming(AT91S_EFC *pEfc, unsigned char enable)
{
SANITY_CHECK(pEfc);
if (enable) {
pEfc->EFC_FMR &= ~AT91C_MC_NEBP;
}
else {
pEfc->EFC_FMR |= AT91C_MC_NEBP;
}
}
//------------------------------------------------------------------------------
/// Translates the given address into EFC, page and offset values. The resulting
/// values are stored in the provided variables if they are not null.
/// \param address Address to translate.
/// \param ppEfc Pointer to target EFC peripheral.
/// \param pPage First page accessed.
/// \param pOffset Byte offset in first page.
//------------------------------------------------------------------------------
void EFC_TranslateAddress(
unsigned int address,
AT91S_EFC **ppEfc,
unsigned short *pPage,
unsigned short *pOffset)
{
AT91S_EFC *pEfc;
unsigned short page;
unsigned short offset;
SANITY_CHECK(address >= AT91C_IFLASH);
SANITY_CHECK(address <= (AT91C_IFLASH + AT91C_IFLASH_SIZE));
#if defined(AT91C_BASE_EFC0)
if (address >= (AT91C_IFLASH + AT91C_IFLASH_SIZE / 2)) {
pEfc = AT91C_BASE_EFC1;
page = (address - AT91C_IFLASH - AT91C_IFLASH_SIZE / 2) / AT91C_IFLASH_PAGE_SIZE;
offset = (address - AT91C_IFLASH - AT91C_IFLASH_SIZE / 2) % AT91C_IFLASH_PAGE_SIZE;
}
else {
pEfc = AT91C_BASE_EFC0;
page = (address - AT91C_IFLASH) / AT91C_IFLASH_PAGE_SIZE;
offset = (address - AT91C_IFLASH) % AT91C_IFLASH_PAGE_SIZE;
}
#else
pEfc = AT91C_BASE_EFC;
page = (address - AT91C_IFLASH) / AT91C_IFLASH_PAGE_SIZE;
offset = (address - AT91C_IFLASH) % AT91C_IFLASH_PAGE_SIZE;
#endif
trace_LOG(trace_DEBUG,
"-D- Translated 0x%08X to EFC=0x%08X, page=%d and offset=%d\n\r",
address, (unsigned int) pEfc, page, offset);
// Store values
if (ppEfc) {
*ppEfc = pEfc;
}
if (pPage) {
*pPage = page;
}
if (pOffset) {
*pOffset = offset;
}
}
//------------------------------------------------------------------------------
/// Computes the address of a flash access given the EFC, page and offset.
/// \param pEfc Pointer to an AT91S_EFC structure.
/// \param page Page number.
/// \param offset Byte offset inside page.
/// \param pAddress Computed address (optional).
//------------------------------------------------------------------------------
void EFC_ComputeAddress(
AT91S_EFC *pEfc,
unsigned short page,
unsigned short offset,
unsigned int *pAddress)
{
unsigned int address;
SANITY_CHECK(pEfc);
#if defined(AT91C_BASE_EFC1)
SANITY_CHECK(page <= (AT91C_IFLASH_NB_OF_PAGES / 2));
#else
SANITY_CHECK(page <= AT91C_IFLASH_NB_OF_PAGES);
#endif
SANITY_CHECK(offset < AT91C_IFLASH_PAGE_SIZE);
// Compute address
address = AT91C_IFLASH + page * AT91C_IFLASH_PAGE_SIZE + offset;
#if defined(AT91C_BASE_EFC1)
if (pEfc == AT91C_BASE_EFC1) {
address += AT91C_IFLASH_SIZE / 2;
}
#endif
// Store result
if (pAddress) {
*pAddress = address;
}
}
//------------------------------------------------------------------------------
/// Starts the executing the given command on an EFC. This function returns
/// as soon as the command is started. It does NOT set the FMCN field automatically.
/// \param pEfc Pointer to an AT91S_EFC structure.
/// \param command Command to execute.
/// \param argument Command argument (should be 0 if not used).
//------------------------------------------------------------------------------
void EFC_StartCommand(
AT91S_EFC *pEfc,
unsigned char command,
unsigned short argument)
{
SANITY_CHECK(pEfc);
ASSERT(lMck != 0, "-F- Master clock not set.\n\r");
// Check command & argument
switch (command) {
case AT91C_MC_FCMD_PROG_AND_LOCK:
ASSERT(0, "-F- Write and lock command cannot be carried out.\n\r");
break;
case AT91C_MC_FCMD_START_PROG:
case AT91C_MC_FCMD_LOCK:
case AT91C_MC_FCMD_UNLOCK:
ASSERT(argument < AT91C_IFLASH_NB_OF_PAGES,
"-F- Maximum number of pages is %d (argument was %d)\n\r",
AT91C_IFLASH_NB_OF_PAGES,
argument);
break;
#if (EFC_NUM_GPNVMS > 0)
case AT91C_MC_FCMD_SET_GP_NVM:
case AT91C_MC_FCMD_CLR_GP_NVM:
ASSERT(argument < EFC_NUM_GPNVMS, "-F- A maximum of %d GPNVMs are available on the chip.\n\r", EFC_NUM_GPNVMS);
break;
#endif
case AT91C_MC_FCMD_ERASE_ALL:
#if !defined(EFC_NO_SECURITY_BIT)
case AT91C_MC_FCMD_SET_SECURITY:
#endif
ASSERT(argument == 0, "-F- Argument is meaningless for the given command\n\r");
break;
default: ASSERT(0, "-F- Unknown command %d\n\r", command);
}
// Set FMCN
switch (command) {
case AT91C_MC_FCMD_LOCK:
case AT91C_MC_FCMD_UNLOCK:
#if (EFC_NUM_GPNVMS > 0)
case AT91C_MC_FCMD_SET_GP_NVM:
case AT91C_MC_FCMD_CLR_GP_NVM:
#endif
#if !defined(EFC_NO_SECURITY_BIT)
case AT91C_MC_FCMD_SET_SECURITY:
#endif
pEfc->EFC_FMR = (pEfc->EFC_FMR & ~AT91C_MC_FMCN) | lMckFMCN;
break;
case AT91C_MC_FCMD_START_PROG:
case AT91C_MC_FCMD_ERASE_ALL:
pEfc->EFC_FMR = (pEfc->EFC_FMR & ~AT91C_MC_FMCN) | lMckFMCN;
break;
}
// Start command
ASSERT((pEfc->EFC_FSR & AT91C_MC_FRDY) != 0, "-F- Efc is not ready\n\r");
pEfc->EFC_FCR = (0x5A << 24) | (argument << 8) | command;
}
//------------------------------------------------------------------------------
/// Performs the given command and wait until its completion (or an error).
/// Returns 0 if successful; otherwise returns an error code.
/// \param pEfc Pointer to an AT91S_EFC structure.
/// \param command Command to perform.
/// \param argument Optional command argument.
//------------------------------------------------------------------------------
#ifdef __ICCARM__
__ramfunc
#else
__attribute__ ((section (".ramfunc")))
#endif
unsigned char EFC_PerformCommand(
AT91S_EFC *pEfc,
unsigned char command,
unsigned short argument)
{
unsigned int status;
// Set FMCN
switch (command) {
case AT91C_MC_FCMD_LOCK:
case AT91C_MC_FCMD_UNLOCK:
#if (EFC_NUM_GPNVMS > 0)
case AT91C_MC_FCMD_SET_GP_NVM:
case AT91C_MC_FCMD_CLR_GP_NVM:
#endif
#if !defined(EFC_NO_SECURITY_BIT)
case AT91C_MC_FCMD_SET_SECURITY:
#endif
pEfc->EFC_FMR = (pEfc->EFC_FMR & ~AT91C_MC_FMCN) | lMckFMCN;
break;
case AT91C_MC_FCMD_START_PROG:
case AT91C_MC_FCMD_ERASE_ALL:
pEfc->EFC_FMR = (pEfc->EFC_FMR & ~AT91C_MC_FMCN) | lMckFMCN;
break;
}
#ifdef BOARD_FLASH_IAP_ADDRESS
// Pointer on IAP function in ROM
static void (*IAP_PerformCommand)(unsigned int, unsigned int);
unsigned int index = 0;
#ifdef AT91C_BASE_EFC1
if (pEfc == AT91C_BASE_EFC1) {
index = 1;
}
#endif
IAP_PerformCommand = (void (*)(unsigned int, unsigned int)) *((unsigned int *) BOARD_FLASH_IAP_ADDRESS);
// Check if IAP function is implemented (opcode in SWI != 'b' or 'ldr') */
if ((((((unsigned long) IAP_PerformCommand >> 24) & 0xFF) != 0xEA) &&
(((unsigned long) IAP_PerformCommand >> 24) & 0xFF) != 0xE5)) {
IAP_PerformCommand(index, (0x5A << 24) | (argument << 8) | command);
return (pEfc->EFC_FSR & (AT91C_MC_LOCKE | AT91C_MC_PROGE));
}
#endif
pEfc->EFC_FCR = (0x5A << 24) | (argument << 8) | command;
do {
status = pEfc->EFC_FSR;
}
while ((status & AT91C_MC_FRDY) == 0);
return (status & (AT91C_MC_PROGE | AT91C_MC_LOCKE));
}
//------------------------------------------------------------------------------
/// Returns the current status of an EFC. Keep in mind that this function clears
/// the value of some status bits (LOCKE, PROGE).
/// \param pEfc Pointer to an AT91S_EFC structure.
//------------------------------------------------------------------------------
unsigned int EFC_GetStatus(AT91S_EFC *pEfc)
{
return pEfc->EFC_FSR;
}
#endif //#ifdef BOARD_FLASH_EFC

View file

@ -0,0 +1,127 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef EFC_H
#define EFC_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#ifdef BOARD_FLASH_EFC
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
/// Number of GPNVMs available on each chip.
#if defined(at91sam7s16) || defined(at91sam7s161) || defined(at91sam7s32) \
|| defined(at91sam7s321) || defined(at91sam7s64) || defined(at91sam7s128) \
|| defined(at91sam7s256) || defined(at91sam7s512)
#define EFC_NUM_GPNVMS 2
#elif defined(at91sam7se32) || defined(at91sam7se256) || defined(at91sam7se512) \
|| defined(at91sam7x128) || defined(at91sam7x256) || defined(at91sam7x512) \
|| defined(at91sam7xc128) || defined(at91sam7xc256) || defined(at91sam7xc512) \
#define EFC_NUM_GPNVMS 3
#elif defined(at91sam7a3)
#define EFC_NUM_GPNVMS 0
#endif
// Missing FRDY bit for SAM7A3
#if defined(at91sam7a3)
#define AT91C_MC_FRDY (AT91C_MC_EOP | AT91C_MC_EOL)
#endif
// No security bit on SAM7A3
#if defined(at91sam7a3)
#define EFC_NO_SECURITY_BIT
#endif
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
// For chips which do not define AT91S_EFC
#if !defined(AT91C_BASE_EFC) && !defined(AT91C_BASE_EFC0)
typedef struct _AT91S_EFC {
AT91_REG EFC_FMR;
AT91_REG EFC_FCR;
AT91_REG EFC_FSR;
} AT91S_EFC, *AT91PS_EFC;
#define AT91C_BASE_EFC (AT91_CAST(AT91PS_EFC) 0xFFFFFF60)
#endif
//------------------------------------------------------------------------------
// Functions
//------------------------------------------------------------------------------
extern void EFC_SetMasterClock(unsigned int mck);
extern void EFC_EnableIt(AT91S_EFC *pEfc, unsigned int sources);
extern void EFC_DisableIt(AT91S_EFC *pEfc, unsigned int sources);
extern void EFC_SetEraseBeforeProgramming(AT91S_EFC *pEfc, unsigned char enable);
extern void EFC_TranslateAddress(
unsigned int address,
AT91S_EFC **ppEfc,
unsigned short *pPage,
unsigned short *pOffset);
extern void EFC_ComputeAddress(
AT91S_EFC *pEfc,
unsigned short page,
unsigned short offset,
unsigned int *pAddress);
extern void EFC_StartCommand(
AT91S_EFC *pEfc,
unsigned char command,
unsigned short argument);
extern unsigned char EFC_PerformCommand(
AT91S_EFC *pEfc,
unsigned char command,
unsigned short argument);
extern unsigned int EFC_GetStatus(AT91S_EFC *pEfc);
#endif //#ifdef BOARD_FLASH_EFC
#endif //#ifndef EFC_H

View file

@ -0,0 +1,833 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//-----------------------------------------------------------------------------
// Headers
//-----------------------------------------------------------------------------
#include <board.h>
#include "emac.h"
#include <utility/trace.h>
#include <utility/assert.h>
#include <string.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
/// The buffer addresses written into the descriptors must be aligned so the
/// last few bits are zero. These bits have special meaning for the EMAC
/// peripheral and cannot be used as part of the address.
#define EMAC_ADDRESS_MASK ((unsigned int)0xFFFFFFFC)
#define EMAC_LENGTH_FRAME ((unsigned int)0x0FFF) /// Length of frame mask
// receive buffer descriptor bits
#define EMAC_RX_OWNERSHIP_BIT (1UL << 0)
#define EMAC_RX_WRAP_BIT (1UL << 1)
#define EMAC_RX_SOF_BIT (1UL << 14)
#define EMAC_RX_EOF_BIT (1UL << 15)
// Transmit buffer descriptor bits
#define EMAC_TX_LAST_BUFFER_BIT (1UL << 15)
#define EMAC_TX_WRAP_BIT (1UL << 30)
#define EMAC_TX_USED_BIT (1UL << 31)
//-----------------------------------------------------------------------------
// Circular buffer management
//-----------------------------------------------------------------------------
// Return count in buffer
#define CIRC_CNT(head,tail,size) (((head) - (tail)) & ((size)-1))
// Return space available, 0..size-1
// We always leave one free char as a completely full buffer
// has head == tail, which is the same as empty
#define CIRC_SPACE(head,tail,size) CIRC_CNT((tail),((head)+1),(size))
// Return count up to the end of the buffer.
// Carefully avoid accessing head and tail more than once,
// so they can change underneath us without returning inconsistent results
#define CIRC_CNT_TO_END(head,tail,size) \
({int end = (size) - (tail); \
int n = ((head) + end) & ((size)-1); \
n < end ? n : end;})
// Return space available up to the end of the buffer
#define CIRC_SPACE_TO_END(head,tail,size) \
({int end = (size) - 1 - (head); \
int n = (end + (tail)) & ((size)-1); \
n <= end ? n : end+1;})
// Increment head or tail
#define CIRC_INC(headortail,size) \
headortail++; \
if(headortail >= size) { \
headortail = 0; \
}
#define CIRC_EMPTY(circ) ((circ)->head == (circ)->tail)
#define CIRC_CLEAR(circ) ((circ)->head = (circ)->tail = 0)
//------------------------------------------------------------------------------
// Structures
//------------------------------------------------------------------------------
#ifdef __ICCARM__ // IAR
#pragma pack(4) // IAR
#define __attribute__(...) // IAR
#endif // IAR
/// Describes the type and attribute of Receive Transfer descriptor.
typedef struct _EmacRxTDescriptor {
unsigned int addr;
unsigned int status;
} __attribute__((packed, aligned(8))) EmacRxTDescriptor, *PEmacRxTDescriptor;
/// Describes the type and attribute of Transmit Transfer descriptor.
typedef struct _EmacTxTDescriptor {
unsigned int addr;
unsigned int status;
} __attribute__((packed, aligned(8))) EmacTxTDescriptor, *PEmacTxTDescriptor;
#ifdef __ICCARM__ // IAR
#pragma pack() // IAR
#endif // IAR
/// Descriptors for RX (required aligned by 8)
typedef struct {
volatile EmacRxTDescriptor td[RX_BUFFERS];
EMAC_RxCallback rxCb; /// Callback function to be invoked once a frame has been received
unsigned short idx;
} RxTd;
/// Descriptors for TX (required aligned by 8)
typedef struct {
volatile EmacTxTDescriptor td[TX_BUFFERS];
EMAC_TxCallback txCb[TX_BUFFERS]; /// Callback function to be invoked once TD has been processed
EMAC_WakeupCallback wakeupCb; /// Callback function to be invoked once several TD have been released
unsigned short wakeupThreshold; /// Number of free TD before wakeupCb is invoked
unsigned short head; /// Circular buffer head pointer incremented by the upper layer (buffer to be sent)
unsigned short tail; /// Circular buffer head pointer incremented by the IT handler (buffer sent)
} TxTd;
//------------------------------------------------------------------------------
// Internal variables
//------------------------------------------------------------------------------
// Receive Transfer Descriptor buffer
#ifdef __ICCARM__ // IAR
#pragma data_alignment=8 // IAR
#endif // IAR
static volatile RxTd rxTd;
// Transmit Transfer Descriptor buffer
#ifdef __ICCARM__ // IAR
#pragma data_alignment=8 // IAR
#endif // IAR
static volatile TxTd txTd;
/// Send Buffer
// Section 3.6 of AMBA 2.0 spec states that burst should not cross 1K Boundaries.
// Receive buffer manager writes are burst of 2 words => 3 lsb bits of the address shall be set to 0
#ifdef __ICCARM__ // IAR
#pragma data_alignment=8 // IAR
#endif // IAR
static volatile unsigned char pTxBuffer[TX_BUFFERS * EMAC_TX_UNITSIZE] __attribute__((aligned(8)));
#ifdef __ICCARM__ // IAR
#pragma data_alignment=8 // IAR
#endif // IAR
/// Receive Buffer
static volatile unsigned char pRxBuffer[RX_BUFFERS * EMAC_RX_UNITSIZE] __attribute__((aligned(8)));
/// Statistics
static volatile EmacStats EmacStatistics;
//-----------------------------------------------------------------------------
// Internal functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// Wait PHY operation complete.
/// Return 1 if the operation completed successfully.
/// May be need to re-implemented to reduce CPU load.
/// \param retry: the retry times, 0 to wait forever until complete.
//-----------------------------------------------------------------------------
static unsigned char EMAC_WaitPhy( unsigned int retry )
{
unsigned int retry_count = 0;
while((AT91C_BASE_EMAC->EMAC_NSR & AT91C_EMAC_IDLE) == 0) {
// Dead LOOP!
if (retry == 0) {
continue;
}
// Timeout check
retry_count++;
if(retry_count >= retry) {
trace_LOG(trace_ERROR, "E: Wait PHY time out\n\r");
return 0;
}
}
return 1;
}
//-----------------------------------------------------------------------------
// Exported functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// PHY management functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// Set MDC clock according to current board clock. Per 802.3, MDC should be
/// less then 2.5MHz.
/// Return 1 if successfully, 0 if MDC clock not found.
//-----------------------------------------------------------------------------
unsigned char EMAC_SetMdcClock( unsigned int mck )
{
int clock_dividor;
if (mck <= 20000000) {
clock_dividor = AT91C_EMAC_CLK_HCLK_8; /// MDC clock = MCK/8
}
else if (mck <= 40000000) {
clock_dividor = AT91C_EMAC_CLK_HCLK_16; /// MDC clock = MCK/16
}
else if (mck <= 80000000) {
clock_dividor = AT91C_EMAC_CLK_HCLK_32; /// MDC clock = MCK/32
}
else if (mck <= 160000000) {
clock_dividor = AT91C_EMAC_CLK_HCLK_64; /// MDC clock = MCK/64
}
else {
trace_LOG(trace_ERROR, "E: No valid MDC clock.\n\r");
return 0;
}
AT91C_BASE_EMAC->EMAC_NCFGR = (AT91C_BASE_EMAC->EMAC_NCFGR & (~AT91C_EMAC_CLK))
| clock_dividor;
return 1;
}
//-----------------------------------------------------------------------------
/// Enable MDI with PHY
//-----------------------------------------------------------------------------
void EMAC_EnableMdio( void )
{
AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_MPE;
}
//-----------------------------------------------------------------------------
/// Enable MDI with PHY
//-----------------------------------------------------------------------------
void EMAC_DisableMdio( void )
{
AT91C_BASE_EMAC->EMAC_NCR &= ~AT91C_EMAC_MPE;
}
//-----------------------------------------------------------------------------
/// Enable MII mode for EMAC, called once after autonegotiate
//-----------------------------------------------------------------------------
void EMAC_EnableMII( void )
{
AT91C_BASE_EMAC->EMAC_USRIO = AT91C_EMAC_CLKEN;
}
//-----------------------------------------------------------------------------
/// Enable RMII mode for EMAC, called once after autonegotiate
//-----------------------------------------------------------------------------
void EMAC_EnableRMII( void )
{
AT91C_BASE_EMAC->EMAC_USRIO = AT91C_EMAC_CLKEN | AT91C_EMAC_RMII;
}
//-----------------------------------------------------------------------------
/// Read PHY register.
/// Return 1 if successfully, 0 if timeout.
/// \param PhyAddress PHY Address
/// \param Address Register Address
/// \param pValue Pointer to a 32 bit location to store read data
/// \param retry The retry times, 0 to wait forever until complete.
//-----------------------------------------------------------------------------
unsigned char EMAC_ReadPhy(unsigned char PhyAddress,
unsigned char Address,
unsigned int *pValue,
unsigned int retry)
{
AT91C_BASE_EMAC->EMAC_MAN = (AT91C_EMAC_SOF & (0x01 << 30))
| (AT91C_EMAC_CODE & (2 << 16))
| (AT91C_EMAC_RW & (2 << 28))
| (AT91C_EMAC_PHYA & ((PhyAddress & 0x1f) << 23))
| (AT91C_EMAC_REGA & (Address << 18));
if ( EMAC_WaitPhy(retry) == 0 ) {
trace_LOG(trace_ERROR, "TimeOut EMAC_ReadPhy\n\r");
return 0;
}
*pValue = ( AT91C_BASE_EMAC->EMAC_MAN & 0x0000ffff );
return 1;
}
//-----------------------------------------------------------------------------
/// Write PHY register
/// Return 1 if successfully, 0 if timeout.
/// \param PhyAddress PHY Address
/// \param Address Register Address
/// \param Value Data to write ( Actually 16 bit data )
/// \param retry The retry times, 0 to wait forever until complete.
//-----------------------------------------------------------------------------
unsigned char EMAC_WritePhy(unsigned char PhyAddress,
unsigned char Address,
unsigned int Value,
unsigned int retry)
{
AT91C_BASE_EMAC->EMAC_MAN = (AT91C_EMAC_SOF & (0x01 << 30))
| (AT91C_EMAC_CODE & (2 << 16))
| (AT91C_EMAC_RW & (1 << 28))
| (AT91C_EMAC_PHYA & ((PhyAddress & 0x1f) << 23))
| (AT91C_EMAC_REGA & (Address << 18))
| (AT91C_EMAC_DATA & Value) ;
if ( EMAC_WaitPhy(retry) == 0 ) {
trace_LOG(trace_ERROR, "TimeOut EMAC_WritePhy\n\r");
return 0;
}
return 1;
}
//-----------------------------------------------------------------------------
/// Setup the EMAC for the link : speed 100M/10M and Full/Half duplex
/// \param speed Link speed, 0 for 10M, 1 for 100M
/// \param fullduplex 1 for Full Duplex mode
//-----------------------------------------------------------------------------
void EMAC_SetLinkSpeed(unsigned char speed, unsigned char fullduplex)
{
unsigned int ncfgr;
ncfgr = AT91C_BASE_EMAC->EMAC_NCFGR;
ncfgr &= ~(AT91C_EMAC_SPD | AT91C_EMAC_FD);
if (speed) {
ncfgr |= AT91C_EMAC_SPD;
}
if (fullduplex) {
ncfgr |= AT91C_EMAC_FD;
}
AT91C_BASE_EMAC->EMAC_NCFGR = ncfgr;
}
//-----------------------------------------------------------------------------
// EMAC functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// EMAC Interrupt handler
//-----------------------------------------------------------------------------
void EMAC_Handler(void)
{
volatile EmacTxTDescriptor *pTxTd;
volatile EMAC_TxCallback *pTxCb;
unsigned int isr;
unsigned int rsr;
unsigned int tsr;
unsigned int rxStatusFlag;
unsigned int txStatusFlag;
//trace_LOG(trace_DEBUG, "EMAC_Handler\n\r");
isr = AT91C_BASE_EMAC->EMAC_ISR & AT91C_BASE_EMAC->EMAC_IMR;
rsr = AT91C_BASE_EMAC->EMAC_RSR;
tsr = AT91C_BASE_EMAC->EMAC_TSR;
// RX packet
if ((isr & AT91C_EMAC_RCOMP) || (rsr & AT91C_EMAC_REC)) {
rxStatusFlag = AT91C_EMAC_REC;
// Frame received
EmacStatistics.rx_packets++;
// Check OVR
if (rsr & AT91C_EMAC_OVR) {
rxStatusFlag |= AT91C_EMAC_OVR;
EmacStatistics.rx_ovrs++;
}
// Check BNA
if (rsr & AT91C_EMAC_BNA) {
rxStatusFlag |= AT91C_EMAC_BNA;
EmacStatistics.rx_bnas++;
}
// Clear status
AT91C_BASE_EMAC->EMAC_RSR |= rxStatusFlag;
// Invoke callbacks
if (rxTd.rxCb) {
rxTd.rxCb(rxStatusFlag);
}
}
// TX packet
if ((isr & AT91C_EMAC_TCOMP) || (tsr & AT91C_EMAC_COMP)) {
txStatusFlag = AT91C_EMAC_COMP;
EmacStatistics.tx_comp ++;
// A frame transmitted
// Check RLE
if (tsr & AT91C_EMAC_RLES) {
txStatusFlag |= AT91C_EMAC_RLES;
EmacStatistics.tx_errors++;
}
// Check COL
if (tsr & AT91C_EMAC_COL) {
txStatusFlag |= AT91C_EMAC_COL;
EmacStatistics.collisions++;
}
// Check BEX
if (tsr & AT91C_EMAC_BEX) {
txStatusFlag |= AT91C_EMAC_BEX;
EmacStatistics.tx_exausts++;
}
// Check UND
if (tsr & AT91C_EMAC_UND) {
txStatusFlag |= AT91C_EMAC_UND;
EmacStatistics.tx_underruns++;
}
// Clear status
AT91C_BASE_EMAC->EMAC_TSR |= txStatusFlag;
// Sanity check: Tx buffers have to be scheduled
ASSERT(!CIRC_EMPTY(&txTd),
"-F- EMAC Tx interrupt received meanwhile no TX buffers has been scheduled\n\r");
// Check the buffers
while (CIRC_CNT(txTd.head, txTd.tail, TX_BUFFERS)) {
pTxTd = txTd.td + txTd.tail;
pTxCb = txTd.txCb + txTd.tail;
// Exit if buffer has not been sent yet
if ((pTxTd->status & EMAC_TX_USED_BIT) == 0) {
break;
}
// Notify upper layer that packet has been sent
if (*pTxCb) {
(*pTxCb)(txStatusFlag);
}
CIRC_INC( txTd.tail, TX_BUFFERS );
}
// If a wakeup has been scheduled, notify upper layer that it can send
// other packets, send will be successfull.
if( (CIRC_SPACE(txTd.head, txTd.tail, TX_BUFFERS) >= txTd.wakeupThreshold)
&& txTd.wakeupCb) {
txTd.wakeupCb();
}
}
}
//-----------------------------------------------------------------------------
/// Initialize the EMAC with the emac controller address
/// \param id HW ID for power management
/// \param pTxWakeUpfct Thresold TX Wakeup Callback
/// \param pRxfct RX Wakeup Callback
/// \param pMacAddress Mac Address
/// \param enableCAF enable AT91C_EMAC_CAF if needed by application
/// \param enableNBC AT91C_EMAC_NBC if needed by application
//-----------------------------------------------------------------------------
void EMAC_Init( unsigned char id, const unsigned char *pMacAddress,
unsigned char enableCAF, unsigned char enableNBC )
{
int Index;
unsigned int Address;
// Check parameters
ASSERT(RX_BUFFERS * EMAC_RX_UNITSIZE > EMAC_FRAME_LENTGH_MAX,
"E: RX buffers too small\n\r");
trace_LOG(trace_DEBUG, "EMAC_Init\n\r");
// Power ON
AT91C_BASE_PMC->PMC_PCER = 1 << id;
// Disable TX & RX and more
AT91C_BASE_EMAC->EMAC_NCR = 0;
// disable
AT91C_BASE_EMAC->EMAC_IDR = ~0;
rxTd.idx = 0;
CIRC_CLEAR(&txTd);
// Setup the RX descriptors.
for(Index = 0; Index < RX_BUFFERS; Index++) {
Address = (unsigned int)(&(pRxBuffer[Index * EMAC_RX_UNITSIZE]));
// Remove EMAC_RX_OWNERSHIP_BIT and EMAC_RX_WRAP_BIT
rxTd.td[Index].addr = Address & EMAC_ADDRESS_MASK;
rxTd.td[Index].status = 0;
}
rxTd.td[RX_BUFFERS - 1].addr |= EMAC_RX_WRAP_BIT;
// Setup the TX descriptors.
for(Index = 0; Index < TX_BUFFERS; Index++) {
Address = (unsigned int)(&(pTxBuffer[Index * EMAC_TX_UNITSIZE]));
txTd.td[Index].addr = Address;
txTd.td[Index].status = EMAC_TX_USED_BIT;
}
txTd.td[TX_BUFFERS - 1].status = EMAC_TX_USED_BIT | EMAC_TX_WRAP_BIT;
// Set the MAC address
if( pMacAddress != (unsigned char *)0 ) {
AT91C_BASE_EMAC->EMAC_SA1L = ( ((unsigned int)pMacAddress[3] << 24)
| ((unsigned int)pMacAddress[2] << 16)
| ((unsigned int)pMacAddress[1] << 8 )
| pMacAddress[0] );
AT91C_BASE_EMAC->EMAC_SA1H = ( ((unsigned int)pMacAddress[5] << 8 )
| pMacAddress[4] );
}
// Now setup the descriptors
// Receive Buffer Queue Pointer Register
AT91C_BASE_EMAC->EMAC_RBQP = (unsigned int) (rxTd.td);
// Transmit Buffer Queue Pointer Register
AT91C_BASE_EMAC->EMAC_TBQP = (unsigned int) (txTd.td);
AT91C_BASE_EMAC->EMAC_NCR = AT91C_EMAC_CLRSTAT;
// Clear all status bits in the receive status register.
AT91C_BASE_EMAC->EMAC_RSR = (AT91C_EMAC_OVR | AT91C_EMAC_REC | AT91C_EMAC_BNA);
// Clear all status bits in the transmit status register
AT91C_BASE_EMAC->EMAC_TSR = ( AT91C_EMAC_UBR | AT91C_EMAC_COL | AT91C_EMAC_RLES
| AT91C_EMAC_BEX | AT91C_EMAC_COMP
| AT91C_EMAC_UND );
// Clear interrupts
AT91C_BASE_EMAC->EMAC_ISR;
// Enable the copy of data into the buffers
// ignore broadcasts, and don't copy FCS.
AT91C_BASE_EMAC->EMAC_NCFGR |= (AT91C_EMAC_DRFCS | AT91C_EMAC_PAE);
if( enableCAF == EMAC_CAF_ENABLE ) {
AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_CAF;
}
if( enableNBC == EMAC_NBC_ENABLE ) {
AT91C_BASE_EMAC->EMAC_NCFGR |= AT91C_EMAC_NBC;
}
// Enable Rx and Tx, plus the stats register.
AT91C_BASE_EMAC->EMAC_NCR |= (AT91C_EMAC_TE | AT91C_EMAC_RE | AT91C_EMAC_WESTAT);
// Setup the interrupts for TX (and errors)
AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RXUBR
| AT91C_EMAC_TUNDR
| AT91C_EMAC_RLEX
| AT91C_EMAC_TXERR
| AT91C_EMAC_TCOMP
| AT91C_EMAC_ROVR
| AT91C_EMAC_HRESP;
}
//-----------------------------------------------------------------------------
/// Get the statstic information & reset it
/// \param pStats Pointer to EmacStats structure to copy the informations
/// \param reset Reset the statistics after copy it
//-----------------------------------------------------------------------------
void EMAC_GetStatistics(EmacStats *pStats, unsigned char reset)
{
unsigned int ncrBackup = 0;
trace_LOG(trace_DEBUG, "EMAC_GetStatistics\n\r");
// Sanity check
if (pStats == (EmacStats *) 0) {
return;
}
ncrBackup = AT91C_BASE_EMAC->EMAC_NCR & (AT91C_EMAC_TE | AT91C_EMAC_RE);
// Disable TX/RX
AT91C_BASE_EMAC->EMAC_NCR = ncrBackup & ~(AT91C_EMAC_TE | AT91C_EMAC_RE);
// Copy the informations
memcpy(pStats, (void*)&EmacStatistics, sizeof(EmacStats));
// Reset the statistics
if (reset) {
memset((void*)&EmacStatistics, 0x00, sizeof(EmacStats));
AT91C_BASE_EMAC->EMAC_NCR = ncrBackup | AT91C_EMAC_CLRSTAT;
}
// restore NCR
AT91C_BASE_EMAC->EMAC_NCR = ncrBackup;
}
//-----------------------------------------------------------------------------
/// Send a packet with EMAC.
/// If the packet size is larger than transfer buffer size error returned.
/// \param buffer The buffer to be send
/// \param size The size of buffer to be send
/// \param fEMAC_TxCallback Threshold Wakeup callback
/// \param fWakeUpCb TX Wakeup
/// \return OK, Busy or invalid packet
//-----------------------------------------------------------------------------
unsigned char EMAC_Send(void *pBuffer,
unsigned int size,
EMAC_TxCallback fEMAC_TxCallback)
{
volatile EmacTxTDescriptor *pTxTd;
volatile EMAC_TxCallback *pTxCb;
//trace_LOG(trace_DEBUG, "EMAC_Send\n\r");
// Check parameter
if (size > EMAC_TX_UNITSIZE) {
trace_LOG(trace_ERROR, "-E- EMAC driver does not split send packets.");
trace_LOG(trace_ERROR, " It can send %d bytes max in one packet (%u bytes requested)\n\r",
EMAC_TX_UNITSIZE, size);
return EMAC_TX_INVALID_PACKET;
}
// If no free TxTd, buffer can't be sent, schedule the wakeup callback
if( CIRC_SPACE(txTd.head, txTd.tail, TX_BUFFERS) == 0) {
return EMAC_TX_BUFFER_BUSY;
}
// Pointers to the current TxTd
pTxTd = txTd.td + txTd.head;
pTxCb = txTd.txCb + txTd.head;
// Sanity check
ASSERT((pTxTd->status & EMAC_TX_USED_BIT) != 0,
"-F- Buffer is still under EMAC control\n\r");
// Setup/Copy data to transmition buffer
if (pBuffer && size) {
// Driver manage the ring buffer
memcpy((void *)pTxTd->addr, pBuffer, size);
}
// Tx Callback
*pTxCb = fEMAC_TxCallback;
// Update TD status
// The buffer size defined is length of ethernet frame
// so it's always the last buffer of the frame.
if (txTd.head == TX_BUFFERS-1) {
pTxTd->status =
(size & EMAC_LENGTH_FRAME) | EMAC_TX_LAST_BUFFER_BIT | EMAC_TX_WRAP_BIT;
}
else {
pTxTd->status = (size & EMAC_LENGTH_FRAME) | EMAC_TX_LAST_BUFFER_BIT;
}
CIRC_INC(txTd.head, TX_BUFFERS)
// Tx packets count
EmacStatistics.tx_packets++;
// Now start to transmit if it is not already done
AT91C_BASE_EMAC->EMAC_NCR |= AT91C_EMAC_TSTART;
return EMAC_TX_OK;
}
//-----------------------------------------------------------------------------
/// Receive a packet with EMAC
/// If not enough buffer for the packet, the remaining data is lost but right
/// frame length is returned.
/// \param pFrame Buffer to store the frame
/// \param frameSize Size of the frame
/// \param pRcvSize Received size
/// \return OK, no data, or frame too small
//-----------------------------------------------------------------------------
unsigned char EMAC_Poll(unsigned char *pFrame,
unsigned int frameSize,
unsigned int *pRcvSize)
{
unsigned short bufferLength;
unsigned int tmpFrameSize=0;
unsigned char *pTmpFrame=0;
unsigned int tmpIdx = rxTd.idx;
volatile EmacRxTDescriptor *pRxTd = rxTd.td + rxTd.idx;
ASSERT(pFrame, "F: EMAC_Poll\n\r");
char isFrame = 0;
// Set the default return value
*pRcvSize = 0;
// Process received RxTd
while ((pRxTd->addr & EMAC_RX_OWNERSHIP_BIT) == EMAC_RX_OWNERSHIP_BIT) {
// A start of frame has been received, discard previous fragments
if ((pRxTd->status & EMAC_RX_SOF_BIT) == EMAC_RX_SOF_BIT) {
// Skip previous fragment
while (tmpIdx != rxTd.idx) {
pRxTd = rxTd.td + rxTd.idx;
pRxTd->addr &= ~(EMAC_RX_OWNERSHIP_BIT);
CIRC_INC(rxTd.idx, RX_BUFFERS);
}
// Reset the temporary frame pointer
pTmpFrame = pFrame;
tmpFrameSize = 0;
// Start to gather buffers in a frame
isFrame = 1;
}
// Increment the pointer
CIRC_INC(tmpIdx, RX_BUFFERS);
// Copy data in the frame buffer
if (isFrame) {
if (tmpIdx == rxTd.idx) {
trace_LOG(trace_INFO,
"I: no EOF (Invalid of buffers too small)\n\r");
do {
pRxTd = rxTd.td + rxTd.idx;
pRxTd->addr &= ~(EMAC_RX_OWNERSHIP_BIT);
CIRC_INC(rxTd.idx, RX_BUFFERS);
} while(tmpIdx != rxTd.idx);
return EMAC_RX_NO_DATA;
}
// Copy the buffer into the application frame
bufferLength = EMAC_RX_UNITSIZE;
if ((tmpFrameSize + bufferLength) > frameSize) {
bufferLength = frameSize - tmpFrameSize;
}
memcpy(pTmpFrame, (void*)(pRxTd->addr & EMAC_ADDRESS_MASK), bufferLength);
pTmpFrame += bufferLength;
tmpFrameSize += bufferLength;
// An end of frame has been received, return the data
if ((pRxTd->status & EMAC_RX_EOF_BIT) == EMAC_RX_EOF_BIT) {
// Frame size from the EMAC
*pRcvSize = (pRxTd->status & EMAC_LENGTH_FRAME);
// Application frame buffer is too small all data have not been copied
if (tmpFrameSize < *pRcvSize) {
printf("size req %u size allocated %u\n\r", *pRcvSize, frameSize);
return EMAC_RX_FRAME_SIZE_TOO_SMALL;
}
trace_LOG(trace_INFO, "packet %d-%u (%u)\n\r", rxTd.idx, tmpIdx, *pRcvSize);
// All data have been copied in the application frame buffer => release TD
while (rxTd.idx != tmpIdx) {
pRxTd = rxTd.td + rxTd.idx;
pRxTd->addr &= ~(EMAC_RX_OWNERSHIP_BIT);
CIRC_INC(rxTd.idx, RX_BUFFERS);
}
EmacStatistics.rx_packets++;
return EMAC_RX_OK;
}
}
// SOF has not been detected, skip the fragment
else {
pRxTd->addr &= ~(EMAC_RX_OWNERSHIP_BIT);
rxTd.idx = tmpIdx;
}
// Process the next buffer
pRxTd = rxTd.td + tmpIdx;
}
//trace_LOG(trace_DEBUG, "E");
return EMAC_RX_NO_DATA;
}
//-----------------------------------------------------------------------------
/// Registers pRxCb callback. Callback will be invoked after the next received
/// frame.
/// When EMAC_Poll() returns EMAC_RX_NO_DATA the application task call EMAC_Set_RxCb()
/// to register pRxCb() callback and enters suspend state. The callback is in charge
/// to resume the task once a new frame has been received. The next time EMAC_Poll()
/// is called, it will be successfull.
/// \param pRxCb Pointer to callback function
//-----------------------------------------------------------------------------
void EMAC_Set_RxCb(EMAC_RxCallback pRxCb)
{
rxTd.rxCb = pRxCb;
AT91C_BASE_EMAC->EMAC_IER = AT91C_EMAC_RCOMP;
}
//-----------------------------------------------------------------------------
/// Remove the RX callback function.
/// This function is usually invoked from the RX callback itself. Once the callback
/// has resumed the application task, there is no need to invoke the callback again.
//-----------------------------------------------------------------------------
void EMAC_Clear_RxCb(void)
{
AT91C_BASE_EMAC->EMAC_IDR = AT91C_EMAC_RCOMP;
rxTd.rxCb = (EMAC_RxCallback) 0;
}
//-----------------------------------------------------------------------------
/// Registers TX wakeup callback callback. Callback will be invoked once several
/// transfer descriptors are available.
/// When EMAC_Send() returns EMAC_TX_BUFFER_BUSY (all TD busy) the application
/// task calls EMAC_Set_TxWakeUpCb() to register pTxWakeUpCb() callback and
/// enters suspend state. The callback is in charge to resume the task once
/// several TD have been released. The next time EMAC_Send() will be called, it
/// shall be successfull.
/// \param pTxWakeUpCb Pointer to callback function
/// \param threshold Minimum number of available transfer descriptors before pTxWakeUpCb() is invoked
/// \return 0= success, 1 = threshold exceeds nuber of transfer descriptors
//-----------------------------------------------------------------------------
char EMAC_Set_TxWakeUpCb(EMAC_WakeupCallback pTxWakeUpCb, unsigned short threshold)
{
if (threshold <= TX_BUFFERS) {
txTd.wakeupCb = pTxWakeUpCb;
txTd.wakeupThreshold = threshold;
return 0;
}
return 1;
}
//-----------------------------------------------------------------------------
/// Remove the TX wakeup callback function.
/// This function is usually invoked from the TX wakeup callback itself. Once the callback
/// has resumed the application task, there is no need to invoke the callback again.
//-----------------------------------------------------------------------------
void EMAC_Clear_TxWakeUpCb(void)
{
txTd.wakeupCb = (EMAC_WakeupCallback) 0;
}

View file

@ -0,0 +1,161 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
// peripherals/emac/emac.h
#ifndef EMAC_H
#define EMAC_H
//-----------------------------------------------------------------------------
/// \dir
/// !Purpose
///
/// Definition of methods and structures for using EMAC
///
/// !Usage
///
/// -# Initialize EMAC with EMAC_Init.
/// -# Setup EMAC with EMAC_SetupTx, EMAC_SetupRx, EMAC_SetupMacAddress
/// and EMAC_SetupStack.
/// -# Drive the EMAC status machine by EMAC_Task.
/// -# EMAC_GetStatus give EMAC status machine current status
/// -# Send a packet to network with EMAC_SendPacket.
/// -# Get a packet from network with EMAC_GetPacket.
///
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Headers
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Definitions
//-----------------------------------------------------------------------------
/// Number of buffer for RX, be carreful: MUST be 2^n
#define RX_BUFFERS 16
/// Number of buffer for TX, be carreful: MUST be 2^n
#define TX_BUFFERS 8
/// Buffer Size
#define EMAC_RX_UNITSIZE 128 /// Fixed size for RX buffer
#define EMAC_TX_UNITSIZE 1518 /// Size for ETH frame length
// The MAC can support frame lengths up to 1536 bytes.
#define EMAC_FRAME_LENTGH_MAX 1536
//-----------------------------------------------------------------------------
// Types
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// Describes the statistics of the EMAC.
//-----------------------------------------------------------------------------
typedef struct _EmacStats {
// TX errors
unsigned int tx_packets; /// Total Number of packets sent
unsigned int tx_comp; /// Packet complete
unsigned int tx_errors; /// TX errors ( Retry Limit Exceed )
unsigned int collisions; /// Collision
unsigned int tx_exausts; /// Buffer exhausted
unsigned int tx_underruns; /// Under Run, not able to read from memory
// RX errors
unsigned int rx_packets; /// Total Number of packets RX
unsigned int rx_eof; /// No EOF error
unsigned int rx_ovrs; /// Over Run, not able to store to memory
unsigned int rx_bnas; /// Buffer is not available
} EmacStats, *PEmacStats;
//-----------------------------------------------------------------------------
// PHY Exported functions
//-----------------------------------------------------------------------------
extern unsigned char EMAC_SetMdcClock( unsigned int mck );
extern void EMAC_EnableMdio( void );
extern void EMAC_DisableMdio( void );
extern void EMAC_EnableMII( void );
extern void EMAC_EnableRMII( void );
extern unsigned char EMAC_ReadPhy(unsigned char PhyAddress,
unsigned char Address,
unsigned int *pValue,
unsigned int retry);
extern unsigned char EMAC_WritePhy(unsigned char PhyAddress,
unsigned char Address,
unsigned int Value,
unsigned int retry);
extern void EMAC_SetLinkSpeed(unsigned char speed,
unsigned char fullduplex);
//-----------------------------------------------------------------------------
// EMAC Exported functions
//-----------------------------------------------------------------------------
/// Callback used by send function
typedef void (*EMAC_TxCallback)(unsigned int status);
typedef void (*EMAC_RxCallback)(unsigned int status);
typedef void (*EMAC_WakeupCallback)(void);
extern void EMAC_Init( unsigned char id, const unsigned char *pMacAddress,
unsigned char enableCAF, unsigned char enableNBC );
#define EMAC_CAF_DISABLE 0
#define EMAC_CAF_ENABLE 1
#define EMAC_NBC_DISABLE 0
#define EMAC_NBC_ENABLE 1
extern void EMAC_Handler(void);
extern unsigned char EMAC_Send(void *pBuffer,
unsigned int size,
EMAC_TxCallback fEMAC_TxCallback);
/// Return for EMAC_Send function
#define EMAC_TX_OK 0
#define EMAC_TX_BUFFER_BUSY 1
#define EMAC_TX_INVALID_PACKET 2
extern unsigned char EMAC_Poll(unsigned char *pFrame,
unsigned int frameSize,
unsigned int *pRcvSize);
/// Return for EMAC_Poll function
#define EMAC_RX_OK 0
#define EMAC_RX_NO_DATA 1
#define EMAC_RX_FRAME_SIZE_TOO_SMALL 2
extern void EMAC_GetStatistics(EmacStats *pStats, unsigned char reset);
#endif // #ifndef EMAC_H

View file

@ -0,0 +1,362 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "lcd.h"
#include <board.h>
#include <utility/assert.h>
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Enables the LCD controller, after waiting for the specified number of
/// frames.
/// \param frames Number of frames before the LCD is enabled.
//------------------------------------------------------------------------------
void LCD_Enable(unsigned int frames)
{
ASSERT((frames & 0xFFFFFF80) == 0,
"LCD_Enable: Wrong frames value.\n\r");
AT91C_BASE_LCDC->LCDC_PWRCON = AT91C_LCDC_PWR | (frames << 1);
}
//------------------------------------------------------------------------------
/// Disables the LCD controller, after waiting for the specified number of
/// frames.
/// \param frames Number of frames before the LCD is shut down.
//------------------------------------------------------------------------------
void LCD_Disable(unsigned int frames)
{
ASSERT((frames & 0xFFFFFF80) == 0,
"LCD_Disable: Wrong frames value.\n\r");
AT91C_BASE_LCDC->LCDC_PWRCON = frames << 1;
}
//------------------------------------------------------------------------------
/// Enables the DMA of the LCD controller.
//------------------------------------------------------------------------------
void LCD_EnableDma()
{
AT91C_BASE_LCDC->LCDC_DMACON = AT91C_LCDC_DMAEN;
}
//------------------------------------------------------------------------------
/// Disables the DMA of the LCD controller.
//------------------------------------------------------------------------------
void LCD_DisableDma()
{
AT91C_BASE_LCDC->LCDC_DMACON = 0;
}
//------------------------------------------------------------------------------
/// Configures the internal clock of the LCD controller given the master clock of
/// the system and the desired pixel clock in MHz.
/// \param masterClock Master clock frequency.
/// \param pixelClock Pixel clock frequency.
//------------------------------------------------------------------------------
void LCD_SetPixelClock(unsigned int masterClock, unsigned int pixelClock)
{
AT91C_BASE_LCDC->LCDC_LCDCON1 = ((masterClock / (2 * pixelClock)) - 1) << 12;
}
//------------------------------------------------------------------------------
/// Sets the type of display used with the LCD controller.
/// \param displayType Type of display used.
//------------------------------------------------------------------------------
void LCD_SetDisplayType(unsigned int displayType)
{
unsigned int value;
ASSERT((displayType & ~AT91C_LCDC_DISTYPE) == 0,
"LCD_SetDisplayType: Wrong display type value.\n\r");
value = AT91C_BASE_LCDC->LCDC_LCDCON2;
value &= ~AT91C_LCDC_DISTYPE;
value |= displayType;
AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
}
//------------------------------------------------------------------------------
/// Sets the scan mode used by the LCD (either single scan or double-scan).
/// \param scanMode Scan mode to use.
//------------------------------------------------------------------------------
void LCD_SetScanMode(unsigned int scanMode)
{
unsigned int value;
ASSERT((scanMode & ~AT91C_LCDC_SCANMOD) == 0,
"LCD_SetScanMode: Wrong scan mode value.\n\r");
value = AT91C_BASE_LCDC->LCDC_LCDCON2;
value &= ~AT91C_LCDC_SCANMOD;
value |= scanMode;
AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
}
//------------------------------------------------------------------------------
/// Sets the number of bits per pixel used by the LCD display.
/// \param bitsPerPixel Number of bits per pixel to use.
//------------------------------------------------------------------------------
void LCD_SetBitsPerPixel(unsigned int bitsPerPixel)
{
unsigned int value;
ASSERT((bitsPerPixel & ~AT91C_LCDC_PIXELSIZE) == 0,
"LCD_SetScanMode: Wrong bitsPerPixel value.\n\r");
value = AT91C_BASE_LCDC->LCDC_LCDCON2;
value &= ~AT91C_LCDC_PIXELSIZE;
value |= bitsPerPixel;
AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
}
//------------------------------------------------------------------------------
/// Sets the LCDD, LCDVSYNC, LCDHSYNC, LCDDOTCLK and LCDDEN signal polarities.
/// \param lcdd LCDD signal polarity.
/// \param lcdvsync LCDVSYNC signal polarity.
/// \param lcdhsync LCDHSYNC signal polarity.
/// \param lcddotclk LCDDOTCLK signal polarity.
/// \param lcdden LCDDEN signal polarity.
//------------------------------------------------------------------------------
void LCD_SetPolarities(
unsigned int lcdd,
unsigned int lcdvsync,
unsigned int lcdhsync,
unsigned int lcddotclk,
unsigned int lcdden)
{
unsigned int value;
ASSERT((lcdd & ~AT91C_LCDC_INVVD) == 0,
"LCD_SetPolarities: Wrong lcdd value.\n\r");
ASSERT((lcdvsync & ~AT91C_LCDC_INVFRAME) == 0,
"LCD_SetPolarities: Wrong lcdvsync value.\n\r");
ASSERT((lcdhsync & ~AT91C_LCDC_INVLINE) == 0,
"LCD_SetPolarities: Wrong lcdhsync value.\n\r");
ASSERT((lcddotclk & ~AT91C_LCDC_INVCLK) == 0,
"LCD_SetPolarities: Wrong lcddotclk value.\n\r");
ASSERT((lcdden & ~AT91C_LCDC_INVDVAL) == 0,
"LCD_SetPolarities: Wrong lcdden value.\n\r");
value = AT91C_BASE_LCDC->LCDC_LCDCON2;
value &= 0xFFFFE0FF;
value |= lcdd | lcdvsync | lcdhsync | lcddotclk | lcdden;
AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
}
//------------------------------------------------------------------------------
/// Sets the LCD clock mode, i.e. always active or active only during display
/// period.
/// \param clockMode Clock mode to use.
//------------------------------------------------------------------------------
void LCD_SetClockMode(unsigned int clockMode)
{
unsigned int value;
ASSERT((clockMode & ~AT91C_LCDC_CLKMOD) == 0,
"LCD_SetScanMode: Wrong scan mode value.\n\r");
value = AT91C_BASE_LCDC->LCDC_LCDCON2;
value &= ~AT91C_LCDC_CLKMOD;
value |= clockMode;
AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
}
//------------------------------------------------------------------------------
/// Sets the format of the frame buffer memory.
/// \param format Memory ordering format.
//------------------------------------------------------------------------------
void LCD_SetMemoryFormat(unsigned int format)
{
unsigned int value;
ASSERT((format & ~AT91C_LCDC_MEMOR) == 0,
"LCD_SetMemoryFormat: Wrong memory format value.\n\r");
value = AT91C_BASE_LCDC->LCDC_LCDCON2;
value &= ~AT91C_LCDC_MEMOR;
value |= format;
AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
}
//------------------------------------------------------------------------------
/// Sets the size in pixel of the LCD display.
/// \param width Width in pixel of the LCD display.
/// \param height Height in pixel of the LCD display.
//------------------------------------------------------------------------------
void LCD_SetSize(unsigned int width, unsigned int height)
{
ASSERT(((width - 1) & 0xFFFFF800) == 0,
"LCD_SetSize: Wrong width value.\n\r");
ASSERT(((height - 1) & 0xFFFFF800) == 0,
"LCD_SetSize: Wrong height value.\n\r");
AT91C_BASE_LCDC->LCDC_LCDFRCFG = ((width - 1) << 21) | (height - 1);
}
//------------------------------------------------------------------------------
/// Sets the vertical timings of the LCD controller. Only meaningful when
/// using a TFT display.
/// \param vfp Number of idle lines at the end of a frame.
/// \param vbp Number of idle lines at the beginning of a frame.
/// \param vpw Vertical synchronization pulse width in number of lines.
/// \param vhdly Delay between LCDVSYNC edge and LCDHSYNC rising edge, in
/// LCDDOTCLK cycles.
//------------------------------------------------------------------------------
void LCD_SetVerticalTimings(
unsigned int vfp,
unsigned int vbp,
unsigned int vpw,
unsigned int vhdly)
{
ASSERT((vfp & 0xFFFFFF00) == 0,
"LCD_SetVerticalTimings: Wrong vfp value.\n\r");
ASSERT((vbp & 0xFFFFFF00) == 0,
"LCD_SetVerticalTimings: Wrong vbp value.\n\r");
ASSERT(((vpw-1) & 0xFFFFFFC0) == 0,
"LCD_SetVerticalTimings: Wrong vpw value.\n\r");
ASSERT(((vhdly-1) & 0xFFFFFFF0) == 0,
"LCD_SetVerticalTimings: Wrong vhdly value.\n\r");
AT91C_BASE_LCDC->LCDC_TIM1 = vfp
| (vbp << 8)
| ((vpw-1) << 16)
| ((vhdly-1) << 24);
}
//------------------------------------------------------------------------------
/// Sets the horizontal timings of the LCD controller. Meaningful for both
/// STN and TFT displays.
/// \param hbp Number of idle LCDDOTCLK cycles at the beginning of a line.
/// \param hpw Width of the LCDHSYNC pulse, in LCDDOTCLK cycles.
/// \param hfp Number of idel LCDDOTCLK cycles at the end of a line.
//------------------------------------------------------------------------------
void LCD_SetHorizontalTimings(
unsigned int hbp,
unsigned int hpw,
unsigned int hfp)
{
ASSERT(((hbp-1) & 0xFFFFFF00) == 0,
"LCD_SetHorizontalTimings: Wrong hbp value.\n\r");
ASSERT(((hpw-1) & 0xFFFFFFC0) == 0,
"LCD_SetHorizontalTimings: Wrong hpw value.\n\r");
ASSERT(((hfp-1) & 0xFFFFFF00) == 0,
"LCD_SetHorizontalTimings: Wrong hfp value.\n\r");
AT91C_BASE_LCDC->LCDC_TIM2 = (hbp-1) | ((hpw-1) << 8) | ((hfp-1) << 24);
}
//------------------------------------------------------------------------------
/// Sets the address of the frame buffer in the LCD controller DMA. When using
/// dual-scan mode, this is the upper frame buffer.
/// \param address Frame buffer address.
//------------------------------------------------------------------------------
void LCD_SetFrameBufferAddress(void *address)
{
AT91C_BASE_LCDC->LCDC_BA1 = (unsigned int) address;
}
//------------------------------------------------------------------------------
/// Sets the size in pixels of a frame (height * width * bpp).
/// \param frameSize Size of frame in pixels.
//------------------------------------------------------------------------------
void LCD_SetFrameSize(unsigned int frameSize)
{
ASSERT((frameSize & 0xFF800000) == 0,
"LCD_SetFrameSize: Wrong frameSize value.\n\r");
AT91C_BASE_LCDC->LCDC_FRMCFG = frameSize | (AT91C_BASE_LCDC->LCDC_FRMCFG & 0xFF000000);
}
//------------------------------------------------------------------------------
/// Sets the DMA controller burst length.
/// \param burstLength Desired burst length.
//------------------------------------------------------------------------------
void LCD_SetBurstLength(unsigned int burstLength)
{
ASSERT(((burstLength-1) & 0xFFFFFF80) == 0,
"LCD_SetBurstLength: Wrong burstLength value.\n\r");
AT91C_BASE_LCDC->LCDC_FRMCFG &= 0x00FFFFFF;
AT91C_BASE_LCDC->LCDC_FRMCFG |= ((burstLength-1) << 24);
AT91C_BASE_LCDC->LCDC_FIFO = 2048 - (2 * burstLength + 3);
}
//------------------------------------------------------------------------------
/// Sets the prescaler value of the contrast control PWM.
/// \param prescaler Desired prescaler value.
//------------------------------------------------------------------------------
void LCD_SetContrastPrescaler(unsigned int prescaler)
{
ASSERT((prescaler & ~AT91C_LCDC_PS) == 0,
"LCD_SetContrastPrescaler: Wrong prescaler value\n\r");
AT91C_BASE_LCDC->LCDC_CTRSTCON &= ~AT91C_LCDC_PS;
AT91C_BASE_LCDC->LCDC_CTRSTCON |= prescaler;
}
//------------------------------------------------------------------------------
/// Sets the polarity of the contrast PWM.
/// \param polarity PWM polarity
//------------------------------------------------------------------------------
void LCD_SetContrastPolarity(unsigned int polarity)
{
ASSERT((polarity & ~AT91C_LCDC_POL) == 0,
"LCD_SetContrastPolarity: Wrong polarity value\n\r");
AT91C_BASE_LCDC->LCDC_CTRSTCON &= ~AT91C_LCDC_POL;
AT91C_BASE_LCDC->LCDC_CTRSTCON |= polarity;
}
//------------------------------------------------------------------------------
/// Sets the threshold value of the constrast PWM.
/// \param value PWM threshold value.
//------------------------------------------------------------------------------
void LCD_SetContrastValue(unsigned int value)
{
ASSERT((value & ~AT91C_LCDC_CVAL) == 0,
"LCD_SetContrastValue: Wrong value.\n\r");
AT91C_BASE_LCDC->LCDC_CTRSTVAL = value;
}
//------------------------------------------------------------------------------
/// Enables the contrast PWM generator.
//------------------------------------------------------------------------------
void LCD_EnableContrast()
{
AT91C_BASE_LCDC->LCDC_CTRSTCON |= AT91C_LCDC_ENA_PWMGEMENABLED;
}

View file

@ -0,0 +1,92 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef LCD_H
#define LCD_H
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void LCD_Enable(unsigned int frames);
extern void LCD_Disable(unsigned int frames);
extern void LCD_EnableDma();
extern void LCD_DisableDma();
extern void LCD_SetPixelClock(unsigned int masterClock, unsigned int pixelClock);
extern void LCD_SetDisplayType(unsigned int displayType);
extern void LCD_SetScanMode(unsigned int scanMode);
extern void LCD_SetBitsPerPixel(unsigned int bitsPerPixel);
extern void LCD_SetPolarities(
unsigned int lcdd,
unsigned int lcdvsync,
unsigned int lcdhsync,
unsigned int lcddotclk,
unsigned int lcdden);
extern void LCD_SetClockMode(unsigned int clockMode);
extern void LCD_SetMemoryFormat(unsigned int format);
extern void LCD_SetSize(unsigned int width, unsigned int height);
extern void LCD_SetVerticalTimings(
unsigned int vfp,
unsigned int vbp,
unsigned int vpw,
unsigned int vhdly);
extern void LCD_SetHorizontalTimings(
unsigned int hbp,
unsigned int hpw,
unsigned int hfp);
extern void LCD_SetFrameBufferAddress(void *address);
extern void LCD_SetFrameSize(unsigned int frameSize);
extern void LCD_SetBurstLength(unsigned int burstLength);
extern void LCD_SetContrastPrescaler(unsigned int prescaler);
extern void LCD_SetContrastPolarity(unsigned int polarity);
extern void LCD_SetContrastValue(unsigned int value);
extern void LCD_EnableContrast();
#endif //#ifndef LCD_H

View file

@ -0,0 +1,551 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support - ROUSSET -
* ----------------------------------------------------------------------------
* Copyright (c) 2006, 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.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the disclaimer below in the documentation and/or
* other materials provided with the distribution.
*
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "mci.h"
#include <utility/assert.h>
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Local constants
//------------------------------------------------------------------------------
/// Bit mask for status register errors.
#define STATUS_ERRORS (AT91C_MCI_UNRE \
| AT91C_MCI_OVRE \
| AT91C_MCI_DTOE \
| AT91C_MCI_DCRCE \
| AT91C_MCI_RTOE \
| AT91C_MCI_RENDE \
| AT91C_MCI_RCRCE \
| AT91C_MCI_RDIRE \
| AT91C_MCI_RINDE)
/// MCI data timeout configuration with 1048576 MCK cycles between 2 data transfers.
#define DTOR_1MEGA_CYCLES (AT91C_MCI_DTOCYC | AT91C_MCI_DTOMUL)
#define SDCARD_APP_OP_COND_CMD (41 | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_TRCMD_NO )
#define MMC_SEND_OP_COND_CMD (1 | AT91C_MCI_TRCMD_NO | AT91C_MCI_SPCMD_NONE | AT91C_MCI_RSPTYP_48 | AT91C_MCI_OPDCMD)
#define DISABLE 0 // Disable MCI interface
#define ENABLE 1 // Enable MCI interface
//------------------------------------------------------------------------------
// Local macros
//------------------------------------------------------------------------------
/// Used to write in PMC registers.
#define WRITE_PMC(pPmc, regName, value) pPmc->regName = (value)
/// Used to write in MCI registers.
#define WRITE_MCI(pMci, regName, value) pMci->regName = (value)
/// Used to read from MCI registers.
#define READ_MCI(pMci, regName) (pMci->regName)
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Enable/disable a MCI driver instance.
/// \param pMci Pointer to a MCI driver instance.
/// \param enb 0 for disable MCI and 1 for enable MCI.
//------------------------------------------------------------------------------
void MCI_Enable(Mci *pMci, unsigned char enb)
{
AT91S_MCI *pMciHw = pMci->pMciHw;
SANITY_CHECK(pMci);
SANITY_CHECK(pMci->pMciHw);
// Set the Control Register: Enable/Disable MCI interface clock
if(enb == DISABLE) {
WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS);
}
else {
WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIEN);
}
}
//------------------------------------------------------------------------------
/// Initializes a MCI driver instance and the underlying peripheral.
/// \param pMci Pointer to a MCI driver instance.
/// \param pMciHw Pointer to a MCI peripheral.
/// \param mciId MCI peripheral identifier.
/// \param mode Slot and type of connected card.
//------------------------------------------------------------------------------
void MCI_Init(
Mci *pMci,
AT91S_MCI *pMciHw,
unsigned char mciId,
unsigned int mode)
{
unsigned short clkDiv;
SANITY_CHECK(pMci);
SANITY_CHECK(pMciHw);
SANITY_CHECK((mode == MCI_MMC_SLOTA) || (mode == MCI_MMC_SLOTB)
|| (mode == MCI_SD_SLOTA) || (mode == MCI_SD_SLOTB));
// Initialize the MCI driver structure
pMci->pMciHw = pMciHw;
pMci->mciId = mciId;
pMci->semaphore = 1;
pMci->pCommand = 0;
// Enable the MCI clock
WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << mciId));
// Reset the MCI
WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_SWRST);
// Disable the MCI
WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS | AT91C_MCI_PWSDIS);
// Disable all the interrupts
WRITE_MCI(pMciHw, MCI_IDR, 0xFFFFFFFF);
// Set the Data Timeout Register
WRITE_MCI(pMciHw, MCI_DTOR, DTOR_1MEGA_CYCLES);
// Set the Mode Register: 400KHz for MCK = 48MHz (CLKDIV = 58)
clkDiv = (BOARD_MCK / (400000 * 2)) - 1;
WRITE_MCI(pMciHw, MCI_MR, (clkDiv | (AT91C_MCI_PWSDIV & (0x7 << 8))));
// Set the SDCard Register
WRITE_MCI(pMciHw, MCI_SDCR, mode);
// Enable the MCI and the Power Saving
WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIEN);
// Disable the MCI peripheral clock.
WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << mciId));
}
//------------------------------------------------------------------------------
/// Close a MCI driver instance and the underlying peripheral.
/// \param pMci Pointer to a MCI driver instance.
/// \param pMciHw Pointer to a MCI peripheral.
/// \param mciId MCI peripheral identifier.
//------------------------------------------------------------------------------
void MCI_Close(Mci *pMci)
{
AT91S_MCI *pMciHw = pMci->pMciHw;
SANITY_CHECK(pMci);
SANITY_CHECK(pMciHw);
// Initialize the MCI driver structure
pMci->semaphore = 1;
pMci->pCommand = 0;
// Disable the MCI peripheral clock.
WRITE_PMC(AT91C_BASE_PMC, PMC_PCDR, (1 << pMci->mciId));
// Disable the MCI
WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS);
// Disable all the interrupts
WRITE_MCI(pMciHw, MCI_IDR, 0xFFFFFFFF);
}
//------------------------------------------------------------------------------
/// Configure the MCI CLKDIV in the MCI_MR register. The max. for MCI clock is
/// MCK/2 and corresponds to CLKDIV = 0
/// \param pMci Pointer to the low level MCI driver.
/// \param mciSpeed MCI clock speed in Hz.
//------------------------------------------------------------------------------
void MCI_SetSpeed(Mci *pMci, unsigned int mciSpeed)
{
AT91S_MCI *pMciHw = pMci->pMciHw;
unsigned int mciMr;
unsigned short clkdiv;
SANITY_CHECK(pMci);
SANITY_CHECK(pMci->pMciHw);
// Set the Mode Register: 400KHz for MCK = 48MHz (CLKDIV = 58)
mciMr = READ_MCI(pMciHw, MCI_MR) & (~AT91C_MCI_CLKDIV);
// Multimedia Card Interface clock (MCCK or MCI_CK) is Master Clock (MCK)
// divided by (2*(CLKDIV+1))
if (mciSpeed > 0) {
clkdiv = (BOARD_MCK / (mciSpeed * 2));
if (clkdiv > 0) {
clkdiv -= 1;
}
}
else {
clkdiv = 0;
}
WRITE_MCI(pMciHw, MCI_MR, mciMr | clkdiv);
}
//------------------------------------------------------------------------------
/// Configure the MCI SDCBUS in the MCI_SDCR register. Only two modes available
///
/// \param pMci Pointer to the low level MCI driver.
/// \param busWidth MCI bus width mode.
//------------------------------------------------------------------------------
void MCI_SetBusWidth(Mci *pMci, unsigned char busWidth)
{
AT91S_MCI *pMciHw = pMci->pMciHw;
unsigned int mciSdcr;
SANITY_CHECK(pMci);
SANITY_CHECK(pMci->pMciHw);
mciSdcr = (READ_MCI(pMciHw, MCI_SDCR) & ~(AT91C_MCI_SCDBUS));
WRITE_MCI(pMciHw, MCI_SDCR, mciSdcr | busWidth);
}
//------------------------------------------------------------------------------
/// Starts a MCI transfer. This is a non blocking function. It will return
/// as soon as the transfer is started.
/// Return 0 if successful; otherwise returns MCI_ERROR_LOCK if the driver is
/// already in use.
/// \param pMci Pointer to an MCI driver instance.
/// \param pCommand Pointer to the command to execute.
//------------------------------------------------------------------------------
unsigned char MCI_SendCommand(Mci *pMci, MciCmd *pCommand)
{
AT91PS_MCI pMciHw = pMci->pMciHw;
unsigned int mciIer, mciMr;
SANITY_CHECK(pMci);
SANITY_CHECK(pMciHw);
SANITY_CHECK(pCommand);
// Try to acquire the MCI semaphore
if (pMci->semaphore == 0) {
return MCI_ERROR_LOCK;
}
pMci->semaphore--;
// trace_LOG(trace_DEBUG, "MCI_SendCommand %x %d\n\r", READ_MCI(pMciHw, MCI_SR), pCommand->cmd & 0x3f);
// Command is now being executed
pMci->pCommand = pCommand;
pCommand->status = MCI_STATUS_PENDING;
// Enable the MCI clock
WRITE_PMC(AT91C_BASE_PMC, PMC_PCER, (1 << pMci->mciId));
//Disable MCI clock, for multi-block data transfer
MCI_Enable(pMci, DISABLE);
// Set PDC data transfer direction
if(pCommand->blockSize > 0) {
if(pCommand->isRead) {
WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTEN);
}
else {
WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_TXTEN);
}
}
// Disable transmitter and receiver
WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS);
mciMr = READ_MCI(pMciHw, MCI_MR) & (~(AT91C_MCI_BLKLEN | AT91C_MCI_PDCMODE));
// Command with DATA stage
if (pCommand->blockSize > 0) {
// Enable PDC mode and set block size
if(pCommand->conTrans != MCI_CONTINUE_TRANSFER) {
WRITE_MCI(pMciHw, MCI_MR, mciMr | AT91C_MCI_PDCMODE | (pCommand->blockSize << 16));
}
// DATA transfer from card to host
if (pCommand->isRead) {
WRITE_MCI(pMciHw, MCI_RPR, (int) pCommand->pData);
// If Multiblock command set the BLKR register
/* if (pCommand->nbBlock > 1) {
WRITE_MCI(pMciHw, MCI_BLKR, pCommand->nbBlock | (pCommand->blockSize << 16));
}
else {
WRITE_MCI(pMciHw, MCI_BLKR, (pCommand->blockSize << 16));
}*/
// Sanity check
if (pCommand->nbBlock == 0)
pCommand->nbBlock = 1;
////////
if ((pCommand->blockSize & 0x3) != 0) {
WRITE_MCI(pMciHw, MCI_RCR, (pCommand->nbBlock * pCommand->blockSize) / 4 + 1);
}
else {
WRITE_MCI(pMciHw, MCI_RCR, (pCommand->nbBlock * pCommand->blockSize) / 4);
}
WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_RXTEN);
mciIer = AT91C_MCI_ENDRX | STATUS_ERRORS;
// mciIer = AT91C_MCI_RXBUFF | STATUS_ERRORS;
}
// DATA transfer from host to card
else {
// Sanity check
if (pCommand->nbBlock == 0)
pCommand->nbBlock = 1;
WRITE_MCI(pMciHw, MCI_TPR, (int) pCommand->pData);
// Update the PDC counter
if ((pCommand->blockSize & 0x3) != 0) {
WRITE_MCI(pMciHw, MCI_TCR, (pCommand->nbBlock * pCommand->blockSize) / 4 + 1);
}
else {
WRITE_MCI(pMciHw, MCI_TCR, (pCommand->nbBlock * pCommand->blockSize) / 4);
}
// MCI_BLKE notifies the end of Multiblock command
mciIer = AT91C_MCI_BLKE | STATUS_ERRORS;
}
}
// No data transfer: stop at the end of the command
else {
WRITE_MCI(pMciHw, MCI_MR, mciMr);
mciIer = AT91C_MCI_CMDRDY | STATUS_ERRORS;
}
// Enable MCI clock
MCI_Enable(pMci, ENABLE);
// Send the command
if((pCommand->conTrans != MCI_CONTINUE_TRANSFER)
|| (pCommand->blockSize == 0)) {
WRITE_MCI(pMciHw, MCI_ARGR, pCommand->arg);
WRITE_MCI(pMciHw, MCI_CMDR, pCommand->cmd);
}
// In case of transmit, the PDC shall be enabled after sending the command
if ((pCommand->blockSize > 0) && !(pCommand->isRead)) {
WRITE_MCI(pMciHw, MCI_PTCR, AT91C_PDC_TXTEN);
}
// Ignore data error
// if (pCommand->blockSize == 0) {
{
mciIer &= ~(AT91C_MCI_UNRE | AT91C_MCI_OVRE \
| AT91C_MCI_DTOE | AT91C_MCI_DCRCE);
}
// Interrupt enable shall be done after PDC TXTEN and RXTEN
WRITE_MCI(pMciHw, MCI_IER, mciIer);
return 0;
}
//------------------------------------------------------------------------------
/// Check NOTBUSY and DTIP bits of status register on the given MCI driver.
/// Return value, 0 for bus ready, 1 for bus busy
/// \param pMci Pointer to a MCI driver instance.
//------------------------------------------------------------------------------
unsigned char MCI_CheckBusy(Mci *pMci)
{
AT91S_MCI *pMciHw = pMci->pMciHw;
unsigned int status;
// Enable MCI clock
MCI_Enable(pMci, ENABLE);
status = READ_MCI(pMciHw, MCI_SR);
// trace_LOG(trace_DEBUG, "status %x\n\r",status);
if(((status & AT91C_MCI_NOTBUSY)!=0)
&& ((status & AT91C_MCI_DTIP)==0)) {
// Disable MCI clock
MCI_Enable(pMci, DISABLE);
return 0;
}
else {
return 1;
}
}
//------------------------------------------------------------------------------
/// Check BLKE bit of status register on the given MCI driver.
/// \param pMci Pointer to a MCI driver instance.
//------------------------------------------------------------------------------
unsigned char MCI_CheckBlke(Mci *pMci)
{
AT91S_MCI *pMciHw = pMci->pMciHw;
unsigned int status;
status = READ_MCI(pMciHw, MCI_SR);
// trace_LOG(trace_DEBUG, "status %x\n\r",status);
if((status & AT91C_MCI_BLKE)!=0) {
return 0;
}
else {
return 1;
}
}
//------------------------------------------------------------------------------
/// Processes pending events on the given MCI driver.
/// \param pMci Pointer to a MCI driver instance.
//------------------------------------------------------------------------------
void MCI_Handler(Mci *pMci)
{
AT91S_MCI *pMciHw = pMci->pMciHw;
MciCmd *pCommand = pMci->pCommand;
unsigned int status;
unsigned char i;
#if defined(at91rm9200)
unsigned int mciCr, mciSdcr, mciMr, mciDtor;
#endif
SANITY_CHECK(pMci);
SANITY_CHECK(pMciHw);
SANITY_CHECK(pCommand);
// Read the status register
status = READ_MCI(pMciHw, MCI_SR) & READ_MCI(pMciHw, MCI_IMR);
// trace_LOG(trace_DEBUG, "status %x\n\r", status);
// Check if an error has occured
if ((status & STATUS_ERRORS) != 0) {
// Check error code
if ((status & STATUS_ERRORS) == AT91C_MCI_RTOE) {
pCommand->status = MCI_STATUS_NORESPONSE;
}
// if the command is SEND_OP_COND the CRC error flag is always present
// (cf : R3 response)
else if (((status & STATUS_ERRORS) != AT91C_MCI_RCRCE)
|| ((pCommand->cmd != SDCARD_APP_OP_COND_CMD)
&& (pCommand->cmd != MMC_SEND_OP_COND_CMD))) {
pCommand->status = MCI_STATUS_ERROR;
}
}
// Check if a transfer has been completed
if (((status & AT91C_MCI_CMDRDY) != 0)
|| ((status & AT91C_MCI_ENDRX) != 0)
|| ((status & AT91C_MCI_RXBUFF) != 0)
|| ((status & AT91C_MCI_ENDTX) != 0)
|| ((status & AT91C_MCI_BLKE) != 0)
|| ((status & AT91C_MCI_RTOE) != 0)) {
if (((status & AT91C_MCI_ENDRX) != 0)
|| ((status & AT91C_MCI_RXBUFF) != 0)
|| ((status & AT91C_MCI_ENDTX) != 0)) {
MCI_Enable(pMci, DISABLE);
}
/// On AT91RM9200-EK, if stop transmission, software reset MCI.
#if defined(at91rm9200)
if ((pCommand->cmd & AT91C_MCI_TRCMD_STOP) != 0) {
mciMr = READ_MCI(pMciHw, MCI_MR);
mciSdcr = READ_MCI(pMciHw, MCI_SDCR);
mciDtor = READ_MCI(pMciHw, MCI_DTOR);
WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_SWRST);
// trace_LOG(trace_DEBUG, "reset MCI\n\r");
WRITE_MCI(pMciHw, MCI_CR, AT91C_MCI_MCIDIS | AT91C_MCI_PWSDIS);
WRITE_MCI(pMciHw, MCI_MR, mciMr);
WRITE_MCI(pMciHw, MCI_SDCR, mciSdcr);
WRITE_MCI(pMciHw, MCI_DTOR, mciDtor);
}
#endif
// If no error occured, the transfer is successful
if (pCommand->status == MCI_STATUS_PENDING) {
pCommand->status = 0;
}
#if 0
if ((status & AT91C_MCI_CMDRDY) != 0)
trace_LOG(trace_DEBUG, ".");
if ((status & AT91C_MCI_ENDRX) != 0)
trace_LOG(trace_DEBUG, "<");
if ((status & AT91C_MCI_ENDTX) != 0)
trace_LOG(trace_DEBUG, "-");
if ((status & AT91C_MCI_BLKE) != 0)
trace_LOG(trace_DEBUG, ">");
trace_LOG(trace_DEBUG, "\n\r");
#endif
// Store the card response in the provided buffer
if (pCommand->pResp) {
for (i=0; i < pCommand->resSize; i++) {
pCommand->pResp[i] = READ_MCI(pMciHw, MCI_RSPR[0]);
}
}
// Disable interrupts
WRITE_MCI(pMciHw, MCI_IDR, READ_MCI(pMciHw, MCI_IMR));
// Release the semaphore
pMci->semaphore++;
// Invoke the callback associated with the current command (if any)
if (pCommand->callback) {
(pCommand->callback)(pCommand->status, pCommand);
}
}
}
//------------------------------------------------------------------------------
/// Returns 1 if the given MCI transfer is complete; otherwise returns 0.
/// \param pCommand Pointer to a MciCmd instance.
//------------------------------------------------------------------------------
unsigned char MCI_IsTxComplete(MciCmd *pCommand)
{
if (pCommand->status != MCI_STATUS_PENDING) {
if (pCommand->status != 0)
printf("MCI_IsTxComplete %d\n\r", pCommand->status);
return 1;
}
else {
return 0;
}
}

View file

@ -0,0 +1,159 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support - ROUSSET -
* ----------------------------------------------------------------------------
* Copyright (c) 2006, 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.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the disclaimer below in the documentation and/or
* other materials provided with the distribution.
*
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef MCI_H
#define MCI_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
/// Transfer is pending.
#define MCI_STATUS_PENDING 1
/// Transfer has been aborted because an error occured.
#define MCI_STATUS_ERROR 2
/// Card did not answer command.
#define MCI_STATUS_NORESPONSE 3
/// MCI driver is currently in use.
#define MCI_ERROR_LOCK 1
/// MCI configuration with 1-bit data bus on slot A (for MMC cards).
#define MCI_MMC_SLOTA 0
/// MCI configuration with 1-bit data bus on slot B (for MMC cards).
#define MCI_MMC_SLOTB 1
/// MCI configuration with 4-bit data bus on slot A (for SD cards).
#define MCI_SD_SLOTA AT91C_MCI_SCDBUS
/// MCI configuration with 4-bit data bus on slot B (for SD cards).
#define MCI_SD_SLOTB (AT91C_MCI_SCDBUS | 1)
/// Start new data transfer
#define MCI_NEW_TRANSFER 0
/// Continue data transfer
#define MCI_CONTINUE_TRANSFER 1
/// MCI SD Bus Width 1-bit
#define MCI_SDCBUS_1BIT (0 << 7)
/// MCI SD Bus Width 4-bit
#define MCI_SDCBUS_4BIT (1 << 7)
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
/// MCI end-of-transfer callback function.
typedef void (*MciCallback)(unsigned char status, void *pCommand);
//------------------------------------------------------------------------------
/// MCI Transfer Request prepared by the application upper layer. This structure
/// is sent to the MCI_SendCommand function to start the transfer. At the end of
/// the transfer, the callback is invoked by the interrupt handler.
//------------------------------------------------------------------------------
typedef struct _MciCmd {
/// Command status.
volatile char status;
/// Command code.
unsigned int cmd;
/// Command argument.
unsigned int arg;
/// Data buffer.
unsigned char *pData;
/// Size of data buffer in bytes.
unsigned short blockSize;
/// Number of blocks to be transfered
unsigned short nbBlock;
/// Indicate if continue to transfer data
unsigned char conTrans;
/// Indicates if the command is a read operation.
unsigned char isRead;
/// Response buffer.
unsigned int *pResp;
/// Size of SD card response in bytes.
unsigned char resSize;
/// Optional user-provided callback function.
MciCallback callback;
/// Optional argument to the callback function.
void *pArg;
} MciCmd;
//------------------------------------------------------------------------------
/// MCI driver structure. Holds the internal state of the MCI driver and
/// prevents parallel access to a MCI peripheral.
//------------------------------------------------------------------------------
typedef struct {
/// Pointer to a MCI peripheral.
AT91S_MCI *pMciHw;
/// MCI peripheral identifier.
unsigned char mciId;
/// Pointer to currently executing command.
MciCmd *pCommand;
/// Mutex.
volatile char semaphore;
} Mci;
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void MCI_Init(
Mci *pMci,
AT91PS_MCI pMciHw,
unsigned char mciId,
unsigned int mode);
extern void MCI_SetSpeed(Mci *pMci, unsigned int mciSpeed);
extern unsigned char MCI_SendCommand(Mci *pMci, MciCmd *pMciCmd);
extern void MCI_Handler(Mci *pMci);
extern unsigned char MCI_IsTxComplete(MciCmd *pMciCmd);
extern unsigned char MCI_CheckBusy(Mci *pMci);
extern void MCI_Close(Mci *pMci);
extern void MCI_SetBusWidth(Mci *pMci, unsigned char busWidth);
#endif //#ifndef MCI_H

View file

@ -0,0 +1,336 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "pio.h"
#include <board.h>
//------------------------------------------------------------------------------
// Internal definitions
//------------------------------------------------------------------------------
/// \internal Returns the current value of a register.
#define READ(peripheral, register) (peripheral->register)
/// \internal Modifies the current value of a register.
#define WRITE(peripheral, register, value) (peripheral->register = value)
//------------------------------------------------------------------------------
// Internal functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures one or more pin(s) of a PIO controller as being controlled by
/// peripheral A. Optionally, the corresponding internal pull-up(s) can be
/// enabled.
/// \param pio Pointer to a PIO controller.
/// \param mask Bitmask of one or more pin(s) to configure.
/// \param enablePullUp Indicates if the pin(s) internal pull-up shall be
/// configured.
//------------------------------------------------------------------------------
static void PIO_SetPeripheralA(AT91S_PIO *pio,
unsigned int mask,
unsigned char enablePullUp)
{
// Disable interrupts on the pin(s)
WRITE(pio, PIO_IDR, mask);
// Enable the pull-up(s) if necessary
if (enablePullUp) {
WRITE(pio, PIO_PPUER, mask);
}
else {
WRITE(pio, PIO_PPUDR, mask);
}
// Configure pin
WRITE(pio, PIO_ASR, mask);
WRITE(pio, PIO_PDR, mask);
}
//------------------------------------------------------------------------------
/// Configures one or more pin(s) of a PIO controller as being controlled by
/// peripheral A. Optionally, the corresponding internal pull-up(s) can be
/// enabled.
/// \param pio Pointer to a PIO controller.
/// \param mask Bitmask of one or more pin(s) to configure.
/// \param enablePullUp Indicates if the pin(s) internal pull-up shall be
/// configured.
//------------------------------------------------------------------------------
static void PIO_SetPeripheralB(AT91S_PIO *pio,
unsigned int mask,
unsigned char enablePullUp)
{
// Disable interrupts on the pin(s)
WRITE(pio, PIO_IDR, mask);
// Enable the pull-up(s) if necessary
if (enablePullUp) {
WRITE(pio, PIO_PPUER, mask);
}
else {
WRITE(pio, PIO_PPUDR, mask);
}
// Configure pin
WRITE(pio, PIO_BSR, mask);
WRITE(pio, PIO_PDR, mask);
}
//------------------------------------------------------------------------------
/// Configures one or more pin(s) or a PIO controller as inputs. Optionally,
/// the corresponding internal pull-up(s) and glitch filter(s) can be
/// enabled.
/// \param pio Pointer to a PIO controller.
/// \param mask Bitmask indicating which pin(s) to configure as input(s).
/// \param enablePullUp Indicates if the internal pull-up(s) must be enabled.
/// \param enableFilter Indicates if the glitch filter(s) must be enabled.
//------------------------------------------------------------------------------
static void PIO_SetInput(AT91S_PIO *pio,
unsigned int mask,
unsigned char enablePullUp,
unsigned char enableFilter)
{
// Disable interrupts
WRITE(pio, PIO_IDR, mask);
// Enable pull-up(s) if necessary
if (enablePullUp) {
WRITE(pio, PIO_PPUER, mask);
}
else {
WRITE(pio, PIO_PPUDR, mask);
}
// Enable filter(s) if necessary
if (enableFilter) {
WRITE(pio, PIO_IFER, mask);
}
else {
WRITE(pio, PIO_IFDR, mask);
}
// Configure pin as input
WRITE(pio, PIO_ODR, mask);
WRITE(pio, PIO_PER, mask);
}
//------------------------------------------------------------------------------
/// Configures one or more pin(s) of a PIO controller as outputs, with the
/// given default value. Optionally, the multi-drive feature can be enabled
/// on the pin(s).
/// \param pio Pointer to a PIO controller.
/// \param mask Bitmask indicating which pin(s) to configure.
/// \param defaultValue Default level on the pin(s).
/// \param enableMultiDrive Indicates if the pin(s) shall be configured as
/// open-drain.
/// \param enablePullUp Indicates if the pin shall have its pull-up activated.
//------------------------------------------------------------------------------
static void PIO_SetOutput(AT91S_PIO *pio,
unsigned int mask,
unsigned char defaultValue,
unsigned char enableMultiDrive,
unsigned char enablePullUp)
{
// Disable interrupts
WRITE(pio, PIO_IDR, mask);
// Enable pull-up(s) if necessary
if (enablePullUp) {
WRITE(pio, PIO_PPUER, mask);
}
else {
WRITE(pio, PIO_PPUDR, mask);
}
// Enable multi-drive if necessary
if (enableMultiDrive) {
WRITE(pio, PIO_MDER, mask);
}
else {
WRITE(pio, PIO_MDDR, mask);
}
// Set default value
if (defaultValue) {
WRITE(pio, PIO_SODR, mask);
}
else {
WRITE(pio, PIO_CODR, mask);
}
// Configure pin(s) as output(s)
WRITE(pio, PIO_OER, mask);
WRITE(pio, PIO_PER, mask);
}
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures a list of Pin instances, which can either hold a single pin or a
/// group of pins, depending on the mask value; all pins are configured by this
/// function.
/// Returns 1 if the configuration has been performed successfully; otherwise 0.
/// \param list Pointer to a list of Pin instances.
/// \param size Size of the Pin list (see <PIO_LISTSIZE>).
//------------------------------------------------------------------------------
unsigned char PIO_Configure(const Pin *list, unsigned int size)
{
// Configure pins
while (size > 0) {
switch (list->type) {
case PIO_PERIPH_A:
PIO_SetPeripheralA(list->pio,
list->mask,
(list->attribute & PIO_PULLUP) ? 1 : 0);
break;
case PIO_PERIPH_B:
PIO_SetPeripheralB(list->pio,
list->mask,
(list->attribute & PIO_PULLUP) ? 1 : 0);
break;
case PIO_INPUT:
AT91C_BASE_PMC->PMC_PCER = 1 << list->id;
PIO_SetInput(list->pio,
list->mask,
(list->attribute & PIO_PULLUP) ? 1 : 0,
(list->attribute & PIO_DEGLITCH)? 1 : 0);
break;
case PIO_OUTPUT_0:
case PIO_OUTPUT_1:
PIO_SetOutput(list->pio,
list->mask,
(list->type == PIO_OUTPUT_1),
(list->attribute & PIO_OPENDRAIN) ? 1 : 0,
(list->attribute & PIO_PULLUP) ? 1 : 0);
break;
default: return 0;
}
list++;
size--;
}
return 1;
}
//------------------------------------------------------------------------------
/// Sets a high output level on one or more pin(s) (if configured as output(s)).
/// \param pin Pointer to a Pin instance describing one or more pins.
//------------------------------------------------------------------------------
void PIO_Set(const Pin *pin)
{
WRITE(pin->pio, PIO_SODR, pin->mask);
}
//------------------------------------------------------------------------------
/// Sets a low output level on one or more pin(s) (if configured as output(s)).
/// \param pin Pointer to a Pin instance describing one or more pins.
//------------------------------------------------------------------------------
void PIO_Clear(const Pin *pin)
{
WRITE(pin->pio, PIO_CODR, pin->mask);
}
//------------------------------------------------------------------------------
/// Returns 1 if one or more PIO of the given Pin instance currently have a high
/// level; otherwise returns 0.
/// \param pin Pointer to a Pin instance describing one or more pins.
//------------------------------------------------------------------------------
unsigned char PIO_Get(const Pin *pin)
{
unsigned int reg;
if ((pin->type == PIO_OUTPUT_0) || (pin->type == PIO_OUTPUT_1)) {
reg = READ(pin->pio, PIO_ODSR);
}
else {
reg = READ(pin->pio, PIO_PDSR);
}
if ((reg & pin->mask) == 0) {
return 0;
}
else {
return 1;
}
}
//------------------------------------------------------------------------------
/// Returns 1 if one or more PIO of the given Pin data to be driven on the I/O line
/// level; otherwise returns 0.
/// \param pin Pointer to a Pin instance describing one or more pins.
//------------------------------------------------------------------------------
unsigned char PIO_GetOutputDataStatus(const Pin *pin)
{
if ((READ(pin->pio, PIO_ODSR) & pin->mask) == 0) {
return 0;
}
else {
return 1;
}
}
//------------------------------------------------------------------------------
/// Returns the value of ISR for the PIO controller of the pin.
/// Reading this register acknoledges all the ITs.
/// \param pin Pointer to a Pin instance describing one or more pins.
//------------------------------------------------------------------------------
unsigned int PIO_GetISR(const Pin *pin)
{
return (READ(pin->pio, PIO_ISR));
}

View file

@ -0,0 +1,169 @@
/* ----------------------------------------------------------------------------
* 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
/// !Purpose
///
/// Definition of methods and structures for using PIOs in a transparent
/// way. The main purpose is to allow portability between several boards.
///
/// !Usage
///
/// -# To configure and use pins, see pio.h.
/// -# To enable and use interrupt generation on PIO status change, see
/// pio_it.h.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \unit
/// !Purpose
///
/// Simple & portable usage of PIO pins.
///
/// !Usage
///
/// -# Define a constant pin description array such as the following one:
/// \code
/// const Pin at91board_dbgu[] = {
/// {AT91C_BASE_PIOA, (1 << 30), PIO_PERIPH_A, PIO_DEFAULT},
/// {AT91C_BASE_PIOA, (1 << 31), PIO_PERIPH_A, PIO_DEFAULT},
/// };
/// \endcode
/// Alternatively, constants defined in the piodefs.h header file of the
/// board module can be used:
/// \code
/// const Pin at91board_dbgu[] = {PINS_DBGU};
/// const Pin at91board_usart[] = {PIN_USART0_RXD, PIN_USART0_TXD};
/// \endcode
/// It is possible to group multiple pins if they share the same
/// attributes, to save memory. Here is the previous DBGU example
/// rewritten in such a way:
/// \code
/// const Pin at91board_dbgu[] = {
/// {AT91C_BASE_PIOA, 0xC0000000, PIO_PERIPH_A, PIO_DEFAULT}
/// };
/// \endcode
/// -# For pins configured as inputs, the PIO controller must be enabled
/// in the PMC (*enabled by PIO_Configure at the moment*).
/// -# Configure a pin array by calling PIO_Configure, using
/// the PIO_LISTSIZE macro to calculate the array size if needed. Do not
/// forget to check the return value for any error.
/// -# Set and get the value of a pin using the PIO_Set, PIO_Clear and
/// PIO_Get methods.
//------------------------------------------------------------------------------
#ifndef PIO_H
#define PIO_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "Pin types"
/// This page lists the available types for a Pin instance (in its type field).
/// !Types
/// - PIO_PERIPH_A
/// - PIO_PERIPH_B
/// - PIO_INPUT
/// - PIO_OUTPUT_0
/// - PIO_OUTPUT_1
/// The pin is controlled by the associated signal of peripheral A.
#define PIO_PERIPH_A 0
/// The pin is controlled by the associated signal of peripheral B.
#define PIO_PERIPH_B 1
/// The pin is an input.
#define PIO_INPUT 2
/// The pin is an output and has a default level of 0.
#define PIO_OUTPUT_0 3
/// The pin is an output and has a default level of 1.
#define PIO_OUTPUT_1 4
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "Pin attributes"
/// This page lists the valid values for the attribute field of a Pin instance.
/// !Attributes
/// - PIO_DEFAULT
/// - PIO_PULLUP
/// - PIO_DEGLITCH
/// - PIO_OPENDRAIN
/// Default pin configuration (no attribute).
#define PIO_DEFAULT (0 << 0)
/// The internal pin pull-up is active.
#define PIO_PULLUP (1 << 0)
/// The internal glitch filter is active.
#define PIO_DEGLITCH (1 << 1)
/// The pin is open-drain.
#define PIO_OPENDRAIN (1 << 2)
//------------------------------------------------------------------------------
/// Calculates the size of a Pin instances array. The array must be local (i.e.
/// not a pointer), otherwise the computation will not be correct.
#define PIO_LISTSIZE(list) (sizeof(list) / sizeof(Pin))
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Describes the type and attribute of one PIO pin or a group of similar pins.
typedef struct {
/// Bitmask indicating which pin(s) to configure.
unsigned int mask;
/// Pointer to the PIO controller which has the pin(s).
AT91S_PIO *pio;
/// Peripheral ID of the PIO controller which has the pin(s).
unsigned char id;
/// Pin type (see "Pin types").
unsigned char type;
/// Pin attribute (see "Pin attributes").
unsigned char attribute;
} Pin;
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern unsigned char PIO_Configure(const Pin *list, unsigned int size);
extern void PIO_Set(const Pin *pin );
extern void PIO_Clear(const Pin *pin);
extern unsigned char PIO_Get(const Pin *pin);
extern unsigned int PIO_GetISR(const Pin *pin);
extern unsigned char PIO_GetOutputDataStatus(const Pin *pin);
#endif //#ifndef PIO_H

View file

@ -0,0 +1,387 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
/// Disable traces for this file
#ifndef NOTRACE
#define NOTRACE
#endif
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "pio_it.h"
#include "pio.h"
#include <aic/aic.h>
#include <board.h>
#include <utility/assert.h>
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Local definitions
//------------------------------------------------------------------------------
/// Returns the current value of a register.
#define READ(peripheral, register) (peripheral->register)
/// Modifies the current value of a register.
#define WRITE(peripheral, register, value) (peripheral->register = value)
/// Maximum number of interrupt sources that can be defined.
#define MAX_INTERRUPT_SOURCES 7
//------------------------------------------------------------------------------
// Local types
//------------------------------------------------------------------------------
/// Describes a PIO interrupt source, including the PIO instance triggering the
/// interrupt and the associated interrupt handler.
typedef struct _InterruptSource {
/// Interrupt source pin.
const Pin *pPin;
/// Interrupt handler.
void (*handler)(const Pin *);
} InterruptSource;
//------------------------------------------------------------------------------
// Local variables
//------------------------------------------------------------------------------
/// List of interrupt sources.
static InterruptSource pSources[MAX_INTERRUPT_SOURCES];
/// Number of currently defined interrupt sources.
static unsigned int numSources;
//------------------------------------------------------------------------------
// Local functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Handles all interrupts on the given PIO controller.
/// \param id PIO controller ID.
/// \param pBase PIO controller base address.
//------------------------------------------------------------------------------
void PioInterruptHandler(unsigned int id, AT91S_PIO *pBase)
{
unsigned int status;
unsigned int i;
// Check PIO controller status
status = pBase->PIO_ISR;
status &= pBase->PIO_IMR;
if (status != 0) {
trace_LOG(trace_DEBUG, "-D- PIO interrupt on PIO controller #%d\n\r", id);
// Check all sources
i = 0;
while (status != 0) {
// There cannot be an unconfigured source enabled.
SANITY_CHECK(i < numSources);
// Source if configured on PIOA
if (pSources[i].pPin->id == id) {
// Source has PIOs which have changed
if ((status & pSources[i].pPin->mask) != 0) {
trace_LOG(trace_DEBUG, "-D- Interrupt source #%d triggered\n\r", i);
pSources[i].handler(pSources[i].pPin);
status &= ~(pSources[i].pPin->mask);
}
}
i++;
}
}
}
//------------------------------------------------------------------------------
/// Generic PIO interrupt handler. Single entry point for interrupts coming
/// from any PIO controller (PIO A, B, C ...). Dispatches the interrupt to
/// the user-configured handlers.
//------------------------------------------------------------------------------
void InterruptHandler()
{
#if defined(AT91C_ID_PIOA)
// Treat PIOA interrupts
PioInterruptHandler(AT91C_ID_PIOA, AT91C_BASE_PIOA);
#endif
#if defined(AT91C_ID_PIOB)
// Treat PIOB interrupts
PioInterruptHandler(AT91C_ID_PIOB, AT91C_BASE_PIOB);
#endif
#if defined(AT91C_ID_PIOC)
// Treat PIOC interrupts
PioInterruptHandler(AT91C_ID_PIOC, AT91C_BASE_PIOC);
#endif
#if defined(AT91C_ID_PIOD)
// Treat PIOD interrupts
PioInterruptHandler(AT91C_ID_PIOD, AT91C_BASE_PIOD);
#endif
#if defined(AT91C_ID_PIOE)
// Treat PIOE interrupts
PioInterruptHandler(AT91C_ID_PIOE, AT91C_BASE_PIOE);
#endif
#if defined(AT91C_ID_PIOABCD)
// Treat PIOABCD interrupts
#if !defined(AT91C_ID_PIOA)
PioInterruptHandler(AT91C_ID_PIOABCD, AT91C_BASE_PIOA);
#endif
#if !defined(AT91C_ID_PIOB)
PioInterruptHandler(AT91C_ID_PIOABCD, AT91C_BASE_PIOB);
#endif
#if !defined(AT91C_ID_PIOC)
PioInterruptHandler(AT91C_ID_PIOABCD, AT91C_BASE_PIOC);
#endif
#if !defined(AT91C_ID_PIOD)
PioInterruptHandler(AT91C_ID_PIOABCD, AT91C_BASE_PIOD);
#endif
#endif
#if defined(AT91C_ID_PIOABCDE)
// Treat PIOABCDE interrupts
#if !defined(AT91C_ID_PIOA)
PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOA);
#endif
#if !defined(AT91C_ID_PIOB)
PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOB);
#endif
#if !defined(AT91C_ID_PIOC)
PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOC);
#endif
#if !defined(AT91C_ID_PIOD)
PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOD);
#endif
#if !defined(AT91C_ID_PIOE)
PioInterruptHandler(AT91C_ID_PIOABCDE, AT91C_BASE_PIOE);
#endif
#endif
#if defined(AT91C_ID_PIOCDE)
// Treat PIOCDE interrupts
#if !defined(AT91C_ID_PIOC)
PioInterruptHandler(AT91C_ID_PIOCDE, AT91C_BASE_PIOC);
#endif
#if !defined(AT91C_ID_PIOD)
PioInterruptHandler(AT91C_ID_PIOCDE, AT91C_BASE_PIOD);
#endif
#if !defined(AT91C_ID_PIOE)
PioInterruptHandler(AT91C_ID_PIOCDE, AT91C_BASE_PIOE);
#endif
#endif
}
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Initializes the PIO interrupt management logic.
/// \param priority PIO controller interrupts priority.
//------------------------------------------------------------------------------
void PIO_InitializeInterrupts(unsigned int priority)
{
trace_LOG(trace_DEBUG, "-D- PIO_Initialize()\n\r");
SANITY_CHECK((priority & ~AT91C_AIC_PRIOR) == 0);
// Reset sources
numSources = 0;
#ifdef AT91C_ID_PIOA
// Configure PIO interrupt sources
trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOA\n\r");
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOA;
AT91C_BASE_PIOA->PIO_ISR;
AT91C_BASE_PIOA->PIO_IDR = 0xFFFFFFFF;
AIC_ConfigureIT(AT91C_ID_PIOA, priority, InterruptHandler);
AIC_EnableIT(AT91C_ID_PIOA);
#endif
#ifdef AT91C_ID_PIOB
trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOB\n\r");
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOB;
AT91C_BASE_PIOB->PIO_ISR;
AT91C_BASE_PIOB->PIO_IDR = 0xFFFFFFFF;
AIC_ConfigureIT(AT91C_ID_PIOB, priority, InterruptHandler);
AIC_EnableIT(AT91C_ID_PIOB);
#endif
#ifdef AT91C_ID_PIOC
trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOC\n\r");
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOC;
AT91C_BASE_PIOC->PIO_ISR;
AT91C_BASE_PIOC->PIO_IDR = 0xFFFFFFFF;
AIC_ConfigureIT(AT91C_ID_PIOC, priority, InterruptHandler);
AIC_EnableIT(AT91C_ID_PIOC);
#endif
#ifdef AT91C_ID_PIOD
trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOD\n\r");
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOD;
AT91C_BASE_PIOC->PIO_ISR;
AT91C_BASE_PIOC->PIO_IDR = 0xFFFFFFFF;
AIC_ConfigureIT(AT91C_ID_PIOD, priority, InterruptHandler);
AIC_EnableIT(AT91C_ID_PIOD);
#endif
#ifdef AT91C_ID_PIOE
trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOE\n\r");
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOE;
AT91C_BASE_PIOC->PIO_ISR;
AT91C_BASE_PIOC->PIO_IDR = 0xFFFFFFFF;
AIC_ConfigureIT(AT91C_ID_PIOE, priority, InterruptHandler);
AIC_EnableIT(AT91C_ID_PIOE);
#endif
#if defined(AT91C_ID_PIOABCD)
// Treat PIOABCD interrupts
#if !defined(AT91C_ID_PIOA) \
&& !defined(AT91C_ID_PIOB) \
&& !defined(AT91C_ID_PIOC) \
&& !defined(AT91C_ID_PIOD)
trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOABCD\n\r");
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOABCD;
AT91C_BASE_PIOA->PIO_ISR;
AT91C_BASE_PIOA->PIO_IDR = 0xFFFFFFFF;
AIC_ConfigureIT(AT91C_ID_PIOABCD, priority, InterruptHandler);
AIC_EnableIT(AT91C_ID_PIOABCD);
#endif
#endif
#if defined(AT91C_ID_PIOABCDE)
// Treat PIOABCDE interrupts
#if !defined(AT91C_ID_PIOA) \
&& !defined(AT91C_ID_PIOB) \
&& !defined(AT91C_ID_PIOC) \
&& !defined(AT91C_ID_PIOD) \
&& !defined(AT91C_ID_PIOE)
trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOABCDE\n\r");
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOABCDE;
AT91C_BASE_PIOA->PIO_ISR;
AT91C_BASE_PIOA->PIO_IDR = 0xFFFFFFFF;
AIC_ConfigureIT(AT91C_ID_PIOABCDE, priority, InterruptHandler);
AIC_EnableIT(AT91C_ID_PIOABCDE);
#endif
#endif
#if defined(AT91C_ID_PIOCDE)
// Treat PIOCDE interrupts
#if !defined(AT91C_ID_PIOC) \
&& !defined(AT91C_ID_PIOD) \
&& !defined(AT91C_ID_PIOE)
trace_LOG(trace_DEBUG, "-D- PIO_Initialize: Configuring PIOC\n\r");
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_PIOCDE;
AT91C_BASE_PIOC->PIO_ISR;
AT91C_BASE_PIOC->PIO_IDR = 0xFFFFFFFF;
AIC_ConfigureIT(AT91C_ID_PIOCDE, priority, InterruptHandler);
AIC_EnableIT(AT91C_ID_PIOCDE);
#endif
#endif
}
//------------------------------------------------------------------------------
/// Configures an interrupt source.
/// \param pPin Interrupt source.
/// \param handler Desired interrupt handler for the source.
//------------------------------------------------------------------------------
void PIO_ConfigureIt(const Pin *pPin, void (*handler)(const Pin *))
{
InterruptSource *pSource;
trace_LOG(trace_DEBUG, "-D- PIO_ConfigureIt()\n\r");
SANITY_CHECK(pPin);
ASSERT(numSources < MAX_INTERRUPT_SOURCES,
"-F- PIO_ConfigureIt: Increase MAX_INTERRUPT_SOURCES\n\r");
// Define new source
trace_LOG(trace_DEBUG, "-D- PIO_ConfigureIt: Defining new source #%d.\n\r", numSources);
pSource = &(pSources[numSources]);
pSource->pPin = pPin;
pSource->handler = handler;
numSources++;
}
//------------------------------------------------------------------------------
/// Enables the given interrupt source if it has been configured.
/// \param pPin Interrupt source to enable.
//------------------------------------------------------------------------------
void PIO_EnableIt(const Pin *pPin)
{
trace_LOG(trace_DEBUG, "-D- PIO_EnableIt()\n\r");
SANITY_CHECK(pPin);
#ifndef NOASSERT
unsigned int i = 0;
unsigned char found = 0;
while ((i < numSources) && !found) {
if (pSources[i].pPin == pPin) {
found = 1;
}
i++;
}
ASSERT(found, "-F- PIO_EnableIt: Interrupt source has not been configured\n\r");
#endif
pPin->pio->PIO_ISR;
pPin->pio->PIO_IER = pPin->mask;
}
//------------------------------------------------------------------------------
/// Disables a given interrupt source.
/// \param pPin Interrupt source to disable.
//------------------------------------------------------------------------------
void PIO_DisableIt(const Pin *pPin)
{
SANITY_CHECK(pPin);
trace_LOG(trace_DEBUG, "-D- PIO_DisableIt()\n\r");
pPin->pio->PIO_IDR = pPin->mask;
}

View file

@ -0,0 +1,61 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
/// !Purpose
///
/// Configuration and handling of interrupts on PIO status changes.
///
/// !Usage
///
/// -# Configure an status change interrupt on one or more pin(s) with
/// PIO_ConfigureIt.
/// -# Enable & disable interrupts on pins using PIO_EnableIt and
/// PIO_DisableIt.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "pio.h"
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void PIO_InitializeInterrupts(unsigned int priority);
extern void PIO_ConfigureIt(const Pin *pPin, void (*handler)(const Pin *));
extern void PIO_EnableIt(const Pin *pPin);
extern void PIO_DisableIt(const Pin *pPin);

View file

@ -0,0 +1,115 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "pit.h"
#include <board.h>
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Initialize the System timer for a period in µsecond with a system clock
/// freq in MHz
/// \param period Period in µsecond.
/// \param pit_frequency System clock frequency in MHz.
//------------------------------------------------------------------------------
void PIT_Init(unsigned int period,
unsigned int pit_frequency)
{
AT91C_BASE_PITC->PITC_PIMR = period? (period * pit_frequency + 8) >> 4 : 0; // +8 to avoid %10 and /10
AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITEN;
}
//------------------------------------------------------------------------------
/// Set the PIT Periodic Interval Value
//------------------------------------------------------------------------------
void PIT_SetPIV(unsigned int piv)
{
AT91C_BASE_PITC->PITC_PIMR = piv | (AT91C_BASE_PITC->PITC_PIMR & (AT91C_PITC_PITEN | AT91C_PITC_PITIEN));
}
//------------------------------------------------------------------------------
/// Enable the PIT
//------------------------------------------------------------------------------
void PIT_Enable(void)
{
AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITEN;
}
//----------------------------------------------------------------------------
/// Enable PIT periodic interrupt
//----------------------------------------------------------------------------
void PIT_EnableIT(void)
{
AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITIEN;
}
//------------------------------------------------------------------------------
/// Disable PIT periodic interrupt
//------------------------------------------------------------------------------
void PIT_DisableIT(void)
{
AT91C_BASE_PITC->PITC_PIMR &= ~AT91C_PITC_PITIEN;
}
//------------------------------------------------------------------------------
/// Read PIT mode register
//------------------------------------------------------------------------------
unsigned int PIT_GetMode(void)
{
return(AT91C_BASE_PITC->PITC_PIMR);
}
//------------------------------------------------------------------------------
/// Read PIT status register
//------------------------------------------------------------------------------
unsigned int PIT_GetStatus(void)
{
return(AT91C_BASE_PITC->PITC_PISR);
}
//------------------------------------------------------------------------------
/// Read PIT CPIV and PICNT without ressetting the counters
//------------------------------------------------------------------------------
unsigned int PIT_GetPIIR(void)
{
return(AT91C_BASE_PITC->PITC_PIIR);
}
//------------------------------------------------------------------------------
/// Read System timer CPIV and PICNT without ressetting the counters
//------------------------------------------------------------------------------
unsigned int PIT_GetPIVR(void)
{
return(AT91C_BASE_PITC->PITC_PIVR);
}

View file

@ -0,0 +1,74 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
/// !Purpose
///
/// Configuration and handling of PIT.
///
/// !Usage
///
/// -# Initialize System timer for a period in µsecond with
/// PIT_Init
/// -# Set the PIT Periodic Interval Value with PIT_SetPIV
/// -# Enable the PIT with PIT_Enable
/// -# Enable & disable PIT interrupts using PIT_EnableInt and
/// PIT_DisableInt
/// -# Read PIT mode register
/// PIT_GetMode
/// -# Read PIT status register
/// PIT_GetStatus
/// -# Read PIT CPIV and PICNT without ressetting the counters
/// PIT_GetPIIR
/// -# Read System timer CPIV and PICNT without ressetting the counters
/// PIT_GetPIVR
//------------------------------------------------------------------------------
#ifndef PIT_H
#define PIT_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void PIT_Init(unsigned int period, unsigned int pit_frequency);
extern void PIT_SetPIV(unsigned int piv);
extern void PIT_Enable(void);
extern void PIT_EnableIT(void);
extern void PIT_DisableIT(void);
extern unsigned int PIT_GetMode(void);
extern unsigned int PIT_GetStatus(void);
extern unsigned int PIT_GetPIIR(void);
extern unsigned int PIT_GetPIVR(void);
#endif //#ifndef PIT_H

View file

@ -0,0 +1,133 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "pmc.h"
#include <board.h>
#include <utility/assert.h>
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
#if defined(at91sam7l64) || defined(at91sam7l128)
//------------------------------------------------------------------------------
/// Sets the fast wake-up inputs that can get the device out of Wait mode.
/// \param inputs Fast wake-up inputs to enable.
//------------------------------------------------------------------------------
void PMC_SetFastWakeUpInputs(unsigned int inputs)
{
SANITY_CHECK((inputs & ~0xFF) == 0);
AT91C_BASE_PMC->PMC_FSMR = inputs;
}
#if !defined(__ICCARM__)
__attribute__ ((section (".ramfunc"))) // GCC
#endif
//------------------------------------------------------------------------------
/// Disables the main oscillator, making the device enter Wait mode.
//------------------------------------------------------------------------------
void PMC_DisableMainOscillatorForWaitMode(void)
{
AT91C_BASE_PMC->PMC_MOR = 0x37 << 16;
while ((AT91C_BASE_PMC->PMC_MOR & AT91C_PMC_MAINSELS) != AT91C_PMC_MAINSELS);
}
#endif
#if defined(at91sam7l)
//------------------------------------------------------------------------------
/// Disables the main oscillator when NOT running on it.
//------------------------------------------------------------------------------
void PMC_DisableMainOscillator(void)
{
AT91C_BASE_PMC->PMC_MOR = 0x37 << 16;
while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MAINSELS) == AT91C_PMC_MAINSELS);
}
#endif
//------------------------------------------------------------------------------
/// Disables the processor clock, making the device enter Idle mode.
//------------------------------------------------------------------------------
void PMC_DisableProcessorClock(void)
{
AT91C_BASE_PMC->PMC_SCDR = AT91C_PMC_PCK;
while ((AT91C_BASE_PMC->PMC_SCSR & AT91C_PMC_PCK) != AT91C_PMC_PCK);
}
//------------------------------------------------------------------------------
/// Enables the clock of a peripheral. The peripheral ID (AT91C_ID_xxx) is used
/// to identify which peripheral is targetted.
/// Note that the ID must NOT be shifted (i.e. 1 << AT91C_ID_xxx).
/// \param id Peripheral ID (AT91C_ID_xxx).
//------------------------------------------------------------------------------
void PMC_EnablePeripheral(unsigned int id)
{
SANITY_CHECK(id < 32);
if ((AT91C_BASE_PMC->PMC_PCSR & (1 << id)) == (1 << id)) {
trace_LOG(trace_INFO,
"-I- PMC_EnablePeripheral: clock of peripheral"
" %u is already enabled\n\r",
id);
}
else {
AT91C_BASE_PMC->PMC_PCER = 1 << id;
}
}
//------------------------------------------------------------------------------
/// Disables the clock of a peripheral. The peripheral ID (AT91C_ID_xxx) is used
/// to identify which peripheral is targetted.
/// Note that the ID must NOT be shifted (i.e. 1 << AT91C_ID_xxx).
/// \param id Peripheral ID (AT91C_ID_xxx).
//------------------------------------------------------------------------------
void PMC_DisablePeripheral(unsigned int id)
{
SANITY_CHECK(id < 32);
if ((AT91C_BASE_PMC->PMC_PCSR & (1 << id)) != (1 << id)) {
trace_LOG(trace_INFO,
"-I- PMC_DisablePeripheral: clock of peripheral"
" %u is not enabled\n\r",
id);
}
else {
AT91C_BASE_PMC->PMC_PCDR = 1 << id;
}
}

View file

@ -0,0 +1,53 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef PMC_H
#define PMC_H
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
#if defined(at91sam7l64) || defined(at91sam7l128)
extern void PMC_SetFastWakeUpInputs(unsigned int inputs);
extern void PMC_DisableMainOscillator(void);
extern
#ifdef __ICCARM__
__ramfunc
#endif
void PMC_DisableMainOscillatorForWaitMode(void);
#endif
extern void PMC_DisableProcessorClock(void);
extern void PMC_EnablePeripheral(unsigned int id);
extern void PMC_DisablePeripheral(unsigned int id);
#endif //#ifndef PMC_H

View file

@ -0,0 +1,238 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "pwmc.h"
#include <board.h>
#include <utility/assert.h>
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Local functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Finds a prescaler/divisor couple to generate the desired frequency from
/// MCK.
/// Returns the value to enter in PWMC_MR or 0 if the configuration cannot be
/// met.
/// \param frequency Desired frequency in Hz.
/// \param mck Master clock frequency in Hz.
//------------------------------------------------------------------------------
static unsigned short FindClockConfiguration(
unsigned int frequency,
unsigned int mck)
{
unsigned int divisors[11] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024};
unsigned char divisor = 0;
unsigned int prescaler;
SANITY_CHECK(frequency < mck);
// Find prescaler and divisor values
prescaler = (mck / divisors[divisor]) / frequency;
while ((prescaler > 255) && (divisor < 11)) {
divisor++;
prescaler = (mck / divisors[divisor]) / frequency;
}
// Return result
if (divisor < 11) {
trace_LOG(trace_DEBUG, "-D- Found divisor=%u and prescaler=%u for freq=%uHz\n\r",
divisors[divisor], prescaler, frequency);
return prescaler | (divisor << 8);
}
else {
return 0;
}
}
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures PWM a channel with the given parameters.
/// The PWM controller must have been clocked in the PMC prior to calling this
/// function.
/// \param channel Channel number.
/// \param prescaler Channel prescaler.
/// \param alignment Channel alignment.
/// \param polarity Channel polarity.
//------------------------------------------------------------------------------
void PWMC_ConfigureChannel(
unsigned char channel,
unsigned int prescaler,
unsigned int alignment,
unsigned int polarity)
{
SANITY_CHECK(prescaler < AT91C_PWMC_CPRE_MCKB);
SANITY_CHECK((alignment & ~AT91C_PWMC_CALG) == 0);
SANITY_CHECK((polarity & ~AT91C_PWMC_CPOL) == 0);
// Disable channel
AT91C_BASE_PWMC->PWMC_DIS = 1 << channel;
// Configure channel
AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CMR = prescaler | alignment | polarity;
}
//------------------------------------------------------------------------------
/// Configures PWM clocks A & B to run at the given frequencies. This function
/// finds the best MCK divisor and prescaler values automatically.
/// \param clka Desired clock A frequency (0 if not used).
/// \param clkb Desired clock B frequency (0 if not used).
/// \param mck Master clock frequency.
//------------------------------------------------------------------------------
void PWMC_ConfigureClocks(unsigned int clka, unsigned int clkb, unsigned int mck)
{
unsigned int mode = 0;
unsigned int result;
// Clock A
if (clka != 0) {
result = FindClockConfiguration(clka, mck);
ASSERT(result != 0, "-F- Could not generate the desired PWM frequency (%uHz)\n\r", clka);
mode |= result;
}
// Clock B
if (clkb != 0) {
result = FindClockConfiguration(clkb, mck);
ASSERT(result != 0, "-F- Could not generate the desired PWM frequency (%uHz)\n\r", clkb);
mode |= (result << 16);
}
// Configure clocks
trace_LOG(trace_DEBUG, "-D- Setting PWMC_MR = 0x%08X\n\r", mode);
AT91C_BASE_PWMC->PWMC_MR = mode;
}
//------------------------------------------------------------------------------
/// Sets the period value used by a PWM channel. This function writes directly
/// to the CPRD register if the channel is disabled; otherwise, it uses the
/// update register CUPD.
/// \param channel Channel number.
/// \param period Period value.
//------------------------------------------------------------------------------
void PWMC_SetPeriod(unsigned char channel, unsigned short period)
{
// If channel is disabled, write to CPRD
if ((AT91C_BASE_PWMC->PWMC_SR & (1 << channel)) == 0) {
AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CPRDR = period;
}
// Otherwise use update register
else {
AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CMR |= AT91C_PWMC_CPD;
AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CUPDR = period;
}
}
//------------------------------------------------------------------------------
/// Sets the duty cycle used by a PWM channel. This function writes directly to
/// the CDTY register if the channel is disabled; otherwise it uses the
/// update register CUPD.
/// Note that the duty cycle must always be inferior or equal to the channel
/// period.
/// \param channel Channel number.
/// \param duty Duty cycle value.
//------------------------------------------------------------------------------
void PWMC_SetDutyCycle(unsigned char channel, unsigned short duty)
{
SANITY_CHECK(duty <= AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CPRDR);
// SAM7S errata
#if defined(at91sam7s16) || defined(at91sam7s161) || defined(at91sam7s32) \
|| defined(at91sam7s321) || defined(at91sam7s64) || defined(at91sam7s128) \
|| defined(at91sam7s256) || defined(at91sam7s512)
ASSERT(duty > 0, "-F- Duty cycle value 0 is not permitted on SAM7S chips.\n\r");
ASSERT((duty > 1) || (AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CMR & AT91C_PWMC_CALG),
"-F- Duty cycle value 1 is not permitted in left-aligned mode on SAM7S chips.\n\r");
#endif
// If channel is disabled, write to CDTY
if ((AT91C_BASE_PWMC->PWMC_SR & (1 << channel)) == 0) {
AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CDTYR = duty;
}
// Otherwise use update register
else {
AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CMR &= ~AT91C_PWMC_CPD;
AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CUPDR = duty;
}
}
//------------------------------------------------------------------------------
/// Enables the given PWM channel. This does NOT enable the corresponding pin;
/// this must be done in the user code.
/// \param channel Channel number.
//------------------------------------------------------------------------------
void PWMC_EnableChannel(unsigned char channel)
{
AT91C_BASE_PWMC->PWMC_ENA = 1 << channel;
}
//------------------------------------------------------------------------------
/// Disables the given PWM channel.
/// \param channel Channel number.
//------------------------------------------------------------------------------
void PWMC_DisableChannel(unsigned char channel)
{
AT91C_BASE_PWMC->PWMC_DIS = 1 << channel;
}
//------------------------------------------------------------------------------
/// Enables the period interrupt for the given PWM channel.
/// \param channel Channel number.
//------------------------------------------------------------------------------
void PWMC_EnableChannelIt(unsigned char channel)
{
AT91C_BASE_PWMC->PWMC_IER = 1 << channel;
}
//------------------------------------------------------------------------------
/// Disables the period interrupt for the given PWM channel.
/// \param channel Channel number.
//------------------------------------------------------------------------------
void PWMC_DisableChannelIt(unsigned char channel)
{
AT91C_BASE_PWMC->PWMC_IDR = 1 << channel;
}

View file

@ -0,0 +1,61 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef PWMC_H
#define PWMC_H
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void PWMC_ConfigureChannel(
unsigned char channel,
unsigned int prescaler,
unsigned int alignment,
unsigned int polarity);
extern void PWMC_ConfigureClocks
(unsigned int clka,
unsigned int clkb,
unsigned int mck);
extern void PWMC_SetPeriod(unsigned char channel, unsigned short period);
extern void PWMC_SetDutyCycle(unsigned char channel, unsigned short duty);
extern void PWMC_EnableChannel(unsigned char channel);
extern void PWMC_DisableChannel(unsigned char channel);
extern void PWMC_EnableChannelIt(unsigned char channel);
extern void PWMC_DisableChannelIt(unsigned char channel);
#endif //#ifndef PWMC_H

View file

@ -0,0 +1,188 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//-----------------------------------------------------------------------------
// Headers
//-----------------------------------------------------------------------------
#include <board.h>
//-----------------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------------
/// WRITE_RSTC: Write RSTC register
#define WRITE_RSTC(pRstc, regName, value) pRstc->regName = (value)
/// READ_RSTC: Read RSTC registers
#define READ_RSTC(pRstc, regName) (pRstc->regName)
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
/// Keywords to write to the reset registers
#define RSTC_KEY_PASSWORD (0xA5UL << 24)
//-----------------------------------------------------------------------------
// Exported functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// Configure the mode of the RSTC peripheral.
/// The configuration is computed by the lib (AT91C_RSTC_*).
/// \param rstc Pointer to an RSTC peripheral.
/// \param rmr Desired mode configuration.
//-----------------------------------------------------------------------------
void RSTC_ConfigureMode(AT91PS_RSTC rstc, unsigned int rmr)
{
rmr &= ~AT91C_RSTC_KEY;
WRITE_RSTC(rstc, RSTC_RMR, rmr | RSTC_KEY_PASSWORD);
}
//-----------------------------------------------------------------------------
/// Enable/Disable the detection of a low level on the pin NRST as User Reset
/// \param rstc Pointer to an RSTC peripheral.
/// \param enable 1 to enable & 0 to disable.
//-----------------------------------------------------------------------------
void RSTC_SetUserResetEnable(AT91PS_RSTC rstc, unsigned char enable)
{
unsigned int rmr = READ_RSTC(rstc, RSTC_RMR) & (~AT91C_RSTC_KEY);
if (enable) {
rmr |= AT91C_RSTC_URSTEN;
}
else {
rmr &= ~AT91C_RSTC_URSTEN;
}
WRITE_RSTC(rstc, RSTC_RMR, rmr | RSTC_KEY_PASSWORD);
}
//-----------------------------------------------------------------------------
/// Enable/Disable the interrupt of a User Reset (USRTS bit in RSTC_RST).
/// \param rstc Pointer to an RSTC peripheral.
/// \param enable 1 to enable & 0 to disable.
//-----------------------------------------------------------------------------
void RSTC_SetUserResetInterruptEnable(AT91PS_RSTC rstc, unsigned char enable)
{
unsigned int rmr = READ_RSTC(rstc, RSTC_RMR) & (~AT91C_RSTC_KEY);
if (enable) {
rmr |= AT91C_RSTC_URSTIEN;
}
else {
rmr &= ~AT91C_RSTC_URSTIEN;
}
WRITE_RSTC(rstc, RSTC_RMR, rmr | RSTC_KEY_PASSWORD);
}
//-----------------------------------------------------------------------------
/// Setup the external reset length. The length is asserted during a time of
/// pow(2, powl+1) Slow Clock(32KHz). The duration is between 60us and 2s.
/// \param rstc Pointer to an RSTC peripheral.
/// \param powl Power length defined.
//-----------------------------------------------------------------------------
void RSTC_SetExtResetLength(AT91PS_RSTC rstc, unsigned char powl)
{
unsigned int rmr = READ_RSTC(rstc, RSTC_RMR);
rmr &= ~(AT91C_RSTC_KEY | AT91C_RSTC_ERSTL);
rmr |= (powl << 8) & AT91C_RSTC_ERSTL;
WRITE_RSTC(rstc, RSTC_RMR, rmr | RSTC_KEY_PASSWORD);
}
//-----------------------------------------------------------------------------
/// Resets the processor.
/// \param rstc Pointer to an RSTC peripheral.
//-----------------------------------------------------------------------------
void RSTC_ProcessorReset(AT91PS_RSTC rstc)
{
WRITE_RSTC(rstc, RSTC_RCR, AT91C_RSTC_PROCRST | RSTC_KEY_PASSWORD);
}
//-----------------------------------------------------------------------------
/// Resets the peripherals.
/// \param rstc Pointer to an RSTC peripheral.
//-----------------------------------------------------------------------------
void RSTC_PeripheralReset(AT91PS_RSTC rstc)
{
WRITE_RSTC(rstc, RSTC_RCR, AT91C_RSTC_PERRST | RSTC_KEY_PASSWORD);
}
//-----------------------------------------------------------------------------
/// Asserts the NRST pin for external resets.
/// \param rstc Pointer to an RSTC peripheral.
//-----------------------------------------------------------------------------
void RSTC_ExtReset(AT91PS_RSTC rstc)
{
WRITE_RSTC(rstc, RSTC_RCR, AT91C_RSTC_EXTRST | RSTC_KEY_PASSWORD);
}
//-----------------------------------------------------------------------------
/// Return NRST pin level ( 1 or 0 ).
/// \param rstc Pointer to an RSTC peripheral.
//-----------------------------------------------------------------------------
unsigned char RSTC_GetNrstLevel(AT91PS_RSTC rstc)
{
if (READ_RSTC(rstc, RSTC_RSR) & AT91C_RSTC_NRSTL) {
return 1;
}
return 0;
}
//-----------------------------------------------------------------------------
/// Returns 1 if at least one high-to-low transition of NRST (User Reset) has
/// been detected since the last read of RSTC_RSR.
/// \param rstc Pointer to an RSTC peripheral.
//-----------------------------------------------------------------------------
unsigned char RSTC_IsUserReseetDetected(AT91PS_RSTC rstc)
{
if (READ_RSTC(rstc, RSTC_RSR) & AT91C_RSTC_URSTS) {
return 1;
}
return 0;
}
//-----------------------------------------------------------------------------
/// Return 1 if a software reset command is being performed by the reset
/// controller. The reset controller is busy.
/// \param rstc Pointer to an RSTC peripheral.
//-----------------------------------------------------------------------------
unsigned char RSTC_IsBusy(AT91PS_RSTC rstc)
{
if (READ_RSTC(rstc, RSTC_RSR) & AT91C_RSTC_SRCMP) {
return 1;
}
return 0;
}

View file

@ -0,0 +1,58 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef _RSTC_H
#define _RSTC_H
//-----------------------------------------------------------------------------
// Exported functions
//-----------------------------------------------------------------------------
extern void RSTC_ConfigureMode(AT91PS_RSTC rstc, unsigned int rmr);
extern void RSTC_SetUserResetEnable(AT91PS_RSTC rstc, unsigned char enable);
extern void RSTC_SetUserResetInterruptEnable(AT91PS_RSTC rstc,
unsigned char enable);
extern void RSTC_SetExtResetLength(AT91PS_RSTC rstc, unsigned char powl);
extern void RSTC_ProcessorReset(AT91PS_RSTC rstc);
extern void RSTC_PeripheralReset(AT91PS_RSTC rstc);
extern void RSTC_ExtReset(AT91PS_RSTC rstc);
extern unsigned char RSTC_GetNrstLevel(AT91PS_RSTC rstc);
extern unsigned char RSTC_IsUserReseetDetected(AT91PS_RSTC rstc);
extern unsigned char RSTC_IsBusy(AT91PS_RSTC rstc);
#endif // #ifndef _RSTC_H

View file

@ -0,0 +1,338 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef trace_LEVEL
#define trace_LEVEL trace_INFO
#endif
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "rtc.h"
#include <board.h>
#include <utility/assert.h>
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Sets the RTC in either 12- or 24-hour mode.
/// \param mode Hour mode.
//------------------------------------------------------------------------------
void RTC_SetHourMode(unsigned int mode)
{
SANITY_CHECK((mode & 0xFFFFFFFE) == 0);
trace_LOG(trace_DEBUG, "-D- RTC_SetHourMode()\n\r");
AT91C_BASE_RTC->RTC_MR = mode;
}
//------------------------------------------------------------------------------
/// Enables the selected interrupt sources of the RTC.
/// \param sources Interrupt sources to enable.
//------------------------------------------------------------------------------
void RTC_EnableIt(unsigned int sources)
{
SANITY_CHECK((sources & ~0x1F) == 0);
trace_LOG(trace_DEBUG, "-D- RTC_EnableIt()\n\r");
AT91C_BASE_RTC->RTC_IER = sources;
}
//------------------------------------------------------------------------------
/// Disables the selected interrupt sources of the RTC.
/// \param sources Interrupt sources to disable.
//------------------------------------------------------------------------------
void RTC_DisableIt(unsigned int sources)
{
SANITY_CHECK((sources & ~0x1F) == 0);
trace_LOG(trace_DEBUG, "-D- RTC_DisableIt()\n\r");
AT91C_BASE_RTC->RTC_IDR = sources;
}
//------------------------------------------------------------------------------
/// Sets the current time in the RTC.
/// \param hour Current hour.
/// \param minute Current minute.
/// \param second Current second.
//------------------------------------------------------------------------------
void RTC_SetTime(unsigned char hour, unsigned char minute, unsigned char second)
{
unsigned int time;
SANITY_CHECK(hour < 24);
SANITY_CHECK(minute < 60);
SANITY_CHECK(second < 60);
trace_LOG(trace_DEBUG, "-D- RTC_SetTime(%02d:%02d:%02d)\n\r", hour, minute, second);
time = (second % 10) | ((second / 10) << 4)
| ((minute % 10) << 8) | ((minute / 10) << 12);
// 12-hour mode
if ((AT91C_BASE_RTC->RTC_MR & AT91C_RTC_HRMOD) == AT91C_RTC_HRMOD) {
if (hour > 12) {
hour -= 12;
time |= AT91C_RTC_AMPM;
}
}
time |= ((hour % 10) << 16) | ((hour / 10) << 20);
// Set time
AT91C_BASE_RTC->RTC_CR |= AT91C_RTC_UPDTIM;
while ((AT91C_BASE_RTC->RTC_SR & AT91C_RTC_ACKUPD) != AT91C_RTC_ACKUPD);
AT91C_BASE_RTC->RTC_SCCR = AT91C_RTC_ACKUPD;
AT91C_BASE_RTC->RTC_TIMR = time;
AT91C_BASE_RTC->RTC_CR &= ~AT91C_RTC_UPDTIM;
SANITY_CHECK((AT91C_BASE_RTC->RTC_CR & AT91C_RTC_UPDTIM) != AT91C_RTC_UPDTIM);
}
//------------------------------------------------------------------------------
/// Retrieves the current time as stored in the RTC in several variables.
/// \param pHour If not null, current hour is stored in this variable.
/// \param pMinute If not null, current minute is stored in this variable.
/// \param pSecond If not null, current second is stored in this variable.
//------------------------------------------------------------------------------
void RTC_GetTime(
unsigned char *pHour,
unsigned char *pMinute,
unsigned char *pSecond)
{
unsigned int time;
SANITY_CHECK(pHour || pMinute || pSecond);
trace_LOG(trace_DEBUG, "-D- RTC_GetTime()\n\r");
// Get current RTC time
time = AT91C_BASE_RTC->RTC_TIMR;
while (time != AT91C_BASE_RTC->RTC_TIMR) {
time = AT91C_BASE_RTC->RTC_TIMR;
}
// Hour
if (pHour) {
*pHour = ((time & 0x00300000) >> 20) * 10
+ ((time & 0x000F0000) >> 16);
if ((time & AT91C_RTC_AMPM) == AT91C_RTC_AMPM) {
*pHour += 12;
}
}
// Minute
if (pMinute) {
*pMinute = ((time & 0x00007000) >> 12) * 10
+ ((time & 0x00000F00) >> 8);
}
// Second
if (pSecond) {
*pSecond = ((time & 0x00000070) >> 4) * 10
+ (time & 0x0000000F);
}
}
//------------------------------------------------------------------------------
/// Sets a time alarm on the RTC. The match is performed only on the provided
/// variables; setting all pointers to 0 disables the time alarm.
/// Note: in AM/PM mode, the hour value must have bit #7 set for PM, cleared for
/// AM (as expected in the time registers).
/// \param pHour If not null, the time alarm will hour-match this value.
/// \param pMinute If not null, the time alarm will minute-match this value.
/// \param pSecond If not null, the time alarm will second-match this value.
//------------------------------------------------------------------------------
void RTC_SetTimeAlarm(
unsigned char *pHour,
unsigned char *pMinute,
unsigned char *pSecond)
{
unsigned int alarm = 0;
SANITY_CHECK(!pHour || ((*pHour & 0x80) == 0));
SANITY_CHECK(!pMinute || (*pMinute < 60));
SANITY_CHECK(!pSecond || (*pSecond < 60));
trace_LOG(trace_DEBUG, "-D- RTC_SetTimeAlarm()\n\r");
// Hour
if (pHour) {
alarm |= AT91C_RTC_HOUREN | ((*pHour / 10) << 20) | ((*pHour % 10) << 16);
}
// Minute
if (pMinute) {
alarm |= AT91C_RTC_MINEN | ((*pMinute / 10) << 12) | ((*pMinute % 10) << 8);
}
// Second
if (pSecond) {
alarm |= AT91C_RTC_SECEN | ((*pSecond / 10) << 4) | (*pSecond % 10);
}
AT91C_BASE_RTC->RTC_TIMALR = alarm;
}
//------------------------------------------------------------------------------
/// Retrieves the current year, month and day from the RTC. Month, day and week
/// values are numbered starting at 1.
/// \param pYear Current year (optional).
/// \param pMonth Current month (optional).
/// \param pDay Current day (optional).
/// \param pWeek Current day in current week (optional).
//------------------------------------------------------------------------------
void RTC_GetDate(
unsigned short *pYear,
unsigned char *pMonth,
unsigned char *pDay,
unsigned char *pWeek)
{
unsigned int date;
// Get current date (multiple reads are necessary to insure a stable value)
do {
date = AT91C_BASE_RTC->RTC_CALR;
}
while (date != AT91C_BASE_RTC->RTC_CALR);
// Retrieve year
if (pYear) {
*pYear = (((date >> 4) & 0x7) * 1000)
+ ((date & 0xF) * 100)
+ (((date >> 12) & 0xF) * 10)
+ ((date >> 8) & 0xF);
}
// Retrieve month
if (pMonth) {
*pMonth = (((date >> 20) & 1) * 10) + ((date >> 16) & 0xF);
}
// Retrieve day
if (pDay) {
*pDay = (((date >> 28) & 0x3) * 10) + ((date >> 24) & 0xF);
}
// Retrieve week
if (pWeek) {
*pWeek = ((date >> 21) & 0x7);
}
}
//------------------------------------------------------------------------------
/// Sets the current year, month and day in the RTC. Month, day and week values
/// must be numbered starting from 1.
/// \param year Current year.
/// \param month Current month.
/// \param day Current day.
/// \param week Day number in current week.
//------------------------------------------------------------------------------
void RTC_SetDate(
unsigned short year,
unsigned char month,
unsigned char day,
unsigned char week)
{
unsigned int date;
SANITY_CHECK((year >= 1900) && (year <= 2099));
SANITY_CHECK((month >= 1) && (month <= 12));
SANITY_CHECK((day >= 1) && (day <= 31));
SANITY_CHECK((week >= 1) && (week <= 7));
// Convert values to date register value
date = ((year / 100) % 10)
| ((year / 1000) << 4)
| ((year % 10) << 8)
| (((year / 10) % 10) << 12)
| ((month % 10) << 16)
| ((month / 10) << 20)
| (week << 21)
| ((day % 10) << 24)
| ((day / 10) << 28);
// Update calendar register
AT91C_BASE_RTC->RTC_CR |= AT91C_RTC_UPDCAL;
while ((AT91C_BASE_RTC->RTC_SR & AT91C_RTC_ACKUPD) != AT91C_RTC_ACKUPD);
AT91C_BASE_RTC->RTC_SCCR = AT91C_RTC_ACKUPD;
AT91C_BASE_RTC->RTC_CALR = date;
AT91C_BASE_RTC->RTC_CR &= ~AT91C_RTC_UPDCAL;
}
//------------------------------------------------------------------------------
/// Sets a date alarm in the RTC. The alarm will match only the provided values;
/// passing a null-pointer disables the corresponding field match.
/// \param pMonth If not null, the RTC alarm will month-match this value.
/// \param pDay If not null, the RTC alarm will day-match this value.
//------------------------------------------------------------------------------
void RTC_SetDateAlarm(unsigned char *pMonth, unsigned char *pDay)
{
unsigned int alarm = 0;
SANITY_CHECK(!pMonth || ((*pMonth >= 1) && (*pMonth <= 12)));
SANITY_CHECK(!pDay || ((*pDay >= 1) && (*pDay <= 31)));
trace_LOG(trace_DEBUG, "-D- RTC_SetDateAlarm()\n\r");
// Compute alarm field value
if (pMonth) {
alarm |= AT91C_RTC_MONTHEN | ((*pMonth / 10) << 20) | ((*pMonth % 10) << 16);
}
if (pDay) {
alarm |= AT91C_RTC_DATEEN | ((*pDay / 10) << 28) | ((*pDay % 10) << 24);
}
// Set alarm
AT91C_BASE_RTC->RTC_CALALR = alarm;
}

View file

@ -0,0 +1,73 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef RTC_H
#define RTC_H
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void RTC_SetHourMode(unsigned int mode);
extern void RTC_EnableIt(unsigned int sources);
extern void RTC_DisableIt(unsigned int sources);
extern void RTC_SetTime(
unsigned char hour,
unsigned char minute,
unsigned char second);
extern void RTC_GetTime(
unsigned char *pHour,
unsigned char *pMinute,
unsigned char *pSecond);
extern void RTC_SetTimeAlarm(
unsigned char *pHour,
unsigned char *pMinute,
unsigned char *pSecond);
void RTC_GetDate(
unsigned short *pYear,
unsigned char *pMonth,
unsigned char *pDay,
unsigned char *pWeek);
extern void RTC_SetDate(
unsigned short year,
unsigned char month,
unsigned char day,
unsigned char week);
extern void RTC_SetDateAlarm(unsigned char *pMonth, unsigned char *pDay);
#endif //#ifndef RTC_H

View file

@ -0,0 +1,93 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "rtt.h"
#include <utility/assert.h>
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Changes the prescaler value of the given RTT and restarts it. This function
/// disables RTT interrupt sources.
/// \param rtt Pointer to a AT91S_RTTC instance.
/// \param prescaler Prescaler value for the RTT.
//------------------------------------------------------------------------------
void RTT_SetPrescaler(AT91S_RTTC *rtt, unsigned short prescaler)
{
rtt->RTTC_RTMR = (prescaler | AT91C_RTTC_RTTRST);
}
//------------------------------------------------------------------------------
/// Returns the current value of the RTT timer value.
/// \param rtt Pointer to a AT91S_RTTC instance.
//------------------------------------------------------------------------------
unsigned int RTT_GetTime(AT91S_RTTC *rtt)
{
return rtt->RTTC_RTVR;
}
//------------------------------------------------------------------------------
/// Enables the specified RTT interrupt sources.
/// \param rtt Pointer to a AT91S_RTTC instance.
/// \param sources Bitmask of interrupts to enable.
//------------------------------------------------------------------------------
void RTT_EnableIT(AT91S_RTTC *rtt, unsigned int sources)
{
ASSERT((sources & 0x0004FFFF) == 0,
"RTT_EnableIT: Wrong sources value.\n\r");
rtt->RTTC_RTMR |= sources;
}
//------------------------------------------------------------------------------
/// Returns the status register value of the given RTT.
/// \param rtt Pointer to an AT91S_RTTC instance.
//------------------------------------------------------------------------------
unsigned int RTT_GetStatus(AT91S_RTTC *rtt)
{
return rtt->RTTC_RTSR;
}
//------------------------------------------------------------------------------
/// Configures the RTT to generate an alarm at the given time.
/// \param pRtt Pointer to an AT91S_RTTC instance.
/// \param time Alarm time.
//------------------------------------------------------------------------------
void RTT_SetAlarm(AT91S_RTTC *pRtt, unsigned int time)
{
SANITY_CHECK(time > 0);
pRtt->RTTC_RTAR = time - 1;
}

View file

@ -0,0 +1,62 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef RTT_H
#define RTT_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
#ifndef AT91C_BASE_RTTC
#define AT91C_BASE_RTTC AT91C_BASE_RTTC0
#endif
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void RTT_SetPrescaler(AT91S_RTTC *rtt, unsigned short prescaler);
extern unsigned int RTT_GetTime(AT91S_RTTC *rtt);
extern void RTT_EnableIT(AT91S_RTTC *rtt, unsigned int sources);
extern unsigned int RTT_GetStatus(AT91S_RTTC *rtt);
extern void RTT_SetAlarm(AT91S_RTTC *pRtt, unsigned int time);
#endif //#ifndef RTT_H

View file

@ -0,0 +1,192 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "slcdc.h"
#include <board.h>
#include <utility/assert.h>
#include <string.h>
//------------------------------------------------------------------------------
// Local definitions
//------------------------------------------------------------------------------
/// Size of SLCDC buffer in bytes.
#define BUFFER_SIZE 320
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Initializes the Segment LCD controller.
/// \param commons Number of commons used by the display.
/// \param segments Number of segments used by the display.
/// \param bias Bias value.
/// \param timeSetting Buffer timing value.
//------------------------------------------------------------------------------
void SLCDC_Configure(
unsigned int commons,
unsigned int segments,
unsigned int bias,
unsigned int timeSetting)
{
SANITY_CHECK((commons > 0) && (commons <= 10));
SANITY_CHECK((segments > 0) && (segments <= 40));
SANITY_CHECK((bias & ~AT91C_SLCDC_BIAS) == 0);
SANITY_CHECK((timeSetting & ~(0xF << 16)) == 0);
SANITY_CHECK((timeSetting >> 16) < 0x0A);
// Enable peripheral clock
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_SLCD;
AT91C_BASE_SLCDC->SLCDC_MR = (commons - 1) | ((segments - 1) << 8) | bias | timeSetting;
}
//------------------------------------------------------------------------------
/// Clears the SLCD display buffer.
//------------------------------------------------------------------------------
void SLCDC_Clear(void)
{
memset((void *) AT91C_BASE_SLCDC->SLCDC_MEM, 0, BUFFER_SIZE);
}
//------------------------------------------------------------------------------
/// Enables the SLCD controller.
//------------------------------------------------------------------------------
void SLCDC_Enable(void)
{
AT91C_BASE_SLCDC->SLCDC_CR = AT91C_SLCDC_LCDEN;
while (AT91C_BASE_SLCDC -> SLCDC_SR != AT91C_SLCDC_ENA);
}
//------------------------------------------------------------------------------
/// Disables the SLCD controller.
//------------------------------------------------------------------------------
void SLCDC_Disable(void)
{
AT91C_BASE_SLCDC->SLCDC_CR = AT91C_SLCDC_LCDDIS;
}
//------------------------------------------------------------------------------
/// Enables the SLCD low power mode.
//------------------------------------------------------------------------------
void SLCDC_EnableLowPowerMode(void)
{
unsigned int value;
value = AT91C_BASE_SLCDC->SLCDC_MR;
value &= ~AT91C_SLCDC_LPMODE;
value |=AT91C_SLCDC_LPMODE;
AT91C_BASE_SLCDC->SLCDC_MR = value;
}
//------------------------------------------------------------------------------
/// Disables the SLCD low power mode
//------------------------------------------------------------------------------
void SLCDC_DisableLowPowerMode(void)
{
unsigned int value;
value = AT91C_BASE_SLCDC->SLCDC_MR;
value &= ~AT91C_SLCDC_LPMODE;
AT91C_BASE_SLCDC->SLCDC_MR = value;
}
//------------------------------------------------------------------------------
/// Adjusts the frame frequency. Frequency = FsCLK / (prescaler * divider . NCOM)
/// \param prescalerValue Prescaler value
/// \param dividerValue Divider value
//------------------------------------------------------------------------------
void SLCDC_SetFrameFreq(unsigned int prescalerValue, unsigned int dividerValue)
{
SANITY_CHECK((prescalerValue & ~AT91C_SLCDC_PRESC) == 0);
SANITY_CHECK((dividerValue & (~(0x07 << 8))) == 0);
AT91C_BASE_SLCDC->SLCDC_FRR = prescalerValue | dividerValue;
}
//------------------------------------------------------------------------------
/// Sets the display mode (normal/force off/force on/blinking).
/// \param mode Display mode to be set
//------------------------------------------------------------------------------
void SLCDC_SetDisplayMode(unsigned int mode)
{
unsigned int value;
SANITY_CHECK(mode < 8);
value = AT91C_BASE_SLCDC->SLCDC_DR;
value &= ~AT91C_SLCDC_DISPMODE;
value |= mode;
AT91C_BASE_SLCDC->SLCDC_DR = value;
}
//------------------------------------------------------------------------------
/// Adjusts the display blinking frequency.
/// Blinking frequency = Frame Frequency / LCDBLKFREQ.
/// \param frequency Frequency value.
//------------------------------------------------------------------------------
void SLCDC_SetBlinkFreq(unsigned int frequency)
{
unsigned int value;
SANITY_CHECK((frequency & ~(0xFF << 8)) == 0);
value = AT91C_BASE_SLCDC->SLCDC_DR;
value &= ~AT91C_SLCDC_BLKFREQ;
value |= frequency;
AT91C_BASE_SLCDC->SLCDC_DR = frequency;
}
//------------------------------------------------------------------------------
/// Enables the selected SLCDC interrupt sources.
/// \param sources Interrupt sources to enable.
//------------------------------------------------------------------------------
void SLCDC_EnableInterrupts(unsigned int sources)
{
SANITY_CHECK((sources & 0xFFFFFFFA) == 0);
AT91C_BASE_SLCDC->SLCDC_IER = sources;
}
//------------------------------------------------------------------------------
/// Disables the selected SLCDC interrupt sources.
/// \param sources Interrupt sources to disable.
//------------------------------------------------------------------------------
void SLCDC_DisableInterrupts(unsigned int sources)
{
SANITY_CHECK((sources & 0xFFFFFFFA) == 0);
AT91C_BASE_SLCDC->SLCDC_IDR = sources;
}

View file

@ -0,0 +1,71 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef SLCDC_H
#define SLCDC_H
//------------------------------------------------------------------------------
// Global definitions
//------------------------------------------------------------------------------
/// Number of segments in SLCD.
#define S7LEKLCD_NUM_SEGMENTS 40
/// Number of commons in SLCD.
#define S7LEKLCD_NUM_COMMONS 10
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void SLCDC_Configure(
unsigned int commons,
unsigned int segments,
unsigned int bias,
unsigned int timeSetting);
extern void SLCDC_Clear(void);
extern void SLCDC_Enable(void);
extern void SLCDC_Disable(void);
extern void SLCDC_SetFrameFreq(
unsigned int prescalerValue,
unsigned int dividerValue);
extern void SLCDC_SetDisplayMode(unsigned int mode);
extern void SLCDC_SetBlinkFreq(unsigned int frequency);
extern void SLCDC_EnableInterrupts(unsigned int sources);
extern void SLCDC_DisableInterrupts(unsigned int sources);
#endif //#ifndef SLCDC_H

View file

@ -0,0 +1,189 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "spi.h"
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Enables a SPI peripheral
/// \param spi Pointer to an AT91S_SPI instance.
//------------------------------------------------------------------------------
void SPI_Enable(AT91S_SPI *spi)
{
spi->SPI_CR = AT91C_SPI_SPIEN;
}
//------------------------------------------------------------------------------
/// Disables a SPI peripheral.
/// \param spi Pointer to an AT91S_SPI instance.
//------------------------------------------------------------------------------
void SPI_Disable(AT91S_SPI *spi)
{
spi->SPI_CR = AT91C_SPI_SPIDIS;
}
//------------------------------------------------------------------------------
/// Configures a SPI peripheral as specified. The configuration can be computed
/// using several macros (see "SPI configuration macros") and the constants
/// defined in LibV3 (AT91C_SPI_*).
/// \param spi Pointer to an AT91S_SPI instance.
/// \param id Peripheral ID of the SPI.
/// \param configuration Value of the SPI configuration register.
//------------------------------------------------------------------------------
void SPI_Configure(AT91S_SPI *spi,
unsigned int id,
unsigned int configuration)
{
AT91C_BASE_PMC->PMC_PCER = 1 << id;
spi->SPI_CR = AT91C_SPI_SPIDIS | AT91C_SPI_SWRST;
spi->SPI_MR = configuration;
}
//------------------------------------------------------------------------------
/// Configures a chip select of a SPI peripheral. The chip select configuration
/// is computed using the definition provided by the LibV3 (AT91C_SPI_*).
/// \param spi Pointer to an AT91S_SPI instance.
/// \param npcs Chip select to configure (1, 2, 3 or 4).
/// \param configuration Desired chip select configuration.
//------------------------------------------------------------------------------
void SPI_ConfigureNPCS(AT91S_SPI *spi,
unsigned int npcs,
unsigned int configuration)
{
spi->SPI_CSR[npcs] = configuration;
}
//------------------------------------------------------------------------------
/// Sends data through a SPI peripheral. If the SPI is configured to use a fixed
/// peripheral select, the npcs value is meaningless. Otherwise, it identifies
/// the component which shall be addressed.
/// \param spi Pointer to an AT91S_SPI instance.
/// \param npcs Chip select of the component to address (1, 2, 3 or 4).
/// \param data Word of data to send.
//------------------------------------------------------------------------------
void SPI_Write(AT91S_SPI *spi, unsigned int npcs, unsigned short data)
{
// Discard contents of RDR register
//volatile unsigned int discard = spi->SPI_RDR;
// Send data
while ((spi->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
spi->SPI_TDR = data | SPI_PCS(npcs);
while ((spi->SPI_SR & AT91C_SPI_TDRE) == 0);
}
//------------------------------------------------------------------------------
/// Sends the contents of buffer through a SPI peripheral, using the PDC to
/// take care of the transfer.
/// \param spi Pointer to an AT91S_SPI instance.
/// \param buffer Data buffer to send.
/// \param length Length of the data buffer.
//------------------------------------------------------------------------------
unsigned char SPI_WriteBuffer(AT91S_SPI *spi,
void *buffer,
unsigned int length)
{
// Check if first bank is free
if (spi->SPI_TCR == 0) {
spi->SPI_TPR = (unsigned int) buffer;
spi->SPI_TCR = length;
spi->SPI_PTCR = AT91C_PDC_TXTEN;
return 1;
}
// Check if second bank is free
else if (spi->SPI_TNCR == 0) {
spi->SPI_TNPR = (unsigned int) buffer;
spi->SPI_TNCR = length;
return 1;
}
// No free banks
return 0;
}
//------------------------------------------------------------------------------
/// Returns 1 if there is no pending write operation on the SPI; otherwise
/// returns 0.
/// \param pSpi Pointer to an AT91S_SPI instance.
//------------------------------------------------------------------------------
unsigned char SPI_IsFinished(AT91S_SPI *pSpi)
{
return ((pSpi->SPI_SR & AT91C_SPI_TXEMPTY) != 0);
}
//------------------------------------------------------------------------------
/// Reads and returns the last word of data received by a SPI peripheral. This
/// method must be called after a successful SPI_Write call.
/// \param spi Pointer to an AT91S_SPI instance.
//------------------------------------------------------------------------------
unsigned short SPI_Read(AT91S_SPI *spi)
{
while ((spi->SPI_SR & AT91C_SPI_RDRF) == 0);
return spi->SPI_RDR & 0xFFFF;
}
//------------------------------------------------------------------------------
/// Reads data from a SPI peripheral until the provided buffer is filled. This
/// method does NOT need to be called after SPI_Write or SPI_WriteBuffer.
/// \param spi Pointer to an AT91S_SPI instance.
/// \param buffer Data buffer to store incoming bytes.
/// \param length Length in bytes of the data buffer.
//------------------------------------------------------------------------------
unsigned char SPI_ReadBuffer(AT91S_SPI *spi,
void *buffer,
unsigned int length)
{
// Check if the first bank is free
if (spi->SPI_RCR == 0) {
spi->SPI_RPR = (unsigned int) buffer;
spi->SPI_RCR = length;
spi->SPI_PTCR = AT91C_PDC_RXTEN;
return 1;
}
// Check if second bank is free
else if (spi->SPI_RNCR == 0) {
spi->SPI_RNPR = (unsigned int) buffer;
spi->SPI_RNCR = length;
return 1;
}
// No free bank
return 0;
}

View file

@ -0,0 +1,114 @@
/* ----------------------------------------------------------------------------
* 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
/// !Purpose
///
/// Definitions for SPI peripheral usage.
///
/// !Usage
///
/// -# Enable the SPI pins required by the application (see pio.h).
/// -# Configure the SPI using the SPI_Configure function. This enables the
/// peripheral clock. The mode register is loaded with the given value.
/// -# Configure all the necessary chip selects with SPI_ConfigureNPCS.
/// -# Enable the SPI by calling SPI_Enable.
/// -# Send/receive data using SPI_Write and SPI_Read. Note that SPI_Read
/// must be called after SPI_Write to retrieve the last value read.
/// -# Send/receive data using the PDC with the SPI_WriteBuffer and
/// SPI_ReadBuffer functions.
/// -# Disable the SPI by calling SPI_Disable.
//------------------------------------------------------------------------------
#ifndef SPI_H
#define SPI_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "SPI configuration macros"
/// This page lists several macros which should be used when configuring a SPI
/// peripheral.
///
/// !Macros
/// - SPI_PCS
/// - SPI_SCBR
/// - SPI_DLYBS
/// - SPI_DLYBCT
/// Calculate the PCS field value given the chip select NPCS value
#define SPI_PCS(npcs) ((~(1 << npcs) & 0xF) << 16)
/// Calculates the value of the CSR SCBR field given the baudrate and MCK.
#define SPI_SCBR(baudrate, masterClock) \
((unsigned int) (masterClock / baudrate) << 8)
/// Calculates the value of the CSR DLYBS field given the desired delay (in ns)
#define SPI_DLYBS(delay, masterClock) \
((unsigned int) (((masterClock / 1000000) * delay) / 1000) << 16)
/// Calculates the value of the CSR DLYBCT field given the desired delay (in ns)
#define SPI_DLYBCT(delay, masterClock) \
((unsigned int) (((masterClock / 1000000) * delay) / 32000) << 16)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void SPI_Enable(AT91S_SPI *spi);
extern void SPI_Disable(AT91S_SPI *spi);
extern void SPI_Configure(AT91S_SPI *spi,
unsigned int id,
unsigned int configuration);
extern void SPI_ConfigureNPCS(AT91S_SPI *spi,
unsigned int npcs,
unsigned int configuration);
extern void SPI_Write(AT91S_SPI *spi, unsigned int npcs, unsigned short data);
extern unsigned char SPI_WriteBuffer(AT91S_SPI *spi,
void *buffer,
unsigned int length);
extern unsigned char SPI_IsFinished(AT91S_SPI *pSpi);
extern unsigned short SPI_Read(AT91S_SPI *spi);
extern unsigned char SPI_ReadBuffer(AT91S_SPI *spi,
void *buffer,
unsigned int length);
#endif //#ifndef SPI_H

View file

@ -0,0 +1,243 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "ssc.h"
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures a SSC peripheral. If the divided clock is not used, the master
/// clock frequency can be set to 0.
/// \note The emitter and transmitter are disabled by this function.
/// \param ssc Pointer to an AT91S_SSC instance.
/// \param id Peripheral ID of the SSC.
//------------------------------------------------------------------------------
void SSC_Configure(AT91S_SSC *ssc,
unsigned int id,
unsigned int bitRate,
unsigned int masterClock)
{
// Enable SSC peripheral clock
AT91C_BASE_PMC->PMC_PCER = 1 << id;
// Reset, disable receiver & transmitter
ssc->SSC_CR = AT91C_SSC_RXDIS | AT91C_SSC_TXDIS | AT91C_SSC_SWRST;
ssc->SSC_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
// Configure clock frequency
if (bitRate != 0) {
ssc->SSC_CMR = masterClock / (2 * bitRate);
}
else {
ssc->SSC_CMR = 0;
}
}
//------------------------------------------------------------------------------
/// Configures the transmitter of a SSC peripheral. Several macros can be used
/// to compute the values of the Transmit Clock Mode Register (TCMR) and the
/// Transmit Frame Mode Register (TFMR) (see "SSC configuration macros").
/// \param ssc Pointer to a AT91S_SSC instance.
/// \param tcmr Transmit Clock Mode Register value.
/// \param tfmr Transmit Frame Mode Register value.
//------------------------------------------------------------------------------
void SSC_ConfigureTransmitter(AT91S_SSC *ssc,
unsigned int tcmr,
unsigned int tfmr)
{
ssc->SSC_TCMR = tcmr;
ssc->SSC_TFMR = tfmr;
}
//------------------------------------------------------------------------------
/// Configures the receiver of a SSC peripheral. Several macros can be used
/// to compute the values of the Receive Clock Mode Register (TCMR) and the
/// Receive Frame Mode Register (TFMR) (see "SSC configuration macros").
/// \param ssc Pointer to a AT91S_SSC instance.
/// \param rcmr Receive Clock Mode Register value.
/// \param rfmr Receive Frame Mode Register value.
//------------------------------------------------------------------------------
void SSC_ConfigureReceiver(AT91S_SSC *ssc,
unsigned int rcmr,
unsigned int rfmr)
{
ssc->SSC_RCMR = rcmr;
ssc->SSC_RFMR = rfmr;
}
//------------------------------------------------------------------------------
/// Enables the transmitter of a SSC peripheral.
/// \param ssc Pointer to an AT91S_SSC instance.
//------------------------------------------------------------------------------
void SSC_EnableTransmitter(AT91S_SSC *ssc)
{
ssc->SSC_CR = AT91C_SSC_TXEN;
}
//------------------------------------------------------------------------------
/// Disables the transmitter of a SSC peripheral.
/// \param ssc Pointer to an AT91S_SSC instance.
//------------------------------------------------------------------------------
void SSC_DisableTransmitter(AT91S_SSC *ssc)
{
ssc->SSC_CR = AT91C_SSC_TXDIS;
}
//------------------------------------------------------------------------------
/// Enables the receiver of a SSC peripheral.
/// \param ssc Pointer to an AT91S_SSC instance.
//------------------------------------------------------------------------------
void SSC_EnableReceiver(AT91S_SSC *ssc)
{
ssc->SSC_CR = AT91C_SSC_RXEN;
}
//------------------------------------------------------------------------------
/// Disables the receiver of a SSC peripheral.
/// \param ssc Pointer to an AT91S_SSC instance.
//------------------------------------------------------------------------------
void SSC_DisableReceiver(AT91S_SSC *ssc)
{
ssc->SSC_CR = AT91C_SSC_RXDIS;
}
//------------------------------------------------------------------------------
/// Enables one or more interrupt sources of a SSC peripheral.
/// \param ssc Pointer to an AT91S_SSC instance.
/// \param sources Interrupt sources to enable.
//------------------------------------------------------------------------------
void SSC_EnableInterrupts(AT91S_SSC *ssc, unsigned int sources)
{
ssc->SSC_IER = sources;
}
//------------------------------------------------------------------------------
/// Disables one or more interrupt sources of a SSC peripheral.
/// \param ssc Pointer to an AT91S_SSC instance.
/// \param sources Interrupt source to disable.
//------------------------------------------------------------------------------
void SSC_DisableInterrupts(AT91S_SSC *ssc, unsigned int sources)
{
ssc->SSC_IDR = sources;
}
//------------------------------------------------------------------------------
/// Sends one data frame through a SSC peripheral. If another frame is currently
/// being sent, this function waits for the previous transfer to complete.
/// \param ssc Pointer to an AT91S_SSC instance.
/// \param frame Data frame to send.
//------------------------------------------------------------------------------
void SSC_Write(AT91S_SSC *ssc, unsigned int frame)
{
while ((ssc->SSC_SR & AT91C_SSC_TXRDY) == 0);
ssc->SSC_THR = frame;
}
//------------------------------------------------------------------------------
/// Sends the contents of a data buffer a SSC peripheral, using the PDC. Returns
/// true if the buffer has been queued for transmission; otherwise returns
/// false.
/// \param ssc Pointer to an AT91S_SSC instance.
/// \param buffer Data buffer to send.
/// \param length Size of the data buffer.
//------------------------------------------------------------------------------
unsigned char SSC_WriteBuffer(AT91S_SSC *ssc,
void *buffer,
unsigned int length)
{
// Check if first bank is free
if (ssc->SSC_TCR == 0) {
ssc->SSC_TPR = (unsigned int) buffer;
ssc->SSC_TCR = length;
ssc->SSC_PTCR = AT91C_PDC_TXTEN;
return 1;
}
// Check if second bank is free
else if (ssc->SSC_TNCR == 0) {
ssc->SSC_TNPR = (unsigned int) buffer;
ssc->SSC_TNCR = length;
return 1;
}
// No free banks
return 0;
}
//------------------------------------------------------------------------------
/// Waits until one frame is received on a SSC peripheral, and returns it.
/// \param ssc Pointer to an AT91S_SSC instance.
//------------------------------------------------------------------------------
unsigned int SSC_Read(AT91S_SSC *ssc)
{
while ((ssc->SSC_SR & AT91C_SSC_RXRDY) == 0);
return ssc->SSC_RHR;
}
//------------------------------------------------------------------------------
/// Reads data coming from a SSC peripheral receiver and stores it into the
/// provided buffer. Returns true if the buffer has been queued for reception;
/// otherwise returns false.
/// \param ssc Pointer to an AT91S_SSC instance.
/// \param buffer Data buffer used for reception.
/// \param length Size in bytes of the data buffer.
//------------------------------------------------------------------------------
unsigned char SSC_ReadBuffer(AT91S_SSC *ssc,
void *buffer,
unsigned int length)
{
// Check if the first bank is free
if (ssc->SSC_RCR == 0) {
ssc->SSC_RPR = (unsigned int) buffer;
ssc->SSC_RCR = length;
ssc->SSC_PTCR = AT91C_PDC_RXTEN;
return 1;
}
// Check if second bank is free
else if (ssc->SSC_RNCR == 0) {
ssc->SSC_RNPR = (unsigned int) buffer;
ssc->SSC_RNCR = length;
return 1;
}
// No free bank
return 0;
}

View file

@ -0,0 +1,133 @@
/* ----------------------------------------------------------------------------
* 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
/// !Purpose
///
/// Set of functions and definition for using a SSC
/// peripheral.
///
/// !Usage
///
/// -# Configure the SSC to operate at a specific frequency by calling
/// SSC_Configure(). This function enables the peripheral clock of the SSC,
/// but not its PIOs.
/// -# Configure the transmitter and/or the receiver using the
/// SSC_ConfigureTransmitter() and SSC_ConfigureEmitter() functions.
/// -# Enable the PIOs or the transmitter and/or the received using
/// CHIP_EnableSSCTransmitter() and CHIP_EnableSSCReceiver().
/// -# Enable the transmitter and/or the receiver using SSC_EnableTransmitter()
/// and SSC_EnableReceiver()
/// -# Send data through the transmitter using SSC_Write() and SSC_WriteBuffer()
/// -# Receive data from the receiver using SSC_Read() and SSC_ReadBuffer()
/// -# Disable the transmitter and/or the receiver using SSC_DisableTransmitter()
/// and SSC_DisableReceiver()
//------------------------------------------------------------------------------
#ifndef SSC_H
#define SSC_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "SSC configuration macros"
/// This page lists several macros which are used when configuring a SSC
/// peripheral.
///
/// !Macros
/// - SSC_STTDLY
/// - SSC_PERIOD
/// - SSC_DATLEN
/// - SSC_DATNB
/// - SSC_FSLEN
/// Calculates the value of the STTDLY field given the number of clock cycles
/// before the first bit of a new frame is transmitted.
#define SSC_STTDLY(bits) (bits << 16)
/// Calculates the value of the PERIOD field of the Transmit Clock Mode Register
/// of an SSC interface, given the desired clock divider.
#define SSC_PERIOD(divider) (((divider / 2) - 1) << 24)
/// Calculates the value of the DATLEN field of the Transmit Frame Mode Register
/// of an SSC interface, given the number of bits in one sample.
#define SSC_DATLEN(bits) (bits - 1)
/// Calculates the value of the DATNB field of the Transmit Frame Mode Register
/// of an SSC interface, given the number of samples in one frame.
#define SSC_DATNB(samples) ((samples -1) << 8)
/// Calculates the value of the FSLEN field of the Transmit Frame Mode Register
/// of an SSC interface, given the number of transmit clock periods that the
/// frame sync signal should take.
#define SSC_FSLEN(periods) ((periods - 1) << 16)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void SSC_Configure(AT91S_SSC *ssc,
unsigned int id,
unsigned int bitRate,
unsigned int masterClock);
extern void SSC_ConfigureTransmitter(AT91S_SSC *ssc,
unsigned int tcmr,
unsigned int tfmr);
extern void SSC_ConfigureReceiver(AT91S_SSC *ssc,
unsigned int rcmr,
unsigned int rfmr);
extern void SSC_EnableTransmitter(AT91S_SSC *ssc);
extern void SSC_DisableTransmitter(AT91S_SSC *ssc);
extern void SSC_EnableReceiver(AT91S_SSC *ssc);
extern void SSC_DisableReceiver(AT91S_SSC *ssc);
extern void SSC_EnableInterrupts(AT91S_SSC *ssc, unsigned int sources);
extern void SSC_DisableInterrupts(AT91S_SSC *ssc, unsigned int sources);
extern void SSC_Write(AT91S_SSC *ssc, unsigned int frame);
extern unsigned char SSC_WriteBuffer(AT91S_SSC *ssc,
void *buffer,
unsigned int length);
extern unsigned int SSC_Read(AT91S_SSC *ssc);
extern unsigned char SSC_ReadBuffer(AT91S_SSC *ssc,
void *buffer,
unsigned int length);
#endif //#ifndef SSC_H

View file

@ -0,0 +1,223 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "supc.h"
#include <board.h>
#include <utility/assert.h>
//------------------------------------------------------------------------------
// Local definitions
//------------------------------------------------------------------------------
/// Key value for the SUPC_MR register.
#define SUPC_KEY ((unsigned int) (0xA5 << 24))
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Enables the SLCD power supply.
/// \param internal If 1, the power supply is configured as internal; otherwise
/// it is set at external.
//------------------------------------------------------------------------------
void SUPC_EnableSlcd(unsigned char internal)
{
if (internal) {
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_LCDMODE) | AT91C_SUPC_LCDMODE_INTERNAL;
}
else {
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_LCDMODE) | AT91C_SUPC_LCDMODE_EXTERNAL;
}
while ((AT91C_BASE_SUPC->SUPC_SR & AT91C_SUPC_LCDS) != AT91C_SUPC_LCDS);
}
//------------------------------------------------------------------------------
/// Disables the SLCD power supply.
//------------------------------------------------------------------------------
void SUPC_DisableSlcd(void)
{
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_LCDMODE);
while ((AT91C_BASE_SUPC->SUPC_SR & AT91C_SUPC_LCDS) == AT91C_SUPC_LCDS);
}
//------------------------------------------------------------------------------
/// Sets the output voltage of the SLCD charge pump.
/// \param voltage Output voltage.
//------------------------------------------------------------------------------
void SUPC_SetSlcdVoltage(unsigned int voltage)
{
SANITY_CHECK((voltage & ~AT91C_SUPC_LCDOUT) == 0);
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_LCDOUT) | voltage;
}
#if !defined(__ICCARM__)
__attribute__ ((section (".ramfunc"))) // GCC
#endif
//------------------------------------------------------------------------------
/// Enables the flash power supply with the given wake-up setting.
/// \param time Wake-up time.
//------------------------------------------------------------------------------
void SUPC_EnableFlash(unsigned int time)
{
AT91C_BASE_SUPC->SUPC_FWUTR = time;
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | AT91C_BASE_SUPC->SUPC_MR | AT91C_SUPC_FLASHON;
while ((AT91C_BASE_SUPC->SUPC_SR & AT91C_SUPC_FLASHS) != AT91C_SUPC_FLASHS);
}
#if !defined(__ICCARM__)
__attribute__ ((section (".ramfunc"))) // GCC
#endif
//------------------------------------------------------------------------------
/// Disables the flash power supply.
//------------------------------------------------------------------------------
void SUPC_DisableFlash(void)
{
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_FLASHON);
while ((AT91C_BASE_SUPC->SUPC_SR & AT91C_SUPC_FLASHS) == AT91C_SUPC_FLASHS);
}
//------------------------------------------------------------------------------
/// Sets the voltage regulator output voltage.
/// \param voltage Voltage to set.
//------------------------------------------------------------------------------
void SUPC_SetVoltageOutput(unsigned int voltage)
{
SANITY_CHECK((voltage & ~AT91C_SUPC_VRVDD) == 0);
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_VRVDD) | voltage;
}
//------------------------------------------------------------------------------
/// Puts the voltage regulator in deep mode.
//------------------------------------------------------------------------------
void SUPC_EnableDeepMode(void)
{
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | AT91C_BASE_SUPC->SUPC_MR | AT91C_SUPC_VRDEEP;
}
//------------------------------------------------------------------------------
/// Puts the voltage regulator in normal mode.
//------------------------------------------------------------------------------
void SUPC_DisableDeepMode(void)
{
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_VRDEEP);
}
//-----------------------------------------------------------------------------
/// Enables the backup SRAM power supply, so its data is saved while the device
/// is in backup mode.
//-----------------------------------------------------------------------------
void SUPC_EnableSram(void)
{
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | AT91C_BASE_SUPC->SUPC_MR | AT91C_SUPC_SRAMON;
}
//-----------------------------------------------------------------------------
/// Disables the backup SRAM power supply.
//-----------------------------------------------------------------------------
void SUPC_DisableSram(void)
{
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_SRAMON);
}
//-----------------------------------------------------------------------------
/// Enables the RTC power supply.
//-----------------------------------------------------------------------------
void SUPC_EnableRtc(void)
{
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | AT91C_BASE_SUPC->SUPC_MR | AT91C_SUPC_RTCON;
while ((AT91C_BASE_SUPC->SUPC_SR & AT91C_SUPC_RTS) != AT91C_SUPC_RTS);
}
//-----------------------------------------------------------------------------
/// Disables the RTC power supply.
//-----------------------------------------------------------------------------
void SUPC_DisableRtc(void)
{
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_RTCON);
while ((AT91C_BASE_SUPC->SUPC_SR & AT91C_SUPC_RTS) == AT91C_SUPC_RTS);
}
//-----------------------------------------------------------------------------
/// Sets the BOD sampling mode (or disables it).
/// \param mode BOD sampling mode.
//-----------------------------------------------------------------------------
void SUPC_SetBodSampling(unsigned int mode)
{
SANITY_CHECK((mode & ~AT91C_SUPC_BODSMPL) == 0);
AT91C_BASE_SUPC->SUPC_BOMR &= ~AT91C_SUPC_BODSMPL;
AT91C_BASE_SUPC->SUPC_BOMR |= mode;
}
//------------------------------------------------------------------------------
/// Disables the voltage regulator, which makes the device enter backup mode.
//------------------------------------------------------------------------------
void SUPC_DisableVoltageRegulator(void)
{
AT91C_BASE_SUPC->SUPC_CR = SUPC_KEY | AT91C_SUPC_VROFF;
while (1);
}
//------------------------------------------------------------------------------
/// Shuts the device down so it enters Off mode.
//------------------------------------------------------------------------------
void SUPC_Shutdown(void)
{
AT91C_BASE_SUPC->SUPC_CR = SUPC_KEY | AT91C_SUPC_SHDW;
while (1);
}
//------------------------------------------------------------------------------
/// Sets the wake-up sources when in backup mode.
/// \param sources Wake-up sources to enable.
//------------------------------------------------------------------------------
void SUPC_SetWakeUpSources(unsigned int sources)
{
SANITY_CHECK((sources & ~0x0000000B) == 0);
AT91C_BASE_SUPC->SUPC_WUMR &= ~0x0000000B;
AT91C_BASE_SUPC->SUPC_WUMR |= sources;
}
//------------------------------------------------------------------------------
/// Sets the wake-up inputs when in backup mode.
/// \param inputs Wake up inputs to enable.
//------------------------------------------------------------------------------
void SUPC_SetWakeUpInputs(unsigned int inputs)
{
SANITY_CHECK((inputs & ~0xFFFF) == 0);
AT91C_BASE_SUPC->SUPC_WUIR &= ~0xFFFF;
AT91C_BASE_SUPC->SUPC_WUIR |= inputs;
}

View file

@ -0,0 +1,80 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef SUPC_H
#define SUPC_H
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void SUPC_EnableSlcd(unsigned char internal);
extern void SUPC_DisableSlcd(void);
extern void SUPC_SetSlcdVoltage(unsigned int voltage);
extern
#ifdef __ICCARM__
__ramfunc // IAR
#endif
void SUPC_EnableFlash(unsigned int time);
extern
#ifdef __ICCARM__
__ramfunc // IAR
#endif
void SUPC_DisableFlash(void);
extern void SUPC_SetVoltageOutput(unsigned int voltage);
extern void SUPC_EnableDeepMode(void);
extern void SUPC_EnableSram(void);
extern void SUPC_DisableSram(void);
extern void SUPC_EnableRtc(void);
extern void SUPC_DisableRtc(void);
extern void SUPC_SetBodSampling(unsigned int mode);
extern void SUPC_DisableDeepMode(void);
extern void SUPC_DisableVoltageRegulator(void);
extern void SUPC_Shutdown(void);
extern void SUPC_SetWakeUpSources(unsigned int sources);
extern void SUPC_SetWakeUpInputs(unsigned int inputs);
#endif //#ifndef SUPC_H

View file

@ -0,0 +1,140 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "tc.h"
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures a Timer Counter to operate in the given mode. Timer is stopped
/// after configuration and must be restarted with TC_Start().
/// to obtain the target frequency.
/// \param pTc Pointer to an AT91S_TC instance.
/// \param mode Operating mode.
//------------------------------------------------------------------------------
void TC_Configure(AT91S_TC *pTc, unsigned int mode)
{
// Disable TC clock
pTc->TC_CCR = AT91C_TC_CLKDIS;
// Disable interrupts
pTc->TC_IDR = 0xFFFFFFFF;
// Clear status register
pTc->TC_SR;
// Set mode
pTc->TC_CMR = mode;
}
//------------------------------------------------------------------------------
/// Starts the timer clock.
/// \param pTc Pointer to an AT91S_TC instance.
//------------------------------------------------------------------------------
void TC_Start(AT91S_TC *pTc)
{
pTc->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
}
//------------------------------------------------------------------------------
/// Stops the timer clock.
/// \param pTc Pointer to an AT91S_TC instance.
//------------------------------------------------------------------------------
void TC_Stop(AT91S_TC *pTc)
{
pTc->TC_CCR = AT91C_TC_CLKDIS;
}
//------------------------------------------------------------------------------
/// Finds the best MCK divisor given the timer frequency and MCK. The result
/// is guaranteed to satisfy the following equation:
/// (MCK / (DIV * 65536)) <= freq <= (MCK / DIV)
/// with DIV being the highest possible value.
/// Returns 1 if a divisor could be found; otherwise returns 0.
/// \param freq Desired timer frequency.
/// \param mck Master clock frequency.
/// \param div Divisor value.
/// \param tcclks TCCLKS field value for divisor.
//------------------------------------------------------------------------------
unsigned char TC_FindMckDivisor(
unsigned int freq,
unsigned int mck,
unsigned int *div,
unsigned int *tcclks)
{
const unsigned int divisors[5] = {2, 8, 32, 128,
#if defined(at91sam9260) || defined(at91sam9261) || defined(at91sam9263) \
|| defined(at91sam9xe) || defined(at91sam9rl64) || defined(at91cap9)
BOARD_MCK / 32768};
#else
1024};
#endif
unsigned int index = 0;
// Satisfy lower bound
while (freq < ((mck / divisors[index]) / 65536)) {
index++;
// If no divisor can be found, return 0
if (index == 5) {
return 0;
}
}
// Try to maximise DIV while satisfying upper bound
while (index < 4) {
if (freq > (mck / divisors[index + 1])) {
break;
}
index++;
}
// Store results
if (div) {
*div = divisors[index];
}
if (tcclks) {
*tcclks = index;
}
return 1;
}

View file

@ -0,0 +1,60 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef TC_H
#define TC_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#if !defined(AT91C_ID_TC0) && defined(AT91C_ID_TC012)
#define AT91C_ID_TC0 AT91C_ID_TC012
#endif
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void TC_Configure(AT91S_TC *pTc, unsigned int mode);
extern void TC_Start(AT91S_TC *pTc);
extern void TC_Stop(AT91S_TC *pTc);
extern unsigned char TC_FindMckDivisor(
unsigned int freq,
unsigned int mck,
unsigned int *div,
unsigned int *tcclks);
#endif //#ifndef TC_H

View file

@ -0,0 +1,232 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef trace_LEVEL
#define trace_LEVEL 1
#endif
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "tdes.h"
#include <board.h>
#include <utility/assert.h>
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures the triple-DES peripheral to cipher/decipher, use single-DES or
/// triple-DES, use two or three keys (when in triple-DES mode), start manually,
/// automatically or via the PDC and use the given operating mode (ECB, CBC,
/// CFB or OFB).
/// \param cipher Encrypts if 1, decrypts if 0.
/// \param tdesmod Single- or triple-DES mode.
/// \param keymod Use two or three keys (must be 0 in single-DES mode).
/// \param smod Start mode.
/// \param opmod Encryption/decryption mode.
//------------------------------------------------------------------------------
void TDES_Configure(
unsigned char cipher,
unsigned int tdesmod,
unsigned int keymod,
unsigned int smod,
unsigned int opmod)
{
trace_LOG(trace_DEBUG, "-D- TDES_Configure()\n\r");
SANITY_CHECK((cipher & 0xFFFFFFFE) == 0);
SANITY_CHECK((tdesmod & 0xFFFFFFFD) == 0);
SANITY_CHECK((keymod & 0xFFFFFFEF) == 0);
SANITY_CHECK((smod & 0xFFFFFCFF) == 0);
SANITY_CHECK((opmod & 0xFFFFCFFF) == 0);
// Reset peripheral
AT91C_BASE_TDES->TDES_CR = AT91C_TDES_SWRST;
// Configure mode register
AT91C_BASE_TDES->TDES_MR = cipher | tdesmod | keymod | smod | opmod;
}
//------------------------------------------------------------------------------
/// Starts the encryption or decryption process if the TDES peripheral is
/// configured in manual or PDC mode.
//------------------------------------------------------------------------------
void TDES_Start(void)
{
trace_LOG(trace_DEBUG, "-D- TDES_Start()\n\r");
SANITY_CHECK(((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_SMOD) == AT91C_TDES_SMOD_MANUAL)
|| ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_SMOD) == AT91C_TDES_SMOD_PDC));
// Manual mode
if ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_SMOD) == AT91C_TDES_SMOD_MANUAL) {
AT91C_BASE_TDES->TDES_CR = AT91C_TDES_START;
}
// PDC mode
else {
AT91C_BASE_TDES->TDES_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
}
}
//------------------------------------------------------------------------------
/// Returns the current status register value of the TDES peripheral.
//------------------------------------------------------------------------------
unsigned int TDES_GetStatus(void)
{
trace_LOG(trace_DEBUG, "-D- TDES_GetStatus()\n\r");
return AT91C_BASE_TDES->TDES_ISR;
}
//------------------------------------------------------------------------------
/// Sets the 64-bits keys (one, two or three depending on the configuration)
/// that shall be used by the TDES algorithm.
/// \param pKey1 Pointer to key #1.
/// \param pKey2 Pointer to key #2 (shall be 0 in single-DES mode).
/// \param pKey3 Pointer to key #3 (shall be 0 when using two keys).
//------------------------------------------------------------------------------
void TDES_SetKeys(
const unsigned int *pKey1,
const unsigned int *pKey2,
const unsigned int *pKey3)
{
trace_LOG(trace_DEBUG, "-D- TDES_SetKeys()\n\r");
SANITY_CHECK(pKey1);
SANITY_CHECK((pKey2 && ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_TDESMOD) == AT91C_TDES_TDESMOD))
|| (!pKey2 && ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_TDESMOD) == 0)));
SANITY_CHECK((pKey3
&& ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_TDESMOD) == AT91C_TDES_TDESMOD)
&& ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_KEYMOD) == 0))
||
(!pKey3
&& ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_TDESMOD) == AT91C_TDES_TDESMOD)
&& ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_KEYMOD) == AT91C_TDES_KEYMOD))
||
(!pKey3
&& ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_TDESMOD) == 0)
&& ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_KEYMOD) == 0)));
// Write key #1
if (pKey1) {
AT91C_BASE_TDES->TDES_KEY1WxR[0] = pKey1[0];
AT91C_BASE_TDES->TDES_KEY1WxR[1] = pKey1[1];
}
// Write key #2
if (pKey1) {
AT91C_BASE_TDES->TDES_KEY2WxR[0] = pKey2[0];
AT91C_BASE_TDES->TDES_KEY2WxR[1] = pKey2[1];
}
// Write key #2
if (pKey1) {
AT91C_BASE_TDES->TDES_KEY3WxR[0] = pKey3[0];
AT91C_BASE_TDES->TDES_KEY3WxR[1] = pKey3[1];
}
}
//------------------------------------------------------------------------------
/// Sets the input data to encrypt/decrypt using TDES.
/// \param pInput Pointer to the 64-bits input data.
//------------------------------------------------------------------------------
void TDES_SetInputData(const unsigned int *pInput)
{
trace_LOG(trace_DEBUG, "-D- TDES_SetInputData()\n\r");
SANITY_CHECK(pInput);
AT91C_BASE_TDES->TDES_IDATAxR[0] = pInput[0];
AT91C_BASE_TDES->TDES_IDATAxR[1] = pInput[1];
}
//------------------------------------------------------------------------------
/// Sets the input data buffer to encrypt/decrypt when in PDC mode.
/// \param pInput Pointer to the input data.
/// \param size Size of buffer in bytes.
//------------------------------------------------------------------------------
void TDES_SetInputBuffer(const unsigned int *pInput, unsigned int size)
{
trace_LOG(trace_DEBUG, "-D- TDES_SetInputBuffer()\n\r");
SANITY_CHECK(pInput);
SANITY_CHECK((size > 0) && ((size % 8) == 0));
AT91C_BASE_TDES->TDES_TPR = (unsigned int) pInput;
AT91C_BASE_TDES->TDES_TCR = size / 4;
}
//------------------------------------------------------------------------------
/// Stores the output data from the last TDES operation into the given 64-bits
/// buffers.
/// \param pOutput Pointer to a 64-bits output buffer.
//------------------------------------------------------------------------------
void TDES_GetOutputData(unsigned int *pOutput)
{
trace_LOG(trace_DEBUG, "-D- TDES_GetOutputData()\n\r");
SANITY_CHECK(pOutput);
pOutput[0] = AT91C_BASE_TDES->TDES_ODATAxR[0];
pOutput[1] = AT91C_BASE_TDES->TDES_ODATAxR[1];
}
//------------------------------------------------------------------------------
/// Sets the output buffer which will receive the encrypted/decrypted data when
/// using the PDC.
/// \param pOutput Pointer to the output data.
/// \param size Size of buffer in bytes.
//------------------------------------------------------------------------------
void TDES_SetOutputBuffer(unsigned int *pOutput, unsigned int size)
{
trace_LOG(trace_DEBUG, "-D- TDES_SetOutputBuffer()\n\r");
SANITY_CHECK(pOutput);
SANITY_CHECK((size > 0) && ((size % 8) == 0));
AT91C_BASE_TDES->TDES_RPR = (unsigned int) pOutput;
AT91C_BASE_TDES->TDES_RCR = size / 4;
}
//------------------------------------------------------------------------------
/// Sets the initialization vector to use when the TDES algorithm is configured
/// in a chained block mode (CBC, CFB or OFB).
/// \param pVector Pointer to the 64-bits vector.
//------------------------------------------------------------------------------
void TDES_SetVector(const unsigned int *pVector)
{
trace_LOG(trace_DEBUG, "-D- TDES_SetVector()\n\r");
SANITY_CHECK(pVector);
AT91C_BASE_TDES->TDES_IVxR[0] = pVector[0];
AT91C_BASE_TDES->TDES_IVxR[1] = pVector[1];
}

View file

@ -0,0 +1,63 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef TDES_H
#define TDES_H
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void TDES_Configure(
unsigned char cipher,
unsigned int tdesmod,
unsigned int keymod,
unsigned int smod,
unsigned int opmod);
extern void TDES_Start(void);
extern unsigned int TDES_GetStatus(void);
extern void TDES_SetKeys(
const unsigned int *pKey1,
const unsigned int *pKey2,
const unsigned int *pKey3);
extern void TDES_SetInputData(const unsigned int *pInput);
extern void TDES_SetInputBuffer(const unsigned int *pInput, unsigned int size);
extern void TDES_GetOutputData(unsigned int *pOutput);
extern void TDES_SetOutputBuffer(unsigned int *pOutput, unsigned int size);
extern void TDES_SetVector(const unsigned int *pVector);
#endif //#ifndef TDES_H

View file

@ -0,0 +1,281 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef trace_LEVEL
#define trace_LEVEL 1
#endif
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "twi.h"
#include <utility/math.h>
#include <utility/assert.h>
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures a TWI peripheral to operate in master mode, at the given
/// frequency (in Hz). The duty cycle of the TWI clock is set to 50%.
/// \param pTwi Pointer to an AT91S_TWI instance.
/// \param twck Desired TWI clock frequency.
/// \param mck Master clock frequency.
//------------------------------------------------------------------------------
void TWI_Configure(AT91S_TWI *pTwi, unsigned int twck, unsigned int mck)
{
unsigned int ckdiv = 0;
unsigned int cldiv;
unsigned char ok = 0;
trace_LOG(trace_DEBUG, "-D- TWI_Configure()\n\r");
SANITY_CHECK(pTwi);
// Reset the TWI
pTwi->TWI_CR = AT91C_TWI_SWRST;
// Set master mode
pTwi->TWI_CR = AT91C_TWI_MSEN;
// Configure clock
while (!ok) {
cldiv = ((mck / (2 * twck)) - 3) / power(2, ckdiv);
if (cldiv <= 255) {
ok = 1;
}
else {
ckdiv++;
}
}
ASSERT(ckdiv < 8, "-F- Cannot find valid TWI clock parameters\n\r");
trace_LOG(trace_INFO, "-D- Using CKDIV = %u and CLDIV/CHDIV = %u\n\r", ckdiv, cldiv);
pTwi->TWI_CWGR = (ckdiv << 16) | (cldiv << 8) | cldiv;
}
//------------------------------------------------------------------------------
/// Sends a STOP condition on the TWI.
/// \param pTwi Pointer to an AT91S_TWI instance.
//------------------------------------------------------------------------------
void TWI_Stop(AT91S_TWI *pTwi)
{
SANITY_CHECK(pTwi);
pTwi->TWI_CR = AT91C_TWI_STOP;
}
//------------------------------------------------------------------------------
/// Starts a read operation on the TWI bus with the specified slave, and returns
/// immediately. Data must then be read using TWI_ReadByte() whenever a byte is
/// available (poll using TWI_ByteReceived()).
/// \param pTwi Pointer to an AT91S_TWI instance.
/// \param address Slave address on the bus.
/// \param iaddress Optional internal address bytes.
/// \param isize Number of internal address bytes.
//-----------------------------------------------------------------------------
void TWI_StartRead(
AT91S_TWI *pTwi,
unsigned char address,
unsigned int iaddress,
unsigned char isize)
{
trace_LOG(trace_DEBUG, "-D- TWI_StartRead()\n\r");
SANITY_CHECK(pTwi);
SANITY_CHECK((address & 0x80) == 0);
SANITY_CHECK((iaddress & 0xFF000000) == 0);
SANITY_CHECK(isize < 4);
// Set slave address and number of internal address bytes
pTwi->TWI_MMR = (isize << 8) | AT91C_TWI_MREAD | (address << 16);
// Set internal address bytes
pTwi->TWI_IADR = iaddress;
// Send START condition
pTwi->TWI_CR = AT91C_TWI_START;
}
//-----------------------------------------------------------------------------
/// Reads a byte from the TWI bus. The read operation must have been started
/// using TWI_StartRead() and a byte must be available (check with
/// TWI_ByteReceived()).
/// Returns the byte read.
/// \param pTwi Pointer to an AT91S_TWI instance.
//-----------------------------------------------------------------------------
unsigned char TWI_ReadByte(AT91S_TWI *pTwi)
{
SANITY_CHECK(pTwi);
return pTwi->TWI_RHR;
}
//-----------------------------------------------------------------------------
/// Sends a byte of data to one of the TWI slaves on the bus. This function
/// must be called once before TWI_StartWrite() with the first byte of data
/// to send, then it shall be called repeatedly after that to send the
/// remaining bytes.
/// \param pTwi Pointer to an AT91S_TWI instance.
/// \param byte Byte to send.
//-----------------------------------------------------------------------------
void TWI_WriteByte(AT91S_TWI *pTwi, unsigned char byte)
{
SANITY_CHECK(pTwi);
pTwi->TWI_THR = byte;
}
//-----------------------------------------------------------------------------
/// Starts a write operation on the TWI to access the selected slave, then
/// returns immediately. A byte of data must be provided to start the write;
/// other bytes are written next.
/// \param pTwi Pointer to an AT91S_TWI instance.
/// \param address Address of slave to acccess on the bus.
/// \param iaddress Optional slave internal address.
/// \param isize Number of internal address bytes.
/// \param byte First byte to send.
//-----------------------------------------------------------------------------
void TWI_StartWrite(
AT91S_TWI *pTwi,
unsigned char address,
unsigned int iaddress,
unsigned char isize,
unsigned char byte)
{
trace_LOG(trace_DEBUG, "-D- TWI_StartWrite()\n\r");
SANITY_CHECK(pTwi);
SANITY_CHECK((address & 0x80) == 0);
SANITY_CHECK((iaddress & 0xFF000000) == 0);
SANITY_CHECK(isize < 4);
// Set slave address and number of internal address bytes
pTwi->TWI_MMR = (isize << 8) | (address << 16);
// Set internal address bytes
pTwi->TWI_IADR = iaddress;
// Write first byte to send
TWI_WriteByte(pTwi, byte);
}
//-----------------------------------------------------------------------------
/// Returns 1 if a byte has been received and can be read on the given TWI
/// peripheral; otherwise, returns 0. This function resets the status register
/// of the TWI.
/// \param pTwi Pointer to an AT91S_TWI instance.
//-----------------------------------------------------------------------------
unsigned char TWI_ByteReceived(AT91S_TWI *pTwi)
{
return ((pTwi->TWI_SR & AT91C_TWI_RXRDY) == AT91C_TWI_RXRDY);
}
//-----------------------------------------------------------------------------
/// Returns 1 if a byte has been sent, so another one can be stored for
/// transmission; otherwise returns 0. This function clears the status register
/// of the TWI.
/// \param pTwi Pointer to an AT91S_TWI instance.
//-----------------------------------------------------------------------------
unsigned char TWI_ByteSent(AT91S_TWI *pTwi)
{
return ((pTwi->TWI_SR & AT91C_TWI_TXRDY) == AT91C_TWI_TXRDY);
}
//-----------------------------------------------------------------------------
/// Returns 1 if the current transmission is complete (the STOP has been sent);
/// otherwise returns 0.
/// \param pTwi Pointer to an AT91S_TWI instance.
//-----------------------------------------------------------------------------
unsigned char TWI_TransferComplete(AT91S_TWI *pTwi)
{
return ((pTwi->TWI_SR & AT91C_TWI_TXCOMP) == AT91C_TWI_TXCOMP);
}
//-----------------------------------------------------------------------------
/// Enables the selected interrupts sources on a TWI peripheral.
/// \param pTwi Pointer to an AT91S_TWI instance.
/// \param sources Bitwise OR of selected interrupt sources.
//-----------------------------------------------------------------------------
void TWI_EnableIt(AT91S_TWI *pTwi, unsigned int sources)
{
SANITY_CHECK(pTwi);
SANITY_CHECK((sources & 0xFFFFFEF8) == 0);
pTwi->TWI_IER = sources;
}
//-----------------------------------------------------------------------------
/// Disables the selected interrupts sources on a TWI peripheral.
/// \param pTwi Pointer to an AT91S_TWI instance.
/// \param sources Bitwise OR of selected interrupt sources.
//-----------------------------------------------------------------------------
void TWI_DisableIt(AT91S_TWI *pTwi, unsigned int sources)
{
SANITY_CHECK(pTwi);
SANITY_CHECK((sources & 0xFFFFFEF8) == 0);
pTwi->TWI_IDR = sources;
}
//-----------------------------------------------------------------------------
/// Returns the current status register of the given TWI peripheral. This
/// resets the internal value of the status register, so further read may yield
/// different values.
/// \param pTwi Pointer to an AT91S_TWI instance.
//-----------------------------------------------------------------------------
unsigned int TWI_GetStatus(AT91S_TWI *pTwi)
{
SANITY_CHECK(pTwi);
return pTwi->TWI_SR;
}
//-----------------------------------------------------------------------------
/// Returns the current status register of the given TWI peripheral, but
/// masking interrupt sources which are not currently enabled.
/// This resets the internal value of the status register, so further read may
/// yield different values.
/// \param pTwi Pointer to an AT91S_TWI instance.
//-----------------------------------------------------------------------------
unsigned int TWI_GetMaskedStatus(AT91S_TWI *pTwi)
{
unsigned int status;
SANITY_CHECK(pTwi);
status = pTwi->TWI_SR;
status &= pTwi->TWI_IMR;
return status;
}

View file

@ -0,0 +1,108 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#ifndef TWI_H
#define TWI_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Global definitions
//------------------------------------------------------------------------------
// Missing AT91C_TWI_TXRDY definition.
#ifndef AT91C_TWI_TXRDY
#define AT91C_TWI_TXRDY AT91C_TWI_TXRDY_MASTER
#endif
// Missing AT91C_TWI_TXCOMP definition.
#ifndef AT91C_TWI_TXCOMP
#define AT91C_TWI_TXCOMP AT91C_TWI_TXCOMP_MASTER
#endif
//------------------------------------------------------------------------------
// Global macros
//------------------------------------------------------------------------------
/// Returns 1 if the TXRDY bit (ready to transmit data) is set in the given
/// status register value.
#define TWI_STATUS_TXRDY(status) ((status & AT91C_TWI_TXRDY) == AT91C_TWI_TXRDY)
/// Returns 1 if the RXRDY bit (ready to receive data) is set in the given
/// status register value.
#define TWI_STATUS_RXRDY(status) ((status & AT91C_TWI_RXRDY) == AT91C_TWI_RXRDY)
/// Returns 1 if the TXCOMP bit (transfer complete) is set in the given
/// status register value.
#define TWI_STATUS_TXCOMP(status) ((status & AT91C_TWI_TXCOMP) == AT91C_TWI_TXCOMP)
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void TWI_Configure(AT91S_TWI *pTwi, unsigned int twck, unsigned int mck);
extern void TWI_Stop(AT91S_TWI *pTwi);
extern void TWI_StartRead(
AT91S_TWI *pTwi,
unsigned char address,
unsigned int iaddress,
unsigned char isize);
extern unsigned char TWI_ReadByte(AT91S_TWI *pTwi);
extern void TWI_WriteByte(AT91S_TWI *pTwi, unsigned char byte);
extern void TWI_StartWrite(
AT91S_TWI *pTwi,
unsigned char address,
unsigned int iaddress,
unsigned char isize,
unsigned char byte);
extern unsigned char TWI_ByteReceived(AT91S_TWI *pTwi);
extern unsigned char TWI_ByteSent(AT91S_TWI *pTwi);
extern unsigned char TWI_TransferComplete(AT91S_TWI *pTwi);
extern void TWI_EnableIt(AT91S_TWI *pTwi, unsigned int sources);
extern void TWI_DisableIt(AT91S_TWI *pTwi, unsigned int sources);
extern unsigned int TWI_GetStatus(AT91S_TWI *pTwi);
extern unsigned int TWI_GetMaskedStatus(AT91S_TWI *pTwi);
#endif //#ifndef TWI_H

View file

@ -0,0 +1,259 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "usart.h"
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures an USART peripheral with the specified parameters.
/// \param usart Pointer to the USART peripheral to configure.
/// \param mode Desired value for the USART mode register (see the datasheet).
/// \param baudrate Baudrate at which the USART should operate (in Hz).
/// \param masterClock Frequency of the system master clock (in Hz).
//------------------------------------------------------------------------------
void USART_Configure(AT91S_USART *usart,
unsigned int mode,
unsigned int baudrate,
unsigned int masterClock)
{
// Reset and disable receiver & transmitter
usart->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX
| AT91C_US_RXDIS | AT91C_US_TXDIS;
// Configure mode
usart->US_MR = mode;
// Configure baudrate
// Asynchronous, no oversampling
if (((mode & AT91C_US_SYNC) == 0)
&& ((mode & AT91C_US_OVER) == 0)) {
usart->US_BRGR = (masterClock / baudrate) / 16;
}
// TODO other modes
}
//------------------------------------------------------------------------------
/// Enables or disables the transmitter of an USART peripheral.
/// \param usart Pointer to an USART peripheral
/// \param enabled If true, the transmitter is enabled; otherwise it is
/// disabled.
//------------------------------------------------------------------------------
void USART_SetTransmitterEnabled(AT91S_USART *usart,
unsigned char enabled)
{
if (enabled) {
usart->US_CR = AT91C_US_TXEN;
}
else {
usart->US_CR = AT91C_US_TXDIS;
}
}
//------------------------------------------------------------------------------
/// Enables or disables the receiver of an USART peripheral
/// \param usart Pointer to an USART peripheral
/// \param enabled If true, the receiver is enabled; otherwise it is disabled.
//------------------------------------------------------------------------------
void USART_SetReceiverEnabled(AT91S_USART *usart,
unsigned char enabled)
{
if (enabled) {
usart->US_CR = AT91C_US_RXEN;
}
else {
usart->US_CR = AT91C_US_RXDIS;
}
}
//------------------------------------------------------------------------------
/// Sends one packet of data through the specified USART peripheral. This
/// function operates synchronously, so it only returns when the data has been
/// actually sent.
/// \param usart Pointer to an USART peripheral.
/// \param data Data to send including 9nth bit and sync field if necessary (in
/// the same format as the US_THR register in the datasheet).
/// \param timeOut Time out value (0 = no timeout).
//------------------------------------------------------------------------------
void USART_Write(
AT91S_USART *usart,
unsigned short data,
volatile unsigned int timeOut)
{
if (timeOut == 0) {
while ((usart->US_CSR & AT91C_US_TXEMPTY) == 0);
}
else {
while ((usart->US_CSR & AT91C_US_TXEMPTY) == 0) {
if (timeOut == 0) {
trace_LOG(trace_ERROR, "-E- USART_Write: Timed out.\n\r");
return;
}
timeOut--;
}
}
usart->US_THR = data;
}
//------------------------------------------------------------------------------
/// Sends the contents of a data buffer through the specified USART peripheral.
/// This function returns immediately (1 if the buffer has been queued, 0
/// otherwise); poll the ENDTX and TXBUFE bits of the USART status register
/// to check for the transfer completion.
/// \param usart Pointer to an USART peripheral.
/// \param buffer Pointer to the data buffer to send.
/// \param size Size of the data buffer (in bytes).
//------------------------------------------------------------------------------
unsigned char USART_WriteBuffer(
AT91S_USART *usart,
void *buffer,
unsigned int size)
{
// Check if the first PDC bank is free
if ((usart->US_TCR == 0) && (usart->US_TNCR == 0)) {
usart->US_TPR = (unsigned int) buffer;
usart->US_TCR = size;
usart->US_PTCR = AT91C_PDC_TXTEN;
return 1;
}
// Check if the second PDC bank is free
else if (usart->US_TNCR == 0) {
usart->US_TNPR = (unsigned int) buffer;
usart->US_TNCR = size;
return 1;
}
else {
return 0;
}
}
//------------------------------------------------------------------------------
/// Reads and return a packet of data on the specified USART peripheral. This
/// function operates asynchronously, so it waits until some data has been
/// received.
/// \param usart Pointer to an USART peripheral.
/// \param timeOut Time out value (0 -> no timeout).
//------------------------------------------------------------------------------
unsigned short USART_Read(
AT91S_USART *usart,
volatile unsigned int timeOut)
{
if (timeOut == 0) {
while ((usart->US_CSR & AT91C_US_RXRDY) == 0);
}
else {
while ((usart->US_CSR & AT91C_US_RXRDY) == 0) {
if (timeOut == 0) {
trace_LOG(trace_ERROR, "-E- USART_Read: Timed out.\n\r");
return 0;
}
timeOut--;
}
}
return usart->US_RHR;
}
//------------------------------------------------------------------------------
/// Reads data from an USART peripheral, filling the provided buffer until it
/// becomes full. This function returns immediately with 1 if the buffer has
/// been queued for transmission; otherwise 0.
/// \param usart Pointer to an USART peripheral.
/// \param buffer Pointer to the buffer where the received data will be stored.
/// \param size Size of the data buffer (in bytes).
//------------------------------------------------------------------------------
unsigned char USART_ReadBuffer(AT91S_USART *usart,
void *buffer,
unsigned int size)
{
// Check if the first PDC bank is free
if ((usart->US_RCR == 0) && (usart->US_RNCR == 0)) {
usart->US_RPR = (unsigned int) buffer;
usart->US_RCR = size;
usart->US_PTCR = AT91C_PDC_RXTEN;
return 1;
}
// Check if the second PDC bank is free
else if (usart->US_RNCR == 0) {
usart->US_RNPR = (unsigned int) buffer;
usart->US_RNCR = size;
return 1;
}
else {
return 0;
}
}
//------------------------------------------------------------------------------
/// Returns 1 if some data has been received and can be read from an USART;
/// otherwise returns 0.
/// \param usart Pointer to an AT91S_USART instance.
//------------------------------------------------------------------------------
unsigned char USART_IsDataAvailable(AT91S_USART *usart)
{
if ((usart->US_CSR & AT91C_US_RXRDY) != 0) {
return 1;
}
else {
return 0;
}
}

View file

@ -0,0 +1,112 @@
/* ----------------------------------------------------------------------------
* 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
/// !Purpose
///
/// This module provides several definitions and methods for using an USART
/// peripheral.
///
/// !Usage
/// -# Enable the USART peripheral clock in the PMC.
/// -# Enable the required USART PIOs (see pio.h).
/// -# Configure the UART by calling USART_Configure.
/// -# Enable the transmitter and/or the receiver of the USART using
/// USART_SetTransmitterEnabled and USART_SetReceiverEnabled.
/// -# Send data through the USART using the USART_Write and
/// USART_WriteBuffer methods.
/// -# Receive data from the USART using the USART_Read and
/// USART_ReadBuffer functions; the availability of data can be polled
/// with USART_IsDataAvailable.
/// -# Disable the transmitter and/or the receiver of the USART with
/// USART_SetTransmitterEnabled and USART_SetReceiverEnabled.
//------------------------------------------------------------------------------
#ifndef USART_H
#define USART_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USART modes"
/// This page lists several common operating modes for an USART peripheral.
///
/// !Modes
/// - USART_MODE_ASYNCHRONOUS
/// Basic asynchronous mode, i.e. 8 bits no parity.
#define USART_MODE_ASYNCHRONOUS (AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void USART_Configure(
AT91S_USART *usart,
unsigned int mode,
unsigned int baudrate,
unsigned int masterClock);
extern void USART_SetTransmitterEnabled(AT91S_USART *usart, unsigned char enabled);
extern void USART_SetReceiverEnabled(AT91S_USART *usart, unsigned char enabled);
extern void USART_Write(
AT91S_USART *usart,
unsigned short data,
volatile unsigned int timeOut);
extern unsigned char USART_WriteBuffer(
AT91S_USART *usart,
void *buffer,
unsigned int size);
extern unsigned short USART_Read(
AT91S_USART *usart,
volatile unsigned int timeOut);
extern unsigned char USART_ReadBuffer(
AT91S_USART *usart,
void *buffer,
unsigned int size);
extern unsigned char USART_IsDataAvailable(AT91S_USART *usart);
#endif //#ifndef USART_H