diff options
| author | Harald Welte <laforge@gnumonks.org> | 2011-07-24 09:39:28 +0200 | 
|---|---|---|
| committer | Harald Welte <laforge@gnumonks.org> | 2011-07-24 09:39:28 +0200 | 
| commit | 98f9d442b44dbe2e3e4b3c8296be7e78d5d05450 (patch) | |
| tree | e9d0a9c86ce3645926c3206f83026deff142af25 /at91lib/peripherals | |
initial import of the usb ccid example for the sam7s
Diffstat (limited to 'at91lib/peripherals')
| -rw-r--r-- | at91lib/peripherals/aic/aic.c | 87 | ||||
| -rw-r--r-- | at91lib/peripherals/aic/aic.h | 79 | ||||
| -rw-r--r-- | at91lib/peripherals/cp15/cp15.c | 268 | ||||
| -rw-r--r-- | at91lib/peripherals/cp15/cp15.h | 84 | ||||
| -rw-r--r-- | at91lib/peripherals/cp15/cp15_asm.S | 138 | ||||
| -rw-r--r-- | at91lib/peripherals/dbgu/dbgu.c | 174 | ||||
| -rw-r--r-- | at91lib/peripherals/dbgu/dbgu.h | 79 | ||||
| -rw-r--r-- | at91lib/peripherals/pio/pio.c | 346 | ||||
| -rw-r--r-- | at91lib/peripherals/pio/pio.h | 163 | ||||
| -rw-r--r-- | at91lib/peripherals/pio/pio_it.c | 395 | ||||
| -rw-r--r-- | at91lib/peripherals/pio/pio_it.h | 83 | ||||
| -rw-r--r-- | at91lib/peripherals/pit/pit.c | 122 | ||||
| -rw-r--r-- | at91lib/peripherals/pit/pit.h | 77 | ||||
| -rw-r--r-- | at91lib/peripherals/pmc/pmc.c | 186 | ||||
| -rw-r--r-- | at91lib/peripherals/pmc/pmc.h | 62 | ||||
| -rw-r--r-- | at91lib/peripherals/usart/usart.c | 272 | ||||
| -rw-r--r-- | at91lib/peripherals/usart/usart.h | 118 | 
17 files changed, 2733 insertions, 0 deletions
| diff --git a/at91lib/peripherals/aic/aic.c b/at91lib/peripherals/aic/aic.c new file mode 100644 index 0000000..4ff52c2 --- /dev/null +++ b/at91lib/peripherals/aic/aic.c @@ -0,0 +1,87 @@ +/* ----------------------------------------------------------------------------
 + *         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>
 +
 +//------------------------------------------------------------------------------
 +//         Global functions
 +//------------------------------------------------------------------------------
 +
 +//------------------------------------------------------------------------------
 +/// Configures an interrupt in the AIC. The interrupt is identified by its
 +/// source (AT91C_ID_xxx) and is configured to use the specified mode and
 +/// interrupt handler function. Mode is the value that will be put in AIC_SMRx
 +/// and the function address will be set in AIC_SVRx.
 +/// The interrupt is disabled before configuration, so it is useless
 +/// to do it before calling this function. When AIC_ConfigureIT returns, the
 +/// interrupt will always be disabled and cleared; it must be enabled by a
 +/// call to AIC_EnableIT().
 +/// \param source  Interrupt source to configure.
 +/// \param mode  Triggering mode and priority 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 (AT91C_ID_xxx).
 +/// \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 (AT91C_ID_xxx).
 +/// \param source  Interrupt source to enable.
 +//------------------------------------------------------------------------------
 +void AIC_DisableIT(unsigned int source)
 +{
 +    AT91C_BASE_AIC->AIC_IDCR = 1 << source;
 +}
 +
 diff --git a/at91lib/peripherals/aic/aic.h b/at91lib/peripherals/aic/aic.h new file mode 100644 index 0000000..bddf787 --- /dev/null +++ b/at91lib/peripherals/aic/aic.h @@ -0,0 +1,79 @@ +/* ----------------------------------------------------------------------------
 + *         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
 +/// 
 +/// 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.
 +///
 +/// \note Most of the time, peripheral interrupts must be also configured
 +/// inside the peripheral itself.
 +//------------------------------------------------------------------------------
 +
 +#ifndef AIC_H
 +#define AIC_H
 +
 +//------------------------------------------------------------------------------
 +//         Headers
 +//------------------------------------------------------------------------------
 +
 +#include <board.h>
 +
 +//------------------------------------------------------------------------------
 +//         Definitions
 +//------------------------------------------------------------------------------
 +
 +#ifndef AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL
 +    /// Interrupt is internal and uses a logical 1 level.
 +    #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
 +
 diff --git a/at91lib/peripherals/cp15/cp15.c b/at91lib/peripherals/cp15/cp15.c new file mode 100644 index 0000000..17a1f70 --- /dev/null +++ b/at91lib/peripherals/cp15/cp15.c @@ -0,0 +1,268 @@ +/* ----------------------------------------------------------------------------
 + *         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>
 +
 +#ifdef CP15_PRESENT
 +
 +#include <utility/trace.h>
 +#include "cp15.h"
 +
 +#if defined(__ICCARM__)
 +#include <intrinsics.h>
 +#endif
 +
 +
 +//-----------------------------------------------------------------------------
 +//         Macros
 +//-----------------------------------------------------------------------------
 +
 +//-----------------------------------------------------------------------------
 +//         Defines
 +//-----------------------------------------------------------------------------
 +/*
 +#define CP15_RR_BIT 14 // RR bit Replacement strategy for ICache and DCache: 
 +                       // 0 = Random replacement 
 +                       // 1 = Round-robin replacement.
 +                      
 +#define CP15_V_BIT  13 // V bit Location of exception vectors: 
 +                       // 0 = Normal exception vectors selected address range = 0x0000 0000 to 0x0000 001C 
 +                       // 1 = High exception vect selected, address range = 0xFFFF 0000 to 0xFFFF 001C
 +*/                       
 +#define CP15_I_BIT  12 // I bit ICache enable/disable: 
 +                       // 0 = ICache disabled 
 +                       // 1 = ICache enabled
 +/*                       
 +#define CP15_R_BIT   9 // R bit ROM protection
 +
 +#define CP15_S_BIT   8 // S bit System protection
 +                  
 +#define CP15_B_BIT   7 // B bit Endianness: 
 +                       // 0 = Little-endian operation 
 +                       // 1 = Big-endian operation.                  
 +*/                     
 +#define CP15_C_BIT   2 // C bit DCache enable/disable: 
 +                       // 0 = Cache disabled 
 +                       // 1 = Cache enabled
 +/*
 +#define CP15_A_BIT   1 // A bit Alignment fault enable/disable:
 +                       // 0 = Data address alignment fault checking disabled
 +                       // 1 = Data address alignment fault checking enabled
 +*/
 +#define CP15_M_BIT   0 // M bit MMU enable/disable: 0 = disabled 1 = enabled.
 +                       // 0 = disabled 
 +                       // 1 = enabled
 +
 +
 +//-----------------------------------------------------------------------------
 +//         Global functions
 +//-----------------------------------------------------------------------------
 +
 +//------------------------------------------------------------------------------
 +/// Check Instruction Cache
 +/// \return 0 if I_Cache disable, 1 if I_Cache enable
 +//------------------------------------------------------------------------------
 +unsigned int CP15_Is_I_CacheEnabled(void)
 +{
 +    unsigned int control;
 +
 +    control = _readControlRegister();
 +    return ((control & (1 << CP15_I_BIT)) != 0);
 +} 
 +
 +//------------------------------------------------------------------------------
 +/// Enable Instruction Cache
 +//------------------------------------------------------------------------------
 +void CP15_Enable_I_Cache(void)
 +{
 +    unsigned int control;
 +
 +    control = _readControlRegister();
 +
 +    // Check if cache is disabled
 +    if ((control & (1 << CP15_I_BIT)) == 0) {
 +
 +        control |= (1 << CP15_I_BIT);
 +        _writeControlRegister(control);        
 +        TRACE_INFO("I cache enabled.\n\r");
 +    }
 +#if !defined(OP_BOOTSTRAP_on)
 +    else {
 +
 +        TRACE_INFO("I cache is already enabled.\n\r");
 +    }
 +#endif
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Disable Instruction Cache
 +//------------------------------------------------------------------------------
 +void CP15_Disable_I_Cache(void)
 +{
 +    unsigned int control;
 +
 +    control = _readControlRegister();
 +
 +    // Check if cache is enabled
 +    if ((control & (1 << CP15_I_BIT)) != 0) {
 +
 +        control &= ~(1 << CP15_I_BIT);
 +        _writeControlRegister(control);        
 +        TRACE_INFO("I cache disabled.\n\r");
 +    }
 +    else {
 +
 +        TRACE_INFO("I cache is already disabled.\n\r");
 +    }
 +} 
 +
 +//------------------------------------------------------------------------------
 +/// Check MMU
 +/// \return 0 if MMU disable, 1 if MMU enable
 +//------------------------------------------------------------------------------
 +unsigned int CP15_Is_MMUEnabled(void)
 +{
 +    unsigned int control;
 +
 +    control = _readControlRegister();
 +    return ((control & (1 << CP15_M_BIT)) != 0);
 +} 
 +
 +//------------------------------------------------------------------------------
 +/// Enable MMU
 +//------------------------------------------------------------------------------
 +void CP15_EnableMMU(void)
 +{
 +    unsigned int control;
 +
 +    control = _readControlRegister();
 +
 +    // Check if MMU is disabled
 +    if ((control & (1 << CP15_M_BIT)) == 0) {
 +
 +        control |= (1 << CP15_M_BIT);
 +        _writeControlRegister(control);        
 +        TRACE_INFO("MMU enabled.\n\r");
 +    }
 +    else {
 +
 +        TRACE_INFO("MMU is already enabled.\n\r");
 +    }
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Disable MMU
 +//------------------------------------------------------------------------------
 +void CP15_DisableMMU(void)
 +{
 +    unsigned int control;
 +
 +    control = _readControlRegister();
 +
 +    // Check if MMU is enabled
 +    if ((control & (1 << CP15_M_BIT)) != 0) {
 +
 +        control &= ~(1 << CP15_M_BIT);
 +        control &= ~(1 << CP15_C_BIT);
 +        _writeControlRegister(control);        
 +        TRACE_INFO("MMU disabled.\n\r");
 +    }
 +    else {
 +
 +        TRACE_INFO("MMU is already disabled.\n\r");
 +    }
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Check D_Cache
 +/// \return 0 if D_Cache disable, 1 if D_Cache enable (with MMU of course)
 +//------------------------------------------------------------------------------
 +unsigned int CP15_Is_DCacheEnabled(void)
 +{
 +    unsigned int control;
 +
 +    control = _readControlRegister();
 +    return ((control & ((1 << CP15_C_BIT)||(1 << CP15_M_BIT))) != 0);
 +} 
 +
 +//------------------------------------------------------------------------------
 +/// Enable Data Cache
 +//------------------------------------------------------------------------------
 +void CP15_Enable_D_Cache(void)
 +{
 +    unsigned int control;
 +
 +    control = _readControlRegister();
 +
 +    if( !CP15_Is_MMUEnabled() ) {
 +        TRACE_ERROR("Do nothing: MMU not enabled\n\r");
 +    }
 +    else {
 +        // Check if cache is disabled
 +        if ((control & (1 << CP15_C_BIT)) == 0) {
 +
 +            control |= (1 << CP15_C_BIT);
 +            _writeControlRegister(control);        
 +            TRACE_INFO("D cache enabled.\n\r");
 +        }
 +        else {
 +
 +            TRACE_INFO("D cache is already enabled.\n\r");
 +        }
 +    }
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Disable Data Cache
 +//------------------------------------------------------------------------------
 +void CP15_Disable_D_Cache(void)
 +{
 +    unsigned int control;
 +
 +    control = _readControlRegister();
 +
 +    // Check if cache is enabled
 +    if ((control & (1 << CP15_C_BIT)) != 0) {
 +
 +        control &= ~(1 << CP15_C_BIT);
 +        _writeControlRegister(control);        
 +        TRACE_INFO("D cache disabled.\n\r");
 +    }
 +    else {
 +
 +        TRACE_INFO("D cache is already disabled.\n\r");
 +    }
 +}
 +
 +#endif // CP15_PRESENT
 +
 diff --git a/at91lib/peripherals/cp15/cp15.h b/at91lib/peripherals/cp15/cp15.h new file mode 100644 index 0000000..ddaaeb6 --- /dev/null +++ b/at91lib/peripherals/cp15/cp15.h @@ -0,0 +1,84 @@ +/* ----------------------------------------------------------------------------
 + *         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
 +/// 
 +/// Methods to manage the Coprocessor 15. Coprocessor 15, or System Control 
 +/// Coprocessor CP15, is used to configure and control all the items in the 
 +/// list below:
 +/// • ARM core
 +/// • Caches (ICache, DCache and write buffer)
 +/// • TCM
 +/// • MMU
 +/// • Other system options
 +/// 
 +/// !Usage
 +///
 +/// -# Enable or disable D cache with Enable_D_Cache and Disable_D_Cache
 +/// -# Enable or disable I cache with Enable_I_Cache and Disable_I_Cache
 +///
 +//------------------------------------------------------------------------------
 +
 +#ifndef _CP15_H
 +#define _CP15_H
 +
 +#ifdef CP15_PRESENT
 +
 +//-----------------------------------------------------------------------------
 +//         Exported functions
 +//-----------------------------------------------------------------------------
 +extern void CP15_Enable_I_Cache(void);
 +extern unsigned int CP15_Is_I_CacheEnabled(void);
 +extern void CP15_Enable_I_Cache(void);
 +extern void CP15_Disable_I_Cache(void);
 +extern unsigned int CP15_Is_MMUEnabled(void);
 +extern void CP15_EnableMMU(void);
 +extern void CP15_DisableMMU(void);
 +extern unsigned int CP15_Is_DCacheEnabled(void);
 +extern void CP15_Enable_D_Cache(void);
 +extern void CP15_Disable_D_Cache(void);
 +
 +//-----------------------------------------------------------------------------
 +//         External functions defined in cp15.S
 +//-----------------------------------------------------------------------------
 +extern unsigned int _readControlRegister(void);
 +extern void _writeControlRegister(unsigned int value);
 +extern void _waitForInterrupt(void);
 +extern void _writeTTB(unsigned int value);
 +extern void _writeDomain(unsigned int value);
 +extern void _writeITLBLockdown(unsigned int value);
 +extern void _prefetchICacheLine(unsigned int value);
 +
 +#endif // CP15_PRESENT
 +
 +#endif // #ifndef _CP15_H
 +
 diff --git a/at91lib/peripherals/cp15/cp15_asm.S b/at91lib/peripherals/cp15/cp15_asm.S new file mode 100644 index 0000000..00ef47d --- /dev/null +++ b/at91lib/peripherals/cp15/cp15_asm.S @@ -0,0 +1,138 @@ +/* ----------------------------------------------------------------------------
 + *         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
 +//------------------------------------------------------------------------------
 +
 +#define __ASSEMBLY__
 +#include "board.h"
 +
 +#ifdef CP15_PRESENT
 +
 +//------------------------------------------------------------------------------
 +/// Functions to access CP15 coprocessor register
 +//------------------------------------------------------------------------------
 +
 +        .global _readControlRegister
 +        .global _writeControlRegister
 +        .global _waitForInterrupt
 +        .global _writeTTB
 +        .global _writeDomain
 +        .global _writeITLBLockdown
 +        .global _prefetchICacheLine
 +
 +//------------------------------------------------------------------------------
 +/// Control Register c1
 +/// Register c1 is the Control Register for the ARM926EJ-S processor. 
 +/// This register specifies the configuration used to enable and disable the 
 +/// caches and MMU. It is recommended that you access this register using a 
 +/// read-modify-write sequence.
 +//------------------------------------------------------------------------------
 +// CP15 Read Control Register
 +_readControlRegister:
 +        mov     r0, #0
 +        mrc     p15, 0, r0, c1, c0, 0
 +        bx      lr
 +
 +// CP15 Write Control Register
 +_writeControlRegister:
 +        mcr     p15, 0, r0, c1, c0, 0
 +        bx      lr
 +
 +//------------------------------------------------------------------------------
 +/// CP15 Wait For Interrupt operation
 +/// The purpose of the Wait For Interrupt operation is to put the processor in
 +/// to a low power state.
 +/// This puts the processor into a low-power state and stops it executing more
 +/// instructions until an interrupt, or debug request occurs, regardless of
 +/// whether the interrupts are disabled by the masks in the CPSR. 
 +/// When an interrupt does occur, the MCR instruction completes and the IRQ or
 +/// FIQ handler is entered as normal. The return link in r14_irq or r14_fiq 
 +/// contains the address of the MCR instruction plus 8, so that the normal 
 +/// instruction used for interrupt return (SUBS PC,R14,#4) returns to the 
 +/// instruction following the MCR.
 +/// Wait For Interrupt : MCR p15, 0, <Rd>, c7, c0, 4
 +//------------------------------------------------------------------------------
 +_waitForInterrupt:
 +        mov     r0, #0
 +        mcr     p15, 0, r0, c7, c0, 4
 +        bx      lr
 +
 +//------------------------------------------------------------------------------
 +/// CP15 Translation Table Base Register c2
 +/// Register c2 is the Translation Table Base Register (TTBR), for the base 
 +/// address of the first-level translation table.
 +/// Reading from c2 returns the pointer to the currently active first-level
 +/// translation table in bits [31:14] and an Unpredictable value in bits [13:0]. 
 +/// Writing to register c2 updates the pointer to the first-level translation 
 +/// table from the value in bits [31:14] of the written value. Bits [13:0] 
 +/// Should Be Zero.
 +/// You can use the following instructions to access the TTBR:
 +/// Read TTBR  : MRC p15, 0, <Rd>, c2, c0, 0
 +/// Write TTBR : MCR p15, 0, <Rd>, c2, c0, 0
 +//------------------------------------------------------------------------------
 +_writeTTB:
 +        MCR     p15, 0, r0, c2, c0, 0
 +        bx      lr
 +
 +//------------------------------------------------------------------------------
 +/// Domain Access Control Register c3
 +/// Read domain access permissions  : MRC p15, 0, <Rd>, c3, c0, 0
 +/// Write domain access permissions : MCR p15, 0, <Rd>, c3, c0, 0
 +//------------------------------------------------------------------------------
 +_writeDomain:
 +        MCR     p15, 0, r0, c3, c0, 0
 +        bx      lr
 +
 +//------------------------------------------------------------------------------
 +/// TLB Lockdown Register c10
 +/// The TLB Lockdown Register controls where hardware page table walks place the
 +/// TLB entry, in the set associative region or the lockdown region of the TLB, 
 +/// and if in the lockdown region, which entry is written. The lockdown region 
 +/// of the TLB contains eight entries. See TLB structure for a description of 
 +/// the structure of the TLB.
 +/// Read data TLB lockdown victim  : MRC p15,0,<Rd>,c10,c0,0
 +/// Write data TLB lockdown victim : MCR p15,0,<Rd>,c10,c0,0
 +//------------------------------------------------------------------------------
 +_writeITLBLockdown:
 +        MCR     p15, 0, r0, c10, c0, 0
 +        bx      lr
 +
 +//------------------------------------------------------------------------------
 +/// Prefetch ICache line
 +/// Performs an ICache lookup of the specified modified virtual address.
 +/// If the cache misses, and the region is cacheable, a linefill is performed.
 +/// Prefetch ICache line (MVA): MCR p15, 0, <Rd>, c7, c13, 1
 +//------------------------------------------------------------------------------
 +_prefetchICacheLine:
 +        MCR     p15, 0, r0, c7, c13, 1
 +        bx      lr
 +#endif
 +
 diff --git a/at91lib/peripherals/dbgu/dbgu.c b/at91lib/peripherals/dbgu/dbgu.c new file mode 100644 index 0000000..2034730 --- /dev/null +++ b/at91lib/peripherals/dbgu/dbgu.c @@ -0,0 +1,174 @@ +/* ----------------------------------------------------------------------------
 + *         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>
 +
 +//------------------------------------------------------------------------------
 +//         Global functions
 +//------------------------------------------------------------------------------
 +//------------------------------------------------------------------------------
 +/// Initializes the DBGU with the given parameters, and enables both the
 +/// transmitter and the receiver. The mode parameter contains the value of the
 +/// DBGU_MR register.
 +/// Value DBGU_STANDARD can be used for mode to get the most common configuration
 +/// (i.e. aysnchronous, 8bits, no parity, 1 stop bit, no flow control).
 +/// \param mode  Operating mode to configure.
 +/// \param baudrate  Desired baudrate (e.g. 115200).
 +/// \param mck  Frequency of the system master clock in Hz.
 +//------------------------------------------------------------------------------
 +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.
 +/// \note This function is synchronous (i.e. uses polling).
 +/// \param c  Character to send.
 +//------------------------------------------------------------------------------
 +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);
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Return 1 if a character can be read in DBGU
 +//------------------------------------------------------------------------------
 +unsigned int DBGU_IsRxReady()
 +{
 +    return (AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_RXRDY);
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Reads and returns a character from the DBGU.
 +/// \note This function is synchronous (i.e. uses polling).
 +/// \return Character received.
 +//------------------------------------------------------------------------------
 +unsigned char DBGU_GetChar(void)
 +{
 +    while ((AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_RXRDY) == 0);
 +    return AT91C_BASE_DBGU->DBGU_RHR;
 +}
 +
 +#ifndef NOFPUT
 +#include <stdio.h>
 +
 +//------------------------------------------------------------------------------
 +/// \exclude
 +/// Implementation of fputc using the DBGU as the standard output. Required
 +/// for printf().
 +/// \param c  Character to write.
 +/// \param pStream  Output stream.
 +/// \param The character written if successful, or -1 if the output stream is
 +/// not stdout or stderr.
 +//------------------------------------------------------------------------------
 +signed int fputc(signed int c, FILE *pStream)
 +{
 +    if ((pStream == stdout) || (pStream == stderr)) {
 +    
 +        DBGU_PutChar(c);
 +        return c;
 +    }
 +    else {
 +
 +        return EOF;
 +    }
 +}
 +
 +//------------------------------------------------------------------------------
 +/// \exclude
 +/// Implementation of fputs using the DBGU as the standard output. Required
 +/// for printf(). Does NOT currently use the PDC.
 +/// \param pStr  String to write.
 +/// \param pStream  Output stream.
 +/// \return Number of characters written if successful, or -1 if the output
 +/// stream is not stdout or stderr.
 +//------------------------------------------------------------------------------
 +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
 +
 +//------------------------------------------------------------------------------
 +/// \exclude
 +/// Outputs a character on the DBGU.
 +/// \param c  Character to output.
 +/// \return The character that was output.
 +//------------------------------------------------------------------------------
 +signed int putchar(signed int c)
 +{
 +    return fputc(c, stdout);
 +}
 +
 +#endif //#ifndef NOFPUT
 +
 diff --git a/at91lib/peripherals/dbgu/dbgu.h b/at91lib/peripherals/dbgu/dbgu.h new file mode 100644 index 0000000..816f11d --- /dev/null +++ b/at91lib/peripherals/dbgu/dbgu.h @@ -0,0 +1,79 @@ +/* ----------------------------------------------------------------------------
 + *         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
 +/// 
 +/// This module provides definitions and functions for using the Debug Unit
 +/// (DBGU).
 +///
 +/// It also overloads the fputc(), fputs() & putchar() functions so the printf()
 +/// method outputs its data on the DBGU. This behavior can be suppressed by
 +/// defining NOFPUT during compilation.
 +///
 +/// !Usage
 +/// 
 +/// -# Enable the DBGU pins (see pio & board.h).
 +/// -# Configure the DBGU using DBGU_Configure with the desired operating mode.
 +/// -# Send characters using DBGU_PutChar() or the printf() method.
 +/// -# Receive characters using DBGU_GetChar().
 +///
 +/// \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
 +//------------------------------------------------------------------------------
 + 
 +/// Standard operating mode (asynchronous, 8bit, no parity, 1 stop bit)
 +#define DBGU_STANDARD           AT91C_US_PAR_NONE
 +
 +//------------------------------------------------------------------------------
 +//         Global functions
 +//------------------------------------------------------------------------------
 +
 +extern void DBGU_Configure(
 +    unsigned int mode,
 +    unsigned int baudrate,
 +    unsigned int mck);
 +
 +extern unsigned char DBGU_GetChar(void);
 +
 +extern void DBGU_PutChar(unsigned char c);
 +
 +extern unsigned int DBGU_IsRxReady(void);
 +
 +#endif //#ifndef DBGU_H
 +
 diff --git a/at91lib/peripherals/pio/pio.c b/at91lib/peripherals/pio/pio.c new file mode 100644 index 0000000..5b21751 --- /dev/null +++ b/at91lib/peripherals/pio/pio.c @@ -0,0 +1,346 @@ +/* ----------------------------------------------------------------------------
 + *         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>
 +
 +//------------------------------------------------------------------------------
 +//         Local 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)
 +    pio->PIO_IDR = mask;
 +
 +    // Enable the pull-up(s) if necessary
 +    if (enablePullUp) {
 +
 +        pio->PIO_PPUER = mask;
 +    }
 +    else {
 +
 +        pio->PIO_PPUDR = mask;
 +    }
 +
 +    // Configure pin
 +    pio->PIO_ASR = mask;
 +    pio->PIO_PDR = mask;
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Configures one or more pin(s) of a PIO controller as being controlled by
 +/// peripheral B. 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)
 +    pio->PIO_IDR = mask;
 +
 +    // Enable the pull-up(s) if necessary
 +    if (enablePullUp) {
 +
 +        pio->PIO_PPUER = mask;
 +    }
 +    else {
 +
 +        pio->PIO_PPUDR = mask;
 +    }
 +
 +    // Configure pin
 +    pio->PIO_BSR = mask;
 +    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
 +    pio->PIO_IDR = mask;
 +
 +    // Enable pull-up(s) if necessary
 +    if (enablePullUp) {
 +    
 +        pio->PIO_PPUER = mask;
 +    }
 +    else {
 +    
 +        pio->PIO_PPUDR = mask;
 +    }
 +
 +    // Enable filter(s) if necessary
 +    if (enableFilter) {
 +    
 +        pio->PIO_IFER = mask;
 +    }
 +    else {
 +    
 +        pio->PIO_IFDR = mask;
 +    }
 +
 +    // Configure pin as input
 +    pio->PIO_ODR = mask;
 +    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
 +    pio->PIO_IDR = mask;
 +
 +    // Enable pull-up(s) if necessary
 +    if (enablePullUp) {
 +    
 +        pio->PIO_PPUER = mask;
 +    }
 +    else {
 +    
 +        pio->PIO_PPUDR = mask;
 +    }
 +
 +    // Enable multi-drive if necessary
 +    if (enableMultiDrive) {
 +    
 +        pio->PIO_MDER = mask;
 +    }
 +    else {
 +    
 +        pio->PIO_MDDR = mask;
 +    }
 +
 +    // Set default value
 +    if (defaultValue) {
 +
 +        pio->PIO_SODR = mask;
 +    }
 +    else {
 +
 +        pio->PIO_CODR = mask;
 +    }
 +
 +    // Configure pin(s) as output(s)
 +    pio->PIO_OER = mask;
 +    pio->PIO_PER = mask;
 +}
 +
 +//------------------------------------------------------------------------------
 +//         Global Functions
 +//------------------------------------------------------------------------------
 +
 +//------------------------------------------------------------------------------
 +/// Configures a list of Pin instances, each of which can either hold a single
 +/// pin or a group of pins, depending on the mask value; all pins are configured
 +/// by this function. The size of the array must also be provided and is easily
 +/// computed using PIO_LISTSIZE whenever its length is not known in advance.
 +/// \param list  Pointer to a list of Pin instances.
 +/// \param size  Size of the Pin list (calculated using PIO_LISTSIZE).
 +/// \return 1 if the pins have been configured properly; otherwise 0.
 +//------------------------------------------------------------------------------
 +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 all the PIOs defined in the given Pin instance.
 +/// This has no immediate effects on PIOs that are not output, but the PIO
 +/// controller will memorize the value they are changed to outputs.
 +/// \param pin  Pointer to a Pin instance describing one or more pins.
 +//------------------------------------------------------------------------------
 +void PIO_Set(const Pin *pin)
 +{
 +    pin->pio->PIO_SODR = pin->mask;
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Sets a low output level on all the PIOs defined in the given Pin instance.
 +/// This has no immediate effects on PIOs that are not output, but the PIO
 +/// controller will memorize the value they are changed to outputs.
 +/// \param pin  Pointer to a Pin instance describing one or more pins.
 +//------------------------------------------------------------------------------
 +void PIO_Clear(const Pin *pin)
 +{
 +    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. This method returns the actual value that is
 +/// being read on the pin. To return the supposed output value of a pin, use
 +/// PIO_GetOutputDataStatus() instead.
 +/// \param pin  Pointer to a Pin instance describing one or more pins.
 +/// \return 1 if the Pin instance contains at least one PIO that currently has
 +/// a high level; otherwise 0.
 +//------------------------------------------------------------------------------
 +unsigned char PIO_Get(const Pin *pin)
 +{
 +    unsigned int reg;
 +    if ((pin->type == PIO_OUTPUT_0) || (pin->type == PIO_OUTPUT_1)) {
 +
 +        reg = pin->pio->PIO_ODSR;
 +    }
 +    else {
 +
 +        reg = 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 are configured to output a
 +/// high level (even if they are not output).
 +/// To get the actual value of the pin, use PIO_Get() instead.
 +/// \param pin  Pointer to a Pin instance describing one or more pins.
 +/// \return 1 if the Pin instance contains at least one PIO that is configured
 +/// to output a high level; otherwise 0.
 +//------------------------------------------------------------------------------
 +unsigned char PIO_GetOutputDataStatus(const Pin *pin)
 +{
 +    if ((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 (pin->pio->PIO_ISR);
 +}
 +
 diff --git a/at91lib/peripherals/pio/pio.h b/at91lib/peripherals/pio/pio.h new file mode 100644 index 0000000..69fe29d --- /dev/null +++ b/at91lib/peripherals/pio/pio.h @@ -0,0 +1,163 @@ +/* ----------------------------------------------------------------------------
 + *         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
 +/// 
 +/// This file provides a basic API for PIO configuration and usage of
 +/// user-controlled pins. Please refer to the board.h file for a list of
 +/// available pin definitions.
 +/// 
 +/// !!!Usage
 +/// 
 +/// -# Define a constant pin description array such as the following one, using
 +///    the existing definitions provided by the board.h file if possible:
 +///    \code
 +///       const Pin pPins[] = {PIN_USART0_TXD, PIN_USART0_RXD};
 +///    \endcode
 +///    Alternatively, it is possible to add new pins by provided the full Pin
 +///    structure:
 +///    \code
 +///    // Pin instance to configure PA10 & PA11 as inputs with the internal
 +///    // pull-up enabled.
 +///    const Pin pPins = {
 +///         (1 << 10) | (1 << 11),
 +///         AT91C_BASE_PIOA,
 +///         AT91C_ID_PIOA,
 +///         PIO_INPUT,
 +///         PIO_PULLUP
 +///    };
 +///    \endcode
 +/// -# Configure a pin array by calling PIO_Configure() with a pointer to the
 +///    array and its size (which is computed using the PIO_LISTSIZE macro).
 +/// -# Change and get the value of a user-controlled pin using the PIO_Set,
 +///    PIO_Clear and PIO_Get methods.
 +/// -# Get the level being currently output by a user-controlled pin configured
 +///    as an output using PIO_GetOutputDataStatus().
 +//------------------------------------------------------------------------------
 + 
 +#ifndef PIO_H
 +#define PIO_H
 +
 +//------------------------------------------------------------------------------
 +//         Headers
 +//------------------------------------------------------------------------------
 +
 +#include <board.h>
 +
 +//------------------------------------------------------------------------------
 +//         Global Definitions
 +//------------------------------------------------------------------------------
 +
 +/// 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
 +
 +/// 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)
 +
 +//------------------------------------------------------------------------------
 +//         Global Macros
 +//------------------------------------------------------------------------------
 +
 +//------------------------------------------------------------------------------
 +/// Calculates the size of an array of Pin instances. The array must be defined
 +/// locally (i.e. not a pointer), otherwise the computation will not be correct.
 +/// \param pPins  Local array of Pin instances.
 +/// \return Number of elements in array.
 +//------------------------------------------------------------------------------
 +#define PIO_LISTSIZE(pPins)    (sizeof(pPins) / sizeof(Pin))
 +
 +//------------------------------------------------------------------------------
 +//         Global Types
 +//------------------------------------------------------------------------------
 +
 +//------------------------------------------------------------------------------
 +/// Describes the type and attribute of one PIO pin or a group of similar pins.
 +/// The #type# field can have the following values:
 +///    - PIO_PERIPH_A
 +///    - PIO_PERIPH_B
 +///    - PIO_OUTPUT_0
 +///    - PIO_OUTPUT_1
 +///    - PIO_INPUT
 +///
 +/// The #attribute# field is a bitmask that can either be set to PIO_DEFAULt,
 +/// or combine (using bitwise OR '|') any number of the following constants:
 +///    - PIO_PULLUP
 +///    - PIO_DEGLITCH
 +///    - PIO_OPENDRAIN
 +//------------------------------------------------------------------------------
 +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.
 +    unsigned char type;
 +    /// Pin attribute.
 +    unsigned char attribute;
 +
 +} Pin;
 +
 +//------------------------------------------------------------------------------
 +//         Global 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
 +
 diff --git a/at91lib/peripherals/pio/pio_it.c b/at91lib/peripherals/pio/pio_it.c new file mode 100644 index 0000000..266feb0 --- /dev/null +++ b/at91lib/peripherals/pio/pio_it.c @@ -0,0 +1,395 @@ +/* ----------------------------------------------------------------------------
 + *         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
 +#undef TRACE_LEVEL
 +#define TRACE_LEVEL 0
 +
 +//------------------------------------------------------------------------------
 +//         Headers
 +//------------------------------------------------------------------------------
 +
 +#include "pio_it.h"
 +#include "pio.h"
 +#include <board.h>
 +#include <aic/aic.h>
 +#include <utility/assert.h>
 +#include <utility/trace.h>
 +
 +//------------------------------------------------------------------------------
 +//         Local definitions
 +//------------------------------------------------------------------------------
 +
 +/// \exclude
 +/// Maximum number of interrupt sources that can be defined. This
 +/// constant can be increased, but the current value is the smallest possible
 +/// that will be compatible with all existing projects.
 +#define MAX_INTERRUPT_SOURCES       7
 +
 +//------------------------------------------------------------------------------
 +//         Local types
 +//------------------------------------------------------------------------------
 +
 +//------------------------------------------------------------------------------
 +/// \exclude
 +/// Describes a PIO interrupt source, including the PIO instance triggering the
 +/// interrupt and the associated interrupt handler.
 +//------------------------------------------------------------------------------
 +typedef struct {
 +
 +    /// Pointer to the source pin instance.
 +    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 pPio  PIO controller base address.
 +//------------------------------------------------------------------------------
 +static void PioInterruptHandler(unsigned int id, AT91S_PIO *pPio)
 +{
 +    unsigned int status;
 +    unsigned int i;
 +
 +    // Read PIO controller status
 +    status = pPio->PIO_ISR;
 +    status &= pPio->PIO_IMR;
 +
 +    // Check pending events
 +    if (status != 0) {
 +
 +        TRACE_DEBUG("PIO interrupt on PIO controller #%d\n\r", id);
 +
 +        // Find triggering source
 +        i = 0;
 +        while (status != 0) {
 +
 +            // There cannot be an unconfigured source enabled.
 +            SANITY_CHECK(i < numSources);
 +
 +            // Source is configured on the same controller
 +            if (pSources[i].pPin->id == id) {
 +
 +                // Source has PIOs whose statuses have changed
 +                if ((status & pSources[i].pPin->mask) != 0) {
 +
 +                    TRACE_DEBUG("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.
 +//------------------------------------------------------------------------------
 +static void InterruptHandler(void)
 +{
 +#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. The desired priority of PIO
 +/// interrupts must be provided. Calling this function multiple times result in
 +/// the reset of currently configured interrupts.
 +/// \param priority  PIO controller interrupts priority.
 +//------------------------------------------------------------------------------
 +void PIO_InitializeInterrupts(unsigned int priority)
 +{
 +    TRACE_DEBUG("PIO_Initialize()\n\r");
 +
 +    SANITY_CHECK((priority & ~AT91C_AIC_PRIOR) == 0);
 +
 +    // Reset sources
 +    numSources = 0;
 +
 +#ifdef AT91C_ID_PIOA
 +    // Configure PIO interrupt sources
 +    TRACE_DEBUG("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_DEBUG("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_DEBUG("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_DEBUG("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_DEBUG("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_DEBUG("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_DEBUG("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_DEBUG("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 a PIO or a group of PIO to generate an interrupt on status
 +/// change. The provided interrupt handler will be called with the triggering
 +/// pin as its parameter (enabling different pin instances to share the same
 +/// handler).
 +/// \param pPin  Pointer to a Pin instance.
 +/// \param handler  Interrupt handler function pointer.
 +//------------------------------------------------------------------------------
 +void PIO_ConfigureIt(const Pin *pPin, void (*handler)(const Pin *))
 +{
 +    InterruptSource *pSource;
 +
 +    TRACE_DEBUG("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_DEBUG("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. The status
 +/// register of the corresponding PIO controller is cleared prior to enabling
 +/// the interrupt.
 +/// \param pPin  Interrupt source to enable.
 +//------------------------------------------------------------------------------
 +void PIO_EnableIt(const Pin *pPin)
 +{
 +    TRACE_DEBUG("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, with no added side effects.
 +/// \param pPin  Interrupt source to disable.
 +//------------------------------------------------------------------------------
 +void PIO_DisableIt(const Pin *pPin)
 +{
 +    SANITY_CHECK(pPin);
 +
 +    TRACE_DEBUG("PIO_DisableIt()\n\r");
 +
 +    pPin->pio->PIO_IDR = pPin->mask;
 +}
 +
 diff --git a/at91lib/peripherals/pio/pio_it.h b/at91lib/peripherals/pio/pio_it.h new file mode 100644 index 0000000..0fcf7be --- /dev/null +++ b/at91lib/peripherals/pio/pio_it.h @@ -0,0 +1,83 @@ +/* ----------------------------------------------------------------------------
 + *         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. The API
 +/// provided here have several advantages over the traditional PIO interrupt
 +/// configuration approach:
 +///    - It is highly portable
 +///    - It automatically demultiplexes interrupts when multiples pins have been
 +///      configured on a single PIO controller
 +///    - It allows a group of pins to share the same interrupt
 +/// 
 +/// However, it also has several minor drawbacks that may prevent from using it
 +/// in particular applications:
 +///    - It enables the clocks of all PIO controllers
 +///    - PIO controllers all share the same interrupt handler, which does the
 +///      demultiplexing and can be slower than direct configuration
 +///    - It reserves space for a fixed number of interrupts, which can be
 +///      increased by modifying the appropriate constant in pio_it.c.
 +///
 +/// !!!Usage
 +/// 
 +/// -# Initialize the PIO interrupt mechanism using PIO_InitializeInterrupts()
 +///    with the desired priority (0 ... 7).
 +/// -# Configure a status change interrupt on one or more pin(s) with
 +///    PIO_ConfigureIt().
 +/// -# Enable & disable interrupts on pins using PIO_EnableIt() and
 +///    PIO_DisableIt().
 +//------------------------------------------------------------------------------
 +
 +#ifndef PIO_IT_H
 +#define PIO_IT_H
 +
 +//------------------------------------------------------------------------------
 +//         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);
 +
 +#endif //#ifndef PIO_IT_H
 +
 diff --git a/at91lib/peripherals/pit/pit.c b/at91lib/peripherals/pit/pit.c new file mode 100644 index 0000000..f15610c --- /dev/null +++ b/at91lib/peripherals/pit/pit.c @@ -0,0 +1,122 @@ +/* ----------------------------------------------------------------------------
 + *         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>
 +
 +//------------------------------------------------------------------------------
 +//         Global functions
 +//------------------------------------------------------------------------------
 +
 +//------------------------------------------------------------------------------
 +/// Initialize the Periodic Interval Timer to generate a tick at the specified
 +/// period, given the current master clock frequency.
 +/// \param period  Period in µsecond.
 +/// \param pit_frequency  Master 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;
 +    AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITEN;
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Set the Periodic Interval Value of the PIT.
 +/// \param piv  PIV value to set.
 +//------------------------------------------------------------------------------
 +void PIT_SetPIV(unsigned int piv)
 +{
 +    AT91C_BASE_PITC->PITC_PIMR = (AT91C_BASE_PITC->PITC_PIMR & AT91C_PITC_PIV)
 +                                 | piv;
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Enables the PIT if this is not already the case.
 +//------------------------------------------------------------------------------
 +void PIT_Enable(void)
 +{
 +    AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITEN;
 +}
 +
 +//----------------------------------------------------------------------------
 +/// Enable the PIT periodic interrupt.
 +//----------------------------------------------------------------------------
 +void PIT_EnableIT(void)
 +{
 +    AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITIEN;
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Disables the PIT periodic interrupt.
 +//------------------------------------------------------------------------------
 +void PIT_DisableIT(void)
 +{
 +    AT91C_BASE_PITC->PITC_PIMR &= ~AT91C_PITC_PITIEN;
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Returns the value of the PIT mode register.
 +/// \return PIT_MR value.
 +//------------------------------------------------------------------------------
 +unsigned int PIT_GetMode(void)
 +{
 +    return AT91C_BASE_PITC->PITC_PIMR;
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Returns the value of the PIT status register, clearing it as a side effect.
 +/// \return PIT_SR value.
 +//------------------------------------------------------------------------------
 +unsigned int PIT_GetStatus(void)
 +{
 +    return AT91C_BASE_PITC->PITC_PISR;
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Returns the value of the PIT Image Register, to read PICNT and CPIV without
 +/// clearing the current values.
 +/// \return PIT_PIIR value.
 +//------------------------------------------------------------------------------
 +unsigned int PIT_GetPIIR(void)
 +{
 +    return AT91C_BASE_PITC->PITC_PIIR;
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Returns the value of the PIT Value Register, clearing it as a side effect.
 +/// \return PIT_PIVR value.
 +//------------------------------------------------------------------------------
 +unsigned int PIT_GetPIVR(void)
 +{
 +    return AT91C_BASE_PITC->PITC_PIVR;
 +}
 diff --git a/at91lib/peripherals/pit/pit.h b/at91lib/peripherals/pit/pit.h new file mode 100644 index 0000000..12aad31 --- /dev/null +++ b/at91lib/peripherals/pit/pit.h @@ -0,0 +1,77 @@ +/* ----------------------------------------------------------------------------
 + *         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
 +///
 +/// Interface for configuration the Periodic Interval Timer (PIT) peripheral.
 +///
 +/// !Usage
 +///
 +/// -# Initialize the PIT with the desired period using PIT_Init().
 +///    Alternatively, the Periodic Interval Value (PIV) can be configured
 +///    manually using PIT_SetPIV().
 +/// -# Start the PIT counting using PIT_Enable().
 +/// -# Enable & disable the PIT interrupt using PIT_EnableIT() and
 +///    PIT_DisableIT().
 +/// -# Retrieve the current status of the PIT using PIT_GetStatus().
 +/// -# To get the current value of the internal counter and the number of ticks
 +///    that have occurred, use either PIT_GetPIVR() or PIT_GetPIIR() depending
 +///    on whether you want the values to be cleared or not.
 +//------------------------------------------------------------------------------
 +
 +#ifndef PIT_H
 +#define PIT_H
 +
 +//------------------------------------------------------------------------------
 +//         Global 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
 +
 diff --git a/at91lib/peripherals/pmc/pmc.c b/at91lib/peripherals/pmc/pmc.c new file mode 100644 index 0000000..136e401 --- /dev/null +++ b/at91lib/peripherals/pmc/pmc.c @@ -0,0 +1,186 @@ +/* ----------------------------------------------------------------------------
 + *         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>
 +
 +#ifdef CP15_PRESENT
 +#include <cp15/cp15.h>
 +#endif
 +
 +#define MASK_STATUS 0x3FFFFFFC
 +
 +//------------------------------------------------------------------------------
 +//         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
 +//------------------------------------------------------------------------------
 +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_INFO("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_INFO("PMC_DisablePeripheral: clock of peripheral"
 +                   " %u is not enabled\n\r",
 +                   id);
 +    }
 +    else {
 +
 +        AT91C_BASE_PMC->PMC_PCDR = 1 << id;
 +    }
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Enable all the periph clock via PMC
 +/// (Becareful of the last 2 bits, it is not periph clock)
 +//------------------------------------------------------------------------------
 +void PMC_EnableAllPeripherals(void)
 +{
 +    AT91C_BASE_PMC->PMC_PCER = MASK_STATUS;
 +    while( (AT91C_BASE_PMC->PMC_PCSR & MASK_STATUS) != MASK_STATUS);
 +    TRACE_INFO("Enable all periph clocks\n\r"); 
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Disable all the periph clock via PMC
 +/// (Becareful of the last 2 bits, it is not periph clock)
 +//------------------------------------------------------------------------------
 +void PMC_DisableAllPeripherals(void)
 +{
 +    AT91C_BASE_PMC->PMC_PCDR = MASK_STATUS;
 +    while((AT91C_BASE_PMC->PMC_PCSR & MASK_STATUS) != 0);
 +    TRACE_INFO("Disable all periph clocks\n\r");
 +}
 +
 +//-----------------------------------------------------------------------------
 +/// Get Periph Status
 +//-----------------------------------------------------------------------------
 +unsigned int PMC_IsAllPeriphEnabled(void)
 +{
 +    return (AT91C_BASE_PMC->PMC_PCSR == MASK_STATUS);
 +}
 +
 +//-----------------------------------------------------------------------------
 +/// Get Periph Status
 +//-----------------------------------------------------------------------------
 +unsigned int PMC_IsPeriphEnabled(unsigned int id)
 +{
 +    return (AT91C_BASE_PMC->PMC_PCSR & (1 << id));  
 +}
 +//------------------------------------------------------------------------------
 +/// Put the CPU in Idle Mode for lower consumption
 +//------------------------------------------------------------------------------
 +void PMC_CPUInIdleMode(void)
 +{
 +    PMC_DisableProcessorClock();
 +#ifdef CP15_PRESENT
 +    _waitForInterrupt();
 +#endif
 +}
 +
 +
 diff --git a/at91lib/peripherals/pmc/pmc.h b/at91lib/peripherals/pmc/pmc.h new file mode 100644 index 0000000..a53b365 --- /dev/null +++ b/at91lib/peripherals/pmc/pmc.h @@ -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 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 //__ICCARM__
 +void PMC_DisableMainOscillatorForWaitMode(void);
 +#endif // at91sam7l64 at91sam7l128
 +
 +extern void PMC_DisableProcessorClock(void);
 +extern void PMC_EnablePeripheral(unsigned int id);
 +extern void PMC_DisablePeripheral(unsigned int id);
 +extern void PMC_CPUInIdleMode(void);
 +
 +
 +extern void PMC_EnableAllPeripherals(void);
 +
 +extern void PMC_DisableAllPeripherals(void);
 +
 +extern unsigned int PMC_IsAllPeriphEnabled(void);
 +
 +extern unsigned int PMC_IsPeriphEnabled(unsigned int id);
 +
 +#endif //#ifndef PMC_H
 +
 diff --git a/at91lib/peripherals/usart/usart.c b/at91lib/peripherals/usart/usart.c new file mode 100644 index 0000000..3f6d0e3 --- /dev/null +++ b/at91lib/peripherals/usart/usart.c @@ -0,0 +1,272 @@ +/* ----------------------------------------------------------------------------
 + *         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>
 +#include <utility/assert.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_ERROR("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_ERROR("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;
 +    }
 +}
 +
 +//------------------------------------------------------------------------------
 +/// Sets the filter value for the IRDA demodulator.
 +/// \param pUsart  Pointer to an AT91S_USART instance.
 +/// \param filter  Filter value.
 +//------------------------------------------------------------------------------
 +void USART_SetIrdaFilter(AT91S_USART *pUsart, unsigned char filter)
 +{
 +    SANITY_CHECK(pUsart);
 +
 +    pUsart->US_IF = filter;
 +}
 +
 diff --git a/at91lib/peripherals/usart/usart.h b/at91lib/peripherals/usart/usart.h new file mode 100644 index 0000000..84a633c --- /dev/null +++ b/at91lib/peripherals/usart/usart.h @@ -0,0 +1,118 @@ +/* ----------------------------------------------------------------------------
 + *         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
 +/// - USART_MODE_IRDA
 +
 +/// Basic asynchronous mode, i.e. 8 bits no parity.
 +#define USART_MODE_ASYNCHRONOUS (AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE)
 +
 +/// IRDA mode
 +#define USART_MODE_IRDA         (AT91C_US_USMODE_IRDA | AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE | AT91C_US_FILTER)
 +//------------------------------------------------------------------------------
 +
 +//------------------------------------------------------------------------------
 +//         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);
 +
 +extern void USART_SetIrdaFilter(AT91S_USART *pUsart, unsigned char filter);
 +
 +#endif //#ifndef USART_H
 +
 | 
