mirror of
https://github.com/arduino/Arduino.git
synced 2025-03-13 10:29:35 +01:00
[sam] adding more peripherals to SAM3X/Due
This commit is contained in:
parent
acfd670124
commit
5d0ba1c64a
@ -32,9 +32,9 @@
|
||||
|
||||
#define part_is_defined(part) (defined(__ ## part ## __))
|
||||
|
||||
/*
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* SAM3 family
|
||||
* SAM3 family
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@ -66,8 +66,17 @@
|
||||
/* Entire SAM3N series */
|
||||
#define SAM3N_SERIES (SAM3N00 || SAM3N0 || SAM3N1 || SAM3N2 || SAM3N4)
|
||||
|
||||
|
||||
|
||||
/* SAM3S series */
|
||||
#define SAM3S00 ( \
|
||||
part_is_defined( SAM3S00A ) || \
|
||||
part_is_defined( SAM3S00B ) )
|
||||
|
||||
#define SAM3S0 ( \
|
||||
part_is_defined( SAM3S0A ) || \
|
||||
part_is_defined( SAM3S0B ) || \
|
||||
part_is_defined( SAM3S0C ) )
|
||||
|
||||
#define SAM3S1 ( \
|
||||
part_is_defined( SAM3S1A ) || \
|
||||
part_is_defined( SAM3S1B ) || \
|
||||
@ -84,7 +93,7 @@
|
||||
part_is_defined( SAM3S4C ) )
|
||||
|
||||
/* Entire SAM3S series */
|
||||
#define SAM3S_SERIES (SAM3S1 || SAM3S2 || SAM3S4)
|
||||
#define SAM3S_SERIES (SAM3S00 || SAM3S0 ||SAM3S1 || SAM3S2 || SAM3S4)
|
||||
|
||||
/* SAM3SD8 series */
|
||||
#define SAM3S8 ( \
|
||||
@ -133,9 +142,9 @@
|
||||
/* Entire SAM3XA series */
|
||||
#define SAM3XA_SERIES ( SAM3X4 || SAM3X8 || SAM3A4 || SAM3A8)
|
||||
|
||||
/*
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* SAM4 family
|
||||
* SAM4 family
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
@ -158,30 +167,30 @@
|
||||
/* Entire SAM4 Family */
|
||||
#define SAM4_SERIES ( SAM4S_SERIES )
|
||||
|
||||
/*
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* SAM9 family
|
||||
* SAM9 family
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* SAM7 family
|
||||
* SAM7 family
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* Whole SAM product line
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#define SAM ( SAM3_SERIES || SAM4_SERIES )
|
||||
|
||||
/*
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
* Header inclusion
|
||||
* Header inclusion
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
@ -25,8 +25,9 @@ SUBMAKE_OPTIONS=--no-builtin-rules --no-builtin-variables --no-print-directory
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
# 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
|
||||
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 $@
|
||||
@ -34,6 +35,7 @@ arduino_due_u:
|
||||
@$(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 $@
|
||||
|
@ -42,14 +42,20 @@
|
||||
* 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/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"
|
||||
@ -59,9 +65,12 @@
|
||||
#include "include/USB_device.h"
|
||||
#include "include/USB_host.h"
|
||||
|
||||
#if SAM3XA_SERIES
|
||||
#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 /* (SAM3XA_SERIES) */
|
||||
|
||||
#endif /* _LIB_SAM_ */
|
||||
|
468
hardware/arduino/sam/system/libsam/include/can.h
Normal file
468
hardware/arduino/sam/system/libsam/include/can.h
Normal file
@ -0,0 +1,468 @@
|
||||
/**
|
||||
* \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);
|
||||
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);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @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 */
|
132
hardware/arduino/sam/system/libsam/include/efc.h
Normal file
132
hardware/arduino/sam/system/libsam/include/efc.h
Normal 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 */
|
1225
hardware/arduino/sam/system/libsam/include/emac.h
Normal file
1225
hardware/arduino/sam/system/libsam/include/emac.h
Normal file
@ -0,0 +1,1225 @@
|
||||
/**
|
||||
* \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
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef EMAC_H_INCLUDED
|
||||
#define EMAC_H_INCLUDED
|
||||
|
||||
#include "../chip.h"
|
||||
//#include "conf_eth.h"
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
||||
|
||||
/** The buffer addresses written into the descriptors must be aligned, so the
|
||||
last few bits are zero. These bits have special meaning for the EMAC
|
||||
peripheral and cannot be used as part of the address. */
|
||||
#define EMAC_RXD_ADDR_MASK 0xFFFFFFFC
|
||||
#define EMAC_RXD_WRAP (1ul << 1) /**< Wrap bit */
|
||||
#define EMAC_RXD_OWNERSHIP (1ul << 0) /**< Ownership bit */
|
||||
|
||||
#define EMAC_RXD_BROADCAST (1ul << 31) /**< Broadcast detected */
|
||||
#define EMAC_RXD_MULTIHASH (1ul << 30) /**< Multicast hash match */
|
||||
#define EMAC_RXD_UNIHASH (1ul << 29) /**< Unicast hash match */
|
||||
#define EMAC_RXD_EXTADDR (1ul << 28) /**< External address match */
|
||||
#define EMAC_RXD_ADDR1 (1ul << 26) /**< Address 1 match */
|
||||
#define EMAC_RXD_ADDR2 (1ul << 25) /**< Address 2 match */
|
||||
#define EMAC_RXD_ADDR3 (1ul << 24) /**< Address 3 match */
|
||||
#define EMAC_RXD_ADDR4 (1ul << 23) /**< Address 4 match */
|
||||
#define EMAC_RXD_TYPE (1ul << 22) /**< Type ID match */
|
||||
#define EMAC_RXD_VLAN (1ul << 21) /**< VLAN tag detected */
|
||||
#define EMAC_RXD_PRIORITY (1ul << 20) /**< Priority tag detected */
|
||||
#define EMAC_RXD_PRIORITY_MASK (3ul << 17) /**< VLAN priority */
|
||||
#define EMAC_RXD_CFI (1ul << 16) /**< Concatenation Format Indicator only if bit 21 is set */
|
||||
#define EMAC_RXD_EOF (1ul << 15) /**< End of frame */
|
||||
#define EMAC_RXD_SOF (1ul << 14) /**< Start of frame */
|
||||
#define EMAC_RXD_OFFSET_MASK /**< Receive buffer offset */
|
||||
#define EMAC_RXD_LEN_MASK (0xFFF) /**< Length of frame including FCS (if selected) */
|
||||
#define EMAC_RXD_LENJUMBO_MASK (0x3FFF) /**< Jumbo frame length */
|
||||
|
||||
#define EMAC_TXD_USED (1ul << 31) /**< Frame is transmitted */
|
||||
#define EMAC_TXD_WRAP (1ul << 30) /**< Last descriptor */
|
||||
#define EMAC_TXD_ERROR (1ul << 29) /**< Retry limit exceeded, error */
|
||||
#define EMAC_TXD_UNDERRUN (1ul << 28) /**< Transmit underrun */
|
||||
#define EMAC_TXD_EXHAUSTED (1ul << 27) /**< Buffer exhausted */
|
||||
#define EMAC_TXD_NOCRC (1ul << 16) /**< No CRC */
|
||||
#define EMAC_TXD_LAST (1ul << 15) /**< Last buffer in frame */
|
||||
#define EMAC_TXD_LEN_MASK (0x7FF) /**< Length of buffer */
|
||||
|
||||
/** The MAC can support frame lengths up to 1536 bytes */
|
||||
#define EMAC_FRAME_LENTGH_MAX 1536
|
||||
|
||||
#define EMAC_RX_UNITSIZE 128 /**< Fixed size for RX buffer */
|
||||
#define EMAC_TX_UNITSIZE 1518 /**< Size for ETH frame length */
|
||||
|
||||
/** EMAC clock speed */
|
||||
#define EMAC_CLOCK_SPEED_160MHZ (160*1000*1000)
|
||||
#define EMAC_CLOCK_SPEED_80MHZ (80*1000*1000)
|
||||
#define EMAC_CLOCK_SPEED_40MHZ (40*1000*1000)
|
||||
#define EMAC_CLOCK_SPEED_20MHZ (20*1000*1000)
|
||||
|
||||
/** EMAC maintain code default value*/
|
||||
#define EMAC_MAN_CODE_VALUE (10)
|
||||
|
||||
/** EMAC maintain start of frame default value*/
|
||||
#define EMAC_MAN_SOF_VALUE (1)
|
||||
|
||||
/** EMAC maintain read/write*/
|
||||
#define EMAC_MAN_RW_TYPE (2)
|
||||
|
||||
/** EMAC maintain read only*/
|
||||
#define EMAC_MAN_READ_ONLY (1)
|
||||
|
||||
/** EMAC address length */
|
||||
#define EMAC_ADDR_LENGTH (6)
|
||||
|
||||
/**
|
||||
* \brief Return codes for EMAC APIs.
|
||||
*/
|
||||
typedef enum {
|
||||
EMAC_OK = 0, /** Operation OK */
|
||||
EMAC_TIMEOUT = 1, /** EMAC operation timeout */
|
||||
EMAC_TX_BUSY, /** TX in progress */
|
||||
EMAC_RX_NULL, /** No data received */
|
||||
EMAC_SIZE_TOO_SMALL, /** Buffer size not enough */
|
||||
EMAC_PARAM, /** Parameter error, TX packet invalid or RX size too small */
|
||||
EMAC_INVALID = 0xFF, /* Invalid */
|
||||
} emac_status_t;
|
||||
|
||||
#if defined __ICCARM__
|
||||
#pragma pack(4) /* IAR */
|
||||
#define __attribute__(...) /* IAR */
|
||||
#endif /* IAR */
|
||||
|
||||
/** Receive buffer descriptor struct */
|
||||
typedef struct emac_rx_descriptor {
|
||||
union emac_rx_addr {
|
||||
uint32_t val;
|
||||
struct emac_rx_addr_bm {
|
||||
uint32_t b_ownership:1, /**< User clear, EMAC sets this to 1 once it has successfully written a frame to memory */
|
||||
b_wrap:1, /**< Marks last descriptor in receive buffer */
|
||||
addr_dw:30; /**< Address in number of DW */
|
||||
} bm;
|
||||
} addr; /**< Address, Wrap & Ownership */
|
||||
union emac_rx_status {
|
||||
uint32_t val;
|
||||
struct emac_rx_status_bm {
|
||||
uint32_t len:12, /** Length of frame including FCS */
|
||||
offset:2, /** Receive buffer offset, bits 13:12 of frame length for jumbo frame */
|
||||
b_sof:1, /** Start of frame */
|
||||
b_eof:1, /** End of frame */
|
||||
b_cfi:1, /** Concatenation Format Indicator */
|
||||
vlan_priority:3, /** VLAN priority (if VLAN detected) */
|
||||
b_priority_detected:1, /** Priority tag detected */
|
||||
b_vlan_detected:1, /**< VLAN tag detected */
|
||||
b_type_id_match:1, /**< Type ID match */
|
||||
b_addr4match:1, /**< Address register 4 match */
|
||||
b_addr3match:1, /**< Address register 3 match */
|
||||
b_addr2match:1, /**< Address register 2 match */
|
||||
b_addr1match:1, /**< Address register 1 match */
|
||||
reserved:1,
|
||||
b_ext_addr_match:1, /**< External address match */
|
||||
b_uni_hash_match:1, /**< Unicast hash match */
|
||||
b_multi_hash_match:1, /**< Multicast hash match */
|
||||
b_boardcast_detect:1; /**< Global broadcast address detected */
|
||||
} bm;
|
||||
} status;
|
||||
} __attribute__ ((packed, aligned(8))) emac_rx_descriptor_t; /* GCC */
|
||||
|
||||
/** Transmit buffer descriptor struct */
|
||||
typedef struct emac_tx_descriptor {
|
||||
uint32_t addr;
|
||||
union emac_tx_status {
|
||||
uint32_t val;
|
||||
struct emac_tx_status_bm {
|
||||
uint32_t len:11, /**< Length of buffer */
|
||||
reserved:4,
|
||||
b_last_buffer:1, /**< Last buffer (in the current frame) */
|
||||
b_no_crc:1, /**< No CRC */
|
||||
reserved1:10,
|
||||
b_exhausted:1, /**< Buffer exhausted in mid frame */
|
||||
b_underrun:1, /**< Transmit underrun */
|
||||
b_error:1, /**< Retry limit exceeded, error detected */
|
||||
b_wrap:1, /**< Marks last descriptor in TD list */
|
||||
b_used:1; /**< User clear, EMAC sets this to 1 once a frame has been successfully transmitted */
|
||||
} bm;
|
||||
} status;
|
||||
} __attribute__ ((packed, aligned(8))) emac_tx_descriptor_t; /* GCC */
|
||||
|
||||
#ifdef __ICCARM__ /* IAR */
|
||||
#pragma pack()
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Input parameters when initializing the emac module mode.
|
||||
*/
|
||||
typedef struct emac_options {
|
||||
/* Enable/Disable CopyAllFrame */
|
||||
uint8_t uc_copy_all_frame;
|
||||
/* Enable/Disable NoBroadCast */
|
||||
uint8_t uc_no_boardcast;
|
||||
/* MAC address */
|
||||
uint8_t uc_mac_addr[EMAC_ADDR_LENGTH];
|
||||
} emac_options_t;
|
||||
|
||||
/** RX callback */
|
||||
typedef void (*emac_dev_tx_cb_t) (uint32_t ul_status);
|
||||
/** Wakeup callback */
|
||||
typedef void (*emac_dev_wakeup_cb_t) (void);
|
||||
|
||||
/**
|
||||
* EMAC driver structure.
|
||||
*/
|
||||
typedef struct emac_device {
|
||||
|
||||
/** Pointer to HW register base */
|
||||
Emac *p_hw;
|
||||
/**
|
||||
* Pointer to allocated TX buffer.
|
||||
* Section 3.6 of AMBA 2.0 spec states that burst should not cross
|
||||
* 1K Boundaries.
|
||||
* Receive buffer manager writes are burst of 2 words => 3 lsb bits
|
||||
* of the address shall be set to 0.
|
||||
*/
|
||||
uint8_t *p_tx_buffer;
|
||||
/** Pointer to allocated RX buffer */
|
||||
uint8_t *p_rx_buffer;
|
||||
/** Pointer to Rx TDs (must be 8-byte aligned) */
|
||||
emac_rx_descriptor_t *p_rx_dscr;
|
||||
/** Pointer to Tx TDs (must be 8-byte aligned) */
|
||||
emac_tx_descriptor_t *p_tx_dscr;
|
||||
/** Optional callback to be invoked once a frame has been received */
|
||||
emac_dev_tx_cb_t func_rx_cb;
|
||||
/** Optional callback to be invoked once several TDs have been released */
|
||||
emac_dev_wakeup_cb_t func_wakeup_cb;
|
||||
/** Optional callback list to be invoked once TD has been processed */
|
||||
emac_dev_tx_cb_t *func_tx_cb_list;
|
||||
/** RX TD list size */
|
||||
uint16_t us_rx_list_size;
|
||||
/** RX index for current processing TD */
|
||||
uint16_t us_rx_idx;
|
||||
/** TX TD list size */
|
||||
uint16_t us_tx_list_size;
|
||||
/** Circular buffer head pointer by upper layer (buffer to be sent) */
|
||||
uint16_t us_tx_head;
|
||||
/** Circular buffer tail pointer incremented by handlers (buffer sent) */
|
||||
uint16_t us_tx_tail;
|
||||
|
||||
/** Number of free TD before wakeup callback is invoked */
|
||||
uint8_t uc_wakeup_threshold;
|
||||
} emac_device_t;
|
||||
|
||||
/**
|
||||
* \brief Write network control value.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param ul_ncr Network control value.
|
||||
*/
|
||||
static inline void emac_network_control(Emac* p_emac, uint32_t ul_ncr)
|
||||
{
|
||||
p_emac->EMAC_NCR = ul_ncr;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get network control value.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*/
|
||||
|
||||
static inline uint32_t emac_get_network_control(Emac* p_emac)
|
||||
{
|
||||
return p_emac->EMAC_NCR;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable EMAC receive.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable EMAC receiver, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_receive(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCR |= EMAC_NCR_RE;
|
||||
} else {
|
||||
p_emac->EMAC_NCR &= ~EMAC_NCR_RE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable EMAC transmit.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable EMAC transmit, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_transmit(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCR |= EMAC_NCR_TE;
|
||||
} else {
|
||||
p_emac->EMAC_NCR &= ~EMAC_NCR_TE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable EMAC management.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable EMAC management, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_management(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCR |= EMAC_NCR_MPE;
|
||||
} else {
|
||||
p_emac->EMAC_NCR &= ~EMAC_NCR_MPE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clear all statistics registers.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*/
|
||||
static inline void emac_clear_statistics(Emac* p_emac)
|
||||
{
|
||||
p_emac->EMAC_NCR |= EMAC_NCR_CLRSTAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Increase all statistics registers.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*/
|
||||
static inline void emac_increase_statistics(Emac* p_emac)
|
||||
{
|
||||
p_emac->EMAC_NCR |= EMAC_NCR_INCSTAT;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable statistics registers writing.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable the statistics registers writing, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_statistics_write(Emac* p_emac,
|
||||
uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCR |= EMAC_NCR_WESTAT;
|
||||
} else {
|
||||
p_emac->EMAC_NCR &= ~EMAC_NCR_WESTAT;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief In half-duplex mode, forces collisions on all received frames.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable the back pressure, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_back_pressure(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCR |= EMAC_NCR_BP;
|
||||
} else {
|
||||
p_emac->EMAC_NCR &= ~EMAC_NCR_BP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Start transmission.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*/
|
||||
static inline void emac_start_transmission(Emac* p_emac)
|
||||
{
|
||||
p_emac->EMAC_NCR |= EMAC_NCR_TSTART;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Halt transmission.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*/
|
||||
static inline void emac_halt_transmission(Emac* p_emac)
|
||||
{
|
||||
p_emac->EMAC_NCR |= EMAC_NCR_THALT;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set up network configuration register.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param ul_cfg Network configuration value.
|
||||
*/
|
||||
static inline void emac_set_configure(Emac* p_emac, uint32_t ul_cfg)
|
||||
{
|
||||
p_emac->EMAC_NCFGR = ul_cfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get network configuration.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*
|
||||
* \return Network configuration.
|
||||
*/
|
||||
static inline uint32_t emac_get_configure(Emac* p_emac)
|
||||
{
|
||||
return p_emac->EMAC_NCFGR;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set speed.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_speed 1 to indicate 100Mbps, 0 to 10Mbps.
|
||||
*/
|
||||
static inline void emac_set_speed(Emac* p_emac, uint8_t uc_speed)
|
||||
{
|
||||
if (uc_speed) {
|
||||
p_emac->EMAC_NCFGR |= EMAC_NCFGR_SPD;
|
||||
} else {
|
||||
p_emac->EMAC_NCFGR &= ~EMAC_NCFGR_SPD;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable Full-Duplex mode.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable the Full-Duplex mode, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_full_duplex(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCFGR |= EMAC_NCFGR_FD;
|
||||
} else {
|
||||
p_emac->EMAC_NCFGR &= ~EMAC_NCFGR_FD;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable Copy(Receive) All Valid Frames.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable copying all valid frames, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_copy_all(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCFGR |= EMAC_NCFGR_CAF;
|
||||
} else {
|
||||
p_emac->EMAC_NCFGR &= ~EMAC_NCFGR_CAF;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable jumbo frames (up to 10240 bytes).
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable the jumbo frames, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_jumbo_frames(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCFGR |= EMAC_NCFGR_JFRAME;
|
||||
} else {
|
||||
p_emac->EMAC_NCFGR &= ~EMAC_NCFGR_JFRAME;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable/Enable broadcast receiving.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 1 to disable the broadcast, else to enable it.
|
||||
*/
|
||||
static inline void emac_disable_broadcast(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCFGR |= EMAC_NCFGR_NBC;
|
||||
} else {
|
||||
p_emac->EMAC_NCFGR &= ~EMAC_NCFGR_NBC;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable multicast hash.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable the multicast hash, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_multicast_hash(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCFGR |= EMAC_NCFGR_UNI;
|
||||
} else {
|
||||
p_emac->EMAC_NCFGR &= ~EMAC_NCFGR_UNI;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable big frames (over 1518, up to 1536).
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable big frames else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_big_frame(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCFGR |= EMAC_NCFGR_BIG;
|
||||
} else {
|
||||
p_emac->EMAC_NCFGR &= ~EMAC_NCFGR_BIG;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set MDC clock divider.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param ul_mck EMAC MCK.
|
||||
*
|
||||
* \return EMAC_OK if successfully.
|
||||
*/
|
||||
static inline uint8_t emac_set_clock(Emac* p_emac, uint32_t ul_mck)
|
||||
{
|
||||
uint32_t ul_clk;
|
||||
|
||||
if (ul_mck > EMAC_CLOCK_SPEED_160MHZ) {
|
||||
return EMAC_INVALID;
|
||||
} else if (ul_mck > EMAC_CLOCK_SPEED_80MHZ) {
|
||||
ul_clk = EMAC_NCFGR_CLK_MCK_64;
|
||||
} else if (ul_mck > EMAC_CLOCK_SPEED_40MHZ) {
|
||||
ul_clk = EMAC_NCFGR_CLK_MCK_32;
|
||||
} else if (ul_mck > EMAC_CLOCK_SPEED_20MHZ) {
|
||||
ul_clk = EMAC_NCFGR_CLK_MCK_16;
|
||||
} else {
|
||||
ul_clk = EMAC_NCFGR_CLK_MCK_8;
|
||||
}
|
||||
|
||||
p_emac->EMAC_NCFGR &= ~EMAC_NCFGR_CLK_Msk;
|
||||
p_emac->EMAC_NCFGR |= ul_clk;
|
||||
|
||||
return EMAC_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable retry test.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable the EMAC receiver, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_retry_test(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCFGR |= EMAC_NCFGR_RTY;
|
||||
} else {
|
||||
p_emac->EMAC_NCFGR &= ~EMAC_NCFGR_RTY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable pause (when a valid pause frame is received).
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable pause frame, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_pause_frame(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCFGR |= EMAC_NCFGR_PAE;
|
||||
} else {
|
||||
p_emac->EMAC_NCFGR &= ~EMAC_NCFGR_PAE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set receive buffer offset to 0 ~ 3.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*/
|
||||
static inline void emac_set_rx_buffer_offset(Emac* p_emac, uint8_t uc_offset)
|
||||
{
|
||||
p_emac->EMAC_NCFGR &= ~EMAC_NCFGR_RBOF_Msk;
|
||||
p_emac->EMAC_NCFGR |=
|
||||
(EMAC_NCFGR_RBOF_Msk & ((uc_offset) << EMAC_NCFGR_RBOF_Pos));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable receive length field checking.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable receive length field checking, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_rx_length_check(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCFGR |= EMAC_NCFGR_RLCE;
|
||||
} else {
|
||||
p_emac->EMAC_NCFGR &= ~EMAC_NCFGR_RLCE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable discarding FCS field of received frames.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable discarding FCS field of received frames, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_discard_fcs(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCFGR |= EMAC_NCFGR_DRFCS;
|
||||
} else {
|
||||
p_emac->EMAC_NCFGR &= ~EMAC_NCFGR_DRFCS;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable frames to be received in half-duplex mode
|
||||
* while transmitting.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable the received in half-duplex mode, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_efrhd(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCFGR |= EMAC_NCFGR_EFRHD;
|
||||
} else {
|
||||
p_emac->EMAC_NCFGR &= ~EMAC_NCFGR_EFRHD;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable ignore RX FCS.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable ignore RX FCS, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_ignore_rx_fcs(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_NCFGR |= EMAC_NCFGR_IRXFCS;
|
||||
} else {
|
||||
p_emac->EMAC_NCFGR &= ~EMAC_NCFGR_IRXFCS;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get Network Status.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*
|
||||
* \return Network status.
|
||||
*/
|
||||
static inline uint32_t emac_get_status(Emac* p_emac)
|
||||
{
|
||||
return p_emac->EMAC_NSR;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get MDIO IN pin status.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*
|
||||
* \return MDIO IN pin status.
|
||||
*/
|
||||
static inline uint8_t emac_get_MDIO(Emac* p_emac)
|
||||
{
|
||||
return ((p_emac->EMAC_NSR & EMAC_NSR_MDIO) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if PHY is idle.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*
|
||||
* \return 1 if PHY is idle.
|
||||
*/
|
||||
static inline uint8_t emac_is_phy_idle(Emac* p_emac)
|
||||
{
|
||||
return ((p_emac->EMAC_NSR & EMAC_NSR_IDLE) > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return transmit status.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*
|
||||
* \return Transmit status.
|
||||
*/
|
||||
static inline uint32_t emac_get_tx_status(Emac* p_emac)
|
||||
{
|
||||
return p_emac->EMAC_TSR;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clear transmit status.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param ul_status Transmit status.
|
||||
*/
|
||||
static inline void emac_clear_tx_status(Emac* p_emac, uint32_t ul_status)
|
||||
{
|
||||
p_emac->EMAC_TSR = ul_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return receive status.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*/
|
||||
static inline uint32_t emac_get_rx_status(Emac* p_emac)
|
||||
{
|
||||
return p_emac->EMAC_RSR;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clear receive status.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param ul_status Receive status.
|
||||
*/
|
||||
static inline void emac_clear_rx_status(Emac* p_emac, uint32_t ul_status)
|
||||
{
|
||||
p_emac->EMAC_RSR = ul_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set Rx Queue.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param ul_addr Rx queue address.
|
||||
*/
|
||||
static inline void emac_set_rx_queue(Emac* p_emac, uint32_t ul_addr)
|
||||
{
|
||||
p_emac->EMAC_RBQP = EMAC_RBQP_ADDR_Msk & ul_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get Rx Queue Address.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*
|
||||
* \return Rx queue address.
|
||||
*/
|
||||
static inline uint32_t emac_get_rx_queue(Emac* p_emac)
|
||||
{
|
||||
return p_emac->EMAC_RBQP;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set Tx Queue.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param ul_addr Tx queue address.
|
||||
*/
|
||||
static inline void emac_set_tx_queue(Emac* p_emac, uint32_t ul_addr)
|
||||
{
|
||||
p_emac->EMAC_TBQP = EMAC_TBQP_ADDR_Msk & ul_addr;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get Tx Queue.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*
|
||||
* \return Rx queue address.
|
||||
*/
|
||||
static inline uint32_t emac_get_tx_queue(Emac* p_emac)
|
||||
{
|
||||
return p_emac->EMAC_TBQP;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable interrupt(s).
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param ul_source Interrupt source(s) to be enabled.
|
||||
*/
|
||||
static inline void emac_enable_interrupt(Emac* p_emac, uint32_t ul_source)
|
||||
{
|
||||
p_emac->EMAC_IER = ul_source;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable interrupt(s).
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param ul_source Interrupt source(s) to be disabled.
|
||||
*/
|
||||
static inline void emac_disable_interrupt(Emac* p_emac, uint32_t ul_source)
|
||||
{
|
||||
p_emac->EMAC_IDR = ul_source;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return interrupt status.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*
|
||||
* \return Interrupt status.
|
||||
*/
|
||||
static inline uint32_t emac_get_interrupt_status(Emac* p_emac)
|
||||
{
|
||||
return p_emac->EMAC_ISR;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return interrupt mask.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*
|
||||
* \return Interrupt mask.
|
||||
*/
|
||||
static inline uint32_t emac_get_interrupt_mask(Emac* p_emac)
|
||||
{
|
||||
return p_emac->EMAC_IMR;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Execute PHY maintenance command.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_phy_addr PHY address.
|
||||
* \param uc_reg_addr Register address.
|
||||
* \param uc_rw 1 to Read, 0 to write.
|
||||
* \param us_data Data to be performed, write only.
|
||||
*/
|
||||
static inline void emac_maintain_phy(Emac* p_emac,
|
||||
uint8_t uc_phy_addr, uint8_t uc_reg_addr, uint8_t uc_rw,
|
||||
uint16_t us_data)
|
||||
{
|
||||
/* Wait until bus idle */
|
||||
while ((p_emac->EMAC_NSR & EMAC_NSR_IDLE) == 0);
|
||||
/* Write maintain register */
|
||||
p_emac->EMAC_MAN = EMAC_MAN_CODE(EMAC_MAN_CODE_VALUE)
|
||||
| EMAC_MAN_SOF(EMAC_MAN_SOF_VALUE)
|
||||
| EMAC_MAN_PHYA(uc_phy_addr)
|
||||
| EMAC_MAN_REGA(uc_reg_addr)
|
||||
| EMAC_MAN_RW((uc_rw ? EMAC_MAN_RW_TYPE : EMAC_MAN_READ_ONLY))
|
||||
| EMAC_MAN_DATA(us_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get PHY maintenance data returned.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*
|
||||
* \return Get PHY data.
|
||||
*/
|
||||
static inline uint16_t emac_get_phy_data(Emac* p_emac)
|
||||
{
|
||||
/* Wait until bus idle */
|
||||
while ((p_emac->EMAC_NSR & EMAC_NSR_IDLE) == 0);
|
||||
/* Return data */
|
||||
return (uint16_t) (p_emac->EMAC_MAN & EMAC_MAN_DATA_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set pause time.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param us_pause_time Pause time.
|
||||
*/
|
||||
static inline void emac_set_pause_time(Emac* p_emac, uint16_t us_pause_time)
|
||||
{
|
||||
p_emac->EMAC_PTR = us_pause_time;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set Hash.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param ul_hash_top Hash top.
|
||||
* \param ul_hash_bottom Hash bottom.
|
||||
*/
|
||||
static inline void emac_set_hash(Emac* p_emac, uint32_t ul_hash_top,
|
||||
uint32_t ul_hash_bottom)
|
||||
{
|
||||
p_emac->EMAC_HRB = ul_hash_bottom;
|
||||
p_emac->EMAC_HRT = ul_hash_top;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set 64 bits Hash.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param ull_hash 64 bits hash value.
|
||||
*/
|
||||
static inline void emac_set_hash64(Emac* p_emac, uint64_t ull_hash)
|
||||
{
|
||||
p_emac->EMAC_HRB = (uint32_t) ull_hash;
|
||||
p_emac->EMAC_HRT = (uint32_t) (ull_hash >> 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set MAC Address.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_index EMAC specific address register index.
|
||||
* \param p_mac_addr EMAC address.
|
||||
*/
|
||||
static inline void emac_set_address(Emac* p_emac, uint8_t uc_index,
|
||||
uint8_t* p_mac_addr)
|
||||
{
|
||||
p_emac->EMAC_SA[uc_index].EMAC_SAxB = (p_mac_addr[3] << 24)
|
||||
| (p_mac_addr[2] << 16)
|
||||
| (p_mac_addr[1] << 8)
|
||||
| (p_mac_addr[0]);
|
||||
p_emac->EMAC_SA[uc_index].EMAC_SAxT = (p_mac_addr[5] << 8)
|
||||
| (p_mac_addr[4]);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set MAC Address via 2 dword.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_index EMAC specific address register index.
|
||||
* \param ul_mac_top EMAC top address.
|
||||
* \param ul_mac_bottom EMAC bottom address.
|
||||
*/
|
||||
static inline void emac_set_address32(Emac* p_emac, uint8_t uc_index,
|
||||
uint32_t ul_mac_top, uint32_t ul_mac_bottom)
|
||||
{
|
||||
p_emac->EMAC_SA[uc_index].EMAC_SAxB = ul_mac_bottom;
|
||||
p_emac->EMAC_SA[uc_index].EMAC_SAxT = ul_mac_top;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set MAC Address via int64.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_index EMAC specific address register index.
|
||||
* \param ull_mac 64-bit EMAC address.
|
||||
*/
|
||||
static inline void emac_set_address64(Emac* p_emac, uint8_t uc_index,
|
||||
uint64_t ull_mac)
|
||||
{
|
||||
p_emac->EMAC_SA[uc_index].EMAC_SAxB = (uint32_t) ull_mac;
|
||||
p_emac->EMAC_SA[uc_index].EMAC_SAxT = (uint32_t) (ull_mac >> 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set type ID.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param us_type_id Type to be set.
|
||||
*/
|
||||
static inline void emac_set_type_id(Emac* p_emac, uint16_t us_type_id)
|
||||
{
|
||||
p_emac->EMAC_TID = EMAC_TID_TID(us_type_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get type ID.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
*
|
||||
* \return Type ID.
|
||||
*/
|
||||
static inline uint16_t emac_get_type_id(Emac* p_emac)
|
||||
{
|
||||
return (p_emac->EMAC_TID & EMAC_TID_TID_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable RMII.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable the RMII mode, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_rmii(Emac* p_emac, uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_USRIO |= EMAC_USRIO_RMII;
|
||||
} else {
|
||||
p_emac->EMAC_USRIO &= ~EMAC_USRIO_RMII;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable transceiver input clock.
|
||||
*
|
||||
* \param p_emac Pointer to the EMAC instance.
|
||||
* \param uc_enable 0 to disable transceiver input clock, else to enable it.
|
||||
*/
|
||||
static inline void emac_enable_transceiver_clock(Emac* p_emac,
|
||||
uint8_t uc_enable)
|
||||
{
|
||||
if (uc_enable) {
|
||||
p_emac->EMAC_USRIO |= EMAC_USRIO_CLKEN;
|
||||
} else {
|
||||
p_emac->EMAC_USRIO &= ~EMAC_USRIO_CLKEN;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t emac_phy_read(Emac* p_emac, uint8_t uc_phy_address, uint8_t uc_address,
|
||||
uint32_t* p_value);
|
||||
uint8_t emac_phy_write(Emac* p_emac, uint8_t uc_phy_address,
|
||||
uint8_t uc_address, uint32_t ul_value);
|
||||
void emac_dev_init(Emac* p_emac, emac_device_t* p_emac_dev,
|
||||
emac_options_t* p_opt);
|
||||
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);
|
||||
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);
|
||||
uint32_t emac_dev_get_tx_load(emac_device_t* p_emac_dev);
|
||||
void emac_dev_set_rx_callback(emac_device_t* p_emac_dev,
|
||||
emac_dev_tx_cb_t func_rx_cb);
|
||||
uint8_t emac_dev_set_tx_wakeup_callback(emac_device_t* p_emac_dev,
|
||||
emac_dev_wakeup_cb_t func_wakeup, uint8_t uc_threshold);
|
||||
void emac_dev_reset(emac_device_t* p_emac_dev);
|
||||
void emac_handler(emac_device_t* p_emac_dev);
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
||||
|
||||
/**
|
||||
* \page emac_quickstart Quickstart guide for EMAC driver.
|
||||
*
|
||||
* This is the quickstart guide for the \ref emac_group "Ethernet MAC",
|
||||
* 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 emac_basic_use_case Basic use case
|
||||
* In the basic use case, the EMAC driver are configured for:
|
||||
* - PHY component DM9161A is used
|
||||
* - EMAC uses RMII mode
|
||||
* - The number of receive buffer is 16
|
||||
* - The number of transfer buffer is 8
|
||||
* - MAC address is set to 00-04-25-1c-a0-02
|
||||
* - IP address is set to 192.168.0.2
|
||||
* - IP address is set to 192.168.0.2
|
||||
* - Gateway is set to 192.168.0.1
|
||||
* - Network mask is 255.255.255.0
|
||||
* - PHY operation max retry count is 1000000
|
||||
* - EMAC is configured to not support copy all frame and support broadcast
|
||||
* - The reset PIN of DM9161A is connected to the NRST of SAM3X
|
||||
* - The data will be read from the ethernet
|
||||
*
|
||||
* \section emac_basic_use_case_setup Setup steps
|
||||
*
|
||||
* \subsection emac_basic_use_case_setup_prereq Prerequisites
|
||||
* -# \ref sysclk_group "System Clock Management (sysclock)"
|
||||
* -# \ref pio_group "Parallel Input/Output Controller (pio)"
|
||||
* -# \ref pmc_group "Power Management Controller (pmc)"
|
||||
* -# \ref sam_drivers_rstc_group "Reset Controller (RSTC)"
|
||||
* -# \ref dm9161a_ethernet_phy_group "PHY component (DM9161A)"
|
||||
*
|
||||
* \subsection emac_basic_use_case_setup_code Example code
|
||||
* Content of conf_eth.h
|
||||
* \code
|
||||
* #define EMAC_RX_BUFFERS 16
|
||||
* #define EMAC_TX_BUFFERS 8
|
||||
* #define MAC_PHY_RETRY_MAX 1000000
|
||||
* #define ETHERNET_CONF_ETHADDR0 0x00
|
||||
* #define ETHERNET_CONF_ETHADDR0 0x00
|
||||
* #define ETHERNET_CONF_ETHADDR1 0x04
|
||||
* #define ETHERNET_CONF_ETHADDR2 0x25
|
||||
* #define ETHERNET_CONF_ETHADDR3 0x1C
|
||||
* #define ETHERNET_CONF_ETHADDR4 0xA0
|
||||
* #define ETHERNET_CONF_ETHADDR5 0x02
|
||||
* #define ETHERNET_CONF_IPADDR0 192
|
||||
* #define ETHERNET_CONF_IPADDR1 168
|
||||
* #define ETHERNET_CONF_IPADDR2 0
|
||||
* #define ETHERNET_CONF_IPADDR3 2
|
||||
* #define ETHERNET_CONF_GATEWAY_ADDR0 192
|
||||
* #define ETHERNET_CONF_GATEWAY_ADDR1 168
|
||||
* #define ETHERNET_CONF_GATEWAY_ADDR2 0
|
||||
* #define ETHERNET_CONF_GATEWAY_ADDR3 1
|
||||
* #define ETHERNET_CONF_NET_MASK0 255
|
||||
* #define ETHERNET_CONF_NET_MASK1 255
|
||||
* #define ETHERNET_CONF_NET_MASK2 255
|
||||
* #define ETHERNET_CONF_NET_MASK3 0
|
||||
* #define ETH_PHY_MODE BOARD_EMAC_MODE_RMII
|
||||
* \endcode
|
||||
*
|
||||
* A specific emac device and the receive data buffer must be defined; another ul_frm_size should be defined
|
||||
* to trace the actual size of the data received.
|
||||
* \code
|
||||
* static emac_device_t gs_emac_dev;
|
||||
* static volatile uint8_t gs_uc_eth_buffer[EMAC_FRAME_LENTGH_MAX];
|
||||
*
|
||||
* uint32_t ul_frm_size;
|
||||
* \endcode
|
||||
*
|
||||
* Add to application C-file:
|
||||
* \code
|
||||
* void emac_init(void)
|
||||
* {
|
||||
* sysclk_init();
|
||||
*
|
||||
* board_init();
|
||||
*
|
||||
* rstc_set_external_reset(RSTC, 13);
|
||||
* rstc_reset_extern(RSTC);
|
||||
* while (rstc_get_status(RSTC) & RSTC_SR_NRSTL) {
|
||||
* };
|
||||
*
|
||||
* ul_delay = sysclk_get_cpu_hz() / 1000 / 3 * 400;
|
||||
* while (ul_delay--);
|
||||
*
|
||||
* pmc_enable_periph_clk(ID_EMAC);
|
||||
*
|
||||
* emac_option.uc_copy_all_frame = 0;
|
||||
* emac_option.uc_no_boardcast = 0;
|
||||
* memcpy(emac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));
|
||||
* gs_emac_dev.p_hw = EMAC;
|
||||
*
|
||||
* emac_dev_init(EMAC, &gs_emac_dev, &emac_option);
|
||||
*
|
||||
* NVIC_EnableIRQ(EMAC_IRQn);
|
||||
*
|
||||
* ethernet_phy_init(EMAC, BOARD_EMAC_PHY_ADDR, sysclk_get_cpu_hz()
|
||||
*
|
||||
* ethernet_phy_auto_negotiate(EMAC, BOARD_EMAC_PHY_ADDR
|
||||
*
|
||||
* ethernet_phy_set_link(EMAC, BOARD_EMAC_PHY_ADDR, 1)
|
||||
* \endcode
|
||||
*
|
||||
* \subsection emac_basic_use_case_setup_flow Workflow
|
||||
* -# Ensure that conf_emac.h is present and contains the
|
||||
* following configuration symbol. This configuration file is used
|
||||
* by the driver and should not be included by the user.
|
||||
* - \code
|
||||
* #define EMAC_RX_BUFFERS 16
|
||||
* #define EMAC_TX_BUFFERS 8
|
||||
* #define MAC_PHY_RETRY_MAX 1000000
|
||||
* #define ETHERNET_CONF_ETHADDR0 0x00
|
||||
* #define ETHERNET_CONF_ETHADDR0 0x00
|
||||
* #define ETHERNET_CONF_ETHADDR1 0x04
|
||||
* #define ETHERNET_CONF_ETHADDR2 0x25
|
||||
* #define ETHERNET_CONF_ETHADDR3 0x1C
|
||||
* #define ETHERNET_CONF_ETHADDR4 0xA0
|
||||
* #define ETHERNET_CONF_ETHADDR5 0x02
|
||||
* #define ETHERNET_CONF_IPADDR0 192
|
||||
* #define ETHERNET_CONF_IPADDR1 168
|
||||
* #define ETHERNET_CONF_IPADDR2 0
|
||||
* #define ETHERNET_CONF_IPADDR3 2
|
||||
* #define ETHERNET_CONF_GATEWAY_ADDR0 192
|
||||
* #define ETHERNET_CONF_GATEWAY_ADDR1 168
|
||||
* #define ETHERNET_CONF_GATEWAY_ADDR2 0
|
||||
* #define ETHERNET_CONF_GATEWAY_ADDR3 1
|
||||
* #define ETHERNET_CONF_NET_MASK0 255
|
||||
* #define ETHERNET_CONF_NET_MASK1 255
|
||||
* #define ETHERNET_CONF_NET_MASK2 255
|
||||
* #define ETHERNET_CONF_NET_MASK3 0
|
||||
* #define ETH_PHY_MODE BOARD_EMAC_MODE_RMII
|
||||
* \endcode
|
||||
* -# Enable the system clock:
|
||||
* - \code sysclk_init(); \endcode
|
||||
* -# Enable PIO configurations for EMAC:
|
||||
* - \code board_init(); \endcode
|
||||
* -# Reset PHY; this is required by the DM9161A component:
|
||||
* - \code
|
||||
* rstc_set_external_reset(RSTC, 13);
|
||||
* rstc_reset_extern(RSTC);
|
||||
* while (rstc_get_status(RSTC) & RSTC_SR_NRSTL) {
|
||||
* };
|
||||
* \endcode
|
||||
* -# Wait for PHY ready:
|
||||
* - \code
|
||||
* ul_delay = sysclk_get_cpu_hz() / 1000 / 3 * 400;
|
||||
* while (ul_delay--);
|
||||
* \endcode
|
||||
* -# Enable PMC clock for EMAC:
|
||||
* - \code pmc_enable_periph_clk(ID_EMAC); \endcode
|
||||
* -# Set the EMAC options; it's set to copy all frame and support broadcast:
|
||||
* - \code
|
||||
* emac_option.uc_copy_all_frame = 0;
|
||||
* emac_option.uc_no_boardcast = 0;
|
||||
* memcpy(emac_option.uc_mac_addr, gs_uc_mac_address, sizeof(gs_uc_mac_address));
|
||||
* gs_emac_dev.p_hw = EMAC;
|
||||
* \endcode
|
||||
* -# Initialize EMAC device with the filled option:
|
||||
* - \code
|
||||
* emac_dev_init(EMAC, &gs_emac_dev, &emac_option);
|
||||
* \endcode
|
||||
* -# Enable the interrupt service for EMAC:
|
||||
* - \code
|
||||
* NVIC_EnableIRQ(EMAC_IRQn);
|
||||
* \endcode
|
||||
* -# Initialize the PHY component:
|
||||
* - \code
|
||||
* ethernet_phy_init(EMAC, BOARD_EMAC_PHY_ADDR, sysclk_get_cpu_hz());
|
||||
* \endcode
|
||||
* -# The link will be established based on auto negotiation.
|
||||
* - \code
|
||||
* ethernet_phy_auto_negotiate(EMAC, BOARD_EMAC_PHY_ADDR);
|
||||
* \endcode
|
||||
* -# Establish the ethernet link; the network can be worked from now on:
|
||||
* - \code
|
||||
* ethernet_phy_set_link(EMAC, BOARD_EMAC_PHY_ADDR, 1);
|
||||
* \endcode
|
||||
*
|
||||
* \section emac_basic_use_case_usage Usage steps
|
||||
* \subsection emac_basic_use_case_usage_code Example code
|
||||
* Add to, e.g., main loop in application C-file:
|
||||
* \code
|
||||
* emac_dev_read(&gs_emac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size));
|
||||
* \endcode
|
||||
*
|
||||
* \subsection emac_basic_use_case_usage_flow Workflow
|
||||
* -# Start reading the data from the ethernet:
|
||||
* - \code emac_dev_read(&gs_emac_dev, (uint8_t *) gs_uc_eth_buffer, sizeof(gs_uc_eth_buffer), &ul_frm_size)); \endcode
|
||||
*/
|
||||
|
||||
#endif /* EMAC_H_INCLUDED */
|
80
hardware/arduino/sam/system/libsam/include/gpbr.h
Normal file
80
hardware/arduino/sam/system/libsam/include/gpbr.h
Normal 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 */
|
210
hardware/arduino/sam/system/libsam/include/ssc.h
Normal file
210
hardware/arduino/sam/system/libsam/include/ssc.h
Normal 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 */
|
73
hardware/arduino/sam/system/libsam/include/trng.h
Normal file
73
hardware/arduino/sam/system/libsam/include/trng.h
Normal 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 */
|
@ -386,7 +386,7 @@ Pdc *adc12b_get_pdc_base(const Adc12b *p_adc)
|
||||
{
|
||||
return PDC_ADC12B;
|
||||
}
|
||||
#endif
|
||||
#endif // SAM3U_SERIES
|
||||
|
||||
//@}
|
||||
|
||||
|
776
hardware/arduino/sam/system/libsam/source/can.c
Normal file
776
hardware/arduino/sam/system/libsam/source/can.c
Normal file
@ -0,0 +1,776 @@
|
||||
/**
|
||||
* \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"
|
||||
|
||||
/// @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);
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SAM3XA_SERIES
|
||||
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
@ -27,7 +27,7 @@
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "dacc.h"
|
||||
#include "../chip.h"
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
@ -37,6 +37,8 @@ extern "C" {
|
||||
/**INDENT-ON**/
|
||||
/// @endcond
|
||||
|
||||
#if (SAM3XA_SERIES) || (SAM3N_SERIES) || (SAM3S_SERIES)
|
||||
|
||||
/**
|
||||
* \defgroup sam_drivers_dacc_group Digital-to-Analog Converter Controller (DACC)
|
||||
*
|
||||
@ -472,6 +474,9 @@ uint32_t dacc_get_analog_control(Dacc *p_dacc)
|
||||
|
||||
//@}
|
||||
|
||||
#endif // SAM3XA_SERIES
|
||||
|
||||
|
||||
/// @cond 0
|
||||
/**INDENT-OFF**/
|
||||
#ifdef __cplusplus
|
||||
|
402
hardware/arduino/sam/system/libsam/source/efc.c
Normal file
402
hardware/arduino/sam/system/libsam/source/efc.c
Normal 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
|
797
hardware/arduino/sam/system/libsam/source/emac.c.disabled
Normal file
797
hardware/arduino/sam/system/libsam/source/emac.c.disabled
Normal file
@ -0,0 +1,797 @@
|
||||
/**
|
||||
* \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.
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** 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, true);
|
||||
emac_enable_receive(p_emac, true);
|
||||
emac_enable_statistics_write(p_emac, true);
|
||||
|
||||
/* 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
|
94
hardware/arduino/sam/system/libsam/source/gpbr.c
Normal file
94
hardware/arduino/sam/system/libsam/source/gpbr.c
Normal 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
|
835
hardware/arduino/sam/system/libsam/source/ssc.c
Normal file
835
hardware/arduino/sam/system/libsam/source/ssc.c
Normal 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
|
160
hardware/arduino/sam/system/libsam/source/trng.c
Normal file
160
hardware/arduino/sam/system/libsam/source/trng.c
Normal 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
|
||||
|
||||
/**
|
||||
* \}
|
||||
*/
|
Binary file not shown.
@ -72,7 +72,6 @@ pmc.o:
|
||||
00000000 T pmc_switch_udpck_to_upllck
|
||||
|
||||
pwmc.o:
|
||||
00000000 r C.9.7280
|
||||
00000000 t FindClockConfiguration
|
||||
00000000 T PWMC_ConfigureChannel
|
||||
00000000 T PWMC_ConfigureChannelExt
|
||||
@ -100,14 +99,14 @@ pwmc.o:
|
||||
00000000 T PWMC_SetSyncChannelUpdateUnlock
|
||||
00000000 T PWMC_WriteBuffer
|
||||
U __assert_func
|
||||
00000000 r __func__.5974
|
||||
00000000 r __func__.5985
|
||||
00000000 r __func__.6000
|
||||
00000000 r __func__.6011
|
||||
00000000 r __func__.6022
|
||||
00000000 r __func__.6029
|
||||
00000000 r __func__.6113
|
||||
00000000 r __func__.6119
|
||||
00000000 r __func__.6271
|
||||
00000000 r __func__.6282
|
||||
00000000 r __func__.6297
|
||||
00000000 r __func__.6308
|
||||
00000000 r __func__.6319
|
||||
00000000 r __func__.6326
|
||||
00000000 r __func__.6410
|
||||
00000000 r __func__.6416
|
||||
|
||||
rtc.o:
|
||||
00000000 T RTC_ClearSCCR
|
||||
@ -123,9 +122,9 @@ rtc.o:
|
||||
00000000 T RTC_SetTime
|
||||
00000000 T RTC_SetTimeAlarm
|
||||
U __assert_func
|
||||
00000000 r __func__.5971
|
||||
00000000 r __func__.5980
|
||||
00000000 r __func__.5985
|
||||
00000000 r __func__.6268
|
||||
00000000 r __func__.6277
|
||||
00000000 r __func__.6282
|
||||
|
||||
rtt.o:
|
||||
00000000 T RTT_EnableIT
|
||||
@ -134,8 +133,8 @@ rtt.o:
|
||||
00000000 T RTT_SetAlarm
|
||||
00000000 T RTT_SetPrescaler
|
||||
U __assert_func
|
||||
00000000 r __func__.5978
|
||||
00000000 r __func__.5986
|
||||
00000000 r __func__.6275
|
||||
00000000 r __func__.6283
|
||||
|
||||
spi.o:
|
||||
00000000 T SPI_Configure
|
||||
@ -161,9 +160,9 @@ tc.o:
|
||||
00000000 T TC_Start
|
||||
00000000 T TC_Stop
|
||||
U __assert_func
|
||||
00000000 r __func__.5973
|
||||
00000000 r __func__.5979
|
||||
00000000 r __func__.5985
|
||||
00000000 r __func__.6270
|
||||
00000000 r __func__.6276
|
||||
00000000 r __func__.6282
|
||||
|
||||
timetick.o:
|
||||
00000000 T GetTickCount
|
||||
@ -190,18 +189,18 @@ twi.o:
|
||||
00000000 T TWI_TransferComplete
|
||||
00000000 T TWI_WriteByte
|
||||
U __assert_func
|
||||
00000000 r __func__.6346
|
||||
00000000 r __func__.6361
|
||||
00000000 r __func__.6365
|
||||
00000000 r __func__.6372
|
||||
00000000 r __func__.6376
|
||||
00000000 r __func__.6381
|
||||
00000000 r __func__.6389
|
||||
00000000 r __func__.6403
|
||||
00000000 r __func__.6408
|
||||
00000000 r __func__.6412
|
||||
00000000 r __func__.6417
|
||||
00000000 r __func__.6421
|
||||
00000000 r __func__.6635
|
||||
00000000 r __func__.6650
|
||||
00000000 r __func__.6654
|
||||
00000000 r __func__.6661
|
||||
00000000 r __func__.6665
|
||||
00000000 r __func__.6670
|
||||
00000000 r __func__.6678
|
||||
00000000 r __func__.6692
|
||||
00000000 r __func__.6697
|
||||
00000000 r __func__.6701
|
||||
00000000 r __func__.6706
|
||||
00000000 r __func__.6710
|
||||
|
||||
usart.o:
|
||||
00000000 T USART_Configure
|
||||
@ -220,7 +219,7 @@ usart.o:
|
||||
00000000 T USART_Write
|
||||
00000000 T USART_WriteBuffer
|
||||
U __assert_func
|
||||
00000000 r __func__.6267
|
||||
00000000 r __func__.6556
|
||||
|
||||
wdt.o:
|
||||
00000000 T WDT_Disable
|
||||
@ -430,3 +429,110 @@ dacc.o:
|
||||
00000000 T dacc_set_trigger
|
||||
00000000 T dacc_set_writeprotect
|
||||
00000000 T dacc_write_conversion_data
|
||||
|
||||
can.o:
|
||||
00000000 R can_bit_time
|
||||
00000000 T can_disable
|
||||
00000000 T can_disable_autobaud_listen_mode
|
||||
00000000 T can_disable_interrupt
|
||||
00000000 T can_disable_low_power_mode
|
||||
00000000 T can_disable_overload_frame
|
||||
00000000 T can_disable_time_triggered_mode
|
||||
00000000 T can_disable_timer_freeze
|
||||
00000000 T can_disable_tx_repeat
|
||||
00000000 T can_enable
|
||||
00000000 T can_enable_autobaud_listen_mode
|
||||
00000000 T can_enable_interrupt
|
||||
00000000 T can_enable_low_power_mode
|
||||
00000000 T can_enable_overload_frame
|
||||
00000000 T can_enable_time_triggered_mode
|
||||
00000000 T can_enable_timer_freeze
|
||||
00000000 T can_enable_tx_repeat
|
||||
00000000 T can_get_internal_timer_value
|
||||
00000000 T can_get_interrupt_mask
|
||||
00000000 T can_get_rx_error_cnt
|
||||
00000000 T can_get_status
|
||||
00000000 T can_get_timestamp_value
|
||||
00000000 T can_get_tx_error_cnt
|
||||
00000000 T can_global_send_abort_cmd
|
||||
00000000 T can_global_send_transfer_cmd
|
||||
00000000 T can_init
|
||||
00000000 T can_mailbox_get_status
|
||||
00000000 T can_mailbox_init
|
||||
00000000 T can_mailbox_read
|
||||
00000000 T can_mailbox_send_abort_cmd
|
||||
00000000 T can_mailbox_send_transfer_cmd
|
||||
00000000 T can_mailbox_set_timemark
|
||||
00000000 T can_mailbox_tx_remote_frame
|
||||
00000000 T can_mailbox_write
|
||||
00000000 T can_reset_all_mailbox
|
||||
00000000 T can_reset_internal_timer
|
||||
00000000 T can_set_rx_sync_stage
|
||||
00000000 T can_set_timestamp_capture_point
|
||||
|
||||
efc.o:
|
||||
00000000 T efc_disable_frdy_interrupt
|
||||
00000000 T efc_enable_frdy_interrupt
|
||||
00000000 T efc_get_flash_access_mode
|
||||
00000000 T efc_get_result
|
||||
00000000 T efc_get_status
|
||||
00000000 T efc_get_wait_state
|
||||
00000000 T efc_init
|
||||
00000000 T efc_perform_command
|
||||
0000006c T efc_perform_fcr
|
||||
00000000 T efc_perform_read_sequence
|
||||
00000000 T efc_set_flash_access_mode
|
||||
00000000 T efc_set_wait_state
|
||||
00000068 T efc_write_fmr
|
||||
00000000 b iap_perform_command.6537
|
||||
|
||||
gpbr.o:
|
||||
00000000 T gpbr_read
|
||||
00000000 T gpbr_write
|
||||
|
||||
ssc.o:
|
||||
U memset
|
||||
00000000 T ssc_disable_interrupt
|
||||
00000000 T ssc_disable_rx
|
||||
00000000 T ssc_disable_tx
|
||||
00000000 T ssc_disable_tx_frame_sync_data
|
||||
00000000 T ssc_enable_interrupt
|
||||
00000000 T ssc_enable_rx
|
||||
00000000 T ssc_enable_tx
|
||||
00000000 T ssc_enable_tx_frame_sync_data
|
||||
00000000 T ssc_get_interrupt_mask
|
||||
00000000 T ssc_get_rx_access
|
||||
00000000 T ssc_get_rx_compare
|
||||
00000000 T ssc_get_status
|
||||
00000000 T ssc_get_tx_access
|
||||
00000000 T ssc_get_writeprotect_status
|
||||
00000000 T ssc_i2s_set_receiver
|
||||
00000000 T ssc_i2s_set_transmitter
|
||||
00000000 T ssc_is_rx_enabled
|
||||
00000000 T ssc_is_rx_ready
|
||||
00000000 T ssc_is_tx_empty
|
||||
00000000 T ssc_is_tx_enabled
|
||||
00000000 T ssc_is_tx_ready
|
||||
00000000 T ssc_read
|
||||
00000000 T ssc_read_sync_data
|
||||
00000000 T ssc_reset
|
||||
00000000 T ssc_set_clock_divider
|
||||
00000000 T ssc_set_loop_mode
|
||||
00000000 T ssc_set_normal_mode
|
||||
00000000 T ssc_set_receiver
|
||||
00000000 T ssc_set_rx_compare
|
||||
00000000 T ssc_set_rx_stop_selection
|
||||
00000000 T ssc_set_td_default_level
|
||||
00000000 T ssc_set_transmitter
|
||||
00000000 T ssc_set_writeprotect
|
||||
00000000 T ssc_write
|
||||
00000000 T ssc_write_sync_data
|
||||
|
||||
trng.o:
|
||||
00000000 T trng_disable
|
||||
00000000 T trng_disable_interrupt
|
||||
00000000 T trng_enable
|
||||
00000000 T trng_enable_interrupt
|
||||
00000000 T trng_get_interrupt_mask
|
||||
00000000 T trng_get_interrupt_status
|
||||
00000000 T trng_read_output_data
|
||||
|
Loading…
x
Reference in New Issue
Block a user