set linux end of line

Change-Id: I5200f0d6f39b0641cac26a4109a3cd33e8474b9b
This commit is contained in:
Kévin Redon
2018-07-08 13:26:15 +02:00
parent 9a12d68c74
commit 93717e43b3
16 changed files with 6071 additions and 6071 deletions

View File

@@ -1,113 +1,113 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** /**
* \file * \file
* *
* \section Purpose * \section Purpose
* *
* Interface for configuration the Enhanced Embedded Flash Controller (EEFC) peripheral. * Interface for configuration the Enhanced Embedded Flash Controller (EEFC) peripheral.
* *
* \section Usage * \section Usage
* *
* -# Enable/disable %flash ready interrupt sources using EFC_EnableFrdyIt() * -# Enable/disable %flash ready interrupt sources using EFC_EnableFrdyIt()
* and EFC_DisableFrdyIt(). * and EFC_DisableFrdyIt().
* -# Translates the given address into which EEFC, page and offset values * -# Translates the given address into which EEFC, page and offset values
* for difference density %flash memory using EFC_TranslateAddress(). * for difference density %flash memory using EFC_TranslateAddress().
* -# Computes the address of a %flash access given the EFC, page and offset * -# Computes the address of a %flash access given the EFC, page and offset
* for difference density %flash memory using EFC_ComputeAddress(). * for difference density %flash memory using EFC_ComputeAddress().
* -# Start the executing command with EFC_StartCommand() * -# Start the executing command with EFC_StartCommand()
* -# Retrieve the current status of the EFC using EFC_GetStatus(). * -# Retrieve the current status of the EFC using EFC_GetStatus().
* -# Retrieve the result of the last executed command with EFC_GetResult(). * -# Retrieve the result of the last executed command with EFC_GetResult().
*/ */
#ifndef _EEFC_ #ifndef _EEFC_
#define _EEFC_ #define _EEFC_
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Headers * Headers
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include <stdint.h> #include <stdint.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Definitions * Definitions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/* EFC command */ /* EFC command */
#define EFC_FCMD_GETD 0x00 #define EFC_FCMD_GETD 0x00
#define EFC_FCMD_WP 0x01 #define EFC_FCMD_WP 0x01
#define EFC_FCMD_WPL 0x02 #define EFC_FCMD_WPL 0x02
#define EFC_FCMD_EWP 0x03 #define EFC_FCMD_EWP 0x03
#define EFC_FCMD_EWPL 0x04 #define EFC_FCMD_EWPL 0x04
#define EFC_FCMD_EA 0x05 #define EFC_FCMD_EA 0x05
#define EFC_FCMD_SLB 0x08 #define EFC_FCMD_SLB 0x08
#define EFC_FCMD_CLB 0x09 #define EFC_FCMD_CLB 0x09
#define EFC_FCMD_GLB 0x0A #define EFC_FCMD_GLB 0x0A
#define EFC_FCMD_SFB 0x0B #define EFC_FCMD_SFB 0x0B
#define EFC_FCMD_CFB 0x0C #define EFC_FCMD_CFB 0x0C
#define EFC_FCMD_GFB 0x0D #define EFC_FCMD_GFB 0x0D
#define EFC_FCMD_STUI 0x0E /* Start unique ID */ #define EFC_FCMD_STUI 0x0E /* Start unique ID */
#define EFC_FCMD_SPUI 0x0F /* Stop unique ID */ #define EFC_FCMD_SPUI 0x0F /* Stop unique ID */
/* The IAP function entry addreass */ /* The IAP function entry addreass */
#define CHIP_FLASH_IAP_ADDRESS (0x00800008) #define CHIP_FLASH_IAP_ADDRESS (0x00800008)
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported functions * Exported functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
extern void EFC_EnableFrdyIt( Efc* efc ) ; extern void EFC_EnableFrdyIt( Efc* efc ) ;
extern void EFC_DisableFrdyIt( Efc* efc ) ; extern void EFC_DisableFrdyIt( Efc* efc ) ;
extern void EFC_SetWaitState( Efc* efc, uint8_t cycles ) ; extern void EFC_SetWaitState( Efc* efc, uint8_t cycles ) ;
extern void EFC_TranslateAddress( Efc** pEfc, uint32_t dwAddress, uint16_t *pwPage, uint16_t *pwOffset ) ; extern void EFC_TranslateAddress( Efc** pEfc, uint32_t dwAddress, uint16_t *pwPage, uint16_t *pwOffset ) ;
extern void EFC_ComputeAddress( Efc* efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress ) ; extern void EFC_ComputeAddress( Efc* efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress ) ;
extern void EFC_StartCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument ) ; extern void EFC_StartCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument ) ;
extern uint32_t EFC_PerformCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument, uint32_t dwUseIAP ) ; extern uint32_t EFC_PerformCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument, uint32_t dwUseIAP ) ;
extern uint32_t EFC_GetStatus( Efc* efc ) ; extern uint32_t EFC_GetStatus( Efc* efc ) ;
extern uint32_t EFC_GetResult( Efc* efc ) ; extern uint32_t EFC_GetResult( Efc* efc ) ;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* #ifndef _EEFC_ */ #endif /* #ifndef _EEFC_ */

View File

@@ -1,79 +1,79 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** /**
* \file * \file
* *
* The flash driver provides the unified interface for flash program operations. * The flash driver provides the unified interface for flash program operations.
* *
*/ */
#ifndef _FLASHD_ #ifndef _FLASHD_
#define _FLASHD_ #define _FLASHD_
#include <stdint.h> #include <stdint.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported functions * Exported functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
extern void FLASHD_Initialize( uint32_t dwMCk, uint32_t dwUseIAP ) ; extern void FLASHD_Initialize( uint32_t dwMCk, uint32_t dwUseIAP ) ;
extern uint32_t FLASHD_Erase( uint32_t dwAddress ) ; extern uint32_t FLASHD_Erase( uint32_t dwAddress ) ;
extern uint32_t FLASHD_Write( uint32_t dwAddress, const void *pvBuffer, uint32_t dwSize ) ; extern uint32_t FLASHD_Write( uint32_t dwAddress, const void *pvBuffer, uint32_t dwSize ) ;
extern uint32_t FLASHD_Lock( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwActualStart, uint32_t *pdwActualEnd ) ; extern uint32_t FLASHD_Lock( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwActualStart, uint32_t *pdwActualEnd ) ;
extern uint32_t FLASHD_Unlock( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwActualStart, uint32_t *pdwActualEnd ) ; extern uint32_t FLASHD_Unlock( uint32_t dwStart, uint32_t dwEnd, uint32_t *pdwActualStart, uint32_t *pdwActualEnd ) ;
extern uint32_t FLASHD_IsLocked( uint32_t dwStart, uint32_t dwEnd ) ; extern uint32_t FLASHD_IsLocked( uint32_t dwStart, uint32_t dwEnd ) ;
extern uint32_t FLASHD_SetGPNVM( uint8_t gpnvm ) ; extern uint32_t FLASHD_SetGPNVM( uint8_t gpnvm ) ;
extern uint32_t FLASHD_ClearGPNVM( uint8_t gpnvm ) ; extern uint32_t FLASHD_ClearGPNVM( uint8_t gpnvm ) ;
extern uint32_t FLASHD_IsGPNVMSet( uint8_t gpnvm ) ; extern uint32_t FLASHD_IsGPNVMSet( uint8_t gpnvm ) ;
#define FLASHD_IsSecurityBitSet() FLASHD_IsGPNVMSet( 0 ) #define FLASHD_IsSecurityBitSet() FLASHD_IsGPNVMSet( 0 )
#define FLASHD_SetSecurityBit() FLASHD_SetGPNVM( 0 ) #define FLASHD_SetSecurityBit() FLASHD_SetGPNVM( 0 )
extern uint32_t FLASHD_ReadUniqueID( uint32_t* pdwUniqueID ) ; extern uint32_t FLASHD_ReadUniqueID( uint32_t* pdwUniqueID ) ;
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif /* #ifndef _FLASHD_ */ #endif /* #ifndef _FLASHD_ */

View File

