mirror of
https://github.com/FreeRTOS/FreeRTOS-Kernel.git
synced 2025-04-23 23:11:58 -04:00
Add SAMA5D2 Xplained IAR demo.
This commit is contained in:
parent
5252301cb8
commit
f0f2378961
|
@ -0,0 +1,94 @@
|
|||
# Atmel SAMA5D2x Software Package
|
||||
|
||||
|
||||
## Version 1.2 - 2015-12
|
||||
|
||||
### New drivers/examples
|
||||
|
||||
- USB Device examples and stack: CDC Serial, HID Keyboard, HID Mouse, Audio,
|
||||
Mass Storage and some composite examples.
|
||||
- NAND flash driver and examples: supports MLC/SLC, up to 32-bit ECC.
|
||||
- SDMMC/eMMC driver and example
|
||||
- Low Power examples: power_consumption_pll, pmc_clock_switching,
|
||||
low_power_mode
|
||||
- New storagemedia library to abstract storage devices (only supports RAM disk
|
||||
for now, but will support SDMMC/eMMC and NAND flash in later releases)
|
||||
|
||||
### Enhancements
|
||||
|
||||
- Several new functions in PMC driver, notably 'pmc_set_custom_pck_mck' that
|
||||
allow changing easily the main clock settings.
|
||||
- IAR project generator now uses defines and include directories from
|
||||
CFLAGS_DEFS and CFLAGS_INC mkefile variables. It also generates projects with
|
||||
CMSIS-DAP debugger selected and proper optimization level.
|
||||
|
||||
### Fixes
|
||||
|
||||
- Fix CP15 driver to invalidate caches before enable. This fixes some lock-ups
|
||||
when caches were previously enabled and still contain stale data.
|
||||
|
||||
|
||||
|
||||
## Version 1.1 - 2015-10
|
||||
|
||||
### New drivers
|
||||
|
||||
- Class-D audio driver + example
|
||||
|
||||
### Enhancements
|
||||
|
||||
- Support for ISO7816 and LIN modes to UART driver + example
|
||||
- Several functions added to PMC driver, mostly UPLL and AudioPLL support
|
||||
- ISC/sensors: support for new capture modes / resolutions
|
||||
|
||||
### Fixes
|
||||
|
||||
- Several fixes to ADC driver and example
|
||||
- Fixed MMU setup (some memory regions where not defined)
|
||||
|
||||
|
||||
|
||||
## Version 1.0 - 2015-09
|
||||
|
||||
### New drivers
|
||||
|
||||
- MCAN driver + example
|
||||
|
||||
### Changes
|
||||
|
||||
- sama5d2-xplained target adapted for final revA board
|
||||
|
||||
### Enhancements
|
||||
|
||||
- Clock initialization changed to be more reliable
|
||||
- PMC driver now supports setting generated clocks on sama5d2
|
||||
- Add support for new memory models to at25 driver (MX25L12835F, MX25L4005,
|
||||
N25Q032, S25FL127S)
|
||||
|
||||
|
||||
|
||||
## Version 0.3 -- 2015-08
|
||||
|
||||
### New drivers
|
||||
|
||||
- ACC driver
|
||||
- ADC driver + example
|
||||
- AES / TDES / SHA drivers + examples
|
||||
- L2CC driver
|
||||
- GMAC driver + examples (using ad-hoc / LWIP / UIP stacks)
|
||||
- QT1070 driver
|
||||
- SHDWC driver
|
||||
|
||||
### Enhancements
|
||||
|
||||
- FPU is now enabled in GCC startup (was already enabled for IAR)
|
||||
- ISC example now demonstrates Auto White Balance / Auto Exposure
|
||||
- SPID/TWID/USARTD drivers now switch the Flexcom mode when appropriate
|
||||
- MMU is now has a non-cacheable DDR region (used by LCD and GMAC examples)
|
||||
|
||||
### Fixes
|
||||
|
||||
- RAM timings / configuration adjusted for sama5d2-xplained target
|
||||
- Component headers in target/sama5d2/components updated to reflect latest
|
||||
datasheet updates
|
||||
- PIO and TRNG callbacks now have a configurable user-defined argument
|
|
@ -0,0 +1,166 @@
|
|||
Copyright (c) 2015, Atmel Corporation All rights reserved.
|
||||
----------------------------------------------------------
|
||||
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
|
||||
# Atmel SAMA5D2x Software Package
|
||||
|
||||
## Overview
|
||||
|
||||
This softpack comes as an early delivery and all presented APIs are subject to change.
|
||||
|
||||
Each software module is provided with full source code, example of usage, and ready-to-use projects.
|
||||
|
||||
### Supported Platforms
|
||||
|
||||
Windows and Linux with the gnu GCC ARM Embedded toolchain. It is downloadable at this address: https://launchpad.net/gcc-arm-embedded (Mac OS X should also work but as not been tested yet).
|
||||
Dependencies:
|
||||
- GNU make (from MinGW, Cygwin or GnuWin32 for Windows architectures)
|
||||
- bash (from MinGW, Cygwin for Windows architectures)
|
||||
|
||||
Windows with IAR Embedded Workbench.
|
||||
Dependencies:
|
||||
- IAR Embedded Workbench (Tested on version 7.40)
|
||||
- bash (from MinGW, Cygwin or GnuWin32) for IAR project generation
|
||||
- GNU make (from MinGW, Cygwin or GnuWin32) for IAR project generation
|
||||
- mktemp (from MinGW, Cygwin or GnuWin32) for IAR project generation
|
||||
|
||||
Notice: This softpack comes as an early delivery and all presented APIs are subject to change.
|
||||
|
||||
## Contents
|
||||
|
||||
### Directory Architecture
|
||||
|
||||
- target/sama5d2
|
||||
All chip and board specific source files
|
||||
|
||||
- target/sama5d2/toolchain/
|
||||
Linker and debugger scripts
|
||||
|
||||
- scripts/
|
||||
generators and build script templates (Makefiles)
|
||||
|
||||
- drivers/
|
||||
Driver source files
|
||||
|
||||
- examples/
|
||||
All examples
|
||||
|
||||
### Examples
|
||||
|
||||
This release contains the following examples:
|
||||
|
||||
adc: Example using ADC
|
||||
|
||||
can: Example using CAN
|
||||
|
||||
crypto_aes: AES hardware computation (with and without DMA)
|
||||
|
||||
crypto_sha: SHA hardware computation (with and without DMA)
|
||||
|
||||
crypto_tdes: Triple-DES hardware computation (with and without DMA)
|
||||
|
||||
fifo: Test Flexcom USART FIFO
|
||||
|
||||
gettting-started: LED blink (uses PIT and PIO)
|
||||
|
||||
gmac: GMAC example using a simple IP stack
|
||||
|
||||
gmac_lwip: GMAC example using LWIP stack
|
||||
|
||||
gmac_uip_helloworld: GMAC example using UIP stack (UIP helloworld example)
|
||||
|
||||
gmac_uip_telnetd: GMAC example using UIP stack (UIP telnetd example)
|
||||
|
||||
gmac_uip_webserver: GMAC example using UIP stack (UIP webserver example)
|
||||
|
||||
isc: Example using ISC controller (OV7740 sensor)
|
||||
|
||||
lcd: Example using LCD controller
|
||||
|
||||
qspi_flash: Read/Write/Delete commands to a QSPI serial flash
|
||||
|
||||
rtc: RTC Example
|
||||
|
||||
spi_serialflash: Read/Write/Delete commands to an SPI serial flash
|
||||
|
||||
trng: Example using hardware RNG (interrupt mode)
|
||||
|
||||
twi_eeprom: Read/Write/Delete commands to an Two-Wire EEPROM
|
||||
|
||||
wdt: Example using watchdog timer
|
||||
|
||||
xdma: Memory-to-memory DMA transfert example
|
||||
|
||||
xdma_usart: Bidirectionnal Usart-memory DMA transfert example
|
||||
|
||||
## Usage (GCC ARM Embedded)
|
||||
|
||||
### Environment Variable
|
||||
|
||||
TARGET: Name of the wanted target (sama5d2-xplained for samad52 XPLAINED ULTRA boards). This variable is mandatory to launch any build.
|
||||
|
||||
DEBUG: Build with debug flags (default).
|
||||
|
||||
TRACE_LEVEL: The wanted log level, 5 correspond to full, 0 to none (default to 5)
|
||||
|
||||
RELEASE: Build with the release flags
|
||||
|
||||
only TARGET must be provided or set at each make invocation.
|
||||
|
||||
### Build
|
||||
|
||||
Run:
|
||||
|
||||
make
|
||||
#or
|
||||
make TARGET=wanted_target # if TARGET is not set
|
||||
|
||||
### Run and Debug (with GDB)
|
||||
|
||||
To run examples with gdb, first, JLinkGDBServer must be started. It can be downloaded for each platform at http://www.segger.com
|
||||
|
||||
A make target is provided to launch the test with the correct gdb command arguments, run:
|
||||
|
||||
make debug
|
||||
#or
|
||||
make TARGET=wanted_target debug # if TARGET is not set
|
||||
|
||||
## Usage (IAR)
|
||||
|
||||
The Win version of this softpack release comes with pregenerated IAR projects compatible with IAR Systems Embedded Workbench for ARM version 7.40.
|
||||
|
||||
The C-SPY device description files and device selections files are not included and must be installed manually.
|
||||
|
||||
### IAR Project generation
|
||||
|
||||
An IAR project can be generated with GNU make, run in the example directory:
|
||||
|
||||
make iar
|
||||
#or
|
||||
make TARGET=wanted_target iar # if TARGET is not set
|
||||
|
||||
All needed IAR project files will be put in the example directory, including a default workspace one.
|
||||
|
||||
Notice:
|
||||
GNU make may fail on Windows platforms if the Makefile contains UNIX line endings.
|
||||
You can use unix2dos on all Makefile files in scripts/ directory to fix this issue.
|
|
@ -0,0 +1,803 @@
|
|||
-- *****************************************************************************
|
||||
|
||||
-- BSDL file for design top
|
||||
|
||||
-- Created by Synopsys Version I-2013.12-SP3 (Apr 18, 2014)
|
||||
|
||||
-- Designer:
|
||||
-- Company:
|
||||
|
||||
-- Date: Thu Feb 5 22:28:17 2015
|
||||
|
||||
-- *****************************************************************************
|
||||
|
||||
|
||||
entity top is
|
||||
|
||||
-- This section identifies the default device package selected.
|
||||
|
||||
generic (PHYSICAL_PIN_MAP: string:= "BGA196");
|
||||
|
||||
-- This section declares all the ports in the design.
|
||||
|
||||
port (
|
||||
PD14 : in bit;
|
||||
PD15 : in bit;
|
||||
PD17 : in bit;
|
||||
PD18 : in bit;
|
||||
-- PA0 : linkage bit; -- NC Port
|
||||
-- PA1 : linkage bit; -- NC Port
|
||||
-- PA10 : linkage bit; -- NC Port
|
||||
-- PA11 : linkage bit; -- NC Port
|
||||
-- PA12 : linkage bit; -- NC Port
|
||||
-- PA13 : linkage bit; -- NC Port
|
||||
-- PA14 : linkage bit; -- NC Port
|
||||
-- PA15 : linkage bit; -- NC Port
|
||||
-- PA16 : linkage bit; -- NC Port
|
||||
-- PA17 : linkage bit; -- NC Port
|
||||
PA18 : inout bit;
|
||||
PA19 : inout bit;
|
||||
-- PA2 : linkage bit; -- NC Port
|
||||
PA20 : inout bit;
|
||||
PA21 : inout bit;
|
||||
PA22 : inout bit;
|
||||
PA23 : inout bit;
|
||||
PA24 : inout bit;
|
||||
PA25 : inout bit;
|
||||
PA26 : inout bit;
|
||||
PA27 : inout bit;
|
||||
PA28 : inout bit;
|
||||
PA29 : inout bit;
|
||||
-- PA3 : linkage bit; -- NC Port
|
||||
PA30 : inout bit;
|
||||
PA31 : inout bit;
|
||||
-- PA4 : linkage bit; -- NC Port
|
||||
-- PA5 : linkage bit; -- NC Port
|
||||
-- PA6 : linkage bit; -- NC Port
|
||||
-- PA7 : linkage bit; -- NC Port
|
||||
-- PA8 : linkage bit; -- NC Port
|
||||
-- PA9 : linkage bit; -- NC Port
|
||||
PB0 : inout bit;
|
||||
PB1 : inout bit;
|
||||
PB10 : inout bit;
|
||||
PB11 : inout bit;
|
||||
PB12 : inout bit;
|
||||
PB13 : inout bit;
|
||||
PB14 : inout bit;
|
||||
PB15 : inout bit;
|
||||
PB16 : inout bit;
|
||||
PB17 : inout bit;
|
||||
PB18 : inout bit;
|
||||
PB19 : inout bit;
|
||||
PB2 : inout bit;
|
||||
PB20 : inout bit;
|
||||
PB21 : inout bit;
|
||||
PB22 : inout bit;
|
||||
PB23 : inout bit;
|
||||
PB24 : inout bit;
|
||||
PB25 : inout bit;
|
||||
PB26 : inout bit;
|
||||
PB27 : inout bit;
|
||||
PB28 : inout bit;
|
||||
PB29 : inout bit;
|
||||
PB3 : inout bit;
|
||||
PB30 : inout bit;
|
||||
PB31 : inout bit;
|
||||
PB4 : inout bit;
|
||||
PB5 : inout bit;
|
||||
PB6 : inout bit;
|
||||
PB7 : inout bit;
|
||||
PB8 : inout bit;
|
||||
PB9 : inout bit;
|
||||
PC0 : inout bit;
|
||||
PC1 : inout bit;
|
||||
-- PC10 : linkage bit; -- NC Port
|
||||
-- PC11 : linkage bit; -- NC Port
|
||||
-- PC12 : linkage bit; -- NC Port
|
||||
-- PC13 : linkage bit; -- NC Port
|
||||
-- PC14 : linkage bit; -- NC Port
|
||||
-- PC15 : linkage bit; -- NC Port
|
||||
-- PC16 : linkage bit; -- NC Port
|
||||
-- PC17 : linkage bit; -- NC Port
|
||||
-- PC18 : linkage bit; -- NC Port
|
||||
-- PC19 : linkage bit; -- NC Port
|
||||
PC2 : inout bit;
|
||||
-- PC20 : linkage bit; -- NC Port
|
||||
-- PC21 : linkage bit; -- NC Port
|
||||
-- PC22 : linkage bit; -- NC Port
|
||||
-- PC23 : linkage bit; -- NC Port
|
||||
-- PC24 : linkage bit; -- NC Port
|
||||
-- PC25 : linkage bit; -- NC Port
|
||||
-- PC26 : linkage bit; -- NC Port
|
||||
-- PC27 : linkage bit; -- NC Port
|
||||
-- PC28 : linkage bit; -- NC Port
|
||||
-- PC29 : linkage bit; -- NC Port
|
||||
PC3 : inout bit;
|
||||
-- PC30 : linkage bit; -- NC Port
|
||||
-- PC31 : linkage bit; -- NC Port
|
||||
PC4 : inout bit;
|
||||
PC5 : inout bit;
|
||||
PC6 : inout bit;
|
||||
PC7 : inout bit;
|
||||
PC8 : inout bit;
|
||||
-- PC9 : linkage bit; -- NC Port
|
||||
-- PD0 : linkage bit; -- NC Port
|
||||
-- PD1 : linkage bit; -- NC Port
|
||||
PD10 : inout bit;
|
||||
PD11 : inout bit;
|
||||
PD12 : inout bit;
|
||||
PD13 : inout bit;
|
||||
PD19 : inout bit;
|
||||
-- PD2 : linkage bit; -- NC Port
|
||||
PD20 : inout bit;
|
||||
PD21 : inout bit;
|
||||
PD22 : inout bit;
|
||||
PD23 : inout bit;
|
||||
-- PD24 : linkage bit; -- NC Port
|
||||
-- PD25 : linkage bit; -- NC Port
|
||||
-- PD26 : linkage bit; -- NC Port
|
||||
-- PD27 : linkage bit; -- NC Port
|
||||
-- PD28 : linkage bit; -- NC Port
|
||||
-- PD29 : linkage bit; -- NC Port
|
||||
-- PD3 : linkage bit; -- NC Port
|
||||
-- PD30 : linkage bit; -- NC Port
|
||||
-- PD31 : linkage bit; -- NC Port
|
||||
-- PD4 : linkage bit; -- NC Port
|
||||
-- PD5 : linkage bit; -- NC Port
|
||||
-- PD6 : linkage bit; -- NC Port
|
||||
PD7 : inout bit;
|
||||
PD8 : inout bit;
|
||||
PD9 : inout bit;
|
||||
DDR_D : inout bit_vector (0 to 15);
|
||||
DDR_DQS : inout bit_vector (0 to 1);
|
||||
DDR_DQSN : inout bit_vector (0 to 1);
|
||||
DDR_CAS : out bit;
|
||||
DDR_CKE : out bit;
|
||||
DDR_CLK : out bit;
|
||||
DDR_CLKN : out bit;
|
||||
DDR_CS : out bit;
|
||||
DDR_RAS : out bit;
|
||||
DDR_RESETN : out bit;
|
||||
DDR_WE : out bit;
|
||||
PD16 : out bit;
|
||||
DDR_A : out bit_vector (0 to 13);
|
||||
DDR_BA : out bit_vector (0 to 2);
|
||||
DDR_DQM : out bit_vector (0 to 1);
|
||||
-- ADVREFN : linkage bit;
|
||||
ADVREFP : linkage bit;
|
||||
CLK_AUDIO : linkage bit;
|
||||
COMPN : linkage bit;
|
||||
COMPP : linkage bit;
|
||||
DDR_CAL : linkage bit;
|
||||
DDR_VREF : linkage bit; -- DDR_VREFB0 : linkage bit;
|
||||
-- DDR_VREFB1 : linkage bit;
|
||||
-- DDR_VREFB2 : linkage bit;
|
||||
-- DDR_VREFB3 : linkage bit;
|
||||
-- DDR_VREFCM : linkage bit;
|
||||
HHSDMA : linkage bit;
|
||||
HHSDMB : linkage bit;
|
||||
-- HHSDMSTRC : linkage bit; -- NC Port
|
||||
HHSDPA : linkage bit;
|
||||
HHSDPB : linkage bit;
|
||||
-- HHSDPDATC : linkage bit; -- NC Port
|
||||
JTAGSEL : in bit;
|
||||
NRST : linkage bit;
|
||||
-- RXD : linkage bit; -- NC Port
|
||||
-- SDCAL : linkage bit; -- NC Port
|
||||
SHDN : linkage bit;
|
||||
TST : in bit;
|
||||
VBG : linkage bit;
|
||||
WKUP : linkage bit;
|
||||
XIN : linkage bit;
|
||||
XIN32 : linkage bit;
|
||||
XOUT : linkage bit;
|
||||
XOUT32 : linkage bit;
|
||||
-- tst_drst_ana : linkage bit; -- NC Port
|
||||
-- tst_drst_ddr : linkage bit; -- NC Port
|
||||
-- tst_drst_iop0 : linkage bit; -- NC Port
|
||||
-- tst_drst_iop1 : linkage bit; -- NC Port
|
||||
-- tst_drst_iop2 : linkage bit; -- NC Port
|
||||
-- tst_drst_isi : linkage bit; -- NC Port
|
||||
-- tst_drst_osc : linkage bit; -- NC Port
|
||||
-- tst_drst_sdhc : linkage bit; -- NC Port
|
||||
-- tst_lft_plla : linkage bit; -- NC Port
|
||||
-- tst_lft_utmi : linkage bit; -- NC Port
|
||||
-- tst_por_1v2 : linkage bit; -- NC Port
|
||||
-- tst_por_1v8 : linkage bit; -- NC Port
|
||||
-- tst_por_bu : linkage bit; -- NC Port
|
||||
-- tst_psw_bu : linkage bit; -- NC Port
|
||||
-- tst_psw_fuse : linkage bit; -- NC Port
|
||||
PIOBU : linkage bit_vector (0 to 5)
|
||||
);
|
||||
|
||||
use STD_1149_1_1994.all;
|
||||
|
||||
attribute COMPONENT_CONFORMANCE of top: entity is "STD_1149_1_1993";
|
||||
|
||||
attribute PIN_MAP of top: entity is PHYSICAL_PIN_MAP;
|
||||
|
||||
-- This section specifies the pin map for each port. This information is
|
||||
-- extracted from the port-to-pin map file that was read in using the
|
||||
-- "read_pin_map" command.
|
||||
|
||||
constant BGA196: PIN_MAP_STRING :=
|
||||
"PD14 : G6," &
|
||||
"PD15 : H5," &
|
||||
"PD17 : G2," &
|
||||
"PD18 : G3," &
|
||||
"PA18 : L9," &
|
||||
"PA19 : N9," &
|
||||
"PA20 : M9," &
|
||||
"PA21 : M10," &
|
||||
"PA22 : P9," &
|
||||
"PA23 : P10," &
|
||||
"PA24 : N10," &
|
||||
"PA25 : L10," &
|
||||
"PA26 : P11," &
|
||||
"PA27 : P12," &
|
||||
"PA28 : M11," &
|
||||
"PA29 : N11," &
|
||||
"PA30 : N12," &
|
||||
"PA31 : M12," &
|
||||
"PB0 : A6," &
|
||||
"PB1 : A5," &
|
||||
"PB10 : A1," &
|
||||
"PB11 : B1," &
|
||||
"PB12 : B2," &
|
||||
"PB13 : C1," &
|
||||
"PB14 : D5," &
|
||||
"PB15 : E5," &
|
||||
"PB16 : C5," &
|
||||
"PB17 : C2," &
|
||||
"PB18 : D4," &
|
||||
"PB19 : C4," &
|
||||
"PB2 : B6," &
|
||||
"PB20 : C3," &
|
||||
"PB21 : D1," &
|
||||
"PB22 : D2," &
|
||||
"PB23 : E1," &
|
||||
"PB24 : D3," &
|
||||
"PB25 : E3," &
|
||||
"PB26 : E2," &
|
||||
"PB27 : E6," &
|
||||
"PB28 : F1," &
|
||||
"PB29 : F6," &
|
||||
"PB3 : B5," &
|
||||
"PB30 : F2," &
|
||||
"PB31 : F7," &
|
||||
"PB4 : A4," &
|
||||
"PB5 : D6," &
|
||||
"PB6 : A3," &
|
||||
"PB7 : B4," &
|
||||
"PB8 : A2," &
|
||||
"PB9 : B3," &
|
||||
"PC0 : M13," &
|
||||
"PC1 : P13," &
|
||||
"PC2 : N13," &
|
||||
"PC3 : K10," &
|
||||
"PC4 : P14," &
|
||||
"PC5 : J8," &
|
||||
"PC6 : N14," &
|
||||
"PC7 : M14," &
|
||||
"PC8 : J9," &
|
||||
"PD10 : G4," &
|
||||
"PD11 : H1," &
|
||||
"PD12 : H6," &
|
||||
"PD13 : H3," &
|
||||
"PD19 : H4," &
|
||||
"PD20 : J1," &
|
||||
"PD21 : K1," &
|
||||
"PD22 : J3," &
|
||||
"PD23 : K2," &
|
||||
"PD7 : F5," &
|
||||
"PD8 : F3," &
|
||||
"PD9 : G5," &
|
||||
"DDR_D : (B7, A7, C8, B9, A9, C9, A10, B10, H13, H14, J13, J14, L13, L14, J12, K12)," &
|
||||
"DDR_DQS : (B8, K14)," &
|
||||
"DDR_DQSN : (A8, K13)," &
|
||||
"DDR_CAS : C13," &
|
||||
"DDR_CKE : E14," &
|
||||
"DDR_CLK : A13," &
|
||||
"DDR_CLKN : B13," &
|
||||
"DDR_CS : F11," &
|
||||
"DDR_DQM : (D8, G14)," &
|
||||
"DDR_RAS : C14," &
|
||||
"DDR_RESETN : D13," &
|
||||
"DDR_WE : A14," &
|
||||
"PD16 : G1," &
|
||||
"DDR_A : (E11, C11, B12, A12, D11, D14, B14, D9, C10, D10, " &
|
||||
"F9, A11, B11, E13)," &
|
||||
"DDR_BA : (F13, G13, F14)," &
|
||||
"ADVREFP : L2," &
|
||||
"CLK_AUDIO : J7," &
|
||||
"COMPN : P2," &
|
||||
"COMPP : N2," &
|
||||
"DDR_CAL : F10," &
|
||||
"HHSDMA : P7," &
|
||||
"HHSDMB : P8," &
|
||||
"HHSDPA : N7," &
|
||||
"HHSDPB : N8," &
|
||||
"JTAGSEL : L4," &
|
||||
"NRST : N3," &
|
||||
"SHDN : N1," &
|
||||
"TST : M2," &
|
||||
"VBG : L7," &
|
||||
"WKUP : P1," &
|
||||
"XIN : P5," &
|
||||
"XIN32 : M1," &
|
||||
"XOUT : P6," &
|
||||
"XOUT32 : L1," &
|
||||
"PIOBU : (K5, L3, M3, N4, L5, M6)";
|
||||
|
||||
-- This section specifies the differential IO port groupings.
|
||||
|
||||
attribute PORT_GROUPING of top: entity is
|
||||
"Differential_Voltage ( " &
|
||||
"(DDR_CLK,DDR_CLKN))";
|
||||
|
||||
-- This section specifies the TAP ports. For the TAP TCK port, the parameters in
|
||||
-- the brackets are:
|
||||
-- First Field : Maximum TCK frequency.
|
||||
-- Second Field: Allowable states TCK may be stopped in.
|
||||
|
||||
attribute TAP_SCAN_CLOCK of PD14: signal is (10.0e6, BOTH);
|
||||
attribute TAP_SCAN_IN of PD15: signal is true;
|
||||
attribute TAP_SCAN_MODE of PD17: signal is true;
|
||||
attribute TAP_SCAN_OUT of PD16: signal is true;
|
||||
attribute TAP_SCAN_RESET of PD18: signal is true;
|
||||
|
||||
-- Specifies the compliance enable patterns for the design. It lists a set of
|
||||
-- design ports and the values that they should be set to, in order to enable
|
||||
-- compliance to IEEE Std 1149.1
|
||||
|
||||
attribute COMPLIANCE_PATTERNS of top: entity is
|
||||
"(JTAGSEL, TST) (10)";
|
||||
|
||||
-- Specifies the number of bits in the instruction register.
|
||||
|
||||
attribute INSTRUCTION_LENGTH of top: entity is 4;
|
||||
|
||||
-- Specifies the boundary-scan instructions implemented in the design and their
|
||||
-- opcodes.
|
||||
|
||||
attribute INSTRUCTION_OPCODE of top: entity is
|
||||
"BYPASS (1111, 0001, 0101, 0110, 1100, 0111, 1101, 1000, 1001, 1011, " &
|
||||
"1110)," &
|
||||
"EXTEST (0000)," &
|
||||
"SAMPLE (0100)," &
|
||||
"INTEST (0010)," &
|
||||
"IDCODE (0011)," &
|
||||
"RUNBIST (1010)";
|
||||
|
||||
-- Specifies the bit pattern that is loaded into the instruction register when
|
||||
-- the TAP controller passes through the Capture-IR state. The standard mandates
|
||||
-- that the two LSBs must be "01". The remaining bits are design specific.
|
||||
|
||||
attribute INSTRUCTION_CAPTURE of top: entity is "0001";
|
||||
|
||||
-- Specifies the bit pattern that is loaded into the DEVICE_ID register during
|
||||
-- the IDCODE instruction when the TAP controller passes through the Capture-DR
|
||||
-- state.
|
||||
|
||||
attribute IDCODE_REGISTER of top: entity is
|
||||
"0000" &
|
||||
-- 4-bit version number
|
||||
"0101101100111111" &
|
||||
-- 16-bit part number
|
||||
"00000011111" &
|
||||
-- 11-bit identity of the manufacturer
|
||||
"1";
|
||||
-- Required by IEEE Std 1149.1
|
||||
|
||||
-- This section specifies the test data register placed between TDI and TDO for
|
||||
-- each implemented instruction.
|
||||
|
||||
attribute REGISTER_ACCESS of top: entity is
|
||||
"BYPASS (BYPASS)," &
|
||||
"BOUNDARY (EXTEST, SAMPLE, INTEST)," &
|
||||
"DEVICE_ID (IDCODE)," &
|
||||
"UTDR1[41] (RUNBIST)";
|
||||
|
||||
-- Specifies the length of the boundary scan register.
|
||||
|
||||
attribute BOUNDARY_LENGTH of top: entity is 374;
|
||||
|
||||
-- The following list specifies the characteristics of each cell in the boundary
|
||||
-- scan register from TDI to TDO. The following is a description of the label
|
||||
-- fields:
|
||||
-- num : Is the cell number.
|
||||
-- cell : Is the cell type as defined by the standard.
|
||||
-- port : Is the design port name. Control cells do not have a port
|
||||
-- name.
|
||||
-- function: Is the function of the cell as defined by the standard. Is one
|
||||
-- of input, output2, output3, bidir, control or controlr.
|
||||
-- safe : Specifies the value that the BSR cell should be loaded with
|
||||
-- for safe operation when the software might otherwise choose a
|
||||
-- random value.
|
||||
-- ccell : The control cell number. Specifies the control cell that
|
||||
-- drives the output enable for this port.
|
||||
-- disval : Specifies the value that is loaded into the control cell to
|
||||
-- disable the output enable for the corresponding port.
|
||||
-- rslt : Resulting state. Shows the state of the driver when it is
|
||||
-- disabled.
|
||||
|
||||
attribute BOUNDARY_REGISTER of top: entity is
|
||||
--
|
||||
-- num cell port function safe [ccell disval rslt]
|
||||
--
|
||||
"373 (BC_1, *, control, 1), " &
|
||||
"372 (BC_7, PD13, bidir, X, 373, 1, Z), " &
|
||||
"371 (BC_1, *, control, 1), " &
|
||||
"370 (BC_7, PD12, bidir, X, 371, 1, Z), " &
|
||||
"369 (BC_1, *, control, 1), " &
|
||||
"368 (BC_7, PD11, bidir, X, 369, 1, Z), " &
|
||||
"367 (BC_1, *, control, 1), " &
|
||||
"366 (BC_7, PD19, bidir, X, 367, 1, Z), " &
|
||||
"365 (BC_1, *, control, 1), " &
|
||||
"364 (BC_7, PD20, bidir, X, 365, 1, Z), " &
|
||||
"363 (BC_0, *, internal, X), " &
|
||||
"362 (BC_0, *, internal, X), " &
|
||||
"361 (BC_1, *, control, 1), " &
|
||||
"360 (BC_7, PD21, bidir, X, 361, 1, Z), " &
|
||||
"359 (BC_0, *, internal, X), " &
|
||||
"358 (BC_0, *, internal, X), " &
|
||||
"357 (BC_0, *, internal, X), " &
|
||||
"356 (BC_0, *, internal, X), " &
|
||||
"355 (BC_1, *, control, 1), " &
|
||||
"354 (BC_7, PD22, bidir, X, 355, 1, Z), " &
|
||||
"353 (BC_0, *, internal, X), " &
|
||||
"352 (BC_0, *, internal, X), " &
|
||||
"351 (BC_1, *, control, 1), " &
|
||||
"350 (BC_7, PD23, bidir, X, 351, 1, Z), " &
|
||||
"349 (BC_0, *, internal, X), " &
|
||||
"348 (BC_0, *, internal, X), " &
|
||||
"347 (BC_0, *, internal, X), " &
|
||||
"346 (BC_0, *, internal, X), " &
|
||||
"345 (BC_0, *, internal, X), " &
|
||||
"344 (BC_0, *, internal, X), " &
|
||||
"343 (BC_0, *, internal, X), " &
|
||||
"342 (BC_0, *, internal, X), " &
|
||||
"341 (BC_0, *, internal, X), " &
|
||||
"340 (BC_0, *, internal, X), " &
|
||||
"339 (BC_0, *, internal, X), " &
|
||||
"338 (BC_0, *, internal, X), " &
|
||||
"337 (BC_0, *, internal, X), " &
|
||||
"336 (BC_0, *, internal, X), " &
|
||||
"335 (BC_0, *, internal, X), " &
|
||||
"334 (BC_0, *, internal, X), " &
|
||||
"333 (BC_0, *, internal, X), " &
|
||||
"332 (BC_0, *, internal, X), " &
|
||||
"331 (BC_0, *, internal, X), " &
|
||||
"330 (BC_0, *, internal, X), " &
|
||||
"329 (BC_0, *, internal, X), " &
|
||||
"328 (BC_0, *, internal, X), " &
|
||||
"327 (BC_0, *, internal, X), " &
|
||||
"326 (BC_0, *, internal, X), " &
|
||||
"325 (BC_0, *, internal, X), " &
|
||||
"324 (BC_0, *, internal, X), " &
|
||||
"323 (BC_0, *, internal, X), " &
|
||||
"322 (BC_0, *, internal, X), " &
|
||||
"321 (BC_0, *, internal, X), " &
|
||||
"320 (BC_0, *, internal, X), " &
|
||||
"319 (BC_1, *, control, 1), " &
|
||||
"318 (BC_7, PA18, bidir, X, 319, 1, Z), " &
|
||||
"317 (BC_1, *, control, 1), " &
|
||||
"316 (BC_7, PA20, bidir, X, 317, 1, Z), " &
|
||||
"315 (BC_1, *, control, 1), " &
|
||||
"314 (BC_7, PA19, bidir, X, 315, 1, Z), " &
|
||||
"313 (BC_1, *, control, 1), " &
|
||||
"312 (BC_7, PA21, bidir, X, 313, 1, Z), " &
|
||||
"311 (BC_1, *, control, 1), " &
|
||||
"310 (BC_7, PA22, bidir, X, 311, 1, Z), " &
|
||||
"309 (BC_1, *, control, 1), " &
|
||||
"308 (BC_7, PA23, bidir, X, 309, 1, Z), " &
|
||||
"307 (BC_1, *, control, 1), " &
|
||||
"306 (BC_7, PA24, bidir, X, 307, 1, Z), " &
|
||||
"305 (BC_1, *, control, 1), " &
|
||||
"304 (BC_7, PA25, bidir, X, 305, 1, Z), " &
|
||||
"303 (BC_1, *, control, 1), " &
|
||||
"302 (BC_7, PA26, bidir, X, 303, 1, Z), " &
|
||||
"301 (BC_1, *, control, 1), " &
|
||||
"300 (BC_7, PA27, bidir, X, 301, 1, Z), " &
|
||||
"299 (BC_1, *, control, 1), " &
|
||||
"298 (BC_7, PA28, bidir, X, 299, 1, Z), " &
|
||||
"297 (BC_1, *, control, 1), " &
|
||||
"296 (BC_7, PA30, bidir, X, 297, 1, Z), " &
|
||||
"295 (BC_1, *, control, 1), " &
|
||||
"294 (BC_7, PA29, bidir, X, 295, 1, Z), " &
|
||||
"293 (BC_1, *, control, 1), " &
|
||||
"292 (BC_7, PA31, bidir, X, 293, 1, Z), " &
|
||||
"291 (BC_1, *, control, 1), " &
|
||||
"290 (BC_7, PC0, bidir, X, 291, 1, Z), " &
|
||||
"289 (BC_0, *, internal, X), " &
|
||||
"288 (BC_0, *, internal, X), " &
|
||||
"287 (BC_1, *, control, 1), " &
|
||||
"286 (BC_7, PC1, bidir, X, 287, 1, Z), " &
|
||||
"285 (BC_0, *, internal, X), " &
|
||||
"284 (BC_0, *, internal, X), " &
|
||||
"283 (BC_0, *, internal, X), " &
|
||||
"282 (BC_0, *, internal, X), " &
|
||||
"281 (BC_1, *, control, 1), " &
|
||||
"280 (BC_7, PC2, bidir, X, 281, 1, Z), " &
|
||||
"279 (BC_0, *, internal, X), " &
|
||||
"278 (BC_0, *, internal, X), " &
|
||||
"277 (BC_0, *, internal, X), " &
|
||||
"276 (BC_0, *, internal, X), " &
|
||||
"275 (BC_1, *, control, 1), " &
|
||||
"274 (BC_7, PC3, bidir, X, 275, 1, Z), " &
|
||||
"273 (BC_1, *, control, 1), " &
|
||||
"272 (BC_7, PC4, bidir, X, 273, 1, Z), " &
|
||||
"271 (BC_0, *, internal, X), " &
|
||||
"270 (BC_0, *, internal, X), " &
|
||||
"269 (BC_0, *, internal, X), " &
|
||||
"268 (BC_0, *, internal, X), " &
|
||||
"267 (BC_1, *, control, 1), " &
|
||||
"266 (BC_7, PC5, bidir, X, 267, 1, Z), " &
|
||||
"265 (BC_1, *, control, 1), " &
|
||||
"264 (BC_7, PC7, bidir, X, 265, 1, Z), " &
|
||||
"263 (BC_1, *, control, 1), " &
|
||||
"262 (BC_7, PC6, bidir, X, 263, 1, Z), " &
|
||||
"261 (BC_1, *, control, 1), " &
|
||||
"260 (BC_7, PC8, bidir, X, 261, 1, Z), " &
|
||||
"259 (BC_0, *, internal, X), " &
|
||||
"258 (BC_0, *, internal, X), " &
|
||||
"257 (BC_0, *, internal, X), " &
|
||||
"256 (BC_0, *, internal, X), " &
|
||||
"255 (BC_0, *, internal, X), " &
|
||||
"254 (BC_0, *, internal, X), " &
|
||||
"253 (BC_0, *, internal, X), " &
|
||||
"252 (BC_0, *, internal, X), " &
|
||||
"251 (BC_0, *, internal, X), " &
|
||||
"250 (BC_0, *, internal, X), " &
|
||||
"249 (BC_0, *, internal, X), " &
|
||||
"248 (BC_0, *, internal, X), " &
|
||||
"247 (BC_0, *, internal, X), " &
|
||||
"246 (BC_0, *, internal, X), " &
|
||||
"245 (BC_0, *, internal, X), " &
|
||||
"244 (BC_0, *, internal, X), " &
|
||||
"243 (BC_0, *, internal, X), " &
|
||||
"242 (BC_0, *, internal, X), " &
|
||||
"241 (BC_0, *, internal, X), " &
|
||||
"240 (BC_0, *, internal, X), " &
|
||||
"239 (BC_1, *, control, 1), " &
|
||||
"238 (BC_7, DDR_D(15), bidir, X, 239, 1, Z), " &
|
||||
"237 (BC_1, *, control, 1), " &
|
||||
"236 (BC_7, DDR_D(14), bidir, X, 237, 1, Z), " &
|
||||
"235 (BC_1, *, control, 1), " &
|
||||
"234 (BC_7, DDR_D(13), bidir, X, 235, 1, Z), " &
|
||||
"233 (BC_1, *, control, 1), " &
|
||||
"232 (BC_7, DDR_D(12), bidir, X, 233, 1, Z), " &
|
||||
"231 (BC_1, *, control, 1), " &
|
||||
"230 (BC_7, DDR_DQS(1), bidir, X, 231, 1, Z), " &
|
||||
"229 (BC_1, *, control, 1), " &
|
||||
"228 (BC_7, DDR_D(11), bidir, X, 229, 1, Z), " &
|
||||
"227 (BC_1, *, control, 1), " &
|
||||
"226 (BC_7, DDR_D(10), bidir, X, 227, 1, Z), " &
|
||||
"225 (BC_1, *, control, 1), " &
|
||||
"224 (BC_7, DDR_D(9), bidir, X, 225, 1, Z), " &
|
||||
"223 (BC_1, *, control, 1), " &
|
||||
"222 (BC_7, DDR_D(8), bidir, X, 223, 1, Z), " &
|
||||
"221 (BC_0, *, control, 1), " &
|
||||
"220 (BC_0, DDR_DQM(1), output3, X, 221, 1, Z), " &
|
||||
"219 (BC_0, *, control, 1), " &
|
||||
"218 (BC_0, DDR_BA(2), output3, X, 219, 1, Z), " &
|
||||
"217 (BC_0, *, control, 1), " &
|
||||
"216 (BC_0, DDR_BA(1), output3, X, 217, 1, Z), " &
|
||||
"215 (BC_0, *, control, 1), " &
|
||||
"214 (BC_0, DDR_BA(0), output3, X, 215, 1, Z), " &
|
||||
"213 (BC_0, *, control, 1), " &
|
||||
"212 (BC_0, DDR_CKE, output3, X, 213, 1, Z), " &
|
||||
"211 (BC_0, *, control, 1), " &
|
||||
"210 (BC_0, DDR_CS, output3, X, 211, 1, Z), " &
|
||||
"209 (BC_0, *, control, 1), " &
|
||||
"208 (BC_0, DDR_A(13), output3, X, 209, 1, Z), " &
|
||||
"207 (BC_0, *, control, 1), " &
|
||||
"206 (BC_0, DDR_RESETN, output3, X, 207, 1, Z), " &
|
||||
"205 (BC_0, *, control, 1), " &
|
||||
"204 (BC_0, DDR_A(5), output3, X, 205, 1, Z), " &
|
||||
"203 (BC_0, *, control, 1), " &
|
||||
"202 (BC_0, DDR_A(6), output3, X, 203, 1, Z), " &
|
||||
"201 (BC_0, *, control, 1), " &
|
||||
"200 (BC_0, DDR_RAS, output3, X, 201, 1, Z), " &
|
||||
"199 (BC_0, *, control, 1), " &
|
||||
"198 (BC_0, DDR_CAS, output3, X, 199, 1, Z), " &
|
||||
"197 (BC_0, *, control, 1), " &
|
||||
"196 (BC_0, DDR_WE, output3, X, 197, 1, Z), " &
|
||||
"195 (BC_0, *, control, 1), " &
|
||||
"194 (BC_0, DDR_CLK, output3, X, 195, 1, Z), " &
|
||||
"193 (BC_0, *, control, 1), " &
|
||||
"192 (BC_0, DDR_A(0), output3, X, 193, 1, Z), " &
|
||||
"191 (BC_0, *, control, 1), " &
|
||||
"190 (BC_0, DDR_A(1), output3, X, 191, 1, Z), " &
|
||||
"189 (BC_0, *, control, 1), " &
|
||||
"188 (BC_0, DDR_A(2), output3, X, 189, 1, Z), " &
|
||||
"187 (BC_0, *, control, 1), " &
|
||||
"186 (BC_0, DDR_A(3), output3, X, 187, 1, Z), " &
|
||||
"185 (BC_0, *, control, 1), " &
|
||||
"184 (BC_0, DDR_A(4), output3, X, 185, 1, Z), " &
|
||||
"183 (BC_0, *, control, 1), " &
|
||||
"182 (BC_0, DDR_A(12), output3, X, 183, 1, Z), " &
|
||||
"181 (BC_0, *, control, 1), " &
|
||||
"180 (BC_0, DDR_A(11), output3, X, 181, 1, Z), " &
|
||||
"179 (BC_0, *, control, 1), " &
|
||||
"178 (BC_0, DDR_A(10), output3, X, 179, 1, Z), " &
|
||||
"177 (BC_0, *, control, 1), " &
|
||||
"176 (BC_0, DDR_A(9), output3, X, 177, 1, Z), " &
|
||||
"175 (BC_0, *, control, 1), " &
|
||||
"174 (BC_0, DDR_A(8), output3, X, 175, 1, Z), " &
|
||||
"173 (BC_0, *, control, 1), " &
|
||||
"172 (BC_0, DDR_A(7), output3, X, 173, 1, Z), " &
|
||||
"171 (BC_1, *, control, 1), " &
|
||||
"170 (BC_7, DDR_D(7), bidir, X, 171, 1, Z), " &
|
||||
"169 (BC_1, *, control, 1), " &
|
||||
"168 (BC_7, DDR_D(6), bidir, X, 169, 1, Z), " &
|
||||
"167 (BC_1, *, control, 1), " &
|
||||
"166 (BC_7, DDR_D(5), bidir, X, 167, 1, Z), " &
|
||||
"165 (BC_1, *, control, 1), " &
|
||||
"164 (BC_7, DDR_D(4), bidir, X, 165, 1, Z), " &
|
||||
"163 (BC_1, *, control, 1), " &
|
||||
"162 (BC_7, DDR_DQS(0), bidir, X, 163, 1, Z), " &
|
||||
"161 (BC_1, *, control, 1), " &
|
||||
"160 (BC_7, DDR_D(3), bidir, X, 161, 1, Z), " &
|
||||
"159 (BC_1, *, control, 1), " &
|
||||
"158 (BC_7, DDR_D(2), bidir, X, 159, 1, Z), " &
|
||||
"157 (BC_1, *, control, 1), " &
|
||||
"156 (BC_7, DDR_D(1), bidir, X, 157, 1, Z), " &
|
||||
"155 (BC_1, *, control, 1), " &
|
||||
"154 (BC_7, DDR_D(0), bidir, X, 155, 1, Z), " &
|
||||
"153 (BC_0, *, control, 1), " &
|
||||
"152 (BC_0, DDR_DQM(0), output3, X, 153, 1, Z), " &
|
||||
"151 (BC_0, *, internal, X), " &
|
||||
"150 (BC_0, *, internal, X), " &
|
||||
"149 (BC_0, *, internal, X), " &
|
||||
"148 (BC_0, *, internal, X), " &
|
||||
"147 (BC_0, *, internal, X), " &
|
||||
"146 (BC_0, *, internal, X), " &
|
||||
"145 (BC_0, *, internal, X), " &
|
||||
"144 (BC_0, *, internal, X), " &
|
||||
"143 (BC_0, *, internal, X), " &
|
||||
"142 (BC_0, *, internal, X), " &
|
||||
"141 (BC_0, *, internal, X), " &
|
||||
"140 (BC_0, *, internal, X), " &
|
||||
"139 (BC_0, *, internal, X), " &
|
||||
"138 (BC_0, *, internal, X), " &
|
||||
"137 (BC_0, *, internal, X), " &
|
||||
"136 (BC_0, *, internal, X), " &
|
||||
"135 (BC_0, *, internal, X), " &
|
||||
"134 (BC_0, *, internal, X), " &
|
||||
"133 (BC_0, *, internal, X), " &
|
||||
"132 (BC_0, *, internal, X), " &
|
||||
"131 (BC_0, *, internal, X), " &
|
||||
"130 (BC_0, *, internal, X), " &
|
||||
"129 (BC_0, *, internal, X), " &
|
||||
"128 (BC_0, *, internal, X), " &
|
||||
"127 (BC_0, *, internal, X), " &
|
||||
"126 (BC_0, *, internal, X), " &
|
||||
"125 (BC_0, *, internal, X), " &
|
||||
"124 (BC_0, *, internal, X), " &
|
||||
"123 (BC_0, *, internal, X), " &
|
||||
"122 (BC_0, *, internal, X), " &
|
||||
"121 (BC_0, *, internal, X), " &
|
||||
"120 (BC_0, *, internal, X), " &
|
||||
"119 (BC_0, *, internal, X), " &
|
||||
"118 (BC_0, *, internal, X), " &
|
||||
"117 (BC_0, *, internal, X), " &
|
||||
"116 (BC_0, *, internal, X), " &
|
||||
"115 (BC_0, *, internal, X), " &
|
||||
"114 (BC_0, *, internal, X), " &
|
||||
"113 (BC_1, *, control, 1), " &
|
||||
"112 (BC_7, PB0, bidir, X, 113, 1, Z), " &
|
||||
"111 (BC_1, *, control, 1), " &
|
||||
"110 (BC_7, PB2, bidir, X, 111, 1, Z), " &
|
||||
"109 (BC_1, *, control, 1), " &
|
||||
"108 (BC_7, PB1, bidir, X, 109, 1, Z), " &
|
||||
"107 (BC_1, *, control, 1), " &
|
||||
"106 (BC_7, PB3, bidir, X, 107, 1, Z), " &
|
||||
"105 (BC_1, *, control, 1), " &
|
||||
"104 (BC_7, PB4, bidir, X, 105, 1, Z), " &
|
||||
"103 (BC_1, *, control, 1), " &
|
||||
"102 (BC_7, PB5, bidir, X, 103, 1, Z), " &
|
||||
"101 (BC_1, *, control, 1), " &
|
||||
"100 (BC_7, PB6, bidir, X, 101, 1, Z), " &
|
||||
"99 (BC_1, *, control, 1), " &
|
||||
"98 (BC_7, PB8, bidir, X, 99, 1, Z), " &
|
||||
"97 (BC_1, *, control, 1), " &
|
||||
"96 (BC_7, PB7, bidir, X, 97, 1, Z), " &
|
||||
"95 (BC_1, *, control, 1), " &
|
||||
"94 (BC_7, PB10, bidir, X, 95, 1, Z), " &
|
||||
"93 (BC_1, *, control, 1), " &
|
||||
"92 (BC_7, PB9, bidir, X, 93, 1, Z), " &
|
||||
"91 (BC_1, *, control, 1), " &
|
||||
"90 (BC_7, PB11, bidir, X, 91, 1, Z), " &
|
||||
"89 (BC_1, *, control, 1), " &
|
||||
"88 (BC_7, PB12, bidir, X, 89, 1, Z), " &
|
||||
"87 (BC_1, *, control, 1), " &
|
||||
"86 (BC_7, PB14, bidir, X, 87, 1, Z), " &
|
||||
"85 (BC_1, *, control, 1), " &
|
||||
"84 (BC_7, PB13, bidir, X, 85, 1, Z), " &
|
||||
"83 (BC_1, *, control, 1), " &
|
||||
"82 (BC_7, PB15, bidir, X, 83, 1, Z), " &
|
||||
"81 (BC_1, *, control, 1), " &
|
||||
"80 (BC_7, PB16, bidir, X, 81, 1, Z), " &
|
||||
"79 (BC_1, *, control, 1), " &
|
||||
"78 (BC_7, PB17, bidir, X, 79, 1, Z), " &
|
||||
"77 (BC_1, *, control, 1), " &
|
||||
"76 (BC_7, PB19, bidir, X, 77, 1, Z), " &
|
||||
"75 (BC_1, *, control, 1), " &
|
||||
"74 (BC_7, PB18, bidir, X, 75, 1, Z), " &
|
||||
"73 (BC_1, *, control, 1), " &
|
||||
"72 (BC_7, PB20, bidir, X, 73, 1, Z), " &
|
||||
"71 (BC_1, *, control, 1), " &
|
||||
"70 (BC_7, PB21, bidir, X, 71, 1, Z), " &
|
||||
"69 (BC_1, *, control, 1), " &
|
||||
"68 (BC_7, PB23, bidir, X, 69, 1, Z), " &
|
||||
"67 (BC_1, *, control, 1), " &
|
||||
"66 (BC_7, PB22, bidir, X, 67, 1, Z), " &
|
||||
"65 (BC_1, *, control, 1), " &
|
||||
"64 (BC_7, PB25, bidir, X, 65, 1, Z), " &
|
||||
"63 (BC_1, *, control, 1), " &
|
||||
"62 (BC_7, PB24, bidir, X, 63, 1, Z), " &
|
||||
"61 (BC_1, *, control, 1), " &
|
||||
"60 (BC_7, PB26, bidir, X, 61, 1, Z), " &
|
||||
"59 (BC_1, *, control, 1), " &
|
||||
"58 (BC_7, PB28, bidir, X, 59, 1, Z), " &
|
||||
"57 (BC_1, *, control, 1), " &
|
||||
"56 (BC_7, PB27, bidir, X, 57, 1, Z), " &
|
||||
"55 (BC_1, *, control, 1), " &
|
||||
"54 (BC_7, PB30, bidir, X, 55, 1, Z), " &
|
||||
"53 (BC_1, *, control, 1), " &
|
||||
"52 (BC_7, PB29, bidir, X, 53, 1, Z), " &
|
||||
"51 (BC_1, *, control, 1), " &
|
||||
"50 (BC_7, PB31, bidir, X, 51, 1, Z), " &
|
||||
"49 (BC_0, *, internal, X), " &
|
||||
"48 (BC_0, *, internal, X), " &
|
||||
"47 (BC_0, *, internal, X), " &
|
||||
"46 (BC_0, *, internal, X), " &
|
||||
"45 (BC_0, *, internal, X), " &
|
||||
"44 (BC_0, *, internal, X), " &
|
||||
"43 (BC_0, *, internal, X), " &
|
||||
"42 (BC_0, *, internal, X), " &
|
||||
"41 (BC_0, *, internal, X), " &
|
||||
"40 (BC_0, *, internal, X), " &
|
||||
"39 (BC_0, *, internal, X), " &
|
||||
"38 (BC_0, *, internal, X), " &
|
||||
"37 (BC_0, *, internal, X), " &
|
||||
"36 (BC_0, *, internal, X), " &
|
||||
"35 (BC_0, *, internal, X), " &
|
||||
"34 (BC_0, *, internal, X), " &
|
||||
"33 (BC_0, *, internal, X), " &
|
||||
"32 (BC_0, *, internal, X), " &
|
||||
"31 (BC_0, *, internal, X), " &
|
||||
"30 (BC_0, *, internal, X), " &
|
||||
"29 (BC_0, *, internal, X), " &
|
||||
"28 (BC_0, *, internal, X), " &
|
||||
"27 (BC_0, *, internal, X), " &
|
||||
"26 (BC_0, *, internal, X), " &
|
||||
"25 (BC_0, *, internal, X), " &
|
||||
"24 (BC_0, *, internal, X), " &
|
||||
"23 (BC_0, *, internal, X), " &
|
||||
"22 (BC_0, *, internal, X), " &
|
||||
"21 (BC_0, *, internal, X), " &
|
||||
"20 (BC_0, *, internal, X), " &
|
||||
"19 (BC_0, *, internal, X), " &
|
||||
"18 (BC_0, *, internal, X), " &
|
||||
"17 (BC_0, *, internal, X), " &
|
||||
"16 (BC_0, *, internal, X), " &
|
||||
"15 (BC_1, *, control, 1), " &
|
||||
"14 (BC_7, PD10, bidir, X, 15, 1, Z), " &
|
||||
"13 (BC_1, *, control, 1), " &
|
||||
"12 (BC_7, PD9, bidir, X, 13, 1, Z), " &
|
||||
"11 (BC_1, *, control, 1), " &
|
||||
"10 (BC_7, PD8, bidir, X, 11, 1, Z), " &
|
||||
"9 (BC_1, *, control, 1), " &
|
||||
"8 (BC_7, PD7, bidir, X, 9, 1, Z), " &
|
||||
"7 (BC_0, *, internal, X), " &
|
||||
"6 (BC_0, *, internal, X), " &
|
||||
"5 (BC_0, *, internal, X), " &
|
||||
"4 (BC_0, *, internal, X), " &
|
||||
"3 (BC_0, *, internal, X), " &
|
||||
"2 (BC_0, *, internal, X), " &
|
||||
"1 (BC_0, *, internal, X), " &
|
||||
"0 (BC_0, *, internal, X) ";
|
||||
|
||||
end top;
|
|
@ -0,0 +1,842 @@
|
|||
-- *****************************************************************************
|
||||
|
||||
-- BSDL file for design top
|
||||
|
||||
-- Created by Synopsys Version I-2013.12-SP3 (Apr 18, 2014)
|
||||
|
||||
-- Designer:
|
||||
-- Company:
|
||||
|
||||
-- Date: Thu Feb 5 22:56:11 2015
|
||||
|
||||
-- *****************************************************************************
|
||||
|
||||
|
||||
entity top is
|
||||
|
||||
-- This section identifies the default device package selected.
|
||||
|
||||
generic (PHYSICAL_PIN_MAP: string:= "BGA256");
|
||||
|
||||
-- This section declares all the ports in the design.
|
||||
|
||||
port (
|
||||
PD14 : in bit;
|
||||
PD15 : in bit;
|
||||
PD17 : in bit;
|
||||
PD18 : in bit;
|
||||
PA0 : inout bit;
|
||||
PA1 : inout bit;
|
||||
PA10 : inout bit;
|
||||
PA11 : inout bit;
|
||||
PA12 : inout bit;
|
||||
PA13 : inout bit;
|
||||
PA14 : inout bit;
|
||||
PA15 : inout bit;
|
||||
PA16 : inout bit;
|
||||
PA17 : inout bit;
|
||||
PA18 : inout bit;
|
||||
PA19 : inout bit;
|
||||
PA2 : inout bit;
|
||||
PA20 : inout bit;
|
||||
PA21 : inout bit;
|
||||
PA22 : inout bit;
|
||||
PA23 : inout bit;
|
||||
PA24 : inout bit;
|
||||
PA25 : inout bit;
|
||||
PA26 : inout bit;
|
||||
PA27 : inout bit;
|
||||
PA28 : inout bit;
|
||||
PA29 : inout bit;
|
||||
PA3 : inout bit;
|
||||
PA30 : inout bit;
|
||||
PA31 : inout bit;
|
||||
PA4 : inout bit;
|
||||
PA5 : inout bit;
|
||||
PA6 : inout bit;
|
||||
PA7 : inout bit;
|
||||
PA8 : inout bit;
|
||||
PA9 : inout bit;
|
||||
PB0 : inout bit;
|
||||
PB1 : inout bit;
|
||||
PB10 : inout bit;
|
||||
PB11 : inout bit;
|
||||
PB12 : inout bit;
|
||||
PB13 : inout bit;
|
||||
PB14 : inout bit;
|
||||
PB15 : inout bit;
|
||||
PB16 : inout bit;
|
||||
PB17 : inout bit;
|
||||
PB18 : inout bit;
|
||||
PB19 : inout bit;
|
||||
PB2 : inout bit;
|
||||
PB20 : inout bit;
|
||||
PB21 : inout bit;
|
||||
PB22 : inout bit;
|
||||
PB23 : inout bit;
|
||||
PB24 : inout bit;
|
||||
PB25 : inout bit;
|
||||
PB26 : inout bit;
|
||||
PB27 : inout bit;
|
||||
PB28 : inout bit;
|
||||
PB29 : inout bit;
|
||||
PB3 : inout bit;
|
||||
PB30 : inout bit;
|
||||
PB31 : inout bit;
|
||||
PB4 : inout bit;
|
||||
PB5 : inout bit;
|
||||
PB6 : inout bit;
|
||||
PB7 : inout bit;
|
||||
PB8 : inout bit;
|
||||
PB9 : inout bit;
|
||||
PC0 : inout bit;
|
||||
PC1 : inout bit;
|
||||
-- PC10 : linkage bit; -- NC(No Connect) Port
|
||||
-- PC11 : linkage bit; -- NC Port
|
||||
-- PC12 : linkage bit; -- NC Port
|
||||
-- PC13 : linkage bit; -- NC Port
|
||||
-- PC14 : linkage bit; -- NC Port
|
||||
-- PC15 : linkage bit; -- NC Port
|
||||
-- PC16 : linkage bit; -- NC Port
|
||||
-- PC17 : linkage bit; -- NC Port
|
||||
-- PC18 : linkage bit; -- NC Port
|
||||
-- PC19 : linkage bit; -- NC Port
|
||||
PC2 : inout bit;
|
||||
-- PC20 : linkage bit; -- NC Port
|
||||
-- PC21 : linkage bit; -- NC Port
|
||||
-- PC22 : linkage bit; -- NC Port
|
||||
-- PC23 : linkage bit; -- NC Port
|
||||
-- PC24 : linkage bit; -- NC Port
|
||||
-- PC25 : linkage bit; -- NC Port
|
||||
-- PC26 : linkage bit; -- NC Port
|
||||
-- PC27 : linkage bit; -- NC Port
|
||||
-- PC28 : linkage bit; -- NC Port
|
||||
-- PC29 : linkage bit; -- NC Port
|
||||
PC3 : inout bit;
|
||||
-- PC30 : linkage bit; -- NC Port
|
||||
-- PC31 : linkage bit; -- NC Port
|
||||
PC4 : inout bit;
|
||||
PC5 : inout bit;
|
||||
PC6 : inout bit;
|
||||
PC7 : inout bit;
|
||||
PC8 : inout bit;
|
||||
-- PC9 : linkage bit; -- NC Port
|
||||
PD0 : inout bit;
|
||||
PD1 : inout bit;
|
||||
PD10 : inout bit;
|
||||
PD11 : inout bit;
|
||||
PD12 : inout bit;
|
||||
PD13 : inout bit;
|
||||
PD19 : inout bit;
|
||||
PD2 : inout bit;
|
||||
PD20 : inout bit;
|
||||
PD21 : inout bit;
|
||||
PD22 : inout bit;
|
||||
PD23 : inout bit;
|
||||
PD24 : inout bit;
|
||||
PD25 : inout bit;
|
||||
PD26 : inout bit;
|
||||
PD27 : inout bit;
|
||||
PD28 : inout bit;
|
||||
PD29 : inout bit;
|
||||
PD3 : inout bit;
|
||||
PD30 : inout bit;
|
||||
PD31 : inout bit;
|
||||
PD4 : inout bit;
|
||||
PD5 : inout bit;
|
||||
PD6 : inout bit;
|
||||
PD7 : inout bit;
|
||||
PD8 : inout bit;
|
||||
PD9 : inout bit;
|
||||
DDR_D : inout bit_vector (0 to 31);
|
||||
DDR_DQS : inout bit_vector (0 to 3);
|
||||
DDR_DQSN : inout bit_vector (0 to 3);
|
||||
DDR_CAS : out bit;
|
||||
DDR_CKE : out bit;
|
||||
DDR_CLK : out bit;
|
||||
DDR_CLKN : out bit;
|
||||
DDR_CS : out bit;
|
||||
DDR_RAS : out bit;
|
||||
DDR_RESETN : out bit;
|
||||
DDR_WE : out bit;
|
||||
PD16 : out bit;
|
||||
DDR_A : out bit_vector (0 to 13);
|
||||
DDR_BA : out bit_vector (0 to 2);
|
||||
DDR_DQM : out bit_vector (0 to 3);
|
||||
-- ADVREFN : linkage bit;
|
||||
ADVREFP : linkage bit;
|
||||
CLK_AUDIO : linkage bit;
|
||||
COMPN : linkage bit;
|
||||
COMPP : linkage bit;
|
||||
DDR_CAL : linkage bit;
|
||||
DDR_VREF : linkage bit; -- DDR_VREFB0 : linkage bit;
|
||||
-- DDR_VREFB1 : linkage bit;
|
||||
-- DDR_VREFB2 : linkage bit;
|
||||
-- DDR_VREFB3 : linkage bit;
|
||||
-- DDR_VREFCM : linkage bit;
|
||||
HHSDMA : linkage bit;
|
||||
HHSDMB : linkage bit;
|
||||
HHSDMSTRC : linkage bit;
|
||||
HHSDPA : linkage bit;
|
||||
HHSDPB : linkage bit;
|
||||
HHSDPDATC : linkage bit;
|
||||
JTAGSEL : in bit;
|
||||
NRST : linkage bit;
|
||||
RXD : linkage bit;
|
||||
SDCAL : linkage bit;
|
||||
SHDN : linkage bit;
|
||||
TST : in bit;
|
||||
VBG : linkage bit;
|
||||
WKUP : linkage bit;
|
||||
XIN : linkage bit;
|
||||
XIN32 : linkage bit;
|
||||
XOUT : linkage bit;
|
||||
XOUT32 : linkage bit;
|
||||
-- tst_drst_ana : linkage bit; -- NC Port
|
||||
-- tst_drst_ddr : linkage bit; -- NC Port
|
||||
-- tst_drst_iop0 : linkage bit; -- NC Port
|
||||
-- tst_drst_iop1 : linkage bit; -- NC Port
|
||||
-- tst_drst_iop2 : linkage bit; -- NC Port
|
||||
-- tst_drst_isi : linkage bit; -- NC Port
|
||||
-- tst_drst_osc : linkage bit; -- NC Port
|
||||
-- tst_drst_sdhc : linkage bit; -- NC Port
|
||||
-- tst_lft_plla : linkage bit; -- NC Port
|
||||
-- tst_lft_utmi : linkage bit; -- NC Port
|
||||
-- tst_por_1v2 : linkage bit; -- NC Port
|
||||
-- tst_por_1v8 : linkage bit; -- NC Port
|
||||
-- tst_por_bu : linkage bit; -- NC Port
|
||||
-- tst_psw_bu : linkage bit; -- NC Port
|
||||
-- tst_psw_fuse : linkage bit; -- NC Port
|
||||
PIOBU : linkage bit_vector (0 to 1)
|
||||
);
|
||||
|
||||
use STD_1149_1_1994.all;
|
||||
|
||||
attribute COMPONENT_CONFORMANCE of top: entity is "STD_1149_1_1993";
|
||||
|
||||
attribute PIN_MAP of top: entity is PHYSICAL_PIN_MAP;
|
||||
|
||||
-- This section specifies the pin map for each port. This information is
|
||||
-- extracted from the port-to-pin map file that was read in using the
|
||||
-- "read_pin_map" command.
|
||||
|
||||
constant BGA256: PIN_MAP_STRING :=
|
||||
"PD14 : K6," &
|
||||
"PD15 : K4," &
|
||||
"PD17 : K2," &
|
||||
"PD18 : L5," &
|
||||
"PA0 : R10," &
|
||||
"PA1 : R9," &
|
||||
"PA10 : U13," &
|
||||
"PA11 : R14," &
|
||||
"PA12 : N13," &
|
||||
"PA13 : P14," &
|
||||
"PA14 : P17," &
|
||||
"PA15 : R18," &
|
||||
"PA16 : N15," &
|
||||
"PA17 : P18," &
|
||||
"PA18 : M9," &
|
||||
"PA19 : V13," &
|
||||
"PA2 : U11," &
|
||||
"PA20 : L9," &
|
||||
"PA21 : M10," &
|
||||
"PA22 : V14," &
|
||||
"PA23 : U14," &
|
||||
"PA24 : R13," &
|
||||
"PA25 : U15," &
|
||||
"PA26 : L10," &
|
||||
"PA27 : V17," &
|
||||
"PA28 : U16," &
|
||||
"PA29 : U17," &
|
||||
"PA3 : P10," &
|
||||
"PA30 : V18," &
|
||||
"PA31 : U18," &
|
||||
"PA4 : P11," &
|
||||
"PA5 : V11," &
|
||||
"PA6 : U12," &
|
||||
"PA7 : V12," &
|
||||
"PA8 : N11," &
|
||||
"PA9 : P12," &
|
||||
"PB0 : G9," &
|
||||
"PB1 : A7," &
|
||||
"PB10 : D6," &
|
||||
"PB11 : A4," &
|
||||
"PB12 : B3," &
|
||||
"PB13 : A3," &
|
||||
"PB14 : B4," &
|
||||
"PB15 : G8," &
|
||||
"PB16 : E5," &
|
||||
"PB17 : G7," &
|
||||
"PB18 : A2," &
|
||||
"PB19 : H7," &
|
||||
"PB2 : B7," &
|
||||
"PB20 : A1," &
|
||||
"PB21 : D2," &
|
||||
"PB22 : G5," &
|
||||
"PB23 : C2," &
|
||||
"PB24 : F4," &
|
||||
"PB25 : C1," &
|
||||
"PB26 : E4," &
|
||||
"PB27 : F1," &
|
||||
"PB28 : D1," &
|
||||
"PB29 : F2," &
|
||||
"PB3 : B6," &
|
||||
"PB30 : E2," &
|
||||
"PB31 : E1," &
|
||||
"PB4 : A6," &
|
||||
"PB5 : D7," &
|
||||
"PB6 : B5," &
|
||||
"PB7 : A5," &
|
||||
"PB8 : E7," &
|
||||
"PB9 : F6," &
|
||||
"PC0 : R15," &
|
||||
"PC1 : M11," &
|
||||
"PC2 : P15," &
|
||||
"PC3 : K9," &
|
||||
"PC4 : K10," &
|
||||
"PC5 : L11," &
|
||||
"PC6 : L12," &
|
||||
"PC7 : M12," &
|
||||
"PC8 : K11," &
|
||||
"PD0 : E9," &
|
||||
"PD1 : F8," &
|
||||
"PD10 : G2," &
|
||||
"PD11 : H2," &
|
||||
"PD12 : K5," &
|
||||
"PD13 : J5," &
|
||||
"PD19 : L4," &
|
||||
"PD2 : F9," &
|
||||
"PD20 : M1," &
|
||||
"PD21 : M2," &
|
||||
"PD22 : M4," &
|
||||
"PD23 : P1," &
|
||||
"PD24 : L6," &
|
||||
"PD25 : M5," &
|
||||
"PD26 : N1," &
|
||||
"PD27 : N2," &
|
||||
"PD28 : P2," &
|
||||
"PD29 : R1," &
|
||||
"PD3 : J4," &
|
||||
"PD30 : N4," &
|
||||
"PD31 : T1," &
|
||||
"PD4 : H6," &
|
||||
"PD5 : H1," &
|
||||
"PD6 : G4," &
|
||||
"PD7 : H5," &
|
||||
"PD8 : G1," &
|
||||
"PD9 : H4," &
|
||||
"DDR_D : (B12, B13, D13, A13, A15, D14, B15, B16, G18, K17, " &
|
||||
"J13, H15, J15, J14, K13, K18, A8, B9, D9, A9, B11, D10, A11, A12, " &
|
||||
"L18, K15, K14, M18, N17, M14, M15, N18)," &
|
||||
"DDR_DQS : (A14, H18, A10, M17)," &
|
||||
"DDR_DQSN : (B14, J18, B10, L17)," &
|
||||
"DDR_CAS : E17," &
|
||||
"DDR_CKE : F18," &
|
||||
"DDR_CLK : C18," &
|
||||
"DDR_CLKN : C17," &
|
||||
"DDR_CS : J12," &
|
||||
"DDR_RAS : E18," &
|
||||
"DDR_RESETN : F17," &
|
||||
"DDR_WE : D18," &
|
||||
"PD16 : K1," &
|
||||
"DDR_A : (D17, A17, A18, F15, G12, H12, F13, H10, A16, E12, " &
|
||||
"H11, J10, D15, J11)," &
|
||||
"DDR_BA : (H13, K12, H17)," &
|
||||
"DDR_DQM : (D11, H14, B8, L13)," &
|
||||
"ADVREFP : P5," &
|
||||
"CLK_AUDIO : M8," &
|
||||
"COMPN : V4," &
|
||||
"COMPP : V3," &
|
||||
"DDR_CAL : G17," &
|
||||
"HHSDMA : V8," &
|
||||
"HHSDMB : V9," &
|
||||
"HHSDMSTRC : V10," &
|
||||
"HHSDPA : U8," &
|
||||
"HHSDPB : U9," &
|
||||
"HHSDPDATC : U10," &
|
||||
"JTAGSEL : V2," &
|
||||
"NRST : V1," &
|
||||
"RXD : U2," &
|
||||
"SDCAL : N10," &
|
||||
"SHDN : U1," &
|
||||
"TST : P4," &
|
||||
"VBG : R7," &
|
||||
"WKUP : R5," &
|
||||
"XIN : V7," &
|
||||
"XIN32 : T2," &
|
||||
"XOUT : V6," &
|
||||
"XOUT32 : R2," &
|
||||
"PIOBU : (R6, R4)";
|
||||
|
||||
-- This section specifies the differential IO port groupings.
|
||||
|
||||
attribute PORT_GROUPING of top: entity is
|
||||
"Differential_Voltage ( " &
|
||||
"(DDR_CLK,DDR_CLKN))";
|
||||
|
||||
-- This section specifies the TAP ports. For the TAP TCK port, the parameters in
|
||||
-- the brackets are:
|
||||
-- First Field : Maximum TCK frequency.
|
||||
-- Second Field: Allowable states TCK may be stopped in.
|
||||
|
||||
attribute TAP_SCAN_CLOCK of PD14: signal is (10.0e6, BOTH);
|
||||
attribute TAP_SCAN_IN of PD15: signal is true;
|
||||
attribute TAP_SCAN_MODE of PD17: signal is true;
|
||||
attribute TAP_SCAN_OUT of PD16: signal is true;
|
||||
attribute TAP_SCAN_RESET of PD18: signal is true;
|
||||
|
||||
-- Specifies the compliance enable patterns for the design. It lists a set of
|
||||
-- design ports and the values that they should be set to, in order to enable
|
||||
-- compliance to IEEE Std 1149.1
|
||||
|
||||
attribute COMPLIANCE_PATTERNS of top: entity is
|
||||
"(JTAGSEL, TST) (10)";
|
||||
|
||||
-- Specifies the number of bits in the instruction register.
|
||||
|
||||
attribute INSTRUCTION_LENGTH of top: entity is 4;
|
||||
|
||||
-- Specifies the boundary-scan instructions implemented in the design and their
|
||||
-- opcodes.
|
||||
|
||||
attribute INSTRUCTION_OPCODE of top: entity is
|
||||
"BYPASS (1111, 0001, 0101, 0110, 1100, 0111, 1101, 1000, 1001, 1011, " &
|
||||
"1110)," &
|
||||
"EXTEST (0000)," &
|
||||
"SAMPLE (0100)," &
|
||||
"INTEST (0010)," &
|
||||
"IDCODE (0011)," &
|
||||
"RUNBIST (1010)";
|
||||
|
||||
-- Specifies the bit pattern that is loaded into the instruction register when
|
||||
-- the TAP controller passes through the Capture-IR state. The standard mandates
|
||||
-- that the two LSBs must be "01". The remaining bits are design specific.
|
||||
|
||||
attribute INSTRUCTION_CAPTURE of top: entity is "0001";
|
||||
|
||||
-- Specifies the bit pattern that is loaded into the DEVICE_ID register during
|
||||
-- the IDCODE instruction when the TAP controller passes through the Capture-DR
|
||||
-- state.
|
||||
|
||||
attribute IDCODE_REGISTER of top: entity is
|
||||
"0000" &
|
||||
-- 4-bit version number
|
||||
"0101101100111111" &
|
||||
-- 16-bit part number
|
||||
"00000011111" &
|
||||
-- 11-bit identity of the manufacturer
|
||||
"1";
|
||||
-- Required by IEEE Std 1149.1
|
||||
|
||||
-- This section specifies the test data register placed between TDI and TDO for
|
||||
-- each implemented instruction.
|
||||
|
||||
attribute REGISTER_ACCESS of top: entity is
|
||||
"BYPASS (BYPASS)," &
|
||||
"BOUNDARY (EXTEST, SAMPLE, INTEST)," &
|
||||
"DEVICE_ID (IDCODE)," &
|
||||
"UTDR1[41] (RUNBIST)";
|
||||
|
||||
-- Specifies the length of the boundary scan register.
|
||||
|
||||
attribute BOUNDARY_LENGTH of top: entity is 374;
|
||||
|
||||
-- The following list specifies the characteristics of each cell in the boundary
|
||||
-- scan register from TDI to TDO. The following is a description of the label
|
||||
-- fields:
|
||||
-- num : Is the cell number.
|
||||
-- cell : Is the cell type as defined by the standard.
|
||||
-- port : Is the design port name. Control cells do not have a port
|
||||
-- name.
|
||||
-- function: Is the function of the cell as defined by the standard. Is one
|
||||
-- of input, output2, output3, bidir, control or controlr.
|
||||
-- safe : Specifies the value that the BSR cell should be loaded with
|
||||
-- for safe operation when the software might otherwise choose a
|
||||
-- random value.
|
||||
-- ccell : The control cell number. Specifies the control cell that
|
||||
-- drives the output enable for this port.
|
||||
-- disval : Specifies the value that is loaded into the control cell to
|
||||
-- disable the output enable for the corresponding port.
|
||||
-- rslt : Resulting state. Shows the state of the driver when it is
|
||||
-- disabled.
|
||||
|
||||
attribute BOUNDARY_REGISTER of top: entity is
|
||||
--
|
||||
-- num cell port function safe [ccell disval rslt]
|
||||
--
|
||||
"373 (BC_1, *, control, 1), " &
|
||||
"372 (BC_7, PD13, bidir, X, 373, 1, Z), " &
|
||||
"371 (BC_1, *, control, 1), " &
|
||||
"370 (BC_7, PD12, bidir, X, 371, 1, Z), " &
|
||||
"369 (BC_1, *, control, 1), " &
|
||||
"368 (BC_7, PD11, bidir, X, 369, 1, Z), " &
|
||||
"367 (BC_1, *, control, 1), " &
|
||||
"366 (BC_7, PD19, bidir, X, 367, 1, Z), " &
|
||||
"365 (BC_1, *, control, 1), " &
|
||||
"364 (BC_7, PD20, bidir, X, 365, 1, Z), " &
|
||||
"363 (BC_1, *, control, 1), " &
|
||||
"362 (BC_7, PD24, bidir, X, 363, 1, Z), " &
|
||||
"361 (BC_1, *, control, 1), " &
|
||||
"360 (BC_7, PD21, bidir, X, 361, 1, Z), " &
|
||||
"359 (BC_1, *, control, 1), " &
|
||||
"358 (BC_7, PD25, bidir, X, 359, 1, Z), " &
|
||||
"357 (BC_1, *, control, 1), " &
|
||||
"356 (BC_7, PD26, bidir, X, 357, 1, Z), " &
|
||||
"355 (BC_1, *, control, 1), " &
|
||||
"354 (BC_7, PD22, bidir, X, 355, 1, Z), " &
|
||||
"353 (BC_1, *, control, 1), " &
|
||||
"352 (BC_7, PD27, bidir, X, 353, 1, Z), " &
|
||||
"351 (BC_1, *, control, 1), " &
|
||||
"350 (BC_7, PD23, bidir, X, 351, 1, Z), " &
|
||||
"349 (BC_1, *, control, 1), " &
|
||||
"348 (BC_7, PD28, bidir, X, 349, 1, Z), " &
|
||||
"347 (BC_1, *, control, 1), " &
|
||||
"346 (BC_7, PD30, bidir, X, 347, 1, Z), " &
|
||||
"345 (BC_1, *, control, 1), " &
|
||||
"344 (BC_7, PD29, bidir, X, 345, 1, Z), " &
|
||||
"343 (BC_1, *, control, 1), " &
|
||||
"342 (BC_7, PD31, bidir, X, 343, 1, Z), " &
|
||||
"341 (BC_1, *, control, 1), " &
|
||||
"340 (BC_7, PA0, bidir, X, 341, 1, Z), " &
|
||||
"339 (BC_1, *, control, 1), " &
|
||||
"338 (BC_7, PA1, bidir, X, 339, 1, Z), " &
|
||||
"337 (BC_1, *, control, 1), " &
|
||||
"336 (BC_7, PA2, bidir, X, 337, 1, Z), " &
|
||||
"335 (BC_1, *, control, 1), " &
|
||||
"334 (BC_7, PA3, bidir, X, 335, 1, Z), " &
|
||||
"333 (BC_1, *, control, 1), " &
|
||||
"332 (BC_7, PA4, bidir, X, 333, 1, Z), " &
|
||||
"331 (BC_1, *, control, 1), " &
|
||||
"330 (BC_7, PA5, bidir, X, 331, 1, Z), " &
|
||||
"329 (BC_1, *, control, 1), " &
|
||||
"328 (BC_7, PA6, bidir, X, 329, 1, Z), " &
|
||||
"327 (BC_1, *, control, 1), " &
|
||||
"326 (BC_7, PA7, bidir, X, 327, 1, Z), " &
|
||||
"325 (BC_1, *, control, 1), " &
|
||||
"324 (BC_7, PA8, bidir, X, 325, 1, Z), " &
|
||||
"323 (BC_1, *, control, 1), " &
|
||||
"322 (BC_7, PA9, bidir, X, 323, 1, Z), " &
|
||||
"321 (BC_1, *, control, 1), " &
|
||||
"320 (BC_7, PA10, bidir, X, 321, 1, Z), " &
|
||||
"319 (BC_1, *, control, 1), " &
|
||||
"318 (BC_7, PA18, bidir, X, 319, 1, Z), " &
|
||||
"317 (BC_1, *, control, 1), " &
|
||||
"316 (BC_7, PA20, bidir, X, 317, 1, Z), " &
|
||||
"315 (BC_1, *, control, 1), " &
|
||||
"314 (BC_7, PA19, bidir, X, 315, 1, Z), " &
|
||||
"313 (BC_1, *, control, 1), " &
|
||||
"312 (BC_7, PA21, bidir, X, 313, 1, Z), " &
|
||||
"311 (BC_1, *, control, 1), " &
|
||||
"310 (BC_7, PA22, bidir, X, 311, 1, Z), " &
|
||||
"309 (BC_1, *, control, 1), " &
|
||||
"308 (BC_7, PA23, bidir, X, 309, 1, Z), " &
|
||||
"307 (BC_1, *, control, 1), " &
|
||||
"306 (BC_7, PA24, bidir, X, 307, 1, Z), " &
|
||||
"305 (BC_1, *, control, 1), " &
|
||||
"304 (BC_7, PA25, bidir, X, 305, 1, Z), " &
|
||||
"303 (BC_1, *, control, 1), " &
|
||||
"302 (BC_7, PA26, bidir, X, 303, 1, Z), " &
|
||||
"301 (BC_1, *, control, 1), " &
|
||||
"300 (BC_7, PA27, bidir, X, 301, 1, Z), " &
|
||||
"299 (BC_1, *, control, 1), " &
|
||||
"298 (BC_7, PA28, bidir, X, 299, 1, Z), " &
|
||||
"297 (BC_1, *, control, 1), " &
|
||||
"296 (BC_7, PA30, bidir, X, 297, 1, Z), " &
|
||||
"295 (BC_1, *, control, 1), " &
|
||||
"294 (BC_7, PA29, bidir, X, 295, 1, Z), " &
|
||||
"293 (BC_1, *, control, 1), " &
|
||||
"292 (BC_7, PA31, bidir, X, 293, 1, Z), " &
|
||||
"291 (BC_1, *, control, 1), " &
|
||||
"290 (BC_7, PC0, bidir, X, 291, 1, Z), " &
|
||||
"289 (BC_1, *, control, 1), " &
|
||||
"288 (BC_7, PA11, bidir, X, 289, 1, Z), " &
|
||||
"287 (BC_1, *, control, 1), " &
|
||||
"286 (BC_7, PC1, bidir, X, 287, 1, Z), " &
|
||||
"285 (BC_1, *, control, 1), " &
|
||||
"284 (BC_7, PA13, bidir, X, 285, 1, Z), " &
|
||||
"283 (BC_1, *, control, 1), " &
|
||||
"282 (BC_7, PA12, bidir, X, 283, 1, Z), " &
|
||||
"281 (BC_1, *, control, 1), " &
|
||||
"280 (BC_7, PC2, bidir, X, 281, 1, Z), " &
|
||||
"279 (BC_1, *, control, 1), " &
|
||||
"278 (BC_7, PA14, bidir, X, 279, 1, Z), " &
|
||||
"277 (BC_1, *, control, 1), " &
|
||||
"276 (BC_7, PA15, bidir, X, 277, 1, Z), " &
|
||||
"275 (BC_1, *, control, 1), " &
|
||||
"274 (BC_7, PC3, bidir, X, 275, 1, Z), " &
|
||||
"273 (BC_1, *, control, 1), " &
|
||||
"272 (BC_7, PC4, bidir, X, 273, 1, Z), " &
|
||||
"271 (BC_1, *, control, 1), " &
|
||||
"270 (BC_7, PA16, bidir, X, 271, 1, Z), " &
|
||||
"269 (BC_1, *, control, 1), " &
|
||||
"268 (BC_7, PA17, bidir, X, 269, 1, Z), " &
|
||||
"267 (BC_1, *, control, 1), " &
|
||||
"266 (BC_7, PC5, bidir, X, 267, 1, Z), " &
|
||||
"265 (BC_1, *, control, 1), " &
|
||||
"264 (BC_7, PC7, bidir, X, 265, 1, Z), " &
|
||||
"263 (BC_1, *, control, 1), " &
|
||||
"262 (BC_7, PC6, bidir, X, 263, 1, Z), " &
|
||||
"261 (BC_1, *, control, 1), " &
|
||||
"260 (BC_7, PC8, bidir, X, 261, 1, Z), " &
|
||||
"259 (BC_1, *, control, 1), " &
|
||||
"258 (BC_7, DDR_D(31), bidir, X, 259, 1, Z), " &
|
||||
"257 (BC_1, *, control, 1), " &
|
||||
"256 (BC_7, DDR_D(30), bidir, X, 257, 1, Z), " &
|
||||
"255 (BC_1, *, control, 1), " &
|
||||
"254 (BC_7, DDR_D(29), bidir, X, 255, 1, Z), " &
|
||||
"253 (BC_1, *, control, 1), " &
|
||||
"252 (BC_7, DDR_D(28), bidir, X, 253, 1, Z), " &
|
||||
"251 (BC_1, *, control, 1), " &
|
||||
"250 (BC_7, DDR_DQS(3), bidir, X, 251, 1, Z), " &
|
||||
"249 (BC_1, *, control, 1), " &
|
||||
"248 (BC_7, DDR_D(27), bidir, X, 249, 1, Z), " &
|
||||
"247 (BC_1, *, control, 1), " &
|
||||
"246 (BC_7, DDR_D(26), bidir, X, 247, 1, Z), " &
|
||||
"245 (BC_1, *, control, 1), " &
|
||||
"244 (BC_7, DDR_D(25), bidir, X, 245, 1, Z), " &
|
||||
"243 (BC_1, *, control, 1), " &
|
||||
"242 (BC_7, DDR_D(24), bidir, X, 243, 1, Z), " &
|
||||
"241 (BC_0, *, control, 1), " &
|
||||
"240 (BC_0, DDR_DQM(3), output3, X, 241, 1, Z), " &
|
||||
"239 (BC_1, *, control, 1), " &
|
||||
"238 (BC_7, DDR_D(15), bidir, X, 239, 1, Z), " &
|
||||
"237 (BC_1, *, control, 1), " &
|
||||
"236 (BC_7, DDR_D(14), bidir, X, 237, 1, Z), " &
|
||||
"235 (BC_1, *, control, 1), " &
|
||||
"234 (BC_7, DDR_D(13), bidir, X, 235, 1, Z), " &
|
||||
"233 (BC_1, *, control, 1), " &
|
||||
"232 (BC_7, DDR_D(12), bidir, X, 233, 1, Z), " &
|
||||
"231 (BC_1, *, control, 1), " &
|
||||
"230 (BC_7, DDR_DQS(1), bidir, X, 231, 1, Z), " &
|
||||
"229 (BC_1, *, control, 1), " &
|
||||
"228 (BC_7, DDR_D(11), bidir, X, 229, 1, Z), " &
|
||||
"227 (BC_1, *, control, 1), " &
|
||||
"226 (BC_7, DDR_D(10), bidir, X, 227, 1, Z), " &
|
||||
"225 (BC_1, *, control, 1), " &
|
||||
"224 (BC_7, DDR_D(9), bidir, X, 225, 1, Z), " &
|
||||
"223 (BC_1, *, control, 1), " &
|
||||
"222 (BC_7, DDR_D(8), bidir, X, 223, 1, Z), " &
|
||||
"221 (BC_0, *, control, 1), " &
|
||||
"220 (BC_0, DDR_DQM(1), output3, X, 221, 1, Z), " &
|
||||
"219 (BC_0, *, control, 1), " &
|
||||
"218 (BC_0, DDR_BA(2), output3, X, 219, 1, Z), " &
|
||||
"217 (BC_0, *, control, 1), " &
|
||||
"216 (BC_0, DDR_BA(1), output3, X, 217, 1, Z), " &
|
||||
"215 (BC_0, *, control, 1), " &
|
||||
"214 (BC_0, DDR_BA(0), output3, X, 215, 1, Z), " &
|
||||
"213 (BC_0, *, control, 1), " &
|
||||
"212 (BC_0, DDR_CKE, output3, X, 213, 1, Z), " &
|
||||
"211 (BC_0, *, control, 1), " &
|
||||
"210 (BC_0, DDR_CS, output3, X, 211, 1, Z), " &
|
||||
"209 (BC_0, *, control, 1), " &
|
||||
"208 (BC_0, DDR_A(13), output3, X, 209, 1, Z), " &
|
||||
"207 (BC_0, *, control, 1), " &
|
||||
"206 (BC_0, DDR_RESETN, output3, X, 207, 1, Z), " &
|
||||
"205 (BC_0, *, control, 1), " &
|
||||
"204 (BC_0, DDR_A(5), output3, X, 205, 1, Z), " &
|
||||
"203 (BC_0, *, control, 1), " &
|
||||
"202 (BC_0, DDR_A(6), output3, X, 203, 1, Z), " &
|
||||
"201 (BC_0, *, control, 1), " &
|
||||
"200 (BC_0, DDR_RAS, output3, X, 201, 1, Z), " &
|
||||
"199 (BC_0, *, control, 1), " &
|
||||
"198 (BC_0, DDR_CAS, output3, X, 199, 1, Z), " &
|
||||
"197 (BC_0, *, control, 1), " &
|
||||
"196 (BC_0, DDR_WE, output3, X, 197, 1, Z), " &
|
||||
"195 (BC_0, *, control, 1), " &
|
||||
"194 (BC_0, DDR_CLK, output3, X, 195, 1, Z), " &
|
||||
"193 (BC_0, *, control, 1), " &
|
||||
"192 (BC_0, DDR_A(0), output3, X, 193, 1, Z), " &
|
||||
"191 (BC_0, *, control, 1), " &
|
||||
"190 (BC_0, DDR_A(1), output3, X, 191, 1, Z), " &
|
||||
"189 (BC_0, *, control, 1), " &
|
||||
"188 (BC_0, DDR_A(2), output3, X, 189, 1, Z), " &
|
||||
"187 (BC_0, *, control, 1), " &
|
||||
"186 (BC_0, DDR_A(3), output3, X, 187, 1, Z), " &
|
||||
"185 (BC_0, *, control, 1), " &
|
||||
"184 (BC_0, DDR_A(4), output3, X, 185, 1, Z), " &
|
||||
"183 (BC_0, *, control, 1), " &
|
||||
"182 (BC_0, DDR_A(12), output3, X, 183, 1, Z), " &
|
||||
"181 (BC_0, *, control, 1), " &
|
||||
"180 (BC_0, DDR_A(11), output3, X, 181, 1, Z), " &
|
||||
"179 (BC_0, *, control, 1), " &
|
||||
"178 (BC_0, DDR_A(10), output3, X, 179, 1, Z), " &
|
||||
"177 (BC_0, *, control, 1), " &
|
||||
"176 (BC_0, DDR_A(9), output3, X, 177, 1, Z), " &
|
||||
"175 (BC_0, *, control, 1), " &
|
||||
"174 (BC_0, DDR_A(8), output3, X, 175, 1, Z), " &
|
||||
"173 (BC_0, *, control, 1), " &
|
||||
"172 (BC_0, DDR_A(7), output3, X, 173, 1, Z), " &
|
||||
"171 (BC_1, *, control, 1), " &
|
||||
"170 (BC_7, DDR_D(7), bidir, X, 171, 1, Z), " &
|
||||
"169 (BC_1, *, control, 1), " &
|
||||
"168 (BC_7, DDR_D(6), bidir, X, 169, 1, Z), " &
|
||||
"167 (BC_1, *, control, 1), " &
|
||||
"166 (BC_7, DDR_D(5), bidir, X, 167, 1, Z), " &
|
||||
"165 (BC_1, *, control, 1), " &
|
||||
"164 (BC_7, DDR_D(4), bidir, X, 165, 1, Z), " &
|
||||
"163 (BC_1, *, control, 1), " &
|
||||
"162 (BC_7, DDR_DQS(0), bidir, X, 163, 1, Z), " &
|
||||
"161 (BC_1, *, control, 1), " &
|
||||
"160 (BC_7, DDR_D(3), bidir, X, 161, 1, Z), " &
|
||||
"159 (BC_1, *, control, 1), " &
|
||||
"158 (BC_7, DDR_D(2), bidir, X, 159, 1, Z), " &
|
||||
"157 (BC_1, *, control, 1), " &
|
||||
"156 (BC_7, DDR_D(1), bidir, X, 157, 1, Z), " &
|
||||
"155 (BC_1, *, control, 1), " &
|
||||
"154 (BC_7, DDR_D(0), bidir, X, 155, 1, Z), " &
|
||||
"153 (BC_0, *, control, 1), " &
|
||||
"152 (BC_0, DDR_DQM(0), output3, X, 153, 1, Z), " &
|
||||
"151 (BC_1, *, control, 1), " &
|
||||
"150 (BC_7, DDR_D(23), bidir, X, 151, 1, Z), " &
|
||||
"149 (BC_1, *, control, 1), " &
|
||||
"148 (BC_7, DDR_D(22), bidir, X, 149, 1, Z), " &
|
||||
"147 (BC_1, *, control, 1), " &
|
||||
"146 (BC_7, DDR_D(21), bidir, X, 147, 1, Z), " &
|
||||
"145 (BC_1, *, control, 1), " &
|
||||
"144 (BC_7, DDR_D(20), bidir, X, 145, 1, Z), " &
|
||||
"143 (BC_1, *, control, 1), " &
|
||||
"142 (BC_7, DDR_DQS(2), bidir, X, 143, 1, Z), " &
|
||||
"141 (BC_1, *, control, 1), " &
|
||||
"140 (BC_7, DDR_D(19), bidir, X, 141, 1, Z), " &
|
||||
"139 (BC_1, *, control, 1), " &
|
||||
"138 (BC_7, DDR_D(18), bidir, X, 139, 1, Z), " &
|
||||
"137 (BC_1, *, control, 1), " &
|
||||
"136 (BC_7, DDR_D(17), bidir, X, 137, 1, Z), " &
|
||||
"135 (BC_1, *, control, 1), " &
|
||||
"134 (BC_7, DDR_D(16), bidir, X, 135, 1, Z), " &
|
||||
"133 (BC_0, *, control, 1), " &
|
||||
"132 (BC_0, DDR_DQM(2), output3, X, 133, 1, Z), " &
|
||||
"131 (BC_1, *, control, 1), " &
|
||||
"130 (BC_7, PD0, bidir, X, 131, 1, Z), " &
|
||||
"129 (BC_1, *, control, 1), " &
|
||||
"128 (BC_7, PD1, bidir, X, 129, 1, Z), " &
|
||||
"127 (BC_1, *, control, 1), " &
|
||||
"126 (BC_7, PD2, bidir, X, 127, 1, Z), " &
|
||||
"125 (BC_0, *, internal, X), " &
|
||||
"124 (BC_0, *, internal, X), " &
|
||||
"123 (BC_0, *, internal, X), " &
|
||||
"122 (BC_0, *, internal, X), " &
|
||||
"121 (BC_0, *, internal, X), " &
|
||||
"120 (BC_0, *, internal, X), " &
|
||||
"119 (BC_0, *, internal, X), " &
|
||||
"118 (BC_0, *, internal, X), " &
|
||||
"117 (BC_0, *, internal, X), " &
|
||||
"116 (BC_0, *, internal, X), " &
|
||||
"115 (BC_0, *, internal, X), " &
|
||||
"114 (BC_0, *, internal, X), " &
|
||||
"113 (BC_1, *, control, 1), " &
|
||||
"112 (BC_7, PB0, bidir, X, 113, 1, Z), " &
|
||||
"111 (BC_1, *, control, 1), " &
|
||||
"110 (BC_7, PB2, bidir, X, 111, 1, Z), " &
|
||||
"109 (BC_1, *, control, 1), " &
|
||||
"108 (BC_7, PB1, bidir, X, 109, 1, Z), " &
|
||||
"107 (BC_1, *, control, 1), " &
|
||||
"106 (BC_7, PB3, bidir, X, 107, 1, Z), " &
|
||||
"105 (BC_1, *, control, 1), " &
|
||||
"104 (BC_7, PB4, bidir, X, 105, 1, Z), " &
|
||||
"103 (BC_1, *, control, 1), " &
|
||||
"102 (BC_7, PB5, bidir, X, 103, 1, Z), " &
|
||||
"101 (BC_1, *, control, 1), " &
|
||||
"100 (BC_7, PB6, bidir, X, 101, 1, Z), " &
|
||||
"99 (BC_1, *, control, 1), " &
|
||||
"98 (BC_7, PB8, bidir, X, 99, 1, Z), " &
|
||||
"97 (BC_1, *, control, 1), " &
|
||||
"96 (BC_7, PB7, bidir, X, 97, 1, Z), " &
|
||||
"95 (BC_1, *, control, 1), " &
|
||||
"94 (BC_7, PB10, bidir, X, 95, 1, Z), " &
|
||||
"93 (BC_1, *, control, 1), " &
|
||||
"92 (BC_7, PB9, bidir, X, 93, 1, Z), " &
|
||||
"91 (BC_1, *, control, 1), " &
|
||||
"90 (BC_7, PB11, bidir, X, 91, 1, Z), " &
|
||||
"89 (BC_1, *, control, 1), " &
|
||||
"88 (BC_7, PB12, bidir, X, 89, 1, Z), " &
|
||||
"87 (BC_1, *, control, 1), " &
|
||||
"86 (BC_7, PB14, bidir, X, 87, 1, Z), " &
|
||||
"85 (BC_1, *, control, 1), " &
|
||||
"84 (BC_7, PB13, bidir, X, 85, 1, Z), " &
|
||||
"83 (BC_1, *, control, 1), " &
|
||||
"82 (BC_7, PB15, bidir, X, 83, 1, Z), " &
|
||||
"81 (BC_1, *, control, 1), " &
|
||||
"80 (BC_7, PB16, bidir, X, 81, 1, Z), " &
|
||||
"79 (BC_1, *, control, 1), " &
|
||||
"78 (BC_7, PB17, bidir, X, 79, 1, Z), " &
|
||||
"77 (BC_1, *, control, 1), " &
|
||||
"76 (BC_7, PB19, bidir, X, 77, 1, Z), " &
|
||||
"75 (BC_1, *, control, 1), " &
|
||||
"74 (BC_7, PB18, bidir, X, 75, 1, Z), " &
|
||||
"73 (BC_1, *, control, 1), " &
|
||||
"72 (BC_7, PB20, bidir, X, 73, 1, Z), " &
|
||||
"71 (BC_1, *, control, 1), " &
|
||||
"70 (BC_7, PB21, bidir, X, 71, 1, Z), " &
|
||||
"69 (BC_1, *, control, 1), " &
|
||||
"68 (BC_7, PB23, bidir, X, 69, 1, Z), " &
|
||||
"67 (BC_1, *, control, 1), " &
|
||||
"66 (BC_7, PB22, bidir, X, 67, 1, Z), " &
|
||||
"65 (BC_1, *, control, 1), " &
|
||||
"64 (BC_7, PB25, bidir, X, 65, 1, Z), " &
|
||||
"63 (BC_1, *, control, 1), " &
|
||||
"62 (BC_7, PB24, bidir, X, 63, 1, Z), " &
|
||||
"61 (BC_1, *, control, 1), " &
|
||||
"60 (BC_7, PB26, bidir, X, 61, 1, Z), " &
|
||||
"59 (BC_1, *, control, 1), " &
|
||||
"58 (BC_7, PB28, bidir, X, 59, 1, Z), " &
|
||||
"57 (BC_1, *, control, 1), " &
|
||||
"56 (BC_7, PB27, bidir, X, 57, 1, Z), " &
|
||||
"55 (BC_1, *, control, 1), " &
|
||||
"54 (BC_7, PB30, bidir, X, 55, 1, Z), " &
|
||||
"53 (BC_1, *, control, 1), " &
|
||||
"52 (BC_7, PB29, bidir, X, 53, 1, Z), " &
|
||||
"51 (BC_1, *, control, 1), " &
|
||||
"50 (BC_7, PB31, bidir, X, 51, 1, Z), " &
|
||||
"49 (BC_0, *, internal, X), " &
|
||||
"48 (BC_0, *, internal, X), " &
|
||||
"47 (BC_0, *, internal, X), " &
|
||||
"46 (BC_0, *, internal, X), " &
|
||||
"45 (BC_0, *, internal, X), " &
|
||||
"44 (BC_0, *, internal, X), " &
|
||||
"43 (BC_0, *, internal, X), " &
|
||||
"42 (BC_0, *, internal, X), " &
|
||||
"41 (BC_0, *, internal, X), " &
|
||||
"40 (BC_0, *, internal, X), " &
|
||||
"39 (BC_0, *, internal, X), " &
|
||||
"38 (BC_0, *, internal, X), " &
|
||||
"37 (BC_0, *, internal, X), " &
|
||||
"36 (BC_0, *, internal, X), " &
|
||||
"35 (BC_0, *, internal, X), " &
|
||||
"34 (BC_0, *, internal, X), " &
|
||||
"33 (BC_0, *, internal, X), " &
|
||||
"32 (BC_0, *, internal, X), " &
|
||||
"31 (BC_0, *, internal, X), " &
|
||||
"30 (BC_0, *, internal, X), " &
|
||||
"29 (BC_0, *, internal, X), " &
|
||||
"28 (BC_0, *, internal, X), " &
|
||||
"27 (BC_0, *, internal, X), " &
|
||||
"26 (BC_0, *, internal, X), " &
|
||||
"25 (BC_0, *, internal, X), " &
|
||||
"24 (BC_0, *, internal, X), " &
|
||||
"23 (BC_0, *, internal, X), " &
|
||||
"22 (BC_0, *, internal, X), " &
|
||||
"21 (BC_0, *, internal, X), " &
|
||||
"20 (BC_0, *, internal, X), " &
|
||||
"19 (BC_0, *, internal, X), " &
|
||||
"18 (BC_0, *, internal, X), " &
|
||||
"17 (BC_0, *, internal, X), " &
|
||||
"16 (BC_0, *, internal, X), " &
|
||||
"15 (BC_1, *, control, 1), " &
|
||||
"14 (BC_7, PD10, bidir, X, 15, 1, Z), " &
|
||||
"13 (BC_1, *, control, 1), " &
|
||||
"12 (BC_7, PD9, bidir, X, 13, 1, Z), " &
|
||||
"11 (BC_1, *, control, 1), " &
|
||||
"10 (BC_7, PD8, bidir, X, 11, 1, Z), " &
|
||||
"9 (BC_1, *, control, 1), " &
|
||||
"8 (BC_7, PD7, bidir, X, 9, 1, Z), " &
|
||||
"7 (BC_1, *, control, 1), " &
|
||||
"6 (BC_7, PD6, bidir, X, 7, 1, Z), " &
|
||||
"5 (BC_1, *, control, 1), " &
|
||||
"4 (BC_7, PD5, bidir, X, 5, 1, Z), " &
|
||||
"3 (BC_1, *, control, 1), " &
|
||||
"2 (BC_7, PD4, bidir, X, 3, 1, Z), " &
|
||||
"1 (BC_1, *, control, 1), " &
|
||||
"0 (BC_7, PD3, bidir, X, 1, 1, Z) ";
|
||||
|
||||
end top;
|
|
@ -0,0 +1,865 @@
|
|||
-- *****************************************************************************
|
||||
|
||||
-- BSDL file for design top
|
||||
|
||||
-- Created by Synopsys Version I-2013.12-SP3 (Apr 18, 2014)
|
||||
|
||||
-- Designer:
|
||||
-- Company:
|
||||
|
||||
-- Date: Thu Feb 5 23:41:59 2015
|
||||
|
||||
-- *****************************************************************************
|
||||
|
||||
|
||||
entity top is
|
||||
|
||||
-- This section identifies the default device package selected.
|
||||
|
||||
generic (PHYSICAL_PIN_MAP: string:= "BGA289");
|
||||
|
||||
-- This section declares all the ports in the design.
|
||||
|
||||
port (
|
||||
PD14 : in bit;
|
||||
PD15 : in bit;
|
||||
PD17 : in bit;
|
||||
PD18 : in bit;
|
||||
PA0 : inout bit;
|
||||
PA1 : inout bit;
|
||||
PA10 : inout bit;
|
||||
PA11 : inout bit;
|
||||
PA12 : inout bit;
|
||||
PA13 : inout bit;
|
||||
PA14 : inout bit;
|
||||
PA15 : inout bit;
|
||||
PA16 : inout bit;
|
||||
PA17 : inout bit;
|
||||
PA18 : inout bit;
|
||||
PA19 : inout bit;
|
||||
PA2 : inout bit;
|
||||
PA20 : inout bit;
|
||||
PA21 : inout bit;
|
||||
PA22 : inout bit;
|
||||
PA23 : inout bit;
|
||||
PA24 : inout bit;
|
||||
PA25 : inout bit;
|
||||
PA26 : inout bit;
|
||||
PA27 : inout bit;
|
||||
PA28 : inout bit;
|
||||
PA29 : inout bit;
|
||||
PA3 : inout bit;
|
||||
PA30 : inout bit;
|
||||
PA31 : inout bit;
|
||||
PA4 : inout bit;
|
||||
PA5 : inout bit;
|
||||
PA6 : inout bit;
|
||||
PA7 : inout bit;
|
||||
PA8 : inout bit;
|
||||
PA9 : inout bit;
|
||||
PB0 : inout bit;
|
||||
PB1 : inout bit;
|
||||
PB10 : inout bit;
|
||||
PB11 : inout bit;
|
||||
PB12 : inout bit;
|
||||
PB13 : inout bit;
|
||||
PB14 : inout bit;
|
||||
PB15 : inout bit;
|
||||
PB16 : inout bit;
|
||||
PB17 : inout bit;
|
||||
PB18 : inout bit;
|
||||
PB19 : inout bit;
|
||||
PB2 : inout bit;
|
||||
PB20 : inout bit;
|
||||
PB21 : inout bit;
|
||||
PB22 : inout bit;
|
||||
PB23 : inout bit;
|
||||
PB24 : inout bit;
|
||||
PB25 : inout bit;
|
||||
PB26 : inout bit;
|
||||
PB27 : inout bit;
|
||||
PB28 : inout bit;
|
||||
PB29 : inout bit;
|
||||
PB3 : inout bit;
|
||||
PB30 : inout bit;
|
||||
PB31 : inout bit;
|
||||
PB4 : inout bit;
|
||||
PB5 : inout bit;
|
||||
PB6 : inout bit;
|
||||
PB7 : inout bit;
|
||||
PB8 : inout bit;
|
||||
PB9 : inout bit;
|
||||
PC0 : inout bit;
|
||||
PC1 : inout bit;
|
||||
PC10 : inout bit;
|
||||
PC11 : inout bit;
|
||||
PC12 : inout bit;
|
||||
PC13 : inout bit;
|
||||
PC14 : inout bit;
|
||||
PC15 : inout bit;
|
||||
PC16 : inout bit;
|
||||
PC17 : inout bit;
|
||||
PC18 : inout bit;
|
||||
PC19 : inout bit;
|
||||
PC2 : inout bit;
|
||||
PC20 : inout bit;
|
||||
PC21 : inout bit;
|
||||
PC22 : inout bit;
|
||||
PC23 : inout bit;
|
||||
PC24 : inout bit;
|
||||
PC25 : inout bit;
|
||||
PC26 : inout bit;
|
||||
PC27 : inout bit;
|
||||
PC28 : inout bit;
|
||||
PC29 : inout bit;
|
||||
PC3 : inout bit;
|
||||
PC30 : inout bit;
|
||||
PC31 : inout bit;
|
||||
PC4 : inout bit;
|
||||
PC5 : inout bit;
|
||||
PC6 : inout bit;
|
||||
PC7 : inout bit;
|
||||
PC8 : inout bit;
|
||||
PC9 : inout bit;
|
||||
PD0 : inout bit;
|
||||
PD1 : inout bit;
|
||||
PD10 : inout bit;
|
||||
PD11 : inout bit;
|
||||
PD12 : inout bit;
|
||||
PD13 : inout bit;
|
||||
PD19 : inout bit;
|
||||
PD2 : inout bit;
|
||||
PD20 : inout bit;
|
||||
PD21 : inout bit;
|
||||
PD22 : inout bit;
|
||||
PD23 : inout bit;
|
||||
PD24 : inout bit;
|
||||
PD25 : inout bit;
|
||||
PD26 : inout bit;
|
||||
PD27 : inout bit;
|
||||
PD28 : inout bit;
|
||||
PD29 : inout bit;
|
||||
PD3 : inout bit;
|
||||
PD30 : inout bit;
|
||||
PD31 : inout bit;
|
||||
PD4 : inout bit;
|
||||
PD5 : inout bit;
|
||||
PD6 : inout bit;
|
||||
PD7 : inout bit;
|
||||
PD8 : inout bit;
|
||||
PD9 : inout bit;
|
||||
DDR_D : inout bit_vector (0 to 31);
|
||||
DDR_DQS : inout bit_vector (0 to 3);
|
||||
DDR_DQSN : inout bit_vector (0 to 3);
|
||||
DDR_CAS : out bit;
|
||||
DDR_CKE : out bit;
|
||||
DDR_CLK : out bit;
|
||||
DDR_CLKN : out bit;
|
||||
DDR_CS : out bit;
|
||||
DDR_RAS : out bit;
|
||||
DDR_RESETN : out bit;
|
||||
DDR_WE : out bit;
|
||||
PD16 : out bit;
|
||||
DDR_A : out bit_vector (0 to 13);
|
||||
DDR_BA : out bit_vector (0 to 2);
|
||||
DDR_DQM : out bit_vector (0 to 3);
|
||||
-- ADVREFN : linkage bit;
|
||||
ADVREFP : linkage bit;
|
||||
CLK_AUDIO : linkage bit;
|
||||
COMPN : linkage bit;
|
||||
COMPP : linkage bit;
|
||||
DDR_CAL : linkage bit;
|
||||
DDR_VREF : linkage bit; -- DDR_VREFB0 : linkage bit;
|
||||
-- DDR_VREFB1 : linkage bit;
|
||||
-- DDR_VREFB2 : linkage bit;
|
||||
-- DDR_VREFB3 : linkage bit;
|
||||
-- DDR_VREFCM : linkage bit;
|
||||
HHSDMA : linkage bit;
|
||||
HHSDMB : linkage bit;
|
||||
HHSDMSTRC : linkage bit;
|
||||
HHSDPA : linkage bit;
|
||||
HHSDPB : linkage bit;
|
||||
HHSDPDATC : linkage bit;
|
||||
JTAGSEL : in bit;
|
||||
NRST : linkage bit;
|
||||
RXD : linkage bit;
|
||||
SDCAL : linkage bit;
|
||||
SHDN : linkage bit;
|
||||
TST : in bit;
|
||||
VBG : linkage bit;
|
||||
WKUP : linkage bit;
|
||||
XIN : linkage bit;
|
||||
XIN32 : linkage bit;
|
||||
XOUT : linkage bit;
|
||||
XOUT32 : linkage bit;
|
||||
-- tst_drst_ana : linkage bit; -- NC Port
|
||||
-- tst_drst_ddr : linkage bit; -- NC Port
|
||||
-- tst_drst_iop0 : linkage bit; -- NC Port
|
||||
-- tst_drst_iop1 : linkage bit; -- NC Port
|
||||
-- tst_drst_iop2 : linkage bit; -- NC Port
|
||||
-- tst_drst_isi : linkage bit; -- NC Port
|
||||
-- tst_drst_osc : linkage bit; -- NC Port
|
||||
-- tst_drst_sdhc : linkage bit; -- NC Port
|
||||
-- tst_lft_plla : linkage bit; -- NC Port
|
||||
-- tst_lft_utmi : linkage bit; -- NC Port
|
||||
-- tst_por_1v2 : linkage bit; -- NC Port
|
||||
-- tst_por_1v8 : linkage bit; -- NC Port
|
||||
-- tst_por_bu : linkage bit; -- NC Port
|
||||
-- tst_psw_bu : linkage bit; -- NC Port
|
||||
-- tst_psw_fuse : linkage bit; -- NC Port
|
||||
PIOBU : linkage bit_vector (0 to 7)
|
||||
);
|
||||
|
||||
use STD_1149_1_1994.all;
|
||||
|
||||
attribute COMPONENT_CONFORMANCE of top: entity is "STD_1149_1_1993";
|
||||
|
||||
attribute PIN_MAP of top: entity is PHYSICAL_PIN_MAP;
|
||||
|
||||
-- This section specifies the pin map for each port. This information is
|
||||
-- extracted from the port-to-pin map file that was read in using the
|
||||
-- "read_pin_map" command.
|
||||
|
||||
constant BGA289: PIN_MAP_STRING :=
|
||||
"PD14 : K4," &
|
||||
"PD15 : K7," &
|
||||
"PD17 : K2," &
|
||||
"PD18 : J5," &
|
||||
"PA0 : U11," &
|
||||
"PA1 : P10," &
|
||||
"PA10 : U13," &
|
||||
"PA11 : P15," &
|
||||
"PA12 : N15," &
|
||||
"PA13 : P16," &
|
||||
"PA14 : M14," &
|
||||
"PA15 : N16," &
|
||||
"PA16 : M10," &
|
||||
"PA17 : N17," &
|
||||
"PA18 : U14," &
|
||||
"PA19 : T14," &
|
||||
"PA2 : T11," &
|
||||
"PA20 : P12," &
|
||||
"PA21 : R13," &
|
||||
"PA22 : U15," &
|
||||
"PA23 : U16," &
|
||||
"PA24 : T15," &
|
||||
"PA25 : U17," &
|
||||
"PA26 : P13," &
|
||||
"PA27 : T16," &
|
||||
"PA28 : R16," &
|
||||
"PA29 : T17," &
|
||||
"PA3 : R10," &
|
||||
"PA30 : R15," &
|
||||
"PA31 : R17," &
|
||||
"PA4 : U12," &
|
||||
"PA5 : T12," &
|
||||
"PA6 : R12," &
|
||||
"PA7 : T13," &
|
||||
"PA8 : N10," &
|
||||
"PA9 : N11," &
|
||||
"PB0 : J8," &
|
||||
"PB1 : A8," &
|
||||
"PB10 : H8," &
|
||||
"PB11 : B5," &
|
||||
"PB12 : D6," &
|
||||
"PB13 : B4," &
|
||||
"PB14 : C5," &
|
||||
"PB15 : H7," &
|
||||
"PB16 : D5," &
|
||||
"PB17 : C4," &
|
||||
"PB18 : A3," &
|
||||
"PB19 : D4," &
|
||||
"PB2 : A7," &
|
||||
"PB20 : B3," &
|
||||
"PB21 : A2," &
|
||||
"PB22 : C3," &
|
||||
"PB23 : A1," &
|
||||
"PB24 : E5," &
|
||||
"PB25 : B2," &
|
||||
"PB26 : E4," &
|
||||
"PB27 : B1," &
|
||||
"PB28 : C2," &
|
||||
"PB29 : D3," &
|
||||
"PB3 : A6," &
|
||||
"PB30 : D2," &
|
||||
"PB31 : C1," &
|
||||
"PB4 : B6," &
|
||||
"PB5 : B7," &
|
||||
"PB6 : C7," &
|
||||
"PB7 : C6," &
|
||||
"PB8 : A5," &
|
||||
"PB9 : A4," &
|
||||
"PC0 : P17," &
|
||||
"PC1 : N12," &
|
||||
"PC10 : E3," &
|
||||
"PC11 : E2," &
|
||||
"PC12 : E1," &
|
||||
"PC13 : F3," &
|
||||
"PC14 : F5," &
|
||||
"PC15 : F2," &
|
||||
"PC16 : G6," &
|
||||
"PC17 : F1," &
|
||||
"PC18 : H6," &
|
||||
"PC19 : G2," &
|
||||
"PC2 : N14," &
|
||||
"PC20 : G3," &
|
||||
"PC21 : G1," &
|
||||
"PC22 : H2," &
|
||||
"PC23 : G5," &
|
||||
"PC24 : H1," &
|
||||
"PC25 : H5," &
|
||||
"PC26 : J9," &
|
||||
"PC27 : H9," &
|
||||
"PC28 : E8," &
|
||||
"PC29 : G8," &
|
||||
"PC3 : M15," &
|
||||
"PC30 : F8," &
|
||||
"PC31 : D8," &
|
||||
"PC4 : M11," &
|
||||
"PC5 : L10," &
|
||||
"PC6 : K10," &
|
||||
"PC7 : M16," &
|
||||
"PC8 : J10," &
|
||||
"PC9 : D1," &
|
||||
"PD0 : G10," &
|
||||
"PD1 : E10," &
|
||||
"PD10 : J3," &
|
||||
"PD11 : M1," &
|
||||
"PD12 : K8," &
|
||||
"PD13 : L2," &
|
||||
"PD19 : K6," &
|
||||
"PD2 : G9," &
|
||||
"PD20 : M2," &
|
||||
"PD21 : N1," &
|
||||
"PD22 : L4," &
|
||||
"PD23 : M3," &
|
||||
"PD24 : L7," &
|
||||
"PD25 : L6," &
|
||||
"PD26 : N2," &
|
||||
"PD27 : L8," &
|
||||
"PD28 : M4," &
|
||||
"PD29 : N3," &
|
||||
"PD3 : K1," &
|
||||
"PD30 : L9," &
|
||||
"PD31 : M7," &
|
||||
"PD4 : J6," &
|
||||
"PD5 : J4," &
|
||||
"PD6 : J2," &
|
||||
"PD7 : J7," &
|
||||
"PD8 : J1," &
|
||||
"PD9 : K9," &
|
||||
"DDR_D : (B12, A12, C12, A13, A14, C13, A15, B15, G17, G16, " &
|
||||
"H17, K17, K16, J13, K14, K15, B8, B9, C9, A9, A10, D10, B11, A11, " &
|
||||
"J12, H10, J11, K11, L13, L11, L12, M17)," &
|
||||
"DDR_DQS : (B13, J17, C10, L17)," &
|
||||
"DDR_DQSN : (B14, J16, B10, L16)," &
|
||||
"DDR_CAS : G12," &
|
||||
"DDR_CKE : F16," &
|
||||
"DDR_CLK : E17," &
|
||||
"DDR_CLKN : D17," &
|
||||
"DDR_CS : G13," &
|
||||
"DDR_RAS : F13," &
|
||||
"DDR_RESETN : E16," &
|
||||
"DDR_WE : F15," &
|
||||
"PD16 : L1," &
|
||||
"DDR_A : (F12, C17, B17, B16, C16, G14, F14, F11, C14, D13, " &
|
||||
"C15, A16, A17, G11)," &
|
||||
"DDR_BA : (H12, H13, F17)," &
|
||||
"DDR_DQM : (C11, G15, C8, H11)," &
|
||||
"ADVREFP : M6," &
|
||||
"CLK_AUDIO : U3," &
|
||||
"COMPN : U1," &
|
||||
"COMPP : T1," &
|
||||
"DDR_CAL : E13," &
|
||||
"HHSDMA : R8," &
|
||||
"HHSDMB : U9," &
|
||||
"HHSDMSTRC : U10," &
|
||||
"HHSDPA : T8," &
|
||||
"HHSDPB : U8," &
|
||||
"HHSDPDATC : T9," &
|
||||
"JTAGSEL : T2," &
|
||||
"NRST : U2," &
|
||||
"RXD : N4," &
|
||||
"SDCAL : T10," &
|
||||
"SHDN : R1," &
|
||||
"TST : P3," &
|
||||
"VBG : R6," &
|
||||
"WKUP : P4," &
|
||||
"XIN : U7," &
|
||||
"XIN32 : P1," &
|
||||
"XOUT : U6," &
|
||||
"XOUT32 : P2," &
|
||||
"PIOBU : (R3, N8, R2, R5, R4, P5, P6, M8)";
|
||||
|
||||
-- This section specifies the differential IO port groupings.
|
||||
|
||||
attribute PORT_GROUPING of top: entity is
|
||||
"Differential_Voltage ( " &
|
||||
"(DDR_CLK,DDR_CLKN))";
|
||||
|
||||
-- This section specifies the TAP ports. For the TAP TCK port, the parameters in
|
||||
-- the brackets are:
|
||||
-- First Field : Maximum TCK frequency.
|
||||
-- Second Field: Allowable states TCK may be stopped in.
|
||||
|
||||
attribute TAP_SCAN_CLOCK of PD14: signal is (10.0e6, BOTH);
|
||||
attribute TAP_SCAN_IN of PD15: signal is true;
|
||||
attribute TAP_SCAN_MODE of PD17: signal is true;
|
||||
attribute TAP_SCAN_OUT of PD16: signal is true;
|
||||
attribute TAP_SCAN_RESET of PD18: signal is true;
|
||||
|
||||
-- Specifies the compliance enable patterns for the design. It lists a set of
|
||||
-- design ports and the values that they should be set to, in order to enable
|
||||
-- compliance to IEEE Std 1149.1
|
||||
|
||||
attribute COMPLIANCE_PATTERNS of top: entity is
|
||||
"(JTAGSEL, TST) (10)";
|
||||
|
||||
-- Specifies the number of bits in the instruction register.
|
||||
|
||||
attribute INSTRUCTION_LENGTH of top: entity is 4;
|
||||
|
||||
-- Specifies the boundary-scan instructions implemented in the design and their
|
||||
-- opcodes.
|
||||
|
||||
attribute INSTRUCTION_OPCODE of top: entity is
|
||||
"BYPASS (1111, 0001, 0101, 0110, 1100, 0111, 1101, 1000, 1001, 1011, " &
|
||||
"1110)," &
|
||||
"EXTEST (0000)," &
|
||||
"SAMPLE (0100)," &
|
||||
"INTEST (0010)," &
|
||||
"IDCODE (0011)," &
|
||||
"RUNBIST (1010)";
|
||||
|
||||
-- Specifies the bit pattern that is loaded into the instruction register when
|
||||
-- the TAP controller passes through the Capture-IR state. The standard mandates
|
||||
-- that the two LSBs must be "01". The remaining bits are design specific.
|
||||
|
||||
attribute INSTRUCTION_CAPTURE of top: entity is "0001";
|
||||
|
||||
-- Specifies the bit pattern that is loaded into the DEVICE_ID register during
|
||||
-- the IDCODE instruction when the TAP controller passes through the Capture-DR
|
||||
-- state.
|
||||
|
||||
attribute IDCODE_REGISTER of top: entity is
|
||||
"0000" &
|
||||
-- 4-bit version number
|
||||
"0101101100111111" &
|
||||
-- 16-bit part number
|
||||
"00000011111" &
|
||||
-- 11-bit identity of the manufacturer
|
||||
"1";
|
||||
-- Required by IEEE Std 1149.1
|
||||
|
||||
-- This section specifies the test data register placed between TDI and TDO for
|
||||
-- each implemented instruction.
|
||||
|
||||
attribute REGISTER_ACCESS of top: entity is
|
||||
"BYPASS (BYPASS)," &
|
||||
"BOUNDARY (EXTEST, SAMPLE, INTEST)," &
|
||||
"DEVICE_ID (IDCODE)," &
|
||||
"UTDR1[41] (RUNBIST)";
|
||||
|
||||
-- Specifies the length of the boundary scan register.
|
||||
|
||||
attribute BOUNDARY_LENGTH of top: entity is 374;
|
||||
|
||||
-- The following list specifies the characteristics of each cell in the boundary
|
||||
-- scan register from TDI to TDO. The following is a description of the label
|
||||
-- fields:
|
||||
-- num : Is the cell number.
|
||||
-- cell : Is the cell type as defined by the standard.
|
||||
-- port : Is the design port name. Control cells do not have a port
|
||||
-- name.
|
||||
-- function: Is the function of the cell as defined by the standard. Is one
|
||||
-- of input, output2, output3, bidir, control or controlr.
|
||||
-- safe : Specifies the value that the BSR cell should be loaded with
|
||||
-- for safe operation when the software might otherwise choose a
|
||||
-- random value.
|
||||
-- ccell : The control cell number. Specifies the control cell that
|
||||
-- drives the output enable for this port.
|
||||
-- disval : Specifies the value that is loaded into the control cell to
|
||||
-- disable the output enable for the corresponding port.
|
||||
-- rslt : Resulting state. Shows the state of the driver when it is
|
||||
-- disabled.
|
||||
|
||||
attribute BOUNDARY_REGISTER of top: entity is
|
||||
--
|
||||
-- num cell port function safe [ccell disval rslt]
|
||||
--
|
||||
"373 (BC_1, *, control, 1), " &
|
||||
"372 (BC_7, PD13, bidir, X, 373, 1, Z), " &
|
||||
"371 (BC_1, *, control, 1), " &
|
||||
"370 (BC_7, PD12, bidir, X, 371, 1, Z), " &
|
||||
"369 (BC_1, *, control, 1), " &
|
||||
"368 (BC_7, PD11, bidir, X, 369, 1, Z), " &
|
||||
"367 (BC_1, *, control, 1), " &
|
||||
"366 (BC_7, PD19, bidir, X, 367, 1, Z), " &
|
||||
"365 (BC_1, *, control, 1), " &
|
||||
"364 (BC_7, PD20, bidir, X, 365, 1, Z), " &
|
||||
"363 (BC_1, *, control, 1), " &
|
||||
"362 (BC_7, PD24, bidir, X, 363, 1, Z), " &
|
||||
"361 (BC_1, *, control, 1), " &
|
||||
"360 (BC_7, PD21, bidir, X, 361, 1, Z), " &
|
||||
"359 (BC_1, *, control, 1), " &
|
||||
"358 (BC_7, PD25, bidir, X, 359, 1, Z), " &
|
||||
"357 (BC_1, *, control, 1), " &
|
||||
"356 (BC_7, PD26, bidir, X, 357, 1, Z), " &
|
||||
"355 (BC_1, *, control, 1), " &
|
||||
"354 (BC_7, PD22, bidir, X, 355, 1, Z), " &
|
||||
"353 (BC_1, *, control, 1), " &
|
||||
"352 (BC_7, PD27, bidir, X, 353, 1, Z), " &
|
||||
"351 (BC_1, *, control, 1), " &
|
||||
"350 (BC_7, PD23, bidir, X, 351, 1, Z), " &
|
||||
"349 (BC_1, *, control, 1), " &
|
||||
"348 (BC_7, PD28, bidir, X, 349, 1, Z), " &
|
||||
"347 (BC_1, *, control, 1), " &
|
||||
"346 (BC_7, PD30, bidir, X, 347, 1, Z), " &
|
||||
"345 (BC_1, *, control, 1), " &
|
||||
"344 (BC_7, PD29, bidir, X, 345, 1, Z), " &
|
||||
"343 (BC_1, *, control, 1), " &
|
||||
"342 (BC_7, PD31, bidir, X, 343, 1, Z), " &
|
||||
"341 (BC_1, *, control, 1), " &
|
||||
"340 (BC_7, PA0, bidir, X, 341, 1, Z), " &
|
||||
"339 (BC_1, *, control, 1), " &
|
||||
"338 (BC_7, PA1, bidir, X, 339, 1, Z), " &
|
||||
"337 (BC_1, *, control, 1), " &
|
||||
"336 (BC_7, PA2, bidir, X, 337, 1, Z), " &
|
||||
"335 (BC_1, *, control, 1), " &
|
||||
"334 (BC_7, PA3, bidir, X, 335, 1, Z), " &
|
||||
"333 (BC_1, *, control, 1), " &
|
||||
"332 (BC_7, PA4, bidir, X, 333, 1, Z), " &
|
||||
"331 (BC_1, *, control, 1), " &
|
||||
"330 (BC_7, PA5, bidir, X, 331, 1, Z), " &
|
||||
"329 (BC_1, *, control, 1), " &
|
||||
"328 (BC_7, PA6, bidir, X, 329, 1, Z), " &
|
||||
"327 (BC_1, *, control, 1), " &
|
||||
"326 (BC_7, PA7, bidir, X, 327, 1, Z), " &
|
||||
"325 (BC_1, *, control, 1), " &
|
||||
"324 (BC_7, PA8, bidir, X, 325, 1, Z), " &
|
||||
"323 (BC_1, *, control, 1), " &
|
||||
"322 (BC_7, PA9, bidir, X, 323, 1, Z), " &
|
||||
"321 (BC_1, *, control, 1), " &
|
||||
"320 (BC_7, PA10, bidir, X, 321, 1, Z), " &
|
||||
"319 (BC_1, *, control, 1), " &
|
||||
"318 (BC_7, PA18, bidir, X, 319, 1, Z), " &
|
||||
"317 (BC_1, *, control, 1), " &
|
||||
"316 (BC_7, PA20, bidir, X, 317, 1, Z), " &
|
||||
"315 (BC_1, *, control, 1), " &
|
||||
"314 (BC_7, PA19, bidir, X, 315, 1, Z), " &
|
||||
"313 (BC_1, *, control, 1), " &
|
||||
"312 (BC_7, PA21, bidir, X, 313, 1, Z), " &
|
||||
"311 (BC_1, *, control, 1), " &
|
||||
"310 (BC_7, PA22, bidir, X, 311, 1, Z), " &
|
||||
"309 (BC_1, *, control, 1), " &
|
||||
"308 (BC_7, PA23, bidir, X, 309, 1, Z), " &
|
||||
"307 (BC_1, *, control, 1), " &
|
||||
"306 (BC_7, PA24, bidir, X, 307, 1, Z), " &
|
||||
"305 (BC_1, *, control, 1), " &
|
||||
"304 (BC_7, PA25, bidir, X, 305, 1, Z), " &
|
||||
"303 (BC_1, *, control, 1), " &
|
||||
"302 (BC_7, PA26, bidir, X, 303, 1, Z), " &
|
||||
"301 (BC_1, *, control, 1), " &
|
||||
"300 (BC_7, PA27, bidir, X, 301, 1, Z), " &
|
||||
"299 (BC_1, *, control, 1), " &
|
||||
"298 (BC_7, PA28, bidir, X, 299, 1, Z), " &
|
||||
"297 (BC_1, *, control, 1), " &
|
||||
"296 (BC_7, PA30, bidir, X, 297, 1, Z), " &
|
||||
"295 (BC_1, *, control, 1), " &
|
||||
"294 (BC_7, PA29, bidir, X, 295, 1, Z), " &
|
||||
"293 (BC_1, *, control, 1), " &
|
||||
"292 (BC_7, PA31, bidir, X, 293, 1, Z), " &
|
||||
"291 (BC_1, *, control, 1), " &
|
||||
"290 (BC_7, PC0, bidir, X, 291, 1, Z), " &
|
||||
"289 (BC_1, *, control, 1), " &
|
||||
"288 (BC_7, PA11, bidir, X, 289, 1, Z), " &
|
||||
"287 (BC_1, *, control, 1), " &
|
||||
"286 (BC_7, PC1, bidir, X, 287, 1, Z), " &
|
||||
"285 (BC_1, *, control, 1), " &
|
||||
"284 (BC_7, PA13, bidir, X, 285, 1, Z), " &
|
||||
"283 (BC_1, *, control, 1), " &
|
||||
"282 (BC_7, PA12, bidir, X, 283, 1, Z), " &
|
||||
"281 (BC_1, *, control, 1), " &
|
||||
"280 (BC_7, PC2, bidir, X, 281, 1, Z), " &
|
||||
"279 (BC_1, *, control, 1), " &
|
||||
"278 (BC_7, PA14, bidir, X, 279, 1, Z), " &
|
||||
"277 (BC_1, *, control, 1), " &
|
||||
"276 (BC_7, PA15, bidir, X, 277, 1, Z), " &
|
||||
"275 (BC_1, *, control, 1), " &
|
||||
"274 (BC_7, PC3, bidir, X, 275, 1, Z), " &
|
||||
"273 (BC_1, *, control, 1), " &
|
||||
"272 (BC_7, PC4, bidir, X, 273, 1, Z), " &
|
||||
"271 (BC_1, *, control, 1), " &
|
||||
"270 (BC_7, PA16, bidir, X, 271, 1, Z), " &
|
||||
"269 (BC_1, *, control, 1), " &
|
||||
"268 (BC_7, PA17, bidir, X, 269, 1, Z), " &
|
||||
"267 (BC_1, *, control, 1), " &
|
||||
"266 (BC_7, PC5, bidir, X, 267, 1, Z), " &
|
||||
"265 (BC_1, *, control, 1), " &
|
||||
"264 (BC_7, PC7, bidir, X, 265, 1, Z), " &
|
||||
"263 (BC_1, *, control, 1), " &
|
||||
"262 (BC_7, PC6, bidir, X, 263, 1, Z), " &
|
||||
"261 (BC_1, *, control, 1), " &
|
||||
"260 (BC_7, PC8, bidir, X, 261, 1, Z), " &
|
||||
"259 (BC_1, *, control, 1), " &
|
||||
"258 (BC_7, DDR_D(31), bidir, X, 259, 1, Z), " &
|
||||
"257 (BC_1, *, control, 1), " &
|
||||
"256 (BC_7, DDR_D(30), bidir, X, 257, 1, Z), " &
|
||||
"255 (BC_1, *, control, 1), " &
|
||||
"254 (BC_7, DDR_D(29), bidir, X, 255, 1, Z), " &
|
||||
"253 (BC_1, *, control, 1), " &
|
||||
"252 (BC_7, DDR_D(28), bidir, X, 253, 1, Z), " &
|
||||
"251 (BC_1, *, control, 1), " &
|
||||
"250 (BC_7, DDR_DQS(3), bidir, X, 251, 1, Z), " &
|
||||
"249 (BC_1, *, control, 1), " &
|
||||
"248 (BC_7, DDR_D(27), bidir, X, 249, 1, Z), " &
|
||||
"247 (BC_1, *, control, 1), " &
|
||||
"246 (BC_7, DDR_D(26), bidir, X, 247, 1, Z), " &
|
||||
"245 (BC_1, *, control, 1), " &
|
||||
"244 (BC_7, DDR_D(25), bidir, X, 245, 1, Z), " &
|
||||
"243 (BC_1, *, control, 1), " &
|
||||
"242 (BC_7, DDR_D(24), bidir, X, 243, 1, Z), " &
|
||||
"241 (BC_0, *, control, 1), " &
|
||||
"240 (BC_0, DDR_DQM(3), output3, X, 241, 1, Z), " &
|
||||
"239 (BC_1, *, control, 1), " &
|
||||
"238 (BC_7, DDR_D(15), bidir, X, 239, 1, Z), " &
|
||||
"237 (BC_1, *, control, 1), " &
|
||||
"236 (BC_7, DDR_D(14), bidir, X, 237, 1, Z), " &
|
||||
"235 (BC_1, *, control, 1), " &
|
||||
"234 (BC_7, DDR_D(13), bidir, X, 235, 1, Z), " &
|
||||
"233 (BC_1, *, control, 1), " &
|
||||
"232 (BC_7, DDR_D(12), bidir, X, 233, 1, Z), " &
|
||||
"231 (BC_1, *, control, 1), " &
|
||||
"230 (BC_7, DDR_DQS(1), bidir, X, 231, 1, Z), " &
|
||||
"229 (BC_1, *, control, 1), " &
|
||||
"228 (BC_7, DDR_D(11), bidir, X, 229, 1, Z), " &
|
||||
"227 (BC_1, *, control, 1), " &
|
||||
"226 (BC_7, DDR_D(10), bidir, X, 227, 1, Z), " &
|
||||
"225 (BC_1, *, control, 1), " &
|
||||
"224 (BC_7, DDR_D(9), bidir, X, 225, 1, Z), " &
|
||||
"223 (BC_1, *, control, 1), " &
|
||||
"222 (BC_7, DDR_D(8), bidir, X, 223, 1, Z), " &
|
||||
"221 (BC_0, *, control, 1), " &
|
||||
"220 (BC_0, DDR_DQM(1), output3, X, 221, 1, Z), " &
|
||||
"219 (BC_0, *, control, 1), " &
|
||||
"218 (BC_0, DDR_BA(2), output3, X, 219, 1, Z), " &
|
||||
"217 (BC_0, *, control, 1), " &
|
||||
"216 (BC_0, DDR_BA(1), output3, X, 217, 1, Z), " &
|
||||
"215 (BC_0, *, control, 1), " &
|
||||
"214 (BC_0, DDR_BA(0), output3, X, 215, 1, Z), " &
|
||||
"213 (BC_0, *, control, 1), " &
|
||||
"212 (BC_0, DDR_CKE, output3, X, 213, 1, Z), " &
|
||||
"211 (BC_0, *, control, 1), " &
|
||||
"210 (BC_0, DDR_CS, output3, X, 211, 1, Z), " &
|
||||
"209 (BC_0, *, control, 1), " &
|
||||
"208 (BC_0, DDR_A(13), output3, X, 209, 1, Z), " &
|
||||
"207 (BC_0, *, control, 1), " &
|
||||
"206 (BC_0, DDR_RESETN, output3, X, 207, 1, Z), " &
|
||||
"205 (BC_0, *, control, 1), " &
|
||||
"204 (BC_0, DDR_A(5), output3, X, 205, 1, Z), " &
|
||||
"203 (BC_0, *, control, 1), " &
|
||||
"202 (BC_0, DDR_A(6), output3, X, 203, 1, Z), " &
|
||||
"201 (BC_0, *, control, 1), " &
|
||||
"200 (BC_0, DDR_RAS, output3, X, 201, 1, Z), " &
|
||||
"199 (BC_0, *, control, 1), " &
|
||||
"198 (BC_0, DDR_CAS, output3, X, 199, 1, Z), " &
|
||||
"197 (BC_0, *, control, 1), " &
|
||||
"196 (BC_0, DDR_WE, output3, X, 197, 1, Z), " &
|
||||
"195 (BC_0, *, control, 1), " &
|
||||
"194 (BC_0, DDR_CLK, output3, X, 195, 1, Z), " &
|
||||
"193 (BC_0, *, control, 1), " &
|
||||
"192 (BC_0, DDR_A(0), output3, X, 193, 1, Z), " &
|
||||
"191 (BC_0, *, control, 1), " &
|
||||
"190 (BC_0, DDR_A(1), output3, X, 191, 1, Z), " &
|
||||
"189 (BC_0, *, control, 1), " &
|
||||
"188 (BC_0, DDR_A(2), output3, X, 189, 1, Z), " &
|
||||
"187 (BC_0, *, control, 1), " &
|
||||
"186 (BC_0, DDR_A(3), output3, X, 187, 1, Z), " &
|
||||
"185 (BC_0, *, control, 1), " &
|
||||
"184 (BC_0, DDR_A(4), output3, X, 185, 1, Z), " &
|
||||
"183 (BC_0, *, control, 1), " &
|
||||
"182 (BC_0, DDR_A(12), output3, X, 183, 1, Z), " &
|
||||
"181 (BC_0, *, control, 1), " &
|
||||
"180 (BC_0, DDR_A(11), output3, X, 181, 1, Z), " &
|
||||
"179 (BC_0, *, control, 1), " &
|
||||
"178 (BC_0, DDR_A(10), output3, X, 179, 1, Z), " &
|
||||
"177 (BC_0, *, control, 1), " &
|
||||
"176 (BC_0, DDR_A(9), output3, X, 177, 1, Z), " &
|
||||
"175 (BC_0, *, control, 1), " &
|
||||
"174 (BC_0, DDR_A(8), output3, X, 175, 1, Z), " &
|
||||
"173 (BC_0, *, control, 1), " &
|
||||
"172 (BC_0, DDR_A(7), output3, X, 173, 1, Z), " &
|
||||
"171 (BC_1, *, control, 1), " &
|
||||
"170 (BC_7, DDR_D(7), bidir, X, 171, 1, Z), " &
|
||||
"169 (BC_1, *, control, 1), " &
|
||||
"168 (BC_7, DDR_D(6), bidir, X, 169, 1, Z), " &
|
||||
"167 (BC_1, *, control, 1), " &
|
||||
"166 (BC_7, DDR_D(5), bidir, X, 167, 1, Z), " &
|
||||
"165 (BC_1, *, control, 1), " &
|
||||
"164 (BC_7, DDR_D(4), bidir, X, 165, 1, Z), " &
|
||||
"163 (BC_1, *, control, 1), " &
|
||||
"162 (BC_7, DDR_DQS(0), bidir, X, 163, 1, Z), " &
|
||||
"161 (BC_1, *, control, 1), " &
|
||||
"160 (BC_7, DDR_D(3), bidir, X, 161, 1, Z), " &
|
||||
"159 (BC_1, *, control, 1), " &
|
||||
"158 (BC_7, DDR_D(2), bidir, X, 159, 1, Z), " &
|
||||
"157 (BC_1, *, control, 1), " &
|
||||
"156 (BC_7, DDR_D(1), bidir, X, 157, 1, Z), " &
|
||||
"155 (BC_1, *, control, 1), " &
|
||||
"154 (BC_7, DDR_D(0), bidir, X, 155, 1, Z), " &
|
||||
"153 (BC_0, *, control, 1), " &
|
||||
"152 (BC_0, DDR_DQM(0), output3, X, 153, 1, Z), " &
|
||||
"151 (BC_1, *, control, 1), " &
|
||||
"150 (BC_7, DDR_D(23), bidir, X, 151, 1, Z), " &
|
||||
"149 (BC_1, *, control, 1), " &
|
||||
"148 (BC_7, DDR_D(22), bidir, X, 149, 1, Z), " &
|
||||
"147 (BC_1, *, control, 1), " &
|
||||
"146 (BC_7, DDR_D(21), bidir, X, 147, 1, Z), " &
|
||||
"145 (BC_1, *, control, 1), " &
|
||||
"144 (BC_7, DDR_D(20), bidir, X, 145, 1, Z), " &
|
||||
"143 (BC_1, *, control, 1), " &
|
||||
"142 (BC_7, DDR_DQS(2), bidir, X, 143, 1, Z), " &
|
||||
"141 (BC_1, *, control, 1), " &
|
||||
"140 (BC_7, DDR_D(19), bidir, X, 141, 1, Z), " &
|
||||
"139 (BC_1, *, control, 1), " &
|
||||
"138 (BC_7, DDR_D(18), bidir, X, 139, 1, Z), " &
|
||||
"137 (BC_1, *, control, 1), " &
|
||||
"136 (BC_7, DDR_D(17), bidir, X, 137, 1, Z), " &
|
||||
"135 (BC_1, *, control, 1), " &
|
||||
"134 (BC_7, DDR_D(16), bidir, X, 135, 1, Z), " &
|
||||
"133 (BC_0, *, control, 1), " &
|
||||
"132 (BC_0, DDR_DQM(2), output3, X, 133, 1, Z), " &
|
||||
"131 (BC_1, *, control, 1), " &
|
||||
"130 (BC_7, PD0, bidir, X, 131, 1, Z), " &
|
||||
"129 (BC_1, *, control, 1), " &
|
||||
"128 (BC_7, PD1, bidir, X, 129, 1, Z), " &
|
||||
"127 (BC_1, *, control, 1), " &
|
||||
"126 (BC_7, PD2, bidir, X, 127, 1, Z), " &
|
||||
"125 (BC_1, *, control, 1), " &
|
||||
"124 (BC_7, PC26, bidir, X, 125, 1, Z), " &
|
||||
"123 (BC_1, *, control, 1), " &
|
||||
"122 (BC_7, PC27, bidir, X, 123, 1, Z), " &
|
||||
"121 (BC_1, *, control, 1), " &
|
||||
"120 (BC_7, PC28, bidir, X, 121, 1, Z), " &
|
||||
"119 (BC_1, *, control, 1), " &
|
||||
"118 (BC_7, PC29, bidir, X, 119, 1, Z), " &
|
||||
"117 (BC_1, *, control, 1), " &
|
||||
"116 (BC_7, PC30, bidir, X, 117, 1, Z), " &
|
||||
"115 (BC_1, *, control, 1), " &
|
||||
"114 (BC_7, PC31, bidir, X, 115, 1, Z), " &
|
||||
"113 (BC_1, *, control, 1), " &
|
||||
"112 (BC_7, PB0, bidir, X, 113, 1, Z), " &
|
||||
"111 (BC_1, *, control, 1), " &
|
||||
"110 (BC_7, PB2, bidir, X, 111, 1, Z), " &
|
||||
"109 (BC_1, *, control, 1), " &
|
||||
"108 (BC_7, PB1, bidir, X, 109, 1, Z), " &
|
||||
"107 (BC_1, *, control, 1), " &
|
||||
"106 (BC_7, PB3, bidir, X, 107, 1, Z), " &
|
||||
"105 (BC_1, *, control, 1), " &
|
||||
"104 (BC_7, PB4, bidir, X, 105, 1, Z), " &
|
||||
"103 (BC_1, *, control, 1), " &
|
||||
"102 (BC_7, PB5, bidir, X, 103, 1, Z), " &
|
||||
"101 (BC_1, *, control, 1), " &
|
||||
"100 (BC_7, PB6, bidir, X, 101, 1, Z), " &
|
||||
"99 (BC_1, *, control, 1), " &
|
||||
"98 (BC_7, PB8, bidir, X, 99, 1, Z), " &
|
||||
"97 (BC_1, *, control, 1), " &
|
||||
"96 (BC_7, PB7, bidir, X, 97, 1, Z), " &
|
||||
"95 (BC_1, *, control, 1), " &
|
||||
"94 (BC_7, PB10, bidir, X, 95, 1, Z), " &
|
||||
"93 (BC_1, *, control, 1), " &
|
||||
"92 (BC_7, PB9, bidir, X, 93, 1, Z), " &
|
||||
"91 (BC_1, *, control, 1), " &
|
||||
"90 (BC_7, PB11, bidir, X, 91, 1, Z), " &
|
||||
"89 (BC_1, *, control, 1), " &
|
||||
"88 (BC_7, PB12, bidir, X, 89, 1, Z), " &
|
||||
"87 (BC_1, *, control, 1), " &
|
||||
"86 (BC_7, PB14, bidir, X, 87, 1, Z), " &
|
||||
"85 (BC_1, *, control, 1), " &
|
||||
"84 (BC_7, PB13, bidir, X, 85, 1, Z), " &
|
||||
"83 (BC_1, *, control, 1), " &
|
||||
"82 (BC_7, PB15, bidir, X, 83, 1, Z), " &
|
||||
"81 (BC_1, *, control, 1), " &
|
||||
"80 (BC_7, PB16, bidir, X, 81, 1, Z), " &
|
||||
"79 (BC_1, *, control, 1), " &
|
||||
"78 (BC_7, PB17, bidir, X, 79, 1, Z), " &
|
||||
"77 (BC_1, *, control, 1), " &
|
||||
"76 (BC_7, PB19, bidir, X, 77, 1, Z), " &
|
||||
"75 (BC_1, *, control, 1), " &
|
||||
"74 (BC_7, PB18, bidir, X, 75, 1, Z), " &
|
||||
"73 (BC_1, *, control, 1), " &
|
||||
"72 (BC_7, PB20, bidir, X, 73, 1, Z), " &
|
||||
"71 (BC_1, *, control, 1), " &
|
||||
"70 (BC_7, PB21, bidir, X, 71, 1, Z), " &
|
||||
"69 (BC_1, *, control, 1), " &
|
||||
"68 (BC_7, PB23, bidir, X, 69, 1, Z), " &
|
||||
"67 (BC_1, *, control, 1), " &
|
||||
"66 (BC_7, PB22, bidir, X, 67, 1, Z), " &
|
||||
"65 (BC_1, *, control, 1), " &
|
||||
"64 (BC_7, PB25, bidir, X, 65, 1, Z), " &
|
||||
"63 (BC_1, *, control, 1), " &
|
||||
"62 (BC_7, PB24, bidir, X, 63, 1, Z), " &
|
||||
"61 (BC_1, *, control, 1), " &
|
||||
"60 (BC_7, PB26, bidir, X, 61, 1, Z), " &
|
||||
"59 (BC_1, *, control, 1), " &
|
||||
"58 (BC_7, PB28, bidir, X, 59, 1, Z), " &
|
||||
"57 (BC_1, *, control, 1), " &
|
||||
"56 (BC_7, PB27, bidir, X, 57, 1, Z), " &
|
||||
"55 (BC_1, *, control, 1), " &
|
||||
"54 (BC_7, PB30, bidir, X, 55, 1, Z), " &
|
||||
"53 (BC_1, *, control, 1), " &
|
||||
"52 (BC_7, PB29, bidir, X, 53, 1, Z), " &
|
||||
"51 (BC_1, *, control, 1), " &
|
||||
"50 (BC_7, PB31, bidir, X, 51, 1, Z), " &
|
||||
"49 (BC_1, *, control, 1), " &
|
||||
"48 (BC_7, PC9, bidir, X, 49, 1, Z), " &
|
||||
"47 (BC_1, *, control, 1), " &
|
||||
"46 (BC_7, PC11, bidir, X, 47, 1, Z), " &
|
||||
"45 (BC_1, *, control, 1), " &
|
||||
"44 (BC_7, PC10, bidir, X, 45, 1, Z), " &
|
||||
"43 (BC_1, *, control, 1), " &
|
||||
"42 (BC_7, PC12, bidir, X, 43, 1, Z), " &
|
||||
"41 (BC_1, *, control, 1), " &
|
||||
"40 (BC_7, PC13, bidir, X, 41, 1, Z), " &
|
||||
"39 (BC_1, *, control, 1), " &
|
||||
"38 (BC_7, PC14, bidir, X, 39, 1, Z), " &
|
||||
"37 (BC_1, *, control, 1), " &
|
||||
"36 (BC_7, PC15, bidir, X, 37, 1, Z), " &
|
||||
"35 (BC_1, *, control, 1), " &
|
||||
"34 (BC_7, PC17, bidir, X, 35, 1, Z), " &
|
||||
"33 (BC_1, *, control, 1), " &
|
||||
"32 (BC_7, PC16, bidir, X, 33, 1, Z), " &
|
||||
"31 (BC_1, *, control, 1), " &
|
||||
"30 (BC_7, PC19, bidir, X, 31, 1, Z), " &
|
||||
"29 (BC_1, *, control, 1), " &
|
||||
"28 (BC_7, PC18, bidir, X, 29, 1, Z), " &
|
||||
"27 (BC_1, *, control, 1), " &
|
||||
"26 (BC_7, PC20, bidir, X, 27, 1, Z), " &
|
||||
"25 (BC_1, *, control, 1), " &
|
||||
"24 (BC_7, PC21, bidir, X, 25, 1, Z), " &
|
||||
"23 (BC_1, *, control, 1), " &
|
||||
"22 (BC_7, PC22, bidir, X, 23, 1, Z), " &
|
||||
"21 (BC_1, *, control, 1), " &
|
||||
"20 (BC_7, PC23, bidir, X, 21, 1, Z), " &
|
||||
"19 (BC_1, *, control, 1), " &
|
||||
"18 (BC_7, PC24, bidir, X, 19, 1, Z), " &
|
||||
"17 (BC_1, *, control, 1), " &
|
||||
"16 (BC_7, PC25, bidir, X, 17, 1, Z), " &
|
||||
"15 (BC_1, *, control, 1), " &
|
||||
"14 (BC_7, PD10, bidir, X, 15, 1, Z), " &
|
||||
"13 (BC_1, *, control, 1), " &
|
||||
"12 (BC_7, PD9, bidir, X, 13, 1, Z), " &
|
||||
"11 (BC_1, *, control, 1), " &
|
||||
"10 (BC_7, PD8, bidir, X, 11, 1, Z), " &
|
||||
"9 (BC_1, *, control, 1), " &
|
||||
"8 (BC_7, PD7, bidir, X, 9, 1, Z), " &
|
||||
"7 (BC_1, *, control, 1), " &
|
||||
"6 (BC_7, PD6, bidir, X, 7, 1, Z), " &
|
||||
"5 (BC_1, *, control, 1), " &
|
||||
"4 (BC_7, PD5, bidir, X, 5, 1, Z), " &
|
||||
"3 (BC_1, *, control, 1), " &
|
||||
"2 (BC_7, PD4, bidir, X, 3, 1, Z), " &
|
||||
"1 (BC_1, *, control, 1), " &
|
||||
"0 (BC_7, PD3, bidir, X, 1, 1, Z) ";
|
||||
|
||||
end top;
|
|
@ -0,0 +1,51 @@
|
|||
# ----------------------------------------------------------------------------
|
||||
# SAM Software Package License
|
||||
# ----------------------------------------------------------------------------
|
||||
# Copyright (c) 2013, Atmel Corporation
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# - Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the disclaimer below.
|
||||
#
|
||||
# Atmel's name may not be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
CFLAGS_INC += -I$(TOP)/drivers
|
||||
|
||||
lib-y += drivers/drivers.a
|
||||
|
||||
drivers-y :=
|
||||
|
||||
include $(TOP)/drivers/cortex-a/Makefile.inc
|
||||
include $(TOP)/drivers/memories/Makefile.inc
|
||||
include $(TOP)/drivers/misc/Makefile.inc
|
||||
include $(TOP)/drivers/network/Makefile.inc
|
||||
include $(TOP)/drivers/peripherals/Makefile.inc
|
||||
include $(TOP)/drivers/power/Makefile.inc
|
||||
include $(TOP)/drivers/video/Makefile.inc
|
||||
include $(TOP)/drivers/usb/Makefile.inc
|
||||
|
||||
DRIVERS_OBJS := $(addprefix $(BUILDDIR)/,$(drivers-y))
|
||||
|
||||
-include $(DRIVERS_OBJS:.o=.d)
|
||||
|
||||
$(BUILDDIR)/drivers/drivers.a: $(DRIVERS_OBJS)
|
||||
@mkdir -p $(BUILDDIR)/drivers
|
||||
$(ECHO) AR $@
|
||||
$(Q)$(AR) -cr $@ $^
|
|
@ -0,0 +1,34 @@
|
|||
# ----------------------------------------------------------------------------
|
||||
# SAM Software Package License
|
||||
# ----------------------------------------------------------------------------
|
||||
# Copyright (c) 2015, Atmel Corporation
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# - Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the disclaimer below.
|
||||
#
|
||||
# Atmel's name may not be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
drivers-y += drivers/cortex-a/cortexa5_interrupts.o
|
||||
drivers-y += drivers/cortex-a/cp15.o
|
||||
drivers-y += drivers/cortex-a/cp15_asm_gcc.o
|
||||
drivers-y += drivers/cortex-a/cp15_pmu.o
|
||||
drivers-y += drivers/cortex-a/cpsr_gcc.o
|
||||
drivers-y += drivers/cortex-a/mmu.o
|
|
@ -0,0 +1,194 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Provides the low-level initialization function that called on chip startup.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "compiler.h"
|
||||
#include "peripherals/aic.h"
|
||||
#include "cortexa5_interrupts.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Constants
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/* IFSR status */
|
||||
static const char* _prefetch_abort_status[32] = {
|
||||
NULL,
|
||||
NULL,
|
||||
"debug event",
|
||||
"access flag fault, section",
|
||||
NULL,
|
||||
"translation fault, section",
|
||||
"access flag fault, page",
|
||||
"translation fault, page",
|
||||
"synchronous external abort",
|
||||
"domain fault, section",
|
||||
NULL,
|
||||
"domain fault, page",
|
||||
"L1 translation, synchronous external abort",
|
||||
"permission fault, section",
|
||||
"L2 translation, synchronous external abort",
|
||||
"permission fault, page",
|
||||
};
|
||||
|
||||
/* DFSR status */
|
||||
static const char* _data_abort_status[32] = {
|
||||
NULL,
|
||||
"alignment fault",
|
||||
"debug event",
|
||||
"access flag fault, section",
|
||||
"instruction cache maintenance fault",
|
||||
"translation fault, section",
|
||||
"access flag fault, page",
|
||||
"translation fault, page",
|
||||
"synchronous external abort, nontranslation",
|
||||
"domain fault, section",
|
||||
NULL,
|
||||
"domain fault, page",
|
||||
"1st level translation, synchronous external abort",
|
||||
"permission fault, section",
|
||||
"2nd level translation, synchronous external abort",
|
||||
"permission fault, page",
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
"asynchronous external abort"
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Functions Prototypes
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void default_undefined_instruction_irq_handler(void);
|
||||
void default_software_interrupt_irq_handler(void);
|
||||
void default_data_abort_irq_handler(void);
|
||||
void default_prefetch_abort_irq_handler(void);
|
||||
|
||||
#pragma weak undefined_instruction_irq_handler=default_undefined_instruction_irq_handler
|
||||
#pragma weak software_interrupt_irq_handler=default_software_interrupt_irq_handler
|
||||
#pragma weak data_abort_irq_handler=default_data_abort_irq_handler
|
||||
#pragma weak prefetch_abort_irq_handler=default_prefetch_abort_irq_handler
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Default handler for "Undefined Instruction" exception
|
||||
*/
|
||||
void default_undefined_instruction_irq_handler(void)
|
||||
{
|
||||
printf("\n\r");
|
||||
printf("#####################\n\r");
|
||||
printf("Undefined Instruction\n\r");
|
||||
printf("#####################\n\r");
|
||||
|
||||
asm("bkpt #0");
|
||||
while(1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Default handler for "Software Interrupt" exception
|
||||
*/
|
||||
void default_software_interrupt_irq_handler(void)
|
||||
{
|
||||
printf("\n\r");
|
||||
printf("##################\n\r");
|
||||
printf("Software Interrupt\n\r");
|
||||
printf("##################\n\r");
|
||||
|
||||
asm("bkpt #0");
|
||||
while(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Default handler for "Data Abort" exception
|
||||
*/
|
||||
void default_data_abort_irq_handler(void)
|
||||
{
|
||||
uint32_t v1, v2, dfsr;
|
||||
|
||||
asm("mrc p15, 0, %0, c5, c0, 0" : "=r"(v1));
|
||||
asm("mrc p15, 0, %0, c6, c0, 0" : "=r"(v2));
|
||||
|
||||
printf("\n\r");
|
||||
printf("####################\n\r");
|
||||
dfsr = ((v1 >> 4) & 0x0F);
|
||||
printf("Data Fault occured in %x domain\n\r", (unsigned int)dfsr);
|
||||
dfsr = (((v1 & 0x400) >> 6) | (v1 & 0x0F));
|
||||
if (_data_abort_status[dfsr])
|
||||
printf("Data Fault reason is: %s\n\r", _data_abort_status[dfsr]);
|
||||
else
|
||||
printf("Data Fault reason is unknown\n\r");
|
||||
printf("Data Fault occured at address: 0x%08x\n\n\r", (unsigned int)v2);
|
||||
printf("Data Fault status register value: 0x%x\n\r", (unsigned int)v1);
|
||||
printf("####################\n\r");
|
||||
|
||||
asm("bkpt #0");
|
||||
while(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Default handler for "Prefetch Abort" exception
|
||||
*/
|
||||
void default_prefetch_abort_irq_handler(void)
|
||||
{
|
||||
uint32_t v1, v2, ifsr;
|
||||
|
||||
asm("mrc p15, 0, %0, c5, c0, 1" : "=r"(v1));
|
||||
asm("mrc p15, 0, %0, c6, c0, 2" : "=r"(v2));
|
||||
|
||||
printf("\n\r");
|
||||
printf("####################\n\r");
|
||||
ifsr = (((v1 & 0x400) >> 6) | (v1 & 0x0F));
|
||||
if (_prefetch_abort_status[ifsr])
|
||||
printf("Prefetch Fault reason is: %s\n\r", _prefetch_abort_status[ifsr]);
|
||||
else
|
||||
printf("Prefetch Fault reason is unknown\n\r");
|
||||
printf("prefetch Fault occured at address: 0x%08x\n\n\r", (unsigned int)v2);
|
||||
printf("Prefetch Fault status register value: 0x%x\n\r", (unsigned int)v1);
|
||||
printf("####################\n\r");
|
||||
|
||||
asm("bkpt #0");
|
||||
while(1);
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Cortex-A5 core interrupt handlers
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef INTERRUPTS_CORTEXA5_H
|
||||
#define INTERRUPTS_CORTEXA5_H
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
extern WEAK void undefined_instruction_irq_handler(void);
|
||||
extern WEAK void software_interrupt_irq_handler(void);
|
||||
extern WEAK void prefetch_abort_irq_handler(void);
|
||||
extern WEAK void data_abort_irq_handler(void);
|
||||
|
||||
#endif /* INTERRUPTS_CORTEXA5_H */
|
|
@ -0,0 +1,350 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Reg Reads Writes
|
||||
//----------------------------------------------------------------------------
|
||||
// 0 ID code Unpredictable
|
||||
// 0 cache type Unpredictable
|
||||
// 0 TCM status Unpredictable
|
||||
// 1 Control Control
|
||||
// 2 Translation table base Translation table base
|
||||
// 3 Domain access control Domain access control
|
||||
// 4 (Reserved)
|
||||
// 5 Data fault status Data fault status
|
||||
// 5 Instruction fault status Instruction fault status
|
||||
// 6 Fault address Fault address
|
||||
// 7 cache operations cache operations
|
||||
// 8 Unpredictable TLB operations
|
||||
// 9 cache lockdown cache lockdown
|
||||
// 9 TCM region TCM region
|
||||
// 10 TLB lockdown TLB lockdown
|
||||
// 11 (Reserved)
|
||||
// 12 (Reserved)
|
||||
// 13 FCSE PID FCSE PID
|
||||
// 13 Context ID Context ID
|
||||
// 14 (Reserved)
|
||||
// 15 Test configuration Test configuration
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/** \page cp15_f CP15 Functions
|
||||
*
|
||||
* \section CP15 function Usage
|
||||
*
|
||||
* Methods to manage the Coprocessor 15. Coprocessor 15, or System Control
|
||||
* Coprocessor CP15, is used to configure and control all the items in the
|
||||
* list below:
|
||||
* <ul>
|
||||
* <li> ARM core
|
||||
* <li> caches (Icache, Dcache and write buffer)
|
||||
* <li> TCM
|
||||
* <li> MMU
|
||||
* <li> Other system options
|
||||
* </ul>
|
||||
* \section Usage
|
||||
*
|
||||
* -# Enable or disable D cache with cp15_enable_dcache() and cp15_disable_dcache()
|
||||
* -# Enable or disable I cache with cp15_enable_icache() and cp15_disable_icache()
|
||||
*
|
||||
* Related files:\n
|
||||
* \ref cp15.h\n
|
||||
* \ref cp15.c\n
|
||||
*/
|
||||
|
||||
/** \file */
|
||||
|
||||
/**
|
||||
* \addtogroup cp15_cache L1 Cache Operations
|
||||
* \ingroup cache_module
|
||||
*
|
||||
* \section Usage
|
||||
*
|
||||
* They are performed as MCR instructions and only operate on a level 1 cache associated with
|
||||
* ATM v7 processor.
|
||||
* The supported operations are:
|
||||
* <ul>
|
||||
* <li> Any of these operations can be applied to
|
||||
* -# any data cache
|
||||
* -# any unified cache.
|
||||
* <li> Invalidate by MVA
|
||||
* Performs an invalidate of a data or unified cache line based on the address it contains.
|
||||
* <li> Invalidate by set/way
|
||||
* Performs an invalidate of a data or unified cache line based on its location in the cache hierarchy.
|
||||
* <li> Clean by MVA
|
||||
* Performs a clean of a data or unified cache line based on the address it contains.
|
||||
* <li> Clean by set/way
|
||||
* Performs a clean of a data or unified cache line based on its location in the cache hierarchy.
|
||||
* <li> Clean and Invalidate by MVA
|
||||
* Performs a clean and invalidate of a data or unified cache line based on the address it contains.
|
||||
* <li> Clean and Invalidate by set/way
|
||||
* Performs a clean and invalidate of a data or unified cache line based on its location in the cache hierarchy.
|
||||
* </ul>
|
||||
*
|
||||
* Related files:\n
|
||||
* \ref cp15.h\n
|
||||
* \ref cp15_asm_gcc.S \n
|
||||
* \ref cp15_asm_iar.s \n
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
#if defined(__ICCARM__)
|
||||
#include <intrinsics.h>
|
||||
#endif
|
||||
|
||||
#include "cortex-a/cp15.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Global functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Check Instruction cache
|
||||
* \return 0 if I_cache disable, 1 if I_cache enable
|
||||
*/
|
||||
unsigned int cp15_is_icached_enabled(void)
|
||||
{
|
||||
unsigned int control;
|
||||
control = cp15_read_control();
|
||||
return ((control & (1 << CP15_I_BIT)) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable Instruction cache
|
||||
*/
|
||||
void cp15_enable_icache(void)
|
||||
{
|
||||
unsigned int control;
|
||||
control = cp15_read_control();
|
||||
// Check if cache is disabled
|
||||
if ((control & (1 << CP15_I_BIT)) == 0) {
|
||||
cp15_icache_invalidate();
|
||||
control |= (1 << CP15_I_BIT);
|
||||
cp15_write_control(control);
|
||||
trace_info("I cache enabled.\n\r");
|
||||
} else {
|
||||
|
||||
trace_info("I cache is already enabled.\n\r");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable Instruction cache
|
||||
*/
|
||||
void cp15_disable_icache(void)
|
||||
{
|
||||
unsigned int control;
|
||||
control = cp15_read_control();
|
||||
// Check if cache is enabled
|
||||
if ((control & (1 << CP15_I_BIT)) != 0) {
|
||||
|
||||
control &= ~(1ul << CP15_I_BIT);
|
||||
cp15_write_control(control);
|
||||
trace_info("I cache disabled.\n\r");
|
||||
} else {
|
||||
|
||||
trace_info("I cache is already disabled.\n\r");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check MMU
|
||||
* \return 0 if MMU disable, 1 if MMU enable
|
||||
*/
|
||||
unsigned int cp15_is_mmu_enabled(void)
|
||||
{
|
||||
unsigned int control;
|
||||
control = cp15_read_control();
|
||||
return ((control & (1 << CP15_M_BIT)) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable MMU
|
||||
*/
|
||||
void cp15_enable_mmu(void)
|
||||
{
|
||||
unsigned int control;
|
||||
control = cp15_read_control();
|
||||
// Check if MMU is disabled
|
||||
if ((control & (1 << CP15_M_BIT)) == 0) {
|
||||
|
||||
control |= (1 << CP15_M_BIT);
|
||||
cp15_write_control(control);
|
||||
trace_info("MMU enabled.\n\r");
|
||||
} else {
|
||||
trace_info("MMU is already enabled.\n\r");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable MMU
|
||||
*/
|
||||
void cp15_disable_mmu(void)
|
||||
{
|
||||
unsigned int control;
|
||||
control = cp15_read_control();
|
||||
// Check if MMU is enabled
|
||||
if ((control & (1 << CP15_M_BIT)) != 0) {
|
||||
|
||||
control &= ~(1ul << CP15_M_BIT);
|
||||
control &= ~(1ul << CP15_C_BIT);
|
||||
cp15_write_control(control);
|
||||
trace_info("MMU disabled.\n\r");
|
||||
} else {
|
||||
trace_info("MMU is already disabled.\n\r");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check D_cache
|
||||
* \return 0 if D_cache disable, 1 if D_cache enable (with MMU of course)
|
||||
*/
|
||||
unsigned int cp15_is_dcache_enabled(void)
|
||||
{
|
||||
unsigned int control;
|
||||
control = cp15_read_control();
|
||||
return ((control & ((1 << CP15_C_BIT) || (1 << CP15_M_BIT))) != 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable Data cache
|
||||
*/
|
||||
void cp15_enable_dcache(void)
|
||||
{
|
||||
unsigned int control;
|
||||
control = cp15_read_control();
|
||||
if (!cp15_is_mmu_enabled()) {
|
||||
trace_error("Do nothing: MMU not enabled\n\r");
|
||||
} else {
|
||||
// Check if cache is disabled
|
||||
if ((control & (1 << CP15_C_BIT)) == 0) {
|
||||
cp15_dcache_invalidate();
|
||||
control |= (1 << CP15_C_BIT);
|
||||
cp15_write_control(control);
|
||||
trace_info("D cache enabled.\n\r");
|
||||
} else {
|
||||
trace_info("D cache is already enabled.\n\r");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable Data cache
|
||||
*/
|
||||
void cp15_disable_dcache(void)
|
||||
{
|
||||
unsigned int control;
|
||||
control = cp15_read_control();
|
||||
// Check if cache is enabled
|
||||
if ((control & (1 << CP15_C_BIT)) != 0) {
|
||||
|
||||
control &= ~(1ul << CP15_C_BIT);
|
||||
cp15_write_control(control);
|
||||
trace_info("D cache disabled.\n\r");
|
||||
} else {
|
||||
|
||||
trace_info("D cache is already disabled.\n\r");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clean Data cache
|
||||
*/
|
||||
void cp15_dcache_clean(void)
|
||||
{
|
||||
cp15_select_dcache();
|
||||
cp15_clean_dcache_by_set_way();
|
||||
asm("DSB");
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Invalidate Icache
|
||||
*/
|
||||
void cp15_icache_invalidate(void)
|
||||
{
|
||||
cp15_select_icache();
|
||||
cp15_invalid_icache_inner_sharable();
|
||||
asm ("ISB");
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Invalidate Dcache
|
||||
*/
|
||||
void cp15_dcache_invalidate(void)
|
||||
{
|
||||
cp15_select_dcache();
|
||||
cp15_invalid_dcache_by_set_way();
|
||||
asm ("DSB");
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Flush(Clean and invalidate) Data cache
|
||||
*/
|
||||
void cp15_dcache_flush(void)
|
||||
{
|
||||
cp15_select_dcache();
|
||||
cp15_clean_invalid_dcache_by_set_way();
|
||||
asm("DSB");
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Invalidate Data cache by address
|
||||
*/
|
||||
void cp15_invalid_dcache_by_va(uint32_t S_Add, uint32_t E_Add)
|
||||
{
|
||||
cp15_select_dcache();
|
||||
cp15_invalid_dcache_by_mva(S_Add, E_Add);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clean Data cache by address
|
||||
*/
|
||||
void cp15_clean_dcache_by_va(uint32_t S_Add, uint32_t E_Add)
|
||||
{
|
||||
cp15_select_dcache();
|
||||
cp15_clean_dcache_by_mva(S_Add, E_Add);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Flush Data cache by address
|
||||
*/
|
||||
|
||||
void cp15_flush_dcache_by_va(uint32_t S_Add, uint32_t E_Add)
|
||||
{
|
||||
cp15_select_dcache();
|
||||
cp15_clean_invalid_dcache_by_mva(S_Add, E_Add);
|
||||
}
|
|
@ -0,0 +1,318 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _CP15_H
|
||||
#define _CP15_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Definition
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define CP15_L4_BIT 15 // Determines if the T bit is set when load instructions
|
||||
// change the PC:
|
||||
// 0 = loads to PC set the T bit
|
||||
// 1 = loads to PC do not set T bit
|
||||
|
||||
#define CP15_RR_BIT 14 // RR bit Replacement strategy for Icache and Dcache:
|
||||
// 0 = Random replacement
|
||||
// 1 = Round-robin replacement.
|
||||
|
||||
#define CP15_V_BIT 13 // V bit Location of exception vectors:
|
||||
// 0 = Normal exception vectors selected address range = 0x0000 0000 to 0x0000 001C
|
||||
// 1 = High exception vect selected, address range = 0xFFFF 0000 to 0xFFFF 001C
|
||||
|
||||
#define CP15_I_BIT 12 // I bit Icache enable/disable:
|
||||
// 0 = Icache disabled
|
||||
// 1 = Icache enabled
|
||||
|
||||
#define CP15_R_BIT 9 // R bit ROM protection
|
||||
|
||||
#define CP15_S_BIT 8 // S bit System protection
|
||||
|
||||
#define CP15_B_BIT 7 // B bit Endianness:
|
||||
// 0 = Little-endian operation
|
||||
// 1 = Big-endian operation.
|
||||
|
||||
#define CP15_C_BIT 2 // C bit Dcache enable/disable:
|
||||
// 0 = cache disabled
|
||||
// 1 = cache enabled
|
||||
|
||||
#define CP15_A_BIT 1 // A bit Alignment fault enable/disable:
|
||||
// 0 = Data address alignment fault checking disabled
|
||||
// 1 = Data address alignment fault checking enabled
|
||||
|
||||
#define CP15_M_BIT 0 // M bit MMU enable/disable: 0 = disabled 1 = enabled.
|
||||
// 0 = disabled
|
||||
// 1 = enabled
|
||||
|
||||
/** No access Any access generates a domain fault. */
|
||||
#define CP15_DOMAIN_NO_ACCESS 0x00
|
||||
/** Client Accesses are checked against the access permission bits in the section or page descriptor. */
|
||||
#define CP15_DOMAIN_CLIENT_ACCESS 0x01
|
||||
/** Manager Accesses are not checked against the access permission bits so a permission fault cannot be generated. */
|
||||
#define CP15_DOMAIN_MANAGER_ACCESS 0x03
|
||||
|
||||
#define CP15_ICache 1
|
||||
#define CP15_DCache 0
|
||||
|
||||
#define CP15_PMCNTENSET_ENABLE 31
|
||||
#define CP15_PMCR_DIVIDER 3
|
||||
#define CP15_PMCR_RESET 2
|
||||
#define CP15_PMCR_ENABLE 0
|
||||
|
||||
/*------------------------------------------------------------------------------ */
|
||||
/* Exported functions */
|
||||
/*------------------------------------------------------------------------------ */
|
||||
|
||||
/**
|
||||
* \brief Read the Main ID Register (MIDR).
|
||||
* \return register contents
|
||||
*/
|
||||
extern unsigned int cp15_read_id(void);
|
||||
|
||||
/**
|
||||
* \brief Read the System Control Register (SCTLR).
|
||||
* \return register contents
|
||||
*/
|
||||
extern unsigned int cp15_read_control(void);
|
||||
|
||||
/**
|
||||
* \brief Indicate CPU that L2 is in exclusive caching mode.
|
||||
*/
|
||||
extern void cp15_exclusive_cache(void);
|
||||
|
||||
/**
|
||||
* \brief Allow data to reside in the L1 and L2 caches at the same time.
|
||||
*/
|
||||
extern void cp15_non_exclusive_cache(void);
|
||||
|
||||
/**
|
||||
* \brief Instruction Synchronization Barrier operation.
|
||||
*/
|
||||
extern void cp15_isb(void);
|
||||
|
||||
/**
|
||||
* \brief Data Synchronization Barrier operation.
|
||||
*/
|
||||
extern void cp15_dsb(void);
|
||||
|
||||
/**
|
||||
* \brief Data Memory Barrier operation.
|
||||
*/
|
||||
extern void cp15_dmb(void);
|
||||
|
||||
/**
|
||||
* \brief Invalidate unified Translation Lookaside Buffer.
|
||||
*/
|
||||
extern void cp15_invalidate_tlb(void);
|
||||
|
||||
/**
|
||||
* \brief Select the data cache as the one to later retrieve architecture
|
||||
* information about.
|
||||
*/
|
||||
extern void cp15_select_dcache(void);
|
||||
|
||||
/**
|
||||
* \brief Select the instruction cache as the one to later retrieve architecture
|
||||
* information about.
|
||||
*/
|
||||
extern void cp15_select_icache(void);
|
||||
|
||||
/**
|
||||
* \brief Modify the System Control Register (SCTLR).
|
||||
* This register specifies the configuration used to enable and disable the
|
||||
* caches and MMU.
|
||||
* It is recommended that you access this register using a read-modify-
|
||||
* write sequence.
|
||||
* \param value new value for SCTLR
|
||||
*/
|
||||
extern void cp15_write_control(unsigned int value);
|
||||
|
||||
/**
|
||||
* \brief ARMv7A architecture supports two translation tables.
|
||||
* Configure translation table base (TTB) control register 0.
|
||||
* \param value address of our page table base
|
||||
*/
|
||||
extern void cp15_write_ttb(unsigned int value);
|
||||
|
||||
/**
|
||||
* \brief Modify the Domain Access Control Register (DACR).
|
||||
* \param value new value for DACR
|
||||
*/
|
||||
extern void cp15_write_domain_access_control(unsigned int value);
|
||||
|
||||
/**
|
||||
* \brief Invalidate I cache predictor array to point of unification Inner
|
||||
* Shareable.
|
||||
*/
|
||||
extern void cp15_invalid_icache_inner_sharable(void);
|
||||
|
||||
/**
|
||||
* \brief Invalidate entire branch predictor array Inner Shareable
|
||||
*/
|
||||
extern void cp15_invalid_btb_inner_sharable(void);
|
||||
|
||||
/**
|
||||
* \brief Invalidate all instruction caches to point of unification.
|
||||
* Also flush branch target cache.
|
||||
*/
|
||||
extern void cp15_invalid_icache(void);
|
||||
|
||||
/**
|
||||
* \brief Invalidate instruction caches by virtual address to point of
|
||||
* unification.
|
||||
*/
|
||||
extern void cp15_invalid_icache_by_mva(void);
|
||||
|
||||
/**
|
||||
* \brief Invalidate entire branch predictor array.
|
||||
*/
|
||||
extern void cp15_invalid_btb(void);
|
||||
|
||||
/**
|
||||
* \brief Invalidate branch predictor array entry by modified virtual address.
|
||||
* \param addr virtual address
|
||||
*/
|
||||
extern void cp15_invalid_btb_by_mva(uint32_t addr);
|
||||
|
||||
/**
|
||||
* \brief Invalidate entire data cache by set/way.
|
||||
* Should be called further to cp15_select_dcache(), not
|
||||
* cp15_select_icache().
|
||||
*/
|
||||
extern void cp15_invalid_dcache_by_set_way(void);
|
||||
|
||||
/**
|
||||
* \brief Clean entire data cache by set/way.
|
||||
* Should be called further to cp15_select_dcache(), not
|
||||
* cp15_select_icache().
|
||||
*/
|
||||
extern void cp15_clean_dcache_by_set_way(void);
|
||||
|
||||
/**
|
||||
* \brief Clean and invalidate entire data cache by set/way
|
||||
* Should be called further to cp15_select_dcache(), not
|
||||
* cp15_select_icache().
|
||||
*/
|
||||
extern void cp15_clean_invalid_dcache_by_set_way(void);
|
||||
|
||||
/**
|
||||
* \brief Invalidate data cache by virtual address to point of coherency.
|
||||
* \param start virtual start address of region
|
||||
* \param end virtual end address of region
|
||||
*/
|
||||
extern void cp15_invalid_dcache_by_mva(uint32_t start, uint32_t end);
|
||||
|
||||
/**
|
||||
* \brief Clean data cache by modified virtual address to point of coherency.
|
||||
* \param start virtual start address of region
|
||||
* \param end virtual end address of region
|
||||
*/
|
||||
extern void cp15_clean_dcache_by_mva(uint32_t start, uint32_t end);
|
||||
|
||||
/**
|
||||
* \brief Clean and invalidate data cache by virtual address to point of
|
||||
* coherency.
|
||||
* \param start virtual start address of region
|
||||
* \param end virtual end address of region
|
||||
*/
|
||||
extern void cp15_clean_invalid_dcache_by_mva(uint32_t start, uint32_t end);
|
||||
|
||||
/**
|
||||
* \brief Clean unified cache by modified virtual address to point of
|
||||
* unification.
|
||||
*/
|
||||
extern void cp15_clean_dcache_umva(void);
|
||||
|
||||
/**
|
||||
* \brief Ensure that the I and D caches are coherent within the specified
|
||||
* region. This is typically used when code has been written to
|
||||
* a memory region, and will be executed.
|
||||
* \param start virtual start address of region
|
||||
* \param end virtual end address of region
|
||||
*/
|
||||
extern void cp15_coherent_dcache_for_dma(uint32_t start, uint32_t end);
|
||||
|
||||
/**
|
||||
* \brief Invalidate the data cache within the specified region; we will
|
||||
* be performing a DMA operation in this region and we want to purge the
|
||||
* cache of old data. Cache data will be discarded, not flushed.
|
||||
* The specified region should be aligned on cache lines. Otherwise mind
|
||||
* the data loss that may occur in the collateral part of start/end lines,
|
||||
* since cache data won't be flushed.
|
||||
* \param start virtual start address of region
|
||||
* \param end virtual end address of region
|
||||
*/
|
||||
extern void cp15_invalidate_dcache_for_dma(uint32_t start, uint32_t end);
|
||||
|
||||
/**
|
||||
* \brief Clean the data cache within the specified region.
|
||||
* \param start virtual start address of region
|
||||
* \param end virtual end address of region
|
||||
*/
|
||||
extern void cp15_clean_dcache_for_dma(uint32_t start, uint32_t end);
|
||||
|
||||
/**
|
||||
* \brief Flush, i.e. clean and invalidate, the data cache within the specified
|
||||
* region.
|
||||
* \param start virtual start address of region
|
||||
* \param end virtual end address of region
|
||||
*/
|
||||
extern void cp15_flush_dcache_for_dma(uint32_t start, uint32_t end);
|
||||
|
||||
/*------------------------------------------------------------------------------ */
|
||||
/* Exported functions from CP15.c */
|
||||
/*------------------------------------------------------------------------------ */
|
||||
|
||||
/** MMU (Status/Enable/Disable) */
|
||||
extern unsigned int cp15_is_mmu_enabled(void);
|
||||
extern void cp15_enable_mmu(void);
|
||||
extern void cp15_disable_mmu(void);
|
||||
|
||||
/** I cache (Status/Enable/Disable) */
|
||||
extern unsigned int cp15_is_icached_enabled(void);
|
||||
extern void cp15_enable_icache(void);
|
||||
extern void cp15_disable_icache(void);
|
||||
|
||||
/** D cache (Status/Enable/Disable) */
|
||||
extern unsigned int cp15_is_dcache_enabled(void);
|
||||
extern void cp15_enable_dcache(void);
|
||||
extern void cp15_disable_dcache(void);
|
||||
|
||||
extern void cp15_dcache_clean(void);
|
||||
extern void cp15_dcache_invalidate(void);
|
||||
extern void cp15_icache_invalidate(void);
|
||||
extern void cp15_dcache_flush(void);
|
||||
extern void cp15_invalid_dcache_by_va(uint32_t S_Add, uint32_t E_Add);
|
||||
extern void cp15_clean_dcache_by_va(uint32_t S_Add, uint32_t E_Add);
|
||||
extern void cp15_flush_dcache_by_va(uint32_t S_Add, uint32_t E_Add);
|
||||
|
||||
#endif // #ifndef _CP15_H
|
|
@ -0,0 +1,412 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file */
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Functions to access CP15 coprocessor register
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
.section .text.cp15_read_id
|
||||
.global cp15_read_id
|
||||
cp15_read_id:
|
||||
mov r0, #0
|
||||
mrc p15, 0, r0, c0, c0, 0 // read MIDR
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_isb
|
||||
.global cp15_isb
|
||||
cp15_isb:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 4 // CP15ISB()
|
||||
nop
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_dsb
|
||||
.global cp15_dsb
|
||||
cp15_dsb:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c10, 4 // CP15DSB()
|
||||
nop
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_dmb
|
||||
.global cp15_dmb
|
||||
cp15_dmb:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c10, 5 // CP15DMB
|
||||
nop
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_invalidate_tlb
|
||||
.global cp15_invalidate_tlb
|
||||
cp15_invalidate_tlb:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c8, c7, 0 // TLBIALL()
|
||||
dsb
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_exclusive_cache
|
||||
.global cp15_exclusive_cache
|
||||
cp15_exclusive_cache:
|
||||
mov r0, #0
|
||||
mrc p15, 0, r0, c1, c0, 1 // Read ACTLR
|
||||
orr r0, r0, #0x00000080 // Set EXCL
|
||||
mcr p15, 0, r0, c1, c0, 1 // Write ACTLR
|
||||
nop
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_non_exclusive_cache
|
||||
.global cp15_non_exclusive_cache
|
||||
cp15_non_exclusive_cache:
|
||||
mov r0, #0
|
||||
mrc p15, 0, r0, c1, c0, 1 // Read ACTLR
|
||||
bic r0, r0, #0x00000080 // Clear EXCL
|
||||
mcr p15, 0, r0, c1, c0, 1 // Write ACTLR
|
||||
nop
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_select_icache
|
||||
.global cp15_select_icache
|
||||
cp15_select_icache:
|
||||
mrc p15, 2, r0, c0, c0, 0 // Read CSSELR
|
||||
orr r0, r0, #0x1 // Set InD: cache type = ICache
|
||||
mcr p15, 2, r0, c0, c0, 0 // Write CSSELR
|
||||
nop
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_select_dcache
|
||||
.global cp15_select_dcache
|
||||
cp15_select_dcache:
|
||||
mrc p15, 2, r0, c0, c0, 0 // Read CSSELR
|
||||
and r0, r0, #0xFFFFFFFE // Clear InD: cache type = DCache
|
||||
mcr p15, 2, r0, c0, c0, 0 // Write CSSELR
|
||||
nop
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_read_control
|
||||
.global cp15_read_control
|
||||
cp15_read_control:
|
||||
mov r0, #0
|
||||
mrc p15, 0, r0, c1, c0, 0 // read SCTLR
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_write_control
|
||||
.global cp15_write_control
|
||||
cp15_write_control:
|
||||
mcr p15, 0, r0, c1, c0, 0 // rewrite SCTLR
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_write_domain_access_control
|
||||
.global cp15_write_domain_access_control
|
||||
cp15_write_domain_access_control:
|
||||
mcr p15, 0, r0, c3, c0, 0 // rewrite DACR
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_write_ttb
|
||||
.global cp15_write_ttb
|
||||
cp15_write_ttb:
|
||||
mcr p15, 0, r0, c2, c0, 0 // rewrite TTBR0
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_invalid_icache_inner_sharable
|
||||
.global cp15_invalid_icache_inner_sharable
|
||||
cp15_invalid_icache_inner_sharable:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c1, 0 // ICIALLUIS()
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_invalid_btb_inner_sharable
|
||||
.global cp15_invalid_btb_inner_sharable
|
||||
cp15_invalid_btb_inner_sharable:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c1, 6 // BPIALLIS()
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_invalid_icache
|
||||
.global cp15_invalid_icache
|
||||
cp15_invalid_icache:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 // ICIALLU()
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_invalid_icache_by_mva
|
||||
.global cp15_invalid_icache_by_mva
|
||||
cp15_invalid_icache_by_mva:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 1 // ICIMVAU()
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_invalid_btb
|
||||
.global cp15_invalid_btb
|
||||
cp15_invalid_btb:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 6 // BPIALL()
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_invalid_btb_by_mva
|
||||
.global cp15_invalid_btb_by_mva
|
||||
cp15_invalid_btb_by_mva:
|
||||
mcr p15, 0, r0, c7, c5, 7 // BPIMVA()
|
||||
bx lr
|
||||
|
||||
/***********************************************************
|
||||
* Data Cache related maintenance functions
|
||||
***********************************************************/
|
||||
|
||||
.section .text.cp15_invalid_dcache_by_set_way
|
||||
.global cp15_invalid_dcache_by_set_way
|
||||
cp15_invalid_dcache_by_set_way:
|
||||
push {r1-r4}
|
||||
mrc p15, 1, r0, c0, c0, 0 // Read CCSIDR
|
||||
mov r1, r0, lsr #3 // Get Associativity (num of ways)
|
||||
and r1, r1, #3 // 3 is specific to CortexA5 with 32 KB
|
||||
mov r2, r0, lsr #13 // Get NumSets (num of sets)
|
||||
and r2, r2, #0xFF // 8bit is specific to CortexA5 with 32 KB
|
||||
mov r0, #0 // 0:SHL:5
|
||||
1:
|
||||
lsl r4, r1, #30
|
||||
mov r3, r2
|
||||
2:
|
||||
orr r0, r4, r3, lsl #5
|
||||
mcr p15, 0, r0, c7, c6, 2 // DCISW()
|
||||
subs r3, r3, #1 // 1:SHL:30
|
||||
bpl 2b
|
||||
subs r1, r1, #1
|
||||
bpl 1b
|
||||
dsb
|
||||
pop {r1-r4}
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_clean_dcache_by_set_way
|
||||
.global cp15_clean_dcache_by_set_way
|
||||
cp15_clean_dcache_by_set_way:
|
||||
push {r1-r4}
|
||||
mrc p15, 1, r0, c0, c0, 0 // Read CCSIDR
|
||||
mov r1, r0, lsr #3 // Get Associativity (num of ways)
|
||||
and r1, r1, #3 // 3 is specific to CortexA5 with 32 KB
|
||||
mov r2, r0, lsr #13 // Get NumSets (num of sets)
|
||||
and r2, r2, #0xFF // 8bit is specific to CortexA5 with 32 KB
|
||||
mov r0, #0 // 0:SHL:5
|
||||
1:
|
||||
lsl r4, r1, #30
|
||||
mov r3, r2
|
||||
2:
|
||||
orr r0, r4, r3, lsl #5
|
||||
mcr p15, 0, r0, c7, c10, 2 // DCCSW()
|
||||
subs r3, r3, #1 // 1:SHL:30
|
||||
bpl 2b
|
||||
subs r1, r1, #1
|
||||
bpl 1b
|
||||
dsb
|
||||
pop {r1-r4}
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_clean_invalid_dcache_by_set_way
|
||||
.global cp15_clean_invalid_dcache_by_set_way
|
||||
cp15_clean_invalid_dcache_by_set_way:
|
||||
push {r1-r4}
|
||||
mrc p15, 1, r0, c0, c0, 0 // Read CCSIDR
|
||||
mov r1, r0, lsr #3 // Get Associativity (num of ways)
|
||||
and r1, r1, #3 // 3 is specific to CortexA5 with 32 KB
|
||||
mov r2, r0, lsr #13 // Get NumSets (num of sets)
|
||||
and r2, r2, #0xFF // 8bit is specific to CortexA5 with 32 KB
|
||||
mov r0, #0 // 0:SHL:5
|
||||
1:
|
||||
lsl r4, r1, #30
|
||||
mov r3, r2
|
||||
2:
|
||||
orr r0, r4, r3, lsl #5
|
||||
mcr p15, 0, r0, c7, c14, 2 // DCCISW()
|
||||
subs r3, r3, #1 // 1:SHL:30
|
||||
bpl 2b
|
||||
subs r1, r1, #1
|
||||
bpl 1b
|
||||
dsb
|
||||
pop {r1-r4}
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_invalid_dcache_by_mva
|
||||
.global cp15_invalid_dcache_by_mva
|
||||
cp15_invalid_dcache_by_mva:
|
||||
mov r2, #0x20 // Eight words per line, Cortex-A5 L1 Line Size 32 Bytes
|
||||
mov r3, r0
|
||||
inv_loop:
|
||||
mcr p15, 0, r0, c7, c6, 1 // DCIMVAC()
|
||||
add r3, r3, r2
|
||||
cmp r3, r1
|
||||
bls inv_loop
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_clean_dcache_by_mva
|
||||
.global cp15_clean_dcache_by_mva
|
||||
cp15_clean_dcache_by_mva:
|
||||
mov r2, #0x20 // Eight words per line, Cortex-A5 L1 Line Size 32 Bytes
|
||||
mov r3, r0
|
||||
clean_loop:
|
||||
mcr p15, 0, r0, c7, c10, 1 // DCCMVAC()
|
||||
add r3, r3, r2
|
||||
cmp r3, r1
|
||||
bls clean_loop
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_clean_dcache_umva
|
||||
.global cp15_clean_dcache_umva
|
||||
cp15_clean_dcache_umva:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c11, 1 // DCCMVAU()
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_clean_invalid_dcache_by_mva
|
||||
.global cp15_clean_invalid_dcache_by_mva
|
||||
cp15_clean_invalid_dcache_by_mva:
|
||||
mov r2, #0x20 // Eight words per line, Cortex-A5 L1 Line Size 32 Bytes
|
||||
mov r3, r0
|
||||
clinv_loop:
|
||||
mcr p15, 0, r0, c7, c14, 1 // DCCIMVAC()
|
||||
add r3, r3, r2
|
||||
cmp r3, r1
|
||||
bls clinv_loop
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_coherent_dcache_for_dma
|
||||
.global cp15_coherent_dcache_for_dma
|
||||
cp15_coherent_dcache_for_dma:
|
||||
push {r2-r4}
|
||||
mrc p15, 0, r3, c0, c0, 1 // read Cache Type Register
|
||||
lsr r3, r3, #16
|
||||
and r3, r3, #0xf // DminLine
|
||||
mov r2, #4
|
||||
mov r2, r2, lsl r3 // cache line size, in bytes (4*2^DminLine)
|
||||
|
||||
sub r3, r2, #1 // cache line mask
|
||||
bic r4, r0, r3 // address of the first cache line
|
||||
1:
|
||||
mcr p15, 0, r4, c7, c11, 1 // DCCMVAU()
|
||||
add r4, r4, r2
|
||||
cmp r4, r1
|
||||
blo 1b
|
||||
dsb
|
||||
|
||||
bic r4, r0, r3
|
||||
2:
|
||||
mcr p15, 0, r4, c7, c5, 1 // ICIMVAU()
|
||||
add r4, r4, r2
|
||||
cmp r4, r1
|
||||
blo 2b
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c1, 6 // BPIALLIS()
|
||||
mcr p15, 0, r0, c7, c5, 6 // BPIALL()
|
||||
dsb
|
||||
isb
|
||||
pop {r2-r4}
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_invalidate_dcache_for_dma
|
||||
.global cp15_invalidate_dcache_for_dma
|
||||
cp15_invalidate_dcache_for_dma:
|
||||
push {r2-r3}
|
||||
mrc p15, 0, r3, c0, c0, 1 // read CP15 Cache Type Register
|
||||
lsr r3, r3, #16
|
||||
and r3, r3, #0xf // DminLine
|
||||
mov r2, #4
|
||||
mov r2, r2, lsl r3 // cache line size, in bytes (4*2^DminLine)
|
||||
|
||||
sub r3, r2, #1 // cache line mask
|
||||
bic r0, r0, r3 // address of the first cache line
|
||||
3:
|
||||
mcr p15, 0, r0, c7, c6, 1 // CP15:DCIMVAC(r0)
|
||||
add r0, r0, r2
|
||||
cmp r0, r1 // while ('cache line address' < 'end')
|
||||
blo 3b
|
||||
dsb
|
||||
pop {r2-r3}
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_clean_dcache_for_dma
|
||||
.global cp15_clean_dcache_for_dma
|
||||
cp15_clean_dcache_for_dma:
|
||||
mrc p15, 0, r3, c0, c0, 1 // read Cache Type Register
|
||||
lsr r3, r3, #16
|
||||
and r3, r3, #0xf // DminLine
|
||||
mov r2, #4
|
||||
mov r2, r2, lsl r3 // cache line size, in bytes (4*2^DminLine)
|
||||
|
||||
sub r3, r2, #1 // cache line mask
|
||||
bic r0, r0, r3 // address of the first cache line
|
||||
4:
|
||||
mcr p15, 0, r0, c7, c10, 1 // DCCMVAC()
|
||||
add r0, r0, r2
|
||||
cmp r0, r1
|
||||
blo 4b
|
||||
dsb
|
||||
bx lr
|
||||
|
||||
.section .text.cp15_flush_dcache_for_dma
|
||||
.global cp15_flush_dcache_for_dma
|
||||
cp15_flush_dcache_for_dma:
|
||||
mrc p15, 0, r3, c0, c0, 1 // read Cache Type Register
|
||||
lsr r3, r3, #16
|
||||
and r3, r3, #0xf // DminLine
|
||||
mov r2, #4
|
||||
mov r2, r2, lsl r3 // cache line size, in bytes (4*2^DminLine)
|
||||
|
||||
sub r3, r2, #1 // cache line mask
|
||||
bic r0, r0, r3 // address of the first cache line
|
||||
5:
|
||||
mcr p15, 0, r0, c7, c14, 1 // DCCIMVAC()
|
||||
add r0, r0, r2
|
||||
cmp r0, r1
|
||||
blo 5b
|
||||
dsb
|
||||
bx lr
|
|
@ -0,0 +1,420 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file */
|
||||
|
||||
MODULE ?cp15
|
||||
|
||||
/* Forward declaration of sections. */
|
||||
SECTION IRQ_STACK:DATA:NOROOT(2)
|
||||
SECTION CSTACK:DATA:NOROOT(3)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Functions to access CP15 coprocessor register
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
SECTION .cp15_read_id:CODE:NOROOT(2)
|
||||
PUBLIC cp15_read_id
|
||||
cp15_read_id:
|
||||
mov r0, #0
|
||||
mrc p15, 0, r0, c0, c0, 0 ; read MIDR
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_isb:CODE:NOROOT(2)
|
||||
PUBLIC cp15_isb
|
||||
cp15_isb:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 4 ; CP15ISB()
|
||||
nop
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_dsb:CODE:NOROOT(2)
|
||||
PUBLIC cp15_dsb
|
||||
cp15_dsb:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c10, 4 ; CP15DSB()
|
||||
nop
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_dmb:CODE:NOROOT(2)
|
||||
PUBLIC cp15_dmb
|
||||
cp15_dmb:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c10, 5 ; CP15DMB()
|
||||
nop
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_invalidate_tlb:CODE:NOROOT(2)
|
||||
PUBLIC cp15_invalidate_tlb
|
||||
cp15_invalidate_tlb:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c8, c7, 0 ; TLBIALL()
|
||||
dsb
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_exclusive_cache:CODE:NOROOT(2)
|
||||
PUBLIC cp15_exclusive_cache
|
||||
cp15_exclusive_cache:
|
||||
mov r0, #0
|
||||
mrc p15, 0, r0, c1, c0, 1 ; Read ACTLR
|
||||
orr r0, r0, #0x00000080 ; Set EXCL
|
||||
mcr p15, 0, r0, c1, c0, 1 ; Write ACTLR
|
||||
nop
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_non_exclusive_cache:CODE:NOROOT(2)
|
||||
PUBLIC cp15_non_exclusive_cache
|
||||
cp15_non_exclusive_cache:
|
||||
mov r0, #0
|
||||
mrc p15, 0, r0, c1, c0, 1 ; Read ACTLR
|
||||
bic r0, r0, #0x00000080 ; Clear EXCL
|
||||
mcr p15, 0, r0, c1, c0, 1 ; Write ACTLR
|
||||
nop
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_select_icache:CODE:NOROOT(2)
|
||||
PUBLIC cp15_select_icache
|
||||
cp15_select_icache:
|
||||
mrc p15, 2, r0, c0, c0, 0 ; Read CSSELR
|
||||
orr r0, r0, #0x1 ; Set InD: cache type = ICache
|
||||
mcr p15, 2, r0, c0, c0, 0 ; Write CSSELR
|
||||
nop
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_select_dcache:CODE:NOROOT(2)
|
||||
PUBLIC cp15_select_dcache
|
||||
cp15_select_dcache:
|
||||
mrc p15, 2, r0, c0, c0, 0 ; Read CSSELR
|
||||
and r0, r0, #0xFFFFFFFE ; Clear InD: cache type = DCache
|
||||
mcr p15, 2, r0, c0, c0, 0 ; Write CSSELR
|
||||
nop
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_read_control:CODE:NOROOT(2)
|
||||
PUBLIC cp15_read_control
|
||||
cp15_read_control:
|
||||
mov r0, #0
|
||||
mrc p15, 0, r0, c1, c0, 0 ; read SCTLR
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_write_control:CODE:NOROOT(2)
|
||||
PUBLIC cp15_write_control
|
||||
cp15_write_control:
|
||||
mcr p15, 0, r0, c1, c0, 0 ; rewrite SCTLR
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_write_domain_access_control:CODE:NOROOT(2)
|
||||
PUBLIC cp15_write_domain_access_control
|
||||
cp15_write_domain_access_control:
|
||||
mcr p15, 0, r0, c3, c0, 0 ; rewrite DACR
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_write_ttb:CODE:NOROOT(2)
|
||||
PUBLIC cp15_write_ttb
|
||||
cp15_write_ttb:
|
||||
mcr p15, 0, r0, c2, c0, 0 ; rewrite TTBR0
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_invalid_icache_inner_sharable:CODE:NOROOT(2)
|
||||
PUBLIC cp15_invalid_icache_inner_sharable
|
||||
cp15_invalid_icache_inner_sharable:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c1, 0 ; ICIALLUIS()
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_invalid_btb_inner_sharable:CODE:NOROOT(2)
|
||||
PUBLIC cp15_invalid_btb_inner_sharable
|
||||
cp15_invalid_btb_inner_sharable:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c1, 6 ; BPIALLIS()
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_invalid_icache:CODE:NOROOT(2)
|
||||
PUBLIC cp15_invalid_icache
|
||||
cp15_invalid_icache:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 0 ; ICIALLU()
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_invalid_icache_by_mva:CODE:NOROOT(2)
|
||||
PUBLIC cp15_invalid_icache_by_mva
|
||||
cp15_invalid_icache_by_mva:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 1 ; ICIMVAU()
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_invalid_btb:CODE:NOROOT(2)
|
||||
PUBLIC cp15_invalid_btb
|
||||
cp15_invalid_btb:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c5, 6 ; BPIALL()
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_invalid_btb_by_mva:CODE:NOROOT(2)
|
||||
PUBLIC cp15_invalid_btb_by_mva
|
||||
cp15_invalid_btb_by_mva:
|
||||
mcr p15, 0, r0, c7, c5, 7 ; BPIMVA()
|
||||
bx lr
|
||||
|
||||
/***********************************************************
|
||||
* Data Cache related maintenance functions
|
||||
***********************************************************/
|
||||
|
||||
SECTION .cp15_invalid_dcache_by_set_way:CODE:NOROOT(2)
|
||||
PUBLIC cp15_invalid_dcache_by_set_way
|
||||
cp15_invalid_dcache_by_set_way:
|
||||
push {r1-r4}
|
||||
mrc p15, 1, r0, c0, c0, 0 ; Read CCSIDR
|
||||
mov r1, r0, lsr #3 ; Get Associativity (num of ways)
|
||||
and r1, r1, #3 ; 3 is specific to CortexA5 with 32 KB
|
||||
mov r2, r0, lsr #13 ; Get NumSets (num of sets)
|
||||
and r2, r2, #0xFF ; 8bit is specific to CortexA5 with 32 KB
|
||||
mov r0, #0 ; 0:SHL:5
|
||||
dinv_way_loop:
|
||||
lsl r4, r1, #30
|
||||
mov r3, r2
|
||||
dinv_set_loop:
|
||||
orr r0, r4, r3, lsl #5
|
||||
mcr p15, 0, r0, c7, c6, 2 ; DCISW()
|
||||
subs r3, r3, #1 ; 1:SHL:30
|
||||
bpl dinv_set_loop
|
||||
subs r1, r1, #1
|
||||
bpl dinv_way_loop
|
||||
dsb
|
||||
pop {r1-r4}
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_clean_dcache_by_set_way:CODE:NOROOT(2)
|
||||
PUBLIC cp15_clean_dcache_by_set_way
|
||||
cp15_clean_dcache_by_set_way:
|
||||
push {r1-r4}
|
||||
mrc p15, 1, r0, c0, c0, 0 ; Read CCSIDR
|
||||
mov r1, r0, lsr #3 ; Get Associativity (num of ways)
|
||||
and r1, r1, #3 ; 3 is specific to CortexA5 with 32 KB
|
||||
mov r2, r0, lsr #13 ; Get NumSets (num of sets)
|
||||
and r2, r2, #0xFF ; 8bit is specific to CortexA5 with 32 KB
|
||||
mov r0, #0 ; 0:SHL:5
|
||||
dclean_way_loop:
|
||||
lsl r4, r1, #30
|
||||
mov r3, r2
|
||||
dclean_set_loop:
|
||||
orr r0, r4, r3, lsl #5
|
||||
mcr p15, 0, r0, c7, c10, 2 ; DCCSW()
|
||||
subs r3, r3, #1 ; 1:SHL:30
|
||||
bpl dclean_set_loop
|
||||
subs r1, r1, #1
|
||||
bpl dclean_way_loop
|
||||
dsb
|
||||
pop {r1-r4}
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_clean_invalid_dcache_by_set_way:CODE:NOROOT(2)
|
||||
PUBLIC cp15_clean_invalid_dcache_by_set_way
|
||||
cp15_clean_invalid_dcache_by_set_way:
|
||||
push {r1-r4}
|
||||
mrc p15, 1, r0, c0, c0, 0 ; Read CCSIDR
|
||||
mov r1, r0, lsr #3 ; Get Associativity (num of ways)
|
||||
and r1, r1, #3 ; 3 is specific to CortexA5 with 32 KB
|
||||
mov r2, r0, lsr #13 ; Get NumSets (num of sets)
|
||||
and r2, r2, #0xFF ; 8bit is specific to CortexA5 with 32 KB
|
||||
mov r0, #0 ; 0:SHL:5
|
||||
dclinv_way_loop:
|
||||
lsl r4, r1, #30
|
||||
mov r3, r2
|
||||
dclinv_set_loop:
|
||||
orr r0, r4, r3, lsl #5
|
||||
mcr p15, 0, r0, c7, c14, 2 ; DCCISW()
|
||||
subs r3, r3, #1 ; 1:SHL:30
|
||||
bpl dclinv_set_loop
|
||||
subs r1, r1, #1
|
||||
bpl dclinv_way_loop
|
||||
dsb
|
||||
pop {r1-r4}
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_invalid_dcache_by_mva:CODE:NOROOT(2)
|
||||
PUBLIC cp15_invalid_dcache_by_mva
|
||||
cp15_invalid_dcache_by_mva:
|
||||
mov r2, #0x20 ; Eight words per line, Cortex-A5 L1 Line Size 32 Bytes
|
||||
mov r3, r0
|
||||
inv_loop:
|
||||
mcr p15, 0, r0, c7, c6, 1 ; DCIMVAC()
|
||||
add r3, r3, r2
|
||||
cmp r3, r1
|
||||
bls inv_loop
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_clean_dcache_by_mva:CODE:NOROOT(2)
|
||||
PUBLIC cp15_clean_dcache_by_mva
|
||||
cp15_clean_dcache_by_mva:
|
||||
mov r2, #0x20 ; Eight words per line, Cortex-A5 L1 Line Size 32 Bytes
|
||||
mov r3, r0
|
||||
clean_loop:
|
||||
mcr p15, 0, r0, c7, c10, 1 ; DCCMVAC()
|
||||
add r3, r3, r2
|
||||
cmp r3, r1
|
||||
bls clean_loop
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_clean_dcache_umva:CODE:NOROOT(2)
|
||||
PUBLIC cp15_clean_dcache_umva
|
||||
cp15_clean_dcache_umva:
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c11, 1 ; DCCMVAU()
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_clean_invalid_dcache_by_mva:CODE:NOROOT(2)
|
||||
PUBLIC cp15_clean_invalid_dcache_by_mva
|
||||
cp15_clean_invalid_dcache_by_mva:
|
||||
mov r2, #0x20 ; Eight words per line, Cortex-A5 L1 Line Size 32 Bytes
|
||||
mov r3, r0
|
||||
clinv_loop:
|
||||
mcr p15, 0, r0, c7, c14, 1 ; DCCIMVAC()
|
||||
add r3, r3, r2
|
||||
cmp r3, r1
|
||||
bls clinv_loop
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_coherent_dcache_for_dma:CODE:NOROOT(2)
|
||||
PUBLIC cp15_coherent_dcache_for_dma
|
||||
cp15_coherent_dcache_for_dma:
|
||||
push {r2-r4}
|
||||
mrc p15, 0, r3, c0, c0, 1 ; read Cache Type Register
|
||||
lsr r3, r3, #16
|
||||
and r3, r3, #0xf ; DminLine
|
||||
mov r2, #4
|
||||
mov r2, r2, lsl r3 ; cache line size, in bytes (4*2^DminLine)
|
||||
|
||||
sub r3, r2, #1 ; cache line mask
|
||||
bic r4, r0, r3 ; address of the first cache line
|
||||
loop1:
|
||||
mcr p15, 0, r4, c7, c11, 1 ; DCCMVAU()
|
||||
add r4, r4, r2
|
||||
cmp r4, r1
|
||||
blo loop1
|
||||
dsb
|
||||
|
||||
bic r4, r0, r3
|
||||
loop2:
|
||||
mcr p15, 0, r4, c7, c5, 1 ; ICIMVAU()
|
||||
add r4, r4, r2
|
||||
cmp r4, r1
|
||||
blo loop2
|
||||
mov r0, #0
|
||||
mcr p15, 0, r0, c7, c1, 6 ; BPIALLIS()
|
||||
mcr p15, 0, r0, c7, c5, 6 ; BPIALL()
|
||||
dsb
|
||||
isb
|
||||
pop {r2-r4}
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_invalidate_dcache_for_dma:CODE:NOROOT(2)
|
||||
PUBLIC cp15_invalidate_dcache_for_dma
|
||||
cp15_invalidate_dcache_for_dma:
|
||||
push {r2-r3}
|
||||
mrc p15, 0, r3, c0, c0, 1 ; read CP15 Cache Type Register
|
||||
lsr r3, r3, #16
|
||||
and r3, r3, #0xf ; DminLine
|
||||
mov r2, #4
|
||||
mov r2, r2, lsl r3 ; cache line size, in bytes (4*2^DminLine)
|
||||
|
||||
sub r3, r2, #1 ; cache line mask
|
||||
bic r0, r0, r3 ; address of the first cache line
|
||||
loop3:
|
||||
mcr p15, 0, r0, c7, c6, 1 ; CP15:DCIMVAC(r0)
|
||||
add r0, r0, r2
|
||||
cmp r0, r1 ; while ('cache line address' < 'end')
|
||||
blo loop3
|
||||
dsb
|
||||
pop {r2-r3}
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_clean_dcache_for_dma:CODE:NOROOT(2)
|
||||
PUBLIC cp15_clean_dcache_for_dma
|
||||
cp15_clean_dcache_for_dma:
|
||||
mrc p15, 0, r3, c0, c0, 1 ; read Cache Type Register
|
||||
lsr r3, r3, #16
|
||||
and r3, r3, #0xf ; DminLine
|
||||
mov r2, #4
|
||||
mov r2, r2, lsl r3 ; cache line size, in bytes (4*2^DminLine)
|
||||
|
||||
sub r3, r2, #1 ; cache line mask
|
||||
bic r0, r0, r3 ; address of the first cache line
|
||||
loop4:
|
||||
mcr p15, 0, r0, c7, c10, 1 ; DCCMVAC()
|
||||
add r0, r0, r2
|
||||
cmp r0, r1
|
||||
blo loop4
|
||||
dsb
|
||||
bx lr
|
||||
|
||||
SECTION .cp15_flush_dcache_for_dma:CODE:NOROOT(2)
|
||||
PUBLIC cp15_flush_dcache_for_dma
|
||||
cp15_flush_dcache_for_dma:
|
||||
mrc p15, 0, r3, c0, c0, 1 ; read Cache Type Register
|
||||
lsr r3, r3, #16
|
||||
and r3, r3, #0xf ; DminLine
|
||||
mov r2, #4
|
||||
mov r2, r2, lsl r3 ; cache line size, in bytes (4*2^DminLine)
|
||||
|
||||
sub r3, r2, #1 ; cache line mask
|
||||
bic r0, r0, r3 ; address of the first cache line
|
||||
loop5:
|
||||
mcr p15, 0, r0, c7, c14, 1 ; DCCIMVAC()
|
||||
add r0, r0, r2
|
||||
cmp r0, r1
|
||||
blo loop5
|
||||
dsb
|
||||
bx lr
|
||||
|
||||
END
|
|
@ -0,0 +1,252 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file */
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
#if defined(__ICCARM__)
|
||||
#include <intrinsics.h>
|
||||
#endif
|
||||
|
||||
#include "cortex-a/cp15_pmu.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Global functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Resets the counter and enables/disables all counters including PMCCNTR.
|
||||
* \param ResetCounterType CounterType: Performance or Cycle counter
|
||||
*/
|
||||
static void cp15_pmu_control(uint8_t ResetCounterType, uint8_t EnableCounter)
|
||||
{
|
||||
uint32_t PMU_Value = 0;
|
||||
|
||||
asm("mrc p15, 0, %0, c9, c12, 0":"=r"(PMU_Value));
|
||||
PMU_Value |= ((ResetCounterType << 1) | EnableCounter);
|
||||
asm("mcr p15, 0, %0, c9, c12, 0": :"r"(PMU_Value));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Select Cycle Count divider
|
||||
* \param Divider 0 for increment of counter at every single cycle or 1 for at every 64th cycle
|
||||
*/
|
||||
static void cp15_cycle_count_divider(uint8_t Divider)
|
||||
{
|
||||
uint32_t PMU_Value = 0;
|
||||
assert((Divider > 1 ? 0 : 1));
|
||||
asm("mrc p15, 0, %0, c9, c12, 0":"=r"(PMU_Value));
|
||||
PMU_Value |= (Divider << 3);
|
||||
asm("mcr p15, 0, %0, c9, c12, 0": :"r"(PMU_Value));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enables PMCCNTR.
|
||||
*/
|
||||
static void cp15_enable_PMCNT(void)
|
||||
{
|
||||
uint32_t CNT_Value = 0;
|
||||
asm("mrc p15, 0, %0, c9, c12, 1":"=r"(CNT_Value));
|
||||
CNT_Value |= (uint32_t) ((1 << CP15_PMCNTENSET));
|
||||
asm("mcr p15, 0, %0, c9, c12, 1": :"r"(CNT_Value));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enables PMCCNTR.
|
||||
*/
|
||||
static void cp15_enable_counter(uint8_t Counter)
|
||||
{
|
||||
uint32_t CNT_Value = 0;
|
||||
asm("mrc p15, 0, %0, c9, c12, 1":"=r"(CNT_Value));
|
||||
CNT_Value |= Counter;
|
||||
asm("mcr p15, 0, %0, c9, c12, 1": :"r"(CNT_Value));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disables/clear PMCCNTR.
|
||||
* \param Counter 0 or 1 to selct counter
|
||||
*/
|
||||
|
||||
static void cp15_clear_PMCNT(void)
|
||||
{
|
||||
uint32_t CNT_Value = 0;
|
||||
asm("mrc p15, 0, %0, c9, c12, 2":"=r"(CNT_Value));
|
||||
CNT_Value |= (uint32_t) (1 << CP15_PMCNTENCLEAR);
|
||||
asm("mcr p15, 0, %0, c9, c12, 2": :"r"(CNT_Value));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disables/Enables overflow flag.
|
||||
* \param Enable Enables or disables the flag option
|
||||
* \param ClearCounterFlag selects the counter flag to clear
|
||||
*/
|
||||
void cp15_overflow_status(uint8_t Enable, uint8_t ClearCounterFlag)
|
||||
{
|
||||
uint32_t OFW_Value = 0;
|
||||
asm("mrc p15, 0, %0, c9, c12, 3":"=r"(OFW_Value));
|
||||
OFW_Value |= ((Enable << 31) | ClearCounterFlag);
|
||||
asm("mcr p15, 0, %0, c9, c12, 3": :"r"(OFW_Value));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disables/Enables overflow flag.
|
||||
* \param EventCounter Counter of the events
|
||||
*/
|
||||
uint32_t cp15_read_overflow_status(uint8_t EventCounter)
|
||||
{
|
||||
uint32_t OFW_Value = 0;
|
||||
asm("mrc p15, 0, %0, c9, c12, 3":"=r"(OFW_Value));
|
||||
OFW_Value = ((OFW_Value & EventCounter) >> (EventCounter - 1));
|
||||
return OFW_Value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Increments the count of a performance monitor count register.
|
||||
* \param IncrCounter 0 or 1 counters
|
||||
*/
|
||||
void cp15_soft_incr(uint8_t IncrCounter)
|
||||
{
|
||||
uint32_t INRC_Value = 0;
|
||||
asm("mrc p15, 0, %0, c9, c12, 4":"=r"(INRC_Value));
|
||||
INRC_Value |= IncrCounter;
|
||||
asm("mcr p15, 0, %0, c9, c12, 4": :"r"(INRC_Value));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Increments the count of a performance monitor count register.
|
||||
* \param EventType Select Event Type
|
||||
* \param Counter 0 or 1 counters
|
||||
*/
|
||||
static void cp15_select_event(PerfEventType EventType, uint8_t Counter)
|
||||
{
|
||||
uint32_t CounterSelect = 0;
|
||||
assert((Counter == 1) || (Counter == 2));
|
||||
CounterSelect = (Counter & 0x1F);
|
||||
asm("mcr p15, 0, %0, c9, c12, 5": :"r"(CounterSelect));
|
||||
CounterSelect = (EventType & 0xFF);
|
||||
asm("mcr p15, 0, %0, c9, c13, 1": :"r"(CounterSelect));
|
||||
// PMXEVTYPER
|
||||
asm("mrc p15, 0, %0, c9, c13, 1":"=r"(CounterSelect));
|
||||
// PMXEVTYPER
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enables USER mode
|
||||
*/
|
||||
void cp15_enable_user_mode(void)
|
||||
{
|
||||
uint8_t Value = 1;
|
||||
asm("mcr p15, 0, %0, c9, c14, 0": :"r"(Value));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enables Oveflows interrupt
|
||||
* \param Enable Enables the Interrupt
|
||||
* \param Counter 0 or 1 counters
|
||||
*/
|
||||
void cp15_enable_interrupt(uint8_t Enable, uint8_t Counter)
|
||||
{
|
||||
uint32_t ITE_Value = 0;
|
||||
ITE_Value |= ((Enable << 31) | Counter);
|
||||
asm("mcr p15, 0, %0, c9, c14, 1": :"r"(ITE_Value));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disables Oveflows interrupt
|
||||
* \param Disable Disables the Interrupt
|
||||
* \param Counter 0 or 1 counters
|
||||
*/
|
||||
void cp15_disable_interrupt(uint8_t Disable, uint8_t Counter)
|
||||
{
|
||||
uint32_t ITE_Value = 0;
|
||||
ITE_Value |= ((Disable << 31) | Counter);
|
||||
asm("mcr p15, 0, %0, c9, c14, 2": :"r"(ITE_Value));
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initialize Cycle counter with Divider 64
|
||||
*/
|
||||
uint32_t cp15_init_cycle_counter(void)
|
||||
{
|
||||
uint32_t value;
|
||||
cp15_clear_PMCNT();
|
||||
cp15_enable_PMCNT();
|
||||
cp15_overflow_status(true, CP15_BothCounter);
|
||||
cp15_cycle_count_divider(CP15_CountDivider64);
|
||||
cp15_pmu_control(CP15_ResetCycCounter, true);
|
||||
|
||||
asm("mrc p15, 0, %0, c9, c13, 0":"=r"(value));
|
||||
return value;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initialize Performance monitor counter with Divider 64
|
||||
* \param Event Event type
|
||||
* \param Counter 0 or 1 counters
|
||||
*/
|
||||
|
||||
void cp15_init_perf_counter(PerfEventType Event, uint8_t Counter)
|
||||
{
|
||||
cp15_pmu_control(CP15_ResetPerCounter, true);
|
||||
cp15_select_event(Event, Counter);
|
||||
cp15_overflow_status(false, CP15_BothCounter);
|
||||
cp15_enable_counter(Counter);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief gives total number of event count
|
||||
* \param Counter 0 or 1 counters
|
||||
*/
|
||||
uint32_t cp15_count_evt(uint8_t Counter)
|
||||
{
|
||||
uint32_t value;
|
||||
asm("mcr p15, 0, %0, c9, c12, 5": :"r"(Counter));
|
||||
asm("mrc p15, 0, %0, c9, c13, 2":"=r"(value));
|
||||
// PMXEVTYPER
|
||||
return (value);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief gives total number of cycle count
|
||||
|
||||
*/
|
||||
uint32_t cp15_get_cycle_counter(void)
|
||||
{
|
||||
uint32_t value;
|
||||
asm("mrc p15, 0, %0, c9, c13, 0":"=r"(value));
|
||||
return value;
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _CP15_PMU_H
|
||||
#define _CP15_PMU_H
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Definition
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#define CP15_PMCNTENSET 31
|
||||
#define CP15_PMCNTENCLEAR 31
|
||||
#define CP15_PMCR_DIVIDER 3
|
||||
#define CP15_PMCR_RESET 2
|
||||
#define CP15_PMCR_ENABLE 0
|
||||
|
||||
#define CP15_NoReset 0
|
||||
#define CP15_ResetPerCounter 1
|
||||
#define CP15_ResetCycCounter 2
|
||||
#define CP15_ResetPerCycCounter 3
|
||||
|
||||
#define CP15_CountDividerSingle 0
|
||||
#define CP15_CountDivider64 1
|
||||
|
||||
#define CP15_CounterNone 0
|
||||
#define CP15_Counter0 1
|
||||
#define CP15_Counter1 2
|
||||
#define CP15_BothCounter 3
|
||||
|
||||
typedef enum {
|
||||
L1_IC_FILL, // Level 1 instruction cache refill
|
||||
L1_ITLB_FILL, // Level 1 instruction TLB refill
|
||||
L1_DC_FILL, // Level 1 data cache refill
|
||||
L1_DC_ACC, // Level 1 data cache access
|
||||
L1_DTLB_FILL, // Level 1 data TLB refill
|
||||
LOAD, // Load
|
||||
STORE, // Store
|
||||
InstArchExec, // Instruction architecturally executed
|
||||
ExcepetionTaken, // Exception taken
|
||||
ExcepetionRet, // Exception return
|
||||
WrCONTEXTIDR, // Write to CONTEXTIDR
|
||||
SoftPCChange, // Software change of the PC
|
||||
ImmBr, // Immediate branch
|
||||
ProcRet, // Procedure return
|
||||
UnalingedLdStr, // Unaligned load or store
|
||||
MispredictedBranchExec, // Mispredicted or not predicted branch speculatively executed
|
||||
PredictedBranchExec, // Predictable branch speculatively executed
|
||||
DataMemAcc, // Data memory access.
|
||||
ICAcc, // Instruction Cache access.
|
||||
DCEviction, // Data cache eviction.
|
||||
IRQException, // IRQ exception taken.
|
||||
FIQException, // FIQ exception taken.
|
||||
ExtMemReq, // External memory request.
|
||||
NCExtMemReq, // Non-cacheable external memory request
|
||||
PrefetchLineFill, // Linefill because of prefetch.
|
||||
PrefetchLineDrop, // Prefetch linefill dropped.
|
||||
EnteringRAmode, // Entering read allocate mode.
|
||||
RAmode, // Read allocate mode.
|
||||
reserved, // Reserved, do not use
|
||||
DWstallSBFfull // Data Write operation that stalls the pipeline because the store buffer is full.
|
||||
} PerfEventType;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
extern uint32_t cp15_init_cycle_counter(void);
|
||||
extern uint32_t cp15_get_cycle_counter(void);
|
||||
|
||||
extern uint32_t cp15_read_overflow_status(uint8_t EventCounter);
|
||||
extern void cp15_overflow_status(uint8_t Enable, uint8_t ClearCounterFlag);
|
||||
extern void cp15_soft_incr(uint8_t IncrCounter);
|
||||
|
||||
extern uint32_t cp15_count_evt(uint8_t Counter);
|
||||
extern void cp15_enable_user_mode(void);
|
||||
extern void cp15_enable_interrupt(uint8_t Enable, uint8_t Counter);
|
||||
extern void cp15_disable_interrupt(uint8_t Disable, uint8_t Counter);
|
||||
extern void cp15_init_perf_counter(PerfEventType Event, uint8_t Counter);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,43 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#ifndef CPSR_HEARDER_
|
||||
#define CPSR_HEARDER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define CPSR_MASK_IRQ 0x00000080
|
||||
#define CPSR_MASK_FIQ 0x00000040
|
||||
|
||||
extern void v_arm_clr_cpsr_bits(uint32_t mask);
|
||||
|
||||
extern void v_arm_set_cpsr_bits(uint32_t mask);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,55 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file */
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Functions to access CPSR
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
.section .text.v_arm_clr_cpsr_bits
|
||||
.global v_arm_clr_cpsr_bits
|
||||
v_arm_clr_cpsr_bits:
|
||||
push {r1}
|
||||
mrs r1, cpsr
|
||||
mvn r0, r0
|
||||
and r1, r1,r0
|
||||
msr CPSR_c, r1
|
||||
pop {r1}
|
||||
bx lr
|
||||
|
||||
.section .text.v_arm_set_cpsr_bits
|
||||
.global v_arm_set_cpsr_bits
|
||||
v_arm_set_cpsr_bits:
|
||||
push {r1}
|
||||
mrs r1, cpsr
|
||||
orr r1, r1, r0
|
||||
msr cpsr_c, r1
|
||||
pop {r1}
|
||||
bx lr
|
|
@ -0,0 +1,63 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file */
|
||||
|
||||
MODULE ?cpsr
|
||||
|
||||
/* Forward declaration of sections. */
|
||||
SECTION IRQ_STACK:DATA:NOROOT(2)
|
||||
SECTION CSTACK:DATA:NOROOT(3)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Functions to access CPSR
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
SECTION .v_arm_clr_cpsr_bits:CODE:NOROOT(2)
|
||||
PUBLIC v_arm_clr_cpsr_bits
|
||||
v_arm_clr_cpsr_bits:
|
||||
push {r1}
|
||||
mrs r1, cpsr
|
||||
mvn r0, r0
|
||||
and r1, r1,r0
|
||||
msr CPSR_c, r1
|
||||
pop {r1}
|
||||
bx lr
|
||||
|
||||
SECTION .v_arm_set_cpsr_bits:CODE:NOROOT(2)
|
||||
PUBLIC v_arm_set_cpsr_bits
|
||||
v_arm_set_cpsr_bits:
|
||||
push {r1}
|
||||
mrs r1, cpsr
|
||||
orr r1, r1, r0
|
||||
msr cpsr_c, r1
|
||||
pop {r1}
|
||||
bx lr
|
||||
|
||||
END
|
|
@ -0,0 +1,89 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file */
|
||||
|
||||
/**
|
||||
* \addtogroup mmu MMU Initialization
|
||||
*
|
||||
* \section Usage
|
||||
*
|
||||
* Translation Lookaside Buffers (TLBs) are an implementation technique that caches translations or
|
||||
* translation table entries. TLBs avoid the requirement for every memory access to perform a translation table
|
||||
* lookup. The ARM architecture does not specify the exact form of the TLB structures for any design. In a
|
||||
* similar way to the requirements for caches, the architecture only defines certain principles for TLBs:
|
||||
*
|
||||
* The MMU supports memory accesses based on memory sections or pages:
|
||||
* Supersections Consist of 16MB blocks of memory. Support for Supersections is optional.
|
||||
* -# Sections Consist of 1MB blocks of memory.
|
||||
* -# Large pages Consist of 64KB blocks of memory.
|
||||
* -# Small pages Consist of 4KB blocks of memory.
|
||||
*
|
||||
* Access to a memory region is controlled by the access permission bits and the domain field in the TLB entry.
|
||||
* Memory region attributes
|
||||
* Each TLB entry has an associated set of memory region attributes. These control accesses to the caches,
|
||||
* how the write buffer is used, and if the memory region is Shareable and therefore must be kept coherent.
|
||||
*
|
||||
* Related files:\n
|
||||
* \ref mmu.c\n
|
||||
* \ref mmu.h \n
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------ */
|
||||
/* Headers */
|
||||
/*------------------------------------------------------------------------------ */
|
||||
|
||||
#include "chip.h"
|
||||
#include "board.h"
|
||||
#include "cortex-a/cp15.h"
|
||||
#include "cortex-a/mmu.h"
|
||||
|
||||
#include "compiler.h"
|
||||
|
||||
/*------------------------------------------------------------------------------ */
|
||||
/* Local variables */
|
||||
/*------------------------------------------------------------------------------ */
|
||||
|
||||
ALIGNED(16384) static uint32_t _tlb[4096];
|
||||
|
||||
/*------------------------------------------------------------------------------ */
|
||||
/* Exported functions */
|
||||
/*------------------------------------------------------------------------------ */
|
||||
|
||||
void mmu_initialize(void)
|
||||
{
|
||||
board_setup_tlb(_tlb);
|
||||
cp15_write_ttb((unsigned int)_tlb);
|
||||
/* Program the domain access register */
|
||||
/* only domain 15: access are not checked */
|
||||
cp15_write_domain_access_control(0xC0000000);
|
||||
asm volatile("": : :"memory");
|
||||
asm("dsb");
|
||||
asm("isb");
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _MMU_
|
||||
#define _MMU_
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported definitions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#define TTB_TYPE(x) ((x) << 0)
|
||||
#define TTB_TYPE_SECT TTB_TYPE(2)
|
||||
|
||||
#define TTB_SECT_B(x) ((x) << 2)
|
||||
#define TTB_SECT_WRITE_THROUGH TTB_SECT_B(0)
|
||||
#define TTB_SECT_WRITE_BACK TTB_SECT_B(1)
|
||||
|
||||
#define TTB_SECT_C(x) ((x) << 3)
|
||||
#define TTB_SECT_NON_CACHEABLE TTB_SECT_C(0)
|
||||
#define TTB_SECT_CACHEABLE TTB_SECT_C(1)
|
||||
|
||||
#define TTB_SECT_XN(x) ((x) << 4)
|
||||
#define TTB_SECT_EXEC TTB_SECT_XN(0)
|
||||
#define TTB_SECT_EXEC_NEVER TTB_SECT_XN(1)
|
||||
|
||||
#define TTB_SECT_DOMAIN(x) ((x) << 5)
|
||||
|
||||
#define TTB_SECT_AP(x) ((x) << 10)
|
||||
#define TTB_SECT_APX(x) ((x) << 15)
|
||||
#define TTB_SECT_AP_PRIV_ONLY (TTB_SECT_APX(0) | TTB_SECT_AP(1))
|
||||
#define TTB_SECT_AP_NO_USER_WRITE (TTB_SECT_APX(0) | TTB_SECT_AP(2))
|
||||
#define TTB_SECT_AP_FULL_ACCESS (TTB_SECT_APX(0) | TTB_SECT_AP(3))
|
||||
#define TTB_SECT_AP_PRIV_READ_ONLY (TTB_SECT_APX(1) | TTB_SECT_AP(1))
|
||||
#define TTB_SECT_AP_READ_ONLY (TTB_SECT_APX(1) | TTB_SECT_AP(2))
|
||||
|
||||
#define TTB_SECT_TEX(x) ((x) << 12)
|
||||
#define TTB_SECT_STRONGLY_ORDERED (TTB_SECT_TEX(0) | TTB_SECT_NON_CACHEABLE | TTB_SECT_WRITE_THROUGH)
|
||||
#define TTB_SECT_SHAREABLE_DEVICE (TTB_SECT_TEX(0) | TTB_SECT_NON_CACHEABLE | TTB_SECT_WRITE_BACK)
|
||||
#define TTB_SECT_CACHEABLE_WT (TTB_SECT_TEX(0) | TTB_SECT_CACHEABLE | TTB_SECT_WRITE_THROUGH)
|
||||
#define TTB_SECT_CACHEABLE_WB (TTB_SECT_TEX(0) | TTB_SECT_CACHEABLE | TTB_SECT_WRITE_BACK)
|
||||
|
||||
#define TTB_SECT_ADDR(x) ((x) & 0xFFF00000)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief initializes the MMU
|
||||
*/
|
||||
extern void mmu_initialize(void);
|
||||
|
||||
#endif /* #ifndef _MMU_ */
|
|
@ -0,0 +1,32 @@
|
|||
# ----------------------------------------------------------------------------
|
||||
# SAM Software Package License
|
||||
# ----------------------------------------------------------------------------
|
||||
# Copyright (c) 2015, Atmel Corporation
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# - Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the disclaimer below.
|
||||
#
|
||||
# Atmel's name may not be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
drivers-y += drivers/misc/console.o
|
||||
drivers-y += drivers/misc/led.o
|
||||
|
||||
drivers-$(CONFIG_SOC_SAMA5D2) += drivers/misc/bmp280.o
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,444 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
/*! \file bmp280.h
|
||||
\brief BMP280 Sensor Driver Support Header File */
|
||||
|
||||
#ifndef __BMP280_H__
|
||||
#define __BMP280_H__
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Definition
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#define BMP280_64BITSUPPORT_PRESENT
|
||||
|
||||
/********************************************/
|
||||
/**\name ENABLE FLATING OUTPUT */
|
||||
/**************************************/
|
||||
|
||||
// If the user wants to support floating point calculations, please set the following define.
|
||||
#define BMP280_ENABLE_FLOAT
|
||||
|
||||
// If the user wants to support 64 bit integer calculation (needed for optimal pressure accuracy)
|
||||
// please set the following definition. If int64 calculation is not wanted (e.g. because it would include
|
||||
// large libraries), please do not set the definition.
|
||||
#define BMP280_ENABLE_INT64
|
||||
|
||||
/****************************************/
|
||||
/**\name DELAY */
|
||||
/****************************************/
|
||||
|
||||
// defines the return parameter type of the BMP280_DELAY_FUNCTION
|
||||
#define BMP280_DELAY_RETURN_TYPE void
|
||||
|
||||
// defines the calling parameter types of the BMP280_DELAY_FUNCTION
|
||||
#define BMP280_DELAY_PARAM_TYPES uint16_t
|
||||
|
||||
/***************************************************************/
|
||||
/**\name GET AND SET BITSLICE FUNCTIONS */
|
||||
/***************************************************************/
|
||||
|
||||
/* never change this line */
|
||||
#define BMP280_DELAY_FUNC(delay_in_msec) delay_func(delay_in_msec)
|
||||
|
||||
#define BMP280_GET_BITSLICE(regvar, bitname) ((regvar & bitname##__MSK) >> bitname##__POS)
|
||||
|
||||
#define BMP280_SET_BITSLICE(regvar, bitname, val) ((regvar & ~bitname##__MSK) | ((val<<bitname##__POS)&bitname##__MSK))
|
||||
|
||||
/***************************************************************/
|
||||
/**\name COMMON USED CONSTANTS */
|
||||
/***************************************************************/
|
||||
/* Constants */
|
||||
#define BMP280_NULL 0
|
||||
#define BMP280_INIT_VALUE 0
|
||||
|
||||
/************************************************/
|
||||
/**\name ERROR CODES */
|
||||
/************************************************/
|
||||
#define SUCCESS ((uint8_t)0)
|
||||
#define ERROR ((uint8_t)0xFF)
|
||||
#define E_BMP280_NULL_PTR ((uint8_t)ERROR-1)
|
||||
#define E_BMP280_COMM_RES ((uint8_t)ERROR-2)
|
||||
#define E_BMP280_OUT_OF_RANGE ((uint8_t)ERROR-3)
|
||||
|
||||
/************************************************/
|
||||
/**\name I2C ADDRESS DEFINITION */
|
||||
/***********************************************/
|
||||
#define BMP280_I2C_ADDRESS1 0x76
|
||||
#define BMP280_I2C_ADDRESS2 0x77
|
||||
/************************************************/
|
||||
/**\name POWER MODE DEFINITION */
|
||||
/***********************************************/
|
||||
/* Sensor Specific constants */
|
||||
#define BMP280_SLEEP_MODE 0x00
|
||||
#define BMP280_FORCED_MODE 0x01
|
||||
#define BMP280_NORMAL_MODE 0x03
|
||||
#define BMP280_SOFT_RESET_CODE 0xB6
|
||||
/************************************************/
|
||||
/**\name STANDBY TIME DEFINITION */
|
||||
/***********************************************/
|
||||
#define BMP280_STANDBY_TIME_1_MS 0x00
|
||||
#define BMP280_STANDBY_TIME_63_MS 0x01
|
||||
#define BMP280_STANDBY_TIME_125_MS 0x02
|
||||
#define BMP280_STANDBY_TIME_250_MS 0x03
|
||||
#define BMP280_STANDBY_TIME_500_MS 0x04
|
||||
#define BMP280_STANDBY_TIME_1000_MS 0x05
|
||||
#define BMP280_STANDBY_TIME_2000_MS 0x06
|
||||
#define BMP280_STANDBY_TIME_4000_MS 0x07
|
||||
/************************************************/
|
||||
/**\name OVERSAMPLING DEFINITION */
|
||||
/***********************************************/
|
||||
#define BMP280_OVERSAMPLING_SKIPPED 0x00
|
||||
#define BMP280_OVERSAMP_1X 0x01
|
||||
#define BMP280_OVERSAMP_2X 0x02
|
||||
#define BMP280_OVERSAMP_4X 0x03
|
||||
#define BMP280_OVERSAMP_8X 0x04
|
||||
#define BMP280_OVERSAMP_16X 0x05
|
||||
/************************************************/
|
||||
/**\name WORKING MODE DEFINITION */
|
||||
/***********************************************/
|
||||
#define BMP280_ULTRA_LOW_POWER_MODE 0x00
|
||||
#define BMP280_LOW_POWER_MODE 0x01
|
||||
#define BMP280_STANDARD_RESOLUTION_MODE 0x02
|
||||
#define BMP280_HIGH_RESOLUTION_MODE 0x03
|
||||
#define BMP280_ULTRA_HIGH_RESOLUTION_MODE 0x04
|
||||
|
||||
#define BMP280_ULTRALOWPOWER_OVRS_PRES BMP280_OVERSAMP_1X
|
||||
#define BMP280_ULTRALOWPOWER_OVRS_TEMP BMP280_OVERSAMP_1X
|
||||
|
||||
#define BMP280_LOWPOWER_OVRS_PRES BMP280_OVERSAMP_2X
|
||||
#define BMP280_LOWPOWER_OVRS_TEMP BMP280_OVERSAMP_1X
|
||||
|
||||
#define BMP280_STANDARDRESOLUTION_OVRS_PRES BMP280_OVERSAMP_4X
|
||||
#define BMP280_STANDARDRESOLUTION_OVRS_TEMP BMP280_OVERSAMP_1X
|
||||
|
||||
#define BMP280_HIGHRESOLUTION_OVRS_PRES BMP280_OVERSAMP_8X
|
||||
#define BMP280_HIGHRESOLUTION_OVRS_TEMP BMP280_OVERSAMP_1X
|
||||
|
||||
#define BMP280_ULTRAHIGHRESOLUTION_OVRS_PRES BMP280_OVERSAMP_16X
|
||||
#define BMP280_ULTRAHIGHRESOLUTION_OVRS_TEMP BMP280_OVERSAMP_2X
|
||||
/************************************************/
|
||||
/**\name FILTER DEFINITION */
|
||||
/***********************************************/
|
||||
#define BMP280_FILTER_COEFF_OFF 0x00
|
||||
#define BMP280_FILTER_COEFF_2 0x01
|
||||
#define BMP280_FILTER_COEFF_4 0x02
|
||||
#define BMP280_FILTER_COEFF_8 0x03
|
||||
#define BMP280_FILTER_COEFF_16 0x04
|
||||
/************************************************/
|
||||
/**\name DELAY TIME DEFINITION */
|
||||
/***********************************************/
|
||||
#define T_INIT_MAX 20 /* 20/16 = 1.25 ms */
|
||||
#define T_MEASURE_PER_OSRS_MAX 37 /* 37/16 = 2.3125 ms*/
|
||||
#define T_SETUP_PRESSURE_MAX 10 /* 10/16 = 0.625 ms */
|
||||
/************************************************/
|
||||
/**\name CALIBRATION PARAMETERS DEFINITION */
|
||||
/***********************************************/
|
||||
/*calibration parameters */
|
||||
#define BMP280_DIG_T1_LSB_REG 0x88
|
||||
#define BMP280_DIG_T1_MSB_REG 0x89
|
||||
#define BMP280_DIG_T2_LSB_REG 0x8A
|
||||
#define BMP280_DIG_T2_MSB_REG 0x8B
|
||||
#define BMP280_DIG_T3_LSB_REG 0x8C
|
||||
#define BMP280_DIG_T3_MSB_REG 0x8D
|
||||
#define BMP280_DIG_P1_LSB_REG 0x8E
|
||||
#define BMP280_DIG_P1_MSB_REG 0x8F
|
||||
#define BMP280_DIG_P2_LSB_REG 0x90
|
||||
#define BMP280_DIG_P2_MSB_REG 0x91
|
||||
#define BMP280_DIG_P3_LSB_REG 0x92
|
||||
#define BMP280_DIG_P3_MSB_REG 0x93
|
||||
#define BMP280_DIG_P4_LSB_REG 0x94
|
||||
#define BMP280_DIG_P4_MSB_REG 0x95
|
||||
#define BMP280_DIG_P5_LSB_REG 0x96
|
||||
#define BMP280_DIG_P5_MSB_REG 0x97
|
||||
#define BMP280_DIG_P6_LSB_REG 0x98
|
||||
#define BMP280_DIG_P6_MSB_REG 0x99
|
||||
#define BMP280_DIG_P7_LSB_REG 0x9A
|
||||
#define BMP280_DIG_P7_MSB_REG 0x9B
|
||||
#define BMP280_DIG_P8_LSB_REG 0x9C
|
||||
#define BMP280_DIG_P8_MSB_REG 0x9D
|
||||
#define BMP280_DIG_P9_LSB_REG 0x9E
|
||||
#define BMP280_DIG_P9_MSB_REG 0x9F
|
||||
/************************************************/
|
||||
/**\name REGISTER ADDRESS DEFINITION */
|
||||
/***********************************************/
|
||||
#define BMP280_CHIP_ID_REG 0xD0 /*Chip ID Register */
|
||||
#define BMP280_RST_REG 0xE0 /*Softreset Register */
|
||||
#define BMP280_STAT_REG 0xF3 /*Status Register */
|
||||
#define BMP280_CTRL_MEAS_REG 0xF4 /*Ctrl Measure Register */
|
||||
#define BMP280_CONFIG_REG 0xF5 /*Configuration Register */
|
||||
#define BMP280_PRESSURE_MSB_REG 0xF7 /*Pressure MSB Register */
|
||||
#define BMP280_PRESSURE_LSB_REG 0xF8 /*Pressure LSB Register */
|
||||
#define BMP280_PRESSURE_XLSB_REG 0xF9 /*Pressure XLSB Register */
|
||||
#define BMP280_TEMPERATURE_MSB_REG 0xFA /*Temperature MSB Reg */
|
||||
#define BMP280_TEMPERATURE_LSB_REG 0xFB /*Temperature LSB Reg */
|
||||
#define BMP280_TEMPERATURE_XLSB_REG 0xFC /*Temperature XLSB Reg */
|
||||
/************************************************/
|
||||
/**\name BIT LENGTH,POSITION AND MASK DEFINITION */
|
||||
/***********************************************/
|
||||
/* Status Register */
|
||||
#define BMP280_STATUS_REG_MEASURING__POS 3
|
||||
#define BMP280_STATUS_REG_MEASURING__MSK 0x08
|
||||
#define BMP280_STATUS_REG_MEASURING__LEN 1
|
||||
#define BMP280_STATUS_REG_MEASURING__REG BMP280_STAT_REG
|
||||
|
||||
#define BMP280_STATUS_REG_IM_UPDATE__POS 0
|
||||
#define BMP280_STATUS_REG_IM_UPDATE__MSK 0x01
|
||||
#define BMP280_STATUS_REG_IM_UPDATE__LEN 1
|
||||
#define BMP280_STATUS_REG_IM_UPDATE__REG BMP280_STAT_REG
|
||||
/************************************************/
|
||||
/**\name BIT LENGTH,POSITION AND MASK DEFINITION
|
||||
FOR TEMPERATURE OVERSAMPLING */
|
||||
/***********************************************/
|
||||
/* Control Measurement Register */
|
||||
#define BMP280_CTRL_MEAS_REG_OVRS_TEMP__POS 5
|
||||
#define BMP280_CTRL_MEAS_REG_OVRS_TEMP__MSK 0xE0
|
||||
#define BMP280_CTRL_MEAS_REG_OVRS_TEMP__LEN 3
|
||||
#define BMP280_CTRL_MEAS_REG_OVRS_TEMP__REG \
|
||||
BMP280_CTRL_MEAS_REG
|
||||
/************************************************/
|
||||
/**\name BIT LENGTH,POSITION AND MASK DEFINITION
|
||||
FOR PRESSURE OVERSAMPLING */
|
||||
/***********************************************/
|
||||
#define BMP280_CTRL_MEAS_REG_OVRS_PRES__POS 2
|
||||
#define BMP280_CTRL_MEAS_REG_OVRS_PRES__MSK 0x1C
|
||||
#define BMP280_CTRL_MEAS_REG_OVRS_PRES__LEN 3
|
||||
#define BMP280_CTRL_MEAS_REG_OVRS_PRES__REG \
|
||||
BMP280_CTRL_MEAS_REG
|
||||
/************************************************/
|
||||
/**\name BIT LENGTH,POSITION AND MASK DEFINITION
|
||||
FOR POWER MODE */
|
||||
/***********************************************/
|
||||
#define BMP280_CTRL_MEAS_REG_POWER_MODE__POS 0
|
||||
#define BMP280_CTRL_MEAS_REG_POWER_MODE__MSK 0x03
|
||||
#define BMP280_CTRL_MEAS_REG_POWER_MODE__LEN 2
|
||||
#define BMP280_CTRL_MEAS_REG_POWER_MODE__REG BMP280_CTRL_MEAS_REG
|
||||
/************************************************/
|
||||
/**\name BIT LENGTH,POSITION AND MASK DEFINITION
|
||||
FOR STANDBY DURATION */
|
||||
/***********************************************/
|
||||
/* Configuration Register */
|
||||
#define BMP280_CONFIG_REG_STANDBY_DURN__POS 5
|
||||
#define BMP280_CONFIG_REG_STANDBY_DURN__MSK 0xE0
|
||||
#define BMP280_CONFIG_REG_STANDBY_DURN__LEN 3
|
||||
#define BMP280_CONFIG_REG_STANDBY_DURN__REG BMP280_CONFIG_REG
|
||||
/************************************************/
|
||||
/**\name BIT LENGTH,POSITION AND MASK DEFINITION
|
||||
FOR IIR FILTER */
|
||||
/***********************************************/
|
||||
#define BMP280_CONFIG_REG_FILTER__POS 2
|
||||
#define BMP280_CONFIG_REG_FILTER__MSK 0x1C
|
||||
#define BMP280_CONFIG_REG_FILTER__LEN 3
|
||||
#define BMP280_CONFIG_REG_FILTER__REG BMP280_CONFIG_REG
|
||||
/************************************************/
|
||||
/**\name BIT LENGTH,POSITION AND MASK DEFINITION
|
||||
FOR SPI ENABLE*/
|
||||
/***********************************************/
|
||||
#define BMP280_CONFIG_REG_SPI3_ENABLE__POS 0
|
||||
#define BMP280_CONFIG_REG_SPI3_ENABLE__MSK 0x01
|
||||
#define BMP280_CONFIG_REG_SPI3_ENABLE__LEN 1
|
||||
#define BMP280_CONFIG_REG_SPI3_ENABLE__REG BMP280_CONFIG_REG
|
||||
/************************************************/
|
||||
/**\name BIT LENGTH,POSITION AND MASK DEFINITION
|
||||
FOR PRESSURE AND TEMPERATURE DATA REGISTERS */
|
||||
/***********************************************/
|
||||
/* Data Register */
|
||||
#define BMP280_PRESSURE_XLSB_REG__POS 4
|
||||
#define BMP280_PRESSURE_XLSB_REG__MSK 0xF0
|
||||
#define BMP280_PRESSURE_XLSB_REG__LEN 4
|
||||
#define BMP280_PRESSURE_XLSB_REG__REG BMP280_PRESSURE_XLSB_REG
|
||||
|
||||
#define BMP280_TEMPERATURE_XLSB_REG__POS 4
|
||||
#define BMP280_TEMPERATURE_XLSB_REG__MSK 0xF0
|
||||
#define BMP280_TEMPERATURE_XLSB_REG__LEN 4
|
||||
#define BMP280_TEMPERATURE_XLSB_REG__REG BMP280_TEMPERATURE_XLSB_REG
|
||||
|
||||
/****************************************************/
|
||||
/**\name ARRAY PARAMETERS */
|
||||
/***************************************************/
|
||||
#define LSB_ZERO 0
|
||||
#define MSB_ONE 1
|
||||
#define LSB_TWO 2
|
||||
#define MSB_THREE 3
|
||||
#define LSB_FOUR 4
|
||||
#define MSB_FIVE 5
|
||||
#define LSB_SIX 6
|
||||
#define MSB_SEVEN 7
|
||||
/****************************************************/
|
||||
/**\name TRUE TEMPERATURE CALUCULATION PARAMETERS */
|
||||
/***************************************************/
|
||||
#define BMP280_DEC_TRUE_TEMP_5 5
|
||||
#define BMP280_DEC_TRUE_TEMP_128 128
|
||||
/****************************************************/
|
||||
/**\name TRUE PRESSURE CALUCULATION PARAMETERS */
|
||||
/***************************************************/
|
||||
#define BMP280_DEC_TRUE_PRES_64000 64000
|
||||
#define BMP280_DEC_TRUE_PRES_2 2
|
||||
#define BMP280_DEC_TRUE_PRES_32768 32768
|
||||
#define BMP280_DEC_TRUE_PRES_1048576 1048576
|
||||
#define BMP280_DEC_TRUE_PRES_3125 3125
|
||||
#define BMP280_HEX_TRUE_PRES_8M 0x80000000
|
||||
|
||||
/****************************************************/
|
||||
/**\name TRUE TEMPERATURE CALCULATION FLOAT RETURN */
|
||||
/***************************************************/
|
||||
#define BMP280_FLOAT_TRUE_TEMP_16384 16384.0
|
||||
#define BMP280_FLOAT_TRUE_TEMP_1024 1024.0
|
||||
#define BMP280_FLOAT_TRUE_TEMP_131072 131072.0
|
||||
#define BMP280_FLOAT_TRUE_TEMP_8192 8192.0
|
||||
#define BMP280_FLOAT_TRUE_TEMP_5120 5120.0
|
||||
|
||||
/****************************************************/
|
||||
/**\name TRUE PRESSURE CALCULATION FLOAT RETURN */
|
||||
/***************************************************/
|
||||
#define BMP280_FLOAT_TRUE_PRES_1 1.0
|
||||
#define BMP280_FLOAT_TRUE_PRES_0 0.0
|
||||
#define BMP280_FLOAT_TRUE_PRES_2 2.0
|
||||
#define BMP280_FLOAT_TRUE_PRES_4 4.0
|
||||
#define BMP280_FLOAT_TRUE_PRES_1_6 16.0
|
||||
#define BMP280_FLOAT_TRUE_PRES_64000 64000.0
|
||||
#define BMP280_FLOAT_TRUE_PRES_32768 32768.0
|
||||
#define BMP280_FLOAT_TRUE_PRES_65536 65536.0
|
||||
#define BMP280_FLOAT_TRUE_PRES_524288 524288.0
|
||||
#define BMP280_FLOAT_TRUE_PRES_1048576 1048576.0
|
||||
#define BMP280_FLOAT_TRUE_PRES_4096 4096.0
|
||||
#define BMP280_FLOAT_TRUE_PRES_6250 6250.0
|
||||
#define BMP280_FLOAT_TRUE_PRES_2147483648 2147483648.0
|
||||
|
||||
/****************************************************/
|
||||
/**\name TRUE PRESSURE CALUCULATION 64BIT RETURN */
|
||||
/***************************************************/
|
||||
#define BMP280_TRUE_PRES_128000 128000
|
||||
#define BMP280_TRUE_PRES_1048576 1048576
|
||||
#define BMP280_TRUE_PRES_3125 3125
|
||||
#define BMP280_TRUE_PRES_1 1
|
||||
|
||||
/**************************************************************/
|
||||
/**\name CHIP ID */
|
||||
/**************************************************************/
|
||||
#define BMP280_CHIP_ID 0x58
|
||||
|
||||
/**************************************************************/
|
||||
/**\name STRUCTURE DEFINITIONS */
|
||||
/**************************************************************/
|
||||
// This structure holds all device specific calibration parameters
|
||||
struct _bmp280_calib_par
|
||||
{
|
||||
uint16_t dig_T1; /**<calibration T1 data*/
|
||||
int16_t dig_T2; /**<calibration T2 data*/
|
||||
int16_t dig_T3; /**<calibration T3 data*/
|
||||
uint16_t dig_P1; /**<calibration P1 data*/
|
||||
int16_t dig_P2; /**<calibration P2 data*/
|
||||
int16_t dig_P3; /**<calibration P3 data*/
|
||||
int16_t dig_P4; /**<calibration P4 data*/
|
||||
int16_t dig_P5; /**<calibration P5 data*/
|
||||
int16_t dig_P6; /**<calibration P6 data*/
|
||||
int16_t dig_P7; /**<calibration P7 data*/
|
||||
int16_t dig_P8; /**<calibration P8 data*/
|
||||
int16_t dig_P9; /**<calibration P9 data*/
|
||||
int32_t t_fine; /**<calibration t_fine data*/
|
||||
};
|
||||
|
||||
// This structure holds BMP280 initialization parameters
|
||||
struct _bmp280
|
||||
{
|
||||
struct _twi_desc* twid;
|
||||
|
||||
struct _bmp280_calib_par calpar; /**<calibration data*/
|
||||
uint8_t chip_id; /**< chip id of the sensor*/
|
||||
uint8_t dev_addr; /**< device address of the sensor*/
|
||||
uint8_t overs_temp; /**< temperature over sampling*/
|
||||
uint8_t overs_pres; /**< pressure over sampling*/
|
||||
void(*delay_msec)(uint16_t); /**< delay function pointer*/
|
||||
};
|
||||
|
||||
/**************************************************************/
|
||||
/**\name FUNCTION DECLARATIONS */
|
||||
/**************************************************************/
|
||||
|
||||
static uint8_t _bmp280_read(struct _bmp280* bmp280, uint8_t* buffer, uint32_t len);
|
||||
static uint8_t _bmp280_write(struct _bmp280* bmp280, const uint8_t* buffer, uint32_t len);
|
||||
|
||||
uint8_t bmp280_write_register(struct _bmp280* bmp280, uint8_t addr, uint8_t* pdata, uint8_t len);
|
||||
uint8_t bmp280_read_register(struct _bmp280* bmp280, uint8_t addr, uint8_t* pdata, uint8_t len);
|
||||
|
||||
uint8_t bmp280_read_uncompensed_temperature (struct _bmp280* bmp280, int32_t* uncT);
|
||||
int32_t bmp280_compensate_temperatureC (struct _bmp280* bmp280, int32_t uncT);
|
||||
uint8_t bmp280_read_uncompensed_pressure (struct _bmp280* bmp280, int32_t* uncP);
|
||||
uint32_t bmp280_compensate_pressureP (struct _bmp280* bmp280, int32_t uncP);
|
||||
uint8_t bmp280_read_uncompensed_pressure_temperature (struct _bmp280* bmp280, int32_t* uncP, int32_t* uncT);
|
||||
uint8_t bmp280_read_pressure_temperature (struct _bmp280* bmp280, uint32_t* pressure, int32_t* temperature);
|
||||
uint8_t bmp280_get_calpar (struct _bmp280* bmp280);
|
||||
uint8_t bmp280_get_overs_temp (struct _bmp280* bmp280, uint8_t* value);
|
||||
uint8_t bmp280_set_overs_temp (struct _bmp280* bmp280, uint8_t value);
|
||||
uint8_t bmp280_get_overs_pres (struct _bmp280* bmp280, uint8_t* value);
|
||||
uint8_t bmp280_set_overs_pres (struct _bmp280* bmp280, uint8_t value);
|
||||
uint8_t bmp280_get_power_mode(struct _bmp280* bmp280, uint8_t* power_mode);
|
||||
uint8_t bmp280_set_power_mode (struct _bmp280* bmp280, uint8_t power_mode);
|
||||
uint8_t bmp280_set_soft_rst (struct _bmp280* bmp280);
|
||||
uint8_t bmp280_get_spi3 (struct _bmp280* bmp280, uint8_t* enable_disable);
|
||||
uint8_t bmp280_set_spi3 (struct _bmp280* bmp280, uint8_t enable_disable);
|
||||
uint8_t bmp280_get_filter (struct _bmp280* bmp280, uint8_t *value);
|
||||
uint8_t bmp280_set_filter (struct _bmp280* bmp280, uint8_t value);
|
||||
uint8_t bmp280_get_standby_durn(struct _bmp280* bmp280, uint8_t* standby_durn);
|
||||
uint8_t bmp280_set_standby_durn (struct _bmp280* bmp280, uint8_t standby_durn);
|
||||
uint8_t bmp280_set_work_mode (struct _bmp280* bmp280, uint8_t work_mode);
|
||||
uint8_t bmp280_get_forced_uncP_temperature(struct _bmp280* bmp280, int32_t* uncP, int32_t* uncT);
|
||||
|
||||
uint8_t bmp280_read_id_get_calib_param (struct _bmp280* bmp280);
|
||||
|
||||
/**************************************************************/
|
||||
/**\name FUNCTION FOR TRUE TEMPERATURE CALCULATION */
|
||||
/**************************************************************/
|
||||
|
||||
#ifdef BMP280_ENABLE_FLOAT
|
||||
double bmp280_compensate_T_double(struct _bmp280* bmp280, int32_t uncT);
|
||||
double bmp280_compensate_P_double(struct _bmp280* bmp280, int32_t uncP);
|
||||
#endif
|
||||
|
||||
#if defined(BMP280_ENABLE_INT64) && defined(BMP280_64BITSUPPORT_PRESENT)
|
||||
uint32_t bmp280_compensate_P_int64(struct _bmp280* bmp280, int32_t uncP);
|
||||
#endif
|
||||
|
||||
/**************************************************************/
|
||||
/**\name FUNCTION FOR DELAY CALCULATION DURING FORCEMODE */
|
||||
/**************************************************************/
|
||||
|
||||
uint8_t bmp280_compute_wait_time (struct _bmp280* bmp280, uint8_t* delaytimer);
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------------------
|
||||
#endif
|
|
@ -0,0 +1,372 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implements CONSOLE.
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "board.h"
|
||||
#include "chip.h"
|
||||
#include "misc/console.h"
|
||||
#include "peripherals/pio.h"
|
||||
#include "peripherals/pmc.h"
|
||||
#include "peripherals/uart.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Variables
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
typedef void (*_init_handler) (void*,uint32_t,uint32_t);
|
||||
typedef void (*_put_char_handler) (void*, uint8_t);
|
||||
typedef uint32_t (*_get_char_handler) (void*);
|
||||
typedef uint32_t (*_rx_ready_handler) (void*);
|
||||
typedef void (*_enable_it_handler) (void*,uint32_t);
|
||||
|
||||
/* Initialize console structure according to board configuration */
|
||||
#if CONSOLE_DRIVER == DRV_USART
|
||||
#include "peripherals/usart.h"
|
||||
static const struct _console console = {
|
||||
CONSOLE_PER_ADD,
|
||||
(_init_handler) usart_configure,
|
||||
(_put_char_handler) usart_put_char,
|
||||
(_get_char_handler) usart_get_char,
|
||||
(_rx_ready_handler) usart_is_rx_ready,
|
||||
(_enable_it_handler) usart_enable_it
|
||||
};
|
||||
#elif CONSOLE_DRIVER == DRV_UART
|
||||
#include "peripherals/uart.h"
|
||||
static const struct _console console = {
|
||||
CONSOLE_PER_ADD,
|
||||
(_init_handler) uart_configure,
|
||||
(_put_char_handler) uart_put_char,
|
||||
(_get_char_handler) uart_get_char,
|
||||
(_rx_ready_handler) uart_is_rx_ready,
|
||||
(_enable_it_handler) uart_set_int
|
||||
};
|
||||
#elif CONSOLE_DRIVER == DRV_DBGU
|
||||
#include "peripherals/dbgu.h"
|
||||
static const struct _console console = {
|
||||
CONSOLE_PER_ADD,
|
||||
(_init_handler) dbgu_configure,
|
||||
(_put_char_handler) dbgu_put_char,
|
||||
(_get_char_handler) dbgu_get_char,
|
||||
(_rx_ready_handler) dbgu_is_rx_ready,
|
||||
(_enable_it_handler) dbgu_enable_it
|
||||
};
|
||||
#endif
|
||||
|
||||
/** Pins for CONSOLE */
|
||||
static const struct _pin pinsConsole[] = PINS_CONSOLE;
|
||||
|
||||
/** Console initialize status */
|
||||
static uint8_t _bConsoleIsInitialized = 0;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Configures a CONSOLE peripheral with the specified parameters.
|
||||
*
|
||||
* \param baudrate Baudrate at which the CONSOLE should operate (in Hz).
|
||||
*/
|
||||
void console_configure(uint32_t baudrate)
|
||||
{
|
||||
/* Configure PIO */
|
||||
pio_configure(pinsConsole, ARRAY_SIZE(pinsConsole));
|
||||
|
||||
pmc_enable_peripheral(CONSOLE_ID);
|
||||
|
||||
uint32_t mode;
|
||||
#if CONSOLE_DRIVER != DRV_DBGU
|
||||
mode = US_MR_CHMODE_NORMAL | US_MR_PAR_NO | US_MR_CHRL_8_BIT;
|
||||
#else
|
||||
mode = US_MR_CHMODE_NORMAL | US_MR_PAR_NO;
|
||||
#endif
|
||||
|
||||
#if CONSOLE_DRIVER == DRV_UART
|
||||
uint32_t mr;
|
||||
mr = mode & US_MR_FILTER ? UART_MR_FILTER_ENABLED
|
||||
: UART_MR_FILTER_DISABLED;
|
||||
mr |= UART_MR_PAR((mode & US_MR_PAR_Msk) >> US_MR_PAR_Pos);
|
||||
if ((mode & US_MR_USCLKS_Msk) == US_MR_USCLKS_PMC_PCK)
|
||||
mr |= UART_MR_BRSRCCK_PMC_PCK;
|
||||
else
|
||||
mr |= UART_MR_BRSRCCK_PERIPH_CLK;
|
||||
mr |= UART_MR_CHMODE((mode & US_MR_CHMODE_Msk) >> US_MR_CHMODE_Pos);
|
||||
mode = mr;
|
||||
#endif
|
||||
|
||||
/* Initialize driver to use */
|
||||
console.init(console.addr, mode, baudrate);
|
||||
|
||||
/* Finally */
|
||||
_bConsoleIsInitialized = 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Outputs a character on the CONSOLE line.
|
||||
*
|
||||
* \note This function is synchronous (i.e. uses polling).
|
||||
* \param c Character to send.
|
||||
*/
|
||||
void console_put_char(uint8_t c)
|
||||
{
|
||||
if (!_bConsoleIsInitialized)
|
||||
console_configure(CONSOLE_BAUDRATE);
|
||||
|
||||
console.put_char(console.addr, c);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Input a character from the CONSOLE line.
|
||||
*
|
||||
* \note This function is synchronous
|
||||
* \return character received.
|
||||
*/
|
||||
extern uint32_t console_get_char(void)
|
||||
{
|
||||
if (!_bConsoleIsInitialized)
|
||||
console_configure(CONSOLE_BAUDRATE);
|
||||
return console.get_char(console.addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if there is Input from DBGU line.
|
||||
*
|
||||
* \return true if there is Input.
|
||||
*/
|
||||
extern uint32_t console_is_rx_ready(void)
|
||||
{
|
||||
if (!_bConsoleIsInitialized)
|
||||
console_configure(CONSOLE_BAUDRATE);
|
||||
return console.is_rx_ready(console.addr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the content of the given frame on the DBGU.
|
||||
*
|
||||
* \param pucFrame Pointer to the frame to dump.
|
||||
* \param size Buffer size in bytes.
|
||||
*/
|
||||
void console_dump_frame(uint8_t * pframe, uint32_t size)
|
||||
{
|
||||
uint32_t dw;
|
||||
|
||||
for (dw = 0; dw < size; dw++) {
|
||||
printf("%02X ", pframe[dw]);
|
||||
}
|
||||
printf("\n\r");
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the content of the given buffer on the DBGU.
|
||||
*
|
||||
* \param pbuffer Pointer to the buffer to dump.
|
||||
* \param size Buffer size in bytes.
|
||||
* \param address Start address to display
|
||||
*/
|
||||
void console_dump_memory(uint8_t * pbuffer, uint32_t size,
|
||||
uint32_t address)
|
||||
{
|
||||
uint32_t i, j;
|
||||
uint32_t last_line_start;
|
||||
uint8_t *tmp;
|
||||
|
||||
for (i = 0; i < (size / 16); i++) {
|
||||
printf("0x%08X: ", (unsigned int)(address + (i * 16)));
|
||||
tmp = (uint8_t *) & pbuffer[i * 16];
|
||||
for (j = 0; j < 4; j++) {
|
||||
printf("%02X%02X%02X%02X ", tmp[0], tmp[1], tmp[2],
|
||||
tmp[3]);
|
||||
tmp += 4;
|
||||
}
|
||||
tmp = (uint8_t *) & pbuffer[i * 16];
|
||||
for (j = 0; j < 16; j++) {
|
||||
console_put_char(*tmp++);
|
||||
}
|
||||
printf("\n\r");
|
||||
}
|
||||
if ((size % 16) != 0) {
|
||||
last_line_start = size - (size % 16);
|
||||
printf("0x%08X: ", (unsigned int)(address + last_line_start));
|
||||
for (j = last_line_start; j < last_line_start + 16; j++) {
|
||||
if ((j != last_line_start) && (j % 4 == 0)) {
|
||||
printf(" ");
|
||||
}
|
||||
if (j < size)
|
||||
printf("%02X", pbuffer[j]);
|
||||
else
|
||||
printf(" ");
|
||||
}
|
||||
printf(" ");
|
||||
for (j = last_line_start; j < size; j++) {
|
||||
console_put_char(pbuffer[j]);
|
||||
}
|
||||
printf("\n\r");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an integer
|
||||
*
|
||||
* \param pvalue Pointer to the uint32_t variable to contain the input value.
|
||||
*/
|
||||
extern uint32_t console_get_integer(uint32_t * pvalue)
|
||||
{
|
||||
uint8_t key;
|
||||
uint8_t nb = 0;
|
||||
uint32_t value = 0;
|
||||
|
||||
while (1) {
|
||||
key = console_get_char();
|
||||
console_put_char(key);
|
||||
|
||||
if (key >= '0' && key <= '9') {
|
||||
value = (value * 10) + (key - '0');
|
||||
nb++;
|
||||
} else {
|
||||
if (key == 0x0D || key == ' ') {
|
||||
if (nb == 0) {
|
||||
printf
|
||||
("\n\rWrite a number and press ENTER or SPACE!\n\r");
|
||||
return 0;
|
||||
} else {
|
||||
printf("\n\r");
|
||||
*pvalue = value;
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
printf("\n\r'%c' not a number!\n\r", key);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an integer and check the value
|
||||
*
|
||||
* \param pvalue Pointer to the uint32_t variable to contain the input value.
|
||||
* \param dwMin Minimum value
|
||||
* \param dwMax Maximum value
|
||||
*/
|
||||
extern uint32_t console_get_integer_min_max(uint32_t * pvalue, uint32_t min,
|
||||
uint32_t max)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
|
||||
if (console_get_integer(&value) == 0)
|
||||
return 0;
|
||||
if (value < min || value > max) {
|
||||
printf("\n\rThe number have to be between %u and %u\n\r",
|
||||
(unsigned int)min, (unsigned int)max);
|
||||
return 0;
|
||||
}
|
||||
printf("\n\r");
|
||||
*pvalue = value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void console_enable_interrupts(uint32_t mask)
|
||||
{
|
||||
console.enable_interrupts(console.addr, mask);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads an hexadecimal number
|
||||
*
|
||||
* \param pvalue Pointer to the uint32_t variable to contain the input value.
|
||||
*/
|
||||
extern uint32_t console_get_hexa_32(uint32_t * pvalue)
|
||||
{
|
||||
uint8_t key;
|
||||
uint32_t dw = 0;
|
||||
uint32_t value = 0;
|
||||
|
||||
for (dw = 0; dw < 8; dw++) {
|
||||
key = console_get_char();
|
||||
console_put_char(key);
|
||||
|
||||
if (key >= '0' && key <= '9') {
|
||||
value = (value * 16) + (key - '0');
|
||||
} else {
|
||||
if (key >= 'A' && key <= 'F') {
|
||||
value = (value * 16) + (key - 'A' + 10);
|
||||
} else {
|
||||
if (key >= 'a' && key <= 'f') {
|
||||
value = (value * 16) + (key - 'a' + 10);
|
||||
} else {
|
||||
printf
|
||||
("\n\rIt is not a hexa character!\n\r");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("\n\r");
|
||||
*pvalue = value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void console_clear_screen(void)
|
||||
{
|
||||
printf("\033[2J\033[0;0f");
|
||||
}
|
||||
|
||||
void console_reset_cursor(void)
|
||||
{
|
||||
printf("\033[0;0f");
|
||||
}
|
||||
|
||||
void console_echo(uint8_t c)
|
||||
{
|
||||
switch (c) {
|
||||
case '\r':
|
||||
case '\n':
|
||||
printf("\r\n");
|
||||
break;
|
||||
case 0x7F:
|
||||
printf("\033[1D\033[K");
|
||||
break;
|
||||
case '\b':
|
||||
printf("\033[1D\033[K");
|
||||
break;
|
||||
default:
|
||||
console_put_char(c);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _CONSOLE_H_
|
||||
#define _CONSOLE_H_
|
||||
|
||||
/*-----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define DRV_UART (1)
|
||||
#define DRV_USART (2)
|
||||
#define DRV_DBGU (3)
|
||||
//#define DRV_FLEXCOM (4)
|
||||
|
||||
struct _console {
|
||||
void* addr;
|
||||
void (*init)(void*, uint32_t, uint32_t);
|
||||
void (*put_char)(void*, uint8_t);
|
||||
uint32_t (*get_char)(void*);
|
||||
uint32_t (*is_rx_ready)(void*);
|
||||
void (*enable_interrupts)(void*, uint32_t);
|
||||
};
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* Global function
|
||||
* ---------------------------------------------------------------------------*/
|
||||
|
||||
extern void console_configure(uint32_t baudrate);
|
||||
extern void console_put_char(uint8_t uc);
|
||||
extern uint32_t console_get_char(void);
|
||||
extern uint32_t console_is_rx_ready(void);
|
||||
extern void console_enable_interrupts(uint32_t mask);
|
||||
extern void console_dump_frame(uint8_t * pframe, uint32_t size);
|
||||
extern void console_dump_memory(uint8_t * pbuffer, uint32_t size,
|
||||
uint32_t address);
|
||||
extern uint32_t console_get_integer(uint32_t * pvalue);
|
||||
extern uint32_t console_get_integer_min_max(uint32_t * pvalue, uint32_t min,
|
||||
uint32_t max);
|
||||
extern uint32_t console_get_hexa_32(uint32_t * pvalue);
|
||||
|
||||
extern void console_echo(uint8_t c);
|
||||
extern void console_clear_screen(void);
|
||||
extern void console_reset_cursor(void);
|
||||
|
||||
#endif /* _CONSOLE_H_ */
|
|
@ -0,0 +1,149 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include "board.h"
|
||||
#include "misc/led.h"
|
||||
#include "peripherals/pio.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Local Variables
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef PINS_LEDS
|
||||
static const struct _pin pinsLeds[] = PINS_LEDS;
|
||||
|
||||
static const uint32_t numLeds = ARRAY_SIZE(pinsLeds);
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Global Functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Configures the pin associated with the given LED number. If the LED does
|
||||
* not exist on the board, the function does nothing.
|
||||
* \param dwLed Number of the LED to configure.
|
||||
* \return 1 if the LED exists and has been configured; otherwise 0.
|
||||
*/
|
||||
extern uint32_t led_configure (uint32_t led)
|
||||
{
|
||||
#ifdef PINS_LEDS
|
||||
// Check that LED exists
|
||||
if (led >= numLeds) {
|
||||
return 0;
|
||||
}
|
||||
// Configure LED
|
||||
return pio_configure(&pinsLeds[led], 1);
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns the given LED on if it exists; otherwise does nothing.
|
||||
* \param dwLed Number of the LED to turn on.
|
||||
* \return 1 if the LED has been turned on; 0 otherwise.
|
||||
*/
|
||||
extern uint32_t led_set(uint32_t led)
|
||||
{
|
||||
#ifdef PINS_LEDS
|
||||
/* Check if LED exists */
|
||||
if (led >= numLeds) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Turn LED on */
|
||||
if (pinsLeds[led].type == PIO_OUTPUT_0) {
|
||||
pio_set(&pinsLeds[led]);
|
||||
} else {
|
||||
pio_clear(&pinsLeds[led]);
|
||||
}
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns a LED off.
|
||||
*
|
||||
* \param dwLed Number of the LED to turn off.
|
||||
* \return 1 if the LED has been turned off; 0 otherwise.
|
||||
*/
|
||||
extern uint32_t led_clear (uint32_t led)
|
||||
{
|
||||
#ifdef PINS_LEDS
|
||||
/* Check if LED exists */
|
||||
if (led >= numLeds) {
|
||||
return 0;
|
||||
}
|
||||
/* Turn LED off */
|
||||
if (pinsLeds[led].type == PIO_OUTPUT_0) {
|
||||
pio_clear(&pinsLeds[led]);
|
||||
} else {
|
||||
pio_set(&pinsLeds[led]);
|
||||
}
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the current state of a LED.
|
||||
*
|
||||
* \param dwLed Number of the LED to toggle.
|
||||
* \return 1 if the LED has been toggled; otherwise 0.
|
||||
*/
|
||||
extern uint32_t led_toggle(uint32_t led)
|
||||
{
|
||||
#ifdef PINS_LEDS
|
||||
/* Check if LED exists */
|
||||
if (led >= numLeds) {
|
||||
return 0;
|
||||
}
|
||||
/* Toggle LED */
|
||||
if (pio_get_output_data_status(&pinsLeds[led])) {
|
||||
pio_clear(&pinsLeds[led]);
|
||||
} else {
|
||||
pio_set(&pinsLeds[led]);
|
||||
}
|
||||
return 1;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \section Purpose
|
||||
*
|
||||
* Small set of functions for simple and portable LED usage.
|
||||
*
|
||||
* \section Usage
|
||||
*
|
||||
* -# Configure one or more LEDs using led_configure and
|
||||
* LED_ConfigureAll.
|
||||
* -# Set, clear and toggle LEDs using led_set, led_clear and
|
||||
* led_toggle.
|
||||
*
|
||||
* LEDs are numbered starting from 0; the number of LEDs depend on the
|
||||
* board being used. All the functions defined here will compile properly
|
||||
* regardless of whether the LED is defined or not; they will simply
|
||||
* return 0 when a LED which does not exist is given as an argument.
|
||||
* Also, these functions take into account how each LED is connected on to
|
||||
* board; thus, \ref led_set might change the level on the corresponding pin
|
||||
* to 0 or 1, but it will always light the LED on; same thing for the other
|
||||
* methods.
|
||||
*/
|
||||
|
||||
#ifndef _LED_
|
||||
#define _LED_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Global Functions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
extern uint32_t led_configure(uint32_t led);
|
||||
extern uint32_t led_set(uint32_t led);
|
||||
extern uint32_t led_clear(uint32_t led);
|
||||
extern uint32_t led_toggle(uint32_t led);
|
||||
|
||||
#endif /* #ifndef LED_H */
|
|
@ -0,0 +1,74 @@
|
|||
# ----------------------------------------------------------------------------
|
||||
# SAM Software Package License
|
||||
# ----------------------------------------------------------------------------
|
||||
# Copyright (c) 2015, Atmel Corporation
|
||||
#
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# - Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the disclaimer below.
|
||||
#
|
||||
# Atmel's name may not be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
# DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
drivers-y += drivers/peripherals/adc.o
|
||||
drivers-y += drivers/peripherals/aes.o
|
||||
drivers-y += drivers/peripherals/aic.o
|
||||
drivers-y += drivers/peripherals/gmacd.o
|
||||
drivers-y += drivers/peripherals/gmac.o
|
||||
drivers-y += drivers/peripherals/l2cc.o
|
||||
drivers-y += drivers/peripherals/matrix.o
|
||||
drivers-y += drivers/peripherals/mpddrc.o
|
||||
drivers-y += drivers/peripherals/pit.o
|
||||
drivers-y += drivers/peripherals/pmc.o
|
||||
drivers-y += drivers/peripherals/pmecc.o
|
||||
drivers-y += drivers/peripherals/pmecc_gallois_field_512.o
|
||||
drivers-y += drivers/peripherals/pmecc_gallois_field_1024.o
|
||||
drivers-y += drivers/peripherals/pwmc.o
|
||||
drivers-y += drivers/peripherals/rstc.o
|
||||
drivers-y += drivers/peripherals/rtc.o
|
||||
drivers-y += drivers/peripherals/sha.o
|
||||
drivers-y += drivers/peripherals/hsmc.o
|
||||
drivers-y += drivers/peripherals/spid.o
|
||||
drivers-y += drivers/peripherals/spi.o
|
||||
drivers-y += drivers/peripherals/tc.o
|
||||
drivers-y += drivers/peripherals/tdes.o
|
||||
drivers-y += drivers/peripherals/trng.o
|
||||
drivers-y += drivers/peripherals/twid_legacy.o
|
||||
drivers-y += drivers/peripherals/twi.o
|
||||
drivers-y += drivers/peripherals/uart.o
|
||||
drivers-y += drivers/peripherals/usartd.o
|
||||
drivers-y += drivers/peripherals/usart_iso7816_4.o
|
||||
drivers-y += drivers/peripherals/usart.o
|
||||
drivers-y += drivers/peripherals/wdt.o
|
||||
drivers-y += drivers/peripherals/xdmac.o
|
||||
drivers-y += drivers/peripherals/xdmad.o
|
||||
|
||||
drivers-$(CONFIG_HAVE_FLEXCOM) += drivers/peripherals/flexcom.o
|
||||
drivers-$(CONFIG_HAVE_USART_LIN) += drivers/peripherals/usart_lin.o
|
||||
drivers-$(CONFIG_HAVE_PIO4) += drivers/peripherals/pio4.o
|
||||
drivers-$(CONFIG_HAVE_QSPI) += drivers/peripherals/qspi.o
|
||||
drivers-$(CONFIG_HAVE_MCAN) += drivers/peripherals/mcan.o
|
||||
drivers-$(CONFIG_HAVE_SDMMC) += drivers/peripherals/sdmmc.o
|
||||
|
||||
drivers-$(CONFIG_SOC_SAMA5D2) += drivers/peripherals/acc.o
|
||||
drivers-$(CONFIG_SOC_SAMA5D2) += drivers/peripherals/classd.o
|
||||
drivers-$(CONFIG_SOC_SAMA5D2) += drivers/peripherals/isc.o
|
||||
drivers-$(CONFIG_SOC_SAMA5D2) += drivers/peripherals/sfrbu.o
|
||||
drivers-$(CONFIG_SOC_SAMA5D2) += drivers/peripherals/shdwc.o
|
||||
drivers-$(CONFIG_SOC_SAMA5D2) += drivers/peripherals/twid.o
|
|
@ -0,0 +1,135 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/acc.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Types
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#define ACC_MR_INV_Pos 12 /* ACC invert output (reg offset) */
|
||||
|
||||
#define ACC_ACR_HYST_0mv_max 0x00 /* Hysteresis levels */
|
||||
#define ACC_ACR_HYST_50mv_max 0x01
|
||||
#define ACC_ACR_HYST_90mv_max 0x11
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void acc_init(Acc *p_acc, uint32_t select_plus, uint32_t select_minus,
|
||||
uint32_t edge_type, uint32_t invert)
|
||||
{
|
||||
/* Reset the controller */
|
||||
p_acc->ACC_CR |= ACC_CR_SWRST;
|
||||
|
||||
/* Write to the MR register */
|
||||
p_acc->ACC_MR = (((select_plus << ACC_MR_SELPLUS_Pos) & ACC_MR_SELPLUS_Msk) |
|
||||
((select_minus << ACC_MR_SELMINUS_Pos) & ACC_MR_SELMINUS_Msk) |
|
||||
((edge_type << ACC_MR_EDGETYP_Pos) & ACC_MR_EDGETYP_Msk) |
|
||||
((invert << ACC_MR_INV_Pos) & ACC_MR_INV));
|
||||
|
||||
/* Set hysteresis and current selection (ISEL) */
|
||||
p_acc->ACC_ACR = (ACC_ACR_ISEL_HISP | ACC_ACR_HYST(ACC_ACR_HYST_50mv_max));
|
||||
|
||||
/* Automatic Output Masking Period */
|
||||
while (p_acc->ACC_ISR & (uint32_t)ACC_ISR_MASK) ;
|
||||
}
|
||||
|
||||
void acc_enable(Acc *p_acc)
|
||||
{
|
||||
p_acc->ACC_MR |= ACC_MR_ACEN_EN;
|
||||
}
|
||||
|
||||
void acc_disable(Acc *p_acc)
|
||||
{
|
||||
p_acc->ACC_MR &= ~ACC_MR_ACEN_EN;
|
||||
}
|
||||
|
||||
void acc_reset(Acc *p_acc)
|
||||
{
|
||||
p_acc->ACC_CR = ACC_CR_SWRST;
|
||||
}
|
||||
|
||||
void acc_set_input(Acc *p_acc, uint32_t select_minus, uint32_t select_plus)
|
||||
{
|
||||
p_acc->ACC_MR &= ~(ACC_MR_SELMINUS_Msk & ACC_MR_SELPLUS_Msk);
|
||||
p_acc->ACC_MR |= select_plus | select_minus;
|
||||
}
|
||||
|
||||
void acc_set_output(Acc *p_acc, uint32_t invert, uint32_t fault_enable,
|
||||
uint32_t fault_source)
|
||||
{
|
||||
p_acc->ACC_MR &= ~(ACC_MR_INV_EN & ACC_MR_FE_EN & ACC_MR_SELFS_OUTPUT);
|
||||
p_acc->ACC_MR |= invert | fault_source | fault_enable;
|
||||
}
|
||||
|
||||
uint32_t acc_get_comparison_result(Acc *p_acc)
|
||||
{
|
||||
uint32_t temp = p_acc->ACC_MR;
|
||||
uint32_t status = p_acc->ACC_ISR;
|
||||
|
||||
if ((temp & ACC_MR_INV_EN) == ACC_MR_INV_EN)
|
||||
return status & ACC_ISR_SCO ? 0 : 1;
|
||||
else
|
||||
return status & ACC_ISR_SCO ? 1 : 0;
|
||||
}
|
||||
|
||||
void acc_enable_interrupt(Acc *p_acc)
|
||||
{
|
||||
p_acc->ACC_IER = ACC_IER_CE;
|
||||
}
|
||||
|
||||
void acc_disable_interrupt(Acc *p_acc)
|
||||
{
|
||||
p_acc->ACC_IDR = ACC_IDR_CE;
|
||||
}
|
||||
|
||||
uint32_t acc_get_interrupt_status(Acc *p_acc)
|
||||
{
|
||||
return p_acc->ACC_ISR;
|
||||
}
|
||||
|
||||
void acc_set_write_protect(Acc *p_acc, uint32_t enable)
|
||||
{
|
||||
if (enable)
|
||||
p_acc->ACC_WPMR = ACC_WPMR_WPKEY_PASSWD | ACC_WPMR_WPEN;
|
||||
else
|
||||
p_acc->ACC_WPMR = ACC_WPMR_WPKEY_PASSWD;
|
||||
}
|
||||
|
||||
uint32_t acc_get_write_protect_status(Acc *p_acc)
|
||||
{
|
||||
return p_acc->ACC_WPSR & ACC_WPSR_WPVS;
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implementation of Analog Comparator Controller (ACC).
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _ACC_H
|
||||
#define _ACC_H
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Global functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Initialize the Analog Comparator Controller.
|
||||
* \param p_acc Pointer to an Acc instance.
|
||||
* \param select_plus Input connected to inp, 0~7.
|
||||
* \param select_minus Input connected to inm, 0~7.
|
||||
* \param edge_type CF flag triggering mode
|
||||
* Use pattern defined in the device header file.
|
||||
* \param invert Invert comparator output.
|
||||
*/
|
||||
extern void acc_init(Acc *p_acc, uint32_t select_plus, uint32_t select_minus,
|
||||
uint32_t edge_type, uint32_t invert);
|
||||
|
||||
/**
|
||||
* \brief Enable the ACC.
|
||||
* \param p_acc Pointer to ACC registers set instance.
|
||||
*/
|
||||
extern void acc_enable(Acc *p_acc);
|
||||
|
||||
/**
|
||||
* \brief Disable the ACC.
|
||||
* \param p_acc Pointer to ACC registers set instance.
|
||||
*/
|
||||
extern void acc_disable(Acc *p_acc);
|
||||
|
||||
/**
|
||||
* \brief Reset the ACC.
|
||||
* \param p_acc Pointer to ACC registers set instance.
|
||||
*/
|
||||
extern void acc_reset(Acc *p_acc);
|
||||
|
||||
/**
|
||||
* \brief Set the input source.
|
||||
* \param p_acc Pointer to ACC registers set instance.
|
||||
* \param select_minus Selection for minus comparator input.
|
||||
* \param select_plus Selection for plus comparator input.
|
||||
*/
|
||||
extern void acc_set_input(Acc *p_acc, uint32_t select_minus,
|
||||
uint32_t select_plus);
|
||||
|
||||
/**
|
||||
* \brief Set the output of the ACC.
|
||||
* \param p_acc Pointer to ACC registers set instance.
|
||||
* \param invert Invert comparator output, 0 for disable, 1 for enable.
|
||||
* \param fault_enable Fault enable, 0 for disable, 1 for enable.
|
||||
* \param fault_source Selection of fault source, 0 for CF, 1 for output.
|
||||
*/
|
||||
extern void acc_set_output(Acc *p_acc, uint32_t invert, uint32_t fault_enable,
|
||||
uint32_t fault_source);
|
||||
|
||||
/**
|
||||
* \brief Get the comparison result.
|
||||
* \param p_acc Pointer to ACC registers set instance.
|
||||
* \return Result of the comparison, 0 for inn > inp, 1 for inp > inn.
|
||||
*/
|
||||
extern uint32_t acc_get_comparison_result(Acc *p_acc);
|
||||
|
||||
/**
|
||||
* \brief Enable the interrupt.
|
||||
* \param p_acc Pointer to ACC registers set instance.
|
||||
*/
|
||||
extern void acc_enable_interrupt(Acc *p_acc);
|
||||
|
||||
/**
|
||||
* \brief Disable the interrupt.
|
||||
* \param p_acc Pointer to ACC registers set instance.
|
||||
*/
|
||||
extern void acc_disable_interrupt(Acc *p_acc);
|
||||
|
||||
/**
|
||||
* \brief Get the interrupt status.
|
||||
* \param p_acc Pointer to ACC registers set instance.
|
||||
* \return Contents of the Interrupt Status Register.
|
||||
*/
|
||||
extern uint32_t acc_get_interrupt_status(Acc *p_acc);
|
||||
|
||||
/**
|
||||
* \brief Write-protect the Mode Register and the Analog Control Register.
|
||||
* \param p_acc Pointer to ACC registers set instance.
|
||||
* \param enable 1 to enable, 0 to disable.
|
||||
*/
|
||||
extern void acc_set_write_protect(Acc *p_acc, uint32_t enable);
|
||||
|
||||
/**
|
||||
* \brief Return write protect status.
|
||||
* \param p_acc Pointer to ACC registers set instance.
|
||||
* \retval 0 No write protection violation occurred.
|
||||
* \retval 1 At least one write attempt to a write-protected register has been
|
||||
* detected, since the previous call to this function.
|
||||
*/
|
||||
extern uint32_t acc_get_write_protect_status(Acc *p_acc);
|
||||
|
||||
#endif /* _ACC_H */
|
|
@ -0,0 +1,639 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \addtogroup adc_module Working with ADC
|
||||
* \ingroup peripherals_module
|
||||
* \section Purpose
|
||||
* The ADC driver provides the interface to configure and use the ADC peripheral.
|
||||
* \n
|
||||
*
|
||||
* It converts the analog input to digital format. The converted result could be
|
||||
* 12bit.
|
||||
*
|
||||
* To Enable a ADC conversion,the user has to follow these few steps:
|
||||
* <ul>
|
||||
* <li> Select an appropriate reference voltage on ADVREF </li>
|
||||
* <li> Configure the ADC according to its requirements and special needs,which
|
||||
* could be broken down into several parts:
|
||||
* -# Select the resolution by setting or clearing ADC_MR_LOWRES bit in
|
||||
* ADC_MR (Mode Register)
|
||||
* -# Set ADC clock by setting ADC_MR_PRESCAL bits in ADC_MR, the clock is
|
||||
* calculated with ADCClock = MCK / ( (PRESCAL+1) * 2 )
|
||||
* -# Set Startup Time,Tracking Clock cycles and Transfer Clock respectively
|
||||
* in ADC_MR.
|
||||
</li>
|
||||
* <li> Start conversion by setting ADC_CR_START in ADC_CR. </li>
|
||||
* </ul>
|
||||
*
|
||||
* \section Usage
|
||||
* <ul>
|
||||
* <li> Initialize the ADC controller using adc_initialize().
|
||||
* <li> ADC clock and timing configuration using adc_set_clock() and adc_set_timing().
|
||||
* <li> For ADC trigger using adc_set_trigger(), adc_set_trigger_mode() and
|
||||
* adc_set_trigger_period().
|
||||
* <li> For ADC sequence mode using adc_set_sequence_mode(), adc_set_sequence() and
|
||||
* adc_set_sequence_by_list().
|
||||
* <li> For ADC compare mode using adc_set_compare_channel(), adc_set_compare_mode()
|
||||
* and adc_set_comparison_window().
|
||||
* <li> ADC works with touchscreen using adc_ts_calibration(), adc_set_ts_mode(),
|
||||
* adc_set_ts_debounce(), adc_set_ts_pen_detect(), adc_set_ts_average(),
|
||||
* adc_get_ts_xposition(), adc_get_ts_yposition() and adc_get_ts_pressure().
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* For more accurate information, please look at the ADC section of the
|
||||
* Datasheet.
|
||||
*
|
||||
* Related files :\n
|
||||
* \ref adc.c\n
|
||||
* \ref adc.h\n
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implementation of Analog-to-Digital Converter (ADC).
|
||||
*
|
||||
*/
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/adc.h"
|
||||
#include "peripherals/pmc.h"
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local definitions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef ADC_MR_TRANSFER
|
||||
/* for compatibility with older peripheral versions */
|
||||
#define ADC_MR_TRANSFER(x) 0
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local variables
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/** Current working clock */
|
||||
static uint32_t _adc_clock = 0;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
uint32_t adc_num_channels(void)
|
||||
{
|
||||
return ARRAY_SIZE(ADC->ADC_CDR);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initialize the ADC controller
|
||||
*
|
||||
*/
|
||||
void adc_initialize(void)
|
||||
{
|
||||
/* Enable peripheral clock */
|
||||
pmc_enable_peripheral(ID_ADC);
|
||||
|
||||
/* Reset the controller */
|
||||
ADC->ADC_CR = ADC_CR_SWRST;
|
||||
|
||||
/* Reset Mode Register */
|
||||
ADC->ADC_MR = 0;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set ADC clock.
|
||||
*
|
||||
* \param clk adc clock frequency
|
||||
*
|
||||
* \return ADC clock
|
||||
*/
|
||||
uint32_t adc_set_clock(uint32_t clk)
|
||||
{
|
||||
uint32_t prescale, mode_reg;
|
||||
uint32_t mck = pmc_get_peripheral_clock(ID_ADC);
|
||||
/* Formula for PRESCAL is:
|
||||
ADCClock = MCK / ( (PRESCAL+1) * 2 )
|
||||
PRESCAL = (MCK / (2 * ADCCLK)) + 1
|
||||
First, we do the division, multiplied by 10 to get higher precision
|
||||
If the last digit is not zero, we round up to avoid generating a higher
|
||||
than required frequency. */
|
||||
prescale = (mck * 5) / clk;
|
||||
if (prescale % 10)
|
||||
prescale = prescale / 10;
|
||||
else {
|
||||
if (prescale == 0)
|
||||
return 0;
|
||||
prescale = prescale / 10 - 1;
|
||||
}
|
||||
|
||||
mode_reg = ADC_MR_PRESCAL(prescale);
|
||||
if (mode_reg == 0)
|
||||
return 0;
|
||||
|
||||
mode_reg |= (ADC->ADC_MR & ~ADC_MR_PRESCAL_Msk);
|
||||
ADC->ADC_MR = mode_reg;
|
||||
|
||||
_adc_clock = mck / (prescale + 1) / 2;
|
||||
//_adc_clock = _adc_clock / 1000 * 1000;
|
||||
return _adc_clock;
|
||||
}
|
||||
|
||||
void adc_enable_it(uint32_t mask)
|
||||
{
|
||||
ADC->ADC_IER |= mask;
|
||||
}
|
||||
|
||||
void adc_disable_it(uint32_t mask)
|
||||
{
|
||||
ADC->ADC_IER &= ~mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set ADC timing.
|
||||
*
|
||||
* \param startup startup value
|
||||
* \param tracking tracking value
|
||||
* \param settling settling value
|
||||
*/
|
||||
void adc_set_timing(uint32_t startup, uint32_t tracking, uint32_t settling)
|
||||
{
|
||||
uint32_t mode_reg;
|
||||
|
||||
#ifndef CONFIG_HAVE_ADC_SETTLING_TIME
|
||||
if (settling) {
|
||||
settling = 0;
|
||||
trace_warning("adc: Analog settling time not supported, IGNORED!\r\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
mode_reg = ADC->ADC_MR;
|
||||
mode_reg &= (~ADC_MR_STARTUP_Msk) & (~ADC_MR_TRACKTIM_Msk);
|
||||
|
||||
/* Formula:
|
||||
* Startup Time = startup value / ADCClock
|
||||
* Transfer Time = (TRANSFER * 2 + 3) / ADCClock
|
||||
* Tracking Time = (TRACKTIM + 1) / ADCClock
|
||||
* Settling Time = settling value / ADCClock
|
||||
*/
|
||||
mode_reg |= ADC_MR_STARTUP(startup);
|
||||
mode_reg |= ADC_MR_TRACKTIM(tracking);
|
||||
mode_reg |= ADC_MR_TRANSFER(2);
|
||||
#ifdef CONFIG_HAVE_ADC_SETTLING_TIME
|
||||
mode_reg |= ADC_MR_SETTLING(settling);
|
||||
#endif
|
||||
ADC->ADC_MR |= mode_reg;
|
||||
}
|
||||
|
||||
void adc_set_trigger_mode(uint32_t mode)
|
||||
{
|
||||
uint32_t trg_reg = ADC->ADC_TRGR & ~ADC_TRGR_TRGMOD_Msk;
|
||||
ADC->ADC_TRGR = trg_reg | mode;
|
||||
}
|
||||
|
||||
void adc_set_sleep_mode(uint8_t enable)
|
||||
{
|
||||
if (enable) {
|
||||
ADC->ADC_MR |= ADC_MR_SLEEP;
|
||||
} else {
|
||||
ADC->ADC_MR &= ~ADC_MR_SLEEP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable seqnence mode.
|
||||
*
|
||||
* \param enable Enable/Disable seqnence mode.
|
||||
*/
|
||||
void adc_set_sequence_mode(uint8_t enable)
|
||||
{
|
||||
if (enable) {
|
||||
/* User Sequence Mode: The sequence respects what is defined in
|
||||
ADC_SEQR1 and ADC_SEQR2 */
|
||||
ADC->ADC_MR |= ADC_MR_USEQ;
|
||||
} else {
|
||||
/* Normal Mode: The controller converts channels in a simple numeric order. */
|
||||
ADC->ADC_MR &= ~ADC_MR_USEQ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set channel sequence.
|
||||
*
|
||||
* \param seq1 Sequence 1 ~ 8 channel number.
|
||||
* \param seq2 Sequence 9 ~ 16 channel number.
|
||||
*/
|
||||
|
||||
void adc_set_sequence(uint32_t seq1, uint32_t seq2)
|
||||
{
|
||||
ADC->ADC_SEQR1 = seq1;
|
||||
#ifdef CONFIG_HAVE_ADC_SEQ_REG2
|
||||
ADC->ADC_SEQR2 = seq2;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set channel sequence by given channel list.
|
||||
*
|
||||
* \param channel_list Channel list.
|
||||
* \param len Number of channels in list.
|
||||
*/
|
||||
|
||||
void adc_set_sequence_by_list(uint8_t channel_list[], uint8_t len)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t shift;
|
||||
|
||||
if (len <= 8) {
|
||||
ADC->ADC_SEQR1 = 0;
|
||||
for (i = 0, shift = 0; i < len; i++, shift += 4) {
|
||||
if (i >= len) return;
|
||||
ADC->ADC_SEQR1 |= channel_list[i] << shift;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ADC->ADC_SEQR1 = 0;
|
||||
for (i = 0, shift = 0; i < 8; i++, shift += 4) {
|
||||
if (i >= len) return;
|
||||
ADC->ADC_SEQR1 |= channel_list[i] << shift;
|
||||
}
|
||||
#ifdef CONFIG_HAVE_ADC_SEQ_REG2
|
||||
ADC->ADC_SEQR2 = 0;
|
||||
for (i = 0, shift = 0; i < (len-8); i++, shift += 4) {
|
||||
if (i >= len) return;
|
||||
ADC->ADC_SEQR2 |= channel_list[8+i] << shift;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void adc_set_tag_enable(uint8_t enable)
|
||||
{
|
||||
if (enable) {
|
||||
ADC->ADC_EMR |= ADC_EMR_TAG;
|
||||
} else {
|
||||
ADC->ADC_EMR &= ~ADC_EMR_TAG;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set compare channel.
|
||||
*
|
||||
* \param channel channel number to be set, xx for all channels
|
||||
*/
|
||||
void adc_set_compare_channel(uint32_t channel)
|
||||
{
|
||||
assert(channel <= adc_num_channels());
|
||||
|
||||
if (channel < adc_num_channels()) {
|
||||
ADC->ADC_EMR &= ~(ADC_EMR_CMPALL);
|
||||
ADC->ADC_EMR &= ~(ADC_EMR_CMPSEL_Msk);
|
||||
ADC->ADC_EMR |= (channel << ADC_EMR_CMPSEL_Pos);
|
||||
} else {
|
||||
ADC->ADC_EMR |= ADC_EMR_CMPALL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set compare mode.
|
||||
*
|
||||
* \param mode compare mode
|
||||
*/
|
||||
void adc_set_compare_mode(uint32_t mode)
|
||||
{
|
||||
ADC->ADC_EMR &= ~(ADC_EMR_CMPMODE_Msk);
|
||||
ADC->ADC_EMR |= (mode & ADC_EMR_CMPMODE_Msk);
|
||||
}
|
||||
|
||||
void adc_set_comparison_window(uint32_t window)
|
||||
{
|
||||
ADC->ADC_CWR = window;
|
||||
}
|
||||
|
||||
uint8_t adc_check_configuration(void)
|
||||
{
|
||||
uint32_t mode_reg;
|
||||
uint32_t prescale;
|
||||
uint32_t clock;
|
||||
uint32_t mck = pmc_get_peripheral_clock(ID_ADC);
|
||||
|
||||
mode_reg = ADC->ADC_MR;
|
||||
|
||||
prescale = (mode_reg & ADC_MR_PRESCAL_Msk) >> ADC_MR_PRESCAL_Pos;
|
||||
/* Formula: ADCClock = MCK / ( (PRESCAL+1) * 2 ) */
|
||||
clock = mck / ((prescale + 1) * 2);
|
||||
if (clock > ADC_CLOCK_MAX) {
|
||||
printf ("ADC clock is too high (out of specification: %d Hz)\r\n",
|
||||
(int) ADC_CLOCK_MAX);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t adc_get_converted_data(uint32_t channel)
|
||||
{
|
||||
assert(channel < adc_num_channels());
|
||||
|
||||
if (channel < adc_num_channels()) {
|
||||
return ADC->ADC_CDR[channel];
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void adc_set_startup_time(uint32_t startup)
|
||||
{
|
||||
uint32_t start;
|
||||
uint32_t mode_reg;
|
||||
|
||||
if (_adc_clock == 0)
|
||||
return;
|
||||
/* Formula for STARTUP is:
|
||||
STARTUP = (time x ADCCLK) / (1000000) - 1
|
||||
Division multiplied by 10 for higher precision */
|
||||
|
||||
start = (startup * _adc_clock) / (100000);
|
||||
if (start % 10)
|
||||
start /= 10;
|
||||
else {
|
||||
start /= 10;
|
||||
if (start)
|
||||
start--;
|
||||
}
|
||||
if (start > 896)
|
||||
mode_reg = ADC_MR_STARTUP_SUT960;
|
||||
else if (start > 832)
|
||||
mode_reg = ADC_MR_STARTUP_SUT896;
|
||||
else if (start > 768)
|
||||
mode_reg = ADC_MR_STARTUP_SUT832;
|
||||
else if (start > 704)
|
||||
mode_reg = ADC_MR_STARTUP_SUT768;
|
||||
else if (start > 640)
|
||||
mode_reg = ADC_MR_STARTUP_SUT704;
|
||||
else if (start > 576)
|
||||
mode_reg = ADC_MR_STARTUP_SUT640;
|
||||
else if (start > 512)
|
||||
mode_reg = ADC_MR_STARTUP_SUT576;
|
||||
else if (start > 112)
|
||||
mode_reg = ADC_MR_STARTUP_SUT512;
|
||||
else if (start > 96)
|
||||
mode_reg = ADC_MR_STARTUP_SUT112;
|
||||
else if (start > 80)
|
||||
mode_reg = ADC_MR_STARTUP_SUT96;
|
||||
else if (start > 64)
|
||||
mode_reg = ADC_MR_STARTUP_SUT80;
|
||||
else if (start > 24)
|
||||
mode_reg = ADC_MR_STARTUP_SUT64;
|
||||
else if (start > 16)
|
||||
mode_reg = ADC_MR_STARTUP_SUT24;
|
||||
else if (start > 8)
|
||||
mode_reg = ADC_MR_STARTUP_SUT16;
|
||||
else if (start > 0)
|
||||
mode_reg = ADC_MR_STARTUP_SUT8;
|
||||
else
|
||||
mode_reg = ADC_MR_STARTUP_SUT0;
|
||||
|
||||
mode_reg |= ADC->ADC_MR & ~ADC_MR_STARTUP_Msk;
|
||||
ADC->ADC_MR = mode_reg;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_ADC_INPUT_OFFSET
|
||||
/**
|
||||
* \brief Enable differential input for the specified channel.
|
||||
*
|
||||
* \param channel ADC channel number.
|
||||
*/
|
||||
void adc_enable_channel_differential_input (uint32_t channel)
|
||||
{
|
||||
/* (ADC_COR) Differential Inputs for Channel n */
|
||||
ADC->ADC_COR |= 0x01u << (16 + channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable differential input for the specified channel.
|
||||
*
|
||||
* \param channel ADC channel number.
|
||||
*/
|
||||
void adc_disable_channel_differential_input(uint32_t channel)
|
||||
{
|
||||
uint32_t temp;
|
||||
temp = ADC->ADC_COR;
|
||||
ADC->ADC_COR &= 0xFFFEFFFFu << channel;
|
||||
ADC->ADC_COR |= temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable analog signal offset for the specified channel.
|
||||
*
|
||||
* \param channel ADC channel number.
|
||||
*/
|
||||
void adc_enable_channel_input_offset (uint32_t channel)
|
||||
{
|
||||
ADC->ADC_COR |= 0x01u << channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable analog signal offset for the specified channel.
|
||||
*
|
||||
* \param channel ADC channel number.
|
||||
*/
|
||||
void adc_disable_channel_input_offset (uint32_t channel)
|
||||
{
|
||||
uint32_t temp;
|
||||
temp = ADC->ADC_COR;
|
||||
ADC->ADC_COR &= (0xFFFFFFFEu << channel);
|
||||
ADC->ADC_COR |= temp;
|
||||
}
|
||||
#endif /* CONFIG_HAVE_ADC_INPUT_OFFSET */
|
||||
|
||||
#ifdef CONFIG_HAVE_ADC_INPUT_GAIN
|
||||
/**
|
||||
* \brief Configure input gain for the specified channel.
|
||||
*
|
||||
* \param channel ADC channel number.
|
||||
* \param gain Gain value for the input.
|
||||
*/
|
||||
void adc_set_channel_input_gain (uint32_t channel, uint32_t gain)
|
||||
{
|
||||
assert(gain < 3);
|
||||
uint32_t temp;
|
||||
temp = ADC->ADC_CGR;
|
||||
temp |= gain << (2 * channel);
|
||||
ADC->ADC_CGR = temp;
|
||||
}
|
||||
#endif /* CONFIG_HAVE_ADC_INPUT_GAIN */
|
||||
|
||||
void adc_set_tracking_time(uint32_t dwNs)
|
||||
{
|
||||
uint32_t dwShtim;
|
||||
uint32_t mode_reg;
|
||||
|
||||
if (_adc_clock == 0)
|
||||
return;
|
||||
/* Formula for SHTIM is:
|
||||
SHTIM = (time x ADCCLK) / (1000000000) - 1
|
||||
Since 1 billion is close to the maximum value for an integer, we first
|
||||
divide ADCCLK by 1000 to avoid an overflow */
|
||||
dwShtim = (dwNs * (_adc_clock / 1000)) / 100000;
|
||||
if (dwShtim % 10)
|
||||
dwShtim /= 10;
|
||||
else {
|
||||
dwShtim /= 10;
|
||||
if (dwShtim)
|
||||
dwShtim--;
|
||||
}
|
||||
mode_reg = ADC_MR_TRACKTIM(dwShtim);
|
||||
mode_reg |= ADC->ADC_MR & ~ADC_MR_TRACKTIM_Msk;
|
||||
ADC->ADC_MR = mode_reg;
|
||||
}
|
||||
|
||||
void adc_set_trigger_period(uint32_t period)
|
||||
{
|
||||
uint32_t trg_period;
|
||||
uint32_t trg_reg;
|
||||
if (_adc_clock == 0)
|
||||
return;
|
||||
trg_period = period * (_adc_clock/1000) - 1;
|
||||
trg_reg = ADC->ADC_TRGR & ~ADC_TRGR_TRGPER_Msk;
|
||||
trg_reg |= ADC_TRGR_TRGPER(trg_period);
|
||||
ADC->ADC_TRGR = trg_reg;
|
||||
}
|
||||
|
||||
void adc_ts_calibration(void)
|
||||
{
|
||||
ADC->ADC_CR = ADC_CR_TSCALIB;
|
||||
}
|
||||
|
||||
void adc_set_ts_mode(uint32_t mode)
|
||||
{
|
||||
ADC->ADC_TSMR = (ADC->ADC_TSMR & ~ADC_TSMR_TSMODE_Msk) | mode;
|
||||
}
|
||||
|
||||
void adc_configure_ext_mode(uint32_t mode)
|
||||
{
|
||||
ADC->ADC_EMR = mode;
|
||||
}
|
||||
|
||||
void adc_set_ts_debounce(uint32_t time)
|
||||
{
|
||||
uint32_t div = 1000000000;
|
||||
uint32_t clk = _adc_clock;
|
||||
uint32_t dwPenbc = 0;
|
||||
uint32_t target, current;
|
||||
uint32_t tsmr;
|
||||
if (time == 0 || _adc_clock == 0)
|
||||
return;
|
||||
/* Divide time & ADCCLK to avoid overflows */
|
||||
while ((div > 1) && ((time % 10) == 0)) {
|
||||
time /= 10;
|
||||
div /= 10;
|
||||
}
|
||||
while ((div > 1) && ((clk & 10) == 0)) {
|
||||
clk /= 10;
|
||||
div /= 10;
|
||||
}
|
||||
/* Compute PENDBC */
|
||||
target = time * clk / div;
|
||||
current = 1;
|
||||
while (current < target) {
|
||||
dwPenbc++;
|
||||
current *= 2;
|
||||
}
|
||||
tsmr = ADC_TSMR_PENDBC(dwPenbc);
|
||||
if (tsmr == 0)
|
||||
return;
|
||||
tsmr |= ADC->ADC_TSMR & ~ADC_TSMR_PENDBC_Msk;
|
||||
ADC->ADC_TSMR = tsmr;
|
||||
}
|
||||
|
||||
void adc_set_ts_pen_detect(uint8_t enable)
|
||||
{
|
||||
if (enable)
|
||||
ADC->ADC_TSMR |= ADC_TSMR_PENDET;
|
||||
else
|
||||
ADC->ADC_TSMR &= ~ADC_TSMR_PENDET;
|
||||
}
|
||||
|
||||
void adc_set_ts_average(uint32_t avg_2_conv)
|
||||
{
|
||||
uint32_t mode_reg = ADC->ADC_TSMR & ~ADC_TSMR_TSAV_Msk;
|
||||
uint32_t ts_av = avg_2_conv >> ADC_TSMR_TSAV_Pos;
|
||||
uint32_t ts_freq = (mode_reg & ADC_TSMR_TSFREQ_Msk) >> ADC_TSMR_TSFREQ_Pos;
|
||||
if (ts_av) {
|
||||
if (ts_av > ts_freq) {
|
||||
mode_reg &= ~ADC_TSMR_TSFREQ_Msk;
|
||||
mode_reg |= ADC_TSMR_TSFREQ(ts_av);
|
||||
}
|
||||
}
|
||||
ADC->ADC_TSMR = mode_reg | avg_2_conv;
|
||||
}
|
||||
|
||||
uint32_t adc_get_ts_xposition(void)
|
||||
{
|
||||
return ADC->ADC_XPOSR;
|
||||
}
|
||||
|
||||
uint32_t adc_get_ts_yposition(void)
|
||||
{
|
||||
return ADC->ADC_YPOSR;
|
||||
}
|
||||
|
||||
uint32_t adc_get_ts_pressure(void)
|
||||
{
|
||||
return ADC->ADC_PRESSR;
|
||||
}
|
||||
|
||||
void adc_set_trigger(uint32_t trigger)
|
||||
{
|
||||
uint32_t mode_reg;
|
||||
|
||||
mode_reg = ADC->ADC_MR;
|
||||
mode_reg &= ~ADC_MR_TRGSEL_Msk;
|
||||
mode_reg |= trigger;
|
||||
ADC->ADC_MR |= mode_reg;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_ADC_LOW_RES
|
||||
void adc_set_low_resolution(uint8_t enable)
|
||||
{
|
||||
if (enable) {
|
||||
ADC->ADC_MR |= ADC_MR_LOWRES;
|
||||
} else {
|
||||
ADC->ADC_MR &= ~ADC_MR_LOWRES;
|
||||
}
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,399 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \section Purpose
|
||||
*
|
||||
* Interface for configuration the Analog-to-Digital Converter (ADC) peripheral.
|
||||
*
|
||||
* \section Usage
|
||||
*
|
||||
* -# Configurate the pins for ADC.
|
||||
* -# Initialize the ADC with adc_initialize().
|
||||
* -# Set ADC clock and timing with adc_set_clock() and adc_set_timing().
|
||||
* -# Select the active channel using adc_enable_channel().
|
||||
* -# Start the conversion with adc_start_conversion().
|
||||
* -# Wait the end of the conversion by polling status with adc_get_status().
|
||||
* -# Finally, get the converted data using adc_get_converted_data() or adc_get_last_converted_data().
|
||||
*
|
||||
*/
|
||||
#ifndef _ADC_
|
||||
#define _ADC_
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Definitions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/* Max. ADC Clock Frequency (Hz) */
|
||||
#define ADC_CLOCK_MAX 20000000
|
||||
|
||||
/* Max. normal ADC startup time (us) */
|
||||
#define ADC_STARTUP_NORMAL_MAX 40
|
||||
/* Max. fast ADC startup time (us) */
|
||||
#define ADC_STARTUP_FAST_MAX 12
|
||||
|
||||
/* Definitions for ADC channels */
|
||||
#define ADC_CHANNEL_0 0
|
||||
#define ADC_CHANNEL_1 1
|
||||
#define ADC_CHANNEL_2 2
|
||||
#define ADC_CHANNEL_3 3
|
||||
#define ADC_CHANNEL_4 4
|
||||
#define ADC_CHANNEL_5 5
|
||||
#define ADC_CHANNEL_6 6
|
||||
#define ADC_CHANNEL_7 7
|
||||
#define ADC_CHANNEL_8 8
|
||||
#define ADC_CHANNEL_9 9
|
||||
#define ADC_CHANNEL_10 10
|
||||
#define ADC_CHANNEL_11 11
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Macros function of register access
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#define adc_get_mode_reg() (ADC->ADC_MR)
|
||||
|
||||
#define adc_start_conversion() (ADC->ADC_CR = ADC_CR_START)
|
||||
|
||||
#define adc_enable_channel(channel) { \
|
||||
ADC->ADC_CHER = (1 << (channel)); \
|
||||
}
|
||||
|
||||
#define adc_disable_channel(channel) { \
|
||||
ADC->ADC_CHDR = (1 << (channel)); \
|
||||
}
|
||||
|
||||
#define adc_enable_interrupt(mode) { \
|
||||
ADC->ADC_IER = (mode); \
|
||||
}
|
||||
|
||||
#define adc_disable_interrupt(mode) { \
|
||||
ADC->ADC_IDR = (mode); \
|
||||
}
|
||||
|
||||
#define adc_set_channel_gain(mode) { \
|
||||
ADC->ADC_CGR = mode; \
|
||||
}
|
||||
|
||||
#define adc_enable_data_ready_it() (ADC->ADC_IER = ADC_IER_DRDY)
|
||||
|
||||
#define adc_get_status() (ADC->ADC_ISR)
|
||||
|
||||
#define adc_get_compare_mode() ((ADC->ADC_EMR)& (ADC_EMR_CMPMODE_Msk))
|
||||
|
||||
#define adc_get_channel_status() (ADC->ADC_CHSR)
|
||||
|
||||
#define adc_interrupt_mask_status() (ADC->ADC_IMR)
|
||||
|
||||
#define adc_get_last_converted_data() (ADC->ADC_LCDR)
|
||||
|
||||
#define adc_get_overrun_status() (ADC->ADC_OVER)
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Returns the number of ADC channels
|
||||
*/
|
||||
extern uint32_t adc_num_channels(void);
|
||||
|
||||
/**
|
||||
* \brief Initialize the ADC controller
|
||||
*/
|
||||
extern void adc_initialize(void);
|
||||
|
||||
/**
|
||||
* \brief Set ADC clock.
|
||||
*
|
||||
* \param clk Desired ADC clock frequency.
|
||||
*
|
||||
* \return ADC clock
|
||||
*/
|
||||
extern uint32_t adc_set_clock(uint32_t clk);
|
||||
|
||||
/**
|
||||
* \brief Enable ADC interrupt sources
|
||||
*
|
||||
* \param mask bitmask of the sources to enable
|
||||
*/
|
||||
extern void adc_enable_it(uint32_t mask);
|
||||
|
||||
/**
|
||||
* \brief Disable ADC interrupt sources
|
||||
*
|
||||
* \param mask bitmask of the sources to disable
|
||||
*/
|
||||
extern void adc_disable_it(uint32_t mask);
|
||||
|
||||
/**
|
||||
* \brief Set ADC timing.
|
||||
*
|
||||
* \param startup startup value
|
||||
* \param tracking tracking value
|
||||
* \param settling settling value
|
||||
*/
|
||||
extern void adc_set_timing(uint32_t startup, uint32_t tracking,
|
||||
uint32_t settling);
|
||||
|
||||
/**
|
||||
* Sets the trigger mode to following:
|
||||
* - \ref ADC_TRGR_TRGMOD_NO_TRIGGER
|
||||
* - \ref ADC_TRGR_TRGMOD_EXT_TRIG_RISE
|
||||
* - \ref ADC_TRGR_TRGMOD_EXT_TRIG_FALL
|
||||
* - \ref ADC_TRGR_TRGMOD_EXT_TRIG_ANY
|
||||
* - \ref ADC_TRGR_TRGMOD_PEN_TRIG
|
||||
* - \ref ADC_TRGR_TRGMOD_PERIOD_TRIG
|
||||
* - \ref ADC_TRGR_TRGMOD_CONTINUOUS
|
||||
* \param mode Trigger mode.
|
||||
*/
|
||||
extern void adc_set_trigger_mode(uint32_t mode);
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable sleep mode.
|
||||
*
|
||||
* \param enable Enable/Disable sleep mode.
|
||||
*/
|
||||
extern void adc_set_sleep_mode(uint8_t enable);
|
||||
|
||||
extern void adc_set_fast_wakeup(uint8_t enable);
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable seqnence mode.
|
||||
*
|
||||
* \param enable Enable/Disable seqnence mode.
|
||||
*/
|
||||
extern void adc_set_sequence_mode(uint8_t enable);
|
||||
|
||||
/**
|
||||
* \brief Set channel sequence.
|
||||
*
|
||||
* \param seq1 Sequence 1 ~ 8 channel number.
|
||||
* \param seq2 Sequence 9 ~ 16 channel number.
|
||||
*/
|
||||
extern void adc_set_sequence(uint32_t seq1, uint32_t seq2);
|
||||
|
||||
/**
|
||||
* \brief Set channel sequence by given channel list.
|
||||
*
|
||||
* \param channel_list Channel list.
|
||||
* \param len Number of channels in list.
|
||||
*/
|
||||
extern void adc_set_sequence_by_list(uint8_t channel_list[],
|
||||
uint8_t len);
|
||||
|
||||
/**
|
||||
* \brief Set "TAG" mode, show channel number in last data or not.
|
||||
*
|
||||
* \param enable Enable/Disable TAG value.
|
||||
*/
|
||||
extern void adc_set_tag_enable(uint8_t enable);
|
||||
|
||||
/**
|
||||
* Configure extended mode register
|
||||
* \param mode ADC extended mode.
|
||||
*/
|
||||
extern void adc_configure_ext_mode(uint32_t mode);
|
||||
|
||||
/**
|
||||
* \brief Set compare channel.
|
||||
*
|
||||
* \param channel channel number to be set,16 for all channels
|
||||
*/
|
||||
extern void adc_set_compare_channel(uint32_t channel);
|
||||
|
||||
/**
|
||||
* \brief Set compare mode.
|
||||
*
|
||||
* \param mode compare mode
|
||||
*/
|
||||
extern void adc_set_compare_mode(uint32_t mode);
|
||||
|
||||
/**
|
||||
* \brief Set comparsion window.
|
||||
*
|
||||
* \param window Comparison Window
|
||||
*/extern void adc_set_comparison_window(uint32_t window);
|
||||
|
||||
/**
|
||||
* \brief Check if ADC configuration is right.
|
||||
*
|
||||
* \return 0 if check ok, others if not ok.
|
||||
*/
|
||||
extern uint8_t adc_check_configuration(void);
|
||||
|
||||
/**
|
||||
* \brief Return the Channel Converted Data
|
||||
*
|
||||
* \param channel channel to get converted value
|
||||
*/
|
||||
extern uint32_t adc_get_converted_data(uint32_t channel);
|
||||
|
||||
#ifdef CONFIG_HAVE_ADC_INPUT_OFFSET
|
||||
/**
|
||||
* \brief Enable differential input for the specified channel.
|
||||
*
|
||||
* \param channel ADC channel number.
|
||||
*/
|
||||
extern void adc_enable_channel_differential_input (uint32_t channel);
|
||||
|
||||
/**
|
||||
* \brief Disable differential input for the specified channel.
|
||||
*
|
||||
* \param channel ADC channel number.
|
||||
*/
|
||||
extern void adc_disable_channel_differential_input(uint32_t channel);
|
||||
|
||||
/**
|
||||
* \brief Enable analog signal offset for the specified channel.
|
||||
*
|
||||
* \param channel ADC channel number.
|
||||
*/
|
||||
extern void adc_enable_channel_input_offset (uint32_t channel);
|
||||
|
||||
/**
|
||||
* \brief Disable analog signal offset for the specified channel.
|
||||
*
|
||||
* \param channel ADC channel number.
|
||||
*/
|
||||
extern void adc_disable_channel_input_offset (uint32_t channel);
|
||||
#endif /* CONFIG_HAVE_ADC_INPUT_OFFSET */
|
||||
|
||||
#ifdef CONFIG_HAVE_ADC_INPUT_GAIN
|
||||
/**
|
||||
* \brief Configure input gain for the specified channel.
|
||||
*
|
||||
* \param channel ADC channel number.
|
||||
* \param gain Gain value for the input.
|
||||
*/
|
||||
extern void adc_set_channel_input_gain (uint32_t channel, uint32_t gain);
|
||||
#endif /* CONFIG_HAVE_ADC_INPUT_GAIN */
|
||||
|
||||
/**
|
||||
* Sets the average of the touch screen ADC. The mode can be:
|
||||
* - \ref ADC_TSMR_TSAV_NO_FILTER (No filtering)
|
||||
* - \ref ADC_TSMR_TSAV_AVG2CONV (Average 2 conversions)
|
||||
* - \ref ADC_TSMR_TSAV_AVG4CONV (Average 4 conversions)
|
||||
* - \ref ADC_TSMR_TSAV_AVG8CONV (Average 8 conversions)
|
||||
* \param avg_2_conv Average mode for touch screen
|
||||
*/
|
||||
extern void adc_set_ts_average(uint32_t avg_2_conv);
|
||||
|
||||
/**
|
||||
* Return X measurement position value.
|
||||
*/
|
||||
extern uint32_t adc_get_ts_xposition(void);
|
||||
|
||||
/**
|
||||
* Return Y measurement position value.
|
||||
*/
|
||||
extern uint32_t adc_get_ts_yposition(void);
|
||||
|
||||
/**
|
||||
* Return Z measurement position value.
|
||||
*/
|
||||
extern uint32_t adc_get_ts_pressure(void);
|
||||
|
||||
/**
|
||||
* Sets the touchscreen pan debounce time.
|
||||
* \param time Debounce time in nS.
|
||||
*/
|
||||
extern void adc_set_ts_debounce(uint32_t time);
|
||||
|
||||
/**
|
||||
* Enable/Disable touch screen pen detection.
|
||||
* \param enable If true, pen detection is enabled;
|
||||
* in normal mode otherwise.
|
||||
*/
|
||||
extern void adc_set_ts_pen_detect(uint8_t enable);
|
||||
|
||||
/**
|
||||
* Sets the ADC startup time.
|
||||
* \param startup Startup time in uS.
|
||||
*/
|
||||
extern void adc_set_startup_time(uint32_t startup);
|
||||
|
||||
/**
|
||||
* Set ADC tracking time
|
||||
* \param dwNs Tracking time in nS.
|
||||
*/
|
||||
extern void adc_set_tracking_time(uint32_t dwNs);
|
||||
|
||||
/**
|
||||
* Sets the trigger period.
|
||||
* \param period Trigger period in nS.
|
||||
*/
|
||||
extern void adc_set_trigger_period(uint32_t period);
|
||||
|
||||
/**
|
||||
* Sets the operation mode of the touch screen ADC. The mode can be:
|
||||
* - \ref ADC_TSMR_TSMODE_NONE (TSADC off)
|
||||
* - \ref ADC_TSMR_TSMODE_4_WIRE_NO_PM
|
||||
* - \ref ADC_TSMR_TSMODE_4_WIRE (CH 0~3 used)
|
||||
* - \ref ADC_TSMR_TSMODE_5_WIRE (CH 0~4 used)
|
||||
* \param mode Desired mode
|
||||
*/
|
||||
extern void adc_set_ts_mode(uint32_t mode);
|
||||
|
||||
/**
|
||||
* Start screen calibration (VDD/GND measurement)
|
||||
*/
|
||||
extern void adc_ts_calibration(void);
|
||||
|
||||
/**
|
||||
* \brief Set ADC trigger.
|
||||
*
|
||||
* \param trigger Trigger selection
|
||||
*/
|
||||
extern void adc_set_trigger(uint32_t trigger);
|
||||
|
||||
#ifdef CONFIG_HAVE_ADC_LOW_RES
|
||||
/**
|
||||
* \brief Enable/Disable low resolution.
|
||||
*
|
||||
* \param enable Enable/Disable low resolution.
|
||||
*/
|
||||
extern void adc_set_low_resolution(uint8_t enable);
|
||||
#endif /* CONFIG_HAVE_ADC_LOW_RES */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _ADC_ */
|
|
@ -0,0 +1,201 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \addtogroup aes_module Working with AES
|
||||
* \ingroup peripherals_module
|
||||
* The AES driver provides the interface to configure and use the AES
|
||||
* peripheral.
|
||||
* \n
|
||||
*
|
||||
* The Advanced Encryption Standard (AES) specifies a FIPS-approved
|
||||
* cryptographic algorithm that can be used to protect electronic data. The AES
|
||||
* algorithm is a symmetric block cipher that can encrypt (encipher) and decrypt
|
||||
* (decipher) information.
|
||||
* Encryption converts data to an unintelligible form called ciphertext.
|
||||
* Decrypting the ciphertext converts the data back into its original form,
|
||||
* called plaintext. The CIPHER bit in the AES Mode Register (AES_MR) allows
|
||||
* selection between the encryption and the decryption processes. The AES is
|
||||
* capable of using cryptographic keys of 128/192/256 bits to encrypt and
|
||||
* decrypt data in blocks of 128 bits.
|
||||
* This 128-bit/192-bit/256-bit key is defined in the Key Registers (AES_KEYWRx)
|
||||
* and set by aes_write_key(). The input to the encryption processes of the CBC,
|
||||
* CFB, and OFB modes includes, in addition to the plaintext, a 128-bit data
|
||||
* block called the initialization vector (IV), which must be set using
|
||||
* aes_set_vector(). The initialization vector is used in an initial step in the
|
||||
* encryption of a message and in the corresponding decryption of the message.
|
||||
* The Initialization Vector Registers are also used by the CTR mode to set the
|
||||
* counter value.
|
||||
*
|
||||
* To enable AES encryption and decryption, the user has to follow these few
|
||||
* steps:
|
||||
* <ul>
|
||||
* <li> A software triggered hardware reset of the AES interface is performed by
|
||||
* aes_soft_reset().</li>
|
||||
* <li> Configure AES algorithm mode, key mode, start mode and operation mode
|
||||
* with aes_configure().</li>
|
||||
* <li> Input AES data for encryption and decryption with function
|
||||
* aes_set_input().</li>
|
||||
* <li> Set AES key with fucntion aes_write_key().</li>
|
||||
* <li> To start the encryption or the decryption process with aes_start().</li>
|
||||
* <li> To get the encryption or decryption result by aes_get_output().</li>
|
||||
* </ul>
|
||||
*
|
||||
*
|
||||
* For more accurate information, please look at the AES section of the
|
||||
* Datasheet.
|
||||
*
|
||||
* Related files :\n
|
||||
* \ref aes.c\n
|
||||
* \ref aes.h\n
|
||||
*/
|
||||
/*@{*/
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implementation of Advanced Encryption Standard (AES)
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/aes.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void aes_start(void)
|
||||
{
|
||||
AES->AES_CR = AES_CR_START;
|
||||
}
|
||||
|
||||
void aes_soft_reset(void)
|
||||
{
|
||||
AES->AES_CR = AES_CR_SWRST;
|
||||
}
|
||||
|
||||
void aes_configure(uint32_t mode)
|
||||
{
|
||||
AES->AES_MR = mode;
|
||||
}
|
||||
|
||||
void aes_enable_it(uint32_t sources)
|
||||
{
|
||||
AES->AES_IER = sources;
|
||||
}
|
||||
|
||||
void aes_disable_it(uint32_t sources)
|
||||
{
|
||||
AES->AES_IDR = sources;
|
||||
}
|
||||
|
||||
uint32_t aes_get_status(void)
|
||||
{
|
||||
return AES->AES_ISR;
|
||||
}
|
||||
|
||||
void aes_write_key(const uint32_t * key, uint32_t len)
|
||||
{
|
||||
AES->AES_KEYWR[0] = key[0];
|
||||
AES->AES_KEYWR[1] = key[1];
|
||||
AES->AES_KEYWR[2] = key[2];
|
||||
AES->AES_KEYWR[3] = key[3];
|
||||
|
||||
if (len >= 24) {
|
||||
AES->AES_KEYWR[4] = key[4];
|
||||
AES->AES_KEYWR[5] = key[5];
|
||||
}
|
||||
if (len == 32) {
|
||||
AES->AES_KEYWR[6] = key[6];
|
||||
AES->AES_KEYWR[7] = key[7];
|
||||
}
|
||||
}
|
||||
|
||||
void aes_set_input(uint32_t * data)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < 4; i++)
|
||||
AES->AES_IDATAR[i] = data[i];
|
||||
}
|
||||
|
||||
void aes_get_output(uint32_t * data)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < 4; i++)
|
||||
data[i] = AES->AES_ODATAR[i];
|
||||
}
|
||||
|
||||
void aes_set_vector(const uint32_t * vector)
|
||||
{
|
||||
AES->AES_IVR[0] = vector[0];
|
||||
AES->AES_IVR[1] = vector[1];
|
||||
AES->AES_IVR[2] = vector[2];
|
||||
AES->AES_IVR[3] = vector[3];
|
||||
}
|
||||
|
||||
void aes_set_aad_len(uint32_t len)
|
||||
{
|
||||
AES->AES_AADLENR = len;
|
||||
}
|
||||
|
||||
void aes_set_data_len(uint32_t len)
|
||||
{
|
||||
AES->AES_CLENR = len;
|
||||
}
|
||||
|
||||
void aes_set_gcm_hash(uint32_t * hash)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < 4; i++)
|
||||
AES->AES_GHASHR[i] = hash[i];
|
||||
}
|
||||
|
||||
void aes_get_gcm_tag(uint32_t * tag)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < 4; i++)
|
||||
tag[i] = AES->AES_TAGR[i];
|
||||
}
|
||||
|
||||
void aes_get_gcm_counter(uint32_t * counter)
|
||||
{
|
||||
*counter = AES->AES_CTRR;
|
||||
}
|
||||
|
||||
void aes_get_gcm_hash_subkey(uint32_t * h)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < 4; i++)
|
||||
h[i] = AES->AES_GCMHR[i];
|
||||
}
|
|
@ -0,0 +1,155 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _AES_
|
||||
#define _AES_
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
/* Definition */
|
||||
/*------------------------------------------------------------------------------*/
|
||||
#define AES_MR_CIPHER_ENCRYPT 1
|
||||
#define AES_MR_CIPHER_DECRYPT 0
|
||||
/*------------------------------------------------------------------------------*/
|
||||
/* Exported functions */
|
||||
/*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Starts Manual encryption/decryption process.
|
||||
*/
|
||||
void aes_start(void);
|
||||
|
||||
/**
|
||||
* \brief Resets the AES.
|
||||
* A software triggered hardware reset of the AES interface is performed.
|
||||
*/
|
||||
void aes_soft_reset(void);
|
||||
|
||||
/**
|
||||
* \brief Configures an AES peripheral with the specified parameters.
|
||||
* \param mode Desired value for the AES mode register (see the datasheet).
|
||||
*/
|
||||
void aes_configure(uint32_t mode);
|
||||
|
||||
/**
|
||||
* \brief Enables the selected interrupts sources on a AES peripheral.
|
||||
* \param sources Bitwise OR of selected interrupt sources.
|
||||
*/
|
||||
void aes_enable_it(uint32_t sources);
|
||||
|
||||
/**
|
||||
* \brief Disables the selected interrupts sources on a AES peripheral.
|
||||
* \param sources Bitwise OR of selected interrupt sources.
|
||||
*/
|
||||
void aes_disable_it(uint32_t sources);
|
||||
|
||||
/**
|
||||
* \brief Get the current status register of the given AES peripheral.
|
||||
* \return AES status register.
|
||||
*/
|
||||
extern uint32_t aes_get_status(void);
|
||||
|
||||
/**
|
||||
* \brief Set the 128-bit/192-bit/256-bit cryptographic key used for
|
||||
* encryption/decryption.
|
||||
* \param key Pointer to a 16/24/32 bytes cipher key.
|
||||
* \param len Length of the key, in bytes.
|
||||
*/
|
||||
void aes_write_key(const uint32_t * key, uint32_t len);
|
||||
|
||||
/**
|
||||
* \brief Set the for 32-bit input Data allow to set the 128-bit data block used
|
||||
* for encryption/decryption.
|
||||
* \param data Pointer to the 16-bytes data to cipher/decipher.
|
||||
*/
|
||||
void aes_set_input(uint32_t * data);
|
||||
|
||||
/**
|
||||
* \brief Get the four 32-bit data contain the 128-bit data block which has
|
||||
* been encrypted/decrypted.
|
||||
* \param data Pointer to the word that has been encrypted/decrypted..
|
||||
*/
|
||||
void aes_get_output(uint32_t * data);
|
||||
|
||||
/**
|
||||
* \brief Set four 64-bit initialization vector data block, which is used by
|
||||
* some modes of operation as an additional initial input.
|
||||
* \param vector Pointer to the word of the initialization vector.
|
||||
*/
|
||||
void aes_set_vector(const uint32_t * vector);
|
||||
|
||||
/**
|
||||
* \brief Set Length in bytes of the Additional Authenticated Data that are to
|
||||
* be processed.
|
||||
* \param len Length.
|
||||
*/
|
||||
void aes_set_aad_len(uint32_t len);
|
||||
|
||||
/**
|
||||
* \brief Set Length in bytes of the plaintext/ciphertext data (that is, the C
|
||||
* portion of the message) that are to be processed.
|
||||
* \param len Length.
|
||||
*/
|
||||
void aes_set_data_len(uint32_t len);
|
||||
|
||||
/**
|
||||
* \brief Set The four 32-bit Hash Word registers expose the intermediate GHASH
|
||||
* value. May be read to save the current GHASH value so processing can later be
|
||||
* resumed, presumably on a later message fragment.
|
||||
* Modes of operation as an additional initial input.
|
||||
* \param hash Pointer to the word of the hash.
|
||||
*/
|
||||
void aes_set_gcm_hash(uint32_t * hash);
|
||||
|
||||
/**
|
||||
* \brief Get The four 32-bit Tag which contain the final 128-bit GCM
|
||||
* Authentication tag 'T' when GCM processing is complete.
|
||||
* \param tag Pointer to the word of the tag.
|
||||
*/
|
||||
void aes_get_gcm_tag(uint32_t * tag);
|
||||
|
||||
/**
|
||||
* \brief Reports the current value of the 32-bit GCM counter.
|
||||
* \param counter Pointer to value of GCM counter.
|
||||
*/
|
||||
void aes_get_gcm_counter(uint32_t * counter);
|
||||
|
||||
/**
|
||||
* \brief Get the four 32-bit data containing the 128-bit H value computed from
|
||||
* the KEYW value.
|
||||
* \param h Pointer to the word that has been encrypted/decrypted.
|
||||
*/
|
||||
void aes_get_gcm_hash_subkey(uint32_t * h);
|
||||
|
||||
#endif /* #ifndef _AES_ */
|
|
@ -0,0 +1,429 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \addtogroup aic_module
|
||||
*
|
||||
* \section Purpose
|
||||
* The Advanced Interrupt Controller (AIC) is an 8-level priority, individually
|
||||
* maskable, vectored interrupt controller, providing handling of up to thirty-two interrupt sources.
|
||||
*
|
||||
* \section Usage
|
||||
* <ul>
|
||||
* <li> Each interrupt source can be enabled or disabled by using the aic_enable() and aic_disable()</li>
|
||||
* </ul>
|
||||
*
|
||||
* For more accurate information, please look at the AIC section of the
|
||||
* Datasheet.
|
||||
*
|
||||
* Related files :\n
|
||||
* \ref aic.c\n
|
||||
* \ref aic.h\n
|
||||
*/
|
||||
/*@{*/
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implementation of Advanced Interrupt Controller (AIC) controller.
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/aic.h"
|
||||
#include "peripherals/matrix.h"
|
||||
#include "cortex-a/cp15.h"
|
||||
#include "cortex-a/cp15_pmu.h"
|
||||
#include "cortex-a/cpsr.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Local functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Default interrupt handler.
|
||||
*/
|
||||
static void _aic_default_irq_handler(void)
|
||||
{
|
||||
while (1);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Interrupt Init.
|
||||
*/
|
||||
static void _aic_initialize(Aic* aic)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
/* Disable all interrupts */
|
||||
for (i = 1; i < ID_PERIPH_COUNT; i++)
|
||||
{
|
||||
aic->AIC_SSR = i;
|
||||
aic->AIC_IDCR = AIC_IDCR_INTD;
|
||||
}
|
||||
|
||||
/* Clear All pending interrupts flags */
|
||||
for (i = 0; i < ID_PERIPH_COUNT; i++)
|
||||
{
|
||||
aic->AIC_SSR = i;
|
||||
aic->AIC_ICCR = AIC_ICCR_INTCLR;
|
||||
}
|
||||
|
||||
/* Perform 8 IT acknowledge (write any value in EOICR) (VPy) */
|
||||
for (i = 0; i < 8; i++)
|
||||
aic->AIC_EOICR = 0;
|
||||
|
||||
/* Assign default handler */
|
||||
for (i = 0; i < ID_PERIPH_COUNT; i++)
|
||||
{
|
||||
aic->AIC_SSR = i;
|
||||
aic->AIC_SVR = (uint32_t)_aic_default_irq_handler;
|
||||
}
|
||||
aic->AIC_SPU = (uint32_t)_aic_default_irq_handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configures an interrupt in the AIC. The interrupt is identified by its
|
||||
* source (ID_xxx) and is configured to use the specified mode and
|
||||
* interrupt handler function. Mode is the value that will be put in AIC_SMRx
|
||||
* and the function address will be set in AIC_SVRx.
|
||||
* The interrupt is disabled before configuration, so it is useless
|
||||
* to do it before calling this function. When aic_configure returns, the
|
||||
* interrupt will always be disabled and cleared; it must be enabled by a
|
||||
* call to aic_enable().
|
||||
*
|
||||
* \param source Interrupt source to configure.
|
||||
* \param mode Triggering mode and priority of the interrupt.
|
||||
* \param handler Interrupt handler function.
|
||||
*/
|
||||
|
||||
static void _aic_configure_it(uint32_t source, uint8_t mode)
|
||||
{
|
||||
AIC->AIC_SSR = source;
|
||||
/* Disable the interrupt first */
|
||||
AIC->AIC_IDCR = AIC_IDCR_INTD;
|
||||
/* Configure mode and handler */
|
||||
AIC->AIC_SMR = mode;
|
||||
/* Clear interrupt */
|
||||
AIC->AIC_ICCR = AIC_ICCR_INTCLR;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enables interrupts coming from the given AIC and (unique) source (ID_xxx).
|
||||
*
|
||||
* \param aic AIC instance.
|
||||
* \param source Interrupt source to enable.
|
||||
*/
|
||||
static void _aic_enable_it(Aic * aic, uint32_t source)
|
||||
{
|
||||
aic->AIC_SSR = AIC_SSR_INTSEL(source);
|
||||
aic->AIC_IECR = AIC_IECR_INTEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disables interrupts coming from the given AIC and (unique) source (ID_xxx).
|
||||
*
|
||||
* \param aic AIC instance.
|
||||
* \param source Interrupt source to disable.
|
||||
*/
|
||||
static void _aic_disable_it(Aic * aic, uint32_t source)
|
||||
{
|
||||
aic->AIC_SSR = AIC_SSR_INTSEL(source);
|
||||
aic->AIC_IDCR = AIC_IDCR_INTD;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure corresponding handler for the interrupts coming from the given (unique) source (ID_xxx).
|
||||
*
|
||||
* \param aic AIC instance.
|
||||
* \param source Interrupt source to configure.
|
||||
* \param handler handler for the interrupt.
|
||||
*/
|
||||
static void _aic_set_source_vector(Aic * aic, uint32_t source, void (*handler)(void))
|
||||
{
|
||||
if (aic->AIC_WPMR & AIC_WPMR_WPEN) {
|
||||
aic_write_protection(aic, 1);
|
||||
}
|
||||
aic->AIC_SSR = AIC_SSR_INTSEL(source);
|
||||
aic->AIC_SVR = (uint32_t)handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure the spurious interrupt handler
|
||||
*
|
||||
* \param aic AIC instance.
|
||||
* \param handler handler for the interrupt.
|
||||
*/
|
||||
static void _aic_set_spurious_vector(Aic * aic, void (*handler)(void))
|
||||
{
|
||||
if (aic->AIC_WPMR & AIC_WPMR_WPEN) {
|
||||
aic_write_protection(aic, 1);
|
||||
}
|
||||
aic->AIC_SPU = (uint32_t)handler;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clears interrupts coming from the given AIC and (unique) source (ID_xxx).
|
||||
*
|
||||
* \param aic AIC instance.
|
||||
* \param source Interrupt source to disable.
|
||||
*/
|
||||
static void _aic_clear_it(Aic * aic, uint32_t source)
|
||||
{
|
||||
aic->AIC_SSR = AIC_SSR_INTSEL(source);
|
||||
aic->AIC_ICCR = AIC_ICCR_INTCLR;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets interrupts coming from the given AIC and (unique) source (ID_xxx).
|
||||
*
|
||||
* \param aic AIC instance.
|
||||
* \param source Interrupt source to disable.
|
||||
*/
|
||||
static void _aic_set_it(Aic * aic, uint32_t source)
|
||||
{
|
||||
aic->AIC_SSR = AIC_SSR_INTSEL(source);
|
||||
aic->AIC_ISCR = AIC_ISCR_INTSET;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Set the default handler for all interrupts
|
||||
*/
|
||||
void aic_initialize(void)
|
||||
{
|
||||
/* Disable IRQ and FIQ at core level */
|
||||
v_arm_set_cpsr_bits(CPSR_MASK_IRQ | CPSR_MASK_FIQ);
|
||||
|
||||
/* Set default vectors */
|
||||
_aic_initialize(AIC);
|
||||
_aic_initialize(SAIC);
|
||||
|
||||
/* Redirect all interrupts to Non-secure AIC */
|
||||
SFR->SFR_AICREDIR = (SFR_AICREDIR_AICREDIRKEY(AICREDIR_KEY) ^ SFR->SFR_SN1) |
|
||||
SFR_AICREDIR_NSAIC;
|
||||
|
||||
/* Enable IRQ and FIQ at core level */
|
||||
v_arm_clr_cpsr_bits(CPSR_MASK_IRQ | CPSR_MASK_FIQ);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enables interrupts coming from the given (unique) source (ID_xxx).
|
||||
*
|
||||
* \param source Interrupt source to enable.
|
||||
*/
|
||||
void aic_enable(uint32_t source)
|
||||
{
|
||||
if (SFR->SFR_AICREDIR) {
|
||||
_aic_enable_it(AIC, source);
|
||||
return;
|
||||
}
|
||||
|
||||
Matrix* matrix = get_peripheral_matrix(source);
|
||||
if (!matrix_is_peripheral_secured(matrix, source)) {
|
||||
_aic_enable_it(AIC, source);
|
||||
} else {
|
||||
_aic_enable_it(SAIC, source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disables interrupts coming from the given (unique) source (ID_xxx).
|
||||
*
|
||||
* \param source Interrupt source to disable.
|
||||
*/
|
||||
void aic_disable(uint32_t source)
|
||||
{
|
||||
if (SFR->SFR_AICREDIR) {
|
||||
_aic_disable_it(AIC, source);
|
||||
return;
|
||||
}
|
||||
|
||||
Matrix* matrix = get_peripheral_matrix(source);
|
||||
if (!matrix_is_peripheral_secured(matrix, source)) {
|
||||
_aic_disable_it(AIC, source);
|
||||
} else {
|
||||
_aic_disable_it(SAIC, source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure interrupts' source mode.
|
||||
*
|
||||
* \param source Interrupt source to configure.
|
||||
* \param mode mode combined of priority level and interrupt source type.
|
||||
*/
|
||||
void aic_configure(uint32_t source, uint8_t mode)
|
||||
{
|
||||
if (SFR->SFR_AICREDIR) {
|
||||
_aic_configure_it(source, mode);
|
||||
return;
|
||||
}
|
||||
|
||||
Matrix* matrix = get_peripheral_matrix(source);
|
||||
if (!matrix_is_peripheral_secured(matrix, source)) {
|
||||
_aic_configure_it(source, mode);
|
||||
} else {
|
||||
// Does not apply for SAIC
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure corresponding handler for the interrupts coming from the given (unique) source (ID_xxx).
|
||||
*
|
||||
* \param source Interrupt source to configure.
|
||||
* \param handler handler for the interrupt.
|
||||
*/
|
||||
void aic_set_source_vector(uint32_t source, void (*handler)(void))
|
||||
{
|
||||
Aic *aic = AIC;
|
||||
|
||||
if (SFR->SFR_AICREDIR == 0) {
|
||||
Matrix* matrix = get_peripheral_matrix(source);
|
||||
if (matrix_is_peripheral_secured(matrix, source))
|
||||
aic = SAIC;
|
||||
}
|
||||
_aic_set_source_vector(aic, source, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure the spurious interrupt handler
|
||||
*
|
||||
* \param handler handler for the interrupt.
|
||||
*/
|
||||
void aic_set_spurious_vector(void (*handler)(void))
|
||||
{
|
||||
Aic *aic = AIC;
|
||||
|
||||
if (SFR->SFR_AICREDIR == 0) {
|
||||
aic = SAIC;
|
||||
}
|
||||
|
||||
_aic_set_spurious_vector(aic, handler);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure interrupts' source mode.
|
||||
*
|
||||
* \param source Interrupt source to configure.
|
||||
* \param mode mode combined of priority level and interrupt source type.
|
||||
*/
|
||||
void aic_set_or_clear(uint32_t source, uint8_t set)
|
||||
{
|
||||
Aic *aic = AIC;
|
||||
|
||||
if (SFR->SFR_AICREDIR == 0) {
|
||||
Matrix* matrix = get_peripheral_matrix(source);
|
||||
if (matrix_is_peripheral_secured(matrix, source))
|
||||
aic = SAIC;
|
||||
}
|
||||
|
||||
if (set) {
|
||||
_aic_set_it(aic, source);
|
||||
} else {
|
||||
_aic_clear_it(aic, source);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Indicate treatment completion for interrupts coming from the given AIC and (unique) source (ID_xxx).
|
||||
*
|
||||
* \param aic AIC instance.
|
||||
*/
|
||||
void aic_end_interrupt(Aic * aic)
|
||||
{
|
||||
aic->AIC_EOICR = AIC_EOICR_ENDIT;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configuration of protection mode and general interrupt mask for debug.
|
||||
*
|
||||
* \param aic AIC instance.
|
||||
* \param protect Enable/Disable protection mode.
|
||||
* \param mask Enable/Disable mask IRQ and FIQ.
|
||||
*
|
||||
* \retval 0 - succeed. 1 - failed.
|
||||
*/
|
||||
uint32_t aic_debug_config(Aic * aic, uint8_t protect, uint8_t mask)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
/* return in case the "Write Protection Mode" is enabled */
|
||||
if (aic->AIC_WPMR & AIC_WPMR_WPEN)
|
||||
return 1;
|
||||
|
||||
tmp = protect ? (1 << 1) : (0 << 1);
|
||||
if (mask)
|
||||
tmp++;
|
||||
aic->AIC_DCR = tmp;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable AIC write protection mode.
|
||||
*
|
||||
* \param aic AIC instance.
|
||||
* \param enable Enable/Disable AIC write protection mode.
|
||||
*/
|
||||
void aic_write_protection(Aic * aic, uint32_t enable)
|
||||
{
|
||||
if (enable) {
|
||||
aic->AIC_WPMR = AIC_WPMR_WPKEY_PASSWD | AIC_WPMR_WPEN;
|
||||
} else {
|
||||
aic->AIC_WPMR = AIC_WPMR_WPKEY_PASSWD;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get AIC Write Protection Status.
|
||||
*
|
||||
* \param aic AIC instance.
|
||||
* \param pViolationSource pointer to address to store the violation source
|
||||
*
|
||||
* \retval 0 - No violation occured. 1 - violation occured.
|
||||
*/
|
||||
uint32_t aic_violation_occured(Aic * aic, uint32_t * pViolationSource)
|
||||
{
|
||||
if (aic->AIC_WPSR & AIC_WPSR_WPVS) {
|
||||
*pViolationSource =
|
||||
(aic->
|
||||
AIC_WPSR & AIC_WPSR_WPVSRC_Msk) >> AIC_WPSR_WPVSRC_Pos;
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \section Purpose
|
||||
*
|
||||
* Methods and definitions for configuring interrupts.
|
||||
*
|
||||
* \section Usage
|
||||
* -# Enable or disable interrupt generation of a particular source with
|
||||
* IRQ_EnableIT and IRQ_DisableIT.
|
||||
*/
|
||||
|
||||
#ifndef AIC_H
|
||||
#define AIC_H
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void(*aic_handler_t)(void);
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Global functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void aic_initialize(void);
|
||||
extern void aic_enable(uint32_t source);
|
||||
extern void aic_disable(uint32_t source);
|
||||
extern void aic_configure(uint32_t source, uint8_t mode);
|
||||
extern void aic_set_source_vector(uint32_t source, void (*handler)(void));
|
||||
extern void aic_set_spurious_vector(void (*handler)(void));
|
||||
extern void aic_set_or_clear(uint32_t source, uint8_t set);
|
||||
extern void aic_end_interrupt(Aic * aic);
|
||||
extern uint32_t aic_debug_config(Aic * aic, uint8_t protect, uint8_t mask);
|
||||
extern void aic_write_protection(Aic * aic, uint32_t enable);
|
||||
extern uint32_t aic_violation_occured(Aic * aic, uint32_t * pViolationSource);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif //#ifndef AIC_H
|
|
@ -0,0 +1,386 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "board.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "peripherals/classd.h"
|
||||
#include "peripherals/pmc.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local constants
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static const struct {
|
||||
uint32_t rate;
|
||||
uint32_t sample_rate;
|
||||
uint32_t dsp_clk;
|
||||
} audio_info[] = {
|
||||
{ 8000, CLASSD_INTPMR_FRAME_FRAME_8K, CLASSD_INTPMR_DSPCLKFREQ_12M288 },
|
||||
{ 16000, CLASSD_INTPMR_FRAME_FRAME_16K, CLASSD_INTPMR_DSPCLKFREQ_12M288 },
|
||||
{ 32000, CLASSD_INTPMR_FRAME_FRAME_32K, CLASSD_INTPMR_DSPCLKFREQ_12M288 },
|
||||
{ 48000, CLASSD_INTPMR_FRAME_FRAME_48K, CLASSD_INTPMR_DSPCLKFREQ_12M288 },
|
||||
{ 96000, CLASSD_INTPMR_FRAME_FRAME_96K, CLASSD_INTPMR_DSPCLKFREQ_12M288 },
|
||||
{ 22050, CLASSD_INTPMR_FRAME_FRAME_22K, CLASSD_INTPMR_DSPCLKFREQ_11M2896 },
|
||||
{ 44100, CLASSD_INTPMR_FRAME_FRAME_44K, CLASSD_INTPMR_DSPCLKFREQ_11M2896 },
|
||||
{ 88200, CLASSD_INTPMR_FRAME_FRAME_88K, CLASSD_INTPMR_DSPCLKFREQ_11M2896 },
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static bool _dspclk_configure(uint32_t dsp_clk)
|
||||
{
|
||||
struct _pmc_audio_cfg cfg;
|
||||
|
||||
/* Pad Clock: not used */
|
||||
cfg.div = 0;
|
||||
cfg.qdaudio = 0;
|
||||
|
||||
/* PMC Clock: */
|
||||
/* 12Mhz * (ND + 1 + FRACR/2^22) / (QDPMC + 1) = 8 * DSPCLK */
|
||||
switch (dsp_clk) {
|
||||
case CLASSD_INTPMR_DSPCLKFREQ_12M288:
|
||||
/* 12Mhz * (56 + 1 + 1442841/2^22) / (6 + 1) = 8 * 12.288Mhz */
|
||||
cfg.nd = 56;
|
||||
cfg.fracr = 1442841;
|
||||
cfg.qdpmc = 6;
|
||||
break;
|
||||
case CLASSD_INTPMR_DSPCLKFREQ_11M2896:
|
||||
/* 12Mhz * (59 + 1 + 885837/2^22) / (7 + 1) = 8 * 11.2896Mhz */
|
||||
cfg.nd = 59;
|
||||
cfg.fracr = 885837;
|
||||
cfg.qdpmc = 7;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
pmc_configure_audio(&cfg);
|
||||
pmc_enable_audio(true, false);
|
||||
|
||||
#ifndef NDEBUG
|
||||
{
|
||||
uint32_t clk;
|
||||
clk = pmc_get_audio_pmc_clock();
|
||||
trace_debug("Configured Audio PLL PMC Clock: %u (= 8 * %u)\r\n",
|
||||
(unsigned)clk, (unsigned)(clk >> 3));
|
||||
}
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _set_eqcfg_bits(enum _classd_eqcfg eqcfg, volatile uint32_t *intpmr)
|
||||
{
|
||||
uint32_t mask = CLASSD_INTPMR_EQCFG_Msk;
|
||||
uint32_t bits = 0;
|
||||
|
||||
switch (eqcfg) {
|
||||
case CLASSD_EQCFG_FLAT:
|
||||
bits = CLASSD_INTPMR_EQCFG_FLAT;
|
||||
break;
|
||||
case CLASSD_EQCFG_BBOOST12:
|
||||
bits = CLASSD_INTPMR_EQCFG_BBOOST12;
|
||||
break;
|
||||
case CLASSD_EQCFG_BBOOST6:
|
||||
bits = CLASSD_INTPMR_EQCFG_BBOOST6;
|
||||
break;
|
||||
case CLASSD_EQCFG_BCUT12:
|
||||
bits = CLASSD_INTPMR_EQCFG_BCUT12;
|
||||
break;
|
||||
case CLASSD_EQCFG_BCUT6:
|
||||
bits = CLASSD_INTPMR_EQCFG_BCUT6;
|
||||
break;
|
||||
case CLASSD_EQCFG_MBOOST3:
|
||||
bits = CLASSD_INTPMR_EQCFG_MBOOST3;
|
||||
break;
|
||||
case CLASSD_EQCFG_MBOOST8:
|
||||
bits = CLASSD_INTPMR_EQCFG_MBOOST8;
|
||||
break;
|
||||
case CLASSD_EQCFG_MCUT3:
|
||||
bits = CLASSD_INTPMR_EQCFG_MCUT3;
|
||||
break;
|
||||
case CLASSD_EQCFG_MCUT8:
|
||||
bits = CLASSD_INTPMR_EQCFG_MCUT8;
|
||||
break;
|
||||
case CLASSD_EQCFG_TBOOST12:
|
||||
bits = CLASSD_INTPMR_EQCFG_TBOOST12;
|
||||
break;
|
||||
case CLASSD_EQCFG_TBOOST6:
|
||||
bits = CLASSD_INTPMR_EQCFG_TBOOST6;
|
||||
break;
|
||||
case CLASSD_EQCFG_TCUT12:
|
||||
bits = CLASSD_INTPMR_EQCFG_TCUT12;
|
||||
break;
|
||||
case CLASSD_EQCFG_TCUT6:
|
||||
bits = CLASSD_INTPMR_EQCFG_TCUT6;
|
||||
break;
|
||||
default:
|
||||
trace_warning("classd: invalid equalizer config %u\r\n",
|
||||
(unsigned)eqcfg);
|
||||
return false;
|
||||
};
|
||||
|
||||
*intpmr = (*intpmr & ~mask) | bits;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _set_mono_bits(bool mono, enum _classd_mono mono_mode, volatile uint32_t *intpmr)
|
||||
{
|
||||
uint32_t mask = CLASSD_INTPMR_MONO_ENABLED | CLASSD_INTPMR_MONOMODE_Msk;
|
||||
uint32_t bits = 0;
|
||||
|
||||
if (mono) {
|
||||
bits = CLASSD_INTPMR_MONO_ENABLED;
|
||||
switch (mono_mode) {
|
||||
case CLASSD_MONO_MIXED:
|
||||
bits |= CLASSD_INTPMR_MONOMODE_MONOMIX;
|
||||
break;
|
||||
case CLASSD_MONO_SAT:
|
||||
bits |= CLASSD_INTPMR_MONOMODE_MONOSAT;
|
||||
break;
|
||||
case CLASSD_MONO_LEFT:
|
||||
bits |= CLASSD_INTPMR_MONOMODE_MONOLEFT;
|
||||
break;
|
||||
case CLASSD_MONO_RIGHT:
|
||||
bits |= CLASSD_INTPMR_MONOMODE_MONORIGHT;
|
||||
break;
|
||||
default:
|
||||
trace_warning("classd: invalid mono mode %u\r\n",
|
||||
(unsigned)mono_mode);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
*intpmr = (*intpmr & ~mask) | bits;
|
||||
return true;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
bool classd_configure(struct _classd_desc *desc)
|
||||
{
|
||||
uint8_t i;
|
||||
uint32_t mr, intpmr, dsp_clk_set, frame_set;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(audio_info); i++) {
|
||||
if (audio_info[i].rate == desc->sample_rate) {
|
||||
dsp_clk_set = audio_info[i].dsp_clk;
|
||||
frame_set = audio_info[i].sample_rate;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(i == ARRAY_SIZE(audio_info))
|
||||
return false;
|
||||
|
||||
if (!_dspclk_configure(dsp_clk_set))
|
||||
return false;
|
||||
|
||||
/* enable peripheral clock, disable audio clock for now */
|
||||
pmc_enable_peripheral(ID_CLASSD);
|
||||
pmc_disable_gck(ID_CLASSD);
|
||||
pmc_configure_gck(ID_CLASSD, PMC_PCR_GCKCSS_AUDIO_CLK, 0);
|
||||
|
||||
/* perform soft reset */
|
||||
CLASSD->CLASSD_CR = CLASSD_CR_SWRST;
|
||||
CLASSD->CLASSD_IDR = CLASSD_IDR_DATRDY;
|
||||
|
||||
/* initial MR/INTPMR values */
|
||||
mr = 0;
|
||||
intpmr = dsp_clk_set | frame_set;
|
||||
|
||||
/* configure output mode */
|
||||
switch (desc->mode) {
|
||||
case CLASSD_OUTPUT_SINGLE_ENDED:
|
||||
break;
|
||||
case CLASSD_OUTPUT_DIFFERENTIAL:
|
||||
mr |= CLASSD_MR_PWMTYP;
|
||||
break;
|
||||
case CLASSD_OUTPUT_HALF_BRIDGE:
|
||||
mr |= CLASSD_MR_NON_OVERLAP;
|
||||
break;
|
||||
case CLASSD_OUTPUT_FULL_BRIDGE:
|
||||
mr |= CLASSD_MR_PWMTYP | CLASSD_MR_NON_OVERLAP;
|
||||
break;
|
||||
default:
|
||||
trace_warning("classd: invalid mode %u\n", (unsigned)desc->mode);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* configure non-overlapping time */
|
||||
if (mr & CLASSD_MR_NON_OVERLAP) {
|
||||
switch (desc->non_ovr) {
|
||||
case CLASSD_NONOVR_5NS:
|
||||
mr |= CLASSD_MR_NOVRVAL_5NS;
|
||||
break;
|
||||
case CLASSD_NONOVR_10NS:
|
||||
mr |= CLASSD_MR_NOVRVAL_10NS;
|
||||
break;
|
||||
case CLASSD_NONOVR_15NS:
|
||||
mr |= CLASSD_MR_NOVRVAL_15NS;
|
||||
break;
|
||||
case CLASSD_NONOVR_20NS:
|
||||
mr |= CLASSD_MR_NOVRVAL_20NS;
|
||||
break;
|
||||
default:
|
||||
trace_warning("classd: invalid non overlap value %u\r\n",
|
||||
(unsigned)desc->non_ovr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* configure mono/stereo */
|
||||
if (desc->swap_channels)
|
||||
intpmr |= CLASSD_INTPMR_SWAP;
|
||||
if (!_set_mono_bits(desc->mono, desc->mono_mode, &intpmr))
|
||||
return false;
|
||||
|
||||
/* configure left channel (muted, max attn) */
|
||||
if (desc->left_enable)
|
||||
mr |= CLASSD_MR_LEN;
|
||||
mr |= CLASSD_MR_LMUTE;
|
||||
intpmr |= CLASSD_INTPMR_ATTL(CLASSD_INTPMR_ATTL_Msk);
|
||||
|
||||
/* configure right channel (muted, max attn) */
|
||||
if (desc->right_enable)
|
||||
mr |= CLASSD_MR_REN;
|
||||
mr |= CLASSD_MR_RMUTE;
|
||||
intpmr |= CLASSD_INTPMR_ATTR(CLASSD_INTPMR_ATTL_Msk);
|
||||
|
||||
/* write configuration */
|
||||
CLASSD->CLASSD_MR = mr;
|
||||
CLASSD->CLASSD_INTPMR = intpmr;
|
||||
|
||||
/* enable audio clock */
|
||||
pmc_enable_gck(ID_CLASSD);
|
||||
|
||||
return (CLASSD->CLASSD_INTSR & CLASSD_INTSR_CFGERR) == 0;
|
||||
}
|
||||
|
||||
void classd_disable(void)
|
||||
{
|
||||
pmc_disable_audio();
|
||||
pmc_disable_gck(ID_CLASSD);
|
||||
pmc_disable_peripheral(ID_CLASSD);
|
||||
}
|
||||
|
||||
void classd_swap_channels(bool swap)
|
||||
{
|
||||
if (swap) {
|
||||
CLASSD->CLASSD_INTPMR |= CLASSD_INTPMR_SWAP;
|
||||
} else {
|
||||
CLASSD->CLASSD_INTPMR &= ~CLASSD_INTPMR_SWAP;
|
||||
}
|
||||
}
|
||||
|
||||
void classd_enable_mono(enum _classd_mono mono_mode)
|
||||
{
|
||||
_set_mono_bits(true, mono_mode, &CLASSD->CLASSD_INTPMR);
|
||||
}
|
||||
|
||||
void classd_disable_mono(void)
|
||||
{
|
||||
_set_mono_bits(false, CLASSD_MONO_MIXED, &CLASSD->CLASSD_INTPMR);
|
||||
}
|
||||
|
||||
void classd_set_equalizer(enum _classd_eqcfg eqcfg)
|
||||
{
|
||||
_set_eqcfg_bits(eqcfg, &CLASSD->CLASSD_INTPMR);
|
||||
}
|
||||
|
||||
void classd_enable_channels(bool left, bool right)
|
||||
{
|
||||
uint32_t bits = 0;
|
||||
if (left)
|
||||
bits |= CLASSD_MR_LEN;
|
||||
if (right)
|
||||
bits |= CLASSD_MR_REN;
|
||||
CLASSD->CLASSD_MR |= bits;
|
||||
}
|
||||
|
||||
void classd_disable_channels(bool left, bool right)
|
||||
{
|
||||
uint32_t bits = 0;
|
||||
if (left)
|
||||
bits |= CLASSD_MR_LEN;
|
||||
if (right)
|
||||
bits |= CLASSD_MR_REN;
|
||||
CLASSD->CLASSD_MR &= ~bits;
|
||||
}
|
||||
|
||||
void classd_set_left_attenuation(uint8_t attn)
|
||||
{
|
||||
if (attn < 1 || attn > 0x3f)
|
||||
return;
|
||||
|
||||
uint32_t intpmr = CLASSD->CLASSD_INTPMR & ~CLASSD_INTPMR_ATTL_Msk;
|
||||
CLASSD->CLASSD_INTPMR = intpmr | CLASSD_INTPMR_ATTL(attn);
|
||||
}
|
||||
|
||||
void classd_set_right_attenuation(uint8_t attn)
|
||||
{
|
||||
if (attn < 1 || attn > 0x3f)
|
||||
return;
|
||||
|
||||
uint32_t intpmr = CLASSD->CLASSD_INTPMR & ~CLASSD_INTPMR_ATTR_Msk;
|
||||
CLASSD->CLASSD_INTPMR = intpmr | CLASSD_INTPMR_ATTR(attn);
|
||||
}
|
||||
|
||||
void classd_volume_mute(bool left, bool right)
|
||||
{
|
||||
uint32_t bits = 0;
|
||||
if (left)
|
||||
bits |= CLASSD_MR_LMUTE;
|
||||
if (right)
|
||||
bits |= CLASSD_MR_RMUTE;
|
||||
CLASSD->CLASSD_MR |= bits;
|
||||
}
|
||||
|
||||
void classd_volume_unmute(bool left, bool right)
|
||||
{
|
||||
uint32_t bits = 0;
|
||||
if (left)
|
||||
bits |= CLASSD_MR_LMUTE;
|
||||
if (right)
|
||||
bits |= CLASSD_MR_RMUTE;
|
||||
CLASSD->CLASSD_MR &= ~bits;
|
||||
}
|
||||
|
|
@ -0,0 +1,125 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _CLASSD_H
|
||||
#define _CLASSD_H
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Includes
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Types
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
enum _classd_mode
|
||||
{
|
||||
CLASSD_OUTPUT_SINGLE_ENDED,
|
||||
CLASSD_OUTPUT_DIFFERENTIAL,
|
||||
CLASSD_OUTPUT_HALF_BRIDGE,
|
||||
CLASSD_OUTPUT_FULL_BRIDGE,
|
||||
};
|
||||
|
||||
enum _classd_non_ovr
|
||||
{
|
||||
CLASSD_NONOVR_5NS,
|
||||
CLASSD_NONOVR_10NS,
|
||||
CLASSD_NONOVR_15NS,
|
||||
CLASSD_NONOVR_20NS,
|
||||
};
|
||||
|
||||
enum _classd_eqcfg
|
||||
{
|
||||
CLASSD_EQCFG_FLAT,
|
||||
CLASSD_EQCFG_BBOOST12,
|
||||
CLASSD_EQCFG_BBOOST6,
|
||||
CLASSD_EQCFG_BCUT12,
|
||||
CLASSD_EQCFG_BCUT6,
|
||||
CLASSD_EQCFG_MBOOST3,
|
||||
CLASSD_EQCFG_MBOOST8,
|
||||
CLASSD_EQCFG_MCUT3,
|
||||
CLASSD_EQCFG_MCUT8,
|
||||
CLASSD_EQCFG_TBOOST12,
|
||||
CLASSD_EQCFG_TBOOST6,
|
||||
CLASSD_EQCFG_TCUT12,
|
||||
CLASSD_EQCFG_TCUT6,
|
||||
};
|
||||
|
||||
enum _classd_mono
|
||||
{
|
||||
CLASSD_MONO_MIXED,
|
||||
CLASSD_MONO_SAT,
|
||||
CLASSD_MONO_LEFT,
|
||||
CLASSD_MONO_RIGHT,
|
||||
};
|
||||
|
||||
struct _classd_desc
|
||||
{
|
||||
uint32_t sample_rate;
|
||||
enum _classd_mode mode;
|
||||
enum _classd_non_ovr non_ovr;
|
||||
bool swap_channels;
|
||||
bool mono;
|
||||
enum _classd_mono mono_mode;
|
||||
bool left_enable;
|
||||
bool right_enable;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
extern bool classd_configure(struct _classd_desc *desc);
|
||||
|
||||
extern void classd_disable(void);
|
||||
|
||||
extern void classd_swap_channels(bool swap);
|
||||
|
||||
extern void classd_enable_mono(enum _classd_mono mono_mode);
|
||||
|
||||
extern void classd_disable_mono(void);
|
||||
|
||||
extern void classd_set_equalizer(enum _classd_eqcfg eqcfg);
|
||||
|
||||
extern void classd_enable_channels(bool left, bool right);
|
||||
|
||||
extern void classd_disable_channels(bool left, bool right);
|
||||
|
||||
extern void classd_set_left_attenuation(uint8_t attn);
|
||||
|
||||
extern void classd_set_right_attenuation(uint8_t attn);
|
||||
|
||||
extern void classd_volume_mute(bool left, bool right);
|
||||
|
||||
extern void classd_volume_unmute(bool left, bool right);
|
||||
|
||||
#endif /* _CLASSD_H */
|
|
@ -0,0 +1,82 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/flexcom.h"
|
||||
|
||||
#include "peripherals/usart.h"
|
||||
#include "peripherals/spi.h"
|
||||
#include "peripherals/twi.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Select a protocol for a FLEXCOM device
|
||||
*
|
||||
*
|
||||
* \param flexcom Pointer to FLEXCOM peripheral to configure.
|
||||
* \param protocol Protocol to use.
|
||||
*/
|
||||
void flexcom_select(Flexcom * flexcom, uint32_t protocol)
|
||||
{
|
||||
assert(flexcom);
|
||||
uint32_t current_protocol = flexcom->FLEX_MR;
|
||||
|
||||
usart_set_receiver_enabled(&flexcom->usart, 0u);
|
||||
|
||||
/* Shutdown previous protocol */
|
||||
switch (current_protocol) {
|
||||
case FLEX_MR_OPMODE_USART:
|
||||
usart_set_receiver_enabled(&flexcom->usart, 0u);
|
||||
usart_set_transmitter_enabled(&flexcom->usart, 0u);
|
||||
break;
|
||||
case FLEX_MR_OPMODE_SPI:
|
||||
spi_disable(&flexcom->spi);
|
||||
break;
|
||||
case FLEX_MR_OPMODE_TWI:
|
||||
twi_stop(&flexcom->twi);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
assert(protocol & FLEX_MR_OPMODE_NO_COM ||
|
||||
protocol & FLEX_MR_OPMODE_USART ||
|
||||
FLEX_MR_OPMODE_SPI || FLEX_MR_OPMODE_TWI);
|
||||
|
||||
/* Activate the new mode () */
|
||||
flexcom->FLEX_MR = protocol;
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \par Purpose
|
||||
*
|
||||
* This module provides several definitions and methods for using an USART
|
||||
* peripheral.
|
||||
*
|
||||
* \par Usage
|
||||
*
|
||||
* -# Enable the USART peripheral clock in the PMC.
|
||||
* -# Enable the required USART PIOs (see pio.h).
|
||||
* -# Configure the UART by calling usart_configure.
|
||||
* -# Enable the transmitter and/or the receiver of the USART using
|
||||
* usart_set_transmitter_enabled and usart_set_receiver_enabled.
|
||||
* -# Send data through the USART using the usart_write methods.
|
||||
* -# Receive data from the USART using the usart_read functions; the availability of data can be polled
|
||||
* with usart_is_data_available.
|
||||
* -# Disable the transmitter and/or the receiver of the USART with
|
||||
* usart_set_transmitter_enabled and usart_set_receiver_enabled.
|
||||
*/
|
||||
|
||||
#ifndef _FLEXCOM_
|
||||
#define _FLEXCOM_
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------*/
|
||||
/* Exported functions */
|
||||
/*------------------------------------------------------------------------------*/
|
||||
|
||||
extern void flexcom_select(Flexcom * flexcom, uint32_t protocol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* #ifndef _FLEXCOM_ */
|
|
@ -0,0 +1,518 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "trace.h"
|
||||
#include "peripherals/gmac.h"
|
||||
#include "peripherals/pmc.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local definitions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/* some IP versions don't have this configuration flag and instead expect 0 */
|
||||
#ifndef GMAC_NCFGR_DBW_DBW32
|
||||
#define GMAC_NCFGR_DBW_DBW32 0
|
||||
#endif
|
||||
|
||||
/* some IP versions don't have this error flag, set it to 0 to ignore it */
|
||||
#ifndef GMAC_TSR_UND
|
||||
#define GMAC_TSR_UND 0
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static bool _gmac_configure_mdc_clock(Gmac *gmac)
|
||||
{
|
||||
uint32_t mck, clk;
|
||||
|
||||
mck = pmc_get_peripheral_clock(get_gmac_id_from_addr(gmac));
|
||||
|
||||
/* Disable RX/TX */
|
||||
gmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
|
||||
|
||||
/* Find divider */
|
||||
if (mck <= 20000000) {
|
||||
clk = GMAC_NCFGR_CLK_MCK_8; // MCK/8
|
||||
} else if (mck <= 40000000) {
|
||||
clk = GMAC_NCFGR_CLK_MCK_16; // MCK/16
|
||||
} else if (mck <= 80000000) {
|
||||
clk = GMAC_NCFGR_CLK_MCK_32; // MCK/32
|
||||
} else if (mck <= 120000000) {
|
||||
clk = GMAC_NCFGR_CLK_MCK_48; // MCK/48
|
||||
} else if (mck <= 160000000) {
|
||||
clk = GMAC_NCFGR_CLK_MCK_64; // MCK/64
|
||||
} else if (mck <= 240000000) {
|
||||
clk = GMAC_NCFGR_CLK_MCK_96; // MCK/96
|
||||
} else {
|
||||
trace_error("MCK too high, cannot configure MDC clock.\r\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* configure MDC clock divider and enable RX/TX */
|
||||
gmac->GMAC_NCFGR = (gmac->GMAC_NCFGR & ~GMAC_NCFGR_CLK_Msk) | clk;
|
||||
gmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool _gmac_phy_wait_idle(Gmac* gmac, uint32_t retries)
|
||||
{
|
||||
uint32_t count = 0;
|
||||
while ((gmac->GMAC_NSR & GMAC_NSR_IDLE) == 0) {
|
||||
if (retries > 0 && count > retries) {
|
||||
trace_debug("Timeout reached while waiting for PHY management logic to become idle");
|
||||
return false;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void _gmac_set_link_speed(Gmac* gmac, enum _gmac_speed speed, enum _gmac_duplex duplex)
|
||||
{
|
||||
/* Configure duplex */
|
||||
switch (duplex) {
|
||||
case GMAC_DUPLEX_HALF:
|
||||
gmac->GMAC_NCFGR &= ~GMAC_NCFGR_FD;
|
||||
break;
|
||||
case GMAC_DUPLEX_FULL:
|
||||
gmac->GMAC_NCFGR |= GMAC_NCFGR_FD;
|
||||
break;
|
||||
default:
|
||||
trace_error("Invalid duplex value %d\r\n", duplex);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Configure speed */
|
||||
switch (speed) {
|
||||
case GMAC_SPEED_10M:
|
||||
gmac->GMAC_NCFGR &= ~GMAC_NCFGR_SPD;
|
||||
break;
|
||||
case GMAC_SPEED_100M:
|
||||
gmac->GMAC_NCFGR |= GMAC_NCFGR_SPD;
|
||||
break;
|
||||
default:
|
||||
trace_error("Invalid speed value %d\r\n", speed);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
bool gmac_configure(Gmac* gmac)
|
||||
{
|
||||
pmc_enable_peripheral(get_gmac_id_from_addr(gmac));
|
||||
|
||||
/* Disable TX & RX and more */
|
||||
gmac_set_network_control_register(gmac, 0);
|
||||
gmac_set_network_config_register(gmac, GMAC_NCFGR_DBW_DBW32);
|
||||
|
||||
/* Disable interrupts */
|
||||
gmac_disable_it(gmac, 0, ~0u);
|
||||
#ifdef CONFIG_HAVE_GMAC_QUEUES
|
||||
gmac_disable_it(gmac, 1, ~0u);
|
||||
gmac_disable_it(gmac, 2, ~0u);
|
||||
#endif
|
||||
|
||||
/* Clear statistics */
|
||||
gmac_clear_statistics(gmac);
|
||||
|
||||
/* Clear all status bits in the receive status register. */
|
||||
gmac_clear_rx_status(gmac, GMAC_RSR_RXOVR | GMAC_RSR_REC |
|
||||
GMAC_RSR_BNA | GMAC_RSR_HNO);
|
||||
|
||||
/* Clear all status bits in the transmit status register */
|
||||
gmac_clear_tx_status(gmac, GMAC_TSR_UBR | GMAC_TSR_COL |
|
||||
GMAC_TSR_RLE | GMAC_TSR_TXGO | GMAC_TSR_TFC |
|
||||
GMAC_TSR_TXCOMP | GMAC_TSR_UND | GMAC_TSR_HRESP);
|
||||
|
||||
/* Clear interrupts */
|
||||
gmac_get_it_status(gmac, 0);
|
||||
#ifdef CONFIG_HAVE_GMAC_QUEUES
|
||||
gmac_get_it_status(gmac, 1);
|
||||
gmac_get_it_status(gmac, 2);
|
||||
#endif
|
||||
|
||||
return _gmac_configure_mdc_clock(gmac);
|
||||
}
|
||||
|
||||
void gmac_set_network_control_register(Gmac* gmac, uint32_t ncr)
|
||||
{
|
||||
gmac->GMAC_NCR = ncr;
|
||||
}
|
||||
|
||||
uint32_t gmac_get_network_control_register(Gmac* gmac)
|
||||
{
|
||||
return gmac->GMAC_NCR;
|
||||
}
|
||||
|
||||
void gmac_set_network_config_register(Gmac* gmac, uint32_t ncfgr)
|
||||
{
|
||||
gmac->GMAC_NCFGR = ncfgr;
|
||||
}
|
||||
|
||||
uint32_t gmac_get_network_config_register(Gmac* gmac)
|
||||
{
|
||||
return gmac->GMAC_NCFGR;
|
||||
}
|
||||
|
||||
void gmac_enable_mdio(Gmac* gmac)
|
||||
{
|
||||
/* Disable RX/TX */
|
||||
gmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
|
||||
|
||||
/* Enable MDIO */
|
||||
gmac->GMAC_NCR |= GMAC_NCR_MPE;
|
||||
|
||||
/* Enable RX/TX */
|
||||
gmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
|
||||
}
|
||||
|
||||
void gmac_disable_mdio(Gmac* gmac)
|
||||
{
|
||||
/* Disable RX/TX */
|
||||
gmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
|
||||
|
||||
/* Disable MDIO */
|
||||
gmac->GMAC_NCR &= ~GMAC_NCR_MPE;
|
||||
|
||||
/* Enable RX/TX */
|
||||
gmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
|
||||
}
|
||||
|
||||
bool gmac_phy_read(Gmac* gmac, uint8_t phy_addr, uint8_t reg_addr, uint16_t* data,
|
||||
uint32_t retries)
|
||||
{
|
||||
/* Wait until idle */
|
||||
if (!_gmac_phy_wait_idle(gmac, retries))
|
||||
return false;
|
||||
|
||||
/* Write maintenance register */
|
||||
gmac->GMAC_MAN = GMAC_MAN_CLTTO |
|
||||
GMAC_MAN_OP(2) |
|
||||
GMAC_MAN_WTN(2) |
|
||||
GMAC_MAN_PHYA(phy_addr) |
|
||||
GMAC_MAN_REGA(reg_addr);
|
||||
|
||||
/* Wait until idle */
|
||||
if (!_gmac_phy_wait_idle(gmac, retries))
|
||||
return false;
|
||||
|
||||
*data = (gmac->GMAC_MAN & GMAC_MAN_DATA_Msk) >> GMAC_MAN_DATA_Pos;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool gmac_phy_write(Gmac* gmac, uint8_t phy_addr, uint8_t reg_addr, uint16_t data,
|
||||
uint32_t retries)
|
||||
{
|
||||
/* Wait until idle */
|
||||
if (!_gmac_phy_wait_idle(gmac, retries))
|
||||
return false;
|
||||
|
||||
/* Write maintenance register */
|
||||
gmac->GMAC_MAN = GMAC_MAN_CLTTO |
|
||||
GMAC_MAN_OP(1) |
|
||||
GMAC_MAN_WTN(2) |
|
||||
GMAC_MAN_PHYA(phy_addr) |
|
||||
GMAC_MAN_REGA(reg_addr) |
|
||||
GMAC_MAN_DATA(data);
|
||||
|
||||
/* Wait until idle */
|
||||
return _gmac_phy_wait_idle(gmac, retries);
|
||||
}
|
||||
|
||||
void gmac_enable_mii(Gmac* gmac)
|
||||
{
|
||||
/* Disable RX/TX */
|
||||
gmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
|
||||
|
||||
/* Disable RMII */
|
||||
gmac->GMAC_UR &= ~GMAC_UR_RMII;
|
||||
|
||||
/* Enable RX/TX */
|
||||
gmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
|
||||
}
|
||||
|
||||
void gmac_enable_rmii(Gmac* gmac, enum _gmac_speed speed, enum _gmac_duplex duplex)
|
||||
{
|
||||
/* Disable RX/TX */
|
||||
gmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
|
||||
|
||||
/* Configure speed/duplex */
|
||||
_gmac_set_link_speed(gmac, speed, duplex);
|
||||
|
||||
/* Enable RMII */
|
||||
gmac->GMAC_UR |= GMAC_UR_RMII;
|
||||
|
||||
/* Enable RX/TX */
|
||||
gmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
|
||||
}
|
||||
|
||||
void gmac_set_link_speed(Gmac* gmac, enum _gmac_speed speed, enum _gmac_duplex duplex)
|
||||
{
|
||||
/* Disable RX/TX */
|
||||
gmac->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
|
||||
|
||||
/* Configure speed/duplex */
|
||||
_gmac_set_link_speed(gmac, speed, duplex);
|
||||
|
||||
/* Enable RX/TX */
|
||||
gmac->GMAC_NCR |= (GMAC_NCR_RXEN | GMAC_NCR_TXEN);
|
||||
}
|
||||
|
||||
void gmac_enable_local_loopback(Gmac* gmac)
|
||||
{
|
||||
gmac->GMAC_NCR |= GMAC_NCR_LBL;
|
||||
}
|
||||
|
||||
void gmac_disable_local_loopback(Gmac* gmac)
|
||||
{
|
||||
gmac->GMAC_NCR &= ~GMAC_NCR_LBL;
|
||||
}
|
||||
|
||||
uint32_t gmac_get_tx_status(Gmac* gmac)
|
||||
{
|
||||
return gmac->GMAC_TSR;
|
||||
}
|
||||
|
||||
void gmac_clear_tx_status(Gmac* gmac, uint32_t mask)
|
||||
{
|
||||
gmac->GMAC_TSR = mask;
|
||||
}
|
||||
|
||||
uint32_t gmac_get_rx_status(Gmac* gmac)
|
||||
{
|
||||
return gmac->GMAC_RSR;
|
||||
}
|
||||
|
||||
void gmac_clear_rx_status(Gmac* gmac, uint32_t mask)
|
||||
{
|
||||
gmac->GMAC_RSR = mask;
|
||||
}
|
||||
|
||||
void gmac_receive_enable(Gmac* gmac, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
gmac->GMAC_NCR |= GMAC_NCR_RXEN;
|
||||
else
|
||||
gmac->GMAC_NCR &= ~GMAC_NCR_RXEN;
|
||||
}
|
||||
|
||||
void gmac_transmit_enable(Gmac* gmac, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
gmac->GMAC_NCR |= GMAC_NCR_TXEN;
|
||||
else
|
||||
gmac->GMAC_NCR &= ~GMAC_NCR_TXEN;
|
||||
}
|
||||
|
||||
void gmac_set_rx_desc(Gmac* gmac, uint8_t queue, struct _gmac_desc* desc)
|
||||
{
|
||||
if (queue == 0) {
|
||||
gmac->GMAC_RBQB = ((uint32_t)desc) & GMAC_RBQB_ADDR_Msk;
|
||||
}
|
||||
#ifdef CONFIG_HAVE_GMAC_QUEUES
|
||||
else if (queue <= GMAC_NUM_QUEUES) {
|
||||
gmac->GMAC_RBQBAPQ[queue - 1] = ((uint32_t)desc) & GMAC_RBQBAPQ_RXBQBA_Msk;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
trace_debug("Invalid queue number %d\r\n", queue);
|
||||
}
|
||||
}
|
||||
|
||||
struct _gmac_desc* gmac_get_rx_desc(Gmac* gmac, uint8_t queue)
|
||||
{
|
||||
if (queue == 0) {
|
||||
return (struct _gmac_desc*)(gmac->GMAC_RBQB & GMAC_RBQB_ADDR_Msk);
|
||||
}
|
||||
#ifdef CONFIG_HAVE_GMAC_QUEUES
|
||||
else if (queue <= GMAC_NUM_QUEUES) {
|
||||
return (struct _gmac_desc*)(gmac->GMAC_RBQBAPQ[queue - 1] & GMAC_RBQBAPQ_RXBQBA_Msk);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
trace_debug("Invalid queue number %d\r\n", queue);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void gmac_set_tx_desc(Gmac* gmac, uint8_t queue, struct _gmac_desc* desc)
|
||||
{
|
||||
if (queue == 0) {
|
||||
gmac->GMAC_TBQB = ((uint32_t)desc) & GMAC_TBQB_ADDR_Msk;
|
||||
}
|
||||
#ifdef CONFIG_HAVE_GMAC_QUEUES
|
||||
else if (queue <= GMAC_NUM_QUEUES) {
|
||||
gmac->GMAC_TBQBAPQ[queue - 1] = ((uint32_t)desc) & GMAC_TBQBAPQ_TXBQBA_Msk;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
trace_debug("Invalid queue number %d\r\n", queue);
|
||||
}
|
||||
}
|
||||
|
||||
struct _gmac_desc* gmac_get_tx_desc(Gmac* gmac, uint8_t queue)
|
||||
{
|
||||
if (queue == 0) {
|
||||
return (struct _gmac_desc*)(gmac->GMAC_TBQB & GMAC_TBQB_ADDR_Msk);
|
||||
}
|
||||
#ifdef CONFIG_HAVE_GMAC_QUEUES
|
||||
else if (queue <= GMAC_NUM_QUEUES) {
|
||||
return (struct _gmac_desc*)(gmac->GMAC_TBQBAPQ[queue - 1] & GMAC_TBQBAPQ_TXBQBA_Msk);
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
trace_debug("Invalid queue number %d\r\n", queue);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t gmac_get_it_mask(Gmac* gmac, uint8_t queue)
|
||||
{
|
||||
if (queue == 0) {
|
||||
return gmac->GMAC_IMR;
|
||||
}
|
||||
#ifdef CONFIG_HAVE_GMAC_QUEUES
|
||||
else if (queue <= GMAC_NUM_QUEUES) {
|
||||
return gmac->GMAC_IMRPQ[queue - 1];
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
trace_debug("Invalid queue number %d\r\n", queue);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void gmac_enable_it(Gmac* gmac, uint8_t queue, uint32_t mask)
|
||||
{
|
||||
if (queue == 0) {
|
||||
gmac->GMAC_IER = mask;
|
||||
}
|
||||
#ifdef CONFIG_HAVE_GMAC_QUEUES
|
||||
else if (queue <= GMAC_NUM_QUEUES) {
|
||||
gmac->GMAC_IERPQ[queue - 1] = mask;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
trace_debug("Invalid queue number %d\r\n", queue);
|
||||
}
|
||||
}
|
||||
|
||||
void gmac_disable_it(Gmac * gmac, uint8_t queue, uint32_t mask)
|
||||
{
|
||||
if (queue == 0) {
|
||||
gmac->GMAC_IDR = mask;
|
||||
}
|
||||
#ifdef CONFIG_HAVE_GMAC_QUEUES
|
||||
else if (queue <= GMAC_NUM_QUEUES) {
|
||||
gmac->GMAC_IDRPQ[queue - 1] = mask;
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
trace_debug("Invalid queue number %d\r\n", queue);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t gmac_get_it_status(Gmac* gmac, uint8_t queue)
|
||||
{
|
||||
if (queue == 0) {
|
||||
return gmac->GMAC_ISR;
|
||||
}
|
||||
#ifdef CONFIG_HAVE_GMAC_QUEUES
|
||||
else if (queue <= GMAC_NUM_QUEUES) {
|
||||
return gmac->GMAC_ISRPQ[queue - 1];
|
||||
}
|
||||
#endif
|
||||
else {
|
||||
trace_debug("Invalid queue number %d\r\n", queue);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void gmac_set_mac_addr(Gmac* gmac, uint8_t sa_idx, uint8_t* mac)
|
||||
{
|
||||
gmac->GMAC_SA[sa_idx].GMAC_SAB = (mac[3] << 24) |
|
||||
(mac[2] << 16) | (mac[1] << 8) | mac[0];
|
||||
gmac->GMAC_SA[sa_idx].GMAC_SAT = (mac[5] << 8) |
|
||||
mac[4];
|
||||
}
|
||||
|
||||
void gmac_set_mac_addr32(Gmac* gmac, uint8_t sa_idx,
|
||||
uint32_t mac_top, uint32_t mac_bottom)
|
||||
{
|
||||
gmac->GMAC_SA[sa_idx].GMAC_SAB = mac_bottom;
|
||||
gmac->GMAC_SA[sa_idx].GMAC_SAT = mac_top;
|
||||
}
|
||||
|
||||
void gmac_set_mac_addr64(Gmac* gmac, uint8_t sa_idx, uint64_t mac)
|
||||
{
|
||||
gmac->GMAC_SA[sa_idx].GMAC_SAB = (uint32_t)(mac & 0xffffffff);
|
||||
gmac->GMAC_SA[sa_idx].GMAC_SAT = (uint32_t)(mac >> 32);
|
||||
}
|
||||
|
||||
void gmac_clear_statistics(Gmac* gmac)
|
||||
{
|
||||
gmac->GMAC_NCR |= GMAC_NCR_CLRSTAT;
|
||||
}
|
||||
|
||||
void gmac_increase_statistics(Gmac* gmac)
|
||||
{
|
||||
gmac->GMAC_NCR |= GMAC_NCR_INCSTAT;
|
||||
}
|
||||
|
||||
void gmac_enable_statistics_write(Gmac* gmac, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
gmac->GMAC_NCR |= GMAC_NCR_WESTAT;
|
||||
else
|
||||
gmac->GMAC_NCR &= ~GMAC_NCR_WESTAT;
|
||||
}
|
||||
|
||||
void gmac_start_transmission(Gmac * gmac)
|
||||
{
|
||||
gmac->GMAC_NCR |= GMAC_NCR_TSTART;
|
||||
}
|
||||
|
||||
void gmac_halt_transmission(Gmac * gmac)
|
||||
{
|
||||
gmac->GMAC_NCR |= GMAC_NCR_THALT;
|
||||
}
|
|
@ -0,0 +1,361 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file */
|
||||
|
||||
/** \addtogroup gmac_module
|
||||
* @{
|
||||
* Provides the interface to configure and use the GMAC peripheral.
|
||||
*
|
||||
* \section gmac_usage Usage
|
||||
* - Configure Gmac::GMAC_NCFG with gmac_configure(), some of related controls
|
||||
* are also available, such as:
|
||||
* - gmac_set_link_speed(): Setup GMAC working clock.
|
||||
* - gmac_full_duplex_enable(): Working in full duplex or not.
|
||||
* - gmac_cpy_all_enable(): Copying all valid frames (\ref GMAC_NCFG_CAF).
|
||||
* - ...
|
||||
* - Setup Gmac::GMAC_NCR with gmac_network_control(), more related controls
|
||||
* can modify with:
|
||||
* - gmac_receive_enable(): Enable/Disable Rx.
|
||||
* - gmac_transmit_enable(): Enable/Disable Tx.
|
||||
* - gmac_broadcast_disable(): Enable/Disable broadcast receiving.
|
||||
* - ...
|
||||
* - Manage GMAC interrupts with GMAC_EnableIt(), gmac_disable_it(),
|
||||
* gmac_get_it_mask() and gmac_get_it_status().
|
||||
* - Manage GMAC Tx/Rx status with gmac_get_tx_status(), gmac_get_rx_status()
|
||||
* gmac_clear_tx_status() and gmac_clear_rx_status().
|
||||
* - Manage GMAC Queue with gmac_set_tx_queue(), GMAC_GetTxQueue(),
|
||||
* gmac_set_rx_queue() and GMAC_GetRxQueue(), the queue descriptor can define
|
||||
* by \ref _gmac_rx_descriptor and \ref _gmac_tx_descriptor.
|
||||
* - Manage PHY through GMAC is performed by
|
||||
* - gmac_management_enable(): Enable/Disable PHY management.
|
||||
* - gmac_phy_maintain(): Execute PHY management commands.
|
||||
* - gmac_phy_data(): Return PHY management data.
|
||||
* - gmac_is_idle(): Check if PHY is idle.
|
||||
* - Setup GMAC parameters with following functions:
|
||||
* - gmac_set_hash(): Set Hash value.
|
||||
* - gmac_set_address(): Set MAC address.
|
||||
* - Enable/Disable GMAC transceiver clock via GMAC_TransceiverClockEnable()
|
||||
* - Switch GMAC MII/RMII mode through gmac_enable_rgmii()
|
||||
*
|
||||
* For more accurate information, please look at the GMAC section of the
|
||||
* Datasheet.
|
||||
*
|
||||
* \sa \ref gmacd_module
|
||||
*
|
||||
* Related files:\n
|
||||
* gmac.c\n
|
||||
* gmac.h.\n
|
||||
*
|
||||
* \defgroup gmac_defines GMAC Defines
|
||||
* \defgroup gmac_structs GMAC Data Structs
|
||||
* \defgroup gmac_functions GMAC Functions
|
||||
*/
|
||||
/**@}*/
|
||||
|
||||
#ifndef _GMAC_H_
|
||||
#define _GMAC_H_
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Defines
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/** \addtogroup gmac_defines
|
||||
@{*/
|
||||
|
||||
#ifdef CONFIG_HAVE_GMAC_QUEUES
|
||||
#define GMAC_NUM_QUEUES 3
|
||||
#else
|
||||
#define GMAC_NUM_QUEUES 1
|
||||
#endif
|
||||
|
||||
#define GMAC_MAX_FRAME_LENGTH 1536
|
||||
#define GMAC_MAX_JUMBO_FRAME_LENGTH 10240
|
||||
|
||||
enum _gmac_duplex {
|
||||
GMAC_DUPLEX_HALF = 0,
|
||||
GMAC_DUPLEX_FULL = 1,
|
||||
};
|
||||
|
||||
enum _gmac_speed {
|
||||
GMAC_SPEED_10M = 0,
|
||||
GMAC_SPEED_100M = 1,
|
||||
};
|
||||
|
||||
/* Bits contained in struct _gmac_desc addr when used for RX*/
|
||||
#define GMAC_RX_ADDR_OWN (1u << 0)
|
||||
#define GMAC_RX_ADDR_WRAP (1u << 1)
|
||||
#define GMAC_RX_ADDR_MASK 0xfffffffcu
|
||||
|
||||
/* Bits contained in struct _gmac_desc status when used for RX */
|
||||
#define GMAC_RX_STATUS_LENGTH_MASK 0x3fffu
|
||||
#define GMAC_RX_STATUS_SOF (1u << 14)
|
||||
#define GMAC_RX_STATUS_EOF (1u << 15)
|
||||
|
||||
/* Bits contained in struct _gmac_desc status when used for TX */
|
||||
#define GMAC_TX_STATUS_LASTBUF (1u << 15)
|
||||
#define GMAC_TX_STATUS_WRAP (1u << 30)
|
||||
#define GMAC_TX_STATUS_USED (1u << 31)
|
||||
|
||||
/**@}*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Types
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/** \addtogroup gmac_structs
|
||||
@{*/
|
||||
|
||||
/** Transmit/Receive buffer descriptor struct */
|
||||
struct _gmac_desc {
|
||||
uint32_t addr;
|
||||
uint32_t status;
|
||||
};
|
||||
|
||||
/** @}*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* TODO
|
||||
*/
|
||||
extern bool gmac_configure(Gmac *gmac);
|
||||
|
||||
/**
|
||||
* \brief Write NCR register value
|
||||
*/
|
||||
extern void gmac_set_network_control_register(Gmac * gmac, uint32_t ncr);
|
||||
|
||||
/**
|
||||
* \brief Get NCR register value
|
||||
*/
|
||||
extern uint32_t gmac_get_network_control_register(Gmac * gmac);
|
||||
|
||||
/**
|
||||
* \brief Set network configuration register
|
||||
*/
|
||||
extern void gmac_set_network_config_register(Gmac* gmac, uint32_t ncfgr);
|
||||
|
||||
/**
|
||||
* \brief Get network configuration register
|
||||
*/
|
||||
|
||||
extern uint32_t gmac_get_network_config_register(Gmac* gmac);
|
||||
|
||||
/**
|
||||
* \brief Enable MDI with PHY
|
||||
* \param gmac Pointer to an Gmac instance.
|
||||
*/
|
||||
extern void gmac_enable_mdio(Gmac* gmac);
|
||||
|
||||
/**
|
||||
* \brief Disable MDI with PHY
|
||||
* \param gmac Pointer to an Gmac instance.
|
||||
*/
|
||||
extern void gmac_disable_mdio(Gmac* gmac);
|
||||
|
||||
/**
|
||||
* \brief Execute PHY read command
|
||||
*/
|
||||
extern bool gmac_phy_read(Gmac* gmac, uint8_t phy_addr, uint8_t reg_addr,
|
||||
uint16_t* data, uint32_t retries);
|
||||
|
||||
/**
|
||||
* \brief Execute PHY write command
|
||||
*/
|
||||
extern bool gmac_phy_write(Gmac* gmac, uint8_t phy_addr, uint8_t reg_addr,
|
||||
uint16_t data, uint32_t retries);
|
||||
|
||||
/**
|
||||
* \brief Enable MII mode for GMAC, called once after autonegotiate
|
||||
* \param gmac Pointer to an Gmac instance.
|
||||
*/
|
||||
extern void gmac_enable_mii(Gmac* gmac);
|
||||
|
||||
/**
|
||||
* \brief Enable RMII mode for GMAC, called once after autonegotiate
|
||||
* \param gmac Pointer to an Gmac instance.
|
||||
* \param duplex: 1 full duplex 0 half duplex
|
||||
* \param speed: 0 10M 1 100M
|
||||
*/
|
||||
extern void gmac_enable_rmii(Gmac* gmac, enum _gmac_speed speed,
|
||||
enum _gmac_duplex duplex);
|
||||
|
||||
/**
|
||||
* \brief Setup the GMAC for the link : speed 100M/10M and Full/Half duplex
|
||||
* \param gmac Pointer to an Gmac instance.
|
||||
* \param speed Link speed, 0 for 10M, 1 for 100M
|
||||
* \param fullduplex 1 for Full Duplex mode
|
||||
*/
|
||||
extern void gmac_set_link_speed(Gmac* gmac, enum _gmac_speed speed,
|
||||
enum _gmac_duplex duplex);
|
||||
|
||||
/**
|
||||
* \brief Enable local loop back
|
||||
* \param gmac Pointer to an Gmac instance.
|
||||
*/
|
||||
extern void gmac_enable_local_loopback(Gmac* gmac);
|
||||
|
||||
/**
|
||||
* \brief Disable local loop back
|
||||
* \param gmac Pointer to an Gmac instance.
|
||||
*/
|
||||
extern void gmac_disable_local_loopback(Gmac* gmac);
|
||||
|
||||
/**
|
||||
* \brief Return transmit status
|
||||
*/
|
||||
extern uint32_t gmac_get_tx_status(Gmac* gmac);
|
||||
|
||||
/**
|
||||
* \brief Clear transmit status
|
||||
*/
|
||||
extern void gmac_clear_tx_status(Gmac* gmac, uint32_t mask);
|
||||
|
||||
/**
|
||||
* \brief Return receive status
|
||||
*/
|
||||
extern uint32_t gmac_get_rx_status(Gmac* gmac);
|
||||
|
||||
/**
|
||||
* \brief Clear receive status
|
||||
*/
|
||||
extern void gmac_clear_rx_status(Gmac* gmac, uint32_t mask);
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable GMAC receive.
|
||||
*/
|
||||
extern void gmac_receive_enable(Gmac* gmac, bool enable);
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable GMAC transmit.
|
||||
*/
|
||||
extern void gmac_transmit_enable(Gmac* gmac, bool enable);
|
||||
|
||||
/**
|
||||
* \brief Set RX descriptor address
|
||||
*/
|
||||
void gmac_set_rx_desc(Gmac* gmac, uint8_t queue, struct _gmac_desc* desc);
|
||||
|
||||
/**
|
||||
* \brief Get RX descriptor address
|
||||
*/
|
||||
struct _gmac_desc* gmac_get_rx_desc(Gmac* gmac, uint8_t queue);
|
||||
|
||||
/**
|
||||
* \brief Set TX descriptor address
|
||||
*/
|
||||
void gmac_set_tx_desc(Gmac* gmac, uint8_t queue, struct _gmac_desc* desc);
|
||||
|
||||
/**
|
||||
* \brief Get TX descriptor address
|
||||
*/
|
||||
struct _gmac_desc* gmac_get_tx_desc(Gmac* gmac, uint8_t queue);
|
||||
|
||||
/**
|
||||
* \brief Return interrupt mask.
|
||||
*/
|
||||
extern uint32_t gmac_get_it_mask(Gmac* gmac, uint8_t queue);
|
||||
|
||||
/**
|
||||
* \brief Enable interrupt(s).
|
||||
*/
|
||||
extern void gmac_enable_it(Gmac* gmac, uint8_t queue, uint32_t mask);
|
||||
|
||||
/**
|
||||
* \brief Disable interrupt(s).
|
||||
*/
|
||||
extern void gmac_disable_it(Gmac * gmac, uint8_t queue, uint32_t mask);
|
||||
|
||||
/**
|
||||
* \brief Return interrupt status mask.
|
||||
*/
|
||||
extern uint32_t gmac_get_it_status(Gmac* gmac, uint8_t queue);
|
||||
|
||||
/**
|
||||
* \brief Set MAC Address
|
||||
*/
|
||||
extern void gmac_set_mac_addr(Gmac* gmac, uint8_t sa_idx, uint8_t* mac);
|
||||
|
||||
/**
|
||||
* \brief Set MAC Address using two 32-bit integers
|
||||
*/
|
||||
extern void gmac_set_mac_addr32(Gmac* gmac, uint8_t sa_idx,
|
||||
uint32_t mac_top, uint32_t mac_bottom);
|
||||
|
||||
/**
|
||||
* \brief Set MAC Address using a 64-bit integer
|
||||
*/
|
||||
extern void gmac_set_mac_addr64(Gmac* gmac, uint8_t sa_idx, uint64_t mac);
|
||||
|
||||
/**
|
||||
* \brief Clear all statistics registers
|
||||
*/
|
||||
extern void gmac_clear_statistics(Gmac* gmac);
|
||||
|
||||
/**
|
||||
* \brief Increase all statistics registers
|
||||
*/
|
||||
extern void gmac_increase_statistics(Gmac* gmac);
|
||||
|
||||
/**
|
||||
* \brief Enable/Disable statistics registers writing.
|
||||
*/
|
||||
extern void gmac_enable_statistics_write(Gmac* gmac, bool enable);
|
||||
|
||||
/**
|
||||
* \brief Start transmission
|
||||
*/
|
||||
extern void gmac_start_transmission(Gmac* gmac);
|
||||
|
||||
/**
|
||||
* \brief Halt transmission
|
||||
*/
|
||||
extern void gmac_halt_transmission(Gmac* gmac);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _GMAC_H_ */
|
|
@ -0,0 +1,823 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Headers
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "trace.h"
|
||||
#include "ring.h"
|
||||
|
||||
#include "peripherals/aic.h"
|
||||
#include "peripherals/gmacd.h"
|
||||
#include "peripherals/gmac.h"
|
||||
#include "peripherals/l2cc.h"
|
||||
#include "peripherals/pmc.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Definitions
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Interrupt bits
|
||||
#define GMAC_INT_RX_BITS (GMAC_IER_RCOMP | GMAC_IER_RXUBR | GMAC_IER_ROVR)
|
||||
#define GMAC_INT_TX_ERR_BITS (GMAC_IER_TUR | GMAC_IER_RLEX | GMAC_IER_TFC)
|
||||
#define GMAC_INT_TX_BITS (GMAC_INT_TX_ERR_BITS | GMAC_IER_TCOMP)
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Types
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
struct _gmacd_irq_handler {
|
||||
Gmac* addr;
|
||||
struct _gmacd** gmacd;
|
||||
uint32_t irq;
|
||||
aic_handler_t handler;
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* IRQ Handlers
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef CONFIG_HAVE_GMAC_QUEUES
|
||||
#if GMAC_NUM_QUEUES != 3
|
||||
#error This driver assumes that GMAC_NUM_QUEUES is 3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static struct _gmacd* _gmacd0;
|
||||
#ifdef GMAC1
|
||||
static struct _gmacd* _gmacd1;
|
||||
#endif
|
||||
|
||||
static void _gmacd_handler(struct _gmacd* gmacd, uint8_t queue);
|
||||
|
||||
static void _gmacd_gmac0_irq_handler(void)
|
||||
{
|
||||
_gmacd_handler(_gmacd0, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_GMAC_QUEUES
|
||||
static void _gmacd_gmac0q1_irq_handler(void)
|
||||
{
|
||||
_gmacd_handler(_gmacd0, 1);
|
||||
}
|
||||
|
||||
static void _gmacd_gmac0q2_irq_handler(void)
|
||||
{
|
||||
_gmacd_handler(_gmacd0, 2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef GMAC1
|
||||
static void _gmacd_gmac1_irq_handler(void)
|
||||
{
|
||||
_gmacd_handler(_gmacd1, 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_GMAC_QUEUES
|
||||
static void _gmacd_gmac1q1_irq_handler(void)
|
||||
{
|
||||
_gmacd_handler(_gmacd1, 1);
|
||||
}
|
||||
|
||||
static void _gmacd_gmac1q2_irq_handler(void)
|
||||
{
|
||||
_gmacd_handler(_gmacd1, 2);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static const struct _gmacd_irq_handler _gmacd_irq_handlers[] = {
|
||||
{ GMAC0, &_gmacd0, ID_GMAC0, _gmacd_gmac0_irq_handler },
|
||||
#ifdef CONFIG_HAVE_GMAC_QUEUES
|
||||
{ GMAC0, &_gmacd0, ID_GMAC0_Q1, _gmacd_gmac0q1_irq_handler },
|
||||
{ GMAC0, &_gmacd0, ID_GMAC0_Q2, _gmacd_gmac0q2_irq_handler },
|
||||
#endif
|
||||
#ifdef GMAC1
|
||||
{ GMAC1, &_gmacd1, ID_GMAC1, _gmacd_gmac1_irq_handler },
|
||||
#ifdef CONFIG_HAVE_GMAC_QUEUES
|
||||
{ GMAC1, &_gmacd1, ID_GMAC1_Q1, _gmacd_gmac1q1_irq_handler },
|
||||
{ GMAC1, &_gmacd1, ID_GMAC1_Q2, _gmacd_gmac1q2_irq_handler },
|
||||
#endif
|
||||
#endif
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Dummy Buffers for unconfigured queues
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#define DUMMY_BUFFERS 2
|
||||
#define DUMMY_UNITSIZE 128
|
||||
|
||||
/** TX descriptors list */
|
||||
ALIGNED(8) SECTION(".region_ddr_nocache")
|
||||
static struct _gmac_desc dummy_tx_desc[DUMMY_BUFFERS];
|
||||
|
||||
/** RX descriptors list */
|
||||
ALIGNED(8) SECTION(".region_ddr_nocache")
|
||||
static struct _gmac_desc dummy_rx_desc[DUMMY_BUFFERS];
|
||||
|
||||
/** Send Buffer */
|
||||
ALIGNED(32)
|
||||
static uint8_t dummy_buffer[DUMMY_BUFFERS * DUMMY_UNITSIZE];
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Local functions
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Disable TX & reset registers and descriptor list
|
||||
* \param gmacd Pointer to GMAC Driver instance.
|
||||
*/
|
||||
static void _gmacd_reset_tx(struct _gmacd* gmacd, uint8_t queue)
|
||||
{
|
||||
struct _gmacd_queue* q = &gmacd->queues[queue];
|
||||
uint32_t addr = (uint32_t)q->tx_buffer;
|
||||
uint32_t i;
|
||||
|
||||
/* Disable TX */
|
||||
gmac_transmit_enable(gmacd->gmac, false);
|
||||
|
||||
/* Setup the TX descriptors */
|
||||
RING_CLEAR(q->tx_head, q->tx_tail);
|
||||
for (i = 0; i < q->tx_size; i++) {
|
||||
q->tx_desc[i].addr = addr;
|
||||
DSB();
|
||||
q->tx_desc[i].status = GMAC_TX_STATUS_USED;
|
||||
addr += GMAC_TX_UNITSIZE;
|
||||
}
|
||||
q->tx_desc[q->tx_size - 1].status |= GMAC_TX_STATUS_WRAP;
|
||||
|
||||
/* Transmit Buffer Queue Pointer Register */
|
||||
gmac_set_tx_desc(gmacd->gmac, queue, q->tx_desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable RX & reset registers and descriptor list
|
||||
* \param gmacd Pointer to GMAC Driver instance.
|
||||
*/
|
||||
static void _gmacd_reset_rx(struct _gmacd* gmacd, uint8_t queue)
|
||||
{
|
||||
struct _gmacd_queue* q = &gmacd->queues[queue];
|
||||
uint32_t addr = (uint32_t)q->rx_buffer;
|
||||
uint32_t i;
|
||||
|
||||
/* Disable RX */
|
||||
gmac_receive_enable(gmacd->gmac, false);
|
||||
|
||||
/* Setup the RX descriptors */
|
||||
q->rx_head = 0;
|
||||
for (i = 0; i < q->rx_size; i++) {
|
||||
q->rx_desc[i].addr = addr & GMAC_RX_ADDR_MASK;
|
||||
DSB();
|
||||
q->rx_desc[i].status = 0;
|
||||
addr += GMAC_RX_UNITSIZE;
|
||||
}
|
||||
q->rx_desc[q->rx_size - 1].addr |= GMAC_RX_ADDR_WRAP;
|
||||
|
||||
/* Receive Buffer Queue Pointer Register */
|
||||
gmac_set_rx_desc(gmacd->gmac, queue, q->rx_desc);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Process successfully sent packets
|
||||
* \param gmacd Pointer to GMAC Driver instance.
|
||||
*/
|
||||
static void _gmacd_tx_complete_handler(struct _gmacd* gmacd, uint8_t queue)
|
||||
{
|
||||
Gmac* gmac = gmacd->gmac;
|
||||
struct _gmacd_queue* q = &gmacd->queues[queue];
|
||||
struct _gmac_desc *desc;
|
||||
gmacd_callback_t callback;
|
||||
uint32_t tsr;
|
||||
|
||||
//printf("<TX>\r\n");
|
||||
|
||||
/* Clear status */
|
||||
tsr = gmac_get_tx_status(gmac);
|
||||
gmac_clear_tx_status(gmac, tsr);
|
||||
|
||||
while (!RING_EMPTY(q->tx_head, q->tx_tail)) {
|
||||
desc = &q->tx_desc[q->tx_tail];
|
||||
|
||||
/* Exit if frame has not been sent yet:
|
||||
* On TX completion, the GMAC set the USED bit only into the
|
||||
* very first buffer descriptor of the sent frame.
|
||||
* Otherwise it updates this descriptor with status error bits.
|
||||
* This is the descriptor writeback.
|
||||
*/
|
||||
if ((desc->status & GMAC_TX_STATUS_USED) == 0)
|
||||
break;
|
||||
|
||||
/* Process all buffers of the current transmitted frame */
|
||||
while ((desc->status & GMAC_TX_STATUS_LASTBUF) == 0) {
|
||||
RING_INC(q->tx_tail, q->tx_size);
|
||||
desc = &q->tx_desc[q->tx_tail];
|
||||
}
|
||||
|
||||
/* Notify upper layer that a frame has been sent */
|
||||
if (q->tx_callbacks) {
|
||||
callback = q->tx_callbacks[q->tx_tail];
|
||||
if (callback)
|
||||
callback(queue, tsr);
|
||||
}
|
||||
|
||||
/* Go to next frame */
|
||||
RING_INC(q->tx_tail, q->tx_size);
|
||||
}
|
||||
|
||||
/* If a wakeup callback has been set, notify upper layer that it can
|
||||
send more packets now */
|
||||
if (q->tx_wakeup_callback) {
|
||||
if (RING_SPACE(q->tx_head, q->tx_tail, q->tx_size) >=
|
||||
q->tx_wakeup_threshold) {
|
||||
q->tx_wakeup_callback(queue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reset TX queue when errors are detected
|
||||
* \param gmacd Pointer to GMAC Driver instance.
|
||||
*/
|
||||
static void _gmacd_tx_error_handler(struct _gmacd* gmacd, uint8_t queue)
|
||||
{
|
||||
Gmac *gmac = gmacd->gmac;
|
||||
struct _gmacd_queue* q = &gmacd->queues[queue];
|
||||
struct _gmac_desc* desc;
|
||||
gmacd_callback_t callback;
|
||||
uint32_t tsr;
|
||||
|
||||
printf("<TXERR>\r\n");
|
||||
|
||||
/* Clear TXEN bit into the Network Configuration Register:
|
||||
* this is a workaround to recover from TX lockups that
|
||||
* occur on sama5d4 gmac (r1p24f2) when using scatter-gather.
|
||||
* This issue has never been seen on sama5d4 gmac (r1p31).
|
||||
*/
|
||||
gmac_transmit_enable(gmac, false);
|
||||
|
||||
/* The following step should be optional since this function is called
|
||||
* directly by the IRQ handler. Indeed, according to Cadence
|
||||
* documentation, the transmission is halted on errors such as
|
||||
* too many retries or transmit under run.
|
||||
* However it would become mandatory if the call of this function
|
||||
* were scheduled as a task by the IRQ handler (this is how Linux
|
||||
* driver works). Then this function might compete with GMACD_Send().
|
||||
*
|
||||
* Setting bit 10, tx_halt, of the Network Control Register is not enough:
|
||||
* We should wait for bit 3, tx_go, of the Transmit Status Register to
|
||||
* be cleared at transmit completion if a frame is being transmitted.
|
||||
*/
|
||||
gmac_halt_transmission(gmac);
|
||||
while (gmac_get_tx_status(gmac) & GMAC_TSR_TXGO);
|
||||
|
||||
/* Treat frames in TX queue including the ones that caused the error. */
|
||||
while (!RING_EMPTY(q->tx_head, q->tx_tail)) {
|
||||
int tx_completed = 0;
|
||||
desc = &q->tx_desc[q->tx_tail];
|
||||
|
||||
/* Check USED bit on the very first buffer descriptor to validate
|
||||
* TX completion.
|
||||
*/
|
||||
if (desc->status & GMAC_TX_STATUS_USED)
|
||||
tx_completed = 1;
|
||||
|
||||
/* Go to the last buffer descriptor of the frame */
|
||||
while ((desc->status & GMAC_TX_STATUS_LASTBUF) == 0) {
|
||||
RING_INC(q->tx_tail, q->tx_size);
|
||||
desc = &q->tx_desc[q->tx_tail];
|
||||
}
|
||||
|
||||
/* Notify upper layer that a frame status */
|
||||
// TODO: which error to notify?
|
||||
if (q->tx_callbacks) {
|
||||
callback = q->tx_callbacks[q->tx_tail];
|
||||
if (callback)
|
||||
callback(queue, tx_completed ? GMAC_TSR_TXCOMP : 0);
|
||||
}
|
||||
|
||||
/* Go to next frame */
|
||||
RING_INC(q->tx_tail, q->tx_size);
|
||||
}
|
||||
|
||||
/* Reset TX queue */
|
||||
_gmacd_reset_tx(gmacd, queue);
|
||||
|
||||
/* Clear status */
|
||||
tsr = gmac_get_tx_status(gmac);
|
||||
gmac_clear_tx_status(gmac, tsr);
|
||||
|
||||
/* Now we are ready to start transmission again */
|
||||
gmac_transmit_enable(gmac, true);
|
||||
if (q->tx_wakeup_callback)
|
||||
q->tx_wakeup_callback(queue);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief GMAC Interrupt handler
|
||||
* \param gmacd Pointer to GMAC Driver instance.
|
||||
*/
|
||||
static void _gmacd_handler(struct _gmacd * gmacd, uint8_t queue)
|
||||
{
|
||||
Gmac *gmac = gmacd->gmac;
|
||||
struct _gmacd_queue* q = &gmacd->queues[queue];
|
||||
uint32_t isr;
|
||||
uint32_t rsr;
|
||||
|
||||
/* Interrupt Status Register is cleared on read */
|
||||
while ((isr = gmac_get_it_status(gmac, queue)) != 0) {
|
||||
/* RX packet */
|
||||
if (isr & GMAC_INT_RX_BITS) {
|
||||
/* Clear status */
|
||||
rsr = gmac_get_rx_status(gmac);
|
||||
gmac_clear_rx_status(gmac, rsr);
|
||||
|
||||
/* Invoke callback */
|
||||
if (q->rx_callback)
|
||||
q->rx_callback(queue, rsr);
|
||||
}
|
||||
|
||||
/* TX error */
|
||||
if (isr & GMAC_INT_TX_ERR_BITS) {
|
||||
_gmacd_tx_error_handler(gmacd, queue);
|
||||
break;
|
||||
}
|
||||
|
||||
/* TX packet */
|
||||
if (isr & GMAC_IER_TCOMP) {
|
||||
_gmacd_tx_complete_handler(gmacd, queue);
|
||||
}
|
||||
|
||||
/* HRESP not OK */
|
||||
if (isr & GMAC_IER_HRESP) {
|
||||
trace_error("HRESP not OK\n\r");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initialize the GMAC with the Gmac controller address
|
||||
* \param gmacd Pointer to GMAC Driver instance.
|
||||
* \param gmac Pointer to HW address for registers.
|
||||
* \param enableCAF Enable/Disable CopyAllFrame.
|
||||
* \param enableNBC Enable/Disable NoBroadCast.
|
||||
*/
|
||||
void gmacd_configure(struct _gmacd * gmacd,
|
||||
Gmac * gmac, uint8_t enableCAF, uint8_t enableNBC)
|
||||
{
|
||||
uint32_t ncfgr;
|
||||
int i;
|
||||
|
||||
/* Initialize struct */
|
||||
gmacd->gmac = gmac;
|
||||
|
||||
gmac_configure(gmac);
|
||||
|
||||
uint32_t id = get_gmac_id_from_addr(gmac);
|
||||
for (i = 0; i < ARRAY_SIZE(_gmacd_irq_handlers); i++) {
|
||||
if (_gmacd_irq_handlers[i].addr == gmac) {
|
||||
*_gmacd_irq_handlers[i].gmacd = gmacd;
|
||||
aic_set_source_vector(_gmacd_irq_handlers[i].irq,
|
||||
_gmacd_irq_handlers[i].handler);
|
||||
}
|
||||
}
|
||||
aic_enable(id);
|
||||
|
||||
/* Enable the copy of data into the buffers
|
||||
ignore broadcasts, and don't copy FCS. */
|
||||
ncfgr = gmac_get_network_config_register(gmac);
|
||||
ncfgr |= GMAC_NCFGR_FD;
|
||||
if (enableCAF) {
|
||||
ncfgr |= GMAC_NCFGR_CAF;
|
||||
}
|
||||
if (enableNBC) {
|
||||
ncfgr |= GMAC_NCFGR_NBC;
|
||||
}
|
||||
gmac_set_network_config_register(gmac, ncfgr);
|
||||
|
||||
for (i = 0; i < GMAC_NUM_QUEUES; i++) {
|
||||
gmacd_setup_queue(gmacd, i,
|
||||
DUMMY_BUFFERS, dummy_buffer, dummy_rx_desc,
|
||||
DUMMY_BUFFERS, dummy_buffer, dummy_tx_desc,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize necessary allocated buffer lists for GMAC Driver to transfer data.
|
||||
* Must be invoked after GMACD_Init() but before RX/TX start.
|
||||
* \param gmacd Pointer to GMAC Driver instance.
|
||||
* \param rx_buffer Pointer to allocated buffer for RX. The address should
|
||||
* be 8-byte aligned and the size should be
|
||||
* GMAC_RX_UNITSIZE * wRxSize.
|
||||
* \param rx_desc Pointer to allocated RX descriptor list.
|
||||
* \param wRxSize RX size, in number of registered units (RX descriptors).
|
||||
* \param tx_buffer Pointer to allocated buffer for TX. The address should
|
||||
* be 8-byte aligned and the size should be
|
||||
* GMAC_TX_UNITSIZE * wTxSize.
|
||||
* \param tx_desc Pointer to allocated TX descriptor list.
|
||||
* \param pTxCb Pointer to allocated TX callback list.
|
||||
* \param wTxSize TX size, in number of registered units (TX descriptors).
|
||||
* \return GMACD_OK or GMACD_PARAM.
|
||||
* \note If input address is not 8-byte aligned the address is automatically
|
||||
* adjusted and the list size is reduced by one.
|
||||
*/
|
||||
|
||||
|
||||
uint8_t gmacd_setup_queue(struct _gmacd* gmacd, uint8_t queue,
|
||||
uint16_t rx_size, uint8_t* rx_buffer, struct _gmac_desc* rx_desc,
|
||||
uint16_t tx_size, uint8_t* tx_buffer, struct _gmac_desc* tx_desc,
|
||||
gmacd_callback_t *tx_callbacks)
|
||||
{
|
||||
Gmac *gmac = gmacd->gmac;
|
||||
struct _gmacd_queue* q = &gmacd->queues[queue];
|
||||
|
||||
if (rx_size <= 1 || tx_size <= 1)
|
||||
return GMACD_PARAM;
|
||||
|
||||
/* Assign RX buffers */
|
||||
if (((uint32_t)rx_buffer & 0x7)
|
||||
|| ((uint32_t)rx_desc & 0x7)) {
|
||||
rx_size--;
|
||||
trace_debug("RX list address adjusted\n\r");
|
||||
}
|
||||
q->rx_buffer = (uint8_t*)((uint32_t)rx_buffer & 0xFFFFFFF8);
|
||||
q->rx_desc = (struct _gmac_desc *)((uint32_t)rx_desc & 0xFFFFFFF8);
|
||||
q->rx_size = rx_size;
|
||||
q->rx_callback = NULL;
|
||||
|
||||
/* Assign TX buffers */
|
||||
if (((uint32_t)tx_buffer & 0x7)
|
||||
|| ((uint32_t)tx_desc & 0x7)) {
|
||||
tx_size--;
|
||||
trace_debug("TX list address adjusted\n\r");
|
||||
}
|
||||
q->tx_buffer = (uint8_t*)((uint32_t)tx_buffer & 0xFFFFFFF8);
|
||||
q->tx_desc = (struct _gmac_desc*)((uint32_t)tx_desc & 0xFFFFFFF8);
|
||||
q->tx_size = tx_size;
|
||||
q->tx_callbacks = tx_callbacks;
|
||||
q->tx_wakeup_callback = NULL;
|
||||
|
||||
/* Reset TX & RX */
|
||||
_gmacd_reset_rx(gmacd, queue);
|
||||
_gmacd_reset_tx(gmacd, queue);
|
||||
|
||||
/* Setup the interrupts for RX/TX completion (and errors) */
|
||||
gmac_enable_it(gmac, queue, GMAC_INT_RX_BITS | GMAC_INT_TX_BITS | GMAC_IER_HRESP);
|
||||
|
||||
return GMACD_OK;
|
||||
}
|
||||
|
||||
void gmacd_start(struct _gmacd * gmacd)
|
||||
{
|
||||
/* Enable Rx and Tx, plus the stats register. */
|
||||
gmac_transmit_enable(gmacd->gmac, true);
|
||||
gmac_receive_enable(gmacd->gmac, true);
|
||||
gmac_enable_statistics_write(gmacd->gmac, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset TX & RX queue & statistics
|
||||
* \param gmacd Pointer to GMAC Driver instance.
|
||||
*/
|
||||
void gmacd_reset(struct _gmacd* gmacd)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < GMAC_NUM_QUEUES; i++) {
|
||||
_gmacd_reset_rx(gmacd, i);
|
||||
_gmacd_reset_tx(gmacd, i);
|
||||
}
|
||||
|
||||
gmac_set_network_control_register(gmacd->gmac, GMAC_NCR_TXEN | GMAC_NCR_RXEN |
|
||||
GMAC_NCR_WESTAT | GMAC_NCR_CLRSTAT);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Send a frame splitted into buffers. If the frame size is larger than transfer buffer size
|
||||
* error returned. If frame transfer status is monitored, specify callback for each frame.
|
||||
* \param gmacd Pointer to GMAC Driver instance.
|
||||
* \param sgl Pointer to a scatter-gather list describing the buffers of the ethernet frame.
|
||||
* \param fTxCb Pointer to callback function.
|
||||
*/
|
||||
uint8_t gmacd_send_sg(struct _gmacd* gmacd, uint8_t queue,
|
||||
const struct _gmac_sg_list* sgl, gmacd_callback_t callback)
|
||||
{
|
||||
Gmac* gmac = gmacd->gmac;
|
||||
struct _gmacd_queue* q = &gmacd->queues[queue];
|
||||
struct _gmac_desc* desc;
|
||||
uint16_t idx, tx_head;
|
||||
int i;
|
||||
|
||||
if (callback && !q->tx_callbacks) {
|
||||
trace_error("Cannot set send callback, no tx_callbacks "\
|
||||
"buffer configured for queue %u", queue);
|
||||
}
|
||||
|
||||
/* Check parameter */
|
||||
if (!sgl->size) {
|
||||
trace_error("gmacd_send_sg: ethernet frame is empty.\r\n");
|
||||
return GMACD_PARAM;
|
||||
}
|
||||
if (sgl->size >= q->tx_size) {
|
||||
trace_error("gmacd_send_sg: ethernet frame has too many buffers.\r\n");
|
||||
return GMACD_PARAM;
|
||||
}
|
||||
|
||||
/* Check available space */
|
||||
if (RING_SPACE(q->tx_head, q->tx_tail, q->tx_size) < sgl->size) {
|
||||
trace_error("gmacd_send_sg: not enough free buffers in TX queue.\r\n");
|
||||
return GMACD_TX_BUSY;
|
||||
}
|
||||
|
||||
/* Tag end of TX queue */
|
||||
tx_head = fixed_mod(q->tx_head + sgl->size, q->tx_size);
|
||||
idx = tx_head;
|
||||
if (q->tx_callbacks)
|
||||
q->tx_callbacks[idx] = NULL;
|
||||
desc = &q->tx_desc[idx];
|
||||
desc->status |= GMAC_TX_STATUS_USED;
|
||||
|
||||
/* Update buffer descriptors in reverse order to avoid a race
|
||||
* condition with hardware.
|
||||
*/
|
||||
for (i = sgl->size - 1; i >= 0; i--) {
|
||||
const struct _gmac_sg *sg = &sgl->entries[i];
|
||||
uint32_t status;
|
||||
|
||||
if (sg->size > GMAC_TX_UNITSIZE) {
|
||||
trace_error("gmacd_send_sg: buffer size is too big.\r\n");
|
||||
return GMACD_PARAM;
|
||||
}
|
||||
|
||||
RING_DEC(idx, q->tx_size);
|
||||
|
||||
/* Reset TX callback */
|
||||
if (q->tx_callbacks)
|
||||
q->tx_callbacks[idx] = NULL;
|
||||
|
||||
desc = &q->tx_desc[idx];
|
||||
|
||||
/* Copy data into transmittion buffer */
|
||||
if (sg->buffer && sg->size) {
|
||||
memcpy((void*)desc->addr, sg->buffer, sg->size);
|
||||
l2cc_clean_region(desc->addr, desc->addr + sg->size);
|
||||
}
|
||||
|
||||
/* Compute buffer descriptor status word */
|
||||
status = sg->size & GMAC_RX_STATUS_LENGTH_MASK;
|
||||
if (i == (sgl->size - 1)) {
|
||||
status |= GMAC_TX_STATUS_LASTBUF;
|
||||
if (q->tx_callbacks)
|
||||
q->tx_callbacks[idx] = callback;
|
||||
}
|
||||
if (idx == (q->tx_size - 1)) {
|
||||
status |= GMAC_TX_STATUS_WRAP;
|
||||
}
|
||||
|
||||
/* Update buffer descriptor status word: clear USED bit */
|
||||
desc->status = status;
|
||||
DSB();
|
||||
}
|
||||
|
||||
/* Update TX ring buffer pointers */
|
||||
q->tx_head = tx_head;
|
||||
|
||||
/* Now start to transmit if it is not already done */
|
||||
gmac_start_transmission(gmac);
|
||||
|
||||
return GMACD_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Send a packet with GMAC. If the packet size is larger than transfer buffer size
|
||||
* error returned. If packet transfer status is monitored, specify callback for each packet.
|
||||
* \param gmacd Pointer to GMAC Driver instance.
|
||||
* \param pBuffer The buffer to be send
|
||||
* \param size The size of buffer to be send
|
||||
* \param fTxCb Threshold Wakeup callback
|
||||
* \return OK, Busy or invalid packet
|
||||
*/
|
||||
uint8_t gmacd_send(struct _gmacd* gmacd, uint8_t queue, void *buffer,
|
||||
uint32_t size, gmacd_callback_t callback)
|
||||
{
|
||||
struct _gmac_sg sg;
|
||||
struct _gmac_sg_list sgl;
|
||||
|
||||
/* Init single entry scatter-gather list */
|
||||
sg.size = size;
|
||||
sg.buffer = buffer;
|
||||
sgl.size = 1;
|
||||
sgl.entries = &sg;
|
||||
|
||||
return gmacd_send_sg(gmacd, queue, &sgl, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return current load of TX.
|
||||
* \param gmacd Pointer to GMAC Driver instance.
|
||||
*/
|
||||
uint32_t gmacd_get_tx_load(struct _gmacd* gmacd, uint8_t queue)
|
||||
{
|
||||
struct _gmacd_queue* q = &gmacd->queues[queue];
|
||||
return RING_CNT(q->tx_head, q->tx_tail, q->tx_size);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Receive a packet with GMAC.
|
||||
* If not enough buffer for the packet, the remaining data is lost but right
|
||||
* frame length is returned.
|
||||
* \param gmacd Pointer to GMAC Driver instance.
|
||||
* \param pFrame Buffer to store the frame
|
||||
* \param frameSize Size of the frame
|
||||
* \param pRcvSize Received size
|
||||
* \return OK, no data, or frame too small
|
||||
*/
|
||||
uint8_t gmacd_poll(struct _gmacd* gmacd, uint8_t queue,
|
||||
uint8_t* buffer, uint32_t buffer_size, uint32_t* recv_size)
|
||||
{
|
||||
struct _gmacd_queue* q = &gmacd->queues[queue];
|
||||
struct _gmac_desc *desc;
|
||||
uint32_t idx;
|
||||
uint32_t cur_frame_size = 0;
|
||||
uint8_t *cur_frame = 0;
|
||||
|
||||
if (!buffer)
|
||||
return GMACD_PARAM;
|
||||
|
||||
/* Set the default return value */
|
||||
*recv_size = 0;
|
||||
|
||||
/* Process RX descriptors */
|
||||
idx = q->rx_head;
|
||||
desc = &q->rx_desc[idx];
|
||||
while (desc->addr & GMAC_RX_ADDR_OWN) {
|
||||
/* A start of frame has been received, discard previous fragments */
|
||||
if (desc->status & GMAC_RX_STATUS_SOF) {
|
||||
/* Skip previous fragment */
|
||||
while (idx != q->rx_head) {
|
||||
desc = &q->rx_desc[q->rx_head];
|
||||
desc->addr &= ~GMAC_RX_ADDR_OWN;
|
||||
RING_INC(q->rx_head, q->rx_size);
|
||||
}
|
||||
cur_frame = buffer;
|
||||
cur_frame_size = 0;
|
||||
}
|
||||
|
||||
/* Increment the index */
|
||||
RING_INC(idx, q->rx_size);
|
||||
|
||||
/* Copy data in the frame buffer */
|
||||
if (cur_frame) {
|
||||
if (idx == q->rx_head) {
|
||||
trace_info("no EOF (buffers probably too small)\r\n");
|
||||
|
||||
do {
|
||||
desc = &q->rx_desc[q->rx_head];
|
||||
desc->addr &= ~GMAC_RX_ADDR_OWN;
|
||||
RING_INC(q->rx_head, q->rx_size);
|
||||
} while (idx != q->rx_head);
|
||||
return GMACD_RX_NULL;
|
||||
}
|
||||
|
||||
/* Copy the buffer into the application frame */
|
||||
uint32_t length = GMAC_RX_UNITSIZE;
|
||||
if ((cur_frame_size + length) > buffer_size) {
|
||||
length = buffer_size - cur_frame_size;
|
||||
}
|
||||
|
||||
uint32_t addr = desc->addr & GMAC_RX_ADDR_MASK;
|
||||
l2cc_invalidate_region(addr, addr + length);
|
||||
memcpy(cur_frame, (void*)addr, length);
|
||||
cur_frame += length;
|
||||
cur_frame_size += length;
|
||||
|
||||
/* An end of frame has been received, return the data */
|
||||
if (desc->status & GMAC_RX_STATUS_EOF) {
|
||||
/* Frame size from the GMAC */
|
||||
*recv_size = desc->status & GMAC_RX_STATUS_LENGTH_MASK;
|
||||
|
||||
/* Application frame buffer is too small all
|
||||
* data have not been copied */
|
||||
if (cur_frame_size < *recv_size) {
|
||||
return GMACD_SIZE_TOO_SMALL;
|
||||
}
|
||||
|
||||
/* All data have been copied in the application
|
||||
* frame buffer => release descriptors */
|
||||
while (q->rx_head != idx) {
|
||||
desc = &q->rx_desc[q->rx_head];
|
||||
desc->addr &= ~GMAC_RX_ADDR_OWN;
|
||||
RING_INC(q->rx_head, q->rx_size);
|
||||
}
|
||||
|
||||
return GMACD_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* SOF has not been detected, skip the fragment */
|
||||
else {
|
||||
desc->addr &= ~GMAC_RX_ADDR_OWN;
|
||||
q->rx_head = idx;
|
||||
}
|
||||
|
||||
/* Process the next buffer */
|
||||
desc = &q->rx_desc[idx];
|
||||
}
|
||||
return GMACD_RX_NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Registers pRxCb callback. Callback will be invoked after the next received
|
||||
* frame. When GMAC_Poll() returns GMAC_RX_NO_DATA the application task call GMAC_Set_RxCb()
|
||||
* to register pRxCb() callback and enters suspend state. The callback is in charge
|
||||
* to resume the task once a new frame has been received. The next time GMAC_Poll()
|
||||
* is called, it will be successful.
|
||||
* \param gmacd Pointer to GMAC Driver instance.
|
||||
* \param fRxCb Pointer to callback function
|
||||
* \return OK, no data, or frame too small
|
||||
*/
|
||||
|
||||
void gmacd_set_rx_callback(struct _gmacd* gmacd, uint8_t queue, gmacd_callback_t callback)
|
||||
{
|
||||
struct _gmacd_queue* q = &gmacd->queues[queue];
|
||||
if (!callback) {
|
||||
gmac_disable_it(gmacd->gmac, queue, GMAC_IDR_RCOMP);
|
||||
q->rx_callback = NULL;
|
||||
} else {
|
||||
q->rx_callback = callback;
|
||||
gmac_enable_it(gmacd->gmac, queue, GMAC_IER_RCOMP);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register/Clear TX wakeup callback.
|
||||
*
|
||||
* When GMACD_Send() returns GMACD_TX_BUSY (all TD busy) the application
|
||||
* task calls GMACD_SetTxWakeupCallback() to register fWakeup() callback and
|
||||
* enters suspend state. The callback is in charge to resume the task once
|
||||
* several TD have been released. The next time GMACD_Send() 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 gmacd Pointer to GMAC Driver instance.
|
||||
* \param fWakeup Wakeup callback.
|
||||
* \param bThreshold Number of free TD before wakeup callback invoked.
|
||||
* \return GMACD_OK, GMACD_PARAM on parameter error.
|
||||
*/
|
||||
uint8_t gmacd_set_tx_wakeup_callback(struct _gmacd* gmacd, uint8_t queue,
|
||||
gmacd_wakeup_cb_t callback, uint16_t threshold)
|
||||
{
|
||||
struct _gmacd_queue* q = &gmacd->queues[queue];
|
||||
if (!callback) {
|
||||
q->tx_wakeup_callback = NULL;
|
||||
} else {
|
||||
if (threshold <= q->tx_size) {
|
||||
q->tx_wakeup_callback = callback;
|
||||
q->tx_wakeup_threshold = threshold;
|
||||
} else {
|
||||
return GMACD_PARAM;
|
||||
}
|
||||
}
|
||||
|
||||
return GMACD_OK;
|
||||
}
|
||||
|
||||
/**@}*/
|
|
@ -0,0 +1,189 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file */
|
||||
|
||||
/** \addtogroup gmacd_module
|
||||
* @{
|
||||
* Implement GMAC data transfer and PHY management functions.
|
||||
*
|
||||
* \section Usage
|
||||
* -# Implement GMAC interrupt handler, which must invoke GMACD_Handler()
|
||||
* to handle GMAC interrupt events.
|
||||
* -# Implement struct _gmacd instance in application.
|
||||
* -# Initialize the instance with GMACD_Init() and GMACD_InitTransfer(),
|
||||
* so that GMAC data can be transmitted/received.
|
||||
* -# Some management callbacks can be set by GMACD_SetRxCallback()
|
||||
* and GMACD_SetTxWakeupCallback().
|
||||
* -# Send ethernet packets using GMACD_Send(), GMACD_TxLoad() is used
|
||||
* to check the free space in TX queue.
|
||||
* -# Check and obtain received ethernet packets via GMACD_Poll().
|
||||
*
|
||||
* \sa \ref gmacb_module, \ref gmac_module
|
||||
*
|
||||
* Related files:\n
|
||||
* \ref gmacd.c\n
|
||||
* \ref gmacd.h.\n
|
||||
*
|
||||
* \defgroup gmacd_defines GMAC Driver Defines
|
||||
* \defgroup gmacd_types GMAC Driver Types
|
||||
* \defgroup gmacd_functions GMAC Driver Functions
|
||||
*/
|
||||
/**@}*/
|
||||
|
||||
#ifndef _GMACD_H_
|
||||
#define _GMACD_H_
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Headers
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "peripherals/gmac.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Definitions
|
||||
*---------------------------------------------------------------------------*/
|
||||
/** \addtogroup gmacd_defines
|
||||
@{*/
|
||||
|
||||
/** \addtogroup gmacd_buf_size GMACD Default Buffer Size
|
||||
@{*/
|
||||
#define GMAC_RX_UNITSIZE 128 /**< RX buffer size, must be 128 */
|
||||
#define GMAC_TX_UNITSIZE 1536 /**< TX buffer size, must be multiple
|
||||
of 32 (cache line) */
|
||||
/** @}*/
|
||||
|
||||
/** \addtogroup gmacd_rc GMACD Return Codes
|
||||
@{*/
|
||||
#define GMACD_OK 0 /**< Operation OK */
|
||||
#define GMACD_TX_BUSY 1 /**< TX in progress */
|
||||
#define GMACD_RX_NULL 1 /**< No data received */
|
||||
/** Buffer size not enough */
|
||||
#define GMACD_SIZE_TOO_SMALL 2
|
||||
/** Parameter error, TX packet invalid or RX size too small */
|
||||
#define GMACD_PARAM 3
|
||||
/** Transter is not initialized */
|
||||
#define GMACD_NOT_INITIALIZED 4
|
||||
/** @}*/
|
||||
|
||||
/** @}*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Types
|
||||
*---------------------------------------------------------------------------*/
|
||||
/** \addtogroup gmacd_types
|
||||
@{*/
|
||||
|
||||
/** RX/TX callback */
|
||||
typedef void (*gmacd_callback_t)(uint8_t queue, uint32_t status);
|
||||
|
||||
/** TX Wakeup callback */
|
||||
typedef void (*gmacd_wakeup_cb_t)(uint8_t queue);
|
||||
|
||||
/** GMAC scatter-gather entry */
|
||||
struct _gmac_sg {
|
||||
uint32_t size;
|
||||
void *buffer;
|
||||
struct _gmac_sg *next;
|
||||
};
|
||||
|
||||
/** GMAC scatter-gather list */
|
||||
struct _gmac_sg_list {
|
||||
uint32_t size;
|
||||
struct _gmac_sg *entries;
|
||||
};
|
||||
|
||||
struct _gmacd_queue {
|
||||
uint8_t *rx_buffer;
|
||||
struct _gmac_desc *rx_desc;
|
||||
uint16_t rx_size;
|
||||
uint16_t rx_head;
|
||||
gmacd_callback_t rx_callback;
|
||||
|
||||
uint8_t *tx_buffer;
|
||||
struct _gmac_desc *tx_desc;
|
||||
uint16_t tx_size;
|
||||
uint16_t tx_head;
|
||||
uint16_t tx_tail;
|
||||
gmacd_callback_t *tx_callbacks;
|
||||
|
||||
gmacd_wakeup_cb_t tx_wakeup_callback;
|
||||
uint16_t tx_wakeup_threshold;
|
||||
};
|
||||
|
||||
/**
|
||||
* GMAC driver struct.
|
||||
*/
|
||||
struct _gmacd {
|
||||
Gmac* gmac; /**< GMAC instance */
|
||||
struct _gmacd_queue queues[GMAC_NUM_QUEUES];
|
||||
};
|
||||
|
||||
/** @}*/
|
||||
|
||||
/** \addtogroup gmacd_functions
|
||||
@{*/
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* GMAC Exported functions
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
extern void gmacd_configure(struct _gmacd* gmacd, Gmac *pHw, uint8_t enableCAF, uint8_t enableNBC);
|
||||
|
||||
extern uint8_t gmacd_setup_queue(struct _gmacd* gmacd, uint8_t queue,
|
||||
uint16_t rx_size, uint8_t* rx_buffer, struct _gmac_desc* rx_desc,
|
||||
uint16_t tx_size, uint8_t* tx_buffer, struct _gmac_desc* tx_desc,
|
||||
gmacd_callback_t *tx_callbacks);
|
||||
|
||||
extern void gmacd_start(struct _gmacd* gmacd);
|
||||
|
||||
extern void gmacd_reset(struct _gmacd* gmacd);
|
||||
|
||||
extern uint8_t gmacd_send_sg(struct _gmacd* gmacd, uint8_t queue,
|
||||
const struct _gmac_sg_list* sgl, gmacd_callback_t callback);
|
||||
|
||||
extern uint8_t gmacd_send(struct _gmacd* gmacd, uint8_t queue, void *buffer,
|
||||
uint32_t size, gmacd_callback_t callback);
|
||||
|
||||
extern uint32_t gmacd_get_tx_load(struct _gmacd* gmacd, uint8_t queue);
|
||||
|
||||
extern uint8_t gmacd_poll(struct _gmacd* gmacd, uint8_t queue,
|
||||
uint8_t* buffer, uint32_t buffer_size, uint32_t* recv_size);
|
||||
|
||||
extern void gmacd_set_rx_callback(struct _gmacd *gmacd, uint8_t queue,
|
||||
gmacd_callback_t callback);
|
||||
|
||||
extern uint8_t gmacd_set_tx_wakeup_callback(struct _gmacd *gmacd,
|
||||
uint8_t queue, gmacd_wakeup_cb_t wakeup_callback,
|
||||
uint16_t threshold);
|
||||
|
||||
/** @}*/
|
||||
|
||||
#endif /* _GMACD_H_ */
|
|
@ -0,0 +1,250 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implementation of HSMC functions.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
#include "peripherals/pmc.h"
|
||||
#include "peripherals/hsmc.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static uint32_t _nfc_read_cmd(uint32_t cmd)
|
||||
{
|
||||
return *(volatile uint32_t*)(NFC_ADDR + cmd);
|
||||
}
|
||||
|
||||
static void _nfc_write_cmd(uint32_t cmd, uint32_t value)
|
||||
{
|
||||
*(volatile uint32_t*)(NFC_ADDR + cmd) = value;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Sets SMC timing for NAND FLASH.
|
||||
* \param cs chip select.
|
||||
* \param bus_width bus width 8/16.
|
||||
*/
|
||||
void hsmc_nand_configure(uint8_t cs, uint8_t bus_width)
|
||||
{
|
||||
pmc_enable_peripheral(ID_HSMC);
|
||||
|
||||
HSMC->SMC_CS_NUMBER[cs].HSMC_SETUP =
|
||||
HSMC_SETUP_NWE_SETUP(2) |
|
||||
HSMC_SETUP_NCS_WR_SETUP(2) |
|
||||
HSMC_SETUP_NRD_SETUP(2) |
|
||||
HSMC_SETUP_NCS_RD_SETUP(2);
|
||||
|
||||
HSMC->SMC_CS_NUMBER[cs].HSMC_PULSE =
|
||||
HSMC_PULSE_NWE_PULSE(7) |
|
||||
HSMC_PULSE_NCS_WR_PULSE(7) |
|
||||
HSMC_PULSE_NRD_PULSE(7) |
|
||||
HSMC_PULSE_NCS_RD_PULSE(7);
|
||||
|
||||
HSMC->SMC_CS_NUMBER[cs].HSMC_CYCLE =
|
||||
HSMC_CYCLE_NWE_CYCLE(13) |
|
||||
HSMC_CYCLE_NRD_CYCLE(13);
|
||||
|
||||
HSMC->SMC_CS_NUMBER[cs].HSMC_TIMINGS =
|
||||
HSMC_TIMINGS_TCLR(3) |
|
||||
HSMC_TIMINGS_TADL(27) |
|
||||
HSMC_TIMINGS_TAR(3) |
|
||||
HSMC_TIMINGS_TRR(6) |
|
||||
HSMC_TIMINGS_TWB(5) |
|
||||
HSMC_TIMINGS_RBNSEL(3) |
|
||||
HSMC_TIMINGS_NFSEL;
|
||||
|
||||
HSMC->SMC_CS_NUMBER[cs].HSMC_MODE =
|
||||
HSMC_MODE_READ_MODE |
|
||||
HSMC_MODE_WRITE_MODE |
|
||||
((bus_width == 8 ) ? HSMC_MODE_DBW_BIT_8 : HSMC_MODE_DBW_BIT_16) |
|
||||
HSMC_MODE_TDF_CYCLES(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets SMC timing for NOR FLASH.
|
||||
* \param cs chip select.
|
||||
* \param bus_width bus width 8/16.
|
||||
*/
|
||||
void hsmc_nor_configure(uint8_t cs, uint8_t bus_width)
|
||||
{
|
||||
pmc_enable_peripheral(ID_HSMC);
|
||||
|
||||
HSMC->SMC_CS_NUMBER[cs].HSMC_SETUP =
|
||||
HSMC_SETUP_NWE_SETUP(1) |
|
||||
HSMC_SETUP_NCS_WR_SETUP(0) |
|
||||
HSMC_SETUP_NRD_SETUP(2) |
|
||||
HSMC_SETUP_NCS_RD_SETUP(0);
|
||||
|
||||
HSMC->SMC_CS_NUMBER[cs].HSMC_PULSE =
|
||||
HSMC_PULSE_NWE_PULSE(10) |
|
||||
HSMC_PULSE_NCS_WR_PULSE(10) |
|
||||
HSMC_PULSE_NRD_PULSE(11) |
|
||||
HSMC_PULSE_NCS_RD_PULSE(11);
|
||||
|
||||
HSMC->SMC_CS_NUMBER[cs].HSMC_CYCLE =
|
||||
HSMC_CYCLE_NWE_CYCLE(11) |
|
||||
HSMC_CYCLE_NRD_CYCLE(14);
|
||||
|
||||
HSMC->SMC_CS_NUMBER[cs].HSMC_TIMINGS = 0;
|
||||
|
||||
HSMC->SMC_CS_NUMBER[cs].HSMC_MODE =
|
||||
HSMC_MODE_READ_MODE |
|
||||
HSMC_MODE_WRITE_MODE |
|
||||
(bus_width == 8 ? HSMC_MODE_DBW_BIT_8 : HSMC_MODE_DBW_BIT_16) |
|
||||
HSMC_MODE_EXNW_MODE_DISABLED |
|
||||
HSMC_MODE_TDF_CYCLES(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reset NFC controller.
|
||||
*/
|
||||
void hsmc_nfc_reset(void)
|
||||
{
|
||||
/* Disable all the SMC NFC interrupts */
|
||||
HSMC->HSMC_IDR = 0xFFFFFFFF;
|
||||
HSMC->HSMC_CTRL = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if spare area be read in read mode.
|
||||
*
|
||||
* \return Returns true if NFC controller reads both main and spare area in
|
||||
* read mode, otherwise returns false.
|
||||
*/
|
||||
bool hsmc_nfc_is_spare_read_enabled(void)
|
||||
{
|
||||
return (((HSMC->HSMC_CFG) >> 9) & 0x1) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if spare area be written in write mode.
|
||||
*
|
||||
* \return Returns true if NFC controller writes both main and spare area in
|
||||
* write mode, otherwise returns false.
|
||||
*/
|
||||
bool hsmc_nfc_is_spare_write_enabled(void)
|
||||
{
|
||||
return (((HSMC->HSMC_CFG) >> 8) & 0x1) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if NFC Controller is busy.
|
||||
*
|
||||
* \return Returns 1 if NFC Controller is activated and accesses the memory device,
|
||||
* otherwise returns 0.
|
||||
*/
|
||||
bool hsmc_nfc_is_nfc_busy(void)
|
||||
{
|
||||
return ((HSMC->HSMC_SR & HSMC_SR_NFCBUSY) == HSMC_SR_NFCBUSY);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if the host controller is busy.
|
||||
* \return Returns 1 if the host controller is busy, otherwise returns 0.
|
||||
*/
|
||||
static bool smc_nfc_is_host_busy(void)
|
||||
{
|
||||
return (_nfc_read_cmd(NFCADDR_CMD_NFCCMD) & 0x8000000) == 0x8000000;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Wait for Ready-busy pin falling and then rising.
|
||||
*/
|
||||
void hsmc_wait_rb(void)
|
||||
{
|
||||
/* Wait for RB pin falling */
|
||||
while ((HSMC->HSMC_SR & HSMC_SR_RB_FALL) != HSMC_SR_RB_FALL);
|
||||
|
||||
/* Wait for RB pin rising */
|
||||
while ((HSMC->HSMC_SR & HSMC_SR_RB_RISE) != HSMC_SR_RB_RISE);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Wait for NFC command has done.
|
||||
*/
|
||||
void hsmc_nfc_wait_cmd_done(void)
|
||||
{
|
||||
while ((HSMC->HSMC_SR & HSMC_SR_CMDDONE) != HSMC_SR_CMDDONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Wait for NFC Data Transfer Terminated.
|
||||
*/
|
||||
void hsmc_nfc_wait_xfr_done(void)
|
||||
{
|
||||
while ((HSMC->HSMC_SR & HSMC_SR_XFRDONE) != HSMC_SR_XFRDONE);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Wait for NFC Ready/Busy Line 3 Edge Detected.
|
||||
*/
|
||||
void hsmc_nfc_wait_rb_busy(void)
|
||||
{
|
||||
while ((HSMC->HSMC_SR & HSMC_SR_RB_EDGE0) != HSMC_SR_RB_EDGE0);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Wait for PMECC ready.
|
||||
*/
|
||||
void hsmc_pmecc_wait_ready(void)
|
||||
{
|
||||
while((HSMC->HSMC_PMECCSR) & HSMC_PMECCSR_BUSY);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Uses the HOST NANDFLASH controller to send a command to the NFC.
|
||||
* \param cmd command to send.
|
||||
* \param address_cycle address cycle when command access id decoded.
|
||||
* \param cycle0 address at first cycle.
|
||||
*/
|
||||
void hsmc_nfc_send_cmd(uint32_t cmd, uint32_t address_cycle, uint32_t cycle0)
|
||||
{
|
||||
/* Wait until host controller is not busy. */
|
||||
while (smc_nfc_is_host_busy());
|
||||
|
||||
/* Send the command plus the ADDR_CYCLE */
|
||||
HSMC->HSMC_ADDR = cycle0;
|
||||
_nfc_write_cmd(cmd, address_cycle);
|
||||
hsmc_nfc_wait_cmd_done();
|
||||
}
|
|
@ -0,0 +1,139 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Definitions and function prototype for smc module
|
||||
*/
|
||||
|
||||
#ifndef _HSMC_
|
||||
#define _HSMC_
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Macros
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#define hsmc_nfc_configure(mode) {HSMC->HSMC_CFG = mode ;}
|
||||
#define hsmc_nfc_enable() {HSMC->HSMC_CTRL |= HSMC_CTRL_NFCEN;}
|
||||
#define hsmc_nfc_disable() {HSMC->HSMC_CTRL |= HSMC_CTRL_NFCDIS;}
|
||||
#define hsmc_nfc_get_status() {HSMC->HSMC_SR;}
|
||||
|
||||
#define hsmc_nfc_enable_spare_read() {HSMC->HSMC_CFG |= HSMC_CFG_RSPARE;}
|
||||
#define hsmc_nfc_disable_spare_read() {HSMC->HSMC_CFG &= (~HSMC_CFG_RSPARE);}
|
||||
#define hsmc_nfc_enable_spare_write() {HSMC->HSMC_CFG |= HSMC_CFG_WSPARE;}
|
||||
#define hsmc_nfc_disable_spare_write() {HSMC->HSMC_CFG &= (~HSMC_CFG_WSPARE);}
|
||||
|
||||
#define hsmc_pmecc_reset() {HSMC->HSMC_PMECCTRL = HSMC_PMECCTRL_RST; }
|
||||
#define hsmc_pmecc_or_reset() {HSMC->HSMC_PMECCTRL |= HSMC_PMECCTRL_RST; }
|
||||
#define hsmc_pmecc_data_phase() {HSMC->HSMC_PMECCTRL |= HSMC_PMECCTRL_DATA; }
|
||||
#define hsmc_pmecc_enable_write() {HSMC->HSMC_PMECCFG |= HSMC_PMECCFG_NANDWR;}
|
||||
#define hsmc_pmecc_enable_read() {HSMC->HSMC_PMECCFG &= (~HSMC_PMECCFG_NANDWR);}
|
||||
|
||||
#define hsmc_pmecc_error_status() (HSMC->HSMC_PMECCISR )
|
||||
#define hsmc_pmecc_enable() {HSMC->HSMC_PMECCTRL = HSMC_PMECCTRL_ENABLE;}
|
||||
#define hsmc_pmecc_disable() {HSMC->HSMC_PMECCTRL = HSMC_PMECCTRL_DISABLE;}
|
||||
#define hsmc_pmecc_auto_enable() {HSMC->HSMC_PMECCFG |= HSMC_PMECCFG_AUTO;}
|
||||
#define hsmc_pmecc_auto_disable() {HSMC->HSMC_PMECCFG &= (~HSMC_PMECCFG_AUTO);}
|
||||
#define hsmc_pmecc_auto_apare_en() ((HSMC->HSMC_PMECCFG & HSMC_PMECCFG_SPAREEN) == HSMC_PMECCFG_SPAREEN)
|
||||
#define hsmc_pmecc(i) (HSMC->SMC_PMECC[i])
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Definitions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#define HSMC_SR_RB_EDGE0 (0x1u << 24)
|
||||
|
||||
/* -------- NFCADDR_CMD : NFC Address Command -------- */
|
||||
|
||||
#define NFCADDR_CMD_CMD1 (0xFFu << 2) /* Command Register Value for Cycle 1 */
|
||||
#define NFCADDR_CMD_CMD2 (0xFFu << 10) /* Command Register Value for Cycle 2 */
|
||||
#define NFCADDR_CMD_VCMD2 (0x1u << 18) /* Valid Cycle 2 Command */
|
||||
#define NFCADDR_CMD_ACYCLE (0x7u << 19) /* Number of Address required for the current command */
|
||||
#define NFCADDR_CMD_ACYCLE_NONE (0x0u << 19) /* No address cycle */
|
||||
#define NFCADDR_CMD_ACYCLE_ONE (0x1u << 19) /* One address cycle */
|
||||
#define NFCADDR_CMD_ACYCLE_TWO (0x2u << 19) /* Two address cycles */
|
||||
#define NFCADDR_CMD_ACYCLE_THREE (0x3u << 19) /* Three address cycles */
|
||||
#define NFCADDR_CMD_ACYCLE_FOUR (0x4u << 19) /* Four address cycles */
|
||||
#define NFCADDR_CMD_ACYCLE_FIVE (0x5u << 19) /* Five address cycles */
|
||||
#define NFCADDR_CMD_CSID (0x7u << 22) /* Chip Select Identifier */
|
||||
#define NFCADDR_CMD_CSID_0 (0x0u << 22) /* CS0 */
|
||||
#define NFCADDR_CMD_CSID_1 (0x1u << 22) /* CS1 */
|
||||
#define NFCADDR_CMD_CSID_2 (0x2u << 22) /* CS2 */
|
||||
#define NFCADDR_CMD_CSID_3 (0x3u << 22) /* CS3 */
|
||||
#define NFCADDR_CMD_CSID_4 (0x4u << 22) /* CS4 */
|
||||
#define NFCADDR_CMD_CSID_5 (0x5u << 22) /* CS5 */
|
||||
#define NFCADDR_CMD_CSID_6 (0x6u << 22) /* CS6 */
|
||||
#define NFCADDR_CMD_CSID_7 (0x7u << 22) /* CS7 */
|
||||
#define NFCADDR_CMD_DATAEN (0x1u << 25) /* NFC Data Enable */
|
||||
#define NFCADDR_CMD_DATADIS (0x0u << 25) /* NFC Data disable */
|
||||
#define NFCADDR_CMD_NFCRD (0x0u << 26) /* NFC Read Enable */
|
||||
#define NFCADDR_CMD_NFCWR (0x1u << 26) /* NFC Write Enable */
|
||||
#define NFCADDR_CMD_NFCCMD (0x1u << 27) /* NFC Command Enable */
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
extern void hsmc_nand_configure(uint8_t cs, uint8_t bus_width);
|
||||
|
||||
extern void hsmc_nor_configure(uint8_t cs, uint8_t bus_width);
|
||||
|
||||
extern void hsmc_nfc_reset(void);
|
||||
|
||||
extern bool hsmc_nfc_is_spare_read_enabled(void);
|
||||
|
||||
extern bool hsmc_nfc_is_spare_write_enabled(void);
|
||||
|
||||
extern bool hsmc_nfc_is_nfc_busy(void);
|
||||
|
||||
extern void hsmc_wait_rb(void);
|
||||
|
||||
extern void hsmc_nfc_send_cmd(uint32_t cmd, uint32_t address_cycle, uint32_t cycle0);
|
||||
|
||||
extern void hsmc_nfc_wait_cmd_done(void);
|
||||
|
||||
extern void hsmc_nfc_wait_xfr_done(void);
|
||||
|
||||
extern void hsmc_nfc_wait_rb_busy(void);
|
||||
|
||||
extern void hsmc_nfc_wait_hamming_ready(void);
|
||||
|
||||
extern void hsmc_pmecc_wait_ready(void);
|
||||
|
||||
#endif /* _HSMC_ */
|
|
@ -0,0 +1,694 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2013, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/isc.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Export functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/*------------------------------------------
|
||||
* ISC Control functions
|
||||
*----------------------------------------*/
|
||||
/**
|
||||
* \brief Send Capture Input Stream Command to start a single shot capture or a
|
||||
* multiple frame.
|
||||
*/
|
||||
void isc_start_capture(void)
|
||||
{
|
||||
ISC->ISC_CTRLEN = ISC_CTRLEN_CAPTURE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief end the capture at the next Vertical Synchronization Detection.
|
||||
*/
|
||||
void isc_stop_capture(void)
|
||||
{
|
||||
ISC->ISC_CTRLDIS = ISC_CTRLDIS_DISABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns ISC Control Status.
|
||||
*/
|
||||
uint32_t isc_get_ctrl_status(void)
|
||||
{
|
||||
return (ISC->ISC_CTRLSR);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief update the color profile.
|
||||
*/
|
||||
void isc_update_profile(void)
|
||||
{
|
||||
ISC->ISC_CTRLEN = ISC_CTRLEN_UPPRO;
|
||||
while((ISC->ISC_CTRLSR & ISC_CTRLSR_UPPRO) == ISC_CTRLSR_UPPRO);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Perform software reset of the interface.
|
||||
*/
|
||||
void isc_software_reset(void)
|
||||
{
|
||||
ISC->ISC_CTRLDIS = ISC_CTRLDIS_SWRST;
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
* PFE(Parallel Front End) functions
|
||||
*----------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief configure PFE(Parallel Front End) video mode.
|
||||
* \param vmode: Parallel Front End Mode
|
||||
*/
|
||||
void isc_pfe_set_video_mode(uint32_t vmode)
|
||||
{
|
||||
ISC->ISC_PFE_CFG0 &= ~ISC_PFE_CFG0_MODE_Msk;
|
||||
ISC->ISC_PFE_CFG0 |= vmode;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief set PFE(Parallel Front End) H/V synchronization polarity.
|
||||
* \param hpol: Horizontal Synchronization Polarity
|
||||
* \param vpol: Vertical Synchronization Polarity
|
||||
*/
|
||||
void isc_pfe_set_sync_polarity(uint32_t hpol, uint32_t vpol)
|
||||
{
|
||||
ISC->ISC_PFE_CFG0 &= ~ISC_PFE_CFG0_HPOL;
|
||||
ISC->ISC_PFE_CFG0 &= ~ISC_PFE_CFG0_VPOL;
|
||||
ISC->ISC_PFE_CFG0 |= hpol | vpol;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief set PFE(Parallel Front End) pixel clock polarity.
|
||||
* \param ppol: pixel clock Polarity, The pixel stream is sampled on the
|
||||
* rising or falling edge of the pixel clock
|
||||
*/
|
||||
void isc_pfe_set_pixel_polarity(uint32_t ppol)
|
||||
{
|
||||
ISC->ISC_PFE_CFG0 &= ~ISC_PFE_CFG0_PPOL;
|
||||
ISC->ISC_PFE_CFG0 |= ppol ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief set PFE(Parallel Front End) field polarity.
|
||||
* \param fpol: Top/bottom field polarity configuration.
|
||||
*/
|
||||
void isc_pfe_set_field_polarity(uint32_t fpol)
|
||||
{
|
||||
ISC->ISC_PFE_CFG0 &= ~ISC_PFE_CFG0_FPOL;
|
||||
ISC->ISC_PFE_CFG0 |= fpol ;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief Enables/disable PFE(Parallel Front End) cropping
|
||||
* \param enCol: Column Cropping enable/disable(1/0)
|
||||
* \param enRow: Row Cropping enable/disable(1/0)
|
||||
*/
|
||||
void isc_pfe_set_cropping_enabled(uint8_t enCol, uint8_t enRow)
|
||||
{
|
||||
ISC->ISC_PFE_CFG0 &= ~ISC_PFE_CFG0_COLEN;
|
||||
ISC->ISC_PFE_CFG0 &= ~ISC_PFE_CFG0_ROWEN;
|
||||
if (enCol) ISC->ISC_PFE_CFG0 |=ISC_PFE_CFG0_COLEN;
|
||||
if (enRow) ISC->ISC_PFE_CFG0 |=ISC_PFE_CFG0_ROWEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief set PFE(Parallel Front End) Bits Per Sample.
|
||||
* \param bps: Bits Per Sample.
|
||||
*/
|
||||
void isc_pfe_set_bps(uint32_t bps)
|
||||
{
|
||||
ISC->ISC_PFE_CFG0 &= ~ISC_PFE_CFG0_BPS_Msk;
|
||||
ISC->ISC_PFE_CFG0 |= bps ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief set PFE(Parallel Front End)in single shot mode
|
||||
*/
|
||||
void isc_pfe_set_single_shot(void)
|
||||
{
|
||||
ISC->ISC_PFE_CFG0 &= ~ISC_PFE_CFG0_CONT;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief set PFE(Parallel Front End)in continuous mode
|
||||
*/
|
||||
void isc_pfe_set_continuous_shot(void)
|
||||
{
|
||||
ISC->ISC_PFE_CFG0 |= ISC_PFE_CFG0_CONT;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* \brief set PFE(Parallel Front End) gated clock.
|
||||
* \param en: enable/disable gated clock.
|
||||
*/
|
||||
void isc_pfe_set_gated_clock(uint8_t en)
|
||||
{
|
||||
ISC->ISC_PFE_CFG0 &= ~ISC_PFE_CFG0_GATED;
|
||||
if (en) ISC->ISC_PFE_CFG0 |= ISC_PFE_CFG0_GATED ;
|
||||
}
|
||||
/**
|
||||
* \brief configure PFE(Parallel Front End) cropping area.
|
||||
* \param Hstart: Horizontal starting position of the cropping area
|
||||
* \param Hend: Horizontal ending position of the cropping area
|
||||
* \param Vstart: Vertical starting position of the cropping area
|
||||
* \param Hend: Vertical ending position of the cropping area
|
||||
*/
|
||||
void isc_pfe_set_cropping_area(
|
||||
uint32_t Hstart, uint32_t Hend, uint32_t Vstart, uint32_t Vend)
|
||||
{
|
||||
ISC->ISC_PFE_CFG1 = ISC_PFE_CFG1_COLMIN(Hstart) | ISC_PFE_CFG1_COLMAX(Hend);
|
||||
ISC->ISC_PFE_CFG2 = ISC_PFE_CFG2_ROWMIN(Vstart) | ISC_PFE_CFG2_ROWMAX(Vend);
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
* Clock configuration functions
|
||||
*----------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Configure the ISP clock.
|
||||
* \param ispClockDiv ISP Clock Divider.
|
||||
* \param ispClockSelection ISP Clock Selection.
|
||||
0: HCLOCK is selected.
|
||||
1: GCK is selected.
|
||||
*/
|
||||
void isc_configure_isp_clock(uint32_t ispClockDiv, uint32_t ispClockSelection)
|
||||
{
|
||||
ISC->ISC_CLKCFG |= ISC_CLKCFG_ICDIV(ispClockDiv) | (ispClockSelection << 8);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enables the ISP clock.
|
||||
*/
|
||||
void isc_enable_isp_clock(void)
|
||||
{
|
||||
ISC->ISC_CLKEN = ISC_CLKEN_ICEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disables the ISP clock.
|
||||
*/
|
||||
void isc_disable_isp_clock(void)
|
||||
{
|
||||
ISC->ISC_CLKDIS = ISC_CLKDIS_ICDIS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Software reset the ISP clock.
|
||||
*/
|
||||
void isc_reset_isp_clock(void)
|
||||
{
|
||||
ISC->ISC_CLKDIS = ISC_CLKDIS_ICSWRST;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure the Master clock.
|
||||
* \param masterClockDiv Master Clock Divider.
|
||||
* \param masterClockSelection Master Clock Selection.
|
||||
0: HCLOCK is selected.
|
||||
1: GCK is selected.
|
||||
2: 480-MHz system clock is selected.
|
||||
*/
|
||||
void isc_configure_master_clock(uint32_t masterClockDiv, uint32_t masterClockSelection)
|
||||
{
|
||||
ISC->ISC_CLKCFG |= ISC_CLKCFG_MCDIV(masterClockDiv)
|
||||
| ISC_CLKCFG_MCSEL(masterClockSelection);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enables the master clock.
|
||||
*/
|
||||
void isc_enable_master_clock(void)
|
||||
{
|
||||
ISC->ISC_CLKEN = ISC_CLKEN_MCEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disables the master clock.
|
||||
*/
|
||||
void isc_disable_master_clock(void)
|
||||
{
|
||||
ISC->ISC_CLKDIS = ISC_CLKDIS_MCDIS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Software reset the master clock.
|
||||
*/
|
||||
void isc_reset_master_clock(void)
|
||||
{
|
||||
ISC->ISC_CLKDIS = ISC_CLKDIS_MCSWRST;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns ISC clock Status.
|
||||
*/
|
||||
uint32_t isc_get_clock_status(void)
|
||||
{
|
||||
return (ISC->ISC_CLKSR);
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
* Interrupt functions
|
||||
*----------------------------------------*/
|
||||
/**
|
||||
* \brief Enable ISC interrupt
|
||||
* \param flag of interrupt to enable
|
||||
*/
|
||||
void isc_enable_interrupt(uint32_t flag)
|
||||
{
|
||||
ISC->ISC_INTEN = flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable ISC interrupt
|
||||
* \param flag of interrupt to disable
|
||||
*/
|
||||
void isc_disable_interrupt(uint32_t flag)
|
||||
{
|
||||
ISC->ISC_INTDIS = flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return ISC status register
|
||||
* \return Status of ISC register
|
||||
*/
|
||||
uint32_t isc_interrupt_status(void)
|
||||
{
|
||||
return(ISC->ISC_INTSR);
|
||||
}
|
||||
|
||||
|
||||
/*------------------------------------------
|
||||
* White Balance functions
|
||||
*----------------------------------------*/
|
||||
/**
|
||||
* \brief Enables/disable White Balance.
|
||||
*/
|
||||
void isc_wb_enabled(uint8_t enabled)
|
||||
{
|
||||
if (enabled)
|
||||
ISC->ISC_WB_CTRL = ISC_WB_CTRL_ENABLE;
|
||||
else
|
||||
ISC->ISC_WB_CTRL = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief White Balance Bayer Configuration (Pixel Color Pattern).
|
||||
*/
|
||||
void isc_wb_set_bayer_pattern(uint8_t pattern)
|
||||
{
|
||||
ISC->ISC_WB_CFG = pattern;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief adjust White Balance with color component.
|
||||
* \param rOffset Offset Red Component (signed 13 bits 1:12:0)
|
||||
* \param grOffset Offset Green Component for Red Row (signed 13 bits 1:12:0)
|
||||
* \param bOffset Offset Blue Component (signed 13 bits, 1:12:0)
|
||||
* \param gbOffset Offset Green Component for Blue Row (signed 13 bits, 1:12:0)
|
||||
* \param rGain Red Component Gain (unsigned 13 bits, 0:4:9)
|
||||
* \param grGain Green Component (Red row) Gain (unsigned 13 bits, 0:4:9)
|
||||
* \param bGain Blue Component Gain (unsigned 13 bits, 0:4:9)
|
||||
* \param gbGain Green Component (Blue row) Gain (unsigned 13 bits, 0:4:9)
|
||||
*/
|
||||
void isc_wb_adjust_bayer_color(uint32_t rOffset, uint32_t grOffset,
|
||||
uint32_t bOffset, uint32_t gbOffset,
|
||||
uint32_t rGain, uint32_t grGain,
|
||||
uint32_t bGain, uint32_t gbGain)
|
||||
{
|
||||
ISC->ISC_WB_O_RGR =
|
||||
ISC_WB_O_RGR_ROFST(rOffset) | ISC_WB_O_RGR_GROFST(grOffset);
|
||||
ISC->ISC_WB_O_BGB =
|
||||
ISC_WB_O_BGB_BOFST(bOffset) | ISC_WB_O_BGB_GBOFST(gbOffset);
|
||||
ISC->ISC_WB_G_RGR =
|
||||
ISC_WB_G_RGR_RGAIN(rGain) | ISC_WB_G_RGR_GRGAIN(grGain);
|
||||
ISC->ISC_WB_G_BGB =
|
||||
ISC_WB_G_BGB_BGAIN(bGain) | ISC_WB_G_BGB_GBGAIN(gbGain);
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
* Color Filter Array functions
|
||||
*----------------------------------------*/
|
||||
/**
|
||||
* \brief Enables/disable Color Filter Array Interpolation.
|
||||
*/
|
||||
void isc_cfa_enabled(uint8_t enabled)
|
||||
{
|
||||
if (enabled)
|
||||
ISC->ISC_CFA_CTRL = ISC_CFA_CTRL_ENABLE;
|
||||
else
|
||||
ISC->ISC_CFA_CTRL = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief configure color filter array interpolation.
|
||||
* \param pattern Color Filter Array Pattern
|
||||
* \param edge Edge Interpolation
|
||||
0: Edges are not interpolated.
|
||||
1: Edge interpolation is performed.
|
||||
*/
|
||||
void isc_cfa_configure(uint8_t pattern, uint8_t edge)
|
||||
{
|
||||
ISC->ISC_CFA_CFG = pattern | (edge << 4);
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
* Color Correction functions
|
||||
*----------------------------------------*/
|
||||
/**
|
||||
* \brief Enables/disable Color Correction.
|
||||
*/
|
||||
void isc_cc_enabled(uint8_t enabled)
|
||||
{
|
||||
if (enabled)
|
||||
ISC->ISC_CC_CTRL = ISC_CC_CTRL_ENABLE;
|
||||
else
|
||||
ISC->ISC_CFA_CTRL = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Color correction with color component.
|
||||
* \param cc Pointer to structure _color_correct
|
||||
*/
|
||||
void isc_cc_configure(struct _color_correct* cc)
|
||||
{
|
||||
ISC->ISC_CC_RR_RG =
|
||||
ISC_CC_RR_RG_RRGAIN(cc->rrGain) | ISC_CC_RR_RG_RGGAIN(cc->rgGain);
|
||||
ISC->ISC_CC_RB_OR =
|
||||
ISC_CC_RB_OR_RBGAIN(cc->rbGain) | ISC_CC_RB_OR_ROFST(cc->rOffset);
|
||||
ISC->ISC_CC_GR_GG =
|
||||
ISC_CC_GR_GG_GRGAIN(cc->grGain) | ISC_CC_GR_GG_GGGAIN(cc->ggGain);
|
||||
ISC->ISC_CC_GB_OG =
|
||||
ISC_CC_GB_OG_GBGAIN(cc->gbGain) | ISC_CC_GB_OG_ROFST(cc->gOffset);
|
||||
ISC->ISC_CC_BR_BG =
|
||||
ISC_CC_BR_BG_BRGAIN(cc->brGain) | ISC_CC_BR_BG_BGGAIN(cc->bgGain);
|
||||
ISC->ISC_CC_BB_OB =
|
||||
ISC_CC_BB_OB_BBGAIN(cc->bbGain) | ISC_CC_BB_OB_BOFST(cc->bOffset);
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
* Gamma Correction functions
|
||||
*----------------------------------------*/
|
||||
/**
|
||||
* \brief Enables/disable Gamma Correction with giving channels.
|
||||
* \param enabled 1: enable, 0: disable
|
||||
* \param channels ISC_GAM_CTRL_BENABLE/ISC_GAM_CTRL_GENABLE/ISC_GAM_CTRL_RENABLE
|
||||
*/
|
||||
void isc_gamma_enabled(uint8_t enabled, uint8_t channels)
|
||||
{
|
||||
if (enabled)
|
||||
ISC->ISC_GAM_CTRL |= ISC_GAM_CTRL_ENABLE | channels;
|
||||
else
|
||||
ISC->ISC_GAM_CTRL = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure gamma correction with give table.
|
||||
* \param rGamConstant Pointer to red Color Constant instance (64 half-word).
|
||||
* \param rGamSlope Pointer to red Color Slope instance (64 half-word).
|
||||
* \param gGamConstant Pointer to green Color Constant instance (64 half-word).
|
||||
* \param gGamSlope Pointer to green Color Slope instance (64 half-word).
|
||||
* \param bGamConstant Pointer to blue Color Constant instance (64 half-word).
|
||||
* \param bGamSlope Pointer to blue Color Slope instance (64 half-word).
|
||||
*/
|
||||
void isc_gamma_configure(uint16_t* rGamConstant, uint16_t* rGamSlope,
|
||||
uint16_t* gGamConstant, uint16_t* gGamSlope,
|
||||
uint16_t* bGamConstant, uint16_t* bGamSlope)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < 64 ; i++) {
|
||||
ISC->ISC_GAM_BENTRY[i] =
|
||||
ISC_GAM_BENTRY_BCONSTANT(bGamConstant[i])
|
||||
| ISC_GAM_BENTRY_BSLOPE(bGamSlope[i]);
|
||||
ISC->ISC_GAM_GENTRY[i] =
|
||||
ISC_GAM_GENTRY_GCONSTANT(bGamConstant[i])
|
||||
| ISC_GAM_GENTRY_GSLOPE(bGamSlope[i]);
|
||||
ISC->ISC_GAM_RENTRY[i] =
|
||||
ISC_GAM_RENTRY_RCONSTANT(bGamConstant[i])
|
||||
| ISC_GAM_RENTRY_RSLOPE(bGamSlope[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
* Color Space Conversion functions
|
||||
*----------------------------------------*/
|
||||
/**
|
||||
* \brief Enables/disable Color Space Conversion.
|
||||
*/
|
||||
void isc_csc_enabled(uint8_t enabled)
|
||||
{
|
||||
if (enabled)
|
||||
ISC->ISC_CSC_CTRL = ISC_CSC_CTRL_ENABLE;
|
||||
else
|
||||
ISC->ISC_CSC_CTRL = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Color space convert with color space component.
|
||||
* \param cs Pointer to structure _color_space
|
||||
*/
|
||||
void isc_csc_configure(struct _color_space* cs)
|
||||
{
|
||||
ISC->ISC_CSC_YR_YG = ISC_CSC_YR_YG_YRGAIN(cs->YrGain)
|
||||
| ISC_CSC_YR_YG_YGGAIN(cs->YgGain);
|
||||
ISC->ISC_CSC_YB_OY = ISC_CSC_YB_OY_YBGAIN(cs->YbGain)
|
||||
| ISC_CSC_YB_OY_YOFST(cs->Yoffset);
|
||||
ISC->ISC_CSC_CBR_CBG = ISC_CSC_CBR_CBG_CBRGAIN(cs->cbrGain)
|
||||
| ISC_CSC_CBR_CBG_CBGGAIN(cs->cbgGain);
|
||||
ISC->ISC_CSC_CBB_OCB = ISC_CSC_CBB_OCB_CBBGAIN(cs->cbbGain)
|
||||
| ISC_CSC_CBB_OCB_CBOFST(cs->cbOffset);
|
||||
ISC->ISC_CSC_CRR_CRG = ISC_CSC_CRR_CRG_CRRGAIN(cs->crrGain)
|
||||
| ISC_CSC_CRR_CRG_CRGGAIN(cs->crgGain);
|
||||
ISC->ISC_CSC_CRB_OCR = ISC_CSC_CRB_OCR_CRBGAIN(cs->crbGain)
|
||||
| ISC_CSC_CRB_OCR_CROFST(cs->crOffset);
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
* Contrast And Brightness functions
|
||||
*----------------------------------------*/
|
||||
/**
|
||||
* \brief Enables/disable contrast and brightness control.
|
||||
*/
|
||||
void isc_cbc_enabled(uint8_t enabled)
|
||||
{
|
||||
if (enabled)
|
||||
ISC->ISC_CBC_CTRL = ISC_CBC_CTRL_ENABLE;
|
||||
else
|
||||
ISC->ISC_CBC_CTRL = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure Contrast and brightness with give parameter.
|
||||
* \param ccir656 CCIR656 Stream Enable.
|
||||
0: Raw mode
|
||||
1: CCIR mode
|
||||
* \param byteOrder CCIR656 Byte Ordering.
|
||||
* \param brightness Brightness Control (signed 11 bits 1:10:0).
|
||||
* \param Contrast Contrast (signed 12 bits 1:3:8).
|
||||
*/
|
||||
void isc_cbc_configure(uint8_t ccir656, uint8_t byteOrder,
|
||||
uint16_t brightness, uint16_t contrast)
|
||||
{
|
||||
if (ccir656)
|
||||
ISC->ISC_CBC_CFG = ISC_CBC_CFG_CCIR | byteOrder ;
|
||||
else
|
||||
ISC->ISC_CBC_CFG = 0;
|
||||
ISC->ISC_CBC_BRIGHT = ISC_CBC_BRIGHT_BRIGHT(brightness);
|
||||
ISC->ISC_CBC_CONTRAST = ISC_CBC_CONTRAST_CONTRAST(contrast);
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
* Sub-sampling functions
|
||||
*----------------------------------------*/
|
||||
/**
|
||||
* \brief Enables/disable 4:4:4 to 4:2:2 Chrominance Horizontal Subsampling Filter Enable.
|
||||
*/
|
||||
void isc_sub422_enabled(uint8_t enabled)
|
||||
{
|
||||
if (enabled)
|
||||
ISC->ISC_SUB422_CTRL = ISC_SUB422_CTRL_ENABLE;
|
||||
else
|
||||
ISC->ISC_SUB422_CTRL = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure Subsampling 4:4:4 to 4:2:2 with giving value.
|
||||
* \param ccir656 CCIR656 Stream Enable.
|
||||
0: Raw mode
|
||||
1: CCIR mode
|
||||
* \param byteOrder CCIR656 Byte Ordering.
|
||||
* \param lpf Low Pass Filter Selection.
|
||||
*/
|
||||
void isc_sub422_configure(uint8_t ccir656, uint8_t byteOrder, uint8_t lpf)
|
||||
{
|
||||
if (ccir656)
|
||||
ISC->ISC_SUB422_CFG = ISC_SUB422_CFG_CCIR | byteOrder ;
|
||||
else
|
||||
ISC->ISC_SUB422_CFG = 0;
|
||||
ISC->ISC_SUB422_CFG |= lpf;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure 4:2:2 to 4:2:0 Vertical Subsampling Filter Enable
|
||||
(Center Aligned) with giving value.
|
||||
* \param enabled Subsampler enabled.
|
||||
0: disabled
|
||||
1: enabled
|
||||
* \param filter Interlaced or Progressive Chrominance Filter.
|
||||
0: Progressive filter {0.5, 0.5}
|
||||
1: Field-dependent filter, top field filter is {0.75, 0.25},
|
||||
bottom field filter is {0.25, 0.75}
|
||||
*/
|
||||
void isc_sub420_configure(uint8_t enabled, uint8_t filter)
|
||||
{
|
||||
if (enabled){
|
||||
ISC->ISC_SUB420_CTRL = ISC_SUB420_CTRL_ENABLE;
|
||||
if (filter){
|
||||
ISC->ISC_SUB420_CTRL |= ISC_SUB420_CTRL_FILTER;
|
||||
}
|
||||
} else {
|
||||
ISC->ISC_SUB420_CTRL = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
* Rounding, Limiting and Packing functions
|
||||
*----------------------------------------*/
|
||||
/**
|
||||
* \brief Configure Rounding, Limiting and Packing Mode.
|
||||
* \param rlpMode Rounding, Limiting and Packing Mode.
|
||||
* \param alpha Alpha Value for Alpha-enabled RGB Mode.
|
||||
*/
|
||||
void isc_rlp_configure(uint8_t rlpMode, uint8_t alpha)
|
||||
{
|
||||
ISC->ISC_RLP_CFG = rlpMode;
|
||||
if (alpha)
|
||||
ISC->ISC_RLP_CFG |= ISC_RLP_CFG_ALPHA(alpha);
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
* Histogram functions
|
||||
*----------------------------------------*/
|
||||
/**
|
||||
* \brief Enables/disable Histogram
|
||||
*/
|
||||
void isc_histogram_enabled(uint8_t enabled)
|
||||
{
|
||||
if (enabled)
|
||||
ISC->ISC_HIS_CTRL = ISC_HIS_CTRL_ENABLE;
|
||||
else
|
||||
ISC->ISC_HIS_CTRL = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure Histogram.
|
||||
* \param mode Histogram Operating Mode.
|
||||
* \param baySel Bayer Color Component Selection.
|
||||
* \param reset Histogram Reset After Read
|
||||
0: Reset after read mode is disabled
|
||||
1: Reset after read mode is enabled.
|
||||
*/
|
||||
void isc_histogram_configure(uint8_t mode, uint8_t baySel, uint8_t reset)
|
||||
{
|
||||
ISC->ISC_HIS_CFG = mode | baySel;
|
||||
if (reset)
|
||||
ISC->ISC_HIS_CFG |= ISC_HIS_CFG_RAR;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief update the histogram table.
|
||||
*/
|
||||
void isc_update_histogram_table(void)
|
||||
{
|
||||
while((ISC->ISC_CTRLSR & ISC_CTRLSR_HISREQ) == ISC_CTRLSR_HISREQ);
|
||||
ISC->ISC_CTRLEN = ISC_CTRLEN_HISREQ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief clear the histogram table.
|
||||
*/
|
||||
void isc_clear_histogram_table(void)
|
||||
{
|
||||
ISC->ISC_CTRLEN = ISC_CTRLEN_HISCLR;
|
||||
}
|
||||
|
||||
/*------------------------------------------
|
||||
* DMA functions
|
||||
*----------------------------------------*/
|
||||
/**
|
||||
* \brief Configure ISC DMA input mode.
|
||||
* \param mode Operating Mode.
|
||||
*/
|
||||
void isc_dma_configure_input_mode(uint32_t mode)
|
||||
{
|
||||
ISC->ISC_DCFG = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure ISC DMA with giving entry.
|
||||
* \param descEntry entry of DMA descriptor VIEW.
|
||||
*/
|
||||
void isc_dma_configure_desc_entry(uint32_t desc_entry)
|
||||
{
|
||||
ISC->ISC_DNDA = desc_entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable ISC DMA with giving view.
|
||||
* \param ctrl setting for DMA descriptor VIEW.
|
||||
*/
|
||||
void isc_dma_enable(uint32_t ctrl)
|
||||
{
|
||||
ISC->ISC_DCTRL = ctrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure ISC DMA start address.
|
||||
* \param channel channel number.
|
||||
* \param address address for giving channel.
|
||||
* \param stride stride for giving channel.
|
||||
*/
|
||||
void isc_dma_adderss(uint8_t channel, uint32_t address, uint32_t stride)
|
||||
{
|
||||
ISC->ISC_SUB0[channel].ISC_DAD = address;
|
||||
ISC->ISC_SUB0[channel].ISC_DST = stride;
|
||||
}
|
|
@ -0,0 +1,281 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2013, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file */
|
||||
|
||||
/** \addtogroup isc_module
|
||||
* @{
|
||||
* \section isc_usage Usage
|
||||
* - isc_start_capture: Send Capture Input Stream Command to start a single
|
||||
* shot capture or a multiple frame
|
||||
*/
|
||||
/**@}*/
|
||||
|
||||
#ifndef ISC_H
|
||||
#define ISC_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Type
|
||||
*----------------------------------------------------------------------------*/
|
||||
/** color correction components structure */
|
||||
struct _color_correct {
|
||||
/** Red Component Offset (signed 13 bits, 1:12:0) */
|
||||
uint16_t rOffset;
|
||||
/** Green Component Offset (signed 13 bits, 1:12:0)*/
|
||||
uint16_t gOffset;
|
||||
/** Green Component Offset (signed 13 bits, 1:12:0)*/
|
||||
uint16_t bOffset;
|
||||
/** Red Gain for Red Component (signed 12 bits, 1:3:8)*/
|
||||
uint16_t rrGain;
|
||||
/** Green Component (Red row) Gain (unsigned 13 bits, 0:4:9)*/
|
||||
uint16_t rgGain;
|
||||
/** Blue Gain for Red Component (signed 12 bits, 1:3:8)*/
|
||||
uint16_t rbGain;
|
||||
/** Green Gain for Green Component (signed 12 bits, 1:3:8)*/
|
||||
uint16_t ggGain;
|
||||
/** Red Gain for Green Component (signed 12 bits, 1:3:8)*/
|
||||
uint16_t grGain;
|
||||
/** Blue Gain for Green Component (signed 12 bits, 1:3:8)*/
|
||||
uint16_t gbGain;
|
||||
/** Green Gain for Blue Component (signed 12 bits, 1:3:8) */
|
||||
uint16_t bgGain;
|
||||
/** Red Gain for Blue Component (signed 12 bits, 1:3:8) */
|
||||
uint16_t brGain;
|
||||
/** Blue Gain for Blue Component (signed 12 bits, 1:3:8)*/
|
||||
uint16_t bbGain;
|
||||
};
|
||||
|
||||
/** color space convertion components structure */
|
||||
struct _color_space {
|
||||
/** Red Gain for Luminance (signed 12 bits 1:3:8) */
|
||||
uint16_t YrGain;
|
||||
/** Green Gain for Luminance (signed 12 bits 1:3:8)*/
|
||||
uint16_t YgGain;
|
||||
/** Blue Gain for Luminance Component (12 bits signed 1:3:8)*/
|
||||
uint16_t YbGain;
|
||||
/** Luminance Offset (11 bits signed 1:10:0)*/
|
||||
uint16_t Yoffset;
|
||||
/** Green Gain for Blue Chrominance (signed 12 bits 1:3:8)*/
|
||||
uint16_t cbrGain;
|
||||
/** Red Gain for Blue Chrominance (signed 12 bits, 1:3:8)*/
|
||||
uint16_t cbgGain;
|
||||
/** Blue Gain for Blue Chrominance (signed 12 bits 1:3:8)*/
|
||||
uint16_t cbbGain;
|
||||
/** Blue Chrominance Offset (signed 11 bits 1:10:0)*/
|
||||
uint16_t cbOffset;
|
||||
/** Red Gain for Red Chrominance (signed 12 bits 1:3:8)*/
|
||||
uint16_t crrGain;
|
||||
/** Green Gain for Red Chrominance (signed 12 bits 1:3:8)*/
|
||||
uint16_t crgGain;
|
||||
/** Blue Gain for Red Chrominance (signed 12 bits 1:3:8)*/
|
||||
uint16_t crbGain;
|
||||
/** Red Chrominance Offset (signed 11 bits 1:10:0)*/
|
||||
uint16_t crOffset;
|
||||
};
|
||||
|
||||
/** \brief Structure for ISC DMA descriptor view0 that can be
|
||||
* performed when the pixel or data stream is packed.*/
|
||||
struct _isc_dma_view0
|
||||
{
|
||||
/** ISC DMA Control. */
|
||||
uint32_t ctrl;
|
||||
/** Next ISC DMA Descriptor Address number. */
|
||||
uint32_t next_desc;
|
||||
/** Transfer Address. */
|
||||
uint32_t addr;
|
||||
/** stride . */
|
||||
uint32_t stride;
|
||||
};
|
||||
|
||||
/** \brief Structure for ISC DMA descriptor view1 that can be
|
||||
* performed for YCbCr semi-planar pixel stream.*/
|
||||
struct _isc_dma_view1
|
||||
{
|
||||
/** ISC DMA Control. */
|
||||
uint32_t ctrl;
|
||||
/** Next ISC DMA Descriptor Address number. */
|
||||
uint32_t next_desc;
|
||||
/** Transfer Address 0. */
|
||||
uint32_t addr0;
|
||||
/** stride 0 . */
|
||||
uint32_t stride0;
|
||||
/** Transfer Address 1. */
|
||||
uint32_t addr1;
|
||||
/** stride 1 . */
|
||||
uint32_t stride1;
|
||||
|
||||
};
|
||||
|
||||
/** \brief Structure for ISC DMA descriptor view2 that can be
|
||||
* performed for used for YCbCr planar pixel stream.*/
|
||||
struct _isc_dma_view2
|
||||
{
|
||||
/** ISC DMA Control. */
|
||||
uint32_t ctrl;
|
||||
/** Next ISC DMA Descriptor Address number. */
|
||||
uint32_t next_desc;
|
||||
/** Transfer Address 0. */
|
||||
uint32_t addr0;
|
||||
/** stride 0. */
|
||||
uint32_t stride0;
|
||||
/** Transfer Address 1. */
|
||||
uint32_t addr1;
|
||||
/** stride 1 . */
|
||||
uint32_t stride1;
|
||||
/** Transfer Address 2. */
|
||||
uint32_t addr2;
|
||||
/** stride 2. */
|
||||
uint32_t stride2;
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
/*------------------------------------------
|
||||
* ISC Control functions
|
||||
*----------------------------------------*/
|
||||
extern void isc_start_capture(void);
|
||||
extern void isc_stop_capture(void);
|
||||
extern uint32_t isc_get_ctrl_status(void);
|
||||
extern void isc_update_profile(void);
|
||||
extern void isc_software_reset(void);
|
||||
|
||||
/*------------------------------------------
|
||||
* PFE(Parallel Front End) functions
|
||||
*----------------------------------------*/
|
||||
extern void isc_pfe_set_video_mode(uint32_t vmode);
|
||||
extern void isc_pfe_set_sync_polarity(uint32_t hpol, uint32_t vpol);
|
||||
extern void isc_pfe_set_pixel_polarity(uint32_t ppol);
|
||||
extern void isc_pfe_set_field_polarity(uint32_t fpol);
|
||||
extern void isc_pfe_set_gated_clock(uint8_t en);
|
||||
extern void isc_pfe_set_cropping_enabled(uint8_t enCol, uint8_t enRow);
|
||||
extern void isc_pfe_set_bps(uint32_t bps);
|
||||
extern void isc_pfe_set_single_shot(void);
|
||||
extern void isc_pfe_set_continuous_shot(void);
|
||||
extern void isc_pfe_set_cropping_area(uint32_t Hstart, uint32_t Hend,
|
||||
uint32_t Vstart, uint32_t Vend);
|
||||
|
||||
/*------------------------------------------
|
||||
* Clock configuration functions
|
||||
*----------------------------------------*/
|
||||
extern void isc_configure_isp_clock(uint32_t isp_clk_div,
|
||||
uint32_t isp_clk_sel);
|
||||
extern void isc_enable_isp_clock(void);
|
||||
extern void isc_disable_isp_clock(void);
|
||||
extern void isc_reset_isp_clock(void);
|
||||
extern void isc_configure_master_clock(uint32_t master_clk_div,
|
||||
uint32_t master_clk_sel);
|
||||
extern void isc_enable_master_clock(void);
|
||||
extern void isc_disable_master_clock(void);
|
||||
extern void isc_reset_master_clock(void);
|
||||
extern uint32_t isc_get_clock_status(void);
|
||||
|
||||
/*------------------------------------------
|
||||
* Interrupt functions
|
||||
*----------------------------------------*/
|
||||
extern void isc_enable_interrupt(uint32_t flag);
|
||||
extern void isc_disable_interrupt(uint32_t flag);
|
||||
extern uint32_t isc_interrupt_status(void);
|
||||
|
||||
/*------------------------------------------
|
||||
* White Balance functions
|
||||
*----------------------------------------*/
|
||||
extern void isc_wb_enabled(uint8_t enabled);
|
||||
extern void isc_wb_set_bayer_pattern(uint8_t pattern);
|
||||
extern void isc_wb_adjust_bayer_color(uint32_t rOffset, uint32_t grOffset,
|
||||
uint32_t bOffset, uint32_t gbOffset,
|
||||
uint32_t rGain, uint32_t grGain,
|
||||
uint32_t bGain, uint32_t gbGain);
|
||||
|
||||
/*------------------------------------------
|
||||
* Color Filter Array functions
|
||||
*----------------------------------------*/
|
||||
extern void isc_cfa_enabled(uint8_t enabled);
|
||||
extern void isc_cfa_configure(uint8_t pattern, uint8_t edge);
|
||||
|
||||
/*------------------------------------------
|
||||
* Color Correction functions
|
||||
*----------------------------------------*/
|
||||
extern void isc_cc_enabled(uint8_t enabled);
|
||||
extern void isc_cc_configure(struct _color_correct* cc);
|
||||
|
||||
/*------------------------------------------
|
||||
* Gamma Correction functions
|
||||
*----------------------------------------*/
|
||||
extern void isc_gamma_enabled(uint8_t enabled, uint8_t channels);
|
||||
extern void isc_gamma_configure(uint16_t* rGamConstant, uint16_t* rGamSlope,
|
||||
uint16_t* gGamConstant, uint16_t* gGamSlope,
|
||||
uint16_t* bGamConstant, uint16_t* bGamSlope);
|
||||
|
||||
/*------------------------------------------
|
||||
* Color Space Conversion functions
|
||||
*----------------------------------------*/
|
||||
extern void isc_csc_enabled(uint8_t enabled);
|
||||
extern void isc_csc_configure(struct _color_space* cs);
|
||||
|
||||
/*------------------------------------------
|
||||
* Contrast And Brightness functions
|
||||
*----------------------------------------*/
|
||||
extern void isc_cbc_enabled(uint8_t enabled);
|
||||
extern void isc_cbc_configure(uint8_t ccir656, uint8_t byteOrder,
|
||||
uint16_t brightness, uint16_t contrast);
|
||||
|
||||
/*------------------------------------------
|
||||
* Sub-sampling functions
|
||||
*----------------------------------------*/
|
||||
extern void isc_sub422_enabled(uint8_t enabled);
|
||||
extern void isc_sub422_configure(uint8_t ccir656, uint8_t byte_order,
|
||||
uint8_t lpf);
|
||||
extern void isc_sub420_configure(uint8_t enabled, uint8_t filter);
|
||||
|
||||
/*------------------------------------------
|
||||
* Rounding, Limiting and Packing functions
|
||||
*----------------------------------------*/
|
||||
extern void isc_rlp_configure(uint8_t rlpMode, uint8_t alpha);
|
||||
|
||||
/*------------------------------------------
|
||||
* Histogram functions
|
||||
*----------------------------------------*/
|
||||
extern void isc_histogram_enabled(uint8_t enabled);
|
||||
extern void isc_histogram_configure(uint8_t mode, uint8_t bay_sel,
|
||||
uint8_t reset);
|
||||
extern void isc_update_histogram_table(void);
|
||||
extern void isc_clear_histogram_table(void);
|
||||
|
||||
/*------------------------------------------
|
||||
* DMA functions
|
||||
*----------------------------------------*/
|
||||
extern void isc_dma_configure_input_mode(uint32_t mode);
|
||||
extern void isc_dma_configure_desc_entry(uint32_t desc_entry);
|
||||
extern void isc_dma_enable(uint32_t ctrl);
|
||||
extern void isc_dma_adderss(uint8_t channel, uint32_t address, uint32_t stride);
|
||||
|
||||
#endif //#ifndef ISC_H
|
|
@ -0,0 +1,433 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file */
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/l2cc.h"
|
||||
#include "cortex-a/cp15.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
uint32_t l2cc_is_enabled(void)
|
||||
{
|
||||
return ((L2CC->L2CC_CR) & L2CC_CR_L2CEN);
|
||||
}
|
||||
|
||||
void l2cc_enable(void)
|
||||
{
|
||||
L2CC->L2CC_CR |= L2CC_CR_L2CEN;
|
||||
asm volatile("": : :"memory");
|
||||
asm("dsb");
|
||||
asm("isb");
|
||||
trace_info("L2 cache is enabled\r\n");
|
||||
}
|
||||
|
||||
void l2cc_disable(void)
|
||||
{
|
||||
L2CC->L2CC_CR &= ~L2CC_CR_L2CEN;
|
||||
asm volatile("": : :"memory");
|
||||
asm("dsb");
|
||||
asm("isb");
|
||||
trace_info("L2 cache is disabled\r\n");
|
||||
}
|
||||
|
||||
void l2cc_exclusive_cache(uint8_t enable)
|
||||
{
|
||||
uint32_t cfg;
|
||||
if (l2cc_is_enabled()) {
|
||||
l2cc_disable();
|
||||
}
|
||||
cfg = L2CC->L2CC_ACR;
|
||||
if (enable) {
|
||||
cp15_exclusive_cache();
|
||||
cfg |= L2CC_ACR_EXCC;
|
||||
trace_info("L2 Exclusive mode enabled\n\r");
|
||||
} else {
|
||||
cp15_non_exclusive_cache();
|
||||
cfg &= ~L2CC_ACR_EXCC;
|
||||
trace_info("L2 Exclusive mode disabled\n\r");
|
||||
}
|
||||
L2CC->L2CC_ACR |= cfg;
|
||||
}
|
||||
|
||||
void l2cc_config_lat_ram(struct _ram_latency_control * latencies)
|
||||
{
|
||||
if (l2cc_is_enabled()) {
|
||||
l2cc_disable();
|
||||
}
|
||||
|
||||
L2CC->L2CC_TRCR =
|
||||
(L2CC_TRCR_TSETLAT(latencies->tag.setup) |
|
||||
L2CC_TRCR_TRDLAT(latencies->tag.read) |
|
||||
L2CC_TRCR_TWRLAT(latencies->tag.write));
|
||||
L2CC->L2CC_DRCR =
|
||||
(L2CC_DRCR_DSETLAT(latencies->data.setup) |
|
||||
L2CC_DRCR_DRDLAT(latencies->data.read) |
|
||||
L2CC_DRCR_DWRLAT(latencies->data.write));
|
||||
}
|
||||
|
||||
void l2cc_set_config(const struct _l2cc_control* cfg)
|
||||
{
|
||||
uint32_t aux_control, debug_control, prefetch_control, power_control;
|
||||
|
||||
if (cfg->offset > 31) {
|
||||
assert(0);
|
||||
}
|
||||
if ((cfg->offset > 7) && (cfg->offset < 15)) {
|
||||
assert(0);
|
||||
}
|
||||
if ((cfg->offset > 15) && (cfg->offset < 23)) {
|
||||
assert(0);
|
||||
}
|
||||
if ((cfg->offset > 23) && (cfg->offset < 31)) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if (l2cc_is_enabled()) {
|
||||
l2cc_disable();
|
||||
}
|
||||
|
||||
aux_control = ((cfg->high_prior_so << 10) |
|
||||
(cfg->store_buff_dev_limit << 11) |
|
||||
(cfg->shared_attr_invalidate << 13) |
|
||||
(cfg->evt_mon_bus << 20) |
|
||||
(cfg->parity << 21) |
|
||||
(cfg->shared_attr_override << 22) |
|
||||
(L2CC_ACR_FWA(cfg->force_write_alloc)) |
|
||||
(cfg->cache_replacement << 25) |
|
||||
(cfg->non_sec_lockdown << 26) |
|
||||
(cfg->it_acces_non_sec << 27) |
|
||||
(cfg->data_prefetch << 28) |
|
||||
(cfg->instruct_prefetch << 29));
|
||||
|
||||
debug_control = ((cfg->no_cache_linefill << 0) |
|
||||
(cfg->no_write_back << 1));
|
||||
|
||||
prefetch_control = ((L2CC_PCR_OFFSET(cfg->offset << 0)) |
|
||||
(cfg->exclusive_seq_same_id << 21) |
|
||||
(cfg->incr_double_linefill << 23) |
|
||||
(cfg->prefetch_drop << 24) |
|
||||
(cfg->DLFWRDIS << 27) |
|
||||
(cfg->data_prefetch << 28) |
|
||||
(cfg->instruct_prefetch << 29) |
|
||||
(cfg->double_linefill << 30));
|
||||
|
||||
power_control = ((cfg->standby_mode << 0) |
|
||||
(cfg->dyn_clock_gating << 1));
|
||||
|
||||
L2CC->L2CC_ACR = aux_control;
|
||||
L2CC->L2CC_DCR = debug_control;
|
||||
L2CC->L2CC_PCR = prefetch_control;
|
||||
L2CC->L2CC_POWCR = power_control;
|
||||
}
|
||||
|
||||
void l2cc_data_prefetch_enable(void)
|
||||
{
|
||||
L2CC->L2CC_PCR |= L2CC_PCR_DATPEN;
|
||||
}
|
||||
|
||||
void l2cc_inst_prefetch_enable(void)
|
||||
{
|
||||
L2CC->L2CC_PCR |= L2CC_PCR_INSPEN;
|
||||
}
|
||||
|
||||
void l2cc_enable_reset_counter(uint8_t event_counter)
|
||||
{
|
||||
assert((event_counter > 3) ? 0 : 1);
|
||||
L2CC->L2CC_ECR = (L2CC_ECR_EVCEN | (event_counter << 1));
|
||||
}
|
||||
|
||||
void l2cc_event_config(uint8_t event_counter, uint8_t source, uint8_t it)
|
||||
{
|
||||
if (l2cc_is_enabled()) {
|
||||
L2CC->L2CC_CR = false;
|
||||
}
|
||||
assert((event_counter > 1) ? 0 : 1);
|
||||
if (!event_counter) {
|
||||
L2CC->L2CC_ECFGR0 = (source | it);
|
||||
} else {
|
||||
L2CC->L2CC_ECFGR1 = (source | it);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint32_t l2cc_event_counter_value(uint8_t event_counter)
|
||||
{
|
||||
assert((event_counter > 1) ? 0 : 1);
|
||||
if (!event_counter) {
|
||||
return L2CC->L2CC_EVR0;
|
||||
} else {
|
||||
return L2CC->L2CC_EVR1;
|
||||
}
|
||||
}
|
||||
|
||||
void l2cc_enable_it(uint16_t sources)
|
||||
{
|
||||
L2CC->L2CC_IMR |= sources;
|
||||
}
|
||||
|
||||
void l2cc_disable_it(uint16_t sources)
|
||||
{
|
||||
L2CC->L2CC_IMR &= (!sources);
|
||||
}
|
||||
|
||||
unsigned short l2cc_it_status_raw(uint16_t sources)
|
||||
{
|
||||
return ((L2CC->L2CC_RISR) & sources) ? 1 : 0;
|
||||
}
|
||||
|
||||
uint16_t l2cc_it_status_mask(uint16_t sources)
|
||||
{
|
||||
return ((L2CC->L2CC_MISR) & sources) ? 1 : 0;
|
||||
}
|
||||
|
||||
void l2cc_it_clear(uint16_t sources)
|
||||
{
|
||||
L2CC->L2CC_ICR |= sources;
|
||||
}
|
||||
|
||||
uint8_t l2cc_poll_spniden()
|
||||
{
|
||||
return ((L2CC->L2CC_DCR & L2CC_DCR_SPNIDEN) >> 2);
|
||||
}
|
||||
|
||||
void l2cc_cache_sync()
|
||||
{
|
||||
while ((L2CC->L2CC_CSR) & L2CC_CSR_C) ;
|
||||
L2CC->L2CC_CSR = L2CC_CSR_C;
|
||||
while ((L2CC->L2CC_CSR) & L2CC_CSR_C) ;
|
||||
}
|
||||
|
||||
void l2cc_invalidate_pal(uint32_t phys_addr)
|
||||
{
|
||||
static uint32_t Tag;
|
||||
static uint16_t Index;
|
||||
Tag = (phys_addr >> (OFFSET_BIT + INDEX_BIT));
|
||||
Index = (phys_addr >> OFFSET_BIT) & ((1 << INDEX_BIT) - 1);
|
||||
L2CC->L2CC_IPALR = (L2CC_IPALR_TAG(Tag) | L2CC_IPALR_IDX(Index) | L2CC_IPALR_C);
|
||||
while ((L2CC->L2CC_IPALR) & L2CC_IPALR_C) ;
|
||||
}
|
||||
|
||||
void l2cc_clean_pal(uint32_t phys_addr)
|
||||
{
|
||||
static uint32_t Tag;
|
||||
static uint16_t Index;
|
||||
|
||||
Tag = (phys_addr >> (OFFSET_BIT + INDEX_BIT));
|
||||
Index = (phys_addr >> OFFSET_BIT) & ((1 << INDEX_BIT) - 1);
|
||||
L2CC->L2CC_CPALR =
|
||||
(L2CC_CPALR_TAG(Tag) | L2CC_CPALR_IDX(Index) | L2CC_CPALR_C);
|
||||
while ((L2CC->L2CC_CPALR) & L2CC_CPALR_C) ;
|
||||
}
|
||||
|
||||
void l2cc_clean_ix(uint32_t phys_addr)
|
||||
{
|
||||
static uint32_t Tag;
|
||||
static uint16_t Index;
|
||||
|
||||
Tag = (phys_addr >> (OFFSET_BIT + INDEX_BIT));
|
||||
Index = (phys_addr >> OFFSET_BIT) & ((1 << INDEX_BIT) - 1);
|
||||
L2CC->L2CC_CIPALR =
|
||||
(L2CC_CIPALR_TAG(Tag) | L2CC_CIPALR_IDX(Index) | L2CC_CIPALR_C);
|
||||
while ((L2CC->L2CC_CIPALR) & L2CC_CIPALR_C) ;
|
||||
}
|
||||
|
||||
void l2cc_invalidate_way(uint8_t way)
|
||||
{
|
||||
L2CC->L2CC_IWR = way;
|
||||
while (L2CC->L2CC_IWR) ;
|
||||
while (L2CC->L2CC_CSR) ;
|
||||
}
|
||||
|
||||
void l2cc_clean_way(uint8_t way)
|
||||
{
|
||||
L2CC->L2CC_CWR = way;
|
||||
while (L2CC->L2CC_CWR) ;
|
||||
while (L2CC->L2CC_CSR) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clean Invalidate cache by way
|
||||
* \param way way number
|
||||
*/
|
||||
static void l2cc_clean_invalidate_way(uint8_t way)
|
||||
{
|
||||
L2CC->L2CC_CIWR = way;
|
||||
while (L2CC->L2CC_CSR) ;
|
||||
}
|
||||
|
||||
void l2cc_clean_index(uint32_t phys_addr, uint8_t way)
|
||||
{
|
||||
static uint16_t Index;
|
||||
|
||||
Index = (phys_addr >> OFFSET_BIT) & ((1 << INDEX_BIT) - 1);
|
||||
L2CC->L2CC_CIR =
|
||||
(L2CC_CIR_IDX(Index) | L2CC_CIR_WAY(way) | L2CC_CIR_C);
|
||||
while ((L2CC->L2CC_CIR) & L2CC_CIR_C) ;
|
||||
}
|
||||
|
||||
void l2cc_clean_invalidate_index(uint32_t phys_addr, uint8_t way)
|
||||
{
|
||||
static uint16_t Index;
|
||||
|
||||
(void) way;
|
||||
Index = (phys_addr >> OFFSET_BIT) & ((1 << INDEX_BIT) - 1);
|
||||
L2CC->L2CC_CIIR =
|
||||
(L2CC_CIIR_IDX(Index) | L2CC_CIIR_WAY(Index) | L2CC_CIIR_C);
|
||||
while ((L2CC->L2CC_CIIR) & L2CC_CIIR_C) ;
|
||||
}
|
||||
|
||||
void l2cc_data_lockdown(uint8_t way)
|
||||
{
|
||||
L2CC->L2CC_DLKR = way;
|
||||
while (L2CC->L2CC_CSR) ;
|
||||
}
|
||||
|
||||
void l2cc_instruction_lockdown(uint8_t way)
|
||||
{
|
||||
L2CC->L2CC_ILKR = way;
|
||||
while (L2CC->L2CC_CSR) ;
|
||||
}
|
||||
|
||||
static void l2cc_clean(void)
|
||||
{
|
||||
// Clean of L1; This is broadcast within the cluster
|
||||
cp15_dcache_clean();
|
||||
if (l2cc_is_enabled()) {
|
||||
// forces the address out past level 2
|
||||
l2cc_clean_way(0xFF);
|
||||
// Ensures completion of the L2 clean
|
||||
l2cc_cache_sync();
|
||||
}
|
||||
}
|
||||
|
||||
static void l2cc_invalidate(void)
|
||||
{
|
||||
if (l2cc_is_enabled()) {
|
||||
// forces the address out past level 2
|
||||
l2cc_invalidate_way(0xFF);
|
||||
// Ensures completion of the L2 inval
|
||||
l2cc_cache_sync();
|
||||
}
|
||||
// Inval of L1; This is broadcast within the cluster
|
||||
cp15_dcache_invalidate();
|
||||
}
|
||||
|
||||
static void l2cc_clean_invalidate(void)
|
||||
{
|
||||
/* Clean of L1; This is broadcast within the cluster */
|
||||
cp15_dcache_clean();
|
||||
|
||||
if (l2cc_is_enabled()) {
|
||||
/* forces the address out past level 2 */
|
||||
l2cc_clean_invalidate_way(0xFF);
|
||||
/* Ensures completion of the L2 inval */
|
||||
l2cc_cache_sync();
|
||||
}
|
||||
|
||||
/* Inval of L1; This is broadcast within the cluster */
|
||||
cp15_dcache_invalidate();
|
||||
}
|
||||
|
||||
void l2cc_cache_maintenance(enum _maint_op maintenance)
|
||||
{
|
||||
switch (maintenance) {
|
||||
case L2CC_DCACHE_CLEAN:
|
||||
l2cc_clean();
|
||||
break;
|
||||
case L2CC_DCACHE_INVAL:
|
||||
l2cc_invalidate();
|
||||
break;
|
||||
case L2CC_DCACHE_FLUSH:
|
||||
l2cc_clean_invalidate();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void l2cc_invalidate_region(uint32_t start, uint32_t end)
|
||||
{
|
||||
assert(start < end);
|
||||
uint32_t current = start & ~0x1fUL;
|
||||
if (l2cc_is_enabled()) {
|
||||
while (current <= end) {
|
||||
l2cc_invalidate_pal(current);
|
||||
current += 32;
|
||||
}
|
||||
l2cc_invalidate_pal(end);
|
||||
}
|
||||
cp15_invalidate_dcache_for_dma(start, end);
|
||||
}
|
||||
|
||||
void l2cc_clean_region(uint32_t start, uint32_t end)
|
||||
{
|
||||
assert(start < end);
|
||||
uint32_t current = start & ~0x1fUL;
|
||||
if (l2cc_is_enabled()) {
|
||||
while (current <= end) {
|
||||
l2cc_clean_pal(current);
|
||||
current += 32;
|
||||
}
|
||||
l2cc_clean_pal(end);
|
||||
}
|
||||
cp15_clean_dcache_for_dma(start, end);
|
||||
}
|
||||
|
||||
void l2cc_configure(const struct _l2cc_control* cfg)
|
||||
{
|
||||
l2cc_event_config(0, L2CC_ECFGR0_ESRC_SRC_DRHIT,
|
||||
L2CC_ECFGR0_EIGEN_INT_DIS);
|
||||
l2cc_event_config(1, L2CC_ECFGR0_ESRC_SRC_DWHIT,
|
||||
L2CC_ECFGR0_EIGEN_INT_DIS);
|
||||
|
||||
l2cc_enable_reset_counter(L2CC_RESET_BOTH_COUNTER);
|
||||
l2cc_set_config(cfg);
|
||||
/* Enable Prefetch */
|
||||
l2cc_inst_prefetch_enable();
|
||||
l2cc_data_prefetch_enable();
|
||||
/* Invalidate whole L2CC */
|
||||
l2cc_invalidate_way(0xFF);
|
||||
/* Disable all L2CC Interrupt */
|
||||
l2cc_disable_it(0x1FF);
|
||||
/* Clear all L2CC Interrupt */
|
||||
l2cc_it_clear(0xFF);
|
||||
l2cc_exclusive_cache(true);
|
||||
l2cc_enable();
|
||||
}
|
|
@ -0,0 +1,347 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Interface for Level 2 cache (L2CC) controller.
|
||||
*
|
||||
*/
|
||||
|
||||
/** \addtogroup l2cc_module L2 Cache Operations
|
||||
* \ingroup cache_module
|
||||
* \section Usage
|
||||
* - Enable or disable L2CC with L2CC_Enable() or L2CC_Disable().
|
||||
* - Check if L2CC is enabled with L2CC_IsEnabled().
|
||||
* - Enable or disable L2CC interrupt with L2CC_EnableIT() or L2CC_DisableIT().
|
||||
* - Enable data or instruction prefetch with L2CC_DataPrefetchEnable() or L2CC_InstPrefetchEnable().
|
||||
*
|
||||
* Related files:\n
|
||||
* \ref l2cc.h\n
|
||||
* \ref l2cc.c\n
|
||||
*/
|
||||
|
||||
#ifndef _L2CC_H
|
||||
#define _L2CC_H
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
#include "chip.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Define
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define OFFSET_BIT 5
|
||||
#define INDEX_BIT 9
|
||||
#define TAG_BIT 18
|
||||
|
||||
#define L2CC_RESET_EVCOUNTER0 0
|
||||
#define L2CC_RESET_EVCOUNTER1 1
|
||||
#define L2CC_RESET_BOTH_COUNTER 3
|
||||
|
||||
#define FWA_DEFAULT 0u
|
||||
#define FWA_NO_ALLOCATE 1u
|
||||
#define FWA_FORCE_ALLOCATE 2u
|
||||
#define FWA_INTERNALLY_MAPPED 3u
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Types
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
enum _maint_op {
|
||||
L2CC_DCACHE_CLEAN,
|
||||
L2CC_DCACHE_INVAL,
|
||||
L2CC_DCACHE_FLUSH
|
||||
};
|
||||
|
||||
struct _latency {
|
||||
uint8_t setup;
|
||||
uint8_t read;
|
||||
uint8_t write;
|
||||
};
|
||||
|
||||
struct _ram_latency_control {
|
||||
struct _latency tag;
|
||||
struct _latency data;
|
||||
};
|
||||
|
||||
/** L2CC structure */
|
||||
struct _l2cc_control {
|
||||
/** High Priority for SO and Dev Reads Enable */
|
||||
uint32_t high_prior_so: 1,
|
||||
/** Store Buffer Device Limitation Enable */
|
||||
store_buff_dev_limit: 1,
|
||||
/** Shared Attribute Invalidate Enable */
|
||||
shared_attr_invalidate: 1,
|
||||
/** Event Monitor Bus Enable */
|
||||
evt_mon_bus: 1,
|
||||
/** Parity Enable */
|
||||
parity: 1,
|
||||
/** Shared Attribute Override Enable */
|
||||
shared_attr_override: 1,
|
||||
/** Force Write Allocate */
|
||||
force_write_alloc: 2,
|
||||
/** Cache Replacement Policy */
|
||||
cache_replacement: 1,
|
||||
/** Non-Secure Lockdown Enable*/
|
||||
non_sec_lockdown: 1,
|
||||
/** Non-Secure Interrupt Access Control */
|
||||
it_acces_non_sec: 1,
|
||||
/** Data Prefetch Enable*/
|
||||
data_prefetch: 1,
|
||||
/** Instruction Prefetch Enable */
|
||||
instruct_prefetch: 1,
|
||||
/** Prefetch Offset */
|
||||
offset: 5,
|
||||
/** Not Same ID on Exclusive Sequence Enable */
|
||||
exclusive_seq_same_id: 1,
|
||||
/** INCR Double Linefill Enable */
|
||||
incr_double_linefill: 1,
|
||||
/** Prefetch Drop Enable*/
|
||||
prefetch_drop: 1,
|
||||
/** Double Linefill on WRAP Read Disable */
|
||||
DLFWRDIS: 1,
|
||||
/** Double linefill Enable */
|
||||
double_linefill: 1,
|
||||
/** Standby Mode Enable */
|
||||
standby_mode: 1,
|
||||
/** Dynamic Clock Gating Enable */
|
||||
dyn_clock_gating: 1,
|
||||
/** Disable Cache Linefill*/
|
||||
no_cache_linefill: 1,
|
||||
/** Disable Write-back, Force Write-through */
|
||||
no_write_back: 1;
|
||||
};
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Check if Level 2 cache is enable.
|
||||
*/
|
||||
extern uint32_t l2cc_is_enabled(void);
|
||||
|
||||
/**
|
||||
* \brief Enable Level 2 cache.
|
||||
*/
|
||||
extern void l2cc_enable(void);
|
||||
|
||||
/**
|
||||
* \brief Disable Level 2 cache.
|
||||
*/
|
||||
extern void l2cc_disable(void);
|
||||
|
||||
/**
|
||||
* \brief Configures Level 2 cache as exclusive cache.
|
||||
* \param Enable Enable/disable exclusive cache.
|
||||
*/
|
||||
extern void l2cc_exclusive_cache(uint8_t enable);
|
||||
|
||||
/**
|
||||
* \brief Configures Level 2 cache RAM Latency (Tag and Data).
|
||||
* \param latencies Structure containing RAM Tag and Data latencies
|
||||
*/
|
||||
extern void l2cc_config_lat_ram(struct _ram_latency_control * latencies);
|
||||
|
||||
/**
|
||||
* \brief Configures Level 2 cache.
|
||||
* \param cfg Configuration values to put in Auxiliary, prefetch,
|
||||
* debug and powercontrol registers.
|
||||
*/
|
||||
extern void l2cc_set_config(const struct _l2cc_control* cfg);
|
||||
|
||||
/**
|
||||
* \brief Enables Data prefetch on L2
|
||||
*/
|
||||
extern void l2cc_data_prefetch_enable(void);
|
||||
|
||||
/**
|
||||
* \brief Enables instruction prefetch on L2
|
||||
*/
|
||||
extern void l2cc_inst_prefetch_enable(void);
|
||||
|
||||
/**
|
||||
* \brief Enables instruction prefetch on L2
|
||||
* \param event_counter Counter of the events.
|
||||
*/
|
||||
extern void l2cc_enable_reset_counter(uint8_t event_counter);
|
||||
|
||||
/**
|
||||
* \brief Configures Event of Level 2 cache.
|
||||
* \param event_counter Eventcounter 1 or 0
|
||||
* \param source Event Genration source
|
||||
* \param it Event Counter Interrupt Generation condition
|
||||
*/
|
||||
extern void l2cc_event_config(uint8_t event_counter, uint8_t source,
|
||||
uint8_t it);
|
||||
|
||||
/**
|
||||
* \brief Reads Event Counter value.
|
||||
* \param event_counter choose Eventcounter 1 or 0
|
||||
*/
|
||||
extern uint32_t l2cc_event_counter_value(uint8_t event_counter);
|
||||
|
||||
/**
|
||||
* \brief Enable interrupts
|
||||
* \param sources Interrupt source
|
||||
*/
|
||||
extern void l2cc_enable_it(uint16_t sources);
|
||||
|
||||
/**
|
||||
* \brief Disable interrupts
|
||||
* \param sources Interrupt source
|
||||
*/
|
||||
extern void l2cc_disable_it(uint16_t sources);
|
||||
|
||||
/**
|
||||
* \brief Enabled interrupt's raw status
|
||||
* \param sources Interrupt source
|
||||
*/
|
||||
extern uint16_t l2cc_it_status_raw(uint16_t sources);
|
||||
|
||||
/**
|
||||
* \brief Status of masked interrupts
|
||||
* \param sources Interrupt source
|
||||
*/
|
||||
extern uint16_t l2cc_it_status_mask(uint16_t sources);
|
||||
|
||||
/**
|
||||
* \brief Clear interrupts
|
||||
* \param sources Interrupt source
|
||||
*/
|
||||
extern void l2cc_it_clear(uint16_t sources);
|
||||
|
||||
/**
|
||||
* \brief Poll SPNIDEN signal
|
||||
*/
|
||||
extern uint8_t l2cc_poll_spniden(void);
|
||||
|
||||
/**
|
||||
* \brief Synchronizes the L2 cache
|
||||
*/
|
||||
extern void l2cc_cache_sync(void);
|
||||
|
||||
/**
|
||||
* \brief Invalidate cache by way
|
||||
* \param way way number
|
||||
*/
|
||||
extern void l2cc_invalidate_way(uint8_t way);
|
||||
|
||||
/**
|
||||
* \brief Clean cache by way
|
||||
* \param way way number
|
||||
*/
|
||||
extern void l2cc_clean_way(uint8_t way);
|
||||
|
||||
/**
|
||||
* \brief Invalidate cache by Physical addersse
|
||||
* \param phys_addr Physical addresse
|
||||
*/
|
||||
extern void l2cc_invalidate_pal(uint32_t phys_addr);
|
||||
|
||||
/**
|
||||
* \brief Clean cache by Physical addersse
|
||||
* \param phys_addr Physical addresse
|
||||
*/
|
||||
extern void l2cc_clean_pal(uint32_t phys_addr);
|
||||
|
||||
/**
|
||||
* \brief Clean index cache by Physical addersse
|
||||
* \param phys_addr Physical addresse
|
||||
*/
|
||||
extern void l2cc_clean_ix(uint32_t phys_addr);
|
||||
|
||||
/**
|
||||
* \brief Clean cache by Index
|
||||
* \param phys_addr Physical addresse
|
||||
* \param way way number
|
||||
*/
|
||||
extern void l2cc_clean_index(uint32_t phys_addr, uint8_t way);
|
||||
|
||||
/**
|
||||
* \brief Clean Invalidate cache by index
|
||||
* \param phys_addr Physical address
|
||||
* \param way way number
|
||||
*/
|
||||
extern void l2cc_clean_invalidate_index(uint32_t phys_addr, uint8_t way);
|
||||
|
||||
/**
|
||||
* \brief cache Data lockdown
|
||||
* \param way way number
|
||||
*/
|
||||
extern void l2cc_data_lockdown(uint8_t way);
|
||||
|
||||
/**
|
||||
* \brief cache instruction lockdown
|
||||
* \param way way number
|
||||
*/
|
||||
extern void l2cc_instruction_lockdown(uint8_t way);
|
||||
|
||||
/**
|
||||
* \brief L2 DCache maintenance (clean/invalidate/flush)
|
||||
*
|
||||
* \param maintenance Maintenance operation to apply: \sa #_maint_op
|
||||
*/
|
||||
extern void l2cc_cache_maintenance(enum _maint_op maintenance);
|
||||
|
||||
/**
|
||||
* \brief Invalidate cache lines corresponding to a memory region
|
||||
*
|
||||
* \param start Beginning of the memory region
|
||||
* \param end End of the memory region
|
||||
*/
|
||||
extern void l2cc_invalidate_region(uint32_t start, uint32_t end);
|
||||
|
||||
/**
|
||||
* \brief Clean cache lines corresponding to a memory region
|
||||
*
|
||||
* \param start Beginning of the memory region
|
||||
* \param end End of the memory region
|
||||
*/
|
||||
extern void l2cc_clean_region(uint32_t start, uint32_t end);
|
||||
|
||||
/**
|
||||
* \brief Enable level two cache controller (L2CC)
|
||||
*
|
||||
* \param cfg configuration to apply: \sa #_l2cc_control
|
||||
*/
|
||||
extern void l2cc_configure(const struct _l2cc_control* cfg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* #ifndef _L2CC_ */
|
|
@ -0,0 +1,100 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "peripherals/matrix.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
void matrix_configure_slave_sec(Matrix* mtx, uint8_t slave_id,
|
||||
uint8_t sel_mask, uint8_t read_mask,
|
||||
uint8_t write_mask)
|
||||
{
|
||||
mtx->MATRIX_SSR[slave_id] = sel_mask | (read_mask << 8) |
|
||||
(write_mask << 16);
|
||||
}
|
||||
|
||||
void matrix_set_slave_split_addr(Matrix* mtx, uint8_t slave_id,
|
||||
uint8_t area_size, uint8_t mask)
|
||||
{
|
||||
uint8_t i = mask, j = 0;
|
||||
uint32_t value = 0;
|
||||
for (i = 1; (i <= mask) && (j < 32); i <<= 1, j += 4) {
|
||||
if (i & mask)
|
||||
value |= area_size << j;
|
||||
}
|
||||
mtx->MATRIX_SASSR[slave_id] = value;
|
||||
}
|
||||
|
||||
void matrix_set_slave_region_size(Matrix* mtx, uint8_t slave_id,
|
||||
uint8_t area_size, uint8_t mask)
|
||||
{
|
||||
assert(slave_id != 0);
|
||||
uint8_t i = mask, j = 0;
|
||||
uint32_t value = 0;
|
||||
for (i = 1; (i <= mask) && (j < 32 ); i <<= 1, j += 4) {
|
||||
if (i & mask)
|
||||
value |= area_size << j;
|
||||
}
|
||||
mtx->MATRIX_SRTSR[slave_id] = value;
|
||||
}
|
||||
|
||||
uint8_t matrix_is_peripheral_secured(Matrix* mtx, uint32_t periph_id)
|
||||
{
|
||||
if (mtx->MATRIX_SPSELR[periph_id / 32] & (1 << (periph_id % 32))) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void matrix_remove_write_protection(Matrix* mtx)
|
||||
{
|
||||
mtx->MATRIX_WPMR = MATRIX_WPMR_WPKEY_PASSWD;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes the mapping of the chip so that the remap area mirrors the
|
||||
* internal ROM or the EBI CS0.
|
||||
*/
|
||||
void matrix_remap_rom(void)
|
||||
{
|
||||
AXIMX->AXIMX_REMAP = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Changes the mapping of the chip so that the remap area mirrors the
|
||||
* internal RAM.
|
||||
*/
|
||||
|
||||
void matrix_remap_ram(void)
|
||||
{
|
||||
volatile uint32_t i;
|
||||
AXIMX->AXIMX_REMAP = AXIMX_REMAP_REMAP0;
|
||||
for(i=1000;--i;);
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MATRIX_HEADER_
|
||||
#define MATRIX_HEADER_
|
||||
|
||||
#include "chip.h"
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Definitions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#define MATRIX_AREA_4K (0x0u) /* 0x1000 */
|
||||
#define MATRIX_AREA_8K (0x1u) /* 0x2000 */
|
||||
#define MATRIX_AREA_16K (0x2u) /* 0x4000 */
|
||||
#define MATRIX_AREA_32K (0x3u) /* 0x8000 */
|
||||
#define MATRIX_AREA_64K (0x4u) /* 0x10000 */
|
||||
#define MATRIX_AREA_128K (0x5u) /* 0x20000 */
|
||||
#define MATRIX_AREA_256K (0x6u) /* 0x40000 */
|
||||
#define MATRIX_AREA_512K (0x7u) /* 0x80000 */
|
||||
#define MATRIX_AREA_1M (0x8u) /* 0x100000 */
|
||||
#define MATRIX_AREA_2M (0x9u) /* 0x200000 */
|
||||
#define MATRIX_AREA_4M (0xAu) /* 0x400000 */
|
||||
#define MATRIX_AREA_8M (0xBu) /* 0x800000 */
|
||||
#define MATRIX_AREA_16M (0xCu) /* 0x1000000 */
|
||||
#define MATRIX_AREA_32M (0xDu) /* 0x2000000 */
|
||||
#define MATRIX_AREA_64M (0xEu) /* 0x4000000 */
|
||||
#define MATRIX_AREA_128M (0xFu) /* 0x8000000 */
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void matrix_configure_slave_sec(Matrix* mtx, uint8_t slave_id,
|
||||
uint8_t sel_mask, uint8_t read_mask,
|
||||
uint8_t write_mask);
|
||||
|
||||
extern void matrix_set_slave_split_addr(Matrix* mtx, uint8_t slave_id,
|
||||
uint8_t area, uint8_t mask);
|
||||
|
||||
extern void matrix_set_slave_region_size(Matrix* mtx, uint8_t slave_id,
|
||||
uint8_t area, uint8_t mask);
|
||||
|
||||
extern uint8_t matrix_is_peripheral_secured(Matrix* mtx, uint32_t periph_id);
|
||||
|
||||
extern void matrix_remove_write_protection(Matrix* mtx);
|
||||
|
||||
extern void matrix_remap_rom(void);
|
||||
|
||||
extern void matrix_remap_ram(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MATRIX_HEADER_ */
|
|
@ -0,0 +1,749 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* Implements functions for Controller Area Network with Flexible Data-rate,
|
||||
* relying on the MCAN peripheral.
|
||||
*/
|
||||
/** \addtogroup can_module
|
||||
*@{*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "board.h"
|
||||
#include "chip.h"
|
||||
#include "mcan.h"
|
||||
#include "pmc.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Local definitions
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
enum mcan_dlc
|
||||
{
|
||||
CAN_DLC_0 = 0,
|
||||
CAN_DLC_1 = 1,
|
||||
CAN_DLC_2 = 2,
|
||||
CAN_DLC_3 = 3,
|
||||
CAN_DLC_4 = 4,
|
||||
CAN_DLC_5 = 5,
|
||||
CAN_DLC_6 = 6,
|
||||
CAN_DLC_7 = 7,
|
||||
CAN_DLC_8 = 8,
|
||||
CAN_DLC_12 = 9,
|
||||
CAN_DLC_16 = 10,
|
||||
CAN_DLC_20 = 11,
|
||||
CAN_DLC_24 = 12,
|
||||
CAN_DLC_32 = 13,
|
||||
CAN_DLC_48 = 14,
|
||||
CAN_DLC_64 = 15
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Local functions
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Convert data length to Data Length Code.
|
||||
* \param len length, in bytes
|
||||
* \param dlc address where the matching Data Length Code will be written
|
||||
* \return true if a code matched the provided length, false if this exact
|
||||
* length is not supported.
|
||||
*/
|
||||
static bool get_length_code(uint8_t len, enum mcan_dlc *dlc)
|
||||
{
|
||||
assert(dlc);
|
||||
|
||||
if (len <= 8) {
|
||||
*dlc = (enum mcan_dlc)len;
|
||||
return true;
|
||||
}
|
||||
if (len % 4)
|
||||
return false;
|
||||
len /= 4;
|
||||
if (len <= 6) {
|
||||
*dlc = (enum mcan_dlc)(len + 6);
|
||||
return true;
|
||||
}
|
||||
if (len % 4)
|
||||
return false;
|
||||
len /= 4;
|
||||
if (len > 4)
|
||||
return false;
|
||||
*dlc = (enum mcan_dlc)(len + 11);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Convert Data Length Code to actual data length.
|
||||
* \param dlc CAN_DLC_xx enum value
|
||||
* \return Data length, expressed in bytes.
|
||||
*/
|
||||
static uint8_t get_data_length(enum mcan_dlc dlc)
|
||||
{
|
||||
assert((dlc == CAN_DLC_0 || dlc > CAN_DLC_0) && dlc <= CAN_DLC_64);
|
||||
|
||||
if (dlc <= CAN_DLC_8)
|
||||
return (uint8_t)dlc;
|
||||
if (dlc <= CAN_DLC_24)
|
||||
return ((uint8_t)dlc - 6) * 4;
|
||||
return ((uint8_t)dlc - 11) * 16;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compute the size of the Message RAM, depending on the application.
|
||||
* \param set Pointer to a MCAN instance that will be setup accordingly.
|
||||
* \param cfg MCAN configuration to be considered. Only integer size parameters
|
||||
* need to be configured. The other parameters can be left blank at this stage.
|
||||
* \param size address where the required size of the Message RAM will be
|
||||
* written, expressed in (32-bit) words.
|
||||
* \return true if successful, false if a parameter is set to an unsupported
|
||||
* value.
|
||||
*/
|
||||
static bool configure_ram(struct mcan_set *set,
|
||||
const struct mcan_config *cfg, uint32_t *size)
|
||||
{
|
||||
if (cfg->array_size_filt_std > 128 || cfg->array_size_filt_ext > 64
|
||||
|| cfg->fifo_size_rx0 > 64 || cfg->fifo_size_rx1 > 64
|
||||
|| cfg->array_size_rx > 64 || cfg->fifo_size_tx_evt > 32
|
||||
|| cfg->array_size_tx > 32 || cfg->fifo_size_tx > 32
|
||||
|| cfg->array_size_tx + cfg->fifo_size_tx > 32
|
||||
|| cfg->buf_size_rx_fifo0 > 64 || cfg->buf_size_rx_fifo1 > 64
|
||||
|| cfg->buf_size_rx > 64 || cfg->buf_size_tx > 64)
|
||||
return false;
|
||||
|
||||
set->ram_filt_std = cfg->msg_ram;
|
||||
*size = (uint32_t)cfg->array_size_filt_std * MCAN_RAM_FILT_STD_SIZE;
|
||||
set->ram_filt_ext = cfg->msg_ram + *size;
|
||||
*size += (uint32_t)cfg->array_size_filt_ext * MCAN_RAM_FILT_EXT_SIZE;
|
||||
set->ram_fifo_rx0 = cfg->msg_ram + *size;
|
||||
*size += (uint32_t)cfg->fifo_size_rx0 * (MCAN_RAM_BUF_HDR_SIZE
|
||||
+ cfg->buf_size_rx_fifo0 / 4);
|
||||
set->ram_fifo_rx1 = cfg->msg_ram + *size;
|
||||
*size += (uint32_t)cfg->fifo_size_rx1 * (MCAN_RAM_BUF_HDR_SIZE
|
||||
+ cfg->buf_size_rx_fifo1 / 4);
|
||||
set->ram_array_rx = cfg->msg_ram + *size;
|
||||
*size += (uint32_t)cfg->array_size_rx * (MCAN_RAM_BUF_HDR_SIZE
|
||||
+ cfg->buf_size_rx / 4);
|
||||
set->ram_fifo_tx_evt = cfg->msg_ram + *size;
|
||||
*size += (uint32_t)cfg->fifo_size_tx_evt * MCAN_RAM_TX_EVT_SIZE;
|
||||
set->ram_array_tx = cfg->msg_ram + *size;
|
||||
*size += (uint32_t)cfg->array_size_tx * (MCAN_RAM_BUF_HDR_SIZE
|
||||
+ cfg->buf_size_tx / 4);
|
||||
*size += (uint32_t)cfg->fifo_size_tx * (MCAN_RAM_BUF_HDR_SIZE
|
||||
+ cfg->buf_size_tx / 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Exported Functions
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
bool mcan_configure_msg_ram(const struct mcan_config *cfg, uint32_t *size)
|
||||
{
|
||||
assert(cfg);
|
||||
assert(size);
|
||||
|
||||
struct mcan_set tmp_set = { .cfg = { 0 } };
|
||||
|
||||
return configure_ram(&tmp_set, cfg, size);
|
||||
}
|
||||
|
||||
bool mcan_initialize(struct mcan_set *set, const struct mcan_config *cfg)
|
||||
{
|
||||
assert(set);
|
||||
assert(cfg);
|
||||
assert(cfg->regs);
|
||||
assert(cfg->msg_ram);
|
||||
|
||||
Mcan *mcan = cfg->regs;
|
||||
uint32_t *element = NULL, *elem_end = NULL;
|
||||
uint32_t freq, regVal32;
|
||||
enum mcan_dlc dlc;
|
||||
|
||||
memset(set, 0, sizeof(*set));
|
||||
if (!configure_ram(set, cfg, ®Val32))
|
||||
return false;
|
||||
set->cfg = *cfg;
|
||||
|
||||
/* Configure the MSB of the Message RAM Base Address */
|
||||
regVal32 = (uint32_t)cfg->msg_ram >> 16;
|
||||
if (cfg->id == ID_CAN0_INT0 || cfg->id == ID_CAN0_INT1)
|
||||
regVal32 = (SFR->SFR_CAN & ~SFR_CAN_EXT_MEM_CAN0_ADDR_Msk)
|
||||
| SFR_CAN_EXT_MEM_CAN0_ADDR(regVal32);
|
||||
else
|
||||
regVal32 = (SFR->SFR_CAN & ~SFR_CAN_EXT_MEM_CAN1_ADDR_Msk)
|
||||
| SFR_CAN_EXT_MEM_CAN1_ADDR(regVal32);
|
||||
SFR->SFR_CAN = regVal32;
|
||||
|
||||
/* Reset the CC Control Register */
|
||||
mcan->MCAN_CCCR = 0 | MCAN_CCCR_INIT_ENABLED;
|
||||
|
||||
mcan_disable(set);
|
||||
mcan_reconfigure(set);
|
||||
|
||||
/* Global Filter Configuration: Reject remote frames, reject non-matching frames */
|
||||
mcan->MCAN_GFC = MCAN_GFC_RRFE_REJECT | MCAN_GFC_RRFS_REJECT
|
||||
| MCAN_GFC_ANFE(2) | MCAN_GFC_ANFS(2);
|
||||
|
||||
/* Extended ID Filter AND mask */
|
||||
mcan->MCAN_XIDAM = 0x1FFFFFFF;
|
||||
|
||||
/* Interrupt configuration - leave initialization with all interrupts off
|
||||
* Disable all interrupts */
|
||||
mcan->MCAN_IE = 0;
|
||||
mcan->MCAN_TXBTIE = 0x00000000;
|
||||
/* All interrupts directed to Line 0 */
|
||||
mcan->MCAN_ILS = 0x00000000;
|
||||
/* Disable both interrupt LINE 0 & LINE 1 */
|
||||
mcan->MCAN_ILE = 0x00;
|
||||
/* Clear all interrupt flags */
|
||||
mcan->MCAN_IR = 0xFFCFFFFF;
|
||||
|
||||
/* Configure CAN bit timing */
|
||||
if (cfg->bit_rate == 0
|
||||
|| cfg->quanta_before_sp < 3 || cfg->quanta_before_sp > 257
|
||||
|| cfg->quanta_after_sp < 1 || cfg->quanta_after_sp > 128
|
||||
|| cfg->quanta_sync_jump < 1 || cfg->quanta_sync_jump > 128)
|
||||
return false;
|
||||
/* Retrieve the frequency of the CAN core clock i.e. the Generated Clock */
|
||||
freq = pmc_get_gck_clock(cfg->id);
|
||||
/* Compute the Nominal Baud Rate Prescaler */
|
||||
regVal32 = ROUND_INT_DIV(freq, cfg->bit_rate
|
||||
* (cfg->quanta_before_sp + cfg->quanta_after_sp));
|
||||
if (regVal32 < 1 || regVal32 > 512)
|
||||
return false;
|
||||
/* Apply bit timing configuration */
|
||||
mcan->MCAN_NBTP = MCAN_NBTP_NBRP(regVal32 - 1)
|
||||
| MCAN_NBTP_NTSEG1(cfg->quanta_before_sp - 1 - 1)
|
||||
| MCAN_NBTP_NTSEG2(cfg->quanta_after_sp - 1)
|
||||
| MCAN_NBTP_NSJW(cfg->quanta_sync_jump - 1);
|
||||
|
||||
/* Configure fast CAN FD bit timing */
|
||||
if (cfg->bit_rate_fd < cfg->bit_rate
|
||||
|| cfg->quanta_before_sp_fd < 3 || cfg->quanta_before_sp_fd > 33
|
||||
|| cfg->quanta_after_sp_fd < 1 || cfg->quanta_after_sp_fd > 16
|
||||
|| cfg->quanta_sync_jump_fd < 1 || cfg->quanta_sync_jump_fd > 8)
|
||||
return false;
|
||||
/* Compute the Fast Baud Rate Prescaler */
|
||||
regVal32 = ROUND_INT_DIV(freq, cfg->bit_rate_fd
|
||||
* (cfg->quanta_before_sp_fd + cfg->quanta_after_sp_fd));
|
||||
if (regVal32 < 1 || regVal32 > 32)
|
||||
return false;
|
||||
/* Apply bit timing configuration */
|
||||
mcan->MCAN_DBTP = MCAN_DBTP_FBRP(regVal32 - 1)
|
||||
| MCAN_DBTP_DTSEG1(cfg->quanta_before_sp_fd - 1 - 1)
|
||||
| MCAN_DBTP_DTSEG2(cfg->quanta_after_sp_fd - 1)
|
||||
| MCAN_DBTP_DSJW(cfg->quanta_sync_jump_fd - 1);
|
||||
|
||||
/* Configure Message RAM starting addresses and element count */
|
||||
/* 11-bit Message ID Rx Filters */
|
||||
mcan->MCAN_SIDFC =
|
||||
MCAN_SIDFC_FLSSA((uint32_t)set->ram_filt_std >> 2)
|
||||
| MCAN_SIDFC_LSS(cfg->array_size_filt_std);
|
||||
/* 29-bit Message ID Rx Filters */
|
||||
mcan->MCAN_XIDFC =
|
||||
MCAN_XIDFC_FLESA((uint32_t)set->ram_filt_ext >> 2)
|
||||
| MCAN_XIDFC_LSE(cfg->array_size_filt_ext);
|
||||
/* Rx FIFO 0 */
|
||||
mcan->MCAN_RXF0C =
|
||||
MCAN_RXF0C_F0SA((uint32_t)set->ram_fifo_rx0 >> 2)
|
||||
| MCAN_RXF0C_F0S(cfg->fifo_size_rx0)
|
||||
| MCAN_RXF0C_F0WM(0)
|
||||
| 0; /* clear MCAN_RXF0C_F0OM */
|
||||
/* Rx FIFO 1 */
|
||||
mcan->MCAN_RXF1C =
|
||||
MCAN_RXF1C_F1SA((uint32_t)set->ram_fifo_rx1 >> 2)
|
||||
| MCAN_RXF1C_F1S(cfg->fifo_size_rx1)
|
||||
| MCAN_RXF1C_F1WM(0)
|
||||
| 0; /* clear MCAN_RXF1C_F1OM */
|
||||
/* Dedicated Rx Buffers
|
||||
* Note: the HW does not know (and does not care about) how many
|
||||
* dedicated Rx Buffers are used by the application. */
|
||||
mcan->MCAN_RXBC =
|
||||
MCAN_RXBC_RBSA((uint32_t)set->ram_array_rx >> 2);
|
||||
/* Tx Event FIFO */
|
||||
mcan->MCAN_TXEFC =
|
||||
MCAN_TXEFC_EFSA((uint32_t)set->ram_fifo_tx_evt >> 2)
|
||||
| MCAN_TXEFC_EFS(cfg->fifo_size_tx_evt)
|
||||
| MCAN_TXEFC_EFWM(0);
|
||||
/* Tx Buffers */
|
||||
mcan->MCAN_TXBC =
|
||||
MCAN_TXBC_TBSA((uint32_t)set->ram_array_tx >> 2)
|
||||
| MCAN_TXBC_NDTB(cfg->array_size_tx)
|
||||
| MCAN_TXBC_TFQS(cfg->fifo_size_tx)
|
||||
| 0; /* clear MCAN_TXBC_TFQM */
|
||||
|
||||
/* Configure the size of data fields in Rx and Tx Buffer Elements */
|
||||
if (!get_length_code(cfg->buf_size_rx_fifo0, &dlc))
|
||||
return false;
|
||||
regVal32 = MCAN_RXESC_F0DS(dlc < CAN_DLC_8 ? 0 : dlc - CAN_DLC_8);
|
||||
if (!get_length_code(cfg->buf_size_rx_fifo1, &dlc))
|
||||
return false;
|
||||
regVal32 |= MCAN_RXESC_F1DS(dlc < CAN_DLC_8 ? 0 : dlc - CAN_DLC_8);
|
||||
if (!get_length_code(cfg->buf_size_rx, &dlc))
|
||||
return false;
|
||||
regVal32 |= MCAN_RXESC_RBDS(dlc < CAN_DLC_8 ? 0 : dlc - CAN_DLC_8);
|
||||
mcan->MCAN_RXESC = regVal32;
|
||||
if (!get_length_code(cfg->buf_size_tx, &dlc))
|
||||
return false;
|
||||
mcan->MCAN_TXESC =
|
||||
MCAN_TXESC_TBDS(dlc < CAN_DLC_8 ? 0 : dlc - CAN_DLC_8);
|
||||
|
||||
/* Configure Message ID Filters
|
||||
* ...Disable all standard filters */
|
||||
for (element = set->ram_filt_std, elem_end = set->ram_filt_std
|
||||
+ (uint32_t)cfg->array_size_filt_std * MCAN_RAM_FILT_STD_SIZE;
|
||||
element < elem_end;
|
||||
element += MCAN_RAM_FILT_STD_SIZE)
|
||||
element[0] = MCAN_RAM_FILT_SFEC_DIS;
|
||||
/* ...Disable all extended filters */
|
||||
for (element = set->ram_filt_ext, elem_end = set->ram_filt_ext
|
||||
+ (uint32_t)cfg->array_size_filt_ext * MCAN_RAM_FILT_EXT_SIZE;
|
||||
element < elem_end;
|
||||
element += MCAN_RAM_FILT_EXT_SIZE)
|
||||
element[0] = MCAN_RAM_FILT_EFEC_DIS;
|
||||
|
||||
mcan->MCAN_NDAT1 = 0xFFFFFFFF; /* clear new (rx) data flags */
|
||||
mcan->MCAN_NDAT2 = 0xFFFFFFFF; /* clear new (rx) data flags */
|
||||
|
||||
regVal32 = mcan->MCAN_CCCR & ~(MCAN_CCCR_BRSE | MCAN_CCCR_FDOE);
|
||||
mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_PXHD | MCAN_CCCR_BRSE_DISABLED
|
||||
| MCAN_CCCR_FDOE_DISABLED;
|
||||
|
||||
DSB();
|
||||
ISB();
|
||||
return true;
|
||||
}
|
||||
|
||||
void mcan_reconfigure(struct mcan_set *set)
|
||||
{
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
uint32_t regVal32;
|
||||
|
||||
regVal32 = mcan->MCAN_CCCR & ~MCAN_CCCR_CCE;
|
||||
assert((regVal32 & MCAN_CCCR_INIT) == MCAN_CCCR_INIT_ENABLED);
|
||||
/* Enable writing to configuration registers */
|
||||
mcan->MCAN_CCCR = regVal32 | MCAN_CCCR_CCE_CONFIGURABLE;
|
||||
}
|
||||
|
||||
void mcan_set_mode(struct mcan_set *set, enum mcan_can_mode mode)
|
||||
{
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
uint32_t regVal32;
|
||||
|
||||
regVal32 = mcan->MCAN_CCCR & ~(MCAN_CCCR_BRSE | MCAN_CCCR_FDOE);
|
||||
switch (mode) {
|
||||
case MCAN_MODE_CAN:
|
||||
regVal32 |= MCAN_CCCR_BRSE_DISABLED | MCAN_CCCR_FDOE_DISABLED;
|
||||
break;
|
||||
case MCAN_MODE_EXT_LEN_CONST_RATE:
|
||||
regVal32 |= MCAN_CCCR_BRSE_DISABLED | MCAN_CCCR_FDOE_ENABLED;
|
||||
break;
|
||||
case MCAN_MODE_EXT_LEN_DUAL_RATE:
|
||||
regVal32 |= MCAN_CCCR_BRSE_ENABLED | MCAN_CCCR_FDOE_ENABLED;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
mcan->MCAN_CCCR = regVal32;
|
||||
}
|
||||
|
||||
enum mcan_can_mode mcan_get_mode(const struct mcan_set *set)
|
||||
{
|
||||
const uint32_t cccr = set->cfg.regs->MCAN_CCCR;
|
||||
|
||||
if ((cccr & MCAN_CCCR_FDOE) == MCAN_CCCR_FDOE_DISABLED)
|
||||
return MCAN_MODE_CAN;
|
||||
if ((cccr & MCAN_CCCR_BRSE) == MCAN_CCCR_BRSE_DISABLED)
|
||||
return MCAN_MODE_EXT_LEN_CONST_RATE;
|
||||
return MCAN_MODE_EXT_LEN_DUAL_RATE;
|
||||
}
|
||||
|
||||
void mcan_init_loopback(struct mcan_set *set)
|
||||
{
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
|
||||
mcan->MCAN_CCCR |= MCAN_CCCR_TEST_ENABLED;
|
||||
#if 0
|
||||
mcan->MCAN_CCCR |= MCAN_CCCR_MON_ENABLED; /* for internal loop back */
|
||||
#endif
|
||||
mcan->MCAN_TEST |= MCAN_TEST_LBCK_ENABLED;
|
||||
}
|
||||
|
||||
void mcan_set_tx_queue_mode(struct mcan_set *set)
|
||||
{
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
mcan->MCAN_TXBC |= MCAN_TXBC_TFQM;
|
||||
}
|
||||
|
||||
void mcan_enable(struct mcan_set *set)
|
||||
{
|
||||
uint32_t index, val;
|
||||
|
||||
/* Depending on bus condition, the HW may switch back to the
|
||||
* Initialization state, by itself. Therefore, upon timeout, return.
|
||||
* [Using an arbitrary timeout criterion.] */
|
||||
for (index = 0; index < 1024; index++) {
|
||||
val = set->cfg.regs->MCAN_CCCR;
|
||||
if ((val & MCAN_CCCR_INIT) == MCAN_CCCR_INIT_DISABLED)
|
||||
break;
|
||||
if (index == 0)
|
||||
set->cfg.regs->MCAN_CCCR = (val & ~MCAN_CCCR_INIT)
|
||||
| MCAN_CCCR_INIT_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
void mcan_disable(struct mcan_set *set)
|
||||
{
|
||||
uint32_t val;
|
||||
bool initial;
|
||||
|
||||
for (initial = true; true; initial = false) {
|
||||
val = set->cfg.regs->MCAN_CCCR;
|
||||
if ((val & MCAN_CCCR_INIT) == MCAN_CCCR_INIT_ENABLED)
|
||||
break;
|
||||
if (initial)
|
||||
set->cfg.regs->MCAN_CCCR = (val & ~MCAN_CCCR_INIT)
|
||||
| MCAN_CCCR_INIT_ENABLED;
|
||||
}
|
||||
}
|
||||
|
||||
void mcan_loopback_on(struct mcan_set *set)
|
||||
{
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
mcan->MCAN_TEST |= MCAN_TEST_LBCK_ENABLED;
|
||||
}
|
||||
|
||||
void mcan_loopback_off(struct mcan_set *set)
|
||||
{
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
mcan->MCAN_TEST &= ~MCAN_TEST_LBCK_ENABLED;
|
||||
}
|
||||
|
||||
void mcan_enable_rx_array_flag(struct mcan_set *set, uint8_t line)
|
||||
{
|
||||
assert(line == 0 || line == 1);
|
||||
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
if (line) {
|
||||
mcan->MCAN_ILS |= MCAN_ILS_DRXL;
|
||||
mcan->MCAN_ILE |= MCAN_ILE_EINT1;
|
||||
} else {
|
||||
mcan->MCAN_ILS &= ~MCAN_ILS_DRXL;
|
||||
mcan->MCAN_ILE |= MCAN_ILE_EINT0;
|
||||
}
|
||||
mcan->MCAN_IR = MCAN_IR_DRX; /* clear previous flag */
|
||||
mcan->MCAN_IE |= MCAN_IE_DRXE; /* enable it */
|
||||
}
|
||||
|
||||
uint8_t * mcan_prepare_tx_buffer(struct mcan_set *set, uint8_t buf_idx,
|
||||
uint32_t id, uint8_t len)
|
||||
{
|
||||
assert(buf_idx < set->cfg.array_size_tx);
|
||||
assert(len <= set->cfg.buf_size_tx);
|
||||
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
uint32_t *pThisTxBuf = 0;
|
||||
uint32_t val;
|
||||
const enum mcan_can_mode mode = mcan_get_mode(set);
|
||||
enum mcan_dlc dlc;
|
||||
|
||||
if (buf_idx >= set->cfg.array_size_tx)
|
||||
return NULL;
|
||||
if (!get_length_code(len, &dlc))
|
||||
dlc = CAN_DLC_0;
|
||||
pThisTxBuf = set->ram_array_tx + buf_idx
|
||||
* (MCAN_RAM_BUF_HDR_SIZE + set->cfg.buf_size_tx / 4);
|
||||
if (mcan_is_extended_id(id))
|
||||
*pThisTxBuf++ = MCAN_RAM_BUF_XTD | MCAN_RAM_BUF_ID_XTD(id);
|
||||
else
|
||||
*pThisTxBuf++ = MCAN_RAM_BUF_ID_STD(id);
|
||||
val = MCAN_RAM_BUF_MM(0) | MCAN_RAM_BUF_DLC((uint32_t)dlc);
|
||||
if (mode == MCAN_MODE_EXT_LEN_CONST_RATE)
|
||||
val |= MCAN_RAM_BUF_FDF;
|
||||
else if (mode == MCAN_MODE_EXT_LEN_DUAL_RATE)
|
||||
val |= MCAN_RAM_BUF_FDF | MCAN_RAM_BUF_BRS;
|
||||
*pThisTxBuf++ = val;
|
||||
/* enable transmit from buffer to set TC interrupt bit in IR,
|
||||
* but interrupt will not happen unless TC interrupt is enabled */
|
||||
mcan->MCAN_TXBTIE = (1 << buf_idx);
|
||||
return (uint8_t *)pThisTxBuf; /* now it points to the data field */
|
||||
}
|
||||
|
||||
void mcan_send_tx_buffer(struct mcan_set *set, uint8_t buf_idx)
|
||||
{
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
|
||||
if (buf_idx < set->cfg.array_size_tx)
|
||||
mcan->MCAN_TXBAR = (1 << buf_idx);
|
||||
}
|
||||
|
||||
uint8_t mcan_enqueue_outgoing_msg(struct mcan_set *set, uint32_t id,
|
||||
uint8_t len, const uint8_t *data)
|
||||
{
|
||||
assert(len <= set->cfg.buf_size_tx);
|
||||
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
uint32_t val;
|
||||
uint32_t *pThisTxBuf = 0;
|
||||
const enum mcan_can_mode mode = mcan_get_mode(set);
|
||||
enum mcan_dlc dlc;
|
||||
uint8_t putIdx = 255;
|
||||
|
||||
if (!get_length_code(len, &dlc))
|
||||
dlc = CAN_DLC_0;
|
||||
/* Configured for FifoQ and FifoQ not full? */
|
||||
if (set->cfg.fifo_size_tx == 0 || (mcan->MCAN_TXFQS & MCAN_TXFQS_TFQF))
|
||||
return putIdx;
|
||||
putIdx = (uint8_t)((mcan->MCAN_TXFQS & MCAN_TXFQS_TFQPI_Msk)
|
||||
>> MCAN_TXFQS_TFQPI_Pos);
|
||||
pThisTxBuf = set->ram_array_tx + (uint32_t)
|
||||
putIdx * (MCAN_RAM_BUF_HDR_SIZE + set->cfg.buf_size_tx / 4);
|
||||
if (mcan_is_extended_id(id))
|
||||
*pThisTxBuf++ = MCAN_RAM_BUF_XTD | MCAN_RAM_BUF_ID_XTD(id);
|
||||
else
|
||||
*pThisTxBuf++ = MCAN_RAM_BUF_ID_STD(id);
|
||||
val = MCAN_RAM_BUF_MM(0) | MCAN_RAM_BUF_DLC((uint32_t)dlc);
|
||||
if (mode == MCAN_MODE_EXT_LEN_CONST_RATE)
|
||||
val |= MCAN_RAM_BUF_FDF;
|
||||
else if (mode == MCAN_MODE_EXT_LEN_DUAL_RATE)
|
||||
val |= MCAN_RAM_BUF_FDF | MCAN_RAM_BUF_BRS;
|
||||
*pThisTxBuf++ = val;
|
||||
memcpy(pThisTxBuf, data, len);
|
||||
/* enable transmit from buffer to set TC interrupt bit in IR,
|
||||
* but interrupt will not happen unless TC interrupt is enabled
|
||||
*/
|
||||
mcan->MCAN_TXBTIE = (1 << putIdx);
|
||||
/* request to send */
|
||||
mcan->MCAN_TXBAR = (1 << putIdx);
|
||||
return putIdx;
|
||||
}
|
||||
|
||||
bool mcan_is_buffer_sent(const struct mcan_set *set, uint8_t buf_idx)
|
||||
{
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
return mcan->MCAN_TXBTO & (1 << buf_idx) ? true : false;
|
||||
}
|
||||
|
||||
void mcan_filter_single_id(struct mcan_set *set,
|
||||
uint8_t buf_idx, uint8_t filter, uint32_t id)
|
||||
{
|
||||
assert(buf_idx < set->cfg.array_size_rx);
|
||||
assert(id & CAN_EXT_MSG_ID ? filter < set->cfg.array_size_filt_ext
|
||||
: filter < set->cfg.array_size_filt_std);
|
||||
assert(id & CAN_EXT_MSG_ID ? (id & ~CAN_EXT_MSG_ID) <= 0x1fffffff :
|
||||
id <= 0x7ff);
|
||||
|
||||
uint32_t *pThisRxFilt = 0;
|
||||
|
||||
if (buf_idx >= set->cfg.array_size_rx)
|
||||
return;
|
||||
if (mcan_is_extended_id(id)) {
|
||||
pThisRxFilt = set->ram_filt_ext + filter
|
||||
* MCAN_RAM_FILT_EXT_SIZE;
|
||||
*pThisRxFilt++ = MCAN_RAM_FILT_EFEC_BUF
|
||||
| MCAN_RAM_FILT_EFID1(id);
|
||||
*pThisRxFilt = MCAN_RAM_FILT_EFID2_BUF
|
||||
| MCAN_RAM_FILT_EFID2_BUF_IDX(buf_idx);
|
||||
} else {
|
||||
pThisRxFilt = set->ram_filt_std + filter
|
||||
* MCAN_RAM_FILT_STD_SIZE;
|
||||
*pThisRxFilt = MCAN_RAM_FILT_SFEC_BUF
|
||||
| MCAN_RAM_FILT_SFID1(id)
|
||||
| MCAN_RAM_FILT_SFID2_BUF
|
||||
| MCAN_RAM_FILT_SFID2_BUF_IDX(buf_idx);
|
||||
}
|
||||
}
|
||||
|
||||
void mcan_filter_id_mask(struct mcan_set *set, uint8_t fifo, uint8_t filter,
|
||||
uint32_t id, uint32_t mask)
|
||||
{
|
||||
assert(fifo == 0 || fifo == 1);
|
||||
assert(id & CAN_EXT_MSG_ID ? filter < set->cfg.array_size_filt_ext
|
||||
: filter < set->cfg.array_size_filt_std);
|
||||
assert(id & CAN_EXT_MSG_ID ? (id & ~CAN_EXT_MSG_ID) <= 0x1fffffff :
|
||||
id <= 0x7ff);
|
||||
assert(id & CAN_EXT_MSG_ID ? mask <= 0x1fffffff : mask <= 0x7ff);
|
||||
|
||||
uint32_t *pThisRxFilt = 0;
|
||||
uint32_t val;
|
||||
|
||||
if (mcan_is_extended_id(id)) {
|
||||
pThisRxFilt = set->ram_filt_ext + filter
|
||||
* MCAN_RAM_FILT_EXT_SIZE;
|
||||
*pThisRxFilt++ = (fifo ? MCAN_RAM_FILT_EFEC_FIFO1
|
||||
: MCAN_RAM_FILT_EFEC_FIFO0) | MCAN_RAM_FILT_EFID1(id);
|
||||
*pThisRxFilt = MCAN_RAM_FILT_EFT_CLASSIC
|
||||
| MCAN_RAM_FILT_EFID2(mask);
|
||||
} else {
|
||||
pThisRxFilt = set->ram_filt_std + filter
|
||||
* MCAN_RAM_FILT_STD_SIZE;
|
||||
val = MCAN_RAM_FILT_SFT_CLASSIC
|
||||
| MCAN_RAM_FILT_SFID1(id)
|
||||
| MCAN_RAM_FILT_SFID2(mask);
|
||||
*pThisRxFilt = (fifo ? MCAN_RAM_FILT_SFEC_FIFO1
|
||||
: MCAN_RAM_FILT_SFEC_FIFO0) | val;
|
||||
}
|
||||
}
|
||||
|
||||
bool mcan_rx_buffer_data(const struct mcan_set *set, uint8_t buf_idx)
|
||||
{
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
|
||||
if (buf_idx < 32)
|
||||
return mcan->MCAN_NDAT1 & (1 << buf_idx) ? true : false;
|
||||
else if (buf_idx < 64)
|
||||
return mcan->MCAN_NDAT2 & (1 << (buf_idx - 32)) ? true : false;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void mcan_read_rx_buffer(struct mcan_set *set, uint8_t buf_idx,
|
||||
struct mcan_msg_info *msg)
|
||||
{
|
||||
assert(buf_idx < set->cfg.array_size_rx);
|
||||
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
const uint32_t *pThisRxBuf = 0;
|
||||
uint32_t tempRy; /* temp copy of RX buffer word */
|
||||
uint8_t len;
|
||||
|
||||
if (buf_idx >= set->cfg.array_size_rx) {
|
||||
msg->id = 0;
|
||||
msg->timestamp = 0;
|
||||
msg->full_len = 0;
|
||||
msg->data_len = 0;
|
||||
return;
|
||||
}
|
||||
pThisRxBuf = set->ram_array_rx + (buf_idx
|
||||
* (MCAN_RAM_BUF_HDR_SIZE + set->cfg.buf_size_rx / 4));
|
||||
tempRy = *pThisRxBuf++; /* word R0 contains ID */
|
||||
if (tempRy & MCAN_RAM_BUF_XTD)
|
||||
msg->id = CAN_EXT_MSG_ID | (tempRy & MCAN_RAM_BUF_ID_XTD_Msk)
|
||||
>> MCAN_RAM_BUF_ID_XTD_Pos;
|
||||
else
|
||||
msg->id = (tempRy & MCAN_RAM_BUF_ID_STD_Msk)
|
||||
>> MCAN_RAM_BUF_ID_STD_Pos;
|
||||
tempRy = *pThisRxBuf++; /* word R1 contains DLC & time stamp */
|
||||
msg->full_len = len = get_data_length((enum mcan_dlc)
|
||||
((tempRy & MCAN_RAM_BUF_DLC_Msk) >> MCAN_RAM_BUF_DLC_Pos));
|
||||
msg->timestamp = (tempRy & MCAN_RAM_BUF_RXTS_Msk)
|
||||
>> MCAN_RAM_BUF_RXTS_Pos;
|
||||
if (msg->data) {
|
||||
/* copy the data from the Rx Buffer Element to the
|
||||
* application-owned buffer */
|
||||
if (len > set->cfg.buf_size_rx)
|
||||
len = set->cfg.buf_size_rx;
|
||||
if (len > msg->data_len)
|
||||
len = msg->data_len;
|
||||
memcpy(msg->data, pThisRxBuf, len);
|
||||
msg->data_len = len;
|
||||
}
|
||||
else
|
||||
msg->data_len = 0;
|
||||
/* clear the new data flag for the buffer */
|
||||
if (buf_idx < 32)
|
||||
mcan->MCAN_NDAT1 = (1 << buf_idx);
|
||||
else
|
||||
mcan->MCAN_NDAT2 = (1 << (buf_idx - 32));
|
||||
}
|
||||
|
||||
uint8_t mcan_dequeue_received_msg(struct mcan_set *set, uint8_t fifo,
|
||||
struct mcan_msg_info *msg)
|
||||
{
|
||||
assert(fifo == 0 || fifo == 1);
|
||||
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
uint32_t *pThisRxBuf = 0;
|
||||
uint32_t tempRy; /* temp copy of RX buffer word */
|
||||
uint8_t buf_elem_data_size, len;
|
||||
uint32_t *fifo_ack_reg;
|
||||
uint32_t get_index;
|
||||
uint8_t fill_level = 0; /* default: fifo empty */
|
||||
|
||||
if (fifo) {
|
||||
get_index = (mcan->MCAN_RXF1S & MCAN_RXF1S_F1GI_Msk) >>
|
||||
MCAN_RXF1S_F1GI_Pos;
|
||||
fill_level = (uint8_t)((mcan->MCAN_RXF1S & MCAN_RXF1S_F1FL_Msk)
|
||||
>> MCAN_RXF1S_F1FL_Pos);
|
||||
pThisRxBuf = set->ram_fifo_rx1;
|
||||
buf_elem_data_size = set->cfg.buf_size_rx_fifo1;
|
||||
fifo_ack_reg = (uint32_t *) & mcan->MCAN_RXF1A;
|
||||
} else {
|
||||
get_index = (mcan->MCAN_RXF0S & MCAN_RXF0S_F0GI_Msk)
|
||||
>> MCAN_RXF0S_F0GI_Pos;
|
||||
fill_level = (uint8_t)((mcan->MCAN_RXF0S & MCAN_RXF0S_F0FL_Msk)
|
||||
>> MCAN_RXF0S_F0FL_Pos);
|
||||
pThisRxBuf = set->ram_fifo_rx0;
|
||||
buf_elem_data_size = set->cfg.buf_size_rx_fifo0;
|
||||
fifo_ack_reg = (uint32_t *) & mcan->MCAN_RXF0A;
|
||||
}
|
||||
|
||||
if (fill_level == 0)
|
||||
return 0;
|
||||
|
||||
pThisRxBuf += get_index * (MCAN_RAM_BUF_HDR_SIZE + buf_elem_data_size
|
||||
/ 4);
|
||||
tempRy = *pThisRxBuf++; /* word R0 contains ID */
|
||||
if (tempRy & MCAN_RAM_BUF_XTD)
|
||||
msg->id = CAN_EXT_MSG_ID | (tempRy & MCAN_RAM_BUF_ID_XTD_Msk)
|
||||
>> MCAN_RAM_BUF_ID_XTD_Pos;
|
||||
else
|
||||
msg->id = (tempRy & MCAN_RAM_BUF_ID_STD_Msk)
|
||||
>> MCAN_RAM_BUF_ID_STD_Pos;
|
||||
tempRy = *pThisRxBuf++; /* word R1 contains DLC & timestamps */
|
||||
msg->full_len = len = get_data_length((enum mcan_dlc)
|
||||
((tempRy & MCAN_RAM_BUF_DLC_Msk) >> MCAN_RAM_BUF_DLC_Pos));
|
||||
msg->timestamp = (tempRy & MCAN_RAM_BUF_RXTS_Msk)
|
||||
>> MCAN_RAM_BUF_RXTS_Pos;
|
||||
if (msg->data) {
|
||||
/* copy the data from the Rx Buffer Element to the
|
||||
* application-owned buffer */
|
||||
if (len > buf_elem_data_size)
|
||||
len = buf_elem_data_size;
|
||||
if (len > msg->data_len)
|
||||
len = msg->data_len;
|
||||
memcpy(msg->data, pThisRxBuf, len);
|
||||
msg->data_len = len;
|
||||
}
|
||||
else
|
||||
msg->data_len = 0;
|
||||
/* acknowledge reading the fifo entry */
|
||||
*fifo_ack_reg = get_index;
|
||||
/* return entries remaining in FIFO */
|
||||
return (fill_level);
|
||||
}
|
||||
|
||||
/**@}*/
|
|
@ -0,0 +1,439 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \section Purpose
|
||||
*
|
||||
* Controller Area Network with Flexible Data-rate.
|
||||
* Interface for configuring and using the MCAN peripheral.
|
||||
*/
|
||||
|
||||
#ifndef _MCAN_H_
|
||||
#define _MCAN_H_
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Definitions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
enum mcan_can_mode
|
||||
{
|
||||
/* ISO 11898-1 CAN mode */
|
||||
MCAN_MODE_CAN,
|
||||
|
||||
/* Long CAN FD frame.
|
||||
* - TX and RX payloads up to 64 bytes.
|
||||
* - Slow transmitter: TX frames are sent at constant bit rate.
|
||||
* - Fast receiver: both constant-rate (slow) and dual-rate (fast)
|
||||
* RX frames are supported and received. */
|
||||
MCAN_MODE_EXT_LEN_CONST_RATE,
|
||||
|
||||
/* Long and fast CAN FD frame.
|
||||
* - TX and RX payloads up to 64 bytes.
|
||||
* - Fast transmitter: control, data and CRC fields are transmitted at a
|
||||
* higher bit rate.
|
||||
* - Fast receiver. */
|
||||
MCAN_MODE_EXT_LEN_DUAL_RATE,
|
||||
};
|
||||
|
||||
/* Flag signalling a standard (11-bit) message identifiers */
|
||||
#define CAN_STD_MSG_ID (0x0u << 30)
|
||||
/* Flag to be bitwise or'ed to extended (29-bit) message identifiers */
|
||||
#define CAN_EXT_MSG_ID (0x1u << 30)
|
||||
|
||||
struct mcan_msg_info
|
||||
{
|
||||
uint32_t id;
|
||||
uint32_t timestamp;
|
||||
uint8_t *data;
|
||||
uint8_t full_len;
|
||||
uint8_t data_len;
|
||||
};
|
||||
|
||||
struct mcan_config
|
||||
{
|
||||
uint32_t id; /* peripheral ID (ID_xxx) */
|
||||
Mcan *regs; /* set of MCAN hardware registers */
|
||||
uint32_t *msg_ram; /* base address of the Message RAM to be
|
||||
* assigned to this MCAN instance */
|
||||
|
||||
uint8_t array_size_filt_std; /* # of 11-bit Message ID Rx Filters */
|
||||
uint8_t array_size_filt_ext; /* # of 29-bit Message ID Rx Filters */
|
||||
uint8_t fifo_size_rx0; /* # of Rx Buffers in Rx FIFO 0 */
|
||||
uint8_t fifo_size_rx1; /* # of Rx Buffers in Rx FIFO 1 */
|
||||
uint8_t array_size_rx; /* # of dedicated Rx Buffers */
|
||||
uint8_t fifo_size_tx_evt; /* # of Tx Event Elements in the Tx Event
|
||||
* FIFO */
|
||||
uint8_t array_size_tx; /* # of dedicated Tx Buffers */
|
||||
uint8_t fifo_size_tx; /* # of Tx Buffers in the Tx FIFO or Tx
|
||||
* Queue */
|
||||
|
||||
uint8_t buf_size_rx_fifo0; /* size of the data field in each Rx
|
||||
* Buffer of Rx FIFO 0, in bytes */
|
||||
uint8_t buf_size_rx_fifo1; /* size of the data field in each Rx
|
||||
* Buffer of Rx FIFO 1, in bytes */
|
||||
uint8_t buf_size_rx; /* size of the data field in each
|
||||
* dedicated Rx Buffer, in bytes */
|
||||
uint8_t buf_size_tx; /* size of the data field in each Tx
|
||||
* Buffer, in bytes. Applies to all Tx
|
||||
* Buffers, dedicated and in Tx FIFO /
|
||||
* Queue. */
|
||||
|
||||
uint32_t bit_rate; /* requested CAN bit rate in CAN mode,
|
||||
* in bps */
|
||||
uint16_t quanta_before_sp; /* duration of the time segment before the
|
||||
* sample point (Sync_Seg + Prop_Seg +
|
||||
* Phase_Seg1), while in CAN mode,
|
||||
* expressed in CAN time quanta */
|
||||
uint8_t quanta_after_sp; /* duration of the time segment after the
|
||||
* sample point (Phase_Seg2), while in CAN
|
||||
* mode, expressed in CAN time quanta */
|
||||
|
||||
uint32_t bit_rate_fd; /* requested CAN bit rate in fast CAN FD
|
||||
* mode, in bps */
|
||||
uint8_t quanta_before_sp_fd; /* duration of the time segment before the
|
||||
* sample point (Sync_Seg + Prop_Seg +
|
||||
* Phase_Seg1), while in fast CAN FD mode,
|
||||
* expressed in CAN time quanta */
|
||||
uint8_t quanta_after_sp_fd; /* duration of the time segment after the
|
||||
* sample point (Phase_Seg2), while in
|
||||
* fast CAN FD mode, expressed in CAN time
|
||||
* quanta */
|
||||
|
||||
uint8_t quanta_sync_jump; /* duration of a (re)synchronization jump,
|
||||
* while in CAN mode, expressed in CAN
|
||||
* time quanta */
|
||||
uint8_t quanta_sync_jump_fd; /* duration of a (re)synchronization jump,
|
||||
* while in fast CAN FD mode, expressed in
|
||||
* CAN time quanta */
|
||||
};
|
||||
|
||||
/* This structure is private to the MCAN Driver.
|
||||
* Allocate it but ignore its members. */
|
||||
struct mcan_set
|
||||
{
|
||||
struct mcan_config cfg;
|
||||
uint32_t *ram_filt_std;
|
||||
uint32_t *ram_filt_ext;
|
||||
uint32_t *ram_fifo_rx0;
|
||||
uint32_t *ram_fifo_rx1;
|
||||
uint32_t *ram_array_rx;
|
||||
uint32_t *ram_fifo_tx_evt;
|
||||
uint32_t *ram_array_tx;
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported symbols
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline bool mcan_is_enabled(const struct mcan_set *set)
|
||||
{
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
return ((mcan->MCAN_CCCR & MCAN_CCCR_INIT) == MCAN_CCCR_INIT_DISABLED);
|
||||
}
|
||||
|
||||
static inline bool mcan_is_extended_id(uint32_t msg_id)
|
||||
{
|
||||
return msg_id & CAN_EXT_MSG_ID ? true : false;
|
||||
}
|
||||
|
||||
static inline uint32_t mcan_get_id(uint32_t msg_id)
|
||||
{
|
||||
return msg_id & CAN_EXT_MSG_ID ? msg_id & 0x1fffffff : msg_id & 0x7ff;
|
||||
}
|
||||
|
||||
static inline bool mcan_is_tx_complete(const struct mcan_set *set)
|
||||
{
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
return mcan->MCAN_IR & MCAN_IR_TC ? true : false;
|
||||
}
|
||||
|
||||
static inline void mcan_clear_tx_flag(const struct mcan_set *set)
|
||||
{
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
mcan->MCAN_IR = MCAN_IR_TC;
|
||||
}
|
||||
|
||||
static inline bool mcan_rx_array_data(const struct mcan_set *set)
|
||||
{
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
return mcan->MCAN_IR & MCAN_IR_DRX ? true : false;
|
||||
}
|
||||
|
||||
static inline void mcan_clear_rx_array_flag(const struct mcan_set *set)
|
||||
{
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
mcan->MCAN_IR = MCAN_IR_DRX;
|
||||
}
|
||||
|
||||
static inline bool mcan_rx_fifo_data(const struct mcan_set *set, uint8_t fifo)
|
||||
{
|
||||
assert(fifo == 0 || fifo == 1);
|
||||
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
|
||||
return mcan->MCAN_IR & (fifo ? MCAN_IR_RF1N : MCAN_IR_RF0N) ? true
|
||||
: false;
|
||||
}
|
||||
|
||||
static inline void mcan_clear_rx_fifo_flag(const struct mcan_set *set,
|
||||
uint8_t fifo)
|
||||
{
|
||||
assert(fifo == 0 || fifo == 1);
|
||||
|
||||
Mcan *mcan = set->cfg.regs;
|
||||
|
||||
mcan->MCAN_IR = fifo ? MCAN_IR_RF1N : MCAN_IR_RF0N;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Compute the size of the Message RAM to be assigned to the MCAN.
|
||||
* \param cfg MCAN configuration to be considered. Only integer size parameters
|
||||
* need to be configured. The other parameters can be left blank at this stage.
|
||||
* \param size address where the required size of the Message RAM will be
|
||||
* written, expressed in (32-bit) words.
|
||||
* \return true if successful, false if a parameter is set to an unsupported
|
||||
* value.
|
||||
*/
|
||||
bool mcan_configure_msg_ram(const struct mcan_config *cfg, uint32_t *size);
|
||||
|
||||
/**
|
||||
* \brief Initialize the MCAN hardware for the given peripheral.
|
||||
* Default: Non-FD, ISO 11898-1 CAN mode; mixed mode TX Buffer + FIFO.
|
||||
* \param set Pointer to uninitialized driver instance data.
|
||||
* \param cfg MCAN configuration to be used.
|
||||
* \return true if successful, false if a parameter is set to an unsupported
|
||||
* value.
|
||||
*/
|
||||
bool mcan_initialize(struct mcan_set *set, const struct mcan_config *cfg);
|
||||
|
||||
/**
|
||||
* \brief Unlock the peripheral configuration so it can be altered.
|
||||
* Prerequisite: the peripheral shall be disabled. In case the device has been
|
||||
* enabled, call mcan_disable.
|
||||
* \param set Pointer to driver instance data.
|
||||
*/
|
||||
void mcan_reconfigure(struct mcan_set *set);
|
||||
|
||||
/**
|
||||
* \brief Select either the legacy ISO 11898-1 CAN mode or the CAN-FD mode,
|
||||
* along with the FD variant in the latter case.
|
||||
* Should be called further to mcan_initialize() or mcan_reconfigure(), before
|
||||
* mcan_enable().
|
||||
* \param set Pointer to driver instance data.
|
||||
* \param mode CAN mode, and FD variant in case of FD mode.
|
||||
*/
|
||||
void mcan_set_mode(struct mcan_set *set, enum mcan_can_mode mode);
|
||||
|
||||
/**
|
||||
* \brief Query the current CAN mode.
|
||||
* \param set Pointer to driver instance data.
|
||||
* \return Currently selected CAN mode, and FD variant in case of CAN FD mode.
|
||||
*/
|
||||
enum mcan_can_mode mcan_get_mode(const struct mcan_set *set);
|
||||
|
||||
/**
|
||||
* \brief Select the TX Queue mode, disable TX FIFO mode.
|
||||
* INIT must be set - so this should be called between mcan_initialize() and
|
||||
* mcan_enable().
|
||||
* \param set Pointer to driver instance data.
|
||||
*/
|
||||
void mcan_set_tx_queue_mode(struct mcan_set *set);
|
||||
|
||||
/**
|
||||
* \brief Initialize the MCAN in loop back mode.
|
||||
* INIT must be set - so this should be called between mcan_initialize() and
|
||||
* mcan_enable().
|
||||
* \param set Pointer to driver instance data.
|
||||
*/
|
||||
void mcan_init_loopback(struct mcan_set *set);
|
||||
|
||||
/**
|
||||
* \brief Enable the peripheral I/O stage. Synchronize with the bus.
|
||||
* INIT must be set - so this should be called after mcan_initialize().
|
||||
* \param set Pointer to driver instance data.
|
||||
*/
|
||||
void mcan_enable(struct mcan_set *set);
|
||||
|
||||
/**
|
||||
* \brief Disable the peripheral I/O stage. Go Bus_Off.
|
||||
* \note Subsequent operations may include reconfiguring the peripheral
|
||||
* (mcan_reconfigure) and/or re-enabling it (mcan_enable).
|
||||
* \param set Pointer to driver instance data.
|
||||
*/
|
||||
void mcan_disable(struct mcan_set *set);
|
||||
|
||||
/**
|
||||
* \brief Turn the loop-back mode ON.
|
||||
* \note TEST must be set in MCAN_CCCR. This mode should have been enabled upon
|
||||
* initialization.
|
||||
* \param set Pointer to driver instance data.
|
||||
*/
|
||||
void mcan_loopback_on(struct mcan_set *set);
|
||||
|
||||
/**
|
||||
* \brief Turn the loop-back mode OFF.
|
||||
* \param set Pointer to driver instance data.
|
||||
*/
|
||||
void mcan_loopback_off(struct mcan_set *set);
|
||||
|
||||
/**
|
||||
* \brief Select either the m_can_int0 or the m_can_int1 interrupt line.
|
||||
* Also, enable the 'Message stored to Dedicated Receive Buffer' specific
|
||||
* interrupt.
|
||||
* \param set Pointer to driver instance data.
|
||||
* \param int_line The interrupt line to be enabled:
|
||||
* 0 -> m_can_int0
|
||||
* 1 -> m_can_int1.
|
||||
*/
|
||||
void mcan_enable_rx_array_flag(struct mcan_set *set, uint8_t int_line);
|
||||
|
||||
/**
|
||||
* \brief Configure a Dedicated TX Buffer.
|
||||
* \param set Pointer to driver instance data.
|
||||
* \param buf_idx Index of the dedicated transmit buffer to be used.
|
||||
* \param id Message ID.
|
||||
* \param len Data length, in bytes.
|
||||
* \return Address of data byte 0, part of the transmit buffer.
|
||||
*/
|
||||
uint8_t * mcan_prepare_tx_buffer(struct mcan_set *set, uint8_t buf_idx,
|
||||
uint32_t id, uint8_t len);
|
||||
|
||||
/**
|
||||
* \brief Start the transmission of a Dedicated TX Buffer.
|
||||
* \param set Pointer to driver instance data.
|
||||
* \param buf_idx Index of the dedicated transmit buffer to be used.
|
||||
*/
|
||||
void mcan_send_tx_buffer(struct mcan_set *set, uint8_t buf_idx);
|
||||
|
||||
/**
|
||||
* \brief Append the provided message to the TX FIFO, or to the TX Queue,
|
||||
* depending on whether mcan_set_tx_queue_mode() has been invoked or not.
|
||||
* \param set Pointer to driver instance data.
|
||||
* \param id Message ID.
|
||||
* \param len Data length, in bytes.
|
||||
* \param data Pointer to data.
|
||||
* \return Index of the assigned transmit buffer, part of the FIFO / queue.
|
||||
* Or 0xff if the TX FIFO / queue was full, or an error occurred.
|
||||
*/
|
||||
uint8_t mcan_enqueue_outgoing_msg(struct mcan_set *set, uint32_t id,
|
||||
uint8_t len, const uint8_t *data);
|
||||
|
||||
/**
|
||||
* \brief Check if message transmitted from the specified TX Buffer, either
|
||||
* dedicated or part of the TX FIFO or TX Queue.
|
||||
* \param set Pointer to driver instance data.
|
||||
* \param buf_idx Index of the transmit buffer to be queried.
|
||||
* \return true if the message has been successfully transmitted, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool mcan_is_buffer_sent(const struct mcan_set *set, uint8_t buf_idx);
|
||||
|
||||
/**
|
||||
* \brief Configure RX buffer filter.
|
||||
* \param set Pointer to driver instance data.
|
||||
* \param buf_idx Index of the receive buffer to be used as the recipient.
|
||||
* \param filter Index of the filter to be configured.
|
||||
* \param id Single message identifier. Incoming message need to match exactly
|
||||
* to be accepted.
|
||||
*/
|
||||
void mcan_filter_single_id(struct mcan_set *set, uint8_t buf_idx,
|
||||
uint8_t filter, uint32_t id);
|
||||
|
||||
/**
|
||||
* \brief Configure classic RX filter.
|
||||
* The classic filters direct the accepted messages to a FIFO, and include both
|
||||
* an ID and an ID mask.
|
||||
* \param set Pointer to driver instance data.
|
||||
* \param fifo Index of the RX FIFO to be used as the recipient.
|
||||
* \param filter Index of the filter to be configured.
|
||||
* \param id Message identifier.
|
||||
* \param mask Message identifier mask to be matched.
|
||||
*/
|
||||
void mcan_filter_id_mask(struct mcan_set *set, uint8_t fifo, uint8_t filter,
|
||||
uint32_t id, uint32_t mask);
|
||||
|
||||
/**
|
||||
* \brief Check whether some data has been received into the specified RX
|
||||
* Buffer.
|
||||
* \param set Pointer to driver instance data.
|
||||
* \param buf_idx Index of the receive buffer to be queried.
|
||||
* \return true if the receive buffer is flagged as containing an unfetched
|
||||
* frame, and false otherwise.
|
||||
*/
|
||||
bool mcan_rx_buffer_data(const struct mcan_set *set, uint8_t buf_idx);
|
||||
|
||||
/**
|
||||
* \brief Get RX buffer.
|
||||
* \param set Pointer to driver instance data.
|
||||
* \param buf_idx Index of the receive buffer to be read.
|
||||
* \param msg Address where the CAN message properties will be written.
|
||||
* The msg->data and msg->data_len parameters shall be initialized prior to
|
||||
* calling this function. Message contents will be copied to msg->data if
|
||||
* msg->data is not null and if msg->data_len is large enough.
|
||||
*/
|
||||
void mcan_read_rx_buffer(struct mcan_set *set, uint8_t buf_idx,
|
||||
struct mcan_msg_info *msg);
|
||||
|
||||
/**
|
||||
* \brief Detach one received message from the specified RX FIFO, and copy it to
|
||||
* a buffer owned by the application.
|
||||
* \param set Pointer to driver instance data.
|
||||
* \param fifo Index of the RX FIFO to dequeue from.
|
||||
* \param msg Address where the CAN message properties will be written.
|
||||
* The msg->data and msg->data_len parameters shall be initialized prior to
|
||||
* calling this function. Message contents will be copied to msg->data if
|
||||
* msg->data is not null and if msg->data_len is large enough.
|
||||
* \return: # of FIFO entries at the time the function was entered:
|
||||
* 0 -> The FIFO was initially empty.
|
||||
* 1 -> The FIFO had 1 entry upon entry, but is empty upon exit.
|
||||
* 2 to 64 -> The FIFO had several entries upon entry, and still holds one
|
||||
* or more entries upon exit.
|
||||
*/
|
||||
uint8_t mcan_dequeue_received_msg(struct mcan_set *set, uint8_t fifo,
|
||||
struct mcan_msg_info *msg);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef _MCAN_H_ */
|
|
@ -0,0 +1,359 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/mpddrc.h"
|
||||
#include "peripherals/sfrbu.h"
|
||||
#include "peripherals/pmc.h"
|
||||
#include "trace.h"
|
||||
#include "timer.h"
|
||||
#include "compiler.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
static void _set_ddr_timings(struct _mpddrc_desc* desc)
|
||||
{
|
||||
MPDDRC->MPDDRC_TPR0 = desc->tpr0;
|
||||
MPDDRC->MPDDRC_TPR1 = desc->tpr1;
|
||||
MPDDRC->MPDDRC_TPR2 = desc->tpr2;
|
||||
}
|
||||
|
||||
static uint32_t _compute_ba_offset(void)
|
||||
{
|
||||
/* Compute BA[] offset according to CR configuration */
|
||||
uint32_t offset = (MPDDRC->MPDDRC_CR & MPDDRC_CR_NC_Msk) + 9;
|
||||
if (!(MPDDRC->MPDDRC_CR & MPDDRC_CR_DECOD_INTERLEAVED))
|
||||
offset += ((MPDDRC->MPDDRC_CR & MPDDRC_CR_NR_Msk) >> 2) + 11;
|
||||
|
||||
offset += (MPDDRC->MPDDRC_MD & MPDDRC_MD_DBW) ? 1 : 2;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Send a NOP command
|
||||
*/
|
||||
static void _send_nop_cmd(void)
|
||||
{
|
||||
MPDDRC->MPDDRC_MR = MPDDRC_MR_MODE_NOP_CMD;
|
||||
/* Perform a write to a DDR memory access to acknoledge the command */
|
||||
*((uint32_t *)DDR_CS_ADDR) = 0;
|
||||
}
|
||||
|
||||
static void _send_lmr_cmd(void)
|
||||
{
|
||||
MPDDRC->MPDDRC_MR = MPDDRC_MR_MODE_LMR_CMD;
|
||||
/* Perform a write to a DDR memory access to acknoledge the command */
|
||||
*((uint32_t *)DDR_CS_ADDR) = 0u;
|
||||
}
|
||||
|
||||
static void _send_ext_lmr_cmd(uint32_t opcode, uint32_t ba_offset)
|
||||
{
|
||||
MPDDRC->MPDDRC_MR = MPDDRC_MR_MODE_EXT_LMR_CMD;
|
||||
/* Perform a write to a DDR memory access to acknoledge the command */
|
||||
*((uint32_t *)(DDR_CS_ADDR + (opcode << ba_offset))) = 0u;
|
||||
}
|
||||
|
||||
static void _send_normal_cmd(void)
|
||||
{
|
||||
MPDDRC->MPDDRC_MR = MPDDRC_MR_MODE_NORMAL_CMD;
|
||||
/* Perform a write to a DDR memory access to acknoledge the command */
|
||||
*((uint32_t *)DDR_CS_ADDR) = 0;
|
||||
}
|
||||
|
||||
static void _send_precharge_cmd(void)
|
||||
{
|
||||
MPDDRC->MPDDRC_MR = MPDDRC_MR_MODE_PRCGALL_CMD;
|
||||
/* Perform a write to a DDR memory access to acknoledge the command */
|
||||
*((uint32_t *)DDR_CS_ADDR) = 0;
|
||||
}
|
||||
|
||||
static void _send_refresh_cmd(void)
|
||||
{
|
||||
MPDDRC->MPDDRC_MR = MPDDRC_MR_MODE_RFSH_CMD;
|
||||
/* Perform a write to a DDR memory access to acknoledge the command */
|
||||
*((uint32_t *)DDR_CS_ADDR) = 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_DDR3
|
||||
|
||||
static void _send_calib_cmd(void)
|
||||
{
|
||||
MPDDRC->MPDDRC_MR = MPDDRC_MR_MODE_DEEP_CALIB_MD;
|
||||
/* Perform a write to a DDR memory access to acknoledge the command */
|
||||
*((uint32_t *)DDR_CS_ADDR) = 0;
|
||||
}
|
||||
|
||||
static void _configure_ddr3(struct _mpddrc_desc* desc)
|
||||
{
|
||||
/* Timings */
|
||||
_set_ddr_timings(desc);
|
||||
uint32_t ba_offset = _compute_ba_offset();
|
||||
|
||||
/*
|
||||
* Step 3: Issue a NOP command to the memory controller using
|
||||
* its mode register (MPDDRC_MR).
|
||||
*/
|
||||
_send_nop_cmd();
|
||||
|
||||
/*
|
||||
* Step 4: A pause of at least 500us must be observed before a
|
||||
* single toggle.
|
||||
*/
|
||||
timer_sleep(50);
|
||||
/*
|
||||
* Step 5: Issue a NOP command to the memory controller using
|
||||
* its mode register (MPDDRC_MR). CKE is now driven high.
|
||||
*/
|
||||
_send_nop_cmd();
|
||||
timer_sleep(1);
|
||||
/*
|
||||
* Step 6: Issue Extended Mode Register Set 2 (EMRS2) cycle to
|
||||
* choose between commercial or high temperature
|
||||
* operations.
|
||||
*/
|
||||
_send_ext_lmr_cmd(0x2, ba_offset);
|
||||
timer_sleep(1);
|
||||
/*
|
||||
* Step 7: Issue Extended Mode Register Set 3 (EMRS3) cycle to set
|
||||
* the Extended Mode Register to 0.
|
||||
*/
|
||||
_send_ext_lmr_cmd(0x3, ba_offset);
|
||||
timer_sleep(1);
|
||||
/*
|
||||
* Step 8: Issue Extended Mode Register Set 1 (EMRS1) cycle to
|
||||
* disable and to program O.D.S. (Output Driver Strength).
|
||||
*/
|
||||
_send_ext_lmr_cmd(0x1, ba_offset);
|
||||
timer_sleep(1);
|
||||
/*
|
||||
* Step 9: Write a one to the DLL bit (enable DLL reset) in the MPDDRC
|
||||
* Configuration Register (MPDDRC_CR)
|
||||
*/
|
||||
/* Not done for DDR3 */
|
||||
|
||||
/*
|
||||
* Step 10: Issue a Mode Register Set (MRS) cycle to reset DLL.
|
||||
*/
|
||||
_send_lmr_cmd();
|
||||
timer_sleep(5);
|
||||
/*
|
||||
* Step 11: Issue a Calibration command (MRS) cycle to calibrate RTT and
|
||||
* RON values for the Process Voltage Temperature (PVT).
|
||||
*/
|
||||
_send_calib_cmd();
|
||||
timer_sleep(1);
|
||||
|
||||
/*
|
||||
* Step 12: A Normal Mode command is provided.
|
||||
* Program the Normal mode in the MPDDRC_MR and perform a write access
|
||||
* to any DDR3-SDRAM address to acknowledge this command.
|
||||
*/
|
||||
_send_normal_cmd();
|
||||
/*
|
||||
* Step 13: Perform a write access to any DDR3-SDRAM address.
|
||||
*/
|
||||
*((uint32_t *)(DDR_CS_ADDR)) = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void _configure_ddr2(struct _mpddrc_desc* desc)
|
||||
{
|
||||
/* Timings */
|
||||
_set_ddr_timings(desc);
|
||||
uint32_t ba_offset = _compute_ba_offset();
|
||||
|
||||
/* Step 3: An NOP command is issued to the DDR2-SDRAM. Program
|
||||
* the NOP command into the Mode Register and wait minimum 200
|
||||
* us */
|
||||
_send_nop_cmd();
|
||||
timer_sleep(20);
|
||||
|
||||
/* Step 4: Issue a NOP command. */
|
||||
_send_nop_cmd();
|
||||
timer_sleep(1);
|
||||
|
||||
/* Step 5: Issue all banks precharge command. */
|
||||
_send_precharge_cmd();
|
||||
timer_sleep(1);
|
||||
|
||||
/* Step 6: Issue an Extended Mode Register set (EMRS2) cycle
|
||||
* to chose between commercialor high temperature
|
||||
* operations. */
|
||||
_send_ext_lmr_cmd(0x2, ba_offset);
|
||||
timer_sleep(1);
|
||||
|
||||
/* Step 7: Issue an Extended Mode Register set (EMRS3) cycle
|
||||
* to set all registers to 0. */
|
||||
_send_ext_lmr_cmd(0x3, ba_offset);
|
||||
timer_sleep(1);
|
||||
|
||||
/* Step 8: Issue an Extended Mode Register set (EMRS1) cycle
|
||||
* to enable DLL. */
|
||||
_send_ext_lmr_cmd(0x1, ba_offset);
|
||||
timer_sleep(1);
|
||||
|
||||
/* Step 9: Program DLL field into the Configuration Register. */
|
||||
MPDDRC->MPDDRC_CR |= MPDDRC_CR_DLL_RESET_ENABLED;
|
||||
|
||||
/* Step 10: A Mode Register set (MRS) cycle is issued to reset DLL. */
|
||||
MPDDRC->MPDDRC_MR = MPDDRC_MR_MODE_LMR_CMD;
|
||||
/* Perform a write to a DDR memory access to acknoledge the command */
|
||||
*((uint32_t *)DDR_CS_ADDR) = 0;
|
||||
|
||||
timer_sleep(1);
|
||||
|
||||
/* Step 11: Issue all banks precharge command to the DDR2-SDRAM. */
|
||||
_send_precharge_cmd();
|
||||
timer_sleep(1);
|
||||
|
||||
/* Step 12: Two auto-refresh (CBR) cycles are
|
||||
* provided. Program the auto refresh command (CBR) into the
|
||||
* Mode Register. */
|
||||
_send_refresh_cmd();
|
||||
timer_sleep(1);
|
||||
_send_refresh_cmd();
|
||||
timer_sleep(1);
|
||||
|
||||
/* Step 13: Program DLL field into the Configuration Register
|
||||
* to low(Disable DLL reset). */
|
||||
MPDDRC->MPDDRC_CR &= ~MPDDRC_CR_DLL_RESET_ENABLED;
|
||||
|
||||
/* Step 14: Issue a Mode Register set (MRS) cycle to program
|
||||
* the parameters of the DDR2-SDRAM devices. */
|
||||
_send_lmr_cmd();
|
||||
timer_sleep(1);
|
||||
|
||||
/* Step 15: Program OCD field into the Configuration Register
|
||||
* to high (OCD calibration default). */
|
||||
MPDDRC->MPDDRC_CR |= MPDDRC_CR_OCD_DDR2_DEFAULT_CALIB;
|
||||
|
||||
/* Step 16: An Extended Mode Register set (EMRS1) cycle is
|
||||
* issued to OCD default value. */
|
||||
_send_ext_lmr_cmd(0x1, ba_offset);
|
||||
timer_sleep(1);
|
||||
|
||||
/* Step 19,20: A mode Normal command is provided. Program the
|
||||
* Normal mode into Mode Register. */
|
||||
_send_normal_cmd();
|
||||
timer_sleep(1);
|
||||
}
|
||||
|
||||
extern void mpddrc_configure(struct _mpddrc_desc* desc)
|
||||
{
|
||||
/* Retrieve the current resolution to put it back later */
|
||||
uint32_t resolution = timer_get_resolution();
|
||||
/* Configure time to have 10 microseconds resolution */
|
||||
timer_configure(10);
|
||||
|
||||
/* controller and DDR clock */
|
||||
pmc_enable_peripheral(ID_MPDDRC);
|
||||
pmc_enable_system_clock(PMC_SYSTEM_CLOCK_DDR);
|
||||
|
||||
/* Step1: Program memory device type */
|
||||
MPDDRC->MPDDRC_MD = desc->mode;
|
||||
|
||||
/* set driver impedance */
|
||||
uint32_t value = MPDDRC->MPDDRC_IO_CALIBR;
|
||||
value &= ~MPDDRC_IO_CALIBR_RDIV_Msk;
|
||||
value &= ~MPDDRC_IO_CALIBR_TZQIO_Msk;
|
||||
value &= ~MPDDRC_IO_CALIBR_CALCODEP_Msk;
|
||||
value &= ~MPDDRC_IO_CALIBR_CALCODEN_Msk;
|
||||
value |= desc->io_calibr;
|
||||
MPDDRC->MPDDRC_IO_CALIBR = value;
|
||||
|
||||
MPDDRC->MPDDRC_RD_DATA_PATH = desc->data_path;
|
||||
|
||||
/* Step 2: Program features of the DDR3-SDRAM device in the
|
||||
* configuration register and timing parameter registers (TPR0
|
||||
* ans TPR1) */
|
||||
|
||||
/* Configurations */
|
||||
MPDDRC->MPDDRC_CR = desc->control;
|
||||
|
||||
#ifdef CONFIG_HAVE_DDR3_SELFREFRESH
|
||||
if (sfrbu_is_ddr_backup_enabled())
|
||||
/* DDR memory had been initilized and in backup mode */
|
||||
MPDDRC->MPDDRC_LPR =
|
||||
MPDDRC_LPR_LPCB_SELFREFRESH |
|
||||
MPDDRC_LPR_CLK_FR_ENABLED |
|
||||
MPDDRC_LPR_PASR(0) |
|
||||
MPDDRC_LPR_DS(2) |
|
||||
MPDDRC_LPR_TIMEOUT_NONE |
|
||||
MPDDRC_LPR_APDE_DDR2_FAST_EXIT |
|
||||
MPDDRC_LPR_UPD_MR(0);
|
||||
else
|
||||
/* DDR memory is not in backup mode */
|
||||
MPDDRC->MPDDRC_LPR =
|
||||
MPDDRC_LPR_LPCB_SELFREFRESH |
|
||||
MPDDRC_LPR_CLK_FR_ENABLED |
|
||||
MPDDRC_LPR_PASR(0) |
|
||||
MPDDRC_LPR_DS(2) |
|
||||
MPDDRC_LPR_TIMEOUT_DELAY_128_CLK |
|
||||
MPDDRC_LPR_APDE_DDR2_SLOW_EXIT |
|
||||
MPDDRC_LPR_UPD_MR(0);
|
||||
#endif
|
||||
|
||||
switch(desc->type) {
|
||||
#ifdef CONFIG_HAVE_DDR3
|
||||
case MPDDRC_TYPE_DDR3:
|
||||
#ifdef CONFIG_HAVE_DDR3_SELFREFRESH
|
||||
_set_ddr_timings(desc);
|
||||
/* Initialize DDR chip when needed */
|
||||
if (!sfrbu_is_ddr_backup_enabled())
|
||||
#endif
|
||||
_configure_ddr3(desc);
|
||||
break;
|
||||
#endif
|
||||
case MPDDRC_TYPE_DDR2:
|
||||
_configure_ddr2(desc);
|
||||
break;
|
||||
default:
|
||||
trace_error("Device not handled\r\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
/* Last step: Write the refresh rate */
|
||||
/* Refresh Timer is (64ms / (bank_size)) * master_clock */
|
||||
uint32_t master_clock = pmc_get_master_clock()/1000000;
|
||||
MPDDRC->MPDDRC_RTR = MPDDRC_RTR_COUNT(64000*master_clock/desc->bank);
|
||||
|
||||
/* wait for end of calibration */
|
||||
timer_sleep(1);
|
||||
|
||||
/* Restore resolution or put the default one if not already set */
|
||||
timer_configure(resolution);
|
||||
|
||||
#ifdef CONFIG_HAVE_DDR3_SELFREFRESH
|
||||
if (sfrbu_is_ddr_backup_enabled()) {
|
||||
MPDDRC->MPDDRC_MR = MPDDRC_MR_MODE_NORMAL_CMD;
|
||||
sfrbu_disable_ddr_backup();
|
||||
}
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef MPDDRC_HEADER_
|
||||
#define MPDDRC_HEADER_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum _ram_type {
|
||||
MPDDRC_TYPE_DDR3,
|
||||
MPDDRC_TYPE_LPDDR3,
|
||||
MPDDRC_TYPE_DDR2,
|
||||
MPDDRC_TYPE_LPDDR2,
|
||||
MPDDRC_TYPE_DDR
|
||||
};
|
||||
|
||||
struct _mpddrc_desc {
|
||||
enum _ram_type type;
|
||||
uint32_t io_calibr;
|
||||
uint32_t data_path;
|
||||
uint32_t mode;
|
||||
uint32_t control;
|
||||
uint32_t bank;
|
||||
uint32_t tpr0;
|
||||
uint32_t tpr1;
|
||||
uint32_t tpr2;
|
||||
};
|
||||
|
||||
extern void mpddrc_configure(struct _mpddrc_desc* desc);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,205 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _PIO_H
|
||||
#define _PIO_H
|
||||
|
||||
#define IRQ_PIO_HANDLERS_SIZE 16
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Global Types
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
struct _pin
|
||||
{
|
||||
uint8_t group; /*< The IO group containing the pins you want to use. */
|
||||
uint32_t mask; /*< Bitmask indicating which pin(s) to configure. */
|
||||
uint8_t type; /*< Pin type */
|
||||
uint32_t attribute; /*< Pin config attribute. */
|
||||
};
|
||||
|
||||
typedef void(*pio_handler_t)(uint32_t, uint32_t, void*);
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#if defined(CONFIG_HAVE_PIO4)
|
||||
#include "peripherals/pio4.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Configures a list of Pin instances.
|
||||
*
|
||||
* \details Each of them can either hold a single pin or a group of
|
||||
* pins, depending on the mask value; all pins are configured by this
|
||||
* function. The size of the array must also be provided and is easily
|
||||
* computed using ARRAY_SIZE whenever its length is not known in
|
||||
* advance.
|
||||
*
|
||||
* \param list Pointer to a list of Pin instances.
|
||||
* \param size Size of the Pin list (calculated using ARRAY_SIZE).
|
||||
*
|
||||
* \return 1 if the pins have been configured properly; otherwise 0.
|
||||
*/
|
||||
extern uint8_t pio_configure(const struct _pin *list, uint32_t size);
|
||||
|
||||
/**
|
||||
* \brief Sets a high output level on all the PIOs defined in the
|
||||
* given Pin instance.
|
||||
*
|
||||
* \details This has no immediate effects on PIOs that are not output,
|
||||
* but the PIO controller will memorize the value they are changed to
|
||||
* outputs.
|
||||
*
|
||||
* \param pin Pointer to a Pin instance describing one or more pins.
|
||||
*/
|
||||
extern void pio_set(const struct _pin *pin);
|
||||
|
||||
/**
|
||||
* \brief Sets a low output level on all the PIOs defined in the given
|
||||
* Pin instance.
|
||||
*
|
||||
* \details This has no immediate effects on PIOs that are not output,
|
||||
* but the PIO controller will memorize the value they are changed to
|
||||
* outputs.
|
||||
*
|
||||
* \param pin Pointer to a Pin instance describing one or more pins.
|
||||
*/
|
||||
extern void pio_clear(const struct _pin *pin);
|
||||
|
||||
/**
|
||||
* \brief Returns 1 if one or more PIO of the given Pin instance currently have
|
||||
* a high level; otherwise returns 0. This method returns the actual value that
|
||||
* is being read on the pin. To return the supposed output value of a pin, use
|
||||
* \ref pio_get_output_date_status() instead.
|
||||
*
|
||||
* \param pin Pointer to a Pin instance describing one or more pins.
|
||||
*
|
||||
* \return 1 if the Pin instance contains at least one PIO that currently has
|
||||
* a high level; otherwise 0.
|
||||
*/
|
||||
extern uint8_t pio_get(const struct _pin *pin);
|
||||
|
||||
/**
|
||||
* \brief Returns 1 if one or more PIO of the given Pin are configured to output a
|
||||
* high level (even if they are not output).
|
||||
* To get the actual value of the pin, use pio_get() instead.
|
||||
*
|
||||
* \param pin Pointer to a Pin instance describing one or more pins.
|
||||
*
|
||||
* \return 1 if the Pin instance contains at least one PIO that is configured
|
||||
* to output a high level; otherwise 0.
|
||||
*/
|
||||
extern uint8_t pio_get_output_data_status(const struct _pin *pin);
|
||||
|
||||
/**
|
||||
* \brief Configures Glitch or Debouncing filter for input.
|
||||
*
|
||||
* \param pin Pointer to a Pin instance describing one or more pins.
|
||||
* \param cuttoff Cutt off frequency for debounce filter.
|
||||
*/
|
||||
extern void pio_set_debounce_filter(const struct _pin *pin, uint32_t cuttoff);
|
||||
|
||||
/**
|
||||
* \brief Enable write protect.
|
||||
*
|
||||
* \param pin Pointer to a Pin instance describing one or more pins.
|
||||
*/
|
||||
extern void pio_enable_write_protect(const struct _pin *pin);
|
||||
|
||||
/**
|
||||
* \brief Disable write protect.
|
||||
*
|
||||
* \param pin Pointer to a Pin instance describing one or more pins.
|
||||
*/
|
||||
extern void pio_disable_write_protect(const struct _pin *pin);
|
||||
|
||||
/**
|
||||
* \brief Get write protect violation information.
|
||||
*
|
||||
* \param pin Pointer to a Pin instance describing one or more pins.
|
||||
*/
|
||||
extern uint32_t pio_get_write_protect_violation_info(const struct _pin * pin);
|
||||
|
||||
/**
|
||||
* \brief Configure all pio outputs low
|
||||
*
|
||||
* \param group PIO group number
|
||||
* \param mask Bitmask of one or more pin(s) to configure.
|
||||
*/
|
||||
extern void pio_output_low(uint32_t group, uint32_t mask);
|
||||
|
||||
extern void pio_add_handler_to_group(uint32_t group, uint32_t mask,
|
||||
pio_handler_t handler, void* user_arg);
|
||||
|
||||
extern void pio_reset_all_it(void);
|
||||
|
||||
/**
|
||||
* \brief Generate an interrupt on status change for a PIO or a group
|
||||
* of PIO.
|
||||
|
||||
* \details The provided interrupt handler will be called with the
|
||||
* triggering pin as its parameter (enabling different pin instances
|
||||
* to share the same handler).
|
||||
*
|
||||
* \param pin Pointer to a _pin instance.
|
||||
*/
|
||||
extern void pio_configure_it(const struct _pin * pin);
|
||||
|
||||
|
||||
/**
|
||||
* Enables the given interrupt source if it has been configured. The status
|
||||
* register of the corresponding PIO controller is cleared prior to enabling
|
||||
* the interrupt.
|
||||
* \param pin Interrupt source to enable.
|
||||
*/
|
||||
extern void pio_enable_it(const struct _pin * pin);
|
||||
|
||||
/**
|
||||
* Disables a given interrupt source, with no added side effects.
|
||||
*
|
||||
* \param pin Interrupt source to disable.
|
||||
*/
|
||||
extern void pio_disable_it(const struct _pin * pin);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _PIO_H */
|
|
@ -0,0 +1,601 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \addtogroup pio_module Working with PIO
|
||||
* \section Purpose
|
||||
* The PIO driver provides the Interface for configuration the Parallel Input/Output
|
||||
* Controller (PIO).
|
||||
*
|
||||
* \section Usage
|
||||
* <ul>
|
||||
* <li> Initialize the PIO with the desired period using pio_configure().
|
||||
* <li> Set a high or low output level on the given PIO using pio_set() or pio_clear().
|
||||
* <li> Get the level of the given PIOs using pio_get() or pio_get_output_date_status().
|
||||
* <li> Configures Glitch or Debouncing filter for given input PIO using pio_set_debounce_filter().
|
||||
* <li> Enable & disable write protect of the given PIOs using pio_enable_write_protect() or pio_disable_write_protect().
|
||||
* <li> Get write protect violation information of given PIO using pio_get_write_protect_violation_info().
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* For more accurate information, please look at the PIT section of the Datasheet.
|
||||
*
|
||||
* Related files :\n
|
||||
* \ref pio.c\n
|
||||
* \ref pio3.h\n
|
||||
*/
|
||||
/*@{*/
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implementation of PIO V3 (Parallel Input/Output) controller.
|
||||
*
|
||||
*/
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/pio.h"
|
||||
#include "peripherals/pmc.h"
|
||||
#include "peripherals/aic.h"
|
||||
#include "peripherals/matrix.h"
|
||||
|
||||
#include "trace.h"
|
||||
#include "compiler.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local types
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
struct _bitfield_pio_cfgr_func {
|
||||
uint32_t
|
||||
func : 3,
|
||||
rfu3_7 : 5,
|
||||
dir : 1,
|
||||
puen : 1,
|
||||
pden : 1,
|
||||
rfu11 : 1,
|
||||
ifen : 1,
|
||||
ifscen : 1,
|
||||
opd : 1,
|
||||
schmitt : 1,
|
||||
drvstr : 2,
|
||||
rfu18_23 : 6,
|
||||
evtsel : 3,
|
||||
rfu27_28 : 2,
|
||||
pcfs : 1,
|
||||
icfs : 1,
|
||||
tampen : 1;
|
||||
};
|
||||
|
||||
union _pio_cfg {
|
||||
struct _bitfield_pio_cfgr_func bitfield;
|
||||
uint32_t uint32_value;
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local functions declarations
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef ID_PIOA
|
||||
static void _pioa_handler(void);
|
||||
#endif
|
||||
#ifdef ID_PIOB
|
||||
static void _piob_handler(void);
|
||||
#endif
|
||||
#ifdef ID_PIOC
|
||||
static void _pioc_handler(void);
|
||||
#endif
|
||||
#ifdef ID_PIOD
|
||||
static void _piod_handler(void);
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local variables
|
||||
*----------------------------------------------------------------------------*/
|
||||
struct _handler {
|
||||
uint32_t mask;
|
||||
pio_handler_t handler;
|
||||
void *user_arg;
|
||||
};
|
||||
static struct _handler _handlers[IRQ_PIO_HANDLERS_SIZE];
|
||||
|
||||
static const aic_handler_t _generic_handlers[PIO_GROUP_LENGTH] = {
|
||||
#ifdef ID_PIOA
|
||||
_pioa_handler,
|
||||
#endif
|
||||
#ifdef ID_PIOB
|
||||
_piob_handler,
|
||||
#endif
|
||||
#ifdef ID_PIOC
|
||||
_pioc_handler,
|
||||
#endif
|
||||
#ifdef ID_PIOD
|
||||
_piod_handler,
|
||||
#endif
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local functions definitions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static void _handler_push(void (*handler)(uint32_t, uint32_t, void*),
|
||||
uint32_t mask, void* user_arg)
|
||||
{
|
||||
static int i = 0;
|
||||
_handlers[i].mask = mask;
|
||||
_handlers[i].handler = handler;
|
||||
_handlers[i].user_arg = user_arg;
|
||||
++i;
|
||||
assert(i < ARRAY_SIZE(_handlers));
|
||||
}
|
||||
|
||||
#ifdef ID_PIOA
|
||||
static void _pioa_handler(void)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
unsigned int i = 0;
|
||||
if (matrix_is_peripheral_secured(MATRIX1, ID_PIOA))
|
||||
status = PIOA->PIO_PIO_[PIO_GROUP_A].S_PIO_ISR;
|
||||
else
|
||||
status = PIOA->PIO_IO_GROUP[PIO_GROUP_A].PIO_ISR;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(_handlers); ++i) {
|
||||
if (_handlers[i].mask & status) {
|
||||
_handlers[i].handler(PIO_GROUP_A, status,
|
||||
_handlers[i].user_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef ID_PIOB
|
||||
static void _piob_handler(void)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
unsigned int i = 0;
|
||||
if (matrix_is_peripheral_secured(MATRIX1, ID_PIOB))
|
||||
status = PIOA->PIO_PIO_[PIO_GROUP_B].S_PIO_ISR;
|
||||
else
|
||||
status = PIOA->PIO_IO_GROUP[PIO_GROUP_B].PIO_ISR;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(_handlers); ++i) {
|
||||
if (_handlers[i].mask & status) {
|
||||
_handlers[i].handler(PIO_GROUP_B, status,
|
||||
_handlers[i].user_arg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
#ifdef ID_PIOC
|
||||
static void _pioc_handler(void)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
unsigned int i = 0;
|
||||
if (matrix_is_peripheral_secured(MATRIX1, ID_PIOC))
|
||||
status = PIOA->PIO_PIO_[PIO_GROUP_C].S_PIO_ISR;
|
||||
else
|
||||
status = PIOA->PIO_IO_GROUP[PIO_GROUP_C].PIO_ISR;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(_handlers); ++i) {
|
||||
if (_handlers[i].mask & status) {
|
||||
_handlers[i].handler(PIO_GROUP_C, status,
|
||||
_handlers[i].user_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef ID_PIOD
|
||||
static void _piod_handler(void)
|
||||
{
|
||||
uint32_t status = 0;
|
||||
unsigned int i = 0;
|
||||
if (matrix_is_peripheral_secured(MATRIX1, ID_PIOD))
|
||||
status = PIOA->PIO_PIO_[PIO_GROUP_D].S_PIO_ISR;
|
||||
else
|
||||
status = PIOA->PIO_IO_GROUP[PIO_GROUP_D].PIO_ISR;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(_handlers); ++i) {
|
||||
if (_handlers[i].mask & status) {
|
||||
_handlers[i].handler(PIO_GROUP_D, status,
|
||||
_handlers[i].user_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline uint32_t _pio_group_to_id(int group)
|
||||
{
|
||||
switch(group) {
|
||||
case PIO_GROUP_A:
|
||||
return ID_PIOA;
|
||||
case PIO_GROUP_B:
|
||||
return ID_PIOB;
|
||||
case PIO_GROUP_C:
|
||||
return ID_PIOC;
|
||||
case PIO_GROUP_D:
|
||||
return ID_PIOD;
|
||||
default:
|
||||
return (unsigned int)-1;
|
||||
};
|
||||
}
|
||||
|
||||
static void* _pio_configure_pins(const struct _pin *pin, uint32_t periph_id)
|
||||
{
|
||||
PioPio_* piogroup = &PIOA->PIO_PIO_[pin->group];
|
||||
if (!matrix_is_peripheral_secured(MATRIX1, periph_id)) {
|
||||
piogroup->S_PIO_SIONR = pin->mask;
|
||||
return (void*) &PIOA->PIO_IO_GROUP[pin->group];
|
||||
} else {
|
||||
piogroup->S_PIO_SIOSR = pin->mask;
|
||||
return (void*) piogroup;
|
||||
}
|
||||
}
|
||||
|
||||
static void* _pio_retrive_group(const struct _pin *pin, uint32_t periph_id)
|
||||
{
|
||||
if (!matrix_is_peripheral_secured(MATRIX1, periph_id)) {
|
||||
return (void*) &PIOA->PIO_IO_GROUP[pin->group];
|
||||
} else {
|
||||
return (void*) &PIOA->PIO_PIO_[pin->group];
|
||||
}
|
||||
}
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Configures a list of Pin instances, each of which can either
|
||||
* hold a single pin or a group of pins, depending on the mask value;
|
||||
* all pins are configured by this function. The size of the array
|
||||
* must also be provided and is easily computed using ARRAY_SIZE
|
||||
* whenever its length is not known in advance.
|
||||
*
|
||||
* \param list Pointer to a list of _pin instances.
|
||||
* \param size Size of the _pin list (calculated using PIN_LISTSIZE).
|
||||
*
|
||||
* \return 1 if the pins have been configured properly; otherwise 0.
|
||||
*/
|
||||
uint8_t pio_configure(const struct _pin *pin_list, uint32_t size)
|
||||
{
|
||||
union _pio_cfg cfg;
|
||||
PioIo_group* pioiog;
|
||||
|
||||
/* Configure pins */
|
||||
while (size--)
|
||||
{
|
||||
/* Enable the PIO group if needed */
|
||||
uint32_t periph_id = _pio_group_to_id(pin_list->group);
|
||||
|
||||
assert(pin_list->group < PIO_GROUP_LENGTH);
|
||||
cfg.uint32_value = 0;
|
||||
pioiog = (PioIo_group*) _pio_configure_pins(pin_list, periph_id);
|
||||
|
||||
if ( pin_list->attribute != PIO_DEFAULT) {
|
||||
cfg.bitfield.puen = (pin_list->attribute & PIO_PULLUP)? 1:0;
|
||||
cfg.bitfield.pden = (pin_list->attribute & PIO_PULLDOWN)? 1:0;
|
||||
cfg.bitfield.ifen = (pin_list->attribute & PIO_DEGLITCH)? 1:0;
|
||||
cfg.bitfield.ifscen = (pin_list->attribute & PIO_DEBOUNCE)? 1:0;
|
||||
cfg.bitfield.opd = (pin_list->attribute & PIO_OPENDRAIN)? 1:0;
|
||||
cfg.bitfield.schmitt =(pin_list->attribute & PIO_TRIGGER_DIS)? 1:0;
|
||||
|
||||
switch (pin_list->attribute & PIO_DRVSTR_Msk) {
|
||||
case PIO_DRVSTR_HI:
|
||||
cfg.bitfield.drvstr = PIO_CFGR_DRVSTR_HI >> PIO_CFGR_DRVSTR_Pos;
|
||||
break;
|
||||
case PIO_DRVSTR_ME:
|
||||
cfg.bitfield.drvstr = PIO_CFGR_DRVSTR_ME >> PIO_CFGR_DRVSTR_Pos;
|
||||
break;
|
||||
case PIO_DRVSTR_LO:
|
||||
default:
|
||||
cfg.bitfield.drvstr = PIO_CFGR_DRVSTR_LO >> PIO_CFGR_DRVSTR_Pos;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (pin_list->attribute & PIO_EVTSEL_Msk) {
|
||||
case PIO_IT_HIGH_LEVEL:
|
||||
cfg.bitfield.evtsel = PIO_CFGR_EVTSEL_HIGH >> PIO_CFGR_EVTSEL_Pos;
|
||||
break;
|
||||
case PIO_IT_LOW_LEVEL:
|
||||
cfg.bitfield.evtsel = PIO_CFGR_EVTSEL_LOW >> PIO_CFGR_EVTSEL_Pos;
|
||||
break;
|
||||
case PIO_IT_BOTH_EDGE:
|
||||
cfg.bitfield.evtsel = PIO_CFGR_EVTSEL_BOTH >> PIO_CFGR_EVTSEL_Pos;
|
||||
break;
|
||||
case PIO_IT_RISE_EDGE:
|
||||
cfg.bitfield.evtsel = PIO_CFGR_EVTSEL_RISING >> PIO_CFGR_EVTSEL_Pos;
|
||||
break;
|
||||
case PIO_IT_FALL_EDGE:
|
||||
default:
|
||||
cfg.bitfield.evtsel = PIO_CFGR_EVTSEL_FALLING >> PIO_CFGR_EVTSEL_Pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (pin_list->type){
|
||||
|
||||
case PIO_PERIPH_A:
|
||||
cfg.bitfield.func = PIO_CFGR_FUNC_PERIPH_A >> PIO_CFGR_FUNC_Pos;
|
||||
break;
|
||||
case PIO_PERIPH_B:
|
||||
cfg.bitfield.func = PIO_CFGR_FUNC_PERIPH_B >> PIO_CFGR_FUNC_Pos;
|
||||
break;
|
||||
case PIO_PERIPH_C:
|
||||
cfg.bitfield.func = PIO_CFGR_FUNC_PERIPH_C >> PIO_CFGR_FUNC_Pos;
|
||||
break;
|
||||
case PIO_PERIPH_D:
|
||||
cfg.bitfield.func = PIO_CFGR_FUNC_PERIPH_D >> PIO_CFGR_FUNC_Pos;
|
||||
break;
|
||||
case PIO_PERIPH_E:
|
||||
cfg.bitfield.func = PIO_CFGR_FUNC_PERIPH_E >> PIO_CFGR_FUNC_Pos;
|
||||
break;
|
||||
case PIO_PERIPH_F:
|
||||
cfg.bitfield.func = PIO_CFGR_FUNC_PERIPH_F >> PIO_CFGR_FUNC_Pos;
|
||||
break;
|
||||
case PIO_GENERIC:
|
||||
case PIO_INPUT:
|
||||
cfg.bitfield.dir = 0;
|
||||
break;
|
||||
|
||||
case PIO_OUTPUT_0:
|
||||
cfg.bitfield.dir = 1;
|
||||
pio_clear(pin_list);
|
||||
break;
|
||||
|
||||
case PIO_OUTPUT_1:
|
||||
cfg.bitfield.dir = 1;
|
||||
pio_set(pin_list);
|
||||
break;
|
||||
|
||||
default:
|
||||
case PIO_PERIPH_G:
|
||||
return 0;
|
||||
}
|
||||
|
||||
pioiog->PIO_MSKR = pin_list->mask;
|
||||
pioiog->PIO_CFGR = cfg.uint32_value;
|
||||
pmc_enable_peripheral(periph_id);
|
||||
|
||||
++pin_list;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets a high output level on all the PIOs defined in the
|
||||
* given Pin instance. This has no immediate effects on PIOs that are
|
||||
* not output, but the PIO controller will memorize the value they are
|
||||
* changed to outputs.
|
||||
*
|
||||
* \param pin Pointer to a Pin instance describing one or more pins.
|
||||
*/
|
||||
void pio_set(const struct _pin *pin)
|
||||
{
|
||||
assert(pin->group < PIO_GROUP_LENGTH);
|
||||
uint32_t periph_id = _pio_group_to_id(pin->group);
|
||||
PioIo_group* pioiog = (PioIo_group*) _pio_retrive_group(pin, periph_id);
|
||||
pioiog->PIO_SODR = pin->mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sets a low output level on all the PIOs defined in the given
|
||||
* Pin instance. This has no immediate effects on PIOs that are not
|
||||
* output, but the PIO controller will memorize the value they are
|
||||
* changed to outputs.
|
||||
*
|
||||
* \param pin Pointer to a Pin instance describing one or more pins.
|
||||
*/
|
||||
void pio_clear(const struct _pin *pin)
|
||||
{
|
||||
assert(pin->group < PIO_GROUP_LENGTH);
|
||||
uint32_t periph_id = _pio_group_to_id(pin->group);
|
||||
PioIo_group* pioiog = (PioIo_group*) _pio_retrive_group(pin, periph_id);
|
||||
pioiog->PIO_CODR = pin->mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns 1 if one or more PIO of the given Pin instance currently have
|
||||
* a high level; otherwise returns 0. This method returns the actual value that
|
||||
* is being read on the pin. To return the supposed output value of a pin, use
|
||||
* pio_get_output_date_status() instead.
|
||||
*
|
||||
* \param pin Pointer to a Pin instance describing one or more pins.
|
||||
*
|
||||
* \return 1 if the Pin instance contains at least one PIO that currently has
|
||||
* a high level; otherwise 0.
|
||||
*/
|
||||
uint8_t pio_get(const struct _pin *pin)
|
||||
{
|
||||
assert(pin->group < PIO_GROUP_LENGTH);
|
||||
uint32_t reg ;
|
||||
uint32_t periph_id = _pio_group_to_id(pin->group);
|
||||
PioIo_group* pioiog = (PioIo_group*) _pio_retrive_group(pin, periph_id);
|
||||
|
||||
if ((pin->type == PIO_OUTPUT_0) || (pin->type == PIO_OUTPUT_1)) {
|
||||
reg = pioiog->PIO_ODSR ;
|
||||
}
|
||||
else {
|
||||
reg = pioiog->PIO_PDSR ;
|
||||
}
|
||||
if ( (reg & pin->mask) == 0 ) {
|
||||
return 0 ;
|
||||
}
|
||||
else {
|
||||
return 1 ;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns 1 if one or more PIO of the given Pin are configured
|
||||
* to output a high level (even if they are not output). To get the
|
||||
* actual value of the pin, use pio_get() instead.
|
||||
*
|
||||
* \param pin Pointer to a Pin instance describing one or more pins.
|
||||
*
|
||||
* \return 1 if the Pin instance contains at least one PIO that is configured
|
||||
* to output a high level; otherwise 0.
|
||||
*/
|
||||
uint8_t pio_get_output_data_status(const struct _pin *pin)
|
||||
{
|
||||
assert(pin->group < PIO_GROUP_LENGTH);
|
||||
uint32_t periph_id = _pio_group_to_id(pin->group);
|
||||
PioIo_group* pioiog = (PioIo_group*) _pio_retrive_group(pin, periph_id);
|
||||
|
||||
if ((pioiog->PIO_ODSR & pin->mask) == 0) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configures Glitch or Debouncing filter for input.
|
||||
*
|
||||
* \param pin Pointer to a Pin instance describing one or more pins.
|
||||
* \param cuttoff Cutt off frequency for debounce filter.
|
||||
*/
|
||||
void pio_set_debounce_filter(const struct _pin *pin, uint32_t cuttoff)
|
||||
{
|
||||
assert(pin->group < PIO_GROUP_LENGTH);
|
||||
if (cuttoff == 0) {
|
||||
PIOA->S_PIO_SCDR = 0;
|
||||
}
|
||||
else {
|
||||
/* the lowest 14 bits work */
|
||||
PIOA->S_PIO_SCDR =
|
||||
((pmc_get_slow_clock()/(2*(cuttoff))) - 1) & 0x3FFF;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable write protect.
|
||||
*
|
||||
* \param pin Pointer to a Pin instance describing one or more pins.
|
||||
*/
|
||||
void pio_enable_write_protect(const struct _pin *pin)
|
||||
{
|
||||
assert(pin->group < PIO_GROUP_LENGTH);
|
||||
PIOA->PIO_WPMR = (PIO_WPMR_WPKEY_VALID | PIO_WPMR_WPEN_EN );
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable write protect.
|
||||
*
|
||||
* \param pin Pointer to a Pin instance describing one or more pins.
|
||||
*/
|
||||
void pio_disable_write_protect(const struct _pin *pin)
|
||||
{
|
||||
assert(pin->group < PIO_GROUP_LENGTH);
|
||||
PIOA->PIO_WPMR = (PIO_WPMR_WPKEY_VALID | PIO_WPMR_WPEN_DIS );
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get write protect violation information.
|
||||
*
|
||||
* \param pin Pointer to a Pin instance describing one or more pins.
|
||||
*/
|
||||
uint32_t pio_get_write_protect_violation_info(const struct _pin * pin)
|
||||
{
|
||||
assert(pin->group < PIO_GROUP_LENGTH);
|
||||
return PIOA->PIO_WPSR;
|
||||
}
|
||||
|
||||
void pio_add_handler_to_group(uint32_t group, uint32_t mask,
|
||||
pio_handler_t handler, void* user_arg)
|
||||
{
|
||||
trace_debug("Enter in pio_add_handler_to_group()\n\r");
|
||||
assert(group <
|
||||
(sizeof(_generic_handlers)/sizeof(_generic_handlers[0])));
|
||||
_handler_push(handler, mask, user_arg);
|
||||
uint32_t id = _pio_group_to_id(group);
|
||||
aic_set_source_vector(id,
|
||||
(aic_handler_t)_generic_handlers[group]);
|
||||
aic_enable(id);
|
||||
}
|
||||
|
||||
void pio_reset_all_it(void)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < PIO_GROUP_LENGTH; ++i) {
|
||||
PIOA->PIO_IO_GROUP[i].PIO_ISR;
|
||||
PIOA->PIO_IO_GROUP[i].PIO_IDR = ~0UL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures a PIO or a group of PIO to generate an interrupt on status
|
||||
* change. The provided interrupt handler will be called with the triggering
|
||||
* pin as its parameter (enabling different pin instances to share the same
|
||||
* handler).
|
||||
* \param pin Pointer to a _pin instance.
|
||||
*/
|
||||
void pio_configure_it(const struct _pin *pin)
|
||||
{
|
||||
trace_debug("Enter in pio_configure_it()\n\r");
|
||||
assert(pin != NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables the given interrupt source if it has been configured. The status
|
||||
* register of the corresponding PIO controller is cleared prior to enabling
|
||||
* the interrupt.
|
||||
* \param pin Interrupt source to enable.
|
||||
*/
|
||||
void pio_enable_it(const struct _pin *pin)
|
||||
{
|
||||
trace_debug("pio_enable_it() \n\r");
|
||||
assert(pin != NULL);
|
||||
uint32_t periph_id = _pio_group_to_id(pin->group);
|
||||
PioIo_group* pioiog = (PioIo_group*) _pio_retrive_group(pin, periph_id);
|
||||
|
||||
pioiog->PIO_ISR;
|
||||
/* Configure interrupt enable register */
|
||||
pioiog->PIO_IER = pin->mask; /* enable interrupt register */
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables a given interrupt source, with no added side effects.
|
||||
*
|
||||
* \param pin Interrupt source to disable.
|
||||
*/
|
||||
void pio_disable_it(const struct _pin *pin)
|
||||
{
|
||||
trace_debug("pio_enable_it()\n\r");
|
||||
assert(pin != NULL);
|
||||
uint32_t periph_id = _pio_group_to_id(pin->group);
|
||||
PioIo_group* pioiog = (PioIo_group*) _pio_retrive_group(pin, periph_id);
|
||||
pioiog->PIO_IDR = pin->mask;
|
||||
}
|
|
@ -0,0 +1,164 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \section Purpose
|
||||
*
|
||||
* This file provides a basic API for PIO configuration and usage of
|
||||
* user-controlled pins. Please refer to the board.h file for a list of
|
||||
* available pin definitions.
|
||||
*
|
||||
* \section Usage
|
||||
*
|
||||
* -# Define a constant pin description array such as the following one, using
|
||||
* the existing definitions provided by the board.h file if possible:
|
||||
* \code
|
||||
* const struct _pin pins[] = {PIN_USART0_TXD, PIN_USART0_RXD};
|
||||
* \endcode
|
||||
* Alternatively, it is possible to add new pins by provided the full Pin
|
||||
* structure:
|
||||
* \code
|
||||
* // Pin instance to configure PA10 & PA11 as inputs with the internal
|
||||
* // pull-up enabled.
|
||||
* const Pin pins = {
|
||||
* (1 << 10) | (1 << 11),
|
||||
* REG_PIOA,
|
||||
* ID_PIOA,
|
||||
* PIO_INPUT,
|
||||
* PIO_PULLUP
|
||||
* };
|
||||
* \endcode
|
||||
* -# Configure a pin array by calling pio_configure() with a pointer to the
|
||||
* array and its size (which is computed using the ARRAY_SIZE macro).
|
||||
* -# Change and get the value of a user-controlled pin using the pio_set,
|
||||
* pio_clear and pio_get methods.
|
||||
* -# Get the level being currently output by a user-controlled pin configured
|
||||
* as an output using pio_get_output_date_status().
|
||||
*/
|
||||
|
||||
#ifndef _PIO_H
|
||||
#error "pio3.h cannot be included. pio.h should be used instead"
|
||||
#endif
|
||||
|
||||
#ifndef _PIO4_H
|
||||
#define _PIO4_H
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Definitions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/* The IO group is A (or 0) */
|
||||
#define PIO_GROUP_A 0
|
||||
/* The IO group is B (or 1) */
|
||||
#define PIO_GROUP_B 1
|
||||
/* The IO group is C (or 2) */
|
||||
#define PIO_GROUP_C 2
|
||||
/* The IO group is D (or 3) */
|
||||
#define PIO_GROUP_D 3
|
||||
|
||||
#define PIO_GROUP_LENGTH PIOIO_GROUP_NUMBER
|
||||
|
||||
/* The pin is controlled by the generic PIO. */
|
||||
#define PIO_GENERIC 0
|
||||
/* The pin is controlled by the associated signal of peripheral A. */
|
||||
#define PIO_PERIPH_A 1
|
||||
/* The pin is controlled by the associated signal of peripheral B. */
|
||||
#define PIO_PERIPH_B 2
|
||||
/* The pin is controlled by the associated signal of peripheral C. */
|
||||
#define PIO_PERIPH_C 3
|
||||
/* The pin is controlled by the associated signal of peripheral D. */
|
||||
#define PIO_PERIPH_D 4
|
||||
/* The pin is controlled by the associated signal of peripheral E. */
|
||||
#define PIO_PERIPH_E 5
|
||||
/* The pin is controlled by the associated signal of peripheral F. */
|
||||
#define PIO_PERIPH_F 6
|
||||
/* The pin is controlled by the associated signal of peripheral G. */
|
||||
#define PIO_PERIPH_G 7
|
||||
|
||||
/* The pin is an input. */
|
||||
#define PIO_INPUT 10
|
||||
/* The pin is an output. */
|
||||
#define PIO_OUTPUT 11
|
||||
/* The pin is an output and has a default level of 0. */
|
||||
#define PIO_OUTPUT_0 11
|
||||
/* The pin is an output and has a default level of 1. */
|
||||
#define PIO_OUTPUT_1 12
|
||||
|
||||
|
||||
/* Default pin configuration (no attribute). */
|
||||
#define PIO_DEFAULT (0x0u << 0)
|
||||
/* The internal pin pull-up is active. */
|
||||
#define PIO_PULLUP (0x1u << 0)
|
||||
/* The internal pin pull-down is active. */
|
||||
#define PIO_PULLDOWN (0x1u << 1)
|
||||
/* The pin is open-drain. */
|
||||
#define PIO_OPENDRAIN (0x1u << 2)
|
||||
/* The internal glitch filter is active. */
|
||||
#define PIO_DEGLITCH (0x1u << 3)
|
||||
/* The internal Debounce filter is active. */
|
||||
#define PIO_DEBOUNCE (0x1u << 4)
|
||||
/* The internal Schmitt trigger is disable. */
|
||||
#define PIO_TRIGGER_DIS (0x1u << 5)
|
||||
|
||||
/* Drive Strength. */
|
||||
#define PIO_DRVSTR_Pos 10
|
||||
#define PIO_DRVSTR_Msk (0x3u << 10)
|
||||
#define PIO_DRVSTR_HI (0x2u << 10) /* High drive */
|
||||
#define PIO_DRVSTR_ME (0x1u << 10) /* Medium drive */
|
||||
#define PIO_DRVSTR_LO (0x0u << 10) /* Low drive */
|
||||
|
||||
#define PIO_EVTSEL_Pos 12
|
||||
#define PIO_EVTSEL_Msk (0x7u << 12)
|
||||
/* Event detection on input falling edge. */
|
||||
#define PIO_IT_FALL_EDGE (0x0u << 12)
|
||||
/* Event detection on input rising edge. */
|
||||
#define PIO_IT_RISE_EDGE (0x1u << 12)
|
||||
/* Event detection on input both edge. */
|
||||
#define PIO_IT_BOTH_EDGE (0x2u << 12)
|
||||
/* Event detection on low level input. */
|
||||
#define PIO_IT_LOW_LEVEL (0x3u << 12)
|
||||
/*Event detection on high level input. */
|
||||
#define PIO_IT_HIGH_LEVEL (0x4u << 12)
|
||||
|
||||
#define PIO_WPMR_WPEN_EN ( 0x01 << 0 )
|
||||
|
||||
#define PIO_WPMR_WPEN_DIS ( 0x00 << 0 )
|
||||
|
||||
#define PIO_WPMR_WPKEY_VALID ( 0x50494F << 8 )
|
||||
|
||||
#endif /* #ifndef _PIO4_H */
|
|
@ -0,0 +1,128 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \addtogroup pit_module Working with PIT
|
||||
* \section Purpose
|
||||
* The PIT driver provides the Interface for configuration the Periodic
|
||||
* Interval Timer (PIT) peripheral.
|
||||
*
|
||||
* \section Usage
|
||||
* <ul>
|
||||
* <li> Initialize the PIT with the desired period using pit_init().
|
||||
* Alternatively, the Periodic Interval Value (PIV) can be configured
|
||||
* manually using pit_set_piv(). </li>
|
||||
* <li> Start the PIT counting using pit_enable().
|
||||
* <li> Enable & disable the PIT interrupt using pit_enable_it() and
|
||||
* pit_disable_it(). </li>
|
||||
* <li> Retrieve the current status of the PIT using pit_get_status(). </li>
|
||||
* <li> To get the current value of the internal counter and the number of ticks
|
||||
* that have occurred, use either pit_get_pivr() or pit_get_piir() depending
|
||||
* on whether you want the values to be cleared or not. </li>
|
||||
*
|
||||
* </ul>
|
||||
* For more accurate information, please look at the PIT section of the
|
||||
* Datasheet.
|
||||
*
|
||||
* Related files :\n
|
||||
* \ref pit.c\n
|
||||
* \ref pit.h.\n
|
||||
*/
|
||||
/*@{*/
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implementation of PIT (Periodic Interval Timer) controller.
|
||||
*
|
||||
*/
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/pit.h"
|
||||
#include "peripherals/pmc.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
void pit_init(uint32_t period)
|
||||
{
|
||||
uint32_t pit_frequency = pmc_get_peripheral_clock(ID_PIT) / 1000000;
|
||||
PIT->PIT_MR = period ? (period * pit_frequency + 8) >> 4 : 0;
|
||||
PIT->PIT_MR |= PIT_MR_PITEN;
|
||||
}
|
||||
|
||||
void pit_set_piv(uint32_t piv)
|
||||
{
|
||||
uint32_t dwMr = PIT->PIT_MR & (~PIT_MR_PIV_Msk);
|
||||
PIT->PIT_MR = dwMr | PIT_MR_PIV(piv);
|
||||
}
|
||||
|
||||
void pit_enable(void)
|
||||
{
|
||||
PIT->PIT_MR |= PIT_MR_PITEN;
|
||||
}
|
||||
|
||||
void pit_disable(void)
|
||||
{
|
||||
PIT->PIT_MR &= ~PIT_MR_PITEN;
|
||||
}
|
||||
|
||||
void pit_enable_it(void)
|
||||
{
|
||||
PIT->PIT_MR |= PIT_MR_PITIEN;
|
||||
}
|
||||
|
||||
void pit_disable_it(void)
|
||||
{
|
||||
PIT->PIT_MR &= ~PIT_MR_PITIEN;
|
||||
}
|
||||
|
||||
uint32_t pit_get_mode(void)
|
||||
{
|
||||
return PIT->PIT_MR;
|
||||
}
|
||||
|
||||
uint32_t pit_get_status(void)
|
||||
{
|
||||
return PIT->PIT_SR;
|
||||
}
|
||||
|
||||
uint32_t pit_get_piir(void)
|
||||
{
|
||||
return PIT->PIT_PIIR;
|
||||
}
|
||||
|
||||
uint32_t pit_get_pivr(void)
|
||||
{
|
||||
return PIT->PIT_PIVR;
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2011, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _PIT_H_
|
||||
#define _PIT_H_
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Initialize the Periodic Interval Timer to generate a tick at the
|
||||
* specified period, given the current master clock frequency.
|
||||
*
|
||||
* \param period Period in micro seconds.
|
||||
*/
|
||||
extern void pit_init(uint32_t period);
|
||||
|
||||
/**
|
||||
* \brief Set the Periodic Interval Value of the PIT.
|
||||
*
|
||||
* \param piv PIV value to set.
|
||||
*/
|
||||
extern void pit_set_piv(uint32_t piv);
|
||||
|
||||
/**
|
||||
* \brief Enables the PIT if this is not already the case.
|
||||
*
|
||||
*/
|
||||
extern void pit_enable(void);
|
||||
|
||||
/**
|
||||
* \brief Disnables the PIT when PIV value is reached.
|
||||
*
|
||||
*/
|
||||
extern void pit_disable(void);
|
||||
|
||||
/**
|
||||
* \brief Enable the PIT periodic interrupt.
|
||||
*
|
||||
*/
|
||||
extern void pit_enable_it(void);
|
||||
|
||||
/**
|
||||
* \brief Disables the PIT periodic interrupt.
|
||||
*
|
||||
*/
|
||||
extern void pit_disable_it(void);
|
||||
|
||||
/**
|
||||
* \brief Returns the value of the PIT mode register.
|
||||
*
|
||||
* \return PIT_MR value.
|
||||
*/
|
||||
extern uint32_t pit_get_mode(void);
|
||||
|
||||
/**
|
||||
* \brief Returns the value of the PIT status register, clearing it as
|
||||
* a side effect.
|
||||
*
|
||||
* \return PIT_SR value.
|
||||
*/
|
||||
extern uint32_t pit_get_status(void);
|
||||
|
||||
/**
|
||||
* \brief Returns the value of the PIT Image Register, to read PICNT
|
||||
* and CPIV without clearing the current values.
|
||||
*
|
||||
* \return PIT_PIIR value.
|
||||
*/
|
||||
extern uint32_t pit_get_piir(void);
|
||||
|
||||
/**
|
||||
* \brief Returns the value of the PIT Value Register, clearing it as
|
||||
* a side effect.
|
||||
*
|
||||
* \return PITC_PIVR value.
|
||||
*/
|
||||
extern uint32_t pit_get_pivr(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef _PIT_H_ */
|
|
@ -0,0 +1,978 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \addtogroup pmc_module Working with PMC
|
||||
* \section Purpose
|
||||
* The PMC driver provides the Interface for configuration the Power Management
|
||||
* Controller (PMC).
|
||||
*
|
||||
* \section Usage
|
||||
* <ul>
|
||||
* <li> Enable & disable peripherals using pmc_enable_peripheral() and
|
||||
* pmc_enable_all_peripherals() or pmc_disable_peripheral() and
|
||||
* pmc_disable_all_peripherals().
|
||||
* <li> Get & set maximum frequency clock for giving peripheral using
|
||||
* pmc_get_peri_max_freq() and pmc_set_peri_max_clock().
|
||||
* <li> Get Peripheral Status for the given peripheral using pmc_is_periph_enabled()
|
||||
* <li> Select clocks's source using pmc_select_external_crystal(),
|
||||
* pmc_select_internal_crystal(), pmc_select_external_osc() and pmc_select_internal_osc().
|
||||
* <li> Switch MCK using pmc_switch_mck_to_pll(), pmc_switch_mck_to_main() and
|
||||
* pmc_switch_mck_to_slck().
|
||||
* <li> Config PLL using pmc_set_pll_a() and pmc_disable_pll_a().
|
||||
* </li>
|
||||
* </ul>
|
||||
* For more accurate information, please look at the PMC section of the
|
||||
* Datasheet.
|
||||
*
|
||||
* Related files :\n
|
||||
* \ref pmc.c\n
|
||||
* \ref pmc.h\n
|
||||
*/
|
||||
/*@{*/
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implementation of PIO (Parallel Input/Output) controller.
|
||||
*
|
||||
*/
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "board.h"
|
||||
#include "peripherals/pmc.h"
|
||||
#include "trace.h"
|
||||
#include <assert.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Variables
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static uint32_t _pmc_mck = 0;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Private functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static void _pmc_compute_mck(void)
|
||||
{
|
||||
uint32_t clk = 0;
|
||||
uint32_t mckr = PMC->PMC_MCKR;
|
||||
|
||||
uint32_t css = mckr & PMC_MCKR_CSS_Msk;
|
||||
switch (css) {
|
||||
case PMC_MCKR_CSS_SLOW_CLK:
|
||||
clk = pmc_get_slow_clock();
|
||||
break;
|
||||
case PMC_MCKR_CSS_MAIN_CLK:
|
||||
clk = pmc_get_main_clock();
|
||||
break;
|
||||
case PMC_MCKR_CSS_PLLA_CLK:
|
||||
clk = pmc_get_plla_clock();
|
||||
break;
|
||||
case PMC_MCKR_CSS_UPLL_CLK:
|
||||
clk = pmc_get_upll_clock();
|
||||
break;
|
||||
default:
|
||||
/* should never get here... */
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t pres = mckr & PMC_MCKR_PRES_Msk;
|
||||
switch (pres) {
|
||||
case PMC_MCKR_PRES_CLOCK:
|
||||
break;
|
||||
case PMC_MCKR_PRES_CLOCK_DIV2:
|
||||
clk >>= 1;
|
||||
break;
|
||||
case PMC_MCKR_PRES_CLOCK_DIV4:
|
||||
clk >>= 2;
|
||||
break;
|
||||
case PMC_MCKR_PRES_CLOCK_DIV8:
|
||||
clk >>= 3;
|
||||
break;
|
||||
case PMC_MCKR_PRES_CLOCK_DIV16:
|
||||
clk >>= 4;
|
||||
break;
|
||||
case PMC_MCKR_PRES_CLOCK_DIV32:
|
||||
clk >>= 5;
|
||||
break;
|
||||
case PMC_MCKR_PRES_CLOCK_DIV64:
|
||||
clk >>= 6;
|
||||
break;
|
||||
default:
|
||||
/* should never get here... */
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t mdiv = mckr & PMC_MCKR_MDIV_Msk;
|
||||
switch (mdiv) {
|
||||
case PMC_MCKR_MDIV_EQ_PCK:
|
||||
break;
|
||||
case PMC_MCKR_MDIV_PCK_DIV2:
|
||||
clk >>= 1; // divide by 2
|
||||
break;
|
||||
case PMC_MCKR_MDIV_PCK_DIV4:
|
||||
clk >>= 2; // divide by 4
|
||||
break;
|
||||
case PMC_MCKR_MDIV_PCK_DIV3:
|
||||
clk /= 3; // divide by 3
|
||||
break;
|
||||
default:
|
||||
/* should never get here... */
|
||||
break;
|
||||
}
|
||||
|
||||
_pmc_mck = clk;
|
||||
}
|
||||
|
||||
static uint32_t _pmc_get_pck_clock(uint32_t index)
|
||||
{
|
||||
uint32_t clk = 0;
|
||||
uint32_t pck = PMC->PMC_PCK[index];
|
||||
|
||||
switch (pck & PMC_PCK_CSS_Msk) {
|
||||
case PMC_PCK_CSS_SLOW_CLK:
|
||||
clk = pmc_get_slow_clock();
|
||||
break;
|
||||
case PMC_PCK_CSS_MAIN_CLK:
|
||||
clk = pmc_get_main_clock();
|
||||
break;
|
||||
case PMC_PCK_CSS_PLLA_CLK:
|
||||
clk = pmc_get_plla_clock();
|
||||
break;
|
||||
case PMC_PCK_CSS_UPLL_CLK:
|
||||
clk = pmc_get_upll_clock();
|
||||
break;
|
||||
case PMC_PCK_CSS_MCK_CLK:
|
||||
clk = pmc_get_master_clock();
|
||||
break;
|
||||
#ifdef CONFIG_HAVE_PMC_AUDIO_CLOCK
|
||||
case PMC_PCK_CSS_AUDIO_CLK:
|
||||
clk = pmc_get_audio_pmc_clock();
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t prescaler = (pck & PMC_PCK_PRES_Msk) >> PMC_PCK_PRES_Pos;
|
||||
return clk / (prescaler + 1);
|
||||
}
|
||||
|
||||
static bool _pmc_get_system_clock_bits(enum _pmc_system_clock clock,
|
||||
uint32_t *scer, uint32_t* scdr, uint32_t *scsr)
|
||||
{
|
||||
uint32_t e, d, s;
|
||||
|
||||
switch (clock)
|
||||
{
|
||||
#ifdef PMC_SCDR_PCK
|
||||
case PMC_SYSTEM_CLOCK_PCK:
|
||||
e = 0;
|
||||
d = PMC_SCDR_PCK;
|
||||
s = PMC_SCSR_PCK;
|
||||
break;
|
||||
#endif
|
||||
case PMC_SYSTEM_CLOCK_DDR:
|
||||
e = PMC_SCER_DDRCK;
|
||||
d = PMC_SCDR_DDRCK;
|
||||
s = PMC_SCSR_DDRCK;
|
||||
break;
|
||||
case PMC_SYSTEM_CLOCK_LCD:
|
||||
e = PMC_SCER_LCDCK;
|
||||
d = PMC_SCDR_LCDCK;
|
||||
s = PMC_SCSR_LCDCK;
|
||||
break;
|
||||
#ifdef PMC_SCER_SMDCK
|
||||
case PMC_SYSTEM_CLOCK_SMD:
|
||||
e = PMC_SCER_SMDCK;
|
||||
d = PMC_SCDR_SMDCK;
|
||||
s = PMC_SCSR_SMDCK;
|
||||
break;
|
||||
#endif
|
||||
case PMC_SYSTEM_CLOCK_UHP:
|
||||
e = PMC_SCER_UHP;
|
||||
d = PMC_SCDR_UHP;
|
||||
s = PMC_SCSR_UHP;
|
||||
break;
|
||||
case PMC_SYSTEM_CLOCK_UDP:
|
||||
e = PMC_SCER_UDP;
|
||||
d = PMC_SCDR_UDP;
|
||||
s = PMC_SCSR_UDP;
|
||||
break;
|
||||
case PMC_SYSTEM_CLOCK_PCK0:
|
||||
e = PMC_SCER_PCK0;
|
||||
d = PMC_SCDR_PCK0;
|
||||
s = PMC_SCSR_PCK0;
|
||||
break;
|
||||
case PMC_SYSTEM_CLOCK_PCK1:
|
||||
e = PMC_SCER_PCK1;
|
||||
d = PMC_SCDR_PCK1;
|
||||
s = PMC_SCSR_PCK1;
|
||||
break;
|
||||
case PMC_SYSTEM_CLOCK_PCK2:
|
||||
e = PMC_SCER_PCK2;
|
||||
d = PMC_SCDR_PCK2;
|
||||
s = PMC_SCSR_PCK2;
|
||||
break;
|
||||
#ifdef PMC_SCER_ISCCK
|
||||
case PMC_SYSTEM_CLOCK_ISC:
|
||||
e = PMC_SCER_ISCCK;
|
||||
d = PMC_SCDR_ISCCK;
|
||||
s = PMC_SCSR_ISCCK;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
if (scer) {
|
||||
if (e)
|
||||
*scer = e;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if (scdr) {
|
||||
if (d)
|
||||
*scdr = d;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
if (scsr) {
|
||||
if (s)
|
||||
*scsr = s;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions (General)
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
uint32_t pmc_get_master_clock(void)
|
||||
{
|
||||
if (!_pmc_mck) {
|
||||
_pmc_compute_mck();
|
||||
}
|
||||
return _pmc_mck;
|
||||
}
|
||||
|
||||
uint32_t pmc_get_slow_clock(void)
|
||||
{
|
||||
if (SCKC->SCKC_CR & SCKC_CR_OSCSEL)
|
||||
return SLOW_CLOCK_INT_OSC; /* on-chip slow clock RC */
|
||||
else
|
||||
return BOARD_SLOW_CLOCK_EXT_OSC; /* external crystal */
|
||||
}
|
||||
|
||||
uint32_t pmc_get_main_clock(void)
|
||||
{
|
||||
if (PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)
|
||||
return MAIN_CLOCK_INT_OSC; /* on-chip main clock RC */
|
||||
else
|
||||
return BOARD_MAIN_CLOCK_EXT_OSC; /* external crystal */
|
||||
}
|
||||
|
||||
uint32_t pmc_get_plla_clock(void)
|
||||
{
|
||||
uint32_t pllaclk, pllar, pllmula, plldiva;
|
||||
|
||||
if (PMC->CKGR_MOR & CKGR_MOR_MOSCSEL)
|
||||
pllaclk = MAIN_CLOCK_INT_OSC; /* on-chip main clock RC */
|
||||
else
|
||||
pllaclk = BOARD_MAIN_CLOCK_EXT_OSC; /* external crystal */
|
||||
|
||||
pllar = PMC->CKGR_PLLAR;
|
||||
pllmula = (pllar & CKGR_PLLAR_MULA_Msk) >> CKGR_PLLAR_MULA_Pos;
|
||||
plldiva = (pllar & CKGR_PLLAR_DIVA_Msk) >> CKGR_PLLAR_DIVA_Pos;
|
||||
if (plldiva == 0 || pllmula == 0) {
|
||||
pllaclk = 0;
|
||||
} else {
|
||||
pllaclk = pllaclk * (pllmula + 1) / plldiva;
|
||||
if (PMC->PMC_MCKR & PMC_MCKR_PLLADIV2)
|
||||
pllaclk >>= 1;
|
||||
}
|
||||
|
||||
return pllaclk;
|
||||
}
|
||||
|
||||
uint32_t pmc_get_processor_clock(void)
|
||||
{
|
||||
uint32_t procclk, mdiv;
|
||||
|
||||
procclk = pmc_get_master_clock();
|
||||
|
||||
mdiv = PMC->PMC_MCKR & PMC_MCKR_MDIV_Msk;
|
||||
switch (mdiv) {
|
||||
case PMC_MCKR_MDIV_EQ_PCK:
|
||||
break;
|
||||
case PMC_MCKR_MDIV_PCK_DIV2:
|
||||
procclk <<= 1; // multiply by 2
|
||||
break;
|
||||
case PMC_MCKR_MDIV_PCK_DIV3:
|
||||
procclk *= 3; // multiply by 3
|
||||
break;
|
||||
case PMC_MCKR_MDIV_PCK_DIV4:
|
||||
procclk <<= 2; // multiply by 4
|
||||
break;
|
||||
default:
|
||||
/* should never get here... */
|
||||
break;
|
||||
}
|
||||
|
||||
return procclk;
|
||||
}
|
||||
|
||||
void pmc_select_external_crystal(void)
|
||||
{
|
||||
int return_to_sclock = 0;
|
||||
|
||||
if (PMC->PMC_MCKR == PMC_MCKR_CSS(PMC_MCKR_CSS_SLOW_CLK)) {
|
||||
pmc_switch_mck_to_main();
|
||||
return_to_sclock = 1;
|
||||
}
|
||||
|
||||
/* switch from internal RC 32kHz to external OSC 32 kHz */
|
||||
SCKC->SCKC_CR = (SCKC->SCKC_CR & ~SCKC_CR_OSCSEL) | SCKC_CR_OSCSEL_XTAL;
|
||||
|
||||
/* Wait 5 slow clock cycles for internal resynchronization */
|
||||
volatile int count;
|
||||
for (count = 0; count < 0x1000; count++);
|
||||
|
||||
/* Switch to slow clock again if needed */
|
||||
if (return_to_sclock)
|
||||
pmc_switch_mck_to_slck();
|
||||
}
|
||||
|
||||
void pmc_select_internal_crystal(void)
|
||||
{
|
||||
int return_to_sclock = 0;
|
||||
|
||||
if (PMC->PMC_MCKR == PMC_MCKR_CSS(PMC_MCKR_CSS_SLOW_CLK)) {
|
||||
pmc_switch_mck_to_main();
|
||||
return_to_sclock = 1;
|
||||
}
|
||||
|
||||
/* switch from extenal OSC 32kHz to internal RC 32 kHz */
|
||||
/* switch slow clock source to internal OSC 32 kHz */
|
||||
SCKC->SCKC_CR = (SCKC->SCKC_CR & ~SCKC_CR_OSCSEL) | SCKC_CR_OSCSEL_RC;
|
||||
|
||||
/* Wait 5 slow clock cycles for internal resynchronization */
|
||||
volatile int count;
|
||||
for (count = 0; count < 0x1000; count++);
|
||||
|
||||
/* Switch to slow clock again if needed */
|
||||
if (return_to_sclock)
|
||||
pmc_switch_mck_to_slck();
|
||||
}
|
||||
|
||||
void pmc_select_external_osc(void)
|
||||
{
|
||||
/* Enable external osc 12 MHz when needed */
|
||||
if ((PMC->CKGR_MOR & CKGR_MOR_MOSCXTEN) != CKGR_MOR_MOSCXTEN) {
|
||||
PMC->CKGR_MOR |= CKGR_MOR_MOSCXTST(18) | CKGR_MOR_MOSCXTEN | CKGR_MOR_KEY_PASSWD;
|
||||
/* Wait Main Oscillator ready */
|
||||
while(!(PMC->PMC_SR & PMC_SR_MOSCXTS));
|
||||
}
|
||||
|
||||
/* Return if external osc had been selected */
|
||||
if ((PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) == CKGR_MOR_MOSCSEL)
|
||||
return;
|
||||
|
||||
/* switch MAIN clock to external OSC 12 MHz */
|
||||
PMC->CKGR_MOR |= CKGR_MOR_MOSCSEL | CKGR_MOR_KEY_PASSWD;
|
||||
|
||||
/* wait for the command to be taken into account */
|
||||
while ((PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) != CKGR_MOR_MOSCSEL);
|
||||
|
||||
/* wait MAIN clock status change for external OSC 12 MHz selection */
|
||||
while (!(PMC->PMC_SR & PMC_SR_MOSCSELS));
|
||||
|
||||
/* disable internal RC 12 MHz to save power */
|
||||
pmc_disable_internal_osc();
|
||||
}
|
||||
|
||||
void pmc_disable_external_osc(void)
|
||||
{
|
||||
/* disable external OSC 12 MHz */
|
||||
PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCXTEN) | CKGR_MOR_KEY_PASSWD;
|
||||
}
|
||||
|
||||
void pmc_select_internal_osc(void)
|
||||
{
|
||||
#ifdef CKGR_MOR_MOSCRCEN
|
||||
/* Enable internal RC 12 MHz when needed */
|
||||
if ((PMC->CKGR_MOR & CKGR_MOR_MOSCRCEN) != CKGR_MOR_MOSCRCEN) {
|
||||
PMC->CKGR_MOR |= CKGR_MOR_MOSCRCEN | CKGR_MOR_KEY_PASSWD;
|
||||
/* Wait internal 12 MHz RC Startup Time for clock stabilization */
|
||||
while (!(PMC->PMC_SR & PMC_SR_MOSCRCS));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* switch MAIN clock to internal RC 12 MHz */
|
||||
PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCSEL) | CKGR_MOR_KEY_PASSWD;
|
||||
|
||||
/* in case where MCK is running on MAIN CLK */
|
||||
while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
|
||||
|
||||
/* disable external OSC 12 MHz to save power*/
|
||||
pmc_disable_external_osc();
|
||||
}
|
||||
|
||||
void pmc_disable_internal_osc(void)
|
||||
{
|
||||
#ifdef CKGR_MOR_MOSCRCEN
|
||||
/* disable internal RC 12 MHz */
|
||||
PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCEN) | CKGR_MOR_KEY_PASSWD;
|
||||
#endif
|
||||
}
|
||||
|
||||
void pmc_switch_mck_to_pll(void)
|
||||
{
|
||||
/* Select PLL as input clock for PCK and MCK */
|
||||
PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_PLLA_CLK;
|
||||
while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
|
||||
|
||||
_pmc_mck = 0;
|
||||
}
|
||||
|
||||
void pmc_switch_mck_to_upll(void)
|
||||
{
|
||||
/* Select UPLL as input clock for PCK and MCK */
|
||||
PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_MCKR_CSS_UPLL_CLK;
|
||||
while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
|
||||
|
||||
_pmc_mck = 0;
|
||||
}
|
||||
|
||||
void pmc_switch_mck_to_main(void)
|
||||
{
|
||||
/* Select Main Oscillator as input clock for PCK and MCK */
|
||||
PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_PCK_CSS_MAIN_CLK;
|
||||
while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
|
||||
|
||||
_pmc_mck = 0;
|
||||
}
|
||||
|
||||
void pmc_switch_mck_to_slck(void)
|
||||
{
|
||||
/* Select Slow Clock as input clock for PCK and MCK */
|
||||
PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_CSS_Msk) | PMC_PCK_CSS_SLOW_CLK;
|
||||
while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
|
||||
|
||||
_pmc_mck = 0;
|
||||
}
|
||||
|
||||
void pmc_set_mck_prescaler(uint32_t prescaler)
|
||||
{
|
||||
/* Change MCK Prescaler divider in PMC_MCKR register */
|
||||
PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_PRES_Msk) | prescaler;
|
||||
while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
|
||||
}
|
||||
|
||||
void pmc_set_mck_plla_div(uint32_t divider)
|
||||
{
|
||||
if ((PMC->PMC_MCKR & PMC_MCKR_PLLADIV2) == PMC_MCKR_PLLADIV2) {
|
||||
if (divider == 0) {
|
||||
PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_PLLADIV2);
|
||||
}
|
||||
} else {
|
||||
if (divider == PMC_MCKR_PLLADIV2) {
|
||||
PMC->PMC_MCKR = (PMC->PMC_MCKR | PMC_MCKR_PLLADIV2);
|
||||
}
|
||||
}
|
||||
while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
|
||||
}
|
||||
|
||||
void pmc_set_mck_h32mxdiv(uint32_t divider)
|
||||
{
|
||||
if ((PMC->PMC_MCKR & PMC_MCKR_H32MXDIV) == PMC_MCKR_H32MXDIV_H32MXDIV2) {
|
||||
if (divider == PMC_MCKR_H32MXDIV_H32MXDIV1) {
|
||||
PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_H32MXDIV);
|
||||
}
|
||||
} else {
|
||||
if (divider == PMC_MCKR_H32MXDIV_H32MXDIV2) {
|
||||
PMC->PMC_MCKR = (PMC->PMC_MCKR | PMC_MCKR_H32MXDIV_H32MXDIV2);
|
||||
}
|
||||
}
|
||||
while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
|
||||
}
|
||||
|
||||
void pmc_set_mck_divider(uint32_t divider)
|
||||
{
|
||||
/* change MCK Prescaler divider in PMC_MCKR register */
|
||||
PMC->PMC_MCKR = (PMC->PMC_MCKR & ~PMC_MCKR_MDIV_Msk) | divider;
|
||||
while (!(PMC->PMC_SR & PMC_SR_MCKRDY));
|
||||
}
|
||||
|
||||
void pmc_set_plla(uint32_t pll, uint32_t cpcr)
|
||||
{
|
||||
PMC->CKGR_PLLAR = pll;
|
||||
PMC->PMC_PLLICPR = cpcr;
|
||||
|
||||
if ((pll & CKGR_PLLAR_DIVA_Msk) != CKGR_PLLAR_DIVA_0) {
|
||||
while (!(PMC->PMC_SR & PMC_SR_LOCKA));
|
||||
}
|
||||
}
|
||||
|
||||
void pmc_disable_plla(void)
|
||||
{
|
||||
PMC->CKGR_PLLAR = (PMC->CKGR_PLLAR & ~CKGR_PLLAR_MULA_Msk) | CKGR_PLLAR_MULA(0);
|
||||
}
|
||||
|
||||
void pmc_enable_system_clock(enum _pmc_system_clock clock)
|
||||
{
|
||||
uint32_t scer, scsr;
|
||||
if (!_pmc_get_system_clock_bits(clock, &scer, NULL, &scsr))
|
||||
return;
|
||||
|
||||
PMC->PMC_SCER |= scer;
|
||||
while (!(PMC->PMC_SCSR & scsr));
|
||||
}
|
||||
|
||||
void pmc_disable_system_clock(enum _pmc_system_clock clock)
|
||||
{
|
||||
uint32_t scdr, scsr;
|
||||
if (!_pmc_get_system_clock_bits(clock, NULL, &scdr, &scsr))
|
||||
return;
|
||||
|
||||
PMC->PMC_SCDR |= scdr;
|
||||
while (PMC->PMC_SCSR & scsr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_PMC_FAST_STARTUP
|
||||
void pmc_set_fast_startup_mode(uint32_t startup_mode)
|
||||
{
|
||||
PMC->PMC_FSMR = startup_mode;
|
||||
}
|
||||
|
||||
void pmc_set_fast_startup_polarity(uint32_t high_level, uint32_t low_level)
|
||||
{
|
||||
PMC->PMC_FSPR &= ~low_level;
|
||||
PMC->PMC_FSPR |= high_level;
|
||||
}
|
||||
#endif /* CONFIG_HAVE_PMC_FAST_STARTUP */
|
||||
|
||||
void pmc_set_custom_pck_mck(struct pck_mck_cfg *cfg)
|
||||
{
|
||||
pmc_switch_mck_to_slck();
|
||||
|
||||
if (cfg->ext12m)
|
||||
pmc_select_external_osc();
|
||||
else
|
||||
pmc_select_internal_osc();
|
||||
|
||||
pmc_switch_mck_to_main();
|
||||
|
||||
if (cfg->ext32k)
|
||||
pmc_select_external_crystal();
|
||||
else
|
||||
pmc_select_internal_crystal();
|
||||
|
||||
pmc_set_mck_prescaler(cfg->pck_pres);
|
||||
pmc_set_mck_divider(cfg->mck_div);
|
||||
|
||||
pmc_set_mck_plla_div(cfg->plla_div2 ? PMC_MCKR_PLLADIV2 : 0);
|
||||
if (cfg->plla_mul > 0) {
|
||||
pmc_disable_plla();
|
||||
uint32_t tmp = CKGR_PLLAR_ONE |
|
||||
CKGR_PLLAR_PLLACOUNT(0x3F) |
|
||||
CKGR_PLLAR_OUTA(0x0) |
|
||||
CKGR_PLLAR_MULA(cfg->plla_mul) |
|
||||
CKGR_PLLAR_DIVA(cfg->plla_div);
|
||||
pmc_set_plla(tmp, PMC_PLLICPR_IPLL_PLLA(0x3));
|
||||
} else {
|
||||
pmc_disable_plla();
|
||||
}
|
||||
|
||||
if (cfg->h32mxdiv2)
|
||||
pmc_set_mck_h32mxdiv(PMC_MCKR_H32MXDIV_H32MXDIV2);
|
||||
else
|
||||
pmc_set_mck_h32mxdiv(PMC_MCKR_H32MXDIV_H32MXDIV1);
|
||||
|
||||
switch (cfg->pck_input) {
|
||||
case PMC_MCKR_CSS_PLLA_CLK:
|
||||
pmc_switch_mck_to_pll();
|
||||
break;
|
||||
|
||||
case PMC_MCKR_CSS_UPLL_CLK:
|
||||
pmc_switch_mck_to_upll();
|
||||
break;
|
||||
|
||||
case PMC_MCKR_CSS_SLOW_CLK:
|
||||
pmc_switch_mck_to_slck();
|
||||
pmc_disable_internal_osc();
|
||||
pmc_disable_external_osc();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions (Peripherals)
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void pmc_enable_peripheral(uint32_t id)
|
||||
{
|
||||
assert(id > 1 && id < ID_PERIPH_COUNT);
|
||||
|
||||
PMC->PMC_PCR = PMC_PCR_PID(id);
|
||||
volatile uint32_t pcr = PMC->PMC_PCR;
|
||||
|
||||
PMC->PMC_PCR = pcr | PMC_PCR_CMD | PMC_PCR_EN;
|
||||
}
|
||||
|
||||
void pmc_disable_peripheral(uint32_t id)
|
||||
{
|
||||
assert(id > 1 && id < ID_PERIPH_COUNT);
|
||||
|
||||
PMC->PMC_PCR = PMC_PCR_PID(id);
|
||||
volatile uint32_t pcr = PMC->PMC_PCR;
|
||||
|
||||
PMC->PMC_PCR = PMC_PCR_CMD | (pcr & ~PMC_PCR_EN);
|
||||
}
|
||||
|
||||
uint32_t pmc_is_peripheral_enabled(uint32_t id)
|
||||
{
|
||||
assert(id > 1 && id < ID_PERIPH_COUNT);
|
||||
|
||||
PMC->PMC_PCR = PMC_PCR_PID(id);
|
||||
volatile uint32_t pcr = PMC->PMC_PCR;
|
||||
|
||||
return !!(pcr & PMC_PCR_EN);
|
||||
}
|
||||
|
||||
uint32_t pmc_get_peripheral_clock(uint32_t id)
|
||||
{
|
||||
assert(id > 1 && id < ID_PERIPH_COUNT);
|
||||
|
||||
uint32_t div = get_peripheral_clock_divider(id);
|
||||
if (div)
|
||||
return pmc_get_master_clock() / div;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pmc_disable_all_peripherals(void)
|
||||
{
|
||||
int i;
|
||||
for (i = 2; i < ID_PERIPH_COUNT; i++)
|
||||
pmc_disable_peripheral(i);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions (PCK0-2)
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void pmc_configure_pck0(uint32_t clock_source, uint32_t prescaler)
|
||||
{
|
||||
pmc_disable_pck0();
|
||||
PMC->PMC_PCK[0] = (clock_source & PMC_PCK_CSS_Msk) | PMC_PCK_PRES(prescaler);
|
||||
}
|
||||
|
||||
void pmc_enable_pck0(void)
|
||||
{
|
||||
PMC->PMC_SCER = PMC_SCER_PCK0;
|
||||
while (!(PMC->PMC_SR & PMC_SR_PCKRDY0));
|
||||
}
|
||||
|
||||
void pmc_disable_pck0(void)
|
||||
{
|
||||
PMC->PMC_SCDR = PMC_SCDR_PCK0;
|
||||
while (PMC->PMC_SCSR & PMC_SCSR_PCK0);
|
||||
}
|
||||
|
||||
uint32_t pmc_get_pck0_clock(void)
|
||||
{
|
||||
return _pmc_get_pck_clock(0);
|
||||
}
|
||||
|
||||
void pmc_configure_pck1(uint32_t clock_source, uint32_t prescaler)
|
||||
{
|
||||
pmc_disable_pck1();
|
||||
PMC->PMC_PCK[1] = (clock_source & PMC_PCK_CSS_Msk) | PMC_PCK_PRES(prescaler);
|
||||
}
|
||||
|
||||
void pmc_enable_pck1(void)
|
||||
{
|
||||
PMC->PMC_SCER = PMC_SCER_PCK1;
|
||||
while (!(PMC->PMC_SR & PMC_SR_PCKRDY1));
|
||||
}
|
||||
|
||||
void pmc_disable_pck1(void)
|
||||
{
|
||||
PMC->PMC_SCDR = PMC_SCDR_PCK1;
|
||||
while (PMC->PMC_SCSR & PMC_SCSR_PCK1);
|
||||
}
|
||||
|
||||
uint32_t pmc_get_pck1_clock(void)
|
||||
{
|
||||
return _pmc_get_pck_clock(1);
|
||||
}
|
||||
|
||||
void pmc_configure_pck2(uint32_t clock_source, uint32_t prescaler)
|
||||
{
|
||||
pmc_disable_pck2();
|
||||
PMC->PMC_PCK[2] = (clock_source & PMC_PCK_CSS_Msk) | PMC_PCK_PRES(prescaler);
|
||||
}
|
||||
|
||||
void pmc_enable_pck2(void)
|
||||
{
|
||||
PMC->PMC_SCER = PMC_SCER_PCK2;
|
||||
while (!(PMC->PMC_SR & PMC_SR_PCKRDY2));
|
||||
}
|
||||
|
||||
void pmc_disable_pck2(void)
|
||||
{
|
||||
PMC->PMC_SCDR = PMC_SCDR_PCK2;
|
||||
while (PMC->PMC_SCSR & PMC_SCSR_PCK2);
|
||||
}
|
||||
|
||||
uint32_t pmc_get_pck2_clock(void)
|
||||
{
|
||||
return _pmc_get_pck_clock(2);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions (UPLL)
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void pmc_enable_upll_clock(void)
|
||||
{
|
||||
/* enable 480Mhz UPLL */
|
||||
PMC->CKGR_UCKR = CKGR_UCKR_UPLLEN | CKGR_UCKR_UPLLCOUNT(0x3)
|
||||
| CKGR_UCKR_BIASCOUNT(0x1);
|
||||
|
||||
/* wait until UPLL is locked */
|
||||
while (!(PMC->PMC_SR & PMC_SR_LOCKU));
|
||||
}
|
||||
|
||||
void pmc_disable_upll_clock(void)
|
||||
{
|
||||
PMC->CKGR_UCKR &= ~CKGR_UCKR_UPLLEN;
|
||||
}
|
||||
|
||||
uint32_t pmc_get_upll_clock(void)
|
||||
{
|
||||
#ifdef SFR_UTMICKTRIM_FREQ_Msk
|
||||
uint32_t clktrim = SFR->SFR_UTMICKTRIM & SFR_UTMICKTRIM_FREQ_Msk;
|
||||
switch (clktrim) {
|
||||
case SFR_UTMICKTRIM_FREQ_16:
|
||||
return 30 * BOARD_MAIN_CLOCK_EXT_OSC;
|
||||
case SFR_UTMICKTRIM_FREQ_24:
|
||||
return 20 * BOARD_MAIN_CLOCK_EXT_OSC;
|
||||
default:
|
||||
return 40 * BOARD_MAIN_CLOCK_EXT_OSC;
|
||||
}
|
||||
#else
|
||||
return 40 * BOARD_MAIN_CLOCK_EXT_OSC;
|
||||
#endif
|
||||
}
|
||||
|
||||
void pmc_enable_upll_bias(void)
|
||||
{
|
||||
PMC->CKGR_UCKR |= CKGR_UCKR_BIASEN;
|
||||
}
|
||||
|
||||
void pmc_disable_upll_bias(void)
|
||||
{
|
||||
PMC->CKGR_UCKR &= ~CKGR_UCKR_BIASEN;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions (Generated clocks)
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef CONFIG_HAVE_PMC_GENERATED_CLOCKS
|
||||
void pmc_configure_gck(uint32_t id, uint32_t clock_source, uint32_t div)
|
||||
{
|
||||
assert(id > 1 && id < ID_PERIPH_COUNT);
|
||||
assert(!(clock_source & ~PMC_PCR_GCKCSS_Msk));
|
||||
assert(!(div << PMC_PCR_GCKDIV_Pos & ~PMC_PCR_GCKDIV_Msk));
|
||||
|
||||
pmc_disable_gck(id);
|
||||
PMC->PMC_PCR = PMC_PCR_PID(id);
|
||||
volatile uint32_t pcr = PMC->PMC_PCR;
|
||||
PMC->PMC_PCR = pcr | (clock_source & PMC_PCR_GCKCSS_Msk) | PMC_PCR_CMD
|
||||
| PMC_PCR_GCKDIV(div);
|
||||
}
|
||||
|
||||
void pmc_enable_gck(uint32_t id)
|
||||
{
|
||||
assert(id > 1 && id < ID_PERIPH_COUNT);
|
||||
|
||||
PMC->PMC_PCR = PMC_PCR_PID(id);
|
||||
volatile uint32_t pcr = PMC->PMC_PCR;
|
||||
PMC->PMC_PCR = pcr | PMC_PCR_CMD | PMC_PCR_GCKEN;
|
||||
while (!(PMC->PMC_SR & PMC_SR_GCKRDY));
|
||||
}
|
||||
|
||||
void pmc_disable_gck(uint32_t id)
|
||||
{
|
||||
assert(id > 1 && id < ID_PERIPH_COUNT);
|
||||
|
||||
PMC->PMC_PCR = PMC_PCR_PID(id);
|
||||
volatile uint32_t pcr = PMC->PMC_PCR;
|
||||
PMC->PMC_PCR = PMC_PCR_CMD | (pcr & ~PMC_PCR_GCKEN);
|
||||
}
|
||||
|
||||
uint32_t pmc_get_gck_clock(uint32_t id)
|
||||
{
|
||||
uint32_t clk = 0;
|
||||
assert(id > 1 && id < ID_PERIPH_COUNT);
|
||||
|
||||
PMC->PMC_PCR = PMC_PCR_PID(id);
|
||||
volatile uint32_t pcr = PMC->PMC_PCR;
|
||||
|
||||
switch (pcr & PMC_PCR_GCKCSS_Msk) {
|
||||
case PMC_PCR_GCKCSS_SLOW_CLK:
|
||||
clk = pmc_get_slow_clock();
|
||||
break;
|
||||
case PMC_PCR_GCKCSS_MAIN_CLK:
|
||||
clk = pmc_get_main_clock();
|
||||
break;
|
||||
case PMC_PCR_GCKCSS_PLLA_CLK:
|
||||
clk = pmc_get_plla_clock();
|
||||
break;
|
||||
case PMC_PCR_GCKCSS_UPLL_CLK:
|
||||
clk = pmc_get_upll_clock();
|
||||
break;
|
||||
case PMC_PCR_GCKCSS_MCK_CLK:
|
||||
clk = pmc_get_master_clock();
|
||||
break;
|
||||
#ifdef CONFIG_HAVE_PMC_AUDIO_CLOCK
|
||||
case PMC_PCR_GCKCSS_AUDIO_CLK:
|
||||
clk = pmc_get_audio_pmc_clock();
|
||||
break;
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t div = (pcr & PMC_PCR_GCKDIV_Msk) >> PMC_PCR_GCKDIV_Pos;
|
||||
return ROUND_INT_DIV(clk, div + 1);
|
||||
}
|
||||
#endif /* CONFIG_HAVE_PMC_GENERATED_CLOCKS */
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions (Audio PLL)
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef CONFIG_HAVE_PMC_AUDIO_CLOCK
|
||||
void pmc_configure_audio(struct _pmc_audio_cfg *cfg)
|
||||
{
|
||||
/* reset audio clock */
|
||||
PMC->PMC_AUDIO_PLL0 &= ~PMC_AUDIO_PLL0_RESETN;
|
||||
PMC->PMC_AUDIO_PLL0 |= PMC_AUDIO_PLL0_RESETN;
|
||||
|
||||
/* configure values */
|
||||
uint32_t pll0 = PMC->PMC_AUDIO_PLL0;
|
||||
pll0 &= ~PMC_AUDIO_PLL0_ND_Msk;
|
||||
pll0 |= cfg->nd << PMC_AUDIO_PLL0_ND_Pos;
|
||||
pll0 &= ~PMC_AUDIO_PLL0_QDPMC_Msk;
|
||||
pll0 |= cfg->qdpmc << PMC_AUDIO_PLL0_QDPMC_Pos;
|
||||
PMC->PMC_AUDIO_PLL0 = pll0;
|
||||
uint32_t pll1 = PMC->PMC_AUDIO_PLL1;
|
||||
pll1 &= ~PMC_AUDIO_PLL1_DIV_Msk;
|
||||
pll1 |= cfg->div << PMC_AUDIO_PLL1_DIV_Pos;
|
||||
pll1 &= ~PMC_AUDIO_PLL1_FRACR_Msk;
|
||||
pll1 |= cfg->fracr << PMC_AUDIO_PLL1_FRACR_Pos;
|
||||
pll1 &= ~PMC_AUDIO_PLL1_QDAUDIO_Msk;
|
||||
pll1 |= cfg->qdaudio << PMC_AUDIO_PLL1_QDAUDIO_Pos;
|
||||
PMC->PMC_AUDIO_PLL1 = pll1;
|
||||
}
|
||||
|
||||
void pmc_enable_audio(bool pmc_clock, bool pad_clock)
|
||||
{
|
||||
uint32_t bits = PMC_AUDIO_PLL0_PLLEN | PMC_AUDIO_PLL0_RESETN;
|
||||
uint32_t nbits = 0;
|
||||
|
||||
if (pad_clock)
|
||||
bits |= PMC_AUDIO_PLL0_PADEN;
|
||||
else
|
||||
nbits |= PMC_AUDIO_PLL0_PADEN;
|
||||
|
||||
if (pmc_clock)
|
||||
bits |= PMC_AUDIO_PLL0_PMCEN;
|
||||
else
|
||||
nbits |= PMC_AUDIO_PLL0_PMCEN;
|
||||
|
||||
PMC->PMC_AUDIO_PLL0 = (PMC->PMC_AUDIO_PLL0 & ~nbits) | bits;
|
||||
}
|
||||
|
||||
void pmc_disable_audio()
|
||||
{
|
||||
uint32_t nbits = PMC_AUDIO_PLL0_PLLEN | PMC_AUDIO_PLL0_RESETN |
|
||||
PMC_AUDIO_PLL0_PADEN | PMC_AUDIO_PLL0_PMCEN;
|
||||
PMC->PMC_AUDIO_PLL0 &= ~nbits;
|
||||
}
|
||||
|
||||
uint32_t pmc_get_audio_pmc_clock(void)
|
||||
{
|
||||
uint32_t pll0 = PMC->PMC_AUDIO_PLL0;
|
||||
uint32_t pll1 = PMC->PMC_AUDIO_PLL1;
|
||||
|
||||
uint32_t nd = (pll0 & PMC_AUDIO_PLL0_ND_Msk) >> PMC_AUDIO_PLL0_ND_Pos;
|
||||
uint32_t fracr = (pll1 & PMC_AUDIO_PLL1_FRACR_Msk) >> PMC_AUDIO_PLL1_FRACR_Pos;
|
||||
uint32_t qdpmc = (pll0 & PMC_AUDIO_PLL0_QDPMC_Msk) >> PMC_AUDIO_PLL0_QDPMC_Pos;
|
||||
|
||||
uint64_t clk = BOARD_MAIN_CLOCK_EXT_OSC;
|
||||
clk *= ((nd + 1) << 22) + fracr;
|
||||
clk /= 1 << 22;
|
||||
clk /= qdpmc + 1;
|
||||
return (uint32_t)clk;
|
||||
}
|
||||
|
||||
uint32_t pmc_get_audio_pad_clock(void)
|
||||
{
|
||||
uint32_t pll0 = PMC->PMC_AUDIO_PLL0;
|
||||
uint32_t pll1 = PMC->PMC_AUDIO_PLL1;
|
||||
|
||||
uint32_t nd = (pll0 & PMC_AUDIO_PLL0_ND_Msk) >> PMC_AUDIO_PLL0_ND_Pos;
|
||||
uint32_t fracr = (pll1 & PMC_AUDIO_PLL1_FRACR_Msk) >> PMC_AUDIO_PLL1_FRACR_Pos;
|
||||
uint32_t qdaudio = (pll1 & PMC_AUDIO_PLL1_QDAUDIO_Msk) >> PMC_AUDIO_PLL1_QDAUDIO_Pos;
|
||||
if (qdaudio == 0)
|
||||
return 0;
|
||||
|
||||
uint32_t div = (pll1 & PMC_AUDIO_PLL1_DIV_Msk) >> PMC_AUDIO_PLL1_DIV_Pos;
|
||||
if (div != 2 && div != 3)
|
||||
return 0;
|
||||
|
||||
uint64_t clk = BOARD_MAIN_CLOCK_EXT_OSC;
|
||||
clk *= ((nd + 1) << 22) + fracr;
|
||||
clk /= 1 << 22;
|
||||
clk /= div * qdaudio;
|
||||
return (uint32_t)clk;
|
||||
}
|
||||
#endif /* CONFIG_HAVE_PMC_AUDIO_CLOCK */
|
||||
|
|
@ -0,0 +1,466 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _PMC_H_
|
||||
#define _PMC_H_
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "board.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Types
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
struct pck_mck_cfg {
|
||||
/** PLL A, SLCK, MAIN, UPLL */
|
||||
uint32_t pck_input;
|
||||
|
||||
/** RC12M (false) or EXT12M (true) */
|
||||
bool ext12m;
|
||||
|
||||
/** RC32K (false) or EXT32K (true) */
|
||||
bool ext32k;
|
||||
|
||||
/** PLLA MUL value in PMC PLL register */
|
||||
uint32_t plla_mul;
|
||||
|
||||
/** PLLA DIV value in PMC PLL register */
|
||||
uint32_t plla_div;
|
||||
|
||||
/** PLLA DIV value by 2 */
|
||||
bool plla_div2;
|
||||
|
||||
/** Master/Processor Clock Prescaler */
|
||||
uint32_t pck_pres;
|
||||
|
||||
/** Master Clock Division after Prescaler divider */
|
||||
uint32_t mck_div;
|
||||
|
||||
/** true if the AHB 32-bit Matrix frequency is equal to the AHB 64-bit Matrix frequency divided by 2 */
|
||||
bool h32mxdiv2;
|
||||
};
|
||||
|
||||
/**
|
||||
* \brief System clock identifiers, used for pmc_{enable,disable}_system_clock
|
||||
*/
|
||||
enum _pmc_system_clock {
|
||||
PMC_SYSTEM_CLOCK_PCK,
|
||||
PMC_SYSTEM_CLOCK_DDR,
|
||||
PMC_SYSTEM_CLOCK_LCD,
|
||||
PMC_SYSTEM_CLOCK_SMD,
|
||||
PMC_SYSTEM_CLOCK_UHP,
|
||||
PMC_SYSTEM_CLOCK_UDP,
|
||||
PMC_SYSTEM_CLOCK_PCK0,
|
||||
PMC_SYSTEM_CLOCK_PCK1,
|
||||
PMC_SYSTEM_CLOCK_PCK2,
|
||||
PMC_SYSTEM_CLOCK_ISC,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_HAVE_PMC_AUDIO_CLOCK
|
||||
/**
|
||||
* \brief Configuration data for Audio clock
|
||||
*
|
||||
* AUDIOPLLCK = BOARD_EXT_OSC * (nd + 1 + (fracr / 2^22)) / (qdpmc + 1)
|
||||
* AUDIOPINCLK = BOARD_EXT_OSC * (nc + 1 + (fracr / 2^22)) / (div * qdaudio)
|
||||
*/
|
||||
struct _pmc_audio_cfg {
|
||||
uint32_t nd;
|
||||
uint32_t fracr;
|
||||
uint32_t qdpmc;
|
||||
uint32_t div;
|
||||
uint32_t qdaudio;
|
||||
};
|
||||
#endif /* CONFIG_HAVE_PMC_AUDIO_CLOCK */
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Configure PCK and MCK with custom setting
|
||||
*/
|
||||
extern void pmc_set_custom_pck_mck(struct pck_mck_cfg *cfg);
|
||||
|
||||
/**
|
||||
* \brief Get the configured frequency of the master clock
|
||||
* \return master clock frequency in Hz
|
||||
*/
|
||||
extern uint32_t pmc_get_master_clock(void);
|
||||
|
||||
/**
|
||||
* \brief Get the configured frequency of the slow clock
|
||||
* \return slow clock frequency in Hz
|
||||
*/
|
||||
extern uint32_t pmc_get_slow_clock(void);
|
||||
|
||||
/**
|
||||
* \brief Get the configured frequency of the main clock
|
||||
* \return main clock frequency in Hz
|
||||
*/
|
||||
extern uint32_t pmc_get_main_clock(void);
|
||||
|
||||
/**
|
||||
* \brief Get the configured frequency of the PLLA clock
|
||||
* \return PLLA clock frequency in Hz
|
||||
*/
|
||||
extern uint32_t pmc_get_plla_clock(void);
|
||||
|
||||
/**
|
||||
* \brief Get the configured frequency of the processor clock
|
||||
* \return processor clock frequency in Hz
|
||||
*/
|
||||
extern uint32_t pmc_get_processor_clock(void);
|
||||
|
||||
/**
|
||||
* \brief Select external 32K crystal.
|
||||
*/
|
||||
extern void pmc_select_external_crystal(void);
|
||||
|
||||
/**
|
||||
* \brief Select internal 32K crystal.
|
||||
*/
|
||||
extern void pmc_select_internal_crystal(void);
|
||||
|
||||
/**
|
||||
* \brief Select external 12M OSC.
|
||||
*/
|
||||
extern void pmc_select_external_osc(void);
|
||||
|
||||
/**
|
||||
* \brief Disable external 12M OSC.
|
||||
*/
|
||||
extern void pmc_disable_external_osc(void);
|
||||
|
||||
/**
|
||||
* \brief Select internal 12M OSC.
|
||||
*/
|
||||
extern void pmc_select_internal_osc(void);
|
||||
|
||||
/**
|
||||
* \brief Disable internal 12M OSC.
|
||||
*/
|
||||
extern void pmc_disable_internal_osc(void);
|
||||
|
||||
/**
|
||||
* \brief Switch PMC from MCK to PLL clock.
|
||||
*/
|
||||
extern void pmc_switch_mck_to_pll(void);
|
||||
|
||||
/**
|
||||
* \brief Switch PMC from MCK to UPLL clock.
|
||||
*/
|
||||
extern void pmc_switch_mck_to_upll(void);
|
||||
|
||||
/**
|
||||
* \brief Switch PMC from MCK to main clock.
|
||||
*/
|
||||
extern void pmc_switch_mck_to_main(void);
|
||||
|
||||
/**
|
||||
* \brief Switch PMC from MCK to slow clock.
|
||||
*/
|
||||
extern void pmc_switch_mck_to_slck(void);
|
||||
|
||||
/**
|
||||
* \brief Configure PLL Register.
|
||||
* \param pll pll value.
|
||||
* \param cpcr cpcr value.
|
||||
*/
|
||||
extern void pmc_set_plla(uint32_t pll, uint32_t cpcr);
|
||||
|
||||
/**
|
||||
* \brief Configure MCK Prescaler.
|
||||
* \param prescaler prescaler value.
|
||||
*/
|
||||
extern void pmc_set_mck_prescaler(uint32_t prescaler);
|
||||
|
||||
/**
|
||||
* \brief Configure MCK Divider.
|
||||
* \param divider divider value.
|
||||
*/
|
||||
extern void pmc_set_mck_divider(uint32_t divider);
|
||||
|
||||
/**
|
||||
* \brief Configure MCK H32MXDIV.
|
||||
* \param divider divider value.
|
||||
*/
|
||||
extern void pmc_set_mck_h32mxdiv(uint32_t divider);
|
||||
|
||||
/**
|
||||
* \brief Configure MCK PLLA divider.
|
||||
* \param divider PLL divider value.
|
||||
*/
|
||||
extern void pmc_set_mck_plla_div(uint32_t divider);
|
||||
|
||||
/**
|
||||
* \brief Disable PLLA Register.
|
||||
*/
|
||||
extern void pmc_disable_plla(void);
|
||||
|
||||
/**
|
||||
* \brief Enables a system clock
|
||||
* \param clock system clock to enable
|
||||
*/
|
||||
extern void pmc_enable_system_clock(enum _pmc_system_clock clock);
|
||||
|
||||
/**
|
||||
* \brief Disables a system clock
|
||||
* \param clock system clock to disable
|
||||
*/
|
||||
extern void pmc_disable_system_clock(enum _pmc_system_clock clock);
|
||||
|
||||
#ifdef CONFIG_HAVE_PMC_FAST_STARTUP
|
||||
/**
|
||||
* \brief Set up fast startup mode
|
||||
* \param source and low power mode
|
||||
*/
|
||||
extern void pmc_set_fast_startup_mode(uint32_t startup_mode);
|
||||
|
||||
/**
|
||||
* \brief Set up fast startup polarity
|
||||
* \param level
|
||||
*/
|
||||
extern void pmc_set_fast_startup_polarity(uint32_t high_level,
|
||||
uint32_t low_level);
|
||||
#endif /* CONFIG_HAVE_PMC_FAST_STARTUP */
|
||||
|
||||
/**
|
||||
* \brief Enables the clock of a peripheral. The peripheral ID is used
|
||||
* to identify which peripheral is targeted.
|
||||
*
|
||||
* \param id Peripheral ID (ID_xxx).
|
||||
*/
|
||||
extern void pmc_enable_peripheral(uint32_t id);
|
||||
|
||||
/**
|
||||
* \brief Disables the clock of a peripheral. The peripheral ID is used
|
||||
* to identify which peripheral is targeted.
|
||||
*
|
||||
* \param id Peripheral ID (ID_xxx).
|
||||
*/
|
||||
extern void pmc_disable_peripheral(uint32_t id);
|
||||
|
||||
/**
|
||||
* \brief Get Peripheral Status for the given peripheral ID.
|
||||
*
|
||||
* \param id Peripheral ID (ID_xxx).
|
||||
*/
|
||||
extern uint32_t pmc_is_peripheral_enabled(uint32_t id);
|
||||
|
||||
/**
|
||||
* \brief Get current frequency clock for the given peripheral ID.
|
||||
*
|
||||
* \param id Peripheral ID (ID_xxx).
|
||||
*/
|
||||
extern uint32_t pmc_get_peripheral_clock(uint32_t id);
|
||||
|
||||
/**
|
||||
* \brief Disable clocks for all peripherals
|
||||
*/
|
||||
extern void pmc_disable_all_peripherals(void);
|
||||
|
||||
/**
|
||||
* \brief Configure programmable clock 0 (PCK0) with the given master clock
|
||||
* source and clock prescaler
|
||||
* \param clock_source clock source selection (one of the PMC_PCK_CSS_xxx_CLK
|
||||
* constants)
|
||||
* \param prescaler prescaler
|
||||
*/
|
||||
extern void pmc_configure_pck0(uint32_t clock_source, uint32_t prescaler);
|
||||
|
||||
/**
|
||||
* \brief Enable programmable clock 0 (PCK0)
|
||||
*/
|
||||
extern void pmc_enable_pck0(void);
|
||||
|
||||
/**
|
||||
* \brief Disable programmable clock 0 (PCK0)
|
||||
*/
|
||||
extern void pmc_disable_pck0(void);
|
||||
|
||||
/**
|
||||
* \brief Get the frequency of the programmable clock 0 (PCK0)
|
||||
* \return PCK0 frequency in Hz
|
||||
*/
|
||||
extern uint32_t pmc_get_pck0_clock(void);
|
||||
|
||||
/**
|
||||
* \brief Configure programmable clock 1 (PCK1) with the given master clock
|
||||
* source and clock prescaler
|
||||
* \param clock_source Clock source selection (one of the PMC_PCK_CSS_xxx_CLK
|
||||
* constants)
|
||||
* \param prescaler Prescaler value
|
||||
*/
|
||||
extern void pmc_configure_pck1(uint32_t clock_source, uint32_t prescaler);
|
||||
|
||||
/**
|
||||
* \brief Enable programmable clock 1 (PCK1)
|
||||
*/
|
||||
extern void pmc_enable_pck1(void);
|
||||
|
||||
/**
|
||||
* \brief Disable programmable clock 1 (PCK1)
|
||||
*/
|
||||
extern void pmc_disable_pck1(void);
|
||||
|
||||
/**
|
||||
* \brief Get the frequency of the programmable clock 1 (PCK1)
|
||||
* \return PCK1 Frequency in Hz
|
||||
*/
|
||||
extern uint32_t pmc_get_pck1_clock(void);
|
||||
|
||||
/**
|
||||
* \brief Configure programmable clock 2 (PCK2) with the given master clock
|
||||
* source and clock prescaler
|
||||
* \param clock_source Clock source selection (one of the PMC_PCK_CSS_xxx_CLK
|
||||
* constants)
|
||||
* \param prescaler Prescaler value
|
||||
*/
|
||||
extern void pmc_configure_pck2(uint32_t clock_source, uint32_t prescaler);
|
||||
|
||||
/**
|
||||
* \brief Enable programmable clock 2 (PCK2)
|
||||
*/
|
||||
extern void pmc_enable_pck2(void);
|
||||
|
||||
/**
|
||||
* \brief Disable programmable clock 2 (PCK2)
|
||||
*/
|
||||
extern void pmc_disable_pck2(void);
|
||||
|
||||
/**
|
||||
* \brief Get the frequency of the programmable clock 2 (PCK2)
|
||||
* \return PCK2 Frequency in Hz
|
||||
*/
|
||||
extern uint32_t pmc_get_pck2_clock(void);
|
||||
|
||||
/**
|
||||
* \brief Enable the UPLL clock
|
||||
*/
|
||||
extern void pmc_enable_upll_clock(void);
|
||||
|
||||
/**
|
||||
* \brief Disable the UPLL clock
|
||||
*/
|
||||
extern void pmc_disable_upll_clock(void);
|
||||
|
||||
/**
|
||||
* \brief Get the frequency of the UPLL clock
|
||||
* \return UPLL clock frequency in Hz
|
||||
*/
|
||||
extern uint32_t pmc_get_upll_clock(void);
|
||||
|
||||
/**
|
||||
* \brief Enable the UPLL clock bias
|
||||
*/
|
||||
extern void pmc_enable_upll_bias(void);
|
||||
|
||||
/**
|
||||
* \brief Disable the UPLL clock bias
|
||||
*/
|
||||
extern void pmc_disable_upll_bias(void);
|
||||
|
||||
#ifdef CONFIG_HAVE_PMC_GENERATED_CLOCKS
|
||||
/**
|
||||
* \brief Configure the generated clock (GCK) for the given peripheral with the
|
||||
* given master clock source and clock prescaler
|
||||
* \param id Peripheral ID (ID_xxx)
|
||||
* \param clock_source Clock source selection (one of the
|
||||
* PMC_PCR_GCKCSS_xxx_CLK constants)
|
||||
* \param div Generated Clock Division Ratio (selected clock is divided by
|
||||
* div + 1)
|
||||
*/
|
||||
extern void pmc_configure_gck(uint32_t id, uint32_t clock_source, uint32_t div);
|
||||
|
||||
/**
|
||||
* \brief Enable generated clock for the given peripheral
|
||||
* \param id Peripheral ID (ID_xxx)
|
||||
*/
|
||||
extern void pmc_enable_gck(uint32_t id);
|
||||
|
||||
/**
|
||||
* \brief Disable generated clock for the given peripheral
|
||||
* \param id Peripheral ID (ID_xxx)
|
||||
*/
|
||||
extern void pmc_disable_gck(uint32_t id);
|
||||
|
||||
/**
|
||||
* \brief Get the frequency of the generated clock (GCK) for the given
|
||||
* peripheral
|
||||
* \param id Peripheral ID (ID_xxx)
|
||||
* \return GCK Frequency in Hz
|
||||
*/
|
||||
extern uint32_t pmc_get_gck_clock(uint32_t id);
|
||||
#endif /* CONFIG_HAVE_PMC_GENERATED_CLOCKS */
|
||||
|
||||
#ifdef CONFIG_HAVE_PMC_AUDIO_CLOCK
|
||||
/**
|
||||
* \brief Configure the audio clock
|
||||
*/
|
||||
extern void pmc_configure_audio(struct _pmc_audio_cfg *cfg);
|
||||
|
||||
/**
|
||||
* \brief Enable audio clocks
|
||||
* \param pmc_clock if true AUDIOPLLCK is sent to the PMC
|
||||
* \param pad_clock if true the external audio pin is driven by AUDIOPINCLK, if
|
||||
* false the audio pin is driven low
|
||||
*/
|
||||
extern void pmc_enable_audio(bool pmc_clock, bool pad_clock);
|
||||
|
||||
/**
|
||||
* \brief Disable audio clocks
|
||||
*/
|
||||
extern void pmc_disable_audio(void);
|
||||
|
||||
/**
|
||||
* \brief Get the frequency of the audio PMC clock
|
||||
* \return Audio PMC Frequency in Hz
|
||||
*/
|
||||
extern uint32_t pmc_get_audio_pmc_clock(void);
|
||||
|
||||
/**
|
||||
* \brief Get the frequency of the audio pad clock
|
||||
* \return Audio pad Frequency in Hz
|
||||
*/
|
||||
extern uint32_t pmc_get_audio_pad_clock(void);
|
||||
#endif /* CONFIG_HAVE_PMC_AUDIO_CLOCK */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* #ifndef _PMC_H_ */
|
|
@ -0,0 +1,749 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2012, Atmel Corporation
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file */
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "peripherals/pmecc.h"
|
||||
#include "peripherals/pmecc_gallois_field_512.h"
|
||||
#include "peripherals/pmecc_gallois_field_1024.h"
|
||||
|
||||
/*--------------------------------------------------------------------------- */
|
||||
/* Local types */
|
||||
/*--------------------------------------------------------------------------- */
|
||||
|
||||
/** PMECC configuration descriptor */
|
||||
struct _pmecc_descriptor {
|
||||
/** Number of Sectors in one Page */
|
||||
uint32_t page_size;
|
||||
|
||||
/** The spare area size is equal to (SPARESIZE+1) bytes */
|
||||
uint32_t spare_size;
|
||||
|
||||
/** 0 for 512, 1 for 1024 bytes, like in PMECCFG register */
|
||||
uint32_t sector_size;
|
||||
|
||||
/** Coded value of ECC bit number correction
|
||||
* 0 (2 bits), 1 (4 bits), 2 (8 bits), 3 (12 bits), 4 (24 bits), 5 (NU)) */
|
||||
uint32_t err_bit_nbr_capability;
|
||||
|
||||
/** Real size in bytes of ECC in spare */
|
||||
uint32_t ecc_size_byte;
|
||||
|
||||
/** The first byte address of the ECC area */
|
||||
uint32_t ecc_start_address;
|
||||
|
||||
/** The last byte address of the ECC area */
|
||||
uint32_t ecc_end_address;
|
||||
|
||||
/** NAND Write Access*/
|
||||
uint32_t nand_wr;
|
||||
|
||||
/** Spare Enable */
|
||||
uint32_t spare_ena;
|
||||
|
||||
/** Automatic Mode */
|
||||
uint32_t mode_auto;
|
||||
|
||||
/** The PMECC Module data path Setup Time is set to CLKCTRL+1. */
|
||||
uint32_t clk_ctrl;
|
||||
|
||||
/** */
|
||||
uint32_t interrupt;
|
||||
|
||||
/** defines the error correcting capability selected at encoding/decoding time */
|
||||
int32_t tt;
|
||||
|
||||
/** degree of the remainders, GF(2**mm) */
|
||||
int32_t mm;
|
||||
|
||||
/** length of codeword = nn=2**mm -1 */
|
||||
int32_t nn;
|
||||
|
||||
/** Gallois field table */
|
||||
const int16_t *alpha_to;
|
||||
|
||||
/** Index of Gallois field table */
|
||||
const int16_t *index_of;
|
||||
|
||||
/** */
|
||||
int16_t partial_syn[100];
|
||||
|
||||
/** Holds the current syndrome value, an element of that table belongs to the field.*/
|
||||
int16_t si[100];
|
||||
|
||||
/** sigma table */
|
||||
int16_t smu[PMECC_NB_ERROR_MAX + 2][2 * PMECC_NB_ERROR_MAX + 1];
|
||||
|
||||
/** polynom order */
|
||||
int16_t lmu[PMECC_NB_ERROR_MAX + 1];
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------- */
|
||||
/* Local variables */
|
||||
/*--------------------------------------------------------------------------- */
|
||||
|
||||
/** Pmecc decriptor instance */
|
||||
struct _pmecc_descriptor pmecc_desc;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Build the pseudo syndromes table
|
||||
* \param sector Targetted sector.
|
||||
*/
|
||||
static void gen_syn(uint32_t sector)
|
||||
{
|
||||
int16_t *remainer;
|
||||
uint32_t index;
|
||||
|
||||
remainer = (int16_t*)&HSMC->SMC_REM[sector];
|
||||
for (index = 0; index < (uint32_t)pmecc_desc.tt; index++) {
|
||||
/* Fill odd syndromes */
|
||||
pmecc_desc.partial_syn[1 + (2 * index)] = remainer[index];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief The substitute function evaluates the polynomial remainder,
|
||||
* with different values of the field primitive elements.
|
||||
*/
|
||||
static uint32_t substitute(void)
|
||||
{
|
||||
int32_t i, j;
|
||||
int16_t *si;
|
||||
int16_t *p_partial_syn = pmecc_desc.partial_syn;
|
||||
const int16_t *alpha_to = pmecc_desc.alpha_to;
|
||||
const int16_t *index_of = pmecc_desc.index_of;
|
||||
|
||||
/* si[] is a table that holds the current syndrome value, an element of that table belongs to the field.*/
|
||||
si = pmecc_desc.si;
|
||||
|
||||
for (i = 1; i < 2 * PMECC_NB_ERROR_MAX; i++)
|
||||
si[i] = 0;
|
||||
|
||||
/* Computation 2t syndromes based on S(x) */
|
||||
/* Odd syndromes */
|
||||
for (i = 1; i <= 2 * pmecc_desc.tt - 1; i = i + 2) {
|
||||
si[i] = 0;
|
||||
for (j = 0; j < pmecc_desc.mm; j++) {
|
||||
if (p_partial_syn[i] & ((uint16_t)0x1 << j))
|
||||
si[i] = alpha_to[(i * j)] ^ si[i];
|
||||
}
|
||||
}
|
||||
/* Even syndrome = (Odd syndrome) ** 2 */
|
||||
for (i = 2; i <= 2 * pmecc_desc.tt; i = i + 2) {
|
||||
j = i / 2;
|
||||
if (si[j] == 0) {
|
||||
si[i] = 0;
|
||||
} else {
|
||||
si[i] = alpha_to[(2 * index_of[si[j]]) % pmecc_desc.nn];
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief The substitute function finding the value of the error
|
||||
* location polynomial.
|
||||
*/
|
||||
static uint32_t get_sigma(void)
|
||||
{
|
||||
uint32_t dmu_0_count;
|
||||
int32_t i, j, k;
|
||||
int16_t *lmu = pmecc_desc.lmu;
|
||||
int16_t *si = pmecc_desc.si;
|
||||
int16_t tt = pmecc_desc.tt;
|
||||
|
||||
int32_t mu[PMECC_NB_ERROR_MAX+1]; /* mu */
|
||||
int32_t dmu[PMECC_NB_ERROR_MAX+1]; /* discrepancy */
|
||||
int32_t delta[PMECC_NB_ERROR_MAX+1]; /* delta order */
|
||||
int32_t ro; /* index of largest delta */
|
||||
int32_t largest;
|
||||
int32_t diff;
|
||||
|
||||
dmu_0_count = 0;
|
||||
|
||||
/* -- First Row -- */
|
||||
|
||||
/* Mu */
|
||||
mu[0] = -1;
|
||||
/* Actually -1/2 */
|
||||
/* Sigma(x) set to 1 */
|
||||
|
||||
for (i = 0; i < (2 * PMECC_NB_ERROR_MAX + 1); i++)
|
||||
pmecc_desc.smu[0][i] = 0;
|
||||
pmecc_desc.smu[0][0] = 1;
|
||||
|
||||
/* discrepancy set to 1 */
|
||||
dmu[0] = 1;
|
||||
|
||||
/* polynom order set to 0 */
|
||||
lmu[0] = 0;
|
||||
|
||||
/* delta set to -1 */
|
||||
delta[0] = (mu[0] * 2 - lmu[0]) >> 1;
|
||||
|
||||
/* -- Second Row -- */
|
||||
|
||||
/* Mu */
|
||||
mu[1] = 0;
|
||||
|
||||
/* Sigma(x) set to 1 */
|
||||
for (i = 0; i < (2 * PMECC_NB_ERROR_MAX + 1); i++)
|
||||
pmecc_desc.smu[1][i] = 0;
|
||||
pmecc_desc.smu[1][0] = 1;
|
||||
|
||||
/* discrepancy set to S1 */
|
||||
dmu[1] = si[1];
|
||||
|
||||
/* polynom order set to 0 */
|
||||
lmu[1] = 0;
|
||||
|
||||
/* delta set to 0 */
|
||||
delta[1] = (mu[1] * 2 - lmu[1]) >> 1;
|
||||
|
||||
/* Init the Sigma(x) last row */
|
||||
for (i = 0; i < (2 * PMECC_NB_ERROR_MAX + 1); i++)
|
||||
pmecc_desc.smu[tt + 1][i] = 0;
|
||||
|
||||
for (i = 1; i <= tt; i++) {
|
||||
mu[i+1] = i << 1;
|
||||
|
||||
/* Compute Sigma (Mu+1) */
|
||||
/* And L(mu) */
|
||||
/* check if discrepancy is set to 0 */
|
||||
if ( dmu[i] == 0) {
|
||||
dmu_0_count++;
|
||||
if (( tt - (lmu[i] >> 1) - 1) & 0x1) {
|
||||
if (dmu_0_count == (uint32_t)((tt - (lmu[i] >> 1) - 1) / 2) + 2) {
|
||||
for (j = 0; j <= (lmu[i] >> 1) + 1; j++)
|
||||
pmecc_desc.smu[tt+1][j] = pmecc_desc.smu[i][j];
|
||||
lmu[tt + 1] = lmu[i];
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (dmu_0_count == (uint32_t)((tt - (lmu[i] >> 1) - 1) / 2) + 1) {
|
||||
for (j = 0; j <= (lmu[i] >> 1) + 1; j++)
|
||||
pmecc_desc.smu[tt + 1][j] = pmecc_desc.smu[i][j];
|
||||
lmu[tt + 1] = lmu[i];
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* copy polynom */
|
||||
for (j = 0; j <= (lmu[i] >> 1); j++)
|
||||
pmecc_desc.smu[i + 1][j] = pmecc_desc.smu[i][j];
|
||||
|
||||
/* copy previous polynom order to the next */
|
||||
lmu[i + 1] = lmu[i];
|
||||
} else {
|
||||
/* find largest delta with dmu != 0 */
|
||||
ro = 0;
|
||||
largest = -1;
|
||||
for (j = 0; j < i; j++) {
|
||||
if (dmu[j]) {
|
||||
if (delta[j] > largest) {
|
||||
largest = delta[j];
|
||||
ro = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* compute difference */
|
||||
diff = (mu[i] - mu[ro]);
|
||||
|
||||
/* Compute degree of the new smu polynomial */
|
||||
if ((lmu[i] >> 1) > ((lmu[ro] >> 1) + diff))
|
||||
lmu[i + 1] = lmu[i];
|
||||
else
|
||||
lmu[i + 1] = ((lmu[ro] >> 1) + diff) * 2;
|
||||
|
||||
/* Init smu[i+1] with 0 */
|
||||
for (k = 0; k < (2 * PMECC_NB_ERROR_MAX + 1); k++)
|
||||
pmecc_desc.smu[i+1][k] = 0;
|
||||
|
||||
/* Compute smu[i+1] */
|
||||
for (k = 0; k <= (lmu[ro] >> 1); k++) {
|
||||
if (pmecc_desc.smu[ro][k] && dmu[i])
|
||||
pmecc_desc.smu[i + 1][k + diff] = pmecc_desc.alpha_to[(pmecc_desc.index_of[dmu[i]] +
|
||||
(pmecc_desc.nn - pmecc_desc.index_of[dmu[ro]]) +
|
||||
pmecc_desc.index_of[pmecc_desc.smu[ro][k]]) % pmecc_desc.nn];
|
||||
}
|
||||
for (k = 0; k <= (lmu[i] >> 1); k++)
|
||||
pmecc_desc.smu[i+1][k] ^= pmecc_desc.smu[i][k];
|
||||
}
|
||||
|
||||
/*************************************************/
|
||||
/* End Compute Sigma (Mu+1) */
|
||||
/* And L(mu) */
|
||||
/*************************************************/
|
||||
/* In either case compute delta */
|
||||
delta[i + 1] = (mu[i + 1] * 2 - lmu[i + 1]) >> 1;
|
||||
|
||||
/* Do not compute discrepancy for the last iteration */
|
||||
if (i < tt) {
|
||||
for (k = 0 ; k <= (lmu[i + 1] >> 1); k++) {
|
||||
if (k == 0)
|
||||
dmu[i + 1] = si[2 * (i - 1) + 3];
|
||||
/* check if one operand of the multiplier is null, its index is -1 */
|
||||
else if (pmecc_desc.smu[i+1][k] && si[2 * (i - 1) + 3 - k])
|
||||
dmu[i + 1] = pmecc_desc.alpha_to[(pmecc_desc.index_of[pmecc_desc.smu[i + 1][k]] +
|
||||
pmecc_desc.index_of[si[2 * (i - 1) + 3 - k]]) % pmecc_desc.nn] ^ dmu[i + 1];
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Init the PMECC Error Location peripheral and start the error
|
||||
* location processing
|
||||
* \param sector_size_in_bits Size of the sector in bits.
|
||||
* \return Number of errors
|
||||
*/
|
||||
static int32_t error_location (uint32_t sector_size_in_bits)
|
||||
{
|
||||
uint32_t alphax;
|
||||
uint32_t *sigma;
|
||||
uint32_t error_number;
|
||||
uint32_t nbr_of_roots;
|
||||
|
||||
/* Disable PMECC Error Location IP */
|
||||
HSMC->HSMC_ELDIS |= 0xFFFFFFFF;
|
||||
error_number = 0;
|
||||
alphax = 0;
|
||||
|
||||
sigma = (uint32_t*)&HSMC->HSMC_SIGMA0;
|
||||
|
||||
for (alphax = 0; alphax <= (uint32_t)(pmecc_desc.lmu[pmecc_desc.tt + 1] >> 1); alphax++) {
|
||||
*sigma++ = pmecc_desc.smu[pmecc_desc.tt + 1][alphax];
|
||||
error_number++;
|
||||
}
|
||||
|
||||
/* Enable error location process */
|
||||
HSMC->HSMC_ELCFG |= ((error_number - 1) << 16);
|
||||
HSMC->HSMC_ELEN = sector_size_in_bits;
|
||||
|
||||
while ((HSMC->HSMC_ELISR & HSMC_ELISR_DONE) == 0);
|
||||
|
||||
nbr_of_roots = (HSMC->HSMC_ELISR & HSMC_ELISR_ERR_CNT_Msk) >> 8;
|
||||
/* Number of roots == degree of smu hence <= tt */
|
||||
if (nbr_of_roots == (uint32_t)(pmecc_desc.lmu[pmecc_desc.tt + 1] >> 1))
|
||||
return (error_number - 1);
|
||||
|
||||
/* Number of roots not match the degree of smu ==> unable to correct error */
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Correct errors indicated in the PMECCEL error location registers.
|
||||
* \param sector_base_address Base address of the sector.
|
||||
* \param extra_bytes Number of extra bytes of the sector.(encoded Spare Area, only for the last sector)
|
||||
* \param error_nbr Number of error to correct
|
||||
* \return Number of errors
|
||||
*/
|
||||
static uint32_t error_correction(uint32_t sector_base_address, uint32_t extra_bytes, uint32_t error_nbr)
|
||||
{
|
||||
uint32_t *error_pos;
|
||||
uint32_t byte_pos;
|
||||
uint32_t bit_pos;
|
||||
uint32_t sector_size;
|
||||
uint32_t ecc_size;
|
||||
uint32_t ecc_end_addr;
|
||||
|
||||
error_pos = (uint32_t*)&HSMC->HSMC_ERRLOC0;
|
||||
|
||||
sector_size = 512 * (((HSMC->HSMC_PMECCFG & HSMC_PMECCFG_SECTORSZ) >> 4) + 1);
|
||||
|
||||
/* Get number of ECC bytes */
|
||||
ecc_end_addr = HSMC->HSMC_PMECCEADDR;
|
||||
ecc_size = (ecc_end_addr - HSMC->HSMC_PMECCSADDR) + 1;
|
||||
|
||||
while (error_nbr) {
|
||||
byte_pos = (*error_pos - 1) / 8;
|
||||
bit_pos = (*error_pos - 1) % 8;
|
||||
|
||||
/* If error is located in the data area(not in ECC) */
|
||||
if ( byte_pos < (sector_size + extra_bytes)) {
|
||||
uint8_t *data_ptr = NULL;
|
||||
|
||||
/* If the error position is before ECC area */
|
||||
if ( byte_pos < sector_size + HSMC->HSMC_PMECCSADDR) {
|
||||
data_ptr = (uint8_t*)(sector_base_address + byte_pos);
|
||||
} else {
|
||||
data_ptr = (uint8_t*)(sector_base_address + byte_pos + ecc_size);
|
||||
}
|
||||
|
||||
trace_info("Correct error bit @[#Byte %u,Bit# %u]\n\r",
|
||||
(unsigned)byte_pos, (unsigned)bit_pos);
|
||||
|
||||
if (*data_ptr & (1 << bit_pos))
|
||||
*data_ptr &= (0xFF ^ (1 << bit_pos));
|
||||
else
|
||||
*data_ptr |= (1 << bit_pos);
|
||||
}
|
||||
error_pos++;
|
||||
error_nbr--;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure the PMECC peripheral
|
||||
* \param pPmeccDescriptor Pointer to a PmeccDescriptor instance.
|
||||
*/
|
||||
static void _pmecc_configure(void)
|
||||
{
|
||||
/* Disable ECC module */
|
||||
HSMC->HSMC_PMECCTRL |= HSMC_PMECCTRL_DISABLE;
|
||||
|
||||
/* Reset the ECC module */
|
||||
HSMC->HSMC_PMECCTRL = HSMC_PMECCTRL_RST;
|
||||
HSMC->HSMC_PMECCFG = pmecc_desc.err_bit_nbr_capability |
|
||||
pmecc_desc.sector_size |
|
||||
pmecc_desc.page_size |
|
||||
pmecc_desc.nand_wr |
|
||||
pmecc_desc.spare_ena |
|
||||
pmecc_desc.mode_auto;
|
||||
HSMC->HSMC_PMECCSAREA = pmecc_desc.spare_size - 1;
|
||||
HSMC->HSMC_PMECCSADDR = pmecc_desc.ecc_start_address;
|
||||
HSMC->HSMC_PMECCEADDR = pmecc_desc.ecc_end_address - 1;
|
||||
|
||||
/* Disable all interrupts */
|
||||
HSMC->HSMC_PMECCIDR = 0xFF;
|
||||
|
||||
/* Enable ECC module */
|
||||
HSMC->HSMC_PMECCTRL |= HSMC_PMECCTRL_ENABLE;
|
||||
}
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Export functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief This function is able to build Galois Field.
|
||||
* \param mm degree of the remainders.
|
||||
* \param index_of Pointer to a buffer for index_of table.
|
||||
* \param alpha_to Pointer to a buffer for alpha_to table.
|
||||
*/
|
||||
void build_gf(uint32_t mm, int32_t* index_of, int32_t* alpha_to)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t mask;
|
||||
uint32_t nn;
|
||||
uint32_t p[15];
|
||||
|
||||
nn = (1 << mm) - 1;
|
||||
/* set default value */
|
||||
for (i = 1; i < mm; i++)
|
||||
p[i] = 0;
|
||||
|
||||
/* 1 + X^mm */
|
||||
p[0] = 1;
|
||||
p[mm] = 1;
|
||||
|
||||
/* others */
|
||||
if (mm == 3)
|
||||
p[1] = 1;
|
||||
else if (mm == 4)
|
||||
p[1] = 1;
|
||||
else if (mm == 5)
|
||||
p[2] = 1;
|
||||
else if (mm == 6)
|
||||
p[1] = 1;
|
||||
else if (mm == 7)
|
||||
p[3] = 1;
|
||||
else if (mm == 8)
|
||||
p[2] = p[3] = p[4] = 1;
|
||||
else if (mm == 9)
|
||||
p[4] = 1;
|
||||
else if (mm == 10)
|
||||
p[3] = 1;
|
||||
else if (mm == 11)
|
||||
p[2] = 1;
|
||||
else if (mm == 12)
|
||||
p[1] = p[4] = p[6] = 1;
|
||||
else if (mm == 13)
|
||||
p[1] = p[3] = p[4] = 1;
|
||||
else if (mm == 14)
|
||||
p[1] = p[6] = p[10] = 1;
|
||||
else if (mm == 15)
|
||||
p[1] = 1;
|
||||
|
||||
/*-- First of All */
|
||||
/*-- build alpha ^ mm it will help to generate the field (primitiv) */
|
||||
alpha_to[mm] = 0;
|
||||
for (i = 0; i < mm; i++)
|
||||
if (p[i])
|
||||
alpha_to[mm] |= 1 << i;
|
||||
|
||||
/* Secondly */
|
||||
/* Build elements from 0 to mm - 1 */
|
||||
/* very easy because degree is less than mm so it is */
|
||||
/* just a logical shift ! (only the remainder) */
|
||||
mask = 1;
|
||||
for (i = 0; i < mm; i++) {
|
||||
alpha_to[i] = mask;
|
||||
index_of[alpha_to[i]] = i;
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
index_of[alpha_to[mm]] = mm;
|
||||
|
||||
/* use a mask to select the MSB bit of the */
|
||||
/* LFSR ! */
|
||||
mask >>= 1; /* previous value moust be decremented */
|
||||
|
||||
/* then finish the building */
|
||||
for (i = mm + 1; i <= nn; i++) {
|
||||
/* check if the msb bit of the lfsr is set */
|
||||
if (alpha_to[i-1] & mask)
|
||||
/* feedback loop is set */
|
||||
alpha_to[i] = alpha_to[mm] ^ ((alpha_to[i-1] ^ mask) << 1);
|
||||
else
|
||||
/* only shift is enabled */
|
||||
alpha_to[i] = alpha_to[i-1] << 1;
|
||||
/* lookup table */
|
||||
//index_of[alpha_to[i]] = i ;
|
||||
index_of[alpha_to[i]] = i%nn ;
|
||||
}
|
||||
/* of course index of 0 is undefined in a multiplicative field */
|
||||
index_of[0] = -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initialize the PMECC peripheral
|
||||
* \param sector_size 0 for 512, 1 for 1024.
|
||||
* \param ecc_errors_per_sector Coded value of ECC bit number correction(2,4,8,12,24).
|
||||
* \param page_data_size Data area size in byte.
|
||||
* \param page_spare_size Spare area size in byte.
|
||||
* \param ecc_offset_in_spare offset of the first ecc byte in spare zone.
|
||||
* \param spare_protected 1: The spare area is protected with the last sector of data.
|
||||
* 0: The spare area is skipped in read or write mode.
|
||||
* \return 0 if successful; otherwise returns 1.
|
||||
*/
|
||||
uint8_t pmecc_initialize(uint8_t sector_size , uint8_t ecc_errors_per_sector,
|
||||
uint32_t page_data_size, uint32_t page_spare_size,
|
||||
uint16_t ecc_offset_in_spare, uint8_t spare_protected)
|
||||
{
|
||||
uint8_t nb_sectors_per_page = 0;
|
||||
|
||||
if (ecc_errors_per_sector == 0xFF) {
|
||||
/* ONFI 2.2 : a value of 0xff indaicate we must apply a correction on sector > 512 bytes,
|
||||
so we set at the maximum allowed by PMECC 24 bits on 1024 sectors. */
|
||||
ecc_errors_per_sector = 24;
|
||||
sector_size = 1; /* 1 for 1024 bytes per sector */
|
||||
}
|
||||
|
||||
/* Number of Sectors in one Page */
|
||||
switch (sector_size) {
|
||||
/* 512 bytes per sector */
|
||||
case 0:
|
||||
pmecc_desc.sector_size = 0;
|
||||
nb_sectors_per_page = page_data_size / 512;
|
||||
pmecc_desc.mm = 13;
|
||||
pmecc_get_gf_512_tables(&pmecc_desc.alpha_to, &pmecc_desc.index_of);
|
||||
break;
|
||||
|
||||
/* 1024 bytes per sector */
|
||||
case 1:
|
||||
pmecc_desc.sector_size = HSMC_PMECCFG_SECTORSZ;
|
||||
nb_sectors_per_page = page_data_size / 1024;
|
||||
pmecc_desc.mm = 14;
|
||||
pmecc_get_gf_1024_tables(&pmecc_desc.alpha_to, &pmecc_desc.index_of);
|
||||
break;
|
||||
}
|
||||
|
||||
switch (nb_sectors_per_page) {
|
||||
case 1:
|
||||
pmecc_desc.page_size = HSMC_PMECCFG_PAGESIZE_PAGESIZE_1SEC;
|
||||
break;
|
||||
case 2:
|
||||
pmecc_desc.page_size = HSMC_PMECCFG_PAGESIZE_PAGESIZE_2SEC;
|
||||
break;
|
||||
case 4:
|
||||
pmecc_desc.page_size = HSMC_PMECCFG_PAGESIZE_PAGESIZE_4SEC;
|
||||
break;
|
||||
case 8:
|
||||
pmecc_desc.page_size = HSMC_PMECCFG_PAGESIZE_PAGESIZE_8SEC;
|
||||
break;
|
||||
default :
|
||||
pmecc_desc.page_size = HSMC_PMECCFG_PAGESIZE_PAGESIZE_1SEC;
|
||||
break;
|
||||
}
|
||||
|
||||
pmecc_desc.nn = (1 << pmecc_desc.mm) - 1;
|
||||
|
||||
/* Coded value of ECC bit number correction (0 (2 bits), 1 (4 bits), 2 (8 bits), 3 (12 bits), 4 (24 bits), 5 (NU)) */
|
||||
switch (ecc_errors_per_sector) {
|
||||
case 2:
|
||||
pmecc_desc.err_bit_nbr_capability = HSMC_PMECCFG_BCH_ERR_BCH_ERR2;
|
||||
break;
|
||||
case 4:
|
||||
pmecc_desc.err_bit_nbr_capability = HSMC_PMECCFG_BCH_ERR_BCH_ERR4;
|
||||
break;
|
||||
case 8:
|
||||
pmecc_desc.err_bit_nbr_capability = HSMC_PMECCFG_BCH_ERR_BCH_ERR8;
|
||||
break;
|
||||
case 12:
|
||||
pmecc_desc.err_bit_nbr_capability = HSMC_PMECCFG_BCH_ERR_BCH_ERR12;
|
||||
break;
|
||||
case 24:
|
||||
pmecc_desc.err_bit_nbr_capability = HSMC_PMECCFG_BCH_ERR_BCH_ERR24;
|
||||
break;
|
||||
default:
|
||||
pmecc_desc.err_bit_nbr_capability = HSMC_PMECCFG_BCH_ERR_BCH_ERR2;
|
||||
ecc_errors_per_sector = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Real value of ECC bit number correction (2, 4, 8, 12, 24) */
|
||||
pmecc_desc.tt = ecc_errors_per_sector;
|
||||
if (((pmecc_desc.mm * ecc_errors_per_sector ) % 8 ) == 0) {
|
||||
pmecc_desc.ecc_size_byte = ((pmecc_desc.mm * ecc_errors_per_sector ) / 8) * nb_sectors_per_page;
|
||||
} else {
|
||||
pmecc_desc.ecc_size_byte = (((pmecc_desc.mm * ecc_errors_per_sector ) / 8 ) + 1 ) * nb_sectors_per_page;
|
||||
}
|
||||
if (ecc_offset_in_spare <= 2) {
|
||||
pmecc_desc.ecc_start_address = PMECC_ECC_DEFAULT_START_ADDR;
|
||||
} else {
|
||||
pmecc_desc.ecc_start_address = ecc_offset_in_spare;
|
||||
}
|
||||
pmecc_desc.ecc_end_address = pmecc_desc.ecc_start_address + pmecc_desc.ecc_size_byte;
|
||||
if (pmecc_desc.ecc_end_address > page_spare_size) {
|
||||
return 1;
|
||||
}
|
||||
pmecc_desc.spare_size = pmecc_desc.ecc_end_address;
|
||||
|
||||
//pmecc_desc.nand_wr = PMECC_CFG_NANDWR; /* NAND write access */
|
||||
pmecc_desc.nand_wr = 0; /* NAND Read access */
|
||||
if (spare_protected) {
|
||||
pmecc_desc.spare_ena = HSMC_PMECCFG_SPAREEN;
|
||||
} else {
|
||||
pmecc_desc.spare_ena = 0;
|
||||
}
|
||||
/* PMECC_CFG_AUTO indicates that the spare is error protected. In this case, the ECC computation takes into account the whole spare area
|
||||
minus the ECC area in the ECC computation operation */
|
||||
pmecc_desc.mode_auto = 0;
|
||||
/* At 133 Mhz, this field must be programmed with 2,
|
||||
indicating that the setup time is 3 clock cycles.*/
|
||||
pmecc_desc.clk_ctrl = 2;
|
||||
pmecc_desc.interrupt = 0;
|
||||
_pmecc_configure();
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return PMECC page size.
|
||||
*/
|
||||
uint32_t pmecc_get_page_size(void)
|
||||
{
|
||||
return pmecc_desc.page_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return PMECC ecc size.
|
||||
*/
|
||||
uint32_t pmecc_get_ecc_bytes(void)
|
||||
{
|
||||
return pmecc_desc.ecc_size_byte;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return PMECC ecc start address.
|
||||
*/
|
||||
uint32_t pmecc_get_ecc_start_address(void)
|
||||
{
|
||||
return pmecc_desc.ecc_start_address;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Return PMECC ecc end address.
|
||||
*/
|
||||
uint32_t pmecc_get_ecc_end_address(void)
|
||||
{
|
||||
return pmecc_desc.ecc_end_address;
|
||||
}
|
||||
|
||||
|
||||
typedef uint32_t (*pmecc_correction_algo_t)(Smc *, struct _pmecc_descriptor *, uint32_t, uint32_t);
|
||||
|
||||
/**
|
||||
* \brief Launch error detection functions and correct corrupted bits.
|
||||
* \param pmecc_status Value of the PMECC status register.
|
||||
* \param page_buffer Base address of the buffer containing the page to be corrected.
|
||||
* \return 0 if all errors have been corrected, 1 if too many errors detected
|
||||
*/
|
||||
uint32_t pmecc_correction(uint32_t pmecc_status, uint32_t page_buffer)
|
||||
{
|
||||
uint32_t sector_number = 0;
|
||||
uint32_t sector_base_address;
|
||||
volatile int32_t error_nbr;
|
||||
|
||||
/* Set the sector size (512 or 1024 bytes) */
|
||||
HSMC->HSMC_ELCFG = pmecc_desc.sector_size >> 4;
|
||||
|
||||
while (sector_number < (uint32_t)((1 << ((HSMC->HSMC_PMECCFG & HSMC_PMECCFG_PAGESIZE_Msk) >> 8)))) {
|
||||
error_nbr = 0;
|
||||
if (pmecc_status & 0x1) {
|
||||
sector_base_address = page_buffer + (sector_number * ((pmecc_desc.sector_size >> 4) + 1) * 512);
|
||||
gen_syn(sector_number);
|
||||
substitute();
|
||||
get_sigma();
|
||||
error_nbr = error_location((((pmecc_desc.sector_size >> 4) + 1) * 512 * 8) +
|
||||
(pmecc_desc.tt * (13 + (pmecc_desc.sector_size >> 4)))); /* number of bits of the sector + ecc */
|
||||
|
||||
if (error_nbr == -1)
|
||||
return 1;
|
||||
else
|
||||
error_correction(sector_base_address, 0, error_nbr); /* Extra byte is 0 */
|
||||
}
|
||||
sector_number++;
|
||||
pmecc_status = pmecc_status >> 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable pmecc.
|
||||
*/
|
||||
void pmecc_disable(void)
|
||||
{
|
||||
/* Disable ECC module */
|
||||
HSMC->HSMC_PMECCTRL |= HSMC_PMECCTRL_DISABLE;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef PMECC_H
|
||||
#define PMECC_H
|
||||
|
||||
/*----------------------------------------------------------------------- */
|
||||
/* Definition */
|
||||
/*----------------------------------------------------------------------- */
|
||||
|
||||
/** Start address of ECC cvalue in spare zone, this must not be 0 since Bad block tag are at 0. */
|
||||
#define PMECC_ECC_DEFAULT_START_ADDR 0x02
|
||||
|
||||
/*------------------------------------------------------------------------------ */
|
||||
/* Exported functions */
|
||||
/*------------------------------------------------------------------------------ */
|
||||
|
||||
extern uint8_t pmecc_initialize(uint8_t sector_size,
|
||||
uint8_t ecc_errors_per_sector,
|
||||
uint32_t page_data_size,
|
||||
uint32_t page_spare_size,
|
||||
uint16_t ecc_offset_in_spare,
|
||||
uint8_t spare_protected);
|
||||
|
||||
extern uint32_t pmecc_get_page_size(void);
|
||||
|
||||
extern uint32_t pmecc_get_ecc_bytes(void);
|
||||
|
||||
extern uint32_t pmecc_get_ecc_start_address(void);
|
||||
|
||||
extern uint32_t pmecc_get_ecc_end_address(void);
|
||||
|
||||
extern uint32_t pmecc_correction(uint32_t pmecc_status, uint32_t page_buffer);
|
||||
|
||||
extern void build_gf(uint32_t mm, int32_t *index_of, int32_t *alpha_to);
|
||||
|
||||
extern void pmecc_disable(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2013, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef PMECC_TABLES_1024_H
|
||||
#define PMECC_TABLES_1024_H
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Definitions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#define PMECC_GF_1024_SIZE (0x4000)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/** \brief Get the addresses of Gallois Field tables for 1024 bytes sectors */
|
||||
void pmecc_get_gf_1024_tables(const int16_t **alpha_to, const int16_t **index_of);
|
||||
|
||||
#endif /* PMECC_TABLES_1024_H */
|
|
@ -0,0 +1,52 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2013, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
#ifndef PMECC_TABLES_512_H
|
||||
#define PMECC_TABLES_512_H
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Definitions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#define PMECC_GF_512_SIZE (0x2000)
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/** \brief Get the addresses of Gallois Field tables for 512 bytes sectors */
|
||||
void pmecc_get_gf_512_tables(const int16_t **alpha_to, const int16_t **index_of);
|
||||
|
||||
#endif /* PMECC_TABLES_512_H */
|
||||
|
|
@ -0,0 +1,147 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \addtogroup pwm_module Working with PWM
|
||||
* \section Purpose
|
||||
* The PWM driver provides the interface to configure and use the PWM
|
||||
* peripheral.
|
||||
*
|
||||
* The PWM macrocell controls square output waveforms of 4 channels.
|
||||
* Characteristics of output waveforms such as period, duty-cycle can be configured.\n
|
||||
*
|
||||
* Before enabling the channels, they must have been configured first.
|
||||
* The main settings include:
|
||||
* <ul>
|
||||
* <li>Configuration of the clock generator.</li>
|
||||
* <li>Selection of the clock for each channel.</li>
|
||||
* <li>Configuration of output waveform characteristics, such as period, duty-cycle etc.</li>
|
||||
* </ul>
|
||||
*
|
||||
* After the channels is enabled, the user must use respective update registers
|
||||
* to change the wave characteristics to prevent unexpected output waveform.
|
||||
* i.e. PWM_CUPDx register should be used if user want to change duty-cycle
|
||||
* when the channel is enabled.
|
||||
*
|
||||
* \section Usage
|
||||
* <ul>
|
||||
* <li> Configure PWM clock using pwmc_configure_clocks().
|
||||
* <li> Enable & disable given PWM channel using pwmc_enable_channel() and pwmc_disable_channel().
|
||||
* <li> Enable & disable interrupt of given PWM channel using pwmc_enable_channel_it()
|
||||
* and pwmc_disable_channel_it().
|
||||
* <li> Set feature of the given PWM channel's output signal using pwmc_set_period()
|
||||
* and pwmc_set_duty_cycle().
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* For more accurate information, please look at the PWM section of the
|
||||
* Datasheet.
|
||||
*
|
||||
* Related files :\n
|
||||
* \ref pwmc.c\n
|
||||
* \ref pwmc.h.\n
|
||||
*/
|
||||
/*@{*/
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implementation of the Pulse Width Modulation Controller (PWM) peripheral.
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/pwmc.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void pwmc_configure_clocks(Pwm * p_pwm, uint32_t mode)
|
||||
{
|
||||
p_pwm->PWM_CLK = mode;
|
||||
}
|
||||
|
||||
void pwmc_enable_channel(Pwm * p_pwm, uint8_t channel)
|
||||
{
|
||||
p_pwm->PWM_ENA = 0x1ul << channel;
|
||||
}
|
||||
|
||||
void pwmc_disable_channel(Pwm * p_pwm, uint8_t channel)
|
||||
{
|
||||
p_pwm->PWM_DIS = 0x1ul << channel;
|
||||
}
|
||||
|
||||
void pwmc_enable_channel_it(Pwm * p_pwm, uint8_t channel)
|
||||
{
|
||||
p_pwm->PWM_IER1 = 0x1ul << channel;
|
||||
}
|
||||
|
||||
void pwmc_disable_channel_it(Pwm * p_pwm, uint8_t channel)
|
||||
{
|
||||
p_pwm->PWM_IDR1 = 0x1ul << channel;
|
||||
}
|
||||
|
||||
void pwmc_configure_channel(Pwm * p_pwm, uint8_t channel, uint32_t mode)
|
||||
{
|
||||
p_pwm->PWM_CH_NUM[channel].PWM_CMR = mode;
|
||||
}
|
||||
|
||||
void pwmc_set_period(Pwm * p_pwm, uint8_t channel, uint16_t period)
|
||||
{
|
||||
/* If channel is disabled, write to CPRD */
|
||||
if ((p_pwm->PWM_SR & (1 << channel)) == 0) {
|
||||
p_pwm->PWM_CH_NUM[channel].PWM_CPRD = period;
|
||||
}
|
||||
/* Otherwise use update register */
|
||||
else {
|
||||
p_pwm->PWM_CH_NUM[channel].PWM_CPRDUPD = period;
|
||||
}
|
||||
}
|
||||
|
||||
void pwmc_set_duty_cycle(Pwm * p_pwm, uint8_t channel, uint16_t duty)
|
||||
{
|
||||
assert(duty <= p_pwm->PWM_CH_NUM[channel].PWM_CPRD);
|
||||
|
||||
/* If channel is disabled, write to CDTY */
|
||||
if ((p_pwm->PWM_SR & (1 << channel)) == 0) {
|
||||
p_pwm->PWM_CH_NUM[channel].PWM_CDTY = duty;
|
||||
}
|
||||
/* Otherwise use update register */
|
||||
else {
|
||||
p_pwm->PWM_CH_NUM[channel].PWM_CDTYUPD = duty;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \par Purpose
|
||||
*
|
||||
* Interface for configuration the Pulse Width Modulation Controller (PWM) peripheral.
|
||||
*
|
||||
* \par Usage
|
||||
*
|
||||
* -# Configures PWM clocks A & B to run at the given frequencies using
|
||||
* pwmc_configure_clocks().
|
||||
* -# Configure PWMC channel using pwmc_configure_channel(), pwmc_set_period()
|
||||
* and pwmc_set_duty_cycle().
|
||||
* -# Enable & disable channel using pwmc_enable_channel() and pwmc_disable_channel().
|
||||
* -# Enable & disable the period interrupt for the given PWM channel using
|
||||
* pwmc_enable_channel_it() and pwmc_disable_channel_it().
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _PWMC_
|
||||
#define _PWMC_
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Configures PWM clocks
|
||||
* \param p_pwm Pointer to a Pwm instance
|
||||
* \param mode PWM clock source selection and divide factor.
|
||||
*/
|
||||
extern void pwmc_configure_clocks(Pwm * p_pwm, uint32_t mode);
|
||||
|
||||
/**
|
||||
* \brief Enables the given PWM channel.
|
||||
*
|
||||
* This does NOT enable the corresponding pin; this must be done in the user
|
||||
* code.
|
||||
*
|
||||
* \param p_pwm Pointer to a Pwm instance
|
||||
* \param channel Channel number.
|
||||
*/
|
||||
extern void pwmc_enable_channel(Pwm * p_pwm, uint8_t channel);
|
||||
|
||||
/**
|
||||
* \brief Disables the given PWM channel.
|
||||
*
|
||||
* Beware, the channel will be effectively disabled at the end of the current
|
||||
* period.
|
||||
* Applications may check whether the channel is disabled using the following
|
||||
* wait loop:
|
||||
* while ((PWM->PWM_SR & (1 << channel)) != 0) {};
|
||||
*
|
||||
* \param p_pwm Pointer to a Pwm instance
|
||||
* \param channel Channel number.
|
||||
*/
|
||||
extern void pwmc_disable_channel(Pwm * p_pwm, uint8_t channel);
|
||||
|
||||
/**
|
||||
* \brief Enables the selected interrupts sources on a PWMC peripheral.
|
||||
* \param p_pwm Pointer to a Pwm instance
|
||||
* \param channel Channel number.
|
||||
*/
|
||||
extern void pwmc_enable_channel_it(Pwm * p_pwm, uint8_t channel);
|
||||
|
||||
/**
|
||||
* \brief Disables the selected interrupts sources on a PWMC peripheral.
|
||||
* \param p_pwm Pointer to a Pwm instance
|
||||
* \param channel Channel number.
|
||||
*/
|
||||
extern void pwmc_disable_channel_it(Pwm * p_pwm, uint8_t channel);
|
||||
|
||||
/**
|
||||
* \brief Configures a PWM channel with the given parameters, basic configure
|
||||
* function.
|
||||
*
|
||||
* The PWM controller must have been clocked in the PMC prior to calling this
|
||||
* function.
|
||||
* Beware: this function disables the channel. It will wait until the channel is
|
||||
* effectively disabled.
|
||||
*
|
||||
* \param p_pwm Pointer to a Pwm instance
|
||||
* \param channel Channel number.
|
||||
* \param mode Channel mode.
|
||||
*/
|
||||
extern void pwmc_configure_channel(Pwm * p_pwm, uint8_t channel, uint32_t mode);
|
||||
|
||||
/**
|
||||
* \brief Sets the period value used by a PWM channel.
|
||||
*
|
||||
* This function writes directly to the CPRD register if the channel is
|
||||
* disabled. Otherwise it sets the update register CPRDUPD.
|
||||
*
|
||||
* \param p_pwm Pointer to a Pwm instance
|
||||
* \param channel Channel number.
|
||||
* \param period Period value.
|
||||
*/
|
||||
extern void pwmc_set_period(Pwm * p_pwm, uint8_t channel, uint16_t period);
|
||||
|
||||
/**
|
||||
* \brief Sets the duty cycle used by a PWM channel.
|
||||
* This function writes directly to the CDTY register if the channel is
|
||||
* disabled. Otherwise it sets the update register CDTYUPD.
|
||||
* Note that the duty cycle must always be inferior or equal to the channel
|
||||
* period.
|
||||
*
|
||||
* \param p_pwm Pointer to a Pwm instance
|
||||
* \param channel Channel number.
|
||||
* \param duty Duty cycle value.
|
||||
*/
|
||||
extern void pwmc_set_duty_cycle(Pwm * p_pwm, uint8_t channel, uint16_t duty);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* #ifndef _PWMC_ */
|
|
@ -0,0 +1,233 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* ATMEL Microcontroller Software Support
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#include "chip.h"
|
||||
#include "timer.h"
|
||||
#include "trace.h"
|
||||
#include "peripherals/pmc.h"
|
||||
#include "peripherals/qspi.h"
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static void qspi_memcpy(uint8_t *dst, const uint8_t *src, int count)
|
||||
{
|
||||
while (count--)
|
||||
*dst++ = *src++;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Public functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void qspi_initialize(Qspi *qspi)
|
||||
{
|
||||
pmc_enable_peripheral(get_qspi_id_from_addr(qspi));
|
||||
|
||||
/* Disable write protection */
|
||||
qspi->QSPI_WPMR = QSPI_WPMR_WPKEY_PASSWD;
|
||||
|
||||
/* Reset */
|
||||
qspi->QSPI_CR = QSPI_CR_SWRST;
|
||||
|
||||
/* Configure */
|
||||
qspi->QSPI_MR = QSPI_MR_SMM_MEMORY;
|
||||
qspi->QSPI_SCR = 0;
|
||||
|
||||
/* Enable */
|
||||
qspi->QSPI_CR = QSPI_CR_QSPIEN;
|
||||
}
|
||||
|
||||
uint32_t qspi_set_baudrate(Qspi *qspi, uint32_t baudrate)
|
||||
{
|
||||
uint32_t mck, scr, scbr;
|
||||
|
||||
if (!baudrate)
|
||||
return 0;
|
||||
|
||||
/* Serial Clock Baudrate */
|
||||
mck = pmc_get_peripheral_clock(get_qspi_id_from_addr(qspi));
|
||||
scbr = (mck + baudrate - 1) / baudrate;
|
||||
if (scbr > 0)
|
||||
scbr--;
|
||||
|
||||
/* Update the Serial Clock Register */
|
||||
scr = qspi->QSPI_SCR;
|
||||
scr &= ~QSPI_SCR_SCBR_Msk;
|
||||
scr |= QSPI_SCR_SCBR(scbr);
|
||||
qspi->QSPI_SCR = scr;
|
||||
|
||||
return mck / (scbr + 1);
|
||||
}
|
||||
|
||||
bool qspi_perform_command(Qspi *qspi, const struct _qspi_cmd *cmd)
|
||||
{
|
||||
uint32_t iar, icr, ifr;
|
||||
uint32_t offset;
|
||||
|
||||
iar = 0;
|
||||
icr = 0;
|
||||
ifr = (cmd->ifr_width & QSPI_IFR_WIDTH_Msk) | (cmd->ifr_type & QSPI_IFR_TFRTYP_Msk);
|
||||
|
||||
/* Compute address parameters */
|
||||
switch (cmd->enable.address) {
|
||||
case 4:
|
||||
ifr |= QSPI_IFR_ADDRL_32_BIT;
|
||||
/* fallback to the 24-bit address case */
|
||||
case 3:
|
||||
iar = (cmd->enable.data) ? 0 : QSPI_IAR_ADDR(cmd->address);
|
||||
ifr |= QSPI_IFR_ADDREN;
|
||||
offset = cmd->address;
|
||||
break;
|
||||
case 0:
|
||||
offset = 0;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Compute instruction parameters */
|
||||
if (cmd->enable.instruction) {
|
||||
icr |= QSPI_ICR_INST(cmd->instruction);
|
||||
ifr |= QSPI_IFR_INSTEN;
|
||||
}
|
||||
|
||||
/* Compute option parameters */
|
||||
if (cmd->enable.mode && cmd->num_mode_cycles) {
|
||||
uint32_t mode_cycle_bits, mode_bits;
|
||||
|
||||
icr |= QSPI_ICR_OPT(cmd->mode);
|
||||
ifr |= QSPI_IFR_OPTEN;
|
||||
|
||||
switch (ifr & QSPI_IFR_WIDTH_Msk) {
|
||||
case QSPI_IFR_WIDTH_SINGLE_BIT_SPI:
|
||||
case QSPI_IFR_WIDTH_DUAL_OUTPUT:
|
||||
case QSPI_IFR_WIDTH_QUAD_OUTPUT:
|
||||
mode_cycle_bits = 1;
|
||||
break;
|
||||
case QSPI_IFR_WIDTH_DUAL_IO:
|
||||
case QSPI_IFR_WIDTH_DUAL_CMD:
|
||||
mode_cycle_bits = 2;
|
||||
break;
|
||||
case QSPI_IFR_WIDTH_QUAD_IO:
|
||||
case QSPI_IFR_WIDTH_QUAD_CMD:
|
||||
mode_cycle_bits = 4;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
mode_bits = cmd->num_mode_cycles * mode_cycle_bits;
|
||||
switch (mode_bits) {
|
||||
case 1:
|
||||
ifr |= QSPI_IFR_OPTL_OPTION_1BIT;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
ifr |= QSPI_IFR_OPTL_OPTION_2BIT;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
ifr |= QSPI_IFR_OPTL_OPTION_4BIT;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
ifr |= QSPI_IFR_OPTL_OPTION_8BIT;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set number of dummy cycles */
|
||||
if (cmd->enable.dummy)
|
||||
ifr |= QSPI_IFR_NBDUM(cmd->num_dummy_cycles);
|
||||
else
|
||||
ifr |= QSPI_IFR_NBDUM(0);
|
||||
|
||||
/* Set data enable */
|
||||
if (cmd->enable.data) {
|
||||
ifr |= QSPI_IFR_DATAEN;
|
||||
|
||||
/* Special case for Continous Read Mode */
|
||||
if (!cmd->tx_buffer && !cmd->rx_buffer)
|
||||
ifr |= QSPI_IFR_CRM_ENABLED;
|
||||
}
|
||||
|
||||
/* Set QSPI Instruction Frame registers */
|
||||
qspi->QSPI_IAR = iar;
|
||||
qspi->QSPI_ICR = icr;
|
||||
qspi->QSPI_IFR = ifr;
|
||||
|
||||
/* Skip to the final steps if there is no data */
|
||||
if (!cmd->enable.data)
|
||||
goto no_data;
|
||||
|
||||
/* Dummy read of QSPI_IFR to synchronize APB and AHB accesses */
|
||||
(void)qspi->QSPI_IFR;
|
||||
|
||||
/* Send/Receive data */
|
||||
if (cmd->tx_buffer) {
|
||||
/* Write data */
|
||||
uint8_t *ptr = (uint8_t*)get_qspi_mem_from_addr(qspi);
|
||||
qspi_memcpy(ptr + offset, cmd->tx_buffer, cmd->buffer_len);
|
||||
} else if (cmd->rx_buffer) {
|
||||
/* Read data */
|
||||
const uint8_t *ptr = (const uint8_t*)get_qspi_mem_from_addr(qspi);
|
||||
qspi_memcpy(cmd->rx_buffer, ptr + offset, cmd->buffer_len);
|
||||
} else {
|
||||
/* Stop here for continuous read */
|
||||
return true;
|
||||
}
|
||||
|
||||
no_data:
|
||||
/* Release the chip-select */
|
||||
qspi->QSPI_CR = QSPI_CR_LASTXFER;
|
||||
|
||||
/* Wait for INSTRuction End */
|
||||
struct _timeout timeout;
|
||||
timer_start_timeout(&timeout, cmd->timeout);
|
||||
while (!(qspi->QSPI_SR & QSPI_SR_INSTRE)) {
|
||||
if (timer_timeout_reached(&timeout)) {
|
||||
trace_debug("qspi_perform_command timeout reached\r\n");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,143 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Interface for Quad Serial Peripheral Interface (QSPI) controller.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _QSPI_H_
|
||||
#define _QSPI_H_
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Types
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/** QSPI Command structure */
|
||||
struct _qspi_cmd {
|
||||
/** Data Transfer Type (QSPI_IFR_TFRTYP_TRSFR_xxx) */
|
||||
uint32_t ifr_type;
|
||||
|
||||
/** Width of Instruction Code, Address, Option Code and Data
|
||||
* (QSPI_IFR_WIDTH_xxx) */
|
||||
uint32_t ifr_width;
|
||||
|
||||
/** Flags to select which information is included in the command */
|
||||
struct {
|
||||
/** 0: don't send instruction code, 1: send instuction code */
|
||||
uint32_t instruction:1;
|
||||
/** 0: don't send address, 3: send 3-byte address, 4: send
|
||||
* 4-byte address */
|
||||
uint32_t address:3;
|
||||
/** 0: don't send mode bits, 1: send mode bits */
|
||||
uint32_t mode:1;
|
||||
/** 0: don't send dummy bits, 1: send dummy bits */
|
||||
uint32_t dummy:1;
|
||||
/** 0: don't send/recieve data, 1: send/recieve data */
|
||||
uint32_t data:1;
|
||||
/** reserved, not used */
|
||||
uint32_t reserved:25;
|
||||
} enable;
|
||||
|
||||
/** Instruction code */
|
||||
uint8_t instruction;
|
||||
|
||||
/** Mode bits */
|
||||
uint8_t mode;
|
||||
|
||||
/** Number of mode cycles */
|
||||
uint8_t num_mode_cycles;
|
||||
|
||||
/** Number of dummy cycles */
|
||||
uint8_t num_dummy_cycles;
|
||||
|
||||
/** QSPI address */
|
||||
uint32_t address;
|
||||
|
||||
/** Address of the TX buffer */
|
||||
const void *tx_buffer;
|
||||
|
||||
/** Address of the RX buffer */
|
||||
void *rx_buffer;
|
||||
|
||||
/** Size of the RX/TX buffer */
|
||||
uint32_t buffer_len;
|
||||
|
||||
/** Timeout for the command execution, in timer ticks */
|
||||
uint32_t timeout;
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Reset and initialize a QSPI instance.
|
||||
*
|
||||
* \param qspi the QSPI instance
|
||||
*/
|
||||
void qspi_initialize(Qspi *qspi);
|
||||
|
||||
/**
|
||||
* \brief Configure the baudrate for a QSPI instance.
|
||||
*
|
||||
* \param qspi the QSPI instance
|
||||
* \param baudrate the requested baudrate
|
||||
* \return the actual baudrate configured (can be lower than requested)
|
||||
*/
|
||||
uint32_t qspi_set_baudrate(Qspi *qspi, uint32_t baudrate);
|
||||
|
||||
/**
|
||||
* \brief Perform a QSPI command.
|
||||
*
|
||||
* Note that if enable.data is set in the command, data will be sent/recieved:
|
||||
* - if tx_buffer is not NULL, data will be sent
|
||||
* - if rx_buffer is not NULL, data will be recieved
|
||||
* - if both tx_buffer and rx_buffer are NULL, QSPI will be configured in
|
||||
* "Continuous Read" mode and random read access can be done at the address
|
||||
* returned by get_qspi_mem_from_addr
|
||||
*
|
||||
* \param qspi the QSPI instance
|
||||
* \param cmd the QSPI command to perform
|
||||
* \return true if the command was succesfully issued, false otherwise
|
||||
*/
|
||||
bool qspi_perform_command(Qspi *qspi, const struct _qspi_cmd *cmd);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _QSPI_H_ */
|
|
@ -0,0 +1,131 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file */
|
||||
/*---------------------------------------------------------------------------
|
||||
* Headers
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/rstc.h"
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Configure the mode of the RSTC peripheral.
|
||||
* The configuration is computed by the lib (RSTC_RMR_*).
|
||||
* \param mr Desired mode configuration.
|
||||
*/
|
||||
void rstc_configure_mode(uint32_t mr)
|
||||
{
|
||||
RSTC->RSTC_MR = (mr & ~RSTC_MR_KEY_Msk) | RSTC_MR_KEY_PASSWD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable the detection of a low level on the pin NRST as User Reset
|
||||
* \param enable 1 to enable & 0 to disable.
|
||||
*/
|
||||
void rstc_set_user_reset_enable(uint8_t enable)
|
||||
{
|
||||
uint32_t mr = RSTC->RSTC_MR;
|
||||
if (enable) {
|
||||
mr |= RSTC_MR_URSTEN;
|
||||
} else {
|
||||
mr &= ~RSTC_MR_URSTEN;
|
||||
}
|
||||
RSTC->RSTC_MR = mr | RSTC_MR_KEY_PASSWD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable/Disable the interrupt of a User Reset (USRTS bit in RSTC_RST).
|
||||
* \param enable 1 to enable & 0 to disable.
|
||||
*/
|
||||
void rstc_set_user_reset_interrupt_enable(uint8_t enable)
|
||||
{
|
||||
uint32_t mr = RSTC->RSTC_MR;
|
||||
if (enable) {
|
||||
mr |= RSTC_MR_URSTIEN;
|
||||
} else {
|
||||
|
||||
mr &= ~RSTC_MR_URSTIEN;
|
||||
}
|
||||
RSTC->RSTC_MR = mr | RSTC_MR_KEY_PASSWD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the processor.
|
||||
*/
|
||||
void rstc_processor_reset(void)
|
||||
{
|
||||
RSTC->RSTC_CR = RSTC_CR_PROCRST | RSTC_MR_KEY_PASSWD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the peripherals.
|
||||
*/
|
||||
void rstc_peripheral_reset(void)
|
||||
{
|
||||
RSTC->RSTC_CR = RSTC_CR_PERRST | RSTC_MR_KEY_PASSWD;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return NRST pin level ( 1 or 0 ).
|
||||
*/
|
||||
uint8_t rstc_get_nrst_level(void)
|
||||
{
|
||||
return (RSTC->RSTC_SR & RSTC_SR_NRSTL) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns 1 if at least one high-to-low transition of NRST (User Reset) has
|
||||
* been detected since the last read of RSTC_RSR.
|
||||
*/
|
||||
uint8_t rstc_is_user_reset_detected(void)
|
||||
{
|
||||
return (RSTC->RSTC_SR & RSTC_SR_URSTS) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return 1 if a software reset command is being performed by the reset
|
||||
* controller. The reset controller is busy.
|
||||
*/
|
||||
uint8_t rstc_is_busy(void)
|
||||
{
|
||||
return (RSTC->RSTC_SR & RSTC_SR_SRCMP) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the status
|
||||
*/
|
||||
uint32_t rstc_get_status(void)
|
||||
{
|
||||
return RSTC->RSTC_SR;
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _RSTC_H
|
||||
#define _RSTC_H
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Includes
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*---------------------------------------------------------------------------*/
|
||||
|
||||
extern void rstc_configure_mode(uint32_t rmr);
|
||||
extern void rstc_set_user_reset_enable(uint8_t enable);
|
||||
extern void rstc_set_user_reset_interrupt_enable(uint8_t enable);
|
||||
extern void rstc_processor_reset(void);
|
||||
extern void rstc_peripheral_reset(void);
|
||||
extern uint8_t rstc_get_nrst_level(void);
|
||||
extern uint8_t rstc_is_user_reset_detected(void);
|
||||
extern uint8_t rstc_is_busy(void);
|
||||
extern uint32_t rstc_get_status(void);
|
||||
|
||||
#endif /* #ifndef _RSTC_H */
|
|
@ -0,0 +1,554 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \addtogroup rtc_module Working with RTC
|
||||
* \section Purpose
|
||||
* The RTC driver provides the interface to configure and use the RTC
|
||||
* peripheral.
|
||||
*
|
||||
* It manages date, time, and alarms.\n
|
||||
* This timer is clocked by the 32kHz system clock, and is not impacted by
|
||||
* power management settings (PMC). To be accurate, it is better to use an
|
||||
* external 32kHz crystal instead of the internal 32kHz RC.\n
|
||||
*
|
||||
* It uses BCD format, and time can be set in AM/PM or 24h mode through a
|
||||
* configuration bit in the mode register.\n
|
||||
*
|
||||
* To update date or time, the user has to follow these few steps :
|
||||
* <ul>
|
||||
* <li>Set UPDTIM and/or UPDCAL bit(s) in RTC_CR,</li>
|
||||
* <li>Polling or IRQ on the ACKUPD bit of RTC_CR,</li>
|
||||
* <li>Clear ACKUPD bit in RTC_SCCR,</li>
|
||||
* <li>Update Time and/or Calendar values in RTC_TIMR/RTC_CALR (BCD format),</li>
|
||||
* <li>Clear UPDTIM and/or UPDCAL bit in RTC_CR.</li>
|
||||
* </ul>
|
||||
* An alarm can be set to happen on month, date, hours, minutes or seconds,
|
||||
* by setting the proper "Enable" bit of each of these fields in the Time and
|
||||
* Calendar registers.
|
||||
* This allows a large number of configurations to be available for the user.
|
||||
* Alarm occurence can be detected even by polling or interrupt.
|
||||
*
|
||||
* A check of the validity of the date and time format and values written by the user is automatically done.
|
||||
* Errors are reported through the Valid Entry Register.
|
||||
*
|
||||
* \section Usage
|
||||
* <ul>
|
||||
* <li> Enable & disable RTC interrupt using rtc_enable_it() and rtc_disable_it().
|
||||
* <li> Set RTC data, time, alarm using rtc_set_date(), rtc_set_time(),
|
||||
* rtc_set_time_alarm() and rtc_set_date_alarm().
|
||||
* <li> Get RTC data, time using rtc_get_date() and rtc_get_time().
|
||||
* </li>
|
||||
* </ul>
|
||||
*
|
||||
* For more accurate information, please look at the RTC section of the
|
||||
* Datasheet.
|
||||
*
|
||||
* Related files :\n
|
||||
* \ref rtc.c\n
|
||||
* \ref rtc.h.\n
|
||||
*/
|
||||
/*@{*/
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implementation of Real Time Clock (RTC) controller.
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/rtc.h"
|
||||
#include "trace.h"
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local Defines
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/* The BCD code shift value */
|
||||
#define BCD_SHIFT 4
|
||||
|
||||
/* The BCD code mask value */
|
||||
#define BCD_MASK 0xfu
|
||||
|
||||
/* The BCD mul/div factor value */
|
||||
#define BCD_FACTOR 10
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local Types
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
struct rtc_ppm_lookup {
|
||||
int8_t tempr;
|
||||
int16_t ppm;
|
||||
uint8_t negppm;
|
||||
uint8_t highppm;
|
||||
uint16_t correction;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Local constants
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
static const struct rtc_ppm_lookup ppm_lookup[] = {
|
||||
{-40, -168, 0, 1, 22},
|
||||
{-39, -163, 0, 1, 23},
|
||||
{-38, -158, 0, 1, 24},
|
||||
{-37, -153, 0, 1, 25},
|
||||
{-36, -148, 0, 1, 25},
|
||||
{-35, -143, 0, 1, 26},
|
||||
{-34, -138, 0, 1, 27},
|
||||
{-33, -134, 0, 1, 28},
|
||||
{-32, -129, 0, 1, 29},
|
||||
{-31, -124, 0, 1, 31},
|
||||
{-30, -120, 0, 1, 32},
|
||||
{-29, -116, 0, 1, 33},
|
||||
{-28, -111, 0, 1, 34},
|
||||
{-27, -107, 0, 1, 36},
|
||||
{-26, -103, 0, 1, 37},
|
||||
{-25, -99, 0, 1, 38},
|
||||
{-24, -95, 0, 1, 40},
|
||||
{-23, -91, 0, 1, 42},
|
||||
{-22, -87, 0, 1, 44},
|
||||
{-21, -84, 0, 1, 45},
|
||||
{-20, -80, 0, 1, 48},
|
||||
{-19, -76, 0, 1, 50},
|
||||
{-18, -73, 0, 1, 53},
|
||||
{-17, -70, 0, 1, 55},
|
||||
{-16, -66, 0, 1, 58},
|
||||
{-15, -63, 0, 1, 61},
|
||||
{-14, -60, 0, 1, 64},
|
||||
{-13, -57, 0, 1, 68},
|
||||
{-12, -54, 0, 1, 71},
|
||||
{-11, -51, 0, 1, 76},
|
||||
{-10, -48, 0, 1, 80},
|
||||
{-9, -45, 0, 1, 86},
|
||||
{-8, -43, 0, 1, 90},
|
||||
{-7, -40, 0, 1, 97},
|
||||
{-6, -37, 0, 1, 105},
|
||||
{-5, -35, 0, 1, 111},
|
||||
{-4, -33, 0, 1, 117},
|
||||
{-3, -30, 0, 0, 6},
|
||||
{-2, -28, 0, 0, 6},
|
||||
{-1, -26, 0, 0, 7},
|
||||
{0, -24, 0, 0, 7},
|
||||
{1, -22, 0, 0, 8},
|
||||
{2, -20, 0, 0, 9},
|
||||
{3, -18, 0, 0, 10},
|
||||
{4, -17, 0, 0, 10},
|
||||
{5, -15, 0, 0, 12},
|
||||
{6, -13, 0, 0, 14},
|
||||
{7, -12, 0, 0, 15},
|
||||
{8, -11, 0, 0, 17},
|
||||
{9, -9, 0, 0, 21},
|
||||
{10, -8, 0, 0, 23},
|
||||
{11, -7, 0, 0, 27},
|
||||
{12, -6, 0, 0, 32},
|
||||
{13, -5, 0, 0, 38},
|
||||
{14, -4, 0, 0, 48},
|
||||
{15, -3, 0, 0, 64},
|
||||
{16, -2, 0, 0, 97},
|
||||
{17, -2, 0, 0, 97},
|
||||
{18, -1, 0, 0, 127},
|
||||
{19, 0, 1, 0, 0},
|
||||
{20, 0, 1, 0, 0},
|
||||
{21, 0, 1, 0, 0},
|
||||
{22, 1, 1, 0, 127},
|
||||
{23, 1, 1, 0, 127},
|
||||
{24, 1, 1, 0, 127},
|
||||
{25, 1, 1, 0, 127},
|
||||
{26, 1, 1, 0, 127},
|
||||
{27, 1, 1, 0, 127},
|
||||
{28, 1, 1, 0, 127},
|
||||
{29, 0, 1, 0, 0},
|
||||
{30, 0, 1, 0, 0},
|
||||
{31, 0, 1, 0, 0},
|
||||
{32, -1, 0, 0, 127},
|
||||
{33, -2, 0, 0, 97},
|
||||
{34, -2, 0, 0, 97},
|
||||
{35, -3, 0, 0, 64},
|
||||
{36, -4, 0, 0, 48},
|
||||
{37, -5, 0, 0, 38},
|
||||
{38, -6, 0, 0, 32},
|
||||
{39, -7, 0, 0, 27},
|
||||
{40, -8, 0, 0, 23},
|
||||
{41, -9, 0, 0, 21},
|
||||
{42, -11, 0, 0, 17},
|
||||
{43, -12, 0, 0, 15},
|
||||
{44, -13, 0, 0, 14},
|
||||
{45, -15, 0, 0, 12},
|
||||
{46, -17, 0, 0, 10},
|
||||
{47, -18, 0, 0, 10},
|
||||
{48, -20, 0, 0, 9},
|
||||
{49, -22, 0, 0, 8},
|
||||
{50, -24, 0, 0, 7},
|
||||
{51, -26, 0, 0, 7},
|
||||
{52, -28, 0, 0, 6},
|
||||
{53, -30, 0, 0, 6},
|
||||
{54, -33, 0, 1, 117},
|
||||
{55, -35, 0, 1, 111},
|
||||
{56, -37, 0, 1, 105},
|
||||
{57, -40, 0, 1, 97},
|
||||
{58, -43, 0, 1, 90},
|
||||
{59, -45, 0, 1, 86},
|
||||
{60, -48, 0, 1, 80},
|
||||
{61, -51, 0, 1, 76},
|
||||
{62, -54, 0, 1, 71},
|
||||
{63, -57, 0, 1, 68},
|
||||
{64, -60, 0, 1, 64},
|
||||
{65, -63, 0, 1, 61},
|
||||
{66, -66, 0, 1, 58},
|
||||
{67, -70, 0, 1, 55},
|
||||
{68, -73, 0, 1, 53},
|
||||
{69, -76, 0, 1, 50},
|
||||
{70, -80, 0, 1, 48},
|
||||
{71, -84, 0, 1, 45},
|
||||
{72, -87, 0, 1, 44},
|
||||
{73, -91, 0, 1, 42},
|
||||
{74, -95, 0, 1, 40},
|
||||
{75, -99, 0, 1, 38},
|
||||
{76, -103, 0, 1, 37},
|
||||
{77, -107, 0, 1, 36},
|
||||
{78, -111, 0, 1, 34},
|
||||
{79, -116, 0, 1, 33},
|
||||
{80, -120, 0, 1, 32},
|
||||
{81, -124, 0, 1, 31},
|
||||
{82, -129, 0, 1, 29},
|
||||
{83, -134, 0, 1, 28},
|
||||
{84, -138, 0, 1, 27},
|
||||
{85, -143, 0, 1, 26}
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Sets the RTC in either 12 or 24 hour mode.
|
||||
*
|
||||
* \param dwMode Hour mode.
|
||||
*/
|
||||
void rtc_set_hour_mode(uint32_t mode)
|
||||
{
|
||||
assert((mode & 0xFFFFFFFE) == 0);
|
||||
RTC->RTC_MR = mode;
|
||||
}
|
||||
|
||||
extern uint32_t rtc_get_hour_mode(void)
|
||||
{
|
||||
uint32_t mode;
|
||||
mode = RTC->RTC_MR;
|
||||
mode &= 0xFFFFFFFE;
|
||||
return mode;
|
||||
}
|
||||
|
||||
void rtc_enable_it(uint32_t sources)
|
||||
{
|
||||
assert((sources & (uint32_t) (~0x1F)) == 0);
|
||||
RTC->RTC_IER = sources;
|
||||
}
|
||||
|
||||
void rtc_disable_it(uint32_t sources)
|
||||
{
|
||||
assert((sources & (uint32_t) (~0x1F)) == 0);
|
||||
RTC->RTC_IDR = sources;
|
||||
}
|
||||
|
||||
uint32_t rtc_set_time(struct _time *time)
|
||||
{
|
||||
uint32_t ltime = 0;
|
||||
uint8_t hour_bcd , min_bcd, sec_bcd;
|
||||
|
||||
/* if 12-hour mode, set AMPM bit */
|
||||
if ((RTC->RTC_MR & RTC_MR_HRMOD) == RTC_MR_HRMOD) {
|
||||
if (time->hour > 12) {
|
||||
time->hour -= 12;
|
||||
ltime |= RTC_TIMR_AMPM;
|
||||
}
|
||||
}
|
||||
hour_bcd = (time->hour % 10) | ((time->hour / 10) << 4);
|
||||
min_bcd = (time->min % 10) | ((time->min / 10) << 4);
|
||||
sec_bcd = (time->sec % 10) | ((time->sec / 10) << 4);
|
||||
/* value overflow */
|
||||
if ((hour_bcd & (uint8_t) (~RTC_HOUR_BIT_LEN_MASK)) |
|
||||
(min_bcd & (uint8_t) (~RTC_MIN_BIT_LEN_MASK)) |
|
||||
(sec_bcd & (uint8_t) (~RTC_SEC_BIT_LEN_MASK))) {
|
||||
return 1;
|
||||
}
|
||||
ltime = sec_bcd | (min_bcd << 8) | (hour_bcd << 16);
|
||||
RTC->RTC_CR |= RTC_CR_UPDTIM;
|
||||
while ((RTC->RTC_SR & RTC_SR_ACKUPD) != RTC_SR_ACKUPD) ;
|
||||
RTC->RTC_SCCR = RTC_SCCR_ACKCLR;
|
||||
RTC->RTC_TIMR = ltime;
|
||||
RTC->RTC_CR &= (uint32_t) (~RTC_CR_UPDTIM);
|
||||
RTC->RTC_SCCR |= RTC_SCCR_SECCLR;
|
||||
return (uint32_t) (RTC->RTC_VER & RTC_VER_NVTIM);
|
||||
}
|
||||
|
||||
void rtc_get_time(struct _time *time)
|
||||
{
|
||||
uint32_t ltime;
|
||||
|
||||
/* Get current RTC time */
|
||||
ltime = RTC->RTC_TIMR;
|
||||
while (ltime != RTC->RTC_TIMR) {
|
||||
ltime = RTC->RTC_TIMR;
|
||||
}
|
||||
/* Hour */
|
||||
time->hour = ((ltime & 0x00300000) >> 20) * 10 + ((ltime & 0x000F0000) >> 16);
|
||||
if ((ltime & RTC_TIMR_AMPM) == RTC_TIMR_AMPM) {
|
||||
time->hour += 12;
|
||||
}
|
||||
/* Minute */
|
||||
time->min = ((ltime & 0x00007000) >> 12) * 10 + ((ltime & 0x00000F00) >> 8);
|
||||
/* Second */
|
||||
time->sec = ((ltime & 0x00000070) >> 4) * 10 + (ltime & 0x0000000F);
|
||||
}
|
||||
|
||||
uint32_t rtc_set_time_alarm(struct _time *time)
|
||||
{
|
||||
uint32_t alarm = 0;
|
||||
|
||||
/* Hour */
|
||||
if (time->hour) {
|
||||
alarm |= RTC_TIMALR_HOUREN | ((time->hour / 10) << 20) | ((time->hour % 10) << 16);
|
||||
}
|
||||
/* Minute */
|
||||
if (time->min) {
|
||||
alarm |= RTC_TIMALR_MINEN | ((time->min / 10) << 12) | ((time->min % 10) << 8);
|
||||
}
|
||||
/* Second */
|
||||
if (time->sec) {
|
||||
alarm |= RTC_TIMALR_SECEN | ((time->sec / 10) << 4) | (time->sec % 10);
|
||||
}
|
||||
RTC->RTC_TIMALR = alarm;
|
||||
return (uint32_t) (RTC->RTC_VER & RTC_VER_NVTIMALR);
|
||||
}
|
||||
|
||||
void rtc_get_date(struct _date *date)
|
||||
{
|
||||
uint32_t ldate;
|
||||
|
||||
/* Get current date (multiple reads are necessary to insure a stable value) */
|
||||
do {
|
||||
ldate = RTC->RTC_CALR;
|
||||
} while (ldate != RTC->RTC_CALR);
|
||||
|
||||
/* Retrieve values */
|
||||
date->year = (((ldate >> 4) & 0x7) * 1000) + ((ldate & 0xF) * 100)
|
||||
+ (((ldate >> 12) & 0xF) * 10) + ((ldate >> 8) & 0xF);
|
||||
date->month = (((ldate >> 20) & 1) * 10) + ((ldate >> 16) & 0xF);
|
||||
date->day = (((ldate >> 28) & 0x3) * 10) + ((ldate >> 24) & 0xF);
|
||||
date->week = ((ldate >> 21) & 0x7);
|
||||
}
|
||||
|
||||
uint32_t rtc_set_date(struct _date *date)
|
||||
{
|
||||
uint32_t ldate;
|
||||
uint8_t cent_bcd, year_bcd, month_bcd, day_bcd, week_bcd;
|
||||
|
||||
cent_bcd = ((date->year / 100) % 10) | ((date->year / 1000) << 4);
|
||||
year_bcd = (date->year % 10) | (((date->year / 10) % 10) << 4);
|
||||
month_bcd = ((date->month % 10) | (date->month / 10) << 4);
|
||||
day_bcd = ((date->day % 10) | (date->day / 10) << 4);
|
||||
week_bcd = ((date->week % 10) | (date->week / 10) << 4);
|
||||
/* value over flow */
|
||||
if ((cent_bcd & (uint8_t) (~RTC_CENT_BIT_LEN_MASK)) |
|
||||
(year_bcd & (uint8_t) (~RTC_YEAR_BIT_LEN_MASK)) |
|
||||
(month_bcd & (uint8_t) (~RTC_MONTH_BIT_LEN_MASK)) |
|
||||
(week_bcd & (uint8_t) (~RTC_WEEK_BIT_LEN_MASK)) |
|
||||
(day_bcd & (uint8_t) (~RTC_DATE_BIT_LEN_MASK))
|
||||
) {
|
||||
return 1;
|
||||
}
|
||||
/* Convert values to date register value */
|
||||
ldate = cent_bcd | (year_bcd << 8) | (month_bcd << 16) | (week_bcd << 21) | (day_bcd << 24);
|
||||
/* Update calendar register */
|
||||
RTC->RTC_CR |= RTC_CR_UPDCAL;
|
||||
while ((RTC->RTC_SR & RTC_SR_ACKUPD) != RTC_SR_ACKUPD) ;
|
||||
RTC->RTC_SCCR = RTC_SCCR_ACKCLR;
|
||||
RTC->RTC_CALR = ldate;
|
||||
RTC->RTC_CR &= (uint32_t) (~RTC_CR_UPDCAL);
|
||||
RTC->RTC_SCCR |= RTC_SCCR_SECCLR; /* clear SECENV in SCCR */
|
||||
return (uint32_t) (RTC->RTC_VER & RTC_VER_NVCAL);
|
||||
}
|
||||
|
||||
uint32_t rtc_set_date_alarm(struct _date *date)
|
||||
{
|
||||
uint32_t alarm;
|
||||
|
||||
alarm = ((date->month) || (date->day)) ? (0) : (0x01010000);
|
||||
/* Compute alarm field value */
|
||||
if (date->month) {
|
||||
alarm |= RTC_CALALR_MTHEN | ((date->month / 10) << 20) | ((date->month % 10) << 16);
|
||||
}
|
||||
if (date->day) {
|
||||
alarm |= RTC_CALALR_DATEEN | ((date->day / 10) << 28) | ((date->day % 10) << 24);
|
||||
}
|
||||
/* Set alarm */
|
||||
RTC->RTC_CALALR = alarm;
|
||||
return (uint32_t) (RTC->RTC_VER & RTC_VER_NVCALALR);
|
||||
}
|
||||
|
||||
void rtc_clear_sccr(uint32_t mask)
|
||||
{
|
||||
/* Clear all flag bits in status clear command register */
|
||||
mask &= RTC_SCCR_ACKCLR | RTC_SCCR_ALRCLR | RTC_SCCR_SECCLR |
|
||||
RTC_SCCR_TIMCLR | RTC_SCCR_CALCLR;
|
||||
RTC->RTC_SCCR = mask;
|
||||
}
|
||||
|
||||
uint32_t rtc_get_sr(uint32_t mask)
|
||||
{
|
||||
return (RTC->RTC_SR) & mask;
|
||||
}
|
||||
|
||||
void rtc_get_tamper_time(struct _time *time, uint8_t reg_num)
|
||||
{
|
||||
uint32_t ltime, temp;
|
||||
|
||||
/* Get current RTC time */
|
||||
ltime = RTC->RTC_TS[reg_num].RTC_TSTR;
|
||||
while (ltime != RTC->RTC_TS[reg_num].RTC_TSTR) {
|
||||
ltime = RTC->RTC_TS[reg_num].RTC_TSTR;
|
||||
}
|
||||
/* Hour */
|
||||
if (time->hour) {
|
||||
temp = (ltime & RTC_TSTR_HOUR_Msk) >> RTC_TSTR_HOUR_Pos;
|
||||
time->hour = (temp >> BCD_SHIFT) * BCD_FACTOR + (temp & BCD_MASK);
|
||||
if ((ltime & RTC_TSTR_AMPM) == RTC_TSTR_AMPM) {
|
||||
time->hour += 12;
|
||||
}
|
||||
}
|
||||
/* Minute */
|
||||
if (time->min) {
|
||||
temp = (ltime & RTC_TSTR_MIN_Msk) >> RTC_TSTR_MIN_Pos;
|
||||
time->min = (temp >> BCD_SHIFT) * BCD_FACTOR + (temp & BCD_MASK);
|
||||
}
|
||||
/* Second */
|
||||
if (time->sec) {
|
||||
temp = (ltime & RTC_TSTR_SEC_Msk) >> RTC_TSTR_SEC_Pos;
|
||||
time->sec = (temp >> BCD_SHIFT) * BCD_FACTOR + (temp & BCD_MASK);
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_get_tamper_date(struct _date *date, uint8_t reg_num)
|
||||
{
|
||||
uint32_t ldate, cent, temp;
|
||||
|
||||
/* Get the current date (multiple reads are to insure a stable value). */
|
||||
ldate = RTC->RTC_TS[reg_num].RTC_TSDR;
|
||||
while (ldate != RTC->RTC_TS[reg_num].RTC_TSDR) {
|
||||
ldate = RTC->RTC_TS[reg_num].RTC_TSDR;
|
||||
}
|
||||
/* Retrieve year */
|
||||
temp = (ldate & RTC_TSDR_CENT_Msk) >> RTC_TSDR_CENT_Pos;
|
||||
cent = (temp >> BCD_SHIFT) * BCD_FACTOR + (temp & BCD_MASK);
|
||||
temp = (ldate & RTC_TSDR_YEAR_Msk) >> RTC_TSDR_YEAR_Pos;
|
||||
date->year = (cent * BCD_FACTOR * BCD_FACTOR) + (temp >> BCD_SHIFT) * BCD_FACTOR + (temp & BCD_MASK);
|
||||
|
||||
/* Retrieve month */
|
||||
temp = (ldate & RTC_TSDR_MONTH_Msk) >> RTC_TSDR_MONTH_Pos;
|
||||
date->month = (temp >> BCD_SHIFT) * BCD_FACTOR + (temp & BCD_MASK);
|
||||
|
||||
/* Retrieve day */
|
||||
temp = (ldate & RTC_TSDR_DATE_Msk) >> RTC_TSDR_DATE_Pos;
|
||||
date->day = (temp >> BCD_SHIFT) * BCD_FACTOR + (temp & BCD_MASK);
|
||||
|
||||
/* Retrieve week */
|
||||
date->week= ((ldate & RTC_TSDR_DAY_Msk) >> RTC_TSDR_DAY_Pos);
|
||||
}
|
||||
|
||||
uint32_t rtc_get_tamper_source(uint8_t reg_num)
|
||||
{
|
||||
return RTC->RTC_TS[reg_num].RTC_TSSR;
|
||||
}
|
||||
|
||||
uint32_t rtc_get_tamper_event_counter(void)
|
||||
{
|
||||
return (RTC->RTC_TS[0].RTC_TSTR & RTC_TSTR_TEVCNT_Msk) >> RTC_TSTR_TEVCNT_Pos;
|
||||
}
|
||||
|
||||
uint8_t rtc_is_tamper_occur_in_backup_mode(uint8_t reg_num)
|
||||
{
|
||||
if (RTC->RTC_TS[reg_num].RTC_TSTR & RTC_TSTR_BACKUP) {
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void rtc_convert_time_to_hms(struct _time *time, uint32_t count)
|
||||
{
|
||||
count = count % 86400;
|
||||
time->hour = count / 3600;
|
||||
count -= time->hour * 3600;
|
||||
time->min = count / 60;
|
||||
time->sec = count % 60;
|
||||
}
|
||||
|
||||
void rtc_calibration(int32_t current_tempr)
|
||||
{
|
||||
uint32_t i, mr;
|
||||
for (i = 0; i < ARRAY_SIZE(ppm_lookup); i++) {
|
||||
if (ppm_lookup[i].tempr == current_tempr) {
|
||||
mr = RTC_MR_CORRECTION(ppm_lookup[i].correction);
|
||||
mr |= (ppm_lookup[i].highppm << 15);
|
||||
mr |= (ppm_lookup[i].negppm << 4);
|
||||
RTC->RTC_MR = mr; // update the calibration value
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t rtc_set_time_event (uint32_t mask)
|
||||
{
|
||||
uint32_t reg;
|
||||
reg = RTC->RTC_CR;
|
||||
reg &= ~RTC_CR_TIMEVSEL_Msk;
|
||||
reg |= mask;
|
||||
RTC->RTC_CR = reg;
|
||||
return RTC->RTC_CR;
|
||||
}
|
||||
|
||||
uint32_t rtc_set_calendar_event (uint32_t mask)
|
||||
{
|
||||
uint32_t reg;
|
||||
reg = RTC->RTC_CR;
|
||||
reg &= ~RTC_CR_CALEVSEL_Msk;
|
||||
reg |= mask;
|
||||
RTC->RTC_CR = reg;
|
||||
return RTC->RTC_CR;
|
||||
}
|
|
@ -0,0 +1,305 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2011, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Interface for Real Time Clock (RTC) controller.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _RTC_H_
|
||||
#define _RTC_H_
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Definitions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#define RTC_HOUR_BIT_LEN_MASK 0x3F
|
||||
#define RTC_MIN_BIT_LEN_MASK 0x7F
|
||||
#define RTC_SEC_BIT_LEN_MASK 0x7F
|
||||
#define RTC_CENT_BIT_LEN_MASK 0x7F
|
||||
#define RTC_YEAR_BIT_LEN_MASK 0xFF
|
||||
#define RTC_MONTH_BIT_LEN_MASK 0x1F
|
||||
#define RTC_DATE_BIT_LEN_MASK 0x3F
|
||||
#define RTC_WEEK_BIT_LEN_MASK 0x07
|
||||
|
||||
struct _time
|
||||
{
|
||||
uint8_t hour;
|
||||
uint8_t min;
|
||||
uint8_t sec;
|
||||
} ;
|
||||
|
||||
struct _date
|
||||
{
|
||||
uint16_t year;
|
||||
uint8_t month;
|
||||
uint8_t day;
|
||||
uint8_t week;
|
||||
} ;
|
||||
|
||||
#ifdef CONFIG_SOC_SAMA5D2
|
||||
/* -------- RTC_TSTR : (RTC Offset: N/A) TimeStamp Time Register 0 -------- */
|
||||
#define RTC_TSTR_SEC_Pos 0
|
||||
#define RTC_TSTR_SEC_Msk (0x7fu << RTC_TSTR_SEC_Pos) /**< \brief (RTC_TSTR) SEConds of the tamper */
|
||||
#define RTC_TSTR_MIN_Pos 8
|
||||
#define RTC_TSTR_MIN_Msk (0x7fu << RTC_TSTR_MIN_Pos) /**< \brief (RTC_TSTR) MINutes of the tamper */
|
||||
#define RTC_TSTR_HOUR_Pos 16
|
||||
#define RTC_TSTR_HOUR_Msk (0x3fu << RTC_TSTR_HOUR_Pos) /**< \brief (RTC_TSTR) HOURs of the tamper */
|
||||
#define RTC_TSTR_AMPM (0x1u << 22) /**< \brief (RTC_TSTR) AMPM indicator of the tamper */
|
||||
#define RTC_TSTR_TEVCNT_Pos 24
|
||||
#define RTC_TSTR_TEVCNT_Msk (0xfu << RTC_TSTR_TEVCNT_Pos) /**< \brief (RTC_TSTR) Tamper events counter */
|
||||
#define RTC_TSTR_BACKUP (0x1u << 31) /**< \brief (RTC_TSTR) system mode of the tamper */
|
||||
/* -------- RTC_TSDR : (RTC Offset: N/A) TimeStamp Date Register 0 -------- */
|
||||
#define RTC_TSDR_CENT_Pos 0
|
||||
#define RTC_TSDR_CENT_Msk (0x7fu << RTC_TSDR_CENT_Pos) /**< \brief (RTC_TSDR) Century of the tamper */
|
||||
#define RTC_TSDR_YEAR_Pos 8
|
||||
#define RTC_TSDR_YEAR_Msk (0xffu << RTC_TSDR_YEAR_Pos) /**< \brief (RTC_TSDR) Year of the tamper */
|
||||
#define RTC_TSDR_MONTH_Pos 16
|
||||
#define RTC_TSDR_MONTH_Msk (0x1fu << RTC_TSDR_MONTH_Pos) /**< \brief (RTC_TSDR) Month of the tamper */
|
||||
#define RTC_TSDR_DAY_Pos 21
|
||||
#define RTC_TSDR_DAY_Msk (0x7u << RTC_TSDR_DAY_Pos) /**< \brief (RTC_TSDR) Day of the tamper */
|
||||
#define RTC_TSDR_DATE_Pos 24
|
||||
#define RTC_TSDR_DATE_Msk (0x3fu << RTC_TSDR_DATE_Pos) /**< \brief (RTC_TSDR) Date of the tamper */
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief Sets the RTC in either 12 or 24 hour mode.
|
||||
*
|
||||
* \param mode Hour mode.
|
||||
*/
|
||||
extern void rtc_set_hour_mode(uint32_t mode);
|
||||
|
||||
/**
|
||||
* \brief Gets the RTC mode.
|
||||
*
|
||||
* \return Hour mode.
|
||||
*/
|
||||
extern uint32_t rtc_get_hour_mode(void);
|
||||
|
||||
/**
|
||||
* \brief Enables the selected interrupt sources of the RTC.
|
||||
*
|
||||
* \param sources Interrupt sources to enable.
|
||||
*/
|
||||
extern void rtc_enable_it(uint32_t sources);
|
||||
|
||||
/**
|
||||
* \brief Disables the selected interrupt sources of the RTC.
|
||||
*
|
||||
* \param sources Interrupt sources to disable.
|
||||
*/
|
||||
extern void rtc_disable_it(uint32_t sources);
|
||||
|
||||
/**
|
||||
* \brief Sets the current time in the RTC.
|
||||
*
|
||||
* \note In successive update operations, the user must wait at least one second
|
||||
* after resetting the UPDTIM/UPDCAL bit in the RTC_CR before setting these
|
||||
* bits again. Please look at the RTC section of the datasheet for detail.
|
||||
*
|
||||
* \param time Pointer to structure time
|
||||
*
|
||||
* \return 0 sucess, 1 fail to set
|
||||
*/
|
||||
extern uint32_t rtc_set_time(struct _time *time);
|
||||
|
||||
/**
|
||||
* \brief Retrieves the current time as stored in the RTC in several variables.
|
||||
*
|
||||
* \param time Pointer to structure time
|
||||
*/
|
||||
extern void rtc_get_time(struct _time *time);
|
||||
|
||||
/**
|
||||
* \brief Sets a time alarm on the RTC.
|
||||
* The match is performed only on the provided variables;
|
||||
* Setting all pointers to 0 disables the time alarm.
|
||||
*
|
||||
* \note In AM/PM mode, the hour value must have bit #7 set for PM, cleared for
|
||||
* AM (as expected in the time registers).
|
||||
*
|
||||
* \param time Pointer to structure time.
|
||||
*
|
||||
* \return 0 success, 1 fail to set
|
||||
*/
|
||||
extern uint32_t rtc_set_time_alarm(struct _time *time);
|
||||
|
||||
/**
|
||||
* \brief Retrieves the current year, month and day from the RTC.
|
||||
* Month, day and week values are numbered starting at 1.
|
||||
*
|
||||
* \param date Pointer to structure Date.
|
||||
*/
|
||||
extern void rtc_get_date(struct _date *date);
|
||||
|
||||
/**
|
||||
* \brief Sets the current year, month and day in the RTC.
|
||||
* Month, day and week values must be numbered starting from 1.
|
||||
*
|
||||
* \note In successive update operations, the user must wait at least one second
|
||||
* after resetting the UPDTIM/UPDCAL bit in the RTC_CR before setting these
|
||||
* bits again. Please look at the RTC section of the datasheet for detail.
|
||||
*
|
||||
* \param date Pointer to structure Date
|
||||
*
|
||||
* \return 0 success, 1 fail to set
|
||||
*/
|
||||
extern uint32_t rtc_set_date(struct _date *date);
|
||||
|
||||
/**
|
||||
* \brief Sets a date alarm in the RTC.
|
||||
* The alarm will match only the provided values;
|
||||
* Passing a null-pointer disables the corresponding field match.
|
||||
*
|
||||
* \param pucMonth If not null, the RTC alarm will month-match this value.
|
||||
* \param pucDay If not null, the RTC alarm will day-match this value.
|
||||
*
|
||||
* \return 0 success, 1 fail to set
|
||||
*/
|
||||
extern uint32_t rtc_set_date_alarm(struct _date *date);
|
||||
|
||||
/**
|
||||
* \brief Clear flag bits of status clear command register in the RTC.
|
||||
*
|
||||
* \param mask Bits mask of cleared events
|
||||
*/
|
||||
extern void rtc_clear_sccr(uint32_t mask);
|
||||
|
||||
/**
|
||||
* \brief Get flag bits of status register in the RTC.
|
||||
*
|
||||
* \param mask Bits mask of Status Register
|
||||
*
|
||||
* \return Status register & mask
|
||||
*/
|
||||
extern uint32_t rtc_get_sr(uint32_t mask);
|
||||
|
||||
/**
|
||||
* \brief Get the RTC tamper time value.
|
||||
*
|
||||
* \note This function should be called before rtc_get_tamper_source()
|
||||
* function call, Otherwise the tamper time will be cleared.
|
||||
*
|
||||
* \param time Pointer to structure Time.
|
||||
* \param reg_num Tamper register set number.
|
||||
*/
|
||||
extern void rtc_get_tamper_time(struct _time *time, uint8_t reg_num);
|
||||
|
||||
/**
|
||||
* \brief Get the RTC tamper date.
|
||||
*
|
||||
* \note This function should be called before rtc_get_tamper_source()
|
||||
* function call, Otherwise the tamper date will be cleared.
|
||||
*
|
||||
* \param date Pointer to structure Date
|
||||
* \param reg_num Tamper register set number.
|
||||
*/
|
||||
extern void rtc_get_tamper_date(struct _date *date, uint8_t reg_num);
|
||||
|
||||
/**
|
||||
* \brief Get the RTC tamper source.
|
||||
*
|
||||
* \param reg_num Current tamper register set number.
|
||||
*
|
||||
* \return Tamper source.
|
||||
*/
|
||||
extern uint32_t rtc_get_tamper_source(uint8_t reg_num);
|
||||
|
||||
/**
|
||||
* \brief Get the RTC tamper event counter.
|
||||
*
|
||||
* \note This function should be called before rtc_get_tamper_source()
|
||||
* function call, Otherwise the tamper event counter will be cleared.
|
||||
*
|
||||
* \return Tamper event counter
|
||||
*/
|
||||
extern uint32_t rtc_get_tamper_event_counter(void);
|
||||
|
||||
/**
|
||||
* \brief Check the system is in backup mode when RTC tamper event happen.
|
||||
*
|
||||
* \note This function should be called before rtc_get_tamper_source()
|
||||
* function call, Otherwise the flag indicates tamper occur in backup
|
||||
* mode will be cleared.
|
||||
*
|
||||
* \param reg_num Current tamper register set number.
|
||||
*
|
||||
* \return 1 - The system is in backup mode when the tamper event occurs.
|
||||
* 0 - The system is different from backup mode.
|
||||
*/
|
||||
extern uint8_t rtc_is_tamper_occur_in_backup_mode(uint8_t reg_num);
|
||||
|
||||
/**
|
||||
* \brief Convert number of second (count) to HMS format.
|
||||
*
|
||||
*/
|
||||
extern void rtc_convert_time_to_hms (struct _time *time, uint32_t count);
|
||||
|
||||
/**
|
||||
* \brief RTC calibration for Temperature or PPM drift
|
||||
*/
|
||||
extern void rtc_calibration(int32_t current_tempr);
|
||||
|
||||
/**
|
||||
* \brief Set calendar event selection.
|
||||
*
|
||||
* \param mask Bits CALEVSEL of Control Register
|
||||
* \return Status register & mask
|
||||
*/
|
||||
extern uint32_t rtc_set_calendar_event (uint32_t mask);
|
||||
|
||||
/**
|
||||
* \brief Set time event selection.
|
||||
*
|
||||
* \param mask Bits TIMEVSEL of Control Register
|
||||
* \return Status register & mask
|
||||
*/
|
||||
extern uint32_t rtc_set_time_event (uint32_t maskask);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _RTC_H_ */
|
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,109 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _SDMMC_PERIPH_H_
|
||||
#define _SDMMC_PERIPH_H_
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct _SdmmcCommand;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Definitions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/* This structure is private to the SDMMC Driver.
|
||||
* Allocate it but ignore its members. */
|
||||
struct sdmmc_set
|
||||
{
|
||||
uint32_t id; /* SDMMC peripheral ID (ID_SDMMCx) */
|
||||
Sdmmc *regs; /* set of SDMMC hardware registers */
|
||||
uint32_t tc_id; /* Timer/Counter peripheral ID (ID_TCx) */
|
||||
TcChannel *timer; /* set of TC channel hardware registers */
|
||||
uint32_t *table; /* ADMA descriptor table, or NULL when DMA
|
||||
* is not used */
|
||||
uint32_t table_size; /* Max size of the ADMA descriptor table,
|
||||
* in lines */
|
||||
bool use_polling; /* polling mode */
|
||||
bool use_set_blk_cnt; /* implicit SET_BLOCK_COUNT command */
|
||||
|
||||
uint16_t blk_size; /* max data block size, in bytes */
|
||||
uint32_t dev_freq; /* frequency of clock provided to memory
|
||||
* device, in Hz */
|
||||
volatile uint8_t state;
|
||||
struct _SdmmcCommand *cmd; /* pointer to the command being processed */
|
||||
uint16_t blk_index; /* count of data blocks tranferred already,
|
||||
* in the context of the command and data
|
||||
* transfer being executed */
|
||||
uint8_t resp_len; /* size of the response, once retrieved,
|
||||
* in the context of the command being
|
||||
* executed, expressed in 32-bit words */
|
||||
bool expect_auto_end; /* waiting for completion of Auto CMD12 */
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Initialize the specified driver instance and the associated SDMMC
|
||||
* peripheral.
|
||||
* \param set Pointer to uninitialized driver instance data.
|
||||
* \param regs Base address of registers of the SDMMC peripheral.
|
||||
* \param sdmmc_id SDMMC peripheral ID (ID_SDMMCx).
|
||||
* \param tc_id TC peripheral ID (ID_TCx).
|
||||
* \note The application shall have enabled the clock assigned to this
|
||||
* Timer/Counter peripheral.
|
||||
* \param tc_ch TC channel number, within the Timer/Counter module designated
|
||||
* by tc_id. Every instance of the SDMMC Driver requires a Timer/Counter channel
|
||||
* for its exclusive usage.
|
||||
* \param dma_buf Buffer allocated by the application, required when DMA is
|
||||
* used. This is where the DMA descriptor table will be set up. The larger
|
||||
* the buffer is, the greater throughput we achieve. Up to 4 KiB. Shall be
|
||||
* word-aligned. NULL to have the CPU read/write data, word by word.
|
||||
* \param dma_buf_size Size of the dma_buf buffer, in words.
|
||||
* \return true if successful, false if a parameter is assigned an unsupported
|
||||
* value.
|
||||
*/
|
||||
bool sdmmc_initialize(struct sdmmc_set *set, Sdmmc *regs, uint32_t sdmmc_id,
|
||||
uint32_t tc_id, uint32_t tc_ch, uint32_t *dma_buf, uint32_t dma_buf_size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef _SDMMC_PERIPH_H_ */
|
|
@ -0,0 +1,56 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "peripherals/sfrbu.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void sfrbu_enable_ddr_backup(void)
|
||||
{
|
||||
/* Enable DDR backup mode. Isolate the DDR Pads from the CPU domain,
|
||||
VCCCORE */
|
||||
SFRBU->SFRBU_DDRBUMCR = SFRBU_DDRBUMCR_BUMEN;
|
||||
}
|
||||
|
||||
void sfrbu_disable_ddr_backup(void)
|
||||
{
|
||||
/* Connect the DDR Pads to the CPU domain, VCCCORE */
|
||||
SFRBU->SFRBU_DDRBUMCR &= ~SFRBU_DDRBUMCR_BUMEN;
|
||||
}
|
||||
|
||||
bool sfrbu_is_ddr_backup_enabled(void)
|
||||
{
|
||||
return (SFRBU->SFRBU_DDRBUMCR & SFRBU_DDRBUMCR_BUMEN) != 0;
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _SFRBU_H
|
||||
#define _SFRBU_H
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Global functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Enable DDR backup
|
||||
*/
|
||||
extern void sfrbu_enable_ddr_backup(void);
|
||||
|
||||
/**
|
||||
* \brief Disable DDR backup
|
||||
*/
|
||||
extern void sfrbu_disable_ddr_backup(void);
|
||||
|
||||
/**
|
||||
* \brief Get DDR backup status
|
||||
* \return true if DDR BU Mode is enabled, false otherwise
|
||||
*/
|
||||
extern bool sfrbu_is_ddr_backup_enabled(void);
|
||||
|
||||
#endif //#ifndef _SFRBU_H
|
|
@ -0,0 +1,135 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \addtogroup sha_module Working with SHA
|
||||
* \ingroup peripherals_module
|
||||
* The SHA driver provides the interface to configure and use the SHA
|
||||
* peripheral.
|
||||
* \n
|
||||
*
|
||||
* The Secure Hash Algorithm (SHA) module requires a padded message
|
||||
* according to FIPS180-2 specification. The first block of the
|
||||
* message must be indicated to the module by a specific command. The
|
||||
* SHA module produces a N-bit message digest each time a block is
|
||||
* written and processing period ends. N is 160 for SHA1, 224 for
|
||||
* SHA224, 256 for SHA256, 384 for SHA384, 512 for SHA512.
|
||||
*
|
||||
* To Enable a SHA encryption and decrypt,the user has to follow these
|
||||
* few steps:
|
||||
* <ul>
|
||||
* <li> Configure SHA algorithm mode, key mode, start mode and
|
||||
* operation mode by sha_configure(). </li>
|
||||
* <li> Set sha_first_block() to indicates that the next block to
|
||||
* process is the first one of a message.</li>
|
||||
* <li> Input data for encryption by sha_set_input(). </li>
|
||||
* <li> To start the encryption process with sha_start()</li>
|
||||
* <li> To get the encryption reslut by sha_get_output() </li>
|
||||
* </ul>
|
||||
*
|
||||
* For more accurate information, please look at the SHA section of the
|
||||
* Datasheet.
|
||||
*
|
||||
* Related files :\n
|
||||
* \ref sha.c\n
|
||||
* \ref sha.h\n
|
||||
*/
|
||||
/*@{*/
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implementation of Secure Hash Algorithm (SHA)
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/sha.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void sha_start(void)
|
||||
{
|
||||
SHA->SHA_CR = SHA_CR_START;
|
||||
}
|
||||
|
||||
void sha_soft_reset(void)
|
||||
{
|
||||
SHA->SHA_CR = SHA_CR_SWRST;
|
||||
}
|
||||
|
||||
void sha_first_block(void)
|
||||
{
|
||||
SHA->SHA_CR = SHA_CR_FIRST;
|
||||
}
|
||||
|
||||
void sha_configure(uint32_t mode)
|
||||
{
|
||||
SHA->SHA_MR = mode;
|
||||
}
|
||||
|
||||
void sha_enable_it(uint32_t sources)
|
||||
{
|
||||
SHA->SHA_IER = sources;
|
||||
}
|
||||
|
||||
void sha_disable_it(uint32_t sources)
|
||||
{
|
||||
SHA->SHA_IDR = sources;
|
||||
}
|
||||
|
||||
uint32_t sha_get_status(void)
|
||||
{
|
||||
return SHA->SHA_ISR;
|
||||
}
|
||||
|
||||
void sha_set_input(uint32_t * data, uint8_t len)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t num;
|
||||
num = len <= 16 ? len : 16;
|
||||
for (i = 0; i < num; i++)
|
||||
SHA->SHA_IDATAR[i] = (data[i]);
|
||||
num = len > 16 ? len - 16 : 0;
|
||||
for (i = 0; i < num; i++)
|
||||
SHA->SHA_IODATAR[i] = (data[i + 16]);
|
||||
}
|
||||
|
||||
void sha_get_output(uint32_t * data)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < 16; i++)
|
||||
data[i] = SHA->SHA_IODATAR[i];
|
||||
}
|
|
@ -0,0 +1,98 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _SHA_
|
||||
#define _SHA_
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/* Exported functions */
|
||||
/*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Starts Manual hash algorithm process.
|
||||
*/
|
||||
extern void sha_start(void);
|
||||
|
||||
/**
|
||||
* \brief Resets the SHA. A software triggered hardware reset of the
|
||||
* SHA interface is performed.
|
||||
*/
|
||||
extern void sha_soft_reset(void);
|
||||
|
||||
/**
|
||||
* \brief Indicates that the next block to process is the first one of
|
||||
* a message.
|
||||
*/
|
||||
extern void sha_first_block(void);
|
||||
|
||||
/**
|
||||
* \brief Configures an SHA peripheral with the specified parameters.
|
||||
* \param mode Desired value for the SHA mode register (see the datasheet).
|
||||
*/
|
||||
extern void sha_configure(uint32_t mode);
|
||||
|
||||
/**
|
||||
* \brief Enables the selected interrupts sources on a SHA peripheral.
|
||||
* \param sources Bitwise OR of selected interrupt sources.
|
||||
*/
|
||||
extern void sha_enable_it(uint32_t sources);
|
||||
|
||||
/**
|
||||
* \brief Disables the selected interrupts sources on a SHA peripheral.
|
||||
* \param sources Bitwise OR of selected interrupt sources.
|
||||
*/
|
||||
extern void sha_disable_it(uint32_t sources);
|
||||
|
||||
/**
|
||||
* \brief Get the current status register of the given SHA peripheral.
|
||||
* \return SHA status register.
|
||||
*/
|
||||
extern uint32_t sha_get_status(void);
|
||||
|
||||
/**
|
||||
* \brief Set the 32-bit Input Data registers allow to load the data block used for hash processing.
|
||||
* \param data Pointer data block.
|
||||
* \param len 512/1024-bits block size
|
||||
*/
|
||||
extern void sha_set_input(uint32_t * data, uint8_t len);
|
||||
|
||||
/**
|
||||
* \brief Getread the resulting message digest and to write the second part of the message block when the
|
||||
* SHA algorithm is SHA-384 or SHA-512.
|
||||
* \param data pointer to the word that has been encrypted/decrypted..
|
||||
*/
|
||||
extern void sha_get_output(uint32_t * data);
|
||||
|
||||
#endif /* #ifndef _SHA_ */
|
|
@ -0,0 +1,100 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/shdwc.h"
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local Defines
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
struct _bitfield_shdwc_cfgr {
|
||||
uint32_t
|
||||
lpdbcen0: 1,
|
||||
lpdbcen1: 1,
|
||||
rfu2_7: 6,
|
||||
lpdbc: 3,
|
||||
rfu10_15: 5,
|
||||
rttwken: 1,
|
||||
rtcwken: 1,
|
||||
accwken: 1,
|
||||
rxlpwken: 1,
|
||||
rfu20_23: 4,
|
||||
wkupdbc: 3,
|
||||
rfu26_31: 5;
|
||||
};
|
||||
|
||||
union _shdwc_cfg {
|
||||
struct _bitfield_shdwc_cfgr bfield;
|
||||
uint32_t uint32_value;
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void shdwc_configure_wakeup_mode(uint32_t config)
|
||||
{
|
||||
union _shdwc_cfg cfg;
|
||||
|
||||
cfg.uint32_value = SHDWC->SHDW_MR;
|
||||
|
||||
cfg.bfield.lpdbcen0 = (config & SHDW_MR_LPDBCEN0_ENABLE) ? 1 : 0;
|
||||
cfg.bfield.lpdbcen1 = (config & SHDW_MR_LPDBCEN1_ENABLE) ? 1 : 0;
|
||||
cfg.bfield.lpdbc = (config & SHDW_MR_LPDBC_Msk) >> SHDW_MR_LPDBC_Pos;
|
||||
cfg.bfield.rttwken = (config & SHDW_MR_RTTWKEN) ? 1 : 0;
|
||||
cfg.bfield.rtcwken = (config & SHDW_MR_RTCWKEN) ? 1 : 0;
|
||||
cfg.bfield.accwken = (config & SHDW_MR_ACCWKEN) ? 1 : 0;
|
||||
cfg.bfield.rxlpwken = (config & SHDW_MR_RXLPWKEN) ? 1 : 0;
|
||||
cfg.bfield.wkupdbc = (config & SHDW_MR_WKUPDBC_Msk) >> SHDW_MR_WKUPDBC_Pos;
|
||||
|
||||
SHDWC->SHDW_MR = cfg.uint32_value;
|
||||
}
|
||||
|
||||
void shdwc_set_wakeup_input(uint32_t input_enable, uint32_t input_type)
|
||||
{
|
||||
uint32_t wuir = (input_enable & 0x0000FFFF) | (input_type & 0xFFFF0000);
|
||||
|
||||
SHDWC->SHDW_WUIR |= wuir;
|
||||
}
|
||||
|
||||
void shdwc_do_shutdown(void)
|
||||
{
|
||||
SHDWC->SHDW_CR = SHDW_CR_KEY_PASSWD | SHDW_CR_SHDW;
|
||||
}
|
||||
|
||||
uint32_t shdwc_get_status(void)
|
||||
{
|
||||
return SHDWC->SHDW_SR;
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _SHDWC_H
|
||||
#define _SHDWC_H
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Global functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Configure the Shutdown Mode Register
|
||||
*/
|
||||
extern void shdwc_configure_wakeup_mode(uint32_t config);
|
||||
|
||||
/**
|
||||
* \brief Configure the Shutdown Wake-up Input Register
|
||||
*
|
||||
* \param input_enable, WKUPEN0-WKUPEN15: define the corresponding
|
||||
* wake-up input.
|
||||
* \param input_type, WKUPT0-WKUPT15: define falling or rising edge
|
||||
* on wake-up input.
|
||||
*/
|
||||
extern void shdwc_set_wakeup_input(uint32_t input_enable,
|
||||
uint32_t input_type);
|
||||
|
||||
/**
|
||||
* \brief Launch the ShutDown
|
||||
*/
|
||||
extern void shdwc_do_shutdown(void);
|
||||
|
||||
/**
|
||||
* \brief Get Status
|
||||
* \return Contents of the Shutdown Status Register
|
||||
*/
|
||||
extern uint32_t shdwc_get_status(void);
|
||||
|
||||
#endif //#ifndef _SHDWC_H
|
|
@ -0,0 +1,451 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \addtogroup spi_module Working with SPI
|
||||
* \section Purpose
|
||||
* The SPI driver provides the interface to configure and use the SPI
|
||||
* peripheral.
|
||||
*
|
||||
* The Serial Peripheral Interface (SPI) circuit is a synchronous serial
|
||||
* data link that provides communication with external devices in Master
|
||||
* or Slave Mode.
|
||||
*
|
||||
* \section Usage
|
||||
* To use the SPI, the user has to follow these few steps:
|
||||
* -# Enable the SPI pins required by the application (see pio.h).
|
||||
* -# Configure the SPI using the \ref spi_configure(). This enables the
|
||||
* peripheral clock. The mode register is loaded with the given value.
|
||||
* -# Configure all the necessary chip selects with \ref spi_configure_npcs().
|
||||
* -# Enable the SPI by calling \ref spi_enable().
|
||||
* -# Send/receive data using \ref spi_write() and \ref
|
||||
* spi_read(). Note that \ref spi_read()
|
||||
* must be called after \ref spi_write() to retrieve the last value read.
|
||||
* -# Disable the SPI by calling \ref spi_disable().
|
||||
*
|
||||
* For more accurate information, please look at the SPI section of the
|
||||
* Datasheet.
|
||||
*
|
||||
* Related files :\n
|
||||
* \ref spi.c\n
|
||||
* \ref spi.h\n
|
||||
*/
|
||||
/*@{*/
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implementation of Serial Peripheral Interface (SPI) controller.
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
#include "peripherals/spi.h"
|
||||
#include "peripherals/pmc.h"
|
||||
|
||||
#include "io.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Macros
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#define SPI_PCS(npcs) SPI_MR_PCS((~(1 << npcs) & 0xF))
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* local functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static inline uint32_t _spi_compute_scbr(uint32_t bitrate, uint32_t periph_id)
|
||||
{
|
||||
assert(bitrate>0);
|
||||
return SPI_CSR_SCBR(
|
||||
pmc_get_peripheral_clock(periph_id) / (bitrate*1000));
|
||||
}
|
||||
|
||||
static inline uint32_t _spi_compute_dlybs(uint32_t delay, uint32_t periph_id)
|
||||
{
|
||||
uint32_t dlybs =
|
||||
((pmc_get_peripheral_clock(periph_id)/1000000u) * delay) / 100;
|
||||
return SPI_CSR_DLYBS(dlybs);
|
||||
}
|
||||
|
||||
static inline uint32_t _spi_compute_dlybct(uint32_t delay, uint32_t periph_id)
|
||||
{
|
||||
uint32_t dlybct =
|
||||
((pmc_get_peripheral_clock(periph_id)/31250u) * delay) / 100;
|
||||
return SPI_CSR_DLYBCT(dlybct);
|
||||
}
|
||||
|
||||
static inline uint32_t _spi_is_master(Spi* spi)
|
||||
{
|
||||
return (spi->SPI_MR & SPI_MR_MSTR);
|
||||
}
|
||||
|
||||
static inline uint32_t _spi_is_variable_ps(Spi* spi)
|
||||
{
|
||||
return (spi->SPI_MR & SPI_MR_PS);
|
||||
}
|
||||
|
||||
static void _spi_write_dummy(Spi* spi)
|
||||
{
|
||||
if (_spi_is_master(spi)) {
|
||||
writehw(&spi->SPI_TDR, 0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
static void _spi_consume_read(Spi* spi, uint32_t cs)
|
||||
{
|
||||
if (_spi_is_master(spi)) {
|
||||
while(!(spi->SPI_SR & SPI_SR_RDRF));
|
||||
uint16_t value;
|
||||
if ((spi->SPI_CSR[cs] & SPI_CSR_BITS_Msk) < SPI_CSR_BITS_9_BIT) {
|
||||
readb(&spi->SPI_RDR, (uint8_t*)&value);
|
||||
} else {
|
||||
readhw(&spi->SPI_RDR, &value);
|
||||
}
|
||||
(void)value;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_SPI_FIFO
|
||||
|
||||
static void _spi_fifo_clear(Spi* spi, uint32_t fifos)
|
||||
{
|
||||
trace_debug("Spi: Clearing FIFOs\r\n");
|
||||
while (!(spi->SPI_SR & SPI_SR_TXFEF));
|
||||
spi->SPI_CR = fifos & (SPI_CR_RXFCLR | SPI_CR_TXFCLR);
|
||||
}
|
||||
|
||||
static inline void _clear_fifo_control_flags(uint32_t* control_reg)
|
||||
{
|
||||
*control_reg |= SPI_CR_TXFCLR | SPI_CR_RXFCLR | SPI_CR_FIFODIS;
|
||||
}
|
||||
#else
|
||||
#define _clear_fifo_control_flags(dummy) do {} while(0)
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void spi_enable(Spi * spi)
|
||||
{
|
||||
spi->SPI_CR = SPI_CR_SPIEN;
|
||||
}
|
||||
|
||||
void spi_disable(Spi * spi)
|
||||
{
|
||||
spi->SPI_CR = SPI_CR_SPIDIS;
|
||||
}
|
||||
|
||||
void spi_enable_it(Spi * spi, uint32_t dwSources)
|
||||
{
|
||||
spi->SPI_IER = dwSources;
|
||||
}
|
||||
|
||||
void spi_disable_it(Spi * spi, uint32_t dwSources)
|
||||
{
|
||||
spi->SPI_IDR = dwSources;
|
||||
}
|
||||
|
||||
void spi_configure(Spi * spi, uint32_t configuration)
|
||||
{
|
||||
/* Execute a software reset of the SPI twice */
|
||||
spi->SPI_CR = SPI_CR_SWRST;
|
||||
spi->SPI_CR = SPI_CR_SWRST;
|
||||
|
||||
uint32_t control_reg = SPI_CR_SPIDIS;
|
||||
/* Add clear FIFO flags if present */
|
||||
_clear_fifo_control_flags(&control_reg);
|
||||
/* Apply */
|
||||
spi->SPI_CR = control_reg;
|
||||
|
||||
spi->SPI_MR = configuration;
|
||||
}
|
||||
|
||||
void spi_chip_select(Spi * spi, uint8_t cS)
|
||||
{
|
||||
spi->SPI_MR &= ~SPI_MR_PCS_Msk;
|
||||
spi->SPI_MR |= SPI_PCS(cS);
|
||||
}
|
||||
|
||||
void spi_set_mode(Spi * spi, uint32_t dwConfiguration)
|
||||
{
|
||||
spi->SPI_MR = dwConfiguration;
|
||||
}
|
||||
|
||||
void spi_release_cs(Spi * spi)
|
||||
{
|
||||
spi->SPI_CR = SPI_CR_LASTXFER;
|
||||
}
|
||||
|
||||
void spi_configure_cs(Spi * spi, uint32_t cs, uint32_t bitrate,
|
||||
uint32_t delay_dlybs, uint32_t delay_dlybct,
|
||||
uint32_t spi_mode, uint32_t release_on_last)
|
||||
{
|
||||
trace_debug("Spi: configuring chip select %u\r\n", (unsigned int)cs);
|
||||
uint32_t id = get_spi_id_from_addr(spi);
|
||||
assert(id < ID_PERIPH_COUNT);
|
||||
|
||||
bitrate = _spi_compute_scbr(bitrate, id);
|
||||
delay_dlybs = _spi_compute_dlybs(delay_dlybs, id);
|
||||
delay_dlybct = _spi_compute_dlybct(delay_dlybct, id);
|
||||
release_on_last = release_on_last ? SPI_CSR_CSAAT : 0;
|
||||
|
||||
spi->SPI_CSR[cs] = bitrate | delay_dlybs | delay_dlybct
|
||||
| release_on_last | spi_mode;
|
||||
}
|
||||
|
||||
void spi_configure_cs_mode(Spi * spi, uint32_t cs, uint32_t release_on_last)
|
||||
{
|
||||
if (!release_on_last) {
|
||||
spi->SPI_CSR[cs] |= SPI_CSR_CSAAT;
|
||||
} else {
|
||||
spi->SPI_CSR[cs] &= ~SPI_CSR_CSAAT;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t spi_get_status(Spi * spi)
|
||||
{
|
||||
return spi->SPI_SR;
|
||||
}
|
||||
|
||||
uint16_t spi_read(Spi * spi, uint8_t cs)
|
||||
{
|
||||
_spi_write_dummy(spi);
|
||||
while ((spi->SPI_SR & SPI_SR_RDRF) == 0) ;
|
||||
uint16_t value;
|
||||
if ((spi->SPI_CSR[cs] & SPI_CSR_BITS_Msk) < SPI_CSR_BITS_9_BIT) {
|
||||
readb(&spi->SPI_RDR, (uint8_t*)&value);
|
||||
} else {
|
||||
readhw(&spi->SPI_RDR, &value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \details If the SPI is configured to use a fixed peripheral select,
|
||||
* the npcs value is meaningless. Otherwise, it identifies the
|
||||
* component which shall be addressed.
|
||||
*/
|
||||
void spi_write(Spi * spi, uint32_t cs, uint16_t data)
|
||||
{
|
||||
/* Send data */
|
||||
while ((spi->SPI_SR & SPI_SR_TXEMPTY) == 0);
|
||||
if (_spi_is_variable_ps(spi)) {
|
||||
spi->SPI_TDR = data | SPI_PCS(cs);
|
||||
} else {
|
||||
writehw(&spi->SPI_TDR, data);
|
||||
}
|
||||
/* Consume write */
|
||||
_spi_consume_read(spi, cs);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sends last data through a SPI peripheral.
|
||||
*
|
||||
* \details If the SPI is configured to use a fixed peripheral select,
|
||||
* the npcs value is meaningless. Otherwise, it identifies the
|
||||
* component which shall be addressed.
|
||||
*
|
||||
* \param spi Pointer to an Spi instance.
|
||||
* \param dwNpcs Chip select of the component to address (0, 1, 2 or 3).
|
||||
* \param wData Word of data to send.
|
||||
*/
|
||||
void spi_write_last(Spi * spi, uint32_t cs, uint16_t data)
|
||||
{
|
||||
/* Send data */
|
||||
while ((spi->SPI_SR & SPI_SR_TXEMPTY) == 0) ;
|
||||
spi->SPI_TDR = data | SPI_PCS(cs) | SPI_TDR_LASTXFER;
|
||||
/* Consume write to not corrupt FIFO if present (dummy
|
||||
* function if CONFIG_HAV_SPI_FIFO not defined) */
|
||||
_spi_consume_read(spi, cs);
|
||||
}
|
||||
|
||||
uint32_t spi_is_finished(Spi * spi)
|
||||
{
|
||||
return ((spi->SPI_SR & SPI_SR_TXEMPTY) != 0);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_SPI_FIFO
|
||||
|
||||
static void _spi_fifo_set_rx_threshold(Spi* spi, uint8_t rx_thres)
|
||||
{
|
||||
spi->SPI_FMR &= ~SPI_FMR_RXFTHRES_Msk;
|
||||
spi->SPI_FMR |= SPI_FMR_RXFTHRES(rx_thres);
|
||||
}
|
||||
|
||||
static uint32_t _spi_write_stream(Spi *spi, uint32_t chip_select,
|
||||
const void *stream, uint32_t len)
|
||||
{
|
||||
const uint8_t* buffer = stream;
|
||||
uint32_t left = len;
|
||||
|
||||
uint8_t is_ps = _spi_is_variable_ps(spi);
|
||||
uint32_t max_size = is_ps ? sizeof(uint8_t) : sizeof(uint16_t);
|
||||
int32_t fifo_size = get_peripheral_fifo_depth(spi);
|
||||
if (fifo_size < 0)
|
||||
return 0;
|
||||
|
||||
while (left > 0) {
|
||||
if ((spi->SPI_SR & SPI_SR_TDRE) == 0) continue;
|
||||
|
||||
/* Get FIFO free size (int octet) and clamp it */
|
||||
uint32_t buf_size = fifo_size - spi_fifo_tx_size(spi);
|
||||
buf_size = (buf_size > left) ? left : buf_size;
|
||||
|
||||
/* Fill the FIFO as must as possible */
|
||||
while (buf_size >= max_size) {
|
||||
if (is_ps) {
|
||||
spi->SPI_TDR = *(uint8_t*)buffer |
|
||||
SPI_PCS(chip_select);
|
||||
} else {
|
||||
spi->SPI_TDR = *buffer |
|
||||
(*(buffer+1) << 16);
|
||||
}
|
||||
buffer += max_size;
|
||||
left -= max_size;
|
||||
buf_size -= max_size;
|
||||
}
|
||||
if (buf_size >= sizeof(uint8_t)) {
|
||||
writehw(&spi->SPI_TDR, *(uint8_t*)buffer);
|
||||
buffer += sizeof(uint8_t);
|
||||
left -= sizeof(uint8_t);
|
||||
}
|
||||
}
|
||||
trace_debug("Spi (fifo): %u data writen\r\n",
|
||||
(unsigned int)(len-left));
|
||||
return len - left;
|
||||
}
|
||||
|
||||
void spi_fifo_configure(Spi* spi, uint8_t tx_thres,
|
||||
uint8_t rx_thres,
|
||||
uint32_t ready_modes)
|
||||
{
|
||||
/* Disable SPI and activate FIFO */
|
||||
spi->SPI_CR = SPI_CR_SPIDIS | SPI_CR_FIFOEN;
|
||||
|
||||
/* Configure FIFO */
|
||||
spi->SPI_FMR = SPI_FMR_TXFTHRES(tx_thres) | SPI_FMR_RXFTHRES(rx_thres)
|
||||
| ready_modes;
|
||||
|
||||
/* Reenable SPI */
|
||||
spi->SPI_CR = SPI_CR_SPIEN;
|
||||
}
|
||||
|
||||
void spi_fifo_disable(Spi* spi)
|
||||
{
|
||||
uint32_t reg = 0;
|
||||
_clear_fifo_control_flags(®);
|
||||
spi->SPI_CR = reg;
|
||||
}
|
||||
|
||||
uint32_t spi_fifo_rx_size(Spi *spi)
|
||||
{
|
||||
return (spi->SPI_FLR & SPI_FLR_RXFL_Msk) >> SPI_FLR_RXFL_Pos;
|
||||
}
|
||||
|
||||
uint32_t spi_fifo_tx_size(Spi *spi)
|
||||
{
|
||||
return (spi->SPI_FLR & SPI_FLR_TXFL_Msk) >> SPI_FLR_TXFL_Pos;
|
||||
}
|
||||
|
||||
uint32_t spi_read_stream(Spi *spi, uint32_t chip_select,
|
||||
void *stream, uint32_t len)
|
||||
{
|
||||
uint8_t* buffer = stream;
|
||||
uint32_t left = len;
|
||||
|
||||
uint8_t is_master = _spi_is_master(spi);
|
||||
uint32_t max_size = is_master ? sizeof(uint8_t) : sizeof(uint32_t);
|
||||
|
||||
while (left > 0) {
|
||||
uint32_t lenwrite = (left > SPI_FIFO_DEPTH) ?
|
||||
SPI_FIFO_DEPTH : left;
|
||||
|
||||
_spi_fifo_set_rx_threshold(spi, lenwrite);
|
||||
_spi_write_stream(spi, chip_select,
|
||||
stream, lenwrite);
|
||||
|
||||
while (!(spi->SPI_SR & SPI_SR_RXFTHF));
|
||||
|
||||
/* Get FIFO size (in octets) and clamp it */
|
||||
uint32_t buf_size = spi_fifo_rx_size(spi);
|
||||
buf_size = buf_size > left ? left : buf_size;
|
||||
|
||||
/* Fill the buffer as must as possible with four data reads */
|
||||
while (buf_size >= max_size) {
|
||||
if (is_master) {
|
||||
readb(&spi->SPI_RDR, (uint8_t*)buffer);
|
||||
} else {
|
||||
*(uint32_t*)buffer = spi->SPI_RDR;
|
||||
}
|
||||
buffer += max_size;
|
||||
left -= max_size;
|
||||
buf_size -= max_size;
|
||||
}
|
||||
/* Add tail data if stream is not 4 octet aligned */
|
||||
if (buf_size >= sizeof(uint16_t)) {
|
||||
/* two data read */
|
||||
readhw(&spi->SPI_RDR, (uint16_t*)buffer);
|
||||
left -= sizeof(uint16_t);
|
||||
buffer += sizeof(uint16_t);
|
||||
buf_size -= sizeof(uint16_t);
|
||||
}
|
||||
if (buf_size >= sizeof(uint8_t)) {
|
||||
/* two data read */
|
||||
readb(&spi->SPI_RDR, (uint8_t*)buffer);
|
||||
left -= sizeof(uint8_t);
|
||||
buffer += sizeof(uint8_t);
|
||||
}
|
||||
}
|
||||
trace_debug("Spi (fifo): %u data read\r\n",
|
||||
(unsigned int)(len-left));
|
||||
return len - left;
|
||||
}
|
||||
|
||||
uint32_t spi_write_stream(Spi *spi, uint32_t chip_select,
|
||||
const void *stream, uint32_t len)
|
||||
{
|
||||
uint32_t consumed = _spi_write_stream(spi, chip_select, stream, len);
|
||||
_spi_fifo_clear(spi, SPI_CR_RXFCLR);
|
||||
return consumed;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,214 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Interface for Serial Peripheral Interface (SPI) controller.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _SPI_
|
||||
#define _SPI_
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Macros
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#define SPI_KEEP_CS_OW (0)
|
||||
#define SPI_RELEASE_CS_OW (1)
|
||||
|
||||
/*------------------------------------------------------------------------------ */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Enables a SPI peripheral.
|
||||
*
|
||||
* \param spi Pointer to an Spi instance.
|
||||
*/
|
||||
extern void spi_enable(Spi * spi);
|
||||
|
||||
/**
|
||||
* \brief Disables a SPI peripheral.
|
||||
*
|
||||
* \param spi Pointer to an Spi instance.
|
||||
*/
|
||||
extern void spi_disable(Spi * spi);
|
||||
|
||||
/**
|
||||
* \brief Enables one or more interrupt sources of a SPI peripheral.
|
||||
*
|
||||
* \param spi Pointer to an Spi instance.
|
||||
* \param dwSources Bitwise OR of selected interrupt sources.
|
||||
*/
|
||||
extern void spi_enable_it(Spi * spi, uint32_t dwSources);
|
||||
|
||||
/**
|
||||
* \brief Disables one or more interrupt sources of a SPI peripheral.
|
||||
*
|
||||
* \param spi Pointer to an Spi instance.
|
||||
* \param dwSources Bitwise OR of selected interrupt sources.
|
||||
*/
|
||||
extern void spi_disable_it(Spi * spi, uint32_t dwSources);
|
||||
|
||||
/**
|
||||
* \brief Configures a SPI peripheral as specified. The configuration
|
||||
* can be computed
|
||||
* using several macros (see \ref spi_configuration_macros).
|
||||
*
|
||||
* \param spi Pointer to an Spi instance.
|
||||
* \param dwConfiguration Value of the SPI configuration register.
|
||||
*/
|
||||
extern void spi_configure(Spi * spi, uint32_t configuration);
|
||||
|
||||
/**
|
||||
* \brief Configures SPI Mode Register.
|
||||
*
|
||||
* \param spi Pointer to an Spi instance.
|
||||
* \param dwConfiguration Value of the SPI mode register.
|
||||
*/
|
||||
extern void spi_set_mode(Spi * spi, uint32_t dwConfiguration);
|
||||
|
||||
/**
|
||||
* \brief Configures SPI chip select.
|
||||
*
|
||||
* \param spi Pointer to an Spi instance.
|
||||
* \param cS Chip select of NPSCx.
|
||||
*/
|
||||
extern void spi_chip_select(Spi * spi, uint8_t cS);
|
||||
|
||||
/**
|
||||
* \brief Configures SPI to release last used CS line.
|
||||
*
|
||||
* \param spi Pointer to an Spi instance.
|
||||
*/
|
||||
extern void spi_release_cs(Spi * spi);
|
||||
|
||||
/**
|
||||
* \brief Configures a chip select of a SPI peripheral.
|
||||
*
|
||||
* \param spi Pointer to an Spi instance.
|
||||
* \param cs Chip select to configure (0, 1, 2 or 3).
|
||||
* \param bitrate
|
||||
* \param delay_dlybs
|
||||
* \param delay_dlybct
|
||||
* \param spi_mode
|
||||
* \param release_on_last
|
||||
*/
|
||||
extern void spi_configure_cs(Spi * spi, uint32_t cs,uint32_t bitrate,
|
||||
uint32_t delay_dlybs, uint32_t delay_dlybct,
|
||||
uint32_t spi_mode, uint32_t release_on_last);
|
||||
|
||||
/**
|
||||
* \brief Configures a chip select active mode of a SPI peripheral.
|
||||
*
|
||||
* \param spi Pointer to an Spi instance.
|
||||
* \param cs Chip select to configure (0, 1, 2 or 3).
|
||||
* \param release_on_last CS controlled by last transfer.
|
||||
* spi_release_cs() is used to deactive CS.
|
||||
*/
|
||||
extern void spi_configure_cs_mode(Spi * spi, uint32_t cs,
|
||||
uint32_t release_on_last);
|
||||
|
||||
/**
|
||||
* \brief Reads one data from SPI peripheral with a dummy write.
|
||||
*
|
||||
* \param spi Pointer to an Spi instance.
|
||||
*
|
||||
* \return readed data.
|
||||
*/
|
||||
|
||||
extern uint16_t spi_read(Spi * spi, uint8_t cs);
|
||||
|
||||
/**
|
||||
* \brief Sends data through a SPI peripheral consuming reads.
|
||||
*
|
||||
*
|
||||
* \param spi Pointer to an Spi instance.
|
||||
* \param cs Chip select of the component to address (0, 1, 2 or 3).
|
||||
* \param data Word of data to send.
|
||||
*/
|
||||
extern void spi_write(Spi * spi, uint32_t cs, uint16_t data);
|
||||
extern void spi_write_last(Spi * spi, uint32_t cs, uint16_t data);
|
||||
|
||||
/**
|
||||
* \brief Get the current status register of the given SPI peripheral.
|
||||
*
|
||||
* \note This resets the internal value of the status register, so further
|
||||
* read may yield different values.
|
||||
*
|
||||
* \param spi Pointer to a Spi instance.
|
||||
* \return SPI status register.
|
||||
*/
|
||||
extern uint32_t spi_get_status(Spi * spi);
|
||||
|
||||
|
||||
/**
|
||||
* \brief Check if SPI transfer finish.
|
||||
*
|
||||
* \param spi Pointer to an Spi instance.
|
||||
*
|
||||
* \return Returns 1 if there is no pending write operation on the SPI;
|
||||
* otherwise returns 0.
|
||||
*/
|
||||
|
||||
extern uint32_t spi_is_finished(Spi * spi);
|
||||
|
||||
#ifdef CONFIG_HAVE_SPI_FIFO
|
||||
extern void spi_fifo_configure(Spi* spi, uint8_t tx_thres,
|
||||
uint8_t rx_thres,
|
||||
uint32_t ready_modes);
|
||||
extern void spi_fifo_disable(Spi* spi);
|
||||
|
||||
extern uint32_t spi_fifo_rx_size(Spi *spi);
|
||||
extern uint32_t spi_fifo_tx_size(Spi *spi);
|
||||
|
||||
extern uint32_t spi_read_stream(Spi *spi, uint32_t chip_select,
|
||||
void *stream, uint32_t len);
|
||||
extern uint32_t spi_write_stream(Spi *spi, uint32_t chip_select,
|
||||
const void *stream, uint32_t len);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* #ifndef _SPI_ */
|
|
@ -0,0 +1,368 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include "peripherals/aic.h"
|
||||
#ifdef CONFIG_HAVE_FLEXCOM
|
||||
#include "peripherals/flexcom.h"
|
||||
#endif
|
||||
#include "peripherals/pmc.h"
|
||||
#include "peripherals/spid.h"
|
||||
#include "peripherals/spi.h"
|
||||
#include "peripherals/xdmac.h"
|
||||
#include "peripherals/xdmad.h"
|
||||
#include "peripherals/l2cc.h"
|
||||
|
||||
#include "cortex-a/cp15.h"
|
||||
|
||||
#include "trace.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#define SPID_ATTRIBUTE_MASK (SPI_MR_PS | SPI_MR_MODFDIS | SPI_MR_MSTR | SPI_MR_WDRBT)
|
||||
#define SPID_DMA_THRESHOLD 16
|
||||
|
||||
static uint32_t _garbage = 0;
|
||||
|
||||
static void _spid_xdmad_callback_wrapper(struct _xdmad_channel *channel,
|
||||
void *arg)
|
||||
{
|
||||
trace_debug("SPID DMA Transfert Finished\r\n");
|
||||
struct _spi_desc* spid = (struct _spi_desc*) arg;
|
||||
|
||||
xdmad_free_channel(channel);
|
||||
|
||||
if (spid->region_start && spid->region_end) {
|
||||
l2cc_invalidate_region(spid->region_start, spid->region_end);
|
||||
}
|
||||
|
||||
if (spid && spid->callback)
|
||||
spid->callback(spid, spid->cb_args);
|
||||
}
|
||||
|
||||
static void _spid_xdmad_cleanup_callback(struct _xdmad_channel *channel,
|
||||
void *arg)
|
||||
{
|
||||
xdmad_free_channel(channel);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_SPI_FIFO
|
||||
static void spid_fifo_error(void)
|
||||
{
|
||||
trace_error("Fifo pointer error encountered !!\r\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
void spid_configure(struct _spi_desc* desc)
|
||||
{
|
||||
uint32_t id = get_spi_id_from_addr(desc->addr);
|
||||
|
||||
#ifdef CONFIG_HAVE_FLEXCOM
|
||||
Flexcom* flexcom = get_flexcom_addr_from_id(id);
|
||||
if (flexcom) {
|
||||
flexcom_select(flexcom, FLEX_MR_OPMODE_SPI);
|
||||
}
|
||||
#endif
|
||||
/* Enable SPI early otherwise FIFO configuration won't be applied */
|
||||
pmc_enable_peripheral(id);
|
||||
if (desc->transfert_mode == SPID_MODE_FIFO) {
|
||||
desc->attributes &= ~SPI_MR_WDRBT;
|
||||
}
|
||||
spi_configure(desc->addr, (desc->attributes & SPID_ATTRIBUTE_MASK) | SPI_MR_MSTR);
|
||||
spi_chip_select(desc->addr, desc->chip_select);
|
||||
spi_configure_cs(desc->addr, desc->chip_select, desc->bitrate,
|
||||
desc->dlybs, desc->dlybct, desc->spi_mode, 0);
|
||||
#ifdef CONFIG_HAVE_SPI_FIFO
|
||||
if (desc->transfert_mode == SPID_MODE_FIFO) {
|
||||
spi_fifo_configure(desc->addr, SPI_FIFO_DEPTH, SPI_FIFO_DEPTH,
|
||||
SPI_FMR_TXRDYM_ONE_DATA | SPI_FMR_RXRDYM_ONE_DATA);
|
||||
spi_enable_it(desc->addr, SPI_IER_TXFPTEF | SPI_IER_RXFPTEF);
|
||||
aic_set_source_vector(id, spid_fifo_error);
|
||||
aic_enable(id);
|
||||
}
|
||||
#endif
|
||||
(void)spi_get_status(desc->addr);
|
||||
|
||||
spi_enable(desc->addr);
|
||||
}
|
||||
|
||||
void spid_begin_transfert(struct _spi_desc* desc)
|
||||
{
|
||||
spi_chip_select(desc->addr, desc->chip_select);
|
||||
spi_configure_cs_mode(desc->addr, desc->chip_select, SPI_KEEP_CS_OW);
|
||||
}
|
||||
|
||||
static void _spid_init_dma_write_channel(const struct _spi_desc* desc,
|
||||
struct _xdmad_channel** channel,
|
||||
struct _xdmad_cfg* cfg)
|
||||
{
|
||||
assert(cfg);
|
||||
assert(channel);
|
||||
|
||||
uint32_t id = get_spi_id_from_addr(desc->addr);
|
||||
|
||||
memset(cfg, 0x0, sizeof(*cfg));
|
||||
|
||||
*channel =
|
||||
xdmad_allocate_channel(XDMAD_PERIPH_MEMORY, id);
|
||||
assert(*channel);
|
||||
|
||||
xdmad_prepare_channel(*channel);
|
||||
cfg->cfg.uint32_value = XDMAC_CC_TYPE_PER_TRAN
|
||||
| XDMAC_CC_DSYNC_MEM2PER
|
||||
| XDMAC_CC_MEMSET_NORMAL_MODE
|
||||
| XDMAC_CC_CSIZE_CHK_1
|
||||
| XDMAC_CC_DWIDTH_BYTE
|
||||
| XDMAC_CC_DIF_AHB_IF1
|
||||
| XDMAC_CC_SIF_AHB_IF0
|
||||
| XDMAC_CC_DAM_FIXED_AM;
|
||||
|
||||
cfg->dest_addr = (void*)&desc->addr->SPI_TDR;
|
||||
}
|
||||
|
||||
static void _spid_init_dma_read_channel(const struct _spi_desc* desc,
|
||||
struct _xdmad_channel** channel,
|
||||
struct _xdmad_cfg* cfg)
|
||||
{
|
||||
assert(cfg);
|
||||
assert(channel);
|
||||
|
||||
uint32_t id = get_spi_id_from_addr(desc->addr);
|
||||
|
||||
memset(cfg, 0x0, sizeof(*cfg));
|
||||
|
||||
*channel =
|
||||
xdmad_allocate_channel(id, XDMAD_PERIPH_MEMORY);
|
||||
assert(*channel);
|
||||
|
||||
xdmad_prepare_channel(*channel);
|
||||
cfg->cfg.uint32_value = XDMAC_CC_TYPE_PER_TRAN
|
||||
| XDMAC_CC_DSYNC_PER2MEM
|
||||
| XDMAC_CC_MEMSET_NORMAL_MODE
|
||||
| XDMAC_CC_CSIZE_CHK_1
|
||||
| XDMAC_CC_DWIDTH_BYTE
|
||||
| XDMAC_CC_DIF_AHB_IF0
|
||||
| XDMAC_CC_SIF_AHB_IF1
|
||||
| XDMAC_CC_SAM_FIXED_AM;
|
||||
|
||||
cfg->src_addr = (void*)&desc->addr->SPI_RDR;
|
||||
}
|
||||
|
||||
static void _spid_dma_write(const struct _spi_desc* desc,
|
||||
const struct _buffer* buffer)
|
||||
{
|
||||
struct _xdmad_channel* w_channel = NULL;
|
||||
struct _xdmad_channel* r_channel = NULL;
|
||||
struct _xdmad_cfg w_cfg;
|
||||
struct _xdmad_cfg r_cfg;
|
||||
|
||||
_spid_init_dma_write_channel(desc, &w_channel, &w_cfg);
|
||||
_spid_init_dma_read_channel(desc, &r_channel, &r_cfg);
|
||||
|
||||
w_cfg.cfg.bitfield.sam = XDMAC_CC_SAM_INCREMENTED_AM
|
||||
>> XDMAC_CC_SAM_Pos;
|
||||
w_cfg.src_addr = buffer->data;
|
||||
w_cfg.ublock_size = buffer->size;
|
||||
xdmad_configure_transfer(w_channel, &w_cfg, 0, 0);
|
||||
xdmad_set_callback(w_channel, _spid_xdmad_cleanup_callback,
|
||||
NULL);
|
||||
|
||||
r_cfg.cfg.bitfield.dam = XDMAC_CC_DAM_FIXED_AM
|
||||
>> XDMAC_CC_DAM_Pos;
|
||||
r_cfg.dest_addr = &_garbage;
|
||||
r_cfg.ublock_size = buffer->size;
|
||||
xdmad_configure_transfer(r_channel, &r_cfg, 0, 0);
|
||||
xdmad_set_callback(r_channel, _spid_xdmad_callback_wrapper,
|
||||
(void*)desc);
|
||||
|
||||
l2cc_clean_region(desc->region_start, desc->region_end);
|
||||
|
||||
xdmad_start_transfer(w_channel);
|
||||
xdmad_start_transfer(r_channel);
|
||||
}
|
||||
|
||||
static void _spid_dma_read(const struct _spi_desc* desc,
|
||||
struct _buffer* buffer)
|
||||
{
|
||||
struct _xdmad_channel* w_channel = NULL;
|
||||
struct _xdmad_channel* r_channel = NULL;
|
||||
struct _xdmad_cfg w_cfg;
|
||||
struct _xdmad_cfg r_cfg;
|
||||
|
||||
_spid_init_dma_write_channel(desc, &w_channel, &w_cfg);
|
||||
_spid_init_dma_read_channel(desc, &r_channel, &r_cfg);
|
||||
|
||||
w_cfg.cfg.bitfield.sam = XDMAC_CC_SAM_FIXED_AM
|
||||
>> XDMAC_CC_SAM_Pos;
|
||||
w_cfg.src_addr = buffer->data;
|
||||
w_cfg.ublock_size = buffer->size;
|
||||
w_cfg.block_size = 0;
|
||||
xdmad_configure_transfer(w_channel, &w_cfg, 0, 0);
|
||||
xdmad_set_callback(w_channel, _spid_xdmad_cleanup_callback, NULL);
|
||||
|
||||
r_cfg.cfg.bitfield.dam = XDMAC_CC_DAM_INCREMENTED_AM
|
||||
>> XDMAC_CC_DAM_Pos;
|
||||
r_cfg.dest_addr = buffer->data;
|
||||
r_cfg.ublock_size = buffer->size;
|
||||
xdmad_configure_transfer(r_channel, &r_cfg, 0, 0);
|
||||
xdmad_set_callback(r_channel, _spid_xdmad_callback_wrapper,
|
||||
(void*)desc);
|
||||
|
||||
l2cc_clean_region(desc->region_start, desc->region_end);
|
||||
|
||||
xdmad_start_transfer(w_channel);
|
||||
xdmad_start_transfer(r_channel);
|
||||
}
|
||||
|
||||
uint32_t spid_transfert(struct _spi_desc* desc, struct _buffer* rx,
|
||||
struct _buffer* tx, spid_callback_t cb,
|
||||
void* user_args)
|
||||
{
|
||||
Spi* spi = desc->addr;
|
||||
uint32_t i = 0;
|
||||
|
||||
desc->callback = cb;
|
||||
desc->cb_args = user_args;
|
||||
|
||||
if (mutex_try_lock(&desc->mutex)) {
|
||||
return SPID_ERROR_LOCK;
|
||||
}
|
||||
|
||||
switch (desc->transfert_mode) {
|
||||
case SPID_MODE_POLLING:
|
||||
if (tx) {
|
||||
for (i = 0; i < tx->size; ++i) {
|
||||
spi_write(spi, desc->chip_select, tx->data[i]);
|
||||
}
|
||||
}
|
||||
if (rx) {
|
||||
for (i = 0; i < rx->size; ++i) {
|
||||
rx->data[i] = spi_read(spi, desc->chip_select);
|
||||
}
|
||||
}
|
||||
mutex_free(&desc->mutex);
|
||||
if (cb)
|
||||
cb(desc, user_args);
|
||||
break;
|
||||
case SPID_MODE_DMA:
|
||||
if (tx) {
|
||||
if (tx->size < SPID_DMA_THRESHOLD) {
|
||||
for (i = 0; i < tx->size; ++i) {
|
||||
spi_write(spi, desc->chip_select, tx->data[i]);
|
||||
}
|
||||
if (!rx) {
|
||||
if (cb)
|
||||
cb(desc, user_args);
|
||||
mutex_free(&desc->mutex);
|
||||
}
|
||||
} else {
|
||||
desc->region_start = (uint32_t)tx->data;
|
||||
desc->region_end = desc->region_start
|
||||
+ tx->size;
|
||||
_spid_dma_write(desc, tx);
|
||||
if (rx) {
|
||||
spid_wait_transfert(desc);
|
||||
mutex_lock(&desc->mutex);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rx) {
|
||||
if (rx->size < SPID_DMA_THRESHOLD) {
|
||||
for (i = 0; i < rx->size; ++i) {
|
||||
rx->data[i] = spi_read(spi, desc->chip_select);
|
||||
}
|
||||
if (cb)
|
||||
cb(desc, user_args);
|
||||
mutex_free(&desc->mutex);
|
||||
} else {
|
||||
desc->region_start = (uint32_t)rx->data;
|
||||
desc->region_end = desc->region_start
|
||||
+ rx->size;
|
||||
_spid_dma_read(desc, rx);
|
||||
}
|
||||
}
|
||||
break;
|
||||
#ifdef CONFIG_HAVE_SPI_FIFO
|
||||
case SPID_MODE_FIFO:
|
||||
if (tx) {
|
||||
spi_write_stream(spi, desc->chip_select,
|
||||
tx->data, tx->size);
|
||||
}
|
||||
if (rx) {
|
||||
spi_read_stream(spi, desc->chip_select,
|
||||
rx->data, rx->size);
|
||||
}
|
||||
mutex_free(&desc->mutex);
|
||||
if (cb)
|
||||
cb(desc, user_args);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
trace_debug("Unkown mode");
|
||||
}
|
||||
|
||||
return SPID_SUCCESS;
|
||||
}
|
||||
|
||||
void spid_finish_transfert_callback(struct _spi_desc* desc, void* user_args)
|
||||
{
|
||||
(void)user_args;
|
||||
spid_finish_transfert(desc);
|
||||
}
|
||||
|
||||
void spid_finish_transfert(struct _spi_desc* desc)
|
||||
{
|
||||
spi_release_cs(desc->addr);
|
||||
mutex_free(&desc->mutex);
|
||||
}
|
||||
|
||||
void spid_close(const struct _spi_desc* desc)
|
||||
{
|
||||
uint32_t id = get_spi_id_from_addr(desc->addr);
|
||||
#ifdef CONFIG_HAVE_SPI_FIFO
|
||||
spi_fifo_disable(desc->addr);
|
||||
spi_disable_it(desc->addr, SPI_IER_TXFPTEF | SPI_IER_RXFPTEF);
|
||||
aic_disable(id);
|
||||
#endif
|
||||
spi_disable(desc->addr);
|
||||
pmc_disable_peripheral(id);
|
||||
}
|
||||
|
||||
uint32_t spid_is_busy(const struct _spi_desc* desc)
|
||||
{
|
||||
return mutex_is_locked(&desc->mutex);
|
||||
}
|
||||
|
||||
void spid_wait_transfert(const struct _spi_desc* desc)
|
||||
{
|
||||
while (mutex_is_locked(&desc->mutex));
|
||||
}
|
|
@ -0,0 +1,101 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#ifndef SPID_HEADER__
|
||||
#define SPID_HEADER__
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Header
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "mutex.h"
|
||||
#include "io.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Types
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#define SPID_SUCCESS (0)
|
||||
#define SPID_INVALID_ID (1)
|
||||
#define SPID_INVALID_BITRATE (2)
|
||||
#define SPID_ERROR_LOCK (3)
|
||||
|
||||
#define SPID_NO_CALLBACK ((spid_callback_t)0)
|
||||
|
||||
struct _spi_desc;
|
||||
|
||||
typedef void (*spid_callback_t)(struct _spi_desc* spid, void* args);
|
||||
|
||||
enum _spid_trans_mode
|
||||
{
|
||||
SPID_MODE_POLLING,
|
||||
SPID_MODE_FIFO,
|
||||
SPID_MODE_DMA
|
||||
};
|
||||
|
||||
struct _spi_desc
|
||||
{
|
||||
Spi* addr;
|
||||
uint32_t bitrate;
|
||||
uint32_t attributes;
|
||||
uint8_t dlybs;
|
||||
uint8_t dlybct;
|
||||
uint8_t chip_select;
|
||||
uint8_t spi_mode;
|
||||
uint8_t transfert_mode;
|
||||
/* implicit internal padding is mandatory here */
|
||||
spid_callback_t callback;
|
||||
void* cb_args;
|
||||
mutex_t mutex;
|
||||
uint32_t region_start;
|
||||
uint32_t region_end;
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
extern void spid_configure(struct _spi_desc* desc);
|
||||
|
||||
extern void spid_begin_transfert(struct _spi_desc* desc);
|
||||
|
||||
extern uint32_t spid_transfert(struct _spi_desc* desc, struct _buffer* rx,
|
||||
struct _buffer* tx, spid_callback_t cb,
|
||||
void* user_args);
|
||||
extern void spid_finish_transfert(struct _spi_desc* desc);
|
||||
extern void spid_finish_transfert_callback(struct _spi_desc* desc,
|
||||
void* user_arg);
|
||||
extern void spid_close(const struct _spi_desc* desc);
|
||||
|
||||
extern uint32_t spid_is_busy(const struct _spi_desc* desc);
|
||||
extern void spid_wait_transfert(const struct _spi_desc* desc);
|
||||
|
||||
#endif /* SPID_HEADER__ */
|
|
@ -0,0 +1,228 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \addtogroup tc_module
|
||||
* \section Purpose
|
||||
* The TC driver provides the Interface to configure the Timer Counter (TC).
|
||||
*
|
||||
* \section Usage
|
||||
* <ul>
|
||||
* <li> Optionally, use tc_find_mck_divisor() to let the program find the best
|
||||
* TCCLKS field value automatically.</li>
|
||||
* <li> Configure a Timer Counter in the desired mode using tc_configure().</li>
|
||||
* <li> Start or stop the timer clock using tc_start() and tc_stop().</li>
|
||||
* </li>
|
||||
* </ul>
|
||||
* For more accurate information, please look at the TC section of the Datasheet.
|
||||
*
|
||||
* Related files :\n
|
||||
* \ref tc.c\n
|
||||
* \ref tc.h.\n
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \section Purpose
|
||||
*
|
||||
* Interface for configuring and using Timer Counter (TC) peripherals.
|
||||
*
|
||||
* \section Usage
|
||||
* -# Optionally, use tc_find_mck_divisor() to let the program find the best
|
||||
* TCCLKS field value automatically.
|
||||
* -# Configure a Timer Counter in the desired mode using tc_configure().
|
||||
* -# Start or stop the timer clock using tc_start() and tc_stop().
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implementation of Timer Counter (TC).
|
||||
*
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/tc.h"
|
||||
#include "peripherals/pmc.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Global functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Configures a Timer Counter Channel
|
||||
*
|
||||
* Configures a Timer Counter to operate in the given mode. Timer is stopped
|
||||
* after configuration and must be restarted with tc_start(). All the
|
||||
* interrupts of the timer are also disabled.
|
||||
*
|
||||
* \param pTc Pointer to a Tc instance.
|
||||
* \param channel Channel number.
|
||||
* \param mode Operating mode (TC_CMR value).
|
||||
*/
|
||||
void tc_configure(Tc * pTc, uint32_t channel, uint32_t mode)
|
||||
{
|
||||
volatile TcChannel *pTcCh;
|
||||
|
||||
assert(channel <
|
||||
(sizeof (pTc->TC_CHANNEL) / sizeof (pTc->TC_CHANNEL[0])));
|
||||
pTcCh = pTc->TC_CHANNEL + channel;
|
||||
|
||||
/* Disable TC clock */
|
||||
pTcCh->TC_CCR = TC_CCR_CLKDIS;
|
||||
|
||||
/* Disable interrupts */
|
||||
pTcCh->TC_IDR = 0xFFFFFFFF;
|
||||
|
||||
/* Clear status register */
|
||||
pTcCh->TC_SR;
|
||||
|
||||
/* Set mode */
|
||||
pTcCh->TC_CMR = mode;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reset and Start the TC Channel
|
||||
*
|
||||
* Enables the timer clock and performs a software reset to start the counting.
|
||||
*
|
||||
* \param pTc Pointer to a Tc instance.
|
||||
* \param channel Channel number.
|
||||
*/
|
||||
void tc_start(Tc * pTc, uint32_t channel)
|
||||
{
|
||||
volatile TcChannel *pTcCh;
|
||||
|
||||
assert(channel <
|
||||
(sizeof (pTc->TC_CHANNEL) / sizeof (pTc->TC_CHANNEL[0])));
|
||||
|
||||
pTcCh = pTc->TC_CHANNEL + channel;
|
||||
pTcCh->TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG;
|
||||
pTcCh->TC_IER = TC_IER_COVFS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Stop TC Channel
|
||||
*
|
||||
* Disables the timer clock, stopping the counting.
|
||||
*
|
||||
* \param pTc Pointer to a Tc instance.
|
||||
* \param channel Channel number.
|
||||
*/
|
||||
void tc_stop(Tc * pTc, uint32_t channel)
|
||||
{
|
||||
volatile TcChannel *pTcCh;
|
||||
|
||||
assert(channel <
|
||||
(sizeof (pTc->TC_CHANNEL) / sizeof (pTc->TC_CHANNEL[0])));
|
||||
|
||||
pTcCh = pTc->TC_CHANNEL + channel;
|
||||
pTcCh->TC_CCR = TC_CCR_CLKDIS;
|
||||
pTcCh->TC_IDR = TC_IER_COVFS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enables TC channel interrupts
|
||||
*
|
||||
* \param tc Pointer to Tc instance
|
||||
* \param channel Channel number
|
||||
* \param mask mask of interrupts to enable
|
||||
*/
|
||||
void tc_enable_it(Tc* tc, uint32_t channel, uint32_t mask)
|
||||
{
|
||||
assert(channel < (sizeof (tc->TC_CHANNEL) / sizeof (tc->TC_CHANNEL[0])));
|
||||
tc->TC_CHANNEL[channel].TC_IER = mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Find best MCK divisor
|
||||
*
|
||||
* Finds the best MCK divisor given the timer frequency and MCK. The result
|
||||
* is guaranteed to satisfy the following equation:
|
||||
* \code
|
||||
* (MCK / (DIV * 65536)) <= freq <= (MCK / DIV)
|
||||
* \endcode
|
||||
* with DIV being the highest possible value.
|
||||
*
|
||||
* \param freq Desired timer freq.
|
||||
* \param div Divisor value.
|
||||
* \param tc_clks TCCLKS field value for divisor.
|
||||
*
|
||||
* \return 1 if a proper divisor has been found, otherwise 0.
|
||||
*/
|
||||
uint32_t tc_find_mck_divisor (uint32_t freq, uint32_t * div,
|
||||
uint32_t * tc_clks)
|
||||
{
|
||||
const uint32_t periph_clock = pmc_get_peripheral_clock(ID_TC0);
|
||||
const uint32_t available_freqs[5] = {periph_clock >> 1, periph_clock >> 3, periph_clock >> 5, periph_clock >> 7, 32768};
|
||||
|
||||
int i = 0;
|
||||
for (i = 0; i < 5; ++i)
|
||||
{
|
||||
uint32_t tmp = freq << 1;
|
||||
if (tmp > available_freqs[i])
|
||||
break;
|
||||
}
|
||||
|
||||
i = (i == 5 ? i-1 : i);
|
||||
|
||||
/* Store results */
|
||||
if (div) {
|
||||
*div = periph_clock / available_freqs[i];
|
||||
}
|
||||
if (tc_clks) {
|
||||
*tc_clks = i;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint32_t tc_get_status(Tc* tc, uint32_t channel_num)
|
||||
{
|
||||
return tc->TC_CHANNEL[channel_num].TC_SR;
|
||||
}
|
||||
|
||||
|
||||
void tc_trigger_on_freq(Tc* tc, uint32_t channel_num, uint32_t freq)
|
||||
{
|
||||
uint32_t div = 0;
|
||||
uint32_t tcclks = 0;
|
||||
uint32_t tc_id = get_tc_id_from_addr(tc);
|
||||
TcChannel* channel = &tc->TC_CHANNEL[channel_num];
|
||||
|
||||
tc_find_mck_divisor(freq, &div, &tcclks);
|
||||
tc_configure(tc, channel_num, tcclks | TC_CMR_CPCTRG);
|
||||
channel->TC_RC = (pmc_get_peripheral_clock(tc_id) / div) / freq;
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* \section Purpose
|
||||
*
|
||||
* Interface for configuring and using Timer Counter (TC) peripherals.
|
||||
*
|
||||
* \section Usage
|
||||
* -# Optionally, use tc_find_mck_divisor() to let the program find the best
|
||||
* TCCLKS field value automatically.
|
||||
* -# Configure a Timer Counter in the desired mode using tc_configure().
|
||||
* -# Start or stop the timer clock using tc_start() and tc_stop().
|
||||
*/
|
||||
|
||||
#ifndef _TC_
|
||||
#define _TC_
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Global functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void tc_configure (Tc* pTc, uint32_t channel, uint32_t mode);
|
||||
extern void tc_start (Tc * pTc, uint32_t channel);
|
||||
extern void tc_stop (Tc * pTc, uint32_t channel);
|
||||
extern void tc_enable_it(Tc* tc, uint32_t channel, uint32_t mask);
|
||||
extern uint32_t tc_find_mck_divisor (uint32_t freq, uint32_t* div, uint32_t * tc_clks);
|
||||
extern uint32_t tc_get_status(Tc* tc, uint32_t channel_num);
|
||||
extern void tc_trigger_on_freq(Tc* tc, uint32_t channel_num, uint32_t freq);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* #ifndef _TC_ */
|
|
@ -0,0 +1,164 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \addtogroup tdes_module Working with TDES
|
||||
* \ingroup peripherals_module
|
||||
* The TDES driver provides the interface to configure and use the TDES
|
||||
* peripheral.
|
||||
* \n
|
||||
*
|
||||
* The Data Encryption Standard (DES) and the Triple Data Encryption Algorithm
|
||||
* (TDES) specify FIPS-approved cryptographic algorithms that can be used to
|
||||
* protect electronic data.
|
||||
* The TDES bit in the TDES Mode Register (TDES_MR) is used to select either the
|
||||
* single DES or the Triple DES mode (make use of the tdes_configure()
|
||||
* function).
|
||||
*
|
||||
* The DES uses 64-bit cryptographic keys to encrypt and decrypt 64-bit data
|
||||
* blocks. Input data can be fed calling tdes_set_input().
|
||||
* The 64-bit key is defined in the Key 1 Word Registers (TDES_KEY1WRx) and set
|
||||
* by tdes_write_key1().
|
||||
*
|
||||
* The Triple DES key consists in three DES keys, which set is also referred to
|
||||
* as a key bundle. These three 64-bit keys are defined, respectively, in the
|
||||
* Key 1, 2 and 3 Word Registers (TDES_KEY1WRx, TDES_KEY2WRx and TDES_KEY3WRx).
|
||||
* In Triple DES mode (TDES_MR:TDESMOD set to 1), the TDES_MR:KEYMOD bit is used
|
||||
* to select either the two- or three-key algorithm.
|
||||
*
|
||||
* In order to perform TDES encryption/decryption, the user has to follow these
|
||||
* few steps:
|
||||
* <ul>
|
||||
* <li> A software-triggered hardware reset of the TDES interface is performed
|
||||
* by tdes_soft_reset().</li>
|
||||
* <li> Configure TDES algorithm mode, key mode, start mode and operation mode
|
||||
* by means of tdes_configure().</li>
|
||||
* <li> Set DES keys with function tdes_write_key1(), tdes_write_key2(), and
|
||||
* tdes_write_key3().</li>
|
||||
* <li> To start encrypting or decrypting call tdes_start().</li>
|
||||
* <li> Retrieve the encryption or decryption result by means of
|
||||
* tdes_get_output().</li>
|
||||
* </ul>
|
||||
*
|
||||
* For more accurate information, please look at the TDES section of the
|
||||
* Datasheet.
|
||||
*
|
||||
* Related files:\n
|
||||
* \ref tdes.c\n
|
||||
* \ref tdes.h\n
|
||||
*/
|
||||
/*@{*/
|
||||
/*@}*/
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implementation of the Triple Data Encryption Algorithm (TDES).
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/tdes.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
void tdes_start(void)
|
||||
{
|
||||
TDES->TDES_CR = TDES_CR_START;
|
||||
}
|
||||
|
||||
void tdes_soft_reset(void)
|
||||
{
|
||||
TDES->TDES_CR = TDES_CR_SWRST;
|
||||
}
|
||||
|
||||
void tdes_configure(uint32_t mode)
|
||||
{
|
||||
TDES->TDES_MR = mode;
|
||||
}
|
||||
|
||||
void tdes_enable_it(uint32_t sources)
|
||||
{
|
||||
TDES->TDES_IER = sources;
|
||||
}
|
||||
|
||||
void tdes_disable_it(uint32_t sources)
|
||||
{
|
||||
TDES->TDES_IDR = sources;
|
||||
}
|
||||
|
||||
uint32_t tdes_get_status(void)
|
||||
{
|
||||
return TDES->TDES_ISR;
|
||||
}
|
||||
|
||||
void tdes_write_key1(uint32_t key_word0, uint32_t key_word1)
|
||||
{
|
||||
TDES->TDES_KEY1WR[0] = key_word0;
|
||||
TDES->TDES_KEY1WR[1] = key_word1;
|
||||
}
|
||||
|
||||
void tdes_write_key2(uint32_t key_word0, uint32_t key_word1)
|
||||
{
|
||||
TDES->TDES_KEY2WR[0] = key_word0;
|
||||
TDES->TDES_KEY2WR[1] = key_word1;
|
||||
}
|
||||
|
||||
void tdes_write_key3(uint32_t key_word0, uint32_t key_word1)
|
||||
{
|
||||
TDES->TDES_KEY3WR[0] = key_word0;
|
||||
TDES->TDES_KEY3WR[1] = key_word1;
|
||||
}
|
||||
|
||||
void tdes_set_input(uint32_t data0, uint32_t data1)
|
||||
{
|
||||
TDES->TDES_IDATAR[0] = data0;
|
||||
TDES->TDES_IDATAR[1] = data1;
|
||||
}
|
||||
|
||||
void tdes_get_output(uint32_t *data0, uint32_t *data1)
|
||||
{
|
||||
*data0 = TDES->TDES_ODATAR[0];
|
||||
*data1 = TDES->TDES_ODATAR[1];
|
||||
}
|
||||
|
||||
void tdes_set_vector(uint32_t v0, uint32_t v1)
|
||||
{
|
||||
TDES->TDES_IVR[0] = v0;
|
||||
TDES->TDES_IVR[1] = v1;
|
||||
}
|
||||
|
||||
void tdes_set_xtea_rounds(uint32_t rounds)
|
||||
{
|
||||
TDES->TDES_XTEA_RNDR = TDES_XTEA_RNDR_XTEA_RNDS(rounds);
|
||||
}
|
|
@ -0,0 +1,125 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _TDES_
|
||||
#define _TDES_
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Definitions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#define MODE_SINGLE_DES 0x00
|
||||
#define MODE_TRIPLE_DES 0x01
|
||||
#define MODE_XTEA 0x02
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Starts Manual encryption/decryption process.
|
||||
*/
|
||||
void tdes_start(void);
|
||||
|
||||
/**
|
||||
* \brief Resets the TDES.
|
||||
* A software triggered hardware reset of the TDES interface is performed.
|
||||
*/
|
||||
void tdes_soft_reset(void);
|
||||
|
||||
/**
|
||||
* \brief Configures an TDES peripheral with the specified parameters.
|
||||
* \param mode Desired value for the TDES_MR mode register (see the datasheet).
|
||||
*/
|
||||
void tdes_configure(uint32_t mode);
|
||||
|
||||
/**
|
||||
* \brief Enables the selected interrupts sources on a TDES peripheral.
|
||||
* \param sources Bitwise OR of selected interrupt sources.
|
||||
*/
|
||||
void tdes_enable_it(uint32_t sources);
|
||||
|
||||
/**
|
||||
* \brief Disables the selected interrupts sources on a TDES peripheral.
|
||||
* \param sources Bitwise OR of selected interrupt sources.
|
||||
*/
|
||||
void tdes_disable_it(uint32_t sources);
|
||||
|
||||
/**
|
||||
* \brief Get the current status register of the given TDES peripheral.
|
||||
* \return TDES status register.
|
||||
*/
|
||||
extern uint32_t tdes_get_status(void);
|
||||
|
||||
/**
|
||||
* \brief Set KEY 1/2/3.
|
||||
* \param key_word0 Key x, word 0
|
||||
* \param key_word1 Key x, word 1
|
||||
*/
|
||||
void tdes_write_key1(uint32_t key_word0, uint32_t key_word1);
|
||||
void tdes_write_key2(uint32_t key_word0, uint32_t key_word1);
|
||||
void tdes_write_key3(uint32_t key_word0, uint32_t key_word1);
|
||||
|
||||
/**
|
||||
* \brief Set the two 32-bit input data registers. Allows to set the 64-bit data
|
||||
* block used for encryption/decryption.
|
||||
* \param data0 Corresponds to the first word of the data to be processed.
|
||||
* \param data1 Corresponds to the last word of the data to be processed.
|
||||
*/
|
||||
void tdes_set_input(uint32_t data0, uint32_t data1);
|
||||
|
||||
/**
|
||||
* \brief Read from the two 32-bit data registers containing the 64-bit data
|
||||
* block which has been encrypted/decrypted.
|
||||
* \param data0 Points to the first word.
|
||||
* \param data1 Points to the second word.
|
||||
*/
|
||||
void tdes_get_output(uint32_t *data0, uint32_t *data1);
|
||||
|
||||
/**
|
||||
* \brief Set the 64-bit initialization vector data block, which is used by
|
||||
* specific modes of operation as an additional initial input.
|
||||
* \param v0 Corresponds to the first word of the initialization vector.
|
||||
* \param v1 Corresponds to the second word of the initialization vector.
|
||||
*/
|
||||
void tdes_set_vector(uint32_t v0, uint32_t v1);
|
||||
|
||||
/**
|
||||
* \brief Set the 6-bit complete rounds.
|
||||
* \param rounds Corresponds to rounds+1 complete round.
|
||||
*/
|
||||
void tdes_set_xtea_rounds(uint32_t rounds);
|
||||
|
||||
#endif /* #ifndef _TDES_ */
|
|
@ -0,0 +1,128 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \addtogroup rtng_module Working with RTNG
|
||||
* \ingroup peripherals_module
|
||||
* The TRNG driver provides the interface to configure and use the TRNG
|
||||
* peripheral.
|
||||
* \n
|
||||
*
|
||||
* The True Random Number Generator (TRNG) passes the American NIST Special
|
||||
* Publication 800-22 and Diehard Random Tests Suites. As soon as the TRNG is
|
||||
* enabled (trng_enable()), the generator provides one 32-bit value every 84
|
||||
* clock cycles. TRNG Interrupt can be enabled through trng_enable_it()
|
||||
* (respectively disabled with trng_disable_it()). When new random data is
|
||||
* ready, the interrupt will fire and the configured callback will be called.
|
||||
* Alternatively, the TRNG can also be used in polling mode using
|
||||
* trng_get_random_data().
|
||||
*
|
||||
* For more accurate information, please look at the TRNG section of the
|
||||
* datasheet.
|
||||
*
|
||||
* Related files :\n
|
||||
* \ref trng.c\n
|
||||
* \ref trng.h\n
|
||||
*/
|
||||
/*@{*/
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implementation of True Random Number Generator (TRNG)
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/aic.h"
|
||||
#include "peripherals/pmc.h"
|
||||
#include "peripherals/trng.h"
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Local Data
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
static trng_callback_t _trng_callback;
|
||||
static void* _trng_callback_arg;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Local functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
static void _trng_handler(void)
|
||||
{
|
||||
if (TRNG->TRNG_ISR & TRNG_ISR_DATRDY) {
|
||||
if (_trng_callback) {
|
||||
_trng_callback(TRNG->TRNG_ODATA, _trng_callback_arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
void trng_enable()
|
||||
{
|
||||
pmc_enable_peripheral(ID_TRNG);
|
||||
TRNG->TRNG_CR = TRNG_CR_ENABLE | TRNG_CR_KEY_PASSWD;
|
||||
}
|
||||
|
||||
void trng_disable()
|
||||
{
|
||||
TRNG->TRNG_CR = TRNG_CR_KEY_PASSWD;
|
||||
pmc_disable_peripheral(ID_TRNG);
|
||||
}
|
||||
|
||||
void trng_enable_it(trng_callback_t cb, void* user_arg)
|
||||
{
|
||||
_trng_callback = cb;
|
||||
_trng_callback_arg = user_arg;
|
||||
aic_set_source_vector(ID_TRNG, _trng_handler);
|
||||
aic_enable(ID_TRNG);
|
||||
TRNG->TRNG_IER = TRNG_IER_DATRDY;
|
||||
}
|
||||
|
||||
void trng_disable_it(void)
|
||||
{
|
||||
TRNG->TRNG_IDR = TRNG_IDR_DATRDY;
|
||||
aic_disable(ID_TRNG);
|
||||
_trng_callback = NULL;
|
||||
_trng_callback_arg = NULL;
|
||||
}
|
||||
|
||||
uint32_t trng_get_random_data(void)
|
||||
{
|
||||
while (!(TRNG->TRNG_ISR & TRNG_ISR_DATRDY));
|
||||
return TRNG->TRNG_ODATA;
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _TRNG_H_
|
||||
#define _TRNG_H_
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include "chip.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Types
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
typedef void (*trng_callback_t)(uint32_t random_value, void* user_arg);
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Enables the TRNG.
|
||||
*/
|
||||
extern void trng_enable(void);
|
||||
|
||||
/**
|
||||
* \brief Disables the TRNG.
|
||||
*/
|
||||
extern void trng_disable(void);
|
||||
|
||||
/**
|
||||
* \brief Enable the TRNG interrupt, the callback will be called for each new
|
||||
* generated random value.
|
||||
*
|
||||
* \param cb user callback
|
||||
* \param user_arg user argument passed as-is to the callback
|
||||
*/
|
||||
extern void trng_enable_it(trng_callback_t cb, void* user_arg);
|
||||
|
||||
/**
|
||||
* \brief Disable the TRNG interrupt.
|
||||
*/
|
||||
extern void trng_disable_it(void);
|
||||
|
||||
/**
|
||||
* \brief Get the next random value generated by the TRNG. This function will
|
||||
* block until a value is available.
|
||||
* \return a random value
|
||||
*/
|
||||
extern uint32_t trng_get_random_data(void);
|
||||
|
||||
#endif /* _TRNG_H_ */
|
|
@ -0,0 +1,500 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \addtogroup twi_module Working with TWI
|
||||
* \section Purpose
|
||||
* The TWI driver provides the interface to configure and use the TWI
|
||||
* peripheral.
|
||||
*
|
||||
* \section Usage
|
||||
* <ul>
|
||||
* <li> Configures a TWI peripheral to operate in master mode, at the given
|
||||
* frequency (in Hz) using twi_configure(). </li>
|
||||
* <li> Sends a STOP condition on the TWI using twi_stop().</li>
|
||||
* <li> Starts a read operation on the TWI bus with the specified slave using
|
||||
* twi_start_read(). Data must then be read using twi_read_byte() whenever
|
||||
* a byte is available (poll using twi_is_byte_received()).</li>
|
||||
* <li> Starts a write operation on the TWI to access the selected slave using
|
||||
* twi_start_write(). A byte of data must be provided to start the write;
|
||||
* other bytes are written next.</li>
|
||||
* <li> Sends a byte of data to one of the TWI slaves on the bus using twi_write_byte().
|
||||
* This function must be called once before twi_start_write() with the first byte of data
|
||||
* to send, then it shall be called repeatedly after that to send the remaining bytes.</li>
|
||||
* <li> Check if a byte has been received and can be read on the given TWI
|
||||
* peripheral using twi_is_byte_received().<
|
||||
* Check if a byte has been sent using twi_byte_sent().</li>
|
||||
* <li> Check if the current transmission is complete (the STOP has been sent)
|
||||
* using twi_is_transfer_complete().</li>
|
||||
* <li> Enables & disable the selected interrupts sources on a TWI peripheral
|
||||
* using twi_enable_it() and twi_enable_it().</li>
|
||||
* <li> Get current status register of the given TWI peripheral using
|
||||
* twi_get_status(). Get current status register of the given TWI peripheral, but
|
||||
* masking interrupt sources which are not currently enabled using
|
||||
* twi_get_masked_status().</li>
|
||||
* </ul>
|
||||
* For more accurate information, please look at the TWI section of the
|
||||
* Datasheet.
|
||||
*
|
||||
* Related files :\n
|
||||
* \ref twi.c\n
|
||||
* \ref twi.h.\n
|
||||
*/
|
||||
/*@{*/
|
||||
/*@}*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Implementation of Two Wire Interface (TWI).
|
||||
*
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/twi.h"
|
||||
#include "peripherals/pmc.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include "timer.h"
|
||||
#include "io.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Configures a TWI peripheral to operate in master mode, at the given
|
||||
* frequency (in Hz). The duty cycle of the TWI clock is set to 50%.
|
||||
* \param twi Pointer to an Twi instance.
|
||||
* \param twi_clock Desired TWI clock frequency.
|
||||
*/
|
||||
void twi_configure_master(Twi * pTwi, uint32_t twi_clock)
|
||||
{
|
||||
uint32_t ck_div, cl_div, hold, ok, clock;
|
||||
uint32_t id = get_twi_id_from_addr(pTwi);
|
||||
|
||||
trace_debug("twi_configure_master(%u)\n\r", (unsigned)twi_clock);
|
||||
assert(pTwi);
|
||||
assert(id < ID_PERIPH_COUNT);
|
||||
|
||||
/* SVEN: TWI Slave Mode Enabled */
|
||||
pTwi->TWI_CR = TWI_CR_SVEN;
|
||||
|
||||
/* Reset the TWI */
|
||||
pTwi->TWI_CR = TWI_CR_SWRST;
|
||||
pTwi->TWI_RHR;
|
||||
timer_sleep(10);
|
||||
|
||||
/* TWI Slave Mode Disabled, TWI Master Mode Disabled. */
|
||||
pTwi->TWI_MMR = 0;
|
||||
pTwi->TWI_CR = TWI_CR_SVDIS;
|
||||
pTwi->TWI_CR = TWI_CR_MSDIS;
|
||||
clock = pmc_get_peripheral_clock(id);
|
||||
|
||||
/* Compute clock */
|
||||
ck_div = 0; ok = 0;
|
||||
while (!ok) {
|
||||
cl_div = ((clock / (2 * twi_clock)) - 3) >> ck_div;
|
||||
if (cl_div <= 255)
|
||||
ok = 1;
|
||||
else
|
||||
ck_div++;
|
||||
}
|
||||
twi_clock = ROUND_INT_DIV(clock, (((cl_div * 2) << ck_div) + 3));
|
||||
assert(ck_div < 8);
|
||||
trace_debug("twi: CKDIV=%u CLDIV=CHDIV=%u -> TWI Clock %uHz\n\r",
|
||||
(unsigned)ck_div, (unsigned)cl_div, (unsigned)twi_clock);
|
||||
|
||||
/* Compute holding time (I2C spec requires 300ns) */
|
||||
hold = ROUND_INT_DIV((uint32_t)(0.3 * clock), 1000000) - 3;
|
||||
trace_debug("twi: HOLD=%u -> Holding Time %uns\n\r",
|
||||
(unsigned)hold, (unsigned)((1000000 * (hold + 3)) / (clock / 1000)));
|
||||
|
||||
/* Configure clock */
|
||||
pTwi->TWI_CWGR = 0;
|
||||
pTwi->TWI_CWGR = TWI_CWGR_CKDIV(ck_div) | TWI_CWGR_CHDIV(cl_div) |
|
||||
TWI_CWGR_CLDIV(cl_div) | TWI_CWGR_HOLD(hold);
|
||||
|
||||
/* Set master mode */
|
||||
pTwi->TWI_CR = TWI_CR_MSEN;
|
||||
timer_sleep(10);
|
||||
assert((pTwi->TWI_CR & TWI_CR_SVDIS) != TWI_CR_MSDIS);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configures a TWI peripheral to operate in slave mode.
|
||||
* \param twi Pointer to an Twi instance.
|
||||
* \param slaveAddress Slave address.
|
||||
*/
|
||||
void twi_configure_slave(Twi * pTwi, uint8_t slave_address)
|
||||
{
|
||||
trace_debug("twi_configure_slave()\n\r");
|
||||
assert(pTwi);
|
||||
/* TWI software reset */
|
||||
pTwi->TWI_CR = TWI_CR_SWRST;
|
||||
pTwi->TWI_RHR;
|
||||
/* Wait at least 10 ms */
|
||||
timer_sleep(10);
|
||||
/* TWI Slave Mode Disabled, TWI Master Mode Disabled */
|
||||
pTwi->TWI_CR = TWI_CR_SVDIS | TWI_CR_MSDIS;
|
||||
/* Configure slave address. */
|
||||
pTwi->TWI_SMR = 0;
|
||||
pTwi->TWI_SMR = TWI_SMR_SADR(slave_address);
|
||||
/* SVEN: TWI Slave Mode Enabled */
|
||||
pTwi->TWI_CR = TWI_CR_SVEN;
|
||||
/* Wait at least 10 ms */
|
||||
timer_sleep(10);
|
||||
assert((pTwi->TWI_CR & TWI_CR_SVDIS) != TWI_CR_SVDIS);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sends a STOP condition on the TWI.
|
||||
* \param twi Pointer to an Twi instance.
|
||||
*/
|
||||
void twi_stop(Twi * pTwi)
|
||||
{
|
||||
assert(pTwi != NULL);
|
||||
pTwi->TWI_CR = TWI_CR_STOP;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Starts a read operation on the TWI bus with the specified slave, it returns
|
||||
* immediately. Data must then be read using twi_read_byte() whenever a byte is
|
||||
* available (poll using twi_is_byte_received()).
|
||||
* \param twi Pointer to an Twi instance.
|
||||
* \param address Slave address on the bus.
|
||||
* \param iaddress Optional internal address bytes.
|
||||
* \param isize Number of internal address bytes.
|
||||
*/
|
||||
void twi_start_read(Twi * pTwi, uint8_t address,
|
||||
uint32_t iaddress, uint8_t isize)
|
||||
{
|
||||
assert(pTwi != NULL);
|
||||
assert((address & 0x80) == 0);
|
||||
assert((iaddress & 0xFF000000) == 0);
|
||||
assert(isize < 4);
|
||||
/* Set slave address and number of internal address bytes. */
|
||||
pTwi->TWI_MMR = 0;
|
||||
pTwi->TWI_MMR = (isize << 8) | TWI_MMR_MREAD | (address << 16);
|
||||
/* Set internal address bytes */
|
||||
pTwi->TWI_IADR = 0;
|
||||
pTwi->TWI_IADR = iaddress;
|
||||
/* Send START condition */
|
||||
pTwi->TWI_CR = TWI_CR_START;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reads a byte from the TWI bus. The read operation must have been started
|
||||
* using twi_start_read() and a byte must be available (check with twi_is_byte_received()).
|
||||
* \param twi Pointer to an Twi instance.
|
||||
* \return byte read.
|
||||
*/
|
||||
uint8_t twi_read_byte(Twi * twi)
|
||||
{
|
||||
assert(twi != NULL);
|
||||
uint8_t value;
|
||||
readb(&twi->TWI_RHR, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sends a byte of data to one of the TWI slaves on the bus.
|
||||
* \note This function must be called once before twi_start_write() with
|
||||
* the first byte of data to send, then it shall be called repeatedly
|
||||
* after that to send the remaining bytes.
|
||||
* \param twi Pointer to an Twi instance.
|
||||
* \param byte Byte to send.
|
||||
*/
|
||||
void twi_write_byte(Twi * twi, uint8_t byte)
|
||||
{
|
||||
assert(twi != NULL);
|
||||
writeb(&twi->TWI_THR, byte);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Starts a write operation on the TWI to access the selected slave, then
|
||||
* returns immediately. A byte of data must be provided to start the write;
|
||||
* other bytes are written next.
|
||||
* after that to send the remaining bytes.
|
||||
* \param twi Pointer to an Twi instance.
|
||||
* \param address Address of slave to acccess on the bus.
|
||||
* \param iaddress Optional slave internal address.
|
||||
* \param isize Number of internal address bytes.
|
||||
* \param byte First byte to send.
|
||||
*/
|
||||
void twi_start_write(Twi * pTwi, uint8_t address, uint32_t iaddress,
|
||||
uint8_t isize, uint8_t byte)
|
||||
{
|
||||
assert(pTwi != NULL);
|
||||
assert((address & 0x80) == 0);
|
||||
assert((iaddress & 0xFF000000) == 0);
|
||||
assert(isize < 4);
|
||||
/* Set slave address and number of internal address bytes. */
|
||||
pTwi->TWI_MMR = 0;
|
||||
pTwi->TWI_MMR = (isize << 8) | (address << 16);
|
||||
/* Set internal address bytes. */
|
||||
pTwi->TWI_IADR = 0;
|
||||
pTwi->TWI_IADR = iaddress;
|
||||
/* Write first byte to send. */
|
||||
twi_write_byte(pTwi, byte);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if a byte have been receiced from TWI.
|
||||
* \param twi Pointer to an Twi instance.
|
||||
* \return 1 if a byte has been received and can be read on the given TWI
|
||||
* peripheral; otherwise, returns 0. This function resets the status register.
|
||||
*/
|
||||
uint8_t twi_is_byte_received(Twi * pTwi)
|
||||
{
|
||||
assert(pTwi != NULL);
|
||||
return ((pTwi->TWI_SR & TWI_SR_RXRDY) == TWI_SR_RXRDY);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if a byte have been sent to TWI.
|
||||
* \param twi Pointer to an Twi instance.
|
||||
* \return 1 if a byte has been sent so another one can be stored for
|
||||
* transmission; otherwise returns 0. This function clears the status register.
|
||||
*/
|
||||
uint8_t twi_byte_sent(Twi * pTwi)
|
||||
{
|
||||
assert(pTwi != NULL);
|
||||
return ((pTwi->TWI_SR & TWI_SR_TXRDY) == TWI_SR_TXRDY);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Check if current transmission is complet.
|
||||
* \param twi Pointer to an Twi instance.
|
||||
* \return 1 if the current transmission is complete (the STOP has been sent);
|
||||
* otherwise returns 0.
|
||||
*/
|
||||
uint8_t twi_is_transfer_complete(Twi * pTwi)
|
||||
{
|
||||
assert(pTwi != NULL);
|
||||
return ((pTwi->TWI_SR & TWI_SR_TXCOMP) == TWI_SR_TXCOMP);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enables the selected interrupts sources on a TWI peripheral.
|
||||
* \param twi Pointer to an Twi instance.
|
||||
* \param sources Bitwise OR of selected interrupt sources.
|
||||
*/
|
||||
void twi_enable_it(Twi * pTwi, uint32_t sources)
|
||||
{
|
||||
assert(pTwi != NULL);
|
||||
pTwi->TWI_IER = sources;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disables the selected interrupts sources on a TWI peripheral.
|
||||
* \param twi Pointer to an Twi instance.
|
||||
* \param sources Bitwise OR of selected interrupt sources.
|
||||
*/
|
||||
void twi_disable_it(Twi * pTwi, uint32_t sources)
|
||||
{
|
||||
assert(pTwi != NULL);
|
||||
pTwi->TWI_IDR = sources;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the current status register of the given TWI peripheral.
|
||||
* \note This resets the internal value of the status register, so further
|
||||
* read may yield different values.
|
||||
* \param twi Pointer to an Twi instance.
|
||||
* \return TWI status register.
|
||||
*/
|
||||
uint32_t twi_get_status(Twi * pTwi)
|
||||
{
|
||||
assert(pTwi != NULL);
|
||||
return pTwi->TWI_SR;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Returns the current status register of the given TWI peripheral, but
|
||||
* masking interrupt sources which are not currently enabled.
|
||||
* \note This resets the internal value of the status register, so further
|
||||
* read may yield different values.
|
||||
* \param twi Pointer to an Twi instance.
|
||||
*/
|
||||
uint32_t twi_get_masked_status(Twi * pTwi)
|
||||
{
|
||||
uint32_t status;
|
||||
assert(pTwi != NULL);
|
||||
status = pTwi->TWI_SR;
|
||||
status &= pTwi->TWI_IMR;
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Sends a STOP condition. STOP Condition is sent just after completing
|
||||
* the current byte transmission in master read mode.
|
||||
* \param twi Pointer to an Twi instance.
|
||||
*/
|
||||
void twi_send_stop_condition(Twi * pTwi)
|
||||
{
|
||||
assert(pTwi != NULL);
|
||||
pTwi->TWI_CR |= TWI_CR_STOP;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HAVE_TWI_ALTERNATE_CMD
|
||||
void twi_init_write_transfert(Twi * twi, uint8_t addr, uint32_t iaddress,
|
||||
uint8_t isize, uint8_t len)
|
||||
{
|
||||
twi->TWI_RHR;
|
||||
twi->TWI_CR = TWI_CR_MSDIS;
|
||||
twi->TWI_CR = TWI_CR_MSEN;
|
||||
twi->TWI_CR = TWI_CR_MSEN | TWI_CR_SVDIS | TWI_CR_ACMEN;
|
||||
twi->TWI_ACR = 0;
|
||||
twi->TWI_ACR = TWI_ACR_DATAL(len);
|
||||
twi->TWI_MMR = 0;
|
||||
twi->TWI_MMR = TWI_MMR_DADR(addr) | TWI_MMR_IADRSZ(isize);
|
||||
/* Set internal address bytes. */
|
||||
twi->TWI_IADR = 0;
|
||||
twi->TWI_IADR = iaddress;
|
||||
}
|
||||
|
||||
void twi_init_read_transfert(Twi * twi, uint8_t addr, uint32_t iaddress,
|
||||
uint8_t isize, uint8_t len)
|
||||
{
|
||||
twi->TWI_RHR;
|
||||
twi->TWI_CR = TWI_CR_MSEN | TWI_CR_SVDIS | TWI_CR_ACMEN;
|
||||
twi->TWI_ACR = 0;
|
||||
twi->TWI_ACR = TWI_ACR_DATAL(len) | TWI_ACR_DIR;
|
||||
twi->TWI_MMR = 0;
|
||||
twi->TWI_MMR = TWI_MMR_DADR(addr) | TWI_MMR_MREAD
|
||||
| TWI_MMR_IADRSZ(isize);
|
||||
/* Set internal address bytes. */
|
||||
twi->TWI_IADR = 0;
|
||||
twi->TWI_IADR = iaddress;
|
||||
twi->TWI_CR = TWI_CR_START;
|
||||
while(twi->TWI_SR & TWI_SR_TXCOMP);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HAVE_TWI_FIFO
|
||||
void twi_fifo_configure(Twi* twi, uint8_t tx_thres,
|
||||
uint8_t rx_thres,
|
||||
uint32_t ready_modes)
|
||||
{
|
||||
/* Disable TWI master and slave mode and activate FIFO */
|
||||
twi->TWI_CR = TWI_CR_MSDIS | TWI_CR_SVDIS | TWI_CR_FIFOEN;
|
||||
|
||||
/* Configure FIFO */
|
||||
twi->TWI_FMR = TWI_FMR_TXFTHRES(tx_thres) | TWI_FMR_RXFTHRES(rx_thres)
|
||||
| ready_modes;
|
||||
}
|
||||
|
||||
uint32_t twi_fifo_rx_size(Twi *twi)
|
||||
{
|
||||
return (twi->TWI_FLR & TWI_FLR_RXFL_Msk) >> TWI_FLR_RXFL_Pos;
|
||||
}
|
||||
|
||||
uint32_t twi_fifo_tx_size(Twi *twi)
|
||||
{
|
||||
return (twi->TWI_FLR & TWI_FLR_TXFL_Msk) >> TWI_FLR_TXFL_Pos;
|
||||
}
|
||||
|
||||
uint32_t twi_read_stream(Twi *twi, uint32_t addr, uint32_t iaddr,
|
||||
uint32_t isize, const void *stream, uint8_t len)
|
||||
{
|
||||
const uint8_t* buffer = stream;
|
||||
uint8_t left = len;
|
||||
|
||||
twi_init_read_transfert(twi, addr, iaddr, isize, len);
|
||||
if (twi_get_status(twi) & TWI_SR_NACK) {
|
||||
trace_error("twid2: command NACK!\r\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (left > 0) {
|
||||
if ((twi->TWI_SR & TWI_SR_RXRDY) == 0) continue;
|
||||
|
||||
/* Get FIFO free size (int octet) and clamp it */
|
||||
uint32_t buf_size = twi_fifo_rx_size(twi);
|
||||
buf_size = buf_size > left ? left : buf_size;
|
||||
|
||||
/* Fill the FIFO as must as possible */
|
||||
while (buf_size > sizeof(uint32_t)) {
|
||||
*(uint32_t*)buffer = twi->TWI_RHR;
|
||||
buffer += sizeof(uint32_t);
|
||||
left -= sizeof(uint32_t);
|
||||
buf_size -= sizeof(uint32_t);
|
||||
}
|
||||
while (buf_size >= sizeof(uint8_t)) {
|
||||
readb(&twi->TWI_RHR, (uint8_t*)buffer);
|
||||
buffer += sizeof(uint8_t);
|
||||
left -= sizeof(uint8_t);
|
||||
buf_size -= sizeof(uint8_t);
|
||||
}
|
||||
}
|
||||
return len - left;
|
||||
}
|
||||
|
||||
uint32_t twi_write_stream(Twi *twi, uint32_t addr, uint32_t iaddr,
|
||||
uint32_t isize, const void *stream, uint8_t len)
|
||||
{
|
||||
const uint8_t* buffer = stream;
|
||||
uint8_t left = len;
|
||||
|
||||
int32_t fifo_size = get_peripheral_fifo_depth(twi);
|
||||
if (fifo_size < 0)
|
||||
return 0;
|
||||
|
||||
twi_init_write_transfert(twi, addr, iaddr, isize, len);
|
||||
if (twi_get_status(twi) & TWI_SR_NACK) {
|
||||
trace_error("twid2: command NACK!\r\n");
|
||||
return 0;
|
||||
}
|
||||
while (left > 0) {
|
||||
if ((twi->TWI_SR & TWI_SR_TXRDY) == 0) continue;
|
||||
|
||||
/* Get FIFO free size (int octet) and clamp it */
|
||||
uint32_t buf_size = fifo_size - twi_fifo_tx_size(twi);
|
||||
buf_size = buf_size > left ? left : buf_size;
|
||||
|
||||
/* /\* Fill the FIFO as must as possible *\/ */
|
||||
while (buf_size >= sizeof(uint8_t)) {
|
||||
writeb(&twi->TWI_THR,*buffer);
|
||||
buffer += sizeof(uint8_t);
|
||||
left -= sizeof(uint8_t);
|
||||
buf_size -= sizeof(uint8_t);
|
||||
}
|
||||
}
|
||||
return len - left;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,111 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/**
|
||||
* \file
|
||||
*
|
||||
* Interface for configuration the Two Wire Interface (TWI) peripheral.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _TWI_H_
|
||||
#define _TWI_H_
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Macros
|
||||
*----------------------------------------------------------------------------*/
|
||||
/* Returns 1 if the TXRDY bit (ready to transmit data) is set in the given status register value.*/
|
||||
#define TWI_STATUS_TXRDY(status) ((status & TWI_SR_TXRDY) == TWI_SR_TXRDY)
|
||||
|
||||
/* Returns 1 if the RXRDY bit (ready to receive data) is set in the given status register value.*/
|
||||
#define TWI_STATUS_RXRDY(status) ((status & TWI_SR_RXRDY) == TWI_SR_RXRDY)
|
||||
|
||||
/* Returns 1 if the TXCOMP bit (transfer complete) is set in the given status register value.*/
|
||||
#define TWI_STATUS_TXCOMP(status) ((status & TWI_SR_TXCOMP) == TWI_SR_TXCOMP)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* External function
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
extern void twi_configure_master(Twi * pTwi, uint32_t twck);
|
||||
extern void twi_configure_slave(Twi * pTwi, uint8_t slaveAddress);
|
||||
extern void twi_stop(Twi * pTwi);
|
||||
extern void twi_start_read(Twi * pTwi, uint8_t address,
|
||||
uint32_t iaddress, uint8_t isize);
|
||||
extern uint8_t twi_read_byte(Twi * pTwi);
|
||||
extern void twi_write_byte(Twi * pTwi, uint8_t byte);
|
||||
extern void twi_start_write(Twi * pTwi, uint8_t address, uint32_t iaddress,
|
||||
uint8_t isize, uint8_t byte);
|
||||
extern uint8_t twi_is_byte_received(Twi * pTwi);
|
||||
extern uint8_t twi_byte_sent(Twi * pTwi);
|
||||
extern uint8_t twi_is_transfer_complete(Twi * pTwi);
|
||||
extern void twi_enable_it(Twi * pTwi, uint32_t sources);
|
||||
extern void twi_disable_it(Twi * pTwi, uint32_t sources);
|
||||
extern uint32_t twi_get_status(Twi * pTwi);
|
||||
extern uint32_t twi_get_masked_status(Twi * pTwi);
|
||||
extern void twi_send_stop_condition(Twi * pTwi);
|
||||
|
||||
#ifdef CONFIG_HAVE_TWI_ALTERNATE_CMD
|
||||
extern void twi_init_write_transfert(Twi * twi, uint8_t addr, uint32_t iaddress,
|
||||
uint8_t isize, uint8_t len);
|
||||
extern void twi_init_read_transfert(Twi * twi, uint8_t addr, uint32_t iaddress,
|
||||
uint8_t isize, uint8_t len);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_HAVE_TWI_FIFO
|
||||
extern void twi_fifo_configure(Twi* twi, uint8_t tx_thres,
|
||||
uint8_t rx_thres,
|
||||
uint32_t ready_modes);
|
||||
extern void twi_fifo_disable(Twi* twi);
|
||||
|
||||
extern uint32_t twi_fifo_rx_size(Twi *twi);
|
||||
extern uint32_t twi_fifo_tx_size(Twi *twi);
|
||||
|
||||
extern uint32_t twi_read_stream(Twi *twi, uint32_t addr, uint32_t iaddr,
|
||||
uint32_t isize, const void *stream, uint8_t len);
|
||||
extern uint32_t twi_write_stream(Twi *twi, uint32_t addr, uint32_t iaddr,
|
||||
uint32_t isize, const void *stream, uint8_t len);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* #ifndef _TWI_H_ */
|
|
@ -0,0 +1,409 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#ifdef CONFIG_HAVE_FLEXCOM
|
||||
#include "peripherals/flexcom.h"
|
||||
#endif
|
||||
#include "peripherals/pmc.h"
|
||||
#include "peripherals/twid.h"
|
||||
#include "peripherals/twi.h"
|
||||
#include "peripherals/xdmad.h"
|
||||
#include "peripherals/l2cc.h"
|
||||
|
||||
#include "cortex-a/cp15.h"
|
||||
|
||||
#include "trace.h"
|
||||
#include "io.h"
|
||||
#include "timer.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TWID_DMA_THRESHOLD 16
|
||||
#define TWID_TIMEOUT 100
|
||||
|
||||
static uint32_t _twid_wait_twi_transfer(struct _twi_desc* desc)
|
||||
{
|
||||
struct _timeout timeout;
|
||||
timer_start_timeout(&timeout, TWID_TIMEOUT);
|
||||
while(!twi_is_transfer_complete(desc->addr)){
|
||||
if (timer_timeout_reached(&timeout)) {
|
||||
trace_error("twid: Unable to complete transfert!\r\n");
|
||||
twid_configure(desc);
|
||||
return TWID_ERROR_TRANSFER;
|
||||
}
|
||||
}
|
||||
return TWID_SUCCESS;
|
||||
}
|
||||
|
||||
static void _twid_xdmad_callback_wrapper(struct _xdmad_channel* channel,
|
||||
void* args)
|
||||
{
|
||||
trace_debug("TWID DMA Transfert Finished\r\n");
|
||||
struct _twi_desc* twid = (struct _twi_desc*) args;
|
||||
|
||||
xdmad_free_channel(channel);
|
||||
|
||||
if (twid->region_start && twid->region_end) {
|
||||
l2cc_invalidate_region(twid->region_start, twid->region_end);
|
||||
}
|
||||
|
||||
if (twid && twid->callback)
|
||||
twid->callback(twid, twid->cb_args);
|
||||
|
||||
}
|
||||
|
||||
static void _twid_init_dma_read_channel(const struct _twi_desc* desc,
|
||||
struct _xdmad_channel** channel,
|
||||
struct _xdmad_cfg* cfg)
|
||||
{
|
||||
assert(cfg);
|
||||
assert(channel);
|
||||
|
||||
uint32_t id = get_twi_id_from_addr(desc->addr);
|
||||
assert(id < ID_PERIPH_COUNT);
|
||||
|
||||
memset(cfg, 0x0, sizeof(*cfg));
|
||||
|
||||
*channel =
|
||||
xdmad_allocate_channel(id, XDMAD_PERIPH_MEMORY);
|
||||
assert(*channel);
|
||||
|
||||
xdmad_prepare_channel(*channel);
|
||||
cfg->cfg.uint32_value = XDMAC_CC_TYPE_PER_TRAN
|
||||
| XDMAC_CC_DSYNC_PER2MEM
|
||||
| XDMAC_CC_MEMSET_NORMAL_MODE
|
||||
| XDMAC_CC_CSIZE_CHK_1
|
||||
| XDMAC_CC_DWIDTH_BYTE
|
||||
| XDMAC_CC_DIF_AHB_IF0
|
||||
| XDMAC_CC_SIF_AHB_IF1
|
||||
| XDMAC_CC_SAM_FIXED_AM;
|
||||
|
||||
cfg->src_addr = (void*)&desc->addr->TWI_RHR;
|
||||
}
|
||||
|
||||
static void _twid_dma_read(const struct _twi_desc* desc,
|
||||
struct _buffer* buffer)
|
||||
{
|
||||
struct _xdmad_channel* channel = NULL;
|
||||
struct _xdmad_cfg cfg;
|
||||
|
||||
_twid_init_dma_read_channel(desc, &channel, &cfg);
|
||||
|
||||
cfg.cfg.bitfield.dam = XDMAC_CC_DAM_INCREMENTED_AM
|
||||
>> XDMAC_CC_DAM_Pos;
|
||||
cfg.dest_addr = buffer->data;
|
||||
cfg.ublock_size = buffer->size;
|
||||
cfg.block_size = 0;
|
||||
xdmad_configure_transfer(channel, &cfg, 0, 0);
|
||||
xdmad_set_callback(channel, _twid_xdmad_callback_wrapper,
|
||||
(void*)desc);
|
||||
|
||||
l2cc_clean_region(desc->region_start, desc->region_end);
|
||||
|
||||
xdmad_start_transfer(channel);
|
||||
}
|
||||
|
||||
static void _twid_init_dma_write_channel(struct _twi_desc* desc,
|
||||
struct _xdmad_channel** channel,
|
||||
struct _xdmad_cfg* cfg)
|
||||
{
|
||||
assert(cfg);
|
||||
assert(channel);
|
||||
|
||||
uint32_t id = get_twi_id_from_addr(desc->addr);
|
||||
assert(id < ID_PERIPH_COUNT);
|
||||
memset(cfg, 0x0, sizeof(*cfg));
|
||||
|
||||
*channel =
|
||||
xdmad_allocate_channel(XDMAD_PERIPH_MEMORY, id);
|
||||
assert(*channel);
|
||||
|
||||
xdmad_prepare_channel(*channel);
|
||||
cfg->cfg.uint32_value = XDMAC_CC_TYPE_PER_TRAN
|
||||
| XDMAC_CC_DSYNC_MEM2PER
|
||||
| XDMAC_CC_MEMSET_NORMAL_MODE
|
||||
| XDMAC_CC_CSIZE_CHK_1
|
||||
| XDMAC_CC_DWIDTH_BYTE
|
||||
| XDMAC_CC_DIF_AHB_IF1
|
||||
| XDMAC_CC_SIF_AHB_IF0
|
||||
| XDMAC_CC_DAM_FIXED_AM;
|
||||
|
||||
cfg->dest_addr = (void*)&desc->addr->TWI_THR;
|
||||
}
|
||||
|
||||
static void _twid_dma_write(struct _twi_desc* desc,
|
||||
struct _buffer* buffer)
|
||||
{
|
||||
struct _xdmad_channel* channel = NULL;
|
||||
struct _xdmad_cfg cfg;
|
||||
|
||||
_twid_init_dma_write_channel(desc, &channel, &cfg);
|
||||
|
||||
cfg.cfg.bitfield.sam = XDMAC_CC_SAM_INCREMENTED_AM
|
||||
>> XDMAC_CC_SAM_Pos;
|
||||
cfg.src_addr = buffer->data;
|
||||
cfg.ublock_size = buffer->size;
|
||||
cfg.block_size = 0;
|
||||
xdmad_configure_transfer(channel, &cfg, 0, 0);
|
||||
xdmad_set_callback(channel, _twid_xdmad_callback_wrapper,
|
||||
(void*)desc);
|
||||
|
||||
l2cc_clean_region(desc->region_start, desc->region_end);
|
||||
|
||||
xdmad_start_transfer(channel);
|
||||
}
|
||||
|
||||
void twid_configure(struct _twi_desc* desc)
|
||||
{
|
||||
uint32_t id = get_twi_id_from_addr(desc->addr);
|
||||
assert(id < ID_PERIPH_COUNT);
|
||||
|
||||
#ifdef CONFIG_HAVE_FLEXCOM
|
||||
Flexcom* flexcom = get_flexcom_addr_from_id(get_twi_id_from_addr(desc->addr));
|
||||
if (flexcom) {
|
||||
flexcom_select(flexcom, FLEX_MR_OPMODE_TWI);
|
||||
}
|
||||
#endif
|
||||
|
||||
pmc_enable_peripheral(id);
|
||||
twi_configure_master(desc->addr, desc->freq);
|
||||
|
||||
#ifdef CONFIG_HAVE_TWI_FIFO
|
||||
if (desc->transfert_mode == TWID_MODE_FIFO) {
|
||||
uint32_t fifo_depth = get_peripheral_fifo_depth(desc->addr);
|
||||
twi_fifo_configure(desc->addr, fifo_depth/2, fifo_depth/2,
|
||||
TWI_FMR_RXRDYM_ONE_DATA | TWI_FMR_TXRDYM_ONE_DATA);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static uint32_t _twid_poll_write(struct _twi_desc* desc, struct _buffer* buffer)
|
||||
{
|
||||
int i = 0;
|
||||
struct _timeout timeout;
|
||||
twi_init_write_transfert(desc->addr,
|
||||
desc->slave_addr,
|
||||
desc->iaddr,
|
||||
desc->isize,
|
||||
buffer->size);
|
||||
if (twi_get_status(desc->addr) & TWI_SR_NACK) {
|
||||
trace_error("twid: command NACK!\r\n");
|
||||
return TWID_ERROR_ACK;
|
||||
}
|
||||
for (i = 0; i < buffer->size; ++i) {
|
||||
timer_start_timeout(&timeout, TWID_TIMEOUT);
|
||||
while(!twi_byte_sent(desc->addr)) {
|
||||
if (timer_timeout_reached(&timeout)) {
|
||||
trace_error("twid: Device doesn't answer, "
|
||||
"(TX TIMEOUT)\r\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
twi_write_byte(desc->addr, buffer->data[i]);
|
||||
if(twi_get_status(desc->addr) & TWI_SR_NACK) {
|
||||
trace_error("twid: command NACK!\r\n");
|
||||
return TWID_ERROR_ACK;
|
||||
}
|
||||
}
|
||||
/* wait transfert to be finished */
|
||||
return _twid_wait_twi_transfer(desc);
|
||||
}
|
||||
|
||||
static uint32_t _twid_poll_read(struct _twi_desc* desc, struct _buffer* buffer)
|
||||
{
|
||||
int i = 0;
|
||||
struct _timeout timeout;
|
||||
twi_init_read_transfert(desc->addr,
|
||||
desc->slave_addr,
|
||||
desc->iaddr,
|
||||
desc->isize,
|
||||
buffer->size);
|
||||
if (twi_get_status(desc->addr) & TWI_SR_NACK) {
|
||||
trace_error("twid: command NACK!\r\n");
|
||||
return TWID_ERROR_ACK;
|
||||
}
|
||||
for (i = 0; i < buffer->size; ++i) {
|
||||
timer_start_timeout(&timeout, TWID_TIMEOUT);
|
||||
while(!twi_is_byte_received(desc->addr)) {
|
||||
if (timer_timeout_reached(&timeout)) {
|
||||
trace_error("twid: Device doesn't answer, "
|
||||
"(RX TIMEOUT)\r\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
buffer->data[i] = twi_read_byte(desc->addr);
|
||||
if(twi_get_status(desc->addr) & TWI_SR_NACK) {
|
||||
trace_error("twid: command NACK\r\n");
|
||||
return TWID_ERROR_ACK;
|
||||
}
|
||||
}
|
||||
/* wait transfert to be finished */
|
||||
return _twid_wait_twi_transfer(desc);
|
||||
}
|
||||
|
||||
uint32_t twid_transfert(struct _twi_desc* desc, struct _buffer* rx,
|
||||
struct _buffer* tx, twid_callback_t cb,
|
||||
void* user_args)
|
||||
{
|
||||
uint32_t status = TWID_SUCCESS;
|
||||
|
||||
desc->callback = cb;
|
||||
desc->cb_args = user_args;
|
||||
|
||||
if (mutex_try_lock(&desc->mutex)) {
|
||||
return TWID_ERROR_LOCK;
|
||||
}
|
||||
|
||||
switch (desc->transfert_mode) {
|
||||
case TWID_MODE_POLLING:
|
||||
if (tx) {
|
||||
status = _twid_poll_write(desc, tx);
|
||||
if (status) break;
|
||||
}
|
||||
if (rx) {
|
||||
status = _twid_poll_read(desc, rx);
|
||||
if (status) break;
|
||||
}
|
||||
if (cb)
|
||||
cb(desc, user_args);
|
||||
mutex_free(&desc->mutex);
|
||||
break;
|
||||
|
||||
case TWID_MODE_DMA:
|
||||
if (!(rx || tx)) {
|
||||
status = TWID_ERROR_DUPLEX;
|
||||
break;
|
||||
}
|
||||
if (tx) {
|
||||
if (tx->size < TWID_DMA_THRESHOLD) {
|
||||
status = _twid_poll_write(desc, tx);
|
||||
if (status) break;
|
||||
if (cb)
|
||||
cb(desc, user_args);
|
||||
mutex_free(&desc->mutex);
|
||||
} else {
|
||||
twi_init_write_transfert(desc->addr,
|
||||
desc->slave_addr,
|
||||
desc->iaddr,
|
||||
desc->isize,
|
||||
tx->size);
|
||||
desc->region_start = (uint32_t)tx->data;
|
||||
desc->region_end = desc->region_start
|
||||
+ tx->size;
|
||||
_twid_dma_write(desc, tx);
|
||||
}
|
||||
}
|
||||
if (rx) {
|
||||
if (rx->size < TWID_DMA_THRESHOLD) {
|
||||
status = _twid_poll_read(desc, rx);
|
||||
if (status) break;
|
||||
if (cb)
|
||||
cb(desc, user_args);
|
||||
mutex_free(&desc->mutex);
|
||||
} else {
|
||||
twi_init_read_transfert(desc->addr,
|
||||
desc->slave_addr,
|
||||
desc->iaddr,
|
||||
desc->isize,
|
||||
rx->size);
|
||||
desc->region_start = (uint32_t)rx->data;
|
||||
desc->region_end = desc->region_start
|
||||
+ rx->size;
|
||||
if(twi_get_status(desc->addr) & TWI_SR_NACK) {
|
||||
trace_error("twid: Acknolegment "
|
||||
"Error\r\n");
|
||||
status = TWID_ERROR_ACK;
|
||||
break;
|
||||
}
|
||||
_twid_dma_read(desc, rx);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef CONFIG_HAVE_TWI_FIFO
|
||||
case TWID_MODE_FIFO:
|
||||
if (tx) {
|
||||
status = twi_write_stream(desc->addr, desc->slave_addr,
|
||||
desc->iaddr, desc->isize,
|
||||
tx->data, tx->size);
|
||||
status = status ? TWID_SUCCESS : TWID_ERROR_ACK;
|
||||
if (status)
|
||||
break;
|
||||
status = _twid_wait_twi_transfer(desc);
|
||||
if (status)
|
||||
break;
|
||||
}
|
||||
if (rx) {
|
||||
status = twi_read_stream(desc->addr, desc->slave_addr,
|
||||
desc->iaddr, desc->isize,
|
||||
rx->data, rx->size);
|
||||
status = status ? TWID_SUCCESS : TWID_ERROR_ACK;
|
||||
if (status)
|
||||
break;
|
||||
status = _twid_wait_twi_transfer(desc);
|
||||
if (status)
|
||||
break;
|
||||
}
|
||||
if (cb)
|
||||
cb(desc, user_args);
|
||||
mutex_free(&desc->mutex);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
trace_debug("Unkown mode");
|
||||
}
|
||||
|
||||
if (status)
|
||||
mutex_free(&desc->mutex);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
void twid_finish_transfert_callback(struct _twi_desc* desc, void* user_args)
|
||||
{
|
||||
(void)user_args;
|
||||
twid_finish_transfert(desc);
|
||||
}
|
||||
|
||||
void twid_finish_transfert(struct _twi_desc* desc)
|
||||
{
|
||||
mutex_free(&desc->mutex);
|
||||
}
|
||||
|
||||
uint32_t twid_is_busy(const struct _twi_desc* desc)
|
||||
{
|
||||
return mutex_is_locked(&desc->mutex);
|
||||
}
|
||||
|
||||
void twid_wait_transfert(const struct _twi_desc* desc)
|
||||
{
|
||||
while (mutex_is_locked(&desc->mutex));
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef TWID_HEADER__
|
||||
#define TWID_HEADER__
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Header
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "peripherals/twi.h"
|
||||
#include "mutex.h"
|
||||
#include "io.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Types
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#define TWID_SUCCESS (0)
|
||||
#define TWID_INVALID_ID (1)
|
||||
#define TWID_INVALID_BITRATE (2)
|
||||
#define TWID_ERROR_LOCK (3)
|
||||
#define TWID_ERROR_DUPLEX (4)
|
||||
#define TWID_ERROR_ACK (5)
|
||||
#define TWID_ERROR_TIMEOUT (6)
|
||||
#define TWID_ERROR_TRANSFER (7)
|
||||
|
||||
enum _twid_trans_mode
|
||||
{
|
||||
TWID_MODE_POLLING,
|
||||
TWID_MODE_FIFO,
|
||||
TWID_MODE_DMA
|
||||
};
|
||||
|
||||
struct _twi_desc;
|
||||
|
||||
typedef void (*twid_callback_t)(struct _twi_desc* spid, void* args);
|
||||
|
||||
struct _twi_desc
|
||||
{
|
||||
Twi* addr;
|
||||
uint32_t freq;
|
||||
uint32_t slave_addr;
|
||||
uint32_t iaddr;
|
||||
uint32_t isize;
|
||||
uint8_t transfert_mode;
|
||||
/* implicit internal padding is mandatory here */
|
||||
mutex_t mutex;
|
||||
uint32_t region_start;
|
||||
uint32_t region_end;
|
||||
twid_callback_t callback;
|
||||
void* cb_args;
|
||||
};
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
extern void twid_configure(struct _twi_desc* desc);
|
||||
extern uint32_t twid_transfert(struct _twi_desc* desc, struct _buffer* rx,
|
||||
struct _buffer* tx, twid_callback_t cb,
|
||||
void* user_args);
|
||||
extern void twid_finish_transfert_callback(struct _twi_desc* desc,
|
||||
void* user_args);
|
||||
extern void twid_finish_transfert(struct _twi_desc* desc);
|
||||
extern uint32_t twid_is_busy(const struct _twi_desc* desc);
|
||||
extern void twid_wait_transfert(const struct _twi_desc* desc);
|
||||
|
||||
#endif /* TWID_HEADER__ */
|
|
@ -0,0 +1,675 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/** \file */
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "peripherals/twid_legacy.h"
|
||||
#include "peripherals/xdmad.h"
|
||||
#include "cortex-a/cp15.h"
|
||||
#include "trace.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Definition
|
||||
*----------------------------------------------------------------------------*/
|
||||
#define TWITIMEOUTMAX 0xfffff
|
||||
|
||||
static struct _xdmad_cfg twi_dmaCfg;
|
||||
static struct _xdmad_channel *dmaWriteChannel;
|
||||
static struct _xdmad_channel *dmaReadChannel;
|
||||
static struct _xdmad_desc_view1 dmaWriteLinkList[1];
|
||||
static struct _xdmad_desc_view1 dmaReadLinkList[1];
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Types
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/** TWI driver callback function.*/
|
||||
typedef void (*TwiCallback) (struct _async *);
|
||||
|
||||
/** \brief TWI asynchronous transfer descriptor.*/
|
||||
struct _async_twi {
|
||||
volatile uint32_t status; /** Asynchronous transfer status. */
|
||||
TwiCallback callback; /** Callback function to invoke when transfer completes or fails.*/
|
||||
uint8_t *pData; /** Pointer to the data buffer.*/
|
||||
uint32_t num; /** Total number of bytes to transfer.*/
|
||||
uint32_t transferred; /** Number of already transferred bytes.*/
|
||||
};
|
||||
|
||||
//struct _async_twi async_twi ;
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Global functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* \brief Initializes a TWI DMA Read channel.
|
||||
*/
|
||||
static void twid_dma_initialize_read(uint8_t TWI_ID)
|
||||
{
|
||||
/* Allocate a XDMA channel, Read accesses into TWI_THR */
|
||||
dmaReadChannel = xdmad_allocate_channel(TWI_ID, XDMAD_PERIPH_MEMORY);
|
||||
if (!dmaReadChannel) {
|
||||
printf("-E- Can't allocate XDMA channel\n\r");
|
||||
}
|
||||
xdmad_prepare_channel(dmaReadChannel);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initializes a TWI DMA write channel.
|
||||
*/
|
||||
static void twid_dma_initialize_write(uint8_t TWI_ID)
|
||||
{
|
||||
|
||||
/* Allocate a XDMA channel, Write accesses into TWI_THR */
|
||||
dmaWriteChannel = xdmad_allocate_channel(XDMAD_PERIPH_MEMORY, TWI_ID);
|
||||
if (!dmaWriteChannel) {
|
||||
printf("-E- Can't allocate XDMA channel\n\r");
|
||||
}
|
||||
xdmad_prepare_channel(dmaWriteChannel);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Initializes a TWI driver instance, using the given TWI peripheral.
|
||||
* \note The peripheral must have been initialized properly before calling this function.
|
||||
* \param pTwid Pointer to the Twid instance to initialize.
|
||||
* \param pTwi Pointer to the TWI peripheral to use.
|
||||
*/
|
||||
void twid_initialize(struct _twid* pTwid, Twi * pTwi)
|
||||
{
|
||||
trace_debug("twid_initialize()\n\r");
|
||||
assert(pTwid != NULL);
|
||||
assert(pTwi != NULL);
|
||||
|
||||
/* Initialize driver. */
|
||||
pTwid->pTwi = pTwi;
|
||||
pTwid->pTransfer = 0;
|
||||
/* Initialize XDMA driver instance with polling mode */
|
||||
|
||||
// ************* need to be updated XDMAD_Initialize(&twi_dma, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure xDMA write linker list for TWI transfer.
|
||||
*/
|
||||
static void _xdma_configure_write(uint8_t * buf, uint32_t len, uint8_t twi_id)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t xdmaCndc, Thr;
|
||||
Twi* twi = (Twi*)get_twi_addr_from_id(twi_id);
|
||||
|
||||
Thr = (uint32_t) & (TWI0->TWI_THR);
|
||||
if (twi)
|
||||
Thr = (uint32_t) & (twi->TWI_THR);
|
||||
for (i = 0; i < 1; i++) {
|
||||
dmaWriteLinkList[i].ublock_size = XDMA_UBC_NVIEW_NDV1
|
||||
| ((i == len - 1) ? 0 : XDMA_UBC_NDE_FETCH_EN)
|
||||
| len;
|
||||
dmaWriteLinkList[i].src_addr = & buf[i];
|
||||
dmaWriteLinkList[i].dest_addr = (void*)Thr;
|
||||
if (i == len - 1)
|
||||
dmaWriteLinkList[i].next_desc = 0;
|
||||
else
|
||||
dmaWriteLinkList[i].next_desc =
|
||||
& dmaWriteLinkList[i + 1];
|
||||
}
|
||||
twi_dmaCfg.cfg.uint32_value = XDMAC_CC_TYPE_PER_TRAN
|
||||
| XDMAC_CC_MBSIZE_SINGLE
|
||||
| XDMAC_CC_DSYNC_MEM2PER
|
||||
| XDMAC_CC_CSIZE_CHK_1
|
||||
| XDMAC_CC_DWIDTH_BYTE
|
||||
| XDMAC_CC_SIF_AHB_IF0
|
||||
| XDMAC_CC_DIF_AHB_IF1
|
||||
| XDMAC_CC_SAM_INCREMENTED_AM
|
||||
| XDMAC_CC_DAM_FIXED_AM
|
||||
|
|
||||
XDMAC_CC_PERID(get_peripheral_xdma_channel(twi_id, XDMAC0, true));
|
||||
xdmaCndc =
|
||||
XDMAC_CNDC_NDVIEW_NDV1 | XDMAC_CNDC_NDE_DSCR_FETCH_EN |
|
||||
XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED |
|
||||
XDMAC_CNDC_NDDUP_DST_PARAMS_UNCHANGED;
|
||||
cp15_coherent_dcache_for_dma((uint32_t) & dmaWriteLinkList,
|
||||
((uint32_t) & dmaWriteLinkList +
|
||||
sizeof (*dmaWriteLinkList) * len));
|
||||
xdmad_configure_transfer(dmaWriteChannel, &twi_dmaCfg,
|
||||
xdmaCndc, dmaWriteLinkList);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure xDMA read linker list for TWI transfer.
|
||||
*/
|
||||
static void _xdma_configure_read(uint8_t * buf, uint32_t len, uint8_t twi_id)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t xdmaCndc, Rhr;
|
||||
Twi* twi = get_twi_addr_from_id(twi_id);
|
||||
|
||||
Rhr = (uint32_t) & (TWI0->TWI_RHR);
|
||||
if (twi) {
|
||||
Rhr = twi->TWI_RHR;
|
||||
}
|
||||
/* if (twi_id == ID_TWI1) { */
|
||||
/* Rhr = (uint32_t) & (TWI1->TWI_RHR); */
|
||||
/* } */
|
||||
/* if (twi_id == ID_TWI2) { */
|
||||
/* Rhr = (uint32_t) & (TWI2->TWI_RHR); */
|
||||
/* } */
|
||||
for (i = 0; i < 1; i++) {
|
||||
dmaReadLinkList[i].ublock_size = XDMA_UBC_NVIEW_NDV1
|
||||
| ((i == len - 1) ? 0 : XDMA_UBC_NDE_FETCH_EN)
|
||||
| len;
|
||||
dmaReadLinkList[i].src_addr = (void*)Rhr;
|
||||
dmaReadLinkList[i].dest_addr = & buf[i];
|
||||
if (i == len - 1)
|
||||
dmaReadLinkList[i].next_desc = 0;
|
||||
else
|
||||
dmaReadLinkList[i].next_desc =
|
||||
& dmaReadLinkList[i + 1];
|
||||
}
|
||||
twi_dmaCfg.cfg.uint32_value = XDMAC_CC_TYPE_PER_TRAN
|
||||
| XDMAC_CC_MBSIZE_SINGLE
|
||||
| XDMAC_CC_DSYNC_PER2MEM
|
||||
| XDMAC_CC_CSIZE_CHK_1
|
||||
| XDMAC_CC_DWIDTH_BYTE
|
||||
| XDMAC_CC_SIF_AHB_IF1
|
||||
| XDMAC_CC_DIF_AHB_IF0
|
||||
| XDMAC_CC_SAM_FIXED_AM
|
||||
| XDMAC_CC_DAM_INCREMENTED_AM
|
||||
|
|
||||
XDMAC_CC_PERID(get_peripheral_xdma_channel(twi_id, XDMAC0, false));
|
||||
xdmaCndc =
|
||||
XDMAC_CNDC_NDVIEW_NDV1 | XDMAC_CNDC_NDE_DSCR_FETCH_EN |
|
||||
XDMAC_CNDC_NDSUP_SRC_PARAMS_UPDATED |
|
||||
XDMAC_CNDC_NDDUP_DST_PARAMS_UPDATED;
|
||||
cp15_coherent_dcache_for_dma((uint32_t) & dmaReadLinkList,
|
||||
((uint32_t) & dmaReadLinkList +
|
||||
sizeof (*dmaReadLinkList) * len));
|
||||
xdmad_configure_transfer(dmaReadChannel, &twi_dmaCfg, xdmaCndc,
|
||||
dmaReadLinkList);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Interrupt handler for a TWI peripheral. Manages asynchronous transfer
|
||||
* occuring on the bus. This function MUST be called by the interrupt service
|
||||
* routine of the TWI peripheral if asynchronous read/write are needed.
|
||||
* \param pTwid Pointer to a Twid instance.
|
||||
*/
|
||||
void twid_handler(struct _twid* pTwid)
|
||||
{
|
||||
uint32_t status;
|
||||
struct _async_twi* pTransfer;
|
||||
Twi *pTwi;
|
||||
|
||||
assert(pTwid != NULL);
|
||||
|
||||
pTransfer = (struct _async_twi *) pTwid->pTransfer;
|
||||
assert(pTransfer != NULL);
|
||||
pTwi = pTwid->pTwi;
|
||||
assert(pTwi != NULL);
|
||||
|
||||
/* Retrieve interrupt status */
|
||||
status = twi_get_masked_status(pTwi);
|
||||
|
||||
/* Byte received */
|
||||
if (TWI_STATUS_RXRDY(status)) {
|
||||
|
||||
pTransfer->pData[pTransfer->transferred] = twi_read_byte(pTwi);
|
||||
pTransfer->transferred++;
|
||||
|
||||
/* check for transfer finish */
|
||||
if (pTransfer->transferred == pTransfer->num) {
|
||||
|
||||
twi_enable_it(pTwi, TWI_IDR_RXRDY);
|
||||
twi_enable_it(pTwi, TWI_IER_TXCOMP);
|
||||
}
|
||||
/* Last byte? */
|
||||
else if (pTransfer->transferred == (pTransfer->num - 1)) {
|
||||
|
||||
twi_stop(pTwi);
|
||||
}
|
||||
}
|
||||
/* Byte sent */
|
||||
else if (TWI_STATUS_TXRDY(status)) {
|
||||
|
||||
/* Transfer finished ? */
|
||||
if (pTransfer->transferred == pTransfer->num) {
|
||||
|
||||
twi_enable_it(pTwi, TWI_IDR_TXRDY);
|
||||
twi_enable_it(pTwi, TWI_IER_TXCOMP);
|
||||
twi_send_stop_condition(pTwi);
|
||||
}
|
||||
/* Bytes remaining */
|
||||
else {
|
||||
|
||||
twi_write_byte(pTwi,
|
||||
pTransfer->pData[pTransfer->transferred]);
|
||||
pTransfer->transferred++;
|
||||
}
|
||||
}
|
||||
/* Transfer complete */
|
||||
else if (TWI_STATUS_TXCOMP(status)) {
|
||||
|
||||
twi_enable_it(pTwi, TWI_IDR_TXCOMP);
|
||||
pTransfer->status = 0;
|
||||
if (pTransfer->callback) {
|
||||
pTransfer->callback((struct _async *) (void *) pTransfer);
|
||||
}
|
||||
pTwid->pTransfer = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Asynchronously reads data from a slave on the TWI bus. An optional
|
||||
* callback function is triggered when the transfer is complete.
|
||||
* \param pTwid Pointer to a Twid instance.
|
||||
* \param address TWI slave address.
|
||||
* \param iaddress Optional slave internal address.
|
||||
* \param isize Internal address size in bytes.
|
||||
* \param pData Data buffer for storing received bytes.
|
||||
* \param num Number of bytes to read.
|
||||
* \param pAsync Asynchronous transfer descriptor.
|
||||
* \return 0 if the transfer has been started; otherwise returns a TWI error code.
|
||||
*/
|
||||
uint8_t twid_read(struct _twid* pTwid, uint8_t address, uint32_t iaddress,
|
||||
uint8_t isize, uint8_t * pData, uint32_t num, struct _async * pAsync)
|
||||
{
|
||||
Twi *pTwi;
|
||||
struct _async_twi* pTransfer;
|
||||
uint32_t timeout = 0;
|
||||
uint32_t i = 0;
|
||||
uint32_t status;
|
||||
|
||||
assert(pTwid != NULL);
|
||||
pTwi = pTwid->pTwi;
|
||||
pTransfer = (struct _async_twi*) pTwid->pTransfer;
|
||||
|
||||
assert((address & 0x80) == 0);
|
||||
assert((iaddress & 0xFF000000) == 0);
|
||||
assert(isize < 4);
|
||||
|
||||
/* Check that no transfer is already pending */
|
||||
if (pTransfer) {
|
||||
|
||||
trace_error("twid_read: A transfer is already pending\n\r");
|
||||
return TWID_ERROR_BUSY;
|
||||
}
|
||||
|
||||
/* Asynchronous transfer */
|
||||
if (pAsync) {
|
||||
|
||||
/* Update the transfer descriptor */
|
||||
pTwid->pTransfer = pAsync;
|
||||
pTransfer = (struct _async_twi*) pAsync;
|
||||
pTransfer->status = ASYNC_STATUS_PENDING;
|
||||
pTransfer->pData = pData;
|
||||
pTransfer->num = num;
|
||||
pTransfer->transferred = 0;
|
||||
|
||||
/* Enable read interrupt and start the transfer */
|
||||
twi_enable_it(pTwi, TWI_IER_RXRDY);
|
||||
twi_start_read(pTwi, address, iaddress, isize);
|
||||
}
|
||||
/* Synchronous transfer */
|
||||
else {
|
||||
|
||||
/* Start read */
|
||||
twi_start_read(pTwi, address, iaddress, isize);
|
||||
if (num != 1) {
|
||||
status = twi_get_status(pTwi);
|
||||
|
||||
if (status & TWI_SR_NACK)
|
||||
trace_error("TWID NACK error\n\r");
|
||||
timeout = 0;
|
||||
while (!(status & TWI_SR_RXRDY)
|
||||
&& (++timeout < TWITIMEOUTMAX)) {
|
||||
status = twi_get_status(pTwi);
|
||||
//trace_error("TWID status %x\n\r",twi_get_status(pTwi));
|
||||
}
|
||||
|
||||
pData[0] = twi_read_byte(pTwi);
|
||||
for (i = 1; i < num - 1; i++) {
|
||||
status = twi_get_status(pTwi);
|
||||
if (status & TWI_SR_NACK)
|
||||
trace_error("TWID NACK error\n\r");
|
||||
timeout = 0;
|
||||
while (!(status & TWI_SR_RXRDY)
|
||||
&& (++timeout < TWITIMEOUTMAX)) {
|
||||
status = twi_get_status(pTwi);
|
||||
//trace_error("TWID status %x\n\r",twi_get_status(pTwi));
|
||||
}
|
||||
pData[i] = twi_read_byte(pTwi);
|
||||
}
|
||||
}
|
||||
twi_stop(pTwi);
|
||||
status = twi_get_status(pTwi);
|
||||
if (status & TWI_SR_NACK)
|
||||
trace_error("TWID NACK error\n\r");
|
||||
timeout = 0;
|
||||
while (!(status & TWI_SR_RXRDY) && (++timeout < TWITIMEOUTMAX)) {
|
||||
status = twi_get_status(pTwi);
|
||||
//trace_error("TWID status %x\n\r",twi_get_status(pTwi));
|
||||
}
|
||||
|
||||
pData[i] = twi_read_byte(pTwi);
|
||||
timeout = 0;
|
||||
status = twi_get_status(pTwi);
|
||||
while (!(status & TWI_SR_TXCOMP) && (++timeout < TWITIMEOUTMAX)) {
|
||||
status = twi_get_status(pTwi);
|
||||
//trace_error("TWID status %x\n\r",twi_get_status(pTwi));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Asynchronously reads data from a slave on the TWI bus. An optional
|
||||
* callback function is triggered when the transfer is complete.
|
||||
* \param pTwid Pointer to a Twid instance.
|
||||
* \param address TWI slave address.
|
||||
* \param iaddress Optional slave internal address.
|
||||
* \param isize Internal address size in bytes.
|
||||
* \param pData Data buffer for storing received bytes.
|
||||
* \param num Number of bytes to read.
|
||||
* \param pAsync Asynchronous transfer descriptor.
|
||||
* \param twi_id TWI ID for TWI0, TWI1, TWI2.
|
||||
* \return 0 if the transfer has been started; otherwise returns a TWI error code.
|
||||
*/
|
||||
uint8_t twid_dma_read(struct _twid* pTwid, uint8_t address, uint32_t iaddress,
|
||||
uint8_t isize, uint8_t * pData, uint32_t num, struct _async * pAsync, uint8_t twi_id)
|
||||
{
|
||||
Twi *pTwi;
|
||||
struct _async_twi* pTransfer;
|
||||
uint32_t timeout = 0;
|
||||
uint32_t status;
|
||||
|
||||
assert(pTwid != NULL);
|
||||
pTwi = pTwid->pTwi;
|
||||
pTransfer = (struct _async_twi*) pTwid->pTransfer;
|
||||
|
||||
assert((address & 0x80) == 0);
|
||||
assert((iaddress & 0xFF000000) == 0);
|
||||
assert(isize < 4);
|
||||
|
||||
/* Check that no transfer is already pending */
|
||||
if (pTransfer) {
|
||||
|
||||
trace_error("twid_read: A transfer is already pending\n\r");
|
||||
return TWID_ERROR_BUSY;
|
||||
}
|
||||
|
||||
/* Asynchronous transfer */
|
||||
if (pAsync) {
|
||||
|
||||
/* Update the transfer descriptor */
|
||||
pTwid->pTransfer = pAsync;
|
||||
pTransfer = (struct _async_twi*) pAsync;
|
||||
pTransfer->status = ASYNC_STATUS_PENDING;
|
||||
pTransfer->pData = pData;
|
||||
pTransfer->num = num;
|
||||
pTransfer->transferred = 0;
|
||||
|
||||
/* Enable read interrupt and start the transfer */
|
||||
twi_enable_it(pTwi, TWI_IER_RXRDY);
|
||||
twi_start_read(pTwi, address, iaddress, isize);
|
||||
}
|
||||
/* Synchronous transfer */
|
||||
else {
|
||||
|
||||
twid_dma_initialize_read(twi_id);
|
||||
_xdma_configure_read(pData, num, twi_id);
|
||||
/* Start read */
|
||||
xdmad_start_transfer(dmaReadChannel);
|
||||
|
||||
twi_start_read(pTwi, address, iaddress, isize);
|
||||
|
||||
while ((!xdmad_is_transfer_done(dmaReadChannel))
|
||||
&& (++timeout < TWITIMEOUTMAX))
|
||||
xdmad_poll();
|
||||
|
||||
xdmad_stop_transfer(dmaReadChannel);
|
||||
|
||||
status = twi_get_status(pTwi);
|
||||
timeout = 0;
|
||||
while (!(status & TWI_SR_RXRDY)
|
||||
&& (++timeout < TWITIMEOUTMAX)) ;
|
||||
|
||||
twi_stop(pTwi);
|
||||
|
||||
twi_read_byte(pTwi);
|
||||
|
||||
status = twi_get_status(pTwi);
|
||||
timeout = 0;
|
||||
while (!(status & TWI_SR_RXRDY)
|
||||
&& (++timeout < TWITIMEOUTMAX)) ;
|
||||
|
||||
twi_read_byte(pTwi);
|
||||
|
||||
status = twi_get_status(pTwi);
|
||||
timeout = 0;
|
||||
while (!(status & TWI_SR_TXCOMP)
|
||||
&& (++timeout < TWITIMEOUTMAX)) ;
|
||||
if (timeout == TWITIMEOUTMAX) {
|
||||
trace_error("TWID Timeout Read\n\r");
|
||||
}
|
||||
xdmad_free_channel(dmaReadChannel);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Asynchronously sends data to a slave on the TWI bus. An optional callback
|
||||
* function is invoked whenever the transfer is complete.
|
||||
* \param pTwid Pointer to a Twid instance.
|
||||
* \param address TWI slave address.
|
||||
* \param iaddress Optional slave internal address.
|
||||
* \param isize Number of internal address bytes.
|
||||
* \param pData Data buffer for storing received bytes.
|
||||
* \param num Data buffer to send.
|
||||
* \param pAsync Asynchronous transfer descriptor.
|
||||
* \param twi_id TWI ID for TWI0, TWI1, TWI2.
|
||||
* \return 0 if the transfer has been started; otherwise returns a TWI error code.
|
||||
*/
|
||||
uint8_t twid_dma_write(struct _twid* pTwid, uint8_t address, uint32_t iaddress,
|
||||
uint8_t isize, uint8_t * pData, uint32_t num, struct _async * pAsync, uint8_t twi_id)
|
||||
{
|
||||
Twi *pTwi = pTwid->pTwi;
|
||||
struct _async_twi* pTransfer;
|
||||
uint32_t timeout = 0;
|
||||
uint32_t status;
|
||||
//uint8_t singleTransfer = 0;
|
||||
|
||||
assert(pTwi != NULL);
|
||||
assert((address & 0x80) == 0);
|
||||
assert((iaddress & 0xFF000000) == 0);
|
||||
assert(isize < 4);
|
||||
|
||||
pTransfer = (struct _async_twi *) pTwid->pTransfer;
|
||||
// if(num == 1) singleTransfer = 1;
|
||||
/* Check that no transfer is already pending */
|
||||
if (pTransfer) {
|
||||
trace_error("TWI_Write: A transfer is already pending\n\r");
|
||||
return TWID_ERROR_BUSY;
|
||||
}
|
||||
|
||||
/* Asynchronous transfer */
|
||||
if (pAsync) {
|
||||
/* Update the transfer descriptor */
|
||||
pTwid->pTransfer = pAsync;
|
||||
pTransfer = (struct _async_twi*) pAsync;
|
||||
pTransfer->status = ASYNC_STATUS_PENDING;
|
||||
pTransfer->pData = pData;
|
||||
pTransfer->num = num;
|
||||
pTransfer->transferred = 1;
|
||||
/* Enable write interrupt and start the transfer */
|
||||
twi_start_write(pTwi, address, iaddress, isize, *pData);
|
||||
twi_enable_it(pTwi, TWI_IER_TXRDY);
|
||||
}
|
||||
/* Synchronous transfer */
|
||||
else {
|
||||
cp15_coherent_dcache_for_dma((uint32_t) pData, (uint32_t) pData);
|
||||
twid_dma_initialize_write(twi_id);
|
||||
_xdma_configure_write(pData, num, twi_id);
|
||||
/* Set slave address and number of internal address bytes. */
|
||||
pTwi->TWI_MMR = 0;
|
||||
pTwi->TWI_MMR = (isize << 8) | (address << 16);
|
||||
/* Set internal address bytes. */
|
||||
pTwi->TWI_IADR = 0;
|
||||
pTwi->TWI_IADR = iaddress;
|
||||
xdmad_start_transfer(dmaWriteChannel);
|
||||
while (!xdmad_is_transfer_done(dmaWriteChannel))
|
||||
xdmad_poll();
|
||||
xdmad_stop_transfer(dmaWriteChannel);
|
||||
status = twi_get_status(pTwi);
|
||||
timeout = 0;
|
||||
while (!(status & TWI_SR_TXRDY) && (timeout++ < TWITIMEOUTMAX)) {
|
||||
status = twi_get_status(pTwi);
|
||||
}
|
||||
if (timeout == TWITIMEOUTMAX) {
|
||||
trace_error("TWID Timeout TXRDY\n\r");
|
||||
}
|
||||
/* Send a STOP condition */
|
||||
twi_stop(pTwi);
|
||||
status = twi_get_status(pTwi);
|
||||
timeout = 0;
|
||||
while (!(status & TWI_SR_TXCOMP) && (++timeout < TWITIMEOUTMAX)) {
|
||||
status = twi_get_status(pTwi);
|
||||
}
|
||||
if (timeout == TWITIMEOUTMAX) {
|
||||
trace_error("TWID Timeout Write\n\r");
|
||||
}
|
||||
cp15_invalidate_dcache_for_dma((uint32_t) pData, (uint32_t) (pData));
|
||||
xdmad_free_channel(dmaWriteChannel);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Asynchronously sends data to a slave on the TWI bus. An optional callback
|
||||
* function is invoked whenever the transfer is complete.
|
||||
* \param pTwid Pointer to a Twid instance.
|
||||
* \param address TWI slave address.
|
||||
* \param iaddress Optional slave internal address.
|
||||
* \param isize Number of internal address bytes.
|
||||
* \param pData Data buffer for storing received bytes.
|
||||
* \param num Data buffer to send.
|
||||
* \param pAsync Asynchronous transfer descriptor.
|
||||
* \return 0 if the transfer has been started; otherwise returns a TWI error code.
|
||||
*/
|
||||
uint8_t twid_write(struct _twid* pTwid, uint8_t address, uint32_t iaddress,
|
||||
uint8_t isize, uint8_t * pData, uint32_t num, struct _async * pAsync)
|
||||
{
|
||||
Twi *pTwi = pTwid->pTwi;
|
||||
struct _async_twi* pTransfer;
|
||||
uint32_t timeout = 0;
|
||||
uint32_t status;
|
||||
uint8_t singleTransfer = 0;
|
||||
|
||||
assert(pTwi != NULL);
|
||||
assert((address & 0x80) == 0);
|
||||
assert((iaddress & 0xFF000000) == 0);
|
||||
assert(isize < 4);
|
||||
|
||||
pTransfer = (struct _async_twi *) pTwid->pTransfer;
|
||||
if (num == 1)
|
||||
singleTransfer = 1;
|
||||
/* Check that no transfer is already pending */
|
||||
if (pTransfer) {
|
||||
trace_error("TWI_Write: A transfer is already pending\n\r");
|
||||
return TWID_ERROR_BUSY;
|
||||
}
|
||||
/* Asynchronous transfer */
|
||||
if (pAsync) {
|
||||
/* Update the transfer descriptor */
|
||||
pTwid->pTransfer = pAsync;
|
||||
pTransfer = (struct _async_twi*) pAsync;
|
||||
pTransfer->status = ASYNC_STATUS_PENDING;
|
||||
pTransfer->pData = pData;
|
||||
pTransfer->num = num;
|
||||
pTransfer->transferred = 1;
|
||||
/* Enable write interrupt and start the transfer */
|
||||
twi_start_write(pTwi, address, iaddress, isize, *pData);
|
||||
twi_enable_it(pTwi, TWI_IER_TXRDY);
|
||||
}
|
||||
/* Synchronous transfer */
|
||||
else {
|
||||
// Start write
|
||||
twi_start_write(pTwi, address, iaddress, isize, *pData++);
|
||||
num--;
|
||||
if (singleTransfer) {
|
||||
/* Send a STOP condition */
|
||||
twi_send_stop_condition(pTwi);
|
||||
}
|
||||
status = twi_get_status(pTwi);
|
||||
if (status & TWI_SR_NACK)
|
||||
trace_error("TWID NACK error\n\r");
|
||||
while (!(status & TWI_SR_TXRDY) && (timeout++ < TWITIMEOUTMAX)) {
|
||||
status = twi_get_status(pTwi);
|
||||
}
|
||||
if (timeout == TWITIMEOUTMAX) {
|
||||
trace_error("TWID Timeout BS\n\r");
|
||||
}
|
||||
timeout = 0;
|
||||
/* Send all bytes */
|
||||
while (num > 0) {
|
||||
/* Wait before sending the next byte */
|
||||
timeout = 0;
|
||||
twi_write_byte(pTwi, *pData++);
|
||||
status = twi_get_status(pTwi);
|
||||
if (status & TWI_SR_NACK)
|
||||
trace_error("TWID NACK error\n\r");
|
||||
while (!(status & TWI_SR_TXRDY)
|
||||
&& (timeout++ < TWITIMEOUTMAX)) {
|
||||
status = twi_get_status(pTwi);
|
||||
}
|
||||
if (timeout == TWITIMEOUTMAX) {
|
||||
trace_error("TWID Timeout BS\n\r");
|
||||
}
|
||||
num--;
|
||||
}
|
||||
/* Wait for actual end of transfer */
|
||||
timeout = 0;
|
||||
if (!singleTransfer) {
|
||||
/* Send a STOP condition */
|
||||
twi_send_stop_condition(pTwi);
|
||||
}
|
||||
while (!twi_is_transfer_complete(pTwi)
|
||||
&& (++timeout < TWITIMEOUTMAX)) ;
|
||||
if (timeout == TWITIMEOUTMAX) {
|
||||
trace_error("TWID Timeout TC2\n\r");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#ifndef _TWID_
|
||||
#define _TWID_
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Headers
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#include "board.h"
|
||||
#include "peripherals/twi.h"
|
||||
#include "async.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Definition
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/** TWI driver is currently busy. */
|
||||
#define TWID_ERROR_BUSY 1
|
||||
|
||||
// TWI clock frequency in Hz.
|
||||
#define TWCK_400K 400000
|
||||
#define TWCK_200K 200000
|
||||
#define TWCK_100K 100000
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Types
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
/** \brief TWI driver structure. Holds the internal state of the driver.*/
|
||||
struct _twid {
|
||||
Twi *pTwi; /** Pointer to the underlying TWI peripheral.*/
|
||||
struct _async *pTransfer; /** Current asynchronous transfer being processed.*/
|
||||
};
|
||||
|
||||
struct _handler_twi
|
||||
{
|
||||
uint8_t IdTwi; // ID TWI
|
||||
uint8_t Status; // status of the TWI
|
||||
uint8_t PeriphAddr; // Address of the component
|
||||
uint8_t LenData; // Lenfth of the data to be read or write
|
||||
uint8_t AddSize; // Size of the address
|
||||
uint16_t RegMemAddr; // Address of the memory or register
|
||||
uint32_t Twck; // default clock of the bus TWI
|
||||
uint8_t* pData; // pointer to a data buffer
|
||||
struct _twid twid;
|
||||
};
|
||||
|
||||
|
||||
enum TWI_CMD
|
||||
{
|
||||
TWI_RD = 0,
|
||||
TWI_WR = 1
|
||||
};
|
||||
|
||||
enum TWI_STATUS
|
||||
{
|
||||
TWI_STATUS_RESET = 0,
|
||||
TWI_STATUS_HANDLE = 1u<<0,
|
||||
TWI_STATUS_RFU2 = 1u<<1,
|
||||
TWI_STATUS_RFU3 = 1u<<2,
|
||||
TWI_STATUS_RFU4 = 1u<<3,
|
||||
TWI_STATUS_READY = 1u<<7,
|
||||
};
|
||||
|
||||
enum TWI_RESULT
|
||||
{
|
||||
TWI_SUCCES = 0,
|
||||
TWI_FAIL = 1
|
||||
};
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
* Export functions
|
||||
*----------------------------------------------------------------------------*/
|
||||
extern void twid_initialize(struct _twid* pTwid, Twi * pTwi);
|
||||
|
||||
extern void twid_handler(struct _twid* pTwid);
|
||||
|
||||
extern uint8_t twid_read(struct _twid* pTwid, uint8_t address, uint32_t iaddress,
|
||||
uint8_t isize, uint8_t * pData, uint32_t num, struct _async * pAsync);
|
||||
|
||||
extern uint8_t twid_dma_read(struct _twid* pTwid, uint8_t address, uint32_t iaddress,
|
||||
uint8_t isize, uint8_t * pData, uint32_t num,
|
||||
struct _async * pAsync, uint8_t TWI_ID);
|
||||
|
||||
extern uint8_t twid_write(struct _twid* pTwid, uint8_t address, uint32_t iaddress,
|
||||
uint8_t isize, uint8_t * pData, uint32_t num, struct _async * pAsync);
|
||||
|
||||
extern uint8_t twid_dma_write(struct _twid* pTwid, uint8_t address,
|
||||
uint32_t iaddress, uint8_t isize, uint8_t * pData,
|
||||
uint32_t num, struct _async * pAsync, uint8_t TWI_ID);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif //#ifndef TWID_H
|
|
@ -0,0 +1,135 @@
|
|||
/* ----------------------------------------------------------------------------
|
||||
* SAM Software Package License
|
||||
* ----------------------------------------------------------------------------
|
||||
* Copyright (c) 2015, Atmel Corporation
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the disclaimer below.
|
||||
*
|
||||
* Atmel's name may not be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
|
||||
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
|
||||
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
|
||||
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Headers
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
#include "chip.h"
|
||||
#include "peripherals/uart.h"
|
||||
#include "peripherals/pmc.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Exported functions
|
||||
*------------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
* Initializes the UART with the given parameters, and enables both the
|
||||
* transmitter and the receiver. The mode parameter contains the value of the
|
||||
* UART_MR register.
|
||||
* Value UART_STANDARD can be used for mode to get the most common configuration
|
||||
* (i.e. aysnchronous, 8bits, no parity, 1 stop bit, no flow control).
|
||||
* \param mode Operating mode to configure.
|
||||
* \param baudrate Desired baudrate (e.g. 115200).
|
||||
* \param mck Frequency of the system master clock in Hz.
|
||||
*/
|
||||
void uart_configure(Uart* pUart, uint32_t mode, uint32_t baudrate)
|
||||
{
|
||||
uint32_t uart_id = get_uart_id_from_addr(pUart);
|
||||
// Reset & disable receiver and transmitter, disable interrupts
|
||||
pUart->UART_CR = UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | UART_CR_TXDIS
|
||||
| UART_CR_RSTSTA;
|
||||
pUart->UART_IDR = 0xFFFFFFFF;
|
||||
// Configure baud rate
|
||||
pUart->UART_BRGR = pmc_get_peripheral_clock(uart_id) / (baudrate * 16);
|
||||
// Configure mode register
|
||||
pUart->UART_MR = mode;
|
||||
// Enable receiver and transmitter
|
||||
pUart->UART_CR = UART_CR_RXEN | UART_CR_TXEN;
|
||||
}
|
||||
|
||||
/* Enable transmitter
|
||||
*
|
||||
*/
|
||||
void uart_set_transmitter_enabled (Uart* pUart, uint8_t enabled)
|
||||
{
|
||||
if (enabled) pUart->UART_CR = UART_CR_TXEN;
|
||||
else pUart->UART_CR = UART_CR_TXDIS;
|
||||
}
|
||||
|
||||
/* Enable receiver
|
||||
*
|
||||
*/
|
||||
void uart_set_receiver_enabled (Uart* pUart, uint8_t enabled)
|
||||
{
|
||||
if (enabled)
|
||||
pUart->UART_CR = UART_CR_RXEN;
|
||||
else
|
||||
pUart->UART_CR = UART_CR_RXDIS;
|
||||
}
|
||||
|
||||
/* Set interrupt register
|
||||
*
|
||||
*/
|
||||
void uart_set_int (Uart* pUart, uint32_t int_mask)
|
||||
{
|
||||
pUart->UART_IER |= int_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs a character on the UART line.
|
||||
* \note This function is synchronous (i.e. uses polling).
|
||||
* \param c Character to send.
|
||||
*/
|
||||
void uart_put_char(Uart* pUart, uint8_t c)
|
||||
{
|
||||
// Wait for the transmitter to be ready
|
||||
while ((pUart->UART_SR & UART_SR_TXEMPTY) == 0);
|
||||
// Send character
|
||||
pUart->UART_THR = c;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return 1 if a character can be read in UART
|
||||
*/
|
||||
uint32_t uart_is_rx_ready(Uart* pUart)
|
||||
{
|
||||
return (pUart->UART_SR & UART_SR_RXRDY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return 1 if a character can be write in UART
|
||||
*/
|
||||
uint32_t uart_is_tx_ready(Uart* pUart)
|
||||
{
|
||||
return (pUart->UART_SR & UART_SR_TXRDY);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Reads and returns a character from the UART.
|
||||
* \note This function is synchronous (i.e. uses polling).
|
||||
* \return Character received.
|
||||
*/
|
||||
uint8_t uart_get_char(Uart* pUart)
|
||||
{
|
||||
while ((pUart->UART_SR & UART_SR_RXRDY) == 0);
|
||||
return pUart->UART_RHR;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue