From 98f9d442b44dbe2e3e4b3c8296be7e78d5d05450 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 24 Jul 2011 09:39:28 +0200 Subject: initial import of the usb ccid example for the sam7s --- at91lib/peripherals/aic/aic.c | 87 ++++++++ at91lib/peripherals/aic/aic.h | 79 ++++++++ at91lib/peripherals/cp15/cp15.c | 268 ++++++++++++++++++++++++ at91lib/peripherals/cp15/cp15.h | 84 ++++++++ at91lib/peripherals/cp15/cp15_asm.S | 138 +++++++++++++ at91lib/peripherals/dbgu/dbgu.c | 174 ++++++++++++++++ at91lib/peripherals/dbgu/dbgu.h | 79 ++++++++ at91lib/peripherals/pio/pio.c | 346 +++++++++++++++++++++++++++++++ at91lib/peripherals/pio/pio.h | 163 +++++++++++++++ at91lib/peripherals/pio/pio_it.c | 395 ++++++++++++++++++++++++++++++++++++ at91lib/peripherals/pio/pio_it.h | 83 ++++++++ at91lib/peripherals/pit/pit.c | 122 +++++++++++ at91lib/peripherals/pit/pit.h | 77 +++++++ at91lib/peripherals/pmc/pmc.c | 186 +++++++++++++++++ at91lib/peripherals/pmc/pmc.h | 62 ++++++ at91lib/peripherals/usart/usart.c | 272 +++++++++++++++++++++++++ at91lib/peripherals/usart/usart.h | 118 +++++++++++ 17 files changed, 2733 insertions(+) create mode 100644 at91lib/peripherals/aic/aic.c create mode 100644 at91lib/peripherals/aic/aic.h create mode 100644 at91lib/peripherals/cp15/cp15.c create mode 100644 at91lib/peripherals/cp15/cp15.h create mode 100644 at91lib/peripherals/cp15/cp15_asm.S create mode 100644 at91lib/peripherals/dbgu/dbgu.c create mode 100644 at91lib/peripherals/dbgu/dbgu.h create mode 100644 at91lib/peripherals/pio/pio.c create mode 100644 at91lib/peripherals/pio/pio.h create mode 100644 at91lib/peripherals/pio/pio_it.c create mode 100644 at91lib/peripherals/pio/pio_it.h create mode 100644 at91lib/peripherals/pit/pit.c create mode 100644 at91lib/peripherals/pit/pit.h create mode 100644 at91lib/peripherals/pmc/pmc.c create mode 100644 at91lib/peripherals/pmc/pmc.h create mode 100644 at91lib/peripherals/usart/usart.c create mode 100644 at91lib/peripherals/usart/usart.h (limited to 'at91lib/peripherals') 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 + +//------------------------------------------------------------------------------ +// 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 + +//------------------------------------------------------------------------------ +// 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 + +#ifdef CP15_PRESENT + +#include +#include "cp15.h" + +#if defined(__ICCARM__) +#include +#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, , 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, , c2, c0, 0 +/// Write TTBR : MCR p15, 0, , 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, , c3, c0, 0 +/// Write domain access permissions : MCR p15, 0, , 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,,c10,c0,0 +/// Write data TLB lockdown victim : MCR p15,0,,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, , 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 +#include + +//------------------------------------------------------------------------------ +// 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 + +//------------------------------------------------------------------------------ +/// \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 + +//------------------------------------------------------------------------------ +// 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 + +//------------------------------------------------------------------------------ +// 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 +#include +#include +#include + +//------------------------------------------------------------------------------ +// 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 + +//------------------------------------------------------------------------------ +// 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 +#include +#include + +#ifdef CP15_PRESENT +#include +#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 +#include + +//------------------------------------------------------------------------------ +// 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 + +//------------------------------------------------------------------------------ +// 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 + -- cgit v1.2.3