From 5d0ba1c64a1df2a55cab5ee194797dfd175c6aee Mon Sep 17 00:00:00 2001 From: Thibaut VIARD Date: Wed, 19 Dec 2012 15:20:14 +0100 Subject: [PATCH] [sam] adding more peripherals to SAM3X/Due --- .../sam/system/CMSIS/Device/ATMEL/sam.h | 35 +- .../sam/system/libsam/build_gcc/Makefile | 4 +- hardware/arduino/sam/system/libsam/chip.h | 13 +- .../arduino/sam/system/libsam/include/can.h | 468 +++++++ .../arduino/sam/system/libsam/include/efc.h | 132 ++ .../arduino/sam/system/libsam/include/emac.h | 1225 +++++++++++++++++ .../arduino/sam/system/libsam/include/gpbr.h | 80 ++ .../arduino/sam/system/libsam/include/ssc.h | 210 +++ .../arduino/sam/system/libsam/include/trng.h | 73 + .../sam/system/libsam/source/adc12_sam3u.c | 2 +- .../arduino/sam/system/libsam/source/can.c | 776 +++++++++++ .../arduino/sam/system/libsam/source/dacc.c | 7 +- .../arduino/sam/system/libsam/source/efc.c | 402 ++++++ .../sam/system/libsam/source/emac.c.disabled | 797 +++++++++++ .../arduino/sam/system/libsam/source/gpbr.c | 94 ++ .../arduino/sam/system/libsam/source/ssc.c | 835 +++++++++++ .../arduino/sam/system/libsam/source/trng.c | 160 +++ .../arduino_due_x/libsam_sam3x8e_gcc_rel.a | Bin 85290 -> 108544 bytes .../libsam_sam3x8e_gcc_rel.a.txt | 166 ++- 19 files changed, 5431 insertions(+), 48 deletions(-) create mode 100644 hardware/arduino/sam/system/libsam/include/can.h create mode 100644 hardware/arduino/sam/system/libsam/include/efc.h create mode 100644 hardware/arduino/sam/system/libsam/include/emac.h create mode 100644 hardware/arduino/sam/system/libsam/include/gpbr.h create mode 100644 hardware/arduino/sam/system/libsam/include/ssc.h create mode 100644 hardware/arduino/sam/system/libsam/include/trng.h create mode 100644 hardware/arduino/sam/system/libsam/source/can.c create mode 100644 hardware/arduino/sam/system/libsam/source/efc.c create mode 100644 hardware/arduino/sam/system/libsam/source/emac.c.disabled create mode 100644 hardware/arduino/sam/system/libsam/source/gpbr.c create mode 100644 hardware/arduino/sam/system/libsam/source/ssc.c create mode 100644 hardware/arduino/sam/system/libsam/source/trng.c diff --git a/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam.h b/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam.h index 97394e0f5..2c10bba80 100644 --- a/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam.h +++ b/hardware/arduino/sam/system/CMSIS/Device/ATMEL/sam.h @@ -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 * ---------------------------------------------------------------------------- */ diff --git a/hardware/arduino/sam/system/libsam/build_gcc/Makefile b/hardware/arduino/sam/system/libsam/build_gcc/Makefile index 63a124312..a04d3ca32 100644 --- a/hardware/arduino/sam/system/libsam/build_gcc/Makefile +++ b/hardware/arduino/sam/system/libsam/build_gcc/Makefile @@ -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 $@ diff --git a/hardware/arduino/sam/system/libsam/chip.h b/hardware/arduino/sam/system/libsam/chip.h index 0d90c7f19..298e48530 100644 --- a/hardware/arduino/sam/system/libsam/chip.h +++ b/hardware/arduino/sam/system/libsam/chip.h @@ -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_ */ diff --git a/hardware/arduino/sam/system/libsam/include/can.h b/hardware/arduino/sam/system/libsam/include/can.h new file mode 100644 index 000000000..66d4c1a60 --- /dev/null +++ b/hardware/arduino/sam/system/libsam/include/can.h @@ -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 */ diff --git a/hardware/arduino/sam/system/libsam/include/efc.h b/hardware/arduino/sam/system/libsam/include/efc.h new file mode 100644 index 000000000..07f78bba6 --- /dev/null +++ b/hardware/arduino/sam/system/libsam/include/efc.h @@ -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 */ diff --git a/hardware/arduino/sam/system/libsam/include/emac.h b/hardware/arduino/sam/system/libsam/include/emac.h new file mode 100644 index 000000000..cdcd03d00 --- /dev/null +++ b/hardware/arduino/sam/system/libsam/include/emac.h @@ -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 */ diff --git a/hardware/arduino/sam/system/libsam/include/gpbr.h b/hardware/arduino/sam/system/libsam/include/gpbr.h new file mode 100644 index 000000000..531af5d46 --- /dev/null +++ b/hardware/arduino/sam/system/libsam/include/gpbr.h @@ -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 */ diff --git a/hardware/arduino/sam/system/libsam/include/ssc.h b/hardware/arduino/sam/system/libsam/include/ssc.h new file mode 100644 index 000000000..4af8091b9 --- /dev/null +++ b/hardware/arduino/sam/system/libsam/include/ssc.h @@ -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 */ diff --git a/hardware/arduino/sam/system/libsam/include/trng.h b/hardware/arduino/sam/system/libsam/include/trng.h new file mode 100644 index 000000000..3b5f0dc4b --- /dev/null +++ b/hardware/arduino/sam/system/libsam/include/trng.h @@ -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 */ diff --git a/hardware/arduino/sam/system/libsam/source/adc12_sam3u.c b/hardware/arduino/sam/system/libsam/source/adc12_sam3u.c index 64e392337..77def4d3c 100644 --- a/hardware/arduino/sam/system/libsam/source/adc12_sam3u.c +++ b/hardware/arduino/sam/system/libsam/source/adc12_sam3u.c @@ -386,7 +386,7 @@ Pdc *adc12b_get_pdc_base(const Adc12b *p_adc) { return PDC_ADC12B; } -#endif +#endif // SAM3U_SERIES //@} diff --git a/hardware/arduino/sam/system/libsam/source/can.c b/hardware/arduino/sam/system/libsam/source/can.c new file mode 100644 index 000000000..b31562dee --- /dev/null +++ b/hardware/arduino/sam/system/libsam/source/can.c @@ -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 diff --git a/hardware/arduino/sam/system/libsam/source/dacc.c b/hardware/arduino/sam/system/libsam/source/dacc.c index aa8f9fe93..0637909db 100644 --- a/hardware/arduino/sam/system/libsam/source/dacc.c +++ b/hardware/arduino/sam/system/libsam/source/dacc.c @@ -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 diff --git a/hardware/arduino/sam/system/libsam/source/efc.c b/hardware/arduino/sam/system/libsam/source/efc.c new file mode 100644 index 000000000..364926f0e --- /dev/null +++ b/hardware/arduino/sam/system/libsam/source/efc.c @@ -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 + +/// @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 diff --git a/hardware/arduino/sam/system/libsam/source/emac.c.disabled b/hardware/arduino/sam/system/libsam/source/emac.c.disabled new file mode 100644 index 000000000..dfaa36dd1 --- /dev/null +++ b/hardware/arduino/sam/system/libsam/source/emac.c.disabled @@ -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 + +/// @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 diff --git a/hardware/arduino/sam/system/libsam/source/gpbr.c b/hardware/arduino/sam/system/libsam/source/gpbr.c new file mode 100644 index 000000000..83d34ebbc --- /dev/null +++ b/hardware/arduino/sam/system/libsam/source/gpbr.c @@ -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 diff --git a/hardware/arduino/sam/system/libsam/source/ssc.c b/hardware/arduino/sam/system/libsam/source/ssc.c new file mode 100644 index 000000000..ca18a6941 --- /dev/null +++ b/hardware/arduino/sam/system/libsam/source/ssc.c @@ -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 +#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 diff --git a/hardware/arduino/sam/system/libsam/source/trng.c b/hardware/arduino/sam/system/libsam/source/trng.c new file mode 100644 index 000000000..747f73d0f --- /dev/null +++ b/hardware/arduino/sam/system/libsam/source/trng.c @@ -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 + +/** + * \} + */ diff --git a/hardware/arduino/sam/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a b/hardware/arduino/sam/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a index 390d2532e79be39d2f0dc6e8cb78087ff48162e4..62572a465df8998f0b7318bbf06ee16b2c7e1046 100644 GIT binary patch literal 108544 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 diff --git a/hardware/arduino/sam/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a.txt b/hardware/arduino/sam/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a.txt index 600f00497..d2adba75d 100644 --- a/hardware/arduino/sam/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a.txt +++ b/hardware/arduino/sam/variants/arduino_due_x/libsam_sam3x8e_gcc_rel.a.txt @@ -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