Updated AVR32 demos and added AVR32 UC3B demo.

This commit is contained in:
Richard Barry 2007-07-27 07:59:50 +00:00
parent 45e7e5ac55
commit 94c94d3c0e
164 changed files with 21458 additions and 3994 deletions

File diff suppressed because it is too large Load diff

View file

@ -1,20 +1,18 @@
/* This header file is part of the ATMEL FREERTOS-0.9.0 Release */
/*This file has been prepared for Doxygen automatic documentation generation.*/
/*This file is prepared for Doxygen automatic documentation generation.*/
/*! \file *********************************************************************
*
* \brief Flash Controller driver .h file.
* \brief FLASHC driver for AVR32 UC3.
*
* This file defines a useful set of functions for the flash controller
* on AVR32A devices.
* AVR32 Flash Controller driver module.
*
* - Compiler: IAR EWAVR32 and GNU GCC for AVR32
* - Supported devices: All AVR32A devices.
* - Supported devices: All AVR32 devices with a FLASHC module can be used.
* - AppNote:
*
* \author Atmel Corporation: http://www.atmel.com \n
* Support email: avr32@atmel.com
* Support and FAQ: http://support.atmel.no/
*
*****************************************************************************/
******************************************************************************/
/* Copyright (c) 2007, Atmel Corporation All rights reserved.
*
@ -47,147 +45,841 @@
#ifndef _FLASHC_H_
#define _FLASHC_H_
#if __GNUC__
# include <avr32/io.h>
#elif __ICCAVR32__
# include <avr32/iouc3a0512.h>
# include <avr32/uc3a0512.h>
#else
# error Unknown compiler
#endif
#include <avr32/io.h>
#include <stddef.h>
#include "compiler.h"
/*! Value returned by function when it completed successfully */
#define FLASHC_SUCCESS 0
/*! Value returned by function when it was unable to complete successfully
for some unspecified reason */
#define FLASHC_FAILURE -1
/*! Value returned by function when the input paramters are out of range */
#define FLASHC_INVALID_INPUT 1
//! Number of flash regions defined by the FLASHC.
#define AVR32_FLASHC_REGIONS (AVR32_FLASHC_FLASH_SIZE /\
(AVR32_FLASHC_PAGES_PR_REGION * AVR32_FLASHC_PAGE_SIZE))
/*! Get Flash size */
#if __GNUC__
__attribute__((__always_inline__))
#endif
extern __inline__ unsigned int flashc_get_flash_size(void)
{
static const unsigned int FLASHC_SIZE[1 << AVR32_FLASHC_FSR_FSZ_SIZE] =
{
32 << 10,
64 << 10,
128 << 10,
256 << 10,
384 << 10,
512 << 10,
768 << 10,
1024 << 10
};
return FLASHC_SIZE[Rd_bitfield(AVR32_FLASHC.fsr, AVR32_FLASHC_FSR_FSZ_MASK)];
}
/*! Get Flash page count */
#if __GNUC__
__attribute__((__always_inline__))
#endif
extern __inline__ unsigned int flashc_get_page_count(void)
{
return flashc_get_flash_size() / AVR32_FLASHC_PAGE_SIZE;
}
/*! Get Flash page count per region */
#if __GNUC__
__attribute__((__always_inline__))
#endif
extern __inline__ unsigned int flashc_get_page_count_per_region(void)
{
return flashc_get_page_count() / 16;
}
/*! Wait flash ready status, the application must wait before running a new command.
* Warning: Flash status register (FCR) is read, and error status may be automatically
* cleared when reading FCR.
/*! \name Flash Properties
*/
#if __GNUC__
__attribute__((__always_inline__))
#endif
extern __inline__ void flashc_busy_wait(void)
{
while (!Tst_bits(AVR32_FLASHC.fsr, AVR32_FLASHC_FSR_FRDY_MASK));
}
//! @{
/*! Check if security bit is active.
* \warning: Flash status register (FCR) is read, and error status may be automatically
* cleared when reading FCR.
/*! \brief Gets the size of the whole flash array.
*
* \return The size of the whole flash array in bytes.
*/
#if __GNUC__
__attribute__((__always_inline__))
#endif
extern __inline__ Bool flashc_is_security_active(void)
{
return Tst_bits(AVR32_FLASHC.fsr, AVR32_FLASHC_FSR_SECURITY_MASK);
}
extern unsigned int flashc_get_flash_size(void);
/*! \brief Memcopy function
* \param *s1 destination
* \param *s2 source
* \param n number of words to copy
/*! \brief Gets the total number of pages in the flash array.
*
* \return The total number of pages in the flash array.
*/
extern U32 *flashc_memcpy(U32 *s1, const U32 *s2, const U32 n);
extern unsigned int flashc_get_page_count(void);
/*! \brief Set number of wait state
* \param ws 0 if for no-wait state, for 1 wait-state
* \return FLASHC_SUCCESS, FLASHC_INVALID_INPUT or FLASHC_FAILURE
/*! \brief Gets the number of pages in each flash region.
*
* \return The number of pages in each flash region.
*/
extern int flashc_set_wait_state(U16 ws);
extern unsigned int flashc_get_page_count_per_region(void);
/*! \brief Page write number n. Assuming page bubuffer is already loaded.
* \param n Page number
/*! \brief Gets the region number of a page.
*
* \param page_number The page number:
* \arg \c 0 to <tt>(flashc_get_page_count() - 1)</tt>: a page number within
* the flash array;
* \arg <tt>< 0</tt>: the current page number.
*
* \return The region number of the specified page.
*/
extern void flashc_page_write_n(U16 n);
extern unsigned int flashc_get_page_region(int page_number);
/*! \brief Page write
* Assuming the page address is already loaded
/*! \brief Gets the number of the first page of a region.
*
* \param region The region number: \c 0 to <tt>(AVR32_FLASHC_REGIONS - 1)</tt>.
*
* \return The number of the first page of the specified region.
*/
extern void flashc_page_write(U16 page_n);
extern unsigned int flashc_get_region_first_page_number(unsigned int region);
/*! \brief Clear page buffer
//! @}
/*! \name FLASHC Control
*/
extern void flashc_clear_page_buffer(void);
//! @{
/*! \brief Page erase
* Assuming the page address is already loaded
/*! \brief Gets the number of wait states of flash read accesses.
*
* \return The number of wait states of flash read accesses.
*/
extern void flashc_erase_page(U16 page_n);
extern unsigned int flashc_get_wait_state(void);
/*! \brief Erase all Pages
/*! \brief Sets the number of wait states of flash read accesses.
*
* \param wait_state The number of wait states of flash read accesses: \c 0 to
* \c 1.
*/
extern void flashc_set_wait_state(unsigned int wait_state);
/*! \brief Tells whether the Flash Ready interrupt is enabled.
*
* \return Whether the Flash Ready interrupt is enabled.
*/
extern Bool flashc_is_ready_int_enabled(void);
/*! \brief Enables or disables the Flash Ready interrupt.
*
* \param enable Whether to enable the Flash Ready interrupt: \c TRUE or
* \c FALSE.
*/
extern void flashc_enable_ready_int(Bool enable);
/*! \brief Tells whether the Lock Error interrupt is enabled.
*
* \return Whether the Lock Error interrupt is enabled.
*/
extern Bool flashc_is_lock_error_int_enabled(void);
/*! \brief Enables or disables the Lock Error interrupt.
*
* \param enable Whether to enable the Lock Error interrupt: \c TRUE or
* \c FALSE.
*/
extern void flashc_enable_lock_error_int(Bool enable);
/*! \brief Tells whether the Programming Error interrupt is enabled.
*
* \return Whether the Programming Error interrupt is enabled.
*/
extern Bool flashc_is_prog_error_int_enabled(void);
/*! \brief Enables or disables the Programming Error interrupt.
*
* \param enable Whether to enable the Programming Error interrupt: \c TRUE or
* \c FALSE.
*/
extern void flashc_enable_prog_error_int(Bool enable);
//! @}
/*! \name FLASHC Status
*/
//! @{
/*! \brief Tells whether the FLASHC is ready to run a new command.
*
* \return Whether the FLASHC is ready to run a new command.
*/
extern Bool flashc_is_ready(void);
/*! \brief Waits actively until the FLASHC is ready to run a new command.
*
* This is the default function assigned to \ref flashc_wait_until_ready.
*/
extern void flashc_default_wait_until_ready(void);
//! Pointer to the function used by the driver when it needs to wait until the
//! FLASHC is ready to run a new command.
//! The default function is \ref flashc_default_wait_until_ready.
//! The user may change this pointer to use another implementation.
extern void (*volatile flashc_wait_until_ready)(void);
/*! \brief Tells whether a Lock Error has occurred during the last function
* called that issued one or more FLASHC commands.
*
* \return Whether a Lock Error has occurred during the last function called
* that issued one or more FLASHC commands.
*/
extern Bool flashc_is_lock_error(void);
/*! \brief Tells whether a Programming Error has occurred during the last
* function called that issued one or more FLASHC commands.
*
* \return Whether a Programming Error has occurred during the last function
* called that issued one or more FLASHC commands.
*/
extern Bool flashc_is_programming_error(void);
//! @}
/*! \name FLASHC Command Control
*/
//! @{
/*! \brief Gets the last issued FLASHC command.
*
* \return The last issued FLASHC command.
*/
extern unsigned int flashc_get_command(void);
/*! \brief Gets the current FLASHC page number.
*
* \return The current FLASHC page number.
*/
extern unsigned int flashc_get_page_number(void);
/*! \brief Issues a FLASHC command.
*
* \param command The command: \c AVR32_FLASHC_FCMD_CMD_x.
* \param page_number The page number to apply the command to:
* \arg \c 0 to <tt>(flashc_get_page_count() - 1)</tt>: a page number within
* the flash array;
* \arg <tt>< 0</tt>: use this to apply the command to the current page number
* or if the command does not apply to any page number;
* \arg this argument may have other meanings according to the command. See
* the FLASHC chapter of the MCU datasheet.
*
* \warning A Lock Error is issued if the command violates the protection
* mechanism.
*
* \warning A Programming Error is issued if the command is invalid.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern void flashc_issue_command(unsigned int command, int page_number);
//! @}
/*! \name FLASHC Global Commands
*/
//! @{
/*! \brief Issues a No Operation command to the FLASHC.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern void flashc_no_operation(void);
/*! \brief Issues an Erase All command to the FLASHC.
*
* This command erases all bits in the flash array, the general-purpose fuse
* bits and the Security bit. The User page is not erased.
*
* This command also ensures that all volatile memories, such as register file
* and RAMs, are erased before the Security bit is erased, i.e. deactivated.
*
* \warning A Lock Error is issued if at least one region is locked or the
* bootloader protection is active.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*
* \note An erase operation can only set bits.
*/
extern void flashc_erase_all(void);
/*! \brief Erase a page and check if erase is OK
*/
extern int flashc_erase_page_and_check(U16 page_n);
//! @}
/*! \brief Page load and write
* \warning Dest is a FLASH address at a page boundary
* (assuming the page is already erased)
*/
extern void flashc_page_copy_write(U32 *Dest, const U32 *Src) ;
/*! \brief This function allows to write up to 65535 bytes in the flash memory.
* This function manages alignement issue (byte and page alignements).
/*! \name FLASHC Protection Mechanisms
*/
//! @{
/*! \brief Tells whether the Security bit is active.
*
* \param *src Address of data to write.
* \param dst Start address in flash memory where write data
* \param n Number of word to write
* \return FLASHC_SUCCESS or FLASHC_FAILURE
* \return Whether the Security bit is active.
*/
extern int flash_wr_block(U32 * src, U32 dst, U32 n);
extern Bool flashc_is_security_bit_active(void);
/*! \brief Activates the Security bit.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern void flashc_activate_security_bit(void);
/*! \brief Gets the bootloader protected size.
*
* \return The bootloader protected size in bytes.
*/
extern unsigned int flashc_get_bootloader_protected_size(void);
/*! \brief Sets the bootloader protected size.
*
* \param bootprot_size The wanted bootloader protected size in bytes. If this
* size is not supported, the actual size will be the
* nearest greater available size or the maximal possible
* size if the requested size is too large.
*
* \return The actual bootloader protected size in bytes.
*
* \warning A Lock Error is issued if the Security bit is active.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern unsigned int flashc_set_bootloader_protected_size(unsigned int bootprot_size);
/*! \brief Tells whether external privileged fetch is locked.
*
* \return Whether external privileged fetch is locked.
*/
extern Bool flashc_is_external_privileged_fetch_locked(void);
/*! \brief Locks or unlocks external privileged fetch.
*
* \param lock Whether to lock external privileged fetch: \c TRUE or \c FALSE.
*
* \warning A Lock Error is issued if the Security bit is active.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern void flashc_lock_external_privileged_fetch(Bool lock);
/*! \brief Tells whether the region of a page is locked.
*
* \param page_number The page number:
* \arg \c 0 to <tt>(flashc_get_page_count() - 1)</tt>: a page number within
* the flash array;
* \arg <tt>< 0</tt>: the current page number.
*
* \return Whether the region of the specified page is locked.
*/
extern Bool flashc_is_page_region_locked(int page_number);
/*! \brief Tells whether a region is locked.
*
* \param region The region number: \c 0 to <tt>(AVR32_FLASHC_REGIONS - 1)</tt>.
*
* \return Whether the specified region is locked.
*/
extern Bool flashc_is_region_locked(unsigned int region);
/*! \brief Locks or unlocks the region of a page.
*
* \param page_number The page number:
* \arg \c 0 to <tt>(flashc_get_page_count() - 1)</tt>: a page number within
* the flash array;
* \arg <tt>< 0</tt>: the current page number.
* \param lock Whether to lock the region of the specified page: \c TRUE or
* \c FALSE.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern void flashc_lock_page_region(int page_number, Bool lock);
/*! \brief Locks or unlocks a region.
*
* \param region The region number: \c 0 to <tt>(AVR32_FLASHC_REGIONS - 1)</tt>.
* \param lock Whether to lock the specified region: \c TRUE or \c FALSE.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern void flashc_lock_region(unsigned int region, Bool lock);
/*! \brief Locks or unlocks all regions.
*
* \param lock Whether to lock the regions: \c TRUE or \c FALSE.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern void flashc_lock_all_regions(Bool lock);
//! @}
#endif /* #ifndef _FLASHC_H_*/
/*! \name Access to General-Purpose Fuses
*/
//! @{
/*! \brief Reads a general-purpose fuse bit.
*
* \param gp_fuse_bit The general-purpose fuse bit: \c 0 to \c 31.
*
* \return The value of the specified general-purpose fuse bit.
*/
extern Bool flashc_read_gp_fuse_bit(unsigned int gp_fuse_bit);
/*! \brief Reads a general-purpose fuse bit-field.
*
* \param pos The bit-position of the general-purpose fuse bit-field: \c 0 to
* \c 31.
* \param width The bit-width of the general-purpose fuse bit-field: \c 0 to
* \c 32.
*
* \return The value of the specified general-purpose fuse bit-field.
*/
extern U32 flashc_read_gp_fuse_bitfield(unsigned int pos, unsigned int width);
/*! \brief Reads a general-purpose fuse byte.
*
* \param gp_fuse_byte The general-purpose fuse byte: \c 0 to \c 3.
*
* \return The value of the specified general-purpose fuse byte.
*/
extern U8 flashc_read_gp_fuse_byte(unsigned int gp_fuse_byte);
/*! \brief Reads all general-purpose fuses.
*
* \return The value of all general-purpose fuses as a word.
*/
extern U32 flashc_read_all_gp_fuses(void);
/*! \brief Erases a general-purpose fuse bit.
*
* \param gp_fuse_bit The general-purpose fuse bit: \c 0 to \c 31.
* \param check Whether to check erase: \c TRUE or \c FALSE.
*
* \return Whether the erase succeeded or always \c TRUE if erase check was not
* requested.
*
* \warning A Lock Error is issued if the Security bit is active and the command
* is applied to BOOTPROT or EPFL fuses.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*
* \note An erase operation can only set bits.
*/
extern Bool flashc_erase_gp_fuse_bit(unsigned int gp_fuse_bit, Bool check);
/*! \brief Erases a general-purpose fuse bit-field.
*
* \param pos The bit-position of the general-purpose fuse bit-field: \c 0 to
* \c 31.
* \param width The bit-width of the general-purpose fuse bit-field: \c 0 to
* \c 32.
* \param check Whether to check erase: \c TRUE or \c FALSE.
*
* \return Whether the erase succeeded or always \c TRUE if erase check was not
* requested.
*
* \warning A Lock Error is issued if the Security bit is active and the command
* is applied to BOOTPROT or EPFL fuses.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*
* \note An erase operation can only set bits.
*/
extern Bool flashc_erase_gp_fuse_bitfield(unsigned int pos, unsigned int width, Bool check);
/*! \brief Erases a general-purpose fuse byte.
*
* \param gp_fuse_byte The general-purpose fuse byte: \c 0 to \c 3.
* \param check Whether to check erase: \c TRUE or \c FALSE.
*
* \return Whether the erase succeeded or always \c TRUE if erase check was not
* requested.
*
* \warning A Lock Error is issued if the Security bit is active.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*
* \note An erase operation can only set bits.
*/
extern Bool flashc_erase_gp_fuse_byte(unsigned int gp_fuse_byte, Bool check);
/*! \brief Erases all general-purpose fuses.
*
* \param check Whether to check erase: \c TRUE or \c FALSE.
*
* \return Whether the erase succeeded or always \c TRUE if erase check was not
* requested.
*
* \warning A Lock Error is issued if the Security bit is active.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*
* \note An erase operation can only set bits.
*/
extern Bool flashc_erase_all_gp_fuses(Bool check);
/*! \brief Writes a general-purpose fuse bit.
*
* \param gp_fuse_bit The general-purpose fuse bit: \c 0 to \c 31.
* \param value The value of the specified general-purpose fuse bit.
*
* \warning A Lock Error is issued if the Security bit is active and the command
* is applied to BOOTPROT or EPFL fuses.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*
* \note A write operation can only clear bits.
*/
extern void flashc_write_gp_fuse_bit(unsigned int gp_fuse_bit, Bool value);
/*! \brief Writes a general-purpose fuse bit-field.
*
* \param pos The bit-position of the general-purpose fuse bit-field: \c 0 to
* \c 31.
* \param width The bit-width of the general-purpose fuse bit-field: \c 0 to
* \c 32.
* \param value The value of the specified general-purpose fuse bit-field.
*
* \warning A Lock Error is issued if the Security bit is active and the command
* is applied to BOOTPROT or EPFL fuses.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*
* \note A write operation can only clear bits.
*/
extern void flashc_write_gp_fuse_bitfield(unsigned int pos, unsigned int width, U32 value);
/*! \brief Writes a general-purpose fuse byte.
*
* \param gp_fuse_byte The general-purpose fuse byte: \c 0 to \c 3.
* \param value The value of the specified general-purpose fuse byte.
*
* \warning A Lock Error is issued if the Security bit is active.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*
* \note A write operation can only clear bits.
*/
extern void flashc_write_gp_fuse_byte(unsigned int gp_fuse_byte, U8 value);
/*! \brief Writes all general-purpose fuses.
*
* \param value The value of all general-purpose fuses as a word.
*
* \warning A Lock Error is issued if the Security bit is active.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*
* \note A write operation can only clear bits.
*/
extern void flashc_write_all_gp_fuses(U32 value);
/*! \brief Sets a general-purpose fuse bit with the appropriate erase and write
* operations.
*
* \param gp_fuse_bit The general-purpose fuse bit: \c 0 to \c 31.
* \param value The value of the specified general-purpose fuse bit.
*
* \warning A Lock Error is issued if the Security bit is active and the command
* is applied to BOOTPROT or EPFL fuses.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern void flashc_set_gp_fuse_bit(unsigned int gp_fuse_bit, Bool value);
/*! \brief Sets a general-purpose fuse bit-field with the appropriate erase and
* write operations.
*
* \param pos The bit-position of the general-purpose fuse bit-field: \c 0 to
* \c 31.
* \param width The bit-width of the general-purpose fuse bit-field: \c 0 to
* \c 32.
* \param value The value of the specified general-purpose fuse bit-field.
*
* \warning A Lock Error is issued if the Security bit is active and the command
* is applied to BOOTPROT or EPFL fuses.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern void flashc_set_gp_fuse_bitfield(unsigned int pos, unsigned int width, U32 value);
/*! \brief Sets a general-purpose fuse byte with the appropriate erase and write
* operations.
*
* \param gp_fuse_byte The general-purpose fuse byte: \c 0 to \c 3.
* \param value The value of the specified general-purpose fuse byte.
*
* \warning A Lock Error is issued if the Security bit is active.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern void flashc_set_gp_fuse_byte(unsigned int gp_fuse_byte, U8 value);
/*! \brief Sets all general-purpose fuses with the appropriate erase and write
* operations.
*
* \param value The value of all general-purpose fuses as a word.
*
* \warning A Lock Error is issued if the Security bit is active.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern void flashc_set_all_gp_fuses(U32 value);
//! @}
/*! \name Access to Flash Pages
*/
//! @{
/*! \brief Clears the page buffer.
*
* This command resets all bits in the page buffer to one. Write accesses to the
* page buffer can only change page buffer bits from one to zero.
*
* \warning The page buffer is not automatically reset after a page write.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern void flashc_clear_page_buffer(void);
/*! \brief Tells whether the page to which the last Quick Page Read command was
* applied was erased.
*
* \return Whether the page to which the last Quick Page Read command was
* applied was erased.
*/
extern Bool flashc_is_page_erased(void);
/*! \brief Applies the Quick Page Read command to a page.
*
* \param page_number The page number:
* \arg \c 0 to <tt>(flashc_get_page_count() - 1)</tt>: a page number within
* the flash array;
* \arg <tt>< 0</tt>: the current page number.
*
* \return Whether the specified page is erased.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern Bool flashc_quick_page_read(int page_number);
/*! \brief Erases a page.
*
* \param page_number The page number:
* \arg \c 0 to <tt>(flashc_get_page_count() - 1)</tt>: a page number within
* the flash array;
* \arg <tt>< 0</tt>: the current page number.
* \param check Whether to check erase: \c TRUE or \c FALSE.
*
* \return Whether the erase succeeded or always \c TRUE if erase check was not
* requested.
*
* \warning A Lock Error is issued if the command is applied to a page belonging
* to a locked region or to the bootloader protected area.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*
* \note An erase operation can only set bits.
*/
extern Bool flashc_erase_page(int page_number, Bool check);
/*! \brief Erases all pages within the flash array.
*
* \param check Whether to check erase: \c TRUE or \c FALSE.
*
* \return Whether the erase succeeded or always \c TRUE if erase check was not
* requested.
*
* \warning A Lock Error is issued if at least one region is locked or the
* bootloader protection is active.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*
* \note An erase operation can only set bits.
*/
extern Bool flashc_erase_all_pages(Bool check);
/*! \brief Writes a page from the page buffer.
*
* \param page_number The page number:
* \arg \c 0 to <tt>(flashc_get_page_count() - 1)</tt>: a page number within
* the flash array;
* \arg <tt>< 0</tt>: the current page number.
*
* \warning A Lock Error is issued if the command is applied to a page belonging
* to a locked region or to the bootloader protected area.
*
* \warning The page buffer is not automatically reset after a page write.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*
* \note A write operation can only clear bits.
*/
extern void flashc_write_page(int page_number);
/*! \brief Checks whether the User page is erased.
*
* \return Whether the User page is erased.
*/
extern Bool flashc_check_user_page_erase(void);
/*! \brief Erases the User page.
*
* \param check Whether to check erase: \c TRUE or \c FALSE.
*
* \return Whether the erase succeeded or always \c TRUE if erase check was not
* requested.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*
* \note An erase operation can only set bits.
*/
extern Bool flashc_erase_user_page(Bool check);
/*! \brief Writes the User page from the page buffer.
*
* \warning The page buffer is not automatically reset after a page write.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*
* \note A write operation can only clear bits.
*/
extern void flashc_write_user_page(void);
/*! \brief Copies \a nbytes bytes to the flash destination pointed to by \a dst
* from the repeated \a src source byte.
*
* The destination areas that are not within the flash array or the User page
* are ignored.
*
* All pointer and size alignments are supported.
*
* \param dst Pointer to flash destination.
* \param src Source byte.
* \param nbytes Number of bytes to set.
* \param erase Whether to erase before writing: \c TRUE or \c FALSE.
*
* \return The value of \a dst.
*
* \warning A Lock Error is issued if the command is applied to pages belonging
* to a locked region or to the bootloader protected area.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern volatile void *flashc_memset8(volatile void *dst, U8 src, size_t nbytes, Bool erase);
/*! \brief Copies \a nbytes bytes to the flash destination pointed to by \a dst
* from the repeated \a src big-endian source half-word.
*
* The destination areas that are not within the flash array or the User page
* are ignored.
*
* All pointer and size alignments are supported.
*
* \param dst Pointer to flash destination.
* \param src Source half-word.
* \param nbytes Number of bytes to set.
* \param erase Whether to erase before writing: \c TRUE or \c FALSE.
*
* \return The value of \a dst.
*
* \warning A Lock Error is issued if the command is applied to pages belonging
* to a locked region or to the bootloader protected area.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern volatile void *flashc_memset16(volatile void *dst, U16 src, size_t nbytes, Bool erase);
/*! \brief Copies \a nbytes bytes to the flash destination pointed to by \a dst
* from the repeated \a src big-endian source word.
*
* The destination areas that are not within the flash array or the User page
* are ignored.
*
* All pointer and size alignments are supported.
*
* \param dst Pointer to flash destination.
* \param src Source word.
* \param nbytes Number of bytes to set.
* \param erase Whether to erase before writing: \c TRUE or \c FALSE.
*
* \return The value of \a dst.
*
* \warning A Lock Error is issued if the command is applied to pages belonging
* to a locked region or to the bootloader protected area.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern volatile void *flashc_memset32(volatile void *dst, U32 src, size_t nbytes, Bool erase);
/*! \brief Copies \a nbytes bytes to the flash destination pointed to by \a dst
* from the repeated \a src big-endian source double-word.
*
* The destination areas that are not within the flash array or the User page
* are ignored.
*
* All pointer and size alignments are supported.
*
* \param dst Pointer to flash destination.
* \param src Source double-word.
* \param nbytes Number of bytes to set.
* \param erase Whether to erase before writing: \c TRUE or \c FALSE.
*
* \return The value of \a dst.
*
* \warning A Lock Error is issued if the command is applied to pages belonging
* to a locked region or to the bootloader protected area.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern volatile void *flashc_memset64(volatile void *dst, U64 src, size_t nbytes, Bool erase);
/*! \brief Copies \a nbytes bytes to the flash destination pointed to by \a dst
* from the repeated \a src big-endian source pattern.
*
* The destination areas that are not within the flash array or the User page
* are ignored.
*
* All pointer and size alignments are supported.
*
* \param dst Pointer to flash destination.
* \param src Source double-word.
* \param src_width \a src width in bits: 8, 16, 32 or 64.
* \param nbytes Number of bytes to set.
* \param erase Whether to erase before writing: \c TRUE or \c FALSE.
*
* \return The value of \a dst.
*
* \warning A Lock Error is issued if the command is applied to pages belonging
* to a locked region or to the bootloader protected area.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
#define flashc_memset(dst, src, src_width, nbytes, erase) \
TPASTE2(flashc_memset, src_width)((dst), (src), (nbytes), (erase))
/*! \brief Copies \a nbytes bytes to the flash destination pointed to by \a dst
* from the source pointed to by \a src.
*
* The destination areas that are not within the flash array or the User page
* are ignored.
*
* All pointer and size alignments are supported.
*
* \param dst Pointer to flash destination.
* \param src Pointer to source data.
* \param nbytes Number of bytes to copy.
* \param erase Whether to erase before writing: \c TRUE or \c FALSE.
*
* \return The value of \a dst.
*
* \warning If copying takes place between areas that overlap, the behavior is
* undefined.
*
* \warning A Lock Error is issued if the command is applied to pages belonging
* to a locked region or to the bootloader protected area.
*
* \note The FLASHC error status returned by \ref flashc_is_lock_error and
* \ref flashc_is_programming_error is updated.
*/
extern volatile void *flashc_memcpy(volatile void *dst, const void *src, size_t nbytes, Bool erase);
//! @}
#endif // _FLASHC_H_