@@ -1,290 +1,290 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** \addtogroup efc_module Working with EEFC /** \addtogroup efc_module Working with EEFC
* The EEFC driver provides the interface to configure and use the EEFC * The EEFC driver provides the interface to configure and use the EEFC
* peripheral. * peripheral.
* *
* The user needs to set the number of wait states depending on the frequency used.\n * The user needs to set the number of wait states depending on the frequency used.\n
* Configure number of cycles for flash read/write operations in the FWS field of EEFC_FMR. * Configure number of cycles for flash read/write operations in the FWS field of EEFC_FMR.
* *
* It offers a function to send flash command to EEFC and waits for the * It offers a function to send flash command to EEFC and waits for the
* flash to be ready. * flash to be ready.
* *
* To send flash command, the user could do in either of following way: * To send flash command, the user could do in either of following way:
* <ul> * <ul>
* <li>Write a correct key, command and argument in EEFC_FCR. </li> * <li>Write a correct key, command and argument in EEFC_FCR. </li>
* <li>Or, Use IAP (In Application Programming) function which is executed from * <li>Or, Use IAP (In Application Programming) function which is executed from
* ROM directly, this allows flash programming to be done by code running in flash.</li> * ROM directly, this allows flash programming to be done by code running in flash.</li>
* <li>Once the command is achieved, it can be detected even by polling EEFC_FSR or interrupt. * <li>Once the command is achieved, it can be detected even by polling EEFC_FSR or interrupt.
* </ul> * </ul>
* *
* The command argument could be a page number,GPNVM number or nothing, it depends on * The command argument could be a page number,GPNVM number or nothing, it depends on
* the command itself. Some useful functions in this driver could help user tranlate physical * the command itself. Some useful functions in this driver could help user tranlate physical
* flash address into a page number and vice verse. * flash address into a page number and vice verse.
* *
* For more accurate information, please look at the EEFC section of the * For more accurate information, please look at the EEFC section of the
* Datasheet. * Datasheet.
* *
* Related files :\n * Related files :\n
* \ref efc.c\n * \ref efc.c\n
* \ref efc.h.\n * \ref efc.h.\n
*/ */
/*@{*/ /*@{*/
/*@}*/ /*@}*/
/** /**
* \file * \file
* *
* Implementation of Enhanced Embedded Flash Controller (EEFC). * Implementation of Enhanced Embedded Flash Controller (EEFC).
* *
*/ */
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Headers * Headers
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include "efc.h" #include "efc.h"
#include <assert.h> #include <assert.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported functions * Exported functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* \brief Enables the flash ready interrupt source on the EEFC peripheral. * \brief Enables the flash ready interrupt source on the EEFC peripheral.
* *
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
*/ */
extern void EFC_EnableFrdyIt( Efc* efc ) extern void EFC_EnableFrdyIt( Efc* efc )
{ {
efc->EEFC_FMR |= EEFC_FMR_FRDY ; efc->EEFC_FMR |= EEFC_FMR_FRDY ;
} }
/** /**
* \brief Disables the flash ready interrupt source on the EEFC peripheral. * \brief Disables the flash ready interrupt source on the EEFC peripheral.
* *
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
*/ */
extern void EFC_DisableFrdyIt( Efc* efc ) extern void EFC_DisableFrdyIt( Efc* efc )
{ {
efc->EEFC_FMR &= ~((uint32_t)EEFC_FMR_FRDY) ; efc->EEFC_FMR &= ~((uint32_t)EEFC_FMR_FRDY) ;
} }
/** /**
* \brief Set read/write wait state on the EEFC perpherial. * \brief Set read/write wait state on the EEFC perpherial.
* *
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
* \param cycles the number of wait states in cycle. * \param cycles the number of wait states in cycle.
*/ */
extern void EFC_SetWaitState( Efc* efc, uint8_t ucCycles ) extern void EFC_SetWaitState( Efc* efc, uint8_t ucCycles )
{ {
uint32_t dwValue ; uint32_t dwValue ;
dwValue = efc->EEFC_FMR ; dwValue = efc->EEFC_FMR ;
dwValue &= ~((uint32_t)EEFC_FMR_FWS_Msk) ; dwValue &= ~((uint32_t)EEFC_FMR_FWS_Msk) ;
dwValue |= EEFC_FMR_FWS(ucCycles); dwValue |= EEFC_FMR_FWS(ucCycles);
efc->EEFC_FMR = dwValue ; efc->EEFC_FMR = dwValue ;
} }
/** /**
* \brief Returns the current status of the EEFC. * \brief Returns the current status of the EEFC.
* *
* \note Keep in mind that this function clears the value of some status bits (LOCKE, PROGE). * \note Keep in mind that this function clears the value of some status bits (LOCKE, PROGE).
* *
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
*/ */
extern uint32_t EFC_GetStatus( Efc* efc ) extern uint32_t EFC_GetStatus( Efc* efc )
{ {
return efc->EEFC_FSR ; return efc->EEFC_FSR ;
} }
/** /**
* \brief Returns the result of the last executed command. * \brief Returns the result of the last executed command.
* *
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
*/ */
extern uint32_t EFC_GetResult( Efc* efc ) extern uint32_t EFC_GetResult( Efc* efc )
{ {
return efc->EEFC_FRR ; return efc->EEFC_FRR ;
} }
/** /**
* \brief Translates the given address page and offset values. * \brief Translates the given address page and offset values.
* \note The resulting values are stored in the provided variables if they are not null. * \note The resulting values are stored in the provided variables if they are not null.
* *
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
* \param address Address to translate. * \param address Address to translate.
* \param pPage First page accessed. * \param pPage First page accessed.
* \param pOffset Byte offset in first page. * \param pOffset Byte offset in first page.
*/ */
extern void EFC_TranslateAddress( Efc** ppEfc, uint32_t dwAddress, uint16_t* pwPage, uint16_t* pwOffset ) extern void EFC_TranslateAddress( Efc** ppEfc, uint32_t dwAddress, uint16_t* pwPage, uint16_t* pwOffset )
{ {
Efc *pEfc ; Efc *pEfc ;
uint16_t wPage ; uint16_t wPage ;
uint16_t wOffset ; uint16_t wOffset ;
assert( dwAddress >= IFLASH_ADDR ) ; assert( dwAddress >= IFLASH_ADDR ) ;
assert( dwAddress <= (IFLASH_ADDR + IFLASH_SIZE) ) ; assert( dwAddress <= (IFLASH_ADDR + IFLASH_SIZE) ) ;
pEfc = EFC ; pEfc = EFC ;
wPage = (dwAddress - IFLASH_ADDR) / IFLASH_PAGE_SIZE; wPage = (dwAddress - IFLASH_ADDR) / IFLASH_PAGE_SIZE;
wOffset = (dwAddress - IFLASH_ADDR) % IFLASH_PAGE_SIZE; wOffset = (dwAddress - IFLASH_ADDR) % IFLASH_PAGE_SIZE;
TRACE_DEBUG( "Translated 0x%08X to page=%d and offset=%d\n\r", dwAddress, wPage, wOffset ) ; TRACE_DEBUG( "Translated 0x%08X to page=%d and offset=%d\n\r", dwAddress, wPage, wOffset ) ;
/* Store values */ /* Store values */
if ( pEfc ) if ( pEfc )
{ {
*ppEfc = pEfc ; *ppEfc = pEfc ;
} }
if ( pwPage ) if ( pwPage )
{ {
*pwPage = wPage ; *pwPage = wPage ;
} }
if ( pwOffset ) if ( pwOffset )
{ {
*pwOffset = wOffset ; *pwOffset = wOffset ;
} }
} }
/** /**
* \brief Computes the address of a flash access given the page and offset. * \brief Computes the address of a flash access given the page and offset.
* *
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
* \param page Page number. * \param page Page number.
* \param offset Byte offset inside page. * \param offset Byte offset inside page.
* \param pAddress Computed address (optional). * \param pAddress Computed address (optional).
*/ */
extern void EFC_ComputeAddress( Efc *efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress ) extern void EFC_ComputeAddress( Efc *efc, uint16_t wPage, uint16_t wOffset, uint32_t *pdwAddress )
{ {
uint32_t dwAddress ; uint32_t dwAddress ;
assert( efc ) ; assert( efc ) ;
assert( wPage <= IFLASH_NB_OF_PAGES ) ; assert( wPage <= IFLASH_NB_OF_PAGES ) ;
assert( wOffset < IFLASH_PAGE_SIZE ) ; assert( wOffset < IFLASH_PAGE_SIZE ) ;
/* Compute address */ /* Compute address */
dwAddress = IFLASH_ADDR + wPage * IFLASH_PAGE_SIZE + wOffset ; dwAddress = IFLASH_ADDR + wPage * IFLASH_PAGE_SIZE + wOffset ;
/* Store result */ /* Store result */
if ( pdwAddress != NULL ) if ( pdwAddress != NULL )
{ {
*pdwAddress = dwAddress ; *pdwAddress = dwAddress ;
} }
} }
/** /**
* \brief Starts the executing the given command on the EEFC and returns as soon as the command is started. * \brief Starts the executing the given command on the EEFC and returns as soon as the command is started.
* *
* \note It does NOT set the FMCN field automatically. * \note It does NOT set the FMCN field automatically.
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
* \param command Command to execute. * \param command Command to execute.
* \param argument Command argument (should be 0 if not used). * \param argument Command argument (should be 0 if not used).
*/ */
extern void EFC_StartCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument ) extern void EFC_StartCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument )
{ {
/* Check command & argument */ /* Check command & argument */
switch ( dwCommand ) switch ( dwCommand )
{ {
case EFC_FCMD_WP: case EFC_FCMD_WP:
case EFC_FCMD_WPL: case EFC_FCMD_WPL:
case EFC_FCMD_EWP: case EFC_FCMD_EWP:
case EFC_FCMD_EWPL: case EFC_FCMD_EWPL:
case EFC_FCMD_SLB: case EFC_FCMD_SLB:
case EFC_FCMD_CLB: case EFC_FCMD_CLB:
assert( dwArgument < IFLASH_NB_OF_PAGES ) ; assert( dwArgument < IFLASH_NB_OF_PAGES ) ;
break ; break ;
case EFC_FCMD_SFB: case EFC_FCMD_SFB:
case EFC_FCMD_CFB: case EFC_FCMD_CFB:
assert( dwArgument < 2 ) ; assert( dwArgument < 2 ) ;
break; break;
case EFC_FCMD_GETD: case EFC_FCMD_GETD:
case EFC_FCMD_EA: case EFC_FCMD_EA:
case EFC_FCMD_GLB: case EFC_FCMD_GLB:
case EFC_FCMD_GFB: case EFC_FCMD_GFB:
case EFC_FCMD_STUI: case EFC_FCMD_STUI:
assert( dwArgument == 0 ) ; assert( dwArgument == 0 ) ;
break; break;
default: assert( 0 ) ; default: assert( 0 ) ;
} }
/* Start command Embedded flash */ /* Start command Embedded flash */
assert( (efc->EEFC_FSR & EEFC_FMR_FRDY) == EEFC_FMR_FRDY ) ; assert( (efc->EEFC_FSR & EEFC_FMR_FRDY) == EEFC_FMR_FRDY ) ;
efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ; efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ;
} }
/** /**
* \brief Performs the given command and wait until its completion (or an error). * \brief Performs the given command and wait until its completion (or an error).
* *
* \param efc Pointer to a Efc instance * \param efc Pointer to a Efc instance
* \param command Command to perform. * \param command Command to perform.
* \param argument Optional command argument. * \param argument Optional command argument.
* *
* \return 0 if successful, otherwise returns an error code. * \return 0 if successful, otherwise returns an error code.
*/ */
extern uint32_t EFC_PerformCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument, uint32_t dwUseIAP ) extern uint32_t EFC_PerformCommand( Efc* efc, uint32_t dwCommand, uint32_t dwArgument, uint32_t dwUseIAP )
{ {
if ( dwUseIAP != 0 ) if ( dwUseIAP != 0 )
{ {
/* Pointer on IAP function in ROM */ /* Pointer on IAP function in ROM */
static uint32_t (*IAP_PerformCommand)( uint32_t, uint32_t ) ; static uint32_t (*IAP_PerformCommand)( uint32_t, uint32_t ) ;
IAP_PerformCommand = (uint32_t (*)( uint32_t, uint32_t )) *((uint32_t*)CHIP_FLASH_IAP_ADDRESS ) ; IAP_PerformCommand = (uint32_t (*)( uint32_t, uint32_t )) *((uint32_t*)CHIP_FLASH_IAP_ADDRESS ) ;
IAP_PerformCommand( 0, EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ) ; IAP_PerformCommand( 0, EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ) ;
return (efc->EEFC_FSR & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE)) ; return (efc->EEFC_FSR & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE)) ;
} }
else else
{ {
uint32_t dwStatus ; uint32_t dwStatus ;
efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ; efc->EEFC_FCR = EEFC_FCR_FKEY(0x5A) | EEFC_FCR_FARG(dwArgument) | EEFC_FCR_FCMD(dwCommand) ;
do do
{ {
dwStatus = efc->EEFC_FSR ; dwStatus = efc->EEFC_FSR ;
} }
while ( (dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY ) ; while ( (dwStatus & EEFC_FSR_FRDY) != EEFC_FSR_FRDY ) ;
return ( dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE) ) ; return ( dwStatus & (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE) ) ;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,453 +1,453 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2010, Atmel Corporation * Copyright (c) 2010, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** \file */ /** \file */
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Headers * Headers
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include "pio.h" #include "pio.h"
#include "pmc.h" #include "pmc.h"
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Local functions * Local functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* \brief Configures one or more pin(s) of a PIO controller as being controlled by * \brief 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. * peripheral A. Optionally, the corresponding internal pull-up(s) can be enabled.
* *
* \param pio Pointer to a PIO controller. * \param pio Pointer to a PIO controller.
* \param mask Bitmask of one or more pin(s) to configure. * \param mask Bitmask of one or more pin(s) to configure.
* \param enablePullUp Indicates if the pin(s) internal pull-up shall be * \param enablePullUp Indicates if the pin(s) internal pull-up shall be
* configured. * configured.
*/ */
static void PIO_SetPeripheralA( static void PIO_SetPeripheralA(
Pio *pio, Pio *pio,
unsigned int mask, unsigned int mask,
unsigned char enablePullUp) unsigned char enablePullUp)
{ {
unsigned int abcdsr; unsigned int abcdsr;
/* Disable interrupts on the pin(s) */ /* Disable interrupts on the pin(s) */
pio->PIO_IDR = mask; pio->PIO_IDR = mask;
/* Enable the pull-up(s) if necessary */ /* Enable the pull-up(s) if necessary */
if (enablePullUp) { if (enablePullUp) {
pio->PIO_PUER = mask; pio->PIO_PUER = mask;
} }
else { else {
pio->PIO_PUDR = mask; pio->PIO_PUDR = mask;
} }
abcdsr = pio->PIO_ABCDSR[0]; abcdsr = pio->PIO_ABCDSR[0];
pio->PIO_ABCDSR[0] &= (~mask & abcdsr); pio->PIO_ABCDSR[0] &= (~mask & abcdsr);
abcdsr = pio->PIO_ABCDSR[1]; abcdsr = pio->PIO_ABCDSR[1];
pio->PIO_ABCDSR[1] &= (~mask & abcdsr); pio->PIO_ABCDSR[1] &= (~mask & abcdsr);
pio->PIO_PDR = mask; pio->PIO_PDR = mask;
} }
/** /**
* \brief Configures one or more pin(s) of a PIO controller as being controlled by * \brief 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. * peripheral B. Optionally, the corresponding internal pull-up(s) can be enabled.
* *
* \param pio Pointer to a PIO controller. * \param pio Pointer to a PIO controller.
* \param mask Bitmask of one or more pin(s) to configure. * \param mask Bitmask of one or more pin(s) to configure.
* \param enablePullUp Indicates if the pin(s) internal pull-up shall be * \param enablePullUp Indicates if the pin(s) internal pull-up shall be
* configured. * configured.
*/ */
static void PIO_SetPeripheralB( static void PIO_SetPeripheralB(
Pio *pio, Pio *pio,
unsigned int mask, unsigned int mask,
unsigned char enablePullUp) unsigned char enablePullUp)
{ {
unsigned int abcdsr; unsigned int abcdsr;
/* Disable interrupts on the pin(s) */ /* Disable interrupts on the pin(s) */
pio->PIO_IDR = mask; pio->PIO_IDR = mask;
/* Enable the pull-up(s) if necessary */ /* Enable the pull-up(s) if necessary */
if (enablePullUp) { if (enablePullUp) {
pio->PIO_PUER = mask; pio->PIO_PUER = mask;
} }
else { else {
pio->PIO_PUDR = mask; pio->PIO_PUDR = mask;
} }
abcdsr = pio->PIO_ABCDSR[0]; abcdsr = pio->PIO_ABCDSR[0];
pio->PIO_ABCDSR[0] = (mask | abcdsr); pio->PIO_ABCDSR[0] = (mask | abcdsr);
abcdsr = pio->PIO_ABCDSR[1]; abcdsr = pio->PIO_ABCDSR[1];
pio->PIO_ABCDSR[1] &= (~mask & abcdsr); pio->PIO_ABCDSR[1] &= (~mask & abcdsr);
pio->PIO_PDR = mask; pio->PIO_PDR = mask;
} }
/** /**
* \brief Configures one or more pin(s) of a PIO controller as being controlled by * \brief Configures one or more pin(s) of a PIO controller as being controlled by
* peripheral C. Optionally, the corresponding internal pull-up(s) can be enabled. * peripheral C. Optionally, the corresponding internal pull-up(s) can be enabled.
* *
* \param pio Pointer to a PIO controller. * \param pio Pointer to a PIO controller.
* \param mask Bitmask of one or more pin(s) to configure. * \param mask Bitmask of one or more pin(s) to configure.
* \param enablePullUp Indicates if the pin(s) internal pull-up shall be * \param enablePullUp Indicates if the pin(s) internal pull-up shall be
* configured. * configured.
*/ */
static void PIO_SetPeripheralC( static void PIO_SetPeripheralC(
Pio *pio, Pio *pio,
unsigned int mask, unsigned int mask,
unsigned char enablePullUp) unsigned char enablePullUp)
{ {
unsigned int abcdsr; unsigned int abcdsr;
/* Disable interrupts on the pin(s) */ /* Disable interrupts on the pin(s) */
pio->PIO_IDR = mask; pio->PIO_IDR = mask;
/* Enable the pull-up(s) if necessary */ /* Enable the pull-up(s) if necessary */
if (enablePullUp) { if (enablePullUp) {
pio->PIO_PUER = mask; pio->PIO_PUER = mask;
} }
else { else {
pio->PIO_PUDR = mask; pio->PIO_PUDR = mask;
} }
abcdsr = pio->PIO_ABCDSR[0]; abcdsr = pio->PIO_ABCDSR[0];
pio->PIO_ABCDSR[0] &= (~mask & abcdsr); pio->PIO_ABCDSR[0] &= (~mask & abcdsr);
abcdsr = pio->PIO_ABCDSR[1]; abcdsr = pio->PIO_ABCDSR[1];
pio->PIO_ABCDSR[1] = (mask | abcdsr); pio->PIO_ABCDSR[1] = (mask | abcdsr);
pio->PIO_PDR = mask; pio->PIO_PDR = mask;
} }
/** /**
* \brief Configures one or more pin(s) of a PIO controller as being controlled by * \brief Configures one or more pin(s) of a PIO controller as being controlled by
* peripheral D. Optionally, the corresponding internal pull-up(s) can be enabled. * peripheral D. Optionally, the corresponding internal pull-up(s) can be enabled.
* *
* \param pio Pointer to a PIO controller. * \param pio Pointer to a PIO controller.
* \param mask Bitmask of one or more pin(s) to configure. * \param mask Bitmask of one or more pin(s) to configure.
* \param enablePullUp Indicates if the pin(s) internal pull-up shall be * \param enablePullUp Indicates if the pin(s) internal pull-up shall be
* configured. * configured.
*/ */
static void PIO_SetPeripheralD( static void PIO_SetPeripheralD(
Pio *pio, Pio *pio,
unsigned int mask, unsigned int mask,
unsigned char enablePullUp) unsigned char enablePullUp)
{ {
unsigned int abcdsr; unsigned int abcdsr;
/* Disable interrupts on the pin(s) */ /* Disable interrupts on the pin(s) */
pio->PIO_IDR = mask; pio->PIO_IDR = mask;
/* Enable the pull-up(s) if necessary */ /* Enable the pull-up(s) if necessary */
if (enablePullUp) { if (enablePullUp) {
pio->PIO_PUER = mask; pio->PIO_PUER = mask;
} }
else { else {
pio->PIO_PUDR = mask; pio->PIO_PUDR = mask;
} }
abcdsr = pio->PIO_ABCDSR[0]; abcdsr = pio->PIO_ABCDSR[0];
pio->PIO_ABCDSR[0] = (mask | abcdsr); pio->PIO_ABCDSR[0] = (mask | abcdsr);
abcdsr = pio->PIO_ABCDSR[1]; abcdsr = pio->PIO_ABCDSR[1];
pio->PIO_ABCDSR[1] = (mask | abcdsr); pio->PIO_ABCDSR[1] = (mask | abcdsr);
pio->PIO_PDR = mask; pio->PIO_PDR = mask;
} }
/** /**
* \brief Configures one or more pin(s) or a PIO controller as inputs. Optionally, * \brief 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. * the corresponding internal pull-up(s) and glitch filter(s) can be enabled.
* *
* \param pio Pointer to a PIO controller. * \param pio Pointer to a PIO controller.
* \param mask Bitmask indicating which pin(s) to configure as input(s). * \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 enablePullUp Indicates if the internal pull-up(s) must be enabled.
* \param enableFilter Indicates if the glitch filter(s) must be enabled. * \param enableFilter Indicates if the glitch filter(s) must be enabled.
*/ */
static void PIO_SetInput( static void PIO_SetInput(
Pio *pio, Pio *pio,
unsigned int mask, unsigned int mask,
unsigned char attribute) unsigned char attribute)
{ {
/* Disable interrupts */ /* Disable interrupts */
pio->PIO_IDR = mask; pio->PIO_IDR = mask;
/* Enable pull-up(s) if necessary */ /* Enable pull-up(s) if necessary */
if (attribute & PIO_PULLUP) if (attribute & PIO_PULLUP)
pio->PIO_PUER = mask; pio->PIO_PUER = mask;
else else
pio->PIO_PUDR = mask; pio->PIO_PUDR = mask;
/* Enable Input Filter if necessary */ /* Enable Input Filter if necessary */
if (attribute & (PIO_DEGLITCH | PIO_DEBOUNCE)) if (attribute & (PIO_DEGLITCH | PIO_DEBOUNCE))
pio->PIO_IFER = mask; pio->PIO_IFER = mask;
else else
pio->PIO_IFDR = mask; pio->PIO_IFDR = mask;
/* Enable de-glitch or de-bounce if necessary */ /* Enable de-glitch or de-bounce if necessary */
if (attribute & PIO_DEGLITCH) if (attribute & PIO_DEGLITCH)
{ {
pio->PIO_IFSCDR = mask; pio->PIO_IFSCDR = mask;
} }
else else
{ {
if (attribute & PIO_DEBOUNCE) if (attribute & PIO_DEBOUNCE)
{ {
pio->PIO_IFSCER = mask; pio->PIO_IFSCER = mask;
} }
} }
/* Configure pin as input */ /* Configure pin as input */
pio->PIO_ODR = mask; pio->PIO_ODR = mask;
pio->PIO_PER = mask; pio->PIO_PER = mask;
} }
/** /**
* \brief Configures one or more pin(s) of a PIO controller as outputs, with the * \brief 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 * given default value. Optionally, the multi-drive feature can be enabled
* on the pin(s). * on the pin(s).
* *
* \param pio Pointer to a PIO controller. * \param pio Pointer to a PIO controller.
* \param mask Bitmask indicating which pin(s) to configure. * \param mask Bitmask indicating which pin(s) to configure.
* \param defaultValue Default level on the pin(s). * \param defaultValue Default level on the pin(s).
* \param enableMultiDrive Indicates if the pin(s) shall be configured as * \param enableMultiDrive Indicates if the pin(s) shall be configured as
* open-drain. * open-drain.
* \param enablePullUp Indicates if the pin shall have its pull-up activated. * \param enablePullUp Indicates if the pin shall have its pull-up activated.
*/ */
static void PIO_SetOutput( static void PIO_SetOutput(
Pio *pio, Pio *pio,
unsigned int mask, unsigned int mask,
unsigned char defaultValue, unsigned char defaultValue,
unsigned char enableMultiDrive, unsigned char enableMultiDrive,
unsigned char enablePullUp) unsigned char enablePullUp)
{ {
/* Disable interrupts */ /* Disable interrupts */
pio->PIO_IDR = mask; pio->PIO_IDR = mask;
/* Enable pull-up(s) if necessary */ /* Enable pull-up(s) if necessary */
if (enablePullUp) { if (enablePullUp) {
pio->PIO_PUER = mask; pio->PIO_PUER = mask;
} }
else { else {
pio->PIO_PUDR = mask; pio->PIO_PUDR = mask;
} }
/* Enable multi-drive if necessary */ /* Enable multi-drive if necessary */
if (enableMultiDrive) { if (enableMultiDrive) {
pio->PIO_MDER = mask; pio->PIO_MDER = mask;
} }
else { else {
pio->PIO_MDDR = mask; pio->PIO_MDDR = mask;
} }
/* Set default value */ /* Set default value */
if (defaultValue) { if (defaultValue) {
pio->PIO_SODR = mask; pio->PIO_SODR = mask;
} }
else { else {
pio->PIO_CODR = mask; pio->PIO_CODR = mask;
} }
/* Configure pin(s) as output(s) */ /* Configure pin(s) as output(s) */
pio->PIO_OER = mask; pio->PIO_OER = mask;
pio->PIO_PER = mask; pio->PIO_PER = mask;
} }
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Global functions * Global functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* \brief Configures a list of Pin instances, each of which can either hold a single * \brief 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 * 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 * 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. * computed using PIO_LISTSIZE whenever its length is not known in advance.
* *
* \param list Pointer to a list of Pin instances. * \param list Pointer to a list of Pin instances.
* \param size Size of the Pin list (calculated using PIO_LISTSIZE). * \param size Size of the Pin list (calculated using PIO_LISTSIZE).
* *
* \return 1 if the pins have been configured properly; otherwise 0. * \return 1 if the pins have been configured properly; otherwise 0.
*/ */
uint8_t PIO_Configure( const Pin *list, uint32_t size ) uint8_t PIO_Configure( const Pin *list, uint32_t size )
{ {
/* Configure pins */ /* Configure pins */
while ( size > 0 ) while ( size > 0 )
{ {
switch ( list->type ) switch ( list->type )
{ {
case PIO_PERIPH_A: case PIO_PERIPH_A:
PIO_SetPeripheralA(list->pio, PIO_SetPeripheralA(list->pio,
list->mask, list->mask,
(list->attribute & PIO_PULLUP) ? 1 : 0); (list->attribute & PIO_PULLUP) ? 1 : 0);
break; break;
case PIO_PERIPH_B: case PIO_PERIPH_B:
PIO_SetPeripheralB(list->pio, PIO_SetPeripheralB(list->pio,
list->mask, list->mask,
(list->attribute & PIO_PULLUP) ? 1 : 0); (list->attribute & PIO_PULLUP) ? 1 : 0);
break; break;
case PIO_PERIPH_C: case PIO_PERIPH_C:
PIO_SetPeripheralC(list->pio, PIO_SetPeripheralC(list->pio,
list->mask, list->mask,
(list->attribute & PIO_PULLUP) ? 1 : 0); (list->attribute & PIO_PULLUP) ? 1 : 0);
break; break;
case PIO_PERIPH_D: case PIO_PERIPH_D:
PIO_SetPeripheralD(list->pio, PIO_SetPeripheralD(list->pio,
list->mask, list->mask,
(list->attribute & PIO_PULLUP) ? 1 : 0); (list->attribute & PIO_PULLUP) ? 1 : 0);
break; break;
case PIO_INPUT: case PIO_INPUT:
PMC_EnablePeripheral(list->id); PMC_EnablePeripheral(list->id);
PIO_SetInput(list->pio, PIO_SetInput(list->pio,
list->mask, list->mask,
list->attribute); list->attribute);
break; break;
case PIO_OUTPUT_0: case PIO_OUTPUT_0:
case PIO_OUTPUT_1: case PIO_OUTPUT_1:
PIO_SetOutput(list->pio, PIO_SetOutput(list->pio,
list->mask, list->mask,
(list->type == PIO_OUTPUT_1), (list->type == PIO_OUTPUT_1),
(list->attribute & PIO_OPENDRAIN) ? 1 : 0, (list->attribute & PIO_OPENDRAIN) ? 1 : 0,
(list->attribute & PIO_PULLUP) ? 1 : 0); (list->attribute & PIO_PULLUP) ? 1 : 0);
break; break;
default: return 0; default: return 0;
} }
list++; list++;
size--; size--;
} }
return 1; return 1;
} }
/** /**
* \brief Sets a high output level on all the PIOs defined in the given Pin instance. * \brief 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 * This has no immediate effects on PIOs that are not output, but the PIO
* controller will memorize the value they are changed to outputs. * controller will memorize the value they are changed to outputs.
* *
* \param pin Pointer to a Pin instance describing one or more pins. * \param pin Pointer to a Pin instance describing one or more pins.
*/ */
void PIO_Set(const Pin *pin) void PIO_Set(const Pin *pin)
{ {
pin->pio->PIO_SODR = pin->mask; pin->pio->PIO_SODR = pin->mask;
} }
/** /**
* \brief Sets a low output level on all the PIOs defined in the given Pin instance. * \brief 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 * This has no immediate effects on PIOs that are not output, but the PIO
* controller will memorize the value they are changed to outputs. * controller will memorize the value they are changed to outputs.
* *
* \param pin Pointer to a Pin instance describing one or more pins. * \param pin Pointer to a Pin instance describing one or more pins.
*/ */
void PIO_Clear(const Pin *pin) void PIO_Clear(const Pin *pin)
{ {
pin->pio->PIO_CODR = pin->mask; pin->pio->PIO_CODR = pin->mask;
} }
/** /**
* \brief Returns 1 if one or more PIO of the given Pin instance currently have * \brief 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 * 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 * is being read on the pin. To return the supposed output value of a pin, use
* PIO_GetOutputDataStatus() instead. * PIO_GetOutputDataStatus() instead.
* *
* \param pin Pointer to a Pin instance describing one or more pins. * \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 * \return 1 if the Pin instance contains at least one PIO that currently has
* a high level; otherwise 0. * a high level; otherwise 0.
*/ */
unsigned char PIO_Get( const Pin *pin ) unsigned char PIO_Get( const Pin *pin )
{ {
unsigned int reg ; unsigned int reg ;
if ( (pin->type == PIO_OUTPUT_0) || (pin->type == PIO_OUTPUT_1) ) if ( (pin->type == PIO_OUTPUT_0) || (pin->type == PIO_OUTPUT_1) )
{ {
reg = pin->pio->PIO_ODSR ; reg = pin->pio->PIO_ODSR ;
} }
else else
{ {
reg = pin->pio->PIO_PDSR ; reg = pin->pio->PIO_PDSR ;
} }
if ( (reg & pin->mask) == 0 ) if ( (reg & pin->mask) == 0 )
{ {
return 0 ; return 0 ;
} }
else else
{ {
return 1 ; return 1 ;
} }
} }
/** /**
* \brief Returns 1 if one or more PIO of the given Pin are configured to output a * \brief Returns 1 if one or more PIO of the given Pin are configured to output a
* high level (even if they are not output). * high level (even if they are not output).
* To get the actual value of the pin, use PIO_Get() instead. * To get the actual value of the pin, use PIO_Get() instead.
* *
* \param pin Pointer to a Pin instance describing one or more pins. * \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 * \return 1 if the Pin instance contains at least one PIO that is configured
* to output a high level; otherwise 0. * to output a high level; otherwise 0.
*/ */
unsigned char PIO_GetOutputDataStatus(const Pin *pin) unsigned char PIO_GetOutputDataStatus(const Pin *pin)
{ {
if ((pin->pio->PIO_ODSR & pin->mask) == 0) { if ((pin->pio->PIO_ODSR & pin->mask) == 0) {
return 0; return 0;
} }
else { else {
return 1; return 1;
} }
} }
/* /*
* \brief Configures Glitch or Debouncing filter for input. * \brief Configures Glitch or Debouncing filter for input.
* *
* \param pin Pointer to a Pin instance describing one or more pins. * \param pin Pointer to a Pin instance describing one or more pins.
* \param cuttoff Cutt off frequency for debounce filter. * \param cuttoff Cutt off frequency for debounce filter.
*/ */
void PIO_SetDebounceFilter( const Pin *pin, uint32_t cuttoff ) void PIO_SetDebounceFilter( const Pin *pin, uint32_t cuttoff )
{ {
Pio *pio = pin->pio; Pio *pio = pin->pio;
pio->PIO_IFSCER = pin->mask; /* set Debouncing, 0 bit field no effect */ pio->PIO_IFSCER = pin->mask; /* set Debouncing, 0 bit field no effect */
pio->PIO_SCDR = ((32678/(2*(cuttoff))) - 1) & 0x3FFF; /* the lowest 14 bits work */ pio->PIO_SCDR = ((32678/(2*(cuttoff))) - 1) & 0x3FFF; /* the lowest 14 bits work */
} }

View File

@@ -1,315 +1,315 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2008, Atmel Corporation * Copyright (c) 2008, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/* /*
* \file * \file
*/ */
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Headers * Headers
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include <assert.h> #include <assert.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Local definitions * Local definitions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/* Maximum number of interrupt sources that can be defined. This /* Maximum number of interrupt sources that can be defined. This
* constant can be increased, but the current value is the smallest possible * constant can be increased, but the current value is the smallest possible
* that will be compatible with all existing projects. */ * that will be compatible with all existing projects. */
#define MAX_INTERRUPT_SOURCES 7 #define MAX_INTERRUPT_SOURCES 7
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Local types * Local types
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* Describes a PIO interrupt source, including the PIO instance triggering the * Describes a PIO interrupt source, including the PIO instance triggering the
* interrupt and the associated interrupt handler. * interrupt and the associated interrupt handler.
*/ */
typedef struct _InterruptSource typedef struct _InterruptSource
{ {
/* Pointer to the source pin instance. */ /* Pointer to the source pin instance. */
const Pin *pPin; const Pin *pPin;
/* Interrupt handler. */ /* Interrupt handler. */
void (*handler)( const Pin* ) ; void (*handler)( const Pin* ) ;
} InterruptSource ; } InterruptSource ;
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Local variables * Local variables
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/* List of interrupt sources. */ /* List of interrupt sources. */
static InterruptSource _aIntSources[MAX_INTERRUPT_SOURCES] ; static InterruptSource _aIntSources[MAX_INTERRUPT_SOURCES] ;
/* Number of currently defined interrupt sources. */ /* Number of currently defined interrupt sources. */
static uint32_t _dwNumSources = 0; static uint32_t _dwNumSources = 0;
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Local Functions * Local Functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
/** /**
* \brief Stub, to handling all PIO Capture interrupts, if not defined. * \brief Stub, to handling all PIO Capture interrupts, if not defined.
*/ */
/*----------------------------------------------------------------------------*/ /*----------------------------------------------------------------------------*/
extern WEAK void PIO_CaptureHandler( void ) extern WEAK void PIO_CaptureHandler( void )
{ {
} }
/** /**
* \brief Handles all interrupts on the given PIO controller. * \brief Handles all interrupts on the given PIO controller.
* \param id PIO controller ID. * \param id PIO controller ID.
* \param pPio PIO controller base address. * \param pPio PIO controller base address.
*/ */
extern void PioInterruptHandler( uint32_t id, Pio *pPio ) extern void PioInterruptHandler( uint32_t id, Pio *pPio )
{ {
uint32_t status; uint32_t status;
uint32_t i; uint32_t i;
/* Read PIO controller status */ /* Read PIO controller status */
status = pPio->PIO_ISR; status = pPio->PIO_ISR;
status &= pPio->PIO_IMR; status &= pPio->PIO_IMR;
/* Check pending events */ /* Check pending events */
if ( status != 0 ) if ( status != 0 )
{ {
TRACE_DEBUG( "PIO interrupt on PIO controller #%" PRIu32 "\n\r", id ) ; TRACE_DEBUG( "PIO interrupt on PIO controller #%" PRIu32 "\n\r", id ) ;
/* Find triggering source */ /* Find triggering source */
i = 0; i = 0;
while ( status != 0 ) while ( status != 0 )
{ {
/* There cannot be an unconfigured source enabled. */ /* There cannot be an unconfigured source enabled. */
assert(i < _dwNumSources); assert(i < _dwNumSources);
/* Source is configured on the same controller */ /* Source is configured on the same controller */
if (_aIntSources[i].pPin->id == id) if (_aIntSources[i].pPin->id == id)
{ {
/* Source has PIOs whose statuses have changed */ /* Source has PIOs whose statuses have changed */
if ( (status & _aIntSources[i].pPin->mask) != 0 ) if ( (status & _aIntSources[i].pPin->mask) != 0 )
{ {
TRACE_DEBUG( "Interrupt source #%" PRIu32 " triggered\n\r", i ) ; TRACE_DEBUG( "Interrupt source #%" PRIu32 " triggered\n\r", i ) ;
_aIntSources[i].handler(_aIntSources[i].pPin); _aIntSources[i].handler(_aIntSources[i].pPin);
status &= ~(_aIntSources[i].pPin->mask); status &= ~(_aIntSources[i].pPin->mask);
} }
} }
i++; i++;
} }
} }
} }
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Global Functions * Global Functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* \brief Parallel IO Controller A interrupt handler * \brief Parallel IO Controller A interrupt handler
* \Redefined PIOA interrupt handler for NVIC interrupt table. * \Redefined PIOA interrupt handler for NVIC interrupt table.
*/ */
extern void PIOA_IrqHandler( void ) extern void PIOA_IrqHandler( void )
{ {
if ( PIOA->PIO_PCISR != 0 ) if ( PIOA->PIO_PCISR != 0 )
{ {
PIO_CaptureHandler() ; PIO_CaptureHandler() ;
} }
PioInterruptHandler( ID_PIOA, PIOA ) ; PioInterruptHandler( ID_PIOA, PIOA ) ;
} }
/** /**
* \brief Parallel IO Controller B interrupt handler * \brief Parallel IO Controller B interrupt handler
* \Redefined PIOB interrupt handler for NVIC interrupt table. * \Redefined PIOB interrupt handler for NVIC interrupt table.
*/ */
extern void PIOB_IrqHandler( void ) extern void PIOB_IrqHandler( void )
{ {
PioInterruptHandler( ID_PIOB, PIOB ) ; PioInterruptHandler( ID_PIOB, PIOB ) ;
} }
/** /**
* \brief Parallel IO Controller C interrupt handler * \brief Parallel IO Controller C interrupt handler
* \Redefined PIOC interrupt handler for NVIC interrupt table. * \Redefined PIOC interrupt handler for NVIC interrupt table.
*/ */
extern void PIOC_IrqHandler( void ) extern void PIOC_IrqHandler( void )
{ {
PioInterruptHandler( ID_PIOC, PIOC ) ; PioInterruptHandler( ID_PIOC, PIOC ) ;
} }
/** /**
* \brief Initializes the PIO interrupt management logic * \brief Initializes the PIO interrupt management logic
* *
* The desired priority of PIO interrupts must be provided. * The desired priority of PIO interrupts must be provided.
* Calling this function multiple times result in the reset of currently * Calling this function multiple times result in the reset of currently
* configured interrupts. * configured interrupts.
* *
* \param priority PIO controller interrupts priority. * \param priority PIO controller interrupts priority.
*/ */
extern void PIO_InitializeInterrupts( uint32_t dwPriority ) extern void PIO_InitializeInterrupts( uint32_t dwPriority )
{ {
TRACE_DEBUG( "PIO_Initialize()\n\r" ) ; TRACE_DEBUG( "PIO_Initialize()\n\r" ) ;
/* Reset sources */ /* Reset sources */
_dwNumSources = 0 ; _dwNumSources = 0 ;
/* Configure PIO interrupt sources */ /* Configure PIO interrupt sources */
TRACE_DEBUG( "PIO_Initialize: Configuring PIOA\n\r" ) ; TRACE_DEBUG( "PIO_Initialize: Configuring PIOA\n\r" ) ;
PMC_EnablePeripheral( ID_PIOA ) ; PMC_EnablePeripheral( ID_PIOA ) ;
PIOA->PIO_ISR ; PIOA->PIO_ISR ;
PIOA->PIO_IDR = 0xFFFFFFFF ; PIOA->PIO_IDR = 0xFFFFFFFF ;
NVIC_DisableIRQ( PIOA_IRQn ) ; NVIC_DisableIRQ( PIOA_IRQn ) ;
NVIC_ClearPendingIRQ( PIOA_IRQn ) ; NVIC_ClearPendingIRQ( PIOA_IRQn ) ;
NVIC_SetPriority( PIOA_IRQn, dwPriority ) ; NVIC_SetPriority( PIOA_IRQn, dwPriority ) ;
NVIC_EnableIRQ( PIOA_IRQn ) ; NVIC_EnableIRQ( PIOA_IRQn ) ;
TRACE_DEBUG( "PIO_Initialize: Configuring PIOB\n\r" ) ; TRACE_DEBUG( "PIO_Initialize: Configuring PIOB\n\r" ) ;
PMC_EnablePeripheral( ID_PIOB ) ; PMC_EnablePeripheral( ID_PIOB ) ;
PIOB->PIO_ISR ; PIOB->PIO_ISR ;
PIOB->PIO_IDR = 0xFFFFFFFF ; PIOB->PIO_IDR = 0xFFFFFFFF ;
NVIC_DisableIRQ( PIOB_IRQn ) ; NVIC_DisableIRQ( PIOB_IRQn ) ;
NVIC_ClearPendingIRQ( PIOB_IRQn ) ; NVIC_ClearPendingIRQ( PIOB_IRQn ) ;
NVIC_SetPriority( PIOB_IRQn, dwPriority ) ; NVIC_SetPriority( PIOB_IRQn, dwPriority ) ;
NVIC_EnableIRQ( PIOB_IRQn ) ; NVIC_EnableIRQ( PIOB_IRQn ) ;
TRACE_DEBUG( "PIO_Initialize: Configuring PIOC\n\r" ) ; TRACE_DEBUG( "PIO_Initialize: Configuring PIOC\n\r" ) ;
PMC_EnablePeripheral( ID_PIOC ) ; PMC_EnablePeripheral( ID_PIOC ) ;
PIOC->PIO_ISR ; PIOC->PIO_ISR ;
PIOC->PIO_IDR = 0xFFFFFFFF ; PIOC->PIO_IDR = 0xFFFFFFFF ;
NVIC_DisableIRQ( PIOC_IRQn ) ; NVIC_DisableIRQ( PIOC_IRQn ) ;
NVIC_ClearPendingIRQ( PIOC_IRQn ) ; NVIC_ClearPendingIRQ( PIOC_IRQn ) ;
NVIC_SetPriority( PIOC_IRQn, dwPriority ) ; NVIC_SetPriority( PIOC_IRQn, dwPriority ) ;
NVIC_EnableIRQ( PIOC_IRQn ) ; NVIC_EnableIRQ( PIOC_IRQn ) ;
} }
/** /**
* Configures a PIO or a group of PIO to generate an interrupt on status * 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 * change. The provided interrupt handler will be called with the triggering
* pin as its parameter (enabling different pin instances to share the same * pin as its parameter (enabling different pin instances to share the same
* handler). * handler).
* \param pPin Pointer to a Pin instance. * \param pPin Pointer to a Pin instance.
* \param handler Interrupt handler function pointer. * \param handler Interrupt handler function pointer.
*/ */
extern void PIO_ConfigureIt( const Pin *pPin, void (*handler)( const Pin* ) ) extern void PIO_ConfigureIt( const Pin *pPin, void (*handler)( const Pin* ) )
{ {
Pio* pio ; Pio* pio ;
InterruptSource* pSource ; InterruptSource* pSource ;
TRACE_DEBUG( "PIO_ConfigureIt()\n\r" ) ; TRACE_DEBUG( "PIO_ConfigureIt()\n\r" ) ;
assert( pPin ) ; assert( pPin ) ;
pio = pPin->pio ; pio = pPin->pio ;
assert( _dwNumSources < MAX_INTERRUPT_SOURCES ) ; assert( _dwNumSources < MAX_INTERRUPT_SOURCES ) ;
/* Define new source */ /* Define new source */
TRACE_DEBUG( "PIO_ConfigureIt: Defining new source #%" PRIu32 ".\n\r", _dwNumSources ) ; TRACE_DEBUG( "PIO_ConfigureIt: Defining new source #%" PRIu32 ".\n\r", _dwNumSources ) ;
pSource = &(_aIntSources[_dwNumSources]) ; pSource = &(_aIntSources[_dwNumSources]) ;
pSource->pPin = pPin ; pSource->pPin = pPin ;
pSource->handler = handler ; pSource->handler = handler ;
_dwNumSources++ ; _dwNumSources++ ;
/* PIO3 with additional interrupt support /* PIO3 with additional interrupt support
* Configure additional interrupt mode registers */ * Configure additional interrupt mode registers */
if ( pPin->attribute & PIO_IT_AIME ) if ( pPin->attribute & PIO_IT_AIME )
{ {
// enable additional interrupt mode // enable additional interrupt mode
pio->PIO_AIMER = pPin->mask ; pio->PIO_AIMER = pPin->mask ;
// if bit field of selected pin is 1, set as Rising Edge/High level detection event // if bit field of selected pin is 1, set as Rising Edge/High level detection event
if ( pPin->attribute & PIO_IT_RE_OR_HL ) if ( pPin->attribute & PIO_IT_RE_OR_HL )
{ {
pio->PIO_REHLSR = pPin->mask ; pio->PIO_REHLSR = pPin->mask ;
} }
else else
{ {
pio->PIO_FELLSR = pPin->mask; pio->PIO_FELLSR = pPin->mask;
} }
/* if bit field of selected pin is 1, set as edge detection source */ /* if bit field of selected pin is 1, set as edge detection source */
if (pPin->attribute & PIO_IT_EDGE) if (pPin->attribute & PIO_IT_EDGE)
pio->PIO_ESR = pPin->mask; pio->PIO_ESR = pPin->mask;
else else
pio->PIO_LSR = pPin->mask; pio->PIO_LSR = pPin->mask;
} }
else else
{ {
/* disable additional interrupt mode */ /* disable additional interrupt mode */
pio->PIO_AIMDR = pPin->mask; pio->PIO_AIMDR = pPin->mask;
} }
} }
/** /**
* Enables the given interrupt source if it has been configured. The status * Enables the given interrupt source if it has been configured. The status
* register of the corresponding PIO controller is cleared prior to enabling * register of the corresponding PIO controller is cleared prior to enabling
* the interrupt. * the interrupt.
* \param pPin Interrupt source to enable. * \param pPin Interrupt source to enable.
*/ */
extern void PIO_EnableIt( const Pin *pPin ) extern void PIO_EnableIt( const Pin *pPin )
{ {
TRACE_DEBUG( "PIO_EnableIt()\n\r" ) ; TRACE_DEBUG( "PIO_EnableIt()\n\r" ) ;
assert( pPin != NULL ) ; assert( pPin != NULL ) ;
#ifndef NOASSERT #ifndef NOASSERT
uint32_t i = 0; uint32_t i = 0;
uint32_t dwFound = 0; uint32_t dwFound = 0;
while ( (i < _dwNumSources) && !dwFound ) while ( (i < _dwNumSources) && !dwFound )
{ {
if ( _aIntSources[i].pPin == pPin ) if ( _aIntSources[i].pPin == pPin )
{ {
dwFound = 1 ; dwFound = 1 ;
} }
i++ ; i++ ;
} }
assert( dwFound != 0 ) ; assert( dwFound != 0 ) ;
#endif #endif
pPin->pio->PIO_ISR; pPin->pio->PIO_ISR;
pPin->pio->PIO_IER = pPin->mask ; pPin->pio->PIO_IER = pPin->mask ;
} }
/** /**
* Disables a given interrupt source, with no added side effects. * Disables a given interrupt source, with no added side effects.
* *
* \param pPin Interrupt source to disable. * \param pPin Interrupt source to disable.
*/ */
extern void PIO_DisableIt( const Pin *pPin ) extern void PIO_DisableIt( const Pin *pPin )
{ {
assert( pPin != NULL ) ; assert( pPin != NULL ) ;
TRACE_DEBUG( "PIO_DisableIt()\n\r" ) ; TRACE_DEBUG( "PIO_DisableIt()\n\r" ) ;
pPin->pio->PIO_IDR = pPin->mask; pPin->pio->PIO_IDR = pPin->mask;
} }

View File

@@ -1,168 +1,168 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Headers * Headers
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include "trace.h" #include "trace.h"
#include <assert.h> #include <assert.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Local definitions * Local definitions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define MASK_STATUS0 0xFFFFFFFC #define MASK_STATUS0 0xFFFFFFFC
#define MASK_STATUS1 0xFFFFFFFF #define MASK_STATUS1 0xFFFFFFFF
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported functions * Exported functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* \brief Enables the clock of a peripheral. The peripheral ID is used * \brief Enables the clock of a peripheral. The peripheral ID is used
* to identify which peripheral is targetted. * to identify which peripheral is targetted.
* *
* \note The ID must NOT be shifted (i.e. 1 << ID_xxx). * \note The ID must NOT be shifted (i.e. 1 << ID_xxx).
* *
* \param id Peripheral ID (ID_xxx). * \param id Peripheral ID (ID_xxx).
*/ */
extern void PMC_EnablePeripheral( uint32_t dwId ) extern void PMC_EnablePeripheral( uint32_t dwId )
{ {
assert( dwId < 35 ) ; assert( dwId < 35 ) ;
if ( dwId < 32 ) if ( dwId < 32 )
{ {
if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId) ) if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId) )
{ {
TRACE_DEBUG( "PMC_EnablePeripheral: clock of peripheral" " %" PRIu32 " is already enabled\n\r", dwId ) ; TRACE_DEBUG( "PMC_EnablePeripheral: clock of peripheral" " %" PRIu32 " is already enabled\n\r", dwId ) ;
} }
else else
{ {
PMC->PMC_PCER0 = 1 << dwId ; PMC->PMC_PCER0 = 1 << dwId ;
} }
} }
else else
{ {
dwId -= 32; dwId -= 32;
if ((PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId)) if ((PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) == ((uint32_t)1 << dwId))
{ {
TRACE_DEBUG( "PMC_EnablePeripheral: clock of peripheral" " %" PRIu32 " is already enabled\n\r", dwId + 32 ) ; TRACE_DEBUG( "PMC_EnablePeripheral: clock of peripheral" " %" PRIu32 " is already enabled\n\r", dwId + 32 ) ;
} }
else else
{ {
PMC->PMC_PCER1 = 1 << dwId ; PMC->PMC_PCER1 = 1 << dwId ;
} }
} }
} }
/** /**
* \brief Disables the clock of a peripheral. The peripheral ID is used * \brief Disables the clock of a peripheral. The peripheral ID is used
* to identify which peripheral is targetted. * to identify which peripheral is targetted.
* *
* \note The ID must NOT be shifted (i.e. 1 << ID_xxx). * \note The ID must NOT be shifted (i.e. 1 << ID_xxx).
* *
* \param id Peripheral ID (ID_xxx). * \param id Peripheral ID (ID_xxx).
*/ */
extern void PMC_DisablePeripheral( uint32_t dwId ) extern void PMC_DisablePeripheral( uint32_t dwId )
{ {
assert( dwId < 35 ) ; assert( dwId < 35 ) ;
if ( dwId < 32 ) if ( dwId < 32 )
{ {
if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId) ) if ( (PMC->PMC_PCSR0 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId) )
{ {
TRACE_DEBUG("PMC_DisablePeripheral: clock of peripheral" " %" PRIu32 " is not enabled\n\r", dwId ) ; TRACE_DEBUG("PMC_DisablePeripheral: clock of peripheral" " %" PRIu32 " is not enabled\n\r", dwId ) ;
} }
else else
{ {
PMC->PMC_PCDR0 = 1 << dwId ; PMC->PMC_PCDR0 = 1 << dwId ;
} }
} }
else else
{ {
dwId -= 32 ; dwId -= 32 ;
if ( (PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId) ) if ( (PMC->PMC_PCSR1 & ((uint32_t)1 << dwId)) != ((uint32_t)1 << dwId) )
{ {
TRACE_DEBUG( "PMC_DisablePeripheral: clock of peripheral" " %" PRIu32 " is not enabled\n\r", dwId + 32 ) ; TRACE_DEBUG( "PMC_DisablePeripheral: clock of peripheral" " %" PRIu32 " is not enabled\n\r", dwId + 32 ) ;
} }
else else
{ {
PMC->PMC_PCDR1 = 1 << dwId ; PMC->PMC_PCDR1 = 1 << dwId ;
} }
} }
} }
/** /**
* \brief Enable all the periph clock via PMC. * \brief Enable all the periph clock via PMC.
*/ */
extern void PMC_EnableAllPeripherals( void ) extern void PMC_EnableAllPeripherals( void )
{ {
PMC->PMC_PCER0 = MASK_STATUS0 ; PMC->PMC_PCER0 = MASK_STATUS0 ;
while ( (PMC->PMC_PCSR0 & MASK_STATUS0) != MASK_STATUS0 ) ; while ( (PMC->PMC_PCSR0 & MASK_STATUS0) != MASK_STATUS0 ) ;
PMC->PMC_PCER1 = MASK_STATUS1 ; PMC->PMC_PCER1 = MASK_STATUS1 ;
while ( (PMC->PMC_PCSR1 & MASK_STATUS1) != MASK_STATUS1 ) ; while ( (PMC->PMC_PCSR1 & MASK_STATUS1) != MASK_STATUS1 ) ;
TRACE_DEBUG( "Enable all periph clocks\n\r" ) ; TRACE_DEBUG( "Enable all periph clocks\n\r" ) ;
} }
/** /**
* \brief Disable all the periph clock via PMC. * \brief Disable all the periph clock via PMC.
*/ */
extern void PMC_DisableAllPeripherals( void ) extern void PMC_DisableAllPeripherals( void )
{ {
PMC->PMC_PCDR0 = MASK_STATUS0 ; PMC->PMC_PCDR0 = MASK_STATUS0 ;
while ( (PMC->PMC_PCSR0 & MASK_STATUS0) != 0 ) ; while ( (PMC->PMC_PCSR0 & MASK_STATUS0) != 0 ) ;
PMC->PMC_PCDR1 = MASK_STATUS1 ; PMC->PMC_PCDR1 = MASK_STATUS1 ;
while ( (PMC->PMC_PCSR1 & MASK_STATUS1) != 0 ) ; while ( (PMC->PMC_PCSR1 & MASK_STATUS1) != 0 ) ;
TRACE_DEBUG( "Disable all periph clocks\n\r" ) ; TRACE_DEBUG( "Disable all periph clocks\n\r" ) ;
} }
/** /**
* \brief Get Periph Status for the given peripheral ID. * \brief Get Periph Status for the given peripheral ID.
* *
* \param id Peripheral ID (ID_xxx). * \param id Peripheral ID (ID_xxx).
*/ */
extern uint32_t PMC_IsPeriphEnabled( uint32_t dwId ) extern uint32_t PMC_IsPeriphEnabled( uint32_t dwId )
{ {
assert( dwId < 35 ) ; assert( dwId < 35 ) ;
if ( dwId < 32 ) if ( dwId < 32 )
{ {
return ( PMC->PMC_PCSR0 & (1 << dwId) ) ; return ( PMC->PMC_PCSR0 & (1 << dwId) ) ;
} }
else { else {
return ( PMC->PMC_PCSR1 & (1 << (dwId - 32)) ) ; return ( PMC->PMC_PCSR1 & (1 << (dwId - 32)) ) ;
} }
} }

