Add new demo files.

This commit is contained in:
Richard Barry 2009-06-01 11:45:26 +00:00
parent b5ab3cd823
commit 151c72ab7c
125 changed files with 40038 additions and 0 deletions

View file

@ -0,0 +1,805 @@
/******************************************************************************
* @file: core_cm3.c
* @purpose: CMSIS Cortex-M3 Core Peripheral Access Layer Source File
* @version: V1.10
* @date: 24. Feb. 2009
*----------------------------------------------------------------------------
*
* Copyright (C) 2009 ARM Limited. All rights reserved.
*
* ARM Limited (ARM) is supplying this software for use with Cortex-Mx
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*
******************************************************************************/
#include <stdint.h>
/* define compiler specific symbols */
#if defined ( __CC_ARM )
#define __ASM __asm /*!< asm keyword for armcc */
#define __INLINE __inline /*!< inline keyword for armcc */
#elif defined ( __ICCARM__ )
#define __ASM __asm /*!< asm keyword for iarcc */
#define __INLINE inline /*!< inline keyword for iarcc. Only avaiable in High optimization mode! */
#define __nop __no_operation /*!< no operation intrinsic in iarcc */
#elif defined ( __GNUC__ )
#define __ASM asm /*!< asm keyword for gcc */
#define __INLINE inline /*!< inline keyword for gcc */
#endif
#if defined ( __CC_ARM ) /*------------------RealView Compiler -----------------*/
/**
* @brief Return the Process Stack Pointer
*
* @param none
* @return uint32_t ProcessStackPointer
*
* Return the actual process stack pointer
*/
__ASM uint32_t __get_PSP(void)
{
mrs r0, psp
bx lr
}
/**
* @brief Set the Process Stack Pointer
*
* @param uint32_t Process Stack Pointer
* @return none
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
__ASM void __set_PSP(uint32_t topOfProcStack)
{
msr psp, r0
bx lr
}
/**
* @brief Return the Main Stack Pointer
*
* @param none
* @return uint32_t Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
__ASM uint32_t __get_MSP(void)
{
mrs r0, msp
bx lr
}
/**
* @brief Set the Main Stack Pointer
*
* @param uint32_t Main Stack Pointer
* @return none
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
__ASM void __set_MSP(uint32_t mainStackPointer)
{
msr msp, r0
bx lr
}
/**
* @brief Reverse byte order in unsigned short value
*
* @param uint16_t value to reverse
* @return uint32_t reversed value
*
* Reverse byte order in unsigned short value
*/
__ASM uint32_t __REV16(uint16_t value)
{
rev16 r0, r0
bx lr
}
/**
* @brief Reverse byte order in signed short value with sign extension to integer
*
* @param int16_t value to reverse
* @return int32_t reversed value
*
* Reverse byte order in signed short value with sign extension to integer
*/
__ASM int32_t __REVSH(int16_t value)
{
revsh r0, r0
bx lr
}
#if (__ARMCC_VERSION < 400000)
/**
* @brief Remove the exclusive lock created by ldrex
*
* @param none
* @return none
*
* Removes the exclusive lock which is created by ldrex.
*/
__ASM void __CLREX(void)
{
clrex
}
/**
* @brief Return the Base Priority value
*
* @param none
* @return uint32_t BasePriority
*
* Return the content of the base priority register
*/
__ASM uint32_t __get_BASEPRI(void)
{
mrs r0, basepri
bx lr
}
/**
* @brief Set the Base Priority value
*
* @param uint32_t BasePriority
* @return none
*
* Set the base priority register
*/
__ASM void __set_BASEPRI(uint32_t basePri)
{
msr basepri, r0
bx lr
}
/**
* @brief Return the Priority Mask value
*
* @param none
* @return uint32_t PriMask
*
* Return the state of the priority mask bit from the priority mask
* register
*/
__ASM uint32_t __get_PRIMASK(void)
{
mrs r0, primask
bx lr
}
/**
* @brief Set the Priority Mask value
*
* @param uint32_t PriMask
* @return none
*
* Set the priority mask bit in the priority mask register
*/
__ASM void __set_PRIMASK(uint32_t priMask)
{
msr primask, r0
bx lr
}
/**
* @brief Return the Fault Mask value
*
* @param none
* @return uint32_t FaultMask
*
* Return the content of the fault mask register
*/
__ASM uint32_t __get_FAULTMASK(void)
{
mrs r0, faultmask
bx lr
}
/**
* @brief Set the Fault Mask value
*
* @param uint32_t faultMask value
* @return none
*
* Set the fault mask register
*/
__ASM void __set_FAULTMASK(uint32_t faultMask)
{
msr faultmask, r0
bx lr
}
/**
* @brief Return the Control Register value
*
* @param none
* @return uint32_t Control value
*
* Return the content of the control register
*/
__ASM uint32_t __get_CONTROL(void)
{
mrs r0, control
bx lr
}
/**
* @brief Set the Control Register value
*
* @param uint32_t Control value
* @return none
*
* Set the control register
*/
__ASM void __set_CONTROL(uint32_t control)
{
msr control, r0
bx lr
}
#endif /* __ARMCC_VERSION */
#elif (defined (__ICCARM__)) /*------------------ ICC Compiler -------------------*/
#pragma diag_suppress=Pe940
/**
* @brief Return the Process Stack Pointer
*
* @param none
* @return uint32_t ProcessStackPointer
*
* Return the actual process stack pointer
*/
uint32_t __get_PSP(void)
{
__ASM("mrs r0, psp");
__ASM("bx lr");
}
/**
* @brief Set the Process Stack Pointer
*
* @param uint32_t Process Stack Pointer
* @return none
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
void __set_PSP(uint32_t topOfProcStack)
{
__ASM("msr psp, r0");
__ASM("bx lr");
}
/**
* @brief Return the Main Stack Pointer
*
* @param none
* @return uint32_t Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
uint32_t __get_MSP(void)
{
__ASM("mrs r0, msp");
__ASM("bx lr");
}
/**
* @brief Set the Main Stack Pointer
*
* @param uint32_t Main Stack Pointer
* @return none
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
void __set_MSP(uint32_t topOfMainStack)
{
__ASM("msr msp, r0");
__ASM("bx lr");
}
/**
* @brief Reverse byte order in unsigned short value
*
* @param uint16_t value to reverse
* @return uint32_t reversed value
*
* Reverse byte order in unsigned short value
*/
uint32_t __REV16(uint16_t value)
{
__ASM("rev16 r0, r0");
__ASM("bx lr");
}
/**
* @brief Reverse bit order of value
*
* @param uint32_t value to reverse
* @return uint32_t reversed value
*
* Reverse bit order of value
*/
uint32_t __RBIT(uint32_t value)
{
__ASM("rbit r0, r0");
__ASM("bx lr");
}
/**
* @brief LDR Exclusive
*
* @param uint8_t* address
* @return uint8_t value of (*address)
*
* Exclusive LDR command
*/
uint8_t __LDREXB(uint8_t *addr)
{
__ASM("ldrexb r0, [r0]");
__ASM("bx lr");
}
/**
* @brief LDR Exclusive
*
* @param uint16_t* address
* @return uint16_t value of (*address)
*
* Exclusive LDR command
*/
uint16_t __LDREXH(uint16_t *addr)
{
__ASM("ldrexh r0, [r0]");
__ASM("bx lr");
}
/**
* @brief LDR Exclusive
*
* @param uint32_t* address
* @return uint32_t value of (*address)
*
* Exclusive LDR command
*/
uint32_t __LDREXW(uint32_t *addr)
{
__ASM("ldrex r0, [r0]");
__ASM("bx lr");
}
/**
* @brief STR Exclusive
*
* @param uint8_t *address
* @param uint8_t value to store
* @return uint32_t successful / failed
*
* Exclusive STR command
*/
uint32_t __STREXB(uint8_t value, uint8_t *addr)
{
__ASM("strexb r0, r0, [r1]");
__ASM("bx lr");
}
/**
* @brief STR Exclusive
*
* @param uint16_t *address
* @param uint16_t value to store
* @return uint32_t successful / failed
*
* Exclusive STR command
*/
uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
__ASM("strexh r0, r0, [r1]");
__ASM("bx lr");
}
/**
* @brief STR Exclusive
*
* @param uint32_t *address
* @param uint32_t value to store
* @return uint32_t successful / failed
*
* Exclusive STR command
*/
uint32_t __STREXW(uint32_t value, uint32_t *addr)
{
__ASM("strex r0, r0, [r1]");
__ASM("bx lr");
}
#pragma diag_default=Pe940
#elif (defined (__GNUC__)) /*------------------ GNU Compiler ---------------------*/
/**
* @brief Return the Process Stack Pointer
*
* @param none
* @return uint32_t ProcessStackPointer
*
* Return the actual process stack pointer
*/
uint32_t __get_PSP(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, psp" : "=r" (result) );
return(result);
}
/**
* @brief Set the Process Stack Pointer
*
* @param uint32_t Process Stack Pointer
* @return none
*
* Assign the value ProcessStackPointer to the MSP
* (process stack pointer) Cortex processor register
*/
void __set_PSP(uint32_t topOfProcStack)
{
__ASM volatile ("MSR psp, %0" : : "r" (topOfProcStack) );
}
/**
* @brief Return the Main Stack Pointer
*
* @param none
* @return uint32_t Main Stack Pointer
*
* Return the current value of the MSP (main stack pointer)
* Cortex processor register
*/
uint32_t __get_MSP(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, msp" : "=r" (result) );
return(result);
}
/**
* @brief Set the Main Stack Pointer
*
* @param uint32_t Main Stack Pointer
* @return none
*
* Assign the value mainStackPointer to the MSP
* (main stack pointer) Cortex processor register
*/
void __set_MSP(uint32_t topOfMainStack)
{
__ASM volatile ("MSR msp, %0" : : "r" (topOfMainStack) );
}
/**
* @brief Return the Base Priority value
*
* @param none
* @return uint32_t BasePriority
*
* Return the content of the base priority register
*/
uint32_t __get_BASEPRI(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, basepri_max" : "=r" (result) );
return(result);
}
/**
* @brief Set the Base Priority value
*
* @param uint32_t BasePriority
* @return none
*
* Set the base priority register
*/
void __set_BASEPRI(uint32_t value)
{
__ASM volatile ("MSR basepri, %0" : : "r" (value) );
}
/**
* @brief Return the Priority Mask value
*
* @param none
* @return uint32_t PriMask
*
* Return the state of the priority mask bit from the priority mask
* register
*/
uint32_t __get_PRIMASK(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, primask" : "=r" (result) );
return(result);
}
/**
* @brief Set the Priority Mask value
*
* @param uint32_t PriMask
* @return none
*
* Set the priority mask bit in the priority mask register
*/
void __set_PRIMASK(uint32_t priMask)
{
__ASM volatile ("MSR primask, %0" : : "r" (priMask) );
}
/**
* @brief Return the Fault Mask value
*
* @param none
* @return uint32_t FaultMask
*
* Return the content of the fault mask register
*/
uint32_t __get_FAULTMASK(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, faultmask" : "=r" (result) );
return(result);
}
/**
* @brief Set the Fault Mask value
*
* @param uint32_t faultMask value
* @return none
*
* Set the fault mask register
*/
void __set_FAULTMASK(uint32_t faultMask)
{
__ASM volatile ("MSR faultmask, %0" : : "r" (faultMask) );
}
/**
* @brief Reverse byte order in integer value
*
* @param uint32_t value to reverse
* @return uint32_t reversed value
*
* Reverse byte order in integer value
*/
uint32_t __REV(uint32_t value)
{
uint32_t result=0;
__ASM volatile ("rev %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief Reverse byte order in unsigned short value
*
* @param uint16_t value to reverse
* @return uint32_t reversed value
*
* Reverse byte order in unsigned short value
*/
uint32_t __REV16(uint16_t value)
{
uint32_t result=0;
__ASM volatile ("rev16 %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief Reverse byte order in signed short value with sign extension to integer
*
* @param int32_t value to reverse
* @return int32_t reversed value
*
* Reverse byte order in signed short value with sign extension to integer
*/
int32_t __REVSH(int16_t value)
{
uint32_t result=0;
__ASM volatile ("revsh %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief Reverse bit order of value
*
* @param uint32_t value to reverse
* @return uint32_t reversed value
*
* Reverse bit order of value
*/
uint32_t __RBIT(uint32_t value)
{
uint32_t result=0;
__ASM volatile ("rbit %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
/**
* @brief LDR Exclusive
*
* @param uint8_t* address
* @return uint8_t value of (*address)
*
* Exclusive LDR command
*/
uint8_t __LDREXB(uint8_t *addr)
{
uint8_t result=0;
__ASM volatile ("ldrexb %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/**
* @brief LDR Exclusive
*
* @param uint16_t* address
* @return uint16_t value of (*address)
*
* Exclusive LDR command
*/
uint16_t __LDREXH(uint16_t *addr)
{
uint16_t result=0;
__ASM volatile ("ldrexh %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/**
* @brief LDR Exclusive
*
* @param uint32_t* address
* @return uint32_t value of (*address)
*
* Exclusive LDR command
*/
uint32_t __LDREXW(uint32_t *addr)
{
uint32_t result=0;
__ASM volatile ("ldrex %0, [%1]" : "=r" (result) : "r" (addr) );
return(result);
}
/**
* @brief STR Exclusive
*
* @param uint8_t *address
* @param uint8_t value to store
* @return uint32_t successful / failed
*
* Exclusive STR command
*/
uint32_t __STREXB(uint8_t value, uint8_t *addr)
{
uint32_t result=0;
__ASM volatile ("strexb %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}
/**
* @brief STR Exclusive
*
* @param uint16_t *address
* @param uint16_t value to store
* @return uint32_t successful / failed
*
* Exclusive STR command
*/
uint32_t __STREXH(uint16_t value, uint16_t *addr)
{
uint32_t result=0;
__ASM volatile ("strexh %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}
/**
* @brief STR Exclusive
*
* @param uint32_t *address
* @param uint32_t value to store
* @return uint32_t successful / failed
*
* Exclusive STR command
*/
uint32_t __STREXW(uint32_t value, uint32_t *addr)
{
uint32_t result=0;
__ASM volatile ("strex %0, %2, [%1]" : "=r" (result) : "r" (addr), "r" (value) );
return(result);
}
/**
* @brief Return the Control Register value
*
* @param none
* @return uint32_t Control value
*
* Return the content of the control register
*/
uint32_t __get_CONTROL(void)
{
uint32_t result=0;
__ASM volatile ("MRS %0, control" : "=r" (result) );
return(result);
}
/**
* @brief Set the Control Register value
*
* @param uint32_t Control value
* @return none
*
* Set the control register
*/
void __set_CONTROL(uint32_t control)
{
__ASM volatile ("MSR control, %0" : : "r" (control) );
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,376 @@
/* ----------------------------------------------------------------------------
* 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
///
/// HX8347 driver
///
/// !Usage
///
/// Explanation on the usage of the code made available through the header file.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#include <stdio.h>
#ifdef BOARD_LCD_HX8347
#include "hx8347.h"
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
typedef volatile unsigned short REG16;
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
/// LCD index register address
#define LCD_IR(baseAddr) (*((REG16 *)(baseAddr)))
/// LCD status register address
#define LCD_SR(baseAddr) (*((REG16 *)(baseAddr)))
/// LCD data address
#define LCD_D(baseAddr) (*((REG16 *)((unsigned int)(baseAddr) + BOARD_LCD_RS)))
/// HX8347 ID code
#define HX8347_HIMAXID_CODE 0x47
/// HX8347 LCD Registers
#define HX8347_R00H 0x00
#define HX8347_R01H 0x01
#define HX8347_R02H 0x02
#define HX8347_R03H 0x03
#define HX8347_R04H 0x04
#define HX8347_R05H 0x05
#define HX8347_R06H 0x06
#define HX8347_R07H 0x07
#define HX8347_R08H 0x08
#define HX8347_R09H 0x09
#define HX8347_R0AH 0x0A
#define HX8347_R0CH 0x0C
#define HX8347_R0DH 0x0D
#define HX8347_R0EH 0x0E
#define HX8347_R0FH 0x0F
#define HX8347_R10H 0x10
#define HX8347_R11H 0x11
#define HX8347_R12H 0x12
#define HX8347_R13H 0x13
#define HX8347_R14H 0x14
#define HX8347_R15H 0x15
#define HX8347_R16H 0x16
#define HX8347_R18H 0x18
#define HX8347_R19H 0x19
#define HX8347_R1AH 0x1A
#define HX8347_R1BH 0x1B
#define HX8347_R1CH 0x1C
#define HX8347_R1DH 0x1D
#define HX8347_R1EH 0x1E
#define HX8347_R1FH 0x1F
#define HX8347_R20H 0x20
#define HX8347_R21H 0x21
#define HX8347_R22H 0x22
#define HX8347_R23H 0x23
#define HX8347_R24H 0x24
#define HX8347_R25H 0x25
#define HX8347_R26H 0x26
#define HX8347_R27H 0x27
#define HX8347_R28H 0x28
#define HX8347_R29H 0x29
#define HX8347_R2AH 0x2A
#define HX8347_R2BH 0x2B
#define HX8347_R2CH 0x2C
#define HX8347_R2DH 0x2D
#define HX8347_R35H 0x35
#define HX8347_R36H 0x36
#define HX8347_R37H 0x37
#define HX8347_R38H 0x38
#define HX8347_R39H 0x39
#define HX8347_R3AH 0x3A
#define HX8347_R3BH 0x3B
#define HX8347_R3CH 0x3C
#define HX8347_R3DH 0x3D
#define HX8347_R3EH 0x3E
#define HX8347_R40H 0x40
#define HX8347_R41H 0x41
#define HX8347_R42H 0x42
#define HX8347_R43H 0x43
#define HX8347_R44H 0x44
#define HX8347_R45H 0x45
#define HX8347_R46H 0x46
#define HX8347_R47H 0x47
#define HX8347_R48H 0x48
#define HX8347_R49H 0x49
#define HX8347_R4AH 0x4A
#define HX8347_R4BH 0x4B
#define HX8347_R4CH 0x4C
#define HX8347_R4DH 0x4D
#define HX8347_R4EH 0x4E
#define HX8347_R4FH 0x4F
#define HX8347_R50H 0x50
#define HX8347_R51H 0x51
#define HX8347_R64H 0x64
#define HX8347_R65H 0x65
#define HX8347_R66H 0x66
#define HX8347_R67H 0x67
#define HX8347_R70H 0x70
#define HX8347_R72H 0x72
#define HX8347_R90H 0x90
#define HX8347_R91H 0x91
#define HX8347_R93H 0x93
#define HX8347_R94H 0x94
#define HX8347_R95H 0x95
//------------------------------------------------------------------------------
// External functions
//------------------------------------------------------------------------------
// External delay 1 ms function
#include "FreeRTOS.h"
#include "task.h"
#define Delay(ms) vTaskDelay(ms/portTICK_RATE_MS)
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Write data to LCD Register.
/// \param pLcdBase LCD base address.
/// \param reg Register address.
/// \param data Data to be written.
//------------------------------------------------------------------------------
void LCD_WriteReg(void *pLcdBase, unsigned char reg, unsigned short data)
{
LCD_IR(pLcdBase) = reg;
LCD_D(pLcdBase) = data;
}
//------------------------------------------------------------------------------
/// Read data from LCD Register.
/// \param pLcdBase LCD base address.
/// \param reg Register address.
/// \return data Data to be read.
//------------------------------------------------------------------------------
unsigned short LCD_ReadReg(void *pLcdBase, unsigned char reg)
{
LCD_IR(pLcdBase) = reg;
return LCD_D(pLcdBase);
}
//------------------------------------------------------------------------------
/// Read LCD status Register.
/// \param pLcdBase LCD base address.
/// \param reg Register address.
/// \return data Status Data.
//------------------------------------------------------------------------------
unsigned short LCD_ReadStatus(void *pLcdBase)
{
return LCD_SR(pLcdBase);
}
//------------------------------------------------------------------------------
/// Prepare to write GRAM data.
/// \param pLcdBase LCD base address.
//------------------------------------------------------------------------------
void LCD_WriteRAM_Prepare(void *pLcdBase)
{
LCD_IR(pLcdBase) = HX8347_R22H;
}
//------------------------------------------------------------------------------
/// Write data to LCD GRAM.
/// \param pLcdBase LCD base address.
/// \param color 16-bits RGB color.
//------------------------------------------------------------------------------
void LCD_WriteRAM(void *pLcdBase, unsigned short color)
{
// Write 16-bit GRAM Reg
LCD_D(pLcdBase) = color;
}
//------------------------------------------------------------------------------
/// Read GRAM data.
/// \param pLcdBase LCD base address.
/// \return 16-bits RGB color.
//------------------------------------------------------------------------------
unsigned short LCD_ReadRAM(void *pLcdBase)
{
// Read 16-bit GRAM Reg
return LCD_D(pLcdBase);
}
//------------------------------------------------------------------------------
/// Dump register data.
/// \param pLcdBase LCD base address.
/// \param startAddr Register start address.
/// \param endAddr Register end address.
//------------------------------------------------------------------------------
void LCD_DumpReg(void *pLcdBase, unsigned char startAddr, unsigned char endAddr)
{
unsigned short tmp;
unsigned char addr;
for (addr = startAddr; addr <= endAddr; addr++) {
tmp = LCD_ReadReg(pLcdBase, addr);
printf("LCD.r 0x%x = 0x%x\n\r", addr, tmp);
}
}
//------------------------------------------------------------------------------
/// Initialize the LCD controller.
/// \param pLcdBase LCD base address.
//------------------------------------------------------------------------------
void LCD_Initialize(void *pLcdBase)
{
unsigned short chipid;
// Check HX8347 chipid
chipid = LCD_ReadReg(pLcdBase, HX8347_R67H);
if(chipid != HX8347_HIMAXID_CODE) {
printf("Read HX8347 chip ID error, skip initialization.\r\n");
return ;
}
// Start internal OSC
LCD_WriteReg(pLcdBase, HX8347_R19H, 0x49); // OSCADJ=10 0000, OSD_EN=1 //60Hz
LCD_WriteReg(pLcdBase, HX8347_R93H, 0x0C); // RADJ=1100
// Power on flow
LCD_WriteReg(pLcdBase, HX8347_R44H, 0x4D); // VCM=100 1101
LCD_WriteReg(pLcdBase, HX8347_R45H, 0x11); // VDV=1 0001
LCD_WriteReg(pLcdBase, HX8347_R20H, 0x40); // BT=0100
LCD_WriteReg(pLcdBase, HX8347_R1DH, 0x07); // VC1=111
LCD_WriteReg(pLcdBase, HX8347_R1EH, 0x00); // VC3=000
LCD_WriteReg(pLcdBase, HX8347_R1FH, 0x04); // VRH=0100
LCD_WriteReg(pLcdBase, HX8347_R1CH, 0x04); // AP=100
LCD_WriteReg(pLcdBase, HX8347_R1BH, 0x10); // GASENB=0, PON=1, DK=0, XDK=0, DDVDH_TRI=0, STB=0
Delay(50);
LCD_WriteReg(pLcdBase, HX8347_R43H, 0x80); // Set VCOMG=1
Delay(50);
// Gamma for CMO 2.8
LCD_WriteReg(pLcdBase, HX8347_R46H, 0x95);
LCD_WriteReg(pLcdBase, HX8347_R47H, 0x51);
LCD_WriteReg(pLcdBase, HX8347_R48H, 0x00);
LCD_WriteReg(pLcdBase, HX8347_R49H, 0x36);
LCD_WriteReg(pLcdBase, HX8347_R4AH, 0x11);
LCD_WriteReg(pLcdBase, HX8347_R4BH, 0x66);
LCD_WriteReg(pLcdBase, HX8347_R4CH, 0x14);
LCD_WriteReg(pLcdBase, HX8347_R4DH, 0x77);
LCD_WriteReg(pLcdBase, HX8347_R4EH, 0x13);
LCD_WriteReg(pLcdBase, HX8347_R4FH, 0x4C);
LCD_WriteReg(pLcdBase, HX8347_R50H, 0x46);
LCD_WriteReg(pLcdBase, HX8347_R51H, 0x46);
//240x320 window setting
LCD_WriteReg(pLcdBase, HX8347_R02H, 0x00); // Column address start2
LCD_WriteReg(pLcdBase, HX8347_R03H, 0x00); // Column address start1
LCD_WriteReg(pLcdBase, HX8347_R04H, 0x00); // Column address end2
LCD_WriteReg(pLcdBase, HX8347_R05H, 0xEF); // Column address end1
LCD_WriteReg(pLcdBase, HX8347_R06H, 0x00); // Row address start2
LCD_WriteReg(pLcdBase, HX8347_R07H, 0x00); // Row address start1
LCD_WriteReg(pLcdBase, HX8347_R08H, 0x01); // Row address end2
LCD_WriteReg(pLcdBase, HX8347_R09H, 0x3F); // Row address end1
// Display Setting
LCD_WriteReg(pLcdBase, HX8347_R01H, 0x06); // IDMON=0, INVON=1, NORON=1, PTLON=0
LCD_WriteReg(pLcdBase, HX8347_R16H, 0xC8); // MY=1, MX=1, MV=0, BGR=1
LCD_WriteReg(pLcdBase, HX8347_R23H, 0x95); // N_DC=1001 0101
LCD_WriteReg(pLcdBase, HX8347_R24H, 0x95); // P_DC=1001 0101
LCD_WriteReg(pLcdBase, HX8347_R25H, 0xFF); // I_DC=1111 1111
LCD_WriteReg(pLcdBase, HX8347_R27H, 0x06); // N_BP=0000 0110
LCD_WriteReg(pLcdBase, HX8347_R28H, 0x06); // N_FP=0000 0110
LCD_WriteReg(pLcdBase, HX8347_R29H, 0x06); // P_BP=0000 0110
LCD_WriteReg(pLcdBase, HX8347_R2AH, 0x06); // P_FP=0000 0110
LCD_WriteReg(pLcdBase, HX8347_R2CH, 0x06); // I_BP=0000 0110
LCD_WriteReg(pLcdBase, HX8347_R2DH, 0x06); // I_FP=0000 0110
LCD_WriteReg(pLcdBase, HX8347_R3AH, 0x01); // N_RTN=0000, N_NW=001
LCD_WriteReg(pLcdBase, HX8347_R3BH, 0x01); // P_RTN=0000, P_NW=001
LCD_WriteReg(pLcdBase, HX8347_R3CH, 0xF0); // I_RTN=1111, I_NW=000
LCD_WriteReg(pLcdBase, HX8347_R3DH, 0x00); // DIV=00
LCD_WriteReg(pLcdBase, HX8347_R3EH, 0x38); // SON=38h
LCD_WriteReg(pLcdBase, HX8347_R40H, 0x0F); // GDON=0Fh
LCD_WriteReg(pLcdBase, HX8347_R41H, 0xF0); // GDOF=F0h
}
//------------------------------------------------------------------------------
/// Turn on the LCD.
/// \param pLcdBase LCD base address.
//------------------------------------------------------------------------------
void LCD_On(void *pLcdBase)
{
// Display ON Setting
LCD_WriteReg(pLcdBase, HX8347_R90H, 0x7F); // SAP=0111 1111
LCD_WriteReg(pLcdBase, HX8347_R26H, 0x04); // GON=0, DTE=0, D=01
Delay(100);
LCD_WriteReg(pLcdBase, HX8347_R26H, 0x24); // GON=1, DTE=0, D=01
LCD_WriteReg(pLcdBase, HX8347_R26H, 0x2C); // GON=1, DTE=0, D=11
Delay(100);
LCD_WriteReg(pLcdBase, HX8347_R26H, 0x3C); // GON=1, DTE=1, D=11
}
//------------------------------------------------------------------------------
/// Turn off the LCD.
/// \param pLcdBase LCD base address.
//------------------------------------------------------------------------------
void LCD_Off(void *pLcdBase)
{
LCD_WriteReg(pLcdBase, HX8347_R90H, 0x00); // SAP=0000 0000
LCD_WriteReg(pLcdBase, HX8347_R26H, 0x00); // GON=0, DTE=0, D=00
}
//------------------------------------------------------------------------------
/// Set cursor of LCD srceen.
/// \param pLcdBase LCD base address.
/// \param x X-coordinate of upper-left corner on LCD.
/// \param y Y-coordinate of upper-left corner on LCD.
//------------------------------------------------------------------------------
void LCD_SetCursor(void *pLcdBase, unsigned short x, unsigned short y)
{
unsigned char x1, x2, y1, y2;
x1 = x & 0xff;
x2 = (x & 0xff00) >>8;
y1 = y & 0xff;
y2 = (y & 0xff00) >>8;
LCD_WriteReg(pLcdBase, HX8347_R02H, x2); // column high
LCD_WriteReg(pLcdBase, HX8347_R03H, x1); // column low
LCD_WriteReg(pLcdBase, HX8347_R06H, y2); // row high
LCD_WriteReg(pLcdBase, HX8347_R07H, y1); // row low
}
#endif //#ifdef BOARD_LCD_HX8347

View file

@ -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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
///
/// !!!Purpose
///
/// Definition of methods for HX8347 driver.
///
/// !!!Usage
///
/// -# LCD_WriteReg
/// -# LCD_ReadReg
/// -# LCD_ReadStatus
/// -# LCD_DumpReg
/// -# LCD_WriteRAM_Prepare
/// -# LCD_WriteRAM
/// -# LCD_ReadRAM
/// -# LCD_Initialize
/// -# LCD_SetCursor
/// -# LCD_On
/// -# LCD_Off
//------------------------------------------------------------------------------
#ifndef HX8347_H
#define HX8347_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#ifdef BOARD_LCD_HX8347
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
/// Convert 24-bits color to 16-bits color
#define RGB24ToRGB16(color) (((color >> 8) & 0xF800) | \
((color >> 5) & 0x7E0) | \
((color >> 3) & 0x1F))
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
void LCD_WriteReg(void *pLcdBase, unsigned char reg, unsigned short data);
unsigned short LCD_ReadReg(void *pLcdBase, unsigned char reg);
unsigned short LCD_ReadStatus(void *pLcdBase);
void LCD_DumpReg(void *pLcdBase, unsigned char startAddr, unsigned char endAddr);
void LCD_WriteRAM_Prepare(void *pLcdBase);
void LCD_WriteRAM(void *pLcdBase, unsigned short color);
unsigned short LCD_ReadRAM(void *pLcdBase);
void LCD_Initialize(void *pLcdBase);
void LCD_SetCursor(void *pLcdBase, unsigned short x, unsigned short y);
void LCD_On(void *pLcdBase);
void LCD_Off(void *pLcdBase);
#endif //#ifdef BOARD_LCD_HX8347
#endif //#ifndef HX8347_H

View file

@ -0,0 +1,132 @@
/* ----------------------------------------------------------------------------
* 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 COLOR_H
#define COLOR_H
//------------------------------------------------------------------------------
/// RGB 24 Bpp
/// RGB 888
/// R7R6R5R4 R3R2R1R0 G7G6G5G4 G3G2G1G0 B7B6B5B4 B3B2B1B0
//------------------------------------------------------------------------------
#define COLOR_BLACK 0x000000
#define COLOR_WHITE 0xFFFFFF
#define COLOR_BLUE 0x0000FF
#define COLOR_GREEN 0x00FF00
#define COLOR_RED 0xFF0000
#define COLOR_NAVY 0x000080
#define COLOR_DARKBLUE 0x00008B
#define COLOR_DARKGREEN 0x006400
#define COLOR_DARKCYAN 0x008B8B
#define COLOR_CYAN 0x00FFFF
#define COLOR_TURQUOISE 0x40E0D0
#define COLOR_INDIGO 0x4B0082
#define COLOR_DARKRED 0x800000
#define COLOR_OLIVE 0x808000
#define COLOR_GRAY 0x808080
#define COLOR_SKYBLUE 0x87CEEB
#define COLOR_BLUEVIOLET 0x8A2BE2
#define COLOR_LIGHTGREEN 0x90EE90
#define COLOR_DARKVIOLET 0x9400D3
#define COLOR_YELLOWGREEN 0x9ACD32
#define COLOR_BROWN 0xA52A2A
#define COLOR_DARKGRAY 0xA9A9A9
#define COLOR_SIENNA 0xA0522D
#define COLOR_LIGHTBLUE 0xADD8E6
#define COLOR_GREENYELLOW 0xADFF2F
#define COLOR_SILVER 0xC0C0C0
#define COLOR_LIGHTGREY 0xD3D3D3
#define COLOR_LIGHTCYAN 0xE0FFFF
#define COLOR_VIOLET 0xEE82EE
#define COLOR_AZUR 0xF0FFFF
#define COLOR_BEIGE 0xF5F5DC
#define COLOR_MAGENTA 0xFF00FF
#define COLOR_TOMATO 0xFF6347
#define COLOR_GOLD 0xFFD700
#define COLOR_ORANGE 0xFFA500
#define COLOR_SNOW 0xFFFAFA
#define COLOR_YELLOW 0xFFFF00
#endif // #define COLOR_H

View file

@ -0,0 +1,81 @@
/* ----------------------------------------------------------------------------
* 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
///
/// Provides simple drawing function to use with the LCD.
///
/// !!!Usage
///
/// -# Use LCDD_Fill to fill the LCD buffer with a specific color.
/// -# Draw a pixel on the screen at the specified coordinates using
/// LCDD_DrawPixel.
/// -# Draw a rectangle with LCDD_DrawRectangle.
/// -# Draw a string on the LCD with LCDD_DrawString.
//------------------------------------------------------------------------------
#ifndef DRAW_H
#define DRAW_H
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void LCDD_Fill(void *pBuffer, unsigned int color);
extern void LCDD_DrawPixel(
void *pBuffer,
unsigned int x,
unsigned int y,
unsigned int c);
extern void LCDD_DrawRectangle(
void *pBuffer,
unsigned int x,
unsigned int y,
unsigned int width,
unsigned int height,
unsigned int color);
extern void LCDD_DrawString(
void *pBuffer,
unsigned int x,
unsigned int y,
const char *pString,
unsigned int color);
extern void LCDD_GetStringSize(
const char *pString,
unsigned int *pWidth,
unsigned int *pHeight);
#endif //#ifndef DRAW_H

View file

@ -0,0 +1,181 @@
/* ----------------------------------------------------------------------------
* 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 "draw.h"
#include "font.h"
#include <board.h>
#include <utility/assert.h>
#include <hx8347/hx8347.h>
#include <string.h>
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Fills the given LCD buffer with a particular color.
/// Only works in 24-bits packed mode for now.
/// \param pBuffer LCD buffer to fill.
/// \param color Fill color.
//------------------------------------------------------------------------------
void LCDD_Fill(void *pBuffer, unsigned int color)
{
unsigned int i;
unsigned short color16 = RGB24ToRGB16(color);
LCD_SetCursor((void *)BOARD_LCD_BASE, 0, 0);
LCD_WriteRAM_Prepare((void *)BOARD_LCD_BASE);
for (i = 0; i < (BOARD_LCD_WIDTH * BOARD_LCD_HEIGHT); i++) {
LCD_WriteRAM((void *)BOARD_LCD_BASE, color16);
}
}
//------------------------------------------------------------------------------
/// Sets the specified pixel to the given color.
/// !!! Only works in 24-bits packed mode for now. !!!
/// \param pBuffer LCD buffer to draw on.
/// \param x X-coordinate of pixel.
/// \param y Y-coordinate of pixel.
/// \param color Pixel color.
//------------------------------------------------------------------------------
void LCDD_DrawPixel(
void *pBuffer,
unsigned int x,
unsigned int y,
unsigned int color)
{
unsigned short color16 = RGB24ToRGB16(color);
LCD_SetCursor(pBuffer, x, y);
LCD_WriteRAM_Prepare(pBuffer);
LCD_WriteRAM(pBuffer, color16);
}
//------------------------------------------------------------------------------
/// Draws a rectangle inside a LCD buffer, at the given coordinates.
/// \param pBuffer LCD buffer to draw on.
/// \param x X-coordinate of upper-left rectangle corner.
/// \param y Y-coordinate of upper-left rectangle corner.
/// \param width Rectangle width in pixels.
/// \param height Rectangle height in pixels.
/// \param color Rectangle color.
//------------------------------------------------------------------------------
void LCDD_DrawRectangle(
void *pBuffer,
unsigned int x,
unsigned int y,
unsigned int width,
unsigned int height,
unsigned int color)
{
unsigned int rx, ry;
for (ry=0; ry < height; ry++) {
for (rx=0; rx < width; rx++) {
LCDD_DrawPixel(pBuffer, x+rx, y+ry, color);
}
}
}
//------------------------------------------------------------------------------
/// Draws a string inside a LCD buffer, at the given coordinates. Line breaks
/// will be honored.
/// \param pBuffer Buffer to draw on.
/// \param x X-coordinate of string top-left corner.
/// \param y Y-coordinate of string top-left corner.
/// \param pString String to display.
/// \param color String color.
//------------------------------------------------------------------------------
void LCDD_DrawString(
void *pBuffer,
unsigned int x,
unsigned int y,
const char *pString,
unsigned int color)
{
unsigned xorg = x;
while (*pString != 0) {
if (*pString == '\n') {
y += gFont.height + 2;
x = xorg;
}
else {
LCDD_DrawChar(pBuffer, x, y, *pString, color);
x += gFont.width + 2;
}
pString++;
}
}
//------------------------------------------------------------------------------
/// Returns the width & height in pixels that a string will occupy on the screen
/// if drawn using LCDD_DrawString.
/// \param pString String.
/// \param pWidth Pointer for storing the string width (optional).
/// \param pHeight Pointer for storing the string height (optional).
/// \return String width in pixels.
//------------------------------------------------------------------------------
void LCDD_GetStringSize(
const char *pString,
unsigned int *pWidth,
unsigned int *pHeight)
{
unsigned int width = 0;
unsigned int height = gFont.height;
while (*pString != 0) {
if (*pString == '\n') {
height += gFont.height + 2;
}
else {
width += gFont.width + 2;
}
pString++;
}
if (width > 0) width -= 2;
if (pWidth) *pWidth = width;
if (pHeight) *pHeight = height;
}

View file

@ -0,0 +1,86 @@
/* ----------------------------------------------------------------------------
* 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 "font.h"
#include "draw.h"
#include "font10x14.h"
#include <utility/assert.h>
//------------------------------------------------------------------------------
// Local variables
//------------------------------------------------------------------------------
/// Global variable describing the font being instancied.
const Font gFont = {10, 14};
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Draws an ASCII character on the given LCD buffer.
/// \param pBuffer Buffer to write on.
/// \param x X-coordinate of character upper-left corner.
/// \param y Y-coordinate of character upper-left corner.
/// \param c Character to output.
/// \param color Character color.
//------------------------------------------------------------------------------
void LCDD_DrawChar(
void *pBuffer,
unsigned int x,
unsigned int y,
char c,
unsigned int color)
{
unsigned int row, col;
SANITY_CHECK((c >= 0x20) && (c <= 0x7F));
for (col = 0; col < 10; col++) {
for (row = 0; row < 8; row++) {
if ((pCharset10x14[((c - 0x20) * 20) + col * 2] >> (7 - row)) & 0x1) {
LCDD_DrawPixel(pBuffer, x+col, y+row, color);
}
}
for (row = 0; row < 6; row++) {
if ((pCharset10x14[((c - 0x20) * 20) + col * 2 + 1] >> (7 - row)) & 0x1) {
LCDD_DrawPixel(pBuffer, x+col, y+row+8, color);
}
}
}
}

View file

@ -0,0 +1,89 @@
/* ----------------------------------------------------------------------------
* 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
///
/// The font.h files declares a font structure and a LCDD_DrawChar function
/// that must be implemented by a font definition file to be used with the
/// LCDD_DrawString method of draw.h.
///
/// The font10x14.c implements the necessary variable and function for a 10x14
/// font.
///
/// !!!Usage
///
/// -# Declare a gFont global variable with the necessary Font information.
/// -# Implement an LCDD_DrawChar function which displays the specified
/// character on the LCD.
/// -# Use the LCDD_DrawString method defined in draw.h to display a complete
/// string.
//------------------------------------------------------------------------------
#ifndef FONT_H
#define FONT_H
//------------------------------------------------------------------------------
// Global types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Describes the font (width, height, supported characters, etc.) used by
/// the LCD driver draw API.
//------------------------------------------------------------------------------
typedef struct _Font {
/// Font width in pixels.
unsigned char width;
/// Font height in pixels.
unsigned char height;
} Font;
//------------------------------------------------------------------------------
// Global variables
//------------------------------------------------------------------------------
/// Global variable describing the font being instancied.
extern const Font gFont;
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void LCDD_DrawChar(
void *pBuffer,
unsigned int x,
unsigned int y,
char c,
unsigned int color);
#endif //#ifndef FONT_H

View file

@ -0,0 +1,237 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef LCD_FONT_10x14_H
#define LCD_FONT_10x14_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
const unsigned char pCharset10x14[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xCC,
0xFF, 0xCC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x00, 0x00,
0x00, 0x00, 0xF0, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0C, 0xC0, 0x0C, 0xC0, 0xFF, 0xFC, 0xFF, 0xFC, 0x0C, 0xC0,
0x0C, 0xC0, 0xFF, 0xFC, 0xFF, 0xFC, 0x0C, 0xC0, 0x0C, 0xC0,
0x0C, 0x60, 0x1E, 0x70, 0x3F, 0x30, 0x33, 0x30, 0xFF, 0xFC,
0xFF, 0xFC, 0x33, 0x30, 0x33, 0xF0, 0x39, 0xE0, 0x18, 0xC0,
0x60, 0x00, 0xF0, 0x0C, 0xF0, 0x3C, 0x60, 0xF0, 0x03, 0xC0,
0x0F, 0x00, 0x3C, 0x18, 0xF0, 0x3C, 0xC0, 0x3C, 0x00, 0x18,
0x3C, 0xF0, 0x7F, 0xF8, 0xC3, 0x1C, 0xC7, 0x8C, 0xCF, 0xCC,
0xDC, 0xEC, 0x78, 0x78, 0x30, 0x30, 0x00, 0xFC, 0x00, 0xCC,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0xEC, 0x00,
0xF8, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0F, 0xC0, 0x3F, 0xF0, 0x78, 0x78,
0x60, 0x18, 0xC0, 0x0C, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0x60, 0x18,
0x78, 0x78, 0x3F, 0xF0, 0x0F, 0xC0, 0x00, 0x00, 0x00, 0x00,
0x0C, 0x60, 0x0E, 0xE0, 0x07, 0xC0, 0x03, 0x80, 0x3F, 0xF8,
0x3F, 0xF8, 0x03, 0x80, 0x07, 0xC0, 0x0E, 0xE0, 0x0C, 0x60,
0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x3F, 0xF0,
0x3F, 0xF0, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
0x00, 0x44, 0x00, 0xEC, 0x00, 0xF8, 0x00, 0x70, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
0x00, 0x18, 0x00, 0x3C, 0x00, 0x3C, 0x00, 0x18, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x0C, 0x00, 0x3C, 0x00, 0xF0, 0x03, 0xC0,
0x0F, 0x00, 0x3C, 0x00, 0xF0, 0x00, 0xC0, 0x00, 0x00, 0x00,
0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0xFC, 0xC1, 0xCC, 0xC3, 0x8C,
0xC7, 0x0C, 0xCE, 0x0C, 0xFC, 0x1C, 0x7F, 0xF8, 0x3F, 0xF0,
0x00, 0x00, 0x00, 0x00, 0x30, 0x0C, 0x70, 0x0C, 0xFF, 0xFC,
0xFF, 0xFC, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x30, 0x0C, 0x70, 0x1C, 0xE0, 0x3C, 0xC0, 0x7C, 0xC0, 0xEC,
0xC1, 0xCC, 0xC3, 0x8C, 0xE7, 0x0C, 0x7E, 0x0C, 0x3C, 0x0C,
0x30, 0x30, 0x70, 0x38, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C,
0xC3, 0x0C, 0xC3, 0x0C, 0xE3, 0x1C, 0x7F, 0xF8, 0x3C, 0xF0,
0x03, 0xC0, 0x07, 0xC0, 0x0E, 0xC0, 0x1C, 0xC0, 0x38, 0xC0,
0x70, 0xC0, 0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0xC0, 0x00, 0xC0,
0xFC, 0x30, 0xFC, 0x38, 0xCC, 0x1C, 0xCC, 0x0C, 0xCC, 0x0C,
0xCC, 0x0C, 0xCC, 0x0C, 0xCE, 0x1C, 0xC7, 0xF8, 0xC3, 0xF0,
0x3F, 0xF0, 0x7F, 0xF8, 0xE3, 0x1C, 0xC3, 0x0C, 0xC3, 0x0C,
0xC3, 0x0C, 0xC3, 0x0C, 0xE3, 0x9C, 0x71, 0xF8, 0x30, 0xF0,
0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC3, 0xFC,
0xC7, 0xFC, 0xCE, 0x00, 0xDC, 0x00, 0xF8, 0x00, 0xF0, 0x00,
0x3C, 0xF0, 0x7F, 0xF8, 0xE7, 0x9C, 0xC3, 0x0C, 0xC3, 0x0C,
0xC3, 0x0C, 0xC3, 0x0C, 0xE7, 0x9C, 0x7F, 0xF8, 0x3C, 0xF0,
0x3C, 0x00, 0x7E, 0x00, 0xE7, 0x0C, 0xC3, 0x0C, 0xC3, 0x1C,
0xC3, 0x38, 0xC3, 0x70, 0xE7, 0xE0, 0x7F, 0xC0, 0x3F, 0x80,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x60, 0x3C, 0xF0,
0x3C, 0xF0, 0x18, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x44, 0x3C, 0xEC,
0x3C, 0xF8, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x03, 0x00, 0x07, 0x80, 0x0F, 0xC0, 0x1C, 0xE0,
0x38, 0x70, 0x70, 0x38, 0xE0, 0x1C, 0xC0, 0x0C, 0x00, 0x00,
0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0,
0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0,
0x00, 0x00, 0xC0, 0x0C, 0xE0, 0x1C, 0x70, 0x38, 0x38, 0x70,
0x1C, 0xE0, 0x0F, 0xC0, 0x07, 0x80, 0x03, 0x00, 0x00, 0x00,
0x30, 0x00, 0x70, 0x00, 0xE0, 0x00, 0xC0, 0x00, 0xC1, 0xEC,
0xC3, 0xEC, 0xC3, 0x00, 0xE6, 0x00, 0x7E, 0x00, 0x3C, 0x00,
0x30, 0xF0, 0x71, 0xF8, 0xE3, 0x9C, 0xC3, 0x0C, 0xC3, 0xFC,
0xC3, 0xFC, 0xC0, 0x0C, 0xE0, 0x1C, 0x7F, 0xF8, 0x3F, 0xF0,
0x3F, 0xFC, 0x7F, 0xFC, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0,
0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0xC0, 0x7F, 0xFC, 0x3F, 0xFC,
0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x0C, 0xC3, 0x0C, 0xC3, 0x0C,
0xC3, 0x0C, 0xC3, 0x0C, 0xE7, 0x9C, 0x7F, 0xF8, 0x3C, 0xF0,
0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C,
0xC0, 0x0C, 0xC0, 0x0C, 0xE0, 0x1C, 0x70, 0x38, 0x30, 0x30,
0xFF, 0xFC, 0xFF, 0xFC, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C,
0xC0, 0x0C, 0xC0, 0x0C, 0xE0, 0x1C, 0x7F, 0xF8, 0x3F, 0xF0,
0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x0C, 0xC3, 0x0C, 0xC3, 0x0C,
0xC3, 0x0C, 0xC3, 0x0C, 0xC3, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C,
0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x00, 0xC3, 0x00, 0xC3, 0x00,
0xC3, 0x00, 0xC3, 0x00, 0xC3, 0x00, 0xC0, 0x00, 0xC0, 0x00,
0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C,
0xC3, 0x0C, 0xC3, 0x0C, 0xE3, 0x1C, 0x73, 0xF8, 0x33, 0xF0,
0xFF, 0xFC, 0xFF, 0xFC, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
0x03, 0x00, 0x03, 0x00, 0x03, 0x00, 0xFF, 0xFC, 0xFF, 0xFC,
0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0xFF, 0xFC,
0xFF, 0xFC, 0xC0, 0x0C, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x00, 0x38, 0xC0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C,
0xC0, 0x1C, 0xFF, 0xF8, 0xFF, 0xF0, 0xC0, 0x00, 0xC0, 0x00,
0xFF, 0xFC, 0xFF, 0xFC, 0x07, 0x80, 0x07, 0x80, 0x0F, 0xC0,
0x1C, 0xE0, 0x38, 0x70, 0x70, 0x38, 0xE0, 0x1C, 0xC0, 0x0C,
0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C,
0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C,
0xFF, 0xFC, 0xFF, 0xFC, 0x70, 0x00, 0x38, 0x00, 0x1F, 0x00,
0x1F, 0x00, 0x38, 0x00, 0x70, 0x00, 0xFF, 0xFC, 0xFF, 0xFC,
0xFF, 0xFC, 0xFF, 0xFC, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00,
0x03, 0x80, 0x01, 0xC0, 0x00, 0xE0, 0xFF, 0xFC, 0xFF, 0xFC,
0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C,
0xC0, 0x0C, 0xC0, 0x0C, 0xE0, 0x1C, 0x7F, 0xF8, 0x3F, 0xF0,
0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x00, 0xC3, 0x00, 0xC3, 0x00,
0xC3, 0x00, 0xC3, 0x00, 0xE7, 0x00, 0x7E, 0x00, 0x3C, 0x00,
0x3F, 0xF0, 0x7F, 0xF8, 0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0xCC,
0xC0, 0xEC, 0xC0, 0x7C, 0xE0, 0x38, 0x7F, 0xFC, 0x3F, 0xEC,
0xFF, 0xFC, 0xFF, 0xFC, 0xC3, 0x00, 0xC3, 0x80, 0xC3, 0x80,
0xC3, 0xC0, 0xC3, 0xC0, 0xE7, 0x70, 0x7E, 0x3C, 0x3C, 0x1C,
0x3C, 0x18, 0x7E, 0x1C, 0xE7, 0x0C, 0xC3, 0x0C, 0xC3, 0x0C,
0xC3, 0x0C, 0xC3, 0x0C, 0xC3, 0x9C, 0xE1, 0xF8, 0x60, 0xF0,
0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xFF, 0xFC,
0xFF, 0xFC, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00,
0xFF, 0xF0, 0xFF, 0xF8, 0x00, 0x1C, 0x00, 0x0C, 0x00, 0x0C,
0x00, 0x0C, 0x00, 0x0C, 0x00, 0x1C, 0xFF, 0xF8, 0xFF, 0xF0,
0xFF, 0xC0, 0xFF, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C,
0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0xFF, 0xE0, 0xFF, 0xC0,
0xFF, 0xF0, 0xFF, 0xF8, 0x00, 0x1C, 0x00, 0x3C, 0x00, 0xF8,
0x00, 0xF8, 0x00, 0x3C, 0x00, 0x1C, 0xFF, 0xF8, 0xFF, 0xF0,
0xF0, 0x3C, 0xF8, 0x7C, 0x1C, 0xE0, 0x0F, 0xC0, 0x07, 0x80,
0x07, 0x80, 0x0F, 0xC0, 0x1C, 0xE0, 0xF8, 0x7C, 0xF0, 0x3C,
0xFC, 0x00, 0xFE, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01, 0xFC,
0x01, 0xFC, 0x03, 0x80, 0x07, 0x00, 0xFE, 0x00, 0xFC, 0x00,
0xC0, 0x3C, 0xC0, 0x7C, 0xC0, 0xEC, 0xC1, 0xCC, 0xC3, 0x8C,
0xC7, 0x0C, 0xCE, 0x0C, 0xDC, 0x0C, 0xF8, 0x0C, 0xF0, 0x0C,
0x00, 0x00, 0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFC, 0xC0, 0x0C,
0xC0, 0x0C, 0xC0, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x30, 0x00, 0x30, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x03, 0x00,
0x03, 0x00, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0x30, 0x00, 0x30,
0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C,
0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x0C, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x00,
0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0C, 0x00,
0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C,
0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x0C,
0x00, 0x00, 0x00, 0x00, 0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00,
0x38, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x30, 0x06, 0x78, 0x0E, 0xFC, 0x0C, 0xCC, 0x0C, 0xCC,
0x0C, 0xCC, 0x0C, 0xCC, 0x0E, 0xCC, 0x07, 0xFC, 0x03, 0xF8,
0xFF, 0xFC, 0xFF, 0xFC, 0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C,
0x03, 0x0C, 0x03, 0x0C, 0x03, 0x9C, 0x01, 0xF8, 0x00, 0xF0,
0x03, 0xF0, 0x07, 0xF8, 0x0E, 0x1C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0E, 0x1C, 0x07, 0x38, 0x03, 0x30,
0x00, 0xF0, 0x01, 0xF8, 0x03, 0x9C, 0x03, 0x0C, 0x03, 0x0C,
0x03, 0x0C, 0x03, 0x0C, 0x03, 0x0C, 0xFF, 0xFC, 0xFF, 0xFC,
0x03, 0xF0, 0x07, 0xF8, 0x0E, 0xDC, 0x0C, 0xCC, 0x0C, 0xCC,
0x0C, 0xCC, 0x0C, 0xCC, 0x0E, 0xDC, 0x07, 0xD8, 0x03, 0x90,
0x00, 0x00, 0x03, 0x00, 0x3F, 0xFC, 0x7F, 0xFC, 0xE3, 0x00,
0xE3, 0x00, 0x70, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0x18, 0x07, 0x9C, 0x0F, 0xCC, 0x0C, 0xCC, 0x0C, 0xCC,
0x0C, 0xCC, 0x0C, 0xCC, 0x0C, 0xDC, 0x0F, 0xF8, 0x07, 0xF0,
0xFF, 0xFC, 0xFF, 0xFC, 0x03, 0x00, 0x03, 0x00, 0x03, 0x00,
0x03, 0x00, 0x03, 0x80, 0x01, 0xFC, 0x00, 0xFC, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1B, 0xFC,
0x1B, 0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x30, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0C,
0x00, 0x0C, 0x00, 0x1C, 0xCF, 0xF8, 0xCF, 0xF0, 0x00, 0x00,
0x00, 0x00, 0xFF, 0xFC, 0xFF, 0xFC, 0x00, 0xE0, 0x01, 0xE0,
0x03, 0xF0, 0x07, 0x38, 0x0E, 0x1C, 0x0C, 0x0C, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0xFF, 0xFC,
0xFF, 0xFC, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00,
0x0F, 0xFC, 0x0F, 0xFC, 0x0E, 0x00, 0x07, 0x00, 0x03, 0xC0,
0x03, 0xC0, 0x07, 0x00, 0x0E, 0x00, 0x0F, 0xFC, 0x0F, 0xFC,
0x0F, 0xFC, 0x0F, 0xFC, 0x03, 0x00, 0x07, 0x00, 0x0E, 0x00,
0x0C, 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x07, 0xFC, 0x03, 0xFC,
0x03, 0xF0, 0x07, 0xF8, 0x0E, 0x1C, 0x0C, 0x0C, 0x0C, 0x0C,
0x0C, 0x0C, 0x0C, 0x0C, 0x0E, 0x1C, 0x07, 0xF8, 0x03, 0xF0,
0x0F, 0xFC, 0x0F, 0xFC, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0,
0x0C, 0xC0, 0x0C, 0xC0, 0x0F, 0xC0, 0x07, 0x80, 0x03, 0x00,
0x03, 0x00, 0x07, 0x80, 0x0F, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0,
0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0F, 0xFC, 0x0F, 0xFC,
0x0F, 0xFC, 0x0F, 0xFC, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00,
0x0C, 0x00, 0x0C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x00,
0x03, 0x18, 0x07, 0x9C, 0x0F, 0xCC, 0x0C, 0xCC, 0x0C, 0xCC,
0x0C, 0xCC, 0x0C, 0xCC, 0x0C, 0xFC, 0x0E, 0x78, 0x06, 0x30,
0x00, 0x00, 0x0C, 0x00, 0x0C, 0x00, 0xFF, 0xF0, 0xFF, 0xF8,
0x0C, 0x1C, 0x0C, 0x1C, 0x0C, 0x38, 0x0C, 0x30, 0x00, 0x00,
0x0F, 0xF0, 0x0F, 0xF8, 0x00, 0x1C, 0x00, 0x0C, 0x00, 0x0C,
0x00, 0x0C, 0x00, 0x0C, 0x00, 0x1C, 0x0F, 0xF8, 0x0F, 0xF0,
0x0F, 0xC0, 0x0F, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C,
0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x0F, 0xE0, 0x0F, 0xC0,
0x0F, 0xF0, 0x0F, 0xF8, 0x00, 0x1C, 0x00, 0x1C, 0x00, 0xF8,
0x00, 0xF8, 0x00, 0x1C, 0x00, 0x1C, 0x0F, 0xF8, 0x0F, 0xF0,
0x0C, 0x0C, 0x0E, 0x1C, 0x07, 0x38, 0x03, 0xF0, 0x01, 0xE0,
0x01, 0xE0, 0x03, 0xF0, 0x07, 0x38, 0x0E, 0x1C, 0x0C, 0x0C,
0x0C, 0x00, 0x0E, 0x00, 0x07, 0x0C, 0x03, 0x9C, 0x01, 0xF8,
0x01, 0xF0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x0C, 0x00,
0x0C, 0x0C, 0x0C, 0x1C, 0x0C, 0x3C, 0x0C, 0x7C, 0x0C, 0xEC,
0x0D, 0xCC, 0x0F, 0x8C, 0x0F, 0x0C, 0x0E, 0x0C, 0x0C, 0x0C,
0x00, 0x00, 0x03, 0x00, 0x07, 0x80, 0x3F, 0xF0, 0x7C, 0xF8,
0xE0, 0x1C, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0x00, 0x00,
0x03, 0x0C, 0x03, 0x0C, 0x3F, 0xFC, 0x7F, 0xFC, 0xE3, 0x0C,
0xC3, 0x0C, 0xC0, 0x0C, 0xE0, 0x0C, 0x70, 0x0C, 0x30, 0x0C,
0x00, 0x00, 0xC0, 0x0C, 0xC0, 0x0C, 0xC0, 0x0C, 0xE0, 0x1C,
0x7C, 0xF8, 0x3F, 0xF0, 0x07, 0x80, 0x03, 0x00, 0x00, 0x00,
0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00,
0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00, 0xC0, 0x00,
0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC,
0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC, 0xFF, 0xFC
};
#endif // #ifdef _LCD_FONT_10x14_h

View file

@ -0,0 +1,61 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
///
/// !!!Purpose
///
/// Simple driver for the LCD, which takes care of the initialization.
///
/// !!!Usage
///
/// -# Call LCDD_Initialize to configure the LCD controller.
/// -# Set the buffer displayed by the LCD with LCDD_DisplayBuffer if using
/// peripheral LCDC, or start displaying with LCDD_Start if using HX8347.
//------------------------------------------------------------------------------
#ifndef LCDD_H
#define LCDD_H
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void LCDD_Initialize(void); // For peripheral LCDC & HX8347
extern void * LCDD_DisplayBuffer(void *pBuffer); // For peripheral LCDC only
extern void LCDD_Start(void); // For HX8347 only
extern void LCDD_Stop(void); // For peripheral LCDC & HX8347
extern void LCDD_SetBacklight (unsigned int step); // For peripheral LCDC only
#endif //#ifndef LCDD_H

View file

@ -0,0 +1,143 @@
/* ----------------------------------------------------------------------------
* 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 "lcdd.h"
#include <board.h>
#include <pmc/pmc.h>
#include <hx8347/hx8347.h>
#include <pio/pio.h>
#include "FreeRTOS.h"
#include "task.h"
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Initializes the LCD controller.
/// \param pLcdBase LCD base address.
//------------------------------------------------------------------------------
void LCDD_Initialize(void)
{
const Pin pPins[] = {BOARD_LCD_PINS};
AT91PS_HSMC4_CS pSMC = AT91C_BASE_HSMC4_CS2;
unsigned int rMode;
// Enable pins
PIO_Configure(pPins, PIO_LISTSIZE(pPins));
// Enable peripheral clock
PMC_EnablePeripheral(AT91C_ID_HSMC4);
// EBI SMC Configuration
pSMC->HSMC4_SETUP = 0
| ((4 << 0) & AT91C_HSMC4_NWE_SETUP)
| ((2 << 8) & AT91C_HSMC4_NCS_WR_SETUP)
| ((4 << 16) & AT91C_HSMC4_NRD_SETUP)
| ((2 << 24) & AT91C_HSMC4_NCS_RD_SETUP)
;
pSMC->HSMC4_PULSE = 0
| (( 5 << 0) & AT91C_HSMC4_NWE_PULSE)
| (( 18 << 8) & AT91C_HSMC4_NCS_WR_PULSE)
| (( 5 << 16) & AT91C_HSMC4_NRD_PULSE)
| (( 18 << 24) & AT91C_HSMC4_NCS_RD_PULSE)
;
pSMC->HSMC4_CYCLE = 0
| ((22 << 0) & AT91C_HSMC4_NWE_CYCLE)
| ((22 << 16) & AT91C_HSMC4_NRD_CYCLE)
;
rMode = pSMC->HSMC4_MODE;
pSMC->HSMC4_MODE = (rMode & ~(AT91C_HSMC4_DBW | AT91C_HSMC4_READ_MODE
| AT91C_HSMC4_WRITE_MODE | AT91C_HSMC4_PMEN))
| (AT91C_HSMC4_READ_MODE)
| (AT91C_HSMC4_WRITE_MODE)
| (AT91C_HSMC4_DBW_WIDTH_SIXTEEN_BITS)
;
// Initialize LCD controller (HX8347)
LCD_Initialize((void *)BOARD_LCD_BASE);
// Set LCD backlight
LCDD_SetBacklight(25);
}
//------------------------------------------------------------------------------
/// Turn on the LCD
//------------------------------------------------------------------------------
void LCDD_Start(void)
{
LCD_On((void *)BOARD_LCD_BASE);
}
//------------------------------------------------------------------------------
/// Turn off the LCD
//------------------------------------------------------------------------------
void LCDD_Stop(void)
{
LCD_Off((void *)BOARD_LCD_BASE);
}
//------------------------------------------------------------------------------
/// Set the backlight of the LCD.
/// \param level Backlight brightness level [1..32], 32 is maximum level.
//------------------------------------------------------------------------------
void LCDD_SetBacklight (unsigned int level)
{
unsigned int i;
const Pin pPins[] = {BOARD_BACKLIGHT_PIN};
// Enable pins
PIO_Configure(pPins, PIO_LISTSIZE(pPins));
// Switch off backlight
PIO_Clear(pPins);
vTaskDelay( 2 );
// Set new backlight level
for (i = 0; i < level; i++) {
PIO_Set(pPins);
PIO_Set(pPins);
PIO_Set(pPins);
PIO_Clear(pPins);
PIO_Clear(pPins);
PIO_Clear(pPins);
}
PIO_Set(pPins);
}

View file

@ -0,0 +1,692 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "ac97c.h"
#include <board.h>
#include <aic/aic.h>
#include <utility/assert.h>
#include <utility/trace.h>
#include <utility/math.h>
//------------------------------------------------------------------------------
// Local constants
//------------------------------------------------------------------------------
/// Maximum size of one PDC buffer (in bytes).
#define MAX_PDC_COUNTER 65535
//------------------------------------------------------------------------------
// Local types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// AC97 transfer descriptor. Tracks the status and parameters of a transfer
/// on the AC97 bus.
//------------------------------------------------------------------------------
typedef struct _Ac97Transfer {
/// Buffer containing the slots to send.
unsigned char *pBuffer;
/// Total number of samples to send.
volatile unsigned int numSamples;
/// Optional callback function.
Ac97Callback callback;
/// Optional argument to the callback function.
void *pArg;
} Ac97Transfer;
//------------------------------------------------------------------------------
/// AC97 controller driver structure. Monitors the status of transfers on all
/// AC97 channels.
//------------------------------------------------------------------------------
typedef struct _Ac97c {
/// List of transfers occuring on each channel.
Ac97Transfer transfers[5];
} Ac97c;
//------------------------------------------------------------------------------
// Local variables
//------------------------------------------------------------------------------
/// Global AC97 controller instance.
static Ac97c ac97c;
//------------------------------------------------------------------------------
// Local functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Returns the size of one sample (in bytes) on the given channel.
/// \param channel Channel number.
//------------------------------------------------------------------------------
static unsigned char GetSampleSize(unsigned char channel)
{
unsigned int size = 0;
SANITY_CHECK((channel == AC97C_CHANNEL_A)
|| (channel == AC97C_CHANNEL_B)
|| (channel == AC97C_CHANNEL_CODEC));
// Check selected channel
switch (channel) {
case AC97C_CHANNEL_CODEC: return 2;
case AC97C_CHANNEL_A:
size = (AT91C_BASE_AC97C->AC97C_CAMR & AT91C_AC97C_SIZE) >> 16;
break;
case AC97C_CHANNEL_B:
size = (AT91C_BASE_AC97C->AC97C_CBMR & AT91C_AC97C_SIZE) >> 16;
break;
}
// Compute size in bytes given SIZE field
if ((size & 2) != 0) {
return 2;
}
else {
return 4;
}
}
//------------------------------------------------------------------------------
/// Interrupt service routine for Codec, is invoked by AC97C_Handler.
//------------------------------------------------------------------------------
static void CodecHandler(void)
{
unsigned int status;
unsigned int data;
Ac97Transfer *pTransfer = &(ac97c.transfers[AC97C_CODEC_TRANSFER]);
// Read CODEC status register
status = AT91C_BASE_AC97C->AC97C_COSR;
status &= AT91C_BASE_AC97C->AC97C_COMR;
// A sample has been transmitted
if (status & AT91C_AC97C_TXRDY) {
pTransfer->numSamples--;
// If there are remaining samples, transmit one
if (pTransfer->numSamples > 0) {
data = *((unsigned int *) pTransfer->pBuffer);
AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_TXRDY);
AT91C_BASE_AC97C->AC97C_COTHR = data;
// Check if transfer is read or write
if ((data & AT91C_AC97C_READ) != 0) {
AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_RXRDY;
}
else {
pTransfer->pBuffer += sizeof(unsigned int);
AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_TXRDY;
}
}
// Transfer finished
else {
AT91C_BASE_AC97C->AC97C_IDR = AT91C_AC97C_COEVT;
AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_TXRDY);
if (pTransfer->callback) {
pTransfer->callback(pTransfer->pArg, 0, 0);
}
}
}
// A sample has been received
if (status & AT91C_AC97C_RXRDY) {
// Store sample
data = AT91C_BASE_AC97C->AC97C_CORHR;
*((unsigned int *) pTransfer->pBuffer) = data;
pTransfer->pBuffer += sizeof(unsigned int);
pTransfer->numSamples--;
// Transfer finished
if (pTransfer->numSamples > 0) {
data = *((unsigned int *) pTransfer->pBuffer);
AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_RXRDY);
AT91C_BASE_AC97C->AC97C_COTHR = data;
// Check if transfer is read or write
if ((data & AT91C_AC97C_READ) != 0) {
AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_RXRDY;
}
else {
pTransfer->pBuffer += sizeof(unsigned int);
AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_TXRDY;
}
}
else {
AT91C_BASE_AC97C->AC97C_IDR = AT91C_AC97C_COEVT;
AT91C_BASE_AC97C->AC97C_COMR &= ~(AT91C_AC97C_RXRDY);
if (pTransfer->callback) {
pTransfer->callback(pTransfer->pArg, 0, 0);
}
}
}
}
//------------------------------------------------------------------------------
/// Interrupt service routine for channel A, is invoked by AC97C_Handler.
//------------------------------------------------------------------------------
static void ChannelAHandler(void)
{
unsigned int status;
Ac97Transfer *pTransmit = &(ac97c.transfers[AC97C_CHANNEL_A_TRANSMIT]);
Ac97Transfer *pReceive = &(ac97c.transfers[AC97C_CHANNEL_A_RECEIVE]);
// Read channel A status register
status = AT91C_BASE_AC97C->AC97C_CASR;
// A buffer has been transmitted
if ((status & AT91C_AC97C_ENDTX) != 0) {
// Update transfer information
if (pTransmit->numSamples > MAX_PDC_COUNTER) {
pTransmit->numSamples -= MAX_PDC_COUNTER;
}
else {
pTransmit->numSamples = 0;
}
// Transmit new buffers if necessary
if (pTransmit->numSamples > MAX_PDC_COUNTER) {
// Fill next PDC
AT91C_BASE_AC97C->AC97C_TNPR = (unsigned int) pTransmit->pBuffer;
if (pTransmit->numSamples > 2 * MAX_PDC_COUNTER) {
AT91C_BASE_AC97C->AC97C_TNCR = MAX_PDC_COUNTER;
pTransmit->pBuffer += MAX_PDC_COUNTER
* GetSampleSize(AC97C_CHANNEL_A);
}
else {
AT91C_BASE_AC97C->AC97C_TNCR = pTransmit->numSamples
- MAX_PDC_COUNTER;
}
}
// Only one buffer remaining
else {
AT91C_BASE_AC97C->AC97C_CAMR &= ~AT91C_AC97C_ENDTX;
AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_TXBUFE;
}
}
// Transmit completed
if ((status & AT91C_AC97C_TXBUFE) != 0) {
pTransmit->numSamples = 0;
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS;
AT91C_BASE_AC97C->AC97C_CAMR &= ~AT91C_AC97C_TXBUFE;
if (pTransmit->callback) {
pTransmit->callback(pTransmit->pArg, 0, 0);
}
}
// A buffer has been received
if (status & AT91C_AC97C_ENDRX) {
if (pReceive->numSamples > MAX_PDC_COUNTER) {
pReceive->numSamples -= MAX_PDC_COUNTER;
}
else {
pReceive->numSamples = 0;
}
// Transfer remaining samples
if (pReceive->numSamples > MAX_PDC_COUNTER) {
AT91C_BASE_AC97C->AC97C_RNPR = (unsigned int) pReceive->pBuffer;
if (pReceive->numSamples > 2 * MAX_PDC_COUNTER) {
AT91C_BASE_AC97C->AC97C_RNCR = MAX_PDC_COUNTER;
pReceive->pBuffer += MAX_PDC_COUNTER
* GetSampleSize(AC97C_CHANNEL_A);
}
else {
AT91C_BASE_AC97C->AC97C_RNCR = pReceive->numSamples
- MAX_PDC_COUNTER;
}
}
// Only one buffer remaining
else {
AT91C_BASE_AC97C->AC97C_CAMR &= ~(AT91C_AC97C_ENDRX);
AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_RXBUFF;
}
}
// Receive complete
if ((status & AT91C_AC97C_RXBUFF) != 0) {
pReceive->numSamples = 0;
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTDIS;
AT91C_BASE_AC97C->AC97C_CAMR &= ~AT91C_AC97C_RXBUFF;
if (pReceive->callback) {
pReceive->callback(pReceive->pArg, 0, 0);
}
}
}
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// This handler function must be called by the AC97C interrupt service routine.
/// Identifies which event was activated and calls the associated function.
//------------------------------------------------------------------------------
void AC97C_Handler(void)
{
unsigned int status;
// Get the real interrupt source
status = AT91C_BASE_AC97C->AC97C_SR;
status &= AT91C_BASE_AC97C->AC97C_IMR;
// Check if an event on the codec channel is active
if ((status & AT91C_AC97C_COEVT) != 0) {
CodecHandler();
}
// Check if an event on channel A is active
if ((status & AT91C_AC97C_CAEVT) != 0) {
ChannelAHandler();
}
}
//------------------------------------------------------------------------------
/// Starts a read or write transfer on the given channel
/// \param channel particular channel (AC97C_CODEC_TRANSFER,
/// AC97C_CHANNEL_A_RECEIVE, AC97C_CHANNEL_A_TRANSMIT,
/// AC97C_CHANNEL_B_RECEIVE or AC97C_CHANNEL_B_TRANSMIT).
/// \param pBuffer buffer containing the slots to send.
/// \param numSamples total number of samples to send.
/// \param callback optional callback function.
/// \param pArg optional argument to the callback function.
//------------------------------------------------------------------------------
unsigned char AC97C_Transfer(
unsigned char channel,
unsigned char *pBuffer,
unsigned int numSamples,
Ac97Callback callback,
void *pArg)
{
unsigned int size;
unsigned int data;
Ac97Transfer *pTransfer;
SANITY_CHECK(channel <= 5);
SANITY_CHECK(pBuffer);
SANITY_CHECK(numSamples > 0);
// Check that no transfer is pending on the channel
pTransfer = &(ac97c.transfers[channel]);
if (pTransfer->numSamples > 0) {
TRACE_WARNING(
"AC97C_Transfer: Channel %d is busy\n\r", channel);
return AC97C_ERROR_BUSY;
}
// Fill transfer information
pTransfer->pBuffer = pBuffer;
pTransfer->numSamples = numSamples;
pTransfer->callback = callback;
pTransfer->pArg = pArg;
// Transmit or receive over codec channel
if (channel == AC97C_CODEC_TRANSFER) {
// Send command
data = *((unsigned int *) pTransfer->pBuffer);
AT91C_BASE_AC97C->AC97C_COTHR = data;
// Check if transfer is read or write
if ((data & AT91C_AC97C_READ) != 0) {
AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_RXRDY;
}
else {
pTransfer->pBuffer += sizeof(unsigned int);
AT91C_BASE_AC97C->AC97C_COMR |= AT91C_AC97C_TXRDY;
}
// Enable interrupts
AT91C_BASE_AC97C->AC97C_IER |= AT91C_AC97C_COEVT;
}
// Transmit over channel A
else if (channel == AC97C_CHANNEL_A_TRANSMIT) {
// Disable PDC
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS;
// Fill PDC buffers
size = min(pTransfer->numSamples, MAX_PDC_COUNTER);
AT91C_BASE_AC97C->AC97C_TPR = (unsigned int) pTransfer->pBuffer;
AT91C_BASE_AC97C->AC97C_TCR = size;
pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
size = min(pTransfer->numSamples - size, MAX_PDC_COUNTER);
if (size > 0) {
AT91C_BASE_AC97C->AC97C_TNPR = (unsigned int) pTransfer->pBuffer;
AT91C_BASE_AC97C->AC97C_TNCR = size;
pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
}
// Enable interrupts
AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_PDCEN | AT91C_AC97C_ENDTX;
AT91C_BASE_AC97C->AC97C_IER |= AT91C_AC97C_CAEVT;
// Start transfer
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTEN;
}
// Receive over channel A
else if (channel == AC97C_CHANNEL_A_RECEIVE) {
// Disable PDC
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTDIS;
// Fill PDC buffers
size = min(pTransfer->numSamples, MAX_PDC_COUNTER);
AT91C_BASE_AC97C->AC97C_RPR = (unsigned int) pTransfer->pBuffer;
AT91C_BASE_AC97C->AC97C_RCR = size;
pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
size = min(pTransfer->numSamples - size, MAX_PDC_COUNTER);
if (size > 0) {
AT91C_BASE_AC97C->AC97C_RNPR = (unsigned int) pTransfer->pBuffer;
AT91C_BASE_AC97C->AC97C_RNCR = size;
pTransfer->pBuffer += size * GetSampleSize(AC97C_CHANNEL_A);
}
// Enable interrupts
AT91C_BASE_AC97C->AC97C_CAMR |= AT91C_AC97C_PDCEN | AT91C_AC97C_ENDRX;
AT91C_BASE_AC97C->AC97C_IER |= AT91C_AC97C_CAEVT;
// Start transfer
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTEN;
}
return 0;
}
//------------------------------------------------------------------------------
/// Stop read or write transfer on the given channel.
/// \param channel Channel number.
//------------------------------------------------------------------------------
void AC97C_CancelTransfer(unsigned char channel)
{
unsigned int size = 0;
Ac97Transfer *pTransfer;
SANITY_CHECK(channel <= AC97C_CHANNEL_B_TRANSMIT);
// Save remaining size
pTransfer = &(ac97c.transfers[channel]);
size = pTransfer->numSamples;
pTransfer->numSamples = 0;
// Stop PDC
if (channel == AC97C_CHANNEL_A_TRANSMIT) {
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS;
size -= min(size, MAX_PDC_COUNTER) - AT91C_BASE_AC97C->AC97C_TCR;
}
if (channel == AC97C_CHANNEL_A_RECEIVE) {
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_RXTDIS;
size -= min(size, MAX_PDC_COUNTER) - AT91C_BASE_AC97C->AC97C_RCR;
}
// Invoke callback if provided
if (pTransfer->callback) {
pTransfer->callback(pTransfer->pArg, AC97C_ERROR_STOPPED, size);
}
}
//------------------------------------------------------------------------------
/// Initializes the AC97 controller.
//------------------------------------------------------------------------------
void AC97C_Configure(void)
{
unsigned char channel;
// Enable the AC97 controller peripheral clock
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_AC97C);
// Enable the peripheral and variable rate adjustment
AT91C_BASE_AC97C->AC97C_MR = AT91C_AC97C_ENA | AT91C_AC97C_VRA;
// Unassigns all input & output slots
AC97C_AssignInputSlots(0, 0xFFFF);
AC97C_AssignOutputSlots(0, 0xFFFF);
// Install the AC97C interrupt handler
AT91C_BASE_AC97C->AC97C_IDR = 0xFFFFFFFF;
AIC_ConfigureIT(AT91C_ID_AC97C, 0, AC97C_Handler);
AIC_EnableIT(AT91C_ID_AC97C);
// Disable PDC transfers
AT91C_BASE_AC97C->AC97C_PTCR = AT91C_PDC_TXTDIS | AT91C_PDC_RXTDIS;
// Clear channel transfers
for (channel = 0; channel < AC97C_CHANNEL_B_TRANSMIT; channel++) {
ac97c.transfers[channel].numSamples = 0;
}
}
//------------------------------------------------------------------------------
/// Configures the desired channel with the given value.
/// \param channel Channel number.
/// \param cfg Configuration value.
//------------------------------------------------------------------------------
void AC97C_ConfigureChannel(unsigned char channel, unsigned int cfg)
{
SANITY_CHECK((channel == AC97C_CHANNEL_A) || (channel == AC97C_CHANNEL_B));
if (channel == AC97C_CHANNEL_A) {
AT91C_BASE_AC97C->AC97C_CAMR = cfg;
}
else {
AT91C_BASE_AC97C->AC97C_CBMR = cfg;
}
}
//------------------------------------------------------------------------------
/// Assigns the desired input slots to a particular channel.
/// \param channel Channel number (or 0 to unassign slots).
/// \param slots Bitfield value of slots to assign.
//------------------------------------------------------------------------------
void AC97C_AssignInputSlots(unsigned char channel, unsigned int slots)
{
unsigned int value;
unsigned int i;
SANITY_CHECK(channel <= AC97C_CHANNEL_B);
// Assign all slots
slots >>= 3;
for (i = 3; i < 15; i++) {
// Check if slots is selected
if (slots & 1) {
value = AT91C_BASE_AC97C->AC97C_ICA;
value &= ~(0x07 << ((i - 3) * 3));
value |= channel << ((i - 3) * 3);
AT91C_BASE_AC97C->AC97C_ICA = value;
}
slots >>= 1;
}
}
//------------------------------------------------------------------------------
/// Assigns the desired output slots to a particular channel.
/// \param channel Channel number (or 0 to unassign slots).
/// \param slots Bitfield value of slots to assign.
//------------------------------------------------------------------------------
void AC97C_AssignOutputSlots(unsigned char channel, unsigned int slots)
{
unsigned int value;
unsigned int i;
SANITY_CHECK(channel <= AC97C_CHANNEL_B);
// Assign all slots
slots >>= 3;
for (i = 3; i < 15; i++) {
// Check if slots is selected
if (slots & 1) {
value = AT91C_BASE_AC97C->AC97C_OCA;
value &= ~(0x07 << ((i - 3) * 3));
value |= channel << ((i - 3) * 3);
AT91C_BASE_AC97C->AC97C_OCA = value;
}
slots >>= 1;
}
}
//------------------------------------------------------------------------------
/// Returns 1 if no transfer is currently pending on the given channel;
/// otherwise, returns 0.
/// \param channel Channel number.
//------------------------------------------------------------------------------
unsigned char AC97C_IsFinished(unsigned char channel)
{
SANITY_CHECK(channel <= AC97C_CHANNEL_B_TRANSMIT);
if (ac97c.transfers[channel].numSamples > 0) {
return 0;
}
else {
return 1;
}
}
//------------------------------------------------------------------------------
/// Convenience function for synchronously sending commands to the codec.
/// \param address Register address.
/// \param data Command data.
//------------------------------------------------------------------------------
void AC97C_WriteCodec(unsigned char address, unsigned short data)
{
unsigned int sample;
sample = (address << 16) | data;
AC97C_Transfer(AC97C_CODEC_TRANSFER, (unsigned char *) &sample, 1, 0, 0);
while (!AC97C_IsFinished(AC97C_CODEC_TRANSFER));
}
//------------------------------------------------------------------------------
/// Convenience function for receiving data from the AC97 codec.
/// \param address Register address.
//------------------------------------------------------------------------------
unsigned short AC97C_ReadCodec(unsigned char address)
{
unsigned int sample;
sample = AT91C_AC97C_READ | (address << 16);
AC97C_Transfer(AC97C_CODEC_TRANSFER, (unsigned char *) &sample, 1, 0, 0);
while (!AC97C_IsFinished(AC97C_CODEC_TRANSFER));
return sample;
}
//------------------------------------------------------------------------------
/// Sets the size in bits of one sample on the given channel.
/// \param channel Channel number.
/// \param size Size of one sample in bits (10, 16, 18 or 24).
//------------------------------------------------------------------------------
void AC97C_SetChannelSize(unsigned char channel, unsigned char size)
{
unsigned int bits = 0;
SANITY_CHECK((size == 10) || (size == 16) || (size == 18) || (size == 24));
SANITY_CHECK((channel == AC97C_CHANNEL_A) || (channel == AC97C_CHANNEL_B));
switch (size) {
case 10 : bits = AT91C_AC97C_SIZE_10_BITS; break;
case 16 : bits = AT91C_AC97C_SIZE_16_BITS; break;
case 18 : bits = AT91C_AC97C_SIZE_18_BITS; break;
case 20 : bits = AT91C_AC97C_SIZE_20_BITS; break;
}
if (channel == AC97C_CHANNEL_A) {
AT91C_BASE_AC97C->AC97C_CAMR &= ~(AT91C_AC97C_SIZE);
AT91C_BASE_AC97C->AC97C_CAMR |= bits;
}
else {
AT91C_BASE_AC97C->AC97C_CBMR &= ~(AT91C_AC97C_SIZE);
AT91C_BASE_AC97C->AC97C_CBMR |= bits;
}
}

View file

@ -0,0 +1,168 @@
/* ----------------------------------------------------------------------------
* 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 AC'97
/// controller (AC97C).
///
/// !!!Usage
///
/// -# Enable the AC'97 interface pins (see pio & board.h).
/// -# Configure the AC'97 controller using AC97C_Configure
/// -# Assign the input and output slots to channels, and the data size used to
/// transfer AC97 data stream.
/// - Three functions can be used:
/// - AC97C_AssignInputSlots: set slots for AC'97 data in, recording.
/// - AC97C_AssignOutputSlots: set slots for AC'97 data out, playing.
/// - AC97C_SetChannelSize: set data sizes in bits for AC'97 data stream.
/// - Three different channels can be configured:
/// - AC97C_CHANNEL_CODEC: AC'97 register access channel, its size is
/// fixed and #must not# change by AC97C_SetChannelSize
/// - AC97C_CHANNEL_A: AC'97 stream channel, with PDC support.
/// - AC97C_CHANNEL_B: AC'97 data channel, without PDC support.
/// -# Configure the used AC97 channel with AC97C_ConfigureChannel, to enable
/// the channel.
/// -# Then you can operate the connected AC'97 codec:
/// - AC97C_ReadCodec / AC97C_WriteCodec: Read / Write codec register.
/// - AC97C_Transfer: Transfer through AC97C channels to setup codec register
/// or transfer %audio data stream.
/// - AC97C_CODEC_TRANSFER: access the codec register.
/// - AC97C_CHANNEL_A_RECEIVE, AC97C_CHANNEL_B_RECEIVE: start reading.
/// - AC97C_CHANNEL_A_TRANSMIT, AC97C_CHANNEL_B_TRANSMIT: start writing.
/// Normally you can initialize a set of AC'97 codec registers to initialize
/// the codec for %audio playing and recording.
/// -# Example code for playing & recording:
/// - General process:
/// -# Configure the codec registers for the %audio settings and formats;
/// -# Setup the channel size if necessery;
/// -# Start %audio stream transfer.
/// - Audio playing sample:
/// \code
/// // Configure sample rate of codec
/// AC97C_WriteCodec(AD1981B_PMC_DAC, expectedSampleRate);
/// // Set channel size
/// AC97C_SetChannelSize(AC97C_CHANNEL_A, bitsPerSample);
/// // Start channel A transfer
/// AC97C_Transfer(AC97C_CHANNEL_A_TRANSMIT,
/// (unsigned char *) (pointerToAudioDataBuffer),
/// numberOfSamplesToSend,
/// (Ac97Callback) PlayingFinished,
/// 0);
/// \endcode
/// - Audio recording sample:
/// \code
/// // Enable recording
/// AC97C_WriteCodec(AD1981B_REC_SEL, 0);
/// // Set sample rate
/// AC97C_WriteCodec(AD1981B_PMC_ADC, 7000);
/// // Always use 16-bits recording
/// AC97C_SetChannelSize(AC97C_CHANNEL_A, 16);
/// // Start recording
/// AC97C_Transfer(AC97C_CHANNEL_A_RECEIVE,
/// (unsigned char *) RECORD_ADDRESS,
/// MAX_RECORD_SIZE,
/// (Ac97Callback) RecordFinished,
/// 0);
/// \endcode
//------------------------------------------------------------------------------
#ifndef AC97C_H
#define AC97C_H
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
/// The channel is already busy with a transfer.
#define AC97C_ERROR_BUSY 1
/// The transfer has been stopped by the user.
#define AC97C_ERROR_STOPPED 2
/// Codec channel index.
#define AC97C_CHANNEL_CODEC 0
/// Channel A index.
#define AC97C_CHANNEL_A 1
/// Channel B index.
#define AC97C_CHANNEL_B 2
/// Codec transmit/receive transfer index.
#define AC97C_CODEC_TRANSFER 0
/// Channel A receive transfer index.
#define AC97C_CHANNEL_A_RECEIVE 1
/// Channel A transmit transfer index.
#define AC97C_CHANNEL_A_TRANSMIT 2
/// Channel B receive transfer index.
#define AC97C_CHANNEL_B_RECEIVE 3
/// Channel B transmit transfer index.
#define AC97C_CHANNEL_B_TRANSMIT 4
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
/// AC97C transfer callback function.
typedef void (*Ac97Callback)(void *pArg,
unsigned char status,
unsigned int remaining);
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void AC97C_Configure();
extern void AC97C_ConfigureChannel(unsigned char channel, unsigned int cfg);
extern void AC97C_AssignInputSlots(unsigned char channel, unsigned int slots);
extern void AC97C_AssignOutputSlots(unsigned char channel, unsigned int slots);
extern unsigned char AC97C_Transfer(
unsigned char channel,
unsigned char *pBuffer,
unsigned int numSamples,
Ac97Callback callback,
void *pArg);
extern unsigned char AC97C_IsFinished(unsigned char channel);
extern void AC97C_WriteCodec(unsigned char address, unsigned short data);
extern unsigned short AC97C_ReadCodec(unsigned char address);
extern void AC97C_SetChannelSize(unsigned char channel, unsigned char size);
extern void AC97C_CancelTransfer(unsigned char channel);
#endif //#ifndef AC97C_H

View file

@ -0,0 +1,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 <board.h>
#include <adc/adc.h>
#include <utility/trace.h>
#include <utility/assert.h>
//-----------------------------------------------------------------------------
/// Configure the Mode Register of the ADC controller
/// \param pAdc Pointer to an AT91S_ADC instance.
/// \param mode value to write in mode register
//-----------------------------------------------------------------------------
//replaced with macro definition in adc.h
//void ADC_CfgModeReg(AT91S_ADC *pAdc, unsigned int mode, unsigned int extmode)
//{
// ASSERT((mode&0xF00000C0)== 0, "ADC Bad configuration ADC MR");
//
// // Write to the MR register
// pAdc->ADC_MR = mode;
//}
//------------------------------------------------------------------------------
// Global Functions
//------------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// Initialize the ADC controller
/// \param pAdc Pointer to an AT91S_ADC instance.
/// \param trgEn trigger mode, software or Hardware
/// \param trgSel hardware trigger selection
/// \param sleepMode sleep mode selection
/// \param resolution resolution selection 8 bits or 10 bits
/// \param mckClock value of MCK in Hz
/// \param adcClock value of the ADC clock in Hz
/// \param startupTime value of the start up time (in µs) (see datasheet)
/// \param sampleAndHoldTime (in ns)
//-----------------------------------------------------------------------------
void ADC_Initialize (AT91S_ADC *pAdc,
unsigned char idAdc,
unsigned char trgEn,
unsigned char trgSel,
unsigned char sleepMode,
unsigned char resolution,
unsigned int mckClock,
unsigned int adcClock,
unsigned int startupTime,
unsigned int sampleAndHoldTime)
{
unsigned int prescal;
unsigned int startup;
unsigned int shtim;
ASSERT(startupTime<=ADC_STARTUP_TIME_MAX, "ADC Bad startupTime\n\r");
ASSERT(sampleAndHoldTime>=ADC_TRACK_HOLD_TIME_MIN, "ADC Bad sampleAndHoldTime\n\r");
// Example:
// 5 MHz operation, 20µs startup time, 600ns track and hold time
// PRESCAL: Prescaler Rate Selection ADCClock = MCK / ( (PRESCAL+1) * 2 )
// PRESCAL = [MCK / (ADCClock * 2)] -1 = [48/(5*2)]-1 = 3,8
// PRESCAL = 4 -> 48/((4+1)*2) = 48/10 = 4.8MHz
// 48/((3+1)*2) = 48/8 = 6MHz
// Startup Time = (STARTUP+1) * 8 / ADCClock
// STARTUP = [(Startup Time * ADCClock)/8]-1 = [(20 10e-6 * 5000000)/8]-1 = 11,5
// STARTUP = 11 -> (11+1)*8/48000000 = 96/4800000 = 20µs
//
// Sample & Hold Time = (SHTIM+1) / ADCClock
// SHTIM = (HoldTime * ADCClock)-1 = (600 10e-9 * 5000000)-1 = 2
// SHTIM = 2 -> (2+1)/4800000 = 1/1200000 = 833ns
prescal = (mckClock / (2*adcClock)) - 1;
startup = ((adcClock/1000000) * startupTime / 8) - 1;
shtim = (((adcClock/1000000) * sampleAndHoldTime)/1000) - 1;
ASSERT( (prescal<0x3F), "ADC Bad PRESCAL\n\r");
ASSERT(startup<0x7F, "ADC Bad STARTUP\n\r");
ASSERT(shtim<0xF, "ADC Bad SampleAndHoldTime\n\r");
TRACE_DEBUG("adcClock:%d MasterClock:%d\n\r", (mckClock/((prescal+1)*2)), mckClock);
TRACE_DEBUG("prescal:0x%X startup:0x%X shtim:0x%X\n\r", prescal, startup, shtim);
if( adcClock != (mckClock/((prescal+1)*2)) ) {
TRACE_WARNING("User and calculated adcClocks are different : user=%d calc=%d\n\r",
adcClock, (mckClock/((prescal+1)*2)));
}
// Enable peripheral clock
AT91C_BASE_PMC->PMC_PCER = 1 << idAdc;
// Reset the controller
ADC_SoftReset(pAdc);
// Write to the MR register
ADC_CfgModeReg( pAdc,
( trgEn & AT91C_ADC_TRGEN)
| ( trgSel & AT91C_ADC_TRGSEL)
| ( resolution & AT91C_ADC_LOWRES)
| ( sleepMode & AT91C_ADC_SLEEP)
| ( (prescal<<8) & AT91C_ADC_PRESCAL)
| ( (startup<<16) & AT91C_ADC_STARTUP)
| ( (shtim<<24) & AT91C_ADC_SHTIM) );
}
//-----------------------------------------------------------------------------
/// Return the Mode Register of the ADC controller value
/// \param pAdc Pointer to an AT91S_ADC instance.
/// \return ADC Mode register
//-----------------------------------------------------------------------------
//replaced with macro definition in adc.h
//unsigned int ADC_GetModeReg(AT91S_ADC *pAdc)
//{
// return pAdc->ADC_MR;
//}
//-----------------------------------------------------------------------------
/// Enable Channel
/// \param pAdc Pointer to an AT91S_ADC instance.
/// \param channel channel to enable
//-----------------------------------------------------------------------------
//void ADC_EnableChannel(AT91S_ADC *pAdc, unsigned int channel)
//{
// ASSERT(channel < 8, "ADC Channel not exist");
//
// // Write to the CHER register
// pAdc->ADC_CHER = (1 << channel);
//}
//-----------------------------------------------------------------------------
/// Disable Channel
/// \param pAdc Pointer to an AT91S_ADC instance.
/// \param channel channel to disable
//-----------------------------------------------------------------------------
//void ADC_DisableChannel (AT91S_ADC *pAdc, unsigned int channel)
//{
// ASSERT(channel < 8, "ADC Channel not exist");
//
// // Write to the CHDR register
// pAdc->ADC_CHDR = (1 << channel);
//}
//-----------------------------------------------------------------------------
/// Return chanel status
/// \param pAdc Pointer to an AT91S_ADC instance.
/// \return ADC Channel Status Register
//-----------------------------------------------------------------------------
//unsigned int ADC_GetChannelStatus(AT91S_ADC *pAdc)
//{
// return pAdc->ADC_CHSR;
//}
//-----------------------------------------------------------------------------
/// Software request for a analog to digital conversion
/// \param pAdc Pointer to an AT91S_ADC instance.
//-----------------------------------------------------------------------------
//void ADC_StartConversion(AT91S_ADC *pAdc)
//{
// pAdc->ADC_CR = AT91C_ADC_START;
//}
//-----------------------------------------------------------------------------
/// Software reset
/// \param pAdc Pointer to an AT91S_ADC instance.
//-----------------------------------------------------------------------------
//void ADC_SoftReset(AT91S_ADC *pAdc)
//{
// pAdc->ADC_CR = AT91C_ADC_SWRST;
//}
//-----------------------------------------------------------------------------
/// Return the Last Converted Data
/// \param pAdc Pointer to an AT91S_ADC instance.
/// \return Last Converted Data
//-----------------------------------------------------------------------------
//unsigned int ADC_GetLastConvertedData(AT91S_ADC *pAdc)
//{
// return pAdc->ADC_LCDR;
//}
//-----------------------------------------------------------------------------
/// Return the Channel Converted Data
/// \param pAdc Pointer to an AT91S_ADC instance.
/// \param channel channel to get converted value
/// \return Channel converted data of the specified channel
//-----------------------------------------------------------------------------
unsigned int ADC_GetConvertedData(AT91S_ADC *pAdc, unsigned int channel)
{
unsigned int data=0;
ASSERT(channel < 8, "ADC channel not exist");
switch(channel) {
case 0: data = pAdc->ADC_CDR0; break;
case 1: data = pAdc->ADC_CDR1; break;
case 2: data = pAdc->ADC_CDR2; break;
case 3: data = pAdc->ADC_CDR3; break;
#ifdef AT91C_ADC_CDR4
case 4: data = pAdc->ADC_CDR4; break;
#endif
#ifdef AT91C_ADC_CDR5
case 5: data = pAdc->ADC_CDR5; break;
#endif
#ifdef AT91C_ADC_CDR6
case 6: data = pAdc->ADC_CDR6; break;
#endif
#ifdef AT91C_ADC_CDR7
case 7: data = pAdc->ADC_CDR7; break;
#endif
}
return data;
}
//-----------------------------------------------------------------------------
/// Enable ADC interrupt
/// \param pAdc Pointer to an AT91S_ADC instance.
/// \param flag IT to be enabled
//-----------------------------------------------------------------------------
//void ADC_EnableIt(AT91S_ADC *pAdc, unsigned int flag)
//{
// ASSERT((flag&0xFFF00000)== 0, "ADC bad interrupt IER");
//
// // Write to the IER register
// pAdc->ADC_IER = flag;
//}
//-----------------------------------------------------------------------------
/// Enable ADC Data Ready interrupt
/// \param pAdc Pointer to an AT91S_ADC instance.
//-----------------------------------------------------------------------------
//void ADC_EnableDataReadyIt(AT91S_ADC *pAdc)
//{
// pAdc->ADC_IER = AT91C_ADC_DRDY;
//}
//-----------------------------------------------------------------------------
/// Disable ADC interrupt
/// \param pAdc Pointer to an AT91S_ADC instance.
/// \param flag IT to be disabled
//-----------------------------------------------------------------------------
//void ADC_DisableIt(AT91S_ADC *pAdc, unsigned int flag)
//{
// ASSERT((flag&0xFFF00000)== 0, "ADC bad interrupt IDR");
//
// // Write to the IDR register
// pAdc->ADC_IDR = flag;
//}
//-----------------------------------------------------------------------------
/// Return ADC Interrupt Status
/// \param pAdc Pointer to an AT91S_ADC instance.
/// \return ADC Stats register
//-----------------------------------------------------------------------------
//unsigned int ADC_GetStatus(AT91S_ADC *pAdc)
//{
// return pAdc->ADC_SR;
//}
//-----------------------------------------------------------------------------
/// Return ADC Interrupt Mask Status
/// \param pAdc Pointer to an AT91S_ADC instance.
/// \return ADC Interrupt Mask Register
//-----------------------------------------------------------------------------
//unsigned int ADC_GetInterruptMaskStatus(AT91S_ADC *pAdc)
//{
// return pAdc->ADC_IMR;
//}
//-----------------------------------------------------------------------------
/// Test if ADC Interrupt is Masked
/// \param pAdc Pointer to an AT91S_ADC instance.
/// \param flag flag to be tested
/// \return 1 if interrupt is masked, otherwise 0
//-----------------------------------------------------------------------------
unsigned int ADC_IsInterruptMasked(AT91S_ADC *pAdc, unsigned int flag)
{
return (ADC_GetInterruptMaskStatus(pAdc) & flag);
}
//-----------------------------------------------------------------------------
/// Test if ADC Status is Set
/// \param pAdc Pointer to an AT91S_ADC instance.
/// \param flag flag to be tested
/// \return 1 if the staus is set; 0 otherwise
//-----------------------------------------------------------------------------
unsigned int ADC_IsStatusSet(AT91S_ADC *pAdc, unsigned int flag)
{
return (ADC_GetStatus(pAdc) & flag);
}
//-----------------------------------------------------------------------------
/// Test if ADC channel interrupt Status is Set
/// \param adc_sr Value of SR register
/// \param channel Channel to be tested
/// \return 1 if interrupt status is set, otherwise 0
//-----------------------------------------------------------------------------
unsigned char ADC_IsChannelInterruptStatusSet(unsigned int adc_sr,
unsigned int channel)
{
unsigned char status;
if((adc_sr & (1<<channel)) == (1<<channel)) {
status = 1;
}
else {
status = 0;
}
return status;
}

View file

@ -0,0 +1,145 @@
/* ----------------------------------------------------------------------------
* 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 Analog-to-Digital Converter (ADC) peripheral.
///
/// !Usage
///
/// -# Configurate the pins for ADC
/// -# Initialize the ADC with ADC_Initialize().
/// -# Select the active channel using ADC_EnableChannel()
/// -# Start the conversion with ADC_StartConversion()
// -# Wait the end of the conversion by polling status with ADC_GetStatus()
// -# Finally, get the converted data using ADC_GetConvertedData()
///
//------------------------------------------------------------------------------
#ifndef ADC_H
#define ADC_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <utility/assert.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
#define ADC_CHANNEL_0 0
#define ADC_CHANNEL_1 1
#define ADC_CHANNEL_2 2
#define ADC_CHANNEL_3 3
#define ADC_CHANNEL_4 4
#define ADC_CHANNEL_5 5
#define ADC_CHANNEL_6 6
#define ADC_CHANNEL_7 7
//------------------------------------------------------------------------------
// Macros function of register access
//------------------------------------------------------------------------------
#define ADC_CfgModeReg(pAdc, mode) { \
ASSERT(((mode)&0xF00000C0)== 0, "ADC Bad configuration ADC MR");\
(pAdc)->ADC_MR = (mode);\
}
#define ADC_GetModeReg(pAdc) ((pAdc)->ADC_MR)
#define ADC_StartConversion(pAdc) ((pAdc)->ADC_CR = AT91C_ADC_START)
#define ADC_SoftReset(pAdc) ((pAdc)->ADC_CR = AT91C_ADC_SWRST)
#define ADC_EnableChannel(pAdc, channel) {\
ASSERT(channel < 8, "ADC Channel not exist");\
(pAdc)->ADC_CHER = (1 << (channel));\
}
#define ADC_DisableChannel (pAdc, channel) {\
ASSERT((channel) < 8, "ADC Channel not exist");\
(pAdc)->ADC_CHDR = (1 << (channel));\
}
#define ADC_EnableIt(pAdc, mode) {\
ASSERT(((mode)&0xFFF00000)== 0, "ADC bad interrupt IER");\
(pAdc)->ADC_IER = (mode);\
}
#define ADC_DisableIt(pAdc, mode) {\
ASSERT(((mode)&0xFFF00000)== 0, "ADC bad interrupt IDR");\
(pAdc)->ADC_IDR = (mode);\
}
#define ADC_EnableDataReadyIt(pAdc) ((pAdc)->ADC_IER = AT91C_ADC_DRDY)
#define ADC_GetStatus(pAdc) ((pAdc)->ADC_SR)
#define ADC_GetChannelStatus(pAdc) ((pAdc)->ADC_CHSR)
#define ADC_GetInterruptMaskStatus(pAdc) ((pAdc)->ADC_IMR)
#define ADC_GetLastConvertedData(pAdc) ((pAdc)->ADC_LCDR)
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void ADC_Initialize (AT91S_ADC *pAdc,
unsigned char idAdc,
unsigned char trgEn,
unsigned char trgSel,
unsigned char sleepMode,
unsigned char resolution,
unsigned int mckClock,
unsigned int adcClock,
unsigned int startupTime,
unsigned int sampleAndHoldTime);
//extern void ADC_CfgModeReg(AT91S_ADC *pAdc, unsigned int mode);
//extern unsigned int ADC_GetModeReg(AT91S_ADC *pAdc);
//extern void ADC_EnableChannel(AT91S_ADC *pAdc, unsigned int channel);
//extern void ADC_DisableChannel (AT91S_ADC *pAdc, unsigned int channel);
//extern unsigned int ADC_GetChannelStatus(AT91S_ADC *pAdc);
//extern void ADC_StartConversion(AT91S_ADC *pAdc);
//extern void ADC_SoftReset(AT91S_ADC *pAdc);
//extern unsigned int ADC_GetLastConvertedData(AT91S_ADC *pAdc);
extern unsigned int ADC_GetConvertedData(AT91S_ADC *pAdc, unsigned int channel);
//extern void ADC_EnableIt(AT91S_ADC *pAdc, unsigned int flag);
//extern void ADC_EnableDataReadyIt(AT91S_ADC *pAdc);
//extern void ADC_DisableIt(AT91S_ADC *pAdc, unsigned int flag);
//extern unsigned int ADC_GetStatus(AT91S_ADC *pAdc);
//extern unsigned int ADC_GetInterruptMaskStatus(AT91S_ADC *pAdc);
extern unsigned int ADC_IsInterruptMasked(AT91S_ADC *pAdc, unsigned int flag);
extern unsigned int ADC_IsStatusSet(AT91S_ADC *pAdc, unsigned int flag);
extern unsigned char ADC_IsChannelInterruptStatusSet(unsigned int adc_sr,
unsigned int channel);
#endif //#ifndef ADC_H

View file

@ -0,0 +1,142 @@
/* ----------------------------------------------------------------------------
* 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 Analog-to-Digital Converter (ADC) peripheral.
///
/// !Usage
///
/// -# Configurate the pins for ADC
/// -# Initialize the ADC with ADC_Initialize().
/// -# Select the active channel using ADC_EnableChannel()
/// -# Start the conversion with ADC_StartConversion()
// -# Wait the end of the conversion by polling status with ADC_GetStatus()
// -# Finally, get the converted data using ADC_GetConvertedData()
///
//------------------------------------------------------------------------------
#ifndef ADC12_H
#define ADC12_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <utility/assert.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
#define ADC_CHANNEL_0 0
#define ADC_CHANNEL_1 1
#define ADC_CHANNEL_2 2
#define ADC_CHANNEL_3 3
#define ADC_CHANNEL_4 4
#define ADC_CHANNEL_5 5
#define ADC_CHANNEL_6 6
#define ADC_CHANNEL_7 7
//------------------------------------------------------------------------------
// Macros function of register access
//------------------------------------------------------------------------------
#define ADC12_CfgModeReg(pAdc, mode) { \
ASSERT(((mode)&0xF00000C0)== 0, "ADC Bad configuration ADC MR");\
(pAdc)->ADC_MR = (mode);\
}
#define ADC12_GetModeReg(pAdc) ((pAdc)->ADC_MR)
#define ADC12_StartConversion(pAdc) ((pAdc)->ADC_CR = AT91C_ADC_START)
#define ADC12_SoftReset(pAdc) ((pAdc)->ADC_CR = AT91C_ADC_SWRST)
#define ADC12_EnableChannel(pAdc, channel) {\
ASSERT(channel < 8, "ADC Channel not exist");\
(pAdc)->ADC_CHER = (1 << (channel));\
}
#define ADC12_DisableChannel (pAdc, channel) {\
ASSERT((channel) < 8, "ADC Channel not exist");\
(pAdc)->ADC_CHDR = (1 << (channel));\
}
#define ADC12_EnableIt(pAdc, mode) {\
ASSERT(((mode)&0xFFF00000)== 0, "ADC bad interrupt IER");\
(pAdc)->ADC_IER = (mode);\
}
#define ADC12_DisableIt(pAdc, mode) {\
ASSERT(((mode)&0xFFF00000)== 0, "ADC bad interrupt IDR");\
(pAdc)->ADC_IDR = (mode);\
}
#define ADC12_EnableDataReadyIt(pAdc) ((pAdc)->ADC_IER = AT91C_ADC_DRDY)
#define ADC12_GetStatus(pAdc) ((pAdc)->ADC_SR)
#define ADC12_GetChannelStatus(pAdc) ((pAdc)->ADC_CHSR)
#define ADC12_GetInterruptMaskStatus(pAdc) ((pAdc)->ADC_IMR)
#define ADC12_GetLastConvertedData(pAdc) ((pAdc)->ADC_LCDR)
#define ADC12_CfgAnalogCtrlReg(pAdc,mode) {\
ASSERT(((mode) & 0xFFFCFF3C)==0, "ADC bad analog control config");\
(pAdc)->ADC_ACR = (mode);\
}
#define ADC12_CfgExtModeReg(pAdc, extmode) {\
ASSERT(((extmode) & 0xFF00FFFE)==0, "ADC bad extended mode config");\
(pAdc)->ADC_EMR = (extmode);\
}
#define ADC12_GetAnalogCtrlReg(pAdc) ((pAdc)->ADC_ACR)
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void ADC12_Initialize (AT91S_ADC *pAdc,
unsigned char idAdc,
unsigned char trgEn,
unsigned char trgSel,
unsigned char sleepMode,
unsigned char resolution,
unsigned int mckClock,
unsigned int adcClock,
unsigned int startupTime,
unsigned int sampleAndHoldTime);
extern unsigned int ADC12_GetConvertedData(AT91S_ADC *pAdc, unsigned int channel);
extern unsigned int ADC12_IsInterruptMasked(AT91S_ADC *pAdc, unsigned int flag);
extern unsigned int ADC12_IsStatusSet(AT91S_ADC *pAdc, unsigned int flag);
extern unsigned char ADC12_IsChannelInterruptStatusSet(unsigned int adc_sr,
unsigned int channel);
#endif //#ifndef ADC12_H

View file

@ -0,0 +1,192 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "aes.h"
#include <board.h>
#include <utility/trace.h>
#include <utility/assert.h>
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures the AES peripheral to encrypt/decrypt, start mode (manual, auto,
/// PDC) and operating mode (ECB, CBC, OFB, CFB, CTR).
/// \param cipher Indicates if the peripheral should encrypt or decrypt data.
/// \param smode Start mode.
/// \param opmode Operating mode.
//------------------------------------------------------------------------------
void AES_Configure(
unsigned char cipher,
unsigned int smode,
unsigned int opmode)
{
TRACE_DEBUG("AES_Configure()\n\r");
SANITY_CHECK((cipher & 0xFFFFFFFE) == 0);
SANITY_CHECK((smode & 0xFFFFFCFF) == 0);
SANITY_CHECK((opmode & 0xFFFF8FFF) == 0);
// Reset the peripheral first
AT91C_BASE_AES->AES_CR = AT91C_AES_SWRST;
// Configure mode register
AT91C_BASE_AES->AES_MR = cipher | smode | opmode;
}
//------------------------------------------------------------------------------
/// Sets the key used by the AES algorithm to cipher the plain text or
/// decipher the encrypted text.
/// \param pKey Pointer to a 16-bytes cipher key.
//------------------------------------------------------------------------------
void AES_SetKey(const unsigned int *pKey)
{
TRACE_DEBUG("AES_SetKey()\n\r");
SANITY_CHECK(pKey);
AT91C_BASE_AES->AES_KEYWxR[0] = pKey[0];
AT91C_BASE_AES->AES_KEYWxR[1] = pKey[1];
AT91C_BASE_AES->AES_KEYWxR[2] = pKey[2];
AT91C_BASE_AES->AES_KEYWxR[3] = pKey[3];
}
//------------------------------------------------------------------------------
/// Sets the initialization vector that is used to encrypt the plain text or
/// decrypt the cipher text in chained block modes (CBC, CFB, OFB & CTR).
/// \param pVector Pointer to a 16-bytes initialization vector.
//------------------------------------------------------------------------------
void AES_SetVector(const unsigned int *pVector)
{
TRACE_DEBUG("AES_SetVector()\n\r");
SANITY_CHECK(pVector);
AT91C_BASE_AES->AES_IVxR[0] = pVector[0];
AT91C_BASE_AES->AES_IVxR[1] = pVector[1];
AT91C_BASE_AES->AES_IVxR[2] = pVector[2];
AT91C_BASE_AES->AES_IVxR[3] = pVector[3];
}
//------------------------------------------------------------------------------
/// Sets the input data of the AES algorithm (i.e. plain text in cipher mode,
/// ciphered text in decipher mode). If auto mode is active, the encryption is
/// started automatically after writing the last word.
/// \param pData Pointer to the 16-bytes data to cipher/decipher.
//------------------------------------------------------------------------------
void AES_SetInputData(const unsigned int *pData)
{
TRACE_DEBUG("AES_SetInputData()\n\r");
SANITY_CHECK(pData);
AT91C_BASE_AES->AES_IDATAxR[0] = pData[0];
AT91C_BASE_AES->AES_IDATAxR[1] = pData[1];
AT91C_BASE_AES->AES_IDATAxR[2] = pData[2];
AT91C_BASE_AES->AES_IDATAxR[3] = pData[3];
}
//------------------------------------------------------------------------------
/// Stores the result of the last AES operation (encrypt/decrypt) in the
/// provided buffer.
/// \param pData Pointer to a 16-bytes buffer.
//------------------------------------------------------------------------------
void AES_GetOutputData(unsigned int *pData)
{
TRACE_DEBUG("AES_GetOutputData()\n\r");
SANITY_CHECK(pData);
pData[0] = AT91C_BASE_AES->AES_ODATAxR[0];
pData[1] = AT91C_BASE_AES->AES_ODATAxR[1];
pData[2] = AT91C_BASE_AES->AES_ODATAxR[2];
pData[3] = AT91C_BASE_AES->AES_ODATAxR[3];
}
//------------------------------------------------------------------------------
/// Sets the input buffer to use when in PDC mode.
/// \param pInput Pointer to the input buffer.
//------------------------------------------------------------------------------
void AES_SetInputBuffer(const unsigned int *pInput)
{
TRACE_DEBUG("AES_SetInputBuffer()\n\r");
SANITY_CHECK(pInput);
AT91C_BASE_AES->AES_TPR = (unsigned int) pInput;
AT91C_BASE_AES->AES_TCR = 4;
}
//------------------------------------------------------------------------------
/// Sets the output buffer to use when in PDC mode.
/// \param pOutput Pointer to the output buffer.
//------------------------------------------------------------------------------
void AES_SetOutputBuffer(unsigned int *pOutput)
{
TRACE_DEBUG("AES_SetOutputBuffer()\n\r");
SANITY_CHECK(pOutput);
AT91C_BASE_AES->AES_RPR = (unsigned int) pOutput;
AT91C_BASE_AES->AES_RCR = 4;
}
//------------------------------------------------------------------------------
/// Starts the encryption/decryption process when in manual or PDC mode. In
/// manual mode, the key and input data must have been entered using
/// AES_SetKey() and AES_SetInputData(). In PDC mode, the key, input & output
/// buffer must have been set using AES_SetKey(), AES_SetInputBuffer() and
/// AES_SetOutputBuffer().
//------------------------------------------------------------------------------
void AES_Start(void)
{
TRACE_DEBUG("AES_Start()\n\r");
SANITY_CHECK(((AT91C_BASE_AES->AES_MR & AT91C_AES_SMOD) == AT91C_AES_SMOD_MANUAL)
|| ((AT91C_BASE_AES->AES_MR & AT91C_AES_SMOD) == AT91C_AES_SMOD_PDC));
// Manual mode
if ((AT91C_BASE_AES->AES_MR & AT91C_AES_SMOD) == AT91C_AES_SMOD_MANUAL) {
AT91C_BASE_AES->AES_CR = AT91C_AES_START;
}
// PDC
else {
AT91C_BASE_AES->AES_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
}
}
//------------------------------------------------------------------------------
/// Returns the current value of the AES interrupt status register.
//------------------------------------------------------------------------------
unsigned int AES_GetStatus(void)
{
TRACE_DEBUG("AES_GetStatus()\n\r");
return AT91C_BASE_AES->AES_ISR;
}

View file

@ -0,0 +1,76 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef AES_H
#define AES_H
//------------------------------------------------------------------------------
/// \unit
///
/// !Purpose
///
/// Methods to manage the Advanced Encryption Standard (AES)
///
/// !Usage
///
/// -# Configure AES
/// -# Sets the key used by the AES algorithm
/// -# Sets the input data of the AES algorithm
/// -# Starts the encryption/decryption process
/// -# Stores the result of the last AES operation
///
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void AES_Configure(
unsigned char cipher,
unsigned int smode,
unsigned int opmode);
extern void AES_SetKey(const unsigned int *pKey);
extern void AES_SetVector(const unsigned int *pVector);
extern void AES_SetInputData(const unsigned int *pData);
extern void AES_GetOutputData(unsigned int *pData);
extern void AES_SetInputBuffer(const unsigned int *pInput);
extern void AES_SetOutputBuffer(unsigned int *pOutput);
extern void AES_Start(void);
extern unsigned int AES_GetStatus(void);
#endif //#ifndef AES_H

View file

@ -0,0 +1,87 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "aic.h"
#include <board.h>
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures an interrupt in the AIC. The interrupt is identified by its
/// source (AT91C_ID_xxx) and is configured to use the specified mode and
/// interrupt handler function. Mode is the value that will be put in AIC_SMRx
/// and the function address will be set in AIC_SVRx.
/// The interrupt is disabled before configuration, so it is useless
/// to do it before calling this function. When AIC_ConfigureIT returns, the
/// interrupt will always be disabled and cleared; it must be enabled by a
/// call to AIC_EnableIT().
/// \param source Interrupt source to configure.
/// \param mode Triggering mode and priority of the interrupt.
/// \param handler Interrupt handler function.
//------------------------------------------------------------------------------
void AIC_ConfigureIT(
unsigned int source,
unsigned int mode,
void (*handler)(void))
{
// Disable the interrupt first
AT91C_BASE_AIC->AIC_IDCR = 1 << source;
// Configure mode and handler
AT91C_BASE_AIC->AIC_SMR[source] = mode;
AT91C_BASE_AIC->AIC_SVR[source] = (unsigned int) handler;
// Clear interrupt
AT91C_BASE_AIC->AIC_ICCR = 1 << source;
}
//------------------------------------------------------------------------------
/// Enables interrupts coming from the given (unique) source (AT91C_ID_xxx).
/// \param source Interrupt source to enable.
//------------------------------------------------------------------------------
void AIC_EnableIT(unsigned int source)
{
AT91C_BASE_AIC->AIC_IECR = 1 << source;
}
//------------------------------------------------------------------------------
/// Disables interrupts coming from the given (unique) source (AT91C_ID_xxx).
/// \param source Interrupt source to enable.
//------------------------------------------------------------------------------
void AIC_DisableIT(unsigned int source)
{
AT91C_BASE_AIC->AIC_IDCR = 1 << source;
}

View file

@ -0,0 +1,79 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
///
/// !Purpose
///
/// Methods and definitions for configuring interrupts using the Advanced
/// Interrupt Controller (AIC).
///
/// !Usage
///
/// -# Configure an interrupt source using AIC_ConfigureIT
/// -# Enable or disable interrupt generation of a particular source with
/// AIC_EnableIT and AIC_DisableIT.
///
/// \note Most of the time, peripheral interrupts must be also configured
/// inside the peripheral itself.
//------------------------------------------------------------------------------
#ifndef AIC_H
#define AIC_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
#ifndef AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL
/// Interrupt is internal and uses a logical 1 level.
#define AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL AT91C_AIC_SRCTYPE_INT_LEVEL_SENSITIVE
#endif
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void AIC_ConfigureIT(unsigned int source,
unsigned int mode,
void (*handler)( void ));
extern void AIC_EnableIT(unsigned int source);
extern void AIC_DisableIT(unsigned int source);
#endif //#ifndef AIC_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,113 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef _CAN_H
#define _CAN_H
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
#define AT91C_CAN_TIMEOUT 100000
#define AT91C_TEST_NOK 0
#define AT91C_TEST_OK 1
#define CAN_STATUS_SUCCESS 0
#define CAN_STATUS_LOCKED 1
#define CAN_STATUS_ABORTED 2
#define CAN_STATUS_RESET 3
#if defined (AT91C_BASE_CAN)
#define AT91C_BASE_CAN0 AT91C_BASE_CAN
#endif
#if defined (AT91C_ID_CAN)
#define AT91C_ID_CAN0 AT91C_ID_CAN
#endif
#if defined (AT91C_BASE_CAN_MB0)
#define AT91C_BASE_CAN0_MB0 AT91C_BASE_CAN_MB0
#define AT91C_BASE_CAN0_MB1 AT91C_BASE_CAN_MB1
#define AT91C_BASE_CAN0_MB2 AT91C_BASE_CAN_MB2
#define AT91C_BASE_CAN0_MB3 AT91C_BASE_CAN_MB3
#define AT91C_BASE_CAN0_MB4 AT91C_BASE_CAN_MB4
#define AT91C_BASE_CAN0_MB5 AT91C_BASE_CAN_MB5
#define AT91C_BASE_CAN0_MB6 AT91C_BASE_CAN_MB6
#define AT91C_BASE_CAN0_MB7 AT91C_BASE_CAN_MB7
#endif
#if defined (AT91C_BASE_CAN_MB8)
#define AT91C_BASE_CAN0_MB8 AT91C_BASE_CAN_MB8
#define AT91C_BASE_CAN0_MB9 AT91C_BASE_CAN_MB9
#define AT91C_BASE_CAN0_MB10 AT91C_BASE_CAN_MB10
#define AT91C_BASE_CAN0_MB11 AT91C_BASE_CAN_MB11
#define AT91C_BASE_CAN0_MB12 AT91C_BASE_CAN_MB12
#define AT91C_BASE_CAN0_MB13 AT91C_BASE_CAN_MB13
#define AT91C_BASE_CAN0_MB14 AT91C_BASE_CAN_MB14
#define AT91C_BASE_CAN0_MB15 AT91C_BASE_CAN_MB15
#endif
#define NUM_MAILBOX_MAX 16
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
typedef struct
{
volatile unsigned char state;
volatile unsigned char can_number;
volatile unsigned char mailbox_number;
volatile unsigned char test_can;
volatile unsigned int mode_reg;
volatile unsigned int acceptance_mask_reg;
volatile unsigned int identifier;
volatile unsigned int data_low_reg;
volatile unsigned int data_high_reg;
volatile unsigned int control_reg;
volatile unsigned int mailbox_in_use;
volatile int size;
} CanTransfer;
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern unsigned char CAN_Init( unsigned int baudrate,
CanTransfer *canTransferRead,
CanTransfer *canTransferWrite );
extern void CAN_BasicTestSuite(void);
extern void CAN_disable( void );
extern void CAN_ResetAllMailbox( void );
extern void CAN_ResetTransfer( CanTransfer *pTransfer );
extern void CAN_InitMailboxRegisters( CanTransfer *pTransfer );
extern unsigned char CAN_IsInIdle( CanTransfer *pTransfer );
extern unsigned char CAN_Write( CanTransfer *pTransfer );
extern unsigned char CAN_Read( CanTransfer *pTransfer );
extern void CAN_BasicTestSuiteWithoutInterrupt( void );
extern unsigned char CAN_IsInIdle( CanTransfer *pTransfer );
#endif // _CAN_H

View file

@ -0,0 +1,268 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//-----------------------------------------------------------------------------
// Headers
//-----------------------------------------------------------------------------
#include <board.h>
#ifdef CP15_PRESENT
#include <utility/trace.h>
#include "cp15.h"
#if defined(__ICCARM__)
#include <intrinsics.h>
#endif
//-----------------------------------------------------------------------------
// Macros
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
/*
#define CP15_RR_BIT 14 // RR bit Replacement strategy for ICache and DCache:
// 0 = Random replacement
// 1 = Round-robin replacement.
#define CP15_V_BIT 13 // V bit Location of exception vectors:
// 0 = Normal exception vectors selected address range = 0x0000 0000 to 0x0000 001C
// 1 = High exception vect selected, address range = 0xFFFF 0000 to 0xFFFF 001C
*/
#define CP15_I_BIT 12 // I bit ICache enable/disable:
// 0 = ICache disabled
// 1 = ICache enabled
/*
#define CP15_R_BIT 9 // R bit ROM protection
#define CP15_S_BIT 8 // S bit System protection
#define CP15_B_BIT 7 // B bit Endianness:
// 0 = Little-endian operation
// 1 = Big-endian operation.
*/
#define CP15_C_BIT 2 // C bit DCache enable/disable:
// 0 = Cache disabled
// 1 = Cache enabled
/*
#define CP15_A_BIT 1 // A bit Alignment fault enable/disable:
// 0 = Data address alignment fault checking disabled
// 1 = Data address alignment fault checking enabled
*/
#define CP15_M_BIT 0 // M bit MMU enable/disable: 0 = disabled 1 = enabled.
// 0 = disabled
// 1 = enabled
//-----------------------------------------------------------------------------
// Global functions
//-----------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Check Instruction Cache
/// \return 0 if I_Cache disable, 1 if I_Cache enable
//------------------------------------------------------------------------------
unsigned int CP15_Is_I_CacheEnabled(void)
{
unsigned int control;
control = _readControlRegister();
return ((control & (1 << CP15_I_BIT)) != 0);
}
//------------------------------------------------------------------------------
/// Enable Instruction Cache
//------------------------------------------------------------------------------
void CP15_Enable_I_Cache(void)
{
unsigned int control;
control = _readControlRegister();
// Check if cache is disabled
if ((control & (1 << CP15_I_BIT)) == 0) {
control |= (1 << CP15_I_BIT);
_writeControlRegister(control);
TRACE_INFO("I cache enabled.\n\r");
}
#if !defined(OP_BOOTSTRAP_on)
else {
TRACE_INFO("I cache is already enabled.\n\r");
}
#endif
}
//------------------------------------------------------------------------------
/// Disable Instruction Cache
//------------------------------------------------------------------------------
void CP15_Disable_I_Cache(void)
{
unsigned int control;
control = _readControlRegister();
// Check if cache is enabled
if ((control & (1 << CP15_I_BIT)) != 0) {
control &= ~(1 << CP15_I_BIT);
_writeControlRegister(control);
TRACE_INFO("I cache disabled.\n\r");
}
else {
TRACE_INFO("I cache is already disabled.\n\r");
}
}
//------------------------------------------------------------------------------
/// Check MMU
/// \return 0 if MMU disable, 1 if MMU enable
//------------------------------------------------------------------------------
unsigned int CP15_Is_MMUEnabled(void)
{
unsigned int control;
control = _readControlRegister();
return ((control & (1 << CP15_M_BIT)) != 0);
}
//------------------------------------------------------------------------------
/// Enable MMU
//------------------------------------------------------------------------------
void CP15_EnableMMU(void)
{
unsigned int control;
control = _readControlRegister();
// Check if MMU is disabled
if ((control & (1 << CP15_M_BIT)) == 0) {
control |= (1 << CP15_M_BIT);
_writeControlRegister(control);
TRACE_INFO("MMU enabled.\n\r");
}
else {
TRACE_INFO("MMU is already enabled.\n\r");
}
}
//------------------------------------------------------------------------------
/// Disable MMU
//------------------------------------------------------------------------------
void CP15_DisableMMU(void)
{
unsigned int control;
control = _readControlRegister();
// Check if MMU is enabled
if ((control & (1 << CP15_M_BIT)) != 0) {
control &= ~(1 << CP15_M_BIT);
control &= ~(1 << CP15_C_BIT);
_writeControlRegister(control);
TRACE_INFO("MMU disabled.\n\r");
}
else {
TRACE_INFO("MMU is already disabled.\n\r");
}
}
//------------------------------------------------------------------------------
/// Check D_Cache
/// \return 0 if D_Cache disable, 1 if D_Cache enable (with MMU of course)
//------------------------------------------------------------------------------
unsigned int CP15_Is_DCacheEnabled(void)
{
unsigned int control;
control = _readControlRegister();
return ((control & ((1 << CP15_C_BIT)||(1 << CP15_M_BIT))) != 0);
}
//------------------------------------------------------------------------------
/// Enable Data Cache
//------------------------------------------------------------------------------
void CP15_Enable_D_Cache(void)
{
unsigned int control;
control = _readControlRegister();
if( !CP15_Is_MMUEnabled() ) {
TRACE_ERROR("Do nothing: MMU not enabled\n\r");
}
else {
// Check if cache is disabled
if ((control & (1 << CP15_C_BIT)) == 0) {
control |= (1 << CP15_C_BIT);
_writeControlRegister(control);
TRACE_INFO("D cache enabled.\n\r");
}
else {
TRACE_INFO("D cache is already enabled.\n\r");
}
}
}
//------------------------------------------------------------------------------
/// Disable Data Cache
//------------------------------------------------------------------------------
void CP15_Disable_D_Cache(void)
{
unsigned int control;
control = _readControlRegister();
// Check if cache is enabled
if ((control & (1 << CP15_C_BIT)) != 0) {
control &= ~(1 << CP15_C_BIT);
_writeControlRegister(control);
TRACE_INFO("D cache disabled.\n\r");
}
else {
TRACE_INFO("D cache is already disabled.\n\r");
}
}
#endif // CP15_PRESENT

View file

@ -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

View file

@ -0,0 +1,145 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
MODULE ?cp15
;; Forward declaration of sections.
SECTION IRQ_STACK:DATA:NOROOT(2)
SECTION CSTACK:DATA:NOROOT(3)
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#define __ASSEMBLY__
#include "board.h"
#ifdef CP15_PRESENT
//------------------------------------------------------------------------------
/// Functions to access CP15 coprocessor register
//------------------------------------------------------------------------------
PUBLIC _readControlRegister
PUBLIC _writeControlRegister
PUBLIC _waitForInterrupt
PUBLIC _writeTTB
PUBLIC _writeDomain
PUBLIC _writeITLBLockdown
PUBLIC _prefetchICacheLine
//------------------------------------------------------------------------------
/// Control Register c1
/// Register c1 is the Control Register for the ARM926EJ-S processor.
/// This register specifies the configuration used to enable and disable the
/// caches and MMU. It is recommended that you access this register using a
/// read-modify-write sequence.
//------------------------------------------------------------------------------
// CP15 Read Control Register
_readControlRegister:
mov r0, #0
mrc p15, 0, r0, c1, c0, 0
bx lr
// CP15 Write Control Register
_writeControlRegister:
mcr p15, 0, r0, c1, c0, 0
bx lr
//------------------------------------------------------------------------------
/// CP15 Wait For Interrupt operation
/// The purpose of the Wait For Interrupt operation is to put the processor in
/// to a low power state.
/// This puts the processor into a low-power state and stops it executing more
/// instructions until an interrupt, or debug request occurs, regardless of
/// whether the interrupts are disabled by the masks in the CPSR.
/// When an interrupt does occur, the MCR instruction completes and the IRQ or
/// FIQ handler is entered as normal. The return link in r14_irq or r14_fiq
/// contains the address of the MCR instruction plus 8, so that the normal
/// instruction used for interrupt return (SUBS PC,R14,#4) returns to the
/// instruction following the MCR.
/// Wait For Interrupt : MCR p15, 0, <Rd>, c7, c0, 4
//------------------------------------------------------------------------------
_waitForInterrupt:
mov r0, #0
mcr p15, 0, r0, c7, c0, 4
bx lr
//------------------------------------------------------------------------------
/// CP15 Translation Table Base Register c2
/// Register c2 is the Translation Table Base Register (TTBR), for the base
/// address of the first-level translation table.
/// Reading from c2 returns the pointer to the currently active first-level
/// translation table in bits [31:14] and an Unpredictable value in bits [13:0].
/// Writing to register c2 updates the pointer to the first-level translation
/// table from the value in bits [31:14] of the written value. Bits [13:0]
/// Should Be Zero.
/// You can use the following instructions to access the TTBR:
/// Read TTBR : MRC p15, 0, <Rd>, c2, c0, 0
/// Write TTBR : MCR p15, 0, <Rd>, c2, c0, 0
//------------------------------------------------------------------------------
_writeTTB:
MCR p15, 0, r0, c2, c0, 0
bx lr
//------------------------------------------------------------------------------
/// Domain Access Control Register c3
/// Read domain access permissions : MRC p15, 0, <Rd>, c3, c0, 0
/// Write domain access permissions : MCR p15, 0, <Rd>, c3, c0, 0
//------------------------------------------------------------------------------
_writeDomain:
MCR p15, 0, r0, c3, c0, 0
bx lr
//------------------------------------------------------------------------------
/// TLB Lockdown Register c10
/// The TLB Lockdown Register controls where hardware page table walks place the
/// TLB entry, in the set associative region or the lockdown region of the TLB,
/// and if in the lockdown region, which entry is written. The lockdown region
/// of the TLB contains eight entries. See TLB structure for a description of
/// the structure of the TLB.
/// Read data TLB lockdown victim : MRC p15,0,<Rd>,c10,c0,0
/// Write data TLB lockdown victim : MCR p15,0,<Rd>,c10,c0,0
//------------------------------------------------------------------------------
_writeITLBLockdown:
MCR p15, 0, r0, c10, c0, 0
bx lr
//------------------------------------------------------------------------------
/// Prefetch ICache line
/// Performs an ICache lookup of the specified modified virtual address.
/// If the cache misses, and the region is cacheable, a linefill is performed.
/// Prefetch ICache line (MVA): MCR p15, 0, <Rd>, c7, c13, 1
//------------------------------------------------------------------------------
_prefetchICacheLine:
MCR p15, 0, r0, c7, c13, 1
bx lr
#endif
END

View file

@ -0,0 +1,174 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "dbgu.h"
#include <stdarg.h>
#include <board.h>
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Initializes the DBGU with the given parameters, and enables both the
/// transmitter and the receiver. The mode parameter contains the value of the
/// DBGU_MR register.
/// Value DBGU_STANDARD can be used for mode to get the most common configuration
/// (i.e. aysnchronous, 8bits, no parity, 1 stop bit, no flow control).
/// \param mode Operating mode to configure.
/// \param baudrate Desired baudrate (e.g. 115200).
/// \param mck Frequency of the system master clock in Hz.
//------------------------------------------------------------------------------
void DBGU_Configure(
unsigned int mode,
unsigned int baudrate,
unsigned int mck)
{
// Reset & disable receiver and transmitter, disable interrupts
AT91C_BASE_DBGU->DBGU_CR = AT91C_US_RSTRX | AT91C_US_RSTTX;
AT91C_BASE_DBGU->DBGU_IDR = 0xFFFFFFFF;
// Configure baud rate
AT91C_BASE_DBGU->DBGU_BRGR = mck / (baudrate * 16);
// Configure mode register
AT91C_BASE_DBGU->DBGU_MR = mode;
// Disable DMA channel
AT91C_BASE_DBGU->DBGU_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
// Enable receiver and transmitter
AT91C_BASE_DBGU->DBGU_CR = AT91C_US_RXEN | AT91C_US_TXEN;
}
//------------------------------------------------------------------------------
/// Outputs a character on the DBGU line.
/// \note This function is synchronous (i.e. uses polling).
/// \param c Character to send.
//------------------------------------------------------------------------------
void DBGU_PutChar(unsigned char c)
{
// Wait for the transmitter to be ready
while ((AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXEMPTY) == 0);
// Send character
AT91C_BASE_DBGU->DBGU_THR = c;
// Wait for the transfer to complete
while ((AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_TXEMPTY) == 0);
}
//------------------------------------------------------------------------------
/// Return 1 if a character can be read in DBGU
//------------------------------------------------------------------------------
unsigned int DBGU_IsRxReady()
{
return (AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_RXRDY);
}
//------------------------------------------------------------------------------
/// Reads and returns a character from the DBGU.
/// \note This function is synchronous (i.e. uses polling).
/// \return Character received.
//------------------------------------------------------------------------------
unsigned char DBGU_GetChar(void)
{
while ((AT91C_BASE_DBGU->DBGU_CSR & AT91C_US_RXRDY) == 0);
return AT91C_BASE_DBGU->DBGU_RHR;
}
#ifndef NOFPUT
#include <stdio.h>
//------------------------------------------------------------------------------
/// \exclude
/// Implementation of fputc using the DBGU as the standard output. Required
/// for printf().
/// \param c Character to write.
/// \param pStream Output stream.
/// \param The character written if successful, or -1 if the output stream is
/// not stdout or stderr.
//------------------------------------------------------------------------------
signed int fputc(signed int c, FILE *pStream)
{
if ((pStream == stdout) || (pStream == stderr)) {
DBGU_PutChar(c);
return c;
}
else {
return EOF;
}
}
//------------------------------------------------------------------------------
/// \exclude
/// Implementation of fputs using the DBGU as the standard output. Required
/// for printf(). Does NOT currently use the PDC.
/// \param pStr String to write.
/// \param pStream Output stream.
/// \return Number of characters written if successful, or -1 if the output
/// stream is not stdout or stderr.
//------------------------------------------------------------------------------
signed int fputs(const char *pStr, FILE *pStream)
{
signed int num = 0;
while (*pStr != 0) {
if (fputc(*pStr, pStream) == -1) {
return -1;
}
num++;
pStr++;
}
return num;
}
#undef putchar
//------------------------------------------------------------------------------
/// \exclude
/// Outputs a character on the DBGU.
/// \param c Character to output.
/// \return The character that was output.
//------------------------------------------------------------------------------
signed int putchar(signed int c)
{
return fputc(c, stdout);
}
#endif //#ifndef NOFPUT

View file

@ -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

View file

@ -0,0 +1,355 @@
/* ----------------------------------------------------------------------------
* 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 "dma.h"
#include <utility/assert.h>
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configure a DMAC peripheral
//------------------------------------------------------------------------------
void DMA_Config(unsigned int flag)
{
AT91C_BASE_HDMA->HDMA_GCFG = flag;
}
//------------------------------------------------------------------------------
/// Enables a DMAC peripheral
//------------------------------------------------------------------------------
void DMA_Enable(void)
{
AT91C_BASE_HDMA->HDMA_EN = AT91C_HDMA_ENABLE;
}
//------------------------------------------------------------------------------
/// Disables DMAC peripheral
//------------------------------------------------------------------------------
void DMA_Disable(void)
{
AT91C_BASE_HDMA->HDMA_EN = ~(AT91C_HDMA_ENABLE);
}
//-----------------------------------------------------------------------------
/// Enable DMA interrupt
/// \param flag IT to be enabled
//-----------------------------------------------------------------------------
void DMA_EnableIt (unsigned int flag)
{
AT91C_BASE_HDMA->HDMA_EBCIER = flag;
}
//-----------------------------------------------------------------------------
/// Disable DMA interrupt
/// \param flag IT to be enabled
//-----------------------------------------------------------------------------
void DMA_DisableIt (unsigned int flag)
{
AT91C_BASE_HDMA->HDMA_EBCIDR = flag;
}
//-----------------------------------------------------------------------------
/// Return DMA Interrupt Status
//-----------------------------------------------------------------------------
unsigned int DMA_GetStatus(void)
{
return (AT91C_BASE_HDMA->HDMA_EBCISR);
}
//-----------------------------------------------------------------------------
/// Return DMA Interrupt Mask Status
//-----------------------------------------------------------------------------
unsigned int DMA_GetInterruptMask(void)
{
return (AT91C_BASE_HDMA->HDMA_EBCIMR);
}
//-----------------------------------------------------------------------------
/// Returns the current status register of the given DMA peripheral, but
/// masking interrupt sources which are not currently enabled.
//-----------------------------------------------------------------------------
unsigned int DMA_GetMaskedStatus(void)
{
unsigned int status;
status = AT91C_BASE_HDMA->HDMA_EBCISR;
status &= AT91C_BASE_HDMA->HDMA_EBCIMR;
return status;
}
//------------------------------------------------------------------------------
/// Enables DMAC channel
/// \param channel Particular channel number.
//------------------------------------------------------------------------------
void DMA_EnableChannel(unsigned int channel)
{
ASSERT(channel < DMA_CHANNEL_NUM, "this channel does not exist");
AT91C_BASE_HDMA->HDMA_CHER |= DMA_ENA << channel;
}
//------------------------------------------------------------------------------
/// Disables a DMAC channel
/// \param channel Particular channel number.
//------------------------------------------------------------------------------
void DMA_DisableChannel(unsigned int channel)
{
ASSERT(channel < DMA_CHANNEL_NUM, "this channel does not exist");
AT91C_BASE_HDMA->HDMA_CHDR |= DMA_DIS << channel;
}
//------------------------------------------------------------------------------
/// Resume DMAC channel from an stall state.
/// \param channel Particular channel number.
//------------------------------------------------------------------------------
void DMA_KeeponChannel(unsigned int channel)
{
ASSERT(channel < DMA_CHANNEL_NUM, "this channel does not exist");
AT91C_BASE_HDMA->HDMA_CHER |= DMA_KEEPON << channel;
}
//------------------------------------------------------------------------------
/// Clear automatic mode for multi-buffer transfer.
/// \param channel Particular channel number.
//------------------------------------------------------------------------------
void DMA_ClearAutoMode(unsigned int channel)
{
ASSERT(channel < DMA_CHANNEL_NUM, "this channel does not exist");
AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CTRLB &= 0x7FFFFFFF;
}
//------------------------------------------------------------------------------
/// Return DMAC channel status
//------------------------------------------------------------------------------
unsigned int DMA_GetChannelStatus(void)
{
return( AT91C_BASE_HDMA->HDMA_CHSR);
}
//-----------------------------------------------------------------------------
/// Set DMA source address used by a HDMA channel.
/// \param channel Particular channel number.
/// \param sources sources address.
//-----------------------------------------------------------------------------
void DMA_SetSourceAddr(unsigned char channel, unsigned int address)
{
ASSERT(channel < DMA_CHANNEL_NUM, "this channel does not exist");
AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_SADDR = address;
}
//-----------------------------------------------------------------------------
/// Set DMA destination address used by a HDMA channel.
/// \param channel Particular channel number.
/// \param sources destination address.
//-----------------------------------------------------------------------------
void DMA_SetDestinationAddr(unsigned char channel, unsigned int address)
{
ASSERT(channel < DMA_CHANNEL_NUM, "this channel does not exist");
AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_DADDR = address;
}
//-----------------------------------------------------------------------------
/// Set DMA descriptor address used by a HDMA channel.
/// \param channel Particular channel number.
/// \param sources destination address.
//-----------------------------------------------------------------------------
void DMA_SetDescriptorAddr(unsigned char channel, unsigned int address)
{
ASSERT(channel < DMA_CHANNEL_NUM, "this channel does not exist");
AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_DSCR = address ;
}
//-----------------------------------------------------------------------------
/// Set DMA control A register used by a HDMA channel.
/// \param channel Particular channel number.
/// \param size Dma transfer size in byte.
/// \param sourceWidth Single transfer width for source.
/// \param destWidth Single transfer width for destination.
/// \param done Transfer done field.
//-----------------------------------------------------------------------------
void DMA_SetSourceBufferSize(unsigned char channel,
unsigned int size,
unsigned char sourceWidth,
unsigned char destWidth,
unsigned char done)
{
ASSERT(channel < DMA_CHANNEL_NUM, "this channel does not exist");
ASSERT(sourceWidth < 4, "width does not support");
ASSERT(destWidth < 4, "width does not support");
AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CTRLA = (size |
sourceWidth << 24 |
destWidth << 28 |
done << 31);
}
//-----------------------------------------------------------------------------
/// Set DMA transfer mode for source used by a HDMA channel.
/// \param channel Particular channel number.
/// \param transferMode Transfer buffer mode (single, LLI, reload or contiguous)
/// \param addressingType Type of addrassing mode
/// 0 : incrementing, 1: decrementing, 2: fixed.
//-----------------------------------------------------------------------------
void DMA_SetSourceBufferMode(unsigned char channel,
unsigned char transferMode,
unsigned char addressingType)
{
unsigned int value;
ASSERT(channel < DMA_CHANNEL_NUM, "this channel does not exist");
value = AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CTRLB;
value &= ~ (AT91C_SRC_DSCR | AT91C_SRC_INCR | 1<<31);
switch(transferMode){
case DMA_TRANSFER_SINGLE:
value |= AT91C_SRC_DSCR | addressingType << 24;
break;
case DMA_TRANSFER_LLI:
value |= addressingType << 24;
break;
case DMA_TRANSFER_RELOAD:
case DMA_TRANSFER_CONTIGUOUS:
value |= AT91C_SRC_DSCR | addressingType << 24 | 1<<31;
break;
}
AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CTRLB = value;
if(transferMode == DMA_TRANSFER_RELOAD || transferMode == DMA_TRANSFER_CONTIGUOUS){
value = AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CFG;
value &= ~ (AT91C_SRC_REP);
// When automatic mode is activated, the source address and the control register are reloaded from previous transfer.
if(transferMode == DMA_TRANSFER_RELOAD) {
value |= AT91C_SRC_REP;
}
AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CFG = value;
}
else {
AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CFG = 0;
}
}
//-----------------------------------------------------------------------------
/// Set DMA transfer mode for destination used by a HDMA channel.
/// \param channel Particular channel number.
/// \param transferMode Transfer buffer mode (single, LLI, reload or contiguous)
/// \param addressingType Type of addrassing mode
/// 0 : incrementing, 1: decrementing, 2: fixed.
//-----------------------------------------------------------------------------
void DMA_SetDestBufferMode(unsigned char channel,
unsigned char transferMode,
unsigned char addressingType)
{
unsigned int value;
ASSERT(channel < DMA_CHANNEL_NUM, "this channel does not exist");
value = AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CTRLB;
value &= ~ (AT91C_DST_DSCR | AT91C_DST_INCR);
switch(transferMode){
case DMA_TRANSFER_SINGLE:
case DMA_TRANSFER_RELOAD:
case DMA_TRANSFER_CONTIGUOUS:
value |= AT91C_DST_DSCR | addressingType << 24;
break;
case DMA_TRANSFER_LLI:
value |= addressingType << 24;
break;
}
AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CTRLB = value;
if(transferMode == DMA_TRANSFER_RELOAD || transferMode == DMA_TRANSFER_CONTIGUOUS){
value = AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CFG;
value &= ~ (AT91C_DST_REP);
// When automatic mode is activated, the source address and the control register are reloaded from previous transfer.
if(transferMode == DMA_TRANSFER_RELOAD) {
value |= AT91C_DST_REP;
}
AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CFG = value;
}
else {
AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CFG = 0;
}
}
//------------------------------------------------------------------------------
/// Set DMA configuration registe used by a HDMA channel.
/// \param channel Particular channel number.
/// \param value configuration value.
//------------------------------------------------------------------------------
void DMA_SetConfiguration(unsigned char channel, unsigned int value)
{
ASSERT(channel < DMA_CHANNEL_NUM, "this channel does not exist");
AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CFG = value;
}
//------------------------------------------------------------------------------
/// Set DMA source PIP configuration used by a HDMA channel.
/// \param channel Particular channel number.
/// \param pipHole stop on done mode.
/// \param pipBoundary lock mode.
//------------------------------------------------------------------------------
void DMA_SPIPconfiguration(unsigned char channel,
unsigned int pipHole,
unsigned int pipBoundary)
{
unsigned int value;
ASSERT(channel < DMA_CHANNEL_NUM, "this channel does not exist");
value = AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CTRLB;
value &= ~ (AT91C_SRC_PIP);
value |= AT91C_SRC_PIP;
AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CTRLB = value;
AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_SPIP = (pipHole + 1) | pipBoundary <<16;
}
//------------------------------------------------------------------------------
/// Set DMA destination PIP configuration used by a HDMA channel.
/// \param channel Particular channel number.
/// \param pipHole stop on done mode.
/// \param pipBoundary lock mode.
//------------------------------------------------------------------------------
void DMA_DPIPconfiguration(unsigned char channel,
unsigned int pipHole,
unsigned int pipBoundary)
{
unsigned int value;
ASSERT(channel < DMA_CHANNEL_NUM, "this channel does not exist");
value = AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CTRLB;
value &= ~ (AT91C_DST_PIP);
value |= AT91C_DST_PIP;
AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_CTRLB = value;
AT91C_BASE_HDMA->HDMA_CH[channel].HDMA_DPIP = (pipHole + 1) | pipBoundary <<16;
}

View file

@ -0,0 +1,171 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support - ROUSSET -
* ----------------------------------------------------------------------------
* Copyright (c) 2006, Atmel Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaiimer below.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the disclaimer below in the documentation and/or
* other materials provided with the distribution.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \dir
/// !Purpose
///
/// Interface for configuration the %DMA controller(DMAC).
///
/// !Usage
///
/// -# Enable or disable the a DMAC controller with
/// DMA_Enable() and or DMA_Disable().
/// -# Enable or disable %Dma interrupt using DMA_EnableIt()
/// or DMA_DisableIt().
/// -# Get %Dma interrupt status by DMA_GetStatus().
/// -# Enable or disable specified %Dma channel with
/// DMA_EnableChannel() or DMA_DisableChannel().
/// -# Get %Dma channel status by DMA_GetChannelStatus().
/// -# Configure source and/or destination start address with
/// DMA_SetSourceAddr() and/or DMA_SetDestAddr().
/// -# Set %Dma descriptor address using DMA_SetDescriptorAddr().
/// -# Set source transfer buffer size with DMA_SetSourceBufferSize().
/// -# Configure source and/or destination transfer mode with
/// DMA_SetSourceBufferMode() and/or DMA_SetDestBufferMode().
/// -# Configure source and/or destination Picture-In-Picutre
/// mode with DMA_SPIPconfiguration() and/or DMA_DPIPconfiguration().
//------------------------------------------------------------------------------
#ifndef DMA_H
#define DMA_H
#include <board.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
#define DMA_CHANNEL_0 0
#define DMA_CHANNEL_1 1
#define DMA_CHANNEL_2 2
#define DMA_CHANNEL_3 3
#define DMA_CHANNEL_4 4
#define DMA_CHANNEL_5 5
#define DMA_CHANNEL_6 6
#define DMA_CHANNEL_7 7
#if defined(CHIP_DMA_CHANNEL_NUM)
#define DMA_CHANNEL_NUM CHIP_DMA_CHANNEL_NUM
#endif
#define DMA_TRANSFER_SINGLE 0
#define DMA_TRANSFER_LLI 1
#define DMA_TRANSFER_RELOAD 2
#define DMA_TRANSFER_CONTIGUOUS 3
#define DMA_ENA (1 << 0)
#define DMA_DIS (1 << 0)
#define DMA_SUSP (1 << 8)
#define DMA_KEEPON (1 << 24)
#define DMA_BTC (1 << 0)
#define DMA_CBTC (1 << 8)
#define DMA_ERR (1 << 16)
#if defined(at91sam9m10) || defined(at91sam9m11) || defined(at91sam3u4)
#define AT91C_SRC_DSCR AT91C_HDMA_SRC_DSCR
#define AT91C_DST_DSCR AT91C_HDMA_DST_DSCR
#define AT91C_SRC_INCR AT91C_HDMA_SRC_ADDRESS_MODE
#define AT91C_DST_INCR AT91C_HDMA_DST_ADDRESS_MODE
#define AT91C_SRC_PER AT91C_HDMA_SRC_PER
#define AT91C_DST_PER AT91C_HDMA_DST_PER
#define AT91C_SRC_REP AT91C_HDMA_SRC_REP
#define AT91C_DST_REP AT91C_HDMA_DST_REP
#define AT91C_SRC_PIP AT91C_HDMA_SRC_PIP
#define AT91C_DST_PIP AT91C_HDMA_DST_PIP
#define AT91C_BTC (0xFF << 0)
#define AT91C_CBTC (0xFF << 8)
#define AT91C_ERR (0xFF << 16)
#endif
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void DMA_Config(unsigned int flag);
extern void DMA_Enable(void);
extern void DMA_Disable(void);
extern void DMA_EnableChannel(unsigned int channel);
extern void DMA_DisableChannel(unsigned int channel);
extern void DMA_KeeponChannel(unsigned int channel);
extern void DMA_ClearAutoMode(unsigned int channel);
extern unsigned int DMA_GetChannelStatus(void);
extern unsigned int DMA_GetStatus(void);
extern unsigned int DMA_GetInterruptMask(void);
extern unsigned int DMA_GetMaskedStatus(void);
extern void DMA_EnableIt (unsigned int flag);
extern void DMA_DisableIt (unsigned int flag);
extern void DMA_SetSourceAddr(unsigned char channel, unsigned int address);
extern void DMA_SetDestinationAddr(unsigned char channel, unsigned int address);
extern void DMA_SetDescriptorAddr(unsigned char channel, unsigned int address);
extern void DMA_SetSourceBufferSize(unsigned char channel,
unsigned int size,
unsigned char sourceWidth,
unsigned char desDMAdth,
unsigned char done);
extern void DMA_SetSourceBufferMode(unsigned char channel,
unsigned char transferMode,
unsigned char addressingType);
extern void DMA_SetDestBufferMode(unsigned char channel,
unsigned char transferMode,
unsigned char addressingType);
extern void DMA_SetConfiguration(unsigned char channel, unsigned int value);
extern void DMA_SPIPconfiguration(unsigned char channel,
unsigned int pipHole, unsigned int pipBoundary);
extern void DMA_DPIPconfiguration(unsigned char channel,
unsigned int pipHole, unsigned int pipBoundary);
#endif //#ifndef DMA_H

View file

@ -0,0 +1,274 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#include "eefc.h"
#if !defined (CHIP_FLASH_EEFC)
#error eefc not supported
#endif
#include <utility/assert.h>
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Enables the flash ready interrupt source on the EEFC peripheral.
/// \param pEfc Pointer to an AT91S_EFC structure.
//------------------------------------------------------------------------------
void EFC_EnableFrdyIt(AT91S_EFC *pEfc)
{
pEfc->EFC_FMR |= AT91C_EFC_FRDY;
}
//------------------------------------------------------------------------------
/// Disables the flash ready interrupt source on the EEFC peripheral.
/// \param pEfc Pointer to an AT91S_EFC structure.
//------------------------------------------------------------------------------
void EFC_DisableFrdyIt(AT91S_EFC *pEfc)
{
pEfc->EFC_FMR &= ~AT91C_EFC_FRDY;
}
//------------------------------------------------------------------------------
/// Translates the given address page and offset values. The resulting
/// values are stored in the provided variables if they are not null.
/// \param ppEfc Pointer to target EFC peripheral.
/// \param address Address to translate.
/// \param pPage First page accessed.
/// \param pOffset Byte offset in first page.
//------------------------------------------------------------------------------
void EFC_TranslateAddress(
AT91S_EFC **ppEfc,
unsigned int address,
unsigned short *pPage,
unsigned short *pOffset)
{
AT91S_EFC *pEfc;
unsigned short page;
unsigned short offset;
#if defined(AT91C_BASE_EFC1)
SANITY_CHECK(address >= AT91C_IFLASH);
if (address >= AT91C_IFLASH1) {
SANITY_CHECK(address <= (AT91C_IFLASH1 + AT91C_IFLASH1_SIZE));
}
else {
SANITY_CHECK(address <= (AT91C_IFLASH + AT91C_IFLASH_SIZE));
}
#else
SANITY_CHECK(address >= AT91C_IFLASH);
SANITY_CHECK(address <= (AT91C_IFLASH + AT91C_IFLASH_SIZE));
#endif
pEfc = AT91C_BASE_EFC;
page = (address - AT91C_IFLASH) / AT91C_IFLASH_PAGE_SIZE;
offset = (address - AT91C_IFLASH) % AT91C_IFLASH_PAGE_SIZE;
#if defined(AT91C_BASE_EFC1)
if (address >= AT91C_IFLASH1) {
pEfc = AT91C_BASE_EFC1;
page = (address - AT91C_IFLASH1) / AT91C_IFLASH1_PAGE_SIZE;
offset = (address - AT91C_IFLASH1) % AT91C_IFLASH1_PAGE_SIZE;
}
#endif
TRACE_DEBUG("Translated 0x%08X to page=%d and offset=%d\n\r",
address, page, offset);
// Store values
if (ppEfc) {
*ppEfc = pEfc;
}
if (pPage) {
*pPage = page;
}
if (pOffset) {
*pOffset = offset;
}
}
//------------------------------------------------------------------------------
/// Computes the address of a flash access given the page and offset.
/// \param pEfc Pointer to an AT91S_EFC structure.
/// \param page Page number.
/// \param offset Byte offset inside page.
/// \param pAddress Computed address (optional).
//------------------------------------------------------------------------------
void EFC_ComputeAddress(
AT91S_EFC *pEfc,
unsigned short page,
unsigned short offset,
unsigned int *pAddress)
{
unsigned int address;
SANITY_CHECK(pEfc);
SANITY_CHECK(page <= AT91C_IFLASH_NB_OF_PAGES);
SANITY_CHECK(offset < AT91C_IFLASH_PAGE_SIZE);
// Compute address
address = AT91C_IFLASH + page * AT91C_IFLASH_PAGE_SIZE + offset;
#if defined(AT91C_BASE_EFC1)
if (pEfc == AT91C_BASE_EFC1) {
address = AT91C_IFLASH1 + page * AT91C_IFLASH1_PAGE_SIZE + offset;
}
#endif
// Store result
if (pAddress) {
*pAddress = address;
}
}
//------------------------------------------------------------------------------
/// Starts the executing the given command on the EEFC. This function returns
/// as soon as the command is started. It does NOT set the FMCN field automatically.
/// \param pEfc Pointer to an AT91S_EFC structure.
/// \param command Command to execute.
/// \param argument Command argument (should be 0 if not used).
//------------------------------------------------------------------------------
#if defined(flash) || defined (USE_FLASH)
#ifdef __ICCARM__
__ramfunc
#else
__attribute__ ((section (".ramfunc")))
#endif
#endif
void EFC_StartCommand(AT91S_EFC *pEfc, unsigned char command, unsigned short argument)
{
// Check command & argument
switch (command) {
case AT91C_EFC_FCMD_WP:
case AT91C_EFC_FCMD_WPL:
case AT91C_EFC_FCMD_EWP:
case AT91C_EFC_FCMD_EWPL:
case AT91C_EFC_FCMD_EPL:
case AT91C_EFC_FCMD_EPA:
case AT91C_EFC_FCMD_SLB:
case AT91C_EFC_FCMD_CLB:
ASSERT(argument < AT91C_IFLASH_NB_OF_PAGES,
"-F- Embedded flash has only %d pages\n\r",
AT91C_IFLASH_NB_OF_PAGES);
break;
case AT91C_EFC_FCMD_SFB:
case AT91C_EFC_FCMD_CFB:
ASSERT(argument < CHIP_EFC_NUM_GPNVMS, "-F- Embedded flash has only %d GPNVMs\n\r", CHIP_EFC_NUM_GPNVMS);
break;
case AT91C_EFC_FCMD_GETD:
case AT91C_EFC_FCMD_EA:
case AT91C_EFC_FCMD_GLB:
case AT91C_EFC_FCMD_GFB:
#ifdef AT91C_EFC_FCMD_STUI
case AT91C_EFC_FCMD_STUI:
#endif
ASSERT(argument == 0, "-F- Argument is meaningless for the given command.\n\r");
break;
default: ASSERT(0, "-F- Unknown command %d\n\r", command);
}
// Start commandEmbedded flash
ASSERT((pEfc->EFC_FSR & AT91C_EFC_FRDY) == AT91C_EFC_FRDY, "-F- EEFC is not ready\n\r");
pEfc->EFC_FCR = (0x5A << 24) | (argument << 8) | command;
}
//------------------------------------------------------------------------------
/// Performs the given command and wait until its completion (or an error).
/// Returns 0 if successful; otherwise returns an error code.
/// \param pEfc Pointer to an AT91S_EFC structure.
/// \param command Command to perform.
/// \param argument Optional command argument.
//------------------------------------------------------------------------------
#if defined(flash) || defined (USE_FLASH)
#ifdef __ICCARM__
__ramfunc
#else
__attribute__ ((section (".ramfunc")))
#endif
#endif
unsigned char EFC_PerformCommand(AT91S_EFC *pEfc, unsigned char command, unsigned short argument)
{
unsigned int status;
#ifdef CHIP_FLASH_IAP_ADDRESS
// Pointer on IAP function in ROM
static void (*IAP_PerformCommand)(unsigned int);
IAP_PerformCommand = (void (*)(unsigned int)) *((unsigned int *) CHIP_FLASH_IAP_ADDRESS);
// Check if IAP function is implemented (opcode in SWI != 'b' or 'ldr') */
if ((((((unsigned long) IAP_PerformCommand >> 24) & 0xFF) != 0xEA) &&
(((unsigned long) IAP_PerformCommand >> 24) & 0xFF) != 0xE5)) {
IAP_PerformCommand((0x5A << 24) | (argument << 8) | command);
return (pEfc->EFC_FSR & (AT91C_EFC_LOCKE | AT91C_EFC_FCMDE));
}
#endif
pEfc->EFC_FCR = (0x5A << 24) | (argument << 8) | command;
do {
status = pEfc->EFC_FSR;
}
while ((status & AT91C_EFC_FRDY) != AT91C_EFC_FRDY);
return (status & (AT91C_EFC_LOCKE | AT91C_EFC_FCMDE));
}
//------------------------------------------------------------------------------
/// Returns the current status of the EEFC. Keep in mind that this function clears
/// the value of some status bits (LOCKE, PROGE).
/// \param pEfc Pointer to an AT91S_EFC structure.
//------------------------------------------------------------------------------
unsigned int EFC_GetStatus(AT91S_EFC *pEfc)
{
return pEfc->EFC_FSR;
}
//------------------------------------------------------------------------------
/// Returns the result of the last executed command.
/// \param pEfc Pointer to an AT91S_EFC structure.
//------------------------------------------------------------------------------
unsigned int EFC_GetResult(AT91S_EFC *pEfc) {
return pEfc->EFC_FRR;
}

View file

@ -0,0 +1,147 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2009, 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 Enhanced Embedded Flash Controller (EEFC)
/// peripheral.
///
/// !Usage
///
/// -# Enable/disable %flash ready interrupt sources using EFC_EnableFrdyIt()
/// and EFC_DisableFrdyIt().
/// -# Translates the given address into which EEFC, page and offset values
/// for difference density %flash memory using EFC_TranslateAddress().
/// -# Computes the address of a %flash access given the EFC, page and offset
/// for difference density %flash memory using EFC_ComputeAddress().
/// -# Start the executing command with EFC_StartCommand()
/// -# Retrieve the current status of the EFC using EFC_GetStatus().
/// -# Retrieve the result of the last executed command with EFC_GetResult().
//------------------------------------------------------------------------------
#ifndef EEFC_H
#define EEFC_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#if !defined (CHIP_FLASH_EEFC)
#error eefc not supported
#endif
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
// Needed when EEFC is integrated in MC.
#if !defined(AT91C_BASE_EFC) && defined(AT91C_BASE_MC)
typedef struct _AT91S_EFC {
AT91_REG EFC_FMR; // EFC Flash Mode Register
AT91_REG EFC_FCR; // EFC Flash Command Register
AT91_REG EFC_FSR; // EFC Flash Status Register
AT91_REG EFC_FRR; // EFC Flash Result Register
AT91_REG EFC_FVR; // EFC Flash Version Register
} AT91S_EFC, *AT91PS_EFC;
#define AT91C_EFC_FRDY AT91C_MC_FRDY
#define AT91C_EFC_FWS AT91C_MC_FWS
#define AT91C_EFC_FWS_0WS AT91C_MC_FWS_0WS
#define AT91C_EFC_FWS_1WS AT91C_MC_FWS_1WS
#define AT91C_EFC_FWS_2WS AT91C_MC_FWS_2WS
#define AT91C_EFC_FWS_3WS AT91C_MC_FWS_3WS
#define AT91C_EFC_FCMD AT91C_MC_FCMD
#define AT91C_EFC_FCMD_GETD AT91C_MC_FCMD_GETD
#define AT91C_EFC_FCMD_WP AT91C_MC_FCMD_WP
#define AT91C_EFC_FCMD_WPL AT91C_MC_FCMD_WPL
#define AT91C_EFC_FCMD_EWP AT91C_MC_FCMD_EWP
#define AT91C_EFC_FCMD_EWPL AT91C_MC_FCMD_EWPL
#define AT91C_EFC_FCMD_EA AT91C_MC_FCMD_EA
#define AT91C_EFC_FCMD_EPL AT91C_MC_FCMD_EPL
#define AT91C_EFC_FCMD_EPA AT91C_MC_FCMD_EPA
#define AT91C_EFC_FCMD_SLB AT91C_MC_FCMD_SLB
#define AT91C_EFC_FCMD_CLB AT91C_MC_FCMD_CLB
#define AT91C_EFC_FCMD_GLB AT91C_MC_FCMD_GLB
#define AT91C_EFC_FCMD_SFB AT91C_MC_FCMD_SFB
#define AT91C_EFC_FCMD_CFB AT91C_MC_FCMD_CFB
#define AT91C_EFC_FCMD_GFB AT91C_MC_FCMD_GFB
#define AT91C_EFC_FARG AT91C_MC_FARG
#define AT91C_EFC_FKEY AT91C_MC_FKEY
#define AT91C_EFC_FRDY_S AT91C_MC_FRDY_S
#define AT91C_EFC_FCMDE AT91C_MC_FCMDE
#define AT91C_EFC_LOCKE AT91C_MC_LOCKE
#define AT91C_EFC_FVALUE AT91C_MC_FVALUE
#define AT91C_BASE_EFC (AT91_CAST(AT91PS_EFC) 0xFFFFFF60)
#endif //#if !defined(AT91C_BASE_EFC) && defined(AT91C_BASE_MC)
//------------------------------------------------------------------------------
// Functions
//------------------------------------------------------------------------------
extern void EFC_EnableFrdyIt(AT91S_EFC *pEfc);
extern void EFC_DisableFrdyIt(AT91S_EFC *pEfc);
extern void EFC_TranslateAddress(
AT91S_EFC **ppEfc,
unsigned int address,
unsigned short *pPage,
unsigned short *pOffset);
extern void EFC_ComputeAddress(
AT91S_EFC *pEfc,
unsigned short page,
unsigned short offset,
unsigned int *pAddress);
extern void EFC_StartCommand(
AT91S_EFC *pEfc,
unsigned char command,
unsigned short argument);
extern unsigned char EFC_PerformCommand(
AT91S_EFC *pEfc,
unsigned char command,
unsigned short argument);
extern unsigned int EFC_GetStatus(AT91S_EFC *pEfc);
extern unsigned int EFC_GetResult(AT91S_EFC *pEfc);
#endif //#ifndef EEFC_H

View file

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

View file

@ -0,0 +1,147 @@
/* ----------------------------------------------------------------------------
* 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 Embedded Flash Controller (EFC) peripheral.
///
/// !Usage
///
/// -# Initialize system master clock of the EFC with EFC_SetMasterClock().
/// -# Enable/disable interrupt sources using EFC_EnableIt() and EFC_DisableIt().
/// -# Enables or disable the "Erase before programming" feature using
/// EFC_SetEraseBeforeProgramming().
/// -# Translates the given address into which EFC, page and offset values for
/// difference density %flash memory using EFC_TranslateAddress().
/// -# Computes the address of a %flash access given the EFC, page and offset
/// for difference density %flash memory using EFC_ComputeAddress().
/// -# Start the executing command with EFC_StartCommand()
/// -# Retrieve the current status of the EFC using EFC_GetStatus().
///
//------------------------------------------------------------------------------
#ifndef EFC_H
#define EFC_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#ifdef BOARD_FLASH_EFC
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
/// Number of GPNVMs available on each chip.
#if defined(at91sam7s16) || defined(at91sam7s161) || defined(at91sam7s32) \
|| defined(at91sam7s321) || defined(at91sam7s64) || defined(at91sam7s128) \
|| defined(at91sam7s256) || defined(at91sam7s512)
#define EFC_NUM_GPNVMS 2
#elif defined(at91sam7se32) || defined(at91sam7se256) || defined(at91sam7se512) \
|| defined(at91sam7x128) || defined(at91sam7x256) || defined(at91sam7x512) \
|| defined(at91sam7xc128) || defined(at91sam7xc256) || defined(at91sam7xc512) \
#define EFC_NUM_GPNVMS 3
#elif defined(at91sam7a3)
#define EFC_NUM_GPNVMS 0
#endif
// Missing FRDY bit for SAM7A3
#if defined(at91sam7a3)
#define AT91C_MC_FRDY (AT91C_MC_EOP | AT91C_MC_EOL)
#endif
// No security bit on SAM7A3
#if defined(at91sam7a3)
#define EFC_NO_SECURITY_BIT
#endif
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
// For chips which do not define AT91S_EFC
#if !defined(AT91C_BASE_EFC) && !defined(AT91C_BASE_EFC0)
typedef struct _AT91S_EFC {
AT91_REG EFC_FMR;
AT91_REG EFC_FCR;
AT91_REG EFC_FSR;
} AT91S_EFC, *AT91PS_EFC;
#define AT91C_BASE_EFC (AT91_CAST(AT91PS_EFC) 0xFFFFFF60)
#endif
//------------------------------------------------------------------------------
// Functions
//------------------------------------------------------------------------------
extern void EFC_SetMasterClock(unsigned int mck);
extern void EFC_EnableIt(AT91S_EFC *pEfc, unsigned int sources);
extern void EFC_DisableIt(AT91S_EFC *pEfc, unsigned int sources);
extern void EFC_SetEraseBeforeProgramming(AT91S_EFC *pEfc, unsigned char enable);
extern void EFC_TranslateAddress(
unsigned int address,
AT91S_EFC **ppEfc,
unsigned short *pPage,
unsigned short *pOffset);
extern void EFC_ComputeAddress(
AT91S_EFC *pEfc,
unsigned short page,
unsigned short offset,
unsigned int *pAddress);
extern void EFC_StartCommand(
AT91S_EFC *pEfc,
unsigned char command,
unsigned short argument);
extern unsigned char EFC_PerformCommand(
AT91S_EFC *pEfc,
unsigned char command,
unsigned short argument);
extern unsigned int EFC_GetStatus(AT91S_EFC *pEfc);
#endif //#ifdef BOARD_FLASH_EFC
#endif //#ifndef EFC_H

View file

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

View file

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

View file

@ -0,0 +1,82 @@
/* ----------------------------------------------------------------------------
* 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.
///
/// !Usage
///
/// -# Configure an interrupt source using IRQ_ConfigureIT
/// -# Enable or disable interrupt generation of a particular source with
/// IRQ_EnableIT and IRQ_DisableIT.
///
/// \note Most of the time, peripheral interrupts must be also configured
/// inside the peripheral itself.
//------------------------------------------------------------------------------
#ifndef IRQ_H
#define IRQ_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#if defined(cortexm3)
#include <cmsis/core_cm3.h>
#endif
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
#if defined(cortexm3)
#ifdef __NVIC_PRIO_BITS
#undef __NVIC_PRIO_BITS
#define __NVIC_PRIO_BITS ((SCB->AIRCR & 0x700) >> 8)
#endif
#endif
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void IRQ_ConfigureIT(unsigned int source,
unsigned int mode, // mode for AIC, priority for NVIC
void( *handler )( void )); // ISR
extern void IRQ_EnableIT(unsigned int source);
extern void IRQ_DisableIT(unsigned int source);
#endif //#ifndef IRQ_H

View file

@ -0,0 +1,144 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "board.h"
#include "irq.h"
#include "exceptions.h"
#include <utility/trace.h>
/// The index of IRQ handler in the exception table
#define NVIC_IRQ_HANDLER_INDEX 16
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures an interrupt in the NVIC. The interrupt is identified by its
/// source (AT91C_ID_xxx) and is configured to a specified priority and
/// interrupt handler function. priority is the value that will be put in NVIC_IPRx
/// and the function address will be set in "ExceptionTable". The parameter priority
/// will include the preemptionPriority and the subPriority, where the subPriority
/// defined in the B[7:0] of the parameter "priority", and the preemptionPriority defined
/// in the B[15:8] of the parameter "priority".
/// The interrupt is disabled before configuration, so it is useless
/// to do it before calling this function. When NVIC_ConfigureIT returns, the
/// interrupt will always be disabled and cleared; it must be enabled by a
/// call to NVIC_EnableIT().
/// \param source Interrupt source to configure.
/// \param priority Pre-emption priority (B[15:8] )+ subPriority (B[7:0])
/// \param handler Interrupt handler function.
//------------------------------------------------------------------------------
void IRQ_ConfigureIT(
unsigned int source,
//unsigned int preemptionPriority,
//unsigned int subPriority,
unsigned int priority,
IntFunc handler)
{
unsigned int priGroup = __NVIC_PRIO_BITS;
unsigned int nPre = 7 - priGroup;
unsigned int nSub = priGroup + 1;
unsigned int preemptionPriority;
unsigned int subPriority;
unsigned int IRQpriority;
preemptionPriority = (priority & 0xff00) >> 8;
subPriority = (priority & 0xff);
// Disable the interrupt first
NVIC_DisableIRQ((IRQn_Type)source);
// Clear any pending status
NVIC_ClearPendingIRQ((IRQn_Type)source);
// Configure interrupt handler
//if (handler == 0) handler = IrqHandlerNotUsed;
// GetExceptionTable()[NVIC_IRQ_HANDLER_INDEX + source] = handler;
if (subPriority >= (0x01 << nSub))
subPriority = (0x01 << nSub) - 1;
if (preemptionPriority >= (0x01 << nPre))
preemptionPriority = (0x01 << nPre) - 1;
IRQpriority = (subPriority | (preemptionPriority << nSub));
NVIC_SetPriority((IRQn_Type)source, IRQpriority);
}
//------------------------------------------------------------------------------
/// Enables interrupt coming from the given (unique) source (AT91C_ID_xxx).
/// \param source Interrupt source to enable.
//------------------------------------------------------------------------------
void IRQ_EnableIT(unsigned int source)
{
NVIC_EnableIRQ((IRQn_Type)source);
}
//------------------------------------------------------------------------------
/// Disables interrupt coming from the given (unique) source (AT91C_ID_xxx).
/// \param source Interrupt source to disable.
//------------------------------------------------------------------------------
void IRQ_DisableIT(unsigned int source)
{
NVIC_DisableIRQ((IRQn_Type)source);
}
//------------------------------------------------------------------------------
/// Set interrupt pending bit from the given (unique) source (AT91C_ID_xxx).
/// \param source Interrupt source to set.
//------------------------------------------------------------------------------
void NVIC_SetPending(unsigned int source)
{
NVIC_SetPendingIRQ((IRQn_Type)source);
}
//------------------------------------------------------------------------------
/// Clear interrupt pending bit from the given (unique) source (AT91C_ID_xxx).
/// \param source Interrupt source to clear.
//------------------------------------------------------------------------------
void NVIC_ClrPending(unsigned int source)
{
NVIC_ClearPendingIRQ((IRQn_Type)source);
}
#if !defined(USE_CMSIS_on)
//------------------------------------------------------------------------------
/// Use the Software Trigger Interrupt Register to pend an interrupt.
/// \param source Interrupt source to trigger.
//------------------------------------------------------------------------------
void NVIC_Swi(unsigned int source)
{
AT91C_BASE_NVIC->NVIC_STIR = source;
}
#endif

View file

@ -0,0 +1,261 @@
/* ----------------------------------------------------------------------------
* 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
///
/// Image Sensor Interface (ISI) driver
///
/// !Usage
///
/// Explanation on the usage of the code made available through the header file.
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#include <utility/trace.h>
#include <utility/video.h>
#include "isi.h"
#if !defined (BOARD_ISI_V200)
//-----------------------------------------------------------------------------
/// Enable ISI
//-----------------------------------------------------------------------------
void ISI_Enable(void)
{
AT91C_BASE_ISI->ISI_CR1 &= ~AT91C_ISI_DIS;
}
//-----------------------------------------------------------------------------
/// Disable ISI
//-----------------------------------------------------------------------------
void ISI_Disable(void)
{
AT91C_BASE_ISI->ISI_CR1 |= AT91C_ISI_DIS;
}
//-----------------------------------------------------------------------------
/// Enable ISI interrupt
/// \param flag of interrupt to enable
//-----------------------------------------------------------------------------
void ISI_EnableInterrupt(unsigned int flag)
{
AT91C_BASE_ISI->ISI_IER = flag;
}
//-----------------------------------------------------------------------------
/// Disable ISI interrupt
/// \param flag of interrupt to disable
//-----------------------------------------------------------------------------
void ISI_DisableInterrupt(unsigned int flag)
{
AT91C_BASE_ISI->ISI_IDR = flag;
}
//-----------------------------------------------------------------------------
/// Return ISI status register
/// \return Status of ISI register
//-----------------------------------------------------------------------------
unsigned int ISI_StatusRegister(void)
{
return(AT91C_BASE_ISI->ISI_SR);
}
//-----------------------------------------------------------------------------
/// Enable Codec path for capture next frame
//-----------------------------------------------------------------------------
void ISI_CodecPathFull(void)
{
// The codec path is enabled and the next frame is captured.
// Both codec and preview datapaths are working simultaneously
AT91C_BASE_ISI->ISI_CR1 |= AT91C_ISI_CODEC_ON | AT91C_ISI_FULL;
}
//-----------------------------------------------------------------------------
/// Set frame rate
/// \param frate frame rate capture
/// \return
//-----------------------------------------------------------------------------
void ISI_SetFrame(unsigned int frate)
{
if( frate > 7 ) {
TRACE_ERROR("FRate too big\n\r");
frate = 7;
}
AT91C_BASE_ISI->ISI_CR1 |= ((frate<<8) & AT91C_ISI_FRATE);
}
//-----------------------------------------------------------------------------
/// Get the number of byte per pixels
/// \param bmpRgb BMP type can be YUV or RGB
/// \return Number of byte for one pixel
//-----------------------------------------------------------------------------
unsigned char ISI_BytesForOnePixel(unsigned char bmpRgb)
{
unsigned char nbByte_Pixel;
if (bmpRgb == RGB) {
if ((AT91C_BASE_ISI->ISI_CR2 & AT91C_ISI_RGB_MODE) == AT91C_ISI_RGB_MODE_RGB_565){
// RGB: 5:6:5 16bits/pixels
nbByte_Pixel = 2;
}
else {
// RGB: 8:8:8 24bits/pixels
nbByte_Pixel = 3;
}
}
else {
// YUV: 2 pixels for 4 bytes
nbByte_Pixel = 2;
}
return nbByte_Pixel;
}
//-----------------------------------------------------------------------------
/// Reset ISI
//-----------------------------------------------------------------------------
void ISI_Reset(void)
{
unsigned int timeout=0;
// Resets the image sensor interface.
// Finish capturing the current frame and then shut down the module.
AT91C_BASE_ISI->ISI_CR1 = AT91C_ISI_RST | AT91C_ISI_DIS;
// wait Software reset has completed successfully.
while( (!(volatile int)AT91C_BASE_ISI->ISI_SR & AT91C_ISI_SOFTRST)
&& (timeout < 0x5000) ){
timeout++;
}
if( timeout == 0x5000 ) {
TRACE_ERROR("ISI-Reset timeout\n\r");
}
}
//-----------------------------------------------------------------------------
/// ISI initialize with the pVideo parameters.
/// By default, put ISI in RGB mode 565, YCC mode 3, different value for
/// Color Space Conversion Matrix Coefficient
/// \param pVideo structure of video driver
//-----------------------------------------------------------------------------
void ISI_Init(AT91PS_VIDEO pVideo)
{
ISI_Reset();
// AT91C_ISI_HSYNC_POL Horizontal synchronisation polarity
// AT91C_ISI_VSYNC_POL Vertical synchronisation polarity
// AT91C_ISI_PIXCLK_POL Pixel Clock Polarity
// SLD pixel clock periods to wait before the beginning of a line.
// SFD lines are skipped at the beginning of the frame.
AT91C_BASE_ISI->ISI_CR1 |= ((pVideo->Hblank << 16) & AT91C_ISI_SLD)
+ ((pVideo->Vblank << 24) & AT91C_ISI_SFD);
TRACE_DEBUG("ISI_CR1=0x%X\n\r", AT91C_BASE_ISI->ISI_CR1);
// IM_VSIZE: Vertical size of the Image sensor [0..2047]
// Vertical size = IM_VSIZE + 1
// IM_HSIZE: Horizontal size of the Image sensor [0..2047]
// Horizontal size = IM_HSIZE + 1
// YCC_SWAP : YCC image data
AT91C_BASE_ISI->ISI_CR2 = ((pVideo->codec_vsize-1) & AT91C_ISI_IM_VSIZE)
+ (((pVideo->codec_hsize-1) << 16) & AT91C_ISI_IM_HSIZE)
+ AT91C_ISI_YCC_SWAP_YCC_MODE2;
if (pVideo->rgb_or_yuv == RGB) {
AT91C_BASE_ISI->ISI_CR2 |= AT91C_ISI_COL_SPACE | AT91C_ISI_RGB_MODE_RGB_565
| AT91C_ISI_RGB_CFG_RGB_DEFAULT;
}
else {
// AT91C_BASE_HISI->ISI_CR2 &= ~AT91C_ISI_COL_SPACE;
}
TRACE_DEBUG("ISI_CR2=0x%X\n\r", AT91C_BASE_ISI->ISI_CR2);
// Vertical Preview size = PREV_VSIZE + 1 (480 max only in RGB mode).
// Horizontal Preview size = PREV_HSIZE + 1 (640 max only in RGB mode).
#if defined (AT91C_ID_LCDC)
if( (pVideo->lcd_vsize > 480) || (pVideo->lcd_hsize > 640)) {
TRACE_ERROR("Size LCD bad define\n\r");
AT91C_BASE_ISI->ISI_PSIZE = ((BOARD_LCD_HEIGHT-1) & AT91C_ISI_PREV_VSIZE)
+ (((BOARD_LCD_WIDTH-1) << 16) & AT91C_ISI_PREV_HSIZE);
}
else {
AT91C_BASE_ISI->ISI_PSIZE = ((pVideo->lcd_vsize -1) & AT91C_ISI_PREV_VSIZE)
+ (((pVideo->lcd_hsize -1) << 16) & AT91C_ISI_PREV_HSIZE);
}
#endif
// DEC_FACTOR is 8-bit width, range is from 16 to 255.
// Values from 0 to 16 do not perform any decimation.
AT91C_BASE_ISI->ISI_PDECF = (16 * pVideo->codec_hsize) / pVideo->lcd_hsize;
TRACE_DEBUG("codec_hsize: %d\n\r", pVideo->codec_hsize);
TRACE_DEBUG("lcd_hsize: %d\n\r", pVideo->lcd_hsize);
TRACE_DEBUG("ISI_PDECF: %d\n\r", AT91C_BASE_ISI->ISI_PDECF);
if( AT91C_BASE_ISI->ISI_PDECF <16) {
TRACE_ERROR("ISI_PDECF, forbidden value: %d\n\r", AT91C_BASE_ISI->ISI_PDECF);
AT91C_BASE_ISI->ISI_PDECF = 16;
}
// Written with the address of the start of the preview frame buffer queue,
// reads as a pointer to the current buffer being used.
// The frame buffer is forced to word alignment.
AT91C_BASE_ISI->ISI_PPFBD = pVideo->Isi_fbd_base;
// This register contains codec datapath start address of buffer location.
// CODEC_DMA_ADDR: Base address for codec DMA
AT91C_BASE_ISI->ISI_CDBA = pVideo->codec_fb_addr;
// C0: Color Space Conversion Matrix Coefficient C0
// C1: Color Space Conversion Matrix Coefficient C1
// C2: Color Space Conversion Matrix Coefficient C2
// C3: Color Space Conversion Matrix Coefficient C3
AT91C_BASE_ISI->ISI_Y2RSET0 = ( (0x95<< 0) & AT91C_ISI_Y2R_C0)
+ ( (0xFF<< 8) & AT91C_ISI_Y2R_C1)
+ ( (0x68<<16) & AT91C_ISI_Y2R_C2)
+ ( (0x32<<24) & AT91C_ISI_Y2R_C3);
// C4: Color Space Conversion Matrix coefficient C4
// Yoff: Color Space Conversion Luminance 128 offset
// Croff: Color Space Conversion Red Chrominance 16 offset
// Cboff: Color Space Conversion Blue Chrominance 16 offset
AT91C_BASE_ISI->ISI_Y2RSET1 = ( (0xCC<< 0) & AT91C_ISI_Y2R_C4)
+ ( AT91C_ISI_Y2R_YOFF_128)
+ ( AT91C_ISI_Y2R_CROFF_16)
+ ( AT91C_ISI_Y2R_CBOFF_16);
}
#endif // !defined (BOARD_ISI_V200)

View file

@ -0,0 +1,99 @@
/* ----------------------------------------------------------------------------
* 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 Image Sensor Interface (ISI) peripheral.
///
/// !Usage
///
/// -# ISI_Init: initialize ISI with default parameters
/// -# ISI_EnableInterrupt: enable one or more interrupts
/// -# ISI_DisableInterrupt: disable one or more interrupts
/// -# ISI_Enable: enable isi module
/// -# ISI_Disable: disable isi module
/// -# ISI_CodecPathFull: enable codec path
/// -# ISI_SetFrame: set frame rate
/// -# ISI_BytesForOnePixel: return number of byte for one pixel
/// -# ISI_StatusRegister: return ISI status register
/// -# ISI_Reset: make a software reset
//------------------------------------------------------------------------------
#ifndef ISI_H
#define ISI_H
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
/// ISI descriptors
typedef struct
{
/// Current LCD index, used with AT91C_ISI_MAX_PREV_BUFFER
unsigned int CurrentLcdIndex;
/// set if Fifo Codec Empty is present
volatile unsigned int DisplayCodec;
/// upgrade for each Fifo Codec Overflow (statistics use)
unsigned int nb_codec_ovf;
/// upgrade for each Fifo Preview Overflow (statistics use)
unsigned int nb_prev_ovf;
}ISI_Descriptors;
/// Frame Buffer Descriptors
typedef struct
{
/// Address of the Current FrameBuffer
unsigned int Current;
#if defined (BOARD_ISI_V200)
/// Address of the Control
unsigned int Control;
#endif
/// Address of the Next FrameBuffer
unsigned int Next;
}ISI_FrameBufferDescriptors;
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void ISI_Enable(void);
extern void ISI_Disable(void);
extern void ISI_EnableInterrupt(unsigned int flag);
extern void ISI_DisableInterrupt(unsigned int flag);
extern void ISI_CodecPathFull(void);
extern void ISI_SetFrame(unsigned int frate);
extern unsigned char ISI_BytesForOnePixel(unsigned char bmpRgb);
extern void ISI_Reset(void);
extern void ISI_Init(AT91PS_VIDEO pVideo);
extern unsigned int ISI_StatusRegister(void);
#endif //#ifndef ISI_H

View file

@ -0,0 +1,246 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#include <utility/trace.h>
#include <utility/video.h>
#include "isi.h"
#if defined (BOARD_ISI_V200)
//-----------------------------------------------------------------------------
/// Enable ISI
//-----------------------------------------------------------------------------
void ISI_Enable(void)
{
AT91C_BASE_ISI->ISI_CTRL |= AT91C_ISI_EN_1;
while( (AT91C_BASE_ISI->ISI_SR & AT91C_ISI_EN_1)!=AT91C_ISI_EN_1);
AT91C_BASE_ISI->ISI_DMACHER |= AT91C_ISI_P_CH_EN_1;
}
//-----------------------------------------------------------------------------
/// Disable ISI
//-----------------------------------------------------------------------------
void ISI_Disable(void)
{
AT91C_BASE_ISI->ISI_CTRL |= AT91C_ISI_DIS_1;
AT91C_BASE_ISI->ISI_DMACHDR &= ~AT91C_ISI_P_CH_DIS_1;
}
//-----------------------------------------------------------------------------
/// Enable ISI interrupt
/// \param flag of interrupt to enable
//-----------------------------------------------------------------------------
void ISI_EnableInterrupt(unsigned int flag)
{
AT91C_BASE_ISI->ISI_IER = flag;
}
//-----------------------------------------------------------------------------
/// Disable ISI interrupt
/// \param flag of interrupt to disable
//-----------------------------------------------------------------------------
void ISI_DisableInterrupt(unsigned int flag)
{
AT91C_BASE_ISI->ISI_IDR = flag;
}
//-----------------------------------------------------------------------------
/// Return ISI status register
/// \return Status of ISI register
//-----------------------------------------------------------------------------
unsigned int ISI_StatusRegister(void)
{
return(AT91C_BASE_ISI->ISI_SR);
}
//-----------------------------------------------------------------------------
/// Enable Codec path for capture next frame
//-----------------------------------------------------------------------------
void ISI_CodecPathFull(void)
{
// The codec path is enabled and the next frame is captured.
// Both codec and preview datapaths are working simultaneously
AT91C_BASE_ISI->ISI_CTRL |= AT91C_ISI_CDC_1;
AT91C_BASE_ISI->ISI_CFG1 |= AT91C_ISI_FULL;
}
//-----------------------------------------------------------------------------
/// Set frame rate
/// \param frate frame rate capture
/// \return
//-----------------------------------------------------------------------------
void ISI_SetFrame(unsigned int frate)
{
if( frate > 7 ) {
TRACE_ERROR("FRate too big\n\r");
frate = 7;
}
AT91C_BASE_ISI->ISI_CFG1 |= ((frate<<8) & AT91C_ISI_FRATE);
}
//-----------------------------------------------------------------------------
/// Get the number of byte per pixels
/// \param bmpRgb BMP type can be YUV or RGB
/// \return Number of byte for one pixel
//-----------------------------------------------------------------------------
unsigned char ISI_BytesForOnePixel(unsigned char bmpRgb)
{
unsigned char nbByte_Pixel;
if (bmpRgb == RGB) {
if ((AT91C_BASE_ISI->ISI_CFG2 & AT91C_ISI_RGB_MODE) == AT91C_ISI_RGB_MODE_RGB_565){
// RGB: 5:6:5 16bits/pixels
nbByte_Pixel = 2;
}
else {
// RGB: 8:8:8 24bits/pixels
nbByte_Pixel = 3;
}
}
else {
// YUV: 2 pixels for 4 bytes
nbByte_Pixel = 2;
}
return nbByte_Pixel;
}
//-----------------------------------------------------------------------------
/// Reset ISI
//-----------------------------------------------------------------------------
void ISI_Reset(void)
{
unsigned int timeout=0;
// Resets the image sensor interface.
// Finish capturing the current frame and then shut down the module.
AT91C_BASE_ISI->ISI_CTRL = AT91C_ISI_SRST_1 | AT91C_ISI_DIS_1;
// wait Software reset has completed successfully.
while( (!(volatile int)AT91C_BASE_ISI->ISI_SR & AT91C_ISI_SRST)
&& (timeout < 0x5000) ){
timeout++;
}
if( timeout == 0x5000 ) {
TRACE_ERROR("ISI-Reset timeout\n\r");
}
}
//-----------------------------------------------------------------------------
/// ISI initialize
/// \param pVideo structure of video driver
//-----------------------------------------------------------------------------
void ISI_Init(AT91PS_VIDEO pVideo)
{
ISI_Reset();
// AT91C_ISI_HSYNC_POL Horizontal synchronisation polarity
// AT91C_ISI_VSYNC_POL Vertical synchronisation polarity
// AT91C_ISI_PIXCLK_POL Pixel Clock Polarity
// SLD pixel clock periods to wait before the beginning of a line.
// SFD lines are skipped at the beginning of the frame.
AT91C_BASE_ISI->ISI_CFG1 |= ((pVideo->Hblank << 16) & AT91C_ISI_SLD)
+ ((pVideo->Vblank << 24) & AT91C_ISI_SFD);
TRACE_DEBUG("ISI_CFG1=0x%X\n\r", AT91C_BASE_ISI->ISI_CFG1);
// IM_VSIZE: Vertical size of the Image sensor [0..2047]
// Vertical size = IM_VSIZE + 1
// IM_HSIZE: Horizontal size of the Image sensor [0..2047]
// Horizontal size = IM_HSIZE + 1
// YCC_SWAP : YCC image data
AT91C_BASE_ISI->ISI_CFG2 = ((pVideo->codec_vsize-1) & AT91C_ISI_IM_VSIZE)
+ (((pVideo->codec_hsize-1) << 16) & AT91C_ISI_IM_HSIZE)
+ AT91C_ISI_YCC_SWAP_YCC_MODE2;
if (pVideo->rgb_or_yuv == RGB) {
AT91C_BASE_ISI->ISI_CFG2 |= AT91C_ISI_COL_SPACE | AT91C_ISI_RGB_MODE_RGB_565
| AT91C_ISI_RGB_CFG_RGB_DEFAULT;
}
else {
// AT91C_BASE_HISI->ISI_CFG2 &= ~AT91C_ISI_COL_SPACE;
}
TRACE_DEBUG("ISI_CFG2=0x%X\n\r", AT91C_BASE_ISI->ISI_CFG2);
// Vertical Preview size = PREV_VSIZE + 1 (480 max only in RGB mode).
// Horizontal Preview size = PREV_HSIZE + 1 (640 max only in RGB mode).
#if defined (AT91C_ID_LCDC)
if( (pVideo->lcd_vsize > 480) || (pVideo->lcd_hsize > 640)) {
TRACE_ERROR("Size LCD bad define\n\r");
AT91C_BASE_ISI->ISI_PSIZE = ((BOARD_LCD_HEIGHT-1) & AT91C_ISI_PREV_VSIZE)
+ (((BOARD_LCD_WIDTH-1) << 16) & AT91C_ISI_PREV_HSIZE);
}
else {
AT91C_BASE_ISI->ISI_PSIZE = ((pVideo->lcd_vsize -1) & AT91C_ISI_PREV_VSIZE)
+ (((pVideo->lcd_hsize -1) << 16) & AT91C_ISI_PREV_HSIZE);
}
#endif
// DEC_FACTOR is 8-bit width, range is from 16 to 255.
// Values from 0 to 16 do not perform any decimation.
AT91C_BASE_ISI->ISI_PDECF = (16 * pVideo->codec_hsize) / pVideo->lcd_hsize;
TRACE_DEBUG("codec_hsize: %d\n\r", pVideo->codec_hsize);
TRACE_DEBUG("lcd_hsize: %d\n\r", pVideo->lcd_hsize);
TRACE_DEBUG("ISI_PDECF: %d\n\r", AT91C_BASE_ISI->ISI_PDECF);
if( AT91C_BASE_ISI->ISI_PDECF <16) {
TRACE_ERROR("ISI_PDECF, forbidden value: %d\n\r", AT91C_BASE_ISI->ISI_PDECF);
AT91C_BASE_ISI->ISI_PDECF = 16;
}
AT91C_BASE_ISI->ISI_DMAPDSCR = pVideo->Isi_fbd_base;
AT91C_BASE_ISI->ISI_DMAPCTRL = AT91C_ISI_P_FETCH_ENABLE;
AT91C_BASE_ISI->ISI_DMAPADDR = pVideo->lcd_fb_addr;
// C0: Color Space Conversion Matrix Coefficient C0
// C1: Color Space Conversion Matrix Coefficient C1
// C2: Color Space Conversion Matrix Coefficient C2
// C3: Color Space Conversion Matrix Coefficient C3
AT91C_BASE_ISI->ISI_Y2RSET0 = ( (0x95<< 0) & AT91C_ISI_Y2R_C0)
+ ( (0xFF<< 8) & AT91C_ISI_Y2R_C1)
+ ( (0x68<<16) & AT91C_ISI_Y2R_C2)
+ ( (0x32<<24) & AT91C_ISI_Y2R_C3);
// C4: Color Space Conversion Matrix coefficient C4
// Yoff: Color Space Conversion Luminance 128 offset
// Croff: Color Space Conversion Red Chrominance 16 offset
// Cboff: Color Space Conversion Blue Chrominance 16 offset
AT91C_BASE_ISI->ISI_Y2RSET1 = ( (0xCC<< 0) & AT91C_ISI_Y2R_C4)
+ ( AT91C_ISI_Y2R_YOFF_128)
+ ( AT91C_ISI_Y2R_CROFF_16)
+ ( AT91C_ISI_Y2R_CBOFF_16);
}
#endif // defined (BOARD_ISI_V200)

View file

@ -0,0 +1,466 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#include <board.h>
#if defined (AT91C_ID_LCDC)
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "lcd.h"
#include <utility/assert.h>
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Enables the LCD controller, after waiting for the specified number of
/// frames.
/// \param frames Number of frames before the LCD is enabled.
//------------------------------------------------------------------------------
void LCD_Enable(unsigned int frames)
{
TRACE_DEBUG("LCD enable\n\r");
ASSERT((frames & 0xFFFFFF80) == 0,
"LCD_Enable: Wrong frames value.\n\r");
if( (AT91C_BASE_LCDC->LCDC_PWRCON & AT91C_LCDC_BUSY) == AT91C_LCDC_BUSY ) {
TRACE_DEBUG("LCD BUSY E\n\r");
}
AT91C_BASE_LCDC->LCDC_PWRCON = AT91C_LCDC_PWR | (frames << 1);
}
//------------------------------------------------------------------------------
/// Disables the LCD controller, after waiting for the specified number of
/// frames.
/// \param frames Number of frames before the LCD is shut down.
//------------------------------------------------------------------------------
void LCD_Disable(unsigned int frames)
{
TRACE_DEBUG("LCD disable\n\r");
ASSERT((frames & 0xFFFFFF80) == 0,
"LCD_Disable: Wrong frames value.\n\r");
// Remove AT91C_LCDC_PWR
AT91C_BASE_LCDC->LCDC_PWRCON = frames << 1;
// wait LCDC Core is in idle state
while( (AT91C_BASE_LCDC->LCDC_PWRCON & AT91C_LCDC_BUSY) == AT91C_LCDC_BUSY ) {
}
TRACE_DEBUG("LCD is in IDLE state\n\r");
}
//------------------------------------------------------------------------------
/// Enables the DMA of the LCD controller.
//------------------------------------------------------------------------------
void LCD_EnableDma(void)
{
if( (AT91C_BASE_LCDC->LCDC_DMACON & AT91C_LCDC_DMABUSY) == AT91C_LCDC_DMABUSY ) {
TRACE_DEBUG("LCD DMA BUSY E\n\r");
}
AT91C_BASE_LCDC->LCDC_DMACON = AT91C_LCDC_DMAEN;
}
//------------------------------------------------------------------------------
/// Disables the DMA of the LCD controller.
//------------------------------------------------------------------------------
void LCD_DisableDma(void)
{
AT91C_BASE_LCDC->LCDC_DMACON = 0;
// wait LCDC DMA is in idle state
while( (AT91C_BASE_LCDC->LCDC_DMACON & AT91C_LCDC_DMABUSY) == AT91C_LCDC_DMABUSY ) {
}
TRACE_DEBUG("LCD DMA is in IDLE state\n\r");
}
//------------------------------------------------------------------------------
/// Enables the selected LDC interrupt sources.
/// \param sources Interrupt sources to enable.
//------------------------------------------------------------------------------
void LCD_EnableInterrupts(unsigned int sources)
{
AT91C_BASE_LCDC->LCDC_IER = sources;
}
//------------------------------------------------------------------------------
/// Configures the internal clock of the LCD controller given the master clock of
/// the system and the desired pixel clock in MHz.
/// \param masterClock Master clock frequency.
/// \param pixelClock Pixel clock frequency.
//------------------------------------------------------------------------------
void LCD_SetPixelClock(unsigned int masterClock, unsigned int pixelClock)
{
AT91C_BASE_LCDC->LCDC_LCDCON1 = ((masterClock / 2 / pixelClock) - 2) << 12;
}
//------------------------------------------------------------------------------
/// DMA reset
//------------------------------------------------------------------------------
void LCD_DMAReset(void)
{
// DMA Module should be reset only when disabled and in idle state
if( AT91C_LCDC_DMABUSY == (AT91C_BASE_LCDC->LCDC_DMACON & AT91C_LCDC_DMABUSY)) {
TRACE_ERROR("LCD BUSY so NO DMA RESET\n\r");
}
if( AT91C_LCDC_DMAEN == (AT91C_BASE_LCDC->LCDC_DMACON & AT91C_LCDC_DMAEN)) {
TRACE_ERROR("DMA Enabled, so NO DMA RESET\n\r");
}
AT91C_BASE_LCDC->LCDC_DMACON = AT91C_LCDC_DMARST;
}
//------------------------------------------------------------------------------
/// Sets the type of display used with the LCD controller.
/// \param displayType Type of display used.
//------------------------------------------------------------------------------
void LCD_SetDisplayType(unsigned int displayType)
{
unsigned int value;
ASSERT((displayType & ~AT91C_LCDC_DISTYPE) == 0,
"LCD_SetDisplayType: Wrong display type value.\n\r");
value = AT91C_BASE_LCDC->LCDC_LCDCON2;
value &= ~AT91C_LCDC_DISTYPE;
value |= displayType;
AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
}
//------------------------------------------------------------------------------
/// Sets the scan mode used by the LCD (either single scan or double-scan).
/// \param scanMode Scan mode to use.
//------------------------------------------------------------------------------
void LCD_SetScanMode(unsigned int scanMode)
{
unsigned int value;
ASSERT((scanMode & ~AT91C_LCDC_SCANMOD) == 0,
"LCD_SetScanMode: Wrong scan mode value.\n\r");
value = AT91C_BASE_LCDC->LCDC_LCDCON2;
value &= ~AT91C_LCDC_SCANMOD;
value |= scanMode;
AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
}
//------------------------------------------------------------------------------
/// Sets the number of bits per pixel used by the LCD display.
/// \param bitsPerPixel Number of bits per pixel to use.
//------------------------------------------------------------------------------
void LCD_SetBitsPerPixel(unsigned int bitsPerPixel)
{
unsigned int value;
ASSERT((bitsPerPixel & ~AT91C_LCDC_PIXELSIZE) == 0,
"LCD_SetScanMode: Wrong bitsPerPixel value.\n\r");
value = AT91C_BASE_LCDC->LCDC_LCDCON2;
value &= ~AT91C_LCDC_PIXELSIZE;
value |= bitsPerPixel;
AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
}
//------------------------------------------------------------------------------
/// Sets the LCDD, LCDVSYNC, LCDHSYNC, LCDDOTCLK and LCDDEN signal polarities.
/// \param lcdd LCDD signal polarity.
/// \param lcdvsync LCDVSYNC signal polarity.
/// \param lcdhsync LCDHSYNC signal polarity.
/// \param lcddotclk LCDDOTCLK signal polarity.
/// \param lcdden LCDDEN signal polarity.
//------------------------------------------------------------------------------
void LCD_SetPolarities(
unsigned int lcdd,
unsigned int lcdvsync,
unsigned int lcdhsync,
unsigned int lcddotclk,
unsigned int lcdden)
{
unsigned int value;
ASSERT((lcdd & ~AT91C_LCDC_INVVD) == 0,
"LCD_SetPolarities: Wrong lcdd value.\n\r");
ASSERT((lcdvsync & ~AT91C_LCDC_INVFRAME) == 0,
"LCD_SetPolarities: Wrong lcdvsync value.\n\r");
ASSERT((lcdhsync & ~AT91C_LCDC_INVLINE) == 0,
"LCD_SetPolarities: Wrong lcdhsync value.\n\r");
ASSERT((lcddotclk & ~AT91C_LCDC_INVCLK) == 0,
"LCD_SetPolarities: Wrong lcddotclk value.\n\r");
ASSERT((lcdden & ~AT91C_LCDC_INVDVAL) == 0,
"LCD_SetPolarities: Wrong lcdden value.\n\r");
value = AT91C_BASE_LCDC->LCDC_LCDCON2;
value &= 0xFFFFE0FF;
value |= lcdd | lcdvsync | lcdhsync | lcddotclk | lcdden;
AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
}
//------------------------------------------------------------------------------
/// Sets the LCD clock mode, i.e. always active or active only during display
/// period.
/// \param clockMode Clock mode to use.
//------------------------------------------------------------------------------
void LCD_SetClockMode(unsigned int clockMode)
{
unsigned int value;
ASSERT((clockMode & ~AT91C_LCDC_CLKMOD) == 0,
"LCD_SetScanMode: Wrong scan mode value.\n\r");
value = AT91C_BASE_LCDC->LCDC_LCDCON2;
value &= ~AT91C_LCDC_CLKMOD;
value |= clockMode;
AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
}
//------------------------------------------------------------------------------
/// Sets the format of the frame buffer memory.
/// \param format Memory ordering format.
//------------------------------------------------------------------------------
void LCD_SetMemoryFormat(unsigned int format)
{
unsigned int value;
ASSERT((format & ~AT91C_LCDC_MEMOR) == 0,
"LCD_SetMemoryFormat: Wrong memory format value.\n\r");
value = AT91C_BASE_LCDC->LCDC_LCDCON2;
value &= ~AT91C_LCDC_MEMOR;
value |= format;
AT91C_BASE_LCDC->LCDC_LCDCON2 = value;
}
//------------------------------------------------------------------------------
/// Sets the size in pixel of the LCD display.
/// \param width Width in pixel of the LCD display.
/// \param height Height in pixel of the LCD display.
//------------------------------------------------------------------------------
void LCD_SetSize(unsigned int width, unsigned int height)
{
ASSERT(((width - 1) & 0xFFFFF800) == 0,
"LCD_SetSize: Wrong width value.\n\r");
ASSERT(((height - 1) & 0xFFFFF800) == 0,
"LCD_SetSize: Wrong height value.\n\r");
AT91C_BASE_LCDC->LCDC_LCDFRCFG = ((width - 1) << 21) | (height - 1);
}
//------------------------------------------------------------------------------
/// Sets the vertical timings of the LCD controller. Only meaningful when
/// using a TFT display.
/// \param vfp Number of idle lines at the end of a frame.
/// \param vbp Number of idle lines at the beginning of a frame.
/// \param vpw Vertical synchronization pulse width in number of lines.
/// \param vhdly Delay between LCDVSYNC edge and LCDHSYNC rising edge, in
/// LCDDOTCLK cycles.
//------------------------------------------------------------------------------
void LCD_SetVerticalTimings(
unsigned int vfp,
unsigned int vbp,
unsigned int vpw,
unsigned int vhdly)
{
ASSERT((vfp & 0xFFFFFF00) == 0,
"LCD_SetVerticalTimings: Wrong vfp value.\n\r");
ASSERT((vbp & 0xFFFFFF00) == 0,
"LCD_SetVerticalTimings: Wrong vbp value.\n\r");
ASSERT(((vpw-1) & 0xFFFFFFC0) == 0,
"LCD_SetVerticalTimings: Wrong vpw value.\n\r");
ASSERT(((vhdly-1) & 0xFFFFFFF0) == 0,
"LCD_SetVerticalTimings: Wrong vhdly value.\n\r");
AT91C_BASE_LCDC->LCDC_TIM1 = vfp
| (vbp << 8)
| ((vpw-1) << 16)
| ((vhdly-1) << 24);
}
//------------------------------------------------------------------------------
/// Sets the horizontal timings of the LCD controller. Meaningful for both
/// STN and TFT displays.
/// \param hbp Number of idle LCDDOTCLK cycles at the beginning of a line.
/// \param hpw Width of the LCDHSYNC pulse, in LCDDOTCLK cycles.
/// \param hfp Number of idel LCDDOTCLK cycles at the end of a line.
//------------------------------------------------------------------------------
void LCD_SetHorizontalTimings(
unsigned int hbp,
unsigned int hpw,
unsigned int hfp)
{
ASSERT(((hbp-1) & 0xFFFFFF00) == 0,
"LCD_SetHorizontalTimings: Wrong hbp value.\n\r");
ASSERT(((hpw-1) & 0xFFFFFFC0) == 0,
"LCD_SetHorizontalTimings: Wrong hpw value.\n\r");
ASSERT(((hfp-1) & 0xFFFFFF00) == 0,
"LCD_SetHorizontalTimings: Wrong hfp value.\n\r");
AT91C_BASE_LCDC->LCDC_TIM2 = (hbp-1) | ((hpw-1) << 8) | ((hfp-1) << 24);
}
//------------------------------------------------------------------------------
/// Sets the address of the frame buffer in the LCD controller DMA. When using
/// dual-scan mode, this is the upper frame buffer.
/// \param address Frame buffer address.
//------------------------------------------------------------------------------
void* LCD_SetFrameBufferAddress(void *address)
{
void *pOldBuffer;
pOldBuffer = (void *) AT91C_BASE_LCDC->LCDC_BA1;
AT91C_BASE_LCDC->LCDC_BA1 = (unsigned int) address;
return pOldBuffer;
}
//------------------------------------------------------------------------------
/// Sets the size in pixels of a frame (height * width * bpp).
/// \param frameSize Size of frame in pixels.
//------------------------------------------------------------------------------
void LCD_SetFrameSize(unsigned int frameSize)
{
ASSERT((frameSize & 0xFF800000) == 0,
"LCD_SetFrameSize: Wrong frameSize value.\n\r");
AT91C_BASE_LCDC->LCDC_FRMCFG = (frameSize& AT91C_LCDC_FRSIZE)
| (AT91C_BASE_LCDC->LCDC_FRMCFG & AT91C_LCDC_BLENGTH);
}
//------------------------------------------------------------------------------
/// Sets the DMA controller burst length.
/// \param burstLength Desired burst length.
//------------------------------------------------------------------------------
void LCD_SetBurstLength(unsigned int burstLength)
{
ASSERT(((burstLength-1) & 0xFFFFFF80) == 0,
"LCD_SetBurstLength: Wrong burstLength value.\n\r");
AT91C_BASE_LCDC->LCDC_FRMCFG &= ~AT91C_LCDC_BLENGTH;
AT91C_BASE_LCDC->LCDC_FRMCFG |= (((burstLength-1) << 24) & AT91C_LCDC_BLENGTH);
AT91C_BASE_LCDC->LCDC_FIFO = (2048 - (2 * burstLength + 3)) & AT91C_LCDC_FIFOTH;
}
//------------------------------------------------------------------------------
/// Sets the prescaler value of the contrast control PWM.
/// \param prescaler Desired prescaler value.
//------------------------------------------------------------------------------
void LCD_SetContrastPrescaler(unsigned int prescaler)
{
ASSERT((prescaler & ~AT91C_LCDC_PS) == 0,
"LCD_SetContrastPrescaler: Wrong prescaler value\n\r");
AT91C_BASE_LCDC->LCDC_CTRSTCON &= ~AT91C_LCDC_PS;
AT91C_BASE_LCDC->LCDC_CTRSTCON |= prescaler;
}
//------------------------------------------------------------------------------
/// Sets the polarity of the contrast PWM.
/// \param polarity PWM polarity
//------------------------------------------------------------------------------
void LCD_SetContrastPolarity(unsigned int polarity)
{
ASSERT((polarity & ~AT91C_LCDC_POL) == 0,
"LCD_SetContrastPolarity: Wrong polarity value\n\r");
AT91C_BASE_LCDC->LCDC_CTRSTCON &= ~AT91C_LCDC_POL;
AT91C_BASE_LCDC->LCDC_CTRSTCON |= polarity;
}
//------------------------------------------------------------------------------
/// Sets the threshold value of the constrast PWM.
/// \param value PWM threshold value.
//------------------------------------------------------------------------------
void LCD_SetContrastValue(unsigned int value)
{
ASSERT((value & ~AT91C_LCDC_CVAL) == 0,
"LCD_SetContrastValue: Wrong value.\n\r");
AT91C_BASE_LCDC->LCDC_CTRSTVAL = value;
}
//------------------------------------------------------------------------------
/// Enables the contrast PWM generator.
//------------------------------------------------------------------------------
void LCD_EnableContrast(void)
{
AT91C_BASE_LCDC->LCDC_CTRSTCON |= AT91C_LCDC_ENA_PWMGEMENABLED;
}
//------------------------------------------------------------------------------
/// Decode the RGB file
/// \param file Buffer which holds the RGB file.
/// \param bufferLCD Buffer in which to store the decoded image adapted to LCD.
/// \param width Buffer width in pixels.
/// \param height Buffer height in pixels.
/// \param bpp Number of bits per pixels that the buffer stores.
//------------------------------------------------------------------------------
void LCD_DecodeRGB(
unsigned char *file,
unsigned char *bufferLCD,
unsigned int width,
unsigned int height,
unsigned char bpp)
{
unsigned int offsetLine=0, offsetLCD=0;
unsigned int offset=1;
while( offset < (BOARD_LCD_HEIGHT)) {
//TRACE_DEBUG("LCD:%d LINE:%d off:%d\n\r", offsetLCD, offsetLine, offset);
if( width < BOARD_LCD_WIDTH ) {
//TRACE_DEBUG("width < BOARD_LCD_WIDTH\n\r");
while( offsetLine < (width*offset*(bpp/8)) ) {
bufferLCD[offsetLCD] = file[offsetLine];
offsetLine++;
offsetLCD++;
}
//TRACE_DEBUG("add white\n\r");
while( offsetLCD < (BOARD_LCD_WIDTH*offset*(bpp/8)) ) {
bufferLCD[offsetLCD] = 0;
//offsetLine++;
offsetLCD++;
}
}
else {
//TRACE_DEBUG(">");
while( offsetLCD < (BOARD_LCD_WIDTH*offset*(bpp/8)) ) {
bufferLCD[offsetLCD] = file[offsetLine];
offsetLine++;
offsetLCD++;
}
//TRACE_DEBUG("r ");
while( offsetLine < (width*offset*(bpp/8)) ) {
offsetLine++;
}
}
offset++;
}
}
#endif

View file

@ -0,0 +1,124 @@
/* ----------------------------------------------------------------------------
* 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 LCD Controller (LCDC) peripheral.
///
/// !Usage
///
/// -# Decode the RGB file to designated buffer using LCD_DecodeRGB().
/// -# Sets the address of the frame buffer in the LCD controller DMA using
/// LCD_SetFrameBufferAddress().
/// -# LCD Configuration functions prefixed with "LCD_Set" refer to
/// the functions in the #Overview# tab.
///
/// Please refer to the list of functions in the #Overview# tab of this unit
/// for more detailed information.
//------------------------------------------------------------------------------
#ifndef LCD_H
#define LCD_H
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void LCD_Enable(unsigned int frames);
extern void LCD_Disable(unsigned int frames);
extern void LCD_EnableDma(void);
extern void LCD_DisableDma(void);
extern void LCD_EnableInterrupts(unsigned int sources);
extern void LCD_SetPixelClock(unsigned int masterClock, unsigned int pixelClock);
extern void LCD_SetDisplayType(unsigned int displayType);
extern void LCD_SetScanMode(unsigned int scanMode);
extern void LCD_SetBitsPerPixel(unsigned int bitsPerPixel);
extern void LCD_SetPolarities(
unsigned int lcdd,
unsigned int lcdvsync,
unsigned int lcdhsync,
unsigned int lcddotclk,
unsigned int lcdden);
extern void LCD_SetClockMode(unsigned int clockMode);
extern void LCD_SetMemoryFormat(unsigned int format);
extern void LCD_SetSize(unsigned int width, unsigned int height);
extern void LCD_SetVerticalTimings(
unsigned int vfp,
unsigned int vbp,
unsigned int vpw,
unsigned int vhdly);
extern void LCD_SetHorizontalTimings(
unsigned int hbp,
unsigned int hpw,
unsigned int hfp);
extern void* LCD_SetFrameBufferAddress(void *address);
extern void LCD_SetFrameSize(unsigned int frameSize);
extern void LCD_SetBurstLength(unsigned int burstLength);
extern void LCD_SetContrastPrescaler(unsigned int prescaler);
extern void LCD_SetContrastPolarity(unsigned int polarity);
extern void LCD_SetContrastValue(unsigned int value);
extern void LCD_EnableContrast(void);
extern void LCD_SetPixelClock(unsigned int masterClock, unsigned int pixelClock);
extern void LCD_DMAReset(void);
extern void LCD_DecodeRGB(
unsigned char *file,
unsigned char *bufferLCD,
unsigned int width,
unsigned int height,
unsigned char bpp);
#endif //#ifndef LCD_H

View file

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

View file

@ -0,0 +1,172 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \page "mci"
///
/// !Purpose
///
/// mci-interface driver
///
/// !Usage
///
/// -# MCI_Init: Initializes a MCI driver instance and the underlying peripheral.
/// -# MCI_SetSpeed : Configure the MCI CLKDIV in the MCI_MR register.
/// -# MCI_SendCommand: Starts a MCI transfer.
/// -# MCI_Handler : Interrupt handler which is called by ISR handler.
/// -# MCI_SetBusWidth : Configure the MCI SDCBUS in the MCI_SDCR register.
//------------------------------------------------------------------------------
#ifndef MCI_H
#define MCI_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
/// Transfer is pending.
#define MCI_STATUS_PENDING 1
/// Transfer has been aborted because an error occured.
#define MCI_STATUS_ERROR 2
/// Card did not answer command.
#define MCI_STATUS_NORESPONSE 3
/// MCI driver is currently in use.
#define MCI_ERROR_LOCK 1
/// MCI configuration with 1-bit data bus on slot A (for MMC cards).
#define MCI_MMC_SLOTA 0
/// MCI configuration with 1-bit data bus on slot B (for MMC cards).
#define MCI_MMC_SLOTB 1
/// MCI configuration with 4-bit data bus on slot A (for SD cards).
#define MCI_SD_SLOTA AT91C_MCI_SCDBUS
/// MCI configuration with 4-bit data bus on slot B (for SD cards).
#define MCI_SD_SLOTB (AT91C_MCI_SCDBUS | 1)
/// Start new data transfer
#define MCI_NEW_TRANSFER 0
/// Continue data transfer
#define MCI_CONTINUE_TRANSFER 1
/// MCI SD Bus Width 1-bit
#define MCI_SDCBUS_1BIT (0 << 7)
/// MCI SD Bus Width 4-bit
#define MCI_SDCBUS_4BIT (1 << 7)
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
/// MCI end-of-transfer callback function.
typedef void (*MciCallback)(unsigned char status, void *pCommand);
//------------------------------------------------------------------------------
/// MCI Transfer Request prepared by the application upper layer. This structure
/// is sent to the MCI_SendCommand function to start the transfer. At the end of
/// the transfer, the callback is invoked by the interrupt handler.
//------------------------------------------------------------------------------
typedef struct _MciCmd {
/// Command status.
volatile char status;
/// Command code.
unsigned int cmd;
/// Command argument.
unsigned int arg;
/// Data buffer.
unsigned char *pData;
/// Size of data buffer in bytes.
unsigned short blockSize;
/// Number of blocks to be transfered
unsigned short nbBlock;
/// Indicate if continue to transfer data
unsigned char conTrans;
/// Indicates if the command is a read operation.
unsigned char isRead;
/// Response buffer.
unsigned int *pResp;
/// SD card response type.
unsigned char resType;
/// Optional user-provided callback function.
MciCallback callback;
/// Optional argument to the callback function.
void *pArg;
} MciCmd;
//------------------------------------------------------------------------------
/// MCI driver structure. Holds the internal state of the MCI driver and
/// prevents parallel access to a MCI peripheral.
//------------------------------------------------------------------------------
typedef struct {
/// Pointer to a MCI peripheral.
AT91S_MCI *pMciHw;
/// MCI peripheral identifier.
unsigned char mciId;
/// Pointer to currently executing command.
MciCmd *pCommand;
/// Mutex.
volatile char semaphore;
} Mci;
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void MCI_Init(
Mci *pMci,
AT91PS_MCI pMciHw,
unsigned char mciId,
unsigned int mode);
extern void MCI_SetSpeed(Mci *pMci, unsigned int mciSpeed);
extern unsigned char MCI_SendCommand(Mci *pMci, MciCmd *pMciCmd);
extern void MCI_Handler(Mci *pMci);
extern unsigned char MCI_IsTxComplete(MciCmd *pMciCmd);
extern unsigned char MCI_CheckBusy(Mci *pMci);
extern void MCI_Close(Mci *pMci);
extern void MCI_SetBusWidth(Mci *pMci, unsigned char busWidth);
#endif //#ifndef MCI_H

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,205 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \page "mci"
///
/// !Purpose
///
/// mci-interface driver
///
/// !Usage
///
/// -# MCI_Init: Initializes a MCI driver instance and the underlying peripheral.
/// -# MCI_SetSpeed : Configure the MCI CLKDIV in the MCI_MR register.
/// -# MCI_SendCommand: Starts a MCI transfer.
/// -# MCI_Handler : Interrupt handler which is called by ISR handler.
/// -# MCI_SetBusWidth : Configure the MCI SDCBUS in the MCI_SDCR register.
//------------------------------------------------------------------------------
#ifndef MCI_HS_H
#define MCI_HS_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Constants
//------------------------------------------------------------------------------
/// Transfer is pending.
#define MCI_STATUS_PENDING 1
/// Transfer has been aborted because an error occured.
#define MCI_STATUS_ERROR 2
/// Card did not answer command.
#define MCI_STATUS_NORESPONSE 3
/// MCI driver is currently in use.
#define MCI_ERROR_LOCK 1
/// MCI configuration with 1-bit data bus on slot A (for MMC cards).
#define MCI_MMC_SLOTA (AT91C_MCI_SCDSEL_SLOTA | AT91C_MCI_SCDBUS_1BIT)
/// MCI configuration with 4-bit data bus on slot A (for SD cards).
#define MCI_SD_SLOTA (AT91C_MCI_SCDSEL_SLOTA | AT91C_MCI_SCDBUS_4BITS)
#ifdef AT91C_MCI_SCDBUS_8BITS
/// MCI configuration with 1-bit data bus on slot A (for MMC cards).
#define MCI_MMC4_SLOTA (AT91C_MCI_SCDSEL_SLOTA | AT91C_MCI_SCDBUS_8BITS)
#endif
#ifdef AT91C_MCI_SCDSEL_SLOTB
/// MCI configuration with 1-bit data bus on slot B (for MMC cards).
#define MCI_MMC_SLOTB (AT91C_MCI_SCDSEL_SLOTB | AT91C_MCI_SCDBUS_1BIT)
/// MCI configuration with 4-bit data bus on slot B (for SD cards).
#define MCI_SD_SLOTB (AT91C_MCI_SCDSEL_SLOTB | AT91C_MCI_SCDBUS_4BITS)
#ifdef AT91C_MCI_SCDBUS_8BITS
/// MCI configuration with 1-bit data bus on slot A (for MMC cards).
#define MCI_MMC4_SLOTB (AT91C_MCI_SCDSEL_SLOTB | AT91C_MCI_SCDBUS_8BITS)
#endif
#else
#define MCI_MMC_SLOTB MCI_MMC_SLOTA
#define MCI_SD_SLOTB MCI_SD_SLOTA
#endif
/// Start new data transfer
#define MCI_NEW_TRANSFER 0
/// Continue data transfer
#define MCI_CONTINUE_TRANSFER 1
/// Stop data transfer
#define MCI_STOP_TRANSFER 2
/// MCI SD Bus Width 1-bit
#define MCI_SDCBUS_1BIT (0 << 7)
/// MCI SD Bus Width 4-bit
#define MCI_SDCBUS_4BIT (1 << 7)
/// MCI SD Bus Width 8-bit
#define MCI_SDCBUS_8BIT (3 << 6)
/// The MCI Clock Speed after initialize (400K)
#define MCI_INITIAL_SPEED 400000
/// MCI using DMA?
#define MCI_DMA_ENABLE 1
//------------------------------------------------------------------------------
// Types
//------------------------------------------------------------------------------
/// MCI end-of-transfer callback function.
typedef void (*MciCallback)(unsigned char status, void *pCommand);
//------------------------------------------------------------------------------
/// MCI Transfer Request prepared by the application upper layer. This structure
/// is sent to the MCI_SendCommand function to start the transfer. At the end of
/// the transfer, the callback is invoked by the interrupt handler.
//------------------------------------------------------------------------------
typedef struct _MciCmd {
/// Command code.
unsigned int cmd;
/// Command argument.
unsigned int arg;
/// Data buffer.
unsigned char *pData;
/// Size of data block in bytes.
unsigned short blockSize;
/// Number of blocks to be transfered
unsigned short nbBlock;
/// Response buffer.
unsigned int *pResp;
/// Optional user-provided callback function.
MciCallback callback;
/// Optional argument to the callback function.
void *pArg;
/// SD card response type.
unsigned char resType;
/// Indicate if there is data transfer
unsigned char dataTran;
/// Indicate if continue to transfer data
unsigned char tranType;
/// Indicates if the command is a read operation.
unsigned char isRead;
/// Command status.
volatile int status;
} MciCmd;
//------------------------------------------------------------------------------
/// MCI driver structure. Holds the internal state of the MCI driver and
/// prevents parallel access to a MCI peripheral.
//------------------------------------------------------------------------------
typedef struct {
/// Pointer to a MCI peripheral.
AT91S_MCI *pMciHw;
/// Pointer to currently executing command.
MciCmd *pCommand;
/// MCI peripheral identifier.
unsigned char mciId;
/// MCI HW mode
unsigned char mciMode;
/// Mutex.
volatile char semaphore;
} Mci;
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void MCI_Init(
Mci *pMci,
AT91PS_MCI pMciHw,
unsigned char mciId,
unsigned int mode);
extern unsigned int MCI_GetSpeed(Mci *pMci, unsigned int *mciDiv);
extern unsigned int MCI_SetSpeed(Mci *pMci,
unsigned int mciSpeed,
unsigned int mciLimit);
extern unsigned char MCI_SendCommand(Mci *pMci, MciCmd *pMciCmd);
extern void MCI_Handler(Mci *pMci);
extern unsigned char MCI_IsTxComplete(MciCmd *pMciCmd);
extern unsigned char MCI_CheckBusy(Mci *pMci);
extern void MCI_Close(Mci *pMci);
extern void MCI_EnableHsMode(Mci * pMci, unsigned char hsEnable);
extern void MCI_SetBusWidth(Mci *pMci, unsigned char busWidth);
extern unsigned int MCI_FifoTransfer(Mci * pMci, MciCmd * pCommand);
#endif //#ifndef MCI_HS_H

View file

@ -0,0 +1,382 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "pio.h"
#include <board.h>
//------------------------------------------------------------------------------
// Local Functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures one or more pin(s) of a PIO controller as being controlled by
/// peripheral A. Optionally, the corresponding internal pull-up(s) can be
/// enabled.
/// \param pio Pointer to a PIO controller.
/// \param mask Bitmask of one or more pin(s) to configure.
/// \param enablePullUp Indicates if the pin(s) internal pull-up shall be
/// configured.
//------------------------------------------------------------------------------
static void PIO_SetPeripheralA(
AT91S_PIO *pio,
unsigned int mask,
unsigned char enablePullUp)
{
#if !defined(AT91C_PIOA_ASR)
unsigned int abmr;
#endif
// 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
#if defined(AT91C_PIOA_ASR)
pio->PIO_ASR = mask;
#else
abmr = pio->PIO_ABSR;
pio->PIO_ABSR &= (~mask & abmr);
#endif
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)
{
#if !defined(AT91C_PIOA_BSR)
unsigned int abmr;
#endif
// 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
#if defined(AT91C_PIOA_BSR)
pio->PIO_BSR = mask;
#else
abmr = pio->PIO_ABSR;
pio->PIO_ABSR = mask | abmr;
#endif
pio->PIO_PDR = mask;
}
#if defined(AT91C_PIOA_IFDGSR) //Glitch or Debouncing filter selection supported
//------------------------------------------------------------------------------
/// Configures Glitch or Debouncing filter for input
/// \param pio Pointer to a PIO controller.
/// \param mask Bitmask for filter selection.
/// each of 32 bit field, 0 is Glitch, 1 is Debouncing
/// \param clkDiv Clock divider if Debouncing select, using the lowest 14 bits
/// common for all PIO line of selecting deboucing filter
//------------------------------------------------------------------------------
static void PIO_SetFilter(
AT91S_PIO *pio,
unsigned int filterSel,
unsigned int clkDiv)
{
pio->PIO_DIFSR = filterSel;//set Debouncing, 0 bit field no effect
pio->PIO_SCIFSR = ~filterSel;//set Glitch, 0 bit field no effect
pio->PIO_SCDR = clkDiv & 0x3FFF;//the lowest 14 bits work
}
#endif
//------------------------------------------------------------------------------
/// 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);
#if defined(AT91C_PIOA_IFDGSR) //PIO3 with Glitch or Debouncing selection
//if glitch input filter enabled, set it
if(list->attribute & PIO_DEGLITCH)//Glitch input filter enabled
PIO_SetFilter(list->pio,
list->inFilter.filterSel,
list->inFilter.clkDivider);
#endif
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;
}
}

View file

@ -0,0 +1,225 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
///
/// !!!Purpose
///
/// This file provides a basic API for PIO configuration and usage of
/// user-controlled pins. Please refer to the board.h file for a list of
/// available pin definitions.
///
/// !!!Usage
///
/// -# Define a constant pin description array such as the following one, using
/// the existing definitions provided by the board.h file if possible:
/// \code
/// const Pin pPins[] = {PIN_USART0_TXD, PIN_USART0_RXD};
/// \endcode
/// Alternatively, it is possible to add new pins by provided the full Pin
/// structure:
/// \code
/// // Pin instance to configure PA10 & PA11 as inputs with the internal
/// // pull-up enabled.
/// const Pin pPins = {
/// (1 << 10) | (1 << 11),
/// AT91C_BASE_PIOA,
/// AT91C_ID_PIOA,
/// PIO_INPUT,
/// PIO_PULLUP
/// };
/// \endcode
/// -# Configure a pin array by calling PIO_Configure() with a pointer to the
/// array and its size (which is computed using the PIO_LISTSIZE macro).
/// -# Change and get the value of a user-controlled pin using the PIO_Set,
/// PIO_Clear and PIO_Get methods.
/// -# Get the level being currently output by a user-controlled pin configured
/// as an output using PIO_GetOutputDataStatus().
//------------------------------------------------------------------------------
#ifndef PIO_H
#define PIO_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Global Definitions
//------------------------------------------------------------------------------
/// The pin is controlled by the associated signal of peripheral A.
#define PIO_PERIPH_A 0
/// The pin is controlled by the associated signal of peripheral B.
#define PIO_PERIPH_B 1
/// The pin is an input.
#define PIO_INPUT 2
/// The pin is an output and has a default level of 0.
#define PIO_OUTPUT_0 3
/// The pin is an output and has a default level of 1.
#define PIO_OUTPUT_1 4
/// Default pin configuration (no attribute).
#define PIO_DEFAULT (0 << 0)
/// The internal pin pull-up is active.
#define PIO_PULLUP (1 << 0)
/// The internal glitch filter is active.
#define PIO_DEGLITCH (1 << 1)
/// The pin is open-drain.
#define PIO_OPENDRAIN (1 << 2)
//------------------------------------------------------------------------------
// Global Macros
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Calculates the size of an array of Pin instances. The array must be defined
/// locally (i.e. not a pointer), otherwise the computation will not be correct.
/// \param pPins Local array of Pin instances.
/// \return Number of elements in array.
//------------------------------------------------------------------------------
#define PIO_LISTSIZE(pPins) (sizeof(pPins) / sizeof(Pin))
//------------------------------------------------------------------------------
// Global Types
//------------------------------------------------------------------------------
typedef struct _ExtIntMode {
///indicate which pin to enable/disable additional Interrupt mode
///each of 32 bit field represents one PIO line.
unsigned int itMask;
///select Edge or level interrupt detection source
///each of 32 bit field represents one PIO line, 0 is Edge, 1 is Level
unsigned int edgeLvlSel;
///select rising/high or falling/low detection event
///each of 32 bit field represents one PIO line:
///0 is Falling Edge detection event (if selected Edge interrupt
/// detection source, or Low Level detection (if selected
/// Level interrupt detection source;
///1 is Rising Edge detection(if selected Edge interrupt
/// source, or Low Level detection event(if selected Level
/// interrupt detection source.
unsigned int lowFallOrRiseHighSel;
} ExtIntMode;
typedef struct _GlitchDeBounceFilter {
///Select Glitch/Debounce filtering for PIO input
///each of 32 bit field represents one PIO line
///0 is Glitch, 1 is Debouncing
unsigned int filterSel;
///slow clock divider selection for Debouncing filter
unsigned int clkDivider:14;
} GlitchDebounceFilter;
//------------------------------------------------------------------------------
/// 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;
#if defined(AT91C_PIOA_AIMMR)
///Additional Interrupt Mode
ExtIntMode itMode;
#endif
#if defined(AT91C_PIOA_IFDGSR)
///Glitch/Debouncing filter
GlitchDebounceFilter inFilter;
#endif
} Pin;
//------------------------------------------------------------------------------
// Global Access Macros
//------------------------------------------------------------------------------
//Get Glitch input filter enable/disable status
#define PIO_GetIFSR(pPin) ((pPin)->pio->PIO_IFSR)
//Get Glitch/Deboucing selection status
#define PIO_GetIFDGSR(pPin) ((pPin)->pio->PIO_IFDGSR)
//Get Additional PIO interrupt mode mask status
#define PIO_GetAIMMR(pPin) ((pPin)->pio->PIO_AIMMR)
//Get Interrupt status
#define PIO_GetISR(pPin) ((pPin)->pio->PIO_ISR)
//Get Edge or Level selection status
#define PIO_GetELSR(pPin) ((pPin)->pio->PIO_ELSR)
//Get Fall/Rise or Low/High selection status
#define PIO_GetFRLHSR(pPin) ((pPin)->pio->PIO_FRLHSR)
//Get PIO Lock Status
#define PIO_GetLockStatus(pPin) ((pPin)->pio->PIO_LOCKSR)
//------------------------------------------------------------------------------
// 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

View file

@ -0,0 +1,461 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/// Disable traces for this file
#undef TRACE_LEVEL
#define TRACE_LEVEL 0
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "pio_it.h"
#include "pio.h"
#include <board.h>
#include <irq/irq.h>
#include <utility/assert.h>
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Local definitions
//------------------------------------------------------------------------------
/// \exclude
/// Maximum number of interrupt sources that can be defined. This
/// constant can be increased, but the current value is the smallest possible
/// that will be compatible with all existing projects.
#define MAX_INTERRUPT_SOURCES 7
//------------------------------------------------------------------------------
// Local types
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \exclude
/// Describes a PIO interrupt source, including the PIO instance triggering the
/// interrupt and the associated interrupt handler.
//------------------------------------------------------------------------------
typedef struct {
/// Pointer to the source pin instance.
const Pin *pPin;
/// Interrupt handler.
void (*handler)(const Pin *);
} InterruptSource;
//------------------------------------------------------------------------------
// Local variables
//------------------------------------------------------------------------------
/// List of interrupt sources.
static InterruptSource pSources[MAX_INTERRUPT_SOURCES];
/// Number of currently defined interrupt sources.
static unsigned int numSources;
//------------------------------------------------------------------------------
// Local functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Handles all interrupts on the given PIO controller.
/// \param id PIO controller ID.
/// \param pPio PIO controller base address.
//------------------------------------------------------------------------------
static void PioInterruptHandler(unsigned int id, AT91S_PIO *pPio)
{
unsigned int status;
unsigned int i;
// Read PIO controller status
status = pPio->PIO_ISR;
status &= pPio->PIO_IMR;
// Check pending events
if (status != 0) {
TRACE_DEBUG("PIO interrupt on PIO controller #%d\n\r", id);
// Find triggering source
i = 0;
while (status != 0) {
// There cannot be an unconfigured source enabled.
SANITY_CHECK(i < numSources);
// Source is configured on the same controller
if (pSources[i].pPin->id == id) {
// Source has PIOs whose statuses have changed
if ((status & pSources[i].pPin->mask) != 0) {
TRACE_DEBUG("Interrupt source #%d triggered\n\r", i);
pSources[i].handler(pSources[i].pPin);
status &= ~(pSources[i].pPin->mask);
}
}
i++;
}
}
}
//------------------------------------------------------------------------------
/// Generic PIO interrupt handler. Single entry point for interrupts coming
/// from any PIO controller (PIO A, B, C ...). Dispatches the interrupt to
/// the user-configured handlers.
//------------------------------------------------------------------------------
void PIO_IT_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;
IRQ_ConfigureIT(AT91C_ID_PIOA, priority, PIO_IT_InterruptHandler);
IRQ_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;
IRQ_ConfigureIT(AT91C_ID_PIOB, priority, PIO_IT_InterruptHandler);
IRQ_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;
IRQ_ConfigureIT(AT91C_ID_PIOC, priority, PIO_IT_InterruptHandler);
IRQ_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;
IRQ_ConfigureIT(AT91C_ID_PIOD, priority, PIO_IT_InterruptHandler);
IRQ_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;
IRQ_ConfigureIT(AT91C_ID_PIOE, priority, PIO_IT_InterruptHandler);
IRQ_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;
IRQ_ConfigureIT(AT91C_ID_PIOABCD, priority, PIO_IT_InterruptHandler);
IRQ_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;
IRQ_ConfigureIT(AT91C_ID_PIOABCDE, priority, PIO_IT_InterruptHandler);
IRQ_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;
IRQ_ConfigureIT(AT91C_ID_PIOCDE, priority, PIO_IT_InterruptHandler);
IRQ_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;
#if defined(AT91C_PIOA_AIMMR)
//PIO3 with additional interrupt support
//configure additional interrupt mode registers
if(pPin->mask&pPin->itMode.itMask) {
//enable additional interrupt mode
pPin->pio->PIO_AIMER = pPin->itMode.itMask;
if(pPin->mask&pPin->itMode.edgeLvlSel)
//if bit field of selected pin is 1, set as Level detection source
pPin->pio->PIO_LSR = pPin->itMode.edgeLvlSel;
else
//if bit field of selected pin is 0, set as Edge detection source
pPin->pio->PIO_ESR = ~(pPin->itMode.edgeLvlSel);
if(pPin->mask&pPin->itMode.lowFallOrRiseHighSel)
//if bit field of selected pin is 1, set as Rising Edge/High level detection event
pPin->pio->PIO_REHLSR = pPin->itMode.lowFallOrRiseHighSel;
else
//if bit field of selected pin is 0, set as Falling Edge/Low level detection event
pPin->pio->PIO_FELLSR = ~(pPin->itMode.lowFallOrRiseHighSel);
}
#endif
}
//------------------------------------------------------------------------------
/// 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;
#if defined(AT91C_PIOA_AIMMR)
if(pPin->mask & pPin->itMode.itMask)
//disable additional interrupt mode
pPin->pio->PIO_AIMDR = pPin->mask & pPin->itMode.itMask;
#endif
}
#if defined(cortexm3)
//------------------------------------------------------------------------------
/// Override cortex-m3's default PIOA irq handler
//------------------------------------------------------------------------------
void PIOA_IrqHandler(void)
{
#if defined(AT91C_ID_PIOA)
// Treat PIOA interrupts
PioInterruptHandler(AT91C_ID_PIOA, AT91C_BASE_PIOA);
#endif
}
//------------------------------------------------------------------------------
/// Override cortex-m3's default PIOB irq handler
//------------------------------------------------------------------------------
void PIOB_IrqHandler(void)
{
#if defined(AT91C_ID_PIOB)
// Treat PIOA interrupts
PioInterruptHandler(AT91C_ID_PIOB, AT91C_BASE_PIOB);
#endif
}
//------------------------------------------------------------------------------
/// Override cortex-m3's default PIOC irq handler
//------------------------------------------------------------------------------
void PIOC_IrqHandler(void)
{
#if defined(AT91C_ID_PIOC)
// Treat PIOA interrupts
PioInterruptHandler(AT91C_ID_PIOC, AT91C_BASE_PIOC);
#endif
}
#endif

View file

@ -0,0 +1,85 @@
/* ----------------------------------------------------------------------------
* 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);
extern void PIO_IT_InterruptHandler(void);
#endif //#ifndef PIO_IT_H

View file

@ -0,0 +1,122 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "pit.h"
#include <board.h>
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Initialize the Periodic Interval Timer to generate a tick at the specified
/// period, given the current master clock frequency.
/// \param period Period in µsecond.
/// \param pit_frequency Master clock frequency in MHz.
//------------------------------------------------------------------------------
void PIT_Init(unsigned int period, unsigned int pit_frequency)
{
AT91C_BASE_PITC->PITC_PIMR = period? (period * pit_frequency + 8) >> 4 : 0;
AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITEN;
}
//------------------------------------------------------------------------------
/// Set the Periodic Interval Value of the PIT.
/// \param piv PIV value to set.
//------------------------------------------------------------------------------
void PIT_SetPIV(unsigned int piv)
{
AT91C_BASE_PITC->PITC_PIMR = (AT91C_BASE_PITC->PITC_PIMR & AT91C_PITC_PIV)
| piv;
}
//------------------------------------------------------------------------------
/// Enables the PIT if this is not already the case.
//------------------------------------------------------------------------------
void PIT_Enable(void)
{
AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITEN;
}
//----------------------------------------------------------------------------
/// Enable the PIT periodic interrupt.
//----------------------------------------------------------------------------
void PIT_EnableIT(void)
{
AT91C_BASE_PITC->PITC_PIMR |= AT91C_PITC_PITIEN;
}
//------------------------------------------------------------------------------
/// Disables the PIT periodic interrupt.
//------------------------------------------------------------------------------
void PIT_DisableIT(void)
{
AT91C_BASE_PITC->PITC_PIMR &= ~AT91C_PITC_PITIEN;
}
//------------------------------------------------------------------------------
/// Returns the value of the PIT mode register.
/// \return PIT_MR value.
//------------------------------------------------------------------------------
unsigned int PIT_GetMode(void)
{
return AT91C_BASE_PITC->PITC_PIMR;
}
//------------------------------------------------------------------------------
/// Returns the value of the PIT status register, clearing it as a side effect.
/// \return PIT_SR value.
//------------------------------------------------------------------------------
unsigned int PIT_GetStatus(void)
{
return AT91C_BASE_PITC->PITC_PISR;
}
//------------------------------------------------------------------------------
/// Returns the value of the PIT Image Register, to read PICNT and CPIV without
/// clearing the current values.
/// \return PIT_PIIR value.
//------------------------------------------------------------------------------
unsigned int PIT_GetPIIR(void)
{
return AT91C_BASE_PITC->PITC_PIIR;
}
//------------------------------------------------------------------------------
/// Returns the value of the PIT Value Register, clearing it as a side effect.
/// \return PIT_PIVR value.
//------------------------------------------------------------------------------
unsigned int PIT_GetPIVR(void)
{
return AT91C_BASE_PITC->PITC_PIVR;
}

View file

@ -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

View file

@ -0,0 +1,188 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "pmc.h"
#include <board.h>
#include <utility/assert.h>
#include <utility/trace.h>
#ifdef CP15_PRESENT
#include <cp15/cp15.h>
#endif
#define MASK_STATUS 0x3FFFFFFC
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
#if defined(at91sam7l64) || defined(at91sam7l128)
//------------------------------------------------------------------------------
/// Sets the fast wake-up inputs that can get the device out of Wait mode.
/// \param inputs Fast wake-up inputs to enable.
//------------------------------------------------------------------------------
void PMC_SetFastWakeUpInputs(unsigned int inputs)
{
SANITY_CHECK((inputs & ~0xFF) == 0);
AT91C_BASE_PMC->PMC_FSMR = inputs;
}
#if !defined(__ICCARM__)
__attribute__ ((section (".ramfunc"))) // GCC
#endif
//------------------------------------------------------------------------------
/// Disables the main oscillator, making the device enter Wait mode.
//------------------------------------------------------------------------------
void PMC_DisableMainOscillatorForWaitMode(void)
{
AT91C_BASE_PMC->PMC_MOR = 0x37 << 16;
while ((AT91C_BASE_PMC->PMC_MOR & AT91C_PMC_MAINSELS) != AT91C_PMC_MAINSELS);
}
#endif
#if defined(at91sam7l)
//------------------------------------------------------------------------------
/// Disables the main oscillator when NOT running on it.
//------------------------------------------------------------------------------
void PMC_DisableMainOscillator(void)
{
AT91C_BASE_PMC->PMC_MOR = 0x37 << 16;
while ((AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MAINSELS) == AT91C_PMC_MAINSELS);
}
#endif
//------------------------------------------------------------------------------
/// Disables the processor clock
//------------------------------------------------------------------------------
void PMC_DisableProcessorClock(void)
{
AT91C_BASE_PMC->PMC_SCDR = AT91C_PMC_PCK;
while ((AT91C_BASE_PMC->PMC_SCSR & AT91C_PMC_PCK) != AT91C_PMC_PCK);
}
//------------------------------------------------------------------------------
/// Enables the clock of a peripheral. The peripheral ID (AT91C_ID_xxx) is used
/// to identify which peripheral is targetted.
/// Note that the ID must NOT be shifted (i.e. 1 << AT91C_ID_xxx).
/// \param id Peripheral ID (AT91C_ID_xxx).
//------------------------------------------------------------------------------
void PMC_EnablePeripheral(unsigned int id)
{
SANITY_CHECK(id < 32);
if ((AT91C_BASE_PMC->PMC_PCSR & (1 << id)) == (1 << id)) {
TRACE_INFO("PMC_EnablePeripheral: clock of peripheral"
" %u is already enabled\n\r",
id);
}
else {
AT91C_BASE_PMC->PMC_PCER = 1 << id;
}
}
//------------------------------------------------------------------------------
/// Disables the clock of a peripheral. The peripheral ID (AT91C_ID_xxx) is used
/// to identify which peripheral is targetted.
/// Note that the ID must NOT be shifted (i.e. 1 << AT91C_ID_xxx).
/// \param id Peripheral ID (AT91C_ID_xxx).
//------------------------------------------------------------------------------
void PMC_DisablePeripheral(unsigned int id)
{
SANITY_CHECK(id < 32);
if ((AT91C_BASE_PMC->PMC_PCSR & (1 << id)) != (1 << id)) {
TRACE_INFO("PMC_DisablePeripheral: clock of peripheral"
" %u is not enabled\n\r",
id);
}
else {
AT91C_BASE_PMC->PMC_PCDR = 1 << id;
}
}
//------------------------------------------------------------------------------
/// Enable all the periph clock via PMC
/// (Becareful of the last 2 bits, it is not periph clock)
//------------------------------------------------------------------------------
void PMC_EnableAllPeripherals(void)
{
AT91C_BASE_PMC->PMC_PCER = MASK_STATUS;
while( (AT91C_BASE_PMC->PMC_PCSR & MASK_STATUS) != MASK_STATUS);
TRACE_INFO("Enable all periph clocks\n\r");
}
//------------------------------------------------------------------------------
/// Disable all the periph clock via PMC
/// (Becareful of the last 2 bits, it is not periph clock)
//------------------------------------------------------------------------------
void PMC_DisableAllPeripherals(void)
{
AT91C_BASE_PMC->PMC_PCDR = MASK_STATUS;
while((AT91C_BASE_PMC->PMC_PCSR & MASK_STATUS) != 0);
TRACE_INFO("Disable all periph clocks\n\r");
}
//-----------------------------------------------------------------------------
/// Get Periph Status
//-----------------------------------------------------------------------------
unsigned int PMC_IsAllPeriphEnabled(void)
{
return (AT91C_BASE_PMC->PMC_PCSR == MASK_STATUS);
}
//-----------------------------------------------------------------------------
/// Get Periph Status
//-----------------------------------------------------------------------------
unsigned int PMC_IsPeriphEnabled(unsigned int id)
{
return (AT91C_BASE_PMC->PMC_PCSR & (1 << id));
}
//------------------------------------------------------------------------------
/// Put the CPU in Idle Mode for lower consumption
//------------------------------------------------------------------------------
void PMC_CPUInIdleMode(void)
{
#ifndef CP15_PRESENT
PMC_DisableProcessorClock();
#else
AT91C_BASE_PMC->PMC_SCDR = AT91C_PMC_PCK;
CP15_WaitForInterrupt();
#endif
}

View file

@ -0,0 +1,62 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef 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

View file

@ -0,0 +1,245 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "pwmc.h"
#include <board.h>
#include <utility/assert.h>
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Local functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Finds a prescaler/divisor couple to generate the desired frequency from
/// MCK.
/// Returns the value to enter in PWMC_MR or 0 if the configuration cannot be
/// met.
/// \param frequency Desired frequency in Hz.
/// \param mck Master clock frequency in Hz.
//------------------------------------------------------------------------------
static unsigned short FindClockConfiguration(
unsigned int frequency,
unsigned int mck)
{
unsigned int divisors[11] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024};
unsigned char divisor = 0;
unsigned int prescaler;
SANITY_CHECK(frequency < mck);
// Find prescaler and divisor values
prescaler = (mck / divisors[divisor]) / frequency;
while ((prescaler > 255) && (divisor < 11)) {
divisor++;
prescaler = (mck / divisors[divisor]) / frequency;
}
// Return result
if (divisor < 11) {
TRACE_DEBUG("Found divisor=%u and prescaler=%u for freq=%uHz\n\r",
divisors[divisor], prescaler, frequency);
return prescaler | (divisor << 8);
}
else {
return 0;
}
}
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures PWM a channel with the given parameters.
/// The PWM controller must have been clocked in the PMC prior to calling this
/// function.
/// Beware: this function disables the channel. It waits until disable is effective.
/// \param channel Channel number.
/// \param prescaler Channel prescaler.
/// \param alignment Channel alignment.
/// \param polarity Channel polarity.
//------------------------------------------------------------------------------
void PWMC_ConfigureChannel(
unsigned char channel,
unsigned int prescaler,
unsigned int alignment,
unsigned int polarity)
{
SANITY_CHECK(prescaler < AT91C_PWMC_CPRE_MCKB);
SANITY_CHECK((alignment & ~AT91C_PWMC_CALG) == 0);
SANITY_CHECK((polarity & ~AT91C_PWMC_CPOL) == 0);
// Disable channel (effective at the end of the current period)
if ((AT91C_BASE_PWMC->PWMC_SR & (1 << channel)) != 0) {
AT91C_BASE_PWMC->PWMC_DIS = 1 << channel;
while ((AT91C_BASE_PWMC->PWMC_SR & (1 << channel)) != 0);
}
// Configure channel
AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CMR = prescaler | alignment | polarity;
}
//------------------------------------------------------------------------------
/// Configures PWM clocks A & B to run at the given frequencies. This function
/// finds the best MCK divisor and prescaler values automatically.
/// \param clka Desired clock A frequency (0 if not used).
/// \param clkb Desired clock B frequency (0 if not used).
/// \param mck Master clock frequency.
//------------------------------------------------------------------------------
void PWMC_ConfigureClocks(unsigned int clka, unsigned int clkb, unsigned int mck)
{
unsigned int mode = 0;
unsigned int result;
// Clock A
if (clka != 0) {
result = FindClockConfiguration(clka, mck);
ASSERT(result != 0, "-F- Could not generate the desired PWM frequency (%uHz)\n\r", clka);
mode |= result;
}
// Clock B
if (clkb != 0) {
result = FindClockConfiguration(clkb, mck);
ASSERT(result != 0, "-F- Could not generate the desired PWM frequency (%uHz)\n\r", clkb);
mode |= (result << 16);
}
// Configure clocks
TRACE_DEBUG("Setting PWMC_MR = 0x%08X\n\r", mode);
AT91C_BASE_PWMC->PWMC_MR = mode;
}
//------------------------------------------------------------------------------
/// Sets the period value used by a PWM channel. This function writes directly
/// to the CPRD register if the channel is disabled; otherwise, it uses the
/// update register CUPD.
/// \param channel Channel number.
/// \param period Period value.
//------------------------------------------------------------------------------
void PWMC_SetPeriod(unsigned char channel, unsigned short period)
{
// If channel is disabled, write to CPRD
if ((AT91C_BASE_PWMC->PWMC_SR & (1 << channel)) == 0) {
AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CPRDR = period;
}
// Otherwise use update register
else {
AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CMR |= AT91C_PWMC_CPD;
AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CUPDR = period;
}
}
//------------------------------------------------------------------------------
/// Sets the duty cycle used by a PWM channel. This function writes directly to
/// the CDTY register if the channel is disabled; otherwise it uses the
/// update register CUPD.
/// Note that the duty cycle must always be inferior or equal to the channel
/// period.
/// \param channel Channel number.
/// \param duty Duty cycle value.
//------------------------------------------------------------------------------
void PWMC_SetDutyCycle(unsigned char channel, unsigned short duty)
{
SANITY_CHECK(duty <= AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CPRDR);
// SAM7S errata
#if defined(at91sam7s16) || defined(at91sam7s161) || defined(at91sam7s32) \
|| defined(at91sam7s321) || defined(at91sam7s64) || defined(at91sam7s128) \
|| defined(at91sam7s256) || defined(at91sam7s512)
ASSERT(duty > 0, "-F- Duty cycle value 0 is not permitted on SAM7S chips.\n\r");
ASSERT((duty > 1) || (AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CMR & AT91C_PWMC_CALG),
"-F- Duty cycle value 1 is not permitted in left-aligned mode on SAM7S chips.\n\r");
#endif
// If channel is disabled, write to CDTY
if ((AT91C_BASE_PWMC->PWMC_SR & (1 << channel)) == 0) {
AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CDTYR = duty;
}
// Otherwise use update register
else {
AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CMR &= ~AT91C_PWMC_CPD;
AT91C_BASE_PWMC->PWMC_CH[channel].PWMC_CUPDR = duty;
}
}
//------------------------------------------------------------------------------
/// Enables the given PWM channel. This does NOT enable the corresponding pin;
/// this must be done in the user code.
/// \param channel Channel number.
//------------------------------------------------------------------------------
void PWMC_EnableChannel(unsigned char channel)
{
AT91C_BASE_PWMC->PWMC_ENA = 1 << channel;
}
//------------------------------------------------------------------------------
/// Disables the given PWM channel.
/// Beware, channel will be effectively disabled at the end of the current period.
/// Application can check channel is disabled using the following wait loop:
/// while ((AT91C_BASE_PWMC->PWMC_SR & (1 << channel)) != 0);
/// \param channel Channel number.
//------------------------------------------------------------------------------
void PWMC_DisableChannel(unsigned char channel)
{
AT91C_BASE_PWMC->PWMC_DIS = 1 << channel;
}
//------------------------------------------------------------------------------
/// Enables the period interrupt for the given PWM channel.
/// \param channel Channel number.
//------------------------------------------------------------------------------
void PWMC_EnableChannelIt(unsigned char channel)
{
AT91C_BASE_PWMC->PWMC_IER = 1 << channel;
}
//------------------------------------------------------------------------------
/// Disables the period interrupt for the given PWM channel.
/// \param channel Channel number.
//------------------------------------------------------------------------------
void PWMC_DisableChannelIt(unsigned char channel)
{
AT91C_BASE_PWMC->PWMC_IDR = 1 << channel;
}

View file

@ -0,0 +1,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
///
/// Interface for configuration the Pulse Width Modulation Controller (PWM) peripheral.
///
/// !Usage
///
/// -# Configures PWM clocks A & B to run at the given frequencies using
/// PWMC_ConfigureClocks().
/// -# Configure PWMC channel using PWMC_ConfigureChannel(), PWMC_SetPeriod()
/// and PWMC_SetDutyCycle().
/// -# Enable & disable channel using PWMC_EnableChannel() and
/// PWMC_DisableChannel().
/// -# Enable & disable the period interrupt for the given PWM channel using
/// PWMC_EnableChannelIt() and PWMC_DisableChannelIt().
///
/// Please refer to the list of functions in the #Overview# tab of this unit
/// for more detailed information.
//------------------------------------------------------------------------------
#ifndef PWMC_H
#define PWMC_H
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void PWMC_ConfigureChannel(
unsigned char channel,
unsigned int prescaler,
unsigned int alignment,
unsigned int polarity);
extern void PWMC_ConfigureClocks
(unsigned int clka,
unsigned int clkb,
unsigned int mck);
extern void PWMC_SetPeriod(unsigned char channel, unsigned short period);
extern void PWMC_SetDutyCycle(unsigned char channel, unsigned short duty);
extern void PWMC_EnableChannel(unsigned char channel);
extern void PWMC_DisableChannel(unsigned char channel);
extern void PWMC_EnableChannelIt(unsigned char channel);
extern void PWMC_DisableChannelIt(unsigned char channel);
#endif //#ifndef PWMC_H

View file

@ -0,0 +1,176 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//-----------------------------------------------------------------------------
// Headers
//-----------------------------------------------------------------------------
#include <board.h>
//-----------------------------------------------------------------------------
// Defines
//-----------------------------------------------------------------------------
/// Keywords to write to the reset registers
#define RSTC_KEY_PASSWORD (0xA5 << 24)
//-----------------------------------------------------------------------------
// Exported functions
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
/// Configure the mode of the RSTC peripheral.
/// The configuration is computed by the lib (AT91C_RSTC_*).
/// \param rmr Desired mode configuration.
//-----------------------------------------------------------------------------
void RSTC_ConfigureMode(unsigned int rmr)
{
rmr &= ~AT91C_RSTC_KEY;
AT91C_BASE_RSTC->RSTC_RMR = rmr | RSTC_KEY_PASSWORD;
}
//-----------------------------------------------------------------------------
/// Enable/Disable the detection of a low level on the pin NRST as User Reset
/// \param enable 1 to enable & 0 to disable.
//-----------------------------------------------------------------------------
void RSTC_SetUserResetEnable(unsigned char enable)
{
unsigned int rmr = AT91C_BASE_RSTC->RSTC_RMR & (~AT91C_RSTC_KEY);
if (enable) {
rmr |= AT91C_RSTC_URSTEN;
}
else {
rmr &= ~AT91C_RSTC_URSTEN;
}
AT91C_BASE_RSTC->RSTC_RMR = rmr | RSTC_KEY_PASSWORD;
}
//-----------------------------------------------------------------------------
/// Enable/Disable the interrupt of a User Reset (USRTS bit in RSTC_RST).
/// \param enable 1 to enable & 0 to disable.
//-----------------------------------------------------------------------------
void RSTC_SetUserResetInterruptEnable(unsigned char enable)
{
unsigned int rmr = AT91C_BASE_RSTC->RSTC_RMR & (~AT91C_RSTC_KEY);
if (enable) {
rmr |= AT91C_RSTC_URSTIEN;
}
else {
rmr &= ~AT91C_RSTC_URSTIEN;
}
AT91C_BASE_RSTC->RSTC_RMR = rmr | RSTC_KEY_PASSWORD;
}
//-----------------------------------------------------------------------------
/// Setup the external reset length. The length is asserted during a time of
/// pow(2, powl+1) Slow Clock(32KHz). The duration is between 60us and 2s.
/// \param powl Power length defined.
//-----------------------------------------------------------------------------
void RSTC_SetExtResetLength(unsigned char powl)
{
unsigned int rmr = AT91C_BASE_RSTC->RSTC_RMR;
rmr &= ~(AT91C_RSTC_KEY | AT91C_RSTC_ERSTL);
rmr |= (powl << 8) & AT91C_RSTC_ERSTL;
AT91C_BASE_RSTC->RSTC_RMR = rmr | RSTC_KEY_PASSWORD;
}
//-----------------------------------------------------------------------------
/// Resets the processor.
//-----------------------------------------------------------------------------
void RSTC_ProcessorReset(void)
{
AT91C_BASE_RSTC->RSTC_RCR = AT91C_RSTC_PROCRST | RSTC_KEY_PASSWORD;
}
//-----------------------------------------------------------------------------
/// Resets the peripherals.
//-----------------------------------------------------------------------------
void RSTC_PeripheralReset(void)
{
AT91C_BASE_RSTC->RSTC_RCR = AT91C_RSTC_PERRST | RSTC_KEY_PASSWORD;
}
//-----------------------------------------------------------------------------
/// Asserts the NRST pin for external resets.
//-----------------------------------------------------------------------------
void RSTC_ExtReset(void)
{
AT91C_BASE_RSTC->RSTC_RCR = AT91C_RSTC_EXTRST | RSTC_KEY_PASSWORD;
}
//-----------------------------------------------------------------------------
/// Return NRST pin level ( 1 or 0 ).
//-----------------------------------------------------------------------------
unsigned char RSTC_GetNrstLevel(void)
{
if (AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_NRSTL) {
return 1;
}
return 0;
}
//-----------------------------------------------------------------------------
/// Returns 1 if at least one high-to-low transition of NRST (User Reset) has
/// been detected since the last read of RSTC_RSR.
//-----------------------------------------------------------------------------
unsigned char RSTC_IsUserResetDetected(void)
{
if (AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_URSTS) {
return 1;
}
return 0;
}
//-----------------------------------------------------------------------------
/// Return 1 if a software reset command is being performed by the reset
/// controller. The reset controller is busy.
//-----------------------------------------------------------------------------
unsigned char RSTC_IsBusy(void)
{
if (AT91C_BASE_RSTC->RSTC_RSR & AT91C_RSTC_SRCMP) {
return 1;
}
return 0;
}
//-----------------------------------------------------------------------------
/// Get the status
//-----------------------------------------------------------------------------
unsigned char RSTC_GetStatus(void)
{
return (AT91C_BASE_RSTC->RSTC_RSR);
}

View file

@ -0,0 +1,58 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef _RSTC_H
#define _RSTC_H
//-----------------------------------------------------------------------------
// Exported functions
//-----------------------------------------------------------------------------
extern void RSTC_ConfigureMode(unsigned int rmr);
extern void RSTC_SetUserResetEnable(unsigned char enable);
extern void RSTC_SetUserResetInterruptEnable(unsigned char enable);
extern void RSTC_SetExtResetLength(unsigned char powl);
extern void RSTC_ProcessorReset(void);
extern void RSTC_PeripheralReset(void);
extern void RSTC_ExtReset(void);
extern unsigned char RSTC_GetNrstLevel(void);
extern unsigned char RSTC_IsUserResetDetected(void);
extern unsigned char RSTC_IsBusy(void);
#endif // #ifndef _RSTC_H

View file

@ -0,0 +1,403 @@
/* ----------------------------------------------------------------------------
* 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 "rtc.h"
#include <board.h>
#include <utility/assert.h>
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Sets the RTC in either 12- or 24-hour mode.
/// \param mode Hour mode.
//------------------------------------------------------------------------------
void RTC_SetHourMode(unsigned int mode)
{
SANITY_CHECK((mode & 0xFFFFFFFE) == 0);
TRACE_DEBUG("RTC_SetHourMode()\n\r");
AT91C_BASE_RTC->RTC_MR = mode;
}
//------------------------------------------------------------------------------
/// Gets the RTC mode.
/// \return Hour mode.
//------------------------------------------------------------------------------
unsigned int RTC_GetHourMode()
{
unsigned int hmode;
TRACE_DEBUG("RTC_SetHourMode()\n\r");
hmode = AT91C_BASE_RTC->RTC_MR;
hmode &= 0xFFFFFFFE;
return hmode;
}
//------------------------------------------------------------------------------
/// Enables the selected interrupt sources of the RTC.
/// \param sources Interrupt sources to enable.
//------------------------------------------------------------------------------
void RTC_EnableIt(unsigned int sources)
{
SANITY_CHECK((sources & ~0x1F) == 0);
TRACE_DEBUG("RTC_EnableIt()\n\r");
AT91C_BASE_RTC->RTC_IER = sources;
}
//------------------------------------------------------------------------------
/// Disables the selected interrupt sources of the RTC.
/// \param sources Interrupt sources to disable.
//------------------------------------------------------------------------------
void RTC_DisableIt(unsigned int sources)
{
SANITY_CHECK((sources & ~0x1F) == 0);
TRACE_DEBUG("RTC_DisableIt()\n\r");
AT91C_BASE_RTC->RTC_IDR = sources;
}
//------------------------------------------------------------------------------
/// Sets the current time in the RTC.
/// \param hour Current hour in 24 hour mode.
/// \param minute Current minute.
/// \param second Current second.
/// \return 0 sucess, 1 fail to set
//------------------------------------------------------------------------------
int RTC_SetTime(unsigned char hour, unsigned char minute, unsigned char second)
{
unsigned int time=0;
unsigned char hour_bcd;
unsigned char min_bcd;
unsigned char sec_bcd;
TRACE_DEBUG("RTC_SetTime(%02d:%02d:%02d)\n\r", hour, minute, second);
// if 12-hour mode, set AMPM bit
if ((AT91C_BASE_RTC->RTC_MR & AT91C_RTC_HRMOD) == AT91C_RTC_HRMOD) {
if (hour > 12) {
hour -= 12;
time |= AT91C_RTC_AMPM;
}
}
hour_bcd = (hour%10) | ((hour/10)<<4);
min_bcd = (minute%10) | ((minute/10)<<4);
sec_bcd = (second%10) | ((second/10)<<4);
//value overflow
if((hour_bcd & (unsigned char)(~RTC_HOUR_BIT_LEN_MASK)) |
(min_bcd & (unsigned char)(~RTC_MIN_BIT_LEN_MASK)) |
(sec_bcd & (unsigned char)(~RTC_SEC_BIT_LEN_MASK)))
return 1;
time = sec_bcd | (min_bcd << 8) | (hour_bcd<<16);
// time |= ((hour % 10) << 16) | ((hour / 10) << 20);
// Set time
//if((AT91C_BASE_RTC->RTC_SR & AT91C_RTC_SECEV) != AT91C_RTC_SECEV) return 1;
while ((AT91C_BASE_RTC->RTC_SR & AT91C_RTC_SECEV) != AT91C_RTC_SECEV);//wait from previous set
AT91C_BASE_RTC->RTC_CR |= AT91C_RTC_UPDTIM;
while ((AT91C_BASE_RTC->RTC_SR & AT91C_RTC_ACKUPD) != AT91C_RTC_ACKUPD);
AT91C_BASE_RTC->RTC_SCCR = AT91C_RTC_ACKUPD;
AT91C_BASE_RTC->RTC_TIMR = time;
AT91C_BASE_RTC->RTC_CR &= ~AT91C_RTC_UPDTIM;
AT91C_BASE_RTC->RTC_SCCR |= AT91C_RTC_SECEV;//clear SECENV in SCCR
return (int)(AT91C_BASE_RTC->RTC_VER & AT91C_RTC_NVTIM);
}
//------------------------------------------------------------------------------
/// Retrieves the current time as stored in the RTC in several variables.
/// \param pHour If not null, current hour is stored in this variable.
/// \param pMinute If not null, current minute is stored in this variable.
/// \param pSecond If not null, current second is stored in this variable.
//------------------------------------------------------------------------------
void RTC_GetTime(
unsigned char *pHour,
unsigned char *pMinute,
unsigned char *pSecond)
{
unsigned int time;
TRACE_DEBUG("RTC_GetTime()\n\r");
// Get current RTC time
time = AT91C_BASE_RTC->RTC_TIMR;
while (time != AT91C_BASE_RTC->RTC_TIMR) {
time = AT91C_BASE_RTC->RTC_TIMR;
}
// Hour
if (pHour) {
*pHour = ((time & 0x00300000) >> 20) * 10
+ ((time & 0x000F0000) >> 16);
if ((time & AT91C_RTC_AMPM) == AT91C_RTC_AMPM) {
*pHour += 12;
}
}
// Minute
if (pMinute) {
*pMinute = ((time & 0x00007000) >> 12) * 10
+ ((time & 0x00000F00) >> 8);
}
// Second
if (pSecond) {
*pSecond = ((time & 0x00000070) >> 4) * 10
+ (time & 0x0000000F);
}
}
//------------------------------------------------------------------------------
/// Sets a time alarm on the RTC. The match is performed only on the provided
/// variables; setting all pointers to 0 disables the time alarm.
/// Note: in AM/PM mode, the hour value must have bit #7 set for PM, cleared for
/// AM (as expected in the time registers).
/// \param pHour If not null, the time alarm will hour-match this value.
/// \param pMinute If not null, the time alarm will minute-match this value.
/// \param pSecond If not null, the time alarm will second-match this value.
/// \return 0 success, 1 fail to set
//------------------------------------------------------------------------------
int RTC_SetTimeAlarm(
unsigned char *pHour,
unsigned char *pMinute,
unsigned char *pSecond)
{
unsigned int alarm = 0;
TRACE_DEBUG("RTC_SetTimeAlarm()\n\r");
// Hour
if (pHour) {
alarm |= AT91C_RTC_HOUREN | ((*pHour / 10) << 20) | ((*pHour % 10) << 16);
}
// Minute
if (pMinute) {
alarm |= AT91C_RTC_MINEN | ((*pMinute / 10) << 12) | ((*pMinute % 10) << 8);
}
// Second
if (pSecond) {
alarm |= AT91C_RTC_SECEN | ((*pSecond / 10) << 4) | (*pSecond % 10);
}
AT91C_BASE_RTC->RTC_TIMALR = alarm;
return (int)(AT91C_BASE_RTC->RTC_VER & AT91C_RTC_NVTIMALR);
}
//------------------------------------------------------------------------------
/// Retrieves the current year, month and day from the RTC. Month, day and week
/// values are numbered starting at 1.
/// \param pYear Current year (optional).
/// \param pMonth Current month (optional).
/// \param pDay Current day (optional).
/// \param pWeek Current day in current week (optional).
//------------------------------------------------------------------------------
void RTC_GetDate(
unsigned short *pYear,
unsigned char *pMonth,
unsigned char *pDay,
unsigned char *pWeek)
{
unsigned int date;
// Get current date (multiple reads are necessary to insure a stable value)
do {
date = AT91C_BASE_RTC->RTC_CALR;
}
while (date != AT91C_BASE_RTC->RTC_CALR);
// Retrieve year
if (pYear) {
*pYear = (((date >> 4) & 0x7) * 1000)
+ ((date & 0xF) * 100)
+ (((date >> 12) & 0xF) * 10)
+ ((date >> 8) & 0xF);
}
// Retrieve month
if (pMonth) {
*pMonth = (((date >> 20) & 1) * 10) + ((date >> 16) & 0xF);
}
// Retrieve day
if (pDay) {
*pDay = (((date >> 28) & 0x3) * 10) + ((date >> 24) & 0xF);
}
// Retrieve week
if (pWeek) {
*pWeek = ((date >> 21) & 0x7);
}
}
//------------------------------------------------------------------------------
/// Sets the current year, month and day in the RTC. Month, day and week values
/// must be numbered starting from 1.
/// \param year Current year.
/// \param month Current month.
/// \param day Current day.
/// \param week Day number in current week.
/// \return 0 success, 1 fail to set
//------------------------------------------------------------------------------
int RTC_SetDate(
unsigned short year,
unsigned char month,
unsigned char day,
unsigned char week)
{
unsigned int date;
unsigned char cent_bcd;
unsigned char year_bcd;
unsigned char month_bcd;
unsigned char day_bcd;
unsigned char week_bcd;
cent_bcd = ((year/100)%10) | ((year/1000)<<4);
year_bcd = (year%10) | ((year/10)%10);
month_bcd = ((month%10) | (month/10)<<4);
day_bcd = ((day%10) | (day/10)<<4);
week_bcd = ((week%10) | (week/10)<<4);
//value over flow
if((cent_bcd & (unsigned char)(~RTC_CENT_BIT_LEN_MASK)) |
(year_bcd & (unsigned char)(~RTC_YEAR_BIT_LEN_MASK)) |
(month_bcd & (unsigned char)(~RTC_MONTH_BIT_LEN_MASK)) |
(week_bcd & (unsigned char)(~RTC_WEEK_BIT_LEN_MASK)) |
(day_bcd & (unsigned char)(~RTC_DATE_BIT_LEN_MASK)))
return 1;
// Convert values to date register value
date = cent_bcd |
(year_bcd << 8) |
(month_bcd << 16) |
(week_bcd << 21) |
(day_bcd << 24);
// Update calendar register
//if((AT91C_BASE_RTC->RTC_SR & AT91C_RTC_SECEV) != AT91C_RTC_SECEV) return 1;
while ((AT91C_BASE_RTC->RTC_SR & AT91C_RTC_SECEV) != AT91C_RTC_SECEV);//wait from previous set
AT91C_BASE_RTC->RTC_CR |= AT91C_RTC_UPDCAL;
while ((AT91C_BASE_RTC->RTC_SR & AT91C_RTC_ACKUPD) != AT91C_RTC_ACKUPD);
AT91C_BASE_RTC->RTC_SCCR = AT91C_RTC_ACKUPD;
AT91C_BASE_RTC->RTC_CALR = date;
AT91C_BASE_RTC->RTC_CR &= ~AT91C_RTC_UPDCAL;
AT91C_BASE_RTC->RTC_SCCR |= AT91C_RTC_SECEV;//clear SECENV in SCCR
return (int)(AT91C_BASE_RTC->RTC_VER & AT91C_RTC_NVCAL);
}
//------------------------------------------------------------------------------
/// Sets a date alarm in the RTC. The alarm will match only the provided values;
/// passing a null-pointer disables the corresponding field match.
/// \param pMonth If not null, the RTC alarm will month-match this value.
/// \param pDay If not null, the RTC alarm will day-match this value.
/// \return 0 success, 1 fail to set
//------------------------------------------------------------------------------
int RTC_SetDateAlarm(unsigned char *pMonth, unsigned char *pDay)
{
unsigned int alarm = 0x01010000;
TRACE_DEBUG("RTC_SetDateAlarm()\n\r");
// Compute alarm field value
if (pMonth) {
alarm |= AT91C_RTC_MONTHEN | ((*pMonth / 10) << 20) | ((*pMonth % 10) << 16);
}
if (pDay) {
alarm |= AT91C_RTC_DATEEN | ((*pDay / 10) << 28) | ((*pDay % 10) << 24);
}
// Set alarm
AT91C_BASE_RTC->RTC_CALALR = alarm;
return (int)(AT91C_BASE_RTC->RTC_VER & AT91C_RTC_NVCALALR);
}
//------------------------------------------------------------------------------
/// Clear flag bits of status clear command register in the RTC.
/// \param mask Bits mask of cleared events
//------------------------------------------------------------------------------
void RTC_ClearSCCR(unsigned int mask)
{
// Clear all flag bits in status clear command register
mask &= AT91C_RTC_ACKUPD | AT91C_RTC_ALARM | AT91C_RTC_SECEV | \
AT91C_RTC_TIMEV | AT91C_RTC_CALEV;
AT91C_BASE_RTC->RTC_SCCR = mask;
}
//------------------------------------------------------------------------------
/// Get flag bits of status register in the RTC.
/// \param mask Bits mask of Status Register
/// \return Status register & mask
//------------------------------------------------------------------------------
unsigned int RTC_GetSR(unsigned int mask)
{
unsigned int event;
event = AT91C_BASE_RTC->RTC_SR;
return (event & mask);
}

View file

@ -0,0 +1,90 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef RTC_H
#define RTC_H
//------------------------------------------------------------------------------
// Macro used
//------------------------------------------------------------------------------
#define RTC_HOUR_BIT_LEN_MASK 0x3F
#define RTC_MIN_BIT_LEN_MASK 0x7F
#define RTC_SEC_BIT_LEN_MASK 0x7F
#define RTC_CENT_BIT_LEN_MASK 0x7F
#define RTC_YEAR_BIT_LEN_MASK 0xFF
#define RTC_MONTH_BIT_LEN_MASK 0x1F
#define RTC_DATE_BIT_LEN_MASK 0x3F
#define RTC_WEEK_BIT_LEN_MASK 0x07
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void RTC_SetHourMode(unsigned int mode);
extern unsigned int RTC_GetHourMode();
extern void RTC_EnableIt(unsigned int sources);
extern void RTC_DisableIt(unsigned int sources);
extern int RTC_SetTime(
unsigned char hour,
unsigned char minute,
unsigned char second);
extern void RTC_GetTime(
unsigned char *pHour,
unsigned char *pMinute,
unsigned char *pSecond);
extern int RTC_SetTimeAlarm(
unsigned char *pHour,
unsigned char *pMinute,
unsigned char *pSecond);
void RTC_GetDate(
unsigned short *pYear,
unsigned char *pMonth,
unsigned char *pDay,
unsigned char *pWeek);
extern int RTC_SetDate(
unsigned short year,
unsigned char month,
unsigned char day,
unsigned char week);
extern int RTC_SetDateAlarm(unsigned char *pMonth, unsigned char *pDay);
extern void RTC_ClearSCCR(unsigned int mask);
extern unsigned int RTC_GetSR(unsigned int mask);
#endif //#ifndef RTC_H

View file

@ -0,0 +1,93 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "rtt.h"
#include <utility/assert.h>
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Changes the prescaler value of the given RTT and restarts it. This function
/// disables RTT interrupt sources.
/// \param rtt Pointer to a AT91S_RTTC instance.
/// \param prescaler Prescaler value for the RTT.
//------------------------------------------------------------------------------
void RTT_SetPrescaler(AT91S_RTTC *rtt, unsigned short prescaler)
{
rtt->RTTC_RTMR = (prescaler | AT91C_RTTC_RTTRST);
}
//------------------------------------------------------------------------------
/// Returns the current value of the RTT timer value.
/// \param rtt Pointer to a AT91S_RTTC instance.
//------------------------------------------------------------------------------
unsigned int RTT_GetTime(AT91S_RTTC *rtt)
{
return rtt->RTTC_RTVR;
}
//------------------------------------------------------------------------------
/// Enables the specified RTT interrupt sources.
/// \param rtt Pointer to a AT91S_RTTC instance.
/// \param sources Bitmask of interrupts to enable.
//------------------------------------------------------------------------------
void RTT_EnableIT(AT91S_RTTC *rtt, unsigned int sources)
{
ASSERT((sources & 0x0004FFFF) == 0,
"RTT_EnableIT: Wrong sources value.\n\r");
rtt->RTTC_RTMR |= sources;
}
//------------------------------------------------------------------------------
/// Returns the status register value of the given RTT.
/// \param rtt Pointer to an AT91S_RTTC instance.
//------------------------------------------------------------------------------
unsigned int RTT_GetStatus(AT91S_RTTC *rtt)
{
return rtt->RTTC_RTSR;
}
//------------------------------------------------------------------------------
/// Configures the RTT to generate an alarm at the given time.
/// \param pRtt Pointer to an AT91S_RTTC instance.
/// \param time Alarm time.
//------------------------------------------------------------------------------
void RTT_SetAlarm(AT91S_RTTC *pRtt, unsigned int time)
{
SANITY_CHECK(time > 0);
pRtt->RTTC_RTAR = time - 1;
}

View file

@ -0,0 +1,76 @@
/* ----------------------------------------------------------------------------
* 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
///
/// Implementation of RTT Real Time Timer controller.
///
/// !Contents
///
/// Please refer to the list of functions in the #Overview# tab of this unit
/// for more detailed information.
//-----------------------------------------------------------------------------
#ifndef RTT_H
#define RTT_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
#ifndef AT91C_BASE_RTTC
#define AT91C_BASE_RTTC AT91C_BASE_RTTC0
#endif
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void RTT_SetPrescaler(AT91S_RTTC *rtt, unsigned short prescaler);
extern unsigned int RTT_GetTime(AT91S_RTTC *rtt);
extern void RTT_EnableIT(AT91S_RTTC *rtt, unsigned int sources);
extern unsigned int RTT_GetStatus(AT91S_RTTC *rtt);
extern void RTT_SetAlarm(AT91S_RTTC *pRtt, unsigned int time);
#endif //#ifndef RTT_H

View file

@ -0,0 +1,68 @@
/* ----------------------------------------------------------------------------
* 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 "shdwc.h"
#include <utility/assert.h>
#include <utility/trace.h>
#include <utility/util.h>
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configure the Shut Down and do it
/// \param rtt_enable
/// \param wk0_mode
/// \param wk0_debounce
//------------------------------------------------------------------------------
void SHDWC_DoShutDown(
unsigned char rtt_enable,
unsigned char wk0_mode,
unsigned char wk0_debounce
)
{
AT91C_BASE_SHDWC->SHDWC_SHMR = (rtt_enable << 16) |
wk0_mode | ( (wk0_debounce & 0xF) << 4);
AT91C_BASE_SHDWC->SHDWC_SHCR = (0xA5 << 24) | 1;
}
//------------------------------------------------------------------------------
/// Get Status
//------------------------------------------------------------------------------
unsigned int SHDWC_GetStatus(void)
{
return AT91C_BASE_SHDWC->SHDWC_SHSR;
}

View file

@ -0,0 +1,43 @@
/* ----------------------------------------------------------------------------
* 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 SHDWC_H
#define SHDWC_H
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void SHDWC_DoShutDown(unsigned char rtt_enable,
unsigned char wk0_mode,
unsigned char wk0_debounce);
unsigned int SHDWC_GetStatus(void);
#endif //#ifndef SHDWC_H

View file

@ -0,0 +1,192 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "slcdc.h"
#include <board.h>
#include <utility/assert.h>
#include <string.h>
//------------------------------------------------------------------------------
// Local definitions
//------------------------------------------------------------------------------
/// Size of SLCDC buffer in bytes.
#define BUFFER_SIZE 320
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Initializes the Segment LCD controller.
/// \param commons Number of commons used by the display.
/// \param segments Number of segments used by the display.
/// \param bias Bias value.
/// \param timeSetting Buffer timing value.
//------------------------------------------------------------------------------
void SLCDC_Configure(
unsigned int commons,
unsigned int segments,
unsigned int bias,
unsigned int timeSetting)
{
SANITY_CHECK((commons > 0) && (commons <= 10));
SANITY_CHECK((segments > 0) && (segments <= 40));
SANITY_CHECK((bias & ~AT91C_SLCDC_BIAS) == 0);
SANITY_CHECK((timeSetting & ~(0xF << 16)) == 0);
SANITY_CHECK((timeSetting >> 16) < 0x0A);
// Enable peripheral clock
AT91C_BASE_PMC->PMC_PCER = 1 << AT91C_ID_SLCD;
AT91C_BASE_SLCDC->SLCDC_MR = (commons - 1) | ((segments - 1) << 8) | bias | timeSetting;
}
//------------------------------------------------------------------------------
/// Clears the SLCD display buffer.
//------------------------------------------------------------------------------
void SLCDC_Clear(void)
{
memset((void *) AT91C_BASE_SLCDC->SLCDC_MEM, 0, BUFFER_SIZE);
}
//------------------------------------------------------------------------------
/// Enables the SLCD controller.
//------------------------------------------------------------------------------
void SLCDC_Enable(void)
{
AT91C_BASE_SLCDC->SLCDC_CR = AT91C_SLCDC_LCDEN;
while (AT91C_BASE_SLCDC -> SLCDC_SR != AT91C_SLCDC_ENA);
}
//------------------------------------------------------------------------------
/// Disables the SLCD controller.
//------------------------------------------------------------------------------
void SLCDC_Disable(void)
{
AT91C_BASE_SLCDC->SLCDC_CR = AT91C_SLCDC_LCDDIS;
}
//------------------------------------------------------------------------------
/// Enables the SLCD low power mode.
//------------------------------------------------------------------------------
void SLCDC_EnableLowPowerMode(void)
{
unsigned int value;
value = AT91C_BASE_SLCDC->SLCDC_MR;
value &= ~AT91C_SLCDC_LPMODE;
value |=AT91C_SLCDC_LPMODE;
AT91C_BASE_SLCDC->SLCDC_MR = value;
}
//------------------------------------------------------------------------------
/// Disables the SLCD low power mode
//------------------------------------------------------------------------------
void SLCDC_DisableLowPowerMode(void)
{
unsigned int value;
value = AT91C_BASE_SLCDC->SLCDC_MR;
value &= ~AT91C_SLCDC_LPMODE;
AT91C_BASE_SLCDC->SLCDC_MR = value;
}
//------------------------------------------------------------------------------
/// Adjusts the frame frequency. Frequency = FsCLK / (prescaler * divider . NCOM)
/// \param prescalerValue Prescaler value
/// \param dividerValue Divider value
//------------------------------------------------------------------------------
void SLCDC_SetFrameFreq(unsigned int prescalerValue, unsigned int dividerValue)
{
SANITY_CHECK((prescalerValue & ~AT91C_SLCDC_PRESC) == 0);
SANITY_CHECK((dividerValue & (~(0x07 << 8))) == 0);
AT91C_BASE_SLCDC->SLCDC_FRR = prescalerValue | dividerValue;
}
//------------------------------------------------------------------------------
/// Sets the display mode (normal/force off/force on/blinking).
/// \param mode Display mode to be set
//------------------------------------------------------------------------------
void SLCDC_SetDisplayMode(unsigned int mode)
{
unsigned int value;
SANITY_CHECK(mode < 8);
value = AT91C_BASE_SLCDC->SLCDC_DR;
value &= ~AT91C_SLCDC_DISPMODE;
value |= mode;
AT91C_BASE_SLCDC->SLCDC_DR = value;
}
//------------------------------------------------------------------------------
/// Adjusts the display blinking frequency.
/// Blinking frequency = Frame Frequency / LCDBLKFREQ.
/// \param frequency Frequency value.
//------------------------------------------------------------------------------
void SLCDC_SetBlinkFreq(unsigned int frequency)
{
unsigned int value;
SANITY_CHECK((frequency & ~(0xFF << 8)) == 0);
value = AT91C_BASE_SLCDC->SLCDC_DR;
value &= ~AT91C_SLCDC_BLKFREQ;
value |= frequency;
AT91C_BASE_SLCDC->SLCDC_DR = frequency;
}
//------------------------------------------------------------------------------
/// Enables the selected SLCDC interrupt sources.
/// \param sources Interrupt sources to enable.
//------------------------------------------------------------------------------
void SLCDC_EnableInterrupts(unsigned int sources)
{
SANITY_CHECK((sources & 0xFFFFFFFA) == 0);
AT91C_BASE_SLCDC->SLCDC_IER = sources;
}
//------------------------------------------------------------------------------
/// Disables the selected SLCDC interrupt sources.
/// \param sources Interrupt sources to disable.
//------------------------------------------------------------------------------
void SLCDC_DisableInterrupts(unsigned int sources)
{
SANITY_CHECK((sources & 0xFFFFFFFA) == 0);
AT91C_BASE_SLCDC->SLCDC_IDR = sources;
}

View file

@ -0,0 +1,93 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
///
/// !Purpose
///
/// Interface for configuration the Segment LCD Controller (SLCDC) peripheral.
///
/// !Usage
///
/// -# Initializes the Segment LCD controller using SLCDC_Configure().
/// -# Clears the SLCD display buffer using SLCDC_Clear().
/// -# Enable & disable SLCD controller using SLCDC_Enable() and SLCDC_Disable().
/// -# Enables & disable the SLCD low power mode using SLCDC_EnableLowPowerMode ()
/// and SLCDC_DisableLowPowerMode().
/// -# Adjusts the frame frequency using SLCDC_SetFrameFreq().
/// -# Sets the display mode (normal/force off/force on/blinking) using
/// SLCDC_SetDisplayMode().
/// -# Adjusts the display blinking frequency using SLCDC_SetBlinkFreq().
/// -# Enables & disable the selected SLCDC interrupt sources using
/// SLCDC_EnableInterrupts() and SLCDC_DisableInterrupts().
//------------------------------------------------------------------------------
#ifndef SLCDC_H
#define SLCDC_H
//------------------------------------------------------------------------------
// Global definitions
//------------------------------------------------------------------------------
/// Number of segments in SLCD.
#define S7LEKLCD_NUM_SEGMENTS 40
/// Number of commons in SLCD.
#define S7LEKLCD_NUM_COMMONS 10
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void SLCDC_Configure(
unsigned int commons,
unsigned int segments,
unsigned int bias,
unsigned int timeSetting);
extern void SLCDC_Clear(void);
extern void SLCDC_Enable(void);
extern void SLCDC_Disable(void);
extern void SLCDC_SetFrameFreq(
unsigned int prescalerValue,
unsigned int dividerValue);
extern void SLCDC_SetDisplayMode(unsigned int mode);
extern void SLCDC_SetBlinkFreq(unsigned int frequency);
extern void SLCDC_EnableInterrupts(unsigned int sources);
extern void SLCDC_DisableInterrupts(unsigned int sources);
#endif //#ifndef SLCDC_H

View file

@ -0,0 +1,251 @@
/* ----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------
*/
#if defined(at91cap9)
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "slck.h"
#include <utility/assert.h>
#include <utility/trace.h>
#include <utility/util.h>
//------------------------------------------------------------------------------
// Local definitions
//------------------------------------------------------------------------------
/// Start Up Time Slow Clock 32K Oscillator // see DC characteritics in Datasheet
#define T_ST_SLCK_32K_IN_MS 1200
/// Start Up Time Slow Clock RC Oscillator // see DC characteritics in Datasheet
#define T_ST_SLCK_RC_IN_US 75
#define FREQ_SLCK_32K 32768 // see DC characteritics in Datasheet
#define MIN_FREQ_SLCK_RC 20000 // see DC characteritics in Datasheet
#define TIME_5_CYCLES_32K_IN_US ((2 * 5 * 1000000) / FREQ_SLCK_32K)
#define TIME_5_CYCLES_RC_IN_US ((2 * 5 * 1000000) / MIN_FREQ_SLCK_RC)
//------------------------------------------------------------------------------
// Local functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Wait time in ms
//------------------------------------------------------------------------------
// not precise, depends on the compiler and on the options
static void WaitTimeInMs(unsigned int pck, unsigned int time_ms)
{
register unsigned int i = 0;
i = (pck / 1000) * time_ms;
i = i / 4;
while(i--);
}
//------------------------------------------------------------------------------
/// Wait time in us
//------------------------------------------------------------------------------
// not precise, depends on the compiler and on the options
static void WaitTimeInUs(unsigned int pck, unsigned int time_us)
{
volatile unsigned int i = 0;
i = (pck / 1000000) * time_us;
i = i / 4;
while(i--);
}
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Return 1 if the slow clock is 32k
//------------------------------------------------------------------------------
unsigned char SLCK_Is32k(void)
{
return ((*AT91C_SYS_SLCKSEL & AT91C_SLCKSEL_OSCSEL) != 0);
}
//------------------------------------------------------------------------------
/// Configure the 32kHz oscillator for the slow clock
//------------------------------------------------------------------------------
void SLCK_RCto32k(void)
{
// Check that the master clock has a different source than slow clock. If no,
if( (AT91C_BASE_PMC->PMC_MCKR & AT91C_PMC_CSS) == 0)
{
TRACE_WARNING("The master clock use the slow clock. " \
"Not possible to change Slow clock\n\r");
return;
}
// Check that the slow clock source is RC
if( SLCK_Is32k() )
{
TRACE_WARNING("The slow clock is already the external 32.768kHz crystal\n\r");
return;
}
// Enable the 32,768 Hz oscillator by setting the bit OSC32EN to 1.
*AT91C_SYS_SLCKSEL |= AT91C_SLCKSEL_OSC32EN;
// Wait 32,768 Hz Startup Time for clock stabilization (software loop).
WaitTimeInMs(BOARD_MCK*2, T_ST_SLCK_32K_IN_MS);
// Switch from internal RC to 32,768 Hz oscillator by setting the bit OSCSEL to 1.
*AT91C_SYS_SLCKSEL |= AT91C_SLCKSEL_OSCSEL;
// Wait 5 slow clock cycles for internal resynchronization.
WaitTimeInUs(BOARD_MCK*2, TIME_5_CYCLES_32K_IN_US);
// Disable the RC oscillator by setting the bit RCEN to 0.
*AT91C_SYS_SLCKSEL &= (0xFFFFFFFF ^ AT91C_SLCKSEL_RCEN);
TRACE_INFO("The slow clock is now the external 32.768kHz crystal\n\r");
}
//------------------------------------------------------------------------------
/// Configure the RC oscillator for the slow clock
//------------------------------------------------------------------------------
void SLCK_32ktoRC(void)
{
// Check that the master clock has a different source than slow clock.
if( (AT91C_BASE_PMC->PMC_MCKR & AT91C_PMC_CSS) == 0)
{
TRACE_WARNING("The master clock use the slow clock. " \
"Not possible to change Slow clock\n\r");
return;
}
// Check that the slow clock source is RC
if( !SLCK_Is32k() )
{
TRACE_WARNING("The slow clock is already the internal RC oscillator\n\r");
return;
}
// Enable the internal RC oscillator by setting the bit RCEN to 1
*AT91C_SYS_SLCKSEL |= AT91C_SLCKSEL_RCEN;
// Wait internal RC Startup Time for clock stabilization (software loop).
WaitTimeInUs(BOARD_MCK*2, T_ST_SLCK_RC_IN_US);
// Switch from 32768 Hz oscillator to internal RC by setting the bit OSCSEL to 0.
*AT91C_SYS_SLCKSEL &= (0xFFFFFFFF ^ AT91C_SLCKSEL_OSCSEL);
// Wait 5 slow clock cycles for internal resynchronization.
WaitTimeInUs(BOARD_MCK*2, TIME_5_CYCLES_RC_IN_US);
// Disable the 32768 Hz oscillator by setting the bit OSC32EN to 0.
*AT91C_SYS_SLCKSEL &= (0xFFFFFFFF ^ AT91C_SLCKSEL_OSC32EN);
TRACE_INFO("The slow clock is now the internal RC oscillator\n\r");
}
//------------------------------------------------------------------------------
/// by pass the 32kHz oscillator
//------------------------------------------------------------------------------
void SLCK_bypass32Kosc(void)
{
// Enable the bypass path OSC32BYP bit set to 1
*AT91C_SYS_SLCKSEL |= AT91C_SLCKSEL_OSC32BYP;
// Disable the 32,768 Hz oscillator by setting the bit OSC32EN to 0
*AT91C_SYS_SLCKSEL &= (0xFFFFFFFF ^ AT91C_SLCKSEL_OSC32EN);
}
//------------------------------------------------------------------------------
/// set Slow Clock Mode
//------------------------------------------------------------------------------
#define TIMEOUT 10000000
void SLCK_UtilSetSlowClockMode(unsigned int timeInSlowClockMode)
{
unsigned int oldPll;
unsigned int oldMck;
unsigned int timeout = 0;
// Save previous values for PLL A and Master Clock configuration
oldPll = AT91C_BASE_CKGR->CKGR_PLLAR;
oldMck = AT91C_BASE_PMC->PMC_MCKR;
// Slow clock is selected for Master Clock
// 32kKz / 64 = 500Hz
// PCK = 500Hz, MCK = 250 MHz
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_CSS_SLOW_CLK | AT91C_PMC_PRES_CLK_64 | AT91C_PMC_MDIV_2;
timeout = 0;
while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) && timeout++ < TIMEOUT);
// Stop PLL A
// MULA: PLL A Multiplier 0 = The PLL A is deactivated.
AT91C_BASE_CKGR->CKGR_PLLAR = 0x00003f00;
// Stop Main Oscillator
AT91C_BASE_CKGR->CKGR_MOR = AT91C_BASE_CKGR->CKGR_MOR & (~AT91C_CKGR_MOSCEN);
// Wait a while. The clock is at 500Hz...
while( timeInSlowClockMode-- );
// End !
// Restart Main Oscillator
AT91C_BASE_CKGR->CKGR_MOR = AT91C_BASE_CKGR->CKGR_MOR | (AT91C_CKGR_OSCOUNT & (0x32<<8) );
AT91C_BASE_CKGR->CKGR_MOR = AT91C_BASE_CKGR->CKGR_MOR | (AT91C_CKGR_MOSCEN);
// Restart PLL A
AT91C_BASE_CKGR->CKGR_PLLAR = oldPll;
timeout = 0;
while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCKA) && timeout++ < TIMEOUT);
// Selection of Master Clock MCK (so Processor Clock PCK)
AT91C_BASE_PMC->PMC_MCKR = oldMck;
timeout = 0;
while( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) && timeout++ < TIMEOUT);
// Reconfigure DBGU
TRACE_CONFIGURE(DBGU_STANDARD, 115200, BOARD_MCK);
}
//------------------------------------------------------------------------------
/// get the slow clock frequency
//------------------------------------------------------------------------------
unsigned int SLCK_UtilGetFreq(void)
{
unsigned int freq = 0;
SLCK_UtilSetSlowClockMode(0);
if(AT91C_BASE_PMC->PMC_MCFR & (1<<16)) {
freq = BOARD_MAINOSC / (AT91C_BASE_PMC->PMC_MCFR & 0x0000FFFF);
freq *= 16;
}
return freq;
}
#endif //#if defined(at91cap9)

View file

@ -0,0 +1,49 @@
/* ----------------------------------------------------------------------------
* 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 SLCK_H
#define SLCK_H
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern unsigned char SLCK_Is32k(void);
extern void SLCK_RCto32k(void);
extern void SLCK_32ktoRC(void);
extern void SLCK_bypass32Kosc(void);
extern void SLCK_UtilSetSlowClockMode(unsigned int timeInSlowClockMode);
extern unsigned int SLCK_UtilGetFreq(void);
#endif //#ifndef SLCK_H

View file

@ -0,0 +1,192 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "spi.h"
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Enables a SPI peripheral
/// \param spi Pointer to an AT91S_SPI instance.
//------------------------------------------------------------------------------
void SPI_Enable(AT91S_SPI *spi)
{
spi->SPI_CR = AT91C_SPI_SPIEN;
}
//------------------------------------------------------------------------------
/// Disables a SPI peripheral.
/// \param spi Pointer to an AT91S_SPI instance.
//------------------------------------------------------------------------------
void SPI_Disable(AT91S_SPI *spi)
{
spi->SPI_CR = AT91C_SPI_SPIDIS;
}
//------------------------------------------------------------------------------
/// Configures a SPI peripheral as specified. The configuration can be computed
/// using several macros (see "SPI configuration macros") and the constants
/// defined in LibV3 (AT91C_SPI_*).
/// \param spi Pointer to an AT91S_SPI instance.
/// \param id Peripheral ID of the SPI.
/// \param configuration Value of the SPI configuration register.
//------------------------------------------------------------------------------
void SPI_Configure(AT91S_SPI *spi,
unsigned int id,
unsigned int configuration)
{
AT91C_BASE_PMC->PMC_PCER = 1 << id;
spi->SPI_CR = AT91C_SPI_SPIDIS;
// Execute a software reset of the SPI twice
spi->SPI_CR = AT91C_SPI_SWRST;
spi->SPI_CR = AT91C_SPI_SWRST;
spi->SPI_MR = configuration;
}
//------------------------------------------------------------------------------
/// Configures a chip select of a SPI peripheral. The chip select configuration
/// is computed using the definition provided by the LibV3 (AT91C_SPI_*).
/// \param spi Pointer to an AT91S_SPI instance.
/// \param npcs Chip select to configure (1, 2, 3 or 4).
/// \param configuration Desired chip select configuration.
//------------------------------------------------------------------------------
void SPI_ConfigureNPCS(AT91S_SPI *spi,
unsigned int npcs,
unsigned int configuration)
{
spi->SPI_CSR[npcs] = configuration;
}
//------------------------------------------------------------------------------
/// Sends data through a SPI peripheral. If the SPI is configured to use a fixed
/// peripheral select, the npcs value is meaningless. Otherwise, it identifies
/// the component which shall be addressed.
/// \param spi Pointer to an AT91S_SPI instance.
/// \param npcs Chip select of the component to address (1, 2, 3 or 4).
/// \param data Word of data to send.
//------------------------------------------------------------------------------
void SPI_Write(AT91S_SPI *spi, unsigned int npcs, unsigned short data)
{
// Discard contents of RDR register
//volatile unsigned int discard = spi->SPI_RDR;
// Send data
while ((spi->SPI_SR & AT91C_SPI_TXEMPTY) == 0);
spi->SPI_TDR = data | SPI_PCS(npcs);
while ((spi->SPI_SR & AT91C_SPI_TDRE) == 0);
}
//------------------------------------------------------------------------------
/// Sends the contents of buffer through a SPI peripheral, using the PDC to
/// take care of the transfer.
/// \param spi Pointer to an AT91S_SPI instance.
/// \param buffer Data buffer to send.
/// \param length Length of the data buffer.
//------------------------------------------------------------------------------
unsigned char SPI_WriteBuffer(AT91S_SPI *spi,
void *buffer,
unsigned int length)
{
// Check if first bank is free
if (spi->SPI_TCR == 0) {
spi->SPI_TPR = (unsigned int) buffer;
spi->SPI_TCR = length;
spi->SPI_PTCR = AT91C_PDC_TXTEN;
return 1;
}
// Check if second bank is free
else if (spi->SPI_TNCR == 0) {
spi->SPI_TNPR = (unsigned int) buffer;
spi->SPI_TNCR = length;
return 1;
}
// No free banks
return 0;
}
//------------------------------------------------------------------------------
/// Returns 1 if there is no pending write operation on the SPI; otherwise
/// returns 0.
/// \param pSpi Pointer to an AT91S_SPI instance.
//------------------------------------------------------------------------------
unsigned char SPI_IsFinished(AT91S_SPI *pSpi)
{
return ((pSpi->SPI_SR & AT91C_SPI_TXEMPTY) != 0);
}
//------------------------------------------------------------------------------
/// Reads and returns the last word of data received by a SPI peripheral. This
/// method must be called after a successful SPI_Write call.
/// \param spi Pointer to an AT91S_SPI instance.
//------------------------------------------------------------------------------
unsigned short SPI_Read(AT91S_SPI *spi)
{
while ((spi->SPI_SR & AT91C_SPI_RDRF) == 0);
return spi->SPI_RDR & 0xFFFF;
}
//------------------------------------------------------------------------------
/// Reads data from a SPI peripheral until the provided buffer is filled. This
/// method does NOT need to be called after SPI_Write or SPI_WriteBuffer.
/// \param spi Pointer to an AT91S_SPI instance.
/// \param buffer Data buffer to store incoming bytes.
/// \param length Length in bytes of the data buffer.
//------------------------------------------------------------------------------
unsigned char SPI_ReadBuffer(AT91S_SPI *spi,
void *buffer,
unsigned int length)
{
// Check if the first bank is free
if (spi->SPI_RCR == 0) {
spi->SPI_RPR = (unsigned int) buffer;
spi->SPI_RCR = length;
spi->SPI_PTCR = AT91C_PDC_RXTEN;
return 1;
}
// Check if second bank is free
else if (spi->SPI_RNCR == 0) {
spi->SPI_RNPR = (unsigned int) buffer;
spi->SPI_RNCR = length;
return 1;
}
// No free bank
return 0;
}

View file

@ -0,0 +1,114 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \dir
/// !Purpose
///
/// Definitions for SPI peripheral usage.
///
/// !Usage
///
/// -# Enable the SPI pins required by the application (see pio.h).
/// -# Configure the SPI using the SPI_Configure function. This enables the
/// peripheral clock. The mode register is loaded with the given value.
/// -# Configure all the necessary chip selects with SPI_ConfigureNPCS.
/// -# Enable the SPI by calling SPI_Enable.
/// -# Send/receive data using SPI_Write and SPI_Read. Note that SPI_Read
/// must be called after SPI_Write to retrieve the last value read.
/// -# Send/receive data using the PDC with the SPI_WriteBuffer and
/// SPI_ReadBuffer functions.
/// -# Disable the SPI by calling SPI_Disable.
//------------------------------------------------------------------------------
#ifndef SPI_H
#define SPI_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "SPI configuration macros"
/// This page lists several macros which should be used when configuring a SPI
/// peripheral.
///
/// !Macros
/// - SPI_PCS
/// - SPI_SCBR
/// - SPI_DLYBS
/// - SPI_DLYBCT
/// Calculate the PCS field value given the chip select NPCS value
#define SPI_PCS(npcs) ((~(1 << npcs) & 0xF) << 16)
/// Calculates the value of the CSR SCBR field given the baudrate and MCK.
#define SPI_SCBR(baudrate, masterClock) \
((unsigned int) (masterClock / baudrate) << 8)
/// Calculates the value of the CSR DLYBS field given the desired delay (in ns)
#define SPI_DLYBS(delay, masterClock) \
((unsigned int) (((masterClock / 1000000) * delay) / 1000) << 16)
/// Calculates the value of the CSR DLYBCT field given the desired delay (in ns)
#define SPI_DLYBCT(delay, masterClock) \
((unsigned int) (((masterClock / 1000000) * delay) / 32000) << 24)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void SPI_Enable(AT91S_SPI *spi);
extern void SPI_Disable(AT91S_SPI *spi);
extern void SPI_Configure(AT91S_SPI *spi,
unsigned int id,
unsigned int configuration);
extern void SPI_ConfigureNPCS(AT91S_SPI *spi,
unsigned int npcs,
unsigned int configuration);
extern void SPI_Write(AT91S_SPI *spi, unsigned int npcs, unsigned short data);
extern unsigned char SPI_WriteBuffer(AT91S_SPI *spi,
void *buffer,
unsigned int length);
extern unsigned char SPI_IsFinished(AT91S_SPI *pSpi);
extern unsigned short SPI_Read(AT91S_SPI *spi);
extern unsigned char SPI_ReadBuffer(AT91S_SPI *spi,
void *buffer,
unsigned int length);
#endif //#ifndef SPI_H

View file

@ -0,0 +1,243 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "ssc.h"
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures a SSC peripheral. If the divided clock is not used, the master
/// clock frequency can be set to 0.
/// \note The emitter and transmitter are disabled by this function.
/// \param ssc Pointer to an AT91S_SSC instance.
/// \param id Peripheral ID of the SSC.
//------------------------------------------------------------------------------
void SSC_Configure(AT91S_SSC *ssc,
unsigned int id,
unsigned int bitRate,
unsigned int masterClock)
{
// Enable SSC peripheral clock
AT91C_BASE_PMC->PMC_PCER = 1 << id;
// Reset, disable receiver & transmitter
ssc->SSC_CR = AT91C_SSC_RXDIS | AT91C_SSC_TXDIS | AT91C_SSC_SWRST;
ssc->SSC_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS;
// Configure clock frequency
if (bitRate != 0) {
ssc->SSC_CMR = masterClock / (2 * bitRate);
}
else {
ssc->SSC_CMR = 0;
}
}
//------------------------------------------------------------------------------
/// Configures the transmitter of a SSC peripheral. Several macros can be used
/// to compute the values of the Transmit Clock Mode Register (TCMR) and the
/// Transmit Frame Mode Register (TFMR) (see "SSC configuration macros").
/// \param ssc Pointer to a AT91S_SSC instance.
/// \param tcmr Transmit Clock Mode Register value.
/// \param tfmr Transmit Frame Mode Register value.
//------------------------------------------------------------------------------
void SSC_ConfigureTransmitter(AT91S_SSC *ssc,
unsigned int tcmr,
unsigned int tfmr)
{
ssc->SSC_TCMR = tcmr;
ssc->SSC_TFMR = tfmr;
}
//------------------------------------------------------------------------------
/// Configures the receiver of a SSC peripheral. Several macros can be used
/// to compute the values of the Receive Clock Mode Register (TCMR) and the
/// Receive Frame Mode Register (TFMR) (see "SSC configuration macros").
/// \param ssc Pointer to a AT91S_SSC instance.
/// \param rcmr Receive Clock Mode Register value.
/// \param rfmr Receive Frame Mode Register value.
//------------------------------------------------------------------------------
void SSC_ConfigureReceiver(AT91S_SSC *ssc,
unsigned int rcmr,
unsigned int rfmr)
{
ssc->SSC_RCMR = rcmr;
ssc->SSC_RFMR = rfmr;
}
//------------------------------------------------------------------------------
/// Enables the transmitter of a SSC peripheral.
/// \param ssc Pointer to an AT91S_SSC instance.
//------------------------------------------------------------------------------
void SSC_EnableTransmitter(AT91S_SSC *ssc)
{
ssc->SSC_CR = AT91C_SSC_TXEN;
}
//------------------------------------------------------------------------------
/// Disables the transmitter of a SSC peripheral.
/// \param ssc Pointer to an AT91S_SSC instance.
//------------------------------------------------------------------------------
void SSC_DisableTransmitter(AT91S_SSC *ssc)
{
ssc->SSC_CR = AT91C_SSC_TXDIS;
}
//------------------------------------------------------------------------------
/// Enables the receiver of a SSC peripheral.
/// \param ssc Pointer to an AT91S_SSC instance.
//------------------------------------------------------------------------------
void SSC_EnableReceiver(AT91S_SSC *ssc)
{
ssc->SSC_CR = AT91C_SSC_RXEN;
}
//------------------------------------------------------------------------------
/// Disables the receiver of a SSC peripheral.
/// \param ssc Pointer to an AT91S_SSC instance.
//------------------------------------------------------------------------------
void SSC_DisableReceiver(AT91S_SSC *ssc)
{
ssc->SSC_CR = AT91C_SSC_RXDIS;
}
//------------------------------------------------------------------------------
/// Enables one or more interrupt sources of a SSC peripheral.
/// \param ssc Pointer to an AT91S_SSC instance.
/// \param sources Interrupt sources to enable.
//------------------------------------------------------------------------------
void SSC_EnableInterrupts(AT91S_SSC *ssc, unsigned int sources)
{
ssc->SSC_IER = sources;
}
//------------------------------------------------------------------------------
/// Disables one or more interrupt sources of a SSC peripheral.
/// \param ssc Pointer to an AT91S_SSC instance.
/// \param sources Interrupt source to disable.
//------------------------------------------------------------------------------
void SSC_DisableInterrupts(AT91S_SSC *ssc, unsigned int sources)
{
ssc->SSC_IDR = sources;
}
//------------------------------------------------------------------------------
/// Sends one data frame through a SSC peripheral. If another frame is currently
/// being sent, this function waits for the previous transfer to complete.
/// \param ssc Pointer to an AT91S_SSC instance.
/// \param frame Data frame to send.
//------------------------------------------------------------------------------
void SSC_Write(AT91S_SSC *ssc, unsigned int frame)
{
while ((ssc->SSC_SR & AT91C_SSC_TXRDY) == 0);
ssc->SSC_THR = frame;
}
//------------------------------------------------------------------------------
/// Sends the contents of a data buffer a SSC peripheral, using the PDC. Returns
/// true if the buffer has been queued for transmission; otherwise returns
/// false.
/// \param ssc Pointer to an AT91S_SSC instance.
/// \param buffer Data buffer to send.
/// \param length Size of the data buffer.
//------------------------------------------------------------------------------
unsigned char SSC_WriteBuffer(AT91S_SSC *ssc,
void *buffer,
unsigned int length)
{
// Check if first bank is free
if (ssc->SSC_TCR == 0) {
ssc->SSC_TPR = (unsigned int) buffer;
ssc->SSC_TCR = length;
ssc->SSC_PTCR = AT91C_PDC_TXTEN;
return 1;
}
// Check if second bank is free
else if (ssc->SSC_TNCR == 0) {
ssc->SSC_TNPR = (unsigned int) buffer;
ssc->SSC_TNCR = length;
return 1;
}
// No free banks
return 0;
}
//------------------------------------------------------------------------------
/// Waits until one frame is received on a SSC peripheral, and returns it.
/// \param ssc Pointer to an AT91S_SSC instance.
//------------------------------------------------------------------------------
unsigned int SSC_Read(AT91S_SSC *ssc)
{
while ((ssc->SSC_SR & AT91C_SSC_RXRDY) == 0);
return ssc->SSC_RHR;
}
//------------------------------------------------------------------------------
/// Reads data coming from a SSC peripheral receiver and stores it into the
/// provided buffer. Returns true if the buffer has been queued for reception;
/// otherwise returns false.
/// \param ssc Pointer to an AT91S_SSC instance.
/// \param buffer Data buffer used for reception.
/// \param length Size in bytes of the data buffer.
//------------------------------------------------------------------------------
unsigned char SSC_ReadBuffer(AT91S_SSC *ssc,
void *buffer,
unsigned int length)
{
// Check if the first bank is free
if (ssc->SSC_RCR == 0) {
ssc->SSC_RPR = (unsigned int) buffer;
ssc->SSC_RCR = length;
ssc->SSC_PTCR = AT91C_PDC_RXTEN;
return 1;
}
// Check if second bank is free
else if (ssc->SSC_RNCR == 0) {
ssc->SSC_RNPR = (unsigned int) buffer;
ssc->SSC_RNCR = length;
return 1;
}
// No free bank
return 0;
}

View file

@ -0,0 +1,132 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \dir
/// !Purpose
///
/// Set of functions and definition for using a SSC peripheral.
///
/// !Usage
///
/// -# Enable the SSC interface pins (see pio & board.h).
/// -# Configure the SSC to operate at a specific frequency by calling
/// SSC_Configure(). This function enables the peripheral clock of the SSC,
/// but not its PIOs.
/// -# Configure the transmitter and/or the receiver using the
/// SSC_ConfigureTransmitter() and SSC_ConfigureEmitter() functions.
/// -# Enable the PIOs or the transmitter and/or the received.
/// -# Enable the transmitter and/or the receiver using SSC_EnableTransmitter()
/// and SSC_EnableReceiver()
/// -# Send data through the transmitter using SSC_Write() and SSC_WriteBuffer()
/// -# Receive data from the receiver using SSC_Read() and SSC_ReadBuffer()
/// -# Disable the transmitter and/or the receiver using SSC_DisableTransmitter()
/// and SSC_DisableReceiver()
//------------------------------------------------------------------------------
#ifndef SSC_H
#define SSC_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "SSC configuration macros"
/// This page lists several macros which are used when configuring a SSC
/// peripheral.
///
/// !Macros
/// - SSC_STTDLY
/// - SSC_PERIOD
/// - SSC_DATLEN
/// - SSC_DATNB
/// - SSC_FSLEN
/// Calculates the value of the STTDLY field given the number of clock cycles
/// before the first bit of a new frame is transmitted.
#define SSC_STTDLY(bits) (bits << 16)
/// Calculates the value of the PERIOD field of the Transmit Clock Mode Register
/// of an SSC interface, given the desired clock divider.
#define SSC_PERIOD(divider) (((divider / 2) - 1) << 24)
/// Calculates the value of the DATLEN field of the Transmit Frame Mode Register
/// of an SSC interface, given the number of bits in one sample.
#define SSC_DATLEN(bits) (bits - 1)
/// Calculates the value of the DATNB field of the Transmit Frame Mode Register
/// of an SSC interface, given the number of samples in one frame.
#define SSC_DATNB(samples) ((samples -1) << 8)
/// Calculates the value of the FSLEN field of the Transmit Frame Mode Register
/// of an SSC interface, given the number of transmit clock periods that the
/// frame sync signal should take.
#define SSC_FSLEN(periods) ((periods - 1) << 16)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void SSC_Configure(AT91S_SSC *ssc,
unsigned int id,
unsigned int bitRate,
unsigned int masterClock);
extern void SSC_ConfigureTransmitter(AT91S_SSC *ssc,
unsigned int tcmr,
unsigned int tfmr);
extern void SSC_ConfigureReceiver(AT91S_SSC *ssc,
unsigned int rcmr,
unsigned int rfmr);
extern void SSC_EnableTransmitter(AT91S_SSC *ssc);
extern void SSC_DisableTransmitter(AT91S_SSC *ssc);
extern void SSC_EnableReceiver(AT91S_SSC *ssc);
extern void SSC_DisableReceiver(AT91S_SSC *ssc);
extern void SSC_EnableInterrupts(AT91S_SSC *ssc, unsigned int sources);
extern void SSC_DisableInterrupts(AT91S_SSC *ssc, unsigned int sources);
extern void SSC_Write(AT91S_SSC *ssc, unsigned int frame);
extern unsigned char SSC_WriteBuffer(AT91S_SSC *ssc,
void *buffer,
unsigned int length);
extern unsigned int SSC_Read(AT91S_SSC *ssc);
extern unsigned char SSC_ReadBuffer(AT91S_SSC *ssc,
void *buffer,
unsigned int length);
#endif //#ifndef SSC_H

View file

@ -0,0 +1,223 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "supc.h"
#include <board.h>
#include <utility/assert.h>
//------------------------------------------------------------------------------
// Local definitions
//------------------------------------------------------------------------------
/// Key value for the SUPC_MR register.
#define SUPC_KEY ((unsigned int) (0xA5 << 24))
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Enables the SLCD power supply.
/// \param internal If 1, the power supply is configured as internal; otherwise
/// it is set at external.
//------------------------------------------------------------------------------
void SUPC_EnableSlcd(unsigned char internal)
{
if (internal) {
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_LCDMODE) | AT91C_SUPC_LCDMODE_INTERNAL;
}
else {
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_LCDMODE) | AT91C_SUPC_LCDMODE_EXTERNAL;
}
while ((AT91C_BASE_SUPC->SUPC_SR & AT91C_SUPC_LCDS) != AT91C_SUPC_LCDS);
}
//------------------------------------------------------------------------------
/// Disables the SLCD power supply.
//------------------------------------------------------------------------------
void SUPC_DisableSlcd(void)
{
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_LCDMODE);
while ((AT91C_BASE_SUPC->SUPC_SR & AT91C_SUPC_LCDS) == AT91C_SUPC_LCDS);
}
//------------------------------------------------------------------------------
/// Sets the output voltage of the SLCD charge pump.
/// \param voltage Output voltage.
//------------------------------------------------------------------------------
void SUPC_SetSlcdVoltage(unsigned int voltage)
{
SANITY_CHECK((voltage & ~AT91C_SUPC_LCDOUT) == 0);
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_LCDOUT) | voltage;
}
#if !defined(__ICCARM__)
__attribute__ ((section (".ramfunc"))) // GCC
#endif
//------------------------------------------------------------------------------
/// Enables the flash power supply with the given wake-up setting.
/// \param time Wake-up time.
//------------------------------------------------------------------------------
void SUPC_EnableFlash(unsigned int time)
{
AT91C_BASE_SUPC->SUPC_FWUTR = time;
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | AT91C_BASE_SUPC->SUPC_MR | AT91C_SUPC_FLASHON;
while ((AT91C_BASE_SUPC->SUPC_SR & AT91C_SUPC_FLASHS) != AT91C_SUPC_FLASHS);
}
#if !defined(__ICCARM__)
__attribute__ ((section (".ramfunc"))) // GCC
#endif
//------------------------------------------------------------------------------
/// Disables the flash power supply.
//------------------------------------------------------------------------------
void SUPC_DisableFlash(void)
{
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_FLASHON);
while ((AT91C_BASE_SUPC->SUPC_SR & AT91C_SUPC_FLASHS) == AT91C_SUPC_FLASHS);
}
//------------------------------------------------------------------------------
/// Sets the voltage regulator output voltage.
/// \param voltage Voltage to set.
//------------------------------------------------------------------------------
void SUPC_SetVoltageOutput(unsigned int voltage)
{
SANITY_CHECK((voltage & ~AT91C_SUPC_VRVDD) == 0);
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_VRVDD) | voltage;
}
//------------------------------------------------------------------------------
/// Puts the voltage regulator in deep mode.
//------------------------------------------------------------------------------
void SUPC_EnableDeepMode(void)
{
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | AT91C_BASE_SUPC->SUPC_MR | AT91C_SUPC_VRDEEP;
}
//------------------------------------------------------------------------------
/// Puts the voltage regulator in normal mode.
//------------------------------------------------------------------------------
void SUPC_DisableDeepMode(void)
{
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_VRDEEP);
}
//-----------------------------------------------------------------------------
/// Enables the backup SRAM power supply, so its data is saved while the device
/// is in backup mode.
//-----------------------------------------------------------------------------
void SUPC_EnableSram(void)
{
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | AT91C_BASE_SUPC->SUPC_MR | AT91C_SUPC_SRAMON;
}
//-----------------------------------------------------------------------------
/// Disables the backup SRAM power supply.
//-----------------------------------------------------------------------------
void SUPC_DisableSram(void)
{
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_SRAMON);
}
//-----------------------------------------------------------------------------
/// Enables the RTC power supply.
//-----------------------------------------------------------------------------
void SUPC_EnableRtc(void)
{
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | AT91C_BASE_SUPC->SUPC_MR | AT91C_SUPC_RTCON;
while ((AT91C_BASE_SUPC->SUPC_SR & AT91C_SUPC_RTS) != AT91C_SUPC_RTS);
}
//-----------------------------------------------------------------------------
/// Disables the RTC power supply.
//-----------------------------------------------------------------------------
void SUPC_DisableRtc(void)
{
AT91C_BASE_SUPC->SUPC_MR = SUPC_KEY | (AT91C_BASE_SUPC->SUPC_MR & ~AT91C_SUPC_RTCON);
while ((AT91C_BASE_SUPC->SUPC_SR & AT91C_SUPC_RTS) == AT91C_SUPC_RTS);
}
//-----------------------------------------------------------------------------
/// Sets the BOD sampling mode (or disables it).
/// \param mode BOD sampling mode.
//-----------------------------------------------------------------------------
void SUPC_SetBodSampling(unsigned int mode)
{
SANITY_CHECK((mode & ~AT91C_SUPC_BODSMPL) == 0);
AT91C_BASE_SUPC->SUPC_BOMR &= ~AT91C_SUPC_BODSMPL;
AT91C_BASE_SUPC->SUPC_BOMR |= mode;
}
//------------------------------------------------------------------------------
/// Disables the voltage regulator, which makes the device enter backup mode.
//------------------------------------------------------------------------------
void SUPC_DisableVoltageRegulator(void)
{
AT91C_BASE_SUPC->SUPC_CR = SUPC_KEY | AT91C_SUPC_VROFF;
while (1);
}
//------------------------------------------------------------------------------
/// Shuts the device down so it enters Off mode.
//------------------------------------------------------------------------------
void SUPC_Shutdown(void)
{
AT91C_BASE_SUPC->SUPC_CR = SUPC_KEY | AT91C_SUPC_SHDW;
while (1);
}
//------------------------------------------------------------------------------
/// Sets the wake-up sources when in backup mode.
/// \param sources Wake-up sources to enable.
//------------------------------------------------------------------------------
void SUPC_SetWakeUpSources(unsigned int sources)
{
SANITY_CHECK((sources & ~0x0000000B) == 0);
AT91C_BASE_SUPC->SUPC_WUMR &= ~0x0000000B;
AT91C_BASE_SUPC->SUPC_WUMR |= sources;
}
//------------------------------------------------------------------------------
/// Sets the wake-up inputs when in backup mode.
/// \param inputs Wake up inputs to enable.
//------------------------------------------------------------------------------
void SUPC_SetWakeUpInputs(unsigned int inputs)
{
SANITY_CHECK((inputs & ~0xFFFF) == 0);
AT91C_BASE_SUPC->SUPC_WUIR &= ~0xFFFF;
AT91C_BASE_SUPC->SUPC_WUIR |= inputs;
}

View file

@ -0,0 +1,80 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef SUPC_H
#define SUPC_H
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void SUPC_EnableSlcd(unsigned char internal);
extern void SUPC_DisableSlcd(void);
extern void SUPC_SetSlcdVoltage(unsigned int voltage);
extern
#ifdef __ICCARM__
__ramfunc // IAR
#endif
void SUPC_EnableFlash(unsigned int time);
extern
#ifdef __ICCARM__
__ramfunc // IAR
#endif
void SUPC_DisableFlash(void);
extern void SUPC_SetVoltageOutput(unsigned int voltage);
extern void SUPC_EnableDeepMode(void);
extern void SUPC_EnableSram(void);
extern void SUPC_DisableSram(void);
extern void SUPC_EnableRtc(void);
extern void SUPC_DisableRtc(void);
extern void SUPC_SetBodSampling(unsigned int mode);
extern void SUPC_DisableDeepMode(void);
extern void SUPC_DisableVoltageRegulator(void);
extern void SUPC_Shutdown(void);
extern void SUPC_SetWakeUpSources(unsigned int sources);
extern void SUPC_SetWakeUpInputs(unsigned int inputs);
#endif //#ifndef SUPC_H

View file

@ -0,0 +1,63 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "systick.h"
//------------------------------------------------------------------------------
/// Configures the SysTick in .
/// \param countEnable Enable SysTick counting.
/// \param reloadValue Value used for tick counter to reload.
/// \param handler Interrupt handler function, 0 to disable interrupt.
//------------------------------------------------------------------------------
void SysTick_Configure(unsigned char countEnable,
unsigned int reloadValue,
void( *handler )( void ))
{
unsigned int intEnable = handler ? AT91C_NVIC_STICKINT : 0;
// Disable the SysTick & using core source
AT91C_BASE_NVIC->NVIC_STICKCSR = AT91C_NVIC_STICKCLKSOURCE;
// Reset the current value
AT91C_BASE_NVIC->NVIC_STICKCVR &= ~AT91C_NVIC_STICKCURRENT;
// Setup the reload value
AT91C_BASE_NVIC->NVIC_STICKRVR = reloadValue;
// Enable the SysTick
AT91C_BASE_NVIC->NVIC_STICKCSR = AT91C_NVIC_STICKCLKSOURCE
| AT91C_NVIC_STICKENABLE
| intEnable;
}

View file

@ -0,0 +1,68 @@
/* ----------------------------------------------------------------------------
* 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 System Tick in Cortex-M3.
///
/// !Usage
///
/// -# Configure the System Tick with SysTick_Configure
///
//------------------------------------------------------------------------------
#ifndef SYSTICK_H
#define SYSTICK_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#include <cmsis/core_cm3.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
/// Vendor define it's own SysTickConfig function
#define __Vendor_SysTickConfig 1
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void SysTick_Configure(unsigned char countEnable,
unsigned int reloadValue,
void( *handler )( void ));
#endif //#ifndef SYSTICK_H

View file

@ -0,0 +1,143 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "tc.h"
//------------------------------------------------------------------------------
// Global Functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures a Timer Counter to operate in the given mode. Timer is stopped
/// after configuration and must be restarted with TC_Start(). All the
/// interrupts of the timer are also disabled.
/// \param pTc Pointer to an AT91S_TC instance.
/// \param mode Operating mode (TC_CMR value).
//------------------------------------------------------------------------------
void TC_Configure(AT91S_TC *pTc, unsigned int mode)
{
// Disable TC clock
pTc->TC_CCR = AT91C_TC_CLKDIS;
// Disable interrupts
pTc->TC_IDR = 0xFFFFFFFF;
// Clear status register
pTc->TC_SR;
// Set mode
pTc->TC_CMR = mode;
}
//------------------------------------------------------------------------------
/// Enables the timer clock and performs a software reset to start the counting.
/// \param pTc Pointer to an AT91S_TC instance.
//------------------------------------------------------------------------------
void TC_Start(AT91S_TC *pTc)
{
pTc->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG;
}
//------------------------------------------------------------------------------
/// Disables the timer clock, stopping the counting.
/// \param pTc Pointer to an AT91S_TC instance.
//------------------------------------------------------------------------------
void TC_Stop(AT91S_TC *pTc)
{
pTc->TC_CCR = AT91C_TC_CLKDIS;
}
//------------------------------------------------------------------------------
/// Finds the best MCK divisor given the timer frequency and MCK. The result
/// is guaranteed to satisfy the following equation:
/// \pre
/// (MCK / (DIV * 65536)) <= freq <= (MCK / DIV)
/// \endpre
/// with DIV being the highest possible value.
/// \param freq Desired timer frequency.
/// \param mck Master clock frequency.
/// \param div Divisor value.
/// \param tcclks TCCLKS field value for divisor.
/// \return 1 if a proper divisor has been found; otherwise 0.
//------------------------------------------------------------------------------
unsigned char TC_FindMckDivisor(
unsigned int freq,
unsigned int mck,
unsigned int *div,
unsigned int *tcclks)
{
const unsigned int divisors[5] = {2, 8, 32, 128,
#if defined(at91sam9260) || defined(at91sam9261) || defined(at91sam9263) \
|| defined(at91sam9xe) || defined(at91sam9rl64) || defined(at91cap9) \
|| defined(at91sam9m10) || defined(at91sam9m11)
BOARD_MCK / 32768};
#else
1024};
#endif
unsigned int index = 0;
// Satisfy lower bound
while (freq < ((mck / divisors[index]) / 65536)) {
index++;
// If no divisor can be found, return 0
if (index == 5) {
return 0;
}
}
// Try to maximise DIV while satisfying upper bound
while (index < 4) {
if (freq > (mck / divisors[index + 1])) {
break;
}
index++;
}
// Store results
if (div) {
*div = divisors[index];
}
if (tcclks) {
*tcclks = index;
}
return 1;
}

View file

@ -0,0 +1,80 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
///
/// !Purpose
///
/// API for configuring and using Timer Counter (TC) peripherals.
///
/// !Usage
/// -# Optionally, use TC_FindMckDivisor() to let the program find the best
/// TCCLKS field value automatically.
/// -# Configure a Timer Counter in the desired mode using TC_Configure().
/// -# Start or stop the timer clock using TC_Start() and TC_Stop().
//------------------------------------------------------------------------------
#ifndef TC_H
#define TC_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#if defined(AT91C_ID_TC0)
// nothing to do
#elif defined(AT91C_ID_TC012)
#define AT91C_ID_TC0 AT91C_ID_TC012
#elif defined(AT91C_ID_TC)
#define AT91C_ID_TC0 AT91C_ID_TC
#else
#error Pb define ID_TC
#endif
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void TC_Configure(AT91S_TC *pTc, unsigned int mode);
extern void TC_Start(AT91S_TC *pTc);
extern void TC_Stop(AT91S_TC *pTc);
extern unsigned char TC_FindMckDivisor(
unsigned int freq,
unsigned int mck,
unsigned int *div,
unsigned int *tcclks);
#endif //#ifndef TC_H

View file

@ -0,0 +1,228 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "tdes.h"
#include <board.h>
#include <utility/assert.h>
#include <utility/trace.h>
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures the triple-DES peripheral to cipher/decipher, use single-DES or
/// triple-DES, use two or three keys (when in triple-DES mode), start manually,
/// automatically or via the PDC and use the given operating mode (ECB, CBC,
/// CFB or OFB).
/// \param cipher Encrypts if 1, decrypts if 0.
/// \param tdesmod Single- or triple-DES mode.
/// \param keymod Use two or three keys (must be 0 in single-DES mode).
/// \param smod Start mode.
/// \param opmod Encryption/decryption mode.
//------------------------------------------------------------------------------
void TDES_Configure(
unsigned char cipher,
unsigned int tdesmod,
unsigned int keymod,
unsigned int smod,
unsigned int opmod)
{
TRACE_DEBUG("TDES_Configure()\n\r");
SANITY_CHECK((cipher & 0xFFFFFFFE) == 0);
SANITY_CHECK((tdesmod & 0xFFFFFFFD) == 0);
SANITY_CHECK((keymod & 0xFFFFFFEF) == 0);
SANITY_CHECK((smod & 0xFFFFFCFF) == 0);
SANITY_CHECK((opmod & 0xFFFFCFFF) == 0);
// Reset peripheral
AT91C_BASE_TDES->TDES_CR = AT91C_TDES_SWRST;
// Configure mode register
AT91C_BASE_TDES->TDES_MR = cipher | tdesmod | keymod | smod | opmod;
}
//------------------------------------------------------------------------------
/// Starts the encryption or decryption process if the TDES peripheral is
/// configured in manual or PDC mode.
//------------------------------------------------------------------------------
void TDES_Start(void)
{
TRACE_DEBUG("TDES_Start()\n\r");
SANITY_CHECK(((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_SMOD) == AT91C_TDES_SMOD_MANUAL)
|| ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_SMOD) == AT91C_TDES_SMOD_PDC));
// Manual mode
if ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_SMOD) == AT91C_TDES_SMOD_MANUAL) {
AT91C_BASE_TDES->TDES_CR = AT91C_TDES_START;
}
// PDC mode
else {
AT91C_BASE_TDES->TDES_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTEN;
}
}
//------------------------------------------------------------------------------
/// Returns the current status register value of the TDES peripheral.
//------------------------------------------------------------------------------
unsigned int TDES_GetStatus(void)
{
TRACE_DEBUG("TDES_GetStatus()\n\r");
return AT91C_BASE_TDES->TDES_ISR;
}
//------------------------------------------------------------------------------
/// Sets the 64-bits keys (one, two or three depending on the configuration)
/// that shall be used by the TDES algorithm.
/// \param pKey1 Pointer to key #1.
/// \param pKey2 Pointer to key #2 (shall be 0 in single-DES mode).
/// \param pKey3 Pointer to key #3 (shall be 0 when using two keys).
//------------------------------------------------------------------------------
void TDES_SetKeys(
const unsigned int *pKey1,
const unsigned int *pKey2,
const unsigned int *pKey3)
{
TRACE_DEBUG("TDES_SetKeys()\n\r");
SANITY_CHECK(pKey1);
SANITY_CHECK((pKey2 && ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_TDESMOD) == AT91C_TDES_TDESMOD))
|| (!pKey2 && ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_TDESMOD) == 0)));
SANITY_CHECK((pKey3
&& ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_TDESMOD) == AT91C_TDES_TDESMOD)
&& ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_KEYMOD) == 0))
||
(!pKey3
&& ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_TDESMOD) == AT91C_TDES_TDESMOD)
&& ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_KEYMOD) == AT91C_TDES_KEYMOD))
||
(!pKey3
&& ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_TDESMOD) == 0)
&& ((AT91C_BASE_TDES->TDES_MR & AT91C_TDES_KEYMOD) == 0)));
// Write key #1
if (pKey1) {
AT91C_BASE_TDES->TDES_KEY1WxR[0] = pKey1[0];
AT91C_BASE_TDES->TDES_KEY1WxR[1] = pKey1[1];
}
// Write key #2
if (pKey1) {
AT91C_BASE_TDES->TDES_KEY2WxR[0] = pKey2[0];
AT91C_BASE_TDES->TDES_KEY2WxR[1] = pKey2[1];
}
// Write key #2
if (pKey1) {
AT91C_BASE_TDES->TDES_KEY3WxR[0] = pKey3[0];
AT91C_BASE_TDES->TDES_KEY3WxR[1] = pKey3[1];
}
}
//------------------------------------------------------------------------------
/// Sets the input data to encrypt/decrypt using TDES.
/// \param pInput Pointer to the 64-bits input data.
//------------------------------------------------------------------------------
void TDES_SetInputData(const unsigned int *pInput)
{
TRACE_DEBUG("TDES_SetInputData()\n\r");
SANITY_CHECK(pInput);
AT91C_BASE_TDES->TDES_IDATAxR[0] = pInput[0];
AT91C_BASE_TDES->TDES_IDATAxR[1] = pInput[1];
}
//------------------------------------------------------------------------------
/// Sets the input data buffer to encrypt/decrypt when in PDC mode.
/// \param pInput Pointer to the input data.
/// \param size Size of buffer in bytes.
//------------------------------------------------------------------------------
void TDES_SetInputBuffer(const unsigned int *pInput, unsigned int size)
{
TRACE_DEBUG("TDES_SetInputBuffer()\n\r");
SANITY_CHECK(pInput);
SANITY_CHECK((size > 0) && ((size % 8) == 0));
AT91C_BASE_TDES->TDES_TPR = (unsigned int) pInput;
AT91C_BASE_TDES->TDES_TCR = size / 4;
}
//------------------------------------------------------------------------------
/// Stores the output data from the last TDES operation into the given 64-bits
/// buffers.
/// \param pOutput Pointer to a 64-bits output buffer.
//------------------------------------------------------------------------------
void TDES_GetOutputData(unsigned int *pOutput)
{
TRACE_DEBUG("TDES_GetOutputData()\n\r");
SANITY_CHECK(pOutput);
pOutput[0] = AT91C_BASE_TDES->TDES_ODATAxR[0];
pOutput[1] = AT91C_BASE_TDES->TDES_ODATAxR[1];
}
//------------------------------------------------------------------------------
/// Sets the output buffer which will receive the encrypted/decrypted data when
/// using the PDC.
/// \param pOutput Pointer to the output data.
/// \param size Size of buffer in bytes.
//------------------------------------------------------------------------------
void TDES_SetOutputBuffer(unsigned int *pOutput, unsigned int size)
{
TRACE_DEBUG("TDES_SetOutputBuffer()\n\r");
SANITY_CHECK(pOutput);
SANITY_CHECK((size > 0) && ((size % 8) == 0));
AT91C_BASE_TDES->TDES_RPR = (unsigned int) pOutput;
AT91C_BASE_TDES->TDES_RCR = size / 4;
}
//------------------------------------------------------------------------------
/// Sets the initialization vector to use when the TDES algorithm is configured
/// in a chained block mode (CBC, CFB or OFB).
/// \param pVector Pointer to the 64-bits vector.
//------------------------------------------------------------------------------
void TDES_SetVector(const unsigned int *pVector)
{
TRACE_DEBUG("TDES_SetVector()\n\r");
SANITY_CHECK(pVector);
AT91C_BASE_TDES->TDES_IVxR[0] = pVector[0];
AT91C_BASE_TDES->TDES_IVxR[1] = pVector[1];
}

View file

@ -0,0 +1,80 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef TDES_H
#define TDES_H
//------------------------------------------------------------------------------
/// \unit
///
/// !Purpose
///
/// Methods to manage the Triple DES (3DES)
///
/// !Usage
///
/// -# Configure TDES
/// -# Sets the key used by the TDES algorithm
/// -# Sets the input data of the TDES algorithm
/// -# Starts the encryption/decryption process
/// -# Stores the result of the last TDES operation
///
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void TDES_Configure(
unsigned char cipher,
unsigned int tdesmod,
unsigned int keymod,
unsigned int smod,
unsigned int opmod);
extern void TDES_Start(void);
extern unsigned int TDES_GetStatus(void);
extern void TDES_SetKeys(
const unsigned int *pKey1,
const unsigned int *pKey2,
const unsigned int *pKey3);
extern void TDES_SetInputData(const unsigned int *pInput);
extern void TDES_SetInputBuffer(const unsigned int *pInput, unsigned int size);
extern void TDES_GetOutputData(unsigned int *pOutput);
extern void TDES_SetOutputBuffer(unsigned int *pOutput, unsigned int size);
extern void TDES_SetVector(const unsigned int *pVector);
#endif //#ifndef TDES_H

View file

@ -0,0 +1,324 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#ifdef AT91C_BASE_TSADC
#include <utility/trace.h>
#include <utility/assert.h>
//------------------------------------------------------------------------------
// Local variables
//------------------------------------------------------------------------------
/// TSADC clock frequency in Hz.
static unsigned int lAdcclk = 0;
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Sets the operating mode of the TSADCC peripheral. The mode value can be
/// one of the following:
/// - AT91C_TSADC_TSAMOD_ADC_ONLY_MODE
/// - AT91C_TSADC_TSAMOD_TS_ONLY_MODE
/// \param mode Desired mode for the TSADCC.
//------------------------------------------------------------------------------
void TSADCC_SetOperatingMode(unsigned int mode)
{
SANITY_CHECK( (mode == AT91C_TSADC_TSAMOD_ADC_ONLY_MODE)
| (mode == AT91C_TSADC_TSAMOD_TS_ONLY_MODE));
AT91C_BASE_TSADC->TSADC_MR = (AT91C_BASE_TSADC->TSADC_MR
& ~AT91C_TSADC_TSAMOD)
| mode;
}
//------------------------------------------------------------------------------
/// Enables or disables the low resolution precision on the TSADC.
/// \param enable If true, low resolution (8 bit) is used; otherwise the TSADC
/// will use a 10-bit resolution.
//------------------------------------------------------------------------------
void TSADCC_SetLowResolution(unsigned char enable)
{
if (enable) {
AT91C_BASE_TSADC->TSADC_MR |= AT91C_TSADC_LOWRES;
}
else {
AT91C_BASE_TSADC->TSADC_MR &= ~AT91C_TSADC_LOWRES;
}
}
//------------------------------------------------------------------------------
/// Enables or disable SLEEP mode on the TSADC.
/// \param enable If true, the TSADC is put into sleep mode; in normal mode
/// otherwise.
//------------------------------------------------------------------------------
void TSADCC_SetSleepMode(unsigned char enable)
{
if (enable) {
AT91C_BASE_TSADC->TSADC_MR |= AT91C_TSADC_SLEEP;
}
else {
AT91C_BASE_TSADC->TSADC_MR &= ~AT91C_TSADC_SLEEP;
}
}
//------------------------------------------------------------------------------
/// Enables or disables pen detection on the TSADC.
/// \param enable If true, pen detection is enabled; otherwise it is disabled.
//------------------------------------------------------------------------------
void TSADCC_SetPenDetect(unsigned char enable)
{
if (enable) {
AT91C_BASE_TSADC->TSADC_MR |= AT91C_TSADC_PENDET;
}
else {
AT91C_BASE_TSADC->TSADC_MR &= ~AT91C_TSADC_PENDET;
}
}
//------------------------------------------------------------------------------
/// Sets the TSADC clock to the desired frequency. The prescaler is calculated
/// by this function so the resulting frequency is equal or inferior to the
/// desired one.
/// \param adcclk Desired ADC clock frequency in Hz.
/// \param mck Master clock frequency in Hz.
//------------------------------------------------------------------------------
void TSADCC_SetAdcFrequency(unsigned int adcclk, unsigned int mck)
{
unsigned int prescal;
// Formula for PRESCAL is:
// PRESCAL = (MCK / (2 * ADCCLK)) + 1
// First, we do the division, multiplied by 10 to get higher precision
// If the last digit is not zero, we round up to avoid generating a higher
// than required frequency.
prescal = (mck * 5) / adcclk;
if ((prescal % 10) > 0) {
prescal = (prescal / 10);
}
else {
SANITY_CHECK((prescal / 10) != 0);
prescal = (prescal / 10) - 1;
}
SANITY_CHECK((prescal & ~0x3F) == 0);
AT91C_BASE_TSADC->TSADC_MR = ( AT91C_BASE_TSADC->TSADC_MR
& ~AT91C_TSADC_PRESCAL)
| (prescal << 8);
// Save clock frequency for further timing calculations
lAdcclk = adcclk;
}
//------------------------------------------------------------------------------
/// Sets the TSADC startup time. This function relies on the ADCCLK frequency
/// that has been set using TSADCC_SetAdcFrequency(), so it must have been
/// called first.
/// \param time Startup time in µseconds.
//------------------------------------------------------------------------------
void TSADCC_SetStartupTime(unsigned int time)
{
unsigned int startup;
SANITY_CHECK(lAdcclk != 0);
// Formula for STARTUP is:
// STARTUP = (time x ADCCLK) / (1000000 x 8) - 1
// Division multiplied by 10 for higher precision
startup = (time * lAdcclk) / (800000);
if ((startup % 10) > 0) {
startup /= 10;
}
else {
startup /= 10;
if (startup > 0) {
startup--;
}
}
SANITY_CHECK((startup & ~0x7F) == 0);
AT91C_BASE_TSADC->TSADC_MR = ( AT91C_BASE_TSADC->TSADC_MR
& ~AT91C_TSADC_STARTUP)
| (startup << 16);
}
//------------------------------------------------------------------------------
/// Sets the TSADC track and hold time. This function relies on the ADCCLK
/// frequency that has been set with TSADCC_SetAdcFrequency(), to it must be
/// called first.
/// This function also sets the track and hold time in the TSADC_TSR register.
/// \param time Track and hold time in nanoseconds.
//------------------------------------------------------------------------------
void TSADCC_SetTrackAndHoldTime(unsigned int time)
{
unsigned int shtim;
SANITY_CHECK(lAdcclk != 0);
// Formula for SHTIM:
// SHTIM = (time x ADCCLK) / 1000000000 - 1
// Since 1 billion is close to the maximum value for an integer, we first
// divide ADCCLK by 1000 to avoid an overflow
shtim = (time * (lAdcclk / 1000)) / 100000;
if ((shtim % 10) > 0) {
shtim /= 10;
}
else {
shtim /= 10;
if (shtim > 0) shtim--;
}
SANITY_CHECK((shtim & ~0xF) == 0);
AT91C_BASE_TSADC->TSADC_MR = ( AT91C_BASE_TSADC->TSADC_MR
& ~AT91C_TSADC_SHTIM)
| (shtim << 24);
AT91C_BASE_TSADC->TSADC_TSR = shtim << 24;
}
//------------------------------------------------------------------------------
/// Sets the TSADC debounce time. This function relies on the ADCCLK
/// frequency that has been set with TSADCC_SetAdcFrequency(), to it must be
/// called first.
/// \param time Debounce time in nanoseconds (cannot be 0).
//------------------------------------------------------------------------------
void TSADCC_SetDebounceTime(unsigned int time)
{
unsigned int divisor = 1000000000;
unsigned int clock = lAdcclk;
unsigned int pendbc = 0;
unsigned int targetValue;
unsigned int currentValue;
SANITY_CHECK(lAdcclk != 0);
SANITY_CHECK(time != 0);
// Divide time & ADCCLK first to avoid overflows
while ((divisor > 1) && ((time % 10) == 0)) {
time /= 10;
divisor /= 10;
}
while ((divisor > 1) && ((clock % 10) == 0)) {
clock /= 10;
divisor /= 10;
}
// Compute PENDBC value
targetValue = time * clock / divisor;
currentValue = 1;
while (currentValue < targetValue) {
pendbc++;
currentValue *= 2;
}
SANITY_CHECK((pendbc & ~0xF) == 0);
AT91C_BASE_TSADC->TSADC_MR = ( AT91C_BASE_TSADC->TSADC_MR
& ~AT91C_TSADC_PENDBC)
| (pendbc << 28);
}
//------------------------------------------------------------------------------
/// Sets the trigger mode of the TSADCC to one of the following values:
/// - AT91C_TSADC_TRGMOD_NO_TRIGGER
/// - AT91C_TSADC_TRGMOD_EXTERNAL_TRIGGER_RE
/// - AT91C_TSADC_TRGMOD_EXTERNAL_TRIGGER_FE
/// - AT91C_TSADC_TRGMOD_EXTERNAL_TRIGGER_AE
/// - AT91C_TSADC_TRGMOD_PENDET_TRIGGER
/// - AT91C_TSADC_TRGMOD_PERIODIC_TRIGGER
/// - AT91C_TSADC_TRGMOD_CONT_TRIGGER
/// \param mode Trigger mode.
//------------------------------------------------------------------------------
void TSADCC_SetTriggerMode(unsigned int mode)
{
SANITY_CHECK(((mode & ~AT91C_TSADC_TRGMOD) == 0)
| ((mode & AT91C_TSADC_TRGMOD) != 0x7));
AT91C_BASE_TSADC->TSADC_TRGR = (AT91C_BASE_TSADC->TSADC_TRGR
& ~AT91C_TSADC_TRGMOD)
| mode;
}
//------------------------------------------------------------------------------
/// Sets the trigger period when using the TSADCC in periodic trigger mode.
/// As usual, this function requires TSADCC_SetAdcFrequency() to be called
/// before it.
/// \param period Trigger period in nanoseconds.
//------------------------------------------------------------------------------
void TSADCC_SetTriggerPeriod(unsigned int period)
{
unsigned int trgper;
unsigned int divisor = 100000000;
while ((period >= 10) && (divisor >= 10)) {
period /= 10;
divisor /= 10;
}
trgper = (period * lAdcclk) / divisor;
if ((trgper % 10) > 0) {
trgper /= 10;
}
else {
trgper /= 10;
if (trgper > 0) trgper--;
}
SANITY_CHECK((trgper & ~0xFFFF) == 0);
AT91C_BASE_TSADC->TSADC_TRGR = (AT91C_BASE_TSADC->TSADC_TRGR
& ~AT91C_TSADC_TRGPER)
| (trgper << 16);
}
#endif //#ifdef AT91C_BASE_TSADC

View file

@ -0,0 +1,60 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef TSADCC_H
#define TSADCC_H
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
#ifdef AT91C_BASE_TSADC
extern void TSADCC_SetOperatingMode(unsigned int mode);
extern void TSADCC_SetLowResolution(unsigned char enable);
extern void TSADCC_SetSleepMode(unsigned char enable);
extern void TSADCC_SetPenDetect(unsigned char enable);
extern void TSADCC_SetAdcFrequency(unsigned int adcclk, unsigned int mck);
extern void TSADCC_SetStartupTime(unsigned int time);
extern void TSADCC_SetTrackAndHoldTime(unsigned int time);
extern void TSADCC_SetDebounceTime(unsigned int time);
extern void TSADCC_SetTriggerMode(unsigned int mode);
extern void TSADCC_SetTriggerPeriod(unsigned int period);
#endif //#ifdef AT91C_BASE_TSADC
#endif //#ifndef TSADCC_H

View file

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

View file

@ -0,0 +1,150 @@
/* ----------------------------------------------------------------------------
* 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 Two Wire Interface (TWI) peripheral.
///
/// !Usage
///
/// -# Configures a TWI peripheral to operate in master mode, at the given
/// frequency (in Hz) using TWI_ConfigureMaster().
/// -# or if hardware possible, configures a TWI peripheral to operate in
/// slave mode, at the given frequency (in Hz) using TWI_ConfigureSlave().
/// -# Sends a STOP condition on the TWI using TWI_Stop().
/// -# Starts a read operation on the TWI bus with the specified slave using
/// TWI_StartRead(). Data must then be read using TWI_ReadByte() whenever
/// a byte is available (poll using TWI_ByteReceived()).
/// -# Starts a write operation on the TWI to access the selected slave using
/// TWI_StartWrite(). A byte of data must be provided to start the write;
/// other bytes are written next.
/// -# Sends a byte of data to one of the TWI slaves on the bus using TWI_WriteByte().
/// This function must be called once before TWI_StartWrite() with the first byte of data
/// to send, then it shall be called repeatedly after that to send the remaining bytes.
/// -# Check if a byte has been received and can be read on the given TWI
/// peripheral using TWI_ByteReceived().
/// Check if a byte has been sent using TWI_ByteSent().
/// -# Check if the current transmission is complete (the STOP has been sent)
/// using TWI_TransferComplete().
/// -# Enables & disable the selected interrupts sources on a TWI peripheral
/// using TWI_EnableIt() and TWI_DisableIt().
/// -# Get current status register of the given TWI peripheral using
/// TWI_GetStatus(). Get current status register of the given TWI peripheral, but
/// masking interrupt sources which are not currently enabled using
/// TWI_GetMaskedStatus().
//------------------------------------------------------------------------------
#ifndef TWI_H
#define TWI_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Global definitions
//------------------------------------------------------------------------------
// Missing AT91C_TWI_TXRDY definition.
#ifndef AT91C_TWI_TXRDY
#define AT91C_TWI_TXRDY AT91C_TWI_TXRDY_MASTER
#endif
// Missing AT91C_TWI_TXCOMP definition.
#ifndef AT91C_TWI_TXCOMP
#define AT91C_TWI_TXCOMP AT91C_TWI_TXCOMP_MASTER
#endif
//------------------------------------------------------------------------------
// Global macros
//------------------------------------------------------------------------------
/// Returns 1 if the TXRDY bit (ready to transmit data) is set in the given
/// status register value.
#define TWI_STATUS_TXRDY(status) ((status & AT91C_TWI_TXRDY) == AT91C_TWI_TXRDY)
/// Returns 1 if the RXRDY bit (ready to receive data) is set in the given
/// status register value.
#define TWI_STATUS_RXRDY(status) ((status & AT91C_TWI_RXRDY) == AT91C_TWI_RXRDY)
/// Returns 1 if the TXCOMP bit (transfer complete) is set in the given
/// status register value.
#define TWI_STATUS_TXCOMP(status) ((status & AT91C_TWI_TXCOMP) == AT91C_TWI_TXCOMP)
//------------------------------------------------------------------------------
// Global functions
//------------------------------------------------------------------------------
extern void TWI_ConfigureMaster(AT91S_TWI *pTwi, unsigned int twck, unsigned int mck);
#ifdef AT91C_TWI_SVEN // TWI slave
extern void TWI_ConfigureSlave(AT91S_TWI *pTwi, unsigned char slaveAddress);
#endif
extern void TWI_Stop(AT91S_TWI *pTwi);
extern void TWI_StartRead(
AT91S_TWI *pTwi,
unsigned char address,
unsigned int iaddress,
unsigned char isize);
extern unsigned char TWI_ReadByte(AT91S_TWI *pTwi);
extern void TWI_WriteByte(AT91S_TWI *pTwi, unsigned char byte);
extern void TWI_StartWrite(
AT91S_TWI *pTwi,
unsigned char address,
unsigned int iaddress,
unsigned char isize,
unsigned char byte);
extern unsigned char TWI_ByteReceived(AT91S_TWI *pTwi);
extern unsigned char TWI_ByteSent(AT91S_TWI *pTwi);
extern unsigned char TWI_TransferComplete(AT91S_TWI *pTwi);
extern void TWI_EnableIt(AT91S_TWI *pTwi, unsigned int sources);
extern void TWI_DisableIt(AT91S_TWI *pTwi, unsigned int sources);
extern unsigned int TWI_GetStatus(AT91S_TWI *pTwi);
extern unsigned int TWI_GetMaskedStatus(AT91S_TWI *pTwi);
extern void TWI_SendSTOPCondition(AT91S_TWI *pTwi);
#endif //#ifndef TWI_H

View file

@ -0,0 +1,272 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include "usart.h"
#include <utility/trace.h>
#include <utility/assert.h>
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Configures an USART peripheral with the specified parameters.
/// \param usart Pointer to the USART peripheral to configure.
/// \param mode Desired value for the USART mode register (see the datasheet).
/// \param baudrate Baudrate at which the USART should operate (in Hz).
/// \param masterClock Frequency of the system master clock (in Hz).
//------------------------------------------------------------------------------
void USART_Configure(AT91S_USART *usart,
unsigned int mode,
unsigned int baudrate,
unsigned int masterClock)
{
// Reset and disable receiver & transmitter
usart->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX
| AT91C_US_RXDIS | AT91C_US_TXDIS;
// Configure mode
usart->US_MR = mode;
// Configure baudrate
// Asynchronous, no oversampling
if (((mode & AT91C_US_SYNC) == 0)
&& ((mode & AT91C_US_OVER) == 0)) {
usart->US_BRGR = (masterClock / baudrate) / 16;
}
// TODO other modes
}
//------------------------------------------------------------------------------
/// Enables or disables the transmitter of an USART peripheral.
/// \param usart Pointer to an USART peripheral
/// \param enabled If true, the transmitter is enabled; otherwise it is
/// disabled.
//------------------------------------------------------------------------------
void USART_SetTransmitterEnabled(AT91S_USART *usart,
unsigned char enabled)
{
if (enabled) {
usart->US_CR = AT91C_US_TXEN;
}
else {
usart->US_CR = AT91C_US_TXDIS;
}
}
//------------------------------------------------------------------------------
/// Enables or disables the receiver of an USART peripheral
/// \param usart Pointer to an USART peripheral
/// \param enabled If true, the receiver is enabled; otherwise it is disabled.
//------------------------------------------------------------------------------
void USART_SetReceiverEnabled(AT91S_USART *usart,
unsigned char enabled)
{
if (enabled) {
usart->US_CR = AT91C_US_RXEN;
}
else {
usart->US_CR = AT91C_US_RXDIS;
}
}
//------------------------------------------------------------------------------
/// Sends one packet of data through the specified USART peripheral. This
/// function operates synchronously, so it only returns when the data has been
/// actually sent.
/// \param usart Pointer to an USART peripheral.
/// \param data Data to send including 9nth bit and sync field if necessary (in
/// the same format as the US_THR register in the datasheet).
/// \param timeOut Time out value (0 = no timeout).
//------------------------------------------------------------------------------
void USART_Write(
AT91S_USART *usart,
unsigned short data,
volatile unsigned int timeOut)
{
if (timeOut == 0) {
while ((usart->US_CSR & AT91C_US_TXEMPTY) == 0);
}
else {
while ((usart->US_CSR & AT91C_US_TXEMPTY) == 0) {
if (timeOut == 0) {
TRACE_ERROR("USART_Write: Timed out.\n\r");
return;
}
timeOut--;
}
}
usart->US_THR = data;
}
//------------------------------------------------------------------------------
/// Sends the contents of a data buffer through the specified USART peripheral.
/// This function returns immediately (1 if the buffer has been queued, 0
/// otherwise); poll the ENDTX and TXBUFE bits of the USART status register
/// to check for the transfer completion.
/// \param usart Pointer to an USART peripheral.
/// \param buffer Pointer to the data buffer to send.
/// \param size Size of the data buffer (in bytes).
//------------------------------------------------------------------------------
unsigned char USART_WriteBuffer(
AT91S_USART *usart,
void *buffer,
unsigned int size)
{
// Check if the first PDC bank is free
if ((usart->US_TCR == 0) && (usart->US_TNCR == 0)) {
usart->US_TPR = (unsigned int) buffer;
usart->US_TCR = size;
usart->US_PTCR = AT91C_PDC_TXTEN;
return 1;
}
// Check if the second PDC bank is free
else if (usart->US_TNCR == 0) {
usart->US_TNPR = (unsigned int) buffer;
usart->US_TNCR = size;
return 1;
}
else {
return 0;
}
}
//------------------------------------------------------------------------------
/// Reads and return a packet of data on the specified USART peripheral. This
/// function operates asynchronously, so it waits until some data has been
/// received.
/// \param usart Pointer to an USART peripheral.
/// \param timeOut Time out value (0 -> no timeout).
//------------------------------------------------------------------------------
unsigned short USART_Read(
AT91S_USART *usart,
volatile unsigned int timeOut)
{
if (timeOut == 0) {
while ((usart->US_CSR & AT91C_US_RXRDY) == 0);
}
else {
while ((usart->US_CSR & AT91C_US_RXRDY) == 0) {
if (timeOut == 0) {
TRACE_ERROR("USART_Read: Timed out.\n\r");
return 0;
}
timeOut--;
}
}
return usart->US_RHR;
}
//------------------------------------------------------------------------------
/// Reads data from an USART peripheral, filling the provided buffer until it
/// becomes full. This function returns immediately with 1 if the buffer has
/// been queued for transmission; otherwise 0.
/// \param usart Pointer to an USART peripheral.
/// \param buffer Pointer to the buffer where the received data will be stored.
/// \param size Size of the data buffer (in bytes).
//------------------------------------------------------------------------------
unsigned char USART_ReadBuffer(AT91S_USART *usart,
void *buffer,
unsigned int size)
{
// Check if the first PDC bank is free
if ((usart->US_RCR == 0) && (usart->US_RNCR == 0)) {
usart->US_RPR = (unsigned int) buffer;
usart->US_RCR = size;
usart->US_PTCR = AT91C_PDC_RXTEN;
return 1;
}
// Check if the second PDC bank is free
else if (usart->US_RNCR == 0) {
usart->US_RNPR = (unsigned int) buffer;
usart->US_RNCR = size;
return 1;
}
else {
return 0;
}
}
//------------------------------------------------------------------------------
/// Returns 1 if some data has been received and can be read from an USART;
/// otherwise returns 0.
/// \param usart Pointer to an AT91S_USART instance.
//------------------------------------------------------------------------------
unsigned char USART_IsDataAvailable(AT91S_USART *usart)
{
if ((usart->US_CSR & AT91C_US_RXRDY) != 0) {
return 1;
}
else {
return 0;
}
}
//------------------------------------------------------------------------------
/// Sets the filter value for the IRDA demodulator.
/// \param pUsart Pointer to an AT91S_USART instance.
/// \param filter Filter value.
//------------------------------------------------------------------------------
void USART_SetIrdaFilter(AT91S_USART *pUsart, unsigned char filter)
{
SANITY_CHECK(pUsart);
pUsart->US_IF = filter;
}

View file

@ -0,0 +1,118 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \dir
/// !Purpose
///
/// This module provides several definitions and methods for using an USART
/// peripheral.
///
/// !Usage
/// -# Enable the USART peripheral clock in the PMC.
/// -# Enable the required USART PIOs (see pio.h).
/// -# Configure the UART by calling USART_Configure.
/// -# Enable the transmitter and/or the receiver of the USART using
/// USART_SetTransmitterEnabled and USART_SetReceiverEnabled.
/// -# Send data through the USART using the USART_Write and
/// USART_WriteBuffer methods.
/// -# Receive data from the USART using the USART_Read and
/// USART_ReadBuffer functions; the availability of data can be polled
/// with USART_IsDataAvailable.
/// -# Disable the transmitter and/or the receiver of the USART with
/// USART_SetTransmitterEnabled and USART_SetReceiverEnabled.
//------------------------------------------------------------------------------
#ifndef USART_H
#define USART_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// \page "USART modes"
/// This page lists several common operating modes for an USART peripheral.
///
/// !Modes
/// - USART_MODE_ASYNCHRONOUS
/// - USART_MODE_IRDA
/// Basic asynchronous mode, i.e. 8 bits no parity.
#define USART_MODE_ASYNCHRONOUS (AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE)
/// IRDA mode
#define USART_MODE_IRDA (AT91C_US_USMODE_IRDA | AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE | AT91C_US_FILTER)
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
// Exported functions
//------------------------------------------------------------------------------
extern void USART_Configure(
AT91S_USART *usart,
unsigned int mode,
unsigned int baudrate,
unsigned int masterClock);
extern void USART_SetTransmitterEnabled(AT91S_USART *usart, unsigned char enabled);
extern void USART_SetReceiverEnabled(AT91S_USART *usart, unsigned char enabled);
extern void USART_Write(
AT91S_USART *usart,
unsigned short data,
volatile unsigned int timeOut);
extern unsigned char USART_WriteBuffer(
AT91S_USART *usart,
void *buffer,
unsigned int size);
extern unsigned short USART_Read(
AT91S_USART *usart,
volatile unsigned int timeOut);
extern unsigned char USART_ReadBuffer(
AT91S_USART *usart,
void *buffer,
unsigned int size);
extern unsigned char USART_IsDataAvailable(AT91S_USART *usart);
extern void USART_SetIrdaFilter(AT91S_USART *pUsart, unsigned char filter);
#endif //#ifndef USART_H

View file

@ -0,0 +1,114 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
///
/// !Purpose
///
/// Definition of the ASSERT() and SANITY_CHECK() macros, which are used for
/// runtime condition & parameter verifying.
///
/// !Usage
///
/// -# Use ASSERT() in your code to check the value of function parameters,
/// return values, etc. *Warning:* the ASSERT() condition must not have
/// any side-effect; otherwise, the program may not work properly
/// anymore when assertions are disabled.
/// -# Use SANITY_CHECK() to perform checks with a default error message
/// (outputs the file and line number where the error occured). This
/// reduces memory overhead caused by assertion error strings.
/// -# Initialize the dbgu to see failed assertions at run-time.
/// -# Assertions can be entirely disabled by defining the NOASSERT symbol
/// at compilation time.
//------------------------------------------------------------------------------
#ifndef ASSERT_H
#define ASSERT_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <stdio.h>
#include "trace.h"
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
#if defined(NOASSERT)
#define ASSERT(...)
#define SANITY_CHECK(...)
#else
#if (TRACE_LEVEL == 0)
/// Checks that the given condition is true,
/// otherwise stops the program execution.
/// \param condition Condition to verify.
#define ASSERT(condition, ...) { \
if (!(condition)) { \
while (1); \
} \
}
/// Performs the same duty as the ASSERT() macro
/// \param condition Condition to verify.
#define SANITY_CHECK(condition) ASSERT(condition, ...)
#else
/// Checks that the given condition is true, otherwise displays an error
/// message and stops the program execution.
/// \param condition Condition to verify.
#define ASSERT(condition, ...) { \
if (!(condition)) { \
printf("-F- ASSERT: "); \
printf(__VA_ARGS__); \
while (1); \
} \
}
#define SANITY_ERROR "Sanity check failed at %s:%d\n\r"
/// Performs the same duty as the ASSERT() macro, except a default error
/// message is output if the condition is false.
/// \param condition Condition to verify.
#define SANITY_CHECK(condition) ASSERT(condition, SANITY_ERROR, __FILE__, __LINE__)
#endif
#endif
#endif //#ifndef ASSERT_H

View file

@ -0,0 +1,238 @@
/* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support
* ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
/// \unit
///
/// !Purpose
///
/// Standard output methods for reporting debug information, warnings and
/// errors, which can be easily be turned on/off.
///
/// !Usage
/// -# Initialize the DBGU using TRACE_CONFIGURE() if you intend to eventually
/// disable ALL traces; otherwise use DBGU_Configure().
/// -# Uses the TRACE_DEBUG(), TRACE_INFO(), TRACE_WARNING(), TRACE_ERROR()
/// TRACE_FATAL() macros to output traces throughout the program.
/// -# Each type of trace has a level : Debug 5, Info 4, Warning 3, Error 2
/// and Fatal 1. Disable a group of traces by changing the value of
/// TRACE_LEVEL during compilation; traces with a level bigger than TRACE_LEVEL
/// are not generated. To generate no trace, use the reserved value 0.
/// -# Trace disabling can be static or dynamic. If dynamic disabling is selected
/// the trace level can be modified in runtime. If static disabling is selected
/// the disabled traces are not compiled.
///
/// !Trace level description
/// -# TRACE_DEBUG (5): Traces whose only purpose is for debugging the program,
/// and which do not produce meaningful information otherwise.
/// -# TRACE_INFO (4): Informational trace about the program execution. Should
/// enable the user to see the execution flow.
/// -# TRACE_WARNING (3): Indicates that a minor error has happened. In most case
/// it can be discarded safely; it may even be expected.
/// -# TRACE_ERROR (2): Indicates an error which may not stop the program execution,
/// but which indicates there is a problem with the code.
/// -# TRACE_FATAL (1): Indicates a major error which prevents the program from going
/// any further.
//------------------------------------------------------------------------------
#ifndef TRACE_H
#define TRACE_H
//------------------------------------------------------------------------------
// Headers
//------------------------------------------------------------------------------
#include <board.h>
#include <dbgu/dbgu.h>
#include <pio/pio.h>
#include <stdio.h>
//------------------------------------------------------------------------------
// Global Definitions
//------------------------------------------------------------------------------
/// Softpack Version
#define SOFTPACK_VERSION "1.6RC1"
#define TRACE_LEVEL_DEBUG 5
#define TRACE_LEVEL_INFO 4
#define TRACE_LEVEL_WARNING 3
#define TRACE_LEVEL_ERROR 2
#define TRACE_LEVEL_FATAL 1
#define TRACE_LEVEL_NO_TRACE 0
// By default, all traces are output except the debug one.
#if !defined(TRACE_LEVEL)
#define TRACE_LEVEL TRACE_LEVEL_INFO
#endif
// By default, trace level is static (not dynamic)
#if !defined(DYN_TRACES)
#define DYN_TRACES 0
#endif
#if defined(NOTRACE)
#error "Error: NOTRACE has to be not defined !"
#endif
#undef NOTRACE
#if (DYN_TRACES==0)
#if (TRACE_LEVEL == TRACE_LEVEL_NO_TRACE)
#define NOTRACE
#endif
#endif
//------------------------------------------------------------------------------
// Global Macros
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------
/// Initializes the DBGU
/// \param mode DBGU mode.
/// \param baudrate DBGU baudrate.
/// \param mck Master clock frequency.
//------------------------------------------------------------------------------
#define TRACE_CONFIGURE(mode, baudrate, mck) { \
const Pin pinsDbgu[] = {PINS_DBGU}; \
PIO_Configure(pinsDbgu, PIO_LISTSIZE(pinsDbgu)); \
DBGU_Configure(mode, baudrate, mck); \
}
//------------------------------------------------------------------------------
/// Initializes the DBGU for ISP project
/// \param mode DBGU mode.
/// \param baudrate DBGU baudrate.
/// \param mck Master clock frequency.
//------------------------------------------------------------------------------
#if (TRACE_LEVEL==0) && (DYNTRACE==0)
#define TRACE_CONFIGURE_ISP(mode, baudrate, mck) {}
#else
#define TRACE_CONFIGURE_ISP(mode, baudrate, mck) { \
const Pin pinsDbgu[] = {PINS_DBGU}; \
PIO_Configure(pinsDbgu, PIO_LISTSIZE(pinsDbgu)); \
DBGU_Configure(mode, baudrate, mck); \
}
#endif
//------------------------------------------------------------------------------
/// Outputs a formatted string using <printf> if the log level is high
/// enough. Can be disabled by defining TRACE_LEVEL=0 during compilation.
/// \param format Formatted string to output.
/// \param ... Additional parameters depending on formatted string.
//------------------------------------------------------------------------------
#if defined(NOTRACE)
// Empty macro
#define TRACE_DEBUG(...) { }
#define TRACE_INFO(...) { }
#define TRACE_WARNING(...) { }
#define TRACE_ERROR(...) { }
#define TRACE_FATAL(...) { while(1); }
#define TRACE_DEBUG_WP(...) { }
#define TRACE_INFO_WP(...) { }
#define TRACE_WARNING_WP(...) { }
#define TRACE_ERROR_WP(...) { }
#define TRACE_FATAL_WP(...) { while(1); }
#elif (DYN_TRACES == 1)
// Trace output depends on traceLevel value
#define TRACE_DEBUG(...) { if (traceLevel >= TRACE_LEVEL_DEBUG) { printf("-D- " __VA_ARGS__); } }
#define TRACE_INFO(...) { if (traceLevel >= TRACE_LEVEL_INFO) { printf("-I- " __VA_ARGS__); } }
#define TRACE_WARNING(...) { if (traceLevel >= TRACE_LEVEL_WARNING) { printf("-W- " __VA_ARGS__); } }
#define TRACE_ERROR(...) { if (traceLevel >= TRACE_LEVEL_ERROR) { printf("-E- " __VA_ARGS__); } }
#define TRACE_FATAL(...) { if (traceLevel >= TRACE_LEVEL_FATAL) { printf("-F- " __VA_ARGS__); while(1); } }
#define TRACE_DEBUG_WP(...) { if (traceLevel >= TRACE_LEVEL_DEBUG) { printf(__VA_ARGS__); } }
#define TRACE_INFO_WP(...) { if (traceLevel >= TRACE_LEVEL_INFO) { printf(__VA_ARGS__); } }
#define TRACE_WARNING_WP(...) { if (traceLevel >= TRACE_LEVEL_WARNING) { printf(__VA_ARGS__); } }
#define TRACE_ERROR_WP(...) { if (traceLevel >= TRACE_LEVEL_ERROR) { printf(__VA_ARGS__); } }
#define TRACE_FATAL_WP(...) { if (traceLevel >= TRACE_LEVEL_FATAL) { printf(__VA_ARGS__); while(1); } }
#else
// Trace compilation depends on TRACE_LEVEL value
#if (TRACE_LEVEL >= TRACE_LEVEL_DEBUG)
#define TRACE_DEBUG(...) { printf("-D- " __VA_ARGS__); }
#define TRACE_DEBUG_WP(...) { printf(__VA_ARGS__); }
#else
#define TRACE_DEBUG(...) { }
#define TRACE_DEBUG_WP(...) { }
#endif
#if (TRACE_LEVEL >= TRACE_LEVEL_INFO)
#define TRACE_INFO(...) { printf("-I- " __VA_ARGS__); }
#define TRACE_INFO_WP(...) { printf(__VA_ARGS__); }
#else
#define TRACE_INFO(...) { }
#define TRACE_INFO_WP(...) { }
#endif
#if (TRACE_LEVEL >= TRACE_LEVEL_WARNING)
#define TRACE_WARNING(...) { printf("-W- " __VA_ARGS__); }
#define TRACE_WARNING_WP(...) { printf(__VA_ARGS__); }
#else
#define TRACE_WARNING(...) { }
#define TRACE_WARNING_WP(...) { }
#endif
#if (TRACE_LEVEL >= TRACE_LEVEL_ERROR)
#define TRACE_ERROR(...) { printf("-E- " __VA_ARGS__); }
#define TRACE_ERROR_WP(...) { printf(__VA_ARGS__); }
#else
#define TRACE_ERROR(...) { }
#define TRACE_ERROR_WP(...) { }
#endif
#if (TRACE_LEVEL >= TRACE_LEVEL_FATAL)
#define TRACE_FATAL(...) { printf("-F- " __VA_ARGS__); while(1); }
#define TRACE_FATAL_WP(...) { printf(__VA_ARGS__); while(1); }
#else
#define TRACE_FATAL(...) { while(1); }
#define TRACE_FATAL_WP(...) { while(1); }
#endif
#endif
//------------------------------------------------------------------------------
// Exported variables
//------------------------------------------------------------------------------
// Depending on DYN_TRACES, traceLevel is a modifable runtime variable
// or a define
#if !defined(NOTRACE) && (DYN_TRACES == 1)
extern unsigned int traceLevel;
#endif
#endif //#ifndef TRACE_H

View file

@ -0,0 +1,105 @@
/*
FreeRTOS.org V5.3.0 - Copyright (C) 2003-2009 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License (version 2) as published
by the Free Software Foundation and modified by the FreeRTOS exception.
**NOTE** The exception to the GPL is included to allow you to distribute a
combined work that includes FreeRTOS.org without being obliged to provide
the source code for any proprietary components. Alternative commercial
license and support terms are also available upon request. See the
licensing section of http://www.FreeRTOS.org for full details.
FreeRTOS.org is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along
with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59
Temple Place, Suite 330, Boston, MA 02111-1307 USA.
***************************************************************************
* *
* Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation *
* *
* This is a concise, step by step, 'hands on' guide that describes both *
* general multitasking concepts and FreeRTOS specifics. It presents and *
* explains numerous examples that are written using the FreeRTOS API. *
* Full source code for all the examples is provided in an accompanying *
* .zip file. *
* *
***************************************************************************
1 tab == 4 spaces!
Please ensure to read the configuration and relevant port sections of the
online documentation.
http://www.FreeRTOS.org - Documentation, latest information, license and
contact details.
http://www.SafeRTOS.com - A version that is certified for use in safety
critical systems.
http://www.OpenRTOS.com - Commercial support, development, porting,
licensing and training services.
*/
#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H
/*-----------------------------------------------------------
* Application specific definitions.
*
* These definitions should be adjusted for your particular hardware and
* application requirements.
*
* THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE
* FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE.
*
* See http://www.freertos.org/a00110.html.
*----------------------------------------------------------*/
#define configUSE_PREEMPTION 1
#define configUSE_IDLE_HOOK 0
#define configUSE_TICK_HOOK 1
#define configCPU_CLOCK_HZ ( ( unsigned portLONG ) 48000000 )
#define configTICK_RATE_HZ ( ( portTickType ) 1000 )
#define configMINIMAL_STACK_SIZE ( ( unsigned portSHORT ) 70 )
#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 24000 ) )
#define configMAX_TASK_NAME_LEN ( 12 )
#define configUSE_TRACE_FACILITY 1
#define configUSE_16_BIT_TICKS 0
#define configIDLE_SHOULD_YIELD 0
#define configUSE_CO_ROUTINES 0
#define configUSE_MUTEXES 1
#define configUSE_RECURSIVE_MUTEXES 1
#define configCHECK_FOR_STACK_OVERFLOW 2
#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 )
#define configMAX_CO_ROUTINE_PRIORITIES ( 2 )
#define configQUEUE_REGISTRY_SIZE 10
/* Set the following definitions to 1 to include the API function, or zero
to exclude the API function. */
#define INCLUDE_vTaskPrioritySet 1
#define INCLUDE_uxTaskPriorityGet 1
#define INCLUDE_vTaskDelete 1
#define INCLUDE_vTaskCleanUpResources 0
#define INCLUDE_vTaskSuspend 1
#define INCLUDE_vTaskDelayUntil 1
#define INCLUDE_vTaskDelay 1
#define INCLUDE_uxTaskGetStackHighWaterMark 1
#define configKERNEL_INTERRUPT_PRIORITY ( 0x0f << 4 ) /* Priority 15, or 255 as only the top four bits are implemented. This is the lowest priority. */
#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( 5 << 4 ) /* Priority 5, or 80 as only the top four bits are implemented. */
#endif /* FREERTOS_CONFIG_H */

View file

@ -0,0 +1,140 @@
/*
FreeRTOS.org V5.3.0 - Copyright (C) 2003-2009 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License (version 2) as published
by the Free Software Foundation and modified by the FreeRTOS exception.
**NOTE** The exception to the GPL is included to allow you to distribute a
combined work that includes FreeRTOS.org without being obliged to provide
the source code for any proprietary components. Alternative commercial
license and support terms are also available upon request. See the
licensing section of http://www.FreeRTOS.org for full details.
FreeRTOS.org is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along
with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59
Temple Place, Suite 330, Boston, MA 02111-1307 USA.
***************************************************************************
* *
* Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation *
* *
* This is a concise, step by step, 'hands on' guide that describes both *
* general multitasking concepts and FreeRTOS specifics. It presents and *
* explains numerous examples that are written using the FreeRTOS API. *
* Full source code for all the examples is provided in an accompanying *
* .zip file. *
* *
***************************************************************************
1 tab == 4 spaces!
Please ensure to read the configuration and relevant port sections of the
online documentation.
http://www.FreeRTOS.org - Documentation, latest information, license and
contact details.
http://www.SafeRTOS.com - A version that is certified for use in safety
critical systems.
http://www.OpenRTOS.com - Commercial support, development, porting,
licensing and training services.
*/
/*-----------------------------------------------------------
* Simple IO routines to control the LEDs.
*-----------------------------------------------------------*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
/* Demo includes. */
#include "partest.h"
/* Library includes. */
#include <board.h>
#include <pio/pio.h>
#define partestNUM_LEDS ( sizeof( xLEDPins ) / sizeof( Pin ) )
static const Pin xLEDPins[] = { PINS_LEDS };
/*-----------------------------------------------------------*/
void vParTestInitialise( void )
{
long l;
for( l = 0; l < partestNUM_LEDS; l++ )
{
PIO_Configure( &( xLEDPins[ l ] ), pdTRUE );
}
}
/*-----------------------------------------------------------*/
void vParTestSetLED( unsigned portBASE_TYPE uxLED, signed portBASE_TYPE xValue )
{
if( uxLED < partestNUM_LEDS )
{
if( xValue )
{
/* Turn the LED on. */
portENTER_CRITICAL();
{
if( xLEDPins[ uxLED ].type == PIO_OUTPUT_0 )
{
PIO_Set( &( xLEDPins[ uxLED ]) );
}
else
{
PIO_Clear( &( xLEDPins[ uxLED ] ) );
}
}
portEXIT_CRITICAL();
}
else
{
/* Turn the LED off. */
portENTER_CRITICAL();
{
if( xLEDPins[ uxLED ].type == PIO_OUTPUT_0 )
{
PIO_Clear( &( xLEDPins[ uxLED ] ) );
}
else
{
PIO_Set( &( xLEDPins[ uxLED ] ) );
}
}
portEXIT_CRITICAL();
}
}
}
/*-----------------------------------------------------------*/
void vParTestToggleLED( unsigned portBASE_TYPE uxLED )
{
if( uxLED < partestNUM_LEDS )
{
if( PIO_GetOutputDataStatus( &( xLEDPins[ uxLED ] ) ) )
{
PIO_Clear( &( xLEDPins[ uxLED ] ) );
}
else
{
PIO_Set( &( xLEDPins[ uxLED ] ) );
}
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<workspace>
<project>
<path>$WS_DIR$\RTOSDemo.ewp</path>
</project>
<batchBuild/>
</workspace>

Binary file not shown.

View file

@ -0,0 +1,33 @@
This is an internal working file generated by the Source Browser.
13:26 47s
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\BlockQ.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\GenQTest.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\ParTest.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\PollQ.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\QPeek.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\blocktim.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\board_cstartup_iar.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\board_lowlevel.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\board_memories.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\comtest.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\draw_hx8347.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\exceptions.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\flash.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\font.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\heap_2.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\hx8347.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\integer.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\lcd.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\lcdd_hx8347.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\list.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\main.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\nvic.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\pio.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\pmc.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\port.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\queue.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\recmutex.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\semtest.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\serial.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\tasks.pbi
C:\E\Dev\FreeRTOS\WorkingCopy3\Demo\CORTEX_AT91SAM3U256_IAR\Release\Obj\usart.pbi

View file

@ -0,0 +1,60 @@
/*
FreeRTOS.org V5.3.0 - Copyright (C) 2003-2009 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License (version 2) as published
by the Free Software Foundation and modified by the FreeRTOS exception.
**NOTE** The exception to the GPL is included to allow you to distribute a
combined work that includes FreeRTOS.org without being obliged to provide
the source code for any proprietary components. Alternative commercial
license and support terms are also available upon request. See the
licensing section of http://www.FreeRTOS.org for full details.
FreeRTOS.org is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along
with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59
Temple Place, Suite 330, Boston, MA 02111-1307 USA.
***************************************************************************
* *
* Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation *
* *
* This is a concise, step by step, 'hands on' guide that describes both *
* general multitasking concepts and FreeRTOS specifics. It presents and *
* explains numerous examples that are written using the FreeRTOS API. *
* Full source code for all the examples is provided in an accompanying *
* .zip file. *
* *
***************************************************************************
1 tab == 4 spaces!
Please ensure to read the configuration and relevant port sections of the
online documentation.
http://www.FreeRTOS.org - Documentation, latest information, license and
contact details.
http://www.SafeRTOS.com - A version that is certified for use in safety
critical systems.
http://www.OpenRTOS.com - Commercial support, development, porting,
licensing and training services.
*/
#ifndef LCD_MESSAGE_H
#define LCD_MESSAGE_H
typedef struct
{
char const *pcMessage;
} xLCDMessage;
#endif /* LCD_MESSAGE_H */

View file

@ -0,0 +1,317 @@
/*
FreeRTOS.org V5.3.0 - Copyright (C) 2003-2009 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License (version 2) as published
by the Free Software Foundation and modified by the FreeRTOS exception.
**NOTE** The exception to the GPL is included to allow you to distribute a
combined work that includes FreeRTOS.org without being obliged to provide
the source code for any proprietary components. Alternative commercial
license and support terms are also available upon request. See the
licensing section of http://www.FreeRTOS.org for full details.
FreeRTOS.org is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
more details.
You should have received a copy of the GNU General Public License along
with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59
Temple Place, Suite 330, Boston, MA 02111-1307 USA.
***************************************************************************
* *
* Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation *
* *
* This is a concise, step by step, 'hands on' guide that describes both *
* general multitasking concepts and FreeRTOS specifics. It presents and *
* explains numerous examples that are written using the FreeRTOS API. *
* Full source code for all the examples is provided in an accompanying *
* .zip file. *
* *
***************************************************************************
1 tab == 4 spaces!
Please ensure to read the configuration and relevant port sections of the
online documentation.
http://www.FreeRTOS.org - Documentation, latest information, license and
contact details.
http://www.SafeRTOS.com - A version that is certified for use in safety
critical systems.
http://www.OpenRTOS.com - Commercial support, development, porting,
licensing and training services.
*/
/*
* Creates all the demo application tasks, then starts the scheduler. The WEB
* documentation provides more details of the standard demo application tasks
* (which just exist to test the kernel port and provide an example of how to use
* each FreeRTOS API function).
*
* In addition to the standard demo tasks, the following tasks and tests are
* defined and/or created within this file:
*
* "LCD" task - the LCD task is a 'gatekeeper' task. It is the only task that
* is permitted to access the display directly. Other tasks wishing to write a
* message to the LCD send the message on a queue to the LCD task instead of
* accessing the LCD themselves. The LCD task just blocks on the queue waiting
* for messages - waking and displaying the messages as they arrive. The use
* of a gatekeeper in this manner permits both tasks and interrupts to write to
* the LCD without worrying about mutual exclusion. This is demonstrated by the
* check hook (see below) which sends messages to the display even though it
* executes from an interrupt context.
*
* "Check" hook - This only executes fully every five seconds from the tick
* hook. Its main function is to check that all the standard demo tasks are
* still operational. Should any unexpected behaviour be discovered within a
* demo task then the tick hook will write an error to the LCD (via the LCD task).
* If all the demo tasks are executing with their expected behaviour then the
* check task writes PASS to the LCD (again via the LCD task), as described above.
*
*/
/* Scheduler includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* Demo app includes. */
#include "BlockQ.h"
#include "integer.h"
#include "blocktim.h"
#include "flash.h"
#include "partest.h"
#include "semtest.h"
#include "PollQ.h"
#include "lcd_message.h"
#include "GenQTest.h"
#include "QPeek.h"
#include "recmutex.h"
#include "flash.h"
#include "comtest2.h"
/* Atmel library includes. */
#include <board.h>
#include <lcd/color.h>
#include <lcd/lcdd.h>
#include <lcd/draw.h>
/*-----------------------------------------------------------*/
/* The time between cycles of the 'check' functionality (defined within the
tick hook). */
#define mainCHECK_DELAY ( ( portTickType ) 5000 / portTICK_RATE_MS )
/* The LCD task uses the sprintf function so requires a little more stack too. */
#define mainLCD_TASK_STACK_SIZE ( configMINIMAL_STACK_SIZE * 2 )
/* Task priorities. */
#define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define mainLED_TASK_PRIORITY ( tskIDLE_PRIORITY + 1 )
#define mainCOM_TEST_PRIORITY ( tskIDLE_PRIORITY + 2 )
#define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY )
#define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY )
/* The maximum number of message that can be waiting for display at any one
time. */
#define mainLCD_QUEUE_SIZE ( 3 )
/* Constants used by the comtest tasks. There isn't a spare LED so an invalid
LED is specified. */
#define mainBAUD_RATE ( 115200 )
#define mainCOM_TEST_LED ( 10 )
/*-----------------------------------------------------------*/
/*
* Configure the hardware for the demo.
*/
static void prvSetupHardware( void );
/*
* The LCD gatekeeper task. Tasks wishing to write to the LCD do not access
* the LCD directly, but instead send the message to the LCD gatekeeper task.
*/
static void prvLCDTask( void *pvParameters );
/*
* Hook functions that can get called by the kernel. The 'check' functionality
* is implemented within the tick hook.
*/
void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed char *pcTaskName );
/*
* The tick hook function as described in the comments at the top of this file.
* The tick hook is used to monitor all the standard demo tasks to look for
* errors. The tick hook is also used to demonstrate how the LCD gatekeeper
* task can be used to allow interrupts to write to the LCD.
*/
void vApplicationTickHook( void );
/*-----------------------------------------------------------*/
/* The queue used to send messages to the LCD task. */
static xQueueHandle xLCDQueue;
/*-----------------------------------------------------------*/
int main( void )
{
/* Prepare the hardware. */
prvSetupHardware();
/* Create the queue used by the LCD task. Messages for display on the LCD
are received via this queue. */
xLCDQueue = xQueueCreate( mainLCD_QUEUE_SIZE, sizeof( xLCDMessage ) );
/* Start the standard demo tasks. These do nothing other than test the
port and provide some APU usage examples. */
vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY );
vStartGenericQueueTasks( mainGEN_QUEUE_TASK_PRIORITY );
vStartRecursiveMutexTasks();
vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY );
vCreateBlockTimeTasks();
vStartSemaphoreTasks( mainSEM_TEST_PRIORITY );
vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY );
vStartQueuePeekTasks();
vStartLEDFlashTasks( mainLED_TASK_PRIORITY );
vAltStartComTestTasks( mainCOM_TEST_PRIORITY, mainBAUD_RATE, mainCOM_TEST_LED );
/* Start the tasks defined within this file/specific to this demo. */
xTaskCreate( prvLCDTask, ( signed char * ) "LCD", mainLCD_TASK_STACK_SIZE, NULL, tskIDLE_PRIORITY, NULL );
/* Start the scheduler. */
vTaskStartScheduler();
/* Will only get here if there was insufficient memory to create the idle
task. */
return 0;
}
/*-----------------------------------------------------------*/
void prvSetupHardware( void )
{
/* Initialise the port used for the LED outputs. */
vParTestInitialise();
}
/*-----------------------------------------------------------*/
void vApplicationTickHook( void )
{
static xLCDMessage xMessage = { "PASS" };
static unsigned portLONG ulTicksSinceLastDisplay = 0;
portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
/* Called from every tick interrupt. Have enough ticks passed to make it
time to perform our health status check again? */
ulTicksSinceLastDisplay++;
if( ulTicksSinceLastDisplay >= mainCHECK_DELAY )
{
ulTicksSinceLastDisplay = 0;
/* Has an error been found in any task? */
if( xAreGenericQueueTasksStillRunning() != pdTRUE )
{
xMessage.pcMessage = "ERROR IN GEN Q";
}
if( xAreIntegerMathsTaskStillRunning() != pdTRUE )
{
xMessage.pcMessage = "ERROR IN MATH";
}
else if( xAreBlockingQueuesStillRunning() != pdTRUE )
{
xMessage.pcMessage = "ERROR IN BLOCK Q";
}
else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE )
{
xMessage.pcMessage = "ERROR IN BLOCK TIME";
}
else if( xAreSemaphoreTasksStillRunning() != pdTRUE )
{
xMessage.pcMessage = "ERROR IN SEMAPHORE";
}
else if( xArePollingQueuesStillRunning() != pdTRUE )
{
xMessage.pcMessage = "ERROR IN POLL Q";
}
else if( xAreQueuePeekTasksStillRunning() != pdTRUE )
{
xMessage.pcMessage = "ERROR IN PEEK Q";
}
else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE )
{
xMessage.pcMessage = "ERROR IN REC MUTEX";
}
else if( xAreComTestTasksStillRunning() != pdTRUE )
{
xMessage.pcMessage = "ERROR IN COMTEST";
}
/* Send the message to the LCD gatekeeper for display. */
xHigherPriorityTaskWoken = pdFALSE;
xQueueSendFromISR( xLCDQueue, &xMessage, &xHigherPriorityTaskWoken );
}
}
/*-----------------------------------------------------------*/
void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName )
{
( void ) pxTask;
( void ) pcTaskName;
/* If the parameters have been corrupted then inspect pxCurrentTCB to
identify which task has overflowed its stack. */
for( ;; );
}
/*-----------------------------------------------------------*/
static void prvLCDTask( void *pvParameters )
{
xLCDMessage xMessage;
unsigned long ulY = 0;
const unsigned long ulX = 5;
const unsigned long ulMaxY = 250, ulYIncrement = 22, ulWidth = 250, ulHeight = 20;;
/* Initialize LCD. */
LCDD_Initialize();
LCDD_Start();
LCDD_Fill( ( void * ) BOARD_LCD_BASE, COLOR_WHITE );
LCDD_DrawString( ( void * ) BOARD_LCD_BASE, 1, ulY + 3, " www.FreeRTOS.org", COLOR_BLACK );
for( ;; )
{
/* Wait for a message from the check function (which is executed in
the tick hook). */
xQueueReceive( xLCDQueue, &xMessage, portMAX_DELAY );
/* Clear the space where the old message was. */
LCDD_DrawRectangle( ( void * ) BOARD_LCD_BASE, 0, ulY, ulWidth, ulHeight, COLOR_WHITE );
/* Increment to the next drawing position. */
ulY += ulYIncrement;
/* Have the Y position moved past the end of the LCD? */
if( ulY >= ulMaxY )
{
ulY = 0;
}
/* Draw a new rectangle, in which the message will be written. */
LCDD_DrawRectangle( ( void * ) BOARD_LCD_BASE, 0, ulY, ulWidth, ulHeight, COLOR_GREEN );
/* Write the message. */
LCDD_DrawString( ( void * ) BOARD_LCD_BASE, ulX, ulY + 3, xMessage.pcMessage, COLOR_BLACK );
}
}

View file

@ -0,0 +1,293 @@
/*
Copyright 2001, 2002 Georges Menie (www.menie.org)
stdarg version contributed by Christian Ettinger
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
putchar is the only external dependency for this file,
if you have a working putchar, leave it commented out.
If not, uncomment the define below and
replace outbyte(c) by your own function call.
*/
#define putchar(c) c
#include <stdarg.h>
static void printchar(char **str, int c)
{
//extern int putchar(int c);
if (str) {
**str = (char)c;
++(*str);
}
else
{
(void)putchar(c);
}
}
#define PAD_RIGHT 1
#define PAD_ZERO 2
static int prints(char **out, const char *string, int width, int pad)
{
register int pc = 0, padchar = ' ';
if (width > 0) {
register int len = 0;
register const char *ptr;
for (ptr = string; *ptr; ++ptr) ++len;
if (len >= width) width = 0;
else width -= len;
if (pad & PAD_ZERO) padchar = '0';
}
if (!(pad & PAD_RIGHT)) {
for ( ; width > 0; --width) {
printchar (out, padchar);
++pc;
}
}
for ( ; *string ; ++string) {
printchar (out, *string);
++pc;
}
for ( ; width > 0; --width) {
printchar (out, padchar);
++pc;
}
return pc;
}
/* the following should be enough for 32 bit int */
#define PRINT_BUF_LEN 12
static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)
{
char print_buf[PRINT_BUF_LEN];
register char *s;
register int t, neg = 0, pc = 0;
register unsigned int u = (unsigned int)i;
if (i == 0) {
print_buf[0] = '0';
print_buf[1] = '\0';
return prints (out, print_buf, width, pad);
}
if (sg && b == 10 && i < 0) {
neg = 1;
u = (unsigned int)-i;
}
s = print_buf + PRINT_BUF_LEN-1;
*s = '\0';
while (u) {
t = (int)u % b;
if( t >= 10 )
t += letbase - '0' - 10;
*--s = (char)(t + '0');
u /= b;
}
if (neg) {
if( width && (pad & PAD_ZERO) ) {
printchar (out, '-');
++pc;
--width;
}
else {
*--s = '-';
}
}
return pc + prints (out, s, width, pad);
}
static int print( char **out, const char *format, va_list args )
{
register int width, pad;
register int pc = 0;
char scr[2];
for (; *format != 0; ++format) {
if (*format == '%') {
++format;
width = pad = 0;
if (*format == '\0') break;
if (*format == '%') goto out;
if (*format == '-') {
++format;
pad = PAD_RIGHT;
}
while (*format == '0') {
++format;
pad |= PAD_ZERO;
}
for ( ; *format >= '0' && *format <= '9'; ++format) {
width *= 10;
width += *format - '0';
}
if( *format == 's' ) {
register char *s = (char *)va_arg( args, int );
pc += prints (out, s?s:"(null)", width, pad);
continue;
}
if( *format == 'd' ) {
pc += printi (out, va_arg( args, int ), 10, 1, width, pad, 'a');
continue;
}
if( *format == 'x' ) {
pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'a');
continue;
}
if( *format == 'X' ) {
pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'A');
continue;
}
if( *format == 'u' ) {
pc += printi (out, va_arg( args, int ), 10, 0, width, pad, 'a');
continue;
}
if( *format == 'c' ) {
/* char are converted to int then pushed on the stack */
scr[0] = (char)va_arg( args, int );
scr[1] = '\0';
pc += prints (out, scr, width, pad);
continue;
}
}
else {
out:
printchar (out, *format);
++pc;
}
}
if (out) **out = '\0';
va_end( args );
return pc;
}
int printf(const char *format, ...)
{
va_list args;
va_start( args, format );
return print( 0, format, args );
}
int sprintf(char *out, const char *format, ...)
{
va_list args;
va_start( args, format );
return print( &out, format, args );
}
int snprintf( char *buf, unsigned int count, const char *format, ... )
{
va_list args;
( void ) count;
va_start( args, format );
return print( &buf, format, args );
}
#ifdef TEST_PRINTF
int main(void)
{
char *ptr = "Hello world!";
char *np = 0;
int i = 5;
unsigned int bs = sizeof(int)*8;
int mi;
char buf[80];
mi = (1 << (bs-1)) + 1;
printf("%s\n", ptr);
printf("printf test\n");
printf("%s is null pointer\n", np);
printf("%d = 5\n", i);
printf("%d = - max int\n", mi);
printf("char %c = 'a'\n", 'a');
printf("hex %x = ff\n", 0xff);
printf("hex %02x = 00\n", 0);
printf("signed %d = unsigned %u = hex %x\n", -3, -3, -3);
printf("%d %s(s)%", 0, "message");
printf("\n");
printf("%d %s(s) with %%\n", 0, "message");
sprintf(buf, "justif: \"%-10s\"\n", "left"); printf("%s", buf);
sprintf(buf, "justif: \"%10s\"\n", "right"); printf("%s", buf);
sprintf(buf, " 3: %04d zero padded\n", 3); printf("%s", buf);
sprintf(buf, " 3: %-4d left justif.\n", 3); printf("%s", buf);
sprintf(buf, " 3: %4d right justif.\n", 3); printf("%s", buf);
sprintf(buf, "-3: %04d zero padded\n", -3); printf("%s", buf);
sprintf(buf, "-3: %-4d left justif.\n", -3); printf("%s", buf);
sprintf(buf, "-3: %4d right justif.\n", -3); printf("%s", buf);
return 0;
}
/*
* if you compile this file with
* gcc -Wall $(YOUR_C_OPTIONS) -DTEST_PRINTF -c printf.c
* you will get a normal warning:
* printf.c:214: warning: spurious trailing `%' in format
* this line is testing an invalid % at the end of the format string.
*
* this should display (on 32bit int machine) :
*
* Hello world!
* printf test
* (null) is null pointer
* 5 = 5
* -2147483647 = - max int
* char a = 'a'
* hex ff = ff
* hex 00 = 00
* signed -3 = unsigned 4294967293 = hex fffffffd
* 0 message(s)
* 0 message(s) with %
* justif: "left "
* justif: " right"
* 3: 0003 zero padded
* 3: 3 left justif.
* 3: 3 right justif.
* -3: -003 zero padded
* -3: -3 left justif.
* -3: -3 right justif.
*/
#endif
/* To keep linker happy. */
int write( int i, char* c, int n)
{
(void)i;
(void)n;
(void)c;
return 0;
}

Some files were not shown because too many files have changed in this diff Show more