View file

@ -6,11 +6,11 @@
* This file defines a useful set of functions for the GPIO.
*
* - Compiler: IAR EWAVR32 and GNU GCC for AVR32
* - Supported devices: All AVR32 devices with a PWM module can be used.
* - Supported devices: All AVR32 devices with a GPIO module can be used.
* - AppNote:
*
* \author Atmel Corporation: http://www.atmel.com \n
* Support email: avr32@atmel.com
* Support and FAQ: http://support.atmel.no/
*
*****************************************************************************/

View file

@ -10,7 +10,7 @@
* - AppNote:
*
* \author Atmel Corporation: http://www.atmel.com \n
* Support email: avr32@atmel.com
* Support and FAQ: http://support.atmel.no/
*
*****************************************************************************/
@ -45,13 +45,7 @@
#ifndef _GPIO_H_
#define _GPIO_H_
#if __GNUC__
# include <avr32/io.h>
#elif __ICCAVR32__
# include <avr32/iouc3a0512.h>
#else
# error Unknown compiler
#endif
#include <avr32/io.h>
/*! \name Return Values of the GPIO API
@ -90,8 +84,16 @@ extern int gpio_enable_module(const gpio_map_t gpiomap, unsigned int size);
/*! \brief Enables a specific module mode for a pin.
*
* \param pin The pin number.
* \param function The pin function.
* \param pin The pin number.\n
* Refer to the product header file `uc3x.h' (where x is the part
* number; e.g. x = a0512) for module pins. E.g., to enable a PWM
* channel output, the pin number can be AVR32_PWM_PWM_3_PIN for PWM
* channel 3.
* \param function The pin function.\n
* Refer to the product header file `uc3x.h' (where x is the
* part number; e.g. x = a0512) for module pin functions. E.g.,
* to enable a PWM channel output, the pin function can be
* AVR32_PWM_PWM_3_FUNCTION for PWM channel 3.
*
* \return \ref GPIO_SUCCESS or \ref GPIO_INVALID_ARGUMENT.
*/
@ -106,7 +108,12 @@ extern void gpio_enable_gpio(const gpio_map_t gpiomap, unsigned int size);
/*! \brief Enables the GPIO mode of a pin.
*
* \param pin The pin number.
* \param pin The pin number.\n
* Refer to the product header file `uc3x.h' (where x is the part
* number; e.g. x = a0512) for pin definitions. E.g., to enable the
* GPIO mode of PX21, AVR32_PIN_PX21 can be used. Module pins such as
* AVR32_PWM_PWM_3_PIN for PWM channel 3 can also be used to release
* module pins for GPIO.
*/
extern void gpio_enable_gpio_pin(unsigned int pin);

View file