View File

@@ -1,352 +1,352 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** \addtogroup spi_module Working with SPI /** \addtogroup spi_module Working with SPI
* The SPI driver provides the interface to configure and use the SPI * The SPI driver provides the interface to configure and use the SPI
* peripheral. * peripheral.
* *
* The Serial Peripheral Interface (SPI) circuit is a synchronous serial * The Serial Peripheral Interface (SPI) circuit is a synchronous serial
* data link that provides communication with external devices in Master * data link that provides communication with external devices in Master
* or Slave Mode. * or Slave Mode.
* *
* To use the SPI, the user has to follow these few steps: * To use the SPI, the user has to follow these few steps:
* -# Enable the SPI pins required by the application (see pio.h). * -# Enable the SPI pins required by the application (see pio.h).
* -# Configure the SPI using the \ref SPI_Configure(). This enables the * -# Configure the SPI using the \ref SPI_Configure(). This enables the
* peripheral clock. The mode register is loaded with the given value. * peripheral clock. The mode register is loaded with the given value.
* -# Configure all the necessary chip selects with \ref SPI_ConfigureNPCS(). * -# Configure all the necessary chip selects with \ref SPI_ConfigureNPCS().
* -# Enable the SPI by calling \ref SPI_Enable(). * -# Enable the SPI by calling \ref SPI_Enable().
* -# Send/receive data using \ref SPI_Write() and \ref SPI_Read(). Note that \ref SPI_Read() * -# Send/receive data using \ref SPI_Write() and \ref SPI_Read(). Note that \ref SPI_Read()
* must be called after \ref SPI_Write() to retrieve the last value read. * must be called after \ref SPI_Write() to retrieve the last value read.
* -# Send/receive data using the PDC with the \ref SPI_WriteBuffer() and * -# Send/receive data using the PDC with the \ref SPI_WriteBuffer() and
* \ref SPI_ReadBuffer() functions. * \ref SPI_ReadBuffer() functions.
* -# Disable the SPI by calling \ref SPI_Disable(). * -# Disable the SPI by calling \ref SPI_Disable().
* *
* For more accurate information, please look at the SPI section of the * For more accurate information, please look at the SPI section of the
* Datasheet. * Datasheet.
* *
* Related files :\n * Related files :\n
* \ref spi.c\n * \ref spi.c\n
* \ref spi.h.\n * \ref spi.h.\n
*/ */
/*@{*/ /*@{*/
/*@}*/ /*@}*/
/** /**
* \file * \file
* *
* Implementation of Serial Peripheral Interface (SPI) controller. * Implementation of Serial Peripheral Interface (SPI) controller.
* *
*/ */
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Headers * Headers
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include "pmc.h" #include "pmc.h"
#include "spi.h" #include "spi.h"
#include <stdint.h> #include <stdint.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported functions * Exported functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* \brief Enables a SPI peripheral. * \brief Enables a SPI peripheral.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
*/ */
extern void SPI_Enable( Spi* spi ) extern void SPI_Enable( Spi* spi )
{ {
spi->SPI_CR = SPI_CR_SPIEN ; spi->SPI_CR = SPI_CR_SPIEN ;
} }
/** /**
* \brief Disables a SPI peripheral. * \brief Disables a SPI peripheral.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
*/ */
extern void SPI_Disable( Spi* spi ) extern void SPI_Disable( Spi* spi )
{ {
spi->SPI_CR = SPI_CR_SPIDIS ; spi->SPI_CR = SPI_CR_SPIDIS ;
} }
/** /**
* \brief Enables one or more interrupt sources of a SPI peripheral. * \brief Enables one or more interrupt sources of a SPI peripheral.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param sources Bitwise OR of selected interrupt sources. * \param sources Bitwise OR of selected interrupt sources.
*/ */
extern void SPI_EnableIt( Spi* spi, uint32_t dwSources ) extern void SPI_EnableIt( Spi* spi, uint32_t dwSources )
{ {
spi->SPI_IER = dwSources ; spi->SPI_IER = dwSources ;
} }
/** /**
* \brief Disables one or more interrupt sources of a SPI peripheral. * \brief Disables one or more interrupt sources of a SPI peripheral.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param sources Bitwise OR of selected interrupt sources. * \param sources Bitwise OR of selected interrupt sources.
*/ */
extern void SPI_DisableIt( Spi* spi, uint32_t dwSources ) extern void SPI_DisableIt( Spi* spi, uint32_t dwSources )
{ {
spi->SPI_IDR = dwSources ; spi->SPI_IDR = dwSources ;
} }
/** /**
* \brief Configures a SPI peripheral as specified. The configuration can be computed * \brief Configures a SPI peripheral as specified. The configuration can be computed
* using several macros (see \ref spi_configuration_macros). * using several macros (see \ref spi_configuration_macros).
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param id Peripheral ID of the SPI. * \param id Peripheral ID of the SPI.
* \param configuration Value of the SPI configuration register. * \param configuration Value of the SPI configuration register.
*/ */
extern void SPI_Configure( Spi* spi, uint32_t dwId, uint32_t dwConfiguration ) extern void SPI_Configure( Spi* spi, uint32_t dwId, uint32_t dwConfiguration )
{ {
PMC_EnablePeripheral( dwId ) ; PMC_EnablePeripheral( dwId ) ;
spi->SPI_CR = SPI_CR_SPIDIS ; spi->SPI_CR = SPI_CR_SPIDIS ;
/* Execute a software reset of the SPI twice */ /* Execute a software reset of the SPI twice */
spi->SPI_CR = SPI_CR_SWRST ; spi->SPI_CR = SPI_CR_SWRST ;
spi->SPI_CR = SPI_CR_SWRST ; spi->SPI_CR = SPI_CR_SWRST ;
spi->SPI_MR = dwConfiguration ; spi->SPI_MR = dwConfiguration ;
} }
/** /**
* \brief Configures a chip select of a SPI peripheral. The chip select configuration * \brief Configures a chip select of a SPI peripheral. The chip select configuration
* is computed using several macros (see \ref spi_configuration_macros). * is computed using several macros (see \ref spi_configuration_macros).
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param npcs Chip select to configure (0, 1, 2 or 3). * \param npcs Chip select to configure (0, 1, 2 or 3).
* \param configuration Desired chip select configuration. * \param configuration Desired chip select configuration.
*/ */
void SPI_ConfigureNPCS( Spi* spi, uint32_t dwNpcs, uint32_t dwConfiguration ) void SPI_ConfigureNPCS( Spi* spi, uint32_t dwNpcs, uint32_t dwConfiguration )
{ {
spi->SPI_CSR[dwNpcs] = dwConfiguration ; spi->SPI_CSR[dwNpcs] = dwConfiguration ;
} }
/** /**
* \brief Get the current status register of the given SPI peripheral. * \brief Get the current status register of the given SPI peripheral.
* \note This resets the internal value of the status register, so further * \note This resets the internal value of the status register, so further
* read may yield different values. * read may yield different values.
* \param spi Pointer to a Spi instance. * \param spi Pointer to a Spi instance.
* \return SPI status register. * \return SPI status register.
*/ */
extern uint32_t SPI_GetStatus( Spi* spi ) extern uint32_t SPI_GetStatus( Spi* spi )
{ {
return spi->SPI_SR ; return spi->SPI_SR ;
} }
/** /**
* \brief Reads and returns the last word of data received by a SPI peripheral. This * \brief Reads and returns the last word of data received by a SPI peripheral. This
* method must be called after a successful SPI_Write call. * method must be called after a successful SPI_Write call.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* *
* \return readed data. * \return readed data.
*/ */
extern uint32_t SPI_Read( Spi* spi ) extern uint32_t SPI_Read( Spi* spi )
{ {
while ( (spi->SPI_SR & SPI_SR_RDRF) == 0 ) ; while ( (spi->SPI_SR & SPI_SR_RDRF) == 0 ) ;
return spi->SPI_RDR & 0xFFFF ; return spi->SPI_RDR & 0xFFFF ;
} }
/** /**
* \brief Sends data through a SPI peripheral. If the SPI is configured to use a fixed * \brief 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 * peripheral select, the npcs value is meaningless. Otherwise, it identifies
* the component which shall be addressed. * the component which shall be addressed.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param npcs Chip select of the component to address (0, 1, 2 or 3). * \param npcs Chip select of the component to address (0, 1, 2 or 3).
* \param data Word of data to send. * \param data Word of data to send.
*/ */
extern void SPI_Write( Spi* spi, uint32_t dwNpcs, uint16_t wData ) extern void SPI_Write( Spi* spi, uint32_t dwNpcs, uint16_t wData )
{ {
/* Send data */ /* Send data */
while ( (spi->SPI_SR & SPI_SR_TXEMPTY) == 0 ) ; while ( (spi->SPI_SR & SPI_SR_TXEMPTY) == 0 ) ;
spi->SPI_TDR = wData | SPI_PCS( dwNpcs ) ; spi->SPI_TDR = wData | SPI_PCS( dwNpcs ) ;
while ( (spi->SPI_SR & SPI_SR_TDRE) == 0 ) ; while ( (spi->SPI_SR & SPI_SR_TDRE) == 0 ) ;
} }
/** /**
* \brief Check if SPI transfer finish. * \brief Check if SPI transfer finish.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* *
* \return Returns 1 if there is no pending write operation on the SPI; otherwise * \return Returns 1 if there is no pending write operation on the SPI; otherwise
* returns 0. * returns 0.
*/ */
extern uint32_t SPI_IsFinished( Spi* spi ) extern uint32_t SPI_IsFinished( Spi* spi )
{ {
return ((spi->SPI_SR & SPI_SR_TXEMPTY) != 0) ; return ((spi->SPI_SR & SPI_SR_TXEMPTY) != 0) ;
} }
/** /**
* \brief Enable Spi PDC transmit * \brief Enable Spi PDC transmit
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
*/ */
extern void SPI_PdcEnableTx( Spi* spi ) extern void SPI_PdcEnableTx( Spi* spi )
{ {
spi->SPI_PTCR = SPI_PTCR_TXTEN ; spi->SPI_PTCR = SPI_PTCR_TXTEN ;
} }
/** /**
* \brief Disable Spi PDC transmit * \brief Disable Spi PDC transmit
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
*/ */
extern void SPI_PdcDisableTx( Spi* spi ) extern void SPI_PdcDisableTx( Spi* spi )
{ {
spi->SPI_PTCR = SPI_PTCR_TXTDIS ; spi->SPI_PTCR = SPI_PTCR_TXTDIS ;
} }
/** /**
* \brief Enable Spi PDC receive * \brief Enable Spi PDC receive
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
*/ */
extern void SPI_PdcEnableRx( Spi* spi ) extern void SPI_PdcEnableRx( Spi* spi )
{ {
spi->SPI_PTCR = SPI_PTCR_RXTEN ; spi->SPI_PTCR = SPI_PTCR_RXTEN ;
} }
/** /**
* \brief Disable Spi PDC receive * \brief Disable Spi PDC receive
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
*/ */
extern void SPI_PdcDisableRx( Spi* spi ) extern void SPI_PdcDisableRx( Spi* spi )
{ {
spi->SPI_PTCR = SPI_PTCR_RXTDIS ; spi->SPI_PTCR = SPI_PTCR_RXTDIS ;
} }
/** /**
* \brief Set PDC transmit and next transmit buffer address and size. * \brief Set PDC transmit and next transmit buffer address and size.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param txBuf PDC transmit buffer address. * \param txBuf PDC transmit buffer address.
* \param txCount Length in bytes of the transmit buffer. * \param txCount Length in bytes of the transmit buffer.
* \param txNextBuf PDC next transmit buffer address. * \param txNextBuf PDC next transmit buffer address.
* \param txNextCount Length in bytes of the next transmit buffer. * \param txNextCount Length in bytes of the next transmit buffer.
*/ */
extern void SPI_PdcSetTx( Spi* spi, void* pvTxBuf, uint32_t dwTxCount, void* pvTxNextBuf, uint32_t dwTxNextCount ) extern void SPI_PdcSetTx( Spi* spi, void* pvTxBuf, uint32_t dwTxCount, void* pvTxNextBuf, uint32_t dwTxNextCount )
{ {
spi->SPI_TPR = (uint32_t)pvTxBuf ; spi->SPI_TPR = (uint32_t)pvTxBuf ;
spi->SPI_TCR = dwTxCount ; spi->SPI_TCR = dwTxCount ;
spi->SPI_TNPR = (uint32_t)pvTxNextBuf ; spi->SPI_TNPR = (uint32_t)pvTxNextBuf ;
spi->SPI_TNCR = dwTxNextCount ; spi->SPI_TNCR = dwTxNextCount ;
} }
/** /**
* \brief Set PDC receive and next receive buffer address and size. * \brief Set PDC receive and next receive buffer address and size.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param rxBuf PDC receive buffer address. * \param rxBuf PDC receive buffer address.
* \param rxCount Length in bytes of the receive buffer. * \param rxCount Length in bytes of the receive buffer.
* \param rxNextBuf PDC next receive buffer address. * \param rxNextBuf PDC next receive buffer address.
* \param rxNextCount Length in bytes of the next receive buffer. * \param rxNextCount Length in bytes of the next receive buffer.
*/ */
extern void SPI_PdcSetRx( Spi* spi, void* pvRxBuf, uint32_t dwRxCount, void* pvRxNextBuf, uint32_t dwRxNextCount ) extern void SPI_PdcSetRx( Spi* spi, void* pvRxBuf, uint32_t dwRxCount, void* pvRxNextBuf, uint32_t dwRxNextCount )
{ {
spi->SPI_RPR = (uint32_t)pvRxBuf ; spi->SPI_RPR = (uint32_t)pvRxBuf ;
spi->SPI_RCR = dwRxCount ; spi->SPI_RCR = dwRxCount ;
spi->SPI_RNPR = (uint32_t)pvRxNextBuf ; spi->SPI_RNPR = (uint32_t)pvRxNextBuf ;
spi->SPI_RNCR = dwRxNextCount ; spi->SPI_RNCR = dwRxNextCount ;
} }
/** /**
* \brief Sends the contents of buffer through a SPI peripheral, using the PDC to * \brief Sends the contents of buffer through a SPI peripheral, using the PDC to
* take care of the transfer. * take care of the transfer.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param buffer Data buffer to send. * \param buffer Data buffer to send.
* \param length Length of the data buffer. * \param length Length of the data buffer.
*/ */
extern uint32_t SPI_WriteBuffer( Spi* spi, void* pvBuffer, uint32_t dwLength ) extern uint32_t SPI_WriteBuffer( Spi* spi, void* pvBuffer, uint32_t dwLength )
{ {
/* Check if first bank is free */ /* Check if first bank is free */
if ( spi->SPI_TCR == 0 ) if ( spi->SPI_TCR == 0 )
{ {
spi->SPI_TPR = (uint32_t)pvBuffer ; spi->SPI_TPR = (uint32_t)pvBuffer ;
spi->SPI_TCR = dwLength ; spi->SPI_TCR = dwLength ;
spi->SPI_PTCR = PERIPH_PTCR_TXTEN ; spi->SPI_PTCR = PERIPH_PTCR_TXTEN ;
return 1 ; return 1 ;
} }
/* Check if second bank is free */ /* Check if second bank is free */
else else
{ {
if ( spi->SPI_TNCR == 0 ) if ( spi->SPI_TNCR == 0 )
{ {
spi->SPI_TNPR = (uint32_t)pvBuffer ; spi->SPI_TNPR = (uint32_t)pvBuffer ;
spi->SPI_TNCR = dwLength ; spi->SPI_TNCR = dwLength ;
return 1 ; return 1 ;
} }
} }
/* No free banks */ /* No free banks */
return 0 ; return 0 ;
} }
/** /**
* \brief Reads data from a SPI peripheral until the provided buffer is filled. This * \brief 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. * method does NOT need to be called after SPI_Write or SPI_WriteBuffer.
* *
* \param spi Pointer to an Spi instance. * \param spi Pointer to an Spi instance.
* \param buffer Data buffer to store incoming bytes. * \param buffer Data buffer to store incoming bytes.
* \param length Length in bytes of the data buffer. * \param length Length in bytes of the data buffer.
*/ */
extern uint32_t SPI_ReadBuffer( Spi* spi, void *pvBuffer, uint32_t dwLength ) extern uint32_t SPI_ReadBuffer( Spi* spi, void *pvBuffer, uint32_t dwLength )
{ {
/* Check if the first bank is free */ /* Check if the first bank is free */
if ( spi->SPI_RCR == 0 ) if ( spi->SPI_RCR == 0 )
{ {
spi->SPI_RPR = (uint32_t)pvBuffer ; spi->SPI_RPR = (uint32_t)pvBuffer ;
spi->SPI_RCR = dwLength ; spi->SPI_RCR = dwLength ;
spi->SPI_PTCR = PERIPH_PTCR_RXTEN ; spi->SPI_PTCR = PERIPH_PTCR_RXTEN ;
return 1 ; return 1 ;
} }
/* Check if second bank is free */ /* Check if second bank is free */
else else
{ {
if ( spi->SPI_RNCR == 0 ) if ( spi->SPI_RNCR == 0 )
{ {
spi->SPI_RNPR = (uint32_t)pvBuffer ; spi->SPI_RNPR = (uint32_t)pvBuffer ;
spi->SPI_RNCR = dwLength ; spi->SPI_RNCR = dwLength ;
return 1 ; return 1 ;
} }
} }
/* No free bank */ /* No free bank */
return 0 ; return 0 ;
} }

