switch to setup for Arduino Boards Manager

This commit is contained in:
Erik Tylek Kettenburg
2015-06-23 12:42:35 -07:00
parent bc55c9bb45
commit 6ca6b114d5
3581 changed files with 93 additions and 51 deletions

View File

@@ -0,0 +1,130 @@
#
# Copyright (c) 2011 Arduino. All right reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# Makefile for compiling libchip
SUBMAKE_OPTIONS=--no-builtin-rules --no-builtin-variables --no-print-directory
#-------------------------------------------------------------------------------
# Rules
#-------------------------------------------------------------------------------
# libsam_sam3s4c_gcc_rel.a libsam_sam3u4e_gcc_rel.a libsam_sam3x8e_gcc_rel.a libsam_sam3x8h_gcc_rel.a
all: libsam_sam3s4c_gcc_dbg.a libsam_sam3u4e_gcc_dbg.a libsam_sam3x8e_gcc_dbg.a libsam_sam3x8h_gcc_dbg.a arduino_due_x
.PHONY: arduino_due_u
arduino_due_u:
@echo ------------------------------------------------------------------------------------
@echo --- Making $@
@echo ---
@$(MAKE) CHIP=__SAM3U4E__ $(SUBMAKE_OPTIONS) OUTPUT_BIN=../../../variants/arduino_due_u -f sam3.mk
@echo ------------------------------------------------------------------------------------
.PHONY: arduino_due_x
arduino_due_x:
@echo ------------------------------------------------------------------------------------
@echo --- Making $@
@echo ---
@$(MAKE) CHIP=__SAM3X8E__ $(SUBMAKE_OPTIONS) OUTPUT_BIN=../../../variants/arduino_due_x -f sam3.mk
@echo ------------------------------------------------------------------------------------
.PHONY: libsam_sam3s4c_gcc_dbg.a
libsam_sam3s4c_gcc_dbg.a:
@echo ------------------------------------------------------------------------------------
@echo --- Making $@
@echo ---
@$(MAKE) CHIP=__SAM3S4C__ DEBUG=1 $(SUBMAKE_OPTIONS) -f sam3.mk
@echo ------------------------------------------------------------------------------------
.PHONY: libsam_sam3s4c_gcc_rel.a
libsam_sam3s4c_gcc_rel.a:
@echo ------------------------------------------------------------------------------------
@echo --- Making $@
@echo ---
@$(MAKE) CHIP=__SAM3S4C__ $(SUBMAKE_OPTIONS) -f sam3.mk
@echo ------------------------------------------------------------------------------------
.PHONY: libsam_sam3u4e_gcc_dbg.a
libsam_sam3u4e_gcc_dbg.a:
@echo ------------------------------------------------------------------------------------
@echo --- Making $@
@echo ---
@$(MAKE) CHIP=__SAM3U4E__ DEBUG=1 $(SUBMAKE_OPTIONS) -f sam3.mk
@echo ------------------------------------------------------------------------------------
.PHONY: libsam_sam3u4e_gcc_rel.a
libsam_sam3u4e_gcc_rel.a:
@echo ------------------------------------------------------------------------------------
@echo --- Making $@
@echo ---
@$(MAKE) CHIP=__SAM3U4E__ $(SUBMAKE_OPTIONS) -f sam3.mk
@echo ------------------------------------------------------------------------------------
.PHONY: libsam_sam3x8e_gcc_dbg.a
libsam_sam3x8e_gcc_dbg.a:
@echo ------------------------------------------------------------------------------------
@echo --- Making $@
@echo ---
@$(MAKE) CHIP=__SAM3X8E__ DEBUG=1 $(SUBMAKE_OPTIONS) -f sam3.mk
@echo ------------------------------------------------------------------------------------
.PHONY: libsam_sam3x8e_gcc_rel.a
libsam_sam3x8e_gcc_rel.a:
@echo ------------------------------------------------------------------------------------
@echo --- Making $@
@echo ---
@$(MAKE) CHIP=__SAM3X8E__ $(SUBMAKE_OPTIONS) -f sam3.mk
@echo ------------------------------------------------------------------------------------
.PHONY: libsam_sam3x8h_gcc_dbg.a
libsam_sam3x8h_gcc_dbg.a:
@echo ------------------------------------------------------------------------------------
@echo --- Making $@
@echo ---
@$(MAKE) CHIP=__SAM3X8H__ DEBUG=1 $(SUBMAKE_OPTIONS) -f sam3.mk
@echo ------------------------------------------------------------------------------------
.PHONY: libsam_sam3x8h_gcc_rel.a
libsam_sam3x8h_gcc_rel.a:
@echo ------------------------------------------------------------------------------------
@echo --- Making $@
@echo ---
@$(MAKE) CHIP=__SAM3X8H__ $(SUBMAKE_OPTIONS) -f sam3.mk
@echo ------------------------------------------------------------------------------------
.PHONY: clean
clean:
@echo ------------------------------------------------------------------------------------
@echo --- Cleaning sam3s4c release and debug
@$(MAKE) CHIP=__SAM3S4C__ $(SUBMAKE_OPTIONS) -f sam3.mk $@
@$(MAKE) CHIP=__SAM3S4C__ DEBUG=1 $(SUBMAKE_OPTIONS) -f sam3.mk $@
@echo --- Cleaning sam3u4e release and debug
@$(MAKE) CHIP=__SAM3U4E__ $(SUBMAKE_OPTIONS) -f sam3.mk $@
@$(MAKE) CHIP=__SAM3U4E__ DEBUG=1 $(SUBMAKE_OPTIONS) -f sam3.mk $@
@echo --- Cleaning sam3x8e release and debug
@$(MAKE) CHIP=__SAM3X8E__ $(SUBMAKE_OPTIONS) -f sam3.mk $@
@$(MAKE) CHIP=__SAM3X8E__ DEBUG=1 $(SUBMAKE_OPTIONS) -f sam3.mk $@
@echo --- Cleaning sam3x8h release and debug
@$(MAKE) CHIP=__SAM3X8H__ $(SUBMAKE_OPTIONS) -f sam3.mk $@
@$(MAKE) CHIP=__SAM3X8H__ DEBUG=1 $(SUBMAKE_OPTIONS) -f sam3.mk $@
@echo ------------------------------------------------------------------------------------

View File

@@ -0,0 +1,25 @@
#
# Copyright (c) 2011 Arduino. All right reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# Optimization level
# -O1 Optimize
# -O2 Optimize even more
# -O3 Optimize yet more
# -O0 Reduce compilation time and make debugging produce the expected results
# -Os Optimize for size
OPTIMIZATION = -g -O0 -DDEBUG

View File

@@ -0,0 +1,63 @@
#
# Copyright (c) 2011 Arduino. All right reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# Tool suffix when cross-compiling
CROSS_COMPILE = $(ARM_GCC_TOOLCHAIN)/arm-none-eabi-
# Compilation tools
AR = $(CROSS_COMPILE)ar
CC = $(CROSS_COMPILE)gcc
AS = $(CROSS_COMPILE)as
NM = $(CROSS_COMPILE)nm
ifeq ($(OS),Windows_NT)
RM=cs-rm -Rf
#RM=del /s /f
else
RM=rm -Rf
endif
SEP=/
# ---------------------------------------------------------------------------------------
# C Flags
CFLAGS += -Wall -Wchar-subscripts -Wcomment -Wformat=2 -Wimplicit-int
CFLAGS += -Werror-implicit-function-declaration -Wmain -Wparentheses
CFLAGS += -Wsequence-point -Wreturn-type -Wswitch -Wtrigraphs -Wunused
CFLAGS += -Wuninitialized -Wunknown-pragmas -Wfloat-equal -Wundef
CFLAGS += -Wshadow -Wpointer-arith -Wbad-function-cast -Wwrite-strings
CFLAGS += -Wsign-compare -Waggregate-return -Wstrict-prototypes
CFLAGS += -Wmissing-prototypes -Wmissing-declarations
CFLAGS += -Wformat -Wmissing-format-attribute -Wno-deprecated-declarations
CFLAGS += -Wpacked -Wredundant-decls -Wnested-externs -Winline -Wlong-long
CFLAGS += -Wunreachable-code
CFLAGS += -Wcast-align
#CFLAGS += -Wmissing-noreturn
#CFLAGS += -Wconversion
# To reduce application size use only integer printf function.
CFLAGS += -Dprintf=iprintf
CFLAGS += --param max-inline-insns-single=500 -mcpu=cortex-m3 -mthumb -mlong-calls -ffunction-sections -fdata-sections -std=c99
CFLAGS += $(OPTIMIZATION) $(INCLUDES) -D$(CHIP)
# ---------------------------------------------------------------------------------------
# ASM Flags
ASFLAGS = -mcpu=cortex-m3 -mthumb -Wall -a -g $(INCLUDES)

View File

@@ -0,0 +1,25 @@
#
# Copyright (c) 2011 Arduino. All right reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# Optimization level
# -O1 Optimize
# -O2 Optimize even more
# -O3 Optimize yet more
# -O0 Reduce compilation time and make debugging produce the expected results
# -Os Optimize for size
OPTIMIZATION = -Os

View File

@@ -0,0 +1,189 @@
#
# Copyright (c) 2011 Arduino. All right reserved.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
#
# Makefile for compiling libchip
.SUFFIXES: .o .a .c .s
SUB_MAKEFILES=debug.mk gcc.mk release.mk win.mk sam3s.mk
LIBNAME=libsam
TOOLCHAIN=gcc
ifeq ($(OS),Windows_NT)
DEV_NUL=NUL
else
DEV_NUL=/dev/null
endif
ifeq ($(CHIP),)
$(error CHIP not defined)
endif
#CHIP_NAME=$(subst __,,$(CHIP))
#CHIP_NAME=$(subst __,,$(call lc,$(CHIP)))
#-------------------------------------------------------------------------------
# Path
#-------------------------------------------------------------------------------
# Output directories
OUTPUT_BIN = ../../../cores/arduino
# Libraries
PROJECT_BASE_PATH = ..
CMSIS_ROOT_PATH = $(PROJECT_BASE_PATH)/../CMSIS
ifeq ($(CHIP), __SAM3S4C__)
CHIP_NAME=sam3s4c
CHIP_SERIE=sam3s
else ifeq ($(CHIP), __SAM3U4E__)
CHIP_NAME=sam3u4e
CHIP_SERIE=sam3u
else ifeq ($(CHIP), __SAM3N4C__)
CHIP_NAME=sam3n4c
CHIP_SERIE=sam3n
else ifeq ($(CHIP), __SAM3X8E__)
CHIP_NAME=sam3x8e
CHIP_SERIE=sam3xa
else ifeq ($(CHIP), __SAM3X8H__)
CHIP_NAME=sam3x8h
CHIP_SERIE=sam3xa
else
endif
CMSIS_ARM_PATH=$(CMSIS_ROOT_PATH)/CMSIS/Include
CMSIS_ATMEL_PATH=$(CMSIS_ROOT_PATH)/Device/ATMEL
CMSIS_CHIP_PATH=$(CMSIS_ROOT_PATH)/Device/ATMEL/$(CHIP_SERIE)
#-------------------------------------------------------------------------------
# Files
#-------------------------------------------------------------------------------
vpath %.h $(PROJECT_BASE_PATH)/include $(CMSIS_ATMEL_PATH) $(CMSIS_CHIP_PATH)/include
vpath %.c $(PROJECT_BASE_PATH)/source $(CMSIS_ARM_PATH) $(CMSIS_CHIP_PATH)/source
VPATH+=$(PROJECT_BASE_PATH)/source
VPATH+=$(CMSIS_ARM_PATH)
VPATH+=$(CMSIS_CHIP_PATH)/include
VPATH+=$(CMSIS_CHIP_PATH)/source/
VPATH+=$(CMSIS_CHIP_PATH)/source/gcc
INCLUDES = -I$(PROJECT_BASE_PATH)
INCLUDES += -I$(PROJECT_BASE_PATH)/include
INCLUDES += -I$(CMSIS_ARM_PATH)
INCLUDES += -I$(CMSIS_ATMEL_PATH)
INCLUDES += -I$(CMSIS_CHIP_PATH)/include
#-------------------------------------------------------------------------------
ifdef DEBUG
include debug.mk
else
include release.mk
endif
#-------------------------------------------------------------------------------
# Tools
#-------------------------------------------------------------------------------
include $(TOOLCHAIN).mk
#-------------------------------------------------------------------------------
ifdef DEBUG
OUTPUT_OBJ=debug
OUTPUT_LIB=$(LIBNAME)_$(CHIP_NAME)_$(TOOLCHAIN)_dbg.a
else
OUTPUT_OBJ=release
OUTPUT_LIB=$(LIBNAME)_$(CHIP_NAME)_$(TOOLCHAIN)_rel.a
endif
OUTPUT_PATH=$(OUTPUT_OBJ)_$(CHIP_NAME)
#-------------------------------------------------------------------------------
# C source files and objects
#-------------------------------------------------------------------------------
C_SRC=$(wildcard $(PROJECT_BASE_PATH)/source/*.c)
C_SRC+=$(wildcard $(CMSIS_CHIP_PATH)/source/*.c)
C_SRC+=$(wildcard $(CMSIS_CHIP_PATH)/source/gcc/*.c)
C_OBJ_TEMP=$(patsubst %.c, %.o, $(notdir $(C_SRC)))
# during development, remove some files
C_OBJ_FILTER=
C_OBJ=$(filter-out $(C_OBJ_FILTER), $(C_OBJ_TEMP))
#-------------------------------------------------------------------------------
# Assembler source files and objects
#-------------------------------------------------------------------------------
A_SRC=$(wildcard $(PROJECT_BASE_PATH)/source/*.s)
A_OBJ_TEMP=$(patsubst %.s, %.o, $(notdir $(A_SRC)))
# during development, remove some files
A_OBJ_FILTER=
A_OBJ=$(filter-out $(A_OBJ_FILTER), $(A_OBJ_TEMP))
#-------------------------------------------------------------------------------
# Rules
#-------------------------------------------------------------------------------
all: $(CHIP)
$(CHIP): create_output $(OUTPUT_LIB)
.PHONY: create_output
create_output:
@echo ------------------------------------------------------------------------------------
@echo --- Preparing $(CHIP) files $(OUTPUT_PATH) to $(OUTPUT_BIN)
# @echo -------------------------
# @echo *$(C_SRC)
# @echo -------------------------
# @echo *$(C_OBJ)
# @echo -------------------------
# @echo *$(addprefix $(OUTPUT_PATH)/, $(C_OBJ))
# @echo -------------------------
# @echo *$(A_SRC)
# @echo -------------------------
-@mkdir $(subst /,$(SEP),$(OUTPUT_BIN)) 1>$(DEV_NUL) 2>&1
-@mkdir $(OUTPUT_PATH) 1>$(DEV_NUL) 2>&1
@echo ------------------------------------------------------------------------------------
$(addprefix $(OUTPUT_PATH)/,$(C_OBJ)): $(OUTPUT_PATH)/%.o: %.c
# "$(CC)" -v -c $(CFLAGS) -Wa,aln=$(subst .o,.s,$@) $< -o $@
@"$(CC)" -c $(CFLAGS) $< -o $@
# "$(CC)" -c $(CFLAGS) $< -o $@
$(addprefix $(OUTPUT_PATH)/,$(A_OBJ)): $(OUTPUT_PATH)/%.o: %.s
@"$(AS)" -c $(ASFLAGS) $< -o $@
$(OUTPUT_LIB): $(addprefix $(OUTPUT_PATH)/, $(C_OBJ)) $(addprefix $(OUTPUT_PATH)/, $(A_OBJ))
@"$(AR)" -r "$(OUTPUT_BIN)/$@" $^
@"$(NM)" "$(OUTPUT_BIN)/$@" > "$(OUTPUT_BIN)/$@.txt"
.PHONY: clean
clean:
@echo ------------------------------------------------------------------------------------
@echo --- Cleaning $(CHIP) files $(OUTPUT_PATH) $(subst /,$(SEP),$(OUTPUT_BIN)/$(OUTPUT_LIB))
-@$(RM) $(OUTPUT_PATH) 1>$(DEV_NUL) 2>&1
-@$(RM) $(subst /,$(SEP),$(OUTPUT_BIN)/$(OUTPUT_LIB)) 1>$(DEV_NUL) 2>&1
-@$(RM) $(subst /,$(SEP),$(OUTPUT_BIN)/$(OUTPUT_LIB)).txt 1>$(DEV_NUL) 2>&1
@echo ------------------------------------------------------------------------------------
# dependencies
$(addprefix $(OUTPUT_PATH)/,$(C_OBJ)): $(OUTPUT_PATH)/%.o: $(PROJECT_BASE_PATH)/chip.h $(wildcard $(PROJECT_BASE_PATH)/include/*.h) $(wildcard $(CMSIS_BASE_PATH)/*.h)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<workspace>
<project>
<path>$WS_DIR$\..\..\..\cores\sam\build_iar\libarduino.ewp</path>
</project>
<project>
<path>$WS_DIR$\libsam.ewp</path>
</project>
<project>
<path>$WS_DIR$\..\..\..\variants\sam3s_ek\build_iar\libvariant_sam3s_ek.ewp</path>
</project>
<project>
<path>$WS_DIR$\..\..\..\cores\sam\validation\build_iar\test.ewp</path>
</project>
<batchBuild>
<batchDefinition>
<name>all_debug_sam3s</name>
<member>
<project>libsam</project>
<configuration>Debug</configuration>
</member>
<member>
<project>libarduino</project>
<configuration>Debug</configuration>
</member>
<member>
<project>libsam3s_ek</project>
<configuration>Debug</configuration>
</member>
<member>
<project>test</project>
<configuration>Debug</configuration>
</member>
</batchDefinition>
</batchBuild>
</workspace>

View File

@@ -0,0 +1,77 @@
/*
Copyright (c) 2011 Arduino. All right reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef _LIB_SAM_
#define _LIB_SAM_
/*
* Core and peripherals registers definitions
*/
#include "sam.h"
/* Define attribute */
#if defined ( __GNUC__ ) /* GCC CS3 */
#define WEAK __attribute__ ((weak))
#elif defined ( __ICCARM__ ) /* IAR Ewarm 5.41+ */
#define WEAK __weak
#endif
/* Define NO_INIT attribute */
#if defined ( __GNUC__ )
#define NO_INIT
#elif defined ( __ICCARM__ )
#define NO_INIT __no_init
#endif
/*
* Peripherals
*/
#include "include/adc.h"
#if (SAM3XA_SERIES) || (SAM3N_SERIES) || (SAM3S_SERIES)
#include "include/dacc.h"
#endif // (SAM3XA_SERIES) || (SAM3N_SERIES) || (SAM3S_SERIES)
#include "include/interrupt_sam_nvic.h"
#include "include/efc.h"
#include "include/gpbr.h"
#include "include/pio.h"
#include "include/pmc.h"
#include "include/pwmc.h"
#include "include/rstc.h"
#include "include/rtc.h"
#include "include/rtt.h"
#include "include/spi.h"
#include "include/ssc.h"
#include "include/tc.h"
#include "include/twi.h"
#include "include/usart.h"
#include "include/wdt.h"
#include "include/timetick.h"
#include "include/USB_device.h"
#include "include/USB_host.h"
#if (SAM3XA_SERIES)
#include "include/can.h"
#include "include/emac.h"
#include "include/trng.h"
#include "include/uotghs_device.h"
#include "include/uotghs_host.h"
#endif /* (SAM3XA_SERIES) */
#endif /* _LIB_SAM_ */

View File

@@ -0,0 +1,403 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef USB_DEVICE_H_INCLUDED
#define USB_DEVICE_H_INCLUDED
#include <stdint.h>
extern void UDD_WaitIN(void);
extern void UDD_WaitOUT(void);
extern void UDD_ClearIN(void);
extern void UDD_ClearOUT(void);
extern uint32_t UDD_WaitForINOrOUT(void);
extern void UDD_ClearRxFlag(unsigned char bEndpoint);
extern uint32_t UDD_ReceivedSetupInt(void);
extern void UDD_ClearSetupInt(void);
extern uint32_t UDD_ReadWriteAllowed(uint32_t ep);
extern uint32_t UDD_FifoByteCount(uint32_t ep);
extern uint8_t UDD_FifoFree(void);
extern void UDD_ReleaseRX(uint32_t ep);
extern void UDD_ReleaseTX(uint32_t ep);
extern uint8_t UDD_FrameNumber(void);
extern uint8_t UDD_GetConfiguration(void);
extern uint32_t UDD_Send(uint32_t ep, const void* data, uint32_t len);
extern void UDD_Send8(uint32_t ep, uint8_t data );
extern uint8_t UDD_Recv8(uint32_t ep);
extern void UDD_Recv(uint32_t ep, uint8_t* data, uint32_t len);
extern void UDD_InitEndpoints(const uint32_t* eps_table, const uint32_t ul_eps_table_size);
extern void UDD_InitControl(int end);
extern uint32_t UDD_Init(void);
extern void UDD_InitEP( uint32_t ul_ep, uint32_t ul_ep_cfg );
extern void UDD_Attach(void);
extern void UDD_Detach(void);
extern void UDD_SetStack(void (*pf_isr)(void));
extern void UDD_SetAddress(uint32_t addr);
extern void UDD_Stall(void);
extern uint32_t UDD_GetFrameNumber(void);
/*! \name Usual Types
*/
//! @{
typedef unsigned char Bool; //!< Boolean.
#ifndef __cplusplus
#if !defined(__bool_true_false_are_defined)
typedef unsigned char bool; //!< Boolean.
#endif
#endif
typedef int8_t S8; //!< 8-bit signed integer.
typedef uint8_t U8; //!< 8-bit unsigned integer.
typedef int16_t S16; //!< 16-bit signed integer.
typedef uint16_t U16; //!< 16-bit unsigned integer.
typedef uint16_t le16_t;
typedef uint16_t be16_t;
typedef int32_t S32; //!< 32-bit signed integer.
typedef uint32_t U32; //!< 32-bit unsigned integer.
typedef uint32_t le32_t;
typedef uint32_t be32_t;
typedef int64_t S64; //!< 64-bit signed integer.
typedef uint64_t U64; //!< 64-bit unsigned integer.
typedef float F32; //!< 32-bit floating-point number.
typedef double F64; //!< 64-bit floating-point number.
typedef uint32_t iram_size_t;
//! @}
/*! \name Bit-Field Handling
*/
//! @{
/*! \brief Reads the bits of a value specified by a given bit-mask.
*
* \param value Value to read bits from.
* \param mask Bit-mask indicating bits to read.
*
* \return Read bits.
*/
#define Rd_bits( value, mask) ((value) & (mask))
/*! \brief Writes the bits of a C lvalue specified by a given bit-mask.
*
* \param lvalue C lvalue to write bits to.
* \param mask Bit-mask indicating bits to write.
* \param bits Bits to write.
*
* \return Resulting value with written bits.
*/
#define Wr_bits(lvalue, mask, bits) ((lvalue) = ((lvalue) & ~(mask)) |\
((bits ) & (mask)))
/*! \brief Tests the bits of a value specified by a given bit-mask.
*
* \param value Value of which to test bits.
* \param mask Bit-mask indicating bits to test.
*
* \return \c 1 if at least one of the tested bits is set, else \c 0.
*/
#define Tst_bits( value, mask) (Rd_bits(value, mask) != 0)
/*! \brief Clears the bits of a C lvalue specified by a given bit-mask.
*
* \param lvalue C lvalue of which to clear bits.
* \param mask Bit-mask indicating bits to clear.
*
* \return Resulting value with cleared bits.
*/
#define Clr_bits(lvalue, mask) ((lvalue) &= ~(mask))
/*! \brief Sets the bits of a C lvalue specified by a given bit-mask.
*
* \param lvalue C lvalue of which to set bits.
* \param mask Bit-mask indicating bits to set.
*
* \return Resulting value with set bits.
*/
#define Set_bits(lvalue, mask) ((lvalue) |= (mask))
/*! \brief Toggles the bits of a C lvalue specified by a given bit-mask.
*
* \param lvalue C lvalue of which to toggle bits.
* \param mask Bit-mask indicating bits to toggle.
*
* \return Resulting value with toggled bits.
*/
#define Tgl_bits(lvalue, mask) ((lvalue) ^= (mask))
/*! \brief Reads the bit-field of a value specified by a given bit-mask.
*
* \param value Value to read a bit-field from.
* \param mask Bit-mask indicating the bit-field to read.
*
* \return Read bit-field.
*/
#define Rd_bitfield( value, mask) (Rd_bits( value, mask) >> ctz(mask))
/*! \brief Writes the bit-field of a C lvalue specified by a given bit-mask.
*
* \param lvalue C lvalue to write a bit-field to.
* \param mask Bit-mask indicating the bit-field to write.
* \param bitfield Bit-field to write.
*
* \return Resulting value with written bit-field.
*/
#define Wr_bitfield(lvalue, mask, bitfield) (Wr_bits(lvalue, mask, (U32)(bitfield) << ctz(mask)))
//! @}
/*! \name Token Paste
*
* Paste N preprocessing tokens together, these tokens being allowed to be \#defined.
*
* May be used only within macros with the tokens passed as arguments if the tokens are \#defined.
*
* For example, writing TPASTE2(U, WIDTH) within a macro \#defined by
* UTYPE(WIDTH) and invoked as UTYPE(UL_WIDTH) with UL_WIDTH \#defined as 32 is
* equivalent to writing U32.
*/
//! @{
#define TPASTE2( a, b) a##b
#define TPASTE3( a, b, c) a##b##c
#define TPASTE4( a, b, c, d) a##b##c##d
#define TPASTE5( a, b, c, d, e) a##b##c##d##e
#define TPASTE6( a, b, c, d, e, f) a##b##c##d##e##f
#define TPASTE7( a, b, c, d, e, f, g) a##b##c##d##e##f##g
#define TPASTE8( a, b, c, d, e, f, g, h) a##b##c##d##e##f##g##h
#define TPASTE9( a, b, c, d, e, f, g, h, i) a##b##c##d##e##f##g##h##i
#define TPASTE10(a, b, c, d, e, f, g, h, i, j) a##b##c##d##e##f##g##h##i##j
//! @}
/*! \name Absolute Token Paste
*
* Paste N preprocessing tokens together, these tokens being allowed to be \#defined.
*
* No restriction of use if the tokens are \#defined.
*
* For example, writing ATPASTE2(U, UL_WIDTH) anywhere with UL_WIDTH \#defined
* as 32 is equivalent to writing U32.
*/
//! @{
#define ATPASTE2( a, b) TPASTE2( a, b)
#define ATPASTE3( a, b, c) TPASTE3( a, b, c)
#define ATPASTE4( a, b, c, d) TPASTE4( a, b, c, d)
#define ATPASTE5( a, b, c, d, e) TPASTE5( a, b, c, d, e)
#define ATPASTE6( a, b, c, d, e, f) TPASTE6( a, b, c, d, e, f)
#define ATPASTE7( a, b, c, d, e, f, g) TPASTE7( a, b, c, d, e, f, g)
#define ATPASTE8( a, b, c, d, e, f, g, h) TPASTE8( a, b, c, d, e, f, g, h)
#define ATPASTE9( a, b, c, d, e, f, g, h, i) TPASTE9( a, b, c, d, e, f, g, h, i)
#define ATPASTE10(a, b, c, d, e, f, g, h, i, j) TPASTE10(a, b, c, d, e, f, g, h, i, j)
//! @}
/*! \brief Counts the trailing zero bits of the given value considered as a 32-bit integer.
*
* \param u Value of which to count the trailing zero bits.
*
* \return The count of trailing zero bits in \a u.
*/
#if (defined __GNUC__) || (defined __CC_ARM)
# define ctz(u) __builtin_ctz(u)
#else
# define ctz(u) ((u) & (1ul << 0) ? 0 : \
(u) & (1ul << 1) ? 1 : \
(u) & (1ul << 2) ? 2 : \
(u) & (1ul << 3) ? 3 : \
(u) & (1ul << 4) ? 4 : \
(u) & (1ul << 5) ? 5 : \
(u) & (1ul << 6) ? 6 : \
(u) & (1ul << 7) ? 7 : \
(u) & (1ul << 8) ? 8 : \
(u) & (1ul << 9) ? 9 : \
(u) & (1ul << 10) ? 10 : \
(u) & (1ul << 11) ? 11 : \
(u) & (1ul << 12) ? 12 : \
(u) & (1ul << 13) ? 13 : \
(u) & (1ul << 14) ? 14 : \
(u) & (1ul << 15) ? 15 : \
(u) & (1ul << 16) ? 16 : \
(u) & (1ul << 17) ? 17 : \
(u) & (1ul << 18) ? 18 : \
(u) & (1ul << 19) ? 19 : \
(u) & (1ul << 20) ? 20 : \
(u) & (1ul << 21) ? 21 : \
(u) & (1ul << 22) ? 22 : \
(u) & (1ul << 23) ? 23 : \
(u) & (1ul << 24) ? 24 : \
(u) & (1ul << 25) ? 25 : \
(u) & (1ul << 26) ? 26 : \
(u) & (1ul << 27) ? 27 : \
(u) & (1ul << 28) ? 28 : \
(u) & (1ul << 29) ? 29 : \
(u) & (1ul << 30) ? 30 : \
(u) & (1ul << 31) ? 31 : \
32)
#endif
/*! \name Zero-Bit Counting
*
* Under GCC, __builtin_clz and __builtin_ctz behave like macros when
* applied to constant expressions (values known at compile time), so they are
* more optimized than the use of the corresponding assembly instructions and
* they can be used as constant expressions e.g. to initialize objects having
* static storage duration, and like the corresponding assembly instructions
* when applied to non-constant expressions (values unknown at compile time), so
* they are more optimized than an assembly periphrasis. Hence, clz and ctz
* ensure a possible and optimized behavior for both constant and non-constant
* expressions.
*/
//! @{
/*! \brief Counts the leading zero bits of the given value considered as a 32-bit integer.
*
* \param u Value of which to count the leading zero bits.
*
* \return The count of leading zero bits in \a u.
*/
#if (defined __GNUC__) || (defined __CC_ARM)
# define clz(u) __builtin_clz(u)
#elif (defined __ICCARM__)
# define clz(u) __CLZ(u)
#else
# define clz(u) (((u) == 0) ? 32 : \
((u) & (1ul << 31)) ? 0 : \
((u) & (1ul << 30)) ? 1 : \
((u) & (1ul << 29)) ? 2 : \
((u) & (1ul << 28)) ? 3 : \
((u) & (1ul << 27)) ? 4 : \
((u) & (1ul << 26)) ? 5 : \
((u) & (1ul << 25)) ? 6 : \
((u) & (1ul << 24)) ? 7 : \
((u) & (1ul << 23)) ? 8 : \
((u) & (1ul << 22)) ? 9 : \
((u) & (1ul << 21)) ? 10 : \
((u) & (1ul << 20)) ? 11 : \
((u) & (1ul << 19)) ? 12 : \
((u) & (1ul << 18)) ? 13 : \
((u) & (1ul << 17)) ? 14 : \
((u) & (1ul << 16)) ? 15 : \
((u) & (1ul << 15)) ? 16 : \
((u) & (1ul << 14)) ? 17 : \
((u) & (1ul << 13)) ? 18 : \
((u) & (1ul << 12)) ? 19 : \
((u) & (1ul << 11)) ? 20 : \
((u) & (1ul << 10)) ? 21 : \
((u) & (1ul << 9)) ? 22 : \
((u) & (1ul << 8)) ? 23 : \
((u) & (1ul << 7)) ? 24 : \
((u) & (1ul << 6)) ? 25 : \
((u) & (1ul << 5)) ? 26 : \
((u) & (1ul << 4)) ? 27 : \
((u) & (1ul << 3)) ? 28 : \
((u) & (1ul << 2)) ? 29 : \
((u) & (1ul << 1)) ? 30 : \
31)
#endif
/*! \name Mathematics
*
* The same considerations as for clz and ctz apply here but GCC does not
* provide built-in functions to access the assembly instructions abs, min and
* max and it does not produce them by itself in most cases, so two sets of
* macros are defined here:
* - Abs, Min and Max to apply to constant expressions (values known at
* compile time);
* - abs, min and max to apply to non-constant expressions (values unknown at
* compile time), abs is found in stdlib.h.
*/
//! @{
/*! \brief Takes the absolute value of \a a.
*
* \param a Input value.
*
* \return Absolute value of \a a.
*
* \note More optimized if only used with values known at compile time.
*/
#define Abs(a) (((a) < 0 ) ? -(a) : (a))
/*! \brief Takes the minimal value of \a a and \a b.
*
* \param a Input value.
* \param b Input value.
*
* \return Minimal value of \a a and \a b.
*
* \note More optimized if only used with values known at compile time.
*/
#define Min(a, b) (((a) < (b)) ? (a) : (b))
/*! \brief Takes the maximal value of \a a and \a b.
*
* \param a Input value.
* \param b Input value.
*
* \return Maximal value of \a a and \a b.
*
* \note More optimized if only used with values known at compile time.
*/
#define Max(a, b) (((a) > (b)) ? (a) : (b))
// abs() is already defined by stdlib.h
/*! \brief Takes the minimal value of \a a and \a b.
*
* \param a Input value.
* \param b Input value.
*
* \return Minimal value of \a a and \a b.
*
* \note More optimized if only used with values unknown at compile time.
*/
#define min(a, b) Min(a, b)
/*! \brief Takes the maximal value of \a a and \a b.
*
* \param a Input value.
* \param b Input value.
*
* \return Maximal value of \a a and \a b.
*
* \note More optimized if only used with values unknown at compile time.
*/
#define max(a, b) Max(a, b)
//! @}
#endif /* USB_DEVICE_H_INCLUDED */

View File

@@ -0,0 +1,70 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef USB_HOST_H_INCLUDED
#define USB_HOST_H_INCLUDED
#include <stdint.h>
#define tokSETUP UOTGHS_HSTPIPCFG_PTOKEN_SETUP
#define tokIN UOTGHS_HSTPIPCFG_PTOKEN_IN
#define tokOUT UOTGHS_HSTPIPCFG_PTOKEN_OUT
#define tokINHS UOTGHS_HSTPIPCFG_PTOKEN_IN
#define tokOUTHS UOTGHS_HSTPIPCFG_PTOKEN_OUT
//! \brief Device speed
/*typedef enum {
UHD_SPEED_LOW = 0,
UHD_SPEED_FULL = 1,
UHD_SPEED_HIGH = 2,
} uhd_speed_t;*/
//! States of USBB interface
typedef enum {
UHD_STATE_NO_VBUS = 0,
UHD_STATE_DISCONNECTED = 1,
UHD_STATE_CONNECTED = 2,
UHD_STATE_ERROR = 3,
} uhd_vbus_state_t;
//extern uhd_speed_t uhd_get_speed(void);
extern void UHD_SetStack(void (*pf_isr)(void));
extern void UHD_Init(void);
extern void UHD_BusReset(void);
extern uhd_vbus_state_t UHD_GetVBUSState(void);
extern uint32_t UHD_Pipe0_Alloc(uint32_t ul_add, uint32_t ul_ep_size);
extern uint32_t UHD_Pipe_Alloc(uint32_t ul_dev_addr, uint32_t ul_dev_ep, uint32_t ul_type, uint32_t ul_dir, uint32_t ul_maxsize, uint32_t ul_interval, uint32_t ul_nb_bank);
extern void UHD_Pipe_Free(uint32_t ul_pipe);
extern uint32_t UHD_Pipe_Read(uint32_t ul_pipe, uint32_t ul_size, uint8_t* data);
extern void UHD_Pipe_Write(uint32_t ul_pipe, uint32_t ul_size, uint8_t* data);
extern void UHD_Pipe_Send(uint32_t ul_pipe, uint32_t ul_token_type);
extern uint32_t UHD_Pipe_Is_Transfer_Complete(uint32_t ul_pipe, uint32_t ul_token_type);
#endif /* USB_HOST_H_INCLUDED */

View File

@@ -0,0 +1,248 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef ADC_H_INCLUDED
#define ADC_H_INCLUDED
#include "../chip.h"
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
/* The max adc sample freq definition*/
#define ADC_FREQ_MAX 20000000
/* The min adc sample freq definition*/
#define ADC_FREQ_MIN 1000000
/* The normal adc startup time*/
#define ADC_STARTUP_NORM 40
/* The fast adc startup time*/
#define ADC_STARTUP_FAST 12
/* Definitions for ADC resolution */
#if SAM3S_SERIES || SAM4S_SERIES || SAM3XA_SERIES
enum adc_resolution_t {
ADC_10_BITS = ADC_MR_LOWRES_BITS_10, /* ADC 10-bit resolution */
ADC_12_BITS = ADC_MR_LOWRES_BITS_12 /* ADC 12-bit resolution */
};
#elif SAM3N_SERIES
enum adc_resolution_t {
ADC_8_BITS = ADC_MR_LOWRES_BITS_8, /* ADC 8-bit resolution */
ADC_10_BITS = ADC_MR_LOWRES_BITS_10 /* ADC 10-bit resolution */
} ;
#elif SAM3U_SERIES
enum adc_resolution_t {
ADC_8_BITS = ADC_MR_LOWRES_BITS_8, /* ADC 8-bit resolution */
ADC_10_BITS = ADC12B_MR_LOWRES_BITS_10, /* ADC 10-bit resolution */
ADC_12_BITS = ADC12B_MR_LOWRES_BITS_12 /* ADC 12-bit resolution */
} ;
#endif
/* Definitions for ADC trigger */
enum adc_trigger_t {
ADC_TRIG_SW = ADC_MR_TRGEN_DIS, /* Starting a conversion is only possible by software. */
ADC_TRIG_EXT = ((ADC_MR_TRGSEL_ADC_TRIG0 << ADC_MR_TRGSEL_Pos) &
ADC_MR_TRGSEL_Msk) | ADC_MR_TRGEN, /* External trigger */
ADC_TRIG_TIO_CH_0 = (ADC_MR_TRGSEL_ADC_TRIG1 & ADC_MR_TRGSEL_Msk) |
ADC_MR_TRGEN, /* TIO Output of the Timer Counter Channel 0 */
ADC_TRIG_TIO_CH_1 = (ADC_MR_TRGSEL_ADC_TRIG2 & ADC_MR_TRGSEL_Msk) |
ADC_MR_TRGEN, /* TIO Output of the Timer Counter Channel 1 */
ADC_TRIG_TIO_CH_2 = (ADC_MR_TRGSEL_ADC_TRIG3 & ADC_MR_TRGSEL_Msk) |
ADC_MR_TRGEN, /* TIO Output of the Timer Counter Channel 2 */
#if SAM3S_SERIES || SAM4S_SERIES || SAM3XA_SERIES || SAM3U_SERIES
ADC_TRIG_PWM_EVENT_LINE_0 = (ADC_MR_TRGSEL_ADC_TRIG4 & ADC_MR_TRGSEL_Msk) |
ADC_MR_TRGEN, /* PWM Event Line 0 */
ADC_TRIG_PWM_EVENT_LINE_1 = (ADC_MR_TRGSEL_ADC_TRIG5 & ADC_MR_TRGSEL_Msk) |
ADC_MR_TRGEN /* PWM Event Line 1 */
#endif
} ;
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
/* Definitions for ADC channel number */
enum adc_channel_num_t {
ADC_CHANNEL_0 = 0,
ADC_CHANNEL_1 = 1,
ADC_CHANNEL_2 = 2,
ADC_CHANNEL_3 = 3,
ADC_CHANNEL_4 = 4,
ADC_CHANNEL_5 = 5,
ADC_CHANNEL_6 = 6,
ADC_CHANNEL_7 = 7,
ADC_CHANNEL_8 = 8,
ADC_CHANNEL_9 = 9,
ADC_CHANNEL_10 = 10,
ADC_CHANNEL_11 = 11,
ADC_CHANNEL_12 = 12,
ADC_CHANNEL_13 = 13,
ADC_CHANNEL_14 = 14,
ADC_TEMPERATURE_SENSOR = 15,
} ;
#elif SAM3U_SERIES
/* Definitions for ADC channel number */
enum adc_channel_num_t {
ADC_CHANNEL_0 = 0,
ADC_CHANNEL_1 = 1,
ADC_CHANNEL_2 = 2,
ADC_CHANNEL_3 = 3,
ADC_CHANNEL_4 = 4,
ADC_CHANNEL_5 = 5,
ADC_CHANNEL_6 = 6,
ADC_CHANNEL_7 = 7,
} ;
#endif
/* Definitions for ADC gain value */
enum adc_gainvalue_t{
ADC_GAINVALUE_0 = 0,
ADC_GAINVALUE_1 = 1,
ADC_GAINVALUE_2 = 2,
ADC_GAINVALUE_3 = 3
};
/* Definitions for ADC analog settling time */
#if SAM3S_SERIES || SAM4S_SERIES || SAM3XA_SERIES
enum adc_settling_time_t{
ADC_SETTLING_TIME_0 = ADC_MR_SETTLING_AST3,
ADC_SETTLING_TIME_1 = ADC_MR_SETTLING_AST5,
ADC_SETTLING_TIME_2 = ADC_MR_SETTLING_AST9,
ADC_SETTLING_TIME_3 = ADC_MR_SETTLING_AST17
};
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
uint32_t adc_init(Adc *p_adc, const uint32_t ul_mck,
const uint32_t ul_adc_clock, const uint8_t uc_startup);
void adc_configure_trigger(Adc *p_adc, const enum adc_trigger_t trigger,
const uint8_t uc_freerun);
void adc_configure_power_save(Adc *p_adc, const uint8_t uc_sleep, const uint8_t uc_fwup);
void adc_configure_sequence(Adc *p_adc, const enum adc_channel_num_t ch_list[],
const uint8_t uc_num);
void adc_enable_tag(Adc *p_adc);
void adc_disable_tag(Adc *p_adc);
enum adc_channel_num_t adc_get_tag(const Adc *p_adc);
void adc_start_sequencer(Adc *p_adc);
void adc_stop_sequencer(Adc *p_adc);
void adc_set_comparison_mode(Adc *p_adc, const uint8_t uc_mode);
uint32_t adc_get_comparison_mode(const Adc *p_adc);
void adc_set_comparison_window(Adc *p_adc, const uint16_t us_low_threshold,
const uint16_t us_high_threshold);
void adc_set_comparison_channel(Adc *p_adc, const enum adc_channel_num_t channel);
void adc_set_writeprotect(Adc *p_adc, const uint32_t ul_enable);
uint32_t adc_get_writeprotect_status(const Adc *p_adc);
void adc_check(Adc* p_adc, const uint32_t ul_mck);
uint32_t adc_get_overrun_status(const Adc *p_adc);
#elif SAM3U_SERIES
uint32_t adc_init(Adc * p_adc, const uint32_t ul_mck, const uint32_t ul_adc_clock,
const uint32_t ul_startuptime);
void adc_configure_trigger(Adc *p_adc, const enum adc_trigger_t trigger);
void adc_configure_power_save(Adc *p_adc, const uint8_t uc_sleep);
#endif
void adc_set_resolution(Adc *p_adc, const enum adc_resolution_t resolution);
void adc_start(Adc *p_adc);
void adc_stop(Adc *p_adc);
void adc_enable_channel(Adc *p_adc, const enum adc_channel_num_t adc_ch);
void adc_disable_channel(Adc *p_adc, const enum adc_channel_num_t adc_ch);
void adc_enable_all_channel(Adc *p_adc);
void adc_disable_all_channel(Adc *p_adc);
uint32_t adc_get_channel_status(const Adc *p_adc, const enum adc_channel_num_t adc_ch);
uint32_t adc_get_channel_value(const Adc *p_adc,const enum adc_channel_num_t adc_ch);
uint32_t adc_get_latest_value(const Adc *p_adc);
uint32_t adc_get_actual_adc_clock(const Adc *p_adc, const uint32_t ul_mck);
void adc_enable_interrupt(Adc *p_adc, const uint32_t ul_source);
void adc_disable_interrupt(Adc *p_adc, const uint32_t ul_source);
uint32_t adc_get_status(const Adc *p_adc);
uint32_t adc_get_interrupt_mask(const Adc *p_adc);
Pdc *adc_get_pdc_base(const Adc *p_adc);
#if SAM3S_SERIES || SAM4S_SERIES || SAM3XA_SERIES
void adc_configure_timing(Adc *p_adc, const uint8_t uc_tracking,
const enum adc_settling_time_t settling, const uint8_t uc_transfer);
void adc_enable_anch( Adc *p_adc );
void adc_disable_anch( Adc *p_adc );
void adc_enable_channel_differential_input(Adc *p_adc, const enum adc_channel_num_t channel);
void adc_disable_channel_differential_input(Adc *p_adc, const enum adc_channel_num_t channel);
void adc_enable_channel_input_offset(Adc *p_adc, const enum adc_channel_num_t channel);
void adc_disable_channel_input_offset(Adc *p_adc, const enum adc_channel_num_t channel);
void adc_set_channel_input_gain(Adc *p_adc, const enum adc_channel_num_t channel,
const enum adc_gainvalue_t uc_gain);
void adc_set_bias_current(Adc *p_adc, const uint8_t uc_ibctl);
void adc_enable_ts(Adc *p_adc);
void adc_disable_ts(Adc *p_adc);
#elif SAM3N_SERIES
void adc_configure_timing(Adc *p_adc, const uint8_t uc_tracking);
#elif SAM3U_SERIES
void adc_configure_timing(Adc *p_adc, const uint32_t ul_sh);
#endif
#if SAM3SD8_SERIES || SAM4S_SERIES
void adc_set_calibmode(Adc *p_adc);
#endif
#if SAM3U_SERIES
uint32_t adc12b_init(Adc12b *p_adc, const uint32_t ul_mck, const uint32_t ul_adc_clock,
const uint32_t ul_startuptime, const uint32_t ul_offmode_startuptime);
void adc12b_set_resolution(Adc12b *p_adc, const enum adc_resolution_t resolution);
void adc12b_configure_trigger(Adc12b *p_adc, const enum adc_trigger_t trigger);
void adc12b_configure_power_save(Adc12b *p_adc, const uint8_t uc_sleep, const uint8_t uc_offmode);
void adc12b_configure_timing(Adc12b *p_adc, const uint32_t ul_sh);
void adc12b_start(Adc12b *p_adc);
void adc12b_stop(Adc12b *p_adc);
void adc12b_enable_channel(Adc12b *p_adc, const enum adc_channel_num_t adc_ch);
void adc12b_disable_channel(Adc12b *p_adc, const enum adc_channel_num_t adc_ch);
void adc12b_enable_all_channel(Adc12b *p_adc);
void adc12b_disable_all_channel(Adc12b *p_adc);
uint32_t adc12b_get_channel_status(const Adc12b *p_adc,const enum adc_channel_num_t adc_ch);
uint32_t adc12b_get_channel_value(const Adc12b *p_adc, const enum adc_channel_num_t adc_ch);
uint32_t adc12b_get_latest_value(const Adc12b *p_adc);
void adc12b_enable_differential_input(Adc12b *p_adc);
void adc12b_disable_differential_input(Adc12b *p_adc);
void adc12b_enable_input_offset(Adc12b *p_adc);
void adc12b_disable_input_offset(Adc12b *p_adc);
void adc12b_set_input_gain(Adc12b *p_adc, const enum adc_gainvalue_t uc_gain);
uint32_t adc12b_get_actual_adc_clock(const Adc12b *p_adc, const uint32_t ul_mck);
void adc12b_enable_interrupt(Adc12b *p_adc, const uint32_t ul_source);
void adc12b_disable_interrupt(Adc12b *p_adc, const uint32_t ul_source);
uint32_t adc12b_get_interrupt_mask(const Adc12b *p_adc);
uint32_t adc12b_get_status(const Adc12b *p_adc);
void adc12b_set_bias_current(Adc12b *p_adc, const uint8_t uc_ibctl);
Pdc *adc12b_get_pdc_base(const Adc12b *p_adc);
#endif
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond
#endif /* ADC_H_INCLUDED */

View File

@@ -0,0 +1,492 @@
/**
* \file
*
* \brief Controller Area Network (CAN) driver module for SAM.
*
* Copyright (c) 2011 - 2012 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* 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.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* 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.
*
* \asf_license_stop
*
*/
#ifndef CAN_H_INCLUDED
#define CAN_H_INCLUDED
#include "../chip.h"
/** @cond 0 */
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/** @endcond */
/** Define the Mailbox mask for eight mailboxes. */
#define GLOBAL_MAILBOX_MASK 0x000000ff
/** Disable all interrupt mask */
#define CAN_DISABLE_ALL_INTERRUPT_MASK 0xffffffff
/** Define the typical baudrate for CAN communication in KHz. */
#define CAN_BPS_1000K 1000
#define CAN_BPS_800K 800
#define CAN_BPS_500K 500
#define CAN_BPS_250K 250
#define CAN_BPS_125K 125
#define CAN_BPS_50K 50
#define CAN_BPS_25K 25
#define CAN_BPS_10K 10
#define CAN_BPS_5K 5
/** Define the mailbox mode. */
#define CAN_MB_DISABLE_MODE 0
#define CAN_MB_RX_MODE 1
#define CAN_MB_RX_OVER_WR_MODE 2
#define CAN_MB_TX_MODE 3
#define CAN_MB_CONSUMER_MODE 4
#define CAN_MB_PRODUCER_MODE 5
/** Define CAN mailbox transfer status code. */
#define CAN_MAILBOX_TRANSFER_OK 0 //! Read from or write into mailbox successfully.
#define CAN_MAILBOX_NOT_READY 0x01 //! Receiver is empty or transmitter is busy.
#define CAN_MAILBOX_RX_OVER 0x02 //! Message overwriting happens or there're messages lost in different receive modes.
#define CAN_MAILBOX_RX_NEED_RD_AGAIN 0x04 //! Application needs to re-read the data register in Receive with Overwrite mode.
/** Define the struct for CAN message mailbox. */
typedef struct {
uint32_t ul_mb_idx;
uint8_t uc_obj_type; //! Mailbox object type, one of the six different objects.
uint8_t uc_id_ver; //! 0 stands for standard frame, 1 stands for extended frame.
uint8_t uc_length; //! Received data length or transmitted data length.
uint8_t uc_tx_prio; //! Mailbox priority, no effect in receive mode.
uint32_t ul_status; //! Mailbox status register value.
uint32_t ul_id_msk; //! No effect in transmit mode.
uint32_t ul_id; //! Received frame ID or the frame ID to be transmitted.
uint32_t ul_fid; //! Family ID.
uint32_t ul_datal;
uint32_t ul_datah;
} can_mb_conf_t;
/**
* \defgroup sam_driver_can_group Controller Area Network (CAN) Driver
*
* See \ref sam_can_quickstart.
*
* \par Purpose
*
* The CAN controller provides all the features required to implement
* the serial communication protocol CAN defined by Robert Bosch GmbH,
* the CAN specification. This is a driver for configuration, enabling,
* disabling and use of the CAN peripheral.
*
* @{
*/
uint32_t can_init(Can *p_can, uint32_t ul_mck, uint32_t ul_baudrate);
void can_enable(Can *p_can);
void can_disable(Can *p_can);
void can_disable_low_power_mode(Can *p_can);
void can_enable_low_power_mode(Can *p_can);
void can_disable_autobaud_listen_mode(Can *p_can);
void can_enable_autobaud_listen_mode(Can *p_can);
void can_disable_overload_frame(Can *p_can);
void can_enable_overload_frame(Can *p_can);
void can_set_timestamp_capture_point(Can *p_can, uint32_t ul_flag);
void can_disable_time_triggered_mode(Can *p_can);
void can_enable_time_triggered_mode(Can *p_can);
void can_disable_timer_freeze(Can *p_can);
void can_enable_timer_freeze(Can *p_can);
void can_disable_tx_repeat(Can *p_can);
void can_enable_tx_repeat(Can *p_can);
void can_set_rx_sync_stage(Can *p_can, uint32_t ul_stage);
void can_enable_interrupt(Can *p_can, uint32_t dw_mask);
void can_disable_interrupt(Can *p_can, uint32_t dw_mask);
uint32_t can_get_interrupt_mask(Can *p_can);
uint32_t can_get_status(Can *p_can);
uint32_t can_get_internal_timer_value(Can *p_can);
uint32_t can_get_timestamp_value(Can *p_can);
uint8_t can_get_tx_error_cnt(Can *p_can);
uint8_t can_get_rx_error_cnt(Can *p_can);
void can_reset_internal_timer(Can *p_can);
void can_global_send_transfer_cmd(Can *p_can, uint8_t uc_mask);
void can_global_send_abort_cmd(Can *p_can, uint8_t uc_mask);
/*
* Mailbox functions
*/
void can_mailbox_set_timemark(Can *p_can, uint8_t uc_index, uint16_t us_cnt);
uint32_t can_mailbox_get_status(Can *p_can, uint8_t uc_index);
void can_mailbox_send_transfer_cmd(Can *p_can, uint8_t uc_index);
void can_mailbox_send_abort_cmd(Can *p_can, uint8_t uc_index);
void can_mailbox_init(Can *p_can, can_mb_conf_t *p_mailbox);
uint32_t can_mailbox_read(Can *p_can, can_mb_conf_t *p_mailbox);
uint32_t can_mailbox_write(Can *p_can, can_mb_conf_t *p_mailbox);
uint32_t can_mailbox_tx_remote_frame(Can *p_can, can_mb_conf_t *p_mailbox);
void can_reset_all_mailbox(Can *p_can);
// from wilfredo
uint32_t can_reset_mailbox_data(can_mb_conf_t *p_mailbox);
/** @} */
/** @cond 0 */
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/** @endcond */
/**
* \page sam_can_quickstart Quickstart guide for SAM CAN module.
*
* This is the quickstart guide for the \ref sam_drivers_can_group "SAM CAN module",
* with step-by-step instructions on how to configure and use the drivers in a
* selection of use cases.
*
* The use cases contain several code fragments. The code fragments in the
* steps for setup can be copied into a custom initialization function, while
* the steps for usage can be copied into, e.g., the main application function.
*
* \section can_basic_use_case Basic use case
* In this basic use case, as CAN module needs to work in network, two CAN modules
* need to be configured. CAN0 mailbox 0 is configured as transmitter, and CAN1 mailbox 0
* is configured as receiver. The communication baudrate is 1Mbit/s.
*
* \section can_basic_use_case_setup Setup steps
*
* \subsection can_basic_use_case_setup_prereq Prerequisites
* - \ref group_pmc "Power Management Controller driver"
* - \ref group_sn65hvd234_transceiver "CAN transceiver driver"
*
* \subsection can_basic_use_case_setup_code Example code
* Add to application initialization:
* \code
* can_mb_conf_t can0_mailbox;
* can_mb_conf_t can1_mailbox;
*
* pmc_enable_periph_clk(ID_CAN0);
* pmc_enable_periph_clk(ID_CAN1);
*
* can_init(CAN0, ul_sysclk, CAN_BPS_1000K);
* can_init(CAN1, ul_sysclk, CAN_BPS_1000K);
*
* can_reset_all_mailbox(CAN0);
* can_reset_all_mailbox(CAN1);
*
* can1_mailbox.ul_mb_idx = 0;
* can1_mailbox.uc_obj_type = CAN_MB_RX_MODE;
* can1_mailbox.ul_id_msk = CAN_MAM_MIDvA_Msk | CAN_MAM_MIDvB_Msk;
* can1_mailbox.ul_id = CAN_MID_MIDvA(0x07);
* can_mailbox_init(CAN1, &can1_mailbox);
*
* can0_mailbox.ul_mb_idx = 0;
* can0_mailbox.uc_obj_type = CAN_MB_TX_MODE;
* can0_mailbox.uc_tx_prio = 15;
* can0_mailbox.uc_id_ver = 0;
* can0_mailbox.ul_id_msk = 0;
* can_mailbox_init(CAN0, &can0_mailbox);
*
* can0_mailbox.ul_id = CAN_MID_MIDvA(0x07);
* can0_mailbox.ul_datal = 0x12345678;
* can0_mailbox.ul_datah = 0x87654321;
* can0_mailbox.uc_length = 8;
* can_mailbox_write(CAN0, &can0_mailbox);
* \endcode
*
* \subsection can_basic_use_case_setup_flow Workflow
* -# Define the CAN0 and CAN1 Transfer mailbox structure:
* - \code
* can_mb_conf_t can0_mailbox;
* can_mb_conf_t can1_mailbox;
* \endcode
* -# Enable the module clock for CAN0 and CAN1:
* - \code
* pmc_enable_periph_clk(ID_CAN0);
* pmc_enable_periph_clk(ID_CAN1);
* \endcode
* -# Initialize CAN0 and CAN1, baudrate is 1Mb/s:
* - \code
* can_init(CAN0, ul_sysclk, CAN_BPS_1000K);
* can_init(CAN1, ul_sysclk, CAN_BPS_1000K);
* \endcode
* - \note The CAN transceiver should be configured before initializing the CAN module.
* -# Reset all CAN0 and CAN1 mailboxes:
* - \code
* can_reset_all_mailbox(CAN0);
* can_reset_all_mailbox(CAN1);
* \endcode
* -# Initialize CAN1 mailbox 0 as receiver, frame ID is 0x07:
* - \code
* can1_mailbox.ul_mb_idx = 0;
* can1_mailbox.uc_obj_type = CAN_MB_RX_MODE;
* can1_mailbox.ul_id_msk = CAN_MAM_MIDvA_Msk | CAN_MAM_MIDvB_Msk;
* can1_mailbox.ul_id = CAN_MID_MIDvA(0x07);
* can_mailbox_init(CAN1, &can1_mailbox);
* \endcode
* -# Initialize CAN0 mailbox 0 as transmitter, transmit priority is 15:
* - \code
* can0_mailbox.ul_mb_idx = 0;
* can0_mailbox.uc_obj_type = CAN_MB_TX_MODE;
* can0_mailbox.uc_tx_prio = 15;
* can0_mailbox.uc_id_ver = 0;
* can0_mailbox.ul_id_msk = 0;
* can_mailbox_init(CAN0, &can0_mailbox);
* \endcode
* -# Prepare transmit ID, data and data length in CAN0 mailbox 0:
* - \code
* can0_mailbox.ul_id = CAN_MID_MIDvA(0x07);
* can0_mailbox.ul_datal = 0x12345678;
* can0_mailbox.ul_datah = 0x87654321;
* can0_mailbox.uc_length = 8;
* can_mailbox_write(CAN0, &can0_mailbox);
* \endcode
*
* \section can_basic_use_case_usage Usage steps
*
* \subsection can_basic_use_case_usage_code Example code
* Add to, e.g., main loop in application C-file:
* \code
* can_global_send_transfer_cmd(CAN0, CAN_TCR_MB0);
*
* while (!(can_mailbox_get_status(CAN1, 0) & CAN_MSR_MRDY)) {
* }
*
* can_mailbox_read(CAN1, &can1_mailbox);
* \endcode
*
* \subsection can_basic_use_case_usage_flow Workflow
* -# Send out data in CAN0 mailbox 0:
* - \code can_global_send_transfer_cmd(CAN0, CAN_TCR_MB0); \endcode
* -# Wait for CAN1 mailbox 0 to receive the data:
* - \code
* while (!(can_mailbox_get_status(CAN1, 0) & CAN_MSR_MRDY)) {
* }
* \endcode
* -# Read the received data from CAN1 mailbox 0:
* - \code can_mailbox_read(CAN1, &can1_mailbox); \endcode
*
* \section can_use_cases Advanced use cases
* For more advanced use of the CAN driver, see the following use cases:
* - \subpage can_use_case_1 : Two CAN modules work in PRODUCER and CONSUMER mode
* respectively, use CAN interrupt handler to check whether the communication has been
* completed.
*/
/**
* \page can_use_case_1 Use case #1
*
* In this use case, CAN0 mailbox 0 works in PRODUCER mode, and CAN1 mailbox 0
* works in CONSUMER mode. While CAN1 mailbox 0 receives a data frame from the bus,
* an interrupt is triggered.
*
* \section can_use_case_1_setup Setup steps
*
* \subsection can_basic_use_case_setup_prereq Prerequisites
* - \ref group_pmc "Power Management Controller driver"
* - \ref group_sn65hvd234_transceiver "CAN transceiver driver"
*
* \subsection can_use_case_1_setup_code Example code
* Add to application C-file:
* \code
* can_mb_conf_t can0_mailbox;
* can_mb_conf_t can1_mailbox;
* volatile uint32_t g_ul_recv_status = 0;
* \endcode
*
* \code
* void CAN1_Handler(void)
* {
* uint32_t ul_status;
*
* ul_status = can_mailbox_get_status(CAN1, 0);
* if ((ul_status & CAN_MSR_MRDY) == CAN_MSR_MRDY) {
* can1_mailbox.ul_mb_idx = 0;
* can1_mailbox.ul_status = ul_status;
* can_mailbox_read(CAN1, &can1_mailbox);
* g_ul_recv_status = 1;
* }
* }
* \endcode
*
* \code
* pmc_enable_periph_clk(ID_CAN0);
* pmc_enable_periph_clk(ID_CAN1);
*
* can_init(CAN0, ul_sysclk, CAN_BPS_1000K);
* can_init(CAN1, ul_sysclk, CAN_BPS_1000K);
*
* can_reset_all_mailbox(CAN0);
* can_reset_all_mailbox(CAN1);
*
* can0_mailbox.ul_mb_idx = 0;
* can0_mailbox.uc_obj_type = CAN_MB_PRODUCER_MODE;
* can0_mailbox.ul_id_msk = 0;
* can0_mailbox.ul_id = CAN_MID_MIDvA(0x0b);
* can_mailbox_init(CAN0, &can0_mailbox);
*
* can0_mailbox.ul_datal = 0x11223344;
* can0_mailbox.ul_datah = 0x44332211;
* can0_mailbox.uc_length = 8;
* can_mailbox_write(CAN0, &can0_mailbox);
*
* can1_mailbox.ul_mb_idx = 0;
* can1_mailbox.uc_obj_type = CAN_MB_CONSUMER_MODE;
* can1_mailbox.uc_tx_prio = 15;
* can1_mailbox.ul_id_msk = CAN_MID_MIDvA_Msk | CAN_MID_MIDvB_Msk;
* can1_mailbox.ul_id = CAN_MID_MIDvA(0x0b);
* can_mailbox_init(CAN1, &can1_mailbox);
*
* can_enable_interrupt(CAN1, CAN_IER_MB0);
* NVIC_EnableIRQ(CAN1_IRQn);
* \endcode
*
* \subsection can_use_case_1_setup_flow Workflow
* -# Define the CAN0 and CAN1 Transfer mailbox structure:
* - \code
* can_mb_conf_t can0_mailbox;
* can_mb_conf_t can1_mailbox;
* \endcode
* -# Define the receive flag that is changed in CAN1 ISR handler:
* - \code volatile uint32_t g_ul_recv_status = 0; \endcode
* -# Define the CAN1 ISR handler in the application:
* - \code void CAN1_Handler(void); \endcode
* -# In CAN1_Handler(), get CAN1 mailbox 0 status:
* - \code ul_status = can_mailbox_get_status(CAN1, 0); \endcode
* -# In CAN1_Handler(), check whether the mailbox 0 has received a data frame:
* - \code
* if ((ul_status & CAN_MSR_MRDY) == CAN_MSR_MRDY) {
* can1_mailbox.ul_mb_idx = 0;
* can1_mailbox.ul_status = ul_status;
* can_mailbox_read(CAN1, &can1_mailbox);
* g_ul_recv_status = 1;
* }
* \endcode
* -# In CAN1_Handler(), if mailbox 0 is ready, read the received data from CAN1 mailbox 0:
* - \code
* can1_mailbox.ul_mb_idx = 0;
* can1_mailbox.ul_status = ul_status;
* can_mailbox_read(CAN1, &can1_mailbox);
* \endcode
* -# In CAN1_Handler(), if mailbox 0 is ready, set up the receive flag:
* - \code g_ul_recv_status = 1; \endcode
* -# Enable the module clock for CAN0 and CAN1:
* - \code
* pmc_enable_periph_clk(ID_CAN0);
* pmc_enable_periph_clk(ID_CAN1);
* \endcode
* -# Initialize CAN0 and CAN1, baudrate is 1Mb/s:
* - \code
* can_init(CAN0, ul_sysclk, CAN_BPS_1000K);
* can_init(CAN1, ul_sysclk, CAN_BPS_1000K);
* \endcode
* - \note The CAN transceiver should be configured before initializing the CAN module.
* -# Reset all CAN0 and CAN1 mailboxes:
* - \code
* can_reset_all_mailbox(CAN0);
* can_reset_all_mailbox(CAN1);
* \endcode
* -# Initialize CAN0 mailbox 0 as PRODUCER:
* - \code
* can0_mailbox.ul_mb_idx = 0;
* can0_mailbox.uc_obj_type = CAN_MB_PRODUCER_MODE;
* can0_mailbox.ul_id_msk = 0;
* can0_mailbox.ul_id = CAN_MID_MIDvA(0x0b);
* can_mailbox_init(CAN0, &can0_mailbox);
* \endcode
* -# Prepare the response information when it receives a remote frame:
* - \code
* can0_mailbox.ul_datal = 0x11223344;
* can0_mailbox.ul_datah = 0x44332211;
* can0_mailbox.uc_length = 8;
* can_mailbox_write(CAN0, &can0_mailbox);
* \endcode
* -# Initialize CAN1 mailbox 0 as CONSUMER:
* - \code
* can1_mailbox.ul_mb_idx = 0;
* can1_mailbox.uc_obj_type = CAN_MB_CONSUMER_MODE;
* can1_mailbox.uc_tx_prio = 15;
* can1_mailbox.ul_id_msk = CAN_MID_MIDvA_Msk | CAN_MID_MIDvB_Msk;
* can1_mailbox.ul_id = CAN_MID_MIDvA(0x0b);
* can_mailbox_init(CAN1, &can1_mailbox);
* \endcode
* -# Enable the CAN1 mailbox 0 interrupt:
* - \code
* can_enable_interrupt(CAN1, CAN_IER_MB0);
* NVIC_EnableIRQ(CAN1_IRQn);
* \endcode
*
* \section can_use_case_1_usage Usage steps
*
* \subsection can_use_case_1_usage_code Example code
* \code
* can_global_send_transfer_cmd(CAN0, CAN_TCR_MB0);
* can_global_send_transfer_cmd(CAN1, CAN_TCR_MB0);
*
* while (!g_ul_recv_status) {
* }
* \endcode
*
* \subsection can_use_case_1_usage_flow Workflow
* -# Enable CAN0 mailbox 0 to receive remote frame and respond it:
* - \code can_global_send_transfer_cmd(CAN0, CAN_TCR_MB0); \endcode
* -# Enable CAN1 mailbox 0 to send out a remote frame and then receive data frame from bus:
* - \code can_global_send_transfer_cmd(CAN1, CAN_TCR_MB0); \endcode
* -# Wait for the communication to be completed.
* - \code
* while (!g_ul_recv_status) {
* }
* \endcode
*/
#endif /* CAN_H_INCLUDED */

View File

@@ -0,0 +1,102 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef DACC_H_INCLUDED
#define DACC_H_INCLUDED
#include "../chip.h"
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
//! DACC return codes
typedef enum dacc_rc {
DACC_RC_OK = 0, //!< Operation OK
DACC_RC_INVALID_PARAM //!< Invalid parameter
} dacc_rc_t;
#if SAM3N_SERIES
//! DACC resolution in number of data bits
# define DACC_RESOLUTION 10
#else
//! DACC resolution in number of data bits
# define DACC_RESOLUTION 12
#endif
//! DACC max data value
#define DACC_MAX_DATA ((1 << DACC_RESOLUTION) - 1)
void dacc_reset(Dacc *p_dacc);
uint32_t dacc_set_trigger(Dacc *p_dacc, uint32_t ul_trigger);
void dacc_disable_trigger(Dacc *p_dacc);
uint32_t dacc_set_transfer_mode(Dacc *p_dacc, uint32_t ul_mode);
void dacc_enable_interrupt(Dacc *p_dacc, uint32_t ul_interrupt_mask);
void dacc_disable_interrupt(Dacc *p_dacc, uint32_t ul_interrupt_mask);
uint32_t dacc_get_interrupt_mask(Dacc *p_dacc);
uint32_t dacc_get_interrupt_status(Dacc *p_dacc);
void dacc_write_conversion_data(Dacc *p_dacc, uint32_t ul_data);
void dacc_set_writeprotect(Dacc *p_dacc, uint32_t ul_enable);
uint32_t dacc_get_writeprotect_status(Dacc *p_dacc);
Pdc *dacc_get_pdc_base(Dacc *p_dacc);
#if (SAM3N_SERIES) || defined(__DOXYGEN__)
void dacc_enable(Dacc *p_dacc);
void dacc_disable(Dacc *p_dacc);
uint32_t dacc_set_timing(Dacc *p_dacc, uint32_t ul_startup,
uint32_t ul_clock_divider);
#endif /* (SAM3N_SERIES) */
#if (SAM3S_SERIES) || (SAM3XA_SERIES) || (SAM4S_SERIES) || defined(__DOXYGEN__)
uint32_t dacc_set_channel_selection(Dacc *p_dacc, uint32_t ul_channel);
void dacc_enable_flexible_selection(Dacc *p_dacc);
uint32_t dacc_set_power_save(Dacc *p_dacc, uint32_t ul_sleep_mode,
uint32_t ul_fast_wakeup_mode);
uint32_t dacc_set_timing(Dacc *p_dacc, uint32_t ul_refresh, uint32_t ul_maxs,
uint32_t ul_startup);
uint32_t dacc_enable_channel(Dacc *p_dacc, uint32_t ul_channel);
uint32_t dacc_disable_channel(Dacc *p_dacc, uint32_t ul_channel);
uint32_t dacc_get_channel_status(Dacc *p_dacc);
uint32_t dacc_set_analog_control(Dacc *p_dacc, uint32_t ul_analog_control);
uint32_t dacc_get_analog_control(Dacc *p_dacc);
#endif /* (SAM3S_SERIES) || (SAM3XA_SERIES) */
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond
#endif /* DACC_H_INCLUDED */

View File

@@ -0,0 +1,132 @@
/**
* \file
*
* \brief Embedded Flash Controller (EFC) driver for SAM.
*
* Copyright (c) 2011-2012 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* 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.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* 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.
*
* \asf_license_stop
*
*/
#ifndef EFC_H_INCLUDED
#define EFC_H_INCLUDED
#include "../chip.h"
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
/*! \name EFC return codes */
//! @{
typedef enum efc_rc {
EFC_RC_OK = 0, //!< Operation OK
EFC_RC_YES = 0, //!< Yes
EFC_RC_NO = 1, //!< No
EFC_RC_ERROR = 1, //!< General error
EFC_RC_INVALID, //!< Invalid argument input
EFC_RC_NOT_SUPPORT = 0xFFFFFFFF //!< Operation is not supported
} efc_rc_t;
//! @}
/*! \name EFC command */
//! @{
#define EFC_FCMD_GETD 0x00 //!< Get Flash Descriptor
#define EFC_FCMD_WP 0x01 //!< Write page
#define EFC_FCMD_WPL 0x02 //!< Write page and lock
#define EFC_FCMD_EWP 0x03 //!< Erase page and write page
#define EFC_FCMD_EWPL 0x04 //!< Erase page and write page then lock
#define EFC_FCMD_EA 0x05 //!< Erase all
#if (SAM3SD8_SERIES)
#define EFC_FCMD_EPL 0x06 //!< Erase plane
#endif
#if (SAM4S_SERIES)
#define EFC_FCMD_EPA 0x07 //!< Erase pages
#endif
#define EFC_FCMD_SLB 0x08 //!< Set Lock Bit
#define EFC_FCMD_CLB 0x09 //!< Clear Lock Bit
#define EFC_FCMD_GLB 0x0A //!< Get Lock Bit
#define EFC_FCMD_SGPB 0x0B //!< Set GPNVM Bit
#define EFC_FCMD_CGPB 0x0C //!< Clear GPNVM Bit
#define EFC_FCMD_GGPB 0x0D //!< Get GPNVM Bit
#define EFC_FCMD_STUI 0x0E //!< Start unique ID
#define EFC_FCMD_SPUI 0x0F //!< Stop unique ID
#if (SAM3S_SERIES || SAM3N_SERIES || SAM3XA_SERIES || SAM4S_SERIES)
#define EFC_FCMD_GCALB 0x10 //!< Get CALIB Bit
#endif
#if (SAM4S_SERIES)
#define EFC_FCMD_ES 0x11 //!< Erase sector
#define EFC_FCMD_WUS 0x12 //!< Write user signature
#define EFC_FCMD_EUS 0x13 //!< Erase user signature
#define EFC_FCMD_STUS 0x14 //!< Start read user signature
#define EFC_FCMD_SPUS 0x15 //!< Stop read user signature
#endif
//! @}
/*! The IAP function entry address */
#define CHIP_FLASH_IAP_ADDRESS (IROM_ADDR + 8)
/*! \name EFC access mode */
//! @{
#define EFC_ACCESS_MODE_128 0
#define EFC_ACCESS_MODE_64 EEFC_FMR_FAM
//! @}
uint32_t efc_init(Efc *p_efc, uint32_t ul_access_mode, uint32_t ul_fws);
void efc_enable_frdy_interrupt(Efc *p_efc);
void efc_disable_frdy_interrupt(Efc *p_efc);
void efc_set_flash_access_mode(Efc *p_efc, uint32_t ul_mode);
uint32_t efc_get_flash_access_mode(Efc *p_efc);
void efc_set_wait_state(Efc *p_efc, uint32_t ul_fws);
uint32_t efc_get_wait_state(Efc *p_efc);
uint32_t efc_perform_command(Efc *p_efc, uint32_t ul_command, uint32_t ul_argument);
uint32_t efc_get_status(Efc *p_efc);
uint32_t efc_get_result(Efc *p_efc);
uint32_t efc_perform_read_sequence(Efc *p_efc, uint32_t ul_cmd_st, uint32_t ul_cmd_sp, uint32_t *p_ul_buf, uint32_t ul_size);
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond
#endif /* EFC_H_INCLUDED */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,80 @@
/**
* \file
*
* \brief General Purpose Backup Registers (GPBR) driver for SAM.
*
* Copyright (c) 2011-2012 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* 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.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* 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.
*
* \asf_license_stop
*
*/
#ifndef GPBR_H_INCLUDED
#define GPBR_H_INCLUDED
#include "../chip.h"
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
/** GPBR register number type */
typedef enum gpbr_num_type {
GPBR0 = 0,
GPBR1,
GPBR2,
GPBR3,
GPBR4,
GPBR5,
GPBR6,
GPBR7
} gpbr_num_t;
uint32_t gpbr_read(gpbr_num_t ul_reg_num);
void gpbr_write(gpbr_num_t ul_reg_num, uint32_t ul_value);
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond
#endif /* GPBR_H_INCLUDED */

View File

@@ -0,0 +1,153 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef UTILS_INTERRUPT_INTERRUPT_H
#define UTILS_INTERRUPT_INTERRUPT_H
#include "../chip.h"
/**
* \weakgroup interrupt_group
*
* @{
*/
/**
* \name Interrupt Service Routine definition
*
* @{
*/
/**
* \brief Define service routine
*
* \note For NVIC devices the interrupt service routines are predefined to
* add to vector table in binary generation, so there is no service
* register at run time. The routine collections are in exceptions.h.
*
* Usage:
* \code
* ISR(foo_irq_handler)
* {
* // Function definition
* ...
* }
* \endcode
*
* \param func Name for the function.
*/
# define ISR(func) \
void func (void)
/**
* \brief Initialize interrupt vectors
*
* For NVIC the interrupt vectors are put in vector table. So nothing
* to do to initialize them, except defined the vector function with
* right name.
*
* This must be called prior to \ref irq_register_handler.
*/
# define irq_initialize_vectors() \
do { \
} while(0)
/**
* \brief Register handler for interrupt
*
* For NVIC the interrupt vectors are put in vector table. So nothing
* to do to register them, except defined the vector function with
* right name.
*
* Usage:
* \code
* irq_initialize_vectors();
* irq_register_handler(foo_irq_handler);
* \endcode
*
* \note The function \a func must be defined with the \ref ISR macro.
* \note The functions prototypes can be found in the device exception header
* files (exceptions.h).
*/
# define irq_register_handler(...) \
do { \
} while(0)
//@}
# define cpu_irq_enable() \
do { \
g_interrupt_enabled = 1; \
__DMB(); \
__enable_irq(); \
} while (0)
# define cpu_irq_disable() \
do { \
__disable_irq(); \
__DMB(); \
g_interrupt_enabled = 0; \
} while (0)
typedef uint32_t irqflags_t;
extern int g_interrupt_enabled;
static inline irqflags_t cpu_irq_save(void)
{
irqflags_t flags = g_interrupt_enabled;
cpu_irq_disable();
return flags;
}
static inline int cpu_irq_is_enabled_flags(irqflags_t flags)
{
return (flags);
}
static inline void cpu_irq_restore(irqflags_t flags)
{
if (cpu_irq_is_enabled_flags(flags))
cpu_irq_enable();
}
#define cpu_irq_is_enabled() g_interrupt_enabled
/**
* \weakgroup interrupt_deprecated_group
* @{
*/
#define Enable_global_interrupt() cpu_irq_enable()
#define Disable_global_interrupt() cpu_irq_disable()
#define Is_global_interrupt_enabled() cpu_irq_is_enabled()
//@}
//@}
#endif /* UTILS_INTERRUPT_INTERRUPT_H */

View File

@@ -0,0 +1,132 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef _PIO_
#define _PIO_
/*
* Headers
*/
#include "../chip.h"
#include <stdint.h>
/*
* Global Definitions
*/
typedef enum _EPioType
{
PIO_NOT_A_PIN, /* Not under control of a peripheral. */
PIO_PERIPH_A, /* The pin is controlled by the associated signal of peripheral A. */
PIO_PERIPH_B, /* The pin is controlled by the associated signal of peripheral B. */
#if (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3N_)
PIO_PERIPH_C, /* The pin is controlled by the associated signal of peripheral C. */
PIO_PERIPH_D, /* The pin is controlled by the associated signal of peripheral D. */
#endif /* (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3N_) */
PIO_INPUT, /* The pin is an input. */
PIO_OUTPUT_0, /* The pin is an output and has a default level of 0. */
PIO_OUTPUT_1 /* The pin is an output and has a default level of 1. */
} EPioType ;
/* Default pin configuration (no attribute). */
#define PIO_DEFAULT (0u << 0)
/* The internal pin pull-up is active. */
#define PIO_PULLUP (1u << 0)
/* The internal glitch filter is active. */
#define PIO_DEGLITCH (1u << 1)
/* The pin is open-drain. */
#define PIO_OPENDRAIN (1u << 2)
/* The internal debouncing filter is active. */
#define PIO_DEBOUNCE (1u << 3)
/* Enable additional interrupt modes. */
#define PIO_IT_AIME (1u << 4)
/* Interrupt High Level/Rising Edge detection is active. */
#define PIO_IT_RE_OR_HL (1u << 5)
/* Interrupt Edge detection is active. */
#define PIO_IT_EDGE (1u << 6)
/* Low level interrupt is active */
#define PIO_IT_LOW_LEVEL (0 | 0 | PIO_IT_AIME)
/* High level interrupt is active */
#define PIO_IT_HIGH_LEVEL (PIO_IT_RE_OR_HL | 0 | PIO_IT_AIME)
/* Falling edge interrupt is active */
#define PIO_IT_FALL_EDGE (0 | PIO_IT_EDGE | PIO_IT_AIME)
/* Rising edge interrupt is active */
#define PIO_IT_RISE_EDGE (PIO_IT_RE_OR_HL | PIO_IT_EDGE | PIO_IT_AIME)
#ifdef __cplusplus
extern "C" {
#endif
/*
* The #attribute# field is a bitmask that can either be set to PIO_DEFAULt,
* or combine (using bitwise OR '|') any number of the following constants:
* - PIO_PULLUP
* - PIO_DEGLITCH
* - PIO_DEBOUNCE
* - PIO_OPENDRAIN
* - PIO_IT_LOW_LEVEL
* - PIO_IT_HIGH_LEVEL
* - PIO_IT_FALL_EDGE
* - PIO_IT_RISE_EDGE
*/
/*
* Global Functions
*/
extern void PIO_DisableInterrupt( Pio* pPio, const uint32_t dwMask ) ;
extern void PIO_PullUp( Pio* pPio, const uint32_t dwMask, const uint32_t dwPullUpEnable ) ;
extern void PIO_SetDebounceFilter( Pio* pPio, const uint32_t dwMask, const uint32_t dwCuttOff ) ;
extern void PIO_Set( Pio* pPio, const uint32_t dwMask ) ;
extern void PIO_Clear( Pio* pPio, const uint32_t dwMask ) ;
extern uint32_t PIO_Get( Pio* pPio, const EPioType dwType, const uint32_t dwMask ) ;
extern void PIO_SetPeripheral( Pio* pPio, const EPioType dwType, const uint32_t dwMask ) ;
extern void PIO_SetInput( Pio* pPio, uint32_t dwMask, uint32_t dwAttribute ) ;
extern void PIO_SetOutput( Pio* pPio, uint32_t dwMask, uint32_t dwDefaultValue,
uint32_t dwMultiDriveEnable, uint32_t dwPullUpEnable ) ;
extern uint32_t PIO_Configure( Pio* pPio, const EPioType dwType, const uint32_t dwMask, const uint32_t dwAttribute ) ;
extern uint32_t PIO_GetOutputDataStatus( const Pio* pPio, const uint32_t dwMask ) ;
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _PIO_ */

View File

@@ -0,0 +1,96 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* \par Purpose
*
* Configuration and handling of interrupts on PIO status changes. The API
* provided here have several advantages over the traditional PIO interrupt
* configuration approach:
* - It is highly portable
* - It automatically demultiplexes interrupts when multiples pins have been
* configured on a single PIO controller
* - It allows a group of pins to share the same interrupt
*
* However, it also has several minor drawbacks that may prevent from using it
* in particular applications:
* - It enables the clocks of all PIO controllers
* - PIO controllers all share the same interrupt handler, which does the
* demultiplexing and can be slower than direct configuration
* - It reserves space for a fixed number of interrupts, which can be
* increased by modifying the appropriate constant in pio_it.c.
*
* \par Usage
*
* -# Initialize the PIO interrupt mechanism using PIO_InitializeInterrupts()
* with the desired priority (0 ... 7).
* -# Configure a status change interrupt on one or more pin(s) with
* PIO_ConfigureIt().
* -# Enable & disable interrupts on pins using PIO_EnableIt() and
* PIO_DisableIt().
*/
#ifndef _PIO_IT_
#define _PIO_IT_
/*
* Headers
*/
#include "pio.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* Global functions
*/
extern void PIO_InitializeInterrupts( uint32_t dwPriority ) ;
extern void PIO_ConfigureIt( const Pin *pPin, void (*handler)( const Pin* ) ) ;
extern void PIO_EnableIt( const Pio* pPio, const uint32_t dwMask ) ;
extern void PIO_DisableIt( const Pio* pPio, const uint32_t dwMask ) ;
extern void PIO_IT_InterruptHandler( void ) ;
extern void PioInterruptHandler( uint32_t id, Pio *pPio ) ;
extern void PIO_CaptureHandler( void ) ;
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _PIO_IT_ */

View File

@@ -0,0 +1,424 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef PMC_H_INCLUDED
#define PMC_H_INCLUDED
#include "../chip.h"
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
/** Bit mask for peripheral clocks (PCER0) */
#define PMC_MASK_STATUS0 (0xFFFFFFFC)
/** Bit mask for peripheral clocks (PCER1) */
#define PMC_MASK_STATUS1 (0xFFFFFFFF)
/** Loop counter timeout value */
#define PMC_TIMEOUT (2048)
/** Key to unlock CKGR_MOR register */
#define PMC_CKGR_MOR_KEY_VALUE CKGR_MOR_KEY(0x37)
/** Key used to write SUPC registers */
#define SUPC_KEY_VALUE ((uint32_t) 0xA5)
/** PMC xtal statup time */
#define PMC_XTAL_STARTUP_TIME (0x3F)
/** Mask to access fast startup input */
#define PMC_FAST_STARTUP_Msk (0xFFFFu)
/** PMC_WPMR Write Protect KEY, unlock it */
#define PMC_WPMR_WPKEY_VALUE PMC_WPMR_WPKEY((uint32_t) 0x504D43)
/** Using external oscillator */
#define PMC_OSC_XTAL 0
/** Oscillator in bypass mode */
#define PMC_OSC_BYPASS 1
#define PMC_PCK_0 0 /* PCK0 ID */
#define PMC_PCK_1 1 /* PCK1 ID */
#define PMC_PCK_2 2 /* PCK2 ID */
/**
* \name Master clock (MCK) Source and Prescaler configuration
*
* The following functions may be used to select the clock source and
* prescaler for the master clock.
*/
//@{
void pmc_mck_set_prescaler(uint32_t ul_pres);
void pmc_mck_set_source(uint32_t ul_source);
uint32_t pmc_switch_mck_to_sclk(uint32_t ul_pres);
uint32_t pmc_switch_mck_to_mainck(uint32_t ul_pres);
uint32_t pmc_switch_mck_to_pllack(uint32_t ul_pres);
#if (SAM3S_SERIES || SAM4S_SERIES)
uint32_t pmc_switch_mck_to_pllbck(uint32_t ul_pres);
#endif
#if (SAM3XA_SERIES || SAM3U_SERIES)
uint32_t pmc_switch_mck_to_upllck(uint32_t ul_pres);
#endif
//@}
/**
* \name Slow clock (SLCK) oscillator and configuration
*
*/
//@{
void pmc_switch_sclk_to_32kxtal(uint32_t ul_bypass);
uint32_t pmc_osc_is_ready_32kxtal(void);
//@}
/**
* \name Main Clock (MAINCK) oscillator and configuration
*
*/
//@{
void pmc_switch_mainck_to_fastrc(uint32_t ul_moscrcf);
void pmc_osc_enable_fastrc(uint32_t ul_rc);
void pmc_osc_disable_fastrc(void);
void pmc_switch_mainck_to_xtal(uint32_t ul_bypass);
void pmc_osc_disable_xtal(uint32_t ul_bypass);
uint32_t pmc_osc_is_ready_mainck(void);
//@}
/**
* \name PLL oscillator and configuration
*
*/
//@{
void pmc_enable_pllack(uint32_t mula, uint32_t pllacount, uint32_t diva);
void pmc_disable_pllack(void);
uint32_t pmc_is_locked_pllack(void);
#if (SAM3S_SERIES || SAM4S_SERIES)
void pmc_enable_pllbck(uint32_t mulb, uint32_t pllbcount, uint32_t divb);
void pmc_disable_pllbck(void);
uint32_t pmc_is_locked_pllbck(void);
#endif
#if (SAM3XA_SERIES || SAM3U_SERIES)
void pmc_enable_upll_clock(void);
void pmc_disable_upll_clock(void);
uint32_t pmc_is_locked_upll(void);
#endif
//@}
/**
* \name Peripherals clock configuration
*
*/
//@{
uint32_t pmc_enable_periph_clk(uint32_t ul_id);
uint32_t pmc_disable_periph_clk(uint32_t ul_id);
void pmc_enable_all_periph_clk(void);
void pmc_disable_all_periph_clk(void);
uint32_t pmc_is_periph_clk_enabled(uint32_t ul_id);
//@}
/**
* \name Programmable clock Source and Prescaler configuration
*
* The following functions may be used to select the clock source and
* prescaler for the specified programmable clock.
*/
//@{
void pmc_pck_set_prescaler(uint32_t ul_id, uint32_t ul_pres);
void pmc_pck_set_source(uint32_t ul_id, uint32_t ul_source);
uint32_t pmc_switch_pck_to_sclk(uint32_t ul_id, uint32_t ul_pres);
uint32_t pmc_switch_pck_to_mainck(uint32_t ul_id, uint32_t ul_pres);
uint32_t pmc_switch_pck_to_pllack(uint32_t ul_id, uint32_t ul_pres);
#if (SAM3S_SERIES || SAM4S_SERIES)
uint32_t pmc_switch_pck_to_pllbck(uint32_t ul_id, uint32_t ul_pres);
#endif
#if (SAM3XA_SERIES || SAM3U_SERIES)
uint32_t pmc_switch_pck_to_upllck(uint32_t ul_id, uint32_t ul_pres);
#endif
void pmc_enable_pck(uint32_t ul_id);
void pmc_disable_pck(uint32_t ul_id);
void pmc_enable_all_pck(void);
void pmc_disable_all_pck(void);
uint32_t pmc_is_pck_enabled(uint32_t ul_id);
//@}
/**
* \name USB clock configuration
*
*/
//@{
#if (SAM3S_SERIES || SAM3XA_SERIES || SAM4S_SERIES)
void pmc_switch_udpck_to_pllack(uint32_t ul_usbdiv);
#endif
#if (SAM3S_SERIES || SAM4S_SERIES)
void pmc_switch_udpck_to_pllbck(uint32_t ul_usbdiv);
#endif
#if (SAM3XA_SERIES)
void pmc_switch_udpck_to_upllck(uint32_t ul_usbdiv);
#endif
#if (SAM3S_SERIES || SAM3XA_SERIES || SAM4S_SERIES)
void pmc_enable_udpck(void);
void pmc_disable_udpck(void);
#endif
//@}
/**
* \name Interrupt and status management
*
*/
//@{
void pmc_enable_interrupt(uint32_t ul_sources);
void pmc_disable_interrupt(uint32_t ul_sources);
uint32_t pmc_get_interrupt_mask(void);
uint32_t pmc_get_status(void);
//@}
/**
* \name Power management
*
* The following functions are used to configure sleep mode and additionnal
* wake up inputs.
*/
//@{
void pmc_set_fast_startup_input(uint32_t ul_inputs);
void pmc_clr_fast_startup_input(uint32_t ul_inputs);
void pmc_enable_sleepmode(uint8_t uc_type);
void pmc_enable_waitmode(void);
void pmc_enable_backupmode(void);
//@}
/**
* \name Write protection
*
*/
//@{
void pmc_set_writeprotect(uint32_t ul_enable);
uint32_t pmc_get_writeprotect_status(void);
//@}
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond
//! @}
/**
* \page sam_pmc_quickstart Quick start guide for the SAM PMC module
*
* This is the quick start guide for the \ref pmc_group "PMC module", with
* step-by-step instructions on how to configure and use the driver in a
* selection of use cases.
*
* The use cases contain several code fragments. The code fragments in the
* steps for setup can be copied into a custom initialization function, while
* the steps for usage can be copied into, e.g., the main application function.
*
* \section pmc_use_cases PMC use cases
* - \ref pmc_basic_use_case Basic use case - Switch Main Clock sources
* - \ref pmc_use_case_2 Advanced use case - Configure Programmable Clocks
*
* \section pmc_basic_use_case Basic use case - Switch Main Clock sources
* In this use case, the PMC module is configured for a variety of system clock
* sources and speeds. A LED is used to visually indicate the current clock
* speed as the source is switched.
*
* \section pmc_basic_use_case_setup Setup
*
* \subsection pmc_basic_use_case_setup_prereq Prerequisites
* -# \ref gpio_group "General Purpose I/O Management (gpio)"
*
* \subsection pmc_basic_use_case_setup_code Code
* The following function needs to be added to the user application, to flash a
* board LED a variable number of times at a rate given in CPU ticks.
*
* \code
* #define FLASH_TICK_COUNT 0x00012345
*
* void flash_led(uint32_t tick_count, uint8_t flash_count)
* {
* SysTick->CTRL = SysTick_CTRL_ENABLE_Msk;
* SysTick->LOAD = tick_count;
*
* while (flash_count--)
* {
* gpio_toggle_pin(LED0_GPIO);
* while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
* gpio_toggle_pin(LED0_GPIO);
* while (!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk));
* }
* }
* \endcode
*
* \section pmc_basic_use_case_usage Use case
*
* \subsection pmc_basic_use_case_usage_code Example code
* Add to application C-file:
* \code
* for (;;)
* {
* pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_12_MHz);
* flash_led(FLASH_TICK_COUNT, 5);
* pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_8_MHz);
* flash_led(FLASH_TICK_COUNT, 5);
* pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_4_MHz);
* flash_led(FLASH_TICK_COUNT, 5);
* pmc_switch_mainck_to_xtal(0);
* flash_led(FLASH_TICK_COUNT, 5);
* }
* \endcode
*
* \subsection pmc_basic_use_case_usage_flow Workflow
* -# Wrap the code in an infinite loop:
* \code
* for (;;)
* \endcode
* -# Switch the Master CPU frequency to the internal 12MHz RC oscillator, flash
* a LED on the board several times:
* \code
* pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_12_MHz);
* flash_led(FLASH_TICK_COUNT, 5);
* \endcode
* -# Switch the Master CPU frequency to the internal 8MHz RC oscillator, flash
* a LED on the board several times:
* \code
* pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_8_MHz);
* flash_led(FLASH_TICK_COUNT, 5);
* \endcode
* -# Switch the Master CPU frequency to the internal 4MHz RC oscillator, flash
* a LED on the board several times:
* \code
* pmc_switch_mainck_to_fastrc(CKGR_MOR_MOSCRCF_4_MHz);
* flash_led(FLASH_TICK_COUNT, 5);
* \endcode
* -# Switch the Master CPU frequency to the external crystal oscillator, flash
* a LED on the board several times:
* \code
* pmc_switch_mainck_to_xtal(0);
* flash_led(FLASH_TICK_COUNT, 5);
* \endcode
*/
/**
* \page pmc_use_case_2 Use case #2 - Configure Programmable Clocks
* In this use case, the PMC module is configured to start the Slow Clock from
* an attached 32KHz crystal, and start one of the Programmable Clock modules
* sourced from the Slow Clock divided down with a prescale factor of 64.
*
* \section pmc_use_case_2_setup Setup
*
* \subsection pmc_use_case_2_setup_prereq Prerequisites
* -# \ref pio_group "Parallel Input/Output Controller (pio)"
*
* \subsection pmc_use_case_2_setup_code Code
* The following code must be added to the user application:
* \code
* pio_set_peripheral(PIOA, PIO_PERIPH_B, PIO_PA17);
* \endcode
*
* \subsection pmc_use_case_2_setup_code_workflow Workflow
* -# Configure the PCK1 pin to output on a specific port pin (in this case,
* PIOA pin 17) of the microcontroller.
* \code
* pio_set_peripheral(PIOA, PIO_PERIPH_B, PIO_PA17);
* \endcode
* \note The peripheral selection and pin will vary according to your selected
* SAM device model. Refer to the "Peripheral Signal Multiplexing on I/O
* Lines" of your device's datasheet.
*
* \section pmc_use_case_2_usage Use case
* The generated PCK1 clock output can be viewed on an oscilloscope attached to
* the correct pin of the microcontroller.
*
* \subsection pmc_use_case_2_usage_code Example code
* Add to application C-file:
* \code
* pmc_switch_sclk_to_32kxtal(PMC_OSC_XTAL);
* pmc_switch_pck_to_sclk(PMC_PCK_1, PMC_PCK_PRES_CLK_64);
* pmc_enable_pck(PMC_PCK_1);
*
* for (;;)
* {
* // Do Nothing
* }
* \endcode
*
* \subsection pmc_use_case_2_usage_flow Workflow
* -# Switch the Slow Clock source input to an external 32KHz crystal:
* \code
* pmc_switch_sclk_to_32kxtal(PMC_OSC_XTAL);
* \endcode
* -# Switch the Programmable Clock module PCK1 source clock to the Slow Clock,
* with a prescaler of 64:
* \code
* pmc_switch_pck_to_sclk(PMC_PCK_1, PMC_PCK_PRES_CLK_64);
* \endcode
* -# Enable Programmable Clock module PCK1:
* \code
* pmc_enable_pck(PMC_PCK_1);
* \endcode
* -# Enter an infinite loop:
* \code
* for (;;)
* {
* // Do Nothing
* }
* \endcode
*/
#endif /* PMC_H_INCLUDED */

View File

@@ -0,0 +1,109 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* \par Purpose
*
* Interface for configuration the Pulse Width Modulation Controller (PWM) peripheral.
*
* \par Usage
*
* -# Configures PWM clocks A & B to run at the given frequencies using
* \ref PWMC_ConfigureClocks().
* -# Configure PWMC channel using \ref PWMC_ConfigureChannel(), \ref PWMC_ConfigureChannelExt()
* \ref PWMC_SetPeriod(), \ref PWMC_SetDutyCycle() and \ref PWMC_SetDeadTime().
* -# Enable & disable channel using \ref PWMC_EnableChannel() and
* \ref PWMC_DisableChannel().
* -# Enable & disable the period interrupt for the given PWM channel using
* \ref PWMC_EnableChannelIt() and \ref PWMC_DisableChannelIt().
* -# Enable & disable the selected interrupts sources on a PWMC peripheral
* using \ref PWMC_EnableIt() and \ref PWMC_DisableIt().
* -# Control syncronous channel using \ref PWMC_ConfigureSyncChannel(),
* \ref PWMC_SetSyncChannelUpdatePeriod() and \ref PWMC_SetSyncChannelUpdateUnlock().
* -# Control PWM override output using \ref PWMC_SetOverrideValue(),
* \ref PWMC_EnableOverrideOutput() and \ref PWMC_DisableOverrideOutput().
* -# Send data through the transmitter using \ref PWMC_WriteBuffer().
*
*/
#ifndef _PWMC_
#define _PWMC_
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "../chip.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
extern void PWMC_ConfigureChannel( Pwm* pPwm, uint32_t ul_channel, uint32_t prescaler, uint32_t alignment, uint32_t polarity ) ;
extern void PWMC_ConfigureChannelExt( Pwm* pPwm, uint32_t ul_channel, uint32_t prescaler, uint32_t alignment, uint32_t polarity,
uint32_t countEventSelect, uint32_t DTEnable, uint32_t DTHInverte, uint32_t DTLInverte ) ;
extern void PWMC_ConfigureClocks(uint32_t clka, uint32_t clkb, uint32_t mck ) ;
extern void PWMC_SetPeriod( Pwm* pPwm, uint32_t ul_channel, uint16_t period ) ;
extern void PWMC_SetDutyCycle( Pwm* pPwm, uint32_t ul_channel, uint16_t duty ) ;
extern void PWMC_SetDeadTime( Pwm* pPwm, uint32_t ul_channel, uint16_t timeH, uint16_t timeL ) ;
extern void PWMC_ConfigureSyncChannel( Pwm* pPwm, uint32_t ul_channels, uint32_t updateMode, uint32_t requestMode, uint32_t requestComparisonSelect ) ;
extern void PWMC_SetSyncChannelUpdatePeriod( Pwm* pPwm, uint8_t period ) ;
extern void PWMC_SetSyncChannelUpdateUnlock( Pwm* pPwm ) ;
extern void PWMC_EnableChannel( Pwm* pPwm, uint32_t ul_channel ) ;
extern void PWMC_DisableChannel( Pwm* pPwm, uint32_t ul_channel ) ;
extern void PWMC_EnableChannelIt( Pwm* pPwm, uint32_t ul_channel ) ;
extern void PWMC_DisableChannelIt( Pwm* pPwm, uint32_t ul_channel ) ;
extern void PWMC_EnableIt( Pwm* pPwm, uint32_t sources1, uint32_t sources2 ) ;
extern void PWMC_DisableIt( Pwm* pPwm, uint32_t sources1, uint32_t sources2 ) ;
extern uint8_t PWMC_WriteBuffer(Pwm *pwmc, void *buffer, uint32_t length ) ;
extern void PWMC_SetOverrideValue( Pwm* pPwm, uint32_t value ) ;
extern void PWMC_EnableOverrideOutput( Pwm* pPwm, uint32_t value, uint32_t sync ) ;
extern void PWMC_DisableOverrideOutput( Pwm* pPwm, uint32_t value, uint32_t sync ) ;
extern void PWMC_SetFaultMode( Pwm* pPwm, uint32_t mode ) ;
extern void PWMC_FaultClear( Pwm* pPwm, uint32_t fault ) ;
extern void PWMC_SetFaultProtectionValue( Pwm* pPwm, uint32_t value ) ;
extern void PWMC_EnableFaultProtection( Pwm* pPwm, uint32_t ul_channel, uint32_t value ) ;
extern void PWMC_ConfigureComparisonUnit( Pwm* pPwm, uint32_t x, uint32_t value, uint32_t mode ) ;
extern void PWMC_ConfigureEventLineMode( Pwm* pPwm, uint32_t x, uint32_t mode ) ;
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _PWMC_ */

View File

@@ -0,0 +1,78 @@
/**
* \file
*
* \brief Reset Controller (RSTC) driver for SAM.
*
* Copyright (c) 2011-2012 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* 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.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* 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.
*
* \asf_license_stop
*
*/
#ifndef RSTC_H_INCLUDED
#define RSTC_H_INCLUDED
#include "../chip.h"
#ifdef __cplusplus
extern "C" {
#endif
/** Definitions of Reset Controller Status */
/** Reset cause */
#define RSTC_GENERAL_RESET (0 << RSTC_SR_RSTTYP_Pos)
#define RSTC_BACKUP_RESET (1 << RSTC_SR_RSTTYP_Pos)
#define RSTC_WATCHDOG_RESET (2 << RSTC_SR_RSTTYP_Pos)
#define RSTC_SOFTWARE_RESET (3 << RSTC_SR_RSTTYP_Pos)
#define RSTC_USER_RESET (4 << RSTC_SR_RSTTYP_Pos)
/** NRST Pin Level */
#define RSTC_NRST_LOW (LOW << 16)
#define RSTC_NRST_HIGH (HIGH << 16)
void rstc_set_external_reset(Rstc* p_rstc, const uint32_t ul_length);
void rstc_enable_user_reset(Rstc* p_rstc);
void rstc_disable_user_reset(Rstc* p_rstc);
void rstc_enable_user_reset_interrupt(Rstc* p_rstc);
void rstc_disable_user_reset_interrupt(Rstc* p_rstc);
void rstc_start_software_reset(Rstc* p_rstc);
void rstc_reset_extern(Rstc *p_rstc);
uint32_t rstc_get_status(Rstc* p_rstc);
uint32_t rstc_get_reset_cause(Rstc* p_rstc);
#ifdef __cplusplus
}
#endif
#endif /* RSTC_H_INCLUDED */

View File

@@ -0,0 +1,97 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Interface for Real Time Clock (RTC) controller.
*
*/
#ifndef _RTC_
#define _RTC_
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "../chip.h"
#include <stdint.h>
/*----------------------------------------------------------------------------
* Definitions
*----------------------------------------------------------------------------*/
#define RTC_HOUR_BIT_LEN_MASK 0x3F
#define RTC_MIN_BIT_LEN_MASK 0x7F
#define RTC_SEC_BIT_LEN_MASK 0x7F
#define RTC_CENT_BIT_LEN_MASK 0x7F
#define RTC_YEAR_BIT_LEN_MASK 0xFF
#define RTC_MONTH_BIT_LEN_MASK 0x1F
#define RTC_DATE_BIT_LEN_MASK 0x3F
#define RTC_WEEK_BIT_LEN_MASK 0x07
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
extern void RTC_SetHourMode( Rtc* pRtc, uint32_t dwMode ) ;
extern uint32_t RTC_GetHourMode( Rtc* pRtc ) ;
extern void RTC_EnableIt( Rtc* pRtc, uint32_t dwSources ) ;
extern void RTC_DisableIt( Rtc* pRtc, uint32_t dwSources ) ;
extern int RTC_SetTime( Rtc* pRtc, uint8_t ucHour, uint8_t ucMinute, uint8_t ucSecond ) ;
extern void RTC_GetTime( Rtc* pRtc, uint8_t *pucHour, uint8_t *pucMinute, uint8_t *pucSecond ) ;
extern int RTC_SetTimeAlarm( Rtc* pRtc, uint8_t *pucHour, uint8_t *pucMinute, uint8_t *pucSecond ) ;
extern void RTC_GetDate( Rtc* pRtc, uint16_t *pwYear, uint8_t *pucMonth, uint8_t *pucDay, uint8_t *pucWeek ) ;
extern int RTC_SetDate( Rtc* pRtc, uint16_t wYear, uint8_t ucMonth, uint8_t ucDay, uint8_t ucWeek ) ;
extern int RTC_SetDateAlarm( Rtc* pRtc, uint8_t *pucMonth, uint8_t *pucDay ) ;
extern void RTC_ClearSCCR( Rtc* pRtc, uint32_t dwMask ) ;
extern uint32_t RTC_GetSR( Rtc* pRtc, uint32_t dwMask ) ;
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _RTC_ */

View File

@@ -0,0 +1,82 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* \par Purpose
*
* Interface for Real Time Timer (RTT) controller.
*
* \par Usage
*
* -# Changes the prescaler value of the given RTT and restarts it
* using \ref RTT_SetPrescaler().
* -# Get current value of the RTT using \ref RTT_GetTime().
* -# Enables the specified RTT interrupt using \ref RTT_EnableIT().
* -# Get the status register value of the given RTT using \ref RTT_GetStatus().
* -# Configures the RTT to generate an alarm at the given time
* using \ref RTT_SetAlarm().
*/
#ifndef _RTT_
#define _RTT_
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "../chip.h"
#include <stdint.h>
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
extern void RTT_SetPrescaler( Rtt* pRtt, uint16_t wPrescaler ) ;
extern uint32_t RTT_GetTime( Rtt* pRtt ) ;
extern void RTT_EnableIT( Rtt* pRtt, uint32_t dwSources ) ;
extern uint32_t RTT_GetStatus( Rtt *pRtt ) ;
extern void RTT_SetAlarm( Rtt *pRtt, uint32_t dwTime ) ;
#ifdef __cplusplus
}
#endif
#endif /* #ifndef RTT_H */

View File

@@ -0,0 +1,117 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Interface for Serial Peripheral Interface (SPI) controller.
*
*/
#ifndef _SPI_
#define _SPI_
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "../chip.h"
/*----------------------------------------------------------------------------
* Macros
*----------------------------------------------------------------------------*/
/**
*
* Here are several macros which should be used when configuring a SPI
* peripheral.
*
* \section spi_configuration_macros SPI Configuration Macros
* - \ref SPI_PCS
* - \ref SPI_SCBR
* - \ref SPI_DLYBS
* - \ref SPI_DLYBCT
*/
/** Calculate the PCS field value given the chip select NPCS value */
#define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16)
/** Calculates the value of the CSR SCBR field given the baudrate and MCK. */
#define SPI_SCBR(baudrate, masterClock) ((uint32_t) ((masterClock) / (baudrate)) << 8)
/** Calculates the value of the CSR DLYBS field given the desired delay (in ns) */
#define SPI_DLYBS(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 1000) << 16)
/** Calculates the value of the CSR DLYBCT field given the desired delay (in ns) */
#define SPI_DLYBCT(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 32000) << 24)
/*------------------------------------------------------------------------------ */
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
extern void SPI_Enable( Spi* spi ) ;
extern void SPI_Disable( Spi* spi ) ;
extern void SPI_EnableIt( Spi* spi, uint32_t dwSources ) ;
extern void SPI_DisableIt( Spi* spi, uint32_t dwSources ) ;
extern void SPI_Configure( Spi* spi, uint32_t dwId, uint32_t dwConfiguration ) ;
extern void SPI_ConfigureNPCS( Spi* spi, uint32_t dwNpcs, uint32_t dwConfiguration ) ;
extern uint32_t SPI_Read( Spi* spi ) ;
extern void SPI_Write( Spi* spi, uint32_t dwNpcs, uint16_t wData ) ;
extern uint32_t SPI_GetStatus( Spi* spi ) ;
extern uint32_t SPI_IsFinished( Spi* pSpi ) ;
#if (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3N_)
extern void SPI_PdcEnableTx( Spi* spi ) ;
extern void SPI_PdcDisableTx( Spi* spi ) ;
extern void SPI_PdcEnableRx( Spi* spi ) ;
extern void SPI_PdcDisableRx( Spi* spi ) ;
extern void SPI_PdcSetTx( Spi* spi, void* pvTxBuf, uint32_t dwTxCount, void* pvTxNextBuf, uint32_t dwTxNextCount ) ;
extern void SPI_PdcSetRx( Spi* spi, void* pvRxBuf, uint32_t dwRxCount, void* pvRxNextBuf, uint32_t dwRxNextCount ) ;
extern uint32_t SPI_WriteBuffer( Spi* spi, void* pvBuffer, uint32_t dwLength ) ;
extern uint32_t SPI_ReadBuffer( Spi* spi, void* pvBuffer, uint32_t dwLength ) ;
#endif /* (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3N_) */
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _SPI_ */

View File

@@ -0,0 +1,210 @@
/**
* \file
*
* \brief Synchronous Serial Controller (SSC) driver for SAM.
*
* Copyright (c) 2011-2012 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* 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.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* 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.
*
* \asf_license_stop
*
*/
#ifndef SSC_H_INCLUDED
#define SSC_H_INCLUDED
#include "../chip.h"
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
//! Receive stop selection.
#define SSC_RX_STOP_COMPARE_0 0
#define SSC_RX_STOP_COMPARE_0_1 1
//! Compare register ID.
#define COMPARE_ID0 0
#define COMPARE_ID1 1
//! SSC module default timeout. */
#define SSC_DEFAULT_TIMEOUT 10000
//! \brief SSC driver return codes.
enum ssc_return_code {
SSC_RC_OK = 0, //!< OK
SSC_RC_YES = 0, //!< Yes
SSC_RC_NO = 1, //!< No
SSC_RC_ERROR = 1, //!< General error
SSC_RC_INVALID = 0xFFFFFFFF //!< Parameter invalid
};
//! Data frame structure.
typedef struct {
//! Data bits length per transfer, should be 0 to 31.
uint32_t ul_datlen;
//! Bit sequence LSBF or MSBF.
//! For receiver configuration, SSC_RFMR_MSBF or 0.
//! For transmitter configuration, SSC_TFMR_MSBF or 0.
uint32_t ul_msbf;
//! Data number per frame, should be 0 to 15.
uint32_t ul_datnb;
//! Frame Sync. length should be 0 to 15.
uint32_t ul_fslen;
//! Frame Sync. length extension field, should be 0 to 15.
uint32_t ul_fslen_ext;
//! Frame Sync. output selection.
//! For receiver configuration, one of SSC_RFMR_FSOS_NONE, SSC_RFMR_FSOS_NEGATIVE, SSC_RFMR_FSOS_POSITIVE,
//! SSC_RFMR_FSOS_LOW, SSC_RFMR_FSOS_HIGH or SSC_RFMR_FSOS_TOGGLING.
//! For transmitter configuration, one of SSC_TFMR_FSOS_NONE, SSC_TFMR_FSOS_NEGATIVE, SSC_TFMR_FSOS_POSITIVE
//! SSC_TFMR_FSOS_LOW, SSC_TFMR_FSOS_HIGH, SSC_TFMR_FSOS_TOGGLING,
uint32_t ul_fsos;
//! Frame Sync. edge detection.
//! For receiver configuration, SSC_RFMR_FSEDGE_POSITIVE or SSC_RFMR_FSEDGE_NEGATIVE.
//! For transmitter configuration, SSC_TFMR_FSEDGE_POSITIVE or SSC_TFMR_FSEDGE_NEGATIVE.
uint32_t ul_fsedge;
} data_frame_opt_t;
//! Clock mode structure.
typedef struct {
//! Communication clock selection.
//! For receiver configuration, one of SSC_RCMR_CKS_MCK, SSC_RCMR_CKS_TK or SSC_RCMR_CKS_RK.
//! For transmitter configuration, one of SSC_TCMR_CKS_MCK, SSC_TCMR_CKS_TK or SSC_TCMR_CKS_RK.
uint32_t ul_cks;
//! Communication clock output mode selection.
//! For receiver configuration, one of SSC_RCMR_CKO_NONE, SSC_RCMR_CKO_CONTINUOUS or SSC_RCMR_CKO_TRANSFER.
//! For transmitter configuration, one of SSC_TCMR_CKO_NONE, SSC_TCMR_CKO_CONTINUOUS or SSC_TCMR_CKO_TRANSFER.
uint32_t ul_cko;
//! Communication clock inversion.
//! For receiver configuration, SSC_RCMR_CKI or 0.
//! For transmitter configuration, SSC_TCMR_CKI or 0.
uint32_t ul_cki;
//! Communication clock gating selection.
//! For receiver configuration, one of SSC_RCMR_CKG_NONE, SSC_RCMR_CKG_CONTINUOUS and SSC_RCMR_CKG_TRANSFER.
//! For transmitter configuration, one of SSC_TCMR_CKG_NONE, SSC_TCMR_CKG_CONTINUOUS and SSC_TCMR_CKG_TRANSFER.
uint32_t ul_ckg;
//! Period divider selection, should be 0 to 255.
uint32_t ul_period;
//! Communication start delay, should be 0 to 255.
uint32_t ul_sttdly;
//! Communication start selection.
//! For receiver configuration, one of SSC_RCMR_START_CONTINUOUS, SSC_RCMR_START_TRANSMIT, SSC_RCMR_START_RF_LOW,
//! SSC_RCMR_START_RF_HIGH, SSC_RCMR_START_RF_FALLING, SSC_RCMR_START_RF_RISING, SSC_RCMR_START_RF_LEVEL,
//! SSC_RCMR_START_RF_EDGE or SSC_RCMR_START_CMP_0.
//! For transmitter configuration, one of SSC_TCMR_START_CONTINUOUS, SSC_TCMR_START_TRANSMIT, SSC_TCMR_START_RF_LOW,
//! SSC_TCMR_START_RF_HIGH, SSC_TCMR_START_RF_FALLING, SSC_TCMR_START_RF_RISING, SSC_TCMR_START_RF_LEVEL,
//! SSC_TCMR_START_RF_EDGE or SSC_TCMR_START_CMP_0.
uint32_t ul_start_sel;
} clock_opt_t;
//! SSC working role in I2S mode.
#define SSC_I2S_MASTER_OUT (1 << 0) //! Working mode for transmitter as master.
#define SSC_I2S_MASTER_IN (1 << 1) //! Working mode for receiver as master.
#define SSC_I2S_SLAVE_OUT (1 << 2) //! Working mode for transmitter as slave.
#define SSC_I2S_SLAVE_IN (1 << 3) //! Working mode for receiver as slave.
//! Bit for SSC Audio channel left.
#define SSC_AUDIO_CH_LEFT (1 << 0)
//! Bit for SSC Audio channel right.
#define SSC_AUDIO_CH_RIGHT (1 << 1)
//! SSC Audio Channel modes.
enum {
//! Mono, left channel enabled.
SSC_AUDIO_MONO_LEFT = (SSC_AUDIO_CH_LEFT),
//! Mono, right channel enabled.
SSC_AUDIO_MONO_RIGHT = (SSC_AUDIO_CH_RIGHT),
//! Stereo, two channels.
SSC_AUDIO_STERO = (SSC_AUDIO_CH_LEFT | SSC_AUDIO_CH_RIGHT)
};
uint32_t ssc_set_clock_divider(Ssc *p_ssc, uint32_t ul_bitclock, uint32_t ul_mck);
void ssc_i2s_set_transmitter(Ssc *p_ssc, uint32_t ul_mode,
uint32_t ul_cks, uint32_t ul_ch_mode, uint32_t ul_datlen);
void ssc_i2s_set_receiver(Ssc *p_ssc, uint32_t ul_mode,
uint32_t ul_cks, uint32_t ul_ch_mode, uint32_t ul_datlen);
void ssc_reset(Ssc *p_ssc);
void ssc_enable_rx(Ssc *p_ssc);
void ssc_disable_rx(Ssc *p_ssc);
void ssc_enable_tx(Ssc *p_ssc);
void ssc_disable_tx(Ssc *p_ssc);
void ssc_set_normal_mode(Ssc *p_ssc);
void ssc_set_loop_mode(Ssc *p_ssc);
void ssc_set_rx_stop_selection(Ssc *p_ssc, uint32_t ul_sel);
void ssc_set_td_default_level(Ssc *p_ssc, uint32_t ul_level);
void ssc_enable_tx_frame_sync_data(Ssc *p_ssc);
void ssc_disable_tx_frame_sync_data(Ssc *p_ssc);
void ssc_set_receiver(Ssc *p_ssc, clock_opt_t *p_rx_clk_opt, data_frame_opt_t *p_rx_data_frame);
void ssc_set_transmitter(Ssc *p_ssc, clock_opt_t *p_tx_clk_opt, data_frame_opt_t *p_tx_data_frame);
void ssc_set_rx_compare(Ssc *p_ssc, uint32_t ul_id, uint32_t ul_value);
uint32_t ssc_get_rx_compare(Ssc *p_ssc, uint32_t ul_id);
void ssc_enable_interrupt(Ssc *p_ssc, uint32_t ul_sources);
void ssc_disable_interrupt(Ssc *p_ssc, uint32_t ul_sources);
uint32_t ssc_get_interrupt_mask(Ssc *p_ssc);
uint32_t ssc_get_status(Ssc *p_ssc);
uint32_t ssc_is_tx_ready(Ssc *p_ssc);
uint32_t ssc_is_tx_empty(Ssc *p_ssc);
uint32_t ssc_is_rx_ready(Ssc *p_ssc);
uint32_t ssc_is_tx_enabled(Ssc *p_ssc);
uint32_t ssc_is_rx_enabled(Ssc *p_ssc);
#if (defined _SAM3S_) || (defined _SAM4S_)
uint32_t ssc_is_rx_buf_end(Ssc *p_ssc);
uint32_t ssc_is_tx_buf_end(Ssc *p_ssc);
uint32_t ssc_is_rx_buf_full(Ssc *p_ssc);
uint32_t ssc_is_tx_buf_empty(Ssc *p_ssc);
Pdc *ssc_get_pdc_base(Ssc *p_ssc);
#endif
uint32_t ssc_write(Ssc *p_ssc, uint32_t ul_frame);
uint32_t ssc_read(Ssc *p_ssc, uint32_t *ul_data);
void ssc_write_sync_data(Ssc *p_ssc, uint32_t ul_frame);
uint32_t ssc_read_sync_data(Ssc *p_ssc);
#if ((defined _SAM3XA_) || (defined _SAM3U_))
void *ssc_get_tx_access(Ssc *p_ssc);
void *ssc_get_rx_access(Ssc *p_ssc);
#endif
void ssc_set_writeprotect(Ssc *p_ssc, uint32_t ul_enable);
uint32_t ssc_get_writeprotect_status(Ssc *p_ssc);
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond
#endif /* SSC_H_INCLUDED */

View File

@@ -0,0 +1,86 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* \section Purpose
*
* Interface for configuring and using Timer Counter (TC) peripherals.
*
* \section Usage
* -# Optionally, use TC_FindMckDivisor() to let the program find the best
* TCCLKS field value automatically.
* -# Configure a Timer Counter in the desired mode using TC_Configure().
* -# Start or stop the timer clock using TC_Start() and TC_Stop().
*/
#ifndef _TC_
#define _TC_
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include "../chip.h"
#include <stdint.h>
/*------------------------------------------------------------------------------
* Global functions
*------------------------------------------------------------------------------*/
#ifdef __cplusplus
extern "C" {
#endif
extern void TC_Configure( Tc *pTc, uint32_t dwChannel, uint32_t dwMode ) ;
extern void TC_Start( Tc *pTc, uint32_t dwChannel ) ;
extern void TC_Stop( Tc *pTc, uint32_t dwChannel ) ;
extern uint32_t TC_FindMckDivisor( uint32_t dwFreq, uint32_t dwMCk, uint32_t *dwDiv, uint32_t *dwTcClks, uint32_t dwBoardMCK ) ;
extern uint32_t TC_ReadCV(Tc *p_tc, uint32_t ul_channel);
extern uint32_t TC_GetStatus(Tc *p_tc, uint32_t ul_channel);
extern void TC_SetRA(Tc *tc, uint32_t chan, uint32_t v) ;
extern void TC_SetRB(Tc *tc, uint32_t chan, uint32_t v) ;
extern void TC_SetRC(Tc *tc, uint32_t chan, uint32_t v) ;
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _TC_ */

View File

@@ -0,0 +1,78 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* \par Purpose
*
* Methods and definitions for Global time tick and wait functions.
*
* Defines a common and simpliest use of Time Tick, to increase tickCount
* every 1ms, the application can get this value through GetTickCount().
*
* \par Usage
*
* -# Configure the System Tick with TimeTick_Configure() when MCK changed
* \note
* Must be done before any invoke of GetTickCount(), Wait() or Sleep().
* -# Uses GetTickCount to get current tick value.
* -# Uses Wait to wait several ms.
* -# Uses Sleep to enter wait for interrupt mode to wait several ms.
*
*/
#ifndef _TIMETICK_
#define _TIMETICK_
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include <stdint.h>
/*----------------------------------------------------------------------------
* Definitions
*----------------------------------------------------------------------------*/
/*----------------------------------------------------------------------------
* Global functions
*----------------------------------------------------------------------------*/
extern uint32_t TimeTick_Configure( uint32_t dwNew_MCK ) ;
extern void TimeTick_Increment( void ) ;
extern uint32_t GetTickCount( void ) ;
extern void Wait( volatile uint32_t dwMs ) ;
extern void Sleep( volatile uint32_t dwMs ) ;
#endif /* _TIMETICK_ */

View File

@@ -0,0 +1,73 @@
/**
* \file
*
* \brief API for SAM TRNG.
*
* Copyright (c) 2011-2012 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* 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.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* 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.
*
* \asf_license_stop
*
*/
#ifndef TRNG_H_INCLUDED
#define TRNG_H_INCLUDED
#include "../chip.h"
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
void trng_enable(Trng *p_trng);
void trng_disable(Trng *p_trng);
void trng_enable_interrupt(Trng *p_trng);
void trng_disable_interrupt(Trng *p_trng);
uint32_t trng_get_interrupt_mask(Trng *p_trng);
uint32_t trng_get_interrupt_status(Trng *p_trng);
uint32_t trng_read_output_data(Trng *p_trng);
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond
#endif /* TRNG_H_INCLUDED */

View File

@@ -0,0 +1,111 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* Interface for configuration the Two Wire Interface (TWI) peripheral.
*
*/
#ifndef _TWI_
#define _TWI_
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include "../chip.h"
#include <stdint.h>
/*----------------------------------------------------------------------------
* Macros
*----------------------------------------------------------------------------*/
/* Returns 1 if the TXRDY bit (ready to transmit data) is set in the given status register value.*/
#define TWI_STATUS_TXRDY(status) (((status) & TWI_SR_TXRDY) == TWI_SR_TXRDY)
/* Returns 1 if the RXRDY bit (ready to receive data) is set in the given status register value.*/
#define TWI_STATUS_RXRDY(status) (((status) & TWI_SR_RXRDY) == TWI_SR_RXRDY)
/* Returns 1 if the TXCOMP bit (transfer complete) is set in the given status register value.*/
#define TWI_STATUS_TXCOMP(status) (((status) & TWI_SR_TXCOMP) == TWI_SR_TXCOMP)
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------
* External function
*----------------------------------------------------------------------------*/
extern void TWI_ConfigureMaster(Twi *pTwi, uint32_t twck, uint32_t mck);
extern void TWI_ConfigureSlave(Twi *pTwi, uint8_t slaveAddress);
extern void TWI_Stop(Twi *pTwi);
extern void TWI_StartRead(
Twi *pTwi,
uint8_t address,
uint32_t iaddress,
uint8_t isize);
extern uint8_t TWI_ReadByte(Twi *pTwi);
extern void TWI_WriteByte(Twi *pTwi, uint8_t byte);
extern void TWI_StartWrite(
Twi *pTwi,
uint8_t address,
uint32_t iaddress,
uint8_t isize,
uint8_t byte);
extern uint8_t TWI_ByteReceived(Twi *pTwi);
extern uint8_t TWI_ByteSent(Twi *pTwi);
extern uint8_t TWI_TransferComplete(Twi *pTwi);
extern void TWI_EnableIt(Twi *pTwi, uint32_t sources);
extern void TWI_DisableIt(Twi *pTwi, uint32_t sources);
extern uint32_t TWI_GetStatus(Twi *pTwi);
extern uint32_t TWI_GetMaskedStatus(Twi *pTwi);
extern void TWI_SendSTOPCondition(Twi *pTwi);
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _TWI_ */

View File

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

View File

@@ -0,0 +1,91 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef UDPHS_H_INCLUDED
#define UDPHS_H_INCLUDED
#define NUM_IT_MAX 3
#define EP_SINGLE_64 0x32 // EP0
#define EP_DOUBLE_64 0x36 // Other endpoints
// Endpoint 0:
#define EP_TYPE_CONTROL UDPHS_EPTCFG_EPT_SIZE_64 \
| UDPHS_EPTCFG_EPT_TYPE_CTRL8 \
| UDPHS_EPTCFG_BK_NUMBER_1
#ifdef CDC_ENABLED
#define EP_TYPE_BULK_IN UDPHS_EPTCFG_EPT_SIZE_512 \
| UDPHS_EPTCFG_EPT_DIR \
| UDPHS_EPTCFG_EPT_TYPE_BULK \
| UDPHS_EPTCFG_BK_NUMBER_2
#define EP_TYPE_BULK_OUT UDPHS_EPTCFG_EPT_SIZE_512 \
| UDPHS_EPTCFG_EPT_TYPE_BULK \
| UDPHS_EPTCFG_BK_NUMBER_2
#define EP_TYPE_INTERRUPT_IN UDPHS_EPTCFG_EPT_SIZE_64 \
| UDPHS_EPTCFG_EPT_DIR \
| UDPHS_EPTCFG_EPT_TYPE_INT \
| UDPHS_EPTCFG_BK_NUMBER_2
#endif
#ifdef HID_ENABLED
#define EP_TYPE_INTERRUPT_IN_HID UDPHS_EPTCFG_EPT_SIZE_64 \
| UDPHS_EPTCFG_EPT_DIR \
| UDPHS_EPTCFG_EPT_TYPE_INT \
| UDPHS_EPTCFG_BK_NUMBER_2
#endif
#define EP_TYPE_INTERRUPT_OUT UDPHS_EPTCFG_EPT_SIZE_64 \
| UDPHS_EPTCFG_EPT_TYPE_INT \
| UDPHS_EPTCFG_EPT_TYPE_INT \
| UDPHS_EPTCFG_BK_NUMBER_1
#define EP_TYPE_ISOCHRONOUS_IN UDPHS_EPTCFG_EPT_SIZE_1024 \
| UDPHS_EPTCFG_EPT_DIR \
| UDPHS_EPTCFG_EPT_TYPE_ISO \
| UDPHS_EPTCFG_BK_NUMBER_3
#define EP_TYPE_ISOCHRONOUS_OUT UDPHS_EPTCFG_EPT_SIZE_1024 \
| UDPHS_EPTCFG_EPT_TYPE_ISO \
| UDPHS_EPTCFG_BK_NUMBER_3
#ifndef TXLED1
#define TXLED0
#define RXLED0
#define TXLED1
#define RXLED1
#endif
#define UDFNUML ((UDPHS->UDPHS_FNUM & UDPHS_FNUM_FRAME_NUMBER_Msk)>>3)
#define USB_RECV_TIMEOUT
#define UDPHS_EPTFIFO (0x20180000) // (UDPHS_EPTFIFO) Base Address
#endif /* UDPHS_H_INCLUDED */

View File

@@ -0,0 +1,751 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef UOTGHS_DEVICE_H_INCLUDED
#define UOTGHS_DEVICE_H_INCLUDED
#define MAX_ENDPOINTS 10
#define EP0 0
#define EP0_SIZE 64
#define EPX_SIZE 512
#define EP_SINGLE_64 (0x32UL) // EP0
#define EP_DOUBLE_64 (0x36UL) // Other endpoints
// Control Endpoint
#define EP_TYPE_CONTROL (UOTGHS_DEVEPTCFG_EPSIZE_64_BYTE | \
UOTGHS_DEVEPTCFG_EPTYPE_CTRL | \
UOTGHS_DEVEPTCFG_EPBK_1_BANK | \
UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | \
UOTGHS_DEVEPTCFG_ALLOC)
// CDC Endpoints
#define EP_TYPE_BULK_IN (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | \
UOTGHS_DEVEPTCFG_EPDIR_IN | \
UOTGHS_DEVEPTCFG_EPTYPE_BLK | \
UOTGHS_DEVEPTCFG_EPBK_2_BANK | \
UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | \
UOTGHS_DEVEPTCFG_ALLOC)
#define EP_TYPE_BULK_OUT (UOTGHS_DEVEPTCFG_EPSIZE_512_BYTE | \
UOTGHS_DEVEPTCFG_EPTYPE_BLK | \
UOTGHS_DEVEPTCFG_EPBK_2_BANK | \
UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | \
UOTGHS_DEVEPTCFG_ALLOC)
#define EP_TYPE_INTERRUPT_IN (UOTGHS_DEVEPTCFG_EPSIZE_64_BYTE | \
UOTGHS_DEVEPTCFG_EPDIR_IN | \
UOTGHS_DEVEPTCFG_EPTYPE_INTRPT | \
UOTGHS_DEVEPTCFG_EPBK_2_BANK | \
UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | \
UOTGHS_DEVEPTCFG_ALLOC)
// HID Endpoints
#define EP_TYPE_INTERRUPT_IN_HID (UOTGHS_DEVEPTCFG_EPSIZE_64_BYTE | \
UOTGHS_DEVEPTCFG_EPDIR_IN | \
UOTGHS_DEVEPTCFG_EPTYPE_INTRPT | \
UOTGHS_DEVEPTCFG_EPBK_2_BANK | \
UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | \
UOTGHS_DEVEPTCFG_ALLOC)
// Various definitions
#define EP_TYPE_INTERRUPT_OUT (UOTGHS_DEVEPTCFG_EPSIZE_64_BYTE | \
UOTGHS_DEVEPTCFG_EPTYPE_INTRPT | \
UOTGHS_DEVEPTCFG_EPTYPE_INTRPT | \
UOTGHS_DEVEPTCFG_EPBK_1_BANK | \
UOTGHS_DEVEPTCFG_NBTRANS_1_TRANS | \
UOTGHS_DEVEPTCFG_ALLOC)
#define EP_TYPE_ISOCHRONOUS_IN (UOTGHS_DEVEPTCFG_EPSIZE_1024_BYTE | \
UOTGHS_DEVEPTCFG_EPDIR_IN | \
UOTGHS_DEVEPTCFG_EPTYPE_ISO | \
UOTGHS_DEVEPTCFG_EPBK_3_BANK | \
UOTGHS_DEVEPTCFG_NBTRANS_3_TRANS | \
UOTGHS_DEVEPTCFG_ALLOC)
#define EP_TYPE_ISOCHRONOUS_OUT (UOTGHS_DEVEPTCFG_EPSIZE_1024_BYTE | \
UOTGHS_DEVEPTCFG_EPTYPE_ISO | \
UOTGHS_DEVEPTCFG_EPBK_3_BANK | \
UOTGHS_DEVEPTCFG_NBTRANS_3_TRANS | \
UOTGHS_DEVEPTCFG_ALLOC)
//! \ingroup usb_device_group
//! \defgroup udd_group USB Device Driver (UDD)
//! UOTGHS low-level driver for USB device mode
//!
//! @{
#ifndef UOTGHS_DEVEPTCFG_EPDIR_Pos
// Bit pos is not defined in SAM header file but we need it.
# define UOTGHS_DEVEPTCFG_EPDIR_Pos 8
#endif
//! @name UOTGHS Device IP properties
//! These macros give access to IP properties
//! @{
//! Get maximal number of endpoints
#define udd_get_endpoint_max_nbr() (9)
#define UDD_MAX_PEP_NB (udd_get_endpoint_max_nbr() + 1)
//! Get maximal number of banks of endpoints
#define udd_get_endpoint_bank_max_nbr(ep) ((ep == 0) ? 1 : (( ep <= 2) ? 3 : 2))
//! Get maximal size of endpoint (3X, 1024/64)
#define udd_get_endpoint_size_max(ep) (((ep) == 0) ? 64 : 512) // for bulk
//! Get DMA support of endpoints
#define Is_udd_endpoint_dma_supported(ep) ((((ep) >= 1) && ((ep) <= 6)) ? true : false)
//! Get High Band Width support of endpoints
#define Is_udd_endpoint_high_bw_supported(ep) (((ep) >= 2) ? true : false)
//! @}
//! @name UOTGHS Device speeds management
//! @{
//! Enable/disable device low-speed mode
#define udd_low_speed_enable() (Set_bits(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_LS))
#define udd_low_speed_disable() (Clr_bits(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_LS))
//! Test if device low-speed mode is forced
#define Is_udd_low_speed_enable() (Tst_bits(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_LS))
//! Enable high speed mode
#define udd_high_speed_enable() (Wr_bitfield(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_SPDCONF_Msk, 0))
//! Disable high speed mode
#define udd_high_speed_disable() (Wr_bitfield(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_SPDCONF_Msk, 3))
//! Test if controller is in full speed mode
#define Is_udd_full_speed_mode() (Rd_bitfield(UOTGHS->UOTGHS_SR, UOTGHS_SR_SPEED_Msk) == UOTGHS_SR_SPEED_FULL_SPEED)
//! @}
//! @name UOTGHS Device HS test mode management
//! @{
#ifdef UOTGHS_DEVCTRL_SPDCONF_HIGH_SPEED
//! Enable high speed test mode
# define udd_enable_hs_test_mode() (Wr_bitfield(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_SPDCONF_Msk, 2))
# define udd_enable_hs_test_mode_j() (Set_bits(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_TSTJ))
# define udd_enable_hs_test_mode_k() (Set_bits(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_TSTK))
# define udd_enable_hs_test_mode_packet() (Set_bits(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_TSTPCKT))
#endif
//! @}
//! @name UOTGHS Device vbus management
//! @{
#define udd_enable_vbus_interrupt() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSTE))
#define udd_disable_vbus_interrupt() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSTE))
#define Is_udd_vbus_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSTE))
#define Is_udd_vbus_high() (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_VBUS))
#define Is_udd_vbus_low() (!Is_udd_vbus_high())
#define udd_ack_vbus_transition() (UOTGHS->UOTGHS_SCR = UOTGHS_SCR_VBUSTIC)
#define udd_raise_vbus_transition() (UOTGHS->UOTGHS_SFR = UOTGHS_SFR_VBUSTIS)
#define Is_udd_vbus_transition() (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_VBUSTI))
//! @}
//! @name UOTGHS device attach control
//! These macros manage the UOTGHS Device attach.
//! @{
//! Detaches from USB bus
#define udd_detach_device() (Set_bits(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_DETACH))
//! Attaches to USB bus
#define udd_attach_device() (Clr_bits(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_DETACH))
//! Test if the device is detached
#define Is_udd_detached() (Tst_bits(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_DETACH))
//! @}
//! @name UOTGHS device bus events control
//! These macros manage the UOTGHS Device bus events.
//! @{
//! Initiates a remote wake-up event
//! @{
#define udd_initiate_remote_wake_up() (Set_bits(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_RMWKUP))
#define Is_udd_pending_remote_wake_up() (Tst_bits(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_RMWKUP))
//! @}
//! Manage upstream resume event (=remote wakeup)
//! The USB driver sends a resume signal called "Upstream Resume"
//! @{
#define udd_enable_remote_wake_up_interrupt() (UOTGHS->UOTGHS_DEVIER = UOTGHS_DEVIER_UPRSMES)
#define udd_disable_remote_wake_up_interrupt() (UOTGHS->UOTGHS_DEVIDR = UOTGHS_DEVIDR_UPRSMEC)
#define Is_udd_remote_wake_up_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_DEVIMR, UOTGHS_DEVIMR_UPRSME))
#define udd_ack_remote_wake_up_start() (UOTGHS->UOTGHS_DEVICR = UOTGHS_DEVICR_UPRSMC)
#define udd_raise_remote_wake_up_start() (UOTGHS->UOTGHS_DEVIFR = UOTGHS_DEVIFR_UPRSMS)
#define Is_udd_remote_wake_up_start() (Tst_bits(UOTGHS->UOTGHS_DEVISR, UOTGHS_DEVISR_UPRSM))
//! @}
//! Manage downstream resume event (=remote wakeup from host)
//! The USB controller detects a valid "End of Resume" signal initiated by the host
//! @{
#define udd_enable_resume_interrupt() (UOTGHS->UOTGHS_DEVIER = UOTGHS_DEVIER_EORSMES)
#define udd_disable_resume_interrupt() (UOTGHS->UOTGHS_DEVIDR = UOTGHS_DEVIDR_EORSMEC)
#define Is_udd_resume_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_DEVIMR, UOTGHS_DEVIMR_EORSME))
#define udd_ack_resume() (UOTGHS->UOTGHS_DEVICR = UOTGHS_DEVICR_EORSMC)
#define udd_raise_resume() (UOTGHS->UOTGHS_DEVIFR = UOTGHS_DEVIFR_EORSMS)
#define Is_udd_resume() (Tst_bits(UOTGHS->UOTGHS_DEVISR, UOTGHS_DEVISR_EORSM))
//! @}
//! Manage wake-up event (=usb line activity)
//! The USB controller is reactivated by a filtered non-idle signal from the lines
//! @{
#define udd_enable_wake_up_interrupt() (UOTGHS->UOTGHS_DEVIER = UOTGHS_DEVIER_WAKEUPES)
#define udd_disable_wake_up_interrupt() (UOTGHS->UOTGHS_DEVIDR = UOTGHS_DEVIDR_WAKEUPEC)
#define Is_udd_wake_up_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_DEVIMR, UOTGHS_DEVIMR_WAKEUPE))
#define udd_ack_wake_up() (UOTGHS->UOTGHS_DEVICR = UOTGHS_DEVICR_WAKEUPC)
#define udd_raise_wake_up() (UOTGHS->UOTGHS_DEVIFR = UOTGHS_DEVIFR_WAKEUPS)
#define Is_udd_wake_up() (Tst_bits(UOTGHS->UOTGHS_DEVISR, UOTGHS_DEVISR_WAKEUP))
//! @}
//! Manage reset event
//! Set when a USB "End of Reset" has been detected
//! @{
#define udd_enable_reset_interrupt() (UOTGHS->UOTGHS_DEVIER = UOTGHS_DEVIER_EORSTES)
#define udd_disable_reset_interrupt() (UOTGHS->UOTGHS_DEVIDR = UOTGHS_DEVIDR_EORSTEC)
#define Is_udd_reset_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_DEVIMR, UOTGHS_DEVIMR_EORSTE))
#define udd_ack_reset() (UOTGHS->UOTGHS_DEVICR = UOTGHS_DEVICR_EORSTC)
#define udd_raise_reset() (UOTGHS->UOTGHS_DEVIFR = UOTGHS_DEVIFR_EORSTS)
#define Is_udd_reset() (Tst_bits(UOTGHS->UOTGHS_DEVISR, UOTGHS_DEVISR_EORST))
//! @}
//! Manage start of frame event
//! @{
#define udd_enable_sof_interrupt() (UOTGHS->UOTGHS_DEVIER = UOTGHS_DEVIER_SOFES)
#define udd_disable_sof_interrupt() (UOTGHS->UOTGHS_DEVIDR = UOTGHS_DEVIDR_SOFEC)
#define Is_udd_sof_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_DEVIMR, UOTGHS_DEVIMR_SOFE))
#define udd_ack_sof() (UOTGHS->UOTGHS_DEVICR = UOTGHS_DEVICR_SOFC)
#define udd_raise_sof() (UOTGHS->UOTGHS_DEVIFR = UOTGHS_DEVIFR_SOFS)
#define Is_udd_sof() (Tst_bits(UOTGHS->UOTGHS_DEVISR, UOTGHS_DEVISR_SOF))
#define udd_frame_number() (Rd_bitfield(UOTGHS->UOTGHS_DEVFNUM, UOTGHS_DEVFNUM_FNUM_Msk))
#define Is_udd_frame_number_crc_error() (Tst_bits(UOTGHS->UOTGHS_DEVFNUM, UOTGHS_DEVFNUM_FNCERR))
//! @}
//! Manage Micro start of frame event (High Speed Only)
//! @{
#define udd_enable_msof_interrupt() (UOTGHS->UOTGHS_DEVIER = UOTGHS_DEVIER_MSOFES)
#define udd_disable_msof_interrupt() (UOTGHS->UOTGHS_DEVIDR = UOTGHS_DEVIDR_MSOFEC)
#define Is_udd_msof_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_DEVIMR, UOTGHS_DEVIMR_MSOFE))
#define udd_ack_msof() (UOTGHS->UOTGHS_DEVICR = UOTGHS_DEVIMR_MSOFE)
#define udd_raise_msof() (UOTGHS->UOTGHS_DEVIFR = UOTGHS_DEVIFR_MSOFS)
#define Is_udd_msof() (Tst_bits(UOTGHS->UOTGHS_DEVISR, UOTGHS_DEVISR_MSOF))
#define udd_micro_frame_number() \
(Rd_bitfield(UOTGHS->UOTGHS_DEVFNUM, (UOTGHS_DEVFNUM_FNUM_Msk|UOTGHS_DEVFNUM_MFNUM_Msk)))
//! @}
//! Manage suspend event
//! @{
#define udd_enable_suspend_interrupt() (UOTGHS->UOTGHS_DEVIER = UOTGHS_DEVIER_SUSPES)
#define udd_disable_suspend_interrupt() (UOTGHS->UOTGHS_DEVIDR = UOTGHS_DEVIDR_SUSPEC)
#define Is_udd_suspend_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_DEVIMR, UOTGHS_DEVIMR_SUSPE))
#define udd_ack_suspend() (UOTGHS->UOTGHS_DEVICR = UOTGHS_DEVICR_SUSPC)
#define udd_raise_suspend() (UOTGHS->UOTGHS_DEVIFR = UOTGHS_DEVIFR_SUSPS)
#define Is_udd_suspend() (Tst_bits(UOTGHS->UOTGHS_DEVISR, UOTGHS_DEVISR_SUSP))
//! @}
//! @}
//! @name UOTGHS device address control
//! These macros manage the UOTGHS Device address.
//! @{
//! enables USB device address
#define udd_enable_address() (Set_bits(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_ADDEN))
//! disables USB device address
#define udd_disable_address() (Clr_bits(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_ADDEN))
#define Is_udd_address_enabled() (Tst_bits(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_ADDEN))
//! configures the USB device address
#define udd_configure_address(addr) (Wr_bitfield(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_UADD_Msk, addr))
//! gets the currently configured USB device address
#define udd_get_configured_address() (Rd_bitfield(UOTGHS->UOTGHS_DEVCTRL, UOTGHS_DEVCTRL_UADD_Msk))
//! @}
//! @name UOTGHS Device endpoint drivers
//! These macros manage the common features of the endpoints.
//! @{
//! Generic macro for UOTGHS registers that can be arrayed
//! @{
#define UOTGHS_ARRAY(reg,index) ((&(UOTGHS->reg))[(index)])
//! @}
//! @name UOTGHS Device endpoint configuration
//! @{
//! enables the selected endpoint
#define udd_enable_endpoint(ep) (Set_bits(UOTGHS->UOTGHS_DEVEPT, UOTGHS_DEVEPT_EPEN0 << (ep)))
//! disables the selected endpoint
#define udd_disable_endpoint(ep) (Clr_bits(UOTGHS->UOTGHS_DEVEPT, UOTGHS_DEVEPT_EPEN0 << (ep)))
//! tests if the selected endpoint is enabled
#define Is_udd_endpoint_enabled(ep) (Tst_bits(UOTGHS->UOTGHS_DEVEPT, UOTGHS_DEVEPT_EPEN0 << (ep)))
//! resets the selected endpoint
#define udd_reset_endpoint(ep) \
do { \
Set_bits(UOTGHS->UOTGHS_DEVEPT, UOTGHS_DEVEPT_EPRST0 << (ep)); \
Clr_bits(UOTGHS->UOTGHS_DEVEPT, UOTGHS_DEVEPT_EPRST0 << (ep)); \
} while (0)
//! Tests if the selected endpoint is being reset
#define Is_udd_resetting_endpoint(ep) (Tst_bits(UOTGHS->UOTGHS_DEVEPT, UOTGHS_DEVEPT_EPRST0 << (ep)))
//! Configures the selected endpoint type
#define udd_configure_endpoint_type(ep, type) (Wr_bitfield(UOTGHS_ARRAY(UOTGHS_DEVEPTCFG[0], ep), UOTGHS_DEVEPTCFG_EPTYPE_Msk, type))
//! Gets the configured selected endpoint type
#define udd_get_endpoint_type(ep) (Rd_bitfield(UOTGHS_ARRAY(UOTGHS_DEVEPTCFG[0], ep), UOTGHS_DEVEPTCFG_EPTYPE_Msk))
//! Enables the bank autoswitch for the selected endpoint
#define udd_enable_endpoint_bank_autoswitch(ep) (Set_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTCFG[0], ep), UOTGHS_DEVEPTCFG_AUTOSW))
//! Disables the bank autoswitch for the selected endpoint
#define udd_disable_endpoint_bank_autoswitch(ep) (Clr_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTCFG[0], ep), UOTGHS_DEVEPTCFG_AUTOSW))
#define Is_udd_endpoint_bank_autoswitch_enabled(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTCFG[0], ep), UOTGHS_DEVEPTCFG_AUTOSW))
//! Configures the selected endpoint direction
#define udd_configure_endpoint_direction(ep, dir) (Wr_bitfield(UOTGHS_ARRAY(UOTGHS_DEVEPTCFG[0], ep), UOTGHS_DEVEPTCFG_EPDIR, dir))
//! Gets the configured selected endpoint direction
#define udd_get_endpoint_direction(ep) (Rd_bitfield(UOTGHS_ARRAY(UOTGHS_DEVEPTCFG[0], ep), UOTGHS_DEVEPTCFG_EPDIR))
#define Is_udd_endpoint_in(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTCFG[0], ep), UOTGHS_DEVEPTCFG_EPDIR))
//! Bounds given integer size to allowed range and rounds it up to the nearest
//! available greater size, then applies register format of UOTGHS controller
//! for endpoint size bit-field.
#define udd_format_endpoint_size(size) (32 - clz(((uint32_t)min(max(size, 8), 1024) << 1) - 1) - 1 - 3)
//! Configures the selected endpoint size
#define udd_configure_endpoint_size(ep, size) (Wr_bitfield(UOTGHS_ARRAY(UOTGHS_DEVEPTCFG[0], ep), UOTGHS_DEVEPTCFG_EPSIZE_Msk, udd_format_endpoint_size(size)))
//! Gets the configured selected endpoint size
#define udd_get_endpoint_size(ep) (8 << Rd_bitfield(UOTGHS_ARRAY(UOTGHS_DEVEPTCFG[0], ep), UOTGHS_DEVEPTCFG_EPSIZE_Msk))
//! Configures the selected endpoint number of banks
#define udd_configure_endpoint_bank(ep, bank) (Wr_bitfield(UOTGHS_ARRAY(UOTGHS_DEVEPTCFG[0], ep), UOTGHS_DEVEPTCFG_EPBK_Msk, bank))
//! Gets the configured selected endpoint number of banks
#define udd_get_endpoint_bank(ep) (Rd_bitfield(UOTGHS_ARRAY(UOTGHS_DEVEPTCFG[0], ep), UOTGHS_DEVEPTCFG_EPBK_Msk)+1)
//! Allocates the configuration selected endpoint in DPRAM memory
#define udd_allocate_memory(ep) (Set_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTCFG[0], ep), UOTGHS_DEVEPTCFG_ALLOC))
//! un-allocates the configuration selected endpoint in DPRAM memory
#define udd_unallocate_memory(ep) (Clr_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTCFG[0], ep), UOTGHS_DEVEPTCFG_ALLOC))
#define Is_udd_memory_allocated(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTCFG[0], ep), UOTGHS_DEVEPTCFG_ALLOC))
//! Configures selected endpoint in one step
#define udd_configure_endpoint(ep, type, dir, size, bank) (\
Wr_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTCFG[0], ep), UOTGHS_DEVEPTCFG_EPTYPE_Msk |\
UOTGHS_DEVEPTCFG_EPDIR |\
UOTGHS_DEVEPTCFG_EPSIZE_Msk |\
UOTGHS_DEVEPTCFG_EPBK_Msk , \
(((uint32_t)(type) << UOTGHS_DEVEPTCFG_EPTYPE_Pos) & UOTGHS_DEVEPTCFG_EPTYPE_Msk) |\
(((uint32_t)(dir ) << UOTGHS_DEVEPTCFG_EPDIR_Pos ) & UOTGHS_DEVEPTCFG_EPDIR) |\
( (uint32_t)udd_format_endpoint_size(size) << UOTGHS_DEVEPTCFG_EPSIZE_Pos) |\
(((uint32_t)(bank) << UOTGHS_DEVEPTCFG_EPBK_Pos) & UOTGHS_DEVEPTCFG_EPBK_Msk))\
)
//! Tests if current endpoint is configured
#define Is_udd_endpoint_configured(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_CFGOK))
//! Returns the control direction
#define udd_control_direction() (Rd_bitfield(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], EP_CONTROL), UOTGHS_DEVEPTISR_CTRLDIR))
//! Resets the data toggle sequence
#define udd_reset_data_toggle(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIER[0], ep) = UOTGHS_DEVEPTIER_RSTDTS)
//! Tests if the data toggle sequence is being reset
#define Is_udd_data_toggle_reset(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTIMR[0], ep), UOTGHS_DEVEPTIMR_RSTDT))
//! Returns data toggle
#define udd_data_toggle(ep) (Rd_bitfield(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_DTSEQ_Msk))
//! @}
//! @name UOTGHS Device control endpoint
//! These macros control the endpoints.
//! @{
//! @name UOTGHS Device control endpoint interrupts
//! These macros control the endpoints interrupts.
//! @{
//! Enables the selected endpoint interrupt
#define udd_enable_endpoint_interrupt(ep) (UOTGHS->UOTGHS_DEVIER = UOTGHS_DEVIER_PEP_0 << (ep))
//! Disables the selected endpoint interrupt
#define udd_disable_endpoint_interrupt(ep) (UOTGHS->UOTGHS_DEVIDR = UOTGHS_DEVIDR_PEP_0 << (ep))
//! Tests if the selected endpoint interrupt is enabled
#define Is_udd_endpoint_interrupt_enabled(ep) (Tst_bits(UOTGHS->UOTGHS_DEVIMR, UOTGHS_DEVIMR_PEP_0 << (ep)))
//! Tests if an interrupt is triggered by the selected endpoint
#define Is_udd_endpoint_interrupt(ep) (Tst_bits(UOTGHS->UOTGHS_DEVISR, UOTGHS_DEVISR_PEP_0 << (ep)))
//! Returns the lowest endpoint number generating an endpoint interrupt or MAX_PEP_NB if none
#define udd_get_interrupt_endpoint_number() (ctz(((UOTGHS->UOTGHS_DEVISR >> UOTGHS_DEVISR_PEP_Pos) & \
(UOTGHS->UOTGHS_DEVIMR >> UOTGHS_DEVIMR_PEP_Pos)) | \
(1 << MAX_PEP_NB)))
#define UOTGHS_DEVISR_PEP_Pos 12
#define UOTGHS_DEVIMR_PEP_Pos 12
//! @}
//! @name UOTGHS Device control endpoint errors
//! These macros control the endpoint errors.
//! @{
//! Enables the STALL handshake
#define udd_enable_stall_handshake(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIER[0], ep) = UOTGHS_DEVEPTIER_STALLRQS)
//! Disables the STALL handshake
#define udd_disable_stall_handshake(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIDR[0], ep) = UOTGHS_DEVEPTIDR_STALLRQC)
//! Tests if STALL handshake request is running
#define Is_udd_endpoint_stall_requested(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTIMR[0], ep), UOTGHS_DEVEPTIMR_STALLRQ))
//! Tests if STALL sent
#define Is_udd_stall(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_STALLEDI))
//! ACKs STALL sent
#define udd_ack_stall(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTICR[0], ep) = UOTGHS_DEVEPTICR_STALLEDIC)
//! Raises STALL sent
#define udd_raise_stall(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIFR[0], ep) = UOTGHS_DEVEPTIFR_STALLEDIS)
//! Enables STALL sent interrupt
#define udd_enable_stall_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIER[0], ep) = UOTGHS_DEVEPTIER_STALLEDES)
//! Disables STALL sent interrupt
#define udd_disable_stall_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIDR[0], ep) = UOTGHS_DEVEPTIDR_STALLEDEC)
//! Tests if STALL sent interrupt is enabled
#define Is_udd_stall_interrupt_enabled(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTIMR[0], ep), UOTGHS_DEVEPTIMR_STALLEDE))
//! Tests if NAK OUT received
#define Is_udd_nak_out(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_NAKOUTI))
//! ACKs NAK OUT received
#define udd_ack_nak_out(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTICR[0], ep) = UOTGHS_DEVEPTICR_NAKOUTIC)
//! Raises NAK OUT received
#define udd_raise_nak_out(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIFR[0], ep) = UOTGHS_DEVEPTIFR_NAKOUTIS)
//! Enables NAK OUT interrupt
#define udd_enable_nak_out_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIER[0], ep) = UOTGHS_DEVEPTIER_NAKOUTES)
//! Disables NAK OUT interrupt
#define udd_disable_nak_out_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIDR[0], ep) = UOTGHS_DEVEPTIDR_NAKOUTEC)
//! Tests if NAK OUT interrupt is enabled
#define Is_udd_nak_out_interrupt_enabled(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTIMR[0], ep), UOTGHS_DEVEPTIMR_NAKOUTE))
//! Tests if NAK IN received
#define Is_udd_nak_in(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_NAKINI))
//! ACKs NAK IN received
#define udd_ack_nak_in(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTICR[0], ep) = UOTGHS_DEVEPTICR_NAKINIC)
//! Raises NAK IN received
#define udd_raise_nak_in(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIFR[0], ep) = UOTGHS_DEVEPTIFR_NAKINIS)
//! Enables NAK IN interrupt
#define udd_enable_nak_in_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIER[0], ep) = UOTGHS_DEVEPTIER_NAKINES)
//! Disables NAK IN interrupt
#define udd_disable_nak_in_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIDR[0], ep) = UOTGHS_DEVEPTIDR_NAKINEC)
//! Tests if NAK IN interrupt is enabled
#define Is_udd_nak_in_interrupt_enabled(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTIMR[0], ep), UOTGHS_DEVEPTIMR_NAKINE))
//! ACKs endpoint isochronous overflow interrupt
#define udd_ack_overflow_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTICR[0], ep) = UOTGHS_DEVEPTICR_OVERFIC)
//! Raises endpoint isochronous overflow interrupt
#define udd_raise_overflow_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIFR[0], ep) = UOTGHS_DEVEPTIFR_OVERFIS)
//! Tests if an overflow occurs
#define Is_udd_overflow(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_OVERFI))
//! Enables overflow interrupt
#define udd_enable_overflow_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIER[0], ep) = UOTGHS_DEVEPTIER_OVERFES)
//! Disables overflow interrupt
#define udd_disable_overflow_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIDR[0], ep) = UOTGHS_DEVEPTIDR_OVERFEC)
//! Tests if overflow interrupt is enabled
#define Is_udd_overflow_interrupt_enabled(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTIMR[0], ep), UOTGHS_DEVEPTIMR_OVERFE))
//! ACKs endpoint isochronous underflow interrupt
#define udd_ack_underflow_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTICR[0], ep) = UOTGHS_DEVEPTICR_UNDERFIC)
//! Raises endpoint isochronous underflow interrupt
#define udd_raise_underflow_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIFR[0], ep) = UOTGHS_DEVEPTIFR_UNDERFIS)
//! Tests if an underflow occurs
#define Is_udd_underflow(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_UNDERFI))
//! Enables underflow interrupt
#define udd_enable_underflow_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIER[0], ep) = UOTGHS_DEVEPTIER_UNDERFES)
//! Disables underflow interrupt
#define udd_disable_underflow_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIDR[0], ep) = UOTGHS_DEVEPTIDR_UNDERFEC)
//! Tests if underflow interrupt is enabled
#define Is_udd_underflow_interrupt_enabled(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTIMR[0], ep), UOTGHS_DEVEPTIMR_UNDERFE))
//! Tests if CRC ERROR ISO OUT detected
#define Is_udd_crc_error(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_CRCERRI))
//! ACKs CRC ERROR ISO OUT detected
#define udd_ack_crc_error(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTICR[0], ep) = UOTGHS_DEVEPTICR_CRCERRIC)
//! Raises CRC ERROR ISO OUT detected
#define udd_raise_crc_error(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIFR[0], ep) = UOTGHS_DEVEPTIFR_CRCERRIS)
//! Enables CRC ERROR ISO OUT detected interrupt
#define udd_enable_crc_error_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIER[0], ep) = UOTGHS_DEVEPTIER_CRCERRES)
//! Disables CRC ERROR ISO OUT detected interrupt
#define udd_disable_crc_error_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIDR[0], ep) = UOTGHS_DEVEPTIDR_CRCERREC)
//! Tests if CRC ERROR ISO OUT detected interrupt is enabled
#define Is_udd_crc_error_interrupt_enabled(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTIMR[0], ep), UOTGHS_DEVEPTIMR_CRCERRE))
//! @}
//! @name UOTGHS Device control endpoint transfer
//! These macros control the endpoint transfer.
//! @{
//! Tests if endpoint read allowed
#define Is_udd_read_enabled(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_RWALL))
//! Tests if endpoint write allowed
#define Is_udd_write_enabled(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_RWALL))
//! Returns the byte count
#define udd_byte_count(ep) (Rd_bitfield(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_BYCT_Msk))
//! Clears FIFOCON bit
#define udd_ack_fifocon(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIDR[0], ep) = UOTGHS_DEVEPTIDR_FIFOCONC)
//! Tests if FIFOCON bit set
#define Is_udd_fifocon(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTIMR[0], ep), UOTGHS_DEVEPTIMR_FIFOCON))
//! Returns the number of busy banks
#define udd_nb_busy_bank(ep) (Rd_bitfield(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_NBUSYBK_Msk))
//! Returns the number of the current bank
#define udd_current_bank(ep) (Rd_bitfield(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_CURRBK_Msk))
//! Kills last bank
#define udd_kill_last_in_bank(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIER[0], ep) = UOTGHS_DEVEPTIER_KILLBKS)
#define Is_udd_kill_last(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTIMR[0], ep), UOTGHS_DEVEPTIMR_KILLBK))
//! Tests if last bank killed
#define Is_udd_last_in_bank_killed(ep) (!Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTIMR[0], ep), UOTGHS_DEVEPTIMR_KILLBK))
//! Forces all banks full (OUT) or free (IN) interrupt
#define udd_force_bank_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIFR[0], ep) = UOTGHS_DEVEPTIFR_NBUSYBKS)
//! Unforces all banks full (OUT) or free (IN) interrupt
#define udd_unforce_bank_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIFR[0], ep) = UOTGHS_DEVEPTIFR_NBUSYBKS)
//! Enables all banks full (OUT) or free (IN) interrupt
#define udd_enable_bank_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIER[0], ep) = UOTGHS_DEVEPTIER_NBUSYBKES)
//! Disables all banks full (OUT) or free (IN) interrupt
#define udd_disable_bank_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIDR[0], ep) = UOTGHS_DEVEPTIDR_NBUSYBKEC)
//! Tests if all banks full (OUT) or free (IN) interrupt enabled
#define Is_udd_bank_interrupt_enabled(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTIMR[0], ep), UOTGHS_DEVEPTIMR_NBUSYBKE))
//! Tests if SHORT PACKET received
#define Is_udd_short_packet(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_SHORTPACKET))
//! ACKs SHORT PACKET received
#define udd_ack_short_packet(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTICR[0], ep) = UOTGHS_DEVEPTICR_SHORTPACKETC)
//! Raises SHORT PACKET received
#define udd_raise_short_packet(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIFR[0], ep) = UOTGHS_DEVEPTIFR_SHORTPACKETS)
//! Enables SHORT PACKET received interrupt
#define udd_enable_short_packet_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIER[0], ep) = UOTGHS_DEVEPTIER_SHORTPACKETES)
//! Disables SHORT PACKET received interrupt
#define udd_disable_short_packet_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIDR[0], ep) = UOTGHS_DEVEPTIDR_SHORTPACKETEC)
//! Tests if SHORT PACKET received interrupt is enabled
#define Is_udd_short_packet_interrupt_enabled(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTIMR[0], ep), UOTGHS_DEVEPTIMR_SHORTPACKETE))
//! Tests if SETUP received
#define Is_udd_setup_received(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_RXSTPI))
//! ACKs SETUP received
#define udd_ack_setup_received(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTICR[0], ep) = UOTGHS_DEVEPTICR_RXSTPIC)
//! Raises SETUP received
#define udd_raise_setup_received(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIFR[0], ep) = UOTGHS_DEVEPTIFR_RXSTPIS)
//! Enables SETUP received interrupt
#define udd_enable_setup_received_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIER[0], ep) = UOTGHS_DEVEPTIER_RXSTPES)
//! Disables SETUP received interrupt
#define udd_disable_setup_received_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIDR[0], ep) = UOTGHS_DEVEPTIDR_RXSTPEC)
//! Tests if SETUP received interrupt is enabled
#define Is_udd_setup_received_interrupt_enabled(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTIMR[0], ep), UOTGHS_DEVEPTIMR_RXSTPE))
//! Tests if OUT received
#define Is_udd_out_received(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_RXOUTI))
//! ACKs OUT received
#define udd_ack_out_received(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTICR[0], ep) = UOTGHS_DEVEPTICR_RXOUTIC)
//! Raises OUT received
#define udd_raise_out_received(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIFR[0], ep) = UOTGHS_DEVEPTIFR_RXOUTIS)
//! Enables OUT received interrupt
#define udd_enable_out_received_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIER[0], ep) = UOTGHS_DEVEPTIER_RXOUTES)
//! Disables OUT received interrupt
#define udd_disable_out_received_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIDR[0], ep) = UOTGHS_DEVEPTIDR_RXOUTEC)
//! Tests if OUT received interrupt is enabled
#define Is_udd_out_received_interrupt_enabled(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTIMR[0], ep), UOTGHS_DEVEPTIMR_RXOUTE))
//! Tests if IN sending
#define Is_udd_in_send(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTISR[0], ep), UOTGHS_DEVEPTISR_TXINI))
//! ACKs IN sending
#define udd_ack_in_send(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTICR[0], ep) = UOTGHS_DEVEPTICR_TXINIC)
//! Raises IN sending
#define udd_raise_in_send(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIFR[0], ep) = UOTGHS_DEVEPTIFR_TXINIS)
//! Enables IN sending interrupt
#define udd_enable_in_send_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIER[0], ep) = UOTGHS_DEVEPTIER_TXINES)
//! Disables IN sending interrupt
#define udd_disable_in_send_interrupt(ep) (UOTGHS_ARRAY(UOTGHS_DEVEPTIDR[0], ep) = UOTGHS_DEVEPTIDR_TXINEC)
//! Tests if IN sending interrupt is enabled
#define Is_udd_in_send_interrupt_enabled(ep) (Tst_bits(UOTGHS_ARRAY(UOTGHS_DEVEPTIMR[0], ep), UOTGHS_DEVEPTIMR_TXINE))
//! 8-bit access to FIFO data register of selected endpoint.
//! @param ep Endpoint of which to access FIFO data register
//! @return Volatile 8-bit data pointer to FIFO data register
//! @warning It is up to the user of this macro to make sure that all accesses
//! are aligned with their natural boundaries
//! @warning It is up to the user of this macro to make sure that used HSB
//! addresses are identical to the DPRAM internal pointer modulo 32 bits.
#define udd_get_endpoint_fifo_access8(ep) \
(((volatile uint8_t (*)[0x8000])UOTGHS_RAM_ADDR)[(ep)])
//! @}
/*********************************************************************************************************************/
//! @name UOTGHS IP properties
//! These macros give access to IP properties (not defined in 3X)
//! @{
//! Get IP name part 1 or 2
#define otg_get_ip_name()
#define otg_data_memory_barrier()
//! Get IP version
#define otg_get_ip_version()
//! Get DPRAM size (FIFO maximal size) in bytes
#define otg_get_dpram_size()
//! Get size of USBB PB address space
#define otg_get_ip_paddress_size()
//! @}
//! @name UOTGHS OTG ID pin management
//! The ID pin come from the USB OTG connector (A and B receptable) and
//! allows to select the USB mode host or device.
//! The USBB hardware can manage it automaticaly. This feature is optional.
//! When otg_ID_PIN equals true in conf_usb_host.h, the USB_ID must be defined in board.h.
//!
//! @{
//! PIO, PIO ID and MASK for USB_ID according to configuration from OTG_ID
#define OTG_ID_PIN USB_ID_GPIO
#define OTG_ID_FUNCTION USB_ID_FLAGS
//! Input USB_ID from its pin
#define otg_input_id_pin() do { \
pio_configure_pin(OTG_ID_PIN, OTG_ID_FUNCTION); \
} while (0)
//! Enable external OTG_ID pin (listened to by USB)
#define otg_enable_id_pin() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_UIDE))
//! Disable external OTG_ID pin (ignored by USB)
#define otg_disable_id_pin() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_UIDE))
//! Test if external OTG_ID pin enabled (listened to by USB)
#define Is_otg_id_pin_enabled() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_UIDE))
//! Disable external OTG_ID pin and force device mode
#define otg_force_device_mode() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_UIMOD), otg_disable_id_pin())
//! Test if device mode is forced
#define Is_otg_device_mode_forced() (!Is_otg_id_pin_enabled() && Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_UIMOD))
//! Disable external OTG_ID pin and force host mode
#define otg_force_host_mode() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_UIMOD), otg_disable_id_pin())
//! Test if host mode is forced
#define Is_otg_host_mode_forced() (!Is_otg_id_pin_enabled() && !Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_UIMOD))
//! @name UOTGHS OTG ID pin interrupt management
//! These macros manage the ID pin interrupt
//! @{
#define otg_enable_id_interrupt() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_IDTE))
#define otg_disable_id_interrupt() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_IDTE))
#define Is_otg_id_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_IDTE))
#define Is_otg_id_device() (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_ID))
#define Is_otg_id_host() (!Is_otg_id_device())
#define otg_ack_id_transition() (UOTGHS->UOTGHS_SCR = UOTGHS_SCR_IDTIC)
#define otg_raise_id_transition() (UOTGHS->UOTGHS_SFR = UOTGHS_SFR_IDTIS)
#define Is_otg_id_transition() (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_IDTI))
//! @}
//! @name USBB OTG Vbus management
//! @{
#define otg_enable_vbus_interrupt() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSTE))
#define otg_disable_vbus_interrupt() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSTE))
#define Is_otg_vbus_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSTE))
#define Is_otg_vbus_high() (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_VBUS))
#define Is_otg_vbus_low() (!Is_otg_vbus_high())
#define otg_ack_vbus_transition() (UOTGHS->UOTGHS_SCR = UOTGHS_SCR_VBUSTIC)
#define otg_raise_vbus_transition() (UOTGHS->UOTGHS_SFR = UOTGHS_SFR_VBUSTIS)
#define Is_otg_vbus_transition() (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_VBUSTI))
//! @}
//! @name UOTGHS OTG main management
//! These macros allows to enable/disable pad and UOTGHS hardware
//! @{
//! Enable USB macro
#define otg_enable() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_USBE))
//! Disable USB macro
#define otg_disable() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_USBE))
#define Is_otg_enabled() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_USBE))
//! Enable OTG pad
#define otg_enable_pad() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_OTGPADE))
//! Disable OTG pad
#define otg_disable_pad() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_OTGPADE))
#define Is_otg_pad_enabled() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_OTGPADE))
//! Check Clock Usable
//! For parts with HS feature, this one corresponding at UTMI clock
#define Is_otg_clock_usable() (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_CLKUSABLE))
//! Stop (freeze) internal USB clock
#define otg_freeze_clock() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_FRZCLK))
#define otg_unfreeze_clock() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_FRZCLK))
#define Is_otg_clock_frozen() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_FRZCLK))
//! Configure time-out of specified OTG timer
#define otg_configure_timeout(timer, timeout) (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_UNLOCK),\
Wr_bitfield(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_TIMPAGE_Msk, timer),\
Wr_bitfield(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_TIMVALUE_Msk, timeout),\
Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_UNLOCK))
//! Get configured time-out of specified OTG timer
#define otg_get_timeout(timer) (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_UNLOCK),\
Wr_bitfield(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_TIMPAGE_Msk, timer),\
Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_UNLOCK),\
Rd_bitfield(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_TIMVALUE_Msk))
//! Get the dual-role device state of the internal USB finite state machine of the UOTGHS controller
#define otg_get_fsm_drd_state() (Rd_bitfield(UOTGHS->UOTGHS_FSM, UOTGHS_FSM_DRDSTATE_Msk))
//! @}
//! @name UOTGHS OTG hardware protocol
//! These macros manages the hardware OTG protocol
//! @{
//! Initiates a Host Negociation Protocol
#define otg_device_initiate_hnp() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_HNPREQ))
//! Accepts a Host Negociation Protocol
#define otg_host_accept_hnp() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_HNPREQ))
//! Rejects a Host Negociation Protocol
#define otg_host_reject_hnp() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_HNPREQ))
//! initiates a Session Request Protocol
#define otg_device_initiate_srp() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_SRPREQ))
//! Selects VBus as SRP method
#define otg_select_vbus_srp_method() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_SRPSEL))
#define Is_otg_vbus_srp_method_selected() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_SRPSEL))
//! Selects data line as SRP method
#define otg_select_data_srp_method() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_SRPSEL))
#define Is_otg_data_srp_method_selected() (!Is_otg_vbus_srp_method_selected())
//! Tests if a HNP occurs
#define Is_otg_hnp() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_HNPREQ))
//! Tests if a SRP from device occurs
#define Is_otg_device_srp() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_SRPREQ))
//! Enables HNP error interrupt
#define otg_enable_hnp_error_interrupt() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_HNPERRE))
//! Disables HNP error interrupt
#define otg_disable_hnp_error_interrupt() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_HNPERRE))
#define Is_otg_hnp_error_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_HNPERRE))
//! ACKs HNP error interrupt
#define otg_ack_hnp_error_interrupt() (UOTGHS->UOTGHS_SCR = UOTGHS_SCR_HNPERRIC)
//! Raises HNP error interrupt
#define otg_raise_hnp_error_interrupt() (UOTGHS->UOTGHS_SFR = UOTGHS_SFR_HNPERRIS)
//! Tests if a HNP error occurs
#define Is_otg_hnp_error_interrupt() (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_HNPERRI))
//! Enables role exchange interrupt
#define otg_enable_role_exchange_interrupt() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_ROLEEXE))
//! Disables role exchange interrupt
#define otg_disable_role_exchange_interrupt() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_ROLEEXE))
#define Is_otg_role_exchange_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_ROLEEXE))
//! ACKs role exchange interrupt
#define otg_ack_role_exchange_interrupt() (UOTGHS->UOTGHS_SCR = UOTGHS_SCR_ROLEEXIC)
//! Raises role exchange interrupt
#define otg_raise_role_exchange_interrupt() (UOTGHS->UOTGHS_SFR = UOTGHS_SFR_ROLEEXIS)
//! Tests if a role exchange occurs
#define Is_otg_role_exchange_interrupt() (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_ROLEEXI))
//! Eenables SRP interrupt
#define otg_enable_srp_interrupt() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_SRPE))
//! Disables SRP interrupt
#define otg_disable_srp_interrupt() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_SRPE))
#define Is_otg_srp_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_SRPE))
//! ACKs SRP interrupt
#define otg_ack_srp_interrupt() (UOTGHS->UOTGHS_SCR = UOTGHS_SCR_SRPIC)
//! Raises SRP interrupt
#define otg_raise_srp_interrupt() (UOTGHS->UOTGHS_SFR = UOTGHS_SFR_SRPIS)
//! Tests if a SRP occurs
#define Is_otg_srp_interrupt() (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_SRPI))
//! @}
//! @}
#endif /* UOTGHS_DEVICE_H_INCLUDED */

View File

@@ -0,0 +1,389 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#ifndef UOTGHS_HOST_H_INCLUDED
#define UOTGHS_HOST_H_INCLUDED
//! \ingroup usb_host_group
//! \defgroup uhd_group USB Host Driver (UHD)
//! UOTGHS low-level driver for USB host mode
//!
//! @{
//! @name UOTGHS Host IP properties
//!
//! @{
//! Get maximal number of endpoints
#define uhd_get_pipe_max_nbr() (9)
#define UOTGHS_EPT_NUM (uhd_get_pipe_max_nbr()+1)
//! @}
//! @name Host Vbus line control
//!
//! VBOF is an optional output pin which allows to enable or disable
//! the external VBus generator.
//!
//! @{
//! Enables hardware control of USB_VBOF output pin when a Vbus error occur
#define uhd_enable_vbus_error_hw_control() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSHWC))
//! Disables hardware control of USB_VBOF output pin when a Vbus error occur
#define uhd_disable_vbus_error_hw_control() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSHWC))
//! Pin and function for USB_VBOF according to configuration from USB_VBOF
#define USB_VBOF_PIN USB_VBOF_GPIO
#define USB_VBOF_FUNCTION USB_VBOF_FLAGS
//! Output USB_VBOF onto its pin
#define uhd_output_vbof_pin() do {\
pio_configure_pin(USB_VBOF_PIN, USB_VBOF_FUNCTION); \
} while (0)
//! Set USB_VBOF output pin polarity
#define uhd_set_vbof_active_high() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSPO))
#define uhd_set_vbof_active_low() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBUSPO))
//! Requests VBus activation
#define uhd_enable_vbus() (Set_bits(UOTGHS->UOTGHS_SFR, UOTGHS_SR_VBUSRQ))
//! Requests VBus deactivation
#define uhd_disable_vbus() (Set_bits(UOTGHS->UOTGHS_SCR, UOTGHS_SR_VBUSRQ))
//! Tests if VBus activation has been requested
#define Is_uhd_vbus_enabled() (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_VBUSRQ))
//! @}
//! @name Host Vbus line monitoring
//!
//! The VBus level is always checked by USBC hardware.
//!
//! @{
#define uhd_enable_vbus_error_interrupt() (Set_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBERRE))
#define uhd_disable_vbus_error_interrupt() (Clr_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBERRE))
#define Is_uhd_vbus_error_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBERRE))
#define uhd_ack_vbus_error_interrupt() (Set_bits(UOTGHS->UOTGHS_SCR, UOTGHS_SCR_VBERRIC))
#define Is_uhd_vbus_error_interrupt() (Tst_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_VBERRI))
//! @}
#define uhd_ack_errors_interrupt() (UOTGHS->UOTGHS_SCR = (UOTGHS_SCR_VBERRIC|UOTGHS_SCR_BCERRIC|UOTGHS_SCR_HNPERRIC|UOTGHS_SCR_STOIC))
#define Is_uhd_errors_interrupt() (Tst_bits(UOTGHS->UOTGHS_CTRL, UOTGHS_CTRL_VBERRE|UOTGHS_CTRL_BCERRE|UOTGHS_CTRL_HNPERRE|UOTGHS_CTRL_STOE))
#define uhd_enable_suspend_error_interrupt()
#define uhd_enable_hnp_error_interrupt()
#define uhd_enable_bconn_error_interrupt()
//! @name USB device connection/disconnection monitoring
//! @{
#define uhd_enable_connection_int() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_DCONNIES)
#define uhd_disable_connection_int() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_DCONNIEC)
#define Is_uhd_connection_int_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_DCONNIE))
#define uhd_ack_connection() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_DCONNIC)
#define Is_uhd_connection() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_DCONNI))
#define uhd_enable_disconnection_int() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_DDISCIES)
#define uhd_disable_disconnection_int() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_DDISCIEC)
#define Is_uhd_disconnection_int_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_DDISCIE))
#define uhd_ack_disconnection() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_DDISCIC)
#define Is_uhd_disconnection() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_DDISCI))
//! @}
//! @name USB device speed control
//! @{
#define uhd_get_speed_mode() (Rd_bits(UOTGHS->UOTGHS_SR, UOTGHS_SR_SPEED_Msk))
#define Is_uhd_low_speed_mode() (uhd_get_speed_mode() == UOTGHS_SR_SPEED_LOW_SPEED)
#define Is_uhd_full_speed_mode() (uhd_get_speed_mode() == UOTGHS_SR_SPEED_FULL_SPEED)
#define Is_uhd_high_speed_mode() (uhd_get_speed_mode() == UOTGHS_SR_SPEED_HIGH_SPEED)
//! Enable high speed mode
# define uhd_enable_high_speed_mode() (Wr_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SPDCONF_Msk, UOTGHS_HSTCTRL_SPDCONF_HIGH_SPEED))
//! Disable high speed mode
# define uhd_disable_high_speed_mode() (Wr_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SPDCONF_Msk, UOTGHS_HSTCTRL_SPDCONF_FORCED_FS))
//! @}
//! @name Bus events control
//! These macros manage the bus events: reset, SOF, resume, wakeup.
//! @{
//! Initiates a reset event
//! @{
#define uhd_start_reset() (Set_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESET))
#define Is_uhd_starting_reset() (Tst_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESET))
#define uhd_stop_reset() (Clr_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESET))
#define uhd_enable_reset_sent_interrupt() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_RSTIES)
#define uhd_disable_reset_sent_interrupt() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_RSTIEC)
#define Is_uhd_reset_sent_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_RSTIE))
#define uhd_ack_reset_sent() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_RSTIC)
#define Is_uhd_reset_sent() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_RSTI))
//! @}
//! Initiates a SOF events
//! @{
#define uhd_enable_sof() (Set_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SOFE))
#define uhd_disable_sof() (Clr_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SOFE))
#define Is_uhd_sof_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_SOFE))
#define uhd_get_sof_number() ((UOTGHS->UOTGHS_HSTFNUM&UOTGHS_HSTFNUM_FNUM_Msk)>>UOTGHS_HSTFNUM_FNUM_Pos)
#define uhd_get_microsof_number() ((UOTGHS->UOTGHS_HSTFNUM&UOTGHS_HSTFNUM_MFNUM_Msk)>>UOTGHS_HSTFNUM_MFNUM_Pos)
#define uhd_get_frame_position() (Rd_bits(UOTGHS->UOTGHS_HSTFNUM, UOTGHS_HSTFNUM_FLENHIGH_Msk))
#define uhd_enable_sof_interrupt() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_HSOFIES)
#define uhd_disable_sof_interrupt() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_HSOFIEC)
#define Is_uhd_sof_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_HSOFIE))
#define uhd_ack_sof() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_HSOFIC)
#define Is_uhd_sof() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_HSOFI))
//! @}
//! Initiates a resume event
//! It is called downstream resume event.
//! @{
#define uhd_send_resume() (Set_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESUME))
#define Is_uhd_sending_resume() (Tst_bits(UOTGHS->UOTGHS_HSTCTRL, UOTGHS_HSTCTRL_RESUME))
#define uhd_enable_downstream_resume_interrupt() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_RSMEDIES)
#define uhd_disable_downstream_resume_interrupt() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_RSMEDIEC)
#define Is_uhd_downstream_resume_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_RSMEDIE))
#define uhd_ack_downstream_resume() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_RSMEDIC)
#define Is_uhd_downstream_resume() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_RSMEDI))
//! @}
//! Detection of a wake-up event
//! A wake-up event is received when the host controller is in the suspend mode:
//! - and an upstream resume from the peripheral is detected.
//! - and a peripheral disconnection is detected.
//! @{
#define uhd_enable_wakeup_interrupt() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_HWUPIES)
#define uhd_disable_wakeup_interrupt() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_HWUPIEC)
#define Is_uhd_wakeup_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_HWUPIE))
#define uhd_ack_wakeup() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_HWUPIC)
#define Is_uhd_wakeup() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_HWUPI))
#define uhd_enable_upstream_resume_interrupt() (UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTIER_RXRSMIES)
#define uhd_disable_upstream_resume_interrupt() (UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_RXRSMIEC)
#define Is_uhd_upstream_resume_interrupt_enabled() (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_RXRSMIE))
#define uhd_ack_upstream_resume() (UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_RXRSMIC)
#define Is_uhd_upstream_resume() (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_RXRSMI))
//! @}
//! @}
//! @name Pipes management
//! @{
//! USB address of pipes
//! @{
#define uhd_configure_address(p, addr) \
(Wr_bitfield((&UOTGHS->UOTGHS_HSTADDR1)[(p)>>2], \
UOTGHS_HSTADDR1_HSTADDRP0_Msk << (((p)&0x03)<<3), addr))
#define uhd_get_configured_address(p) \
(Rd_bitfield((&UOTGHS->UOTGHS_HSTADDR1)[(p)>>2], \
UOTGHS_HSTADDR1_HSTADDRP0_Msk << (((p)&0x03)<<3)))
//! @}
//! Pipe enable
//! Enable, disable, reset, freeze
//! @{
#define uhd_enable_pipe(p) \
(Set_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p)))
#define uhd_disable_pipe(p) \
(Clr_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p)))
#define Is_uhd_pipe_enabled(p) \
(Tst_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p)))
#define uhd_reset_pipe(p) \
(Set_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p))); \
(Clr_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p)))
#define Is_uhd_resetting_pipe(p) \
(Tst_bits(UOTGHS->UOTGHS_HSTPIP, UOTGHS_HSTPIP_PEN0 << (p)))
#define uhd_freeze_pipe(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_PFREEZES)
#define uhd_unfreeze_pipe(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_PFREEZEC)
#define Is_uhd_pipe_frozen(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_PFREEZE))
#define uhd_reset_data_toggle(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_RSTDTS)
#define Is_uhd_data_toggle_reset(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_RSTDT))
//! @}
//! Pipe configuration
//! @{
#define uhd_configure_pipe_int_req_freq(p,freq) (Wr_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_INTFRQ_Msk, (freq)))
#define uhd_get_pipe_int_req_freq(p) (Rd_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_INTFRQ_Msk))
#define uhd_configure_pipe_endpoint_number(p,ep) (Wr_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PEPNUM_Msk, (ep)))
#define uhd_get_pipe_endpoint_address(p) \
(uhd_is_pipe_in(p) ?\
(uhd_get_pipe_endpoint_number(p) | USB_EP_DIR_IN) :\
(uhd_get_pipe_endpoint_number(p) | USB_EP_DIR_OUT))
#define uhd_get_pipe_endpoint_number(p) (Rd_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], (UOTGHS_HSTPIPCFG_PEPNUM_Msk)))
#define uhd_configure_pipe_type(p, type) (Wr_bitfield(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PTYPE_Msk, type))
#define uhd_get_pipe_type(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PTYPE_Msk))
#define uhd_enable_pipe_bank_autoswitch(p) (Set_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_AUTOSW))
#define uhd_disable_pipe_bank_autoswitch(p) (Clr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_AUTOSW))
#define Is_uhd_pipe_bank_autoswitch_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_AUTOSW))
#define uhd_configure_pipe_token(p, token) (Wr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PTOKEN_Msk, token))
#define uhd_get_pipe_token(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PTOKEN_Msk))
#define uhd_is_pipe_in(p) (UOTGHS_HSTPIPCFG_PTOKEN_IN==uhd_get_pipe_token(p))
#define uhd_is_pipe_out(p) (UOTGHS_HSTPIPCFG_PTOKEN_OUT==uhd_get_pipe_token(p))
//! Bounds given integer size to allowed range and rounds it up to the nearest
//! available greater size, then applies register format of UOTGHS controller
//! for pipe size bit-field.
#define uhd_format_pipe_size(size) \
(32 - clz(((uint32_t)min(max(size, 8), 1024) << 1) - 1) - 1 - 3)
#define uhd_configure_pipe_size(p,size) \
(Wr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PSIZE_Msk, uhd_format_pipe_size(size)))
#define uhd_get_pipe_size(p) (8<<((Rd_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], (UOTGHS_HSTPIPCFG_PSIZE_Msk)))>> UOTGHS_HSTPIPCFG_PSIZE_Pos))
#define uhd_configure_pipe_bank(p,bank) (Wr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PBK_Msk, (bank)))
#define uhd_get_pipe_bank(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PBK_Msk))
#define uhd_allocate_memory(p) (Set_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_ALLOC))
#define uhd_unallocate_memory(p) (Clr_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_ALLOC))
#define Is_uhd_memory_allocated(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_ALLOC))
//! Enable PING management only available in HS mode
# define uhd_enable_ping(p) (Set_bits(UOTGHS->UOTGHS_HSTPIPCFG[p], UOTGHS_HSTPIPCFG_PINGEN))
//#endif
#define uhd_configure_pipe(p, freq, ep_num, type, token, size, bank, bank_switch) \
(UOTGHS->UOTGHS_HSTPIPCFG[p] = \
(bank)|\
((uhd_format_pipe_size(size)<<UOTGHS_HSTPIPCFG_PSIZE_Pos)&UOTGHS_HSTPIPCFG_PSIZE_Msk)|\
((token)&UOTGHS_HSTPIPCFG_PTOKEN_Msk)|\
((type)&UOTGHS_HSTPIPCFG_PTYPE_Msk)|\
(((ep_num)<<UOTGHS_HSTPIPCFG_PEPNUM_Pos)&UOTGHS_HSTPIPCFG_PEPNUM_Msk)|\
bank_switch |\
(((freq)<<UOTGHS_HSTPIPCFG_INTFRQ_Pos)&UOTGHS_HSTPIPCFG_INTFRQ_Msk))
#define Is_uhd_pipe_configured(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_CFGOK))
//! @}
//! Pipe main interrupts management
//! @{
#define uhd_enable_pipe_interrupt(p) (UOTGHS->UOTGHS_HSTIER = (UOTGHS_HSTIER_PEP_0 << (p)))
#define uhd_disable_pipe_interrupt(p) (UOTGHS->UOTGHS_HSTIDR = (UOTGHS_HSTIDR_PEP_0 << (p)))
#define Is_uhd_pipe_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTIMR, UOTGHS_HSTIMR_PEP_0 << (p)))
#define Is_uhd_pipe_interrupt(p) (Tst_bits(UOTGHS->UOTGHS_HSTISR, UOTGHS_HSTISR_PEP_0 << (p)))
//! returns the lowest pipe number generating a pipe interrupt or UOTGHS_EPT_NUM if none
#define uhd_get_interrupt_pipe_number() \
(ctz(((UOTGHS->UOTGHS_HSTISR >> 8) & (UOTGHS->UOTGHS_HSTIMR >> 8)) | (1 << UOTGHS_EPT_NUM)))
//! @}
//! Pipe overflow and underflow for isochronous and interrupt endpoints
//! @{
#define uhd_enable_overflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_OVERFIES)
#define uhd_disable_overflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_OVERFIEC)
#define Is_uhd_overflow_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_OVERFIE))
#define uhd_ack_overflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_OVERFIC)
#define Is_uhd_overflow(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_OVERFI))
#define uhd_enable_underflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_UNDERFIES)
#define uhd_disable_underflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_UNDERFIEC)
#define Is_uhd_underflow_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_UNDERFIE))
#define uhd_ack_underflow_interrupt(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_UNDERFIC)
#define Is_uhd_underflow(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_UNDERFI))
//! @}
//! USB packet errors management
//! @{
#define uhd_enable_stall_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_RXSTALLDES)
#define uhd_disable_stall_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_RXSTALLDEC)
#define Is_uhd_stall_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_RXSTALLDE))
#define uhd_ack_stall(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_RXSTALLDIC)
#define Is_uhd_stall(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_RXSTALLDI))
#define uhd_enable_pipe_error_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_PERRES)
#define uhd_disable_pipe_error_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_PERREC)
#define Is_uhd_pipe_error_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_PERRE))
#define uhd_ack_all_errors(p) (UOTGHS->UOTGHS_HSTPIPERR[p] = 0UL)
#define Is_uhd_pipe_error(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_PERRI))
#define uhd_error_status(p) (UOTGHS->UOTGHS_HSTPIPERR[p])
#define Is_uhd_bad_data_toggle(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_DATATGL))
#define Is_uhd_data_pid_error(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_DATAPID))
#define Is_uhd_pid_error(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_PID))
#define Is_uhd_timeout_error(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_TIMEOUT))
#define Is_uhd_crc16_error(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_CRC16))
#define uhd_get_error_counter(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPERR[p], UOTGHS_HSTPIPERR_COUNTER))
//! @}
//! Pipe data management
//! @{
#define uhd_data_toggle(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_DTSEQ))
#define uhd_enable_bank_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_NBUSYBKES)
#define uhd_disable_bank_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_NBUSYBKEC)
#define Is_uhd_bank_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_NBUSYBKE))
#define uhd_nb_busy_bank(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_NBUSYBK_Msk))
#define uhd_current_bank(p) (Rd_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_CURRBK_Msk ))
#define uhd_enable_short_packet_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_SHORTPACKETES)
#define uhd_disable_short_packet_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_SHORTPACKETIEC)
#define Is_uhd_short_packet_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_SHORTPACKETIE)) )
#define uhd_ack_short_packet(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_SHORTPACKETIC)
#define Is_uhd_short_packet(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_SHORTPACKETI))
#define uhd_byte_count(p) (Rd_bitfield(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_PBYCT_Msk))
#define Is_uhd_fifocon(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_FIFOCON))
#define uhd_ack_fifocon(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_FIFOCONC)
#define uhd_enable_setup_ready_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_TXSTPES)
#define uhd_disable_setup_ready_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_TXSTPEC)
#define Is_uhd_setup_ready_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_TXSTPE))
#define uhd_ack_setup_ready(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_TXSTPIC)
#define Is_uhd_setup_ready(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_TXSTPI))
#define uhd_enable_in_received_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_RXINES)
#define uhd_disable_in_received_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_RXINEC)
#define Is_uhd_in_received_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_RXINE))
#define uhd_ack_in_received(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_RXINIC)
#define Is_uhd_in_received(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_RXINI))
#define uhd_enable_out_ready_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_TXOUTES)
#define uhd_disable_out_ready_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_TXOUTEC)
#define Is_uhd_out_ready_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_TXOUTE))
#define uhd_ack_out_ready(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_TXOUTIC)
#define Is_uhd_out_ready(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_TXOUTI))
#define uhd_raise_out_ready(p) (UOTGHS->UOTGHS_HSTPIPIFR[p] = UOTGHS_HSTPIPIFR_TXOUTIS)
#define uhd_enable_nak_received_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIER[p] = UOTGHS_HSTPIPIER_NAKEDES)
#define uhd_disable_nak_received_interrupt(p) (UOTGHS->UOTGHS_HSTPIPIDR[p] = UOTGHS_HSTPIPIDR_NAKEDEC)
#define Is_uhd_nak_received_interrupt_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPIMR[p], UOTGHS_HSTPIPIMR_NAKEDE))
#define uhd_ack_nak_received(p) (UOTGHS->UOTGHS_HSTPIPICR[p] = UOTGHS_HSTPIPICR_NAKEDIC)
#define Is_uhd_nak_received(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_NAKEDI))
#define Is_uhd_read_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_RWALL))
#define Is_uhd_write_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPISR[p], UOTGHS_HSTPIPISR_RWALL ))
#define uhd_enable_continuous_in_mode(p) (Set_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], UOTGHS_HSTPIPINRQ_INMODE))
#define uhd_disable_continuous_in_mode(p) (Clr_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], UOTGHS_HSTPIPINRQ_INMODE))
#define Is_uhd_continuous_in_mode_enabled(p) (Tst_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], UOTGHS_HSTPIPINRQ_INMODE))
#define uhd_in_request_number(p, in_num) (Set_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], (in_num)-1))
#define uhd_get_in_request_number(p) (((Rd_bits(UOTGHS->UOTGHS_HSTPIPINRQ[p], UOTGHS_HSTPIPINRQ_INRQ_Msk))>>UOTGHS_HSTPIPINRQ_INRQ_Pos)+1)
//! @}
//! Maximum transfer size on USB DMA
#define UHD_PIPE_MAX_TRANS 0x8000
//! Get 64-, 32-, 16- or 8-bit access to FIFO data register of selected pipe.
//! @param p Target Pipe number
//! @param scale Data scale in bits: 64, 32, 16 or 8
//! @return Volatile 64-, 32-, 16- or 8-bit data pointer to FIFO data register
//! @warning It is up to the user of this macro to make sure that all accesses
//! are aligned with their natural boundaries except 64-bit accesses which
//! require only 32-bit alignment.
//! @warning It is up to the user of this macro to make sure that used HSB
//! addresses are identical to the DPRAM internal pointer modulo 32 bits.
#define uhd_get_pipe_fifo_access(p, scale) \
(((volatile TPASTE2(U, scale) (*)[UHD_PIPE_MAX_TRANS / ((scale) / 8)])UOTGHS_RAM_ADDR)[(p)])
#endif /* UOTGHS_HOST_H_INCLUDED */

View File

@@ -0,0 +1,133 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* \par Purpose
*
* This module provides several definitions and methods for using an USART
* peripheral.
*
* \par Usage
*
* -# Enable the USART peripheral clock in the PMC.
* -# Enable the required USART PIOs (see pio.h).
* -# Configure the UART by calling USART_Configure.
* -# Enable the transmitter and/or the receiver of the USART using
* USART_SetTransmitterEnabled and USART_SetReceiverEnabled.
* -# Send data through the USART using the USART_Write and
* USART_WriteBuffer methods.
* -# Receive data from the USART using the USART_Read and
* USART_ReadBuffer functions; the availability of data can be polled
* with USART_IsDataAvailable.
* -# Disable the transmitter and/or the receiver of the USART with
* USART_SetTransmitterEnabled and USART_SetReceiverEnabled.
*/
#ifndef _USART_
#define _USART_
/*------------------------------------------------------------------------------
* Headers
*------------------------------------------------------------------------------*/
#include "../chip.h"
#include <stdint.h>
/*------------------------------------------------------------------------------
* Definitions
*------------------------------------------------------------------------------*/
/** \section USART_mode USART modes
* This section lists several common operating modes for an USART peripheral.
*
* \b Modes
* - USART_MODE_ASYNCHRONOUS
* - USART_MODE_IRDA
*/
/** Basic asynchronous mode, i.e. 8 bits no parity.*/
#define USART_MODE_ASYNCHRONOUS (US_MR_CHRL_8_BIT | US_MR_PAR_NO)
/** IRDA mode*/
#define USART_MODE_IRDA (AT91C_US_USMODE_IRDA | AT91C_US_CHRL_8_BITS | AT91C_US_PAR_NONE | AT91C_US_FILTER)
/** SPI mode*/
#define AT91C_US_USMODE_SPIM 0xE
#define US_SPI_CPOL_0 (0x0<<16)
#define US_SPI_CPHA_0 (0x0<<8)
#define US_SPI_CPOL_1 (0x1<<16)
#define US_SPI_CPHA_1 (0x1<<8)
#define US_SPI_BPMODE_0 (US_SPI_CPOL_0|US_SPI_CPHA_1)
#define US_SPI_BPMODE_1 (US_SPI_CPOL_0|US_SPI_CPHA_0)
#define US_SPI_BPMODE_2 (US_SPI_CPOL_1|US_SPI_CPHA_1)
#define US_SPI_BPMODE_3 (US_SPI_CPOL_1|US_SPI_CPHA_0)
#ifdef __cplusplus
extern "C" {
#endif
/*------------------------------------------------------------------------------*/
/* Exported functions */
/*------------------------------------------------------------------------------*/
extern void USART_Configure( Usart *usart, uint32_t mode, uint32_t baudrate, uint32_t masterClock ) ;
extern uint32_t USART_GetStatus( Usart *usart ) ;
extern void USART_EnableIt( Usart *usart,uint32_t mode ) ;
extern void USART_DisableIt( Usart *usart,uint32_t mode ) ;
extern void USART_SetTransmitterEnabled( Usart *usart, uint8_t enabled ) ;
extern void USART_SetReceiverEnabled( Usart *usart, uint8_t enabled ) ;
extern void USART_Write( Usart *usart, uint16_t data, volatile uint32_t timeOut ) ;
extern uint8_t USART_WriteBuffer( Usart *usart, void *buffer, uint32_t size ) ;
extern uint16_t USART_Read( Usart *usart, volatile uint32_t timeOut ) ;
extern uint8_t USART_ReadBuffer( Usart *usart, void *buffer, uint32_t size ) ;
extern uint8_t USART_IsDataAvailable( Usart *usart ) ;
extern void USART_SetIrdaFilter(Usart *pUsart, uint8_t filter);
extern void USART_PutChar( Usart *usart, uint8_t c ) ;
extern uint32_t USART_IsRxReady( Usart *usart ) ;
extern uint8_t USART_GetChar( Usart *usart ) ;
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _USART_ */

View File

@@ -0,0 +1,74 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
*
* \section Purpose
* Interface for Watchdog Timer (WDT) controller.
*
* \section Usage
* -# Enable watchdog with given mode using \ref WDT_Enable().
* -# Disable watchdog using \ref WDT_Disable()
* -# Restart the watchdog using \ref WDT_Restart().
* -# Get watchdog status using \ref WDT_GetStatus().
* -# Caculate watchdog period value using \ref WDT_GetPeriod().
*/
#ifndef _WDT_
#define _WDT_
#include "../chip.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
extern void WDT_Enable( Wdt* pWDT, uint32_t dwMode ) ;
extern void WDT_Disable( Wdt* pWDT ) ;
extern void WDT_Restart( Wdt* pWDT ) ;
extern uint32_t WDT_GetStatus( Wdt* pWDT ) ;
extern uint32_t WDT_GetPeriod( uint32_t dwMs ) ;
#ifdef __cplusplus
}
#endif
#endif /* #ifndef _WDT_ */

View File

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

View File

@@ -0,0 +1,962 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#include "../chip.h"
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
/**
* \defgroup sam_drivers_adc_group Analog-to-digital Converter (ADC)
*
* Driver for the Analog-to-digital Converter. This driver provides access to the main
* features of the ADC controller.
*
* @{
*/
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES
/**
* \brief Initialize the given ADC with the specified ADC clock and startup time.
*
* \param p_adc Pointer to an ADC instance.
* \param ul_mck Main clock of the device (value in Hz).
* \param ul_adc_clock Analog-to-Digital conversion clock (value in Hz).
* \param uc_startup ADC start up time. Please refer to the product datasheet
* for details.
*
* \return 0 on success.
*/
uint32_t adc_init(Adc *p_adc, const uint32_t ul_mck,
const uint32_t ul_adc_clock, const uint8_t uc_startup)
{
uint32_t ul_prescal;
/* Reset the controller. */
p_adc->ADC_CR = ADC_CR_SWRST;
/* Reset Mode Register. */
p_adc->ADC_MR = 0;
/* Reset PDC transfer. */
p_adc->ADC_PTCR = (ADC_PTCR_RXTDIS | ADC_PTCR_TXTDIS);
p_adc->ADC_RCR = 0;
p_adc->ADC_RNCR = 0;
ul_prescal = ul_mck / (2 * ul_adc_clock) - 1;
p_adc->ADC_MR |= ADC_MR_PRESCAL(ul_prescal) |
((uc_startup << ADC_MR_STARTUP_Pos) &
ADC_MR_STARTUP_Msk);
return 0;
}
#elif SAM3XA_SERIES
/**
* \brief Initialize the given ADC with the specified ADC clock and startup time.
*
* \param p_adc Pointer to an ADC instance.
* \param ul_mck Main clock of the device (value in Hz).
* \param ul_adc_clock Analog-to-Digital conversion clock (value in Hz).
* \param uc_startup ADC start up time. Please refer to the product datasheet
* for details.
*
* \return 0 on success.
*/
uint32_t adc_init(Adc *p_adc, const uint32_t ul_mck,
const uint32_t ul_adc_clock, const uint8_t uc_startuptime)
{
uint32_t startup_table[] = { 0, 8, 16, 24, 64, 80, 96, 112, 512, 576, 640, 704, 768, 832, 896, 960 };
uint32_t ul_prescal, ul_startup, ul_mr_startup, ul_real_adc_clock;
p_adc->ADC_CR = ADC_CR_SWRST;
/* Reset Mode Register. */
p_adc->ADC_MR = 0;
/* Reset PDC transfer. */
p_adc->ADC_PTCR = (ADC_PTCR_RXTDIS | ADC_PTCR_TXTDIS);
p_adc->ADC_RCR = 0;
p_adc->ADC_RNCR = 0;
if (ul_mck % (2 * ul_adc_clock)) {
// Division with reminder
ul_prescal = ul_mck / (2 * ul_adc_clock);
} else {
// Whole division
ul_prescal = ul_mck / (2 * ul_adc_clock) - 1;
}
ul_real_adc_clock = ul_mck / (2 * (ul_prescal + 1));
// ADC clocks needed to get ul_startuptime uS
ul_startup = (ul_real_adc_clock / 1000000) * uc_startuptime;
// Find correct MR_STARTUP value from conversion table
for (ul_mr_startup=0; ul_mr_startup<16; ul_mr_startup++) {
if (startup_table[ul_mr_startup] >= ul_startup)
break;
}
if (ul_mr_startup==16)
return -1;
p_adc->ADC_MR |= ADC_MR_PRESCAL(ul_prescal) |
((ul_mr_startup << ADC_MR_STARTUP_Pos) & ADC_MR_STARTUP_Msk);
return 0;
}
#elif SAM3U_SERIES
/**
* \brief Initialize the given ADC with the specified ADC clock and startup time.
*
* \param p_adc Pointer to an ADC instance.
* \param ul_mck Main clock of the device (value in Hz).
* \param ul_adc_clock Analog-to-Digital conversion clock (in Hz).
* \param ul_startuptime ADC startup time value (value in us).
* Please refer to the product datasheet for details.
* \param ul_offmode_startuptime ADC off mode startup time value (in us).
* Please refer to the product datasheet for details.
*
* \return 0 on success.
*/
uint32_t adc_init(Adc *p_adc, const uint32_t ul_mck, const uint32_t ul_adc_clock,
const uint32_t ul_startuptime)
{
uint32_t ul_prescal, ul_startup;
p_adc->ADC_CR = ADC_CR_SWRST;
/* Reset Mode Register. */
p_adc->ADC_MR = 0;
/* Reset PDC transfer. */
p_adc->ADC_PTCR = (ADC_PTCR_RXTDIS | ADC_PTCR_TXTDIS);
p_adc->ADC_RCR = 0;
p_adc->ADC_RNCR = 0;
ul_prescal = ul_mck / (2 * ul_adc_clock) - 1;
ul_startup = ((ul_adc_clock / 1000000) * ul_startuptime / 8) - 1;
p_adc->ADC_MR |= ADC_MR_PRESCAL(ul_prescal) |
((ul_startup << ADC_MR_STARTUP_Pos) &
ADC_MR_STARTUP_Msk);
return 0;
}
#endif
/**
* \brief Configure the conversion resolution.
*
* \param p_adc Pointer to an ADC instance.
* \param resolution ADC resolution.
*
*/
void adc_set_resolution(Adc *p_adc,const enum adc_resolution_t resolution)
{
p_adc->ADC_MR |= (resolution << 4) & ADC_MR_LOWRES;
}
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
/**
* \brief Configure conversion trigger and free run mode.
*
* \param p_adc Pointer to an ADC instance.
* \param trigger Conversion trigger.
* \param uc_freerun ADC_MR_FREERUN_ON enables freerun mode,
* ADC_MR_FREERUN_OFF disables freerun mode.
*
*/
void adc_configure_trigger(Adc *p_adc, const enum adc_trigger_t trigger,
uint8_t uc_freerun)
{
p_adc->ADC_MR |= trigger | ((uc_freerun << 7) & ADC_MR_FREERUN);
}
#elif SAM3U_SERIES
/**
* \brief Configure conversion trigger and free run mode.
*
* \param p_adc Pointer to an ADC instance.
* \param trigger Conversion trigger.
*/
void adc_configure_trigger(Adc *p_adc, const enum adc_trigger_t trigger)
{
p_adc->ADC_MR |= trigger;
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
/**
* \brief Configures ADC power saving mode.
*
* \param p_adc Pointer to an ADC instance.
* \param uc_sleep ADC_MR_SLEEP_NORMAL keeps the ADC Core and reference voltage
* circuitry ON between conversions.
* ADC_MR_SLEEP_SLEEP keeps the ADC Core and reference voltage circuitry OFF
* between conversions.
* \param uc_fwup ADC_MR_FWUP_OFF configures sleep mode as uc_sleep setting,
* ADC_MR_FWUP_ON keeps voltage reference ON and ADC Core OFF between conversions.
*/
void adc_configure_power_save(Adc *p_adc, const uint8_t uc_sleep, const uint8_t uc_fwup)
{
p_adc->ADC_MR |= (((uc_sleep << 5) & ADC_MR_SLEEP) |
((uc_fwup << 6) & ADC_MR_FWUP));
}
#elif SAM3U_SERIES
/**
* \brief Configure ADC power saving mode.
*
* \param p_adc Pointer to an ADC instance.
* \param uc_sleep ADC_MR_SLEEP_NORMAL keeps the ADC Core and reference
* voltage circuitry ON between conversions.
* ADC_MR_SLEEP_SLEEP keeps the ADC Core and reference voltage circuitry
* OFF between conversions.
* \param uc_offmode 0 for Standby Mode (if Sleep Bit = 1), 1 for Off Mode.
*/
void adc_configure_power_save(Adc *p_adc, const uint8_t uc_sleep)
{
p_adc->ADC_MR |= ((uc_sleep << 5) & ADC_MR_SLEEP);
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
/**
* \brief Configure conversion sequence.
*
* \param p_adc Pointer to an ADC instance.
* \param ch_list Channel sequence list.
* \param number Number of channels in the list.
*/
void adc_configure_sequence(Adc *p_adc, const enum adc_channel_num_t ch_list[],
uint8_t uc_num)
{
uint8_t uc_counter;
if (uc_num < 8) {
for (uc_counter = 0; uc_counter < uc_num; uc_counter++) {
p_adc->ADC_SEQR1 |=
ch_list[uc_counter] << (4 * uc_counter);
}
} else {
for (uc_counter = 0; uc_counter < 8; uc_counter++) {
p_adc->ADC_SEQR1 |=
ch_list[uc_counter] << (4 * uc_counter);
}
for (uc_counter = 0; uc_counter < uc_num - 8; uc_counter++) {
p_adc->ADC_SEQR2 |=
ch_list[uc_counter] << (4 * uc_counter);
}
}
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3XA_SERIES
/**
* \brief Configure ADC timing.
*
* \param p_adc Pointer to an ADC instance.
* \param uc_tracking ADC tracking time = uc_tracking / ADC clock.
* \param uc_settling Analog settling time = (uc_settling + 1) / ADC clock.
* \param uc_transfer Data transfer time = (uc_transfer * 2 + 3) / ADC clock.
*/
void adc_configure_timing(Adc *p_adc, const uint8_t uc_tracking,
const enum adc_settling_time_t settling,const uint8_t uc_transfer)
{
p_adc->ADC_MR |= ADC_MR_TRANSFER(uc_transfer)
| settling | ADC_MR_TRACKTIM(uc_tracking);
}
#elif SAM3N_SERIES
/**
* \brief Configure ADC timing.
*
* \param p_adc Pointer to an ADC instance.
* \param uc_tracking ADC tracking time = uc_tracking / ADC clock.
*/
void adc_configure_timing(Adc *p_adc, const uint8_t uc_tracking)
{
p_adc->ADC_MR |= ADC_MR_TRACKTIM(uc_tracking);
}
#elif SAM3U_SERIES
/**
* \brief Configure ADC timing.
*
* \param p_adc Pointer to an ADC instance.
* \param ul_sh ADC sample and hold time = uc_sh / ADC clock.
*/
void adc_configure_timing(Adc *p_adc, const uint32_t ul_sh)
{
p_adc->ADC_MR |= ADC_MR_SHTIM(ul_sh);
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3XA_SERIES
/**
* \brief Enable analog change.
*
* \note It allows different analog settings for each channel.
*
* \param p_Adc Pointer to an ADC instance.
*/
void adc_enable_anch(Adc *p_adc)
{
p_adc->ADC_MR |= ADC_MR_ANACH;
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3XA_SERIES
/**
* \brief Disable analog change.
*
* \note DIFF0, GAIN0 and OFF0 are used for all channels.
*
* \param p_Adc Pointer to an ADC instance.
*/
void adc_disable_anch(Adc *p_adc)
{
p_adc->ADC_MR &= ~ADC_MR_ANACH;
}
#endif
/**
* \brief Start analog-to-digital conversion.
*
* \note If one of the hardware event is selected as ADC trigger,
* this function can NOT start analog to digital conversion.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc_start(Adc *p_adc)
{
p_adc->ADC_CR = ADC_CR_START;
}
/**
* \brief Stop analog-to-digital conversion.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc_stop(Adc *p_adc)
{
p_adc->ADC_CR = ADC_CR_SWRST;
}
/**
* \brief Enable the specified ADC channel.
*
* \param p_adc Pointer to an ADC instance.
* \param adc_ch ADC channel number.
*/
void adc_enable_channel(Adc *p_adc, const enum adc_channel_num_t adc_ch)
{
p_adc->ADC_CHER = 1 << adc_ch;
}
/**
* \brief Enable all ADC channels.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc_enable_all_channel(Adc *p_adc)
{
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
p_adc->ADC_CHER = 0xFFFF;
#elif SAM3U_SERIES
p_adc->ADC_CHER = 0xFF;
#endif
}
/**
* \brief Disable the specified ADC channel.
*
* \param p_adc Pointer to an ADC instance.
* \param adc_ch ADC channel number.
*/
void adc_disable_channel(Adc *p_adc, const enum adc_channel_num_t adc_ch)
{
p_adc->ADC_CHDR = 1 << adc_ch;
}
/**
* \brief Disable all ADC channel.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc_disable_all_channel(Adc *p_adc)
{
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
p_adc->ADC_CHDR = 0xFFFF;
#elif SAM3U_SERIES
p_adc->ADC_CHDR = 0xFF;
#endif
}
/**
* \brief Read the ADC channel status.
*
* \param p_adc Pointer to an ADC instance.
* \param adc_ch ADC channel number.
*
* \retval 1 if channel is enabled.
* \retval 0 if channel is disabled.
*/
uint32_t adc_get_channel_status(const Adc *p_adc, const enum adc_channel_num_t adc_ch)
{
return p_adc->ADC_CHSR & (1 << adc_ch);
}
/**
* \brief Read the ADC result data of the specified channel.
*
* \param p_adc Pointer to an ADC instance.
* \param adc_ch ADC channel number.
*
* \return ADC value of the specified channel.
*/
uint32_t adc_get_channel_value(const Adc *p_adc, const enum adc_channel_num_t adc_ch)
{
uint32_t ul_data = 0;
if (15 >= adc_ch) {
ul_data = *(p_adc->ADC_CDR + adc_ch);
}
return ul_data;
}
/**
* \brief Read the last ADC result data.
*
* \param p_adc Pointer to an ADC instance.
*
* \return ADC latest value.
*/
uint32_t adc_get_latest_value(const Adc *p_adc)
{
return p_adc->ADC_LCDR;
}
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
/**
* \brief Enable TAG option so that the number of the last converted channel
* can be indicated.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc_enable_tag(Adc *p_adc)
{
p_adc->ADC_EMR |= ADC_EMR_TAG;
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
/**
* \brief Disable TAG option.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc_disable_tag(Adc *p_adc)
{
p_adc->ADC_EMR &= ~ADC_EMR_TAG;
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
/**
* \brief Indicate the last converted channel.
*
* \note If TAG option is NOT enabled before, an incorrect channel
* number is returned.
*
* \param p_adc Pointer to an ADC instance.
*
* \return The last converted channel number.
*/
enum adc_channel_num_t adc_get_tag(const Adc *p_adc)
{
return (p_adc->ADC_LCDR & ADC_LCDR_CHNB_Msk) >> ADC_LCDR_CHNB_Pos;
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
/**
* \brief Enable conversion sequencer.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc_start_sequencer(Adc *p_adc)
{
p_adc->ADC_MR |= ADC_MR_USEQ;
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
/**
* \brief Disable conversion sequencer.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc_stop_sequencer(Adc *p_adc)
{
p_adc->ADC_MR &= ~ADC_MR_USEQ;
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
/**
* \brief Configure comparison mode.
*
* \param p_adc Pointer to an ADC instance.
* \param uc_mode ADC comparison mode.
*/
void adc_set_comparison_mode(Adc *p_adc, const uint8_t uc_mode)
{
p_adc->ADC_EMR &= (uint32_t) ~ (ADC_EMR_CMPMODE_Msk);
p_adc->ADC_EMR |= (uc_mode & ADC_EMR_CMPMODE_Msk);
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
/**
* \brief Get comparison mode.
*
* \param p_adc Pointer to an ADC instance.
*
* \retval Compare mode value.
*/
uint32_t adc_get_comparison_mode(const Adc *p_adc)
{
return p_adc->ADC_EMR & ADC_EMR_CMPMODE_Msk;
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
/**
* \brief Configure ADC compare window.
*
* \param p_adc Pointer to an ADC instance.
* \param w_low_threshold Low threshold of compare window.
* \param w_high_threshold High threshold of compare window.
*/
void adc_set_comparison_window(Adc *p_adc, const uint16_t us_low_threshold,
const uint16_t us_high_threshold)
{
p_adc->ADC_CWR = ADC_CWR_LOWTHRES(us_low_threshold) |
ADC_CWR_HIGHTHRES(us_high_threshold);
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
/**
* \brief Configure comparison selected channel.
*
* \param p_adc Pointer to an ADC instance.
* \param channel ADC channel number.
*/
void adc_set_comparison_channel(Adc *p_adc, const enum adc_channel_num_t channel)
{
if (channel < 16) {
p_adc->ADC_EMR &= (uint32_t) ~ (ADC_EMR_CMPALL);
p_adc->ADC_EMR &= (uint32_t) ~ (ADC_EMR_CMPSEL_Msk);
p_adc->ADC_EMR |= (channel << ADC_EMR_CMPSEL_Pos);
} else {
p_adc->ADC_EMR |= ADC_EMR_CMPALL;
}
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3XA_SERIES
/**
* \brief Enable differential input for the specified channel.
*
* \param p_adc Pointer to an ADC instance.
* \param channel ADC channel number.
*/
void adc_enable_channel_differential_input(Adc *p_adc, const enum adc_channel_num_t channel)
{
p_adc->ADC_COR |= 0x01u << (16 + channel);
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3XA_SERIES
/**
* \brief Disable differential input for the specified channel.
*
* \param p_adc Pointer to an ADC instance.
* \param channel ADC channel number.
*/
void adc_disable_channel_differential_input(Adc *p_adc, const enum adc_channel_num_t channel)
{
uint32_t ul_temp;
ul_temp = p_adc->ADC_COR;
p_adc->ADC_COR &= 0xfffeffffu << channel;
p_adc->ADC_COR |= ul_temp;
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3XA_SERIES
/**
* \brief Enable analog signal offset for the specified channel.
*
* \param p_adc Pointer to an ADC instance.
* \param channel ADC channel number.
*/
void adc_enable_channel_input_offset(Adc *p_adc, const enum adc_channel_num_t channel)
{
p_adc->ADC_COR |= 0x01u << channel;
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3XA_SERIES
/**
* \brief Disable analog signal offset for the specified channel.
*
* \param p_adc Pointer to an ADC instance.
* \param channel ADC channel number.
*/
void adc_disable_channel_input_offset(Adc *p_adc, const enum adc_channel_num_t channel)
{
uint32_t ul_temp;
ul_temp = p_adc->ADC_COR;
p_adc->ADC_COR &= (0xfffffffeu << channel);
p_adc->ADC_COR |= ul_temp;
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3XA_SERIES
/**
* \brief Configure input gain for the specified channel.
*
* \param p_adc Pointer to an ADC instance.
* \param channel ADC channel number.
* \param gain Gain value for the input.
*/
void adc_set_channel_input_gain(Adc *p_adc, const enum adc_channel_num_t channel,
const enum adc_gainvalue_t gain)
{
p_adc->ADC_CGR |= (0x03u << (2 * channel)) & (gain << (2 * channel));
}
#endif
#if SAM3SD8_SERIES || SAM4S_SERIES
/**
* \brief Set ADC auto calibration mode.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc_set_calibmode(Adc * p_adc)
{
p_adc->ADC_CR |= ADC_CR_AUTOCAL;
}
#endif
/**
* \brief Return the actual ADC clock.
*
* \param p_adc Pointer to an ADC instance.
* \param ul_mck Main clock of the device (in Hz).
*
* \return The actual ADC clock (in Hz).
*/
uint32_t adc_get_actual_adc_clock(const Adc *p_adc, const uint32_t ul_mck)
{
uint32_t ul_adcfreq;
uint32_t ul_prescal;
/* ADCClock = MCK / ( (PRESCAL+1) * 2 ) */
ul_prescal = ((p_adc->ADC_MR & ADC_MR_PRESCAL_Msk) >> ADC_MR_PRESCAL_Pos);
ul_adcfreq = ul_mck / ((ul_prescal + 1) * 2);
return ul_adcfreq;
}
/**
* \brief Enable ADC interrupts.
*
* \param p_adc Pointer to an ADC instance.
* \param ul_source Interrupts to be enabled.
*/
void adc_enable_interrupt(Adc *p_adc, const uint32_t ul_source)
{
p_adc->ADC_IER = ul_source;
}
/**
* \brief Disable ADC interrupts.
*
* \param p_adc Pointer to an ADC instance.
* \param ul_source Interrupts to be disabled.
*/
void adc_disable_interrupt(Adc *p_adc, const uint32_t ul_source)
{
p_adc->ADC_IDR = ul_source;
}
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
/**
* \brief Get ADC interrupt and overrun error status.
*
* \param p_adc Pointer to an ADC instance.
*
* \return ADC status structure.
*/
uint32_t adc_get_status(const Adc *p_adc)
{
return p_adc->ADC_ISR;
}
/**
* \brief Get ADC interrupt and overrun error status.
*
* \param p_adc Pointer to an ADC instance.
*
* \return ADC status structure.
*/
uint32_t adc_get_overrun_status(const Adc *p_adc)
{
return p_adc->ADC_OVER;
}
#elif SAM3U_SERIES
/**
* \brief Read ADC interrupt and overrun error status.
*
* \param p_adc Pointer to an ADC instance.
*
* \retval ADC status structure.
*/
uint32_t adc_get_status(const Adc *p_adc)
{
return p_adc->ADC_SR;
}
#endif
/**
* \brief Read ADC interrupt mask.
*
* \param p_adc Pointer to an ADC instance.
*
* \return The interrupt mask value.
*/
uint32_t adc_get_interrupt_mask(const Adc *p_adc)
{
return p_adc->ADC_IMR;
}
#if SAM3S_SERIES || SAM4S_SERIES || SAM3XA_SERIES
/**
* \brief Adapt performance versus power consumption.
*
* \note Please refer to ADC Characteristics in the product datasheet
* for more details.
*
* \param p_adc Pointer to an ADC instance.
* \param ibctl ADC Bias current control.
*/
void adc_set_bias_current(Adc *p_adc, const uint8_t uc_ibctl)
{
p_adc->ADC_ACR |= ADC_ACR_IBCTL(uc_ibctl);
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3XA_SERIES
/**
* \brief Turn on temperature sensor.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc_enable_ts(Adc *p_adc)
{
p_adc->ADC_ACR |= ADC_ACR_TSON;
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3XA_SERIES
/**
* \brief Turn off temperature sensor.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc_disable_ts(Adc *p_adc)
{
p_adc->ADC_ACR &= ~ADC_ACR_TSON;
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
/**
* \brief Enable or disable write protection of ADC registers.
*
* \param p_adc Pointer to an ADC instance.
* \param ul_enable 1 to enable, 0 to disable.
*/
void adc_set_writeprotect(Adc *p_adc, const uint32_t ul_enable)
{
p_adc->ADC_WPMR |= ADC_WPMR_WPKEY(ul_enable);
}
#endif
#if SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3XA_SERIES
/**
* \brief Indicate write protect status.
*
* \param p_adc Pointer to an ADC instance.
*
* \return 0 if the peripheral is not protected, or 16-bit write protect
* violation Status.
*/
uint32_t adc_get_writeprotect_status(const Adc *p_adc)
{
return p_adc->ADC_WPSR & ADC_WPSR_WPVS;
}
#endif
#if 0
/**
* \brief calcul_startup
*/
static uint32_t calcul_startup(const uint32_t ul_startup)
{
uint32_t ul_startup_value = 0;
if (ul_startup == 0)
ul_startup_value = 0;
else if (ul_startup == 1)
ul_startup_value = 8;
else if (ul_startup == 2)
ul_startup_value = 16;
else if (ul_startup == 3)
ul_startup_value = 24;
else if (ul_startup == 4)
ul_startup_value = 64;
else if (ul_startup == 5)
ul_startup_value = 80;
else if (ul_startup == 6)
ul_startup_value = 96;
else if (ul_startup == 7)
ul_startup_value = 112;
else if (ul_startup == 8)
ul_startup_value = 512;
else if (ul_startup == 9)
ul_startup_value = 576;
else if (ul_startup == 10)
ul_startup_value = 640;
else if (ul_startup == 11)
ul_startup_value = 704;
else if (ul_startup == 12)
ul_startup_value = 768;
else if (ul_startup == 13)
ul_startup_value = 832;
else if (ul_startup == 14)
ul_startup_value = 896;
else if (ul_startup == 15)
ul_startup_value = 960;
return ul_startup_value;
}
/**
* \brief Check ADC configurations.
*
* \param p_adc Pointer to an ADC instance.
* \param ul_mck Main clock of the device (in Hz).
*/
void adc_check(Adc *p_adc, const uint32_t ul_mck)
{
uint32_t ul_adcfreq;
uint32_t ul_prescal;
uint32_t ul_startup;
/* ADCClock = MCK / ( (PRESCAL+1) * 2 ) */
ul_prescal = ((p_adc->ADC_MR & ADC_MR_PRESCAL_Msk) >>
ADC_MR_PRESCAL_Pos);
ul_adcfreq = ul_mck / ((ul_prescal + 1) * 2);
printf("ADC clock frequency = %d Hz\r\n", (int)ul_adcfreq);
if (ul_adcfreq < ADC_FREQ_MIN) {
printf("adc frequency too low (out of specification: %d Hz)\r\n",
(int)ADC_FREQ_MIN);
}
if (ul_adcfreq > ADC_FREQ_MAX) {
printf("adc frequency too high (out of specification: %d Hz)\r\n",
(int)ADC_FREQ_MAX);
}
ul_startup = ((p_adc->ADC_MR & ADC_MR_STARTUP_Msk) >>
ADC_MR_STARTUP_Pos);
if (!(p_adc->ADC_MR & ADC_MR_SLEEP_SLEEP)) {
/* 40ms */
if (ADC_STARTUP_NORM * ul_adcfreq / 1000000 >
calcul_startup(ul_startup)) {
printf("Startup time too small: %d, programmed: %d\r\n",
(int)(ADC_STARTUP_NORM * ul_adcfreq /
1000000),
(int)calcul_startup(ul_startup));
}
} else {
if (p_adc->ADC_MR & ADC_MR_FREERUN_ON) {
puts("FreeRun forbidden in sleep mode\r");
}
if (!(p_adc->ADC_MR & ADC_MR_FWUP_ON)) {
/* Sleep 40ms */
if (ADC_STARTUP_NORM * ul_adcfreq / 1000000 >
calcul_startup(ul_startup)) {
printf("Startup time too small: %d, programmed: %d\r\n",
(int)(ADC_STARTUP_NORM * ul_adcfreq / 1000000),
(int)(calcul_startup(ul_startup)));
}
} else {
if (p_adc->ADC_MR & ADC_MR_FWUP_ON) {
/* Fast Wake Up Sleep Mode: 12ms */
if (ADC_STARTUP_FAST * ul_adcfreq / 1000000 >
calcul_startup(ul_startup)) {
printf("Startup time too small: %d, programmed: %d\r\n",
(int)(ADC_STARTUP_NORM * ul_adcfreq / 1000000),
(int)(calcul_startup(ul_startup)));
}
}
}
}
}
#endif
/**
* \brief Get PDC registers base address.
*
* \param p_adc Pointer to an ADC instance.
*
* \return ADC PDC register base address.
*/
Pdc *adc_get_pdc_base(const Adc *p_adc)
{
return PDC_ADC;
}
//@}
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond

View File

@@ -0,0 +1,399 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#include "../chip.h"
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
/**
* \defgroup sam_drivers_adc_group Analog-to-digital Converter (ADC)
*
* Driver for the Analog-to-digital Converter. This driver provides access to the main
* features of the ADC controller.
*
* @{
*/
#if SAM3U_SERIES
/**
* \brief Initialize the given ADC with the specified ADC clock and startup time.
*
* \param p_adc Pointer to an ADC instance.
* \param ul_mck Main clock of the device (in Hz).
* \param ul_adc_clock Analog-to-Digital conversion clock (in Hz).
* \param ul_startuptime ADC startup time value (value in us).
* Please refer to the product datasheet for more details.
* \param ul_offmode_startuptime ADC off mode startup time value (value in us).
* Please refer to the product datasheet for more details.
*
* \return 0 on success.
*/
uint32_t adc12b_init(Adc12b *p_adc, const uint32_t ul_mck, const uint32_t ul_adc_clock,
const uint32_t ul_startuptime, const uint32_t ul_offmode_startuptime)
{
uint32_t ul_prescal, ul_startup, ul_offmode;
p_adc->ADC12B_CR = ADC12B_CR_SWRST;
/* Reset Mode Register */
p_adc->ADC12B_MR = 0;
/* Reset PDC transfer */
p_adc->ADC12B_PTCR = (ADC12B_PTCR_RXTDIS | ADC12B_PTCR_TXTDIS);
p_adc->ADC12B_RCR = 0;
p_adc->ADC12B_RNCR = 0;
ul_prescal = ul_mck / (2 * ul_adc_clock) - 1;
ul_startup = ((ul_adc_clock / 1000000) * ul_startuptime / 8) - 1;
ul_offmode = ((ul_adc_clock / 1000000) * ul_offmode_startuptime / 8) -
1;
p_adc->ADC12B_MR |=
ADC12B_MR_PRESCAL(ul_prescal) | ((ul_startup <<
ADC12B_MR_STARTUP_Pos) &
ADC12B_MR_STARTUP_Msk);
p_adc->ADC12B_EMR |= (ul_offmode << 16) & (0xffu << 16);
return 0;
}
/**
* \brief Configure conversion resolution.
*
* \param p_adc Pointer to an ADC instance.
* \param resolution ADC resolution.
*/
void adc12b_set_resolution(Adc12b *p_adc, const enum adc_resolution_t resolution)
{
p_adc->ADC12B_MR |= (resolution << 4) & ADC12B_MR_LOWRES;
}
/**
* \brief Configure conversion trigger and free run mode.
*
* \param p_adc Pointer to an ADC instance.
* \param trigger Conversion trigger.
*/
void adc12b_configure_trigger(Adc12b *p_adc, const enum adc_trigger_t trigger)
{
p_adc->ADC12B_MR |= trigger;
}
/**
* \brief Configure ADC power saving mode.
*
* \param p_adc Pointer to an ADC instance.
* \param uc_sleep ADC_MR_SLEEP_NORMAL keeps the ADC Core and reference
* voltage circuitry ON between conversions.
* ADC_MR_SLEEP_SLEEP keeps the ADC Core and reference voltage circuitry
* OFF between conversions.
* \param uc_offmode 0 Standby Mode (if Sleep Bit = 1), 1 Off Mode.
*/
void adc12b_configure_power_save(Adc12b *p_adc, const uint8_t uc_sleep,
uint8_t uc_offmode)
{
p_adc->ADC12B_MR |= ((uc_sleep << 5) & ADC12B_MR_SLEEP);
p_adc->ADC12B_EMR |= uc_offmode;
}
/**
* \brief Configure ADC timing.
*
* \param p_adc Pointer to an ADC instance.
* \param ul_sh ADC sample and hold time = uc_sh / ADC clock.
*/
void adc12b_configure_timing(Adc12b *p_adc, const uint32_t ul_sh)
{
p_adc->ADC12B_MR |= ADC12B_MR_SHTIM(ul_sh);
}
/**
* \brief Start ADC conversion.
*
* \note If one of the hardware event is selected as ADC trigger,
* this function can NOT start ADC conversion.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc12b_start(Adc12b *p_adc)
{
p_adc->ADC12B_CR = ADC12B_CR_START;
}
/**
* \brief Stop ADC conversion.
* \param p_adc Pointer to an ADC instance.
*/
void adc12b_stop(Adc12b *p_adc)
{
p_adc->ADC12B_CR = ADC12B_CR_SWRST;
}
/**
* \brief Enable the specified ADC channel.
*
* \param p_adc Pointer to an ADC instance.
* \param adc_ch ADC channel number.
*/
void adc12b_enable_channel(Adc12b *p_adc, const enum adc_channel_num_t adc_ch)
{
p_adc->ADC12B_CHER = 1 << adc_ch;
}
/**
* \brief Enable all ADC channels.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc12b_enable_all_channel(Adc12b *p_adc)
{
p_adc->ADC12B_CHER = 0xFF;
}
/**
* \brief Disable the specified ADC channel.
*
* \param p_adc Pointer to an ADC instance.
* \param adc_ch ADC channel number.
*/
void adc12b_disable_channel(Adc12b *p_adc, const enum adc_channel_num_t adc_ch)
{
p_adc->ADC12B_CHDR = 1 << adc_ch;
}
/**
* \brief Disable all ADC channel.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc12b_disable_all_channel(Adc12b *p_adc)
{
p_adc->ADC12B_CHDR = 0xFF;
}
/**
* \brief Read the ADC channel status.
*
* \param p_adc Pointer to an ADC instance.
* \param adc_ch ADC channel number.
*
* \retval 1 if channel is enabled.
* \retval 0 if channel is disabled.
*/
uint32_t adc12b_get_channel_status(const Adc12b *p_adc, const enum adc_channel_num_t adc_ch)
{
return p_adc->ADC12B_CHSR & (1 << adc_ch);
}
/**
* \brief Read the ADC result data of the specified channel.
*
* \param p_adc Pointer to an ADC instance.
* \param adc_ch ADC channel number.
*
* \return ADC value of the specified channel.
*/
uint32_t adc12b_get_channel_value(const Adc12b *p_adc,const enum adc_channel_num_t adc_ch)
{
uint32_t dwData = 0;
if (15 >= adc_ch) {
dwData = *(p_adc->ADC12B_CDR + adc_ch);
}
return dwData;
}
/**
* \brief Read the last ADC result data.
*
* \param p_adc Pointer to an ADC instance.
*
* \return ADC latest value.
*/
uint32_t adc12b_get_latest_value(const Adc12b *p_adc)
{
return p_adc->ADC12B_LCDR;
}
/**
* \brief Enable differential input for all channels.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc12b_enable_differential_input(Adc12b *p_adc)
{
p_adc->ADC12B_ACR |= (0x01u << 16);
}
/**
* \brief Disable differential input for the specified channel.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc12b_disable_differential_input(Adc12b *p_adc)
{
p_adc->ADC12B_ACR &= (0x01u << 16);
}
/**
* \brief Enable analog signal offset for the specified channel.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc12b_enable_input_offset(Adc12b *p_adc)
{
p_adc->ADC12B_ACR |= (0x01u << 17);
}
/**
* \brief Disable analog signal offset for the specified channel.
*
* \param p_adc Pointer to an ADC instance.
*/
void adc12b_disable_input_offset(Adc12b *p_adc)
{
p_adc->ADC12B_ACR &= (0x01u << 17);
}
/**
* \brief Configure input gain for the specified channel.
*
* \param p_adc Pointer to an ADC instance.
* \param gain Gain value for the input.
*/
void adc12b_set_input_gain(Adc12b *p_adc, const enum adc_gainvalue_t gain)
{
p_adc->ADC12B_ACR |= (0x03u & gain);
}
/**
* \brief Return the actual ADC clock.
*
* \param p_adc Pointer to an ADC instance.
* \param ul_mck Main clock of the device (in Hz).
*
* \retval 0 The actual ADC clock (in Hz).
*/
uint32_t adc12b_get_actual_adc_clock(const Adc12b *p_adc, const uint32_t ul_mck)
{
uint32_t ul_adcfreq;
uint32_t ul_prescal;
/* ADCClock = MCK / ( (PRESCAL+1) * 2 ) */
ul_prescal = ((p_adc->ADC12B_MR & ADC12B_MR_PRESCAL_Msk) >>
ADC12B_MR_PRESCAL_Pos);
ul_adcfreq = ul_mck / ((ul_prescal + 1) * 2);
return ul_adcfreq;
}
/**
* \brief Enable ADC interrupts.
*
* \param p_adc Pointer to an ADC instance.
* \param ul_source Interrupts to be enabled.
*/
void adc12b_enable_interrupt(Adc12b *p_adc, const uint32_t ul_source)
{
p_adc->ADC12B_IER = ul_source;
}
/**
* \brief Disable ADC interrupts.
*
* \param p_adc Pointer to an ADC instance.
* \param ul_source Interrupts to be disabled.
*/
void adc12b_disable_interrupt(Adc12b *p_adc, const uint32_t ul_source)
{
p_adc->ADC12B_IDR = ul_source;
}
/** \brief Read ADC interrupt mask.
*
* \param p_adc Pointer to an ADC instance.
*
* \return The interrupt mask value.
*/
uint32_t adc12b_get_interrupt_mask(const Adc12b *p_adc)
{
return p_adc->ADC12B_IMR;
}
/**
* \brief Read ADC interrupt status.
*
* \param p_adc Pointer to an ADC instance.
*
* \retval ADC interrupt status.
*/
uint32_t adc12b_get_status(const Adc12b *p_adc)
{
return p_adc->ADC12B_SR;
}
/**
* \brief Adapt performance versus power consumption.
*
* \note Please refer to ADC Characteristics in the product datasheet
* for more details.
*
* \param p_adc Pointer to an ADC instance.
* \param uc_ibctl ADC Bias current control.
*/
void adc12b_set_bias_current(Adc12b *p_adc, const uint8_t uc_ibctl)
{
p_adc->ADC12B_ACR |= ADC12B_ACR_IBCTL(uc_ibctl);
}
/**
* \brief Get PDC registers base address.
*
* \param p_adc Pointer to an ADC instance.
*
* \return ADC PDC register base address.
*/
Pdc *adc12b_get_pdc_base(const Adc12b *p_adc)
{
return PDC_ADC12B;
}
#endif // SAM3U_SERIES
//@}
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond

View File

@@ -0,0 +1,804 @@
/**
* \file
*
* \brief Controller Area Network (CAN) driver module for SAM.
*
* Copyright (c) 2011 - 2012 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* 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.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* 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.
*
* \asf_license_stop
*
*/
#include "../chip.h"
#include <string.h>
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
#if SAM3XA_SERIES
/** Define the timemark mask. */
#define TIMEMARK_MASK 0x0000ffff
/* CAN timeout for synchronization. */
#define CAN_TIMEOUT 100000
/** The max value for CAN baudrate prescale. */
#define CAN_BAUDRATE_MAX_DIV 128
/** Define the scope for TQ. */
#define CAN_MIN_TQ_NUM 8
#define CAN_MAX_TQ_NUM 25
/** Define the fixed bit time value. */
#define CAN_BIT_SYNC 1
#define CAN_BIT_IPT 2
typedef struct {
uint8_t uc_tq; //! CAN_BIT_SYNC + uc_prog + uc_phase1 + uc_phase2 = uc_tq, 8 <= uc_tq <= 25.
uint8_t uc_prog; //! Propagation segment, (3-bits + 1), 1~8;
uint8_t uc_phase1; //! Phase segment 1, (3-bits + 1), 1~8;
uint8_t uc_phase2; //! Phase segment 2, (3-bits + 1), 1~8, CAN_BIT_IPT <= uc_phase2;
uint8_t uc_sjw; //! Resynchronization jump width, (2-bits + 1), min(uc_phase1, 4);
uint8_t uc_sp; //! Sample point value, 0~100 in percent.
} can_bit_timing_t;
/** Values of bit time register for different baudrates, Sample point = ((1 + uc_prog + uc_phase1) / uc_tq) * 100%. */
const can_bit_timing_t can_bit_time[] = {
{8, (2 + 1), (1 + 1), (1 + 1), (2 + 1), 75},
{9, (1 + 1), (2 + 1), (2 + 1), (1 + 1), 67},
{10, (2 + 1), (2 + 1), (2 + 1), (2 + 1), 70},
{11, (3 + 1), (2 + 1), (2 + 1), (3 + 1), 72},
{12, (2 + 1), (3 + 1), (3 + 1), (3 + 1), 67},
{13, (3 + 1), (3 + 1), (3 + 1), (3 + 1), 77},
{14, (3 + 1), (3 + 1), (4 + 1), (3 + 1), 64},
{15, (3 + 1), (4 + 1), (4 + 1), (3 + 1), 67},
{16, (4 + 1), (4 + 1), (4 + 1), (3 + 1), 69},
{17, (5 + 1), (4 + 1), (4 + 1), (3 + 1), 71},
{18, (4 + 1), (5 + 1), (5 + 1), (3 + 1), 67},
{19, (5 + 1), (5 + 1), (5 + 1), (3 + 1), 68},
{20, (6 + 1), (5 + 1), (5 + 1), (3 + 1), 70},
{21, (7 + 1), (5 + 1), (5 + 1), (3 + 1), 71},
{22, (6 + 1), (6 + 1), (6 + 1), (3 + 1), 68},
{23, (7 + 1), (7 + 1), (6 + 1), (3 + 1), 70},
{24, (6 + 1), (7 + 1), (7 + 1), (3 + 1), 67},
{25, (7 + 1), (7 + 1), (7 + 1), (3 + 1), 68}
};
/**
* \brief Configure CAN baudrate.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param ul_mck The input main clock for the CAN module.
* \param ul_baudrate Baudrate value (kB/s), allowed values:
* 1000, 800, 500, 250, 125, 50, 25, 10, 5.
*
* \retval Set the baudrate successfully or not.
*/
static uint32_t can_set_baudrate(Can *p_can, uint32_t ul_mck, uint32_t ul_baudrate)
{
uint8_t uc_tq;
uint8_t uc_prescale;
uint32_t ul_mod;
uint32_t ul_cur_mod;
can_bit_timing_t *p_bit_time;
/* Check whether the baudrate prescale will be greater than the max divide value. */
if (((ul_mck + (ul_baudrate * CAN_MAX_TQ_NUM * 1000 - 1)) /
(ul_baudrate * CAN_MAX_TQ_NUM * 1000)) > CAN_BAUDRATE_MAX_DIV) {
return 0;
}
/* Check whether the input MCK is too small. */
if (ul_mck < ul_baudrate * CAN_MIN_TQ_NUM * 1000) {
return 0;
}
/* Initialize it as the minimum Time Quantum. */
uc_tq = CAN_MIN_TQ_NUM;
/* Initialize the remainder as the max value. When the remainder is 0, get the right TQ number. */
ul_mod = 0xffffffff;
/* Find out the approximate Time Quantum according to the baudrate. */
for (uint8_t i = CAN_MIN_TQ_NUM; i <= CAN_MAX_TQ_NUM; i++) {
if ((ul_mck / (ul_baudrate * i * 1000)) <= CAN_BAUDRATE_MAX_DIV) {
ul_cur_mod = ul_mck % (ul_baudrate * i * 1000);
if (ul_cur_mod < ul_mod){
ul_mod = ul_cur_mod;
uc_tq = i;
if (!ul_mod) {
break;
}
}
}
}
/* Calculate the baudrate prescale value. */
uc_prescale = ul_mck / (ul_baudrate * uc_tq * 1000);
/* Get the right CAN BIT Timing group. */
p_bit_time = (can_bit_timing_t *)&can_bit_time[uc_tq - CAN_MIN_TQ_NUM];
/* Before modifying the CANBR register, disable the CAN controller. */
can_disable(p_can);
/* Write into the CAN baudrate register. */
p_can->CAN_BR = CAN_BR_PHASE2(p_bit_time->uc_phase2 - 1) |
CAN_BR_PHASE1(p_bit_time->uc_phase1 - 1) |
CAN_BR_PROPAG(p_bit_time->uc_prog - 1) |
CAN_BR_SJW(p_bit_time->uc_sjw - 1) |
CAN_BR_BRP(uc_prescale - 1);
return 1;
}
/**
* \brief Initialize CAN controller.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param ul_mck CAN module input clock.
* \param ul_baudrate CAN communication baudrate in kbs.
*
* \retval 0 If failed to initialize the CAN module; otherwise successful.
*
* \note PMC clock for CAN peripheral should be enabled before calling this function.
*/
uint32_t can_init(Can *p_can, uint32_t ul_mck, uint32_t ul_baudrate)
{
uint32_t ul_flag;
uint32_t ul_tick;
/* Initialize the baudrate for CAN module. */
ul_flag = can_set_baudrate(p_can, ul_mck, ul_baudrate);
if (ul_flag == 0) {
return 0;
}
/* Reset the CAN eight message mailbox. */
can_reset_all_mailbox(p_can);
/* Enable the CAN controller. */
can_enable(p_can);
/* Wait until the CAN is synchronized with the bus activity. */
ul_flag = 0;
ul_tick = 0;
while (!(ul_flag & CAN_SR_WAKEUP) && (ul_tick < CAN_TIMEOUT)) {
ul_flag = can_get_status(p_can);
ul_tick++;
}
/* Timeout or the CAN module has been synchronized with the bus. */
if (CAN_TIMEOUT == ul_tick) {
return 0;
} else {
return 1;
}
}
/**
* \brief Enable CAN Controller.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void can_enable(Can *p_can)
{
p_can->CAN_MR |= CAN_MR_CANEN;
}
/**
* \brief Disable CAN Controller.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void can_disable(Can *p_can)
{
p_can->CAN_MR &= ~CAN_MR_CANEN;
}
/**
* \brief Disable CAN Controller low power mode.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void can_disable_low_power_mode(Can *p_can)
{
p_can->CAN_MR &= ~CAN_MR_LPM;
}
/**
* \brief Enable CAN Controller low power mode.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void can_enable_low_power_mode(Can *p_can)
{
p_can->CAN_MR |= CAN_MR_LPM;
}
/**
* \brief Disable CAN Controller autobaud/listen mode.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void can_disable_autobaud_listen_mode(Can *p_can)
{
p_can->CAN_MR &= ~CAN_MR_ABM;
}
/**
* \brief Enable CAN Controller autobaud/listen mode.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void can_enable_autobaud_listen_mode(Can *p_can)
{
p_can->CAN_MR |= CAN_MR_ABM;
}
/**
* \brief CAN Controller won't generate overload frame.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void can_disable_overload_frame(Can *p_can)
{
p_can->CAN_MR &= ~CAN_MR_OVL;
}
/**
* \brief CAN Controller will generate an overload frame after each successful
* reception for mailboxes configured in Receive mode, Producer and Consumer.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void can_enable_overload_frame(Can *p_can)
{
p_can->CAN_MR |= CAN_MR_OVL;
}
/**
* \brief Configure the timestamp capture point, at the start or the end of frame.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param ul_flag 0: Timestamp is captured at each start of frame;
* 1: Timestamp is captured at each end of frame.
*/
void can_set_timestamp_capture_point(Can *p_can, uint32_t ul_flag)
{
if (ul_flag) {
p_can->CAN_MR |= CAN_MR_TEOF;
} else {
p_can->CAN_MR &= ~CAN_MR_TEOF;
}
}
/**
* \brief Disable CAN Controller time triggered mode.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void can_disable_time_triggered_mode(Can *p_can)
{
p_can->CAN_MR &= ~CAN_MR_TTM;
}
/**
* \brief Enable CAN Controller time triggered mode.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void can_enable_time_triggered_mode(Can *p_can)
{
p_can->CAN_MR |= CAN_MR_TTM;
}
/**
* \brief Disable CAN Controller timer freeze.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void can_disable_timer_freeze(Can *p_can)
{
p_can->CAN_MR &= ~CAN_MR_TIMFRZ;
}
/**
* \brief Enable CAN Controller timer freeze.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void can_enable_timer_freeze(Can *p_can)
{
p_can->CAN_MR |= CAN_MR_TIMFRZ;
}
/**
* \brief Disable CAN Controller transmit repeat function.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void can_disable_tx_repeat(Can *p_can)
{
p_can->CAN_MR |= CAN_MR_DRPT;
}
/**
* \brief Enable CAN Controller transmit repeat function.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void can_enable_tx_repeat(Can *p_can)
{
p_can->CAN_MR &= ~CAN_MR_DRPT;
}
/**
* \brief Configure CAN Controller reception synchronization stage.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param ul_stage The reception stage to be configured.
*
* \note This is just for debug purpose only.
*/
void can_set_rx_sync_stage(Can *p_can, uint32_t ul_stage)
{
p_can->CAN_MR = (p_can->CAN_MR & ~CAN_MR_RXSYNC_Msk) | ul_stage;
}
/**
* \brief Enable CAN interrupt.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param dw_mask Interrupt to be enabled.
*/
void can_enable_interrupt(Can *p_can, uint32_t dw_mask)
{
p_can->CAN_IER = dw_mask;
}
/**
* \brief Disable CAN interrupt.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param dw_mask Interrupt to be disabled.
*/
void can_disable_interrupt(Can *p_can, uint32_t dw_mask)
{
p_can->CAN_IDR = dw_mask;
}
/**
* \brief Get CAN Interrupt Mask.
*
* \param p_can Pointer to a CAN peripheral instance.
*
* \retval CAN interrupt mask.
*/
uint32_t can_get_interrupt_mask(Can *p_can)
{
return (p_can->CAN_IMR);
}
/**
* \brief Get CAN status.
*
* \param p_can Pointer to a CAN peripheral instance.
*
* \retval CAN status.
*/
uint32_t can_get_status(Can *p_can)
{
return (p_can->CAN_SR);
}
/**
* \brief Get the 16-bit free-running internal timer count.
*
* \param p_can Pointer to a CAN peripheral instance.
*
* \retval The internal CAN free-running timer counter.
*/
uint32_t can_get_internal_timer_value(Can *p_can)
{
return (p_can->CAN_TIM);
}
/**
* \brief Get CAN timestamp register value.
*
* \param p_can Pointer to a CAN peripheral instance.
*
* \retval The timestamp value.
*/
uint32_t can_get_timestamp_value(Can *p_can)
{
return (p_can->CAN_TIMESTP);
}
/**
* \brief Get CAN transmit error counter.
*
* \param p_can Pointer to a CAN peripheral instance.
*
* \retval Transmit error counter.
*/
uint8_t can_get_tx_error_cnt(Can *p_can)
{
return (uint8_t) (p_can->CAN_ECR >> CAN_ECR_TEC_Pos);
}
/**
* \brief Get CAN receive error counter.
*
* \param p_can Pointer to a CAN peripheral instance.
*
* \retval Receive error counter.
*/
uint8_t can_get_rx_error_cnt(Can *p_can)
{
return (uint8_t) (p_can->CAN_ECR >> CAN_ECR_REC_Pos);
}
/**
* \brief Reset the internal free-running 16-bit timer.
*
* \param p_can Pointer to a CAN peripheral instance.
*
* \note If the internal timer counter is frozen, this function automatically
* re-enables it.
*/
void can_reset_internal_timer(Can *p_can)
{
p_can->CAN_TCR |= CAN_TCR_TIMRST;
}
/**
* \brief Send global transfer request.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param uc_mask Mask for mailboxes that are requested to transfer.
*/
void can_global_send_transfer_cmd(Can *p_can, uint8_t uc_mask)
{
uint32_t ul_reg;
ul_reg = p_can->CAN_TCR & ((uint32_t)~GLOBAL_MAILBOX_MASK);
p_can->CAN_TCR = ul_reg | uc_mask;
}
/**
* \brief Send global abort request.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param uc_mask Mask for mailboxes that are requested to abort.
*/
void can_global_send_abort_cmd(Can *p_can, uint8_t uc_mask)
{
uint32_t ul_reg;
ul_reg = p_can->CAN_ACR & ((uint32_t)~GLOBAL_MAILBOX_MASK);
p_can->CAN_ACR = ul_reg | uc_mask;
}
/**
* \brief Configure the timemark for the mailbox.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param uc_index Indicate which mailbox is to be configured.
* \param us_cnt The timemark to be set.
*
* \note The timemark is active in Time Triggered mode only.
*/
void can_mailbox_set_timemark(Can *p_can, uint8_t uc_index, uint16_t us_cnt)
{
uint32_t ul_reg;
ul_reg = p_can->CAN_MB[uc_index].CAN_MMR & ((uint32_t)~TIMEMARK_MASK);
p_can->CAN_MB[uc_index].CAN_MMR = ul_reg | us_cnt;
}
/**
* \brief Get status of the mailbox.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param uc_index Indicate which mailbox is to be read.
*
* \retval The mailbox status.
*/
uint32_t can_mailbox_get_status(Can *p_can, uint8_t uc_index)
{
return (p_can->CAN_MB[uc_index].CAN_MSR);
}
/**
* \brief Send single mailbox transfer request.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param uc_index Indicate which mailbox is to be configured.
*/
void can_mailbox_send_transfer_cmd(Can *p_can, uint8_t uc_index)
{
p_can->CAN_MB[uc_index].CAN_MCR |= CAN_MCR_MTCR;
}
/**
* \brief Send single mailbox abort request.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param uc_index Indicate which mailbox is to be configured.
*/
void can_mailbox_send_abort_cmd(Can *p_can, uint8_t uc_index)
{
p_can->CAN_MB[uc_index].CAN_MCR |= CAN_MCR_MACR;
}
/**
* \brief Initialize the mailbox in different mode and set up related configuration.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param p_mailbox Pointer to a CAN mailbox instance.
*/
void can_mailbox_init(Can *p_can, can_mb_conf_t *p_mailbox)
{
uint8_t uc_index;
uc_index = (uint8_t)p_mailbox->ul_mb_idx;
/* Check the object type of the mailbox. If it's used to disable the mailbox, reset the whole mailbox. */
if (!p_mailbox->uc_obj_type) {
p_can->CAN_MB[uc_index].CAN_MMR = 0;
p_can->CAN_MB[uc_index].CAN_MAM = 0;
p_can->CAN_MB[uc_index].CAN_MID = 0;
p_can->CAN_MB[uc_index].CAN_MDL = 0;
p_can->CAN_MB[uc_index].CAN_MDH = 0;
p_can->CAN_MB[uc_index].CAN_MCR = 0;
return;
}
/* Set the priority in Transmit mode. */
p_can->CAN_MB[uc_index].CAN_MMR = (p_can->CAN_MB[uc_index].CAN_MMR &
~CAN_MMR_PRIOR_Msk) | (p_mailbox-> uc_tx_prio << CAN_MMR_PRIOR_Pos);
/* Set the message ID and message acceptance mask for the mailbox in other modes. */
if (p_mailbox->uc_id_ver) {
p_can->CAN_MB[uc_index].CAN_MAM = p_mailbox->ul_id_msk | CAN_MAM_MIDE;
p_can->CAN_MB[uc_index].CAN_MID = p_mailbox->ul_id | CAN_MAM_MIDE;
} else {
p_can->CAN_MB[uc_index].CAN_MAM = p_mailbox->ul_id_msk;
p_can->CAN_MB[uc_index].CAN_MID = p_mailbox->ul_id;
}
/* Set up mailbox in one of the five different modes. */
p_can->CAN_MB[uc_index].CAN_MMR = (p_can->CAN_MB[uc_index].CAN_MMR &
~CAN_MMR_MOT_Msk) | (p_mailbox-> uc_obj_type << CAN_MMR_MOT_Pos);
}
/**
* \brief Read receive information for the mailbox.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param p_mailbox Pointer to a CAN mailbox instance.
*
* \retval Different CAN mailbox transfer status.
*
* \note Read the mailbox status before calling this function.
*/
uint32_t can_mailbox_read(Can *p_can, can_mb_conf_t *p_mailbox)
{
uint32_t ul_status;
uint8_t uc_index;
uint32_t ul_retval;
ul_retval = 0;
uc_index = (uint8_t)p_mailbox->ul_mb_idx;
ul_status = p_mailbox->ul_status;
/* Check whether there is overwriting happening in Receive with Overwrite mode,
or there're messages lost in Receive mode. */
if ((ul_status & CAN_MSR_MRDY) && (ul_status & CAN_MSR_MMI)) {
ul_retval = CAN_MAILBOX_RX_OVER;
}
/* Read the message family ID. */
p_mailbox->ul_fid = p_can->CAN_MB[uc_index].CAN_MFID & CAN_MFID_MFID_Msk;
/* Read received data length. */
p_mailbox->uc_length = (ul_status & CAN_MSR_MDLC_Msk) >> CAN_MSR_MDLC_Pos;
/* Read received data. */
p_mailbox->ul_datal = p_can->CAN_MB[uc_index].CAN_MDL;
if (p_mailbox->uc_length > 4) {
p_mailbox->ul_datah = p_can->CAN_MB[uc_index].CAN_MDH;
}
/* Read the mailbox status again to check whether the software needs to re-read mailbox data register. */
p_mailbox->ul_status = p_can->CAN_MB[uc_index].CAN_MSR;
ul_status = p_mailbox->ul_status;
if (ul_status & CAN_MSR_MMI) {
ul_retval |= CAN_MAILBOX_RX_NEED_RD_AGAIN;
} else {
ul_retval |= CAN_MAILBOX_TRANSFER_OK;
}
/* Enable next receive process. */
can_mailbox_send_transfer_cmd(p_can, uc_index);
return ul_retval;
}
/**
* \brief Prepare transmit information and write them into the mailbox.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param p_mailbox Pointer to a CAN mailbox instance.
*
* \retval CAN_MAILBOX_NOT_READY: Failed because mailbox isn't ready.
* CAN_MAILBOX_TRANSFER_OK: Successfully write message into mailbox.
*
* \note After calling this function, the mailbox message won't be sent out until
* can_mailbox_send_transfer_cmd() is called.
*/
uint32_t can_mailbox_write(Can *p_can, can_mb_conf_t *p_mailbox)
{
uint32_t ul_status;
uint8_t uc_index;
uc_index = (uint8_t)p_mailbox->ul_mb_idx;
/* Read the mailbox status firstly to check whether the mailbox is ready or not. */
p_mailbox->ul_status = can_mailbox_get_status(p_can, uc_index);
ul_status = p_mailbox->ul_status;
if (!(ul_status & CAN_MSR_MRDY)) {
return CAN_MAILBOX_NOT_READY;
}
/* Write transmit identifier. */
if (p_mailbox->uc_id_ver) {
p_can->CAN_MB[uc_index].CAN_MID = p_mailbox->ul_id | CAN_MAM_MIDE;
} else {
p_can->CAN_MB[uc_index].CAN_MID = p_mailbox->ul_id;
}
/* Write transmit data into mailbox data register. */
p_can->CAN_MB[uc_index].CAN_MDL = p_mailbox->ul_datal;
if (p_mailbox->uc_length > 4) {
p_can->CAN_MB[uc_index].CAN_MDH = p_mailbox->ul_datah;
}
/* Write transmit data length into mailbox control register. */
p_can->CAN_MB[uc_index].CAN_MCR = (p_can->CAN_MB[uc_index].CAN_MCR &
~CAN_MCR_MDLC_Msk) | CAN_MCR_MDLC(p_mailbox->uc_length);
return CAN_MAILBOX_TRANSFER_OK;
}
/**
* \brief Require to send out a remote frame.
*
* \param p_can Pointer to a CAN peripheral instance.
* \param p_mailbox Pointer to a CAN mailbox instance.
*
* \retval CAN_MAILBOX_NOT_READY: Failed because mailbox isn't ready for transmitting message.
* CAN_MAILBOX_TRANSFER_OK: Successfully send out a remote frame.
*/
uint32_t can_mailbox_tx_remote_frame(Can *p_can, can_mb_conf_t *p_mailbox)
{
uint32_t ul_status;
uint8_t uc_index;
uc_index = (uint8_t)p_mailbox->ul_mb_idx;
/* Read the mailbox status firstly to check whether the mailbox is ready or not. */
p_mailbox->ul_status = p_can->CAN_MB[uc_index].CAN_MSR;
ul_status = p_mailbox->ul_status;
if (!(ul_status & CAN_MSR_MRDY)) {
return CAN_MAILBOX_NOT_READY;
}
/* Write transmit identifier. */
if (p_mailbox->uc_id_ver) {
p_can->CAN_MB[uc_index].CAN_MID = p_mailbox->ul_id | CAN_MAM_MIDE;
} else {
p_can->CAN_MB[uc_index].CAN_MID = p_mailbox->ul_id;
}
/* Set the RTR bit in the sent frame. */
p_can->CAN_MB[uc_index].CAN_MCR |= CAN_MCR_MRTR;
/* Set the MBx bit in the Transfer Command Register to send out the remote frame. */
can_global_send_transfer_cmd(p_can, (1 << uc_index));
return CAN_MAILBOX_TRANSFER_OK;
}
/**
* \brief Reset the eight mailboxes.
*
* \param p_can Pointer to a CAN peripheral instance.
*/
void can_reset_all_mailbox(Can *p_can)
{
can_mb_conf_t mb_config_t;
/* Set the mailbox object type parameter to disable the mailbox. */
mb_config_t.uc_obj_type = CAN_MB_DISABLE_MODE;
for (uint8_t i = 0; i < CANMB_NUMBER; i++) {
mb_config_t.ul_mb_idx = i;
can_mailbox_init(p_can, &mb_config_t);
}
}
// from wilfredo
uint32_t can_reset_mailbox_data(can_mb_conf_t *p_mailbox)
{
if ( p_mailbox == NULL )
{
return 1U ;
}
#if 0
p_mailbox->ul_mb_idx = 0;
p_mailbox->uc_obj_type = 0;
p_mailbox->uc_id_ver = 0;
p_mailbox->uc_length = 0;
p_mailbox->uc_tx_prio = 0;
p_mailbox->ul_status = 0;
p_mailbox->ul_id_msk = 0;
p_mailbox->ul_id = 0;
p_mailbox->ul_fid = 0;
p_mailbox->ul_datal = 0;
p_mailbox->ul_datah = 0;
#else
memset( p_mailbox, 0, sizeof( can_mb_conf_t ) ) ;
#endif
return 0U ;
}
#endif // SAM3XA_SERIES
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond

View File

@@ -0,0 +1,486 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#include "../chip.h"
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
#if (SAM3XA_SERIES) || (SAM3N_SERIES) || (SAM3S_SERIES)
/**
* \defgroup sam_drivers_dacc_group Digital-to-Analog Converter Controller (DACC)
*
* \par Purpose
*
* Driver for the Digital-to-Analog Converter Controller. It provides access to the main
* features of the DAC controller.
*
* \par Usage
*
* -# DACC clock should be enabled before using it.
* - \ref pmc_enable_periph_clk() can be used to enable the clock.
* -# Reset DACC with \ref dacc_reset().
* -# If DACC can be enabled/disabled, uses \ref dacc_enable() and
* \ref dacc_disable().
* -# Initialize DACC timing with \ref dacc_set_timing() (different DAC
* peripheral may require different parameters).
* -# Write conversion data with \ref dacc_write_conversion_data().
* -# Configure trigger with \ref dacc_set_trigger()
* and \ref dacc_disable_trigger().
* -# Configure FIFO transfer mode with \ref dacc_set_transfer_mode().
* -# Control interrupts with \ref dacc_enable_interrupt(),
* \ref dacc_disable_interrupt(), \ref dacc_get_interrupt_mask() and
* \ref dacc_get_interrupt_status().
* -# DACC registers support write protect with \ref dacc_set_writeprotect()
* and \ref dacc_get_writeprotect_status().
* -# If the DACC can work with PDC, use \ref dacc_get_pdc_base() to get
* PDC register base for the DAC controller.
* -# If the DACC has several channels to process, the following functions can
* be used:
* - Enable/Disable TAG and select output channel selection by
* \ref dacc_set_channel_selection(),
* \ref dacc_enable_flexible_channel_selection().
* - Enable/disable channel by \ref dacc_enable_channel() /
* \ref dacc_disable_channel(), get channel status by
* \ref dacc_get_channel_status().
*
* \section dependencies Dependencies
* This driver does not depend on other modules.
*
* @{
*/
//! Max channel number
#if (SAM3N_SERIES)
# define MAX_CH_NB 0
#else
# define MAX_CH_NB 1
#endif
//! DACC Write Protect Key "DAC" in ASCII
#define DACC_WP_KEY (0x444143)
/**
* \brief Reset DACC.
*
* \param p_dacc Pointer to a DACC instance.
*/
void dacc_reset(Dacc *p_dacc)
{
p_dacc->DACC_CR = DACC_CR_SWRST;
}
/**
* \brief Enable trigger and set the trigger source.
*
* \param p_dacc Pointer to a DACC instance.
* \param ul_trigger Trigger source number.
*
* \return \ref DACC_RC_OK for OK.
*/
uint32_t dacc_set_trigger(Dacc *p_dacc, uint32_t ul_trigger)
{
uint32_t mr = p_dacc->DACC_MR & (~(DACC_MR_TRGSEL_Msk));
#if (SAM3N_SERIES)
p_dacc->DACC_MR = mr
| DACC_MR_TRGEN
| ((ul_trigger << DACC_MR_TRGSEL_Pos) & DACC_MR_TRGSEL_Msk);
#else
p_dacc->DACC_MR = mr | DACC_MR_TRGEN_EN | DACC_MR_TRGSEL(ul_trigger);
#endif
return DACC_RC_OK;
}
/**
* \brief Disable trigger (free run mode).
*
* \param p_dacc Pointer to a DACC instance.
*/
void dacc_disable_trigger(Dacc *p_dacc)
{
p_dacc->DACC_MR &= ~DACC_MR_TRGEN;
}
/**
* \brief Set the transfer mode.
*
* \param p_dacc Pointer to a DACC instance.
* \param ul_mode Transfer mode configuration.
*
* \return \ref DACC_RC_OK for OK.
*/
uint32_t dacc_set_transfer_mode(Dacc *p_dacc, uint32_t ul_mode)
{
if (ul_mode) {
#if (SAM3N_SERIES)
p_dacc->DACC_MR |= DACC_MR_WORD;
#else
p_dacc->DACC_MR |= DACC_MR_WORD_WORD;
#endif
} else {
#if (SAM3N_SERIES)
p_dacc->DACC_MR &= (~DACC_MR_WORD);
#else
p_dacc->DACC_MR &= (~DACC_MR_WORD_WORD);
#endif
}
return DACC_RC_OK;
}
/**
* \brief Enable DACC interrupts.
*
* \param p_dacc Pointer to a DACC instance.
* \param ul_interrupt_mask The interrupt mask.
*/
void dacc_enable_interrupt(Dacc *p_dacc, uint32_t ul_interrupt_mask)
{
p_dacc->DACC_IER = ul_interrupt_mask;
}
/**
* \brief Disable DACC interrupts.
*
* \param p_dacc Pointer to a DACC instance.
* \param ul_interrupt_mask The interrupt mask.
*/
void dacc_disable_interrupt(Dacc *p_dacc, uint32_t ul_interrupt_mask)
{
p_dacc->DACC_IDR = ul_interrupt_mask;
}
/**
* \brief Get the interrupt mask.
*
* \param p_dacc Pointer to a DACC instance.
*
* \return The interrupt mask.
*/
uint32_t dacc_get_interrupt_mask(Dacc *p_dacc)
{
return p_dacc->DACC_IMR;
}
/**
* \brief Get the interrupt status.
*
* \param p_dacc Pointer to a DACC instance.
*
* \return The interrupt status.
*/
uint32_t dacc_get_interrupt_status(Dacc *p_dacc)
{
return p_dacc->DACC_ISR;
}
/**
* \brief Write data to conversion register.
*
* \note The \a ul_data could be output data or data with channel TAG when
* flexible mode is used.
*
* In flexible mode the 2 bits, DACC_CDR[13:12] which are otherwise unused,
* are employed to select the channel in the same way as with the USER_SEL
* field. Finally, if the WORD field is set, the 2 bits, DACC_CDR[13:12] are
* used for channel selection of the first data and the 2 bits,
* DACC_CDR[29:28] for channel selection of the second data.
*
* \see dacc_enable_flexible_selection()
*
* \param p_dacc Pointer to a DACC instance.
* \param ul_data The data to be transferred to analog value.
*/
void dacc_write_conversion_data(Dacc *p_dacc, uint32_t ul_data)
{
p_dacc->DACC_CDR = ul_data;
}
/**
* \brief Enable or disable write protect of DACC registers.
*
* \param p_dacc Pointer to a DACC instance.
* \param ul_enable 1 to enable, 0 to disable.
*/
void dacc_set_writeprotect(Dacc *p_dacc, uint32_t ul_enable)
{
if (ul_enable) {
p_dacc->DACC_WPMR = DACC_WPMR_WPKEY(DACC_WP_KEY)
| DACC_WPMR_WPEN;
} else {
p_dacc->DACC_WPMR = DACC_WPMR_WPKEY(DACC_WP_KEY);
}
}
/**
* \brief Get the write protect status.
*
* \param p_dacc Pointer to a DACC instance.
*
* \return Write protect status.
*/
uint32_t dacc_get_writeprotect_status(Dacc *p_dacc)
{
return p_dacc->DACC_WPSR;
}
/**
* \brief Get PDC registers base address.
*
* \param p_dacc Pointer to a DACC instance.
*
* \return DACC PDC register base address.
*/
Pdc *dacc_get_pdc_base(Dacc *p_dacc)
{
p_dacc = p_dacc;
return PDC_DACC;
}
#if (SAM3N_SERIES) || defined(__DOXYGEN__)
/**
* \brief Enable DACC.
*
* \param p_dacc Pointer to a DACC instance.
*/
void dacc_enable(Dacc *p_dacc)
{
p_dacc->DACC_MR |= DACC_MR_DACEN;
}
/**
* \brief Disable DACC.
*
* \param p_dacc Pointer to a DACC instance.
*
* \return \ref DACC_RC_OK for OK.
*/
void dacc_disable(Dacc *p_dacc)
{
p_dacc->DACC_MR &= (~DACC_MR_DACEN);
}
/**
* \brief Set the DACC timing.
*
* \param p_dacc Pointer to a DACC instance.
* \param ul_startup Startup time selection.
* \param ul_clock_divider Clock divider for internal trigger.
*
* \return \ref DACC_RC_OK for OK.
*/
uint32_t dacc_set_timing(Dacc *p_dacc, uint32_t ul_startup,
uint32_t ul_clock_divider)
{
uint32_t mr = p_dacc->DACC_MR
& ~(DACC_MR_STARTUP_Msk | DACC_MR_CLKDIV_Msk);
p_dacc->DACC_MR = mr | DACC_MR_STARTUP(ul_startup)
| DACC_MR_CLKDIV(ul_clock_divider);
return DACC_RC_OK;
}
#endif /* #if (SAM3N_SERIES) */
#if (SAM3S_SERIES) || (SAM3XA_SERIES) || (SAM4S_SERIES) || defined(__DOXYGEN__)
/**
* \brief Disable flexible (TAG) mode and select a channel for DAC outputs.
*
* \param p_dacc Pointer to a DACC instance.
* \param ul_channel Channel to select.
*
* \return \ref DACC_RC_OK if successful.
*/
uint32_t dacc_set_channel_selection(Dacc *p_dacc, uint32_t ul_channel)
{
uint32_t mr = p_dacc->DACC_MR & (~DACC_MR_USER_SEL_Msk);
if (ul_channel > MAX_CH_NB) {
return DACC_RC_INVALID_PARAM;
}
mr &= ~(DACC_MR_TAG);
mr |= ul_channel << DACC_MR_USER_SEL_Pos;
p_dacc->DACC_MR = mr;
return DACC_RC_OK;
}
/**
* \brief Enable the flexible channel selection mode (TAG).
*
* In this mode the 2 bits, DACC_CDR[13:12] which are otherwise unused, are
* employed to select the channel in the same way as with the USER_SEL field.
* Finally, if the WORD field is set, the 2 bits, DACC_CDR[13:12] are used
* for channel selection of the first data and the 2 bits, DACC_CDR[29:28]
* for channel selection of the second data.
*
* \param p_dacc Pointer to a DACC instance.
*/
void dacc_enable_flexible_selection(Dacc *p_dacc)
{
p_dacc->DACC_MR |= DACC_MR_TAG;
}
/**
* \brief Set the power save mode.
*
* \param p_dacc Pointer to a DACC instance.
* \param ul_sleep_mode Sleep mode configuration.
* \param ul_fast_wakeup_mode Fast wakeup mode configuration.
*
* \return \ref DACC_RC_OK if successful.
*/
uint32_t dacc_set_power_save(Dacc *p_dacc,
uint32_t ul_sleep_mode, uint32_t ul_fast_wakeup_mode)
{
if (ul_sleep_mode) {
p_dacc->DACC_MR |= DACC_MR_SLEEP;
} else {
p_dacc->DACC_MR &= (~DACC_MR_SLEEP);
}
if (ul_fast_wakeup_mode) {
p_dacc->DACC_MR |= DACC_MR_FASTWKUP;
} else {
p_dacc->DACC_MR &= (~DACC_MR_FASTWKUP);
}
return DACC_RC_OK;
}
/**
* \brief Set DACC timings.
*
* \param p_dacc Pointer to a DACC instance.
* \param ul_refresh Refresh period setting value.
* \param ul_maxs Max speed mode configuration.
* \param ul_startup Startup time selection.
*
* \return \ref DACC_RC_OK for OK.
*/
uint32_t dacc_set_timing(Dacc *p_dacc,
uint32_t ul_refresh, uint32_t ul_maxs, uint32_t ul_startup)
{
uint32_t mr = p_dacc->DACC_MR
& (~(DACC_MR_REFRESH_Msk | DACC_MR_STARTUP_Msk));
mr |= DACC_MR_REFRESH(ul_refresh);
if (ul_maxs) {
mr |= DACC_MR_MAXS;
} else {
mr &= ~DACC_MR_MAXS;
}
mr |= (DACC_MR_STARTUP_Msk & ((ul_startup) << DACC_MR_STARTUP_Pos));
p_dacc->DACC_MR = mr;
return DACC_RC_OK;
}
/**
* \brief Enable DACC channel.
*
* \param p_dacc Pointer to a DACC instance.
* \param ul_channel The output channel to enable.
*
* \return \ref DACC_RC_OK for OK.
*/
uint32_t dacc_enable_channel(Dacc *p_dacc, uint32_t ul_channel)
{
if (ul_channel > MAX_CH_NB)
return DACC_RC_INVALID_PARAM;
p_dacc->DACC_CHER = DACC_CHER_CH0 << ul_channel;
return DACC_RC_OK;
}
/**
* \brief Disable DACC channel.
*
* \param p_dacc Pointer to a DACC instance.
* \param ul_channel The output channel to disable.
*
* \return \ref DACC_RC_OK for OK.
*/
uint32_t dacc_disable_channel(Dacc *p_dacc, uint32_t ul_channel)
{
if (ul_channel > MAX_CH_NB) {
return DACC_RC_INVALID_PARAM;
}
p_dacc->DACC_CHDR = DACC_CHDR_CH0 << ul_channel;
return DACC_RC_OK;
}
/**
* \brief Get the channel status.
*
* \param p_dacc Pointer to a DACC instance.
*
* \return DACC channel status.
*/
uint32_t dacc_get_channel_status(Dacc *p_dacc)
{
return p_dacc->DACC_CHSR;
}
/**
* \brief Set the analog control value.
*
* \param p_dacc Pointer to a DACC instance.
* \param ul_analog_control Analog control configuration.
*
* \return \ref DACC_RC_OK for OK.
*/
uint32_t dacc_set_analog_control(Dacc *p_dacc, uint32_t ul_analog_control)
{
p_dacc->DACC_ACR = ul_analog_control;
return DACC_RC_OK;
}
/**
* \brief Get the analog control value.
*
* \param p_dacc Pointer to a DACC instance.
*
* \return Current setting of analog control.
*/
uint32_t dacc_get_analog_control(Dacc *p_dacc)
{
return p_dacc->DACC_ACR;
}
#endif /* (SAM3S_SERIES) || (SAM3XA_SERIES) */
//@}
#endif // SAM3XA_SERIES
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond

View File

@@ -0,0 +1,402 @@
/**
* \file
*
* \brief Enhanced Embedded Flash Controller (EEFC) driver for SAM.
*
* Copyright (c) 2011-2012 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* 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.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* 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.
*
* \asf_license_stop
*
*/
#include "../chip.h"
#include <string.h>
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
/**
* \defgroup sam_drivers_efc_group Enhanced Embedded Flash Controller (EEFC)
*
* The Enhanced Embedded Flash Controller ensures the interface of the Flash block with
* the 32-bit internal bus.
*
* @{
*/
/* Address definition for read operation */
#if (SAM3XA_SERIES || SAM3U_SERIES /*|| SAM4SD16 || SAM4SD32*/)
# define READ_BUFF_ADDR0 IFLASH0_ADDR
# define READ_BUFF_ADDR1 IFLASH1_ADDR
#elif (SAM3S_SERIES || SAM3N_SERIES)
# define READ_BUFF_ADDR IFLASH_ADDR
#elif (SAM3U_SERIES || SAM4S_SERIES)
# define READ_BUFF_ADDR IFLASH0_ADDR
#else
# warning Only reading unique id for sam3 is implemented.
#endif
/* Flash Writing Protection Key */
#define FWP_KEY 0x5Au
#if SAM4S_SERIES
#define EEFC_FCR_FCMD(value) \
((EEFC_FCR_FCMD_Msk & ((value) << EEFC_FCR_FCMD_Pos)))
#define EEFC_ERROR_FLAGS (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE | EEFC_FSR_FLERR)
#else
#define EEFC_ERROR_FLAGS (EEFC_FSR_FLOCKE | EEFC_FSR_FCMDE)
#endif
/*
* Local function declaration.
* Because they are RAM functions, they need 'extern' declaration.
*/
extern void efc_write_fmr(Efc *p_efc, uint32_t ul_fmr);
extern uint32_t efc_perform_fcr(Efc *p_efc, uint32_t ul_fcr);
/**
* \brief Initialize the EFC controller.
*
* \param ul_access_mode 0 for 128-bit, EEFC_FMR_FAM for 64-bit.
* \param ul_fws The number of wait states in cycle (no shift).
*
* \return 0 if successful.
*/
uint32_t efc_init(Efc *p_efc, uint32_t ul_access_mode, uint32_t ul_fws)
{
efc_write_fmr(p_efc, ul_access_mode | EEFC_FMR_FWS(ul_fws));
return EFC_RC_OK;
}
/**
* \brief Enable the flash ready interrupt.
*
* \param p_efc Pointer to an EFC instance.
*/
void efc_enable_frdy_interrupt(Efc *p_efc)
{
uint32_t ul_fmr = p_efc->EEFC_FMR;
efc_write_fmr(p_efc, ul_fmr | EEFC_FMR_FRDY);
}
/**
* \brief Disable the flash ready interrupt.
*
* \param p_efc Pointer to an EFC instance.
*/
void efc_disable_frdy_interrupt(Efc *p_efc)
{
uint32_t ul_fmr = p_efc->EEFC_FMR;
efc_write_fmr(p_efc, ul_fmr & (~EEFC_FMR_FRDY));
}
/**
* \brief Set flash access mode.
*
* \param p_efc Pointer to an EFC instance.
* \param ul_mode 0 for 128-bit, EEFC_FMR_FAM for 64-bit.
*/
void efc_set_flash_access_mode(Efc *p_efc, uint32_t ul_mode)
{
uint32_t ul_fmr = p_efc->EEFC_FMR & (~EEFC_FMR_FAM);
efc_write_fmr(p_efc, ul_fmr | ul_mode);
}
/**
* \brief Get flash access mode.
*
* \param p_efc Pointer to an EFC instance.
*
* \return 0 for 128-bit or EEFC_FMR_FAM for 64-bit.
*/
uint32_t efc_get_flash_access_mode(Efc *p_efc)
{
return (p_efc->EEFC_FMR & EEFC_FMR_FAM);
}
/**
* \brief Set flash wait state.
*
* \param p_efc Pointer to an EFC instance.
* \param ul_fws The number of wait states in cycle (no shift).
*/
void efc_set_wait_state(Efc *p_efc, uint32_t ul_fws)
{
uint32_t ul_fmr = p_efc->EEFC_FMR & (~EEFC_FMR_FWS_Msk);
efc_write_fmr(p_efc, ul_fmr | EEFC_FMR_FWS(ul_fws));
}
/**
* \brief Get flash wait state.
*
* \param p_efc Pointer to an EFC instance.
*
* \return The number of wait states in cycle (no shift).
*/
uint32_t efc_get_wait_state(Efc *p_efc)
{
return ((p_efc->EEFC_FMR & EEFC_FMR_FWS_Msk) >> EEFC_FMR_FWS_Pos);
}
/**
* \brief Perform the given command and wait until its completion (or an error).
*
* \note Unique ID commands are not supported, use efc_read_unique_id.
*
* \param p_efc Pointer to an EFC instance.
* \param ul_command Command to perform.
* \param ul_argument Optional command argument.
*
* \note This function will automatically choose to use IAP function.
*
* \return 0 if successful, otherwise returns an error code.
*/
uint32_t efc_perform_command(Efc *p_efc, uint32_t ul_command,
uint32_t ul_argument)
{
// Unique ID commands are not supported.
if (ul_command == EFC_FCMD_STUI || ul_command == EFC_FCMD_SPUI) {
return EFC_RC_NOT_SUPPORT;
}
#if (SAM3XA_SERIES || SAM3U4)
// Use IAP function with 2 parameters in ROM.
static uint32_t(*iap_perform_command) (uint32_t, uint32_t);
uint32_t ul_efc_nb = (p_efc == EFC0) ? 0 : 1;
iap_perform_command =
(uint32_t(*)(uint32_t, uint32_t))
*((uint32_t *) CHIP_FLASH_IAP_ADDRESS);
iap_perform_command(ul_efc_nb,
EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(ul_argument) |
EEFC_FCR_FCMD(ul_command));
return (p_efc->EEFC_FSR & EEFC_ERROR_FLAGS);
#elif (SAM3N_SERIES || SAM3S_SERIES || SAM4S_SERIES || SAM3U_SERIES)
// Use IAP function with 2 parameter in ROM.
static uint32_t(*iap_perform_command) (uint32_t, uint32_t);
iap_perform_command =
(uint32_t(*)(uint32_t, uint32_t))
*((uint32_t *) CHIP_FLASH_IAP_ADDRESS);
#if SAM4S_SERIES
uint32_t ul_efc_nb = (p_efc == EFC0) ? 0 : 1;
iap_perform_command(ul_efc_nb,
EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(ul_argument) |
EEFC_FCR_FCMD(ul_command));
#else
iap_perform_command(0,
EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(ul_argument) |
EEFC_FCR_FCMD(ul_command));
#endif
return (p_efc->EEFC_FSR & EEFC_ERROR_FLAGS);
#else
// Use RAM Function.
return efc_perform_fcr(p_efc,
EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(ul_argument) |
EEFC_FCR_FCMD(ul_command));
#endif
}
/**
* \brief Get the current status of the EEFC.
*
* \note This function clears the value of some status bits (FLOCKE, FCMDE).
*
* \param p_efc Pointer to an EFC instance.
*
* \return The current status.
*/
uint32_t efc_get_status(Efc *p_efc)
{
return p_efc->EEFC_FSR;
}
/**
* \brief Get the result of the last executed command.
*
* \param p_efc Pointer to an EFC instance.
*
* \return The result of the last executed command.
*/
uint32_t efc_get_result(Efc *p_efc)
{
return p_efc->EEFC_FRR;
}
/**
* \brief Perform read sequence. Supported sequences are read Unique ID and
* read User Signature
*
* \param p_efc Pointer to an EFC instance.
* \param ul_cmd_st Start command to perform.
* \param ul_cmd_sp Stop command to perform.
* \param p_ul_buf Pointer to an data buffer.
* \param ul_size Buffer size.
*
* \return 0 if successful, otherwise returns an error code.
*/
#ifdef __ICCARM__
__ramfunc
#else
__attribute__ ((section(".ramfunc")))
#endif
uint32_t efc_perform_read_sequence(Efc *p_efc,
uint32_t ul_cmd_st, uint32_t ul_cmd_sp,
uint32_t *p_ul_buf, uint32_t ul_size)
{
volatile uint32_t ul_status;
uint32_t ul_cnt;
#if (SAM3U4 || SAM3XA_SERIES /*|| SAM4SD16 || SAM4SD32*/)
uint32_t *p_ul_data =
(uint32_t *) ((p_efc == EFC0) ?
READ_BUFF_ADDR0 : READ_BUFF_ADDR1);
#elif (SAM3S_SERIES || SAM4S_SERIES || SAM3N_SERIES || SAM3U_SERIES)
uint32_t *p_ul_data = (uint32_t *) READ_BUFF_ADDR;
#else
return EFC_RC_NOT_SUPPORT;
#endif
if (p_ul_buf == NULL) {
return EFC_RC_INVALID;
}
p_efc->EEFC_FMR |= (0x1u << 16);
/* Send the Start Read command */
#if SAM4S_SERIES
p_efc->EEFC_FCR = EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(0)
| EEFC_FCR_FCMD(ul_cmd_st);
#else
p_efc->EEFC_FCR = EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(0)
| EEFC_FCR_FCMD(ul_cmd_st);
#endif
/* Wait for the FRDY bit in the Flash Programming Status Register
* (EEFC_FSR) falls.
*/
do {
ul_status = p_efc->EEFC_FSR;
} while ((ul_status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY);
/* The data is located in the first address of the Flash
* memory mapping.
*/
for (ul_cnt = 0; ul_cnt < ul_size; ul_cnt++) {
p_ul_buf[ul_cnt] = p_ul_data[ul_cnt];
}
/* To stop the read mode */
p_efc->EEFC_FCR =
#if SAM4S_SERIES
EEFC_FCR_FKEY_PASSWD | EEFC_FCR_FARG(0) |
EEFC_FCR_FCMD(ul_cmd_sp);
#else
EEFC_FCR_FKEY(FWP_KEY) | EEFC_FCR_FARG(0) |
EEFC_FCR_FCMD(ul_cmd_sp);
#endif
/* Wait for the FRDY bit in the Flash Programming Status Register (EEFC_FSR)
* rises.
*/
do {
ul_status = p_efc->EEFC_FSR;
} while ((ul_status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);
p_efc->EEFC_FMR &= ~(0x1u << 16);
return EFC_RC_OK;
}
/**
* \brief Set mode register.
*
* \param p_efc Pointer to an EFC instance.
* \param ul_fmr Value of mode register
*/
#ifdef __ICCARM__
__ramfunc
#else
__attribute__ ((section(".ramfunc")))
#endif
void efc_write_fmr(Efc *p_efc, uint32_t ul_fmr)
{
p_efc->EEFC_FMR = ul_fmr;
}
/**
* \brief Perform command.
*
* \param p_efc Pointer to an EFC instance.
* \param ul_fcr Flash command.
*
* \return The current status.
*/
#ifdef __ICCARM__
__ramfunc
#else
__attribute__ ((section(".ramfunc")))
#endif
uint32_t efc_perform_fcr(Efc *p_efc, uint32_t ul_fcr)
{
volatile uint32_t ul_status;
p_efc->EEFC_FCR = ul_fcr;
do {
ul_status = p_efc->EEFC_FSR;
} while ((ul_status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);
return (ul_status & EEFC_ERROR_FLAGS);
}
//@}
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond

View File

@@ -0,0 +1,802 @@
/**
* \file
*
* \brief EMAC (Ethernet MAC) driver for SAM.
*
* Copyright (c) 2011-2012 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* 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.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* 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.
*
* \asf_license_stop
*
*/
#include "../chip.h"
#include <string.h>
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
#if SAM3XA_SERIES
/**
* \defgroup emac_group Ethernet Media Access Controller
*
* See \ref emac_quickstart.
*
* Driver for the EMAC (Ethernet Media Access Controller).
* This file contains basic functions for the EMAC, with support for all modes, settings
* and clock speeds.
*
* \section dependencies Dependencies
* This driver does not depend on other modules.
*
* @{
*/
#define EMAC_RX_BUFFERS 16
#define EMAC_TX_BUFFERS 8
#define MAC_PHY_RETRY_MAX 1000000
/** TX descriptor lists */
#ifdef __ICCARM__ /* IAR */
#pragma data_alignment=8
#endif
static emac_tx_descriptor_t gs_tx_desc[EMAC_TX_BUFFERS];
/** TX callback lists */
static emac_dev_tx_cb_t gs_tx_callback[EMAC_TX_BUFFERS];
/** RX descriptors lists */
#ifdef __ICCARM__ /* IAR */
#pragma data_alignment=8
#endif
static emac_rx_descriptor_t gs_rx_desc[EMAC_RX_BUFFERS];
/** Send Buffer. Section 3.6 of AMBA 2.0 spec states that burst should not cross the
* 1K Boundaries. Receive buffer manager write operations are burst of 2 words => 3 lsb bits
* of the address shall be set to 0.
*/
#ifdef __ICCARM__ /* IAR */
#pragma data_alignment=8
#endif
static uint8_t gs_uc_tx_buffer[EMAC_TX_BUFFERS * EMAC_TX_UNITSIZE]
__attribute__ ((aligned(8)));
#ifdef __ICCARM__ /* IAR */
#pragma data_alignment=8
#endif
/** Receive Buffer */
static uint8_t gs_uc_rx_buffer[EMAC_RX_BUFFERS * EMAC_RX_UNITSIZE]
__attribute__ ((aligned(8)));
/**
* EMAC device memory management struct.
*/
typedef struct emac_dev_mem {
/* Pointer to allocated buffer for RX. The address should be 8-byte aligned
and the size should be EMAC_RX_UNITSIZE * wRxSize. */
uint8_t *p_rx_buffer;
/* Pointer to allocated RX descriptor list. */
emac_rx_descriptor_t *p_rx_dscr;
/* RX size, in number of registered units (RX descriptors). */
uint16_t us_rx_size;
/* Pointer to allocated buffer for TX. The address should be 8-byte aligned
and the size should be EMAC_TX_UNITSIZE * wTxSize. */
uint8_t *p_tx_buffer;
/* Pointer to allocated TX descriptor list. */
emac_tx_descriptor_t *p_tx_dscr;
/* TX size, in number of registered units (TX descriptors). */
uint16_t us_tx_size;
} emac_dev_mem_t;
/** Return count in buffer */
#define CIRC_CNT(head,tail,size) (((head) - (tail)) % (size))
/*
* Return space available, from 0 to size-1.
* Always leave one free char as a completely full buffer that has (head == tail),
* which is the same as empty.
*/
#define CIRC_SPACE(head,tail,size) CIRC_CNT((tail),((head)+1),(size))
/** Circular buffer is empty ? */
#define CIRC_EMPTY(head, tail) (head == tail)
/** Clear circular buffer */
#define CIRC_CLEAR(head, tail) (head = tail = 0)
/** Increment head or tail */
static void circ_inc(uint16_t *headortail, uint32_t size)
{
(*headortail)++;
if((*headortail) >= size) {
(*headortail) = 0;
}
}
/**
* \brief Wait PHY operation to be completed.
*
* \param p_emac HW controller address.
* \param ul_retry The retry times, 0 to wait forever until completeness.
*
* Return EMAC_OK if the operation is completed successfully.
*/
static uint8_t emac_wait_phy(Emac* p_emac, const uint32_t ul_retry)
{
volatile uint32_t ul_retry_count = 0;
while (!emac_is_phy_idle(p_emac)) {
if (ul_retry == 0) {
continue;
}
ul_retry_count++;
if (ul_retry_count >= ul_retry) {
return EMAC_TIMEOUT;
}
}
return EMAC_OK;
}
/**
* \brief Disable transfer, reset registers and descriptor lists.
*
* \param p_dev Pointer to EMAC driver instance.
*
*/
static void emac_reset_tx_mem(emac_device_t* p_dev)
{
Emac *p_hw = p_dev->p_hw;
uint8_t *p_tx_buff = p_dev->p_tx_buffer;
emac_tx_descriptor_t *p_td = p_dev->p_tx_dscr;
uint32_t ul_index;
uint32_t ul_address;
/* Disable TX */
emac_enable_transmit(p_hw, 0);
/* Set up the TX descriptors */
CIRC_CLEAR(p_dev->us_tx_head, p_dev->us_tx_tail);
for (ul_index = 0; ul_index < p_dev->us_tx_list_size; ul_index++) {
ul_address = (uint32_t) (&(p_tx_buff[ul_index * EMAC_TX_UNITSIZE]));
p_td[ul_index].addr = ul_address;
p_td[ul_index].status.val = EMAC_TXD_USED;
}
p_td[p_dev->us_tx_list_size - 1].status.val =
EMAC_TXD_USED | EMAC_TXD_WRAP;
/* Set transmit buffer queue */
emac_set_tx_queue(p_hw, (uint32_t) p_td);
}
/**
* \brief Disable receiver, reset registers and descriptor list.
*
* \param p_drv Pointer to EMAC Driver instance.
*/
static void emac_reset_rx_mem(emac_device_t* p_dev)
{
Emac *p_hw = p_dev->p_hw;
uint8_t *p_rx_buff = p_dev->p_rx_buffer;
emac_rx_descriptor_t *pRd = p_dev->p_rx_dscr;
uint32_t ul_index;
uint32_t ul_address;
/* Disable RX */
emac_enable_receive(p_hw, 0);
/* Set up the RX descriptors */
p_dev->us_rx_idx = 0;
for (ul_index = 0; ul_index < p_dev->us_rx_list_size; ul_index++) {
ul_address = (uint32_t) (&(p_rx_buff[ul_index * EMAC_RX_UNITSIZE]));
pRd[ul_index].addr.val = ul_address & EMAC_RXD_ADDR_MASK;
pRd[ul_index].status.val = 0;
}
pRd[p_dev->us_rx_list_size - 1].addr.val |= EMAC_RXD_WRAP;
/* Set receive buffer queue */
emac_set_rx_queue(p_hw, (uint32_t) pRd);
}
/**
* \brief Initialize the allocated buffer lists for EMAC driver to transfer data.
* Must be invoked after emac_dev_init() but before RX/TX starts.
*
* \note If input address is not 8-byte aligned, the address is automatically
* adjusted and the list size is reduced by one.
*
* \param p_emac Pointer to EMAC instance.
* \param p_emac_dev Pointer to EMAC device instance.
* \param p_dev_mm Pointer to the EMAC memory management control block.
* \param p_tx_cb Pointer to allocated TX callback list.
*
* \return EMAC_OK or EMAC_PARAM.
*/
static uint8_t emac_init_mem(Emac* p_emac, emac_device_t* p_emac_dev,
emac_dev_mem_t* p_dev_mm,
emac_dev_tx_cb_t* p_tx_cb)
{
if (p_dev_mm->us_rx_size <= 1 || p_dev_mm->us_tx_size <= 1 || p_tx_cb == NULL) {
return EMAC_PARAM;
}
/* Assign RX buffers */
if (((uint32_t) p_dev_mm->p_rx_buffer & 0x7)
|| ((uint32_t) p_dev_mm->p_rx_dscr & 0x7)) {
p_dev_mm->us_rx_size--;
}
p_emac_dev->p_rx_buffer =
(uint8_t *) ((uint32_t) p_dev_mm->p_rx_buffer & 0xFFFFFFF8);
p_emac_dev->p_rx_dscr =
(emac_rx_descriptor_t *) ((uint32_t) p_dev_mm->p_rx_dscr
& 0xFFFFFFF8);
p_emac_dev->us_rx_list_size = p_dev_mm->us_rx_size;
/* Assign TX buffers */
if (((uint32_t) p_dev_mm->p_tx_buffer & 0x7)
|| ((uint32_t) p_dev_mm->p_tx_dscr & 0x7)) {
p_dev_mm->us_tx_size--;
}
p_emac_dev->p_tx_buffer =
(uint8_t *) ((uint32_t) p_dev_mm->p_tx_buffer & 0xFFFFFFF8);
p_emac_dev->p_tx_dscr =
(emac_tx_descriptor_t *) ((uint32_t) p_dev_mm->p_tx_dscr
& 0xFFFFFFF8);
p_emac_dev->us_tx_list_size = p_dev_mm->us_tx_size;
p_emac_dev->func_tx_cb_list = p_tx_cb;
/* Reset TX & RX */
emac_reset_rx_mem(p_emac_dev);
emac_reset_tx_mem(p_emac_dev);
/* Enable Rx and Tx, plus the statistics register */
emac_enable_transmit(p_emac, 1);
emac_enable_receive(p_emac, 1);
emac_enable_statistics_write(p_emac, 1);
/* Set up the interrupts for transmission and errors */
emac_enable_interrupt(p_emac,
EMAC_IER_RXUBR | /* Enable receive used bit read interrupt. */
EMAC_IER_TUND | /* Enable transmit underrun interrupt. */
EMAC_IER_RLE | /* Enable retry limit exceeded interrupt. */
EMAC_IER_TXERR | /* Enable transmit buffers exhausted in mid-frame interrupt. */
EMAC_IER_TCOMP | /* Enable transmit complete interrupt. */
EMAC_IER_ROVR | /* Enable receive overrun interrupt. */
EMAC_IER_HRESP | /* Enable Hresp not OK interrupt. */
EMAC_IER_PFR | /* Enable pause frame received interrupt. */
EMAC_IER_PTZ); /* Enable pause time zero interrupt. */
return EMAC_OK;
}
/**
* \brief Read the PHY register.
*
* \param p_emac Pointer to the EMAC instance.
* \param uc_phy_address PHY address.
* \param uc_address Register address.
* \param p_value Pointer to a 32-bit location to store read data.
*
* \Return EMAC_OK if successfully, EMAC_TIMEOUT if timeout.
*/
uint8_t emac_phy_read(Emac* p_emac, uint8_t uc_phy_address, uint8_t uc_address,
uint32_t* p_value)
{
emac_maintain_phy(p_emac, uc_phy_address, uc_address, 1, 0);
if (emac_wait_phy(p_emac, MAC_PHY_RETRY_MAX) == EMAC_TIMEOUT) {
return EMAC_TIMEOUT;
}
*p_value = emac_get_phy_data(p_emac);
return EMAC_OK;
}
/**
* \brief Write the PHY register.
*
* \param p_emac Pointer to the EMAC instance.
* \param uc_phy_address PHY Address.
* \param uc_address Register Address.
* \param ul_value Data to write, actually 16-bit data.
*
* \Return EMAC_OK if successfully, EMAC_TIMEOUT if timeout.
*/
uint8_t emac_phy_write(Emac* p_emac, uint8_t uc_phy_address,
uint8_t uc_address, uint32_t ul_value)
{
emac_maintain_phy(p_emac, uc_phy_address, uc_address, 0, ul_value);
if (emac_wait_phy(p_emac, MAC_PHY_RETRY_MAX) == EMAC_TIMEOUT) {
return EMAC_TIMEOUT;
}
return EMAC_OK;
}
/**
* \brief Initialize the EMAC driver.
*
* \param p_emac Pointer to the EMAC instance.
* \param p_emac_dev Pointer to the EMAC device instance.
* \param p_opt EMAC configure options.
*/
void emac_dev_init(Emac* p_emac, emac_device_t* p_emac_dev,
emac_options_t* p_opt)
{
emac_dev_mem_t emac_dev_mm;
/* Disable TX & RX and more */
emac_network_control(p_emac, 0);
emac_disable_interrupt(p_emac, ~0u);
emac_clear_statistics(p_emac);
/* Clear all status bits in the receive status register. */
emac_clear_rx_status(p_emac, EMAC_RSR_OVR | EMAC_RSR_REC | EMAC_RSR_BNA);
/* Clear all status bits in the transmit status register */
emac_clear_tx_status(p_emac, EMAC_TSR_UBR | EMAC_TSR_COL | EMAC_TSR_RLES
| EMAC_TSR_BEX | EMAC_TSR_COMP | EMAC_TSR_UND);
/* Clear interrupts */
emac_get_interrupt_status(p_emac);
/* Enable the copy of data into the buffers
ignore broadcasts, and not copy FCS. */
emac_set_configure(p_emac,
emac_get_configure(p_emac) | EMAC_NCFGR_DRFCS | EMAC_NCFGR_PAE);
emac_enable_copy_all(p_emac, p_opt->uc_copy_all_frame);
emac_disable_broadcast(p_emac, p_opt->uc_no_boardcast);
/* Fill in EMAC device memory management */
emac_dev_mm.p_rx_buffer = gs_uc_rx_buffer;
emac_dev_mm.p_rx_dscr = gs_rx_desc;
emac_dev_mm.us_rx_size = EMAC_RX_BUFFERS;
emac_dev_mm.p_tx_buffer = gs_uc_tx_buffer;
emac_dev_mm.p_tx_dscr = gs_tx_desc;
emac_dev_mm.us_tx_size = EMAC_TX_BUFFERS;
emac_init_mem(p_emac, p_emac_dev, &emac_dev_mm, gs_tx_callback);
emac_set_address(p_emac, 0, p_opt->uc_mac_addr);
}
/**
* \brief Frames can be read from the EMAC in multiple sections.
* Read ul_frame_size bytes from the EMAC receive buffers to pcTo.
* p_rcv_size is the size of the entire frame. Generally emac_read
* will be repeatedly called until the sum of all the ul_frame_size equals
* the value of p_rcv_size.
*
* \param p_emac_dev Pointer to the EMAC device instance.
* \param p_frame Address of the frame buffer.
* \param ul_frame_size Length of the frame.
* \param p_rcv_size Received frame size.
*
* \return EMAC_OK if receiving frame successfully, otherwise failed.
*/
uint32_t emac_dev_read(emac_device_t* p_emac_dev, uint8_t* p_frame,
uint32_t ul_frame_size, uint32_t* p_rcv_size)
{
uint16_t us_buffer_length;
uint32_t tmp_ul_frame_size = 0;
uint8_t *p_tmp_frame = 0;
uint16_t us_tmp_idx = p_emac_dev->us_rx_idx;
emac_rx_descriptor_t *p_rx_td =
&p_emac_dev->p_rx_dscr[p_emac_dev->us_rx_idx];
int8_t c_is_frame = 0;
if (p_frame == NULL)
return EMAC_PARAM;
/* Set the default return value */
*p_rcv_size = 0;
/* Process received RX descriptor */
while ((p_rx_td->addr.val & EMAC_RXD_OWNERSHIP) == EMAC_RXD_OWNERSHIP) {
/* A start of frame has been received, discard previous fragments */
if ((p_rx_td->status.val & EMAC_RXD_SOF) == EMAC_RXD_SOF) {
/* Skip previous fragment */
while (us_tmp_idx != p_emac_dev->us_rx_idx) {
p_rx_td = &p_emac_dev->p_rx_dscr[p_emac_dev->us_rx_idx];
p_rx_td->addr.val &= ~(EMAC_RXD_OWNERSHIP);
circ_inc(&p_emac_dev->us_rx_idx, p_emac_dev->us_rx_list_size);
}
/* Reset the temporary frame pointer */
p_tmp_frame = p_frame;
tmp_ul_frame_size = 0;
/* Start to gather buffers in a frame */
c_is_frame = 1;
}
/* Increment the pointer */
circ_inc(&us_tmp_idx, p_emac_dev->us_rx_list_size);
/* Copy data in the frame buffer */
if (c_is_frame) {
if (us_tmp_idx == p_emac_dev->us_rx_idx) {
do {
p_rx_td = &p_emac_dev->p_rx_dscr[p_emac_dev->us_rx_idx];
p_rx_td->addr.val &= ~(EMAC_RXD_OWNERSHIP);
circ_inc(&p_emac_dev->us_rx_idx, p_emac_dev->us_rx_list_size);
} while (us_tmp_idx != p_emac_dev->us_rx_idx);
return EMAC_RX_NULL;
}
/* Copy the buffer into the application frame */
us_buffer_length = EMAC_RX_UNITSIZE;
if ((tmp_ul_frame_size + us_buffer_length) > ul_frame_size) {
us_buffer_length = ul_frame_size - tmp_ul_frame_size;
}
memcpy(p_tmp_frame,
(void *)(p_rx_td->addr.val & EMAC_RXD_ADDR_MASK),
us_buffer_length);
p_tmp_frame += us_buffer_length;
tmp_ul_frame_size += us_buffer_length;
/* An end of frame has been received, return the data */
if ((p_rx_td->status.val & EMAC_RXD_EOF) == EMAC_RXD_EOF) {
/* Frame size from the EMAC */
*p_rcv_size = (p_rx_td->status.val & EMAC_RXD_LEN_MASK);
/* All data have been copied in the application frame buffer => release TD */
while (p_emac_dev->us_rx_idx != us_tmp_idx) {
p_rx_td = &p_emac_dev->p_rx_dscr[p_emac_dev->us_rx_idx];
p_rx_td->addr.val &= ~(EMAC_RXD_OWNERSHIP);
circ_inc(&p_emac_dev->us_rx_idx, p_emac_dev->us_rx_list_size);
}
/* Application frame buffer is too small so that all data have not been copied */
if (tmp_ul_frame_size < *p_rcv_size) {
return EMAC_SIZE_TOO_SMALL;
}
return EMAC_OK;
}
}
/* SOF has not been detected, skip the fragment */
else {
p_rx_td->addr.val &= ~(EMAC_RXD_OWNERSHIP);
p_emac_dev->us_rx_idx = us_tmp_idx;
}
/* Process the next buffer */
p_rx_td = &p_emac_dev->p_rx_dscr[us_tmp_idx];
}
return EMAC_RX_NULL;
}
/**
* \brief Send ulLength bytes from pcFrom. This copies the buffer to one of the
* EMAC Tx buffers, and then indicates to the EMAC 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 p_emac_dev Pointer to the EMAC device instance.
* \param p_buffer Pointer to the data buffer.
* \param ul_size Length of the frame.
* \param func_tx_cb Transmit callback function.
*
* \return Length sent.
*/
uint32_t emac_dev_write(emac_device_t* p_emac_dev, void *p_buffer,
uint32_t ul_size, emac_dev_tx_cb_t func_tx_cb)
{
volatile emac_tx_descriptor_t *p_tx_td;
volatile emac_dev_tx_cb_t *p_func_tx_cb;
Emac *p_hw = p_emac_dev->p_hw;
/* Check parameter */
if (ul_size > EMAC_TX_UNITSIZE) {
return EMAC_PARAM;
}
/* Pointers to the current transmit descriptor */
p_tx_td = &p_emac_dev->p_tx_dscr[p_emac_dev->us_tx_head];
/* If no free TxTd, buffer can't be sent, schedule the wakeup callback */
if (CIRC_SPACE(p_emac_dev->us_tx_head, p_emac_dev->us_tx_tail,
p_emac_dev->us_tx_list_size) == 0) {
return EMAC_TX_BUSY;
}
/* Pointers to the current Tx callback */
p_func_tx_cb = &p_emac_dev->func_tx_cb_list[p_emac_dev->us_tx_head];
/* Set up/copy data to transmission buffer */
if (p_buffer && ul_size) {
/* Driver manages the ring buffer */
memcpy((void *)p_tx_td->addr, p_buffer, ul_size);
}
/* Tx callback */
*p_func_tx_cb = func_tx_cb;
/* Update transmit descriptor status */
/* The buffer size defined is the length of ethernet frame,
so it's always the last buffer of the frame. */
if (p_emac_dev->us_tx_head == p_emac_dev->us_tx_list_size - 1) {
p_tx_td->status.val =
(ul_size & EMAC_TXD_LEN_MASK) | EMAC_TXD_LAST
| EMAC_TXD_WRAP;
} else {
p_tx_td->status.val =
(ul_size & EMAC_TXD_LEN_MASK) | EMAC_TXD_LAST;
}
circ_inc(&p_emac_dev->us_tx_head, p_emac_dev->us_tx_list_size);
/* Now start to transmit if it is still not done */
emac_start_transmission(p_hw);
return EMAC_OK;
}
/**
* \brief Get current load of transmit.
*
* \param p_emac_dev Pointer to the EMAC device instance.
*
* \return Current load of transmit.
*/
uint32_t emac_dev_get_tx_load(emac_device_t* p_emac_dev)
{
uint16_t us_head = p_emac_dev->us_tx_head;
uint16_t us_tail = p_emac_dev->us_tx_tail;
return CIRC_CNT(us_head, us_tail, p_emac_dev->us_tx_list_size);
}
/**
* \brief Register/Clear RX callback. Callback will be invoked after the next received
* frame.
*
* When emac_dev_read() returns EMAC_RX_NULL, the application task calls
* emac_dev_set_rx_callback() to register func_rx_cb() callback and enters suspend state.
* The callback is in charge to resume the task once a new frame has been
* received. The next time emac_dev_read() is called, it will be successful.
*
* This function is usually invoked from the RX callback itself with NULL
* callback, to unregister. Once the callback has resumed the application task,
* there is no need to invoke the callback again.
*
* \param p_emac_dev Pointer to the EMAC device instance.
* \param func_tx_cb Receive callback function.
*/
void emac_dev_set_rx_callback(emac_device_t* p_emac_dev,
emac_dev_tx_cb_t func_rx_cb)
{
Emac *p_hw = p_emac_dev->p_hw;
if (func_rx_cb == NULL) {
emac_disable_interrupt(p_hw, EMAC_IDR_RCOMP);
p_emac_dev->func_rx_cb = NULL;
} else {
p_emac_dev->func_rx_cb = func_rx_cb;
emac_enable_interrupt(p_hw, EMAC_IER_RCOMP);
}
}
/**
* \brief Register/Clear TX wakeup callback.
*
* When emac_dev_write() returns EMAC_TX_BUSY (all transmit descriptor busy), the application
* task calls emac_dev_set_tx_wakeup_callback() to register func_wakeup() callback and
* enters suspend state. The callback is in charge to resume the task once
* several transmit descriptors have been released. The next time emac_dev_write() will be called,
* it shall be successful.
*
* This function is usually invoked with NULL callback from the TX wakeup
* callback itself, to unregister. Once the callback has resumed the
* application task, there is no need to invoke the callback again.
*
* \param p_emac_dev Pointer to EMAC device instance.
* \param func_wakeup Pointer to wakeup callback function.
* \param uc_threshold Number of free transmit descriptor before wakeup callback invoked.
*
* \return EMAC_OK, EMAC_PARAM on parameter error.
*/
uint8_t emac_dev_set_tx_wakeup_callback(emac_device_t* p_emac_dev,
emac_dev_wakeup_cb_t func_wakeup_cb, uint8_t uc_threshold)
{
if (func_wakeup_cb == NULL) {
p_emac_dev->func_wakeup_cb = NULL;
} else {
if (uc_threshold <= p_emac_dev->us_tx_list_size) {
p_emac_dev->func_wakeup_cb = func_wakeup_cb;
p_emac_dev->uc_wakeup_threshold = uc_threshold;
} else {
return EMAC_PARAM;
}
}
return EMAC_OK;
}
/**
* \brief Reset TX & RX queue & statistics.
*
* \param p_emac_dev Pointer to EMAC device instance.
*/
void emac_dev_reset(emac_device_t* p_emac_dev)
{
Emac *p_hw = p_emac_dev->p_hw;
emac_reset_rx_mem(p_emac_dev);
emac_reset_tx_mem(p_emac_dev);
emac_network_control(p_hw, EMAC_NCR_TE | EMAC_NCR_RE
| EMAC_NCR_WESTAT | EMAC_NCR_CLRSTAT);
}
/**
* \brief EMAC Interrupt handler.
*
* \param p_emac_dev Pointer to EMAC device instance.
*/
void emac_handler(emac_device_t* p_emac_dev)
{
Emac *p_hw = p_emac_dev->p_hw;
emac_tx_descriptor_t *p_tx_td;
emac_dev_tx_cb_t *p_tx_cb;
volatile uint32_t ul_isr;
volatile uint32_t ul_rsr;
volatile uint32_t ul_tsr;
uint32_t ul_rx_status_flag;
uint32_t ul_tx_status_flag;
ul_isr = emac_get_interrupt_status(p_hw);
ul_rsr = emac_get_rx_status(p_hw);
ul_tsr = emac_get_tx_status(p_hw);
ul_isr &= ~(emac_get_interrupt_mask(p_hw) | 0xFFC300);
/* RX packet */
if ((ul_isr & EMAC_ISR_RCOMP) || (ul_rsr & EMAC_RSR_REC)) {
ul_rx_status_flag = EMAC_RSR_REC;
/* Check OVR */
if (ul_rsr & EMAC_RSR_OVR) {
ul_rx_status_flag |= EMAC_RSR_OVR;
}
/* Check BNA */
if (ul_rsr & EMAC_RSR_BNA) {
ul_rx_status_flag |= EMAC_RSR_BNA;
}
/* Clear status */
emac_clear_rx_status(p_hw, ul_rx_status_flag);
/* Invoke callbacks */
if (p_emac_dev->func_rx_cb) {
p_emac_dev->func_rx_cb(ul_rx_status_flag);
}
}
/* TX packet */
if ((ul_isr & EMAC_ISR_TCOMP) || (ul_tsr & EMAC_TSR_COMP)) {
ul_tx_status_flag = EMAC_TSR_COMP;
/* A frame transmitted */
/* Check RLE */
if (ul_tsr & EMAC_TSR_RLES) {
/* Status RLE & Number of discarded buffers */
ul_tx_status_flag = EMAC_TSR_RLES | CIRC_CNT(p_emac_dev->us_tx_head,
p_emac_dev->us_tx_tail, p_emac_dev->us_tx_list_size);
p_tx_cb = &p_emac_dev->func_tx_cb_list[p_emac_dev->us_tx_tail];
emac_reset_tx_mem(p_emac_dev);
emac_enable_transmit(p_hw, 1);
}
/* Check COL */
if (ul_tsr & EMAC_TSR_COL) {
ul_tx_status_flag |= EMAC_TSR_COL;
}
/* Check BEX */
if (ul_tsr & EMAC_TSR_BEX) {
ul_tx_status_flag |= EMAC_TSR_BEX;
}
/* Check UND */
if (ul_tsr & EMAC_TSR_UND) {
ul_tx_status_flag |= EMAC_TSR_UND;
}
/* Clear status */
emac_clear_tx_status(p_hw, ul_tx_status_flag);
if (!CIRC_EMPTY(p_emac_dev->us_tx_head, p_emac_dev->us_tx_tail)) {
/* Check the buffers */
do {
p_tx_td = &p_emac_dev->p_tx_dscr[p_emac_dev->us_tx_tail];
p_tx_cb = &p_emac_dev->func_tx_cb_list[p_emac_dev->us_tx_tail];
/* Any error? Exit if buffer has not been sent yet */
if ((p_tx_td->status.val & EMAC_TXD_USED) == 0) {
break;
}
/* Notify upper layer that a packet has been sent */
if (*p_tx_cb) {
(*p_tx_cb) (ul_tx_status_flag);
}
circ_inc(&p_emac_dev->us_tx_tail, p_emac_dev->us_tx_list_size);
} while (CIRC_CNT(p_emac_dev->us_tx_head, p_emac_dev->us_tx_tail,
p_emac_dev->us_tx_list_size));
}
if (ul_tsr & EMAC_TSR_RLES) {
/* Notify upper layer RLE */
if (*p_tx_cb) {
(*p_tx_cb) (ul_tx_status_flag);
}
}
/* If a wakeup has been scheduled, notify upper layer that it can
send other packets, and the sending will be successful. */
if ((CIRC_SPACE(p_emac_dev->us_tx_head, p_emac_dev->us_tx_tail,
p_emac_dev->us_tx_list_size) >= p_emac_dev->uc_wakeup_threshold)
&& p_emac_dev->func_wakeup_cb) {
p_emac_dev->func_wakeup_cb();
}
}
}
//@}
#endif // SAM3XA_SERIES
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond

View File

@@ -0,0 +1,94 @@
/**
* \file
*
* \brief General Purpose Backup Registers (GPBR) driver for SAM.
*
* Copyright (c) 2011-2012 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* 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.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* 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.
*
* \asf_license_stop
*
*/
#include "gpbr.h"
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
/**
* \defgroup sam_drivers_gpbr_group General Purpose Backup Registers (GPBR)
*
* Driver for the General Purpose Backup Registers. This driver provides access
* to the main features of the GPBR controller.
*
* @{
*/
/**
* \brief Read the specified backup register.
*
* \param ul_reg_num General purpose backup register number.
*
* \return Value of the specified backup register.
*/
uint32_t gpbr_read(gpbr_num_t ul_reg_num)
{
return GPBR->SYS_GPBR[ul_reg_num];
}
/**
* \brief Write a value to the specified backup register.
*
* \param ul_reg_num General purpose backup register number.
* \param ul_value Value to be written.
*/
void gpbr_write(gpbr_num_t ul_reg_num, uint32_t ul_value)
{
GPBR->SYS_GPBR[ul_reg_num] = ul_value;
}
//@}
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond

View File

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

View File

@@ -0,0 +1,386 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \file */
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
/**
* \brief Configures Pio pin internal pull-up.
*
* \param pPio Pointer to a PIO controller.
* \param dwMask Bitmask of one or more pin(s) to configure.
* \param dwPullUpEnable Indicates if the pin(s) internal pull-up shall be configured.
*/
extern void PIO_DisableInterrupt( Pio *pPio, const uint32_t dwMask )
{
/* Disable interrupts on the pin */
pPio->PIO_IDR = dwMask ;
}
/**
* \brief Configures Pio pin internal pull-up.
*
* \param pPio Pointer to a PIO controller.
* \param dwMask Bitmask of one or more pin(s) to configure.
* \param dwPullUpEnable Indicates if the pin(s) internal pull-up shall be configured.
*/
extern void PIO_PullUp( Pio *pPio, const uint32_t dwMask, const uint32_t dwPullUpEnable )
{
/* Enable the pull-up(s) if necessary */
if ( dwPullUpEnable )
{
pPio->PIO_PUER = dwMask ;
}
else
{
pPio->PIO_PUDR = dwMask ;
}
}
/**
* \brief Configures Glitch or Debouncing filter for input.
*
* \param pin Pointer to a Pin instance describing one or more pins.
* \param cuttoff Cutt off frequency for debounce filter.
*/
extern void PIO_SetDebounceFilter( Pio* pPio, const uint32_t dwMask, const uint32_t dwCuttOff )
{
#if (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3N_)
pPio->PIO_IFSCER = dwMask ; /* set Debouncing, 0 bit field no effect */
#elif (defined _SAM3XA_) || (defined _SAM3U_)
pPio->PIO_DIFSR = dwMask ; /* set Debouncing, 0 bit field no effect */
#else
#error "The specified chip is not supported."
#endif
pPio->PIO_SCDR = ((32678/(2*(dwCuttOff))) - 1) & 0x3FFF; /* the lowest 14 bits work */
}
/**
* \brief Sets a high output level on all the PIOs defined in the given Pin instance.
* This has no immediate effects on PIOs that are not output, but the PIO
* controller will memorize the value they are changed to outputs.
*
* \param pin Pointer to a Pin instance describing one or more pins.
*/
extern void PIO_Set( Pio* pPio, const uint32_t dwMask )
{
pPio->PIO_SODR = dwMask ;
}
/**
* \brief Returns 1 if one or more PIO of the given Pin instance currently have
* a high level; otherwise returns 0. This method returns the actual value that
* is being read on the pin. To return the supposed output value of a pin, use
* PIO_GetOutputDataStatus() instead.
*
* \param pin Pointer to a Pin instance describing one or more pins.
*
* \return 1 if the Pin instance contains at least one PIO that currently has
* a high level; otherwise 0.
*/
extern uint32_t PIO_Get( Pio* pPio, const EPioType dwType, const uint32_t dwMask )
{
uint32_t dwReg ;
if ( (dwType == PIO_OUTPUT_0) || (dwType == PIO_OUTPUT_1) )
{
dwReg = pPio->PIO_ODSR ;
}
else
{
dwReg = pPio->PIO_PDSR ;
}
if ( (dwReg & dwMask) == 0 )
{
return 0 ;
}
else
{
return 1 ;
}
}
/**
* \brief Sets a low output level on all the PIOs defined in the given Pin instance.
* This has no immediate effects on PIOs that are not output, but the PIO
* controller will memorize the value they are changed to outputs.
*
* \param pin Pointer to a Pin instance describing one or more pins.
*/
extern void PIO_Clear( Pio* pPio, const uint32_t dwMask )
{
pPio->PIO_CODR = dwMask ;
}
/**
* \brief Configures one pin of a PIO controller as being controlled by specific peripheral.
*
* \param pPio Pointer to a PIO controller.
* \param dwType PIO type.
* \param dwMask Bitmask of one or more pin(s) to configure.
*/
extern void PIO_SetPeripheral( Pio* pPio, EPioType dwType, uint32_t dwMask )
{
uint32_t dwSR ;
/* Disable interrupts on the pin(s) */
pPio->PIO_IDR = dwMask ;
switch ( dwType )
{
case PIO_PERIPH_A :
#if (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3N_)
dwSR = pPio->PIO_ABCDSR[0] ;
pPio->PIO_ABCDSR[0] &= (~dwMask & dwSR) ;
dwSR = pPio->PIO_ABCDSR[1];
pPio->PIO_ABCDSR[1] &= (~dwMask & dwSR) ;
#endif /* (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3N_) */
#if (defined _SAM3U_) || (defined _SAM3XA_)
dwSR = pPio->PIO_ABSR ;
pPio->PIO_ABSR &= (~dwMask & dwSR) ;
#endif /* (defined _SAM3U_) || (defined _SAM3XA_) */
break ;
case PIO_PERIPH_B :
#if (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3N_)
dwSR = pPio->PIO_ABCDSR[0] ;
pPio->PIO_ABCDSR[0] = (dwMask | dwSR) ;
dwSR = pPio->PIO_ABCDSR[1] ;
pPio->PIO_ABCDSR[1] &= (~dwMask & dwSR) ;
#endif /* (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3N_) */
#if (defined _SAM3U_) || (defined _SAM3XA_)
dwSR = pPio->PIO_ABSR ;
pPio->PIO_ABSR = (dwMask | dwSR) ;
#endif /* (defined _SAM3U_) || (defined _SAM3XA_) */
break ;
#if (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3N_)
case PIO_PERIPH_C :
dwSR = pPio->PIO_ABCDSR[0] ;
pPio->PIO_ABCDSR[0] &= (~dwMask & dwSR) ;
dwSR = pPio->PIO_ABCDSR[1] ;
pPio->PIO_ABCDSR[1] = (dwMask | dwSR) ;
break ;
case PIO_PERIPH_D :
dwSR = pPio->PIO_ABCDSR[0] ;
pPio->PIO_ABCDSR[0] = (dwMask | dwSR) ;
dwSR = pPio->PIO_ABCDSR[1] ;
pPio->PIO_ABCDSR[1] = (dwMask | dwSR) ;
break ;
#endif /* (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3N_) */
// other types are invalid in this function
case PIO_INPUT :
case PIO_OUTPUT_0 :
case PIO_OUTPUT_1 :
case PIO_NOT_A_PIN :
return ;
}
// Remove the pins from under the control of PIO
pPio->PIO_PDR = dwMask ;
}
/**
* \brief Configures one or more pin(s) or a PIO controller as inputs. Optionally,
* the corresponding internal pull-up(s) and glitch filter(s) can be enabled.
*
* \param pPio Pointer to a PIO controller.
* \param dwMask Bitmask indicating which pin(s) to configure as input(s).
* \param dwAttribute .
*/
extern void PIO_SetInput( Pio* pPio, uint32_t dwMask, uint32_t dwAttribute )
{
PIO_DisableInterrupt( pPio, dwMask ) ;
PIO_PullUp( pPio, dwMask, dwAttribute & PIO_PULLUP ) ;
/* Enable Input Filter if necessary */
if ( dwAttribute & (PIO_DEGLITCH | PIO_DEBOUNCE) )
{
pPio->PIO_IFER = dwMask ;
}
else
{
pPio->PIO_IFDR = dwMask ;
}
/* Enable de-glitch or de-bounce if necessary */
#if (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3N_)
if ( dwAttribute & PIO_DEGLITCH )
{
pPio->PIO_IFSCDR = dwMask ;
}
else
{
if ( dwAttribute & PIO_DEBOUNCE )
{
pPio->PIO_IFSCER = dwMask ;
}
}
#elif (defined _SAM3U_) || (defined _SAM3XA_)
if ( dwAttribute & PIO_DEGLITCH )
{
pPio->PIO_SCIFSR = dwMask ;
}
else
{
if ( dwAttribute & PIO_DEBOUNCE )
{
pPio->PIO_SCIFSR = dwMask ;
}
}
#else
#error "The specified chip is not supported."
#endif
/* Configure pin as input */
pPio->PIO_ODR = dwMask ;
pPio->PIO_PER = dwMask ;
}
/**
* \brief Configures one or more pin(s) of a PIO controller as outputs, with the
* given default value. Optionally, the multi-drive feature can be enabled
* on the pin(s).
*
* \param pPio Pointer to a PIO controller.
* \param dwMask Bitmask indicating which pin(s) to configure.
* \param defaultValue Default level on the pin(s).
* \param enableMultiDrive Indicates if the pin(s) shall be configured as open-drain.
* \param enablePullUp Indicates if the pin shall have its pull-up activated.
*/
extern void PIO_SetOutput( Pio* pPio, uint32_t dwMask, uint32_t dwDefaultValue,
uint32_t dwMultiDriveEnable, uint32_t dwPullUpEnable )
{
PIO_DisableInterrupt( pPio, dwMask ) ;
PIO_PullUp( pPio, dwMask, dwPullUpEnable ) ;
/* Enable multi-drive if necessary */
if ( dwMultiDriveEnable )
{
pPio->PIO_MDER = dwMask ;
}
else
{
pPio->PIO_MDDR = dwMask ;
}
/* Set default value */
if ( dwDefaultValue )
{
pPio->PIO_SODR = dwMask ;
}
else
{
pPio->PIO_CODR = dwMask ;
}
/* Configure pin(s) as output(s) */
pPio->PIO_OER = dwMask ;
pPio->PIO_PER = dwMask ;
}
/**
*
* \return 1 if the pins have been configured properly; otherwise 0.
*/
extern uint32_t PIO_Configure( Pio* pPio, const EPioType dwType, const uint32_t dwMask, const uint32_t dwAttribute )
{
/* Configure pins */
switch ( dwType )
{
case PIO_PERIPH_A :
case PIO_PERIPH_B :
#if (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3N_)
case PIO_PERIPH_C :
case PIO_PERIPH_D :
#endif /* (defined _SAM3S_) || (defined _SAM3S8_) || (defined _SAM3N_) */
/* Put the pin under control of peripheral */
PIO_SetPeripheral( pPio, dwType, dwMask ) ;
/* Disable interrupts on the pin(s) */
PIO_DisableInterrupt( pPio, dwMask ) ;
/* Enable Pullup */
PIO_PullUp( pPio, dwMask, (dwAttribute & PIO_PULLUP) ) ;
break;
case PIO_INPUT :
PIO_SetInput( pPio, dwMask, dwAttribute ) ;
break;
case PIO_OUTPUT_0 :
case PIO_OUTPUT_1 :
PIO_SetOutput( pPio, dwMask, (dwType == PIO_OUTPUT_1),
(dwAttribute & PIO_OPENDRAIN) ? 1 : 0,
(dwAttribute & PIO_PULLUP) ? 1 : 0);
break ;
default :
return 0 ;
}
return 1 ;
}
/**
* \brief Returns 1 if one or more PIO of the given Pin are configured to output a
* high level (even if they are not output).
* To get the actual value of the pin, use PIO_Get() instead.
*
* \param pPio Pointer to a Pin instance describing one or more pins.
*
* \return 1 if the Pin instance contains at least one PIO that is configured
* to output a high level; otherwise 0.
*/
extern uint32_t PIO_GetOutputDataStatus( const Pio* pPio, const uint32_t dwMask )
{
/* Test if pin is under control of PIO */
if ( (pPio->PIO_PSR & dwMask) != 0 )
{
/* Test if pin is configured as output */
if ( (pPio->PIO_OSR & dwMask) != 0 )
{
return 1 ;
}
}
return 0 ;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,624 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup pwm_module Working with PWM
* The PWM driver provides the interface to configure and use the PWM
* peripheral.
*
* The PWM macrocell controls square output waveforms of 4 channels.
* Characteristics of output waveforms such as period, duty-cycle,
* dead-time can be configured.\n
* Some of PWM channels can be linked together as synchronous ul_channel and
* duty-cycle of synchronous channels can be updated by PDC automaticly.
*
* Before enabling the channels, they must have been configured first.
* The main settings include:
* <ul>
* <li>Configuration of the clock generator.</li>
* <li>Selection of the clock for each ul_channel.</li>
* <li>Configuration of output waveform characteristics, such as period, duty-cycle etc.</li>
* <li>Configuration for synchronous channels if needed.</li>
* - Selection of the synchronous channels.
* - Selection of the moment when the WRDY flag and the corresponding PDC
* transfer request are set (PTRM and PTRCS in the PWM_SCM register).
* - Configuration of the update mode (UPDM in the PWM_SCM register).
* - Configuration of the update period (UPR in the PWM_SCUP register).
* </ul>
*
* After the channels is enabled, the user must use respective update registers
* to change the wave characteristics to prevent unexpected output waveform.
* i.e. PWM_CDTYUPDx register should be used if user want to change duty-cycle
* when the ul_channel is enabled.
*
* For more accurate information, please look at the PWM section of the
* Datasheet.
*
* Related files :\n
* \ref pwmc.c\n
* \ref pwmc.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of the Pulse Width Modulation Controller (PWM) peripheral.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <stdint.h>
#include <assert.h>
/*----------------------------------------------------------------------------
* Local functions
*----------------------------------------------------------------------------*/
/**
* \brief Finds a prescaler/divisor couple to generate the desired frequency
* from MCK.
*
* Returns the value to enter in PWM_CLK or 0 if the configuration cannot be
* met.
*
* \param frequency Desired frequency in Hz.
* \param mck Master clock frequency in Hz.
*/
static uint16_t FindClockConfiguration(
uint32_t frequency,
uint32_t mck)
{
uint32_t divisors[11] = {1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024};
uint8_t divisor = 0;
uint32_t prescaler;
assert(frequency < mck);
/* Find prescaler and divisor values */
prescaler = (mck / divisors[divisor]) / frequency;
while ((prescaler > 255) && (divisor < 11)) {
divisor++;
prescaler = (mck / divisors[divisor]) / frequency;
}
/* Return result */
if ( divisor < 11 )
{
// TRACE_DEBUG( "Found divisor=%u and prescaler=%u for freq=%uHz\n\r", divisors[divisor], prescaler, frequency ) ;
return prescaler | (divisor << 8) ;
}
else
{
return 0 ;
}
}
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Configures PWM a ul_channel with the given parameters, basic configure function.
*
* The PWM controller must have been clocked in the PMC prior to calling this
* function.
* Beware: this function disables the ul_channel. It waits until disable is effective.
*
* \param ul_channel Channel number.
* \param prescaler Channel prescaler.
* \param alignment Channel alignment.
* \param polarity Channel polarity.
*/
void PWMC_ConfigureChannel( Pwm* pPwm, uint32_t ul_channel, uint32_t prescaler, uint32_t alignment, uint32_t polarity )
{
pPwm->PWM_CH_NUM[0].PWM_CMR = 1;
// assert(prescaler < PWM_CMR0_CPRE_MCKB);
assert((alignment & (uint32_t)~PWM_CMR_CALG) == 0);
assert((polarity & (uint32_t)~PWM_CMR_CPOL) == 0);
/* Disable ul_channel (effective at the end of the current period) */
if ((pPwm->PWM_SR & (1 << ul_channel)) != 0) {
pPwm->PWM_DIS = 1 << ul_channel;
while ((pPwm->PWM_SR & (1 << ul_channel)) != 0);
}
/* Configure ul_channel */
pPwm->PWM_CH_NUM[ul_channel].PWM_CMR = prescaler | alignment | polarity;
}
/**
* \brief Configures PWM a ul_channel with the given parameters, extend configure function.
*
* The PWM controller must have been clocked in the PMC prior to calling this
* function.
* Beware: this function disables the ul_channel. It waits until disable is effective.
*
* \param ul_channel Channel number.
* \param prescaler Channel prescaler.
* \param alignment Channel alignment.
* \param polarity Channel polarity.
* \param countEventSelect Channel counter event selection.
* \param DTEnable Channel dead time generator enable.
* \param DTHInverte Channel Dead-Time PWMHx output Inverted.
* \param DTLInverte Channel Dead-Time PWMHx output Inverted.
*/
void PWMC_ConfigureChannelExt( Pwm* pPwm, uint32_t ul_channel, uint32_t prescaler, uint32_t alignment, uint32_t polarity,
uint32_t countEventSelect, uint32_t DTEnable, uint32_t DTHInverte, uint32_t DTLInverte )
{
// assert(prescaler < PWM_CMR0_CPRE_MCKB);
assert((alignment & (uint32_t)~PWM_CMR_CALG) == 0);
assert((polarity & (uint32_t)~PWM_CMR_CPOL) == 0);
assert((countEventSelect & (uint32_t)~PWM_CMR_CES) == 0);
assert((DTEnable & (uint32_t)~PWM_CMR_DTE) == 0);
assert((DTHInverte & (uint32_t)~PWM_CMR_DTHI) == 0);
assert((DTLInverte & (uint32_t)~PWM_CMR_DTLI) == 0);
/* Disable ul_channel (effective at the end of the current period) */
if ((pPwm->PWM_SR & (1 << ul_channel)) != 0) {
pPwm->PWM_DIS = 1 << ul_channel;
while ((pPwm->PWM_SR & (1 << ul_channel)) != 0);
}
/* Configure ul_channel */
pPwm->PWM_CH_NUM[ul_channel].PWM_CMR = prescaler | alignment | polarity |
countEventSelect | DTEnable | DTHInverte | DTLInverte;
}
/**
* \brief Configures PWM clocks A & B to run at the given frequencies.
*
* This function finds the best MCK divisor and prescaler values automatically.
*
* \param clka Desired clock A frequency (0 if not used).
* \param clkb Desired clock B frequency (0 if not used).
* \param mck Master clock frequency.
*/
void PWMC_ConfigureClocks(uint32_t clka, uint32_t clkb, uint32_t mck)
{
uint32_t mode = 0;
uint32_t result;
/* Clock A */
if (clka != 0) {
result = FindClockConfiguration(clka, mck);
assert( result != 0 ) ;
mode |= result;
}
/* Clock B */
if (clkb != 0) {
result = FindClockConfiguration(clkb, mck);
assert( result != 0 ) ;
mode |= (result << 16);
}
/* Configure clocks */
// TRACE_DEBUG( "Setting PWM_CLK = 0x%08X\n\r", mode ) ;
PWM->PWM_CLK = mode;
}
/**
* \brief Sets the period value used by a PWM ul_channel.
*
* This function writes directly to the CPRD register if the ul_channel is disabled;
* otherwise, it uses the update register CPRDUPD.
*
* \param ul_channel Channel number.
* \param period Period value.
*/
void PWMC_SetPeriod( Pwm* pPwm, uint32_t ul_channel, uint16_t period)
{
/* If ul_channel is disabled, write to CPRD */
if ((pPwm->PWM_SR & (1 << ul_channel)) == 0) {
pPwm->PWM_CH_NUM[ul_channel].PWM_CPRD = period;
}
/* Otherwise use update register */
else {
pPwm->PWM_CH_NUM[ul_channel].PWM_CPRDUPD = period;
}
}
/**
* \brief Sets the duty cycle used by a PWM ul_channel.
* This function writes directly to the CDTY register if the ul_channel is disabled;
* otherwise it uses the update register CDTYUPD.
* Note that the duty cycle must always be inferior or equal to the ul_channel
* period.
*
* \param ul_channel Channel number.
* \param duty Duty cycle value.
*/
void PWMC_SetDutyCycle( Pwm* pPwm, uint32_t ul_channel, uint16_t duty)
{
assert(duty <= pPwm->PWM_CH_NUM[ul_channel].PWM_CPRD);
/* If ul_channel is disabled, write to CDTY */
if ((pPwm->PWM_SR & (1 << ul_channel)) == 0) {
pPwm->PWM_CH_NUM[ul_channel].PWM_CDTY = duty;
}
/* Otherwise use update register */
else {
pPwm->PWM_CH_NUM[ul_channel].PWM_CDTYUPD = duty;
}
}
/**
* \brief Sets the dead time used by a PWM ul_channel.
* This function writes directly to the DT register if the ul_channel is disabled;
* otherwise it uses the update register DTUPD.
* Note that the dead time must always be inferior or equal to the ul_channel
* period.
*
* \param ul_channel Channel number.
* \param timeH Dead time value for PWMHx output.
* \param timeL Dead time value for PWMLx output.
*/
void PWMC_SetDeadTime( Pwm* pPwm, uint32_t ul_channel, uint16_t timeH, uint16_t timeL)
{
assert(timeH <= pPwm->PWM_CH_NUM[ul_channel].PWM_CPRD);
assert(timeL <= pPwm->PWM_CH_NUM[ul_channel].PWM_CPRD);
/* If ul_channel is disabled, write to DT */
if ((pPwm->PWM_SR & (1 << ul_channel)) == 0) {
pPwm->PWM_CH_NUM[ul_channel].PWM_DT = timeH | (timeL << 16);
}
/* Otherwise use update register */
else {
pPwm->PWM_CH_NUM[ul_channel].PWM_DTUPD = timeH | (timeL << 16);
}
}
/**
* \brief Configures Syncronous ul_channel with the given parameters.
* Beware: At this time, the channels should be disabled.
*
* \param channels Bitwise OR of Syncronous channels.
* \param updateMode Syncronous ul_channel update mode.
* \param requestMode PDC transfer request mode.
* \param requestComparisonSelect PDC transfer request comparison selection.
*/
void PWMC_ConfigureSyncChannel( Pwm* pPwm, uint32_t ul_channels, uint32_t updateMode, uint32_t requestMode, uint32_t requestComparisonSelect )
{
pPwm->PWM_SCM = ul_channels | updateMode | requestMode | requestComparisonSelect;
}
/**
* \brief Sets the update period of the synchronous channels.
* This function writes directly to the SCUP register if the ul_channel #0 is disabled;
* otherwise it uses the update register SCUPUPD.
*
* \param period update period.
*/
void PWMC_SetSyncChannelUpdatePeriod( Pwm* pPwm, uint8_t period )
{
/* If ul_channel is disabled, write to SCUP */
if ((pPwm->PWM_SR & (1 << 0)) == 0) {
pPwm->PWM_SCUP = period;
}
/* Otherwise use update register */
else {
pPwm->PWM_SCUPUPD = period;
}
}
/**
* \brief Sets synchronous channels update unlock.
*
* Note: If the UPDM field is set to 0, writing the UPDULOCK bit to 1
* triggers the update of the period value, the duty-cycle and
* the dead-time values of synchronous channels at the beginning
* of the next PWM period. If the field UPDM is set to 1 or 2,
* writing the UPDULOCK bit to 1 triggers only the update of
* the period value and of the dead-time values of synchronous channels.
* This bit is automatically reset when the update is done.
*/
void PWMC_SetSyncChannelUpdateUnlock( Pwm* pPwm )
{
pPwm->PWM_SCUC = PWM_SCUC_UPDULOCK;
}
/**
* \brief Enables the given PWM ul_channel.
*
* This does NOT enable the corresponding pin;this must be done in the user code.
*
* \param ul_channel Channel number.
*/
void PWMC_EnableChannel( Pwm* pPwm, uint32_t ul_channel)
{
pPwm->PWM_ENA = 1 << ul_channel;
}
/**
* \brief Disables the given PWM ul_channel.
*
* Beware, ul_channel will be effectively disabled at the end of the current period.
* Application can check ul_channel is disabled using the following wait loop:
* while ((PWM->PWM_SR & (1 << ul_channel)) != 0);
*
* \param ul_channel Channel number.
*/
void PWMC_DisableChannel( Pwm* pPwm, uint32_t ul_channel)
{
pPwm->PWM_DIS = 1 << ul_channel;
}
/**
* \brief Enables the period interrupt for the given PWM ul_channel.
*
* \param ul_channel Channel number.
*/
void PWMC_EnableChannelIt( Pwm* pPwm, uint32_t ul_channel)
{
pPwm->PWM_IER1 = 1 << ul_channel;
}
/**
* \brief Disables the period interrupt for the given PWM ul_channel.
*
* \param ul_channel Channel number.
*/
void PWMC_DisableChannelIt( Pwm* pPwm, uint32_t ul_channel)
{
pPwm->PWM_IDR1 = 1 << ul_channel;
}
/**
* \brief Enables the selected interrupts sources on a PWMC peripheral.
*
* \param sources1 Bitwise OR of selected interrupt sources of PWM_IER1.
* \param sources2 Bitwise OR of selected interrupt sources of PWM_IER2.
*/
void PWMC_EnableIt( Pwm* pPwm, uint32_t sources1, uint32_t sources2)
{
pPwm->PWM_IER1 = sources1;
pPwm->PWM_IER2 = sources2;
}
/**
* \brief Disables the selected interrupts sources on a PWMC peripheral.
*
* \param sources1 Bitwise OR of selected interrupt sources of PWM_IDR1.
* \param sources2 Bitwise OR of selected interrupt sources of PWM_IDR2.
*/
void PWMC_DisableIt( Pwm* pPwm, uint32_t sources1, uint32_t sources2)
{
pPwm->PWM_IDR1 = sources1;
pPwm->PWM_IDR2 = sources2;
}
/**
* \brief Sends the contents of buffer through a PWMC peripheral, using the PDC to
* take care of the transfer.
*
* Note: Duty cycle of syncronous channels can update by PDC
* when the field UPDM (Update Mode) in the PWM_SCM register is set to 2.
*
* \param pwmc Pointer to an Pwm instance.
* \param pvBuffer Data buffer to send.
* \param length Length of the data buffer.
*/
uint8_t PWMC_WriteBuffer( Pwm *pwmc, void* pvBuffer, uint32_t length)
{
/* Check if first bank is free */
if (pwmc->PWM_TCR == 0) {
pwmc->PWM_TPR = (uint32_t) pvBuffer;
pwmc->PWM_TCR = length;
pwmc->PWM_PTCR = PERIPH_PTCR_TXTEN;
return 1;
}
/* Check if second bank is free */
else if (pwmc->PWM_TNCR == 0) {
pwmc->PWM_TNPR = (uint32_t) pvBuffer;
pwmc->PWM_TNCR = length;
return 1;
}
/* No free banks */
return 0;
}
/**
* \brief Set PWM output override value.
*
* \param value Bitwise OR of output override value.
*/
void PWMC_SetOverrideValue( Pwm* pPwm, uint32_t value)
{
pPwm->PWM_OOV = value;
}
/**
* \brief Enalbe override output.
*
* \param value Bitwise OR of output selection.
* \param sync 0: enable the output asyncronously, 1: enable it syncronously
*/
void PWMC_EnableOverrideOutput( Pwm* pPwm, uint32_t value, uint32_t sync)
{
if (sync) {
pPwm->PWM_OSSUPD = value;
} else {
pPwm->PWM_OSS = value;
}
}
/**
* \brief Disalbe override output.
*
* \param value Bitwise OR of output selection.
* \param sync 0: enable the output asyncronously, 1: enable it syncronously
*/
void PWMC_DisableOverrideOutput( Pwm* pPwm, uint32_t value, uint32_t sync)
{
if (sync) {
pPwm->PWM_OSCUPD = value;
} else {
pPwm->PWM_OSC = value;
}
}
/**
* \brief Set PWM fault mode.
*
* \param mode Bitwise OR of fault mode.
*/
void PWMC_SetFaultMode( Pwm* pPwm, uint32_t mode)
{
pPwm->PWM_FMR = mode;
}
/**
* \brief PWM fault clear.
*
* \param fault Bitwise OR of fault to clear.
*/
void PWMC_FaultClear( Pwm* pPwm, uint32_t fault)
{
pPwm->PWM_FCR = fault;
}
/**
* \brief Set PWM fault protection value.
*
* \param value Bitwise OR of fault protection value.
*/
void PWMC_SetFaultProtectionValue( Pwm* pPwm, uint32_t value)
{
pPwm->PWM_FPV = value;
}
/**
* \brief Enable PWM fault protection.
*
* \param value Bitwise OR of FPEx[y].
*/
void PWMC_EnableFaultProtection( Pwm* pPwm, uint32_t ul_channel, uint32_t ul_value)
{
/* Fault Protection Enable Register */
uint32_t ul_fault_enable_reg = 0;
#if (SAM3XA_SERIES)
if (ul_channel < 4)
{
ul_channel *= 8;
ul_fault_enable_reg = pPwm->PWM_FPE1;
ul_fault_enable_reg &= ~(0xFF << ul_channel);
ul_fault_enable_reg |= (ul_value << ul_channel);
pPwm->PWM_FPE1 = ul_fault_enable_reg;
}
else
{
ul_channel -= 4;
ul_channel *= 8;
ul_fault_enable_reg = pPwm->PWM_FPE2;
ul_fault_enable_reg &= ~(0xFF << ul_channel);
ul_fault_enable_reg |= (ul_value << ul_channel);
pPwm->PWM_FPE2 = ul_fault_enable_reg;
}
#endif
#if (SAM3U_SERIES || SAM3S_SERIES || SAM3SD8_SERIES || SAM4S_SERIES)
ul_channel *= 8;
ul_fault_enable_reg = pPwm->PWM_FPE;
ul_fault_enable_reg &= ~(0xFF << ul_channel);
ul_fault_enable_reg |= (ul_value << ul_channel);
pPwm->PWM_FPE = ul_fault_enable_reg;
#endif
}
/**
* \brief Configure comparison unit.
*
* \param x comparison x index
* \param value comparison x value.
* \param mode comparison x mode
*/
void PWMC_ConfigureComparisonUnit( Pwm* pPwm, uint32_t x, uint32_t value, uint32_t mode)
{
assert(x < 8);
/* If ul_channel is disabled, write to CMPxM & CMPxV */
if ((pPwm->PWM_SR & (1 << 0)) == 0) {
pPwm->PWM_CMP[x].PWM_CMPM = mode;
pPwm->PWM_CMP[x].PWM_CMPV = value;
}
/* Otherwise use update register */
else {
pPwm->PWM_CMP[x].PWM_CMPMUPD = mode;
pPwm->PWM_CMP[x].PWM_CMPVUPD = value;
}
}
/**
* \brief Configure event line mode.
*
* \param x Line x
* \param mode Bitwise OR of line mode selection
*/
void PWMC_ConfigureEventLineMode( Pwm* pPwm, uint32_t x, uint32_t mode)
{
assert(x < 2);
if (x == 0)
{
pPwm->PWM_ELMR[0] = mode;
}
else
{
if (x == 1)
{
pPwm->PWM_ELMR[1] = mode;
}
}
}

View File

@@ -0,0 +1,193 @@
/**
* \file
*
* \brief Reset Controller (RSTC) driver for SAM.
*
* Copyright (c) 2011-2012 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* 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.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* 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.
*
* \asf_license_stop
*
*/
#include "rstc.h"
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
/**
* \defgroup sam_drivers_rstc_group Reset Controller (RSTC)
*
* Driver for the RSTC (Reset Controller). This driver provides access to the main
* features of the Reset controller.
*
* @{
*/
#define RSTC_KEY 0xA5000000
/**
* \brief Set external reset length.
*
* \param p_rstc Pointer to an RSTC instance.
* \param ul_length The length of external reset.
*/
void rstc_set_external_reset(Rstc *p_rstc, const uint32_t ul_length)
{
uint32_t mode = p_rstc->RSTC_MR;
mode &= ~(RSTC_MR_ERSTL_Msk | RSTC_MR_KEY_Msk);
mode |= (RSTC_MR_ERSTL(ul_length) | RSTC_KEY);
p_rstc->RSTC_MR = mode;
}
/**
* \brief Enable user reset.
*
* \param p_rstc Pointer to an RSTC instance.
*/
void rstc_enable_user_reset(Rstc *p_rstc)
{
uint32_t mode = p_rstc->RSTC_MR;
mode &= ~RSTC_MR_KEY_Msk;
mode |= (RSTC_MR_URSTEN | RSTC_KEY);
p_rstc->RSTC_MR = mode;
}
/**
* \brief Disable user reset.
*
* \param p_rstc Pointer to an RSTC instance.
*/
void rstc_disable_user_reset(Rstc *p_rstc)
{
uint32_t mode = p_rstc->RSTC_MR;
mode &= ~(RSTC_MR_URSTEN | RSTC_MR_KEY_Msk);
mode |= RSTC_KEY;
p_rstc->RSTC_MR = mode;
}
/**
* \brief Enable user reset interrupt.
*
* \param p_rstc Pointer to an RSTC instance.
*/
void rstc_enable_user_reset_interrupt(Rstc *p_rstc)
{
uint32_t mode = p_rstc->RSTC_MR;
mode &= ~RSTC_MR_KEY_Msk;
mode |= (RSTC_MR_URSTIEN | RSTC_KEY);
p_rstc->RSTC_MR = mode;
}
/**
* \brief Disable user reset interrupt.
*
* \param p_rstc Pointer to an RSTC instance.
*/
void rstc_disable_user_reset_interrupt(Rstc *p_rstc)
{
uint32_t mode = p_rstc->RSTC_MR;
mode &= ~(RSTC_MR_URSTIEN | RSTC_MR_KEY_Msk);
mode |= RSTC_KEY;
p_rstc->RSTC_MR = mode;
}
/**
* \brief Perform software reset.
*
* \param p_rstc Pointer to an RSTC instance.
*/
void rstc_start_software_reset(Rstc *p_rstc)
{
p_rstc->RSTC_CR = RSTC_KEY | RSTC_CR_PROCRST | RSTC_CR_PERRST;
}
/**
* \brief Asserts the NRST pin for external resets.
*
* \param p_rstc Pointer to an RSTC instance.
*/
void rstc_reset_extern(Rstc *p_rstc)
{
p_rstc->RSTC_CR = RSTC_KEY | RSTC_CR_EXTRST;
}
/**
* \brief Get RSTC status.
*
* \param p_rstc Pointer to an RSTC instance.
*
* \return RSTC status.
*/
uint32_t rstc_get_status(Rstc *p_rstc)
{
return p_rstc->RSTC_SR;
}
/**
* \brief Get reset cause.
*
* \param p_rstc Pointer to an RSTC instance.
*
* \return The last reset cause.
*/
uint32_t rstc_get_reset_cause(Rstc *p_rstc)
{
return (p_rstc->RSTC_SR & RSTC_SR_RSTTYP_Msk);
}
//@}
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond

View File

@@ -0,0 +1,450 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup rtc_module Working with RTC
* The RTC driver provides the interface to configure and use the RTC
* peripheral.
*
* It manages date, time, and alarms.\n
* This timer is clocked by the 32kHz system clock, and is not impacted by
* power management settings (PMC). To be accurate, it is better to use an
* external 32kHz crystal instead of the internal 32kHz RC.\n
*
* It uses BCD format, and time can be set in AM/PM or 24h mode through a
* configuration bit in the mode register.\n
*
* To update date or time, the user has to follow these few steps :
* <ul>
* <li>Set UPDTIM and/or UPDCAL bit(s) in RTC_CR,</li>
* <li>Polling or IRQ on the ACKUPD bit of RTC_CR,</li>
* <li>Clear ACKUPD bit in RTC_SCCR,</li>
* <li>Update Time and/or Calendar values in RTC_TIMR/RTC_CALR (BCD format),</li>
* <li>Clear UPDTIM and/or UPDCAL bit in RTC_CR.</li>
* </ul>
* An alarm can be set to happen on month, date, hours, minutes or seconds,
* by setting the proper "Enable" bit of each of these fields in the Time and
* Calendar registers.
* This allows a large number of configurations to be available for the user.
* Alarm occurence can be detected even by polling or interrupt.
*
* A check of the validity of the date and time format and values written by the user is automatically done.
* Errors are reported through the Valid Entry Register.
*
* For more accurate information, please look at the RTC section of the
* Datasheet.
*
* Related files :\n
* \ref rtc.c\n
* \ref rtc.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of Real Time Clock (RTC) controller.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <stdint.h>
#include <assert.h>
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Sets the RTC in either 12 or 24 hour mode.
*
* \param mode Hour mode.
*/
extern void RTC_SetHourMode( Rtc* pRtc, uint32_t dwMode )
{
assert((dwMode & 0xFFFFFFFE) == 0);
pRtc->RTC_MR = dwMode ;
}
/**
* \brief Gets the RTC mode.
*
* \return Hour mode.
*/
extern uint32_t RTC_GetHourMode( Rtc* pRtc )
{
uint32_t dwMode ;
dwMode = pRtc->RTC_MR;
dwMode &= 0xFFFFFFFE;
return dwMode ;
}
/**
* \brief Enables the selected interrupt sources of the RTC.
*
* \param sources Interrupt sources to enable.
*/
extern void RTC_EnableIt( Rtc* pRtc, uint32_t dwSources )
{
assert((dwSources & (uint32_t)(~0x1F)) == 0);
pRtc->RTC_IER = dwSources ;
}
/**
* \brief Disables the selected interrupt sources of the RTC.
*
* \param sources Interrupt sources to disable.
*/
extern void RTC_DisableIt( Rtc* pRtc, uint32_t dwSources )
{
assert((dwSources & (uint32_t)(~0x1F)) == 0);
pRtc->RTC_IDR = dwSources ;
}
/**
* \brief Sets the current time in the RTC.
*
* \note In successive update operations, the user must wait at least one second
* after resetting the UPDTIM/UPDCAL bit in the RTC_CR before setting these
* bits again. Please look at the RTC section of the datasheet for detail.
*
* \param ucHour Current hour in 12 or 24 hour mode.
* \param ucMinute Current minute.
* \param ucSecond Current second.
*
* \return 0 sucess, 1 fail to set
*/
extern int RTC_SetTime( Rtc* pRtc, uint8_t ucHour, uint8_t ucMinute, uint8_t ucSecond )
{
uint32_t dwTime=0 ;
uint8_t ucHour_bcd ;
uint8_t ucMin_bcd ;
uint8_t ucSec_bcd ;
/* if 12-hour mode, set AMPM bit */
if ( (pRtc->RTC_MR & RTC_MR_HRMOD) == RTC_MR_HRMOD )
{
if ( ucHour > 12 )
{
ucHour -= 12 ;
dwTime |= RTC_TIMR_AMPM ;
}
}
ucHour_bcd = (ucHour%10) | ((ucHour/10)<<4) ;
ucMin_bcd = (ucMinute%10) | ((ucMinute/10)<<4) ;
ucSec_bcd = (ucSecond%10) | ((ucSecond/10)<<4) ;
/* value overflow */
if ( (ucHour_bcd & (uint8_t)(~RTC_HOUR_BIT_LEN_MASK)) |
(ucMin_bcd & (uint8_t)(~RTC_MIN_BIT_LEN_MASK)) |
(ucSec_bcd & (uint8_t)(~RTC_SEC_BIT_LEN_MASK)))
{
return 1 ;
}
dwTime = ucSec_bcd | (ucMin_bcd << 8) | (ucHour_bcd<<16) ;
pRtc->RTC_CR |= RTC_CR_UPDTIM ;
while ((pRtc->RTC_SR & RTC_SR_ACKUPD) != RTC_SR_ACKUPD) ;
pRtc->RTC_SCCR = RTC_SCCR_ACKCLR ;
pRtc->RTC_TIMR = dwTime ;
pRtc->RTC_CR &= (uint32_t)(~RTC_CR_UPDTIM) ;
pRtc->RTC_SCCR |= RTC_SCCR_SECCLR ;
return (int)(pRtc->RTC_VER & RTC_VER_NVTIM) ;
}
/**
* \brief Retrieves the current time as stored in the RTC in several variables.
*
* \param pucHour If not null, current hour is stored in this variable.
* \param pucMinute If not null, current minute is stored in this variable.
* \param pucSecond If not null, current second is stored in this variable.
*/
extern void RTC_GetTime( Rtc* pRtc, uint8_t *pucHour, uint8_t *pucMinute, uint8_t *pucSecond )
{
uint32_t dwTime ;
/* Get current RTC time */
dwTime = pRtc->RTC_TIMR ;
while ( dwTime != pRtc->RTC_TIMR )
{
dwTime = pRtc->RTC_TIMR ;
}
/* Hour */
if ( pucHour )
{
*pucHour = ((dwTime & 0x00300000) >> 20) * 10
+ ((dwTime & 0x000F0000) >> 16);
if ( (dwTime & RTC_TIMR_AMPM) == RTC_TIMR_AMPM )
{
*pucHour += 12 ;
}
}
/* Minute */
if ( pucMinute )
{
*pucMinute = ((dwTime & 0x00007000) >> 12) * 10
+ ((dwTime & 0x00000F00) >> 8);
}
/* Second */
if ( pucSecond )
{
*pucSecond = ((dwTime & 0x00000070) >> 4) * 10
+ (dwTime & 0x0000000F);
}
}
/**
* \brief Sets a time alarm on the RTC.
* The match is performed only on the provided variables;
* Setting all pointers to 0 disables the time alarm.
*
* \note In AM/PM mode, the hour value must have bit #7 set for PM, cleared for
* AM (as expected in the time registers).
*
* \param pucHour If not null, the time alarm will hour-match this value.
* \param pucMinute If not null, the time alarm will minute-match this value.
* \param pucSecond If not null, the time alarm will second-match this value.
*
* \return 0 success, 1 fail to set
*/
extern int RTC_SetTimeAlarm( Rtc* pRtc, uint8_t *pucHour, uint8_t *pucMinute, uint8_t *pucSecond )
{
uint32_t dwAlarm=0 ;
/* Hour */
if ( pucHour )
{
dwAlarm |= RTC_TIMALR_HOUREN | ((*pucHour / 10) << 20) | ((*pucHour % 10) << 16);
}
/* Minute */
if ( pucMinute )
{
dwAlarm |= RTC_TIMALR_MINEN | ((*pucMinute / 10) << 12) | ((*pucMinute % 10) << 8);
}
/* Second */
if ( pucSecond )
{
dwAlarm |= RTC_TIMALR_SECEN | ((*pucSecond / 10) << 4) | (*pucSecond % 10);
}
pRtc->RTC_TIMALR = dwAlarm ;
return (int)(pRtc->RTC_VER & RTC_VER_NVTIMALR) ;
}
/**
* \brief Retrieves the current year, month and day from the RTC.
* Month, day and week values are numbered starting at 1.
*
* \param pYwear Current year (optional).
* \param pucMonth Current month (optional).
* \param pucDay Current day (optional).
* \param pucWeek Current day in current week (optional).
*/
extern void RTC_GetDate( Rtc* pRtc, uint16_t *pwYear, uint8_t *pucMonth, uint8_t *pucDay, uint8_t *pucWeek )
{
uint32_t dwDate ;
/* Get current date (multiple reads are necessary to insure a stable value) */
do
{
dwDate = pRtc->RTC_CALR ;
}
while ( dwDate != pRtc->RTC_CALR ) ;
/* Retrieve year */
if ( pwYear )
{
*pwYear = (((dwDate >> 4) & 0x7) * 1000)
+ ((dwDate & 0xF) * 100)
+ (((dwDate >> 12) & 0xF) * 10)
+ ((dwDate >> 8) & 0xF);
}
/* Retrieve month */
if ( pucMonth )
{
*pucMonth = (((dwDate >> 20) & 1) * 10) + ((dwDate >> 16) & 0xF);
}
/* Retrieve day */
if ( pucDay )
{
*pucDay = (((dwDate >> 28) & 0x3) * 10) + ((dwDate >> 24) & 0xF);
}
/* Retrieve week */
if ( pucWeek )
{
*pucWeek = ((dwDate >> 21) & 0x7);
}
}
/**
* \brief Sets the current year, month and day in the RTC.
* Month, day and week values must be numbered starting from 1.
*
* \note In successive update operations, the user must wait at least one second
* after resetting the UPDTIM/UPDCAL bit in the RTC_CR before setting these
* bits again. Please look at the RTC section of the datasheet for detail.
*
* \param wYear Current year.
* \param ucMonth Current month.
* \param ucDay Current day.
* \param ucWeek Day number in current week.
*
* \return 0 success, 1 fail to set
*/
extern int RTC_SetDate( Rtc* pRtc, uint16_t wYear, uint8_t ucMonth, uint8_t ucDay, uint8_t ucWeek )
{
uint32_t wDate ;
uint8_t ucCent_bcd ;
uint8_t ucYear_bcd ;
uint8_t ucMonth_bcd ;
uint8_t ucDay_bcd ;
uint8_t ucWeek_bcd ;
ucCent_bcd = ((wYear/100)%10) | ((wYear/1000)<<4);
ucYear_bcd = (wYear%10) | (((wYear/10)%10)<<4);
ucMonth_bcd = ((ucMonth%10) | (ucMonth/10)<<4);
ucDay_bcd = ((ucDay%10) | (ucDay/10)<<4);
ucWeek_bcd = ((ucWeek%10) | (ucWeek/10)<<4);
/* value over flow */
if ( (ucCent_bcd & (uint8_t)(~RTC_CENT_BIT_LEN_MASK)) |
(ucYear_bcd & (uint8_t)(~RTC_YEAR_BIT_LEN_MASK)) |
(ucMonth_bcd & (uint8_t)(~RTC_MONTH_BIT_LEN_MASK)) |
(ucWeek_bcd & (uint8_t)(~RTC_WEEK_BIT_LEN_MASK)) |
(ucDay_bcd & (uint8_t)(~RTC_DATE_BIT_LEN_MASK))
)
{
return 1 ;
}
/* Convert values to date register value */
wDate = ucCent_bcd |
(ucYear_bcd << 8) |
(ucMonth_bcd << 16) |
(ucWeek_bcd << 21) |
(ucDay_bcd << 24);
/* Update calendar register */
pRtc->RTC_CR |= RTC_CR_UPDCAL ;
while ((pRtc->RTC_SR & RTC_SR_ACKUPD) != RTC_SR_ACKUPD) ;
pRtc->RTC_SCCR = RTC_SCCR_ACKCLR;
pRtc->RTC_CALR = wDate ;
pRtc->RTC_CR &= (uint32_t)(~RTC_CR_UPDCAL) ;
pRtc->RTC_SCCR |= RTC_SCCR_SECCLR; /* clear SECENV in SCCR */
return (int)(pRtc->RTC_VER & RTC_VER_NVCAL) ;
}
/**
* \brief Sets a date alarm in the RTC.
* The alarm will match only the provided values;
* Passing a null-pointer disables the corresponding field match.
*
* \param pucMonth If not null, the RTC alarm will month-match this value.
* \param pucDay If not null, the RTC alarm will day-match this value.
*
* \return 0 success, 1 fail to set
*/
extern int RTC_SetDateAlarm( Rtc* pRtc, uint8_t *pucMonth, uint8_t *pucDay )
{
uint32_t dwAlarm ;
dwAlarm = ((pucMonth) || (pucDay)) ? (0) : (0x01010000);
/* Compute alarm field value */
if ( pucMonth )
{
dwAlarm |= RTC_CALALR_MTHEN | ((*pucMonth / 10) << 20) | ((*pucMonth % 10) << 16);
}
if ( pucDay )
{
dwAlarm |= RTC_CALALR_DATEEN | ((*pucDay / 10) << 28) | ((*pucDay % 10) << 24);
}
/* Set alarm */
pRtc->RTC_CALALR = dwAlarm ;
return (int)(pRtc->RTC_VER & RTC_VER_NVCALALR) ;
}
/**
* \brief Clear flag bits of status clear command register in the RTC.
*
* \param mask Bits mask of cleared events
*/
extern void RTC_ClearSCCR( Rtc* pRtc, uint32_t dwMask )
{
/* Clear all flag bits in status clear command register */
dwMask &= RTC_SCCR_ACKCLR | RTC_SCCR_ALRCLR | RTC_SCCR_SECCLR | RTC_SCCR_TIMCLR | RTC_SCCR_CALCLR ;
pRtc->RTC_SCCR = dwMask ;
}
/**
* \brief Get flag bits of status register in the RTC.
*
* \param mask Bits mask of Status Register
*
* \return Status register & mask
*/
extern uint32_t RTC_GetSR( Rtc* pRtc, uint32_t dwMask )
{
uint32_t dwEvent ;
dwEvent = pRtc->RTC_SR ;
return (dwEvent & dwMask) ;
}

View File

@@ -0,0 +1,132 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup rtt_module Working with RTT
* The RTT driver provides the interface to configure and use the RTT
* peripheral.
*
* The Real-time Timer is used to count elapsed seconds.\n
* This timer is clocked by the 32kHz system clock divided by a programmable
* 16-bit balue. To be accurate, it is better to use an
* external 32kHz crystal instead of the internal 32kHz RC.\n
*
* To count elapsed seconds, the user could follow these few steps:
* <ul>
* <li>Programming PTPRES in RTT_MR to feeding the timer with a 1Hz signal.</li>
* <li>Writing the bit RTTRST in RTT_MR to restart the timer with new settings.</li>
* </ul>
*
* An alarm can be set to happen on second by setting alarm value in RTT_AR.
* Alarm occurence can be detected by polling or interrupt.
*
* For more accurate information, please look at the RTT section of the
* Datasheet.
*
* Related files :\n
* \ref rtt.c\n
* \ref rtt.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of Real Time Timer (RTT) controller.
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <assert.h>
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Changes the prescaler value of the given RTT and restarts it.
*
* \note This function disables RTT interrupt sources.
*
* \param rtt Pointer to a Rtt instance.
* \param prescaler Prescaler value for the RTT.
*/
void RTT_SetPrescaler(Rtt *rtt, uint16_t prescaler)
{
rtt->RTT_MR = (prescaler | RTT_MR_RTTRST);
}
/**
* \brief Returns the current value of the RTT timer value.
*
* \param rtt Pointer to a Rtt instance.
*/
uint32_t RTT_GetTime(Rtt *rtt)
{
return rtt->RTT_VR;
}
/**
* \brief Enables the specified RTT interrupt sources.
*
* \param rtt Pointer to a Rtt instance.
* \param sources Bitmask of interrupts to enable.
*/
void RTT_EnableIT(Rtt *rtt, uint32_t sources)
{
assert( (sources & 0x0004FFFF) == 0 ) ;
rtt->RTT_MR |= sources;
}
/**
* \brief Returns the status register value of the given RTT.
*
* \param rtt Pointer to an Rtt instance.
*/
uint32_t RTT_GetStatus(Rtt *rtt)
{
return rtt->RTT_SR;
}
/**
* \brief Configures the RTT to generate an alarm at the given time.
*
* \param pRtt Pointer to an Rtt instance.
* \param time Alarm time.
*/
void RTT_SetAlarm(Rtt *pRtt, uint32_t time)
{
assert(time > 0);
pRtt->RTT_AR = time - 1;
}

View File

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

View File

@@ -0,0 +1,835 @@
/**
* \file
*
* \brief Synchronous Serial Controller (SSC) driver for SAM.
*
* Copyright (c) 2011-2012 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* 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.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* 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.
*
* \asf_license_stop
*
*/
#include <string.h>
#include "ssc.h"
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
/**
* \defgroup sam_drivers_ssc_group Synchronous Serial Controller (SSC)
*
* The Synchronous Serial Controller (SSC) provides a synchronous communication
* link with external devices. It supports many serial synchronous communication
* protocols generally used in audio and telecom applications such as I2S,
* Short Frame Sync, Long Frame Sync, etc.
* This is a driver for configuration and use of the SSC peripheral.
*
* @{
*/
#define SSC_WPKEY SSC_WPMR_WPKEY(0x535343)
/**
* \brief Set up clock.
*
* \param p_ssc Pointer to an SSC instance.
* \param ul_bitrate Desired bit clock.
* \param ul_mck MCK clock.
*
* \retval SSC_RC_YES Success.
* \retval SSC_RC_NO Invalid input value.
*/
uint32_t ssc_set_clock_divider(Ssc *p_ssc, uint32_t ul_bitrate,
uint32_t ul_mck)
{
if (ul_mck && ul_bitrate) {
p_ssc->SSC_CMR = SSC_CMR_DIV(((ul_mck + ul_bitrate) / ul_bitrate) >> 1);
return SSC_RC_YES;
} else {
return SSC_RC_NO;
}
}
/**
* \brief Setup for I2S transmitter.
*
* \note If working in master mode, the divided clock needs to be configured before
* calling this function according to the sample rate and ul_datlen field.
*
* \param p_ssc Pointer to an SSC instance.
* \param ul_mode Working mode, SSC_I2S_MASTER_OUT or SSC_I2S_SLAVE_OUT.
* \param ul_cks Source clock selection while working in SSC_I2S_SLAVE_OUT mode.
* \param ul_ch_mode Channel mode, stereo or mono.
* \param ul_datlen Data length for one channel.
*/
void ssc_i2s_set_transmitter(Ssc *p_ssc, uint32_t ul_mode,
uint32_t ul_cks, uint32_t ul_ch_mode, uint32_t ul_datlen)
{
clock_opt_t tx_clk_option;
data_frame_opt_t tx_data_frame_option;
/* Initialize the local variable. */
memset((uint8_t *)&tx_clk_option, 0, sizeof(clock_opt_t));
memset((uint8_t *)&tx_data_frame_option, 0, sizeof(data_frame_opt_t));
/* Data start: MonoLeft-Falling, MonoRight-Rising, Stero-Edge. */
switch (ul_ch_mode) {
case SSC_AUDIO_MONO_RIGHT:
tx_clk_option.ul_start_sel = SSC_TCMR_START_RF_RISING;
break;
case SSC_AUDIO_MONO_LEFT:
tx_clk_option.ul_start_sel = SSC_TCMR_START_RF_FALLING;
break;
case SSC_AUDIO_STERO:
tx_clk_option.ul_start_sel = SSC_TCMR_START_RF_EDGE;
break;
}
if (ul_mode & SSC_I2S_MASTER_OUT) {
/* Stereo has 2 data words, and mono has only one data word. */
if (SSC_AUDIO_STERO == ul_ch_mode) {
tx_data_frame_option.ul_datnb = 1;
} else {
tx_data_frame_option.ul_datnb = 0;
}
/* Configure TCMR Settings. */
tx_clk_option.ul_cks = SSC_TCMR_CKS_MCK;
tx_clk_option.ul_cko = SSC_TCMR_CKO_CONTINUOUS;
tx_clk_option.ul_cki = 0;
tx_clk_option.ul_ckg = SSC_RCMR_CKG_NONE;
/* The delay is defined by I2S protocol. */
tx_clk_option.ul_sttdly = 1;
tx_clk_option.ul_period = ul_datlen - 1;
/* Configure TFMR Settings. */
tx_data_frame_option.ul_datlen = ul_datlen - 1;
tx_data_frame_option.ul_msbf = SSC_TFMR_MSBF;
tx_data_frame_option.ul_fslen = ul_datlen - 1;
tx_data_frame_option.ul_fsos = SSC_TFMR_FSOS_NEGATIVE;
tx_data_frame_option.ul_fsedge = SSC_TFMR_FSEDGE_POSITIVE;
} else if (ul_mode & SSC_I2S_SLAVE_OUT) {
/* Configure TCMR Settings. */
tx_clk_option.ul_cks = ul_cks;
tx_clk_option.ul_cko = SSC_TCMR_CKO_NONE;
tx_clk_option.ul_cki = 0;
tx_clk_option.ul_ckg = SSC_RCMR_CKG_NONE;
tx_clk_option.ul_sttdly = 1;
tx_clk_option.ul_period = 0;
/* Configure TFMR Settings. */
tx_data_frame_option.ul_datlen = ul_datlen - 1;
tx_data_frame_option.ul_msbf = SSC_TFMR_MSBF;
tx_data_frame_option.ul_fslen = 0;
tx_data_frame_option.ul_fsos = SSC_TFMR_FSOS_NONE;
tx_data_frame_option.ul_fsedge = SSC_TFMR_FSEDGE_POSITIVE;
}
/* Configure the default level on TD pin. */
ssc_set_td_default_level(p_ssc, 0);
/* Configure the SSC transmitter. */
ssc_set_transmitter(p_ssc, &tx_clk_option, &tx_data_frame_option);
}
/**
* \brief Setup for I2S receiver.
*
* \note If working in master mode, the divided clock needs to be configured before
* calling this function according to the sample rate and ul_datlen field.
*
* \param p_ssc Pointer to an SSC instance.
* \param ul_mode Working mode, SSC_I2S_MASTER_IN or SSC_I2S_SLAVE_IN.
* \param ul_cks Source clock selection while working in SSC_I2S_SLAVE_IN mode.
* \param ul_ch_mode Channel mode, stereo or mono.
* \param ul_datlen Data length for one channel.
*/
void ssc_i2s_set_receiver(Ssc *p_ssc, uint32_t ul_mode,
uint32_t ul_cks, uint32_t ul_ch_mode, uint32_t ul_datlen)
{
clock_opt_t rx_clk_option;
data_frame_opt_t rx_data_frame_option;
/* Initialize the local variable. */
memset((uint8_t *)&rx_clk_option, 0, sizeof(clock_opt_t));
memset((uint8_t *)&rx_data_frame_option, 0, sizeof(data_frame_opt_t));
/* Data start: MonoLeft-Falling, MonoRight-Rising, Stero-Edge. */
switch (ul_ch_mode) {
case SSC_AUDIO_MONO_RIGHT:
rx_clk_option.ul_start_sel = SSC_RCMR_START_RF_RISING;
break;
case SSC_AUDIO_MONO_LEFT:
rx_clk_option.ul_start_sel = SSC_RCMR_START_RF_FALLING;
break;
case SSC_AUDIO_STERO:
rx_clk_option.ul_start_sel = SSC_RCMR_START_RF_EDGE;
break;
}
if (ul_mode & SSC_I2S_MASTER_IN) {
/* Stereo has 2 data words, and mono has only one data word. */
if (SSC_AUDIO_STERO == ul_ch_mode) {
rx_data_frame_option.ul_datnb = 1;
} else {
rx_data_frame_option.ul_datnb = 0;
}
/* Configure RCMR Settings. */
rx_clk_option.ul_cks = SSC_TCMR_CKS_MCK;
rx_clk_option.ul_cko = SSC_TCMR_CKO_CONTINUOUS;
rx_clk_option.ul_cki = 0;
rx_clk_option.ul_ckg = SSC_RCMR_CKG_NONE;
rx_clk_option.ul_sttdly = 1;
rx_clk_option.ul_period = ul_datlen - 1;
/* Configure RFMR Settings. */
rx_data_frame_option.ul_datlen = ul_datlen - 1;
rx_data_frame_option.ul_msbf = SSC_TFMR_MSBF;
rx_data_frame_option.ul_fslen = ul_datlen - 1;
rx_data_frame_option.ul_fsos = SSC_TFMR_FSOS_NEGATIVE;
rx_data_frame_option.ul_fsedge = SSC_TFMR_FSEDGE_POSITIVE;
} else if (ul_mode & SSC_I2S_SLAVE_IN) {
/* Configure TCMR Settings. */
rx_clk_option.ul_cks = ul_cks;
rx_clk_option.ul_cko = SSC_TCMR_CKO_NONE;
rx_clk_option.ul_cki = 0;
rx_clk_option.ul_ckg = SSC_RCMR_CKG_NONE;
rx_clk_option.ul_sttdly = 1;
rx_clk_option.ul_period = 0;
/* Configure TFMR Settings. */
rx_data_frame_option.ul_datlen = ul_datlen - 1;
rx_data_frame_option.ul_msbf = SSC_TFMR_MSBF;
rx_data_frame_option.ul_fslen = 0;
rx_data_frame_option.ul_fsos = SSC_TFMR_FSOS_NONE;
rx_data_frame_option.ul_fsedge = SSC_TFMR_FSEDGE_POSITIVE;
}
/* Configure the SSC receiver. */
ssc_set_receiver(p_ssc, &rx_clk_option, &rx_data_frame_option);
}
/**
* \brief Reset SSC module.
*
* \param p_ssc Pointer to an SSC instance.
*/
void ssc_reset(Ssc *p_ssc)
{
p_ssc->SSC_CR = SSC_CR_SWRST;
p_ssc->SSC_CMR = 0;
p_ssc->SSC_RCMR = 0;
p_ssc->SSC_RFMR = 0;
p_ssc->SSC_TCMR = 0;
p_ssc->SSC_TFMR = 0;
}
/**
* \brief Enable SSC receiver.
*
* \param p_ssc Pointer to an SSC instance.
*/
void ssc_enable_rx(Ssc *p_ssc)
{
p_ssc->SSC_CR = SSC_CR_RXEN;
}
/**
* \brief Disable SSC receiver.
*
* \param p_ssc Pointer to an SSC instance.
*/
void ssc_disable_rx(Ssc *p_ssc)
{
p_ssc->SSC_CR = SSC_CR_RXDIS;
}
/**
* \brief Enable SSC Transmitter.
*
* \param p_ssc Pointer to an SSC instance.
*/
void ssc_enable_tx(Ssc *p_ssc)
{
p_ssc->SSC_CR = SSC_CR_TXEN;
}
/**
* \brief Disable SSC Transmitter.
*
* \param p_ssc Pointer to an SSC instance.
*/
void ssc_disable_tx(Ssc *p_ssc)
{
p_ssc->SSC_CR = SSC_CR_TXDIS;
}
/**
* \brief Configure SSC to work in normal mode.
*
* \param p_ssc Pointer to an SSC instance.
*/
void ssc_set_normal_mode(Ssc *p_ssc)
{
p_ssc->SSC_RFMR &= ~SSC_RFMR_LOOP;
}
/**
* \brief Configure SSC to work in loop mode.
*
* \param p_ssc Pointer to an SSC instance.
*/
void ssc_set_loop_mode(Ssc *p_ssc)
{
p_ssc->SSC_RFMR |= SSC_RFMR_LOOP;
}
/**
* \brief Configure SSC receive stop selection.
*
* \param p_ssc Pointer to an SSC instance.
* \param ul_sel Compare 0 used or Compare both 0 & 1 used.
*/
void ssc_set_rx_stop_selection(Ssc *p_ssc, uint32_t ul_sel)
{
if (SSC_RX_STOP_COMPARE_0_1 == ul_sel) {
p_ssc->SSC_RCMR |= SSC_RCMR_STOP;
} else if (SSC_RX_STOP_COMPARE_0 == ul_sel) {
p_ssc->SSC_RCMR &= ~SSC_RCMR_STOP;
}
}
/**
* \brief Configure SSC default level driven on the TD pin while
* out of transmission.
*
* \param p_ssc Pointer to an SSC instance.
* \param ul_level The default driven level of TD pin.
*/
void ssc_set_td_default_level(Ssc *p_ssc, uint32_t ul_level)
{
if (ul_level) {
p_ssc->SSC_TFMR |= SSC_TFMR_DATDEF;
} else {
p_ssc->SSC_TFMR &= ~SSC_TFMR_DATDEF;
}
}
/**
* \brief The TD line is driven with the SSC_TSHR register value
* during the transmission of the Transmit Frame Sync Signal.
*
* \param p_ssc Pointer to an SSC instance.
*/
void ssc_enable_tx_frame_sync_data(Ssc *p_ssc)
{
p_ssc->SSC_TFMR |= SSC_TFMR_FSDEN;
}
/**
* \brief The TD line is driven with the default value during the Transmit
* Frame Sync signal.
*
* \param p_ssc Pointer to an SSC instance.
*/
void ssc_disable_tx_frame_sync_data(Ssc *p_ssc)
{
p_ssc->SSC_TFMR &= ~SSC_TFMR_FSDEN;
}
/**
* \brief Configure SSC receiver clock mode and date frame configuration.
*
* \param p_ssc Pointer to an SSC instance.
* \param p_rx_clk_opt Pointer to the receiver clock configuration structure.
* \param p_rx_data_frame Pointer to the receiver data frame configuration structure.
*/
void ssc_set_receiver(Ssc *p_ssc, clock_opt_t *p_rx_clk_opt,
data_frame_opt_t *p_rx_data_frame)
{
if (p_rx_clk_opt == NULL) {
p_ssc->SSC_RCMR = 0;
} else {
p_ssc->SSC_RCMR |= p_rx_clk_opt->ul_cks |
p_rx_clk_opt->ul_cko | p_rx_clk_opt->ul_cki |
p_rx_clk_opt->ul_ckg |
p_rx_clk_opt->ul_start_sel |
SSC_RCMR_PERIOD(p_rx_clk_opt->ul_period) |
SSC_RCMR_STTDLY(p_rx_clk_opt->ul_sttdly);
}
if (p_rx_data_frame == NULL) {
p_ssc->SSC_RFMR = 0;
} else {
p_ssc->SSC_RFMR |= SSC_RFMR_DATLEN(p_rx_data_frame->ul_datlen) |
p_rx_data_frame->ul_msbf |
SSC_RFMR_DATNB(p_rx_data_frame->ul_datnb) |
SSC_RFMR_FSLEN(p_rx_data_frame->ul_fslen) |
SSC_RFMR_FSLEN_EXT(p_rx_data_frame->ul_fslen_ext) |
p_rx_data_frame->ul_fsos |
p_rx_data_frame->ul_fsedge;
}
}
/**
* \brief Configure SSC transmitter clock mode and date frame configuration.
*
* \param p_ssc Pointer to an SSC instance.
* \param p_tx_clk_opt Pointer to the transmitter clock configuration structure.
* \param p_tx_data_frame Pointer to the transmitter data frame configuration structure.
*/
void ssc_set_transmitter(Ssc *p_ssc, clock_opt_t *p_tx_clk_opt,
data_frame_opt_t *p_tx_data_frame)
{
if (p_tx_clk_opt == NULL) {
p_ssc->SSC_TCMR = 0;
} else {
p_ssc->SSC_TCMR |= p_tx_clk_opt->ul_cks |
p_tx_clk_opt->ul_cko | p_tx_clk_opt->ul_cki |
p_tx_clk_opt->ul_ckg |
p_tx_clk_opt->ul_start_sel |
SSC_RCMR_PERIOD(p_tx_clk_opt->ul_period) |
SSC_RCMR_STTDLY(p_tx_clk_opt->ul_sttdly);
}
if (p_tx_data_frame == NULL) {
p_ssc->SSC_TFMR = 0;
} else {
p_ssc->SSC_TFMR |= SSC_RFMR_DATLEN(p_tx_data_frame->ul_datlen) |
p_tx_data_frame->ul_msbf |
SSC_RFMR_DATNB(p_tx_data_frame->ul_datnb) |
SSC_RFMR_FSLEN(p_tx_data_frame->ul_fslen) |
SSC_RFMR_FSLEN_EXT(p_tx_data_frame->ul_fslen_ext) |
p_tx_data_frame->ul_fsos |
p_tx_data_frame->ul_fsedge;
}
}
/**
* \brief Configure SSC Receive Compare Register.
*
* \param p_ssc Pointer to an SSC instance.
* \param ul_id Compare register ID.
* \param ul_value Value to configure.
*/
void ssc_set_rx_compare(Ssc *p_ssc, uint32_t ul_id, uint32_t ul_value)
{
switch (ul_id) {
case COMPARE_ID0:
p_ssc->SSC_RC0R = ul_value;
break;
case COMPARE_ID1:
p_ssc->SSC_RC1R = ul_value;
break;
}
}
/**
* \brief Get SSC Receive Compare Register.
*
* \param p_ssc Pointer to an SSC instance.
* \param ul_id Compare register ID.
*
* \return Receive Compare Register value for the specified ul_id, otherwise SSC_RC_INVALID.
*/
uint32_t ssc_get_rx_compare(Ssc *p_ssc, uint32_t ul_id)
{
switch (ul_id) {
case COMPARE_ID0:
return p_ssc->SSC_RC0R;
case COMPARE_ID1:
return p_ssc->SSC_RC1R;
default:
return SSC_RC_INVALID;
}
}
/**
* \brief Enable SSC interrupts.
*
* \param p_ssc Pointer to an SSC instance.
* \param ul_sources Interrupts to be enabled.
*/
void ssc_enable_interrupt(Ssc *p_ssc, uint32_t ul_sources)
{
p_ssc->SSC_IER = ul_sources;
}
/**
* \brief Disable SSC interrupts.
*
* \param p_ssc Pointer to an SSC instance.
* \param ul_sources Interrupts to be enabled.
*/
void ssc_disable_interrupt(Ssc *p_ssc, uint32_t ul_sources)
{
p_ssc->SSC_IDR = ul_sources;
}
/**
* \brief Read SSC interrupt mask.
*
* \param p_ssc Pointer to an SSC instance.
*
* \return The interrupt mask value.
*/
uint32_t ssc_get_interrupt_mask(Ssc *p_ssc)
{
return p_ssc->SSC_IMR;
}
/**
* \brief Read SSC status.
*
* \param p_ssc Pointer to an SSC instance.
*
* \return The SSC status value.
*/
uint32_t ssc_get_status(Ssc *p_ssc)
{
return p_ssc->SSC_SR;
}
/**
* \brief Check if data has been loaded in SSC_THR and is waiting to be loaded
* in the Transmit Shift Register (TSR).
*
* \param p_ssc Pointer to an SSC instance.
*
* \retval SSC_RC_YES There is no data in the SSC_THR.
* \retval SSC_RC_NO There is one data in the SSC_THR.
*/
uint32_t ssc_is_tx_ready(Ssc *p_ssc)
{
if (p_ssc->SSC_SR & SSC_SR_TXRDY) {
return SSC_RC_YES;
}
return SSC_RC_NO;
}
/**
* \brief Check if the last data written in SSC_THR has been loaded in TSR
* and the last data loaded in TSR has been transmitted.
*
* \param p_ssc Pointer to an SSC instance.
*
* \retval SSC_RC_YES Both of the two registers are empty.
* \retval SSC_RC_NO At least one of the two registers is not empty.
*/
uint32_t ssc_is_tx_empty(Ssc *p_ssc)
{
if (p_ssc->SSC_SR & SSC_SR_TXEMPTY) {
return SSC_RC_YES;
}
return SSC_RC_NO;
}
/**
* \brief Check if data has been received and loaded in SSC_RHR.
*
* \param p_ssc Pointer to an SSC instance.
*
* \retval SSC_RC_YES There is one data in the SSC_RHR.
* \retval SSC_RC_NO There is no data in the SSC_RHR.
*/
uint32_t ssc_is_rx_ready(Ssc *p_ssc)
{
if (p_ssc->SSC_SR & SSC_SR_RXRDY) {
return SSC_RC_YES;
}
return SSC_RC_NO;
}
/**
* \brief Check if transmitter is enabled.
*
* \param p_ssc Pointer to an SSC instance.
*
* \retval SSC_RC_YES The transmitter is enabled.
* \retval SSC_RC_NO The transmitter is disabled.
*/
uint32_t ssc_is_tx_enabled(Ssc *p_ssc)
{
if (p_ssc->SSC_SR & SSC_SR_TXEN) {
return SSC_RC_YES;
}
return SSC_RC_NO;
}
/**
* \brief Check if receiver is enabled.
*
* \param p_ssc Pointer to an SSC instance.
*
* \retval SSC_RC_YES The receiver is enabled.
* \retval SSC_RC_NO The receiver is disabled.
*/
uint32_t ssc_is_rx_enabled(Ssc *p_ssc)
{
if (p_ssc->SSC_SR & SSC_SR_RXEN) {
return SSC_RC_YES;
}
return SSC_RC_NO;
}
#if (SAM3S_SERIES) || (SAM4S_SERIES)
/**
* \brief Check if one receive buffer is filled.
*
* \param p_ssc Pointer to an SSC instance.
*
* \retval SSC_RC_YES Receive Counter has reached zero.
* \retval SSC_RC_NO Data is written on the Receive Counter Register or
* Receive Next Counter Register.
*/
uint32_t ssc_is_rx_buf_end(Ssc *p_ssc)
{
if (p_ssc->SSC_SR & SSC_SR_ENDRX) {
return SSC_RC_YES;
}
return SSC_RC_NO;
}
/**
* \brief Check if the register SSC_TCR has reached 0.
*
* \param p_ssc Pointer to an SSC instance.
*
* \retval SSC_RC_YES The register SSC_TCR has reached 0.
* \retval SSC_RC_NO The register SSC_TCR hasn't reached 0.
*/
uint32_t ssc_is_tx_buf_end(Ssc *p_ssc)
{
if (p_ssc->SSC_SR & SSC_SR_ENDTX) {
return SSC_RC_YES;
}
return SSC_RC_NO;
}
/**
* \brief Check if both receive buffers are full.
*
* \param p_ssc Pointer to an SSC instance.
*
* \retval SSC_RC_YES Both of the two receive buffers have reached 0.
* \retval SSC_RC_NO One of the two receive buffers hasn't reached 0.
*/
uint32_t ssc_is_rx_buf_full(Ssc *p_ssc)
{
if (p_ssc->SSC_SR & SSC_SR_RXBUFF) {
return SSC_RC_YES;
}
return SSC_RC_NO;
}
/**
* \brief Check if both transmit buffers are empty.
*
* \param p_ssc Pointer to an SSC instance.
*
* \retval SSC_RC_YES Both of the two transmit buffers have reached 0.
* \retval SSC_RC_NO One of the two transmit buffers hasn't reached 0.
*/
uint32_t ssc_is_tx_buf_empty(Ssc *p_ssc)
{
if (p_ssc->SSC_SR & SSC_SR_TXBUFE) {
return SSC_RC_YES;
}
return SSC_RC_NO;
}
/**
* \brief Get SSC PDC registers base address.
*
* \param p_ssc Pointer to SSC registers set instance.
*
* \return SSC PDC registers base address for PDC driver to access.
*/
Pdc *ssc_get_pdc_base(Ssc *p_ssc)
{
return (Pdc *)&(p_ssc->SSC_RPR);
}
#endif // (SAM3S_SERIES) || (SAM4S_SERIES)
/**
* \brief Write to SSC Transmit Holding Register.
* Send data through SSC Data frame.
*
* \param p_ssc Pointer to an SSC instance.
* \param ul_frame Frame data to be transmitted.
*
* \retval SSC_RC_ERROR Time-out.
* \retval SSC_RC_OK Success.
*
*/
uint32_t ssc_write(Ssc *p_ssc, uint32_t ul_frame)
{
uint32_t ul_timeout = SSC_DEFAULT_TIMEOUT;
while (!(p_ssc->SSC_SR & SSC_SR_TXEMPTY)) {
if (!ul_timeout--) {
return SSC_RC_ERROR;
}
}
p_ssc->SSC_THR = ul_frame;
return SSC_RC_OK;
}
/**
* \brief Read from SSC Receive Holding Register.
* Read data that is received in SSC Data frame.
*
* \param p_ssc Pointer to an SSC instance.
* \param ul_data Pointer to the location where to store the received data.
*
* \retval SSC_RC_ERROR Time-out.
* \retval SSC_RC_OK Success.
*/
uint32_t ssc_read(Ssc *p_ssc, uint32_t *ul_data)
{
uint32_t ul_timeout = SSC_DEFAULT_TIMEOUT;
while (!(p_ssc->SSC_SR & SSC_SR_RXRDY)) {
if (!ul_timeout--) {
return SSC_RC_ERROR;
}
}
*ul_data = p_ssc->SSC_RHR;
return SSC_RC_OK;
}
/**
* \brief Write to SSC Transmit Synchronization Holding Register.
* Send data through SSC Synchronization frame. If there is sync data that needs to be
* transmitted, call this function first to send out the sync data, and then call the
* ssc_write() function to send out application data.
*
* \param p_ssc Pointer to an SSC instance.
* \param ul_frame Frame Synchronization data.
*/
void ssc_write_sync_data(Ssc *p_ssc, uint32_t ul_frame)
{
p_ssc->SSC_TSHR = ul_frame;
}
/**
* \brief Read from SSC Receive Synchronization Holding Register.
* Read data that is received in SSC Synchronization frame. When the sync data is actually
* used, after successfully reading the application data by calling ssc_read(), call
* this function, and the return sync data is useful.
*
* \param p_ssc Pointer to an SSC instance.
*
* \return Current RSHR value.
*/
uint32_t ssc_read_sync_data(Ssc *p_ssc)
{
return p_ssc->SSC_RSHR;
}
#if (SAM3XA_SERIES || SAM3U_SERIES)
/**
* \brief Get Transmit address for DMA operation.
*
* \param p_ssc Pointer to an SSC instance.
*
* \return Transmitting address for DMA access.
*/
void *ssc_get_tx_access(Ssc *p_ssc)
{
return (void *)&(p_ssc->SSC_THR);
}
/**
* \brief Get Receive address for DMA operation.
*
* \param p_ssc Pointer to an SSC instance.
*
* \return Transmitting address for DMA access.
*/
void *ssc_get_rx_access(Ssc *p_ssc)
{
return (void *)&(p_ssc->SSC_RHR);
}
#endif // (SAM3XA_SERIES || SAM3U_SERIES)
/**
* \brief Enable or disable write protection of SSC registers.
*
* \param p_ssc Pointer to an SSC instance.
* \param ul_enable 1 to enable, 0 to disable.
*/
void ssc_set_writeprotect(Ssc *p_ssc, uint32_t ul_enable)
{
if (ul_enable) {
p_ssc->SSC_WPMR = SSC_WPKEY | SSC_WPMR_WPEN;
} else {
p_ssc->SSC_WPMR = SSC_WPKEY;
}
}
/**
* \brief Indicate write protect status.
*
* \param p_ssc Pointer to an SSC instance.
*
* \return 0 if the peripheral is not protected. Write Protect Violation Status otherwise.
*/
uint32_t ssc_get_writeprotect_status(Ssc *p_ssc)
{
uint32_t ul_reg_val;
ul_reg_val = p_ssc->SSC_WPMR;
if (ul_reg_val & SSC_WPMR_WPEN) {
return (ul_reg_val & SSC_WPSR_WPVSRC_Msk) >> SSC_WPSR_WPVSRC_Pos;
} else {
return 0;
}
}
//@}
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond

View File

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

View File

@@ -0,0 +1,118 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/**
* \file
* Implement simple system tick usage.
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
/*----------------------------------------------------------------------------
* Local variables
*----------------------------------------------------------------------------*/
/** Tick Counter united by ms */
static volatile uint32_t _dwTickCount=0 ;
/*----------------------------------------------------------------------------
* Exported Functions
*----------------------------------------------------------------------------*/
/**
* \brief Handler for Sytem Tick interrupt.
*/
extern void TimeTick_Increment( void )
{
_dwTickCount++ ;
}
/**
* \brief Configures the SAM3 SysTick & reset tickCount.
* Systick interrupt handler will generates 1ms interrupt and increase a
* tickCount.
* \param dwNew_MCK Current master clock.
*/
extern uint32_t TimeTick_Configure( uint32_t dwNew_MCK )
{
_dwTickCount = 0 ;
return SysTick_Config( dwNew_MCK/1000 ) ;
}
/**
* \brief Get current Tick Count, in ms.
*/
extern uint32_t GetTickCount( void )
{
return _dwTickCount ;
}
/**
* \brief Sync Wait for several ms
*/
extern void Wait( volatile uint32_t dwMs )
{
uint32_t dwStart ;
uint32_t dwCurrent ;
dwStart = _dwTickCount ;
do
{
dwCurrent = _dwTickCount ;
} while ( dwCurrent - dwStart < dwMs ) ;
}
/**
* \brief Sync Sleep for several ms
*/
extern void Sleep( volatile uint32_t dwMs )
{
uint32_t dwStart ;
uint32_t dwCurrent ;
dwStart = _dwTickCount ;
do
{
dwCurrent = _dwTickCount ;
if ( dwCurrent - dwStart > dwMs )
{
break ;
}
__WFI() ;
} while( 1 ) ;
}

View File

@@ -0,0 +1,160 @@
/**
* \file
*
* \brief TRNG driver for SAM.
*
* Copyright (c) 2011-2012 Atmel Corporation. All rights reserved.
*
* \asf_license_start
*
* \page License
*
* 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.
*
* 4. This software may only be redistributed and used in connection with an
* Atmel microcontroller product.
*
* THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* 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.
*
* \asf_license_stop
*
*/
/**
* \defgroup group_sam_drivers_trng TRNG - True Random Number Generator
*
* Driver for the TRNG (True Random Number Generator). This driver provides access
* to the main features of the TRNG controller.
*
* \{
*/
#include "../chip.h"
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
extern "C" {
#endif
/**INDENT-ON**/
/// @endcond
#if SAM3XA_SERIES
/* TRNG Security Key Value */
#define TRNG_KEY 0x524E47
/**
* \brief Enable TRNG.
*
* \param p_trng Pointer to a TRNG instance.
*
*/
void trng_enable(Trng *p_trng)
{
p_trng->TRNG_CR = TRNG_CR_ENABLE | TRNG_CR_KEY(TRNG_KEY);
}
/**
* \brief Disable TRNG.
*
* \param p_trng Pointer to a TRNG instance.
*
*/
void trng_disable(Trng *p_trng)
{
p_trng->TRNG_CR = TRNG_CR_KEY(TRNG_KEY);
}
/**
* \brief Enable TRNG interrupt.
*
* \param p_trng Pointer to a TRNG instance.
*
*/
void trng_enable_interrupt(Trng *p_trng)
{
p_trng->TRNG_IER = TRNG_IER_DATRDY;
}
/**
* \brief Disable TRNG interrupt.
*
* \param p_trng Pointer to a TRNG instance.
*
*/
void trng_disable_interrupt(Trng *p_trng)
{
p_trng->TRNG_IDR = TRNG_IER_DATRDY;
}
/**
* \brief Get TRNG interrupt mask.
*
* \param p_trng Pointer to a TRNG instance.
*
* \retval The interrupt mask value.
*/
uint32_t trng_get_interrupt_mask(Trng *p_trng)
{
return p_trng->TRNG_IMR;
}
/**
* \brief Get TRNG interrupt status.
*
* \param p_trng Pointer to a TRNG instance.
*
* \retval The interrupt status value.
*/
uint32_t trng_get_interrupt_status(Trng *p_trng)
{
return p_trng->TRNG_ISR;
}
/**
* \brief Read TRNG output data.
*
* \param p_trng Pointer to a TRNG instance.
*
* \retval The output data value.
*/
uint32_t trng_read_output_data(Trng *p_trng)
{
return p_trng->TRNG_ODATA;
}
#endif // SAM3XA_SERIES
/// @cond 0
/**INDENT-OFF**/
#ifdef __cplusplus
}
#endif
/**INDENT-ON**/
/// @endcond
/**
* \}
*/

View File

@@ -0,0 +1,380 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
/** \addtogroup twi_module Working with TWI
* The TWI driver provides the interface to configure and use the TWI
* peripheral.
*
* \section Usage
* <ul>
* <li> Configures a TWI peripheral to operate in master mode, at the given
* frequency (in Hz) using TWI_Configure(). </li>
* <li> Sends a STOP condition on the TWI using TWI_Stop().</li>
* <li> Starts a read operation on the TWI bus with the specified slave using
* TWI_StartRead(). Data must then be read using TWI_ReadByte() whenever
* a byte is available (poll using TWI_ByteReceived()).</li>
* <li> Starts a write operation on the TWI to access the selected slave using
* TWI_StartWrite(). A byte of data must be provided to start the write;
* other bytes are written next.</li>
* <li> Sends a byte of data to one of the TWI slaves on the bus using TWI_WriteByte().
* This function must be called once before TWI_StartWrite() with the first byte of data
* to send, then it shall be called repeatedly after that to send the remaining bytes.</li>
* <li> Check if a byte has been received and can be read on the given TWI
* peripheral using TWI_ByteReceived().<
* Check if a byte has been sent using TWI_ByteSent().</li>
* <li> Check if the current transmission is complete (the STOP has been sent)
* using TWI_TransferComplete().</li>
* <li> Enables & disable the selected interrupts sources on a TWI peripheral
* using TWI_EnableIt() and TWI_DisableIt().</li>
* <li> Get current status register of the given TWI peripheral using
* TWI_GetStatus(). Get current status register of the given TWI peripheral, but
* masking interrupt sources which are not currently enabled using
* TWI_GetMaskedStatus().</li>
* </ul>
* For more accurate information, please look at the TWI section of the
* Datasheet.
*
* Related files :\n
* \ref twi.c\n
* \ref twi.h.\n
*/
/*@{*/
/*@}*/
/**
* \file
*
* Implementation of Two Wire Interface (TWI).
*
*/
/*----------------------------------------------------------------------------
* Headers
*----------------------------------------------------------------------------*/
#include "chip.h"
#include <stdlib.h>
#include <assert.h>
/*----------------------------------------------------------------------------
* Exported functions
*----------------------------------------------------------------------------*/
/**
* \brief Configures a TWI peripheral to operate in master mode, at the given
* frequency (in Hz). The duty cycle of the TWI clock is set to 50%.
* \param pTwi Pointer to an Twi instance.
* \param twck Desired TWI clock frequency.
* \param mck Master clock frequency.
*/
void TWI_ConfigureMaster( Twi* pTwi, uint32_t dwTwCk, uint32_t dwMCk )
{
uint32_t dwCkDiv = 0 ;
uint32_t dwClDiv ;
uint32_t dwOk = 0 ;
assert( pTwi ) ;
/* SVEN: TWI Slave Mode Enabled */
pTwi->TWI_CR = TWI_CR_SVEN ;
/* Reset the TWI */
pTwi->TWI_CR = TWI_CR_SWRST ;
pTwi->TWI_RHR ;
/* TWI Slave Mode Disabled, TWI Master Mode Disabled. */
pTwi->TWI_CR = TWI_CR_SVDIS ;
pTwi->TWI_CR = TWI_CR_MSDIS ;
/* Set master mode */
pTwi->TWI_CR = TWI_CR_MSEN ;
/* Configure clock */
while ( !dwOk )
{
dwClDiv = ((dwMCk / (2 * dwTwCk)) - 4) / (1<<dwCkDiv) ;
if ( dwClDiv <= 255 )
{
dwOk = 1 ;
}
else
{
dwCkDiv++ ;
}
}
assert( dwCkDiv < 8 ) ;
// TRACE_DEBUG( "Using CKDIV = %u and CLDIV/CHDIV = %u\n\r", dwCkDiv, dwClDiv ) ;
pTwi->TWI_CWGR = 0 ;
pTwi->TWI_CWGR = (dwCkDiv << 16) | (dwClDiv << 8) | dwClDiv ;
}
/**
* \brief Configures a TWI peripheral to operate in slave mode.
* \param pTwi Pointer to an Twi instance.
* \param slaveAddress Slave address.
*/
void TWI_ConfigureSlave(Twi *pTwi, uint8_t slaveAddress)
{
uint32_t i;
/* TWI software reset */
pTwi->TWI_CR = TWI_CR_SWRST;
pTwi->TWI_RHR;
/* Wait at least 10 ms */
for (i=0; i < 1000000; i++);
/* TWI Slave Mode Disabled, TWI Master Mode Disabled*/
pTwi->TWI_CR = TWI_CR_SVDIS | TWI_CR_MSDIS;
/* Configure slave address. */
pTwi->TWI_SMR = 0;
pTwi->TWI_SMR = TWI_SMR_SADR(slaveAddress);
/* SVEN: TWI Slave Mode Enabled */
pTwi->TWI_CR = TWI_CR_SVEN;
/* Wait at least 10 ms */
for (i=0; i < 1000000; i++);
assert( (pTwi->TWI_CR & TWI_CR_SVDIS)!= TWI_CR_SVDIS ) ;
}
/**
* \brief Sends a STOP condition on the TWI.
* \param pTwi Pointer to an Twi instance.
*/
void TWI_Stop( Twi *pTwi )
{
assert( pTwi != NULL ) ;
pTwi->TWI_CR = TWI_CR_STOP;
}
/**
* \brief Starts a read operation on the TWI bus with the specified slave, it returns
* immediately. Data must then be read using TWI_ReadByte() whenever a byte is
* available (poll using TWI_ByteReceived()).
* \param pTwi Pointer to an Twi instance.
* \param address Slave address on the bus.
* \param iaddress Optional internal address bytes.
* \param isize Number of internal address bytes.
*/
void TWI_StartRead(
Twi *pTwi,
uint8_t address,
uint32_t iaddress,
uint8_t isize)
{
assert( pTwi != NULL ) ;
assert( (address & 0x80) == 0 ) ;
assert( (iaddress & 0xFF000000) == 0 ) ;
assert( isize < 4 ) ;
/* Set slave address and number of internal address bytes. */
pTwi->TWI_MMR = 0;
pTwi->TWI_MMR = (isize << 8) | TWI_MMR_MREAD | (address << 16);
/* Set internal address bytes */
pTwi->TWI_IADR = 0;
pTwi->TWI_IADR = iaddress;
/* Send START condition */
pTwi->TWI_CR = TWI_CR_START;
}
/**
* \brief Reads a byte from the TWI bus. The read operation must have been started
* using TWI_StartRead() and a byte must be available (check with TWI_ByteReceived()).
* \param pTwi Pointer to an Twi instance.
* \return byte read.
*/
uint8_t TWI_ReadByte(Twi *pTwi)
{
assert( pTwi != NULL ) ;
return pTwi->TWI_RHR;
}
/**
* \brief Sends a byte of data to one of the TWI slaves on the bus.
* \note This function must be called once before TWI_StartWrite() with
* the first byte of data to send, then it shall be called repeatedly
* after that to send the remaining bytes.
* \param pTwi Pointer to an Twi instance.
* \param byte Byte to send.
*/
void TWI_WriteByte(Twi *pTwi, uint8_t byte)
{
assert( pTwi != NULL ) ;
pTwi->TWI_THR = byte;
}
/**
* \brief Starts a write operation on the TWI to access the selected slave, then
* returns immediately. A byte of data must be provided to start the write;
* other bytes are written next.
* after that to send the remaining bytes.
* \param pTwi Pointer to an Twi instance.
* \param address Address of slave to acccess on the bus.
* \param iaddress Optional slave internal address.
* \param isize Number of internal address bytes.
* \param byte First byte to send.
*/
void TWI_StartWrite(
Twi *pTwi,
uint8_t address,
uint32_t iaddress,
uint8_t isize,
uint8_t byte)
{
assert( pTwi != NULL ) ;
assert( (address & 0x80) == 0 ) ;
assert( (iaddress & 0xFF000000) == 0 ) ;
assert( isize < 4 ) ;
/* Set slave address and number of internal address bytes. */
pTwi->TWI_MMR = 0;
pTwi->TWI_MMR = (isize << 8) | (address << 16);
/* Set internal address bytes. */
pTwi->TWI_IADR = 0;
pTwi->TWI_IADR = iaddress;
/* Write first byte to send.*/
TWI_WriteByte(pTwi, byte);
}
/**
* \brief Check if a byte have been receiced from TWI.
* \param pTwi Pointer to an Twi instance.
* \return 1 if a byte has been received and can be read on the given TWI
* peripheral; otherwise, returns 0. This function resets the status register.
*/
uint8_t TWI_ByteReceived(Twi *pTwi)
{
return ((pTwi->TWI_SR & TWI_SR_RXRDY) == TWI_SR_RXRDY);
}
/**
* \brief Check if a byte have been sent to TWI.
* \param pTwi Pointer to an Twi instance.
* \return 1 if a byte has been sent so another one can be stored for
* transmission; otherwise returns 0. This function clears the status register.
*/
uint8_t TWI_ByteSent(Twi *pTwi)
{
return ((pTwi->TWI_SR & TWI_SR_TXRDY) == TWI_SR_TXRDY);
}
/**
* \brief Check if current transmission is complet.
* \param pTwi Pointer to an Twi instance.
* \return 1 if the current transmission is complete (the STOP has been sent);
* otherwise returns 0.
*/
uint8_t TWI_TransferComplete(Twi *pTwi)
{
return ((pTwi->TWI_SR & TWI_SR_TXCOMP) == TWI_SR_TXCOMP);
}
/**
* \brief Enables the selected interrupts sources on a TWI peripheral.
* \param pTwi Pointer to an Twi instance.
* \param sources Bitwise OR of selected interrupt sources.
*/
void TWI_EnableIt(Twi *pTwi, uint32_t sources)
{
assert( pTwi != NULL ) ;
assert( (sources & 0xFFFFF088) == 0 ) ;
pTwi->TWI_IER = sources;
}
/**
* \brief Disables the selected interrupts sources on a TWI peripheral.
* \param pTwi Pointer to an Twi instance.
* \param sources Bitwise OR of selected interrupt sources.
*/
void TWI_DisableIt(Twi *pTwi, uint32_t sources)
{
assert( pTwi != NULL ) ;
assert( (sources & 0xFFFFF088) == 0 ) ;
pTwi->TWI_IDR = sources;
}
/**
* \brief Get the current status register of the given TWI peripheral.
* \note This resets the internal value of the status register, so further
* read may yield different values.
* \param pTwi Pointer to an Twi instance.
* \return TWI status register.
*/
uint32_t TWI_GetStatus(Twi *pTwi)
{
assert( pTwi != NULL ) ;
return pTwi->TWI_SR;
}
/**
* \brief Returns the current status register of the given TWI peripheral, but
* masking interrupt sources which are not currently enabled.
* \note This resets the internal value of the status register, so further
* read may yield different values.
* \param pTwi Pointer to an Twi instance.
*/
uint32_t TWI_GetMaskedStatus(Twi *pTwi)
{
uint32_t status;
assert( pTwi != NULL ) ;
status = pTwi->TWI_SR;
status &= pTwi->TWI_IMR;
return status;
}
/**
* \brief Sends a STOP condition. STOP Condition is sent just after completing
* the current byte transmission in master read mode.
* \param pTwi Pointer to an Twi instance.
*/
void TWI_SendSTOPCondition(Twi *pTwi)
{
assert( pTwi != NULL ) ;
pTwi->TWI_CR |= TWI_CR_STOP;
}

View File

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

View File

@@ -0,0 +1,471 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#include "chip.h"
#if 0 //SAM3U_SERIES
#include "USB_device.h"
#include "udphs.h"
/// Max size of the FMA FIFO
#define EPT_VIRTUAL_SIZE (16384u)
#define SHIFT_INTERUPT (8u)
int _cmark;
int _cend;
// Global variable for endpoint number
unsigned int NumEndpoint=0;
void USBD_WaitIN(void)
{
// while (!(UEINTX & (1<<TXINI)));
while (!(UDPHS->UDPHS_EPT[0].UDPHS_EPTSTA & UDPHS_EPTSTA_TX_PK_RDY));
}
void USBD_WaitOUT(void)
{
// while (!(UEINTX & (1<<RXOUTI)))
// ;
// Waiting for Status stage
while (UDPHS_EPTSTA_RX_BK_RDY != (UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_RX_BK_RDY));
}
void USBD_ClearIN(void)
{
// UEINTX = ~(1<<TXINI);
UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_TX_COMPLT;
}
void USBD_ClearOUT(void)
{
// UEINTX = ~(1<<RXOUTI);
UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_RX_BK_RDY;
}
uint8_t USBD_WaitForINOrOUT(void)
{
// while (!(UEINTX & ((1<<TXINI)|(1<<RXOUTI))))
// ;
// return (UEINTX & (1<<RXOUTI)) == 0;
while (!(UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & (UDPHS_EPTSTA_RX_BK_RDY | UDPHS_EPTSTA_TX_PK_RDY)));
return (UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_RX_BK_RDY) == 0;
}
void USBD_ClearRxFlag(unsigned char bEndpoint)
{
UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_RX_BK_RDY;
}
void USBD_Stall(void)
{
// UECONX = (1<<STALLRQ) | (1<<EPEN);
UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTSETSTA = UDPHS_EPTSETSTA_FRCESTALL;
}
uint8_t USBD_Stalled(void)
{
// return UEINTX & (1<<STALLEDI);
// Check if the data has been STALLed
return ( UDPHS_EPTSTA_FRCESTALL == (UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_FRCESTALL));
}
uint8_t USBD_ReceivedSetupInt(void)
{
// return UEINTX & (1<<RXSTPI);
return ( UDPHS_EPTSTA_RX_SETUP == (UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_RX_SETUP) );
}
void USBD_ClearSetupInt(void)
{
// UEINTX = ~((1<<RXSTPI) | (1<<RXOUTI) | (1<<TXINI));
UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTCLRSTA = UDPHS_EPTSTA_RX_SETUP | UDPHS_EPTCLRSTA_RX_BK_RDY | UDPHS_EPTCLRSTA_TX_COMPLT;
}
uint8_t USBD_ReadWriteAllowed(void)
{
//return UEINTX & (1<<RWAL);
return 1;
}
void USBD_SetEP(uint8_t ep)
{
// UENUM = ep;
NumEndpoint = ep & 7;
}
uint16_t USBD_FifoByteCount(void)
{
// return UEBCLX;
// SAM3X
//return ((UOTGHS->UOTGHS_DEVEPTISR[ep] & UOTGHS_DEVEPTISR_BYCT_Msk) >> UOTGHS_DEVEPTISR_BYCT_Pos);
// SAM3U //AT91C_UDPHS_BYTE_COUNT (0x7FF << 20)
return ((UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_BYTE_COUNT_Msk) >> UDPHS_EPTSTA_BYTE_COUNT_Pos);
}
uint8_t USBD_FifoFree(void)
{
// return UEINTX & (1<<FIFOCON);
return( 0 != (UDPHS->UDPHS_EPT[NumEndpoint].UDPHS_EPTSTA & UDPHS_EPTSTA_TX_PK_RDY ));
}
void USBD_ReleaseRX(void)
{
UEINTX = 0x6B; // FIFOCON=0 NAKINI=1 RWAL=1 NAKOUTI=0 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=1
}
void USBD_ReleaseTX()
{
UEINTX = 0x3A; // FIFOCON=0 NAKINI=0 RWAL=1 NAKOUTI=1 RXSTPI=1 RXOUTI=0 STALLEDI=1 TXINI=0
}
uint8_t USBD_FrameNumber(void)
{
return UDFNUML;
}
uint8_t USBD_GetConfiguration(void)
{
return _usbConfiguration;
}
void USBD_Recv(volatile uint8_t* data, uint8_t count)
{
uint8_t *pFifo;
pFifo = (uint8_t*)((uint32_t *)UDPHS_RAM_ADDR + (EPT_VIRTUAL_SIZE * NumEndpoint));
while (count--)
{
*data++ = pFifo[0];
}
// RXLED1; // light the RX LED
// RxLEDPulse = TX_RX_LED_PULSE_MS;
}
uint8_t USBD_Recv8(void)
{
uint8_t *pFifo;
// RXLED1; // light the RX LED
// RxLEDPulse = TX_RX_LED_PULSE_MS;
pFifo = (uint8_t*)((uint32_t *)UDPHS_RAM_ADDR + (EPT_VIRTUAL_SIZE * NumEndpoint));
// return UEDATX;
return (pFifo[0]);
}
void USBD_Send8(uint8_t d)
{
uint8_t *pFifo;
pFifo = (uint8_t*)((uint32_t *)UDPHS_RAM_ADDR + (EPT_VIRTUAL_SIZE * NumEndpoint));
// UEDATX = d;
pFifo[0] =d;
}
// Blocking Send of data to an endpoint
int USBD_Send(uint8_t ep, const void* d, int len)
{
if (!_usbConfiguration)
return -1;
int r = len;
const uint8_t* data = (const uint8_t*)d;
uint8_t zero = ep & TRANSFER_ZERO;
uint8_t timeout = 250; // 250ms timeout on send? TODO
while (len)
{
uint8_t n = USB_SendSpace(ep);
if (n == 0)
{
if (!(--timeout))
return -1;
delay(1);
continue;
}
if (n > len)
n = len;
len -= n;
{
SetEP(ep);
if (ep & TRANSFER_ZERO)
{
while (n--)
Send8(0);
}
else if (ep & TRANSFER_PGM)
{
while (n--)
Send8(*data++);
}
else
{
while (n--)
Send8(*data++);
}
// if (!ReadWriteAllowed() || ((len == 0) && (ep & TRANSFER_RELEASE))) // Release full buffer
// ReleaseTX();
}
}
TXLED1; // light the TX LED
TxLEDPulse = TX_RX_LED_PULSE_MS;
return r;
}
// Space in send EP
uint8_t USBD_SendSpace(uint8_t ep)
{
SetEP(ep);
if (!ReadWriteAllowed())
{
return 0;
}
return 64 - FifoByteCount();
}
// Number of bytes, assumes a rx endpoint
uint8_t USBD_Available(uint8_t ep)
{
SetEP(ep);
return FifoByteCount();
}
void USBD_InitEP(uint8_t index, uint8_t type, uint8_t size)
{
UENUM = index;
UECONX = 1;
UECFG0X = type;
UECFG1X = size;
}
void USBD_InitEndpoints(void)
{
for (uint8_t i = 1; i < sizeof(_initEndpoints); i++)
{
// Reset Endpoint Fifos
UDPHS->UDPHS_EPT[i].UDPHS_EPTCLRSTA = UDPHS_EPTCLRSTA_TOGGLESQ | UDPHS_EPTCLRSTA_FRCESTALL;
UDPHS->UDPHS_EPTRST = 1<<i;
//UECONX = 1;
//UECFG0X = pgm_read_byte(_initEndpoints+i);
UDPHS->UDPHS_EPT[i].UDPHS_EPTCFG = _initEndpoints[i];
while( (signed int)UDPHS_EPTCFG_EPT_MAPD != (signed int)((UDPHS->UDPHS_EPT[i].UDPHS_EPTCFG) & (unsigned int)UDPHS_EPTCFG_EPT_MAPD) )
;
UDPHS->UDPHS_EPT[i].UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_EPT_ENABL;
// UECFG1X = EP_DOUBLE_64;
}
///\// UERST = 0x7E; // And reset them
///\// UERST = 0;
}
void USBD_InitControl(int end)
{
SetEP(0);
UDPHS->UDPHS_EPT[0].UDPHS_EPTCFG = _initEndpoints[0];
while( (signed int)UDPHS_EPTCFG_EPT_MAPD != (signed int)((UDPHS->UDPHS_EPT[0].UDPHS_EPTCFG) & (unsigned int)UDPHS_EPTCFG_EPT_MAPD) )
;
UDPHS->UDPHS_EPT[0].UDPHS_EPTCTLENB = UDPHS_EPTCTLENB_RX_BK_RDY
| UDPHS_EPTCTLENB_RX_SETUP
| UDPHS_EPTCTLENB_EPT_ENABL;
_cmark = 0;
_cend = end;
}
void UDPHS_Handler( void )
{
unsigned int status;
unsigned char numIT;
// Get interrupts status
status = UDPHS->UDPHS_INTSTA & UDPHS->UDPHS_IEN;
// Handle all UDPHS interrupts
while (status != 0) {
// Start of Frame - happens every millisecond so we use it for TX and RX LED one-shot timing, too
if ((status & UDPHS_IEN_INT_SOF) != 0) {
#ifdef CDC_ENABLED
USB_Flush(CDC_TX); // Send a tx frame if found
#endif
// check whether the one-shot period has elapsed. if so, turn off the LED
if (TxLEDPulse && !(--TxLEDPulse))
TXLED0;
if (RxLEDPulse && !(--RxLEDPulse))
RXLED0;
// Acknowledge interrupt
UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_INT_SOF;
status &= ~UDPHS_IEN_INT_SOF;
}
// Suspend
// This interrupt is always treated last (hence the '==')
else if (status == UDPHS_IEN_DET_SUSPD) {
//UDPHS_DisableBIAS();
// Enable wakeup
UDPHS->UDPHS_IEN |= UDPHS_IEN_WAKE_UP | UDPHS_IEN_ENDOFRSM;
UDPHS->UDPHS_IEN &= ~UDPHS_IEN_DET_SUSPD;
// Acknowledge interrupt
UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_DET_SUSPD | UDPHS_CLRINT_WAKE_UP;
//UDPHS_DisableUsbClock();
}
// Resume
else if( ((status & UDPHS_IEN_WAKE_UP) != 0) // line activity
|| ((status & UDPHS_IEN_ENDOFRSM) != 0)) { // pc wakeup
{
//UDPHS_EnableUsbClock();
//UDPHS_EnableBIAS();
UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_WAKE_UP | UDPHS_CLRINT_ENDOFRSM
| UDPHS_CLRINT_DET_SUSPD;
UDPHS->UDPHS_IEN |= UDPHS_IEN_ENDOFRSM | UDPHS_IEN_DET_SUSPD;
UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_WAKE_UP | UDPHS_CLRINT_ENDOFRSM;
UDPHS->UDPHS_IEN &= ~UDPHS_IEN_WAKE_UP;
}
}
// End of Reset
else if ((status & UDPHS_IEN_ENDRESET) == UDPHS_IEN_ENDRESET) {
InitControl(0); // init ep0
_usbConfiguration = 0; // not configured yet
//UEIENX = 1 << RXSTPE; // Enable interrupts for ep0
//UDPHS_ResetEndpoints();
//UDPHS_DisableEndpoints();
//USBD_ConfigureEndpoint(0);
UDPHS->UDPHS_IEN |= (1<<SHIFT_INTERUPT<<0);
// Flush and enable the Suspend interrupt
UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_WAKE_UP | UDPHS_CLRINT_DET_SUSPD;
//// Enable the Start Of Frame (SOF) interrupt if needed
UDPHS->UDPHS_IEN |= UDPHS_IEN_INT_SOF;
// Acknowledge end of bus reset interrupt
UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_ENDRESET;
UDPHS->UDPHS_IEN |= UDPHS_IEN_DET_SUSPD;
}
// Handle upstream resume interrupt
else if (status & UDPHS_IEN_UPSTR_RES) {
// - Acknowledge the IT
UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_UPSTR_RES;
}
// Endpoint interrupts
else {
// Handle endpoint interrupts
for (numIT = 0; numIT < NUM_IT_MAX; numIT++) {
if ((status & (1 << SHIFT_INTERUPT << numIT)) != 0) {
USB_ISR();
//EndpointHandler(numIT); // TODO: interrupt for bulk
}
}
}
// Retrieve new interrupt status
status = UDPHS->UDPHS_INTSTA & UDPHS->UDPHS_IEN;
}
}
void USBD_Attach( void )
{/*
_usbConfiguration = 0;
//UHWCON = 0x01; // power internal reg
//USBCON = (1<<USBE)|(1<<FRZCLK); // clock frozen, usb enabled
//PLLCSR = 0x12; // Need 16 MHz xtal
//while (!(PLLCSR & (1<<PLOCK))) // wait for lock pll
// ;
PMC->PMC_PCER = (1 << ID_UDPHS);
// Enable 480MHZ
//AT91C_BASE_CKGR->CKGR_UCKR |= (AT91C_CKGR_PLLCOUNT & (3 << 20)) | AT91C_CKGR_UPLLEN;
CKGR->CKGR_UCKR |= ((0xf << 20) & (3 << 20)) | AT91C_CKGR_UPLLEN;
// Wait until UTMI PLL is locked
while ((PMC->PMC_SR & PMC_LOCKU) == 0);
// Reset and enable IP UDPHS
UDPHS->UDPHS_CTRL &= ~UDPHS_CTRL_EN_UDPHS;
UDPHS->UDPHS_CTRL |= UDPHS_CTRL_EN_UDPHS;
//USBCON = ((1<<USBE)|(1<<OTGPADE)); // start USB clock
UDPHS->UDPHS_IEN = 0;
UDPHS->UDPHS_CLRINT = UDPHS_CLRINT_UPSTR_RES
| UDPHS_CLRINT_ENDOFRSM
| UDPHS_CLRINT_WAKE_UP
| UDPHS_CLRINT_ENDRESET
| UDPHS_CLRINT_INT_SOF
| UDPHS_CLRINT_MICRO_SOF
| UDPHS_CLRINT_DET_SUSPD;
// Enable interrupts for EOR (End of Reset), wake up and SOF (start of frame)
//UDIEN = (1<<EORSTE)|(1<<SOFE);
UDPHS->UDPHS_IEN = UDPHS_IEN_ENDOFRSM
| UDPHS_IEN_WAKE_UP
| UDPHS_IEN_DET_SUSPD;
// enable attach resistor
//UDCON = 0;
UDPHS->UDPHS_CTRL &= ~UDPHS_CTRL_DETACH; // Pull Up on DP
UDPHS->UDPHS_CTRL |= UDPHS_CTRL_PULLD_DIS; // Disable Pull Down
TX_RX_LED_INIT;
*/}
void USBD_Detach( void )
{
UDPHS->UDPHS_CTRL |= UDPHS_CTRL_DETACH; // detach
UDPHS->UDPHS_CTRL &= ~UDPHS_CTRL_PULLD_DIS; // Enable Pull Down
}
#endif /* SAM3U_SERIES */

View File

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

View File

@@ -0,0 +1,334 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#include "chip.h"
#include <stdio.h>
#if SAM3XA_SERIES
//#define TRACE_UOTGHS_DEVICE(x) x
#define TRACE_UOTGHS_DEVICE(x)
extern void (*gpf_isr)(void);
static volatile uint32_t ul_send_fifo_ptr[MAX_ENDPOINTS];
static volatile uint32_t ul_recv_fifo_ptr[MAX_ENDPOINTS];
void UDD_SetStack(void (*pf_isr)(void))
{
gpf_isr = pf_isr;
}
uint32_t UDD_Init(void)
{
uint32_t i;
for (i = 0; i < MAX_ENDPOINTS; ++i)
{
ul_send_fifo_ptr[i] = 0;
ul_recv_fifo_ptr[i] = 0;
}
// Enables the USB Clock
pmc_enable_periph_clk(ID_UOTGHS);
pmc_enable_upll_clock();
pmc_switch_udpck_to_upllck(0); // div=0+1
pmc_enable_udpck();
// Configure interrupts
NVIC_SetPriority((IRQn_Type) ID_UOTGHS, 0UL);
NVIC_EnableIRQ((IRQn_Type) ID_UOTGHS);
// Always authorize asynchrone USB interrupts to exit from sleep mode
// for SAM3 USB wake up device except BACKUP mode
//pmc_set_fast_startup_input(PMC_FSMR_USBAL);
// ID pin not used then force device mode
otg_disable_id_pin();
otg_force_device_mode();
// Enable USB hardware
otg_disable_pad();
otg_enable_pad();
otg_enable();
otg_unfreeze_clock();
// Check USB clock
//while (!Is_otg_clock_usable())
// ;
// Enable High Speed
udd_low_speed_disable();
udd_high_speed_enable();
//otg_ack_vbus_transition();
// Force Vbus interrupt in case of Vbus always with a high level
// This is possible with a short timing between a Host mode stop/start.
/*if (Is_otg_vbus_high()) {
otg_raise_vbus_transition();
}
otg_enable_vbus_interrupt();*/
otg_freeze_clock();
return 0UL ;
}
void UDD_Attach(void)
{
irqflags_t flags = cpu_irq_save();
TRACE_UOTGHS_DEVICE(printf("=> UDD_Attach\r\n");)
otg_unfreeze_clock();
// Check USB clock because the source can be a PLL
while (!Is_otg_clock_usable());
// Authorize attach if Vbus is present
udd_attach_device();
// Enable USB line events
udd_enable_reset_interrupt();
// udd_enable_sof_interrupt();
cpu_irq_restore(flags);
}
void UDD_Detach(void)
{
TRACE_UOTGHS_DEVICE(printf("=> UDD_Detach\r\n");)
UOTGHS->UOTGHS_DEVCTRL |= UOTGHS_DEVCTRL_DETACH;
}
void UDD_InitEP( uint32_t ul_ep_nb, uint32_t ul_ep_cfg )
{
ul_ep_nb = ul_ep_nb & 0xF; // EP range is 0..9, hence mask is 0xF.
TRACE_UOTGHS_DEVICE(printf("=> UDD_InitEP : init EP %lu\r\n", ul_ep_nb);)
// Configure EP
UOTGHS->UOTGHS_DEVEPTCFG[ul_ep_nb] = ul_ep_cfg;
// Enable EP
udd_enable_endpoint(ul_ep_nb);
if (!Is_udd_endpoint_configured(ul_ep_nb)) {
TRACE_UOTGHS_DEVICE(printf("=> UDD_InitEP : ERROR FAILED TO INIT EP %lu\r\n", ul_ep_nb);)
while(1);
}
}
void UDD_InitEndpoints(const uint32_t* eps_table, const uint32_t ul_eps_table_size)
{
uint32_t ul_ep_nb ;
for (ul_ep_nb = 1; ul_ep_nb < ul_eps_table_size; ul_ep_nb++)
{
// Configure EP
UOTGHS->UOTGHS_DEVEPTCFG[ul_ep_nb] = eps_table[ul_ep_nb];
// Enable EP
udd_enable_endpoint(ul_ep_nb);
if (!Is_udd_endpoint_configured(ul_ep_nb)) {
TRACE_UOTGHS_DEVICE(printf("=> UDD_InitEP : ERROR FAILED TO INIT EP %lu\r\n", ul_ep_nb);)
while(1);
}
}
}
// Wait until ready to accept IN packet.
void UDD_WaitIN(void)
{
while (!(UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_TXINI))
;
}
void UDD_WaitOUT(void)
{
while (!(UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_RXOUTI))
;
}
// Send packet.
void UDD_ClearIN(void)
{
TRACE_UOTGHS_DEVICE(printf("=> UDD_ClearIN: sent %lu bytes\r\n", ul_send_fifo_ptr[EP0]);)
UOTGHS->UOTGHS_DEVEPTICR[EP0] = UOTGHS_DEVEPTICR_TXINIC;
ul_send_fifo_ptr[EP0] = 0;
}
void UDD_ClearOUT(void)
{
UOTGHS->UOTGHS_DEVEPTICR[EP0] = UOTGHS_DEVEPTICR_RXOUTIC;
ul_recv_fifo_ptr[EP0] = 0;
}
// Wait for IN FIFO to be ready to accept data or OUT FIFO to receive data.
// Return true if new IN FIFO buffer available.
uint32_t UDD_WaitForINOrOUT(void)
{
while (!(UOTGHS->UOTGHS_DEVEPTISR[EP0] & (UOTGHS_DEVEPTISR_TXINI | UOTGHS_DEVEPTISR_RXOUTI)))
;
return ((UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_RXOUTI) == 0);
}
uint32_t UDD_ReceivedSetupInt(void)
{
return UOTGHS->UOTGHS_DEVEPTISR[EP0] & UOTGHS_DEVEPTISR_RXSTPI;
}
void UDD_ClearSetupInt(void)
{
UOTGHS->UOTGHS_DEVEPTICR[EP0] = (UOTGHS_DEVEPTICR_RXSTPIC);
}
uint32_t UDD_Send(uint32_t ep, const void* data, uint32_t len)
{
const uint8_t *ptr_src = data;
uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(ep);
uint32_t i;
TRACE_UOTGHS_DEVICE(printf("=> UDD_Send (1): ep=%lu ul_send_fifo_ptr=%lu len=%lu\r\n", ep, ul_send_fifo_ptr[ep], len);)
while( UOTGHS_DEVEPTISR_TXINI != (UOTGHS->UOTGHS_DEVEPTISR[ep] & UOTGHS_DEVEPTISR_TXINI )) {}
if (ep == EP0)
{
if (ul_send_fifo_ptr[ep] + len > EP0_SIZE)
len = EP0_SIZE - ul_send_fifo_ptr[ep];
}
else
{
ul_send_fifo_ptr[ep] = 0;
}
for (i = 0, ptr_dest += ul_send_fifo_ptr[ep]; i < len; ++i)
*ptr_dest++ = *ptr_src++;
ul_send_fifo_ptr[ep] += i;
if (ep == EP0)
{
TRACE_UOTGHS_DEVICE(printf("=> UDD_Send (2): ep=%lu ptr_dest=%lu maxlen=%d\r\n", ep, ul_send_fifo_ptr[ep], EP0_SIZE);)
if (ul_send_fifo_ptr[ep] == EP0_SIZE)
{
UDD_ClearIN(); // Fifo is full, release this packet // UOTGHS->UOTGHS_DEVEPTICR[EP0] = UOTGHS_DEVEPTICR_TXINIC;
}
}
else
{
UOTGHS->UOTGHS_DEVEPTICR[ep] = UOTGHS_DEVEPTICR_TXINIC;
UOTGHS->UOTGHS_DEVEPTIDR[ep] = UOTGHS_DEVEPTIDR_FIFOCONC;
}
return len;
}
void UDD_Send8(uint32_t ep, uint8_t data )
{
uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(ep);
TRACE_UOTGHS_DEVICE(printf("=> UDD_Send8 : ul_send_fifo_ptr=%lu data=0x%x\r\n", ul_send_fifo_ptr[ep], data);)
ptr_dest[ul_send_fifo_ptr[ep]] = data;
ul_send_fifo_ptr[ep] += 1;
}
uint8_t UDD_Recv8(uint32_t ep)
{
uint8_t *ptr_dest = (uint8_t *) &udd_get_endpoint_fifo_access8(ep);
uint8_t data = ptr_dest[ul_recv_fifo_ptr[ep]];
TRACE_UOTGHS_DEVICE(printf("=> UDD_Recv8 : ul_recv_fifo_ptr=%lu\r\n", ul_recv_fifo_ptr[ep]);)
ul_recv_fifo_ptr[ep] += 1;
return data;
}
void UDD_Recv(uint32_t ep, uint8_t* data, uint32_t len)
{
uint8_t *ptr_src = (uint8_t *) &udd_get_endpoint_fifo_access8(ep);
uint8_t *ptr_dest = data;
uint32_t i;
for (i = 0, ptr_src += ul_recv_fifo_ptr[ep]; i < len; ++i)
*ptr_dest++ = *ptr_src++;
ul_recv_fifo_ptr[ep] += i;
}
void UDD_Stall(void)
{
UOTGHS->UOTGHS_DEVEPT = (UOTGHS_DEVEPT_EPEN0 << EP0);
UOTGHS->UOTGHS_DEVEPTIER[EP0] = UOTGHS_DEVEPTIER_STALLRQS;
}
uint32_t UDD_FifoByteCount(uint32_t ep)
{
return ((UOTGHS->UOTGHS_DEVEPTISR[ep] & UOTGHS_DEVEPTISR_BYCT_Msk) >> UOTGHS_DEVEPTISR_BYCT_Pos);
}
void UDD_ReleaseRX(uint32_t ep)
{
TRACE_UOTGHS_DEVICE(puts("=> UDD_ReleaseRX\r\n");)
// UOTGHS->UOTGHS_DEVEPTICR[ep] = (UOTGHS_DEVEPTICR_NAKOUTIC | UOTGHS_DEVEPTICR_RXOUTIC);
UOTGHS->UOTGHS_DEVEPTICR[ep] = UOTGHS_DEVEPTICR_RXOUTIC;
UOTGHS->UOTGHS_DEVEPTIDR[ep] = UOTGHS_DEVEPTIDR_FIFOCONC;
ul_recv_fifo_ptr[ep] = 0;
}
void UDD_ReleaseTX(uint32_t ep)
{
TRACE_UOTGHS_DEVICE(printf("=> UDD_ReleaseTX ep=%lu\r\n", ep);)
// UOTGHS->UOTGHS_DEVEPTICR[ep] = (UOTGHS_DEVEPTICR_NAKINIC | UOTGHS_DEVEPTICR_RXOUTIC | UOTGHS_DEVEPTICR_TXINIC);
UOTGHS->UOTGHS_DEVEPTICR[ep] = UOTGHS_DEVEPTICR_TXINIC;
UOTGHS->UOTGHS_DEVEPTIDR[ep] = UOTGHS_DEVEPTIDR_FIFOCONC;
ul_send_fifo_ptr[ep] = 0;
}
// Return true if the current bank is not full.
uint32_t UDD_ReadWriteAllowed(uint32_t ep)
{
return (UOTGHS->UOTGHS_DEVEPTISR[ep] & UOTGHS_DEVEPTISR_RWALL);
}
void UDD_SetAddress(uint32_t addr)
{
TRACE_UOTGHS_DEVICE(printf("=> UDD_SetAddress : setting address to %lu\r\n", addr);)
udd_configure_address(addr);
udd_enable_address();
}
uint32_t UDD_GetFrameNumber(void)
{
return udd_frame_number();
}
#endif /* SAM3XA_SERIES */

View File

@@ -0,0 +1,490 @@
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2011-2012, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following condition is met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
#include "chip.h"
#include <stdio.h>
#if SAM3XA_SERIES
//#define TRACE_UOTGHS_HOST(x) x
#define TRACE_UOTGHS_HOST(x)
extern void (*gpf_isr)(void);
// Handle UOTGHS Host driver state
static uhd_vbus_state_t uhd_state = UHD_STATE_NO_VBUS;
/**
* \brief Interrupt sub routine for USB Host state machine management.
*/
static void UHD_ISR(void)
{
// Manage dis/connection event
if (Is_uhd_disconnection() && Is_uhd_disconnection_int_enabled()) {
TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Disconnection INT\r\n");)
uhd_ack_disconnection();
uhd_disable_disconnection_int();
// Stop reset signal, in case of disconnection during reset
uhd_stop_reset();
// Disable wakeup/resumes interrupts,
// in case of disconnection during suspend mode
//UOTGHS->UOTGHS_HSTIDR = UOTGHS_HSTIDR_HWUPIEC
// | UOTGHS_HSTIDR_RSMEDIEC
// | UOTGHS_HSTIDR_RXRSMIEC;
uhd_ack_connection();
uhd_enable_connection_int();
uhd_state = UHD_STATE_DISCONNECTED;
return;
}
if (Is_uhd_connection() && Is_uhd_connection_int_enabled()) {
TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Connection INT\r\n");)
uhd_ack_connection();
uhd_disable_connection_int();
uhd_ack_disconnection();
uhd_enable_disconnection_int();
//uhd_enable_sof();
uhd_state = UHD_STATE_CONNECTED;
return;
}
// Manage Vbus error
if (Is_uhd_vbus_error_interrupt())
{
TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : VBUS error INT\r\n");)
uhd_ack_vbus_error_interrupt();
uhd_state = UHD_STATE_DISCONNECTED; //UHD_STATE_ERROR;
return;
}
// Check USB clock ready after asynchronous interrupt
while (!Is_otg_clock_usable())
;
otg_unfreeze_clock();
// Manage Vbus state change
if (Is_otg_vbus_transition())
{
otg_ack_vbus_transition();
if (Is_otg_vbus_high())
{
TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : VBUS transition INT : UHD_STATE_DISCONNECT\r\n");)
uhd_state = UHD_STATE_DISCONNECTED;
}
else
{
TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : VBUS transition INT : UHD_STATE_NO_VBUS\r\n");)
otg_freeze_clock();
uhd_state = UHD_STATE_NO_VBUS;
}
TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : VBUS transition INT : done.\r\n");)
return;
}
// Other errors
if (Is_uhd_errors_interrupt())
{
TRACE_UOTGHS_HOST(printf(">>> UHD_ISR : Other error INT\r\n");)
uhd_ack_errors_interrupt();
return;
}
}
/**
* \brief Set the interrupt sub routines callback for USB interrupts.
*
* \param pf_isr the ISR address.
*/
void UHD_SetStack(void (*pf_isr)(void))
{
gpf_isr = pf_isr;
}
/**
* \brief Initialize the UOTGHS host driver.
*/
void UHD_Init(void)
{
irqflags_t flags;
// To avoid USB interrupt before end of initialization
flags = cpu_irq_save();
// Setup USB Host interrupt callback
UHD_SetStack(&UHD_ISR);
// Enables the USB Clock
pmc_enable_upll_clock();
pmc_switch_udpck_to_upllck(0); // div=0+1
pmc_enable_udpck();
pmc_enable_periph_clk(ID_UOTGHS);
// Always authorize asynchronous USB interrupts to exit of sleep mode
// For SAM3 USB wake up device except BACKUP mode
NVIC_SetPriority((IRQn_Type) ID_UOTGHS, 0);
NVIC_EnableIRQ((IRQn_Type) ID_UOTGHS);
// ID pin not used then force host mode
otg_disable_id_pin();
otg_force_host_mode();
// Signal is active low (because all SAM3X Pins are high after startup)
// Hence VBOF must be low after connection request to power up the remote device
// uhd_set_vbof_active_low();
// According to the Arduino Due circuit the VBOF must be active high to power up the remote device
uhd_set_vbof_active_high();
otg_enable_pad();
otg_enable();
otg_unfreeze_clock();
// Check USB clock
while (!Is_otg_clock_usable())
;
// Clear all interrupts that may have been set by a previous host mode
UOTGHS->UOTGHS_HSTICR = UOTGHS_HSTICR_DCONNIC | UOTGHS_HSTICR_DDISCIC
| UOTGHS_HSTICR_HSOFIC | UOTGHS_HSTICR_HWUPIC
| UOTGHS_HSTICR_RSMEDIC | UOTGHS_HSTICR_RSTIC
| UOTGHS_HSTICR_RXRSMIC;
otg_ack_vbus_transition();
// Enable Vbus change and error interrupts
// Disable automatic Vbus control after Vbus error
Set_bits(UOTGHS->UOTGHS_CTRL,
UOTGHS_CTRL_VBUSHWC | UOTGHS_CTRL_VBUSTE | UOTGHS_CTRL_VBERRE);
uhd_enable_vbus();
// Force Vbus interrupt when Vbus is always high
// This is possible due to a short timing between a Host mode stop/start.
if (Is_otg_vbus_high())
{
otg_raise_vbus_transition();
}
// Enable main control interrupt
// Connection, SOF and reset
UOTGHS->UOTGHS_HSTIER = UOTGHS_HSTICR_DCONNIC;
otg_freeze_clock();
uhd_state = UHD_STATE_NO_VBUS;
cpu_irq_restore(flags);
}
/**
* \brief Trigger a USB bus reset.
*/
void UHD_BusReset(void)
{
uhd_start_reset();
}
/**
* \brief Get VBUS state.
*
* \return VBUS status.
*/
uhd_vbus_state_t UHD_GetVBUSState(void)
{
return uhd_state;
}
/*uhd_speed_t uhd_get_speed(void)
{
switch (uhd_get_speed_mode())
{
case UOTGHS_SR_SPEED_HIGH_SPEED:
return UHD_SPEED_HIGH;
case UOTGHS_SR_SPEED_FULL_SPEED:
return UHD_SPEED_FULL;
case UOTGHS_SR_SPEED_LOW_SPEED:
return UHD_SPEED_LOW;
default:
return UHD_SPEED_LOW;
}
}*/
/**
* \brief Allocate FIFO for pipe 0.
*
* \param ul_add Address of remote device for pipe 0.
* \param ul_ep_size Actual size of the FIFO in bytes.
*
* \retval 0 success.
* \retval 1 error.
*/
uint32_t UHD_Pipe0_Alloc(uint32_t ul_add, uint32_t ul_ep_size)
{
if (ul_ep_size < 8)
{
TRACE_UOTGHS_HOST(printf("/!\\ UHD_EP0_Alloc : incorrect pipe size!\r\n");)
return 1;
}
if (Is_uhd_pipe_enabled(0))
{
// Pipe is already allocated
return 0;
}
uhd_enable_pipe(0);
uhd_configure_pipe(0, // Pipe 0
0, // No frequency
0, // Enpoint 0
UOTGHS_HSTPIPCFG_PTYPE_CTRL,
UOTGHS_HSTPIPCFG_PTOKEN_SETUP,
ul_ep_size,
UOTGHS_HSTPIPCFG_PBK_1_BANK, 0);
uhd_allocate_memory(0);
if (!Is_uhd_pipe_configured(0))
{
TRACE_UOTGHS_HOST(printf("/!\\ UHD_EP0_Alloc : incorrect pipe settings!\r\n");)
uhd_disable_pipe(0);
return 1;
}
uhd_configure_address(0, ul_add);
return 0;
}
/**
* \brief Allocate a new pipe.
*
* \note UOTGHS maximum pipe number is limited to 10, meaning that only a limited
* amount of devices can be connected. Unfortunately, using only one pipe shared accross
* various endpoints and devices is not possible because the UOTGHS IP does not allow to
* change the data toggle value through register interface.
*
* \param ul_dev_addr Address of remote device.
* \param ul_dev_ep Targeted endpoint of remote device.
* \param ul_type Pipe type.
* \param ul_dir Pipe direction.
* \param ul_maxsize Pipe size.
* \param ul_interval Polling interval (if applicable to pipe type).
* \param ul_nb_bank Number of banks associated with this pipe.
*
* \return the newly allocated pipe number on success, 0 otherwise.
*/
uint32_t UHD_Pipe_Alloc(uint32_t ul_dev_addr, uint32_t ul_dev_ep, uint32_t ul_type, uint32_t ul_dir, uint32_t ul_maxsize, uint32_t ul_interval, uint32_t ul_nb_bank)
{
uint32_t ul_pipe = 1;
for (ul_pipe = 1; ul_pipe < UOTGHS_EPT_NUM; ++ul_pipe)
{
if (Is_uhd_pipe_enabled(ul_pipe))
{
continue;
}
uhd_enable_pipe(ul_pipe);
uhd_configure_pipe(ul_pipe, ul_interval, ul_dev_ep, ul_type, ul_dir,
ul_maxsize, ul_nb_bank, UOTGHS_HSTPIPCFG_AUTOSW);
uhd_allocate_memory(ul_pipe);
if (!Is_uhd_pipe_configured(ul_pipe))
{
uhd_disable_pipe(ul_pipe);
return 0;
}
uhd_configure_address(ul_pipe, ul_dev_addr);
// Pipe is configured and allocated successfully
return ul_pipe;
}
return 0;
}
/**
* \brief Free a pipe.
*
* \param ul_pipe Pipe number to free.
*/
void UHD_Pipe_Free(uint32_t ul_pipe)
{
// Unalloc pipe
uhd_disable_pipe(ul_pipe);
uhd_unallocate_memory(ul_pipe);
uhd_reset_pipe(ul_pipe);
}
/**
* \brief Read from a pipe.
*
* \param ul_pipe Pipe number.
* \param ul_size Maximum number of data to read.
* \param data Buffer to store the data.
*
* \return number of data read.
*/
uint32_t UHD_Pipe_Read(uint32_t ul_pipe, uint32_t ul_size, uint8_t* data)
{
uint8_t *ptr_ep_data = 0;
uint8_t nb_byte_received = 0;
uint32_t ul_nb_trans = 0;
// Get information to read data
nb_byte_received = uhd_byte_count(ul_pipe);
ptr_ep_data = (uint8_t *) & uhd_get_pipe_fifo_access(ul_pipe, 8);
// Copy data from pipe to payload buffer
while (ul_size && nb_byte_received) {
*data++ = *ptr_ep_data++;
ul_nb_trans++;
ul_size--;
nb_byte_received--;
}
return ul_nb_trans;
}
/**
* \brief Write into a pipe.
*
* \param ul_pipe Pipe number.
* \param ul_size Maximum number of data to read.
* \param data Buffer containing data to write.
*/
void UHD_Pipe_Write(uint32_t ul_pipe, uint32_t ul_size, uint8_t* data)
{
volatile uint8_t *ptr_ep_data = 0;
uint32_t i = 0;
// Check pipe
if (!Is_uhd_pipe_enabled(ul_pipe))
{
// Endpoint not valid
TRACE_UOTGHS_HOST(printf("/!\\ UHD_EP_Send : pipe is not enabled!\r\n");)
return;
}
ptr_ep_data = (volatile uint8_t *)&uhd_get_pipe_fifo_access(ul_pipe, 8);
for (i = 0; i < ul_size; ++i)
*ptr_ep_data++ = *data++;
}
/**
* \brief Send a pipe content.
*
* \param ul_pipe Pipe number.
* \param ul_token_type Token type.
*/
void UHD_Pipe_Send(uint32_t ul_pipe, uint32_t ul_token_type)
{
// Check pipe
if (!Is_uhd_pipe_enabled(ul_pipe))
{
// Endpoint not valid
TRACE_UOTGHS_HOST(printf("/!\\ UHD_EP_Send : pipe %lu is not enabled!\r\n", ul_pipe);)
return;
}
// Set token type for zero length packet
// When actually using the FIFO, pipe token MUST be configured first
uhd_configure_pipe_token(ul_pipe, ul_token_type);
// Clear interrupt flags
uhd_ack_setup_ready(ul_pipe);
uhd_ack_in_received(ul_pipe);
uhd_ack_out_ready(ul_pipe);
uhd_ack_short_packet(ul_pipe);
uhd_ack_nak_received(ul_pipe);
// Send actual packet
uhd_ack_fifocon(ul_pipe);
uhd_unfreeze_pipe(ul_pipe);
}
/**
* \brief Check for pipe transfer completion.
*
* \param ul_pipe Pipe number.
* \param ul_token_type Token type.
*
* \retval 0 transfer is not complete.
* \retval 1 transfer is complete.
*/
uint32_t UHD_Pipe_Is_Transfer_Complete(uint32_t ul_pipe, uint32_t ul_token_type)
{
// Check for transfer completion depending on token type
switch (ul_token_type)
{
case UOTGHS_HSTPIPCFG_PTOKEN_SETUP:
if (Is_uhd_setup_ready(ul_pipe))
{
uhd_freeze_pipe(ul_pipe);
uhd_ack_setup_ready(ul_pipe);
return 1;
}
case UOTGHS_HSTPIPCFG_PTOKEN_IN:
if (Is_uhd_in_received(ul_pipe))
{
// In case of low USB speed and with a high CPU frequency,
// a ACK from host can be always running on USB line
// then wait end of ACK on IN pipe.
while(!Is_uhd_pipe_frozen(ul_pipe))
;
// IN packet received
uhd_ack_in_received(ul_pipe);
return 1;
}
case UOTGHS_HSTPIPCFG_PTOKEN_OUT:
if (Is_uhd_out_ready(ul_pipe))
{
// OUT packet sent
uhd_freeze_pipe(ul_pipe);
uhd_ack_out_ready(ul_pipe);
return 1;
}
}
return 0;
}
#endif /* SAM3XA_SERIES */

View File

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

View File

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