@ -10,7 +10,7 @@
* - AppNote:
*
* \author Atmel Corporation: http://www.atmel.com \n
* Support email: avr32@atmel.com
* Support and FAQ: http://support.atmel.no/
*
******************************************************************************/
@ -42,14 +42,7 @@
*/
#if __GNUC__
# include <avr32/io.h>
#elif __ICCAVR32__
# include <avr32/iouc3a0512.h>
#else
# error Unknown compiler
#endif
#include <avr32/io.h>
#include "compiler.h"
#include "preprocessor.h"
#include "intc.h"
@ -61,7 +54,7 @@ extern const unsigned int ipr_val[AVR32_INTC_NUM_INT_LEVELS];
//! Creates a table of interrupt line handlers per interrupt group in order to optimize RAM space.
//! Each line handler table contains a set of pointers to interrupt handlers.
#define DECL_INT_LINE_HANDLER_TABLE(GRP, unused) \
static volatile __int_handler _int_line_handler_table_##GRP[AVR32_INTC_NUM_IRQS_PER_GRP##GRP];
static volatile __int_handler _int_line_handler_table_##GRP[Max(AVR32_INTC_NUM_IRQS_PER_GRP##GRP, 1)];
MREPEAT(AVR32_INTC_NUM_INT_GRPS, DECL_INT_LINE_HANDLER_TABLE, ~);
#undef DECL_INT_LINE_HANDLER_TABLE
@ -186,6 +179,7 @@ void INTC_init_interrupts(void)
void INTC_register_interrupt(__int_handler handler, unsigned int irq, unsigned int int_lev)
{
// Determine the group of the IRQ.
unsigned int int_grp = irq / AVR32_INTC_MAX_NUM_IRQS_PER_GRP;
// Store in _int_line_handler_table_x the pointer to the interrupt handler, so

View file

@ -10,7 +10,7 @@
* - AppNote:
*
* \author Atmel Corporation: http://www.atmel.com \n
* Support email: avr32@atmel.com
* Support and FAQ: http://support.atmel.no/
*
******************************************************************************/

View file

@ -0,0 +1,999 @@
/*This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file *********************************************************************
*
* \brief MACB driver for EVK1100 board.
*
* This file defines a useful set of functions for the MACB interface on
* AVR32 devices.
*
* - Compiler: IAR EWAVR32 and GNU GCC for AVR32
* - Supported devices: All AVR32 devices with a MACB module can be used.
* - AppNote:
*
* \author Atmel Corporation: http://www.atmel.com \n
* Support and FAQ: http://support.atmel.no/
*
*****************************************************************************/
/* Copyright (c) 2007, Atmel Corporation All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of ATMEL may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
* SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <stdio.h>
#include <string.h>
#include <avr32/io.h>
#ifdef FREERTOS_USED
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#endif
#include "macb.h"
#include "gpio.h"
#include "conf_eth.h"
#include "intc.h"
/* Size of each receive buffer - DO NOT CHANGE. */
#define RX_BUFFER_SIZE 128
/* The buffer addresses written into the descriptors must be aligned so the
last few bits are zero. These bits have special meaning for the MACB
peripheral and cannot be used as part of the address. */
#define ADDRESS_MASK ( ( unsigned long ) 0xFFFFFFFC )
/* Bit used within the address stored in the descriptor to mark the last
descriptor in the array. */
#define RX_WRAP_BIT ( ( unsigned long ) 0x02 )
/* A short delay is used to wait for a buffer to become available, should
one not be immediately available when trying to transmit a frame. */
#define BUFFER_WAIT_DELAY ( 2 )
#ifndef FREERTOS_USED
#define portENTER_CRITICAL Disable_global_interrupt
#define portEXIT_CRITICAL Enable_global_interrupt
#define portENTER_SWITCHING_ISR()
#define portEXIT_SWITCHING_ISR()
#endif
/* Buffer written to by the MACB DMA. Must be aligned as described by the
comment above the ADDRESS_MASK definition. */
#if __GNUC__
static volatile char pcRxBuffer[ ETHERNET_CONF_NB_RX_BUFFERS * RX_BUFFER_SIZE ] __attribute__ ((aligned (8)));
#elif __ICCAVR32__
#pragma data_alignment=8
static volatile char pcRxBuffer[ ETHERNET_CONF_NB_RX_BUFFERS * RX_BUFFER_SIZE ];
#endif
/* Buffer read by the MACB DMA. Must be aligned as described by the comment
above the ADDRESS_MASK definition. */
#if __GNUC__
static volatile char pcTxBuffer[ ETHERNET_CONF_NB_TX_BUFFERS * ETHERNET_CONF_TX_BUFFER_SIZE ] __attribute__ ((aligned (8)));
#elif __ICCAVR32__
#pragma data_alignment=8
static volatile char pcTxBuffer[ ETHERNET_CONF_NB_TX_BUFFERS * ETHERNET_CONF_TX_BUFFER_SIZE ];
#endif
/* Descriptors used to communicate between the program and the MACB peripheral.
These descriptors hold the locations and state of the Rx and Tx buffers. */
static volatile AVR32_TxTdDescriptor xTxDescriptors[ ETHERNET_CONF_NB_TX_BUFFERS ];
static volatile AVR32_RxTdDescriptor xRxDescriptors[ ETHERNET_CONF_NB_RX_BUFFERS ];
/* The IP and Ethernet addresses are read from the header files. */
char cMACAddress[ 6 ] = { ETHERNET_CONF_ETHADDR0,ETHERNET_CONF_ETHADDR1,ETHERNET_CONF_ETHADDR2,ETHERNET_CONF_ETHADDR3,ETHERNET_CONF_ETHADDR4,ETHERNET_CONF_ETHADDR5 };
/*-----------------------------------------------------------*/
/* See the header file for descriptions of public functions. */
/*
* Prototype for the MACB interrupt function - called by the asm wrapper.
*/
#ifdef FREERTOS_USED
#if __GNUC__
__attribute__((naked))
#elif __ICCAVR32__
#pragma shadow_registers = full // Naked.
#endif
#else
#if __GNUC__
__attribute__((__interrupt__))
#elif __ICCAVR32__
__interrupt
#endif
#endif
void vMACB_ISR( void );
static long prvMACB_ISR_NonNakedBehaviour( void );
#if ETHERNET_CONF_USE_PHY_IT
#ifdef FREERTOS_USED
#if __GNUC__
__attribute__((naked))
#elif __ICCAVR32__
#pragma shadow_registers = full // Naked.
#endif
#else
#if __GNUC__
__attribute__((__interrupt__))
#elif __ICCAVR32__
__interrupt
#endif
#endif
void vPHY_ISR( void );
static long prvPHY_ISR_NonNakedBehaviour( void );
#endif
/*
* Initialise both the Tx and Rx descriptors used by the MACB.
*/
static void prvSetupDescriptors(volatile avr32_macb_t * macb);
/*
* Write our MAC address into the MACB.
*/
static void prvSetupMACAddress( volatile avr32_macb_t * macb );
/*
* Configure the MACB for interrupts.
*/
static void prvSetupMACBInterrupt( volatile avr32_macb_t * macb );
/*
* Some initialisation functions.
*/
static Bool prvProbePHY( volatile avr32_macb_t * macb );
static unsigned long ulReadMDIO(volatile avr32_macb_t * macb, unsigned short usAddress);
static void vWriteMDIO(volatile avr32_macb_t * macb, unsigned short usAddress, unsigned short usValue);
#ifdef FREERTOS_USED
/* The semaphore used by the MACB ISR to wake the MACB task. */
static xSemaphoreHandle xSemaphore = NULL;
#else
static volatile Bool DataToRead = FALSE;
#endif
/* Holds the index to the next buffer from which data will be read. */
volatile unsigned long ulNextRxBuffer = 0;
long lMACBSend(volatile avr32_macb_t * macb, char *pcFrom, unsigned long ulLength, long lEndOfFrame )
{
static unsigned long uxTxBufferIndex = 0;
char *pcBuffer;
unsigned long ulLastBuffer, ulDataBuffered = 0, ulDataRemainingToSend, ulLengthToSend;
/* If the length of data to be transmitted is greater than each individual
transmit buffer then the data will be split into more than one buffer.
Loop until the entire length has been buffered. */
while( ulDataBuffered < ulLength )
{
// Is a buffer available ?
while( !( xTxDescriptors[ uxTxBufferIndex ].U_Status.status & AVR32_TRANSMIT_OK ) )
{
// There is no room to write the Tx data to the Tx buffer.
// Wait a short while, then try again.
#ifdef FREERTOS_USED
vTaskDelay( BUFFER_WAIT_DELAY );
#else
__asm__ __volatile__ ("nop");
#endif
}
portENTER_CRITICAL();
{
// Get the address of the buffer from the descriptor,
// then copy the data into the buffer.
pcBuffer = ( char * ) xTxDescriptors[ uxTxBufferIndex ].addr;
// How much can we write to the buffer ?
ulDataRemainingToSend = ulLength - ulDataBuffered;
if( ulDataRemainingToSend <= ETHERNET_CONF_TX_BUFFER_SIZE )
{
// We can write all the remaining bytes.
ulLengthToSend = ulDataRemainingToSend;
}
else
{
// We can't write more than ETH_TX_BUFFER_SIZE in one go.
ulLengthToSend = ETHERNET_CONF_TX_BUFFER_SIZE;
}
// Copy the data into the buffer.
memcpy( ( void * ) pcBuffer, ( void * ) &( pcFrom[ ulDataBuffered ] ), ulLengthToSend );
ulDataBuffered += ulLengthToSend;
// Is this the last data for the frame ?
if( lEndOfFrame && ( ulDataBuffered >= ulLength ) )
{
// No more data remains for this frame so we can start the transmission.
ulLastBuffer = AVR32_LAST_BUFFER;
}
else
{
// More data to come for this frame.
ulLastBuffer = 0;
}
// Fill out the necessary in the descriptor to get the data sent,
// then move to the next descriptor, wrapping if necessary.
if( uxTxBufferIndex >= ( ETHERNET_CONF_NB_TX_BUFFERS - 1 ) )
{
xTxDescriptors[ uxTxBufferIndex ].U_Status.status = ( ulLengthToSend & ( unsigned long ) AVR32_LENGTH_FRAME )
| ulLastBuffer
| AVR32_TRANSMIT_WRAP;
uxTxBufferIndex = 0;
}
else
{
xTxDescriptors[ uxTxBufferIndex ].U_Status.status = ( ulLengthToSend & ( unsigned long ) AVR32_LENGTH_FRAME )
| ulLastBuffer;
uxTxBufferIndex++;
}
/* If this is the last buffer to be sent for this frame we can
start the transmission. */
if( ulLastBuffer )
{
macb->ncr |= AVR32_MACB_TSTART_MASK;
}
}
portEXIT_CRITICAL();
}
return PASS;
}
unsigned long ulMACBInputLength( void )
{
register unsigned long ulIndex , ulLength = 0;
unsigned int uiTemp;
// Skip any fragments. We are looking for the first buffer that contains
// data and has the SOF (start of frame) bit set.
while( ( xRxDescriptors[ ulNextRxBuffer ].addr & AVR32_OWNERSHIP_BIT ) && !( xRxDescriptors[ ulNextRxBuffer ].U_Status.status & AVR32_SOF ) )
{
// Ignoring this buffer. Mark it as free again.
uiTemp = xRxDescriptors[ ulNextRxBuffer ].addr;
xRxDescriptors[ ulNextRxBuffer ].addr = uiTemp & ~( AVR32_OWNERSHIP_BIT );
ulNextRxBuffer++;
if( ulNextRxBuffer >= ETHERNET_CONF_NB_RX_BUFFERS )
{
ulNextRxBuffer = 0;
}
}
// We are going to walk through the descriptors that make up this frame,
// but don't want to alter ulNextRxBuffer as this would prevent vMACBRead()
// from finding the data. Therefore use a copy of ulNextRxBuffer instead.
ulIndex = ulNextRxBuffer;
// Walk through the descriptors until we find the last buffer for this frame.
// The last buffer will give us the length of the entire frame.
while( ( xRxDescriptors[ ulIndex ].addr & AVR32_OWNERSHIP_BIT ) && !ulLength )
{
ulLength = xRxDescriptors[ ulIndex ].U_Status.status & AVR32_LENGTH_FRAME;
// Increment to the next buffer, wrapping if necessary.
ulIndex++;
if( ulIndex >= ETHERNET_CONF_NB_RX_BUFFERS )
{
ulIndex = 0;
}
}
return ulLength;
}
/*-----------------------------------------------------------*/
void vMACBRead( char *pcTo, unsigned long ulSectionLength, unsigned long ulTotalFrameLength )
{
static unsigned long ulSectionBytesReadSoFar = 0, ulBufferPosition = 0, ulFameBytesReadSoFar = 0;
static char *pcSource;
register unsigned long ulBytesRemainingInBuffer, ulRemainingSectionBytes;
unsigned int uiTemp;
// Read ulSectionLength bytes from the Rx buffers.
// This is not necessarily any correspondence between the length of our Rx buffers,
// and the length of the data we are returning or the length of the data being requested.
// Therefore, between calls we have to remember not only which buffer we are currently
// processing, but our position within that buffer.
// This would be greatly simplified if PBUF_POOL_BUFSIZE could be guaranteed to be greater
// than the size of each Rx buffer, and that memory fragmentation did not occur.
// This function should only be called after a call to ulMACBInputLength().
// This will ensure ulNextRxBuffer is set to the correct buffer. */
// vMACBRead is called with pcTo set to NULL to indicate that we are about
// to read a new frame. Any fragments remaining in the frame we were
// processing during the last call should be dropped.
if( pcTo == NULL )
{
// How many bytes are indicated as being in this buffer?
// If none then the buffer is completely full and the frame is contained within more
// than one buffer.
// Reset our state variables ready for the next read from this buffer.
pcSource = ( char * )( xRxDescriptors[ ulNextRxBuffer ].addr & ADDRESS_MASK );
ulFameBytesReadSoFar = ( unsigned long ) 0;
ulBufferPosition = ( unsigned long ) 0;
}
else
{
// Loop until we have obtained the required amount of data.
ulSectionBytesReadSoFar = 0;
while( ulSectionBytesReadSoFar < ulSectionLength )
{
// We may have already read some data from this buffer.
// How much data remains in the buffer?
ulBytesRemainingInBuffer = ( RX_BUFFER_SIZE - ulBufferPosition );
// How many more bytes do we need to read before we have the
// required amount of data?
ulRemainingSectionBytes = ulSectionLength - ulSectionBytesReadSoFar;
// Do we want more data than remains in the buffer?
if( ulRemainingSectionBytes > ulBytesRemainingInBuffer )
{
// We want more data than remains in the buffer so we can
// write the remains of the buffer to the destination, then move
// onto the next buffer to get the rest.
memcpy( &( pcTo[ ulSectionBytesReadSoFar ] ), &( pcSource[ ulBufferPosition ] ), ulBytesRemainingInBuffer );
ulSectionBytesReadSoFar += ulBytesRemainingInBuffer;
ulFameBytesReadSoFar += ulBytesRemainingInBuffer;
// Mark the buffer as free again.
uiTemp = xRxDescriptors[ ulNextRxBuffer ].addr;
xRxDescriptors[ ulNextRxBuffer ].addr = uiTemp & ~( AVR32_OWNERSHIP_BIT );
// Move onto the next buffer.
ulNextRxBuffer++;
if( ulNextRxBuffer >= ETHERNET_CONF_NB_RX_BUFFERS )
{
ulNextRxBuffer = ( unsigned long ) 0;
}
// Reset the variables for the new buffer.
pcSource = ( char * )( xRxDescriptors[ ulNextRxBuffer ].addr & ADDRESS_MASK );
ulBufferPosition = ( unsigned long ) 0;
}
else
{
// We have enough data in this buffer to send back.
// Read out enough data and remember how far we read up to.
memcpy( &( pcTo[ ulSectionBytesReadSoFar ] ), &( pcSource[ ulBufferPosition ] ), ulRemainingSectionBytes );
// There may be more data in this buffer yet.
// Increment our position in this buffer past the data we have just read.
ulBufferPosition += ulRemainingSectionBytes;
ulSectionBytesReadSoFar += ulRemainingSectionBytes;
ulFameBytesReadSoFar += ulRemainingSectionBytes;
// Have we now finished with this buffer?
if( ( ulBufferPosition >= RX_BUFFER_SIZE ) || ( ulFameBytesReadSoFar >= ulTotalFrameLength ) )
{
// Mark the buffer as free again.
uiTemp = xRxDescriptors[ ulNextRxBuffer ].addr;
xRxDescriptors[ ulNextRxBuffer ].addr = uiTemp & ~( AVR32_OWNERSHIP_BIT );
// Move onto the next buffer.
ulNextRxBuffer++;
if( ulNextRxBuffer >= ETHERNET_CONF_NB_RX_BUFFERS )
{
ulNextRxBuffer = 0;
}
pcSource = ( char * )( xRxDescriptors[ ulNextRxBuffer ].addr & ADDRESS_MASK );
ulBufferPosition = 0;
}
}
}
}
}
/*-----------------------------------------------------------*/
void vMACBSetMACAddress(const char * MACAddress)
{
memcpy(cMACAddress, MACAddress, sizeof(cMACAddress));
}
Bool xMACBInit( volatile avr32_macb_t * macb )
{
volatile unsigned long status;
// set up registers
macb->ncr = 0;
macb->tsr = ~0UL;
macb->rsr = ~0UL;
macb->idr = ~0UL;
status = macb->isr;
#if ETHERNET_CONF_USE_RMII_INTERFACE
// RMII used, set 0 to the USRIO Register
macb->usrio &= ~AVR32_MACB_RMII_MASK;
#else
// RMII not used, set 1 to the USRIO Register
macb->usrio |= AVR32_MACB_RMII_MASK;
#endif
// Load our MAC address into the MACB.
prvSetupMACAddress(macb);
// Setup the buffers and descriptors.
prvSetupDescriptors(macb);
#if ETHERNET_CONF_SYSTEM_CLOCK <= 20000000
macb->ncfgr |= (AVR32_MACB_NCFGR_CLK_DIV8 << AVR32_MACB_NCFGR_CLK_OFFSET);
#elif ETHERNET_CONF_SYSTEM_CLOCK <= 40000000
macb->ncfgr |= (AVR32_MACB_NCFGR_CLK_DIV16 << AVR32_MACB_NCFGR_CLK_OFFSET);
#elif ETHERNET_CONF_SYSTEM_CLOCK <= 80000000
macb->ncfgr |= AVR32_MACB_NCFGR_CLK_DIV32 << AVR32_MACB_NCFGR_CLK_OFFSET;
#elif ETHERNET_CONF_SYSTEM_CLOCK <= 160000000
macb->ncfgr |= AVR32_MACB_NCFGR_CLK_DIV64 << AVR32_MACB_NCFGR_CLK_OFFSET;
#else
# error System clock too fast
#endif
// Are we connected?
if( prvProbePHY(macb) == TRUE )
{
// Enable the interrupt!
portENTER_CRITICAL();
{
prvSetupMACBInterrupt(macb);
}
portEXIT_CRITICAL();
// Enable Rx and Tx, plus the stats register.
macb->ncr = AVR32_MACB_NCR_TE_MASK | AVR32_MACB_NCR_RE_MASK;
return (TRUE);
}
return (FALSE);
}
void vDisableMACBOperations(volatile avr32_macb_t * macb)
{
#if ETHERNET_CONF_USE_PHY_IT
volatile avr32_gpio_t *gpio = &AVR32_GPIO;
volatile avr32_gpio_port_t *gpio_port = &gpio->port[MACB_INTERRUPT_PIN/32];
gpio_port->ierc = 1 << (MACB_INTERRUPT_PIN%32);
#endif
// write the MACB control register : disable Tx & Rx
macb->ncr &= ~((1 << AVR32_MACB_RE_OFFSET) | (1 << AVR32_MACB_TE_OFFSET));
// We no more want to interrupt on Rx and Tx events.
macb->idr = AVR32_MACB_IER_RCOMP_MASK | AVR32_MACB_IER_TCOMP_MASK;
}
void vClearMACBTxBuffer( void )
{
static unsigned long uxNextBufferToClear = 0;
// Called on Tx interrupt events to set the AVR32_TRANSMIT_OK bit in each
// Tx buffer within the frame just transmitted. This marks all the buffers
// as available again.
// The first buffer in the frame should have the bit set automatically. */
if( xTxDescriptors[ uxNextBufferToClear ].U_Status.status & AVR32_TRANSMIT_OK )
{
// Loop through the other buffers in the frame.
while( !( xTxDescriptors[ uxNextBufferToClear ].U_Status.status & AVR32_LAST_BUFFER ) )
{
uxNextBufferToClear++;
if( uxNextBufferToClear >= ETHERNET_CONF_NB_TX_BUFFERS )
{
uxNextBufferToClear = 0;
}
xTxDescriptors[ uxNextBufferToClear ].U_Status.status |= AVR32_TRANSMIT_OK;
}
// Start with the next buffer the next time a Tx interrupt is called.
uxNextBufferToClear++;
// Do we need to wrap back to the first buffer?
if( uxNextBufferToClear >= ETHERNET_CONF_NB_TX_BUFFERS )
{
uxNextBufferToClear = 0;
}
}
}
static void prvSetupDescriptors(volatile avr32_macb_t * macb)
{
unsigned long xIndex;
unsigned long ulAddress;
// Initialise xRxDescriptors descriptor.
for( xIndex = 0; xIndex < ETHERNET_CONF_NB_RX_BUFFERS; ++xIndex )
{
// Calculate the address of the nth buffer within the array.
ulAddress = ( unsigned long )( pcRxBuffer + ( xIndex * RX_BUFFER_SIZE ) );
// Write the buffer address into the descriptor.
// The DMA will place the data at this address when this descriptor is being used.
// Mask off the bottom bits of the address as these have special meaning.
xRxDescriptors[ xIndex ].addr = ulAddress & ADDRESS_MASK;
}
// The last buffer has the wrap bit set so the MACB knows to wrap back
// to the first buffer.
xRxDescriptors[ ETHERNET_CONF_NB_RX_BUFFERS - 1 ].addr |= RX_WRAP_BIT;
// Initialise xTxDescriptors.
for( xIndex = 0; xIndex < ETHERNET_CONF_NB_TX_BUFFERS; ++xIndex )
{
// Calculate the address of the nth buffer within the array.
ulAddress = ( unsigned long )( pcTxBuffer + ( xIndex * ETHERNET_CONF_TX_BUFFER_SIZE ) );
// Write the buffer address into the descriptor.
// The DMA will read data from here when the descriptor is being used.
xTxDescriptors[ xIndex ].addr = ulAddress & ADDRESS_MASK;
xTxDescriptors[ xIndex ].U_Status.status = AVR32_TRANSMIT_OK;
}
// The last buffer has the wrap bit set so the MACB knows to wrap back
// to the first buffer.
xTxDescriptors[ ETHERNET_CONF_NB_TX_BUFFERS - 1 ].U_Status.status = AVR32_TRANSMIT_WRAP | AVR32_TRANSMIT_OK;
// Tell the MACB where to find the descriptors.
macb->rbqp = ( unsigned long )xRxDescriptors;
macb->tbqp = ( unsigned long )xTxDescriptors;
// Enable the copy of data into the buffers, ignore broadcasts,
// and don't copy FCS.
macb->ncfgr |= (AVR32_MACB_CAF_MASK | AVR32_MACB_NBC_MASK | AVR32_MACB_NCFGR_DRFCS_MASK);
}
static void prvSetupMACAddress( volatile avr32_macb_t * macb )
{
// Must be written SA1L then SA1H.
macb->sa1b = ( ( unsigned long ) cMACAddress[ 3 ] << 24 ) |
( ( unsigned long ) cMACAddress[ 2 ] << 16 ) |
( ( unsigned long ) cMACAddress[ 1 ] << 8 ) |
cMACAddress[ 0 ];
macb->sa1t = ( ( unsigned long ) cMACAddress[ 5 ] << 8 ) |
cMACAddress[ 4 ];
}
static void prvSetupMACBInterrupt( volatile avr32_macb_t * macb )
{
#ifdef FREERTOS_USED
// Create the semaphore used to trigger the MACB task.
if (xSemaphore == NULL)
{
vSemaphoreCreateBinary( xSemaphore );
}
#else
// Create the flag used to trigger the MACB polling task.
DataToRead = FALSE;
#endif
#ifdef FREERTOS_USED
if( xSemaphore != NULL)
{
// We start by 'taking' the semaphore so the ISR can 'give' it when the
// first interrupt occurs.
xSemaphoreTake( xSemaphore, 0 );
#endif
// Setup the interrupt for MACB.
// Register the interrupt handler to the interrupt controller at interrupt level 2
INTC_register_interrupt((__int_handler)&vMACB_ISR, AVR32_MACB_IRQ, INT2);
#if ETHERNET_CONF_USE_PHY_IT
/* GPIO enable interrupt upon rising edge */
gpio_enable_pin_interrupt(MACB_INTERRUPT_PIN, GPIO_FALLING_EDGE);
// Setup the interrupt for PHY.
// Register the interrupt handler to the interrupt controller at interrupt level 2
INTC_register_interrupt((__int_handler)&vPHY_ISR, (AVR32_GPIO_IRQ_0 + (MACB_INTERRUPT_PIN/8)), INT2);
/* enable interrupts on INT pin */
vWriteMDIO( macb, PHY_MICR , ( MICR_INTEN | MICR_INTOE ));
/* enable "link change" interrupt for Phy */
vWriteMDIO( macb, PHY_MISR , MISR_LINK_INT_EN );
#endif
// We want to interrupt on Rx and Tx events
macb->ier = AVR32_MACB_IER_RCOMP_MASK | AVR32_MACB_IER_TCOMP_MASK;
#ifdef FREERTOS_USED
}
#endif
}
/*! Read a register on MDIO bus (access to the PHY)
* This function is looping until PHY gets ready
*
* \param macb Input. instance of the MACB to use
* \param usAddress Input. register to set.
*
* \return unsigned long data that has been read
*/
static unsigned long ulReadMDIO(volatile avr32_macb_t * macb, unsigned short usAddress)
{
unsigned long value, status;
// initiate transaction : enable management port
macb->ncr |= AVR32_MACB_NCR_MPE_MASK;
// Write the PHY configuration frame to the MAN register
macb->man = (AVR32_MACB_SOF_MASK & (0x01<<AVR32_MACB_SOF_OFFSET)) // SOF
| (2 << AVR32_MACB_CODE_OFFSET) // Code
| (2 << AVR32_MACB_RW_OFFSET) // Read operation
| ((ETHERNET_CONF_PHY_ADDR & 0x1f) << AVR32_MACB_PHYA_OFFSET) // Phy Add
| (usAddress << AVR32_MACB_REGA_OFFSET); // Reg Add
// wait for PHY to be ready
do {
status = macb->nsr;
} while (!(status & AVR32_MACB_NSR_IDLE_MASK));
// read the register value in maintenance register
value = macb->man & 0x0000ffff;
// disable management port
macb->ncr &= ~AVR32_MACB_NCR_MPE_MASK;
// return the read value
return (value);
}
/*! Write a given value to a register on MDIO bus (access to the PHY)
* This function is looping until PHY gets ready
*
* \param *macb Input. instance of the MACB to use
* \param usAddress Input. register to set.
* \param usValue Input. value to write.
*
*/
static void vWriteMDIO(volatile avr32_macb_t * macb, unsigned short usAddress, unsigned short usValue)
{
unsigned long status;
// initiate transaction : enable management port
macb->ncr |= AVR32_MACB_NCR_MPE_MASK;
// Write the PHY configuration frame to the MAN register
macb->man = (( AVR32_MACB_SOF_MASK & (0x01<<AVR32_MACB_SOF_OFFSET)) // SOF
| (2 << AVR32_MACB_CODE_OFFSET) // Code
| (1 << AVR32_MACB_RW_OFFSET) // Write operation
| ((ETHERNET_CONF_PHY_ADDR & 0x1f) << AVR32_MACB_PHYA_OFFSET) // Phy Add
| (usAddress << AVR32_MACB_REGA_OFFSET)) // Reg Add
| (usValue & 0xffff); // Data
// wait for PHY to be ready
do {
status = macb->nsr;
} while (!(status & AVR32_MACB_NSR_IDLE_MASK));
// disable management port
macb->ncr &= ~AVR32_MACB_NCR_MPE_MASK;
}
static Bool prvProbePHY( volatile avr32_macb_t * macb )
{
volatile unsigned long mii_status, phy_ctrl;
volatile unsigned long config;
unsigned long upper, lower, mode, advertise, lpa;
volatile unsigned long physID;
// Read Phy Identifier register 1 & 2
lower = ulReadMDIO(macb, PHY_PHYSID2);
upper = ulReadMDIO(macb, PHY_PHYSID1);
// get Phy ID, ignore Revision
physID = ((upper << 16) & 0xFFFF0000) | (lower & 0xFFF0);
// check if it match config
if (physID == ETHERNET_CONF_PHY_ID)
{
// read RBR
mode = ulReadMDIO(macb, PHY_RBR);
// set RMII mode if not done
if ((mode & RBR_RMII) != RBR_RMII)
{
// force RMII flag if strap options are wrong
mode |= RBR_RMII;
vWriteMDIO(macb, PHY_RBR, mode);
}
// set advertise register
#if ETHERNET_CONF_AN_ENABLE == 1
advertise = ADVERTISE_CSMA | ADVERTISE_ALL;
#else
advertise = ADVERTISE_CSMA;
#if ETHERNET_CONF_USE_100MB
#if ETHERNET_CONF_USE_FULL_DUPLEX
advertise |= ADVERTISE_100FULL;
#else
advertise |= ADVERTISE_100HALF;
#endif
#else
#if ETHERNET_CONF_USE_FULL_DUPLEX
advertise |= ADVERTISE_10FULL;
#else
advertise |= ADVERTISE_10HALF;
#endif
#endif
#endif
// write advertise register
vWriteMDIO(macb, PHY_ADVERTISE, advertise);
// read Control register
config = ulReadMDIO(macb, PHY_BMCR);
// read Phy Control register
phy_ctrl = ulReadMDIO(macb, PHY_PHYCR);
#if ETHERNET_CONF_AN_ENABLE
#if ETHERNET_CONF_AUTO_CROSS_ENABLE
// enable Auto MDIX
phy_ctrl |= PHYCR_MDIX_EN;
#else
// disable Auto MDIX
phy_ctrl &= ~PHYCR_MDIX_EN;
#if ETHERNET_CONF_CROSSED_LINK
// force direct link = Use crossed RJ45 cable
phy_ctrl &= ~PHYCR_MDIX_FORCE;
#else
// force crossed link = Use direct RJ45 cable
phy_ctrl |= PHYCR_MDIX_FORCE;
#endif
#endif
// reset auto-negociation capability
config |= (BMCR_ANRESTART | BMCR_ANENABLE);
#else
// disable Auto MDIX
phy_ctrl &= ~PHYCR_MDIX_EN;
#if ETHERNET_CONF_CROSSED_LINK
// force direct link = Use crossed RJ45 cable
phy_ctrl &= ~PHYCR_MDIX_FORCE;
#else
// force crossed link = Use direct RJ45 cable
phy_ctrl |= PHYCR_MDIX_FORCE;
#endif
// clear AN bit
config &= ~BMCR_ANENABLE;
#if ETHERNET_CONF_USE_100MB
config |= BMCR_SPEED100;
#else
config &= ~BMCR_SPEED100;
#endif
#if ETHERNET_CONF_USE_FULL_DUPLEX
config |= BMCR_FULLDPLX;
#else
config &= ~BMCR_FULLDPLX;
#endif
#endif
// update Phy ctrl register
vWriteMDIO(macb, PHY_PHYCR, phy_ctrl);
// update ctrl register
vWriteMDIO(macb, PHY_BMCR, config);
// loop while link status isn't OK
do {
mii_status = ulReadMDIO(macb, PHY_BMSR);
} while (!(mii_status & BMSR_LSTATUS));
// read the LPA configuration of the PHY
lpa = ulReadMDIO(macb, PHY_LPA);
// read the MACB config register
config = AVR32_MACB.ncfgr;
// if 100MB needed
if ((lpa & advertise) & (LPA_100HALF | LPA_100FULL))
{
config |= AVR32_MACB_SPD_MASK;
}
else
{
config &= ~(AVR32_MACB_SPD_MASK);
}
// if FULL DUPLEX needed
if ((lpa & advertise) & (LPA_10FULL | LPA_100FULL))
{
config |= AVR32_MACB_FD_MASK;
}
else
{
config &= ~(AVR32_MACB_FD_MASK);
}
// write the MACB config register
macb->ncfgr = config;
return TRUE;
}
return FALSE;
}
void vMACBWaitForInput( unsigned long ulTimeOut )
{
#ifdef FREERTOS_USED
// Just wait until we are signled from an ISR that data is available, or
// we simply time out.
xSemaphoreTake( xSemaphore, ulTimeOut );
#else
unsigned long i;
gpio_clr_gpio_pin(LED0_GPIO);
i = ulTimeOut * 1000;
// wait for an interrupt to occurs
do
{
if ( DataToRead == TRUE )
{
// IT occurs, reset interrupt flag
portENTER_CRITICAL();
DataToRead = FALSE;
portEXIT_CRITICAL();
break;
}
i--;
}
while(i != 0);
gpio_set_gpio_pin(LED0_GPIO);
#endif
}
/*
* The MACB ISR. Handles both Tx and Rx complete interrupts.
*/
#ifdef FREERTOS_USED
#if __GNUC__
__attribute__((naked))
#elif __ICCAVR32__
#pragma shadow_registers = full // Naked.
#endif
#else
#if __GNUC__
__attribute__((__interrupt__))
#elif __ICCAVR32__
__interrupt
#endif
#endif
void vMACB_ISR( void )
{
// This ISR can cause a context switch, so the first statement must be a
// call to the portENTER_SWITCHING_ISR() macro. This must be BEFORE any
// variable declarations.
portENTER_SWITCHING_ISR();
// the return value is used by FreeRTOS to change the context if needed after rete instruction
// in standalone use, this value should be ignored
prvMACB_ISR_NonNakedBehaviour();
// Exit the ISR. If a task was woken by either a character being received
// or transmitted then a context switch will occur.
portEXIT_SWITCHING_ISR();
}
/*-----------------------------------------------------------*/
#if __GNUC__
__attribute__((__noinline__))
#elif __ICCAVR32__
#pragma optimize = no_inline
#endif
static long prvMACB_ISR_NonNakedBehaviour( void )
{
// Variable definitions can be made now.
volatile unsigned long ulIntStatus, ulEventStatus;
long xSwitchRequired = FALSE;
// Find the cause of the interrupt.
ulIntStatus = AVR32_MACB.isr;
ulEventStatus = AVR32_MACB.rsr;
if( ( ulIntStatus & AVR32_MACB_IDR_RCOMP_MASK ) || ( ulEventStatus & AVR32_MACB_REC_MASK ) )
{
// A frame has been received, signal the IP task so it can process
// the Rx descriptors.
portENTER_CRITICAL();
#ifdef FREERTOS_USED
xSwitchRequired = xSemaphoreGiveFromISR( xSemaphore, FALSE );
#else
DataToRead = TRUE;
#endif
portEXIT_CRITICAL();
AVR32_MACB.rsr = AVR32_MACB_REC_MASK;
AVR32_MACB.rsr;
}
if( ulIntStatus & AVR32_MACB_TCOMP_MASK )
{
// A frame has been transmitted. Mark all the buffers used by the
// frame just transmitted as free again.
vClearMACBTxBuffer();
AVR32_MACB.tsr = AVR32_MACB_TSR_COMP_MASK;
AVR32_MACB.tsr;
}
return ( xSwitchRequired );
}
#if ETHERNET_CONF_USE_PHY_IT
/*
* The PHY ISR. Handles Phy interrupts.
*/
#ifdef FREERTOS_USED
#if __GNUC__
__attribute__((naked))
#elif __ICCAVR32__
#pragma shadow_registers = full // Naked.
#endif
#else
#if __GNUC__
__attribute__((__interrupt__))
#elif __ICCAVR32__
__interrupt
#endif
#endif
void vPHY_ISR( void )
{
// This ISR can cause a context switch, so the first statement must be a
// call to the portENTER_SWITCHING_ISR() macro. This must be BEFORE any
// variable declarations.
portENTER_SWITCHING_ISR();
// the return value is used by FreeRTOS to change the context if needed after rete instruction
// in standalone use, this value should be ignored
prvPHY_ISR_NonNakedBehaviour();
// Exit the ISR. If a task was woken by either a character being received
// or transmitted then a context switch will occur.
portEXIT_SWITCHING_ISR();
}
/*-----------------------------------------------------------*/
#if __GNUC__
__attribute__((__noinline__))
#elif __ICCAVR32__
#pragma optimize = no_inline
#endif
static long prvPHY_ISR_NonNakedBehaviour( void )
{
// Variable definitions can be made now.
volatile unsigned long ulIntStatus, ulEventStatus;
long xSwitchRequired = FALSE;
volatile avr32_gpio_t *gpio = &AVR32_GPIO;
volatile avr32_gpio_port_t *gpio_port = &gpio->port[MACB_INTERRUPT_PIN/32];
// read Phy Interrupt register Status
ulIntStatus = ulReadMDIO(&AVR32_MACB, PHY_MISR);
// read Phy status register
ulEventStatus = ulReadMDIO(&AVR32_MACB, PHY_BMSR);
// dummy read
ulEventStatus = ulReadMDIO(&AVR32_MACB, PHY_BMSR);
// clear interrupt flag on GPIO
gpio_port->ifrc = 1 << (MACB_INTERRUPT_PIN%32);
return ( xSwitchRequired );
}
#endif

View file

@ -0,0 +1,422 @@
/*This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file *********************************************************************
*
* \brief MACB example driver for EVK1100 board.
*
* This file defines a useful set of functions for the MACB interface on
* AVR32 devices.
*
* - Compiler: IAR EWAVR32 and GNU GCC for AVR32
* - Supported devices: All AVR32 devices with a MACB module can be used.
* - AppNote:
*
* \author Atmel Corporation: http://www.atmel.com \n
* Support and FAQ: http://support.atmel.no/
*
*****************************************************************************/
/* Copyright (c) 2007, Atmel Corporation All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of ATMEL may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
* SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef AVR32_MACB_H
#define AVR32_MACB_H
#include <avr32/io.h>
#ifdef FREERTOS_USED
#include <arch/sys_arch.h>
#endif
#include "conf_eth.h"
/*! \name Rx Ring descriptor flags
*/
//! @{
#define AVR32_MACB_RX_USED_OFFSET 0
#define AVR32_MACB_RX_USED_SIZE 1
#define AVR32_MACB_RX_WRAP_OFFSET 1
#define AVR32_MACB_RX_WRAP_SIZE 1
#define AVR32_MACB_RX_LEN_OFFSET 0
#define AVR32_MACB_RX_LEN_SIZE 12
#define AVR32_MACB_RX_OFFSET_OFFSET 12
#define AVR32_MACB_RX_OFFSET_SIZE 2
#define AVR32_MACB_RX_SOF_OFFSET 14
#define AVR32_MACB_RX_SOF_SIZE 1
#define AVR32_MACB_RX_EOF_OFFSET 15
#define AVR32_MACB_RX_EOF_SIZE 1
#define AVR32_MACB_RX_CFI_OFFSET 16
#define AVR32_MACB_RX_CFI_SIZE 1
//! @}
/*! \name Tx Ring descriptor flags
*/
//! @{
#define AVR32_MACB_TX_LEN_OFFSET 0
#define AVR32_MACB_TX_LEN_SIZE 11
#define AVR32_MACB_TX_EOF_OFFSET 15
#define AVR32_MACB_TX_EOF_SIZE 1
#define AVR32_MACB_TX_NOCRC_OFFSET 16
#define AVR32_MACB_TX_NOCRC_SIZE 1
#define AVR32_MACB_TX_EMF_OFFSET 27
#define AVR32_MACB_TX_EMF_SIZE 1
#define AVR32_MACB_TX_UNR_OFFSET 28
#define AVR32_MACB_TX_UNR_SIZE 1
#define AVR32_MACB_TX_MAXRETRY_OFFSET 29
#define AVR32_MACB_TX_MAXRETRY_SIZE 1
#define AVR32_MACB_TX_WRAP_OFFSET 30
#define AVR32_MACB_TX_WRAP_SIZE 1
#define AVR32_MACB_TX_USED_OFFSET 31
#define AVR32_MACB_TX_USED_SIZE 1
//! @}
/*! \name Generic MII registers.
*/
//! @{
#define PHY_BMCR 0x00 //!< Basic mode control register
#define PHY_BMSR 0x01 //!< Basic mode status register
#define PHY_PHYSID1 0x02 //!< PHYS ID 1
#define PHY_PHYSID2 0x03 //!< PHYS ID 2
#define PHY_ADVERTISE 0x04 //!< Advertisement control reg
#define PHY_LPA 0x05 //!< Link partner ability reg
//! @}
#if BOARD == EVK1100
/*! \name Extended registers for DP83848
*/
//! @{
#define PHY_RBR 0x17 //!< RMII Bypass reg
#define PHY_MICR 0x11 //!< Interrupt Control reg
#define PHY_MISR 0x12 //!< Interrupt Status reg
#define PHY_PHYCR 0x19 //!< Phy CTRL reg
//! @}
#endif
/*! \name Basic mode control register.
*/
//! @{
#define BMCR_RESV 0x007f //!< Unused...
#define BMCR_CTST 0x0080 //!< Collision test
#define BMCR_FULLDPLX 0x0100 //!< Full duplex
#define BMCR_ANRESTART 0x0200 //!< Auto negotiation restart
#define BMCR_ISOLATE 0x0400 //!< Disconnect PHY from MII
#define BMCR_PDOWN 0x0800 //!< Powerdown the PHY
#define BMCR_ANENABLE 0x1000 //!< Enable auto negotiation
#define BMCR_SPEED100 0x2000 //!< Select 100Mbps
#define BMCR_LOOPBACK 0x4000 //!< TXD loopback bits
#define BMCR_RESET 0x8000 //!< Reset the PHY
//! @}
/*! \name Basic mode status register.
*/
//! @{
#define BMSR_ERCAP 0x0001 //!< Ext-reg capability
#define BMSR_JCD 0x0002 //!< Jabber detected
#define BMSR_LSTATUS 0x0004 //!< Link status
#define BMSR_ANEGCAPABLE 0x0008 //!< Able to do auto-negotiation
#define BMSR_RFAULT 0x0010 //!< Remote fault detected
#define BMSR_ANEGCOMPLETE 0x0020 //!< Auto-negotiation complete
#define BMSR_RESV 0x00c0 //!< Unused...
#define BMSR_ESTATEN 0x0100 //!< Extended Status in R15
#define BMSR_100FULL2 0x0200 //!< Can do 100BASE-T2 HDX
#define BMSR_100HALF2 0x0400 //!< Can do 100BASE-T2 FDX
#define BMSR_10HALF 0x0800 //!< Can do 10mbps, half-duplex
#define BMSR_10FULL 0x1000 //!< Can do 10mbps, full-duplex
#define BMSR_100HALF 0x2000 //!< Can do 100mbps, half-duplex
#define BMSR_100FULL 0x4000 //!< Can do 100mbps, full-duplex
#define BMSR_100BASE4 0x8000 //!< Can do 100mbps, 4k packets
//! @}
/*! \name Advertisement control register.
*/
//! @{
#define ADVERTISE_SLCT 0x001f //!< Selector bits
#define ADVERTISE_CSMA 0x0001 //!< Only selector supported
#define ADVERTISE_10HALF 0x0020 //!< Try for 10mbps half-duplex
#define ADVERTISE_1000XFULL 0x0020 //!< Try for 1000BASE-X full-duplex
#define ADVERTISE_10FULL 0x0040 //!< Try for 10mbps full-duplex
#define ADVERTISE_1000XHALF 0x0040 //!< Try for 1000BASE-X half-duplex
#define ADVERTISE_100HALF 0x0080 //!< Try for 100mbps half-duplex
#define ADVERTISE_1000XPAUSE 0x0080 //!< Try for 1000BASE-X pause
#define ADVERTISE_100FULL 0x0100 //!< Try for 100mbps full-duplex
#define ADVERTISE_1000XPSE_ASYM 0x0100 //!< Try for 1000BASE-X asym pause
#define ADVERTISE_100BASE4 0x0200 //!< Try for 100mbps 4k packets
#define ADVERTISE_PAUSE_CAP 0x0400 //!< Try for pause
#define ADVERTISE_PAUSE_ASYM 0x0800 //!< Try for asymetric pause
#define ADVERTISE_RESV 0x1000 //!< Unused...
#define ADVERTISE_RFAULT 0x2000 //!< Say we can detect faults
#define ADVERTISE_LPACK 0x4000 //!< Ack link partners response
#define ADVERTISE_NPAGE 0x8000 //!< Next page bit
//! @}
#define ADVERTISE_FULL (ADVERTISE_100FULL | ADVERTISE_10FULL | ADVERTISE_CSMA)
#define ADVERTISE_ALL (ADVERTISE_10HALF | ADVERTISE_10FULL | \
ADVERTISE_100HALF | ADVERTISE_100FULL)
/*! \name Link partner ability register.
*/
//! @{
#define LPA_SLCT 0x001f //!< Same as advertise selector
#define LPA_10HALF 0x0020 //!< Can do 10mbps half-duplex
#define LPA_1000XFULL 0x0020 //!< Can do 1000BASE-X full-duplex
#define LPA_10FULL 0x0040 //!< Can do 10mbps full-duplex
#define LPA_1000XHALF 0x0040 //!< Can do 1000BASE-X half-duplex
#define LPA_100HALF 0x0080 //!< Can do 100mbps half-duplex
#define LPA_1000XPAUSE 0x0080 //!< Can do 1000BASE-X pause
#define LPA_100FULL 0x0100 //!< Can do 100mbps full-duplex
#define LPA_1000XPAUSE_ASYM 0x0100 //!< Can do 1000BASE-X pause asym
#define LPA_100BASE4 0x0200 //!< Can do 100mbps 4k packets
#define LPA_PAUSE_CAP 0x0400 //!< Can pause
#define LPA_PAUSE_ASYM 0x0800 //!< Can pause asymetrically
#define LPA_RESV 0x1000 //!< Unused...
#define LPA_RFAULT 0x2000 //!< Link partner faulted
#define LPA_LPACK 0x4000 //!< Link partner acked us
#define LPA_NPAGE 0x8000 //!< Next page bit
#define LPA_DUPLEX (LPA_10FULL | LPA_100FULL)
#define LPA_100 (LPA_100FULL | LPA_100HALF | LPA_100BASE4)
//! @}
#if BOARD == EVK1100
/*! RMII Bypass Register */
#define RBR_RMII 0x0020 //!< RMII Mode
/*! \name Interrupt Ctrl Register.
*/
//! @{
#define MICR_INTEN 0x0002 //!< Enable interrupts
#define MICR_INTOE 0x0001 //!< Enable INT output
//! @}
/*! \name Interrupt Status Register.
*/
//! @{
#define MISR_ED_INT_EN 0x0040 //!< Energy Detect enabled
#define MISR_LINK_INT_EN 0x0020 //!< Link status change enabled
#define MISR_SPD_INT_EN 0x0010 //!< Speed change enabled
#define MISR_DP_INT_EN 0x0008 //!< Duplex mode change enabled
#define MISR_ANC_INT_EN 0x0004 //!< Auto-Neg complete enabled
#define MISR_FHF_INT_EN 0x0002 //!< False Carrier enabled
#define MISR_RHF_INT_EN 0x0001 //!< Receive Error enabled
#define MISR_ED_INT 0x4000 //!< Energy Detect
#define MISR_LINK_INT 0x2000 //!< Link status change
#define MISR_SPD_INT 0x1000 //!< Speed change
#define MISR_DP_INT 0x0800 //!< Duplex mode change
#define MISR_ANC_INT 0x0400 //!< Auto-Neg complete
#define MISR_FHF_INT 0x0200 //!< False Carrier
#define MISR_RHF_INT 0x0100 //!< Receive Error
//! @}
/*! \name Phy Ctrl Register.
*/
//! @{
#define PHYCR_MDIX_EN 0x8000 //!< Enable Auto MDIX
#define PHYCR_MDIX_FORCE 0x4000 //!< Force MDIX crossed
//! @}
#endif
/*! Packet structure.
*/
//! @{
typedef struct
{
char *data;
unsigned int len;
} macb_packet_t;
//! @}
/*! Receive Transfer descriptor structure.
*/
//! @{
typedef struct _AVR32_RxTdDescriptor {
unsigned int addr;
union
{
unsigned int status;
struct {
unsigned int BroadCast:1;
unsigned int MultiCast:1;
unsigned int UniCast:1;
unsigned int ExternalAdd:1;
unsigned int Res1:1;
unsigned int Sa1Match:1;
unsigned int Sa2Match:1;
unsigned int Sa3Match:1;
unsigned int Sa4Match:1;
unsigned int TypeID:1;
unsigned int VlanTag:1;
unsigned int PriorityTag:1;
unsigned int VlanPriority:3;
unsigned int Cfi:1;
unsigned int EndOfFrame:1;
unsigned int StartOfFrame:1;
unsigned int Rxbuf_off:2;
unsigned int Res0:1;
unsigned int Length:11;
}S_Status;
}U_Status;
}AVR32_RxTdDescriptor, *AVR32P_RxTdDescriptor;
//! @}
/*! Transmit Transfer descriptor structure.
*/
//! @{
typedef struct _AVR32_TxTdDescriptor {
unsigned int addr;
union
{
unsigned int status;
struct {
unsigned int BuffUsed:1;
unsigned int Wrap:1;
unsigned int TransmitError:1;
unsigned int TransmitUnderrun:1;
unsigned int BufExhausted:1;
unsigned int Res1:10;
unsigned int NoCrc:1;
unsigned int LastBuff:1;
unsigned int Res0:4;
unsigned int Length:11;
}S_Status;
}U_Status;
}AVR32_TxTdDescriptor, *AVR32P_TxTdDescriptor;
//! @}
/*! Mask for frame used. */
#define AVR32_OWNERSHIP_BIT 0x00000001
/*! Receive status defintion.
*/
//! @{
#define AVR32_BROADCAST_ADDR ((unsigned int) (1 << 31)) //* Broadcat address detected
#define AVR32_MULTICAST_HASH ((unsigned int) (1 << 30)) //* MultiCast hash match
#define AVR32_UNICAST_HASH ((unsigned int) (1 << 29)) //* UniCast hash match
#define AVR32_EXTERNAL_ADDR ((unsigned int) (1 << 28)) //* External Address match
#define AVR32_SA1_ADDR ((unsigned int) (1 << 26)) //* Specific address 1 match
#define AVR32_SA2_ADDR ((unsigned int) (1 << 25)) //* Specific address 2 match
#define AVR32_SA3_ADDR ((unsigned int) (1 << 24)) //* Specific address 3 match
#define AVR32_SA4_ADDR ((unsigned int) (1 << 23)) //* Specific address 4 match
#define AVR32_TYPE_ID ((unsigned int) (1 << 22)) //* Type ID match
#define AVR32_VLAN_TAG ((unsigned int) (1 << 21)) //* VLAN tag detected
#define AVR32_PRIORITY_TAG ((unsigned int) (1 << 20)) //* PRIORITY tag detected
#define AVR32_VLAN_PRIORITY ((unsigned int) (7 << 17)) //* PRIORITY Mask
#define AVR32_CFI_IND ((unsigned int) (1 << 16)) //* CFI indicator
#define AVR32_EOF ((unsigned int) (1 << 15)) //* EOF
#define AVR32_SOF ((unsigned int) (1 << 14)) //* SOF
#define AVR32_RBF_OFFSET ((unsigned int) (3 << 12)) //* Receive Buffer Offset Mask
#define AVR32_LENGTH_FRAME ((unsigned int) 0x0FFF) //* Length of frame
//! @}
/* Transmit Status definition */
//! @{
#define AVR32_TRANSMIT_OK ((unsigned int) (1 << 31)) //*
#define AVR32_TRANSMIT_WRAP ((unsigned int) (1 << 30)) //* Wrap bit: mark the last descriptor
#define AVR32_TRANSMIT_ERR ((unsigned int) (1 << 29)) //* RLE:transmit error
#define AVR32_TRANSMIT_UND ((unsigned int) (1 << 28)) //* Transmit Underrun
#define AVR32_BUF_EX ((unsigned int) (1 << 27)) //* Buffers exhausted in mid frame
#define AVR32_TRANSMIT_NO_CRC ((unsigned int) (1 << 16)) //* No CRC will be appended to the current frame
#define AVR32_LAST_BUFFER ((unsigned int) (1 << 15)) //*
//! @}
/**
* \brief Initialise the MACB driver.
*
* \param *macb Base address of the MACB
*
* \return TRUE if success, FALSE otherwise.
*/
Bool xMACBInit( volatile avr32_macb_t * macb );
/**
* \brief Send ulLength bytes from pcFrom. This copies the buffer to one of the
* MACB Tx buffers, then indicates to the MACB that the buffer is ready.
* If lEndOfFrame is true then the data being copied is the end of the frame
* and the frame can be transmitted.
*
* \param *macb Base address of the MACB
* \param *pcFrom Address of the data buffer
* \param ulLength Length of the frame
* \param lEndOfFrame Flag for End Of Frame
*
* \return length sent.
*/
long lMACBSend(volatile avr32_macb_t * macb, char *pcFrom, unsigned long ulLength, long lEndOfFrame );
/**
* \brief Frames can be read from the MACB in multiple sections.
* Read ulSectionLength bytes from the MACB receive buffers to pcTo.
* ulTotalFrameLength is the size of the entire frame. Generally vMACBRead
* will be repetedly called until the sum of all the ulSectionLenths totals
* the value of ulTotalFrameLength.
*
* \param *pcTo Address of the buffer
* \param ulSectionLength Length of the buffer
* \param ulTotalFrameLength Length of the frame
*/
void vMACBRead( char *pcTo, unsigned long ulSectionLength, unsigned long ulTotalFrameLength );
/**
* \brief Called by the Tx interrupt, this function traverses the buffers used to
* hold the frame that has just completed transmission and marks each as
* free again.
*/
void vClearMACBTxBuffer( void );
/**
* \brief Suspend on a semaphore waiting either for the semaphore to be obtained
* or a timeout. The semaphore is used by the MACB ISR to indicate that
* data has been received and is ready for processing.
*
* \param ulTimeOut time to wait for an input
*
*/
void vMACBWaitForInput( unsigned long ulTimeOut );
/**
* \brief Function to get length of the next frame in the receive buffers
*
* \return the length of the next frame in the receive buffers.
*/
unsigned long ulMACBInputLength( void );
/**
* \brief Set the MACB Physical address (SA1B & SA1T registers).
*
* \param *MACAddress the MAC address to set.
*/
void vMACBSetMACAddress(const char * MACAddress);
/**
* \brief Disable MACB operations (Tx and Rx).
*
* \param *macb Base address of the MACB
*/
void vDisableMACBOperations(volatile avr32_macb_t * macb);
#endif