View File

@@ -1,175 +1,175 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** /**
* \file * \file
* *
* Implementation of Timer Counter (TC). * Implementation of Timer Counter (TC).
* *
*/ */
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Headers * Headers
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include <assert.h> #include <assert.h>
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Global functions * Global functions
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
/** /**
* \brief Configures a Timer Counter Channel * \brief Configures a Timer Counter Channel
* *
* Configures a Timer Counter to operate in the given mode. Timer is stopped * Configures a Timer Counter to operate in the given mode. Timer is stopped
* after configuration and must be restarted with TC_Start(). All the * after configuration and must be restarted with TC_Start(). All the
* interrupts of the timer are also disabled. * interrupts of the timer are also disabled.
* *
* \param pTc Pointer to a Tc instance. * \param pTc Pointer to a Tc instance.
* \param channel Channel number. * \param channel Channel number.
* \param mode Operating mode (TC_CMR value). * \param mode Operating mode (TC_CMR value).
*/ */
extern void TC_Configure( Tc *pTc, uint32_t dwChannel, uint32_t dwMode ) extern void TC_Configure( Tc *pTc, uint32_t dwChannel, uint32_t dwMode )
{ {
TcChannel* pTcCh ; TcChannel* pTcCh ;
assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ; assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ;
pTcCh = pTc->TC_CHANNEL+dwChannel ; pTcCh = pTc->TC_CHANNEL+dwChannel ;
/* Disable TC clock */ /* Disable TC clock */
pTcCh->TC_CCR = TC_CCR_CLKDIS ; pTcCh->TC_CCR = TC_CCR_CLKDIS ;
/* Disable interrupts */ /* Disable interrupts */
pTcCh->TC_IDR = 0xFFFFFFFF ; pTcCh->TC_IDR = 0xFFFFFFFF ;
/* Clear status register */ /* Clear status register */
pTcCh->TC_SR ; pTcCh->TC_SR ;
/* Set mode */ /* Set mode */
pTcCh->TC_CMR = dwMode ; pTcCh->TC_CMR = dwMode ;
} }
/** /**
* \brief Reset and Start the TC Channel * \brief Reset and Start the TC Channel
* *
* Enables the timer clock and performs a software reset to start the counting. * Enables the timer clock and performs a software reset to start the counting.
* *
* \param pTc Pointer to a Tc instance. * \param pTc Pointer to a Tc instance.
* \param dwChannel Channel number. * \param dwChannel Channel number.
*/ */
extern void TC_Start( Tc *pTc, uint32_t dwChannel ) extern void TC_Start( Tc *pTc, uint32_t dwChannel )
{ {
TcChannel* pTcCh ; TcChannel* pTcCh ;
assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ; assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ;
pTcCh = pTc->TC_CHANNEL+dwChannel ; pTcCh = pTc->TC_CHANNEL+dwChannel ;
pTcCh->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ; pTcCh->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG ;
} }
/** /**
* \brief Stop TC Channel * \brief Stop TC Channel
* *
* Disables the timer clock, stopping the counting. * Disables the timer clock, stopping the counting.
* *
* \param pTc Pointer to a Tc instance. * \param pTc Pointer to a Tc instance.
* \param dwChannel Channel number. * \param dwChannel Channel number.
*/ */
extern void TC_Stop(Tc *pTc, uint32_t dwChannel ) extern void TC_Stop(Tc *pTc, uint32_t dwChannel )
{ {
TcChannel* pTcCh ; TcChannel* pTcCh ;
assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ; assert( dwChannel < (sizeof( pTc->TC_CHANNEL )/sizeof( pTc->TC_CHANNEL[0] )) ) ;
pTcCh = pTc->TC_CHANNEL+dwChannel ; pTcCh = pTc->TC_CHANNEL+dwChannel ;
pTcCh->TC_CCR = TC_CCR_CLKDIS ; pTcCh->TC_CCR = TC_CCR_CLKDIS ;
} }
/** /**
* \brief Find best MCK divisor * \brief Find best MCK divisor
* *
* Finds the best MCK divisor given the timer frequency and MCK. The result * Finds the best MCK divisor given the timer frequency and MCK. The result
* is guaranteed to satisfy the following equation: * is guaranteed to satisfy the following equation:
* \code * \code
* (MCK / (DIV * 65536)) <= freq <= (MCK / DIV) * (MCK / (DIV * 65536)) <= freq <= (MCK / DIV)
* \endcode * \endcode
* with DIV being the highest possible value. * with DIV being the highest possible value.
* *
* \param dwFreq Desired timer frequency. * \param dwFreq Desired timer frequency.
* \param dwMCk Master clock frequency. * \param dwMCk Master clock frequency.
* \param dwDiv Divisor value. * \param dwDiv Divisor value.
* \param dwTcClks TCCLKS field value for divisor. * \param dwTcClks TCCLKS field value for divisor.
* \param dwBoardMCK Board clock frequency. * \param dwBoardMCK Board clock frequency.
* *
* \return 1 if a proper divisor has been found, otherwise 0. * \return 1 if a proper divisor has been found, otherwise 0.
*/ */
extern uint32_t TC_FindMckDivisor( uint32_t dwFreq, uint32_t dwMCk, uint32_t *dwDiv, uint32_t *dwTcClks, uint32_t dwBoardMCK ) extern uint32_t TC_FindMckDivisor( uint32_t dwFreq, uint32_t dwMCk, uint32_t *dwDiv, uint32_t *dwTcClks, uint32_t dwBoardMCK )
{ {
const uint32_t adwDivisors[5] = { 2, 8, 32, 128, dwBoardMCK / 32768 } ; const uint32_t adwDivisors[5] = { 2, 8, 32, 128, dwBoardMCK / 32768 } ;
uint32_t dwIndex = 0 ; uint32_t dwIndex = 0 ;
/* Satisfy lower bound */ /* Satisfy lower bound */
while ( dwFreq < ((dwMCk / adwDivisors[dwIndex]) / 65536) ) while ( dwFreq < ((dwMCk / adwDivisors[dwIndex]) / 65536) )
{ {
dwIndex++ ; dwIndex++ ;
/* If no divisor can be found, return 0 */ /* If no divisor can be found, return 0 */
if ( dwIndex == (sizeof( adwDivisors )/sizeof( adwDivisors[0] )) ) if ( dwIndex == (sizeof( adwDivisors )/sizeof( adwDivisors[0] )) )
{ {
return 0 ; return 0 ;
} }
} }
/* Try to maximize DIV while satisfying upper bound */ /* Try to maximize DIV while satisfying upper bound */
while ( dwIndex < 4 ) while ( dwIndex < 4 )
{ {
if ( dwFreq > (dwMCk / adwDivisors[dwIndex + 1]) ) if ( dwFreq > (dwMCk / adwDivisors[dwIndex + 1]) )
{ {
break ; break ;
} }
dwIndex++ ; dwIndex++ ;
} }
/* Store results */ /* Store results */
if ( dwDiv ) if ( dwDiv )
{ {
*dwDiv = adwDivisors[dwIndex] ; *dwDiv = adwDivisors[dwIndex] ;
} }
if ( dwTcClks ) if ( dwTcClks )
{ {
*dwTcClks = dwIndex ; *dwTcClks = dwIndex ;
} }
return 1 ; return 1 ;
} }

View File

@@ -1,410 +1,410 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** \addtogroup usart_module Working with USART /** \addtogroup usart_module Working with USART
* The USART driver provides the interface to configure and use the USART peripheral.\n * The USART driver provides the interface to configure and use the USART peripheral.\n
* *
* The USART supports several kinds of comminication modes such as full-duplex asynchronous/ * The USART supports several kinds of comminication modes such as full-duplex asynchronous/
* synchronous serial commnunication,RS485 with driver control signal,ISO7816,SPI and Test modes. * synchronous serial commnunication,RS485 with driver control signal,ISO7816,SPI and Test modes.
* *
* To start a USART transfer with \ref AT91SAM3S_PDC "PDC" support, the user could follow these steps: * To start a USART transfer with \ref AT91SAM3S_PDC "PDC" support, the user could follow these steps:
* <ul> * <ul>
* <li> Configure USART with expected mode and baudrate(see \ref USART_Configure), which could be done by: * <li> Configure USART with expected mode and baudrate(see \ref USART_Configure), which could be done by:
* -# Resetting and disabling transmitter and receiver by setting US_CR(Control Register). </li> * -# Resetting and disabling transmitter and receiver by setting US_CR(Control Register). </li>
* -# Conifguring the USART in a specific mode by setting USART_MODE bits in US_MR(Mode Register) </li> * -# Conifguring the USART in a specific mode by setting USART_MODE bits in US_MR(Mode Register) </li>
* -# Setting baudrate which is different from mode to mode. * -# Setting baudrate which is different from mode to mode.
</li> </li>
* <li> Enable transmitter or receiver respectively by set US_CR_TXEN or US_CR_RXEN in US_CR.</li> * <li> Enable transmitter or receiver respectively by set US_CR_TXEN or US_CR_RXEN in US_CR.</li>
* <li> Read from or write to the peripheral with \ref USART_ReadBuffer or \ref USART_WriteBuffer. * <li> Read from or write to the peripheral with \ref USART_ReadBuffer or \ref USART_WriteBuffer.
These operations could be done by polling or interruption. </li> These operations could be done by polling or interruption. </li>
* <li> For polling, check the status bit US_CSR_ENDRX/US_CSR_RXBUFF (READ) or US_CSR_ENDTX/ * <li> For polling, check the status bit US_CSR_ENDRX/US_CSR_RXBUFF (READ) or US_CSR_ENDTX/
US_CSR_TXBUFE (WRITE). </li> US_CSR_TXBUFE (WRITE). </li>
* <li> For interruption,"enable" the status bit through US_IER and * <li> For interruption,"enable" the status bit through US_IER and
realize the hanler with USARTx_IrqHandler according to IRQ vector realize the hanler with USARTx_IrqHandler according to IRQ vector
table which is defined in board_cstartup_<toolchain>.c table which is defined in board_cstartup_<toolchain>.c
To enable the interruption of USART,it should be configured with priority and enabled first through To enable the interruption of USART,it should be configured with priority and enabled first through
NVIC .</li> NVIC .</li>
* </ul> * </ul>
* *
* For more accurate information, please look at the USART section of the * For more accurate information, please look at the USART section of the
* Datasheet. * Datasheet.
* *
* Related files :\n * Related files :\n
* \ref usart.c\n * \ref usart.c\n
* \ref usart.h\n * \ref usart.h\n
*/ */
/** /**
* \file * \file
* *
* Implementation of USART (Universal Synchronous Asynchronous Receiver Transmitter) * Implementation of USART (Universal Synchronous Asynchronous Receiver Transmitter)
* controller. * controller.
* *
*/ */
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Headers * Headers
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include "trace.h" #include "trace.h"
#include <assert.h> #include <assert.h>
#include <string.h> #include <string.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Local definitions * Local definitions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Exported functions * Exported functions
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
/** /**
* \brief Configures an USART peripheral with the specified parameters. * \brief Configures an USART peripheral with the specified parameters.
* *
* *
* \param usart Pointer to the USART peripheral to configure. * \param usart Pointer to the USART peripheral to configure.
* \param mode Desired value for the USART mode register (see the datasheet). * \param mode Desired value for the USART mode register (see the datasheet).
* \param baudrate Baudrate at which the USART should operate (in Hz). * \param baudrate Baudrate at which the USART should operate (in Hz).
* \param masterClock Frequency of the system master clock (in Hz). * \param masterClock Frequency of the system master clock (in Hz).
*/ */
void USART_Configure(Usart *usart, void USART_Configure(Usart *usart,
uint32_t mode, uint32_t mode,
uint32_t baudrate, uint32_t baudrate,
uint32_t masterClock) uint32_t masterClock)
{ {
/* Reset and disable receiver & transmitter*/ /* Reset and disable receiver & transmitter*/
usart->US_CR = US_CR_RSTRX | US_CR_RSTTX usart->US_CR = US_CR_RSTRX | US_CR_RSTTX
| US_CR_RXDIS | US_CR_TXDIS; | US_CR_RXDIS | US_CR_TXDIS;
/* Configure mode*/ /* Configure mode*/
usart->US_MR = mode; usart->US_MR = mode;
/* Configure baudrate*/ /* Configure baudrate*/
/* Asynchronous, no oversampling*/ /* Asynchronous, no oversampling*/
if ( ((mode & US_MR_SYNC) == 0) && ((mode & US_MR_OVER) == 0) ) if ( ((mode & US_MR_SYNC) == 0) && ((mode & US_MR_OVER) == 0) )
{ {
usart->US_BRGR = (masterClock / baudrate) / 16; usart->US_BRGR = (masterClock / baudrate) / 16;
} }
if( ((mode & US_MR_USART_MODE_SPI_MASTER) == US_MR_USART_MODE_SPI_MASTER) if( ((mode & US_MR_USART_MODE_SPI_MASTER) == US_MR_USART_MODE_SPI_MASTER)
|| ((mode & US_MR_SYNC) == US_MR_SYNC)) || ((mode & US_MR_SYNC) == US_MR_SYNC))
{ {
if( (mode & US_MR_USCLKS_Msk) == US_MR_USCLKS_MCK) if( (mode & US_MR_USCLKS_Msk) == US_MR_USCLKS_MCK)
{ {
usart->US_BRGR = masterClock / baudrate; usart->US_BRGR = masterClock / baudrate;
} }
else else
{ {
if ( (mode & US_MR_USCLKS_DIV) == US_MR_USCLKS_DIV) if ( (mode & US_MR_USCLKS_DIV) == US_MR_USCLKS_DIV)
{ {
usart->US_BRGR = masterClock / baudrate / 8; usart->US_BRGR = masterClock / baudrate / 8;
} }
} }
} }
/* TODO other modes*/ /* TODO other modes*/
} }
/** /**
* \brief Enables or disables the transmitter of an USART peripheral. * \brief Enables or disables the transmitter of an USART peripheral.
* *
* *
* \param usart Pointer to an USART peripheral * \param usart Pointer to an USART peripheral
* \param enabled If true, the transmitter is enabled; otherwise it is * \param enabled If true, the transmitter is enabled; otherwise it is
* disabled. * disabled.
*/ */
void USART_SetTransmitterEnabled(Usart *usart, uint8_t enabled) void USART_SetTransmitterEnabled(Usart *usart, uint8_t enabled)
{ {
if (enabled) { if (enabled) {
usart->US_CR = US_CR_TXEN; usart->US_CR = US_CR_TXEN;
} }
else { else {
usart->US_CR = US_CR_TXDIS; usart->US_CR = US_CR_TXDIS;
} }
} }
/** /**
* \brief Enables or disables the receiver of an USART peripheral * \brief Enables or disables the receiver of an USART peripheral
* *
* *
* \param usart Pointer to an USART peripheral * \param usart Pointer to an USART peripheral
* \param enabled If true, the receiver is enabled; otherwise it is disabled. * \param enabled If true, the receiver is enabled; otherwise it is disabled.
*/ */
void USART_SetReceiverEnabled(Usart *usart, void USART_SetReceiverEnabled(Usart *usart,
uint8_t enabled) uint8_t enabled)
{ {
if (enabled) { if (enabled) {
usart->US_CR = US_CR_RXEN; usart->US_CR = US_CR_RXEN;
} }
else { else {
usart->US_CR = US_CR_RXDIS; usart->US_CR = US_CR_RXDIS;
} }
} }
/** /**
* \brief Sends one packet of data through the specified USART peripheral. This * \brief Sends one packet of data through the specified USART peripheral. This
* function operates synchronously, so it only returns when the data has been * function operates synchronously, so it only returns when the data has been
* actually sent. * actually sent.
* *
* *
* \param usart Pointer to an USART peripheral. * \param usart Pointer to an USART peripheral.
* \param data Data to send including 9nth bit and sync field if necessary (in * \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). * the same format as the US_THR register in the datasheet).
* \param timeOut Time out value (0 = no timeout). * \param timeOut Time out value (0 = no timeout).
*/ */
void USART_Write( void USART_Write(
Usart *usart, Usart *usart,
uint16_t data, uint16_t data,
volatile uint32_t timeOut) volatile uint32_t timeOut)
{ {
if (timeOut == 0) { if (timeOut == 0) {
while ((usart->US_CSR & US_CSR_TXEMPTY) == 0); while ((usart->US_CSR & US_CSR_TXEMPTY) == 0);
} }
else { else {
while ((usart->US_CSR & US_CSR_TXEMPTY) == 0) { while ((usart->US_CSR & US_CSR_TXEMPTY) == 0) {
if (timeOut == 0) { if (timeOut == 0) {
TRACE_ERROR("USART_Write: Timed out.\n\r"); TRACE_ERROR("USART_Write: Timed out.\n\r");
return; return;
} }
timeOut--; timeOut--;
} }
} }
usart->US_THR = data; usart->US_THR = data;
} }
/** /**
* \brief Sends the contents of a data buffer through the specified USART peripheral. * \brief Sends the contents of a data buffer through the specified USART peripheral.
* This function returns immediately (1 if the buffer has been queued, 0 * This function returns immediately (1 if the buffer has been queued, 0
* otherwise); poll the ENDTX and TXBUFE bits of the USART status register * otherwise); poll the ENDTX and TXBUFE bits of the USART status register
* to check for the transfer completion. * to check for the transfer completion.
* *
* \param usart Pointer to an USART peripheral. * \param usart Pointer to an USART peripheral.
* \param buffer Pointer to the data buffer to send. * \param buffer Pointer to the data buffer to send.
* \param size Size of the data buffer (in bytes). * \param size Size of the data buffer (in bytes).
*/ */
uint8_t USART_WriteBuffer( uint8_t USART_WriteBuffer(
Usart *usart, Usart *usart,
void *buffer, void *buffer,
uint32_t size) uint32_t size)
{ {
/* Check if the first PDC bank is free*/ /* Check if the first PDC bank is free*/
if ((usart->US_TCR == 0) && (usart->US_TNCR == 0)) { if ((usart->US_TCR == 0) && (usart->US_TNCR == 0)) {
usart->US_TPR = (uint32_t) buffer; usart->US_TPR = (uint32_t) buffer;
usart->US_TCR = size; usart->US_TCR = size;
usart->US_PTCR = US_PTCR_TXTEN; usart->US_PTCR = US_PTCR_TXTEN;
return 1; return 1;
} }
/* Check if the second PDC bank is free*/ /* Check if the second PDC bank is free*/
else if (usart->US_TNCR == 0) { else if (usart->US_TNCR == 0) {
usart->US_TNPR = (uint32_t) buffer; usart->US_TNPR = (uint32_t) buffer;
usart->US_TNCR = size; usart->US_TNCR = size;
return 1; return 1;
} }
else { else {
return 0; return 0;
} }
} }
/** /**
* \brief Reads and return a packet of data on the specified USART peripheral. This * \brief Reads and return a packet of data on the specified USART peripheral. This
* function operates asynchronously, so it waits until some data has been * function operates asynchronously, so it waits until some data has been
* received. * received.
* *
* \param usart Pointer to an USART peripheral. * \param usart Pointer to an USART peripheral.
* \param timeOut Time out value (0 -> no timeout). * \param timeOut Time out value (0 -> no timeout).
*/ */
uint16_t USART_Read( uint16_t USART_Read(
Usart *usart, Usart *usart,
volatile uint32_t timeOut) volatile uint32_t timeOut)
{ {
if (timeOut == 0) { if (timeOut == 0) {
while ((usart->US_CSR & US_CSR_RXRDY) == 0); while ((usart->US_CSR & US_CSR_RXRDY) == 0);
} }
else { else {
while ((usart->US_CSR & US_CSR_RXRDY) == 0) { while ((usart->US_CSR & US_CSR_RXRDY) == 0) {
if (timeOut == 0) { if (timeOut == 0) {
TRACE_ERROR( "USART_Read: Timed out.\n\r" ) ; TRACE_ERROR( "USART_Read: Timed out.\n\r" ) ;
return 0; return 0;
} }
timeOut--; timeOut--;
} }
} }
return usart->US_RHR; return usart->US_RHR;
} }
/** /**
* \brief Reads data from an USART peripheral, filling the provided buffer until it * \brief Reads data from an USART peripheral, filling the provided buffer until it
* becomes full. This function returns immediately with 1 if the buffer has * becomes full. This function returns immediately with 1 if the buffer has
* been queued for transmission; otherwise 0. * been queued for transmission; otherwise 0.
* *
* \param usart Pointer to an USART peripheral. * \param usart Pointer to an USART peripheral.
* \param buffer Pointer to the buffer where the received data will be stored. * \param buffer Pointer to the buffer where the received data will be stored.
* \param size Size of the data buffer (in bytes). * \param size Size of the data buffer (in bytes).
*/ */
uint8_t USART_ReadBuffer(Usart *usart, uint8_t USART_ReadBuffer(Usart *usart,
void *buffer, void *buffer,
uint32_t size) uint32_t size)
{ {
/* Check if the first PDC bank is free*/ /* Check if the first PDC bank is free*/
if ((usart->US_RCR == 0) && (usart->US_RNCR == 0)) { if ((usart->US_RCR == 0) && (usart->US_RNCR == 0)) {
usart->US_RPR = (uint32_t) buffer; usart->US_RPR = (uint32_t) buffer;
usart->US_RCR = size; usart->US_RCR = size;
usart->US_PTCR = US_PTCR_RXTEN; usart->US_PTCR = US_PTCR_RXTEN;
return 1; return 1;
} }
/* Check if the second PDC bank is free*/ /* Check if the second PDC bank is free*/
else if (usart->US_RNCR == 0) { else if (usart->US_RNCR == 0) {
usart->US_RNPR = (uint32_t) buffer; usart->US_RNPR = (uint32_t) buffer;
usart->US_RNCR = size; usart->US_RNCR = size;
return 1; return 1;
} }
else { else {
return 0; return 0;
} }
} }
/** /**
* \brief Returns 1 if some data has been received and can be read from an USART; * \brief Returns 1 if some data has been received and can be read from an USART;
* otherwise returns 0. * otherwise returns 0.
* *
* \param usart Pointer to an Usart instance. * \param usart Pointer to an Usart instance.
*/ */
uint8_t USART_IsDataAvailable(Usart *usart) uint8_t USART_IsDataAvailable(Usart *usart)
{ {
if ((usart->US_CSR & US_CSR_RXRDY) != 0) { if ((usart->US_CSR & US_CSR_RXRDY) != 0) {
return 1; return 1;
} }
else { else {
return 0; return 0;
} }
} }
/** /**
* \brief Sets the filter value for the IRDA demodulator. * \brief Sets the filter value for the IRDA demodulator.
* *
* \param pUsart Pointer to an Usart instance. * \param pUsart Pointer to an Usart instance.
* \param filter Filter value. * \param filter Filter value.
*/ */
void USART_SetIrdaFilter(Usart *pUsart, uint8_t filter) void USART_SetIrdaFilter(Usart *pUsart, uint8_t filter)
{ {
assert( pUsart != NULL ) ; assert( pUsart != NULL ) ;
pUsart->US_IF = filter; pUsart->US_IF = filter;
} }
/** /**
* \brief Sends one packet of data through the specified USART peripheral. This * \brief Sends one packet of data through the specified USART peripheral. This
* function operates synchronously, so it only returns when the data has been * function operates synchronously, so it only returns when the data has been
* actually sent. * actually sent.
* *
* \param usart Pointer to an USART peripheral. * \param usart Pointer to an USART peripheral.
* \param c Character to send * \param c Character to send
*/ */
void USART_PutChar( void USART_PutChar(
Usart *usart, Usart *usart,
uint8_t c) uint8_t c)
{ {
/* Wait for the transmitter to be ready*/ /* Wait for the transmitter to be ready*/
while ((usart->US_CSR & US_CSR_TXEMPTY) == 0); while ((usart->US_CSR & US_CSR_TXEMPTY) == 0);
/* Send character*/ /* Send character*/
usart->US_THR = c; usart->US_THR = c;
/* Wait for the transfer to complete*/ /* Wait for the transfer to complete*/
while ((usart->US_CSR & US_CSR_TXEMPTY) == 0); while ((usart->US_CSR & US_CSR_TXEMPTY) == 0);
} }
/** /**
* \brief Return 1 if a character can be read in USART * \brief Return 1 if a character can be read in USART
*/ */
uint32_t USART_IsRxReady(Usart *usart) uint32_t USART_IsRxReady(Usart *usart)
{ {
return (usart->US_CSR & US_CSR_RXRDY); return (usart->US_CSR & US_CSR_RXRDY);
} }
/** /**
* \brief Get present status * \brief Get present status
*/ */
uint32_t USART_GetStatus(Usart *usart) uint32_t USART_GetStatus(Usart *usart)
{ {
return usart->US_CSR; return usart->US_CSR;
} }
/** /**
* \brief Enable interrupt * \brief Enable interrupt
*/ */
void USART_EnableIt(Usart *usart,uint32_t mode) void USART_EnableIt(Usart *usart,uint32_t mode)
{ {
usart->US_IER = mode; usart->US_IER = mode;
} }
/** /**
* \brief Disable interrupt * \brief Disable interrupt
*/ */
void USART_DisableIt(Usart *usart,uint32_t mode) void USART_DisableIt(Usart *usart,uint32_t mode)
{ {
usart->US_IDR = mode; usart->US_IDR = mode;
} }
/** /**
* \brief Reads and returns a character from the USART. * \brief Reads and returns a character from the USART.
* *
* \note This function is synchronous (i.e. uses polling). * \note This function is synchronous (i.e. uses polling).
* \param usart Pointer to an USART peripheral. * \param usart Pointer to an USART peripheral.
* \return Character received. * \return Character received.
*/ */
uint8_t USART_GetChar(Usart *usart) uint8_t USART_GetChar(Usart *usart)
{ {
while ((usart->US_CSR & US_CSR_RXRDY) == 0); while ((usart->US_CSR & US_CSR_RXRDY) == 0);
return usart->US_RHR; return usart->US_RHR;
} }