View file

@ -9,7 +9,7 @@
* - AppNote:
*
* \author Atmel Corporation: http://www.atmel.com \n
* Support email: avr32@atmel.com
* Support and FAQ: http://support.atmel.no/
*
*****************************************************************************/
@ -44,297 +44,275 @@
#include "pm.h"
/*! \name PM Writable Bit-Field Registers
*/
//! @{
typedef union
{
unsigned long mcctrl;
avr32_pm_mcctrl_t MCCTRL;
} u_avr32_pm_mcctrl_t;
typedef union
{
unsigned long cksel;
avr32_pm_cksel_t CKSEL;
} u_avr32_pm_cksel_t;
typedef union
{
unsigned long pll;
avr32_pm_pll_t PLL;
} u_avr32_pm_pll_t;
typedef union
{
unsigned long oscctrl0;
avr32_pm_oscctrl0_t OSCCTRL0;
} u_avr32_pm_oscctrl0_t;
typedef union
{
unsigned long oscctrl1;
avr32_pm_oscctrl1_t OSCCTRL1;
} u_avr32_pm_oscctrl1_t;
typedef union
{
unsigned long oscctrl32;
avr32_pm_oscctrl32_t OSCCTRL32;
} u_avr32_pm_oscctrl32_t;
typedef union
{
unsigned long ier;
avr32_pm_ier_t IER;
} u_avr32_pm_ier_t;
typedef union
{
unsigned long idr;
avr32_pm_idr_t IDR;
} u_avr32_pm_idr_t;
typedef union
{
unsigned long icr;
avr32_pm_icr_t ICR;
} u_avr32_pm_icr_t;
typedef union
{
unsigned long gcctrl;
avr32_pm_gcctrl_t GCCTRL;
} u_avr32_pm_gcctrl_t;
typedef union
{
unsigned long rccr;
avr32_pm_rccr_t RCCR;
} u_avr32_pm_rccr_t;
typedef union
{
unsigned long bgcr;
avr32_pm_bgcr_t BGCR;
} u_avr32_pm_bgcr_t;
typedef union
{
unsigned long vregcr;
avr32_pm_vregcr_t VREGCR;
} u_avr32_pm_vregcr_t;
typedef union
{
unsigned long bod;
avr32_pm_bod_t BOD;
} u_avr32_pm_bod_t;
//! @}
/*! \brief Sets the mode of the oscillator 0.
*
* \param pm Base address of the Power Manager (i.e. &AVR32_PM).
* \param mode Oscillator 0 mode (i.e. AVR32_PM_OSCCTRL0_MODE_x).
*/
static void pm_set_osc0_mode(volatile avr32_pm_t *pm, unsigned int mode)
{
// Read
u_avr32_pm_oscctrl0_t u_avr32_pm_oscctrl0 = {pm->oscctrl0};
// Modify
u_avr32_pm_oscctrl0.OSCCTRL0.mode = mode;
// Write
pm->oscctrl0 = u_avr32_pm_oscctrl0.oscctrl0;
}
void pm_enable_osc0_ext_clock(volatile avr32_pm_t *pm)
{
union {
unsigned long oscctrl0;
avr32_pm_oscctrl0_t OSCCTRL0;
} oscctrl0 ;
// Read
oscctrl0.oscctrl0 = pm->oscctrl0;
// Modify
oscctrl0.OSCCTRL0.mode = AVR32_PM_OSCCTRL0_MODE_EXT_CLOCK;
// Write
pm->oscctrl0 = oscctrl0.oscctrl0;
pm_set_osc0_mode(pm, AVR32_PM_OSCCTRL0_MODE_EXT_CLOCK);
}
void pm_enable_osc0_crystal(volatile avr32_pm_t *pm, unsigned int fosc0)
{
union {
unsigned long oscctrl0;
avr32_pm_oscctrl0_t OSCCTRL0;
} oscctrl0 ;
// Read
oscctrl0.oscctrl0 = pm->oscctrl0;
// Modify
oscctrl0.OSCCTRL0.mode = (fosc0 < 8000000) ? AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G2 :
AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G3;
// Write
pm->oscctrl0 = oscctrl0.oscctrl0;
pm_set_osc0_mode(pm, (fosc0 < 8000000) ? AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G2 :
AVR32_PM_OSCCTRL0_MODE_CRYSTAL_G3);
}
void pm_enable_clk0(volatile avr32_pm_t *pm, unsigned int startup)
{
union {
avr32_pm_mcctrl_t MCCTRL;
unsigned long mcctrl;
} mcctrl;
union {
unsigned long oscctrl0;
avr32_pm_oscctrl0_t OSCCTRL0;
} oscctrl0 ;
// Read register
mcctrl.mcctrl = pm->mcctrl;
oscctrl0.oscctrl0 = pm->oscctrl0;
// Modify
mcctrl.MCCTRL.osc0en = 1;
oscctrl0.OSCCTRL0.startup = startup;
// Write back
pm->oscctrl0 = oscctrl0.oscctrl0;
pm->mcctrl = mcctrl.mcctrl;
while(!pm->ISR.osc0rdy); //For osc output valid
pm_enable_clk0_no_wait(pm, startup);
pm_wait_for_clk0_ready(pm);
}
void pm_disable_clk0(volatile avr32_pm_t *pm)
{
union {
avr32_pm_mcctrl_t MCCTRL;
unsigned long mcctrl;
} mcctrl;
// Read register
mcctrl.mcctrl = pm->mcctrl;
// Modify
mcctrl.MCCTRL.osc0en = 0;
// Write back
pm->mcctrl = mcctrl.mcctrl;
pm->mcctrl &= ~AVR32_PM_MCCTRL_OSC0EN_MASK;
}
void pm_enable_clk0_no_wait(volatile avr32_pm_t *pm, unsigned int startup)
{
union {
avr32_pm_mcctrl_t MCCTRL;
unsigned long mcctrl;
} mcctrl;
union {
unsigned long oscctrl0;
avr32_pm_oscctrl0_t OSCCTRL0;
} oscctrl0 ;
// Read register
mcctrl.mcctrl = pm->mcctrl;
oscctrl0.oscctrl0 = pm->oscctrl0;
u_avr32_pm_oscctrl0_t u_avr32_pm_oscctrl0 = {pm->oscctrl0};
// Modify
mcctrl.MCCTRL.osc0en = 1;
oscctrl0.OSCCTRL0.startup=startup;
u_avr32_pm_oscctrl0.OSCCTRL0.startup = startup;
// Write back
pm->mcctrl = mcctrl.mcctrl;
pm->oscctrl0 = oscctrl0.oscctrl0;
pm->oscctrl0 = u_avr32_pm_oscctrl0.oscctrl0;
pm->mcctrl |= AVR32_PM_MCCTRL_OSC0EN_MASK;
}
void pm_wait_for_clk0_ready(volatile avr32_pm_t *pm)
{
while(!pm->ISR.osc0rdy);
while (!(pm->poscsr & AVR32_PM_POSCSR_OSC0RDY_MASK));
}
/*! \brief Sets the mode of the oscillator 1.
*
* \param pm Base address of the Power Manager (i.e. &AVR32_PM).
* \param mode Oscillator 1 mode (i.e. AVR32_PM_OSCCTRL1_MODE_x).
*/
static void pm_set_osc1_mode(volatile avr32_pm_t *pm, unsigned int mode)
{
// Read
u_avr32_pm_oscctrl1_t u_avr32_pm_oscctrl1 = {pm->oscctrl1};
// Modify
u_avr32_pm_oscctrl1.OSCCTRL1.mode = mode;
// Write
pm->oscctrl1 = u_avr32_pm_oscctrl1.oscctrl1;
}
void pm_enable_osc1_ext_clock(volatile avr32_pm_t *pm)
{
union {
unsigned long oscctrl1;
avr32_pm_oscctrl1_t OSCCTRL1;
} oscctrl1 ;
// Read
oscctrl1.oscctrl1= pm->oscctrl1;
// Modify
oscctrl1.OSCCTRL1.mode = AVR32_PM_OSCCTRL1_MODE_EXT_CLOCK;
// Write
pm->oscctrl1 = oscctrl1.oscctrl1;
pm_set_osc1_mode(pm, AVR32_PM_OSCCTRL1_MODE_EXT_CLOCK);
}
void pm_enable_osc1_crystal(volatile avr32_pm_t *pm, unsigned int fosc1)
{
union {
unsigned long oscctrl1;
avr32_pm_oscctrl1_t OSCCTRL1;
} oscctrl1 ;
// Read
oscctrl1.oscctrl1= pm->oscctrl1;
// Modify
oscctrl1.OSCCTRL1.mode = (fosc1 < 8000000) ? AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G2 :
AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G3;
// Write
pm->oscctrl1 = oscctrl1.oscctrl1;
pm_set_osc1_mode(pm, (fosc1 < 8000000) ? AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G2 :
AVR32_PM_OSCCTRL1_MODE_CRYSTAL_G3);
}
void pm_enable_clk1(volatile avr32_pm_t *pm, unsigned int startup)
{
union {
avr32_pm_mcctrl_t MCCTRL;
unsigned long mcctrl;
} mcctrl;
union {
unsigned long oscctrl1;
avr32_pm_oscctrl1_t OSCCTRL1;
} oscctrl1 ;
// Read register
mcctrl.mcctrl = pm->mcctrl;
oscctrl1.oscctrl1 = pm->oscctrl1;
mcctrl.MCCTRL.osc1en = 1;
oscctrl1.OSCCTRL1.startup=startup;
// Write back
pm->oscctrl1 = oscctrl1.oscctrl1;
pm->mcctrl = mcctrl.mcctrl;
while(!pm->ISR.osc1rdy);
pm_enable_clk1_no_wait(pm, startup);
pm_wait_for_clk1_ready(pm);
}
void pm_disable_clk1(volatile avr32_pm_t *pm)
{
union {
avr32_pm_mcctrl_t MCCTRL;
unsigned long mcctrl;
} mcctrl;
// Read register
mcctrl.mcctrl = pm->mcctrl;
// Modify
mcctrl.MCCTRL.osc1en = 0;
// Write back
pm->mcctrl = mcctrl.mcctrl;
pm->mcctrl &= ~AVR32_PM_MCCTRL_OSC1EN_MASK;
}
void pm_enable_clk1_no_wait(volatile avr32_pm_t *pm, unsigned int startup)
{
union {
avr32_pm_mcctrl_t MCCTRL;
unsigned long mcctrl;
} mcctrl;
union {
unsigned long oscctrl1;
avr32_pm_oscctrl1_t OSCCTRL1;
} oscctrl1 ;
// Read register
mcctrl.mcctrl = pm->mcctrl;
oscctrl1.oscctrl1 = pm->oscctrl1;
mcctrl.MCCTRL.osc1en = 1;
oscctrl1.OSCCTRL1.startup=startup;
u_avr32_pm_oscctrl1_t u_avr32_pm_oscctrl1 = {pm->oscctrl1};
// Modify
u_avr32_pm_oscctrl1.OSCCTRL1.startup = startup;
// Write back
pm->oscctrl1 = oscctrl1.oscctrl1;
pm->mcctrl = mcctrl.mcctrl;
pm->oscctrl1 = u_avr32_pm_oscctrl1.oscctrl1;
pm->mcctrl |= AVR32_PM_MCCTRL_OSC1EN_MASK;
}
void pm_wait_for_clk1_ready(volatile avr32_pm_t *pm)
{
while(!pm->ISR.osc1rdy);
while (!(pm->poscsr & AVR32_PM_POSCSR_OSC1RDY_MASK));
}
/*! \brief Sets the mode of the 32-kHz oscillator.
*
* \param pm Base address of the Power Manager (i.e. &AVR32_PM).
* \param mode 32-kHz oscillator mode (i.e. AVR32_PM_OSCCTRL32_MODE_x).
*/
static void pm_set_osc32_mode(volatile avr32_pm_t *pm, unsigned int mode)
{
// Read
u_avr32_pm_oscctrl32_t u_avr32_pm_oscctrl32 = {pm->oscctrl32};
// Modify
u_avr32_pm_oscctrl32.OSCCTRL32.mode = mode;
// Write
pm->oscctrl32 = u_avr32_pm_oscctrl32.oscctrl32;
}
void pm_enable_osc32_ext_clock(volatile avr32_pm_t *pm)
{
union {
unsigned long oscctrl32;
avr32_pm_oscctrl32_t OSCCTRL32;
} u_ctrl;
u_ctrl.oscctrl32 = pm->oscctrl32;
u_ctrl.OSCCTRL32.mode = AVR32_PM_OSCCTRL32_MODE_EXT_CLOCK;
pm->oscctrl32 = u_ctrl.oscctrl32;
pm_set_osc32_mode(pm, AVR32_PM_OSCCTRL32_MODE_EXT_CLOCK);
}
void pm_enable_osc32_crystal(volatile avr32_pm_t *pm)
{
union {
unsigned long oscctrl32;
avr32_pm_oscctrl32_t OSCCTRL32;
} u_ctrl;
u_ctrl.oscctrl32 = pm->oscctrl32;
u_ctrl.OSCCTRL32.mode = AVR32_PM_OSCCTRL32_MODE_CRYSTAL;
pm->oscctrl32 = u_ctrl.oscctrl32;
pm_set_osc32_mode(pm, AVR32_PM_OSCCTRL32_MODE_CRYSTAL);
}
void pm_enable_clk32(volatile avr32_pm_t *pm, unsigned int startup)
{
union {
unsigned long oscctrl32;
avr32_pm_oscctrl32_t OSCCTRL32;
} oscctrl32 ;
// Read register
oscctrl32.oscctrl32 = pm->oscctrl32;
// Modify
oscctrl32.OSCCTRL32.osc32en = 1;
oscctrl32.OSCCTRL32.startup=startup;
// Write back
pm->oscctrl32 = oscctrl32.oscctrl32;
while(!pm->ISR.osc32rdy);
pm_enable_clk32_no_wait(pm, startup);
pm_wait_for_clk32_ready(pm);
}
void pm_disable_clk32(volatile avr32_pm_t *pm)
{
// To get rid of a GCC bug
// This makes C code longer, but not ASM
union {
unsigned long oscctrl32;
avr32_pm_oscctrl32_t OSCCTRL32;
} oscctrl32 ;
// Read register
oscctrl32.oscctrl32 = pm->oscctrl32;
// Modify
oscctrl32.OSCCTRL32.osc32en = 0;
// Write back
pm->oscctrl32 = oscctrl32.oscctrl32;
pm->oscctrl32 &= ~AVR32_PM_OSCCTRL32_OSC32EN_MASK;
}
void pm_enable_clk32_no_wait(volatile avr32_pm_t *pm, unsigned int startup)
{
union {
unsigned long oscctrl32;
avr32_pm_oscctrl32_t OSCCTRL32;
} oscctrl32 ;
// Read register
oscctrl32.oscctrl32 = pm->oscctrl32;
u_avr32_pm_oscctrl32_t u_avr32_pm_oscctrl32 = {pm->oscctrl32};
// Modify
oscctrl32.OSCCTRL32.osc32en = 1;
oscctrl32.OSCCTRL32.startup=startup;
u_avr32_pm_oscctrl32.OSCCTRL32.osc32en = 1;
u_avr32_pm_oscctrl32.OSCCTRL32.startup = startup;
// Write back
pm->oscctrl32 = oscctrl32.oscctrl32;
pm->oscctrl32 = u_avr32_pm_oscctrl32.oscctrl32;
}
void pm_wait_for_clk32_ready(volatile avr32_pm_t *pm)
{
// To get rid of a GCC bug
// This makes C code longer, but not ASM
while(!pm->ISR.osc32rdy);
while (!(pm->poscsr & AVR32_PM_POSCSR_OSC32RDY_MASK));
}
@ -346,29 +324,21 @@ void pm_cksel(volatile avr32_pm_t *pm,
unsigned int hsbdiv,
unsigned int hsbsel)
{
// Force the compiler to generate only one 32 bits access
union {
avr32_pm_cksel_t selval ;
unsigned long uword32;
} cksel;
u_avr32_pm_cksel_t u_avr32_pm_cksel = {0};
cksel.uword32 = 0;
u_avr32_pm_cksel.CKSEL.cpusel = hsbsel;
u_avr32_pm_cksel.CKSEL.cpudiv = hsbdiv;
u_avr32_pm_cksel.CKSEL.hsbsel = hsbsel;
u_avr32_pm_cksel.CKSEL.hsbdiv = hsbdiv;
u_avr32_pm_cksel.CKSEL.pbasel = pbasel;
u_avr32_pm_cksel.CKSEL.pbadiv = pbadiv;
u_avr32_pm_cksel.CKSEL.pbbsel = pbbsel;
u_avr32_pm_cksel.CKSEL.pbbdiv = pbbdiv;
cksel.selval.cpudiv = hsbdiv;
cksel.selval.cpusel = hsbsel;
cksel.selval.hsbdiv = hsbdiv;
cksel.selval.hsbsel = hsbsel;
cksel.selval.pbbdiv = pbbdiv;
cksel.selval.pbbsel = pbbsel;
cksel.selval.pbadiv = pbadiv;
cksel.selval.pbasel = pbasel;
pm->cksel = cksel.uword32;
pm->cksel = u_avr32_pm_cksel.cksel;
// Wait for ckrdy bit and then clear it
while(!(pm->ISR.ckrdy));
return;
while (!(pm->poscsr & AVR32_PM_POSCSR_CKRDY_MASK));
}
@ -377,42 +347,30 @@ void pm_gc_setup(volatile avr32_pm_t *pm,
unsigned int osc_or_pll, // Use Osc (=0) or PLL (=1)
unsigned int pll_osc, // Sel Osc0/PLL0 or Osc1/PLL1
unsigned int diven,
unsigned int div) {
union {
unsigned long gcctrl;
avr32_pm_gcctrl_t GCCTRL;
} u_gc;
unsigned int div)
{
u_avr32_pm_gcctrl_t u_avr32_pm_gcctrl = {0};
u_gc.GCCTRL.oscsel = pll_osc;
u_gc.GCCTRL.pllsel = osc_or_pll;
u_gc.GCCTRL.diven = diven;
u_gc.GCCTRL.div = div;
u_gc.GCCTRL.cen = 0; // Disable GC first
pm->gcctrl[gc] = u_gc.gcctrl;
u_avr32_pm_gcctrl.GCCTRL.oscsel = pll_osc;
u_avr32_pm_gcctrl.GCCTRL.pllsel = osc_or_pll;
u_avr32_pm_gcctrl.GCCTRL.diven = diven;
u_avr32_pm_gcctrl.GCCTRL.div = div;
pm->gcctrl[gc] = u_avr32_pm_gcctrl.gcctrl;
}
void pm_gc_enable(volatile avr32_pm_t *pm,
unsigned int gc) {
union {
unsigned long gcctrl;
avr32_pm_gcctrl_t GCCTRL;
} u_gc;
u_gc.gcctrl = pm->gcctrl[gc];
u_gc.GCCTRL.cen = 1;
pm->gcctrl[gc] = u_gc.gcctrl;
unsigned int gc)
{
pm->gcctrl[gc] |= AVR32_PM_GCCTRL_CEN_MASK;
}
void pm_gc_disable(volatile avr32_pm_t *pm,
unsigned int gc) {
union {
unsigned long gcctrl;
avr32_pm_gcctrl_t GCCTRL;
} u_gc;
u_gc.gcctrl = pm->gcctrl[gc];
u_gc.GCCTRL.cen = 0;
pm->gcctrl[gc] = u_gc.gcctrl;
unsigned int gc)
{
pm->gcctrl[gc] &= ~AVR32_PM_GCCTRL_CEN_MASK;
}
@ -421,25 +379,16 @@ void pm_pll_setup(volatile avr32_pm_t *pm,
unsigned int mul,
unsigned int div,
unsigned int osc,
unsigned int lockcount) {
unsigned int lockcount)
{
u_avr32_pm_pll_t u_avr32_pm_pll = {0};
union {
unsigned long pll ;
avr32_pm_pll_t PLL ;
} u_pll;
u_avr32_pm_pll.PLL.pllosc = osc;
u_avr32_pm_pll.PLL.plldiv = div;
u_avr32_pm_pll.PLL.pllmul = mul;
u_avr32_pm_pll.PLL.pllcount = lockcount;
u_pll.pll=0;
u_pll.PLL.pllmul = mul;
u_pll.PLL.plldiv = div;
u_pll.PLL.pllosc = osc;
u_pll.PLL.pllcount = lockcount;
u_pll.PLL.pllopt = 0;
u_pll.PLL.plltest = 0;
(pm->pll)[pll] = u_pll.pll;
pm->pll[pll] = u_avr32_pm_pll.pll;
}
@ -447,53 +396,38 @@ void pm_pll_set_option(volatile avr32_pm_t *pm,
unsigned int pll,
unsigned int pll_freq,
unsigned int pll_div2,
unsigned int pll_wbwdisable) {
union {
unsigned long pll ;
avr32_pm_pll_t PLL ;
} u_pll;
u_pll.pll = (pm->pll)[pll];
u_pll.PLL.pllopt = pll_freq | (pll_div2<<1) | (pll_wbwdisable<<2);
(pm->pll)[pll] = u_pll.pll;
unsigned int pll_wbwdisable)
{
u_avr32_pm_pll_t u_avr32_pm_pll = {pm->pll[pll]};
u_avr32_pm_pll.PLL.pllopt = pll_freq | (pll_div2 << 1) | (pll_wbwdisable << 2);
pm->pll[pll] = u_avr32_pm_pll.pll;
}
unsigned int pm_pll_get_option(volatile avr32_pm_t *pm,
unsigned int pll) {
return (pm->PLL)[pll].pllopt;
unsigned int pll)
{
return (pm->pll[pll] & AVR32_PM_PLLOPT_MASK) >> AVR32_PM_PLLOPT_OFFSET;
}
void pm_pll_enable(volatile avr32_pm_t *pm,
unsigned int pll) {
union {
unsigned long pll ;
avr32_pm_pll_t PLL ;
} u_pll;
u_pll.pll = (pm->pll)[pll];
u_pll.PLL.pllen = 1;
(pm->pll)[pll] = u_pll.pll;
unsigned int pll)
{
pm->pll[pll] |= AVR32_PM_PLLEN_MASK;
}
void pm_pll_disable(volatile avr32_pm_t *pm,
unsigned int pll) {
union {
unsigned long pll ;
avr32_pm_pll_t PLL ;
} u_pll;
u_pll.pll = (pm->pll)[pll];
u_pll.PLL.pllen = 0;
(pm->pll)[pll] = u_pll.pll;
unsigned int pll)
{
pm->pll[pll] &= ~AVR32_PM_PLLEN_MASK;
}
void pm_wait_for_pll0_locked(volatile avr32_pm_t *pm)
{
while(!pm->ISR.lock0);
while (!(pm->poscsr & AVR32_PM_POSCSR_LOCK0_MASK));
// Bypass the lock signal of the PLL
pm->pll[0] |= AVR32_PM_PLL0_PLLBPL_MASK;
@ -502,7 +436,7 @@ void pm_wait_for_pll0_locked(volatile avr32_pm_t *pm)
void pm_wait_for_pll1_locked(volatile avr32_pm_t *pm)
{
while(!pm->ISR.lock1);
while (!(pm->poscsr & AVR32_PM_POSCSR_LOCK1_MASK));
// Bypass the lock signal of the PLL
pm->pll[1] |= AVR32_PM_PLL1_PLLBPL_MASK;
@ -511,16 +445,12 @@ void pm_wait_for_pll1_locked(volatile avr32_pm_t *pm)
void pm_switch_to_clock(volatile avr32_pm_t *pm, unsigned long clock)
{
union {
avr32_pm_mcctrl_t MCCTRL;
unsigned long mcctrl;
} mcctrl;
// Read
mcctrl.mcctrl = pm->mcctrl;
u_avr32_pm_mcctrl_t u_avr32_pm_mcctrl = {pm->mcctrl};
// Modify
mcctrl.MCCTRL.mcsel = clock;
// Write Back
pm->MCCTRL.mcsel = mcctrl.mcctrl;
u_avr32_pm_mcctrl.MCCTRL.mcsel = clock;
// Write back
pm->mcctrl = u_avr32_pm_mcctrl.mcctrl;
}
@ -532,77 +462,49 @@ void pm_switch_to_osc0(volatile avr32_pm_t *pm, unsigned int fosc0, unsigned int
}
void pm_bod_enable_irq(volatile struct avr32_pm_t *pm) {
union {
unsigned long ier ;
avr32_pm_ier_t IER ;
} u_ier;
u_ier.ier = 0;
u_ier.IER.boddet = 1;
pm->ier = u_ier.ier;
void pm_bod_enable_irq(volatile avr32_pm_t *pm)
{
pm->ier = AVR32_PM_IER_BODDET_MASK;
}
void pm_bod_disable_irq(volatile struct avr32_pm_t *pm) {
union {
unsigned long idr ;
avr32_pm_idr_t IDR ;
} u_idr;
u_idr.idr = 0;
u_idr.IDR.boddet = 1;
pm->idr = u_idr.idr;
void pm_bod_disable_irq(volatile avr32_pm_t *pm)
{
pm->idr = AVR32_PM_IDR_BODDET_MASK;
}
void pm_bod_clear_irq(volatile struct avr32_pm_t *pm) {
union {
unsigned long icr ;
avr32_pm_idr_t ICR ;
} u_icr;
u_icr.icr = 0;
u_icr.ICR.boddet = 1;
pm->icr = u_icr.icr;
void pm_bod_clear_irq(volatile avr32_pm_t *pm)
{
pm->icr = AVR32_PM_ICR_BODDET_MASK;
}
unsigned long pm_bod_get_irq_status(volatile struct avr32_pm_t *pm) {
return pm->ISR.boddet;
unsigned long pm_bod_get_irq_status(volatile avr32_pm_t *pm)
{
return ((pm->isr & AVR32_PM_ISR_BODDET_MASK) != 0);
}
unsigned long pm_bod_get_irq_enable_bit(volatile struct avr32_pm_t *pm) {
return pm->IMR.boddet;
unsigned long pm_bod_get_irq_enable_bit(volatile avr32_pm_t *pm)
{
return ((pm->imr & AVR32_PM_IMR_BODDET_MASK) != 0);
}
unsigned long pm_bod_get_level(volatile avr32_pm_t *pm) {
union {
unsigned long bod ;
avr32_pm_bod_t BOD ;
} u_bod;
u_bod.bod = pm->bod;
return (unsigned long) u_bod.BOD.level;
unsigned long pm_bod_get_level(volatile avr32_pm_t *pm)
{
return (pm->bod & AVR32_PM_BOD_LEVEL_MASK) >> AVR32_PM_BOD_LEVEL_OFFSET;
}
void pm_write_gplp(volatile avr32_pm_t *pm,unsigned long gplp, unsigned long value) {
(pm->gplp)[gplp] = value;
void pm_write_gplp(volatile avr32_pm_t *pm,unsigned long gplp, unsigned long value)
{
pm->gplp[gplp] = value;
}
unsigned long pm_read_gplp(volatile avr32_pm_t *pm,unsigned long gplp) {
return (pm->gplp)[gplp];
unsigned long pm_read_gplp(volatile avr32_pm_t *pm,unsigned long gplp)
{
return pm->gplp[gplp];
}

View file

@ -9,7 +9,7 @@
* - AppNote:
*
* \author Atmel Corporation: http://www.atmel.com \n
* Support email: avr32@atmel.com
* Support and FAQ: http://support.atmel.no/
*
*****************************************************************************/
@ -44,15 +44,7 @@
#ifndef _PM_H_
#define _PM_H_
#if __GNUC__
# include <avr32/io.h>
#elif __ICCAVR32__
# include <avr32/iouc3a0512.h>
# include <avr32/uc3a0512.h>
#else
# error Unknown compiler
#endif
#include <avr32/io.h>
#include "compiler.h"
#include "preprocessor.h"
@ -70,6 +62,22 @@
#define SLEEP(mode) {__asm__ __volatile__ ("sleep "STRINGZ(mode));}
/*! \brief Gets the MCU reset cause.
*
* \param pm Base address of the Power Manager instance (i.e. &AVR32_PM).
*
* \return The MCU reset cause which can be masked with the
* \c AVR32_PM_RCAUSE_x_MASK bit-masks to isolate specific causes.
*/
#if __GNUC__
__attribute__((__always_inline__))
#endif
extern __inline__ unsigned int pm_get_reset_cause(volatile avr32_pm_t *pm)
{
return pm->rcause;
}
/*!
* \brief This function will enable the external clock mode of the oscillator 0.
* \param pm Base address of the Power Manager (i.e. &AVR32_PM)

View file

@ -10,7 +10,7 @@
* - AppNote:
*
* \author Atmel Corporation: http://www.atmel.com \n
* Support email: avr32@atmel.com
* Support and FAQ: http://support.atmel.no/
*
******************************************************************************/
@ -42,14 +42,7 @@
*/
#if __GNUC__
# include <avr32/io.h>
#elif __ICCAVR32__
# include <avr32/iouc3a0512.h>
#else
# error Unknown compiler
#endif
#include <avr32/io.h>
#include "compiler.h"
#include "tc.h"

View file

@ -10,7 +10,7 @@
* - AppNote:
*
* \author Atmel Corporation: http://www.atmel.com \n
* Support email: avr32@atmel.com
* Support and FAQ: http://support.atmel.no/
*
******************************************************************************/
@ -45,17 +45,11 @@
#ifndef _TC_H_
#define _TC_H_
#if __GNUC__
# include <avr32/io.h>
#elif __ICCAVR32__
# include <avr32/iouc3a0512.h>
#else
# error Unknown compiler
#endif
#include <avr32/io.h>
//! TC driver functions return value in case of invalid argument(s).
#define TC_INVALID_ARGUMENT -1
#define TC_INVALID_ARGUMENT (-1)
//! Number of timer/counter channels.
#define TC_NUMBER_OF_CHANNELS (sizeof(((avr32_tc_t *)0)->channel) / sizeof(avr32_tc_channel_t))

View file

@ -0,0 +1,448 @@
/*This file is prepared for Doxygen automatic documentation generation.*/
/*! \file *********************************************************************
*
* \brief USART driver for AVR32 UC3.
*
* This file contains basic functions for the AVR32 USART, with support for all
* modes, settings and clock speeds.
*
* - Compiler: IAR EWAVR32 and GNU GCC for AVR32
* - Supported devices: All AVR32 devices with a USART module can be used.
* - AppNote:
*
* \author Atmel Corporation: http://www.atmel.com \n
* Support and FAQ: http://support.atmel.no/
*
******************************************************************************/
/* Copyright (c) 2007, Atmel Corporation All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of ATMEL may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
* SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "usart.h"
//------------------------------------------------------------------------------
/*! \name Private Functions
*/
//! @{
/*! \brief Checks if the USART is in multidrop mode.
*
* \param usart Base address of the USART instance.
*
* \return \c 1 if the USART is in multidrop mode, otherwise \c 0.
*/
#if __GNUC__
__attribute__((__always_inline__))
#endif
static __inline__ int usart_mode_is_multidrop(volatile avr32_usart_t *usart)
{
return ((usart->mr >> AVR32_USART_MR_PAR_OFFSET) & AVR32_USART_MR_PAR_MULTI) == AVR32_USART_MR_PAR_MULTI;
}
/*! \brief Calculates a clock divider (\e CD) that gets the USART as close to a
* wanted baudrate as possible.
*
* \todo manage the FP fractal part to avoid big errors
*
* Baudrate calculation:
* \f$ baudrate = \frac{Selected Clock}{16 \times CD} \f$ with 16x oversampling or
* \f$ baudrate = \frac{Selected Clock}{8 \times CD} \f$ with 8x oversampling or
* \f$ baudrate = \frac{Selected Clock}{CD} \f$ with SYNC bit set to allow high speed.
*
* \param usart Base address of the USART instance.
* \param baudrate Wanted baudrate.
* \param pba_hz USART module input clock frequency (PBA clock, Hz).
*
* \retval USART_SUCCESS Baudrate successfully initialized.
* \retval USART_INVALID_INPUT Wanted baudrate is impossible with given clock speed.
*/
static int usart_set_baudrate(volatile avr32_usart_t *usart, unsigned int baudrate, long pba_hz)
{
// Clock divider.
int cd;
// Baudrate calculation.
if (baudrate < pba_hz / 16)
{
// Use 16x oversampling, clear SYNC bit.
usart->mr &=~ (AVR32_USART_MR_OVER_MASK | AVR32_USART_MR_SYNC_MASK);
cd = (pba_hz + 8 * baudrate) / (16 * baudrate);
if ((cd >65535)) return USART_INVALID_INPUT;
}
else if (baudrate < pba_hz / 8)
{
// Use 8x oversampling.
usart->mr |= AVR32_USART_MR_OVER_MASK;
// clear SYNC bit
usart->mr &=~ AVR32_USART_MR_SYNC_MASK;
cd = (pba_hz + 4 * baudrate) / (8 * baudrate);
if ((cd < 1)||(cd >65535)) return USART_INVALID_INPUT;
}
else
{
// set SYNC to 1
usart->mr |= AVR32_USART_MR_SYNC_MASK;
// use PBA/BaudRate
cd = (pba_hz / baudrate);
}
usart->brgr = cd << AVR32_USART_BRGR_CD_OFFSET;
return USART_SUCCESS;
}
//! @}
//------------------------------------------------------------------------------
/*! \name Initialization Functions
*/
//! @{
void usart_reset(volatile avr32_usart_t *usart)
{
// Disable all USART interrupts.
// Interrupts needed should be set explicitly on every reset.
usart->idr = 0xFFFFFFFF;
// Reset mode and other registers that could cause unpredictable behavior after reset.
usart->mr = 0;
usart->rtor = 0;
usart->ttgr = 0;
// Shutdown TX and RX (will be re-enabled when setup has successfully completed),
// reset status bits and turn off DTR and RTS.
usart->cr = AVR32_USART_CR_RSTRX_MASK |
AVR32_USART_CR_RSTTX_MASK |
AVR32_USART_CR_RSTSTA_MASK |
AVR32_USART_CR_RSTIT_MASK |
AVR32_USART_CR_RSTNACK_MASK |
AVR32_USART_CR_DTRDIS_MASK |
AVR32_USART_CR_RTSDIS_MASK;
}
int usart_init_rs232(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz)
{
// Reset the USART and shutdown TX and RX.
usart_reset(usart);
// Check input values.
if (!opt) // Null pointer.
return USART_INVALID_INPUT;
if (opt->charlength < 5 || opt->charlength > 9 ||
opt->paritytype > 7 ||
opt->stopbits > 2 + 255 ||
opt->channelmode > 3)
return USART_INVALID_INPUT;
if (usart_set_baudrate(usart, opt->baudrate, pba_hz) == USART_INVALID_INPUT)
return USART_INVALID_INPUT;
if (opt->charlength == 9)
{
// Character length set to 9 bits. MODE9 dominates CHRL.
usart->mr |= AVR32_USART_MR_MODE9_MASK;
}
else
{
// CHRL gives the character length (- 5) when MODE9 = 0.
usart->mr |= (opt->charlength - 5) << AVR32_USART_MR_CHRL_OFFSET;
}
usart->mr |= (opt->channelmode << AVR32_USART_MR_CHMODE_OFFSET) |
(opt->paritytype << AVR32_USART_MR_PAR_OFFSET);
if (opt->stopbits > USART_2_STOPBITS)
{
// Set two stop bits
usart->mr |= AVR32_USART_MR_NBSTOP_2 << AVR32_USART_MR_NBSTOP_OFFSET;
// and a timeguard period gives the rest.
usart->ttgr = opt->stopbits - USART_2_STOPBITS;
}
else
// Insert 1, 1.5 or 2 stop bits.
usart->mr |= opt->stopbits << AVR32_USART_MR_NBSTOP_OFFSET;
// Setup complete; enable communication.
// Enable input and output.
usart->cr |= AVR32_USART_CR_TXEN_MASK |
AVR32_USART_CR_RXEN_MASK;
return USART_SUCCESS;
}
int usart_init_hw_handshaking(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz)
{
// First: Setup standard RS232.
if (usart_init_rs232(usart, opt, pba_hz) == USART_INVALID_INPUT)
return USART_INVALID_INPUT;
// Clear previous mode.
usart->mr &= ~AVR32_USART_MR_MODE_MASK;
// Hardware handshaking.
usart->mr |= USART_MODE_HW_HSH << AVR32_USART_MR_MODE_OFFSET;
return USART_SUCCESS;
}
int usart_init_IrDA(volatile avr32_usart_t *usart, const usart_options_t *opt,
long pba_hz, unsigned char irda_filter)
{
// First: Setup standard RS232.
if (usart_init_rs232(usart, opt, pba_hz) == USART_INVALID_INPUT)
return USART_INVALID_INPUT;
// Set IrDA counter.
usart->ifr = irda_filter;
// Activate "low-pass filtering" of input.
usart->mr |= AVR32_USART_MR_FILTER_MASK;
return USART_SUCCESS;
}
int usart_init_modem(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz)
{
// First: Setup standard RS232.
if (usart_init_rs232(usart, opt, pba_hz) == USART_INVALID_INPUT)
return USART_INVALID_INPUT;
// Clear previous mode.
usart->mr &= ~AVR32_USART_MR_MODE_MASK;
// Set modem mode.
usart->mr |= USART_MODE_MODEM << AVR32_USART_MR_MODE_OFFSET;
return USART_SUCCESS;
}
int usart_init_rs485(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz)
{
// First: Setup standard RS232.
if (usart_init_rs232(usart, opt, pba_hz) == USART_INVALID_INPUT)
return USART_INVALID_INPUT;
// Clear previous mode.
usart->mr &= ~AVR32_USART_MR_MODE_MASK;
// Set RS485 mode.
usart->mr |= USART_MODE_RS485 << AVR32_USART_MR_MODE_OFFSET;
return USART_SUCCESS;
}
int usart_init_iso7816(volatile avr32_usart_t *usart, const iso7816_options_t *opt, int t, long pba_hz)
{
// Reset the USART and shutdown TX and RX.
usart_reset(usart);
// Check input values.
if (!opt) // Null pointer.
return USART_INVALID_INPUT;
if (t == 0)
{
// Set USART mode to ISO7816, T=0.
// The T=0 protocol always uses 2 stop bits.
usart->mr = (USART_MODE_ISO7816_T0 << AVR32_USART_MR_MODE_OFFSET) |
(AVR32_USART_MR_NBSTOP_2 << AVR32_USART_MR_NBSTOP_OFFSET) |
(opt->bit_order << AVR32_USART_MR_MSBF_OFFSET); // Allow MSBF in T=0.
}
else if (t == 1)
{
// Only LSB first in the T=1 protocol.
// max_iterations field is only used in T=0 mode.
if (opt->bit_order != 0 ||
opt->max_iterations != 0)
return USART_INVALID_INPUT;
// Set USART mode to ISO7816, T=1.
// The T=1 protocol always uses 1 stop bit.
usart->mr = (USART_MODE_ISO7816_T1 << AVR32_USART_MR_MODE_OFFSET) |
(AVR32_USART_MR_NBSTOP_1 << AVR32_USART_MR_NBSTOP_OFFSET);
}
else
return USART_INVALID_INPUT;
if (usart_set_baudrate(usart, opt->iso7816_hz, pba_hz) == USART_INVALID_INPUT)
return USART_INVALID_INPUT;
// Set FIDI register: bit rate = selected clock/FI_DI_ratio/16.
usart->fidi = opt->fidi_ratio;
// Set ISO7816 spesific options in the MODE register.
usart->mr |= (opt->inhibit_nack << AVR32_USART_MR_INACK_OFFSET) |
(opt->dis_suc_nack << AVR32_USART_MR_DSNACK_OFFSET) |
(opt->max_iterations << AVR32_USART_MR_MAX_ITERATION_OFFSET) |
AVR32_USART_MR_CLKO_MASK; // Enable clock output.
// Setup complete; enable input.
// Leave TX disabled for now.
usart->cr |= AVR32_USART_CR_RXEN_MASK;
return USART_SUCCESS;
}
//! @}
//------------------------------------------------------------------------------
/*! \name Transmit/Receive Functions
*/
//! @{
int usart_send_address(volatile avr32_usart_t *usart, int address)
{
// Check if USART is in multidrop / RS485 mode.
if (!usart_mode_is_multidrop(usart)) return USART_MODE_FAULT;
// Prepare to send an address.
usart->cr |= AVR32_USART_CR_SENDA_MASK;
// Write the address to TX.
usart_bw_write_char(usart, address);
return USART_SUCCESS;
}
int usart_write_char(volatile avr32_usart_t *usart, int c)
{
if (usart->csr & AVR32_USART_CSR_TXRDY_MASK)
{
usart->thr = c;
return USART_SUCCESS;
}
else
return USART_TX_BUSY;
}
int usart_putchar(volatile avr32_usart_t *usart, int c)
{
int timeout = USART_DEFAULT_TIMEOUT;
if (c == '\n')
{
do
{
if (!timeout--) return USART_FAILURE;
} while (usart_write_char(usart, '\r') != USART_SUCCESS);
timeout = USART_DEFAULT_TIMEOUT;
}
do
{
if (!timeout--) return USART_FAILURE;
} while (usart_write_char(usart, c) != USART_SUCCESS);
return USART_SUCCESS;
}
int usart_read_char(volatile avr32_usart_t *usart, int *c)
{
// Check for errors: frame, parity and overrun. In RS485 mode, a parity error
// would mean that an address char has been received.
if (usart->csr & (AVR32_USART_CSR_OVRE_MASK |
AVR32_USART_CSR_FRAME_MASK |
AVR32_USART_CSR_PARE_MASK))
return USART_RX_ERROR;
// No error; if we really did receive a char, read it and return SUCCESS.
if (usart->csr & AVR32_USART_CSR_RXRDY_MASK)
{
*c = (unsigned short)usart->rhr;
return USART_SUCCESS;
}
else
return USART_RX_EMPTY;
}
int usart_getchar(volatile avr32_usart_t *usart)
{
int c, ret;
while ((ret = usart_read_char(usart, &c)) == USART_RX_EMPTY);
if (ret == USART_RX_ERROR)
return USART_FAILURE;
return c;
}
void usart_write_line(volatile avr32_usart_t *usart, const char *string)
{
while (*string != '\0')
usart_putchar(usart, *string++);
}
int usart_get_echo_line(volatile avr32_usart_t *usart)
{
int rx_char;
int retval = USART_SUCCESS;
while (1)
{
rx_char = usart_getchar(usart);
if (rx_char == USART_FAILURE)
{
usart_write_line(usart, "Error!!!\n");
break;
}
if (rx_char == '\x03')
{
retval = USART_FAILURE;
break;
}
usart_putchar(usart, rx_char);
if (rx_char == '\r')
{
usart_putchar(usart, '\n');
break;
}
}
return retval;
}
//! @}

View file

@ -0,0 +1,475 @@
/*This file is prepared for Doxygen automatic documentation generation.*/
/*! \file *********************************************************************
*
* \brief USART driver for AVR32 UC3.
*
* This file contains basic functions for the AVR32 USART, with support for all
* modes, settings and clock speeds.
*
* - Compiler: IAR EWAVR32 and GNU GCC for AVR32
* - Supported devices: All AVR32 devices with a USART module can be used.
* - AppNote:
*
* \author Atmel Corporation: http://www.atmel.com \n
* Support and FAQ: http://support.atmel.no/
*
******************************************************************************/
/* Copyright (c) 2007, Atmel Corporation All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name of ATMEL may not be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL ``AS IS'' AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND
* SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef _USART_H_
#define _USART_H_
#include <avr32/io.h>
#include "compiler.h"
/*! \name Return Values
*/
//! @{
#define USART_SUCCESS 0 //!< Successful completion.
#define USART_FAILURE -1 //!< Failure because of some unspecified reason.
#define USART_INVALID_INPUT 1 //!< Input value out of range.
#define USART_INVALID_ARGUMENT -1 //!< Argument value out of range.
#define USART_TX_BUSY 2 //!< Transmitter was busy.
#define USART_RX_EMPTY 3 //!< Nothing was received.
#define USART_RX_ERROR 4 //!< Transmission error occurred.
#define USART_MODE_FAULT 5 //!< USART not in the appropriate mode.
//! @}
//! Default time-out value (number of attempts).
#define USART_DEFAULT_TIMEOUT 10000
/*! \name Parity Settings
*/
//! @{
#define USART_EVEN_PARITY AVR32_USART_MR_PAR_EVEN //!< Use even parity on character transmission.
#define USART_ODD_PARITY AVR32_USART_MR_PAR_ODD //!< Use odd parity on character transmission.
#define USART_SPACE_PARITY AVR32_USART_MR_PAR_SPACE //!< Use a space as parity bit.
#define USART_MARK_PARITY AVR32_USART_MR_PAR_MARK //!< Use a mark as parity bit.
#define USART_NO_PARITY AVR32_USART_MR_PAR_NONE //!< Don't use a parity bit.
#define USART_MULTIDROP_PARITY AVR32_USART_MR_PAR_MULTI //!< Parity bit is used to flag address characters.
//! @}
/*! \name Operating Modes
*/
//! @{
#define USART_MODE_NORMAL AVR32_USART_MR_MODE_NORMAL //!< Normal RS232 mode.
#define USART_MODE_RS485 AVR32_USART_MR_MODE_RS485 //!< RS485 mode.
#define USART_MODE_HW_HSH AVR32_USART_MR_MODE_HARDWARE //!< RS232 mode with hardware handshaking.
#define USART_MODE_MODEM AVR32_USART_MR_MODE_MODEM //!< Modem mode.
#define USART_MODE_ISO7816_T0 AVR32_USART_MR_MODE_ISO7816_T0 //!< ISO7816, T = 0 mode.
#define USART_MODE_ISO7816_T1 AVR32_USART_MR_MODE_ISO7816_T1 //!< ISO7816, T = 1 mode.
#define USART_MODE_IRDA AVR32_USART_MR_MODE_IRDA //!< IrDA mode.
#define USART_MODE_SW_HSH AVR32_USART_MR_MODE_SOFTWARE //!< RS232 mode with software handshaking.
//! @}
/*! \name Channel Modes
*/
//! @{
#define USART_NORMAL_CHMODE AVR32_USART_MR_CHMODE_NORMAL //!< Normal communication.
#define USART_AUTO_ECHO AVR32_USART_MR_CHMODE_ECHO //!< Echo data.
#define USART_LOCAL_LOOPBACK AVR32_USART_MR_CHMODE_LOCAL_LOOP //!< Local loopback.
#define USART_REMOTE_LOOPBACK AVR32_USART_MR_CHMODE_REMOTE_LOOP //!< Remote loopback.
//! @}
/*! \name Stop Bits Settings
*/
//! @{
#define USART_1_STOPBIT AVR32_USART_MR_NBSTOP_1 //!< Use 1 stop bit.
#define USART_1_5_STOPBITS AVR32_USART_MR_NBSTOP_1_5 //!< Use 1.5 stop bits.
#define USART_2_STOPBITS AVR32_USART_MR_NBSTOP_2 //!< Use 2 stop bits (for more, just give the number of bits).
//! @}
//! Input parameters when initializing RS232 and similar modes.
typedef struct
{
//! Set baudrate of the USART.
unsigned long baudrate;
//! Number of bits to transmit as a character (5 to 9).
unsigned char charlength;
//! How to calculate the parity bit: \ref USART_EVEN_PARITY, \ref USART_ODD_PARITY,
//! \ref USART_SPACE_PARITY, \ref USART_MARK_PARITY, \ref USART_NO_PARITY or
//! \ref USART_MULTIDROP_PARITY.
unsigned char paritytype;
//! Number of stop bits between two characters: \ref USART_1_STOPBIT,
//! \ref USART_1_5_STOPBITS, \ref USART_2_STOPBITS or any number from 3 to 257
//! which will result in a time guard period of that length between characters.
unsigned short stopbits;
//! Run the channel in testmode: \ref USART_NORMAL_CHMODE, \ref USART_AUTO_ECHO,
//! \ref USART_LOCAL_LOOPBACK or \ref USART_REMOTE_LOOPBACK.
unsigned char channelmode;
} usart_options_t;
//! Input parameters when initializing ISO7816 modes.
typedef struct
{
//! Set the frequency of the ISO7816 clock.
unsigned long iso7816_hz;
//! The number of ISO7816 clock ticks in every bit period (1 to 2047, 0 = disable clock).
//! Bit rate = \ref iso7816_hz / \ref fidi_ratio.
unsigned short fidi_ratio;
//! Inhibit Non Acknowledge:\n
//! - 0: the NACK is generated;\n
//! - 1: the NACK is not generated.
//!
//! \note This bit will be used only in ISO7816 mode, protocol T = 0 receiver.
int inhibit_nack;
//! Disable successive NACKs.
//! Successive parity errors are counted up to the value in the \ref max_iterations field.
//! These parity errors generate a NACK on the ISO line. As soon as this value is reached,
//! no addititional NACK is sent on the ISO line. The ITERATION flag is asserted.
int dis_suc_nack;
//! Max number of repetitions (0 to 7).
unsigned char max_iterations;
//! Bit order in transmitted characters:\n
//! - 0: LSB first;\n
//! - 1: MSB first.
int bit_order;
} iso7816_options_t;
//! Input parameters when initializing ISO7816 modes.
typedef struct
{
//! Set the frequency of the SPI clock.
unsigned long baudrate;
//! Number of bits to transmit as a character (5 to 9).
unsigned char charlength;
//! Run the channel in testmode: \ref USART_NORMAL_CHMODE, \ref USART_AUTO_ECHO,
//! \ref USART_LOCAL_LOOPBACK or \ref USART_REMOTE_LOOPBACK.
unsigned char channelmode;
//! Which SPI mode to use when transmitting.
unsigned char spimode;
} usart_spi_options_t;
//------------------------------------------------------------------------------
/*! \name Initialization Functions
*/
//! @{
/*! \brief Resets the USART and disables TX and RX.
*
* \param usart Base address of the USART instance.
*/
extern void usart_reset(volatile avr32_usart_t *usart);
/*! \brief Sets up the USART to use the standard RS232 protocol.
*
* \param usart Base address of the USART instance.
* \param opt Options needed to set up RS232 communication (see \ref usart_options_t).
* \param pba_hz USART module input clock frequency (PBA clock, Hz).
*
* \retval USART_SUCCESS Mode successfully initialized.
* \retval USART_INVALID_INPUT One or more of the arguments is out of valid range.
*/
extern int usart_init_rs232(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz);
/*! \brief Sets up the USART to use hardware handshaking.
*
* \param usart Base address of the USART instance.
* \param opt Options needed to set up RS232 communication (see \ref usart_options_t).
* \param pba_hz USART module input clock frequency (PBA clock, Hz).
*
* \retval USART_SUCCESS Mode successfully initialized.
* \retval USART_INVALID_INPUT One or more of the arguments is out of valid range.
*
* \note \ref usart_init_rs232 does not need to be invoked before this function.
*/
extern int usart_init_hw_handshaking(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz);
/*! \brief Sets up the USART to use the IrDA protocol.
*
* \param usart Base address of the USART instance.
* \param opt Options needed to set up RS232 communication (see \ref usart_options_t).
* \param pba_hz USART module input clock frequency (PBA clock, Hz).
* \param irda_filter Counter used to distinguish received ones from zeros.
*
* \retval USART_SUCCESS Mode successfully initialized.
* \retval USART_INVALID_INPUT One or more of the arguments is out of valid range.
*/
extern int usart_init_IrDA(volatile avr32_usart_t *usart, const usart_options_t *opt,
long pba_hz, unsigned char irda_filter);
/*! \brief Sets up the USART to use the modem protocol, activating dedicated inputs/outputs.
*
* \param usart Base address of the USART instance.
* \param opt Options needed to set up RS232 communication (see \ref usart_options_t).
* \param pba_hz USART module input clock frequency (PBA clock, Hz).
*
* \retval USART_SUCCESS Mode successfully initialized.
* \retval USART_INVALID_INPUT One or more of the arguments is out of valid range.
*/
extern int usart_init_modem(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz);
/*! \brief Sets up the USART to use the RS485 protocol.
*
* \param usart Base address of the USART instance.
* \param opt Options needed to set up RS232 communication (see \ref usart_options_t).
* \param pba_hz USART module input clock frequency (PBA clock, Hz).
*
* \retval USART_SUCCESS Mode successfully initialized.
* \retval USART_INVALID_INPUT One or more of the arguments is out of valid range.
*/
extern int usart_init_rs485(volatile avr32_usart_t *usart, const usart_options_t *opt, long pba_hz);
/*! \brief Sets up the USART to use the ISO7816 T=0 or T=1 smartcard protocols.
*
* \param usart Base address of the USART instance.
* \param opt Options needed to set up ISO7816 communication (see \ref iso7816_options_t).
* \param t ISO7816 mode to use (T=0 or T=1).
* \param pba_hz USART module input clock frequency (PBA clock, Hz).
*
* \retval USART_SUCCESS Mode successfully initialized.
* \retval USART_INVALID_INPUT One or more of the arguments is out of valid range.
*/
extern int usart_init_iso7816(volatile avr32_usart_t *usart, const iso7816_options_t *opt, int t, long pba_hz);
/*! \brief Sets up the USART to use the SPI mode as master.
*
* \param usart Base address of the USART instance.
* \param opt Options needed to set up SPI mode (see \ref usart_spi_options_t).
* \param pba_hz USART module input clock frequency (PBA clock, Hz).
*
* \retval USART_SUCCESS Mode successfully initialized.
* \retval USART_INVALID_INPUT One or more of the arguments is out of valid range.
*/
extern int usart_init_spi_master(volatile avr32_usart_t *usart, const usart_spi_options_t *opt, long pba_hz);
/*! \brief Sets up the USART to use the SPI mode as slave.
*
* \param usart Base address of the USART instance.
* \param opt Options needed to set up SPI mode (see \ref usart_spi_options_t).
* \param pba_hz USART module input clock frequency (PBA clock, Hz).
*
* \retval USART_SUCCESS Mode successfully initialized.
* \retval USART_INVALID_INPUT One or more of the arguments is out of valid range.
*/
extern int usart_init_spi_slave(volatile avr32_usart_t *usart, const usart_spi_options_t *opt, long pba_hz);
//! @}
//------------------------------------------------------------------------------
/*! \brief Selects slave chip.
*
* \param usart Base address of the USART instance.
*
* \return Status.
* \retval USART_SUCCESS Success.
*/
extern int usart_spi_selectChip(volatile avr32_usart_t *usart);
/*! \brief Unselects slave chip.
*
* \param usart Base address of the USART instance.
*
* \return Status.
* \retval USART_SUCCESS Success.
* \retval USART_FAILURE Time out.
*/
extern int usart_spi_unselectChip(volatile avr32_usart_t *usart);
//------------------------------------------------------------------------------
/*! \name Read and Reset Error Status Bits
*/
//! @{
/*! \brief Resets the error status.
*
* This function resets the status bits indicating that a parity error,
* framing error or overrun has occurred. The RXBRK bit, indicating
* a start/end of break condition on the RX line, is also reset.
*
* \param usart Base address of the USART instance.
*/
#if __GNUC__
__attribute__((__always_inline__))
#endif
extern __inline__ void usart_reset_status(volatile avr32_usart_t *usart)
{
usart->cr |= AVR32_USART_CR_RSTSTA_MASK;
}
/*! \brief Checks if a parity error has occurred since last status reset.
*
* \param usart Base address of the USART instance.
*
* \return \c 1 if a parity error has been detected, otherwise \c 0.
*/
#if __GNUC__
__attribute__((__always_inline__))
#endif
extern __inline__ int usart_parity_error(volatile avr32_usart_t *usart)
{
return (usart->csr & AVR32_USART_CSR_PARE_MASK) != 0;
}
/*! \brief Checks if a framing error has occurred since last status reset.
*
* \param usart Base address of the USART instance.
*
* \return \c 1 if a framing error has been detected, otherwise \c 0.
*/
#if __GNUC__
__attribute__((__always_inline__))
#endif
extern __inline__ int usart_framing_error(volatile avr32_usart_t *usart)
{
return (usart->csr & AVR32_USART_CSR_FRAME_MASK) != 0;
}
/*! \brief Checks if an overrun error has occurred since last status reset.
*
* \param usart Base address of the USART instance.
*
* \return \c 1 if a overrun error has been detected, otherwise \c 0.
*/
#if __GNUC__
__attribute__((__always_inline__))
#endif
extern __inline__ int usart_overrun_error(volatile avr32_usart_t *usart)
{
return (usart->csr & AVR32_USART_CSR_OVRE_MASK) != 0;
}
//! @}
//------------------------------------------------------------------------------
/*! \name Transmit/Receive Functions
*/
//! @{
/*! \brief Addresses a receiver.
*
* While in RS485 mode, receivers only accept data addressed to them.
* A packet/char with the address tag set has to precede any data.
* This function is used to address a receiver. This receiver should read
* all the following data, until an address packet addresses another receiver.
*
* \param usart Base address of the USART instance.
* \param address Address of the target device.
*
* \retval USART_SUCCESS Address successfully sent (if current mode is RS485).
* \retval USART_MODE_FAULT Wrong operating mode.
*/
extern int usart_send_address(volatile avr32_usart_t *usart, int address);
/*! \brief Writes the given character to the TX buffer if the transmitter is ready.
*
* \param usart Base address of the USART instance.
* \param c The character (up to 9 bits) to transmit.
*
* \retval USART_SUCCESS The transmitter was ready.
* \retval USART_TX_BUSY The transmitter was busy.
*/
extern int usart_write_char(volatile avr32_usart_t *usart, int c);
/*! \brief An active wait writing a character to the USART.
*
* \param usart Base address of the USART instance.
* \param c The character (up to 9 bits) to transmit.
*/
#if __GNUC__
__attribute__((__always_inline__))
#endif
extern __inline__ void usart_bw_write_char(volatile avr32_usart_t *usart, int c)
{
while (usart_write_char(usart, c) != USART_SUCCESS);
}
/*! \brief Sends a character with the USART.
*
* \param usart Base address of the USART instance.
* \param c Character to write.
*
* \retval USART_SUCCESS The character was written.
* \retval USART_FAILURE The function timed out before the USART transmitter became ready to send.
*/
extern int usart_putchar(volatile avr32_usart_t *usart, int c);
/*! \brief Checks the RX buffer for a received character, and stores it at the
* given memory location.
*
* \param usart Base address of the USART instance.
* \param c Pointer to the where the read character should be stored
* (must be at least short in order to accept 9-bit characters).
*
* \retval USART_SUCCESS The character was read successfully.
* \retval USART_RX_EMPTY The RX buffer was empty.
* \retval USART_RX_ERROR An error was deteceted.
*/
extern int usart_read_char(volatile avr32_usart_t *usart, int *c);
/*! \brief Waits until a character is received, and returns it.
*
* \param usart Base address of the USART instance.
*
* \return The received character, or \ref USART_FAILURE upon error.
*/
extern int usart_getchar(volatile avr32_usart_t *usart);
/*! \brief Writes one character string to the USART.
*
* \param usart Base address of the USART instance.
* \param string String to be written.
*/
extern void usart_write_line(volatile avr32_usart_t *usart, const char *string);
/*! \brief Gets and echoes characters until end of line.
*
* \param usart Base address of the USART instance.
*
* \retval USART_SUCCESS Success.
* \retval USART_FAILURE ETX character received.
*/
extern int usart_get_echo_line(volatile avr32_usart_t *usart);
//! @}
#endif // _USART_H_