View File

@@ -1,132 +1,132 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** /**
* \file * \file
* *
* Implementation of Watchdog Timer (WDT) controller. * Implementation of Watchdog Timer (WDT) controller.
* *
*/ */
/** \addtogroup wdt_module Working with WDT /** \addtogroup wdt_module Working with WDT
* The WDT driver provides the interface to configure and use the WDT * The WDT driver provides the interface to configure and use the WDT
* peripheral. * peripheral.
* *
* The WDT can be used to prevent system lock-up if the software becomes * The WDT can be used to prevent system lock-up if the software becomes
* trapped in a deadlock. It can generate a general reset or a processor * trapped in a deadlock. It can generate a general reset or a processor
* reset only. It is clocked by slow clock divided by 128. * reset only. It is clocked by slow clock divided by 128.
* *
* The WDT is running at reset with 16 seconds watchdog period (slow clock at 32.768 kHz) * The WDT is running at reset with 16 seconds watchdog period (slow clock at 32.768 kHz)
* and external reset generation enabled. The user must either disable it or * and external reset generation enabled. The user must either disable it or
* reprogram it to meet the application requires. * reprogram it to meet the application requires.
* *
* To use the WDT, the user could follow these few steps: * To use the WDT, the user could follow these few steps:
* <ul> * <ul>
* <li>Enable watchdog with given mode using \ref WDT_Enable(). * <li>Enable watchdog with given mode using \ref WDT_Enable().
* <li>Restart the watchdog using \ref WDT_Restart() within the watchdog period. * <li>Restart the watchdog using \ref WDT_Restart() within the watchdog period.
* </ul> * </ul>
* *
* For more accurate information, please look at the WDT section of the * For more accurate information, please look at the WDT section of the
* Datasheet. * Datasheet.
* *
* \note * \note
* The Watchdog Mode Register (WDT_MR) can be written only once.\n * The Watchdog Mode Register (WDT_MR) can be written only once.\n
* *
* Related files :\n * Related files :\n
* \ref wdt.c\n * \ref wdt.c\n
* \ref wdt.h.\n * \ref wdt.h.\n
*/ */
/*@{*/ /*@{*/
/*@}*/ /*@}*/
/*--------------------------------------------------------------------------- /*---------------------------------------------------------------------------
* Headers * Headers
*---------------------------------------------------------------------------*/ *---------------------------------------------------------------------------*/
#include "chip.h" #include "chip.h"
#include <stdint.h> #include <stdint.h>
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported functions * Exported functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* \brief Enable watchdog with given mode. * \brief Enable watchdog with given mode.
* *
* \note The Watchdog Mode Register (WDT_MR) can be written only once. * \note The Watchdog Mode Register (WDT_MR) can be written only once.
* Only a processor reset resets it. * Only a processor reset resets it.
* *
* \param dwMode WDT mode to be set * \param dwMode WDT mode to be set
*/ */
extern void WDT_Enable( Wdt* pWDT, uint32_t dwMode ) extern void WDT_Enable( Wdt* pWDT, uint32_t dwMode )
{ {
pWDT->WDT_MR = dwMode ; pWDT->WDT_MR = dwMode ;
} }
/** /**
* \brief Disable watchdog. * \brief Disable watchdog.
* *
* \note The Watchdog Mode Register (WDT_MR) can be written only once. * \note The Watchdog Mode Register (WDT_MR) can be written only once.
* Only a processor reset resets it. * Only a processor reset resets it.
*/ */
extern void WDT_Disable( Wdt* pWDT ) extern void WDT_Disable( Wdt* pWDT )
{ {
pWDT->WDT_MR = WDT_MR_WDDIS; pWDT->WDT_MR = WDT_MR_WDDIS;
} }
/** /**
* \brief Watchdog restart. * \brief Watchdog restart.
*/ */
extern void WDT_Restart( Wdt* pWDT ) extern void WDT_Restart( Wdt* pWDT )
{ {
pWDT->WDT_CR = 0xA5000001; pWDT->WDT_CR = 0xA5000001;
} }
/** /**
* \brief Watchdog get status. * \brief Watchdog get status.
*/ */
extern uint32_t WDT_GetStatus( Wdt* pWDT ) extern uint32_t WDT_GetStatus( Wdt* pWDT )
{ {
return (pWDT->WDT_SR & 0x3) ; return (pWDT->WDT_SR & 0x3) ;
} }
/** /**
* \brief Watchdog get period. * \brief Watchdog get period.
* *
* \param dwMs desired watchdog period in millisecond. * \param dwMs desired watchdog period in millisecond.
*/ */
extern uint32_t WDT_GetPeriod( uint32_t dwMs ) extern uint32_t WDT_GetPeriod( uint32_t dwMs )
{ {
if ( (dwMs < 4) || (dwMs > 16000) ) if ( (dwMs < 4) || (dwMs > 16000) )
{ {
return 0 ; return 0 ;
} }
return ((dwMs << 8) / 1000) ; return ((dwMs << 8) / 1000) ;
} }

View File

@@ -1,208 +1,208 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2010, Atmel Corporation * Copyright (c) 2010, Atmel Corporation
* Copyright (c) 2017, Harald Welte <laforge@gnumonks.org> * Copyright (c) 2017, Harald Welte <laforge@gnumonks.org>
* Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de> * Copyright (c) 2018, sysmocom -s.f.m.c. GmbH, Author: Kevin Redon <kredon@sysmocom.de>
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Headers * Headers
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#include "board.h" #include "board.h"
#include "board_lowlevel.h" #include "board_lowlevel.h"
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported variables * Exported variables
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/* Stack Configuration */ /* Stack Configuration */
#define STACK_SIZE 0x900 /** Stack size (in DWords) */ #define STACK_SIZE 0x900 /** Stack size (in DWords) */
__attribute__ ((aligned(8),section(".stack"))) __attribute__ ((aligned(8),section(".stack")))
uint32_t pdwStack[STACK_SIZE] ; uint32_t pdwStack[STACK_SIZE] ;
/* Initialize segments */ /* Initialize segments */
extern uint32_t _sfixed; extern uint32_t _sfixed;
extern uint32_t _efixed; extern uint32_t _efixed;
extern uint32_t _etext; extern uint32_t _etext;
extern uint32_t _srelocate; extern uint32_t _srelocate;
extern uint32_t _erelocate; extern uint32_t _erelocate;
extern uint32_t _szero; extern uint32_t _szero;
extern uint32_t _ezero; extern uint32_t _ezero;
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* ProtoTypes * ProtoTypes
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** \cond DOXYGEN_SHOULD_SKIP_THIS */ /** \cond DOXYGEN_SHOULD_SKIP_THIS */
extern int main( void ) ; extern int main( void ) ;
/** \endcond */ /** \endcond */
void ResetException( void ) ; void ResetException( void ) ;
/*------------------------------------------------------------------------------ /*------------------------------------------------------------------------------
* Exception Table * Exception Table
*------------------------------------------------------------------------------*/ *------------------------------------------------------------------------------*/
__attribute__((section(".vectors"))) __attribute__((section(".vectors")))
IntFunc exception_table[] = { IntFunc exception_table[] = {
/* Configure Initial Stack Pointer, using linker-generated symbols */ /* Configure Initial Stack Pointer, using linker-generated symbols */
(IntFunc)(&pdwStack[STACK_SIZE-1]), (IntFunc)(&pdwStack[STACK_SIZE-1]),
ResetException, ResetException,
NMI_Handler, NMI_Handler,
HardFault_Handler, HardFault_Handler,
MemManage_Handler, MemManage_Handler,
BusFault_Handler, BusFault_Handler,
UsageFault_Handler, UsageFault_Handler,
0, 0, 0, 0, /* Reserved */ 0, 0, 0, 0, /* Reserved */
SVC_Handler, SVC_Handler,
DebugMon_Handler, DebugMon_Handler,
0, /* Reserved */ 0, /* Reserved */
PendSV_Handler, PendSV_Handler,
SysTick_Handler, SysTick_Handler,
/* Configurable interrupts */ /* Configurable interrupts */
SUPC_IrqHandler, /* 0 Supply Controller */ SUPC_IrqHandler, /* 0 Supply Controller */
RSTC_IrqHandler, /* 1 Reset Controller */ RSTC_IrqHandler, /* 1 Reset Controller */
RTC_IrqHandler, /* 2 Real Time Clock */ RTC_IrqHandler, /* 2 Real Time Clock */
RTT_IrqHandler, /* 3 Real Time Timer */ RTT_IrqHandler, /* 3 Real Time Timer */
WDT_IrqHandler, /* 4 Watchdog Timer */ WDT_IrqHandler, /* 4 Watchdog Timer */
PMC_IrqHandler, /* 5 PMC */ PMC_IrqHandler, /* 5 PMC */
EEFC_IrqHandler, /* 6 EEFC */ EEFC_IrqHandler, /* 6 EEFC */
IrqHandlerNotUsed, /* 7 Reserved */ IrqHandlerNotUsed, /* 7 Reserved */
UART0_IrqHandler, /* 8 UART0 */ UART0_IrqHandler, /* 8 UART0 */
UART1_IrqHandler, /* 9 UART1 */ UART1_IrqHandler, /* 9 UART1 */
SMC_IrqHandler, /* 10 SMC */ SMC_IrqHandler, /* 10 SMC */
PIOA_IrqHandler, /* 11 Parallel IO Controller A */ PIOA_IrqHandler, /* 11 Parallel IO Controller A */
PIOB_IrqHandler, /* 12 Parallel IO Controller B */ PIOB_IrqHandler, /* 12 Parallel IO Controller B */
PIOC_IrqHandler, /* 13 Parallel IO Controller C */ PIOC_IrqHandler, /* 13 Parallel IO Controller C */
USART0_IrqHandler, /* 14 USART 0 */ USART0_IrqHandler, /* 14 USART 0 */
USART1_IrqHandler, /* 15 USART 1 */ USART1_IrqHandler, /* 15 USART 1 */
IrqHandlerNotUsed, /* 16 Reserved */ IrqHandlerNotUsed, /* 16 Reserved */
IrqHandlerNotUsed, /* 17 Reserved */ IrqHandlerNotUsed, /* 17 Reserved */
MCI_IrqHandler, /* 18 MCI */ MCI_IrqHandler, /* 18 MCI */
TWI0_IrqHandler, /* 19 TWI 0 */ TWI0_IrqHandler, /* 19 TWI 0 */
TWI1_IrqHandler, /* 20 TWI 1 */ TWI1_IrqHandler, /* 20 TWI 1 */
SPI_IrqHandler, /* 21 SPI */ SPI_IrqHandler, /* 21 SPI */
SSC_IrqHandler, /* 22 SSC */ SSC_IrqHandler, /* 22 SSC */
TC0_IrqHandler, /* 23 Timer Counter 0 */ TC0_IrqHandler, /* 23 Timer Counter 0 */
TC1_IrqHandler, /* 24 Timer Counter 1 */ TC1_IrqHandler, /* 24 Timer Counter 1 */
TC2_IrqHandler, /* 25 Timer Counter 2 */ TC2_IrqHandler, /* 25 Timer Counter 2 */
TC3_IrqHandler, /* 26 Timer Counter 3 */ TC3_IrqHandler, /* 26 Timer Counter 3 */
TC4_IrqHandler, /* 27 Timer Counter 4 */ TC4_IrqHandler, /* 27 Timer Counter 4 */
TC5_IrqHandler, /* 28 Timer Counter 5 */ TC5_IrqHandler, /* 28 Timer Counter 5 */
ADC_IrqHandler, /* 29 ADC controller */ ADC_IrqHandler, /* 29 ADC controller */
DAC_IrqHandler, /* 30 DAC controller */ DAC_IrqHandler, /* 30 DAC controller */
PWM_IrqHandler, /* 31 PWM */ PWM_IrqHandler, /* 31 PWM */
CRCCU_IrqHandler, /* 32 CRC Calculation Unit */ CRCCU_IrqHandler, /* 32 CRC Calculation Unit */
ACC_IrqHandler, /* 33 Analog Comparator */ ACC_IrqHandler, /* 33 Analog Comparator */
USBD_IrqHandler, /* 34 USB Device Port */ USBD_IrqHandler, /* 34 USB Device Port */
IrqHandlerNotUsed /* 35 not used */ IrqHandlerNotUsed /* 35 not used */
}; };
#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu) #if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu)
#include "usb/device/dfu/dfu.h" #include "usb/device/dfu/dfu.h"
static void BootIntoApp(void) static void BootIntoApp(void)
{ {
unsigned int *pSrc; unsigned int *pSrc;
void (*appReset)(void); void (*appReset)(void);
pSrc = (unsigned int *) ((unsigned char *)IFLASH_ADDR + BOARD_DFU_BOOT_SIZE); pSrc = (unsigned int *) ((unsigned char *)IFLASH_ADDR + BOARD_DFU_BOOT_SIZE);
/* set vector table to application vector table (store at the beginning of the application) */ /* set vector table to application vector table (store at the beginning of the application) */
SCB->VTOR = (unsigned int)(pSrc); SCB->VTOR = (unsigned int)(pSrc);
/* set stack pointer to address provided in the beginning of the application (loaded into a register first) */ /* set stack pointer to address provided in the beginning of the application (loaded into a register first) */
__asm__ volatile ("MSR msp,%0" : :"r"(*pSrc)); __asm__ volatile ("MSR msp,%0" : :"r"(*pSrc));
/* start application (by jumping to the reset function which address is stored as second entry of the vector table) */ /* start application (by jumping to the reset function which address is stored as second entry of the vector table) */
appReset = (void(*)(void))pSrc[1]; appReset = (void(*)(void))pSrc[1];
g_dfu->state = DFU_STATE_appIDLE; g_dfu->state = DFU_STATE_appIDLE;
appReset(); appReset();
} }
#endif #endif
/** /**
* \brief This is the code that gets called on processor reset. * \brief This is the code that gets called on processor reset.
* To initialize the device, and call the main() routine. * To initialize the device, and call the main() routine.
*/ */
void ResetException( void ) void ResetException( void )
{ {
uint32_t *pSrc, *pDest ; uint32_t *pSrc, *pDest ;
/* Low level Initialize */ /* Low level Initialize */
LowLevelInit() ; LowLevelInit() ;
#if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu) #if defined(BOARD_USB_DFU) && defined(APPLICATION_dfu)
if (!USBDFU_OverrideEnterDFU()) { if (!USBDFU_OverrideEnterDFU()) {
UART_Exit(); UART_Exit();
__disable_irq(); __disable_irq();
BootIntoApp(); BootIntoApp();
/* Infinite loop */ /* Infinite loop */
while ( 1 ) ; while ( 1 ) ;
} }
#endif #endif
/* Initialize the relocate segment */ /* Initialize the relocate segment */
pSrc = &_etext ; pSrc = &_etext ;
pDest = &_srelocate ; pDest = &_srelocate ;
if ( pSrc != pDest ) if ( pSrc != pDest )
{ {
for ( ; pDest < &_erelocate ; ) for ( ; pDest < &_erelocate ; )
{ {
*pDest++ = *pSrc++ ; *pDest++ = *pSrc++ ;
} }
} }
/* Clear the zero segment */ /* Clear the zero segment */
for ( pDest = &_szero ; pDest < &_ezero ; ) for ( pDest = &_szero ; pDest < &_ezero ; )
{ {
*pDest++ = 0; *pDest++ = 0;
} }
/* Set the vector table base address */ /* Set the vector table base address */
pSrc = (uint32_t *)&_sfixed; pSrc = (uint32_t *)&_sfixed;
SCB->VTOR = ( (uint32_t)pSrc & SCB_VTOR_TBLOFF_Msk ) ; SCB->VTOR = ( (uint32_t)pSrc & SCB_VTOR_TBLOFF_Msk ) ;
if ( ((uint32_t)pSrc >= IRAM_ADDR) && ((uint32_t)pSrc < IRAM_ADDR+IRAM_SIZE) ) if ( ((uint32_t)pSrc >= IRAM_ADDR) && ((uint32_t)pSrc < IRAM_ADDR+IRAM_SIZE) )
{ {
SCB->VTOR |= 1 << SCB_VTOR_TBLBASE_Pos ; SCB->VTOR |= 1 << SCB_VTOR_TBLBASE_Pos ;
} }
/* App should have disabled interrupts during the transition */ /* App should have disabled interrupts during the transition */
__enable_irq(); __enable_irq();
/* Branch to main function */ /* Branch to main function */
main() ; main() ;
/* Infinite loop */ /* Infinite loop */
while ( 1 ) ; while ( 1 ) ;
} }

View File

@@ -1,216 +1,216 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** /**
* \file * \file
* *
* Provides the low-level initialization function that called on chip startup. * Provides the low-level initialization function that called on chip startup.
*/ */
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Headers * Headers
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#include "board.h" #include "board.h"
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Local definitions * Local definitions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8)) #define BOARD_OSCOUNT (CKGR_MOR_MOSCXTST(0x8))
#define BOARD_MCKR (PMC_MCKR_PRES_CLK | PMC_MCKR_CSS_PLLA_CLK) #define BOARD_MCKR (PMC_MCKR_PRES_CLK | PMC_MCKR_CSS_PLLA_CLK)
#if (BOARD_MCK == 48000000) #if (BOARD_MCK == 48000000)
#if (BOARD_MAINOSC == 18432000) #if (BOARD_MAINOSC == 18432000)
/* Clock settings at 48MHz for 18 MHz crystal */ /* Clock settings at 48MHz for 18 MHz crystal */
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \ #define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(13-1) \ | CKGR_PLLAR_MULA(13-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \ | CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(5)) | CKGR_PLLAR_DIVA(5))
#elif (BOARD_MAINOSC == 12000000) #elif (BOARD_MAINOSC == 12000000)
/* QMod has 12 MHz clock, so multply by 8 (96 MHz) and divide by 2 */ /* QMod has 12 MHz clock, so multply by 8 (96 MHz) and divide by 2 */
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \ #define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(8-1) \ | CKGR_PLLAR_MULA(8-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \ | CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(2)) | CKGR_PLLAR_DIVA(2))
#else #else
#error "Please define PLLA config for your MAINOSC frequency" #error "Please define PLLA config for your MAINOSC frequency"
#endif /* MAINOSC */ #endif /* MAINOSC */
#elif (BOARD_MCK == 64000000) #elif (BOARD_MCK == 64000000)
#if (BOARD_MAINOSC == 18432000) #if (BOARD_MAINOSC == 18432000)
/* Clock settings at 64MHz for 18 MHz crystal: 64.512 MHz */ /* Clock settings at 64MHz for 18 MHz crystal: 64.512 MHz */
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \ #define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(7-1) \ | CKGR_PLLAR_MULA(7-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \ | CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(2)) | CKGR_PLLAR_DIVA(2))
#elif (BOARD_MAINOSC == 12000000) #elif (BOARD_MAINOSC == 12000000)
/* QMod has 12 MHz clock, so multply by 10 / div by 2: 60 MHz */ /* QMod has 12 MHz clock, so multply by 10 / div by 2: 60 MHz */
#define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \ #define BOARD_PLLAR (CKGR_PLLAR_STUCKTO1 \
| CKGR_PLLAR_MULA(10-1) \ | CKGR_PLLAR_MULA(10-1) \
| CKGR_PLLAR_PLLACOUNT(0x1) \ | CKGR_PLLAR_PLLACOUNT(0x1) \
| CKGR_PLLAR_DIVA(2)) | CKGR_PLLAR_DIVA(2))
#error "Please define PLLA config for your MAINOSC frequency" #error "Please define PLLA config for your MAINOSC frequency"
#endif /* MAINOSC */ #endif /* MAINOSC */
#else #else
#error "No PLL settings for current BOARD_MCK." #error "No PLL settings for current BOARD_MCK."
#endif #endif
#if (BOARD_MAINOSC == 12000000) #if (BOARD_MAINOSC == 12000000)
#define PLLB_CFG (CKGR_PLLBR_DIVB(2)|CKGR_PLLBR_MULB(8-1)|CKGR_PLLBR_PLLBCOUNT_Msk) #define PLLB_CFG (CKGR_PLLBR_DIVB(2)|CKGR_PLLBR_MULB(8-1)|CKGR_PLLBR_PLLBCOUNT_Msk)
#elif (BOARD_MAINOSC == 18432000) #elif (BOARD_MAINOSC == 18432000)
#define PLLB_CFG (CKGR_PLLBR_DIVB(5)|CKGR_PLLBR_MULB(13-1)|CKGR_PLLBR_PLLBCOUNT_Msk) #define PLLB_CFG (CKGR_PLLBR_DIVB(5)|CKGR_PLLBR_MULB(13-1)|CKGR_PLLBR_PLLBCOUNT_Msk)
#else #else
#error "Please configure PLLB for your MAINOSC freq" #error "Please configure PLLB for your MAINOSC freq"
#endif #endif
/* Define clock timeout */ /* Define clock timeout */
#define CLOCK_TIMEOUT 0xFFFFFFFF #define CLOCK_TIMEOUT 0xFFFFFFFF
/** /**
* \brief Configure 48MHz Clock for USB * \brief Configure 48MHz Clock for USB
*/ */
static void _ConfigureUsbClock(void) static void _ConfigureUsbClock(void)
{ {
/* Enable PLLB for USB */ /* Enable PLLB for USB */
PMC->CKGR_PLLBR = PLLB_CFG; PMC->CKGR_PLLBR = PLLB_CFG;
while ((PMC->PMC_SR & PMC_SR_LOCKB) == 0) ; while ((PMC->PMC_SR & PMC_SR_LOCKB) == 0) ;
/* USB Clock uses PLLB */ /* USB Clock uses PLLB */
PMC->PMC_USB = PMC_USB_USBDIV(0) /* /1 (no divider) */ PMC->PMC_USB = PMC_USB_USBDIV(0) /* /1 (no divider) */
| PMC_USB_USBS; /* PLLB */ | PMC_USB_USBS; /* PLLB */
} }
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Exported functions * Exported functions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** /**
* \brief Performs the low-level initialization of the chip. * \brief Performs the low-level initialization of the chip.
* This includes EFC and master clock configuration. * This includes EFC and master clock configuration.
* It also enable a low level on the pin NRST triggers a user reset. * It also enable a low level on the pin NRST triggers a user reset.
*/ */
extern WEAK void LowLevelInit( void ) extern WEAK void LowLevelInit( void )
{ {
uint32_t timeout = 0; uint32_t timeout = 0;
/* Configure the Supply Monitor to reset the CPU in case VDDIO is /* Configure the Supply Monitor to reset the CPU in case VDDIO is
* lower than 3.0V. As we run the board on 3.3V, any lower voltage * lower than 3.0V. As we run the board on 3.3V, any lower voltage
* might be some kind of leakage that creeps in some way, but is not * might be some kind of leakage that creeps in some way, but is not
* the "official" power supply */ * the "official" power supply */
SUPC->SUPC_SMMR = SUPC_SMMR_SMTH_3_0V | SUPC_SMMR_SMSMPL_CSM | SUPC->SUPC_SMMR = SUPC_SMMR_SMTH_3_0V | SUPC_SMMR_SMSMPL_CSM |
SUPC_SMMR_SMRSTEN_ENABLE; SUPC_SMMR_SMRSTEN_ENABLE;
/* enable both LED and green LED */ /* enable both LED and green LED */
PIOA->PIO_PER |= PIO_LED_RED | PIO_LED_GREEN; PIOA->PIO_PER |= PIO_LED_RED | PIO_LED_GREEN;
PIOA->PIO_OER |= PIO_LED_RED | PIO_LED_GREEN; PIOA->PIO_OER |= PIO_LED_RED | PIO_LED_GREEN;
PIOA->PIO_CODR |= PIO_LED_RED | PIO_LED_GREEN; PIOA->PIO_CODR |= PIO_LED_RED | PIO_LED_GREEN;
/* Set 3 FWS for Embedded Flash Access */ /* Set 3 FWS for Embedded Flash Access */
EFC->EEFC_FMR = EEFC_FMR_FWS(3); EFC->EEFC_FMR = EEFC_FMR_FWS(3);
/* Select external slow clock */ /* Select external slow clock */
/* if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST) /* if ((SUPC->SUPC_SR & SUPC_SR_OSCSEL) != SUPC_SR_OSCSEL_CRYST)
{ {
SUPC->SUPC_CR = (uint32_t)(SUPC_CR_XTALSEL_CRYSTAL_SEL | SUPC_CR_KEY(0xA5)); SUPC->SUPC_CR = (uint32_t)(SUPC_CR_XTALSEL_CRYSTAL_SEL | SUPC_CR_KEY(0xA5));
timeout = 0; timeout = 0;
while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL_CRYST) ); while (!(SUPC->SUPC_SR & SUPC_SR_OSCSEL_CRYST) );
} }
*/ */
#ifndef qmod #ifndef qmod
/* Initialize main oscillator */ /* Initialize main oscillator */
if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) ) if ( !(PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) )
{ {
PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN; PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN;
timeout = 0; timeout = 0;
while (!(PMC->PMC_SR & PMC_SR_MOSCXTS) && (timeout++ < CLOCK_TIMEOUT)); while (!(PMC->PMC_SR & PMC_SR_MOSCXTS) && (timeout++ < CLOCK_TIMEOUT));
} }
/* Switch to 3-20MHz Xtal oscillator */ /* Switch to 3-20MHz Xtal oscillator */
PIOB->PIO_PDR = (1 << 8) | (1 << 9); PIOB->PIO_PDR = (1 << 8) | (1 << 9);
PIOB->PIO_PUDR = (1 << 8) | (1 << 9); PIOB->PIO_PUDR = (1 << 8) | (1 << 9);
PIOB->PIO_PPDDR = (1 << 8) | (1 << 9); PIOB->PIO_PPDDR = (1 << 8) | (1 << 9);
PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL; PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | BOARD_OSCOUNT | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCSEL;
/* wait for Main XTAL oscillator stabilization */ /* wait for Main XTAL oscillator stabilization */
timeout = 0; timeout = 0;
while (!(PMC->PMC_SR & PMC_SR_MOSCSELS) && (timeout++ < CLOCK_TIMEOUT)); while (!(PMC->PMC_SR & PMC_SR_MOSCSELS) && (timeout++ < CLOCK_TIMEOUT));
#else #else
/* QMOD has external 12MHz clock source */ /* QMOD has external 12MHz clock source */
PIOB->PIO_PDR = (1 << 9); PIOB->PIO_PDR = (1 << 9);
PIOB->PIO_PUDR = (1 << 9); PIOB->PIO_PUDR = (1 << 9);
PIOB->PIO_PPDDR = (1 << 9); PIOB->PIO_PPDDR = (1 << 9);
PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTBY| CKGR_MOR_MOSCSEL; PMC->CKGR_MOR = CKGR_MOR_KEY(0x37) | CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCXTBY| CKGR_MOR_MOSCSEL;
#endif #endif
/* disable the red LED after main clock initialization */ /* disable the red LED after main clock initialization */
PIOA->PIO_SODR = PIO_LED_RED; PIOA->PIO_SODR = PIO_LED_RED;
/* "switch" to main clock as master clock source (should already be the case */ /* "switch" to main clock as master clock source (should already be the case */
PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(uint32_t)PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
/* wait for master clock to be ready */ /* wait for master clock to be ready */
for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; ); for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
/* Initialize PLLA */ /* Initialize PLLA */
PMC->CKGR_PLLAR = BOARD_PLLAR; PMC->CKGR_PLLAR = BOARD_PLLAR;
/* Wait for PLLA to lock */ /* Wait for PLLA to lock */
timeout = 0; timeout = 0;
while (!(PMC->PMC_SR & PMC_SR_LOCKA) && (timeout++ < CLOCK_TIMEOUT)); while (!(PMC->PMC_SR & PMC_SR_LOCKA) && (timeout++ < CLOCK_TIMEOUT));
/* Switch to main clock (again ?!?) */ /* Switch to main clock (again ?!?) */
PMC->PMC_MCKR = (BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK; PMC->PMC_MCKR = (BOARD_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_MAIN_CLK;
/* wait for master clock to be ready */ /* wait for master clock to be ready */
for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; ); for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
/* switch to PLLA as master clock source */ /* switch to PLLA as master clock source */
PMC->PMC_MCKR = BOARD_MCKR ; PMC->PMC_MCKR = BOARD_MCKR ;
/* wait for master clock to be ready */ /* wait for master clock to be ready */
for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; ); for ( timeout = 0; !(PMC->PMC_SR & PMC_SR_MCKRDY) && (timeout++ < CLOCK_TIMEOUT) ; );
/* Configure SysTick for 1ms */ /* Configure SysTick for 1ms */
SysTick_Config(BOARD_MCK/1000); SysTick_Config(BOARD_MCK/1000);
_ConfigureUsbClock(); _ConfigureUsbClock();
} }
/* SysTick based delay function */ /* SysTick based delay function */
volatile uint32_t jiffies; volatile uint32_t jiffies;
/* Interrupt handler for SysTick interrupt */ /* Interrupt handler for SysTick interrupt */
void SysTick_Handler(void) void SysTick_Handler(void)
{ {
jiffies++; jiffies++;
} }
void mdelay(unsigned int msecs) void mdelay(unsigned int msecs)
{ {
uint32_t jiffies_start = jiffies; uint32_t jiffies_start = jiffies;
do { do {
} while ((jiffies - jiffies_start) < msecs); } while ((jiffies - jiffies_start) < msecs);
} }

View File

@@ -1,426 +1,426 @@
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* ATMEL Microcontroller Software Support * ATMEL Microcontroller Software Support
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
* Copyright (c) 2009, Atmel Corporation * Copyright (c) 2009, Atmel Corporation
* *
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* *
* - Redistributions of source code must retain the above copyright notice, * - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below. * this list of conditions and the disclaimer below.
* *
* Atmel's name may not be used to endorse or promote products derived from * Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission. * this software without specific prior written permission.
* *
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR * DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, * DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ---------------------------------------------------------------------------- * ----------------------------------------------------------------------------
*/ */
/** /**
* \file * \file
* *
* Implements UART console. * Implements UART console.
* *
*/ */
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Headers * Headers
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#include "board.h" #include "board.h"
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include "ringbuffer.h" #include "ringbuffer.h"
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Definitions * Definitions
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------- /*----------------------------------------------------------------------------
* Variables * Variables
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
/** Is Console Initialized. */ /** Is Console Initialized. */
static uint8_t _ucIsConsoleInitialized=0; static uint8_t _ucIsConsoleInitialized=0;
/** Ring buffer to queue data to be sent */ /** Ring buffer to queue data to be sent */
static ringbuf uart_tx_buffer; static ringbuf uart_tx_buffer;
/** /**
* \brief Configures an USART peripheral with the specified parameters. * \brief Configures an USART peripheral with the specified parameters.
* *
* \param baudrate Baudrate at which the USART should operate (in Hz). * \param baudrate Baudrate at which the USART should operate (in Hz).
* \param masterClock Frequency of the system master clock (in Hz). * \param masterClock Frequency of the system master clock (in Hz).
*/ */
extern void UART_Configure( uint32_t baudrate, uint32_t masterClock) extern void UART_Configure( uint32_t baudrate, uint32_t masterClock)
{ {
const Pin pPins[] = CONSOLE_PINS; const Pin pPins[] = CONSOLE_PINS;
Uart *pUart = CONSOLE_UART; Uart *pUart = CONSOLE_UART;
/* Configure PIO */ /* Configure PIO */
PIO_Configure(pPins, PIO_LISTSIZE(pPins)); PIO_Configure(pPins, PIO_LISTSIZE(pPins));
/* Configure PMC */ /* Configure PMC */
PMC->PMC_PCER0 = 1 << CONSOLE_ID; PMC->PMC_PCER0 = 1 << CONSOLE_ID;
/* Reset and disable receiver & transmitter */ /* Reset and disable receiver & transmitter */
pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX
| UART_CR_RXDIS | UART_CR_TXDIS; | UART_CR_RXDIS | UART_CR_TXDIS;
/* Configure mode */ /* Configure mode */
pUart->UART_MR = UART_MR_PAR_NO; pUart->UART_MR = UART_MR_PAR_NO;
/* Configure baudrate */ /* Configure baudrate */
/* Asynchronous, no oversampling */ /* Asynchronous, no oversampling */
pUart->UART_BRGR = (masterClock / baudrate) / 16; pUart->UART_BRGR = (masterClock / baudrate) / 16;
/* Disable PDC channel */ /* Disable PDC channel */
pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS; pUart->UART_PTCR = UART_PTCR_RXTDIS | UART_PTCR_TXTDIS;
/* Reset transmit ring buffer */ /* Reset transmit ring buffer */
rbuf_reset(&uart_tx_buffer); rbuf_reset(&uart_tx_buffer);
/* Enable TX interrupts */ /* Enable TX interrupts */
pUart->UART_IER = UART_IER_TXRDY; pUart->UART_IER = UART_IER_TXRDY;
NVIC_EnableIRQ(CONSOLE_IRQ); NVIC_EnableIRQ(CONSOLE_IRQ);
/* Enable receiver and transmitter */ /* Enable receiver and transmitter */
pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN; pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
/* Remember the configuration is complete */ /* Remember the configuration is complete */
_ucIsConsoleInitialized=1 ; _ucIsConsoleInitialized=1 ;
} }
/** /**
* \brief Disables the USART peripheral and related IRQ * \brief Disables the USART peripheral and related IRQ
*/ */
void UART_Exit(void) void UART_Exit(void)
{ {
if (!_ucIsConsoleInitialized) { if (!_ucIsConsoleInitialized) {
return; return;
} }
Uart *pUart = CONSOLE_UART; Uart *pUart = CONSOLE_UART;
pUart->UART_IDR = UART_IDR_TXRDY; pUart->UART_IDR = UART_IDR_TXRDY;
pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS | UART_CR_RSTSTA; pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS | UART_CR_RSTSTA;
PMC->PMC_PCDR0 = 1 << CONSOLE_ID; PMC->PMC_PCDR0 = 1 << CONSOLE_ID;
NVIC_DisableIRQ(CONSOLE_IRQ); NVIC_DisableIRQ(CONSOLE_IRQ);
} }
/** Interrupt Service routine to transmit queued data */ /** Interrupt Service routine to transmit queued data */
void CONSOLE_ISR(void) void CONSOLE_ISR(void)
{ {
Uart *uart = CONSOLE_UART; Uart *uart = CONSOLE_UART;
if (uart->UART_SR & UART_SR_TXRDY) { if (uart->UART_SR & UART_SR_TXRDY) {
if (!rbuf_is_empty(&uart_tx_buffer)) { if (!rbuf_is_empty(&uart_tx_buffer)) {
uart->UART_THR = rbuf_read(&uart_tx_buffer); uart->UART_THR = rbuf_read(&uart_tx_buffer);
} else { } else {
uart->UART_IDR = UART_IER_TXRDY; uart->UART_IDR = UART_IER_TXRDY;
} }
} }
} }
/** /**
* \brief Outputs a character on the UART line. * \brief Outputs a character on the UART line.
* *
* \note This function is synchronous (i.e. uses polling). * \note This function is synchronous (i.e. uses polling).
* \param c Character to send. * \param c Character to send.
*/ */
extern void UART_PutChar( uint8_t c ) extern void UART_PutChar( uint8_t c )
{ {
Uart *pUart = CONSOLE_UART ; Uart *pUart = CONSOLE_UART ;
/* Initialize console is not already done */ /* Initialize console is not already done */
if ( !_ucIsConsoleInitialized ) if ( !_ucIsConsoleInitialized )
{ {
UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK); UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
} }
/* Only store input if buffer is not full, else drop it */ /* Only store input if buffer is not full, else drop it */
if (!rbuf_is_full(&uart_tx_buffer)) { if (!rbuf_is_full(&uart_tx_buffer)) {
rbuf_write(&uart_tx_buffer, c); rbuf_write(&uart_tx_buffer, c);
if (!(pUart->UART_IMR & UART_IMR_TXRDY)) { if (!(pUart->UART_IMR & UART_IMR_TXRDY)) {
pUart->UART_IER = UART_IER_TXRDY; pUart->UART_IER = UART_IER_TXRDY;
CONSOLE_ISR(); CONSOLE_ISR();
} }
} }
} }
/** /**
* \brief Input a character from the UART line. * \brief Input a character from the UART line.
* *
* \note This function is synchronous * \note This function is synchronous
* \return character received. * \return character received.
*/ */
extern uint32_t UART_GetChar( void ) extern uint32_t UART_GetChar( void )
{ {
Uart *pUart = CONSOLE_UART ; Uart *pUart = CONSOLE_UART ;
if ( !_ucIsConsoleInitialized ) if ( !_ucIsConsoleInitialized )
{ {
UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK); UART_Configure(CONSOLE_BAUDRATE, BOARD_MCK);
} }
while ( (pUart->UART_SR & UART_SR_RXRDY) == 0 ) while ( (pUart->UART_SR & UART_SR_RXRDY) == 0 )
WDT_Restart(WDT); WDT_Restart(WDT);
return pUart->UART_RHR ; return pUart->UART_RHR ;
} }
/** /**
* \brief Check if there is Input from UART line. * \brief Check if there is Input from UART line.
* *
* \return true if there is Input. * \return true if there is Input.
*/ */
extern uint32_t UART_IsRxReady( void ) extern uint32_t UART_IsRxReady( void )
{ {
Uart *pUart = CONSOLE_UART; Uart *pUart = CONSOLE_UART;
if ( !_ucIsConsoleInitialized ) if ( !_ucIsConsoleInitialized )
{ {
UART_Configure( CONSOLE_BAUDRATE, BOARD_MCK ) ; UART_Configure( CONSOLE_BAUDRATE, BOARD_MCK ) ;
} }
return (pUart->UART_SR & UART_SR_RXRDY) > 0 ; return (pUart->UART_SR & UART_SR_RXRDY) > 0 ;
} }
/** /**
* Displays the content of the given frame on the UART0. * Displays the content of the given frame on the UART0.
* *
* \param pucFrame Pointer to the frame to dump. * \param pucFrame Pointer to the frame to dump.
* \param dwSize Buffer size in bytes. * \param dwSize Buffer size in bytes.
*/ */
extern void UART_DumpFrame( uint8_t* pucFrame, uint32_t dwSize ) extern void UART_DumpFrame( uint8_t* pucFrame, uint32_t dwSize )
{ {
uint32_t dw ; uint32_t dw ;
for ( dw=0 ; dw < dwSize ; dw++ ) for ( dw=0 ; dw < dwSize ; dw++ )
{ {
printf( "%02X ", pucFrame[dw] ) ; printf( "%02X ", pucFrame[dw] ) ;
} }
printf( "\n\r" ) ; printf( "\n\r" ) ;
} }
/** /**
* Displays the content of the given buffer on the UART0. * Displays the content of the given buffer on the UART0.
* *
* \param pucBuffer Pointer to the buffer to dump. * \param pucBuffer Pointer to the buffer to dump.
* \param dwSize Buffer size in bytes. * \param dwSize Buffer size in bytes.
* \param dwAddress Start address to display * \param dwAddress Start address to display
*/ */
extern void UART_DumpMemory( uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress ) extern void UART_DumpMemory( uint8_t* pucBuffer, uint32_t dwSize, uint32_t dwAddress )
{ {
uint32_t i ; uint32_t i ;
uint32_t j ; uint32_t j ;
uint32_t dwLastLineStart ; uint32_t dwLastLineStart ;
uint8_t* pucTmp ; uint8_t* pucTmp ;
for ( i=0 ; i < (dwSize / 16) ; i++ ) for ( i=0 ; i < (dwSize / 16) ; i++ )
{ {
printf( "0x%08X: ", (unsigned int)(dwAddress + (i*16)) ) ; printf( "0x%08X: ", (unsigned int)(dwAddress + (i*16)) ) ;
pucTmp = (uint8_t*)&pucBuffer[i*16] ; pucTmp = (uint8_t*)&pucBuffer[i*16] ;
for ( j=0 ; j < 4 ; j++ ) for ( j=0 ; j < 4 ; j++ )
{ {
printf( "%02X%02X%02X%02X ", pucTmp[0], pucTmp[1], pucTmp[2], pucTmp[3] ) ; printf( "%02X%02X%02X%02X ", pucTmp[0], pucTmp[1], pucTmp[2], pucTmp[3] ) ;
pucTmp += 4 ; pucTmp += 4 ;
} }
pucTmp=(uint8_t*)&pucBuffer[i*16] ; pucTmp=(uint8_t*)&pucBuffer[i*16] ;
for ( j=0 ; j < 16 ; j++ ) for ( j=0 ; j < 16 ; j++ )
{ {
UART_PutChar( *pucTmp++ ) ; UART_PutChar( *pucTmp++ ) ;
} }
printf( "\n\r" ) ; printf( "\n\r" ) ;
} }
if ( (dwSize%16) != 0 ) if ( (dwSize%16) != 0 )
{ {
dwLastLineStart=dwSize - (dwSize%16) ; dwLastLineStart=dwSize - (dwSize%16) ;
printf( "0x%08X: ", (unsigned int)(dwAddress + dwLastLineStart) ) ; printf( "0x%08X: ", (unsigned int)(dwAddress + dwLastLineStart) ) ;
for ( j=dwLastLineStart ; j < dwLastLineStart+16 ; j++ ) for ( j=dwLastLineStart ; j < dwLastLineStart+16 ; j++ )
{ {
if ( (j!=dwLastLineStart) && (j%4 == 0) ) if ( (j!=dwLastLineStart) && (j%4 == 0) )
{ {
printf( " " ) ; printf( " " ) ;
} }
if ( j < dwSize ) if ( j < dwSize )
{ {
printf( "%02X", pucBuffer[j] ) ; printf( "%02X", pucBuffer[j] ) ;
} }
else else
{ {
printf(" ") ; printf(" ") ;
} }
} }
printf( " " ) ; printf( " " ) ;
for ( j=dwLastLineStart ; j < dwSize ; j++ ) for ( j=dwLastLineStart ; j < dwSize ; j++ )
{ {
UART_PutChar( pucBuffer[j] ) ; UART_PutChar( pucBuffer[j] ) ;
} }
printf( "\n\r" ) ; printf( "\n\r" ) ;
} }
} }
/** /**
* Reads an integer * Reads an integer
* *
* \param pdwValue Pointer to the uint32_t variable to contain the input value. * \param pdwValue Pointer to the uint32_t variable to contain the input value.
*/ */
extern uint32_t UART_GetInteger( uint32_t* pdwValue ) extern uint32_t UART_GetInteger( uint32_t* pdwValue )
{ {
uint8_t ucKey ; uint8_t ucKey ;
uint8_t ucNbNb=0 ; uint8_t ucNbNb=0 ;
uint32_t dwValue=0 ; uint32_t dwValue=0 ;
while ( 1 ) while ( 1 )
{ {
ucKey=UART_GetChar() ; ucKey=UART_GetChar() ;
UART_PutChar( ucKey ) ; UART_PutChar( ucKey ) ;
if ( ucKey >= '0' && ucKey <= '9' ) if ( ucKey >= '0' && ucKey <= '9' )
{ {
dwValue = (dwValue * 10) + (ucKey - '0'); dwValue = (dwValue * 10) + (ucKey - '0');
ucNbNb++ ; ucNbNb++ ;
} }
else else
{ {
if ( ucKey == 0x0D || ucKey == ' ' ) if ( ucKey == 0x0D || ucKey == ' ' )
{ {
if ( ucNbNb == 0 ) if ( ucNbNb == 0 )
{ {
printf( "\n\rWrite a number and press ENTER or SPACE!\n\r" ) ; printf( "\n\rWrite a number and press ENTER or SPACE!\n\r" ) ;
return 0 ; return 0 ;
} }
else else
{ {
printf( "\n\r" ) ; printf( "\n\r" ) ;
*pdwValue=dwValue ; *pdwValue=dwValue ;
return 1 ; return 1 ;
} }
} }
else else
{ {
printf( "\n\r'%c' not a number!\n\r", ucKey ) ; printf( "\n\r'%c' not a number!\n\r", ucKey ) ;
return 0 ; return 0 ;
} }
} }
WDT_Restart(WDT); WDT_Restart(WDT);
} }
} }
/** /**
* Reads an integer and check the value * Reads an integer and check the value
* *
* \param pdwValue Pointer to the uint32_t variable to contain the input value. * \param pdwValue Pointer to the uint32_t variable to contain the input value.
* \param dwMin Minimum value * \param dwMin Minimum value
* \param dwMax Maximum value * \param dwMax Maximum value
*/ */
extern uint32_t UART_GetIntegerMinMax( uint32_t* pdwValue, uint32_t dwMin, uint32_t dwMax ) extern uint32_t UART_GetIntegerMinMax( uint32_t* pdwValue, uint32_t dwMin, uint32_t dwMax )
{ {
uint32_t dwValue=0 ; uint32_t dwValue=0 ;
if ( UART_GetInteger( &dwValue ) == 0 ) if ( UART_GetInteger( &dwValue ) == 0 )
{ {
return 0 ; return 0 ;
} }
if ( dwValue < dwMin || dwValue > dwMax ) if ( dwValue < dwMin || dwValue > dwMax )
{ {
printf( "\n\rThe number have to be between %d and %d\n\r", (int)dwMin, (int)dwMax ) ; printf( "\n\rThe number have to be between %d and %d\n\r", (int)dwMin, (int)dwMax ) ;
return 0 ; return 0 ;
} }
printf( "\n\r" ) ; printf( "\n\r" ) ;
*pdwValue = dwValue ; *pdwValue = dwValue ;
return 1 ; return 1 ;
} }
/** /**
* Reads an hexadecimal number * Reads an hexadecimal number
* *
* \param pdwValue Pointer to the uint32_t variable to contain the input value. * \param pdwValue Pointer to the uint32_t variable to contain the input value.
*/ */
extern uint32_t UART_GetHexa32( uint32_t* pdwValue ) extern uint32_t UART_GetHexa32( uint32_t* pdwValue )
{ {
uint8_t ucKey ; uint8_t ucKey ;
uint32_t dw = 0 ; uint32_t dw = 0 ;
uint32_t dwValue = 0 ; uint32_t dwValue = 0 ;
for ( dw=0 ; dw < 8 ; dw++ ) for ( dw=0 ; dw < 8 ; dw++ )
{ {
ucKey = UART_GetChar() ; ucKey = UART_GetChar() ;
UART_PutChar( ucKey ) ; UART_PutChar( ucKey ) ;
if ( ucKey >= '0' && ucKey <= '9' ) if ( ucKey >= '0' && ucKey <= '9' )
{ {
dwValue = (dwValue * 16) + (ucKey - '0') ; dwValue = (dwValue * 16) + (ucKey - '0') ;
} }
else else
{ {
if ( ucKey >= 'A' && ucKey <= 'F' ) if ( ucKey >= 'A' && ucKey <= 'F' )
{ {
dwValue = (dwValue * 16) + (ucKey - 'A' + 10) ; dwValue = (dwValue * 16) + (ucKey - 'A' + 10) ;
} }
else else
{ {
if ( ucKey >= 'a' && ucKey <= 'f' ) if ( ucKey >= 'a' && ucKey <= 'f' )
{ {
dwValue = (dwValue * 16) + (ucKey - 'a' + 10) ; dwValue = (dwValue * 16) + (ucKey - 'a' + 10) ;
} }
else else
{ {
printf( "\n\rIt is not a hexa character!\n\r" ) ; printf( "\n\rIt is not a hexa character!\n\r" ) ;
return 0 ; return 0 ;
} }
} }
} }
} }
printf("\n\r" ) ; printf("\n\r" ) ;
*pdwValue = dwValue ; *pdwValue = dwValue ;
return 1 ; return 1 ;
} }
#if defined __ICCARM__ /* IAR Ewarm 5.41+ */ #if defined __ICCARM__ /* IAR Ewarm 5.41+ */
/** /**
* \brief Outputs a character on the UART. * \brief Outputs a character on the UART.
* *
* \param c Character to output. * \param c Character to output.
* *
* \return The character that was output. * \return The character that was output.
*/ */
extern WEAK signed int putchar( signed int c ) extern WEAK signed int putchar( signed int c )
{ {
UART_PutChar( c ) ; UART_PutChar( c ) ;
return c ; return c ;
} }
#endif // defined __ICCARM__ #endif // defined __ICCARM__