ext: move libmetal to hal
libmetal itself isn't an ipc library, its a generic HAL abstraction library so move it into ext/hal where it belongs. Signed-off-by: Kumar Gala <kumar.gala@linaro.org>
This commit is contained in:
commit
d8fa951a6e
|
@ -0,0 +1,41 @@
|
|||
libmetal
|
||||
#####################
|
||||
|
||||
Origin:
|
||||
https://github.com/OpenAMP/libmetal
|
||||
|
||||
Status:
|
||||
606c31438025b9fb1515dace1c642d5835d8d33c [v2018.04]
|
||||
|
||||
When we import libmetal we removed the tests/ and examples/ dir to reduce
|
||||
the amount of code imported.
|
||||
|
||||
Purpose:
|
||||
HAL abstraction layer used by open-amp
|
||||
|
||||
Description:
|
||||
Libmetal provides common user APIs to access devices, handle device
|
||||
interrupts and request memory across the following operating environments:
|
||||
|
||||
* Linux user space (based on UIO and VFIO support in the kernel)
|
||||
* RTOS (with and without virtual memory)
|
||||
* Bare-metal environments
|
||||
|
||||
Dependencies:
|
||||
Depends on Zephyr itself as it utilizes Zephyr's APIs to provide an
|
||||
abstraction to open-amp.
|
||||
|
||||
URL:
|
||||
https://github.com/OpenAMP/libmetal
|
||||
|
||||
commit:
|
||||
606c31438025b9fb1515dace1c642d5835d8d33c
|
||||
|
||||
Maintained-by:
|
||||
External
|
||||
|
||||
License:
|
||||
BSD-3-Clause
|
||||
|
||||
License Link:
|
||||
https://github.com/OpenAMP/libmetal/blob/master/LICENSE.md
|
|
@ -0,0 +1,12 @@
|
|||
include(ExternalProject)
|
||||
|
||||
ExternalProject_Add(
|
||||
libmetal # Name for custom target
|
||||
SOURCE_DIR $ENV{ZEPHYR_BASE}/ext/hal/libmetal/libmetal/
|
||||
INSTALL_COMMAND "" # This particular build system has no install command
|
||||
CMAKE_ARGS -DWITH_ZEPHYR=ON -DBOARD=${BOARD} -DWITH_DEFAULT_LOGGER=OFF -DWITH_DOC=OFF
|
||||
)
|
||||
|
||||
ExternalProject_Get_property(libmetal BINARY_DIR)
|
||||
set(LIBMETAL_INCLUDE_DIR ${BINARY_DIR}/lib/include)
|
||||
set(LIBMETAL_LIBRARY ${BINARY_DIR}/lib/libmetal.a)
|
|
@ -0,0 +1,18 @@
|
|||
*.o
|
||||
*~
|
||||
!libs/system/zc702evk/linux/lib/*/*.a
|
||||
*.bin
|
||||
*.map
|
||||
*.out
|
||||
*.log
|
||||
*.swp
|
||||
*.swo
|
||||
*.d
|
||||
build*/
|
||||
|
||||
/tags
|
||||
/TAGS
|
||||
|
||||
# cscope files
|
||||
cscope.*
|
||||
ncscope.*
|
|
@ -0,0 +1,100 @@
|
|||
language: minimal # setting language to C will override cross-compiler and fail
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
|
||||
sudo: required
|
||||
dist: trusty
|
||||
|
||||
env:
|
||||
global:
|
||||
- ZEPHYR_GCC_VARIANT=zephyr
|
||||
- ZEPHYR_SDK_INSTALL_DIR=/opt/zephyr-sdk
|
||||
- ZEPHYR_BASE=$TRAVIS_BUILD_DIR/deps/zephyr
|
||||
- ZEPHYR_SDK_VERSION=0.9.2
|
||||
- ZEPHYR_SDK_DOWNLOAD_FOLDER=https://github.com/zephyrproject-rtos/meta-zephyr-sdk/releases/download/$ZEPHYR_SDK_VERSION
|
||||
- ZEPHYR_SDK_SETUP_BINARY=zephyr-sdk-$ZEPHYR_SDK_VERSION-setup.run
|
||||
- ZEPHYR_SDK_DOWNLOAD_URL=$ZEPHYR_SDK_DOWNLOAD_FOLDER/$ZEPHYR_SDK_SETUP_BINARY
|
||||
- FREERTOS_ZIP_URL=https://downloads.sourceforge.net/project/freertos/FreeRTOS/V10.0.1/FreeRTOSv10.0.1.zip
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- os: linux
|
||||
env: TARGET="zephyr"
|
||||
- os: linux
|
||||
env: TARGET="linux"
|
||||
- os: linux
|
||||
env: TARGET="generic"
|
||||
- os: linux
|
||||
env: TARGET="freertos"
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $ZEPHYR_SDK_INSTALL_DIR
|
||||
- /usr/local/bin
|
||||
|
||||
before_install:
|
||||
- if [[ "$TARGET" == "zephyr" ]]; then
|
||||
sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test &&
|
||||
sudo apt-get update -qq &&
|
||||
sudo apt-get install libc6-dev-i386 make gperf gcc g++ python3-ply python3-yaml python3-pip device-tree-compiler ncurses-dev uglifyjs -qq &&
|
||||
sudo pip3 install pyelftools;
|
||||
fi
|
||||
- if [[ "$TARGET" == "linux" ]]; then
|
||||
sudo apt-get update -qq &&
|
||||
sudo apt-get install libsysfs-dev libhugetlbfs-dev make gcc;
|
||||
fi
|
||||
# This is to kick start CI on generic platform. Will need to have a proper way to get the required packages
|
||||
- if [[ "$TARGET" == "generic" || "$TARGET" == "freertos" ]]; then
|
||||
wget http://ppa.launchpad.net/team-gcc-arm-embedded/ppa/ubuntu/pool/main/g/gcc-arm-none-eabi/gcc-arm-embedded_7-2017q4-1~trusty3_amd64.deb &&
|
||||
sudo dpkg -i gcc-arm-embedded_7-2017q4-1~trusty3_amd64.deb;
|
||||
fi
|
||||
- if [[ "$TARGET" == "freertos" ]]; then
|
||||
wget $FREERTOS_ZIP_URL &&
|
||||
pwd && ls &&
|
||||
unzip FreeRTOSv10.0.1.zip > /dev/null;
|
||||
fi
|
||||
|
||||
install: >
|
||||
if [[ "$TARGET" == "zephyr" && "$(cat $ZEPHYR_SDK_INSTALL_DIR/sdk_version)" != "$ZEPHYR_SDK_VERSION" ]]; then
|
||||
wget $ZEPHYR_SDK_DOWNLOAD_URL &&
|
||||
chmod +x $ZEPHYR_SDK_SETUP_BINARY &&
|
||||
rm -rf $ZEPHYR_SDK_INSTALL_DIR &&
|
||||
./$ZEPHYR_SDK_SETUP_BINARY --quiet -- -y -d $ZEPHYR_SDK_INSTALL_DIR > /dev/null;
|
||||
fi
|
||||
|
||||
before_script: >
|
||||
if [[ "$TARGET" == "zephyr" ]]; then
|
||||
cd .. &&
|
||||
git clone --depth=1 https://github.com/zephyrproject-rtos/zephyr.git &&
|
||||
cd zephyr &&
|
||||
source zephyr-env.sh;
|
||||
fi
|
||||
|
||||
script:
|
||||
- if [[ "$TARGET" == "zephyr" ]]; then
|
||||
mkdir -p ../libmetal/build-zephyr &&
|
||||
cd ../libmetal/build-zephyr &&
|
||||
cmake .. -DWITH_ZEPHYR=on -DBOARD=qemu_cortex_m3 -DWITH_TESTS=on &&
|
||||
make VERBOSE=1;
|
||||
fi
|
||||
- if [[ "$TARGET" == "linux" ]]; then
|
||||
mkdir -p build-linux &&
|
||||
cd build-linux &&
|
||||
cmake .. -DWITH_TESTS_EXEC=on &&
|
||||
make VERBOSE=1 all test;
|
||||
fi
|
||||
- if [[ "$TARGET" == "generic" ]]; then
|
||||
mkdir -p build-generic &&
|
||||
cd build-generic &&
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=template-generic &&
|
||||
make VERBOSE=1;
|
||||
fi
|
||||
- if [[ "$TARGET" == "freertos" ]]; then
|
||||
mkdir -p build-freertos &&
|
||||
cd build-freertos &&
|
||||
export &&
|
||||
cmake .. -DCMAKE_TOOLCHAIN_FILE=template-freertos -DCMAKE_C_FLAGS="-I$PWD/../FreeRTOSv10.0.1/FreeRTOS/Source/include/ -I$PWD/../FreeRTOSv10.0.1/FreeRTOS/Demo/CORTEX_STM32F107_GCC_Rowley -I$PWD/../FreeRTOSv10.0.1/FreeRTOS/Source/portable/GCC/ARM_CM3" &&
|
||||
make VERBOSE=1;
|
||||
fi
|
|
@ -0,0 +1,37 @@
|
|||
cmake_minimum_required (VERSION 2.6)
|
||||
|
||||
list (APPEND CMAKE_MODULE_PATH
|
||||
"${CMAKE_SOURCE_DIR}/cmake"
|
||||
"${CMAKE_SOURCE_DIR}/cmake/modules"
|
||||
"${CMAKE_SOURCE_DIR}/cmake/platforms")
|
||||
|
||||
include (syscheck)
|
||||
project (metal C)
|
||||
|
||||
include (CheckIncludeFiles)
|
||||
include (CheckCSourceCompiles)
|
||||
include (collect)
|
||||
include (options)
|
||||
include (depends)
|
||||
|
||||
foreach(_inc_path ${CMAKE_INCLUDE_PATH})
|
||||
collect (PROJECT_INC_DIRS "${_inc_path}")
|
||||
endforeach()
|
||||
|
||||
enable_testing ()
|
||||
|
||||
add_subdirectory (lib)
|
||||
|
||||
if (WITH_TESTS)
|
||||
add_subdirectory (test)
|
||||
endif (WITH_TESTS)
|
||||
|
||||
if (WITH_DOC)
|
||||
add_subdirectory (doc)
|
||||
endif (WITH_DOC)
|
||||
|
||||
if (WITH_EXAMPLES)
|
||||
add_subdirectory (examples)
|
||||
endif (WITH_EXAMPLES)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,41 @@
|
|||
Software License Agreement (BSD License)
|
||||
========================================
|
||||
|
||||
Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of Xilinx nor the names of its contributors may be used
|
||||
to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 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.
|
||||
|
||||
|
||||
Notes
|
||||
=========================================
|
||||
Use the following tag instead of the full license text in the individual files:
|
||||
|
||||
SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
This enables machine processing of license information based on the SPDX
|
||||
License Identifiers that are here available: http://spdx.org/licenses/
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# libmetal Maintainers
|
||||
|
||||
libmetal project is maintained by the OpenAMP open source community.
|
||||
Everyone is encouraged to submit issues and changes to improve libmetal.
|
||||
|
||||
The intention of this file is to provide a set of names that developers can
|
||||
consult when they have a question about OpenAMP and to provide a a set of
|
||||
names to be CC'd when submitting a patch.
|
||||
|
||||
## Project Administration
|
||||
Wendy Liang <wendy.liang@xilinx.com>
|
||||
|
||||
### All patches CC here
|
||||
open-amp@googlegroups.com
|
||||
|
||||
## Machines
|
||||
### Xilinx Platform - Zynq-7000
|
||||
Wendy Liang <wendy.liang@xilinx.com>
|
||||
|
||||
### Xilinx Platform - Zynq UltraScale+ MPSoC
|
||||
Wendy Liang <wendy.liang@xilinx.com>
|
|
@ -0,0 +1,220 @@
|
|||
# libmetal
|
||||
|
||||
## Overview
|
||||
|
||||
Libmetal provides common user APIs to access devices, handle device interrupts
|
||||
and request memory across the following operating environments:
|
||||
* Linux user space (based on UIO and VFIO support in the kernel)
|
||||
* RTOS (with and without virtual memory)
|
||||
* Bare-metal environments
|
||||
|
||||
## Build Steps
|
||||
|
||||
### Building for Linux Host
|
||||
```
|
||||
$ git clone https://github.com/OpenAMP/libmetal.git
|
||||
$ mkdir -p libmetal/<build directory>
|
||||
$ cd libmetal/<build directory>
|
||||
$ cmake ..
|
||||
$ make VERBOSE=1 DESTDIR=<libmetal install location> install
|
||||
```
|
||||
|
||||
### Cross Compiling for Linux Target
|
||||
Use [meta-openamp](https://github.com/openamp/meta-openamp) to build
|
||||
libmetal library.
|
||||
Use package `libmetal` in your yocto config file.
|
||||
|
||||
### Building for Baremetal
|
||||
|
||||
To build on baremetal, you will need to provide a toolchain file. Here is an
|
||||
example toolchain file:
|
||||
```
|
||||
set (CMAKE_SYSTEM_PROCESSOR "arm" CACHE STRING "")
|
||||
set (MACHINE "zynqmp_r5" CACHE STRING "")
|
||||
|
||||
set (CROSS_PREFIX "armr5-none-eabi-" CACHE STRING "")
|
||||
set (CMAKE_C_FLAGS "-mfloat-abi=soft -mcpu=cortex-r5 -Wall -Werror -Wextra \
|
||||
-flto -Os -I/ws/xsdk/r5_0_bsp/psu_cortexr5_0/include" CACHE STRING "")
|
||||
|
||||
SET(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -flto")
|
||||
SET(CMAKE_AR "gcc-ar" CACHE STRING "")
|
||||
SET(CMAKE_C_ARCHIVE_CREATE "<CMAKE_AR> qcs <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
SET(CMAKE_C_ARCHIVE_FINISH true)
|
||||
|
||||
include (cross-generic-gcc)
|
||||
```
|
||||
* Note: other toolchain files can be found in the `cmake/platforms/` directory.
|
||||
* Compile with your toolchain file.
|
||||
```
|
||||
$ mkdir -p build-libmetal
|
||||
$ cd build-libmetal
|
||||
$ cmake <libmetal_source> -DCMAKE_TOOLCHAIN_FILE=<toolchain_file>
|
||||
$ make VERBOSE=1 DESTDIR=<libmetal_install> install
|
||||
```
|
||||
|
||||
### Building for Zephyr
|
||||
As Zephyr uses CMake, we build libmetal library and test application as
|
||||
targets of Zephyr CMake project. Here is how to build libmetal for Zephyr:
|
||||
```
|
||||
$ export ZEPHYR_GCC_VARIANT=zephyr
|
||||
$ export ZEPHYR_SDK_INSTALL_DIR=<where Zephyr SDK is installed>
|
||||
$ source <git_clone_zephyr_project_source_root>/zephyr-env.sh
|
||||
|
||||
$ cmake <libmetal_source_root> -DWITH_ZEPHYR=on -DBOARD=qemu_cortex_m3 \
|
||||
[-DWITH_TESTS=on]
|
||||
$ make VERBOSE=1 all
|
||||
# If we have turned on tests with "-DWITH_TESTS=on" when we run cmake,
|
||||
# we launch libmetal test on Zephyr QEMU platform as follows:
|
||||
$ make VERBOSE=1 run
|
||||
```
|
||||
|
||||
## Interfaces
|
||||
|
||||
The following subsections give an overview of interfaces provided by libmetal.
|
||||
|
||||
### Platform and OS Independent Utilities
|
||||
|
||||
These interfaces do not need to be ported across to new operating systems.
|
||||
|
||||
#### I/O
|
||||
|
||||
The libmetal I/O region abstraction provides access to memory mapped I/O and
|
||||
shared memory regions. This includes:
|
||||
* primitives to read and write memory with ordering constraints, and
|
||||
* ability to translate between physical and virtual addressing on systems
|
||||
that support virtual memory.
|
||||
|
||||
#### Log
|
||||
|
||||
The libmetal logging interface is used to plug log messages generated by
|
||||
libmetal into application specific logging mechanisms (e.g. syslog). This
|
||||
also provides basic message prioritization and filtering mechanisms.
|
||||
|
||||
#### List
|
||||
|
||||
This is a simple doubly linked list implementation used internally within
|
||||
libmetal, and also available for application use.
|
||||
|
||||
#### Other Utilities
|
||||
|
||||
The following utilities are provided in lib/utilities.h:
|
||||
* Min/max, round up/down, etc.
|
||||
* Bitmap operations
|
||||
* Helper to compute container structure pointers
|
||||
* ... and more ...
|
||||
|
||||
#### Version
|
||||
|
||||
The libmetal version interface allows user to get the version of the library.
|
||||
|
||||
### Top Level Interfaces
|
||||
|
||||
The users will need to call two top level interfaces to use libmetal APIs:
|
||||
* metal_init - initialize the libmetal resource
|
||||
* metal_finish - release libmetal resource
|
||||
|
||||
Each system needs to have their own implementation inside libmetal for these
|
||||
two APIs to call:
|
||||
* metal_sys_init
|
||||
* metal_sys_finish
|
||||
|
||||
For the current release, libmetal provides Linux userspace and bare-metal
|
||||
implementation for metal_sys_init and metal_sys_finish.
|
||||
|
||||
For Linux userspace, metal_sys_init sets up a table for available shared pages,
|
||||
checks whether UIO/VFIO drivers are avail, and starts interrupt handling
|
||||
thread.
|
||||
|
||||
For bare-metal, metal_sys_init and metal_sys_finish just returns.
|
||||
|
||||
### Atomics
|
||||
|
||||
The libmetal atomic operations API is consistent with the C11/C++11 stdatomics
|
||||
interface. The stdatomics interface is commonly provided by recent toolchains
|
||||
including GCC and LLVM/Clang. When porting to a different toolchain, it may be
|
||||
necessary to provide an stdatomic compatible implementation if the toolchain
|
||||
does not already provide one.
|
||||
|
||||
### Alloc
|
||||
|
||||
libmetal provides memory allocation and release APIs.
|
||||
|
||||
### Locking
|
||||
|
||||
libmetal provides the following locking APIs.
|
||||
|
||||
#### Mutex
|
||||
|
||||
libmetal has a generic mutex implementation which is a busy wait. It is
|
||||
recommended to have OS specific implementation for mutex.
|
||||
|
||||
The Linux userspace mutex implementation uses futex to wait for the lock
|
||||
and wakeup a waiter.
|
||||
|
||||
#### Condition Variable
|
||||
libmetal condition variable APIs provide "wait" for user applications to wait
|
||||
on some condition to be met, and "signal" to indicate a particular even occurs.
|
||||
|
||||
#### Spinlock
|
||||
libmetal spinlock APIs provides busy waiting mechanism to acquire a lock.
|
||||
|
||||
### Shmem
|
||||
|
||||
libmetal has a generic static shared memory implementation. If your OS has a
|
||||
global shared memory allocation, you will need to port it for the OS.
|
||||
|
||||
The Linux userspace shmem implementation uses libhugetlbfs to support huge page
|
||||
sizes.
|
||||
|
||||
### Bus and Device Abstraction
|
||||
|
||||
libmetal has a static generic implementation. If your OS has a driver model
|
||||
implementation, you will need to port it for the OS.
|
||||
|
||||
The Linux userspace abstraction binds the devices to UIO or VFIO driver.
|
||||
The user applications specify which device to use, e.g. bus "platform" bus,
|
||||
device "f8000000.slcr", and then the abstraction will check if platform UIO
|
||||
driver or platform VFIO driver is there. If platform VFIO driver exists,
|
||||
it will bind the device to the platform VFIO driver, otherwise, if UIO driver
|
||||
exists, it will bind the device to the platform UIO driver.
|
||||
|
||||
The VFIO support is not yet implemented.
|
||||
|
||||
### Interrupt
|
||||
|
||||
libmetal provides APIs to register an interrupt, disable interrupts and restore
|
||||
interrupts.
|
||||
|
||||
The Linux userspace implementation will use a thread to call select() function
|
||||
to listen to the file descriptors of the devices to see if there is an interrupt
|
||||
triggered. If there is an interrupt triggered, it will call the interrupt
|
||||
handler registered by the user application.
|
||||
|
||||
### Cache
|
||||
|
||||
libmetal provides APIs to flush and invalidate caches.
|
||||
|
||||
The cache APIs for Linux userspace are empty functions for now as cache
|
||||
operations system calls are not avaiable for all architectures.
|
||||
|
||||
### DMA
|
||||
|
||||
libmetal DMA APIs provide DMA map and unmap implementation.
|
||||
|
||||
After calling DMA map, the DMA device will own the memory.
|
||||
After calling DMA unmap, the cpu will own the memory.
|
||||
|
||||
For Linux userspace, it only supports to use UIO device memory as DMA
|
||||
memory for this release.
|
||||
|
||||
### Time
|
||||
libmetal time APIs provide getting timestamp implementation.
|
||||
|
||||
### Sleep
|
||||
libmetal sleep APIs provide getting delay execution implementation.
|
||||
|
||||
### Compiler
|
||||
|
||||
This API is for compiler dependent functions. For this release, there is only
|
||||
a GCC implementation, and compiler specific code is limited to atomic
|
||||
operations.
|
|
@ -0,0 +1,36 @@
|
|||
function (collector_create name base)
|
||||
set_property (GLOBAL PROPERTY "COLLECT_${name}_LIST")
|
||||
set_property (GLOBAL PROPERTY "COLLECT_${name}_BASE" "${base}")
|
||||
endfunction (collector_create)
|
||||
|
||||
function (collector_list var name)
|
||||
get_property (_list GLOBAL PROPERTY "COLLECT_${name}_LIST")
|
||||
set (${var} "${_list}" PARENT_SCOPE)
|
||||
endfunction (collector_list)
|
||||
|
||||
function (collector_base var name)
|
||||
get_property (_base GLOBAL PROPERTY "COLLECT_${name}_BASE")
|
||||
set (${var} "${_base}" PARENT_SCOPE)
|
||||
endfunction (collector_base)
|
||||
|
||||
function (collect name)
|
||||
collector_base (_base ${name})
|
||||
string(COMPARE NOTEQUAL "${_base}" "" _is_rel)
|
||||
set (_list)
|
||||
foreach (s IN LISTS ARGN)
|
||||
if (_is_rel)
|
||||
get_filename_component (s "${s}" ABSOLUTE)
|
||||
file (RELATIVE_PATH s "${_base}" "${s}")
|
||||
endif (_is_rel)
|
||||
list (APPEND _list "${s}")
|
||||
endforeach ()
|
||||
set_property (GLOBAL APPEND PROPERTY "COLLECT_${name}_LIST" "${_list}")
|
||||
endfunction (collect)
|
||||
|
||||
# Create global collectors
|
||||
collector_create (PROJECT_INC_DIRS "")
|
||||
collector_create (PROJECT_LIB_DIRS "")
|
||||
collector_create (PROJECT_LIB_DEPS "")
|
||||
collector_create (PROJECT_HDR_TESTS "")
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,36 @@
|
|||
find_package (Doxygen)
|
||||
|
||||
if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
||||
|
||||
check_include_files (stdatomic.h HAVE_STDATOMIC_H)
|
||||
check_include_files (linux/futex.h HAVE_FUTEX_H)
|
||||
|
||||
find_package (HugeTLBFS)
|
||||
if (HUGETLBFS_FOUND)
|
||||
collect (PROJECT_INC_DIRS "${HUGETLBFS_INCLUDE_DIR}")
|
||||
collect (PROJECT_LIB_DEPS "${HUGETLBFS_LIBRARIES}")
|
||||
add_definitions(-DHAVE_HUGETLBFS_H)
|
||||
endif(HUGETLBFS_FOUND)
|
||||
|
||||
find_package (LibSysFS REQUIRED)
|
||||
collect (PROJECT_INC_DIRS "${LIBSYSFS_INCLUDE_DIR}")
|
||||
collect (PROJECT_LIB_DEPS "${LIBSYSFS_LIBRARIES}")
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
collect (PROJECT_LIB_DEPS "${CMAKE_THREAD_LIBS_INIT}")
|
||||
|
||||
find_package(LibRt REQUIRED)
|
||||
collect (PROJECT_LIB_DEPS "${LIBRT_LIBRARIES}")
|
||||
|
||||
else ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
||||
|
||||
# TODO: fix for find_path() to detect stdatomic.h
|
||||
# find_path (HAVE_STDATOMIC_H stdatomic.h)
|
||||
set (_saved_cmake_required_flags ${CMAKE_REQUIRED_FLAGS})
|
||||
set (CMAKE_REQUIRED_FLAGS "-c" CACHE STRING "")
|
||||
check_include_files (stdatomic.h HAVE_STDATOMIC_H)
|
||||
set (CMAKE_REQUIRED_FLAGS ${_saved_cmake_required_flags})
|
||||
|
||||
endif ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux")
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,34 @@
|
|||
# FindHugeTLBFS
|
||||
# --------
|
||||
#
|
||||
# Find HugeTLBFS
|
||||
#
|
||||
# Find the native HugeTLBFS includes and library This module defines
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# HUGETLBFS_INCLUDE_DIR, where to find hugetlbfs.h, etc.
|
||||
# HUGETLBFS_LIBRARIES, the libraries needed to use HugeTLBFS.
|
||||
# HUGETLBFS_FOUND, If false, do not try to use HugeTLBFS.
|
||||
#
|
||||
# also defined, but not for general use are
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# HUGETLBFS_LIBRARY, where to find the HugeTLBFS library.
|
||||
|
||||
find_path (HUGETLBFS_INCLUDE_DIR hugetlbfs.h)
|
||||
|
||||
set (HUGETLBFS_NAMES ${HUGETLBFS_NAMES} hugetlbfs)
|
||||
find_library (HUGETLBFS_LIBRARY NAMES ${HUGETLBFS_NAMES})
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set HUGETLBFS_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
include (FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS (HUGETLBFS DEFAULT_MSG HUGETLBFS_LIBRARY HUGETLBFS_INCLUDE_DIR)
|
||||
|
||||
if (HUGETLBFS_FOUND)
|
||||
set (HUGETLBFS_LIBRARIES ${HUGETLBFS_LIBRARY})
|
||||
endif (HUGETLBFS_FOUND)
|
||||
|
||||
mark_as_advanced (HUGETLBFS_LIBRARY HUGETLBFS_INCLUDE_DIR)
|
|
@ -0,0 +1,46 @@
|
|||
#.rst:
|
||||
# FindLibRt
|
||||
# --------
|
||||
#
|
||||
# Find the native realtime includes and library.
|
||||
#
|
||||
# IMPORTED Targets
|
||||
# ^^^^^^^^^^^^^^^^
|
||||
#
|
||||
# This module defines :prop_tgt:`IMPORTED` target ``LIBRT::LIBRT``, if
|
||||
# LIBRT has been found.
|
||||
#
|
||||
# Result Variables
|
||||
# ^^^^^^^^^^^^^^^^
|
||||
#
|
||||
# This module defines the following variables:
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# LIBRT_INCLUDE_DIRS - where to find time.h, etc.
|
||||
# LIBRT_LIBRARIES - List of libraries when using librt.
|
||||
# LIBRT_FOUND - True if realtime library found.
|
||||
#
|
||||
# Hints
|
||||
# ^^^^^
|
||||
#
|
||||
# A user may set ``LIBRT_ROOT`` to a realtime installation root to tell this
|
||||
# module where to look.
|
||||
|
||||
find_path(LIBRT_INCLUDE_DIRS
|
||||
NAMES time.h
|
||||
PATHS ${LIBRT_ROOT}/include/
|
||||
)
|
||||
find_library(LIBRT_LIBRARIES rt)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(LibRt DEFAULT_MSG LIBRT_LIBRARIES LIBRT_INCLUDE_DIRS)
|
||||
mark_as_advanced(LIBRT_INCLUDE_DIRS LIBRT_LIBRARIES)
|
||||
|
||||
if(LIBRT_FOUND)
|
||||
if(NOT TARGET LIBRT::LIBRT)
|
||||
add_library(LIBRT::LIBRT UNKNOWN IMPORTED)
|
||||
set_target_properties(LIBRT::LIBRT PROPERTIES
|
||||
IMPORTED_LOCATION "${LIBRT_LIBRARIES}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${LIBRT_INCLUDE_DIRS}")
|
||||
endif()
|
||||
endif()
|
|
@ -0,0 +1,34 @@
|
|||
# FindLibSysFS
|
||||
# --------
|
||||
#
|
||||
# Find LibSysFS
|
||||
#
|
||||
# Find the native LibSysFS includes and library This module defines
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# LIBSYSFS_INCLUDE_DIR, where to find libsysfs.h, etc.
|
||||
# LIBSYSFS_LIBRARIES, the libraries needed to use LibSysFS.
|
||||
# LIBSYSFS_FOUND, If false, do not try to use LibSysFS.
|
||||
#
|
||||
# also defined, but not for general use are
|
||||
#
|
||||
# ::
|
||||
#
|
||||
# LIBSYSFS_LIBRARY, where to find the LibSysFS library.
|
||||
|
||||
find_path (LIBSYSFS_INCLUDE_DIR sysfs/libsysfs.h)
|
||||
|
||||
set (LIBSYSFS_NAMES ${LIBSYSFS_NAMES} sysfs)
|
||||
find_library (LIBSYSFS_LIBRARY NAMES ${LIBSYSFS_NAMES})
|
||||
|
||||
# handle the QUIETLY and REQUIRED arguments and set LIBSYSFS_FOUND to TRUE if
|
||||
# all listed variables are TRUE
|
||||
include (FindPackageHandleStandardArgs)
|
||||
FIND_PACKAGE_HANDLE_STANDARD_ARGS (LIBSYSFS DEFAULT_MSG LIBSYSFS_LIBRARY LIBSYSFS_INCLUDE_DIR)
|
||||
|
||||
if (LIBSYSFS_FOUND)
|
||||
set (LIBSYSFS_LIBRARIES ${LIBSYSFS_LIBRARY})
|
||||
endif (LIBSYSFS_FOUND)
|
||||
|
||||
mark_as_advanced (LIBSYSFS_LIBRARY LIBSYSFS_INCLUDE_DIR)
|
|
@ -0,0 +1,59 @@
|
|||
set (PROJECT_VER_MAJOR 0)
|
||||
set (PROJECT_VER_MINOR 1)
|
||||
set (PROJECT_VER_PATCH 0)
|
||||
set (PROJECT_VER 0.1.0)
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE)
|
||||
set (CMAKE_BUILD_TYPE Debug)
|
||||
endif (NOT CMAKE_BUILD_TYPE)
|
||||
message ("-- Build type: ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
if (NOT CMAKE_INSTALL_LIBDIR)
|
||||
set (CMAKE_INSTALL_LIBDIR "lib")
|
||||
endif (NOT CMAKE_INSTALL_LIBDIR)
|
||||
|
||||
if (NOT CMAKE_INSTALL_BINDIR)
|
||||
set (CMAKE_INSTALL_BINDIR "bin")
|
||||
endif (NOT CMAKE_INSTALL_BINDIR)
|
||||
|
||||
set (_host "${CMAKE_HOST_SYSTEM_NAME}/${CMAKE_HOST_SYSTEM_PROCESSOR}")
|
||||
message ("-- Host: ${_host}")
|
||||
|
||||
set (_target "${CMAKE_SYSTEM_NAME}/${CMAKE_SYSTEM_PROCESSOR}")
|
||||
message ("-- Target: ${_target}")
|
||||
|
||||
if (NOT DEFINED MACHINE)
|
||||
set (MACHINE "Generic")
|
||||
endif (NOT DEFINED MACHINE)
|
||||
message ("-- Machine: ${MACHINE}")
|
||||
|
||||
# handle if '-' in machine name
|
||||
string (REPLACE "-" "_" MACHINE ${MACHINE})
|
||||
|
||||
if (NOT DEFINED PROJECT_SYSTEM)
|
||||
string (TOLOWER ${CMAKE_SYSTEM_NAME} PROJECT_SYSTEM)
|
||||
string (TOUPPER ${CMAKE_SYSTEM_NAME} PROJECT_SYSTEM_UPPER)
|
||||
endif (NOT DEFINED PROJECT_SYSTEM)
|
||||
|
||||
string (TOLOWER ${CMAKE_SYSTEM_PROCESSOR} PROJECT_PROCESSOR)
|
||||
string (TOUPPER ${CMAKE_SYSTEM_PROCESSOR} PROJECT_PROCESSOR_UPPER)
|
||||
string (TOLOWER ${MACHINE} PROJECT_MACHINE)
|
||||
string (TOUPPER ${MACHINE} PROJECT_MACHINE_UPPER)
|
||||
|
||||
option (WITH_STATIC_LIB "Build with a static library" ON)
|
||||
|
||||
if ("${PROJECT_SYSTEM}" STREQUAL "linux")
|
||||
option (WITH_SHARED_LIB "Build with a shared library" ON)
|
||||
option (WITH_TESTS "Install test applications" ON)
|
||||
endif ("${PROJECT_SYSTEM}" STREQUAL "linux")
|
||||
|
||||
if (WITH_TESTS AND (${_host} STREQUAL ${_target}))
|
||||
option (WITH_TESTS_EXEC "Run test applications during build" ON)
|
||||
endif (WITH_TESTS AND (${_host} STREQUAL ${_target}))
|
||||
|
||||
option (WITH_DEFAULT_LOGGER "Build with default logger" ON)
|
||||
|
||||
option (WITH_DOC "Build with documentation" ON)
|
||||
|
||||
set (PROJECT_EC_FLAGS "-Wall -Werror -Wextra" CACHE STRING "")
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,6 @@
|
|||
# cmake 3.3.2 does not know CMAKE_SYSTEM_NAME=FreeRTOS, we set it to Generic
|
||||
include (cross-generic-gcc)
|
||||
string (TOLOWER "FreeRTOS" PROJECT_SYSTEM)
|
||||
string (TOUPPER "FreeRTOS" PROJECT_SYSTEM_UPPER)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,10 @@
|
|||
set (CMAKE_SYSTEM_NAME "Generic" CACHE STRING "")
|
||||
set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER CACHE STRING "")
|
||||
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER CACHE STRING "")
|
||||
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER CACHE STRING "")
|
||||
|
||||
include (CMakeForceCompiler)
|
||||
CMAKE_FORCE_C_COMPILER ("${CROSS_PREFIX}gcc" GNU)
|
||||
CMAKE_FORCE_CXX_COMPILER ("${CROSS_PREFIX}g++" GNU)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,10 @@
|
|||
set (CMAKE_SYSTEM_NAME "Generic" CACHE STRING "")
|
||||
set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER CACHE STRING "")
|
||||
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER CACHE STRING "")
|
||||
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER CACHE STRING "")
|
||||
|
||||
include (CMakeForceCompiler)
|
||||
CMAKE_FORCE_C_COMPILER ("icc${CROSS_SUFFIX}" IAR)
|
||||
CMAKE_FORCE_CXX_COMPILER ("icc${CROSS_SUFFIX} --eec++" IAR)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,8 @@
|
|||
set (CMAKE_SYSTEM_NAME "Linux" CACHE STRING "")
|
||||
set (CMAKE_C_COMPILER "${CROSS_PREFIX}gcc" CACHE STRING "")
|
||||
set (CMAKE_CXX_COMPILER "${CROSS_PREFIX}g++" CACHE STRING "")
|
||||
set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER CACHE STRING "")
|
||||
set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY NEVER CACHE STRING "")
|
||||
set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE NEVER CACHE STRING "")
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,7 @@
|
|||
set (CMAKE_SYSTEM_PROCESSOR "microblaze" CACHE STRING "")
|
||||
set (MACHINE "microblaze_generic" CACHE STRING "")
|
||||
set (CROSS_PREFIX "mb-" CACHE STRING "")
|
||||
# These flags are for a demo. If microblaze is changed, the flags need to be changed too.
|
||||
set (CMAKE_C_FLAGS "-mlittle-endian -mxl-barrel-shift -mxl-pattern-compare \
|
||||
-mcpu=v10.0 -mno-xl-soft-mul" CACHE STRING "")
|
||||
include (cross-generic-gcc)
|
|
@ -0,0 +1,12 @@
|
|||
# Modify to match your needs. These setttings can also be overridden at the
|
||||
# command line. (eg. cmake -DCMAKE_C_FLAGS="-O3")
|
||||
|
||||
set (CMAKE_SYSTEM_PROCESSOR "arm" CACHE STRING "")
|
||||
set (MACHINE "template" CACHE STRING "")
|
||||
set (CROSS_PREFIX "arm-none-eabi-" CACHE STRING "")
|
||||
|
||||
set (CMAKE_C_FLAGS "" CACHE STRING "")
|
||||
|
||||
include (cross-freertos-gcc)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,12 @@
|
|||
# Modify to match your needs. These setttings can also be overridden at the
|
||||
# command line. (eg. cmake -DCMAKE_C_FLAGS="-O3")
|
||||
|
||||
set (CMAKE_SYSTEM_PROCESSOR "arm" CACHE STRING "")
|
||||
set (MACHINE "template" CACHE STRING "")
|
||||
set (CROSS_PREFIX "arm-none-eabi-" CACHE STRING "")
|
||||
|
||||
set (CMAKE_C_FLAGS "" CACHE STRING "")
|
||||
|
||||
include (cross-generic-gcc)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,9 @@
|
|||
set (CMAKE_SYSTEM_PROCESSOR "arm" CACHE STRING "")
|
||||
set (MACHINE "zynq7" CACHE STRING "")
|
||||
set (CROSS_PREFIX "arm-none-eabi-" CACHE STRING "")
|
||||
|
||||
set (CMAKE_C_FLAGS "-mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard" CACHE STRING "")
|
||||
|
||||
include (cross-freertos-gcc)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,5 @@
|
|||
set (CMAKE_SYSTEM_PROCESSOR "arm" CACHE STRING "")
|
||||
set (CROSS_SUFFIX "arm" CACHE STRING "")
|
||||
include (cross-generic-iar)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,9 @@
|
|||
set (CMAKE_SYSTEM_PROCESSOR "arm" CACHE STRING "")
|
||||
set (MACHINE "zynq7" CACHE STRING "")
|
||||
set (CROSS_PREFIX "arm-none-eabi-" CACHE STRING "")
|
||||
|
||||
set (CMAKE_C_FLAGS "-mcpu=cortex-a9 -mfpu=vfpv3 -mfloat-abi=hard" CACHE STRING "")
|
||||
|
||||
include (cross-generic-gcc)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,5 @@
|
|||
set (CMAKE_SYSTEM_PROCESSOR "arm" CACHE STRING "")
|
||||
set (CROSS_PREFIX "arm-xilinx-linux-gnueabi-" CACHE STRING "")
|
||||
include (cross-linux-gcc)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,8 @@
|
|||
set (CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE STRING "")
|
||||
set (MACHINE "zynqmp_a53" CACHE STRING "")
|
||||
set (CROSS_PREFIX "aarch64-none-elf-" CACHE STRING "")
|
||||
set (CMAKE_C_FLAGS "" CACHE STRING "")
|
||||
|
||||
include (cross-freertos-gcc)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,8 @@
|
|||
set (CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE STRING "")
|
||||
set (MACHINE "zynqmp_a53" CACHE STRING "")
|
||||
set (CROSS_PREFIX "aarch64-none-elf-" CACHE STRING "")
|
||||
set (CMAKE_C_FLAGS "" CACHE STRING "")
|
||||
|
||||
include (cross-generic-gcc)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,5 @@
|
|||
set (CMAKE_SYSTEM_PROCESSOR "aarch64" CACHE STRING "")
|
||||
set (CROSS_PREFIX "aarch64-linux-gnu-" CACHE STRING "")
|
||||
include (cross-linux-gcc)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,8 @@
|
|||
set (CMAKE_SYSTEM_PROCESSOR "arm" CACHE STRING "")
|
||||
set (MACHINE "zynqmp_r5" CACHE STRING "")
|
||||
set (CROSS_PREFIX "armr5-none-eabi-" CACHE STRING "")
|
||||
set (CMAKE_C_FLAGS "-mfloat-abi=soft -mcpu=cortex-r5" CACHE STRING "")
|
||||
|
||||
include (cross-freertos-gcc)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,10 @@
|
|||
set (CMAKE_SYSTEM_PROCESSOR "arm" CACHE STRING "")
|
||||
set (MACHINE "zynqmp_r5" CACHE STRING "")
|
||||
set (CROSS_PREFIX "armr5-none-eabi-" CACHE STRING "")
|
||||
|
||||
# Xilinx SDK version earlier than 2017.2 use mfloat-abi=soft by default to generat libxil
|
||||
set (CMAKE_C_FLAGS "-mfloat-abi=hard -mfpu=vfpv3-d16 -mcpu=cortex-r5" CACHE STRING "")
|
||||
|
||||
include (cross-generic-gcc)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,12 @@
|
|||
# use "Generic" as CMAKE_SYSTEM_NAME
|
||||
|
||||
if (WITH_ZEPHYR)
|
||||
set (CMAKE_SYSTEM_NAME "Generic" CACHE STRING "")
|
||||
string (TOLOWER "Zephyr" PROJECT_SYSTEM)
|
||||
string (TOUPPER "Zephyr" PROJECT_SYSTEM_UPPER)
|
||||
set(IS_TEST 1)
|
||||
include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
|
||||
if (CONFIG_CPU_CORTEX_M)
|
||||
set (MACHINE "cortexm" CACHE STRING "")
|
||||
endif (CONFIG_CPU_CORTEX_M)
|
||||
endif (WITH_ZEPHYR)
|
|
@ -0,0 +1,19 @@
|
|||
if (DOXYGEN_FOUND)
|
||||
|
||||
configure_file (Doxyfile.in Doxyfile @ONLY)
|
||||
|
||||
add_custom_target (doc ALL
|
||||
${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
)
|
||||
|
||||
install (DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html
|
||||
DESTINATION share/doc/${PROJECT_NAME})
|
||||
install (FILES ${PROJECT_SOURCE_DIR}/README.md
|
||||
DESTINATION share/doc/${PROJECT_NAME})
|
||||
install (FILES ${PROJECT_SOURCE_DIR}/LICENSE.md
|
||||
DESTINATION share/doc/${PROJECT_NAME})
|
||||
|
||||
endif (DOXYGEN_FOUND)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,100 @@
|
|||
collector_create (PROJECT_LIB_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
collector_create (PROJECT_LIB_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
|
||||
collect (PROJECT_LIB_DIRS "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
collect (PROJECT_INC_DIRS "${CMAKE_CURRENT_BINARY_DIR}/include")
|
||||
|
||||
collect (PROJECT_LIB_HEADERS alloc.h)
|
||||
collect (PROJECT_LIB_HEADERS assert.h)
|
||||
collect (PROJECT_LIB_HEADERS atomic.h)
|
||||
collect (PROJECT_LIB_HEADERS cache.h)
|
||||
collect (PROJECT_LIB_HEADERS compiler.h)
|
||||
collect (PROJECT_LIB_HEADERS condition.h)
|
||||
collect (PROJECT_LIB_HEADERS config.h)
|
||||
collect (PROJECT_LIB_HEADERS cpu.h)
|
||||
collect (PROJECT_LIB_HEADERS device.h)
|
||||
collect (PROJECT_LIB_HEADERS dma.h)
|
||||
collect (PROJECT_LIB_HEADERS io.h)
|
||||
collect (PROJECT_LIB_HEADERS irq.h)
|
||||
collect (PROJECT_LIB_HEADERS list.h)
|
||||
collect (PROJECT_LIB_HEADERS log.h)
|
||||
collect (PROJECT_LIB_HEADERS mutex.h)
|
||||
collect (PROJECT_LIB_HEADERS shmem.h)
|
||||
collect (PROJECT_LIB_HEADERS sleep.h)
|
||||
collect (PROJECT_LIB_HEADERS spinlock.h)
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
collect (PROJECT_LIB_HEADERS time.h)
|
||||
collect (PROJECT_LIB_HEADERS utilities.h)
|
||||
collect (PROJECT_LIB_HEADERS version.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES dma.c)
|
||||
collect (PROJECT_LIB_SOURCES device.c)
|
||||
collect (PROJECT_LIB_SOURCES init.c)
|
||||
collect (PROJECT_LIB_SOURCES io.c)
|
||||
collect (PROJECT_LIB_SOURCES log.c)
|
||||
collect (PROJECT_LIB_SOURCES shmem.c)
|
||||
collect (PROJECT_LIB_SOURCES version.c)
|
||||
|
||||
add_subdirectory (compiler)
|
||||
add_subdirectory (processor)
|
||||
add_subdirectory (system)
|
||||
|
||||
collector_list (_inc_dirs PROJECT_INC_DIRS)
|
||||
collector_list (_sources PROJECT_LIB_SOURCES)
|
||||
collector_list (_headers PROJECT_LIB_HEADERS)
|
||||
collector_list (_deps PROJECT_LIB_DEPS)
|
||||
|
||||
foreach (f ${_headers})
|
||||
configure_file (${f} include/${PROJECT_NAME}/${f} @ONLY)
|
||||
install (FILES ${CMAKE_CURRENT_BINARY_DIR}/include/${PROJECT_NAME}/${f}
|
||||
DESTINATION include RENAME ${PROJECT_NAME}/${f})
|
||||
if (${f} MATCHES "^[^/]*\\.h")
|
||||
collect (PROJECT_HDR_TESTS "metal/${f}")
|
||||
endif (${f} MATCHES "^[^/]*\\.h")
|
||||
endforeach (f)
|
||||
|
||||
include_directories (${_inc_dirs})
|
||||
add_definitions (-DMETAL_INTERNAL)
|
||||
|
||||
if (WITH_DEFAULT_LOGGER)
|
||||
add_definitions (-DDEFAULT_LOGGER_ON)
|
||||
endif (WITH_DEFAULT_LOGGER)
|
||||
|
||||
if (WITH_ZEPHYR)
|
||||
zephyr_library_named(metal)
|
||||
add_dependencies(metal offsets_h)
|
||||
target_sources (metal PRIVATE ${_sources})
|
||||
else (WITH_ZEPHYR)
|
||||
# Build a shared library if so configured.
|
||||
if (WITH_SHARED_LIB)
|
||||
set (_lib ${PROJECT_NAME}-shared)
|
||||
add_library (${_lib} SHARED ${_sources})
|
||||
target_link_libraries (${_lib} ${_deps})
|
||||
install (TARGETS ${_lib} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
if (PROJECT_EC_FLAGS)
|
||||
string(REPLACE " " ";" _ec_flgs ${PROJECT_EC_FLAGS})
|
||||
target_compile_options (${_lib} PUBLIC ${_ec_flgs})
|
||||
endif (PROJECT_EC_FLAGS)
|
||||
set_target_properties (${_lib} PROPERTIES
|
||||
OUTPUT_NAME "${PROJECT_NAME}"
|
||||
VERSION "${PROJECT_VER}"
|
||||
SOVERSION "${PROJECT_VER_MAJOR}"
|
||||
)
|
||||
endif (WITH_SHARED_LIB)
|
||||
|
||||
# Build a static library if so configured.
|
||||
if (WITH_STATIC_LIB)
|
||||
set (_lib ${PROJECT_NAME}-static)
|
||||
add_library (${_lib} STATIC ${_sources})
|
||||
install (TARGETS ${_lib} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
if (PROJECT_EC_FLAGS)
|
||||
string(REPLACE " " ";" _ec_flgs ${PROJECT_EC_FLAGS})
|
||||
target_compile_options (${_lib} PUBLIC ${_ec_flgs})
|
||||
endif (PROJECT_EC_FLAGS)
|
||||
set_target_properties (${_lib} PROPERTIES
|
||||
OUTPUT_NAME "${PROJECT_NAME}"
|
||||
)
|
||||
endif (WITH_STATIC_LIB)
|
||||
endif (WITH_ZEPHYR)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file alloc.h
|
||||
* @brief Memory allocation handling primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ALLOC__H__
|
||||
#define __METAL_ALLOC__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup Memory Allocation Interfaces
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
* @brief allocate requested memory size
|
||||
* return a pointer to the allocated memory
|
||||
*
|
||||
* @param[in] size size in byte of requested memory
|
||||
* @return memory pointer, or 0 if it failed to allocate
|
||||
*/
|
||||
static inline void *metal_allocate_memory(unsigned int size);
|
||||
|
||||
/**
|
||||
* @brief free the memory previously allocated
|
||||
*
|
||||
* @param[in] ptr pointer to memory
|
||||
*/
|
||||
static inline void metal_free_memory(void *ptr);
|
||||
|
||||
#include <metal/system/@PROJECT_SYSTEM@/alloc.h>
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_ALLOC__H__ */
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file assert.h
|
||||
* @brief Assertion support.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ASSERT__H__
|
||||
#define __METAL_ASSERT__H__
|
||||
|
||||
#include <metal/system/@PROJECT_SYSTEM@/assert.h>
|
||||
|
||||
/**
|
||||
* @brief Assertion macro.
|
||||
* @param cond Condition to test.
|
||||
*/
|
||||
#define metal_assert(cond) metal_sys_assert(cond)
|
||||
|
||||
#endif /* __METAL_ASSERT_H__ */
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file atomic.h
|
||||
* @brief Atomic primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ATOMIC__H__
|
||||
#define __METAL_ATOMIC__H__
|
||||
|
||||
#include <metal/config.h>
|
||||
|
||||
#if defined(HAVE_STDATOMIC_H) && !defined(__STDC_NO_ATOMICS__) && \
|
||||
!defined(__cplusplus)
|
||||
# include <stdatomic.h>
|
||||
#elif defined(__GNUC__)
|
||||
# include <metal/compiler/gcc/atomic.h>
|
||||
#else
|
||||
# include <metal/processor/@PROJECT_PROCESSOR@/atomic.h>
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_ATOMIC__H__ */
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file cache.h
|
||||
* @brief CACHE operation primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CACHE__H__
|
||||
#define __METAL_CACHE__H__
|
||||
|
||||
#include <metal/system/@PROJECT_SYSTEM@/cache.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** \defgroup cache CACHE Interfaces
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
* @brief flush specified data cache
|
||||
*
|
||||
* @param[in] addr start memory logical address
|
||||
* @param[in] len length of memory
|
||||
* If addr is NULL, and len is 0,
|
||||
* It will flush the whole data cache.
|
||||
*/
|
||||
static inline void metal_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
return __metal_cache_flush(addr, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief invalidate specified data cache
|
||||
*
|
||||
* @param[in] addr start memory logical address
|
||||
* @param[in] len length of memory
|
||||
* If addr is NULL, and len is 0,
|
||||
* It will invalidate the whole data cache.
|
||||
*/
|
||||
static inline void metal_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
return __metal_cache_invalidate(addr, len);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_CACHE__H__ */
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file compiler.h
|
||||
* @brief Compiler specific primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_COMPILER__H__
|
||||
#define __METAL_COMPILER__H__
|
||||
|
||||
#if defined(__GNUC__)
|
||||
# include <metal/compiler/gcc/compiler.h>
|
||||
#else
|
||||
# error "Missing compiler support"
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_COMPILER__H__ */
|
|
@ -0,0 +1,3 @@
|
|||
add_subdirectory (gcc)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,4 @@
|
|||
collect (PROJECT_LIB_HEADERS atomic.h)
|
||||
collect (PROJECT_LIB_HEADERS compiler.h)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,123 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file gcc/atomic.h
|
||||
* @brief GCC specific atomic primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_GCC_ATOMIC__H__
|
||||
#define __METAL_GCC_ATOMIC__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef int atomic_flag;
|
||||
typedef char atomic_char;
|
||||
typedef unsigned char atomic_uchar;
|
||||
typedef short atomic_short;
|
||||
typedef unsigned short atomic_ushort;
|
||||
typedef int atomic_int;
|
||||
typedef unsigned int atomic_uint;
|
||||
typedef long atomic_long;
|
||||
typedef unsigned long atomic_ulong;
|
||||
typedef long long atomic_llong;
|
||||
typedef unsigned long long atomic_ullong;
|
||||
|
||||
#define ATOMIC_FLAG_INIT 0
|
||||
#define ATOMIC_VAR_INIT(VAL) (VAL)
|
||||
|
||||
typedef enum {
|
||||
memory_order_relaxed,
|
||||
memory_order_consume,
|
||||
memory_order_acquire,
|
||||
memory_order_release,
|
||||
memory_order_acq_rel,
|
||||
memory_order_seq_cst,
|
||||
} memory_order;
|
||||
|
||||
#define atomic_flag_test_and_set(FLAG) \
|
||||
__sync_lock_test_and_set((FLAG), 1)
|
||||
#define atomic_flag_test_and_set_explicit(FLAG, MO) \
|
||||
atomic_flag_test_and_set(FLAG)
|
||||
#define atomic_flag_clear(FLAG) \
|
||||
__sync_lock_release((FLAG))
|
||||
#define atomic_flag_clear_explicit(FLAG, MO) \
|
||||
atomic_flag_clear(FLAG)
|
||||
#define atomic_init(OBJ, VAL) \
|
||||
do { *(OBJ) = (VAL); } while (0)
|
||||
#define atomic_is_lock_free(OBJ) \
|
||||
(sizeof(*(OBJ)) <= sizeof(long))
|
||||
#define atomic_store(OBJ, VAL) \
|
||||
do { *(OBJ) = (VAL); __sync_synchronize(); } while (0)
|
||||
#define atomic_store_explicit(OBJ, VAL, MO) \
|
||||
atomic_store((OBJ), (VAL))
|
||||
#define atomic_load(OBJ) \
|
||||
({ __sync_synchronize(); *(OBJ); })
|
||||
#define atomic_load_explicit(OBJ, MO) \
|
||||
atomic_load(OBJ)
|
||||
#define atomic_exchange(OBJ, DES) \
|
||||
({ \
|
||||
typeof(OBJ) obj = (OBJ); \
|
||||
typeof(*obj) des = (DES); \
|
||||
typeof(*obj) expval; \
|
||||
typeof(*obj) oldval = atomic_load(obj); \
|
||||
do { \
|
||||
expval = oldval; \
|
||||
oldval = __sync_val_compare_and_swap( \
|
||||
obj, expval, des); \
|
||||
} while (oldval != expval); \
|
||||
oldval; \
|
||||
})
|
||||
#define atomic_exchange_explicit(OBJ, DES, MO) \
|
||||
atomic_exchange((OBJ), (DES))
|
||||
#define atomic_compare_exchange_strong(OBJ, EXP, DES) \
|
||||
({ \
|
||||
typeof(OBJ) obj = (OBJ); \
|
||||
typeof(EXP) exp = (EXP); \
|
||||
typeof(*obj) expval = *exp; \
|
||||
typeof(*obj) oldval = __sync_val_compare_and_swap( \
|
||||
obj, expval, (DES)); \
|
||||
*exp = oldval; \
|
||||
oldval == expval; \
|
||||
})
|
||||
#define atomic_compare_exchange_strong_explicit(OBJ, EXP, DES, MO) \
|
||||
atomic_compare_exchange_strong((OBJ), (EXP), (DES))
|
||||
#define atomic_compare_exchange_weak(OBJ, EXP, DES) \
|
||||
atomic_compare_exchange_strong((OBJ), (EXP), (DES))
|
||||
#define atomic_compare_exchange_weak_explicit(OBJ, EXP, DES, MO) \
|
||||
atomic_compare_exchange_weak((OBJ), (EXP), (DES))
|
||||
#define atomic_fetch_add(OBJ, VAL) \
|
||||
__sync_fetch_and_add((OBJ), (VAL))
|
||||
#define atomic_fetch_add_explicit(OBJ, VAL, MO) \
|
||||
atomic_fetch_add((OBJ), (VAL))
|
||||
#define atomic_fetch_sub(OBJ, VAL) \
|
||||
__sync_fetch_and_sub((OBJ), (VAL))
|
||||
#define atomic_fetch_sub_explicit(OBJ, VAL, MO) \
|
||||
atomic_fetch_sub((OBJ), (VAL))
|
||||
#define atomic_fetch_or(OBJ, VAL) \
|
||||
__sync_fetch_and_or((OBJ), (VAL))
|
||||
#define atomic_fetch_or_explicit(OBJ, VAL, MO) \
|
||||
atomic_fetch_or((OBJ), (VAL))
|
||||
#define atomic_fetch_xor(OBJ, VAL) \
|
||||
__sync_fetch_and_xor((OBJ), (VAL))
|
||||
#define atomic_fetch_xor_explicit(OBJ, VAL, MO) \
|
||||
atomic_fetch_xor((OBJ), (VAL))
|
||||
#define atomic_fetch_and(OBJ, VAL) \
|
||||
__sync_fetch_and_and((OBJ), (VAL))
|
||||
#define atomic_fetch_and_explicit(OBJ, VAL, MO) \
|
||||
atomic_fetch_and((OBJ), (VAL))
|
||||
#define atomic_thread_fence(MO) \
|
||||
__sync_synchronize()
|
||||
#define atomic_signal_fence(MO) \
|
||||
__sync_synchronize()
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GCC_ATOMIC__H__ */
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file gcc/compiler.h
|
||||
* @brief GCC specific primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_GCC_COMPILER__H__
|
||||
#define __METAL_GCC_COMPILER__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define restrict __restrict__
|
||||
#define metal_align(n) __attribute__((aligned(n)))
|
||||
#define metal_weak __attribute__((weak))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_GCC_COMPILER__H__ */
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file condition.h
|
||||
* @brief Condition variable for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CONDITION__H__
|
||||
#define __METAL_CONDITION__H__
|
||||
|
||||
#include <metal/mutex.h>
|
||||
#include <metal/utilities.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup condition Condition Variable Interfaces
|
||||
* @{ */
|
||||
|
||||
/** Opaque libmetal condition variable data structure. */
|
||||
struct metal_condition;
|
||||
|
||||
/**
|
||||
* @brief Initialize a libmetal condition variable.
|
||||
* @param[in] cv condition variable to initialize.
|
||||
*/
|
||||
static inline void metal_condition_init(struct metal_condition *cv);
|
||||
|
||||
/**
|
||||
* @brief Notify one waiter.
|
||||
* Before calling this function, the caller
|
||||
* should have acquired the mutex.
|
||||
* @param[in] cv condition variable
|
||||
* @return zero on no errors, non-zero on errors
|
||||
* @see metal_condition_wait, metal_condition_broadcast
|
||||
*/
|
||||
static inline int metal_condition_signal(struct metal_condition *cv);
|
||||
|
||||
/**
|
||||
* @brief Notify all waiters.
|
||||
* Before calling this function, the caller
|
||||
* should have acquired the mutex.
|
||||
* @param[in] cv condition variable
|
||||
* @return zero on no errors, non-zero on errors
|
||||
* @see metal_condition_wait, metal_condition_signal
|
||||
*/
|
||||
static inline int metal_condition_broadcast(struct metal_condition *cv);
|
||||
|
||||
/**
|
||||
* @brief Block until the condition variable is notified.
|
||||
* Before calling this function, the caller should
|
||||
* have acquired the mutex.
|
||||
* @param[in] cv condition variable
|
||||
* @param[in] m mutex
|
||||
* @return 0 on success, non-zero on failure.
|
||||
* @see metal_condition_signal
|
||||
*/
|
||||
int metal_condition_wait(struct metal_condition *cv, metal_mutex_t *m);
|
||||
|
||||
#include <metal/system/@PROJECT_SYSTEM@/condition.h>
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_CONDITION__H__ */
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file config.h
|
||||
* @brief Generated configuration settings for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CONFIG__H__
|
||||
#define __METAL_CONFIG__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Library major version number. */
|
||||
#define METAL_VER_MAJOR @PROJECT_VER_MAJOR@
|
||||
|
||||
/** Library minor version number. */
|
||||
#define METAL_VER_MINOR @PROJECT_VER_MINOR@
|
||||
|
||||
/** Library patch level. */
|
||||
#define METAL_VER_PATCH @PROJECT_VER_PATCH@
|
||||
|
||||
/** Library version string. */
|
||||
#define METAL_VER "@PROJECT_VER@"
|
||||
|
||||
/** System type (linux, generic, ...). */
|
||||
#define METAL_SYSTEM "@PROJECT_SYSTEM@"
|
||||
#define METAL_SYSTEM_@PROJECT_SYSTEM_UPPER@
|
||||
|
||||
/** Processor type (arm, x86_64, ...). */
|
||||
#define METAL_PROCESSOR "@PROJECT_PROCESSOR@"
|
||||
#define METAL_PROCESSOR_@PROJECT_PROCESSOR_UPPER@
|
||||
|
||||
/** Machine type (zynq, zynqmp, ...). */
|
||||
#define METAL_MACHINE "@PROJECT_MACHINE@"
|
||||
#define METAL_MACHINE_@PROJECT_MACHINE_UPPER@
|
||||
|
||||
#cmakedefine HAVE_STDATOMIC_H
|
||||
#cmakedefine HAVE_FUTEX_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_CONFIG__H__ */
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file cpu.h
|
||||
* @brief CPU primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CPU__H__
|
||||
#define __METAL_CPU__H__
|
||||
|
||||
# include <metal/processor/@PROJECT_PROCESSOR@/cpu.h>
|
||||
|
||||
#endif /* __METAL_CPU__H__ */
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <metal/assert.h>
|
||||
#include <metal/device.h>
|
||||
#include <metal/list.h>
|
||||
#include <metal/log.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
#include <metal/dma.h>
|
||||
#include <metal/cache.h>
|
||||
|
||||
int metal_bus_register(struct metal_bus *bus)
|
||||
{
|
||||
if (!bus || !bus->name || !strlen(bus->name))
|
||||
return -EINVAL;
|
||||
if (metal_bus_find(bus->name, NULL) == 0)
|
||||
return -EEXIST;
|
||||
metal_list_init(&bus->devices);
|
||||
metal_list_add_tail(&_metal.common.bus_list, &bus->node);
|
||||
metal_log(METAL_LOG_DEBUG, "registered %s bus\n", bus->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int metal_bus_unregister(struct metal_bus *bus)
|
||||
{
|
||||
metal_list_del(&bus->node);
|
||||
if (bus->ops.bus_close)
|
||||
bus->ops.bus_close(bus);
|
||||
metal_log(METAL_LOG_DEBUG, "unregistered %s bus\n", bus->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int metal_bus_find(const char *name, struct metal_bus **result)
|
||||
{
|
||||
struct metal_list *node;
|
||||
struct metal_bus *bus;
|
||||
|
||||
metal_list_for_each(&_metal.common.bus_list, node) {
|
||||
bus = metal_container_of(node, struct metal_bus, node);
|
||||
if (strcmp(bus->name, name) != 0)
|
||||
continue;
|
||||
if (result)
|
||||
*result = bus;
|
||||
return 0;
|
||||
}
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
int metal_device_open(const char *bus_name, const char *dev_name,
|
||||
struct metal_device **device)
|
||||
{
|
||||
struct metal_bus *bus;
|
||||
int error;
|
||||
|
||||
if (!bus_name || !strlen(bus_name) ||
|
||||
!dev_name || !strlen(dev_name) ||
|
||||
!device)
|
||||
return -EINVAL;
|
||||
|
||||
error = metal_bus_find(bus_name, &bus);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
if (!bus->ops.dev_open)
|
||||
return -ENODEV;
|
||||
|
||||
error = (*bus->ops.dev_open)(bus, dev_name, device);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void metal_device_close(struct metal_device *device)
|
||||
{
|
||||
metal_assert(device && device->bus);
|
||||
if (device->bus->ops.dev_close)
|
||||
device->bus->ops.dev_close(device->bus, device);
|
||||
}
|
||||
|
||||
int metal_register_generic_device(struct metal_device *device)
|
||||
{
|
||||
if (!device->name || !strlen(device->name) ||
|
||||
device->num_regions > METAL_MAX_DEVICE_REGIONS)
|
||||
return -EINVAL;
|
||||
|
||||
device->bus = &metal_generic_bus;
|
||||
metal_list_add_tail(&_metal.common.generic_device_list,
|
||||
&device->node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int metal_generic_dev_open(struct metal_bus *bus, const char *dev_name,
|
||||
struct metal_device **device)
|
||||
{
|
||||
struct metal_list *node;
|
||||
struct metal_device *dev;
|
||||
|
||||
(void)bus;
|
||||
|
||||
metal_list_for_each(&_metal.common.generic_device_list, node) {
|
||||
dev = metal_container_of(node, struct metal_device, node);
|
||||
if (strcmp(dev->name, dev_name) != 0)
|
||||
continue;
|
||||
*device = dev;
|
||||
return metal_generic_dev_sys_open(dev);
|
||||
}
|
||||
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
int metal_generic_dev_dma_map(struct metal_bus *bus,
|
||||
struct metal_device *device,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg_in,
|
||||
int nents_in,
|
||||
struct metal_sg *sg_out)
|
||||
{
|
||||
(void)bus;
|
||||
(void)device;
|
||||
int i;
|
||||
|
||||
if (sg_out != sg_in)
|
||||
memcpy(sg_out, sg_in, nents_in*(sizeof(struct metal_sg)));
|
||||
for (i = 0; i < nents_in; i++) {
|
||||
if (dir == METAL_DMA_DEV_W) {
|
||||
metal_cache_flush(sg_out[i].virt, sg_out[i].len);
|
||||
}
|
||||
metal_cache_invalidate(sg_out[i].virt, sg_out[i].len);
|
||||
}
|
||||
|
||||
return nents_in;
|
||||
}
|
||||
|
||||
void metal_generic_dev_dma_unmap(struct metal_bus *bus,
|
||||
struct metal_device *device,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg,
|
||||
int nents)
|
||||
{
|
||||
(void)bus;
|
||||
(void)device;
|
||||
(void)dir;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nents; i++) {
|
||||
metal_cache_invalidate(sg[i].virt, sg[i].len);
|
||||
}
|
||||
}
|
||||
|
||||
struct metal_bus metal_weak metal_generic_bus = {
|
||||
.name = "generic",
|
||||
.ops = {
|
||||
.bus_close = NULL,
|
||||
.dev_open = metal_generic_dev_open,
|
||||
.dev_close = NULL,
|
||||
.dev_irq_ack = NULL,
|
||||
.dev_dma_map = metal_generic_dev_dma_map,
|
||||
.dev_dma_unmap = metal_generic_dev_dma_unmap,
|
||||
},
|
||||
};
|
|
@ -0,0 +1,176 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file device.h
|
||||
* @brief Bus abstraction for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_BUS__H__
|
||||
#define __METAL_BUS__H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <metal/io.h>
|
||||
#include <metal/list.h>
|
||||
#include <metal/dma.h>
|
||||
#include <metal/sys.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup device Bus Abstraction
|
||||
* @{ */
|
||||
|
||||
#ifndef METAL_MAX_DEVICE_REGIONS
|
||||
#define METAL_MAX_DEVICE_REGIONS 32
|
||||
#endif
|
||||
|
||||
struct metal_bus;
|
||||
struct metal_device;
|
||||
|
||||
/** Bus operations. */
|
||||
struct metal_bus_ops {
|
||||
void (*bus_close)(struct metal_bus *bus);
|
||||
int (*dev_open)(struct metal_bus *bus,
|
||||
const char *dev_name,
|
||||
struct metal_device **device);
|
||||
void (*dev_close)(struct metal_bus *bus,
|
||||
struct metal_device *device);
|
||||
void (*dev_irq_ack)(struct metal_bus *bus,
|
||||
struct metal_device *device,
|
||||
int irq);
|
||||
int (*dev_dma_map)(struct metal_bus *bus,
|
||||
struct metal_device *device,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg_in,
|
||||
int nents_in,
|
||||
struct metal_sg *sg_out);
|
||||
void (*dev_dma_unmap)(struct metal_bus *bus,
|
||||
struct metal_device *device,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg,
|
||||
int nents);
|
||||
};
|
||||
|
||||
/** Libmetal bus structure. */
|
||||
struct metal_bus {
|
||||
const char *name;
|
||||
struct metal_bus_ops ops;
|
||||
struct metal_list devices;
|
||||
struct metal_list node;
|
||||
};
|
||||
|
||||
/** Libmetal generic bus. */
|
||||
extern struct metal_bus metal_generic_bus;
|
||||
|
||||
/** Libmetal device structure. */
|
||||
struct metal_device {
|
||||
const char *name; /**< Device name */
|
||||
struct metal_bus *bus; /**< Bus that contains device */
|
||||
unsigned num_regions; /**< Number of I/O regions in
|
||||
device */
|
||||
struct metal_io_region regions[METAL_MAX_DEVICE_REGIONS]; /**< Array of
|
||||
I/O regions in device*/
|
||||
struct metal_list node; /**< Node on bus' list of devices */
|
||||
int irq_num; /**< Number of IRQs per device */
|
||||
void *irq_info; /**< IRQ ID */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Register a libmetal bus.
|
||||
* @param[in] bus Pre-initialized bus structure.
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*/
|
||||
extern int metal_bus_register(struct metal_bus *bus);
|
||||
|
||||
/**
|
||||
* @brief Unregister a libmetal bus.
|
||||
* @param[in] bus Pre-registered bus structure.
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*/
|
||||
extern int metal_bus_unregister(struct metal_bus *bus);
|
||||
|
||||
/**
|
||||
* @brief Find a libmetal bus by name.
|
||||
* @param[in] name Bus name.
|
||||
* @param[out] bus Returned bus handle.
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*/
|
||||
extern int metal_bus_find(const char *name, struct metal_bus **bus);
|
||||
|
||||
/**
|
||||
* @brief Statically register a generic libmetal device.
|
||||
*
|
||||
* In non-Linux systems, devices are always required to be statically
|
||||
* registered at application initialization.
|
||||
* In Linux system, devices can be dynamically opened via sysfs or libfdt based
|
||||
* enumeration at runtime.
|
||||
* This interface is used for static registration of devices. Subsequent calls
|
||||
* to metal_device_open() look up in this list of pre-registered devices on the
|
||||
* "generic" bus.
|
||||
* "generic" bus is used on non-Linux system to group the memory mapped devices.
|
||||
*
|
||||
* @param[in] device Generic device.
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*/
|
||||
extern int metal_register_generic_device(struct metal_device *device);
|
||||
|
||||
/**
|
||||
* @brief Open a libmetal device by name.
|
||||
* @param[in] bus_name Bus name.
|
||||
* @param[in] dev_name Device name.
|
||||
* @param[out] device Returned device handle.
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*/
|
||||
extern int metal_device_open(const char *bus_name, const char *dev_name,
|
||||
struct metal_device **device);
|
||||
|
||||
/**
|
||||
* @brief Close a libmetal device.
|
||||
* @param[in] device Device handle.
|
||||
*/
|
||||
extern void metal_device_close(struct metal_device *device);
|
||||
|
||||
/**
|
||||
* @brief Get an I/O region accessor for a device region.
|
||||
*
|
||||
* @param[in] device Device handle.
|
||||
* @param[in] index Region index.
|
||||
* @return I/O accessor handle, or NULL on failure.
|
||||
*/
|
||||
static inline struct metal_io_region *
|
||||
metal_device_io_region(struct metal_device *device, unsigned index)
|
||||
{
|
||||
return (index < device->num_regions
|
||||
? &device->regions[index]
|
||||
: NULL);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
extern int metal_generic_dev_sys_open(struct metal_device *dev);
|
||||
extern int metal_generic_dev_open(struct metal_bus *bus, const char *dev_name,
|
||||
struct metal_device **device);
|
||||
extern int metal_generic_dev_dma_map(struct metal_bus *bus,
|
||||
struct metal_device *device,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg_in,
|
||||
int nents_in,
|
||||
struct metal_sg *sg_out);
|
||||
extern void metal_generic_dev_dma_unmap(struct metal_bus *bus,
|
||||
struct metal_device *device,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg,
|
||||
int nents);
|
||||
#endif /* METAL_INTERNAL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_BUS__H__ */
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <metal/device.h>
|
||||
#include <metal/log.h>
|
||||
#include <metal/dma.h>
|
||||
#include <metal/atomic.h>
|
||||
|
||||
int metal_dma_map(struct metal_device *dev,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg_in,
|
||||
int nents_in,
|
||||
struct metal_sg *sg_out)
|
||||
{
|
||||
int nents_out;
|
||||
|
||||
if (!dev || !sg_in || !sg_out)
|
||||
return -EINVAL;
|
||||
if (!dev->bus->ops.dev_dma_map)
|
||||
return -ENODEV;
|
||||
|
||||
/* memory barrier */
|
||||
if (dir == METAL_DMA_DEV_R)
|
||||
/* If it is device read, apply memory write fence. */
|
||||
atomic_thread_fence(memory_order_release);
|
||||
else
|
||||
/* If it is device write or device r/w,
|
||||
apply memory r/w fence. */
|
||||
atomic_thread_fence(memory_order_acq_rel);
|
||||
nents_out = dev->bus->ops.dev_dma_map(dev->bus,
|
||||
dev, dir, sg_in, nents_in, sg_out);
|
||||
return nents_out;
|
||||
}
|
||||
|
||||
void metal_dma_unmap(struct metal_device *dev,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg,
|
||||
int nents)
|
||||
{
|
||||
/* memory barrier */
|
||||
if (dir == METAL_DMA_DEV_R)
|
||||
/* If it is device read, apply memory write fence. */
|
||||
atomic_thread_fence(memory_order_release);
|
||||
else
|
||||
/* If it is device write or device r/w,
|
||||
apply memory r/w fence. */
|
||||
atomic_thread_fence(memory_order_acq_rel);
|
||||
|
||||
if (!dev || !dev->bus->ops.dev_dma_unmap || !sg)
|
||||
return;
|
||||
dev->bus->ops.dev_dma_unmap(dev->bus,
|
||||
dev, dir, sg, nents);
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file dma.h
|
||||
* @brief DMA primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_DMA__H__
|
||||
#define __METAL_DMA__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup dma DMA Interfaces
|
||||
* @{ */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <metal/sys.h>
|
||||
|
||||
#define METAL_DMA_DEV_R 1 /**< DMA direction, device read */
|
||||
#define METAL_DMA_DEV_W 2 /**< DMA direction, device write */
|
||||
#define METAL_DMA_DEV_WR 3 /**< DMA direction, device read/write */
|
||||
|
||||
/**
|
||||
* @brief scatter/gather list element structure
|
||||
*/
|
||||
struct metal_sg {
|
||||
void *virt; /**< CPU virtual address */
|
||||
struct metal_io_region *io; /**< IO region */
|
||||
int len; /**< length */
|
||||
};
|
||||
|
||||
struct metal_device;
|
||||
|
||||
/**
|
||||
* @brief Map memory for DMA transaction.
|
||||
* After the memory is DMA mapped, the memory should be
|
||||
* accessed by the DMA device but not the CPU.
|
||||
*
|
||||
* @param[in] dev DMA device
|
||||
* @param[in] dir DMA direction
|
||||
* @param[in] sg_in sg list of memory to map
|
||||
* @param[in] nents_in number of sg list entries of memory to map
|
||||
* @param[out] sg_out sg list of mapped memory
|
||||
* @return number of mapped sg entries, -error on failure.
|
||||
*/
|
||||
int metal_dma_map(struct metal_device *dev,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg_in,
|
||||
int nents_in,
|
||||
struct metal_sg *sg_out);
|
||||
|
||||
/**
|
||||
* @brief Unmap DMA memory
|
||||
* After the memory is DMA unmapped, the memory should
|
||||
* be accessed by the CPU but not the DMA device.
|
||||
*
|
||||
* @param[in] dev DMA device
|
||||
* @param[in] dir DMA direction
|
||||
* @param[in] sg sg list of mapped DMA memory
|
||||
* @param[in] nents number of sg list entries of DMA memory
|
||||
*/
|
||||
void metal_dma_unmap(struct metal_device *dev,
|
||||
uint32_t dir,
|
||||
struct metal_sg *sg,
|
||||
int nents);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_DMA__H__ */
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <metal/sys.h>
|
||||
|
||||
int metal_init(const struct metal_init_params *params)
|
||||
{
|
||||
int error = 0;
|
||||
|
||||
memset(&_metal, 0, sizeof(_metal));
|
||||
|
||||
_metal.common.log_handler = params->log_handler;
|
||||
_metal.common.log_level = params->log_level;
|
||||
|
||||
metal_list_init(&_metal.common.bus_list);
|
||||
metal_list_init(&_metal.common.generic_shmem_list);
|
||||
metal_list_init(&_metal.common.generic_device_list);
|
||||
|
||||
error = metal_sys_init(params);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void metal_finish(void)
|
||||
{
|
||||
metal_sys_finish();
|
||||
memset(&_metal, 0, sizeof(_metal));
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <metal/io.h>
|
||||
#include <metal/sys.h>
|
||||
|
||||
void metal_io_init(struct metal_io_region *io, void *virt,
|
||||
const metal_phys_addr_t *physmap, size_t size,
|
||||
unsigned page_shift, unsigned int mem_flags,
|
||||
const struct metal_io_ops *ops)
|
||||
{
|
||||
const struct metal_io_ops nops = {NULL, NULL, NULL, NULL, NULL, NULL};
|
||||
|
||||
io->virt = virt;
|
||||
io->physmap = physmap;
|
||||
io->size = size;
|
||||
io->page_shift = page_shift;
|
||||
if (page_shift >= sizeof(io->page_mask) * CHAR_BIT)
|
||||
/* avoid overflow */
|
||||
io->page_mask = -1UL;
|
||||
else
|
||||
io->page_mask = (1UL << page_shift) - 1UL;
|
||||
io->mem_flags = mem_flags;
|
||||
io->ops = ops ? *ops : nops;
|
||||
metal_sys_io_mem_map(io);
|
||||
}
|
||||
|
||||
int metal_io_block_read(struct metal_io_region *io, unsigned long offset,
|
||||
void *restrict dst, int len)
|
||||
{
|
||||
void *ptr = metal_io_virt(io, offset);
|
||||
int retlen;
|
||||
|
||||
if (offset > io->size)
|
||||
return -ERANGE;
|
||||
if ((offset + len) > io->size)
|
||||
len = io->size - offset;
|
||||
retlen = len;
|
||||
if (io->ops.block_read) {
|
||||
retlen = (*io->ops.block_read)(
|
||||
io, offset, dst, memory_order_seq_cst, len);
|
||||
} else {
|
||||
atomic_thread_fence(memory_order_seq_cst);
|
||||
while ( len && (
|
||||
((uintptr_t)dst % sizeof(int)) ||
|
||||
((uintptr_t)ptr % sizeof(int)))) {
|
||||
*(unsigned char *)dst =
|
||||
*(const unsigned char *)ptr;
|
||||
dst++;
|
||||
ptr++;
|
||||
len--;
|
||||
}
|
||||
for (; len >= (int)sizeof(int); dst += sizeof(int),
|
||||
ptr += sizeof(int),
|
||||
len -= sizeof(int))
|
||||
*(unsigned int *)dst = *(const unsigned int *)ptr;
|
||||
for (; len != 0; dst++, ptr++, len--)
|
||||
*(unsigned char *)dst =
|
||||
*(const unsigned char *)ptr;
|
||||
}
|
||||
return retlen;
|
||||
}
|
||||
|
||||
int metal_io_block_write(struct metal_io_region *io, unsigned long offset,
|
||||
const void *restrict src, int len)
|
||||
{
|
||||
void *ptr = metal_io_virt(io, offset);
|
||||
int retlen;
|
||||
|
||||
if (offset > io->size)
|
||||
return -ERANGE;
|
||||
if ((offset + len) > io->size)
|
||||
len = io->size - offset;
|
||||
retlen = len;
|
||||
if (io->ops.block_write) {
|
||||
retlen = (*io->ops.block_write)(
|
||||
io, offset, src, memory_order_seq_cst, len);
|
||||
} else {
|
||||
while ( len && (
|
||||
((uintptr_t)ptr % sizeof(int)) ||
|
||||
((uintptr_t)src % sizeof(int)))) {
|
||||
*(unsigned char *)ptr =
|
||||
*(const unsigned char *)src;
|
||||
ptr++;
|
||||
src++;
|
||||
len--;
|
||||
}
|
||||
for (; len >= (int)sizeof(int); ptr += sizeof(int),
|
||||
src += sizeof(int),
|
||||
len -= sizeof(int))
|
||||
*(unsigned int *)ptr = *(const unsigned int *)src;
|
||||
for (; len != 0; ptr++, src++, len--)
|
||||
*(unsigned char *)ptr =
|
||||
*(const unsigned char *)src;
|
||||
atomic_thread_fence(memory_order_seq_cst);
|
||||
}
|
||||
return retlen;
|
||||
}
|
||||
|
||||
int metal_io_block_set(struct metal_io_region *io, unsigned long offset,
|
||||
unsigned char value, int len)
|
||||
{
|
||||
void *ptr = metal_io_virt(io, offset);
|
||||
int retlen = len;
|
||||
|
||||
if (offset > io->size)
|
||||
return -ERANGE;
|
||||
if ((offset + len) > io->size)
|
||||
len = io->size - offset;
|
||||
retlen = len;
|
||||
if (io->ops.block_set) {
|
||||
(*io->ops.block_set)(
|
||||
io, offset, value, memory_order_seq_cst, len);
|
||||
} else {
|
||||
unsigned int cint = value;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 1; i < sizeof(int); i++)
|
||||
cint |= ((unsigned int)value << (8 * i));
|
||||
|
||||
for (; len && ((uintptr_t)ptr % sizeof(int)); ptr++, len--)
|
||||
*(unsigned char *)ptr = (unsigned char) value;
|
||||
for (; len >= (int)sizeof(int); ptr += sizeof(int),
|
||||
len -= sizeof(int))
|
||||
*(unsigned int *)ptr = cint;
|
||||
for (; len != 0; ptr++, len--)
|
||||
*(unsigned char *)ptr = (unsigned char) value;
|
||||
atomic_thread_fence(memory_order_seq_cst);
|
||||
}
|
||||
return retlen;
|
||||
}
|
||||
|
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
* Copyright (c) 2015 - 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file io.h
|
||||
* @brief I/O access primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_IO__H__
|
||||
#define __METAL_IO__H__
|
||||
|
||||
#include <limits.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <metal/assert.h>
|
||||
#include <metal/compiler.h>
|
||||
#include <metal/atomic.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/cpu.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup io IO Interfaces
|
||||
* @{ */
|
||||
|
||||
#ifdef __MICROBLAZE__
|
||||
#define NO_ATOMIC_64_SUPPORT
|
||||
#endif
|
||||
|
||||
struct metal_io_region;
|
||||
|
||||
/** Generic I/O operations. */
|
||||
struct metal_io_ops {
|
||||
uint64_t (*read)(struct metal_io_region *io,
|
||||
unsigned long offset,
|
||||
memory_order order,
|
||||
int width);
|
||||
void (*write)(struct metal_io_region *io,
|
||||
unsigned long offset,
|
||||
uint64_t value,
|
||||
memory_order order,
|
||||
int width);
|
||||
int (*block_read)(struct metal_io_region *io,
|
||||
unsigned long offset,
|
||||
void *restrict dst,
|
||||
memory_order order,
|
||||
int len);
|
||||
int (*block_write)(struct metal_io_region *io,
|
||||
unsigned long offset,
|
||||
const void *restrict src,
|
||||
memory_order order,
|
||||
int len);
|
||||
void (*block_set)(struct metal_io_region *io,
|
||||
unsigned long offset,
|
||||
unsigned char value,
|
||||
memory_order order,
|
||||
int len);
|
||||
void (*close)(struct metal_io_region *io);
|
||||
};
|
||||
|
||||
/** Libmetal I/O region structure. */
|
||||
struct metal_io_region {
|
||||
void *virt; /**< base virtual address */
|
||||
const metal_phys_addr_t *physmap; /**< table of base physical address
|
||||
of each of the pages in the I/O
|
||||
region */
|
||||
size_t size; /**< size of the I/O region */
|
||||
unsigned long page_shift; /**< page shift of I/O region */
|
||||
metal_phys_addr_t page_mask; /**< page mask of I/O region */
|
||||
unsigned int mem_flags; /**< memory attribute of the
|
||||
I/O region */
|
||||
struct metal_io_ops ops; /**< I/O region operations */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Open a libmetal I/O region.
|
||||
*
|
||||
* @param[in, out] io I/O region handle.
|
||||
* @param[in] virt Virtual address of region.
|
||||
* @param[in] physmap Array of physical addresses per page.
|
||||
* @param[in] size Size of region.
|
||||
* @param[in] page_shift Log2 of page size (-1 for single page).
|
||||
* @param[in] mem_flags Memory flags
|
||||
* @param[in] ops ops
|
||||
*/
|
||||
void
|
||||
metal_io_init(struct metal_io_region *io, void *virt,
|
||||
const metal_phys_addr_t *physmap, size_t size,
|
||||
unsigned page_shift, unsigned int mem_flags,
|
||||
const struct metal_io_ops *ops);
|
||||
|
||||
/**
|
||||
* @brief Close a libmetal shared memory segment.
|
||||
* @param[in] io I/O region handle.
|
||||
*/
|
||||
static inline void metal_io_finish(struct metal_io_region *io)
|
||||
{
|
||||
if (io->ops.close)
|
||||
(*io->ops.close)(io);
|
||||
memset(io, 0, sizeof(*io));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get size of I/O region.
|
||||
*
|
||||
* @param[in] io I/O region handle.
|
||||
* @return Size of I/O region.
|
||||
*/
|
||||
static inline size_t metal_io_region_size(struct metal_io_region *io)
|
||||
{
|
||||
return io->size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get virtual address for a given offset into the I/O region.
|
||||
* @param[in] io I/O region handle.
|
||||
* @param[in] offset Offset into shared memory segment.
|
||||
* @return NULL if offset is out of range, or pointer to offset.
|
||||
*/
|
||||
static inline void *
|
||||
metal_io_virt(struct metal_io_region *io, unsigned long offset)
|
||||
{
|
||||
return (io->virt != METAL_BAD_VA && offset <= io->size
|
||||
? (uint8_t *)io->virt + offset
|
||||
: NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a virtual address to offset within I/O region.
|
||||
* @param[in] io I/O region handle.
|
||||
* @param[in] virt Virtual address within segment.
|
||||
* @return METAL_BAD_OFFSET if out of range, or offset.
|
||||
*/
|
||||
static inline unsigned long
|
||||
metal_io_virt_to_offset(struct metal_io_region *io, void *virt)
|
||||
{
|
||||
size_t offset = (uint8_t *)virt - (uint8_t *)io->virt;
|
||||
return (offset < io->size ? offset : METAL_BAD_OFFSET);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get physical address for a given offset into the I/O region.
|
||||
* @param[in] io I/O region handle.
|
||||
* @param[in] offset Offset into shared memory segment.
|
||||
* @return METAL_BAD_PHYS if offset is out of range, or physical address
|
||||
* of offset.
|
||||
*/
|
||||
static inline metal_phys_addr_t
|
||||
metal_io_phys(struct metal_io_region *io, unsigned long offset)
|
||||
{
|
||||
unsigned long page = (io->page_shift >=
|
||||
sizeof(offset) * CHAR_BIT ?
|
||||
0 : offset >> io->page_shift);
|
||||
return (io->physmap != NULL && offset <= io->size
|
||||
? io->physmap[page] + (offset & io->page_mask)
|
||||
: METAL_BAD_PHYS);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a physical address to offset within I/O region.
|
||||
* @param[in] io I/O region handle.
|
||||
* @param[in] phys Physical address within segment.
|
||||
* @return METAL_BAD_OFFSET if out of range, or offset.
|
||||
*/
|
||||
static inline unsigned long
|
||||
metal_io_phys_to_offset(struct metal_io_region *io, metal_phys_addr_t phys)
|
||||
{
|
||||
unsigned long offset =
|
||||
(io->page_mask == (metal_phys_addr_t)(-1) ?
|
||||
phys - io->physmap[0] : phys & io->page_mask);
|
||||
do {
|
||||
if (metal_io_phys(io, offset) == phys)
|
||||
return offset;
|
||||
offset += io->page_mask + 1;
|
||||
} while (offset < io->size);
|
||||
return METAL_BAD_OFFSET;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a physical address to virtual address.
|
||||
* @param[in] io Shared memory segment handle.
|
||||
* @param[in] phys Physical address within segment.
|
||||
* @return NULL if out of range, or corresponding virtual address.
|
||||
*/
|
||||
static inline void *
|
||||
metal_io_phys_to_virt(struct metal_io_region *io, metal_phys_addr_t phys)
|
||||
{
|
||||
return metal_io_virt(io, metal_io_phys_to_offset(io, phys));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Convert a virtual address to physical address.
|
||||
* @param[in] io Shared memory segment handle.
|
||||
* @param[in] virt Virtual address within segment.
|
||||
* @return METAL_BAD_PHYS if out of range, or corresponding
|
||||
* physical address.
|
||||
*/
|
||||
static inline metal_phys_addr_t
|
||||
metal_io_virt_to_phys(struct metal_io_region *io, void *virt)
|
||||
{
|
||||
return metal_io_phys(io, metal_io_virt_to_offset(io, virt));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read a value from an I/O region.
|
||||
* @param[in] io I/O region handle.
|
||||
* @param[in] offset Offset into I/O region.
|
||||
* @param[in] order Memory ordering.
|
||||
* @param[in] width Width in bytes of datatype to read. This must be 1, 2,
|
||||
* 4, or 8, and a compile time constant for this function
|
||||
* to inline cleanly.
|
||||
* @return Value.
|
||||
*/
|
||||
static inline uint64_t
|
||||
metal_io_read(struct metal_io_region *io, unsigned long offset,
|
||||
memory_order order, int width)
|
||||
{
|
||||
void *ptr = metal_io_virt(io, offset);
|
||||
|
||||
if (io->ops.read)
|
||||
return (*io->ops.read)(io, offset, order, width);
|
||||
else if (ptr && sizeof(atomic_uchar) == width)
|
||||
return atomic_load_explicit((atomic_uchar *)ptr, order);
|
||||
else if (ptr && sizeof(atomic_ushort) == width)
|
||||
return atomic_load_explicit((atomic_ushort *)ptr, order);
|
||||
else if (ptr && sizeof(atomic_uint) == width)
|
||||
return atomic_load_explicit((atomic_uint *)ptr, order);
|
||||
else if (ptr && sizeof(atomic_ulong) == width)
|
||||
return atomic_load_explicit((atomic_ulong *)ptr, order);
|
||||
else if (ptr && sizeof(atomic_ullong) == width)
|
||||
#ifndef NO_ATOMIC_64_SUPPORT
|
||||
return atomic_load_explicit((atomic_ullong *)ptr, order);
|
||||
|
||||
#else
|
||||
return metal_processor_io_read64((atomic_ullong *)ptr, order);
|
||||
#endif
|
||||
metal_assert(0);
|
||||
return 0; /* quiet compiler */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write a value into an I/O region.
|
||||
* @param[in] io I/O region handle.
|
||||
* @param[in] offset Offset into I/O region.
|
||||
* @param[in] value Value to write.
|
||||
* @param[in] order Memory ordering.
|
||||
* @param[in] width Width in bytes of datatype to read. This must be 1, 2,
|
||||
* 4, or 8, and a compile time constant for this function
|
||||
* to inline cleanly.
|
||||
*/
|
||||
static inline void
|
||||
metal_io_write(struct metal_io_region *io, unsigned long offset,
|
||||
uint64_t value, memory_order order, int width)
|
||||
{
|
||||
void *ptr = metal_io_virt(io, offset);
|
||||
if (io->ops.write)
|
||||
(*io->ops.write)(io, offset, value, order, width);
|
||||
else if (ptr && sizeof(atomic_uchar) == width)
|
||||
atomic_store_explicit((atomic_uchar *)ptr, value, order);
|
||||
else if (ptr && sizeof(atomic_ushort) == width)
|
||||
atomic_store_explicit((atomic_ushort *)ptr, value, order);
|
||||
else if (ptr && sizeof(atomic_uint) == width)
|
||||
atomic_store_explicit((atomic_uint *)ptr, value, order);
|
||||
else if (ptr && sizeof(atomic_ulong) == width)
|
||||
atomic_store_explicit((atomic_ulong *)ptr, value, order);
|
||||
else if (ptr && sizeof(atomic_ullong) == width)
|
||||
#ifndef NO_ATOMIC_64_SUPPORT
|
||||
atomic_store_explicit((atomic_ullong *)ptr, value, order);
|
||||
#else
|
||||
metal_processor_io_write64((atomic_ullong *)ptr, value, order);
|
||||
#endif
|
||||
else
|
||||
metal_assert (0);
|
||||
}
|
||||
|
||||
#define metal_io_read8_explicit(_io, _ofs, _order) \
|
||||
metal_io_read((_io), (_ofs), (_order), 1)
|
||||
#define metal_io_read8(_io, _ofs) \
|
||||
metal_io_read((_io), (_ofs), memory_order_seq_cst, 1)
|
||||
#define metal_io_write8_explicit(_io, _ofs, _val, _order) \
|
||||
metal_io_write((_io), (_ofs), (_val), (_order), 1)
|
||||
#define metal_io_write8(_io, _ofs, _val) \
|
||||
metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 1)
|
||||
|
||||
#define metal_io_read16_explicit(_io, _ofs, _order) \
|
||||
metal_io_read((_io), (_ofs), (_order), 2)
|
||||
#define metal_io_read16(_io, _ofs) \
|
||||
metal_io_read((_io), (_ofs), memory_order_seq_cst, 2)
|
||||
#define metal_io_write16_explicit(_io, _ofs, _val, _order) \
|
||||
metal_io_write((_io), (_ofs), (_val), (_order), 2)
|
||||
#define metal_io_write16(_io, _ofs, _val) \
|
||||
metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 2)
|
||||
|
||||
#define metal_io_read32_explicit(_io, _ofs, _order) \
|
||||
metal_io_read((_io), (_ofs), (_order), 4)
|
||||
#define metal_io_read32(_io, _ofs) \
|
||||
metal_io_read((_io), (_ofs), memory_order_seq_cst, 4)
|
||||
#define metal_io_write32_explicit(_io, _ofs, _val, _order) \
|
||||
metal_io_write((_io), (_ofs), (_val), (_order), 4)
|
||||
#define metal_io_write32(_io, _ofs, _val) \
|
||||
metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 4)
|
||||
|
||||
#define metal_io_read64_explicit(_io, _ofs, _order) \
|
||||
metal_io_read((_io), (_ofs), (_order), 8)
|
||||
#define metal_io_read64(_io, _ofs) \
|
||||
metal_io_read((_io), (_ofs), memory_order_seq_cst, 8)
|
||||
#define metal_io_write64_explicit(_io, _ofs, _val, _order) \
|
||||
metal_io_write((_io), (_ofs), (_val), (_order), 8)
|
||||
#define metal_io_write64(_io, _ofs, _val) \
|
||||
metal_io_write((_io), (_ofs), (_val), memory_order_seq_cst, 8)
|
||||
|
||||
/**
|
||||
* @brief Read a block from an I/O region.
|
||||
* @param[in] io I/O region handle.
|
||||
* @param[in] offset Offset into I/O region.
|
||||
* @param[in] dst destination to store the read data.
|
||||
* @param[in] len length in bytes to read.
|
||||
* @return On success, number of bytes read. On failure, negative value
|
||||
*/
|
||||
int metal_io_block_read(struct metal_io_region *io, unsigned long offset,
|
||||
void *restrict dst, int len);
|
||||
|
||||
/**
|
||||
* @brief Write a block into an I/O region.
|
||||
* @param[in] io I/O region handle.
|
||||
* @param[in] offset Offset into I/O region.
|
||||
* @param[in] src source to write.
|
||||
* @param[in] len length in bytes to write.
|
||||
* @return On success, number of bytes written. On failure, negative value
|
||||
*/
|
||||
int metal_io_block_write(struct metal_io_region *io, unsigned long offset,
|
||||
const void *restrict src, int len);
|
||||
|
||||
/**
|
||||
* @brief fill a block of an I/O region.
|
||||
* @param[in] io I/O region handle.
|
||||
* @param[in] offset Offset into I/O region.
|
||||
* @param[in] value value to fill into the block
|
||||
* @param[in] len length in bytes to fill.
|
||||
* @return On success, number of bytes filled. On failure, negative value
|
||||
*/
|
||||
int metal_io_block_set(struct metal_io_region *io, unsigned long offset,
|
||||
unsigned char value, int len);
|
||||
|
||||
#include <metal/system/@PROJECT_SYSTEM@/io.h>
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_IO__H__ */
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file irq.h
|
||||
* @brief Interrupt handling primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_IRQ__H__
|
||||
#define __METAL_IRQ__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup irq Interrupt Handling Interfaces
|
||||
* @{ */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
/** IRQ handled status */
|
||||
#define METAL_IRQ_NOT_HANDLED 0
|
||||
#define METAL_IRQ_HANDLED 1
|
||||
|
||||
/**
|
||||
* @brief type of interrupt handler
|
||||
* @param[in] irq interrupt id
|
||||
* @param[in] priv private data
|
||||
* @return irq handled status
|
||||
*/
|
||||
typedef int (*metal_irq_handler) (int irq, void *priv);
|
||||
|
||||
struct metal_device;
|
||||
|
||||
/**
|
||||
* @brief Register interrupt handler for driver ID/device.
|
||||
*
|
||||
* @param[in] irq interrupt id
|
||||
* @param[in] irq_handler interrupt handler
|
||||
* @param[in] dev metal device this irq belongs to (can be NULL).
|
||||
* @param[in] drv_id driver id is a unique interrupt handler identifier.
|
||||
* It can also be used for driver data.
|
||||
* @return 0 for success, non-zero on failure
|
||||
*/
|
||||
int metal_irq_register(int irq,
|
||||
metal_irq_handler irq_handler,
|
||||
struct metal_device *dev,
|
||||
void *drv_id);
|
||||
|
||||
/**
|
||||
* @brief Unregister interrupt handler for driver ID and/or device.
|
||||
*
|
||||
* If interrupt handler (hd), driver ID (drv_id) and device (dev)
|
||||
* are NULL, unregister all handlers for this interrupt.
|
||||
*
|
||||
* If interrupt handler (hd), device (dev) or driver ID (drv_id),
|
||||
* are not NULL, unregister handlers matching non NULL criterias.
|
||||
* e.g: when call is made with drv_id and dev non NULL,
|
||||
* all handlers matching both are unregistered.
|
||||
*
|
||||
* If interrupt is not found, or other criterias not matching,
|
||||
* return -ENOENT
|
||||
*
|
||||
* @param[in] irq interrupt id
|
||||
* @param[in] irq_handler interrupt handler
|
||||
* @param[in] dev metal device this irq belongs to
|
||||
* @param[in] drv_id driver id. It can be used for driver data.
|
||||
* @return 0 for success, non-zero on failure
|
||||
*/
|
||||
int metal_irq_unregister(int irq,
|
||||
metal_irq_handler irq_handler,
|
||||
struct metal_device *dev,
|
||||
void *drv_id);
|
||||
|
||||
/**
|
||||
* @brief disable interrupts
|
||||
* @return interrupts state
|
||||
*/
|
||||
unsigned int metal_irq_save_disable(void);
|
||||
|
||||
/**
|
||||
* @brief restore interrupts to their previous state
|
||||
* @param[in] flags previous interrupts state
|
||||
*/
|
||||
void metal_irq_restore_enable(unsigned int flags);
|
||||
|
||||
/**
|
||||
* @brief metal_irq_enable
|
||||
*
|
||||
* Enables the given interrupt
|
||||
*
|
||||
* @param vector - interrupt vector number
|
||||
*/
|
||||
void metal_irq_enable(unsigned int vector);
|
||||
|
||||
/**
|
||||
* @brief metal_irq_disable
|
||||
*
|
||||
* Disables the given interrupt
|
||||
*
|
||||
* @param vector - interrupt vector number
|
||||
*/
|
||||
void metal_irq_disable(unsigned int vector);
|
||||
|
||||
#include <metal/system/@PROJECT_SYSTEM@/irq.h>
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_IRQ__H__ */
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file list.h
|
||||
* @brief List primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_LIST__H__
|
||||
#define __METAL_LIST__H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup list List Primitives
|
||||
* @{ */
|
||||
|
||||
struct metal_list {
|
||||
struct metal_list *next, *prev;
|
||||
};
|
||||
|
||||
/*
|
||||
* METAL_INIT_LIST - used for initializing an list elmenet in a static struct
|
||||
* or global
|
||||
*/
|
||||
#define METAL_INIT_LIST(name) { .next = &name, .prev = &name }
|
||||
/*
|
||||
* METAL_DECLARE_LIST - used for defining and initializing a global or
|
||||
* static singleton list
|
||||
*/
|
||||
#define METAL_DECLARE_LIST(name) \
|
||||
struct metal_list name = METAL_INIT_LIST(name)
|
||||
|
||||
static inline void metal_list_init(struct metal_list *list)
|
||||
{
|
||||
list->next = list->prev = list;
|
||||
}
|
||||
|
||||
static inline void metal_list_add_before(struct metal_list *node,
|
||||
struct metal_list *new_node)
|
||||
{
|
||||
new_node->prev = node->prev;
|
||||
new_node->next = node;
|
||||
new_node->next->prev = new_node;
|
||||
new_node->prev->next = new_node;
|
||||
}
|
||||
|
||||
static inline void metal_list_add_after(struct metal_list *node,
|
||||
struct metal_list *new_node)
|
||||
{
|
||||
new_node->prev = node;
|
||||
new_node->next = node->next;
|
||||
new_node->next->prev = new_node;
|
||||
new_node->prev->next = new_node;
|
||||
}
|
||||
|
||||
static inline void metal_list_add_head(struct metal_list *list,
|
||||
struct metal_list *node)
|
||||
{
|
||||
metal_list_add_after(list, node);
|
||||
}
|
||||
|
||||
static inline void metal_list_add_tail(struct metal_list *list,
|
||||
struct metal_list *node)
|
||||
{
|
||||
metal_list_add_before(list, node);
|
||||
}
|
||||
|
||||
static inline int metal_list_is_empty(struct metal_list *list)
|
||||
{
|
||||
return list->next == list;
|
||||
}
|
||||
|
||||
static inline void metal_list_del(struct metal_list *node)
|
||||
{
|
||||
node->next->prev = node->prev;
|
||||
node->prev->next = node->next;
|
||||
node->next = node->prev = node;
|
||||
}
|
||||
|
||||
static inline struct metal_list *metal_list_first(struct metal_list *list)
|
||||
{
|
||||
return metal_list_is_empty(list) ? NULL : list->next;
|
||||
}
|
||||
|
||||
#define metal_list_for_each(list, node) \
|
||||
for ((node) = (list)->next; \
|
||||
(node) != (list); \
|
||||
(node) = (node)->next)
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_LIST__H__ */
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <metal/log.h>
|
||||
#include <metal/sys.h>
|
||||
|
||||
void metal_default_log_handler(enum metal_log_level level,
|
||||
const char *format, ...)
|
||||
{
|
||||
#ifdef DEFAULT_LOGGER_ON
|
||||
char msg[1024];
|
||||
va_list args;
|
||||
static const char *level_strs[] = {
|
||||
"metal: emergency: ",
|
||||
"metal: alert: ",
|
||||
"metal: critical: ",
|
||||
"metal: error: ",
|
||||
"metal: warning: ",
|
||||
"metal: notice: ",
|
||||
"metal: info: ",
|
||||
"metal: debug: ",
|
||||
};
|
||||
|
||||
va_start(args, format);
|
||||
vsnprintf(msg, sizeof(msg), format, args);
|
||||
va_end(args);
|
||||
|
||||
if (level <= METAL_LOG_EMERGENCY || level > METAL_LOG_DEBUG)
|
||||
level = METAL_LOG_EMERGENCY;
|
||||
|
||||
fprintf(stderr, "%s%s", level_strs[level], msg);
|
||||
#else
|
||||
(void)level;
|
||||
(void)format;
|
||||
#endif
|
||||
}
|
||||
|
||||
void metal_set_log_handler(metal_log_handler handler)
|
||||
{
|
||||
_metal.common.log_handler = handler;
|
||||
}
|
||||
|
||||
metal_log_handler metal_get_log_handler(void)
|
||||
{
|
||||
return _metal.common.log_handler;
|
||||
}
|
||||
|
||||
void metal_set_log_level(enum metal_log_level level)
|
||||
{
|
||||
_metal.common.log_level = level;
|
||||
}
|
||||
|
||||
enum metal_log_level metal_get_log_level(void)
|
||||
{
|
||||
return _metal.common.log_level;
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file log.h
|
||||
* @brief Logging support for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_METAL_LOG__H__
|
||||
#define __METAL_METAL_LOG__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup logging Library Logging Interfaces
|
||||
* @{ */
|
||||
|
||||
/** Log message priority levels for libmetal. */
|
||||
enum metal_log_level {
|
||||
METAL_LOG_EMERGENCY, /**< system is unusable. */
|
||||
METAL_LOG_ALERT, /**< action must be taken immediately. */
|
||||
METAL_LOG_CRITICAL, /**< critical conditions. */
|
||||
METAL_LOG_ERROR, /**< error conditions. */
|
||||
METAL_LOG_WARNING, /**< warning conditions. */
|
||||
METAL_LOG_NOTICE, /**< normal but significant condition. */
|
||||
METAL_LOG_INFO, /**< informational messages. */
|
||||
METAL_LOG_DEBUG, /**< debug-level messages. */
|
||||
};
|
||||
|
||||
/** Log message handler type. */
|
||||
typedef void (*metal_log_handler)(enum metal_log_level level,
|
||||
const char *format, ...);
|
||||
|
||||
/**
|
||||
* @brief Set libmetal log handler.
|
||||
* @param[in] handler log message handler.
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*/
|
||||
extern void metal_set_log_handler(metal_log_handler handler);
|
||||
|
||||
/**
|
||||
* @brief Get the current libmetal log handler.
|
||||
* @return Current log handler.
|
||||
*/
|
||||
extern metal_log_handler metal_get_log_handler(void);
|
||||
|
||||
/**
|
||||
* @brief Set the level for libmetal logging.
|
||||
* @param[in] level log message level.
|
||||
*/
|
||||
extern void metal_set_log_level(enum metal_log_level level);
|
||||
|
||||
/**
|
||||
* @brief Get the current level for libmetal logging.
|
||||
* @return Current log level.
|
||||
*/
|
||||
extern enum metal_log_level metal_get_log_level(void);
|
||||
|
||||
/**
|
||||
* @brief Default libmetal log handler. This handler prints libmetal log
|
||||
* mesages to stderr.
|
||||
* @param[in] level log message level.
|
||||
* @param[in] format log message format string.
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*/
|
||||
extern void metal_default_log_handler(enum metal_log_level level,
|
||||
const char *format, ...);
|
||||
|
||||
|
||||
/**
|
||||
* Emit a log message if the log level permits.
|
||||
*
|
||||
* @param level Log level.
|
||||
* @param ... Format string and arguments.
|
||||
*/
|
||||
#define metal_log(level, ...) \
|
||||
((level <= _metal.common.log_level && _metal.common.log_handler) \
|
||||
? (void)_metal.common.log_handler(level, __VA_ARGS__) \
|
||||
: (void)0)
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#include <metal/system/@PROJECT_SYSTEM@/log.h>
|
||||
|
||||
#endif /* __METAL_METAL_LOG__H__ */
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file mutex.h
|
||||
* @brief Mutex primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_MUTEX__H__
|
||||
#define __METAL_MUTEX__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup mutex Mutex Interfaces
|
||||
* @{ */
|
||||
|
||||
#include <metal/system/@PROJECT_SYSTEM@/mutex.h>
|
||||
|
||||
/**
|
||||
* @brief Initialize a libmetal mutex.
|
||||
* @param[in] mutex Mutex to initialize.
|
||||
*/
|
||||
static inline void metal_mutex_init(metal_mutex_t *mutex)
|
||||
{
|
||||
__metal_mutex_init(mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deinitialize a libmetal mutex.
|
||||
* @param[in] mutex Mutex to deinitialize.
|
||||
*/
|
||||
static inline void metal_mutex_deinit(metal_mutex_t *mutex)
|
||||
{
|
||||
__metal_mutex_deinit(mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Try to acquire a mutex
|
||||
* @param[in] mutex Mutex to mutex.
|
||||
* @return 0 on failure to acquire, non-zero on success.
|
||||
*/
|
||||
static inline int metal_mutex_try_acquire(metal_mutex_t *mutex)
|
||||
{
|
||||
return __metal_mutex_try_acquire(mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Acquire a mutex
|
||||
* @param[in] mutex Mutex to mutex.
|
||||
*/
|
||||
static inline void metal_mutex_acquire(metal_mutex_t *mutex)
|
||||
{
|
||||
__metal_mutex_acquire(mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release a previously acquired mutex.
|
||||
* @param[in] mutex Mutex to mutex.
|
||||
* @see metal_mutex_try_acquire, metal_mutex_acquire
|
||||
*/
|
||||
static inline void metal_mutex_release(metal_mutex_t *mutex)
|
||||
{
|
||||
__metal_mutex_release(mutex);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checked if a mutex has been acquired.
|
||||
* @param[in] mutex mutex to check.
|
||||
* @see metal_mutex_try_acquire, metal_mutex_acquire
|
||||
*/
|
||||
static inline int metal_mutex_is_acquired(metal_mutex_t *mutex)
|
||||
{
|
||||
return __metal_mutex_is_acquired(mutex);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_MUTEX__H__ */
|
|
@ -0,0 +1,3 @@
|
|||
add_subdirectory (${PROJECT_PROCESSOR})
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,4 @@
|
|||
collect (PROJECT_LIB_HEADERS atomic.h)
|
||||
collect (PROJECT_LIB_HEADERS cpu.h)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file gcc/atomic.h
|
||||
* @brief GCC specific atomic primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_AARCH64_ATOMIC__H__
|
||||
#define __METAL_AARCH64_ATOMIC__H__
|
||||
|
||||
#endif /* __METAL_ARM_ATOMIC__H__ */
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file cpu.h
|
||||
* @brief CPU specific primatives
|
||||
*/
|
||||
|
||||
#ifndef __METAL_AARCH64_CPU__H__
|
||||
#define __METAL_AARCH64_CPU__H__
|
||||
|
||||
#define metal_cpu_yield() asm volatile("yield")
|
||||
|
||||
#endif /* __METAL_AARCH64_CPU__H__ */
|
|
@ -0,0 +1,4 @@
|
|||
collect (PROJECT_LIB_HEADERS atomic.h)
|
||||
collect (PROJECT_LIB_HEADERS cpu.h)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file gcc/atomic.h
|
||||
* @brief GCC specific atomic primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ARM_ATOMIC__H__
|
||||
#define __METAL_ARM_ATOMIC__H__
|
||||
|
||||
#endif /* __METAL_ARM_ATOMIC__H__ */
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file cpu.h
|
||||
* @brief CPU specific primatives
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ARM_CPU__H__
|
||||
#define __METAL_ARM_CPU__H__
|
||||
|
||||
#define metal_cpu_yield()
|
||||
|
||||
#endif /* __METAL_ARM_CPU__H__ */
|
|
@ -0,0 +1,4 @@
|
|||
collect (PROJECT_LIB_HEADERS atomic.h)
|
||||
collect (PROJECT_LIB_HEADERS cpu.h)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file microblaze/atomic.h
|
||||
* @brief Microblaze specific atomic primitives for libmetal
|
||||
*/
|
||||
|
||||
#ifndef __METAL_MICROBLAZE_ATOMIC__H__
|
||||
#define __METAL_MICROBLAZE_ATOMIC__H__
|
||||
|
||||
#endif /* __METAL_MICROBLAZE_ATOMIC__H__ */
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file cpu.h
|
||||
* @brief CPU specific primatives on microblaze platform.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_MICROBLAZE__H__
|
||||
#define __METAL_MICROBLAZE__H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <metal/atomic.h>
|
||||
|
||||
#define metal_cpu_yield()
|
||||
|
||||
static inline void metal_processor_io_write64(void *ptr, uint64_t value,
|
||||
memory_order order)
|
||||
{
|
||||
void *tmp = &value;
|
||||
|
||||
atomic_store_explicit((atomic_ulong *)ptr, *((atomic_ulong *)tmp), order);
|
||||
tmp += sizeof(atomic_ulong);
|
||||
ptr += sizeof(atomic_ulong);
|
||||
atomic_store_explicit((atomic_ulong *)ptr, *((atomic_ulong *)tmp), order);
|
||||
}
|
||||
|
||||
static inline uint64_t metal_processor_io_read64(void *ptr, memory_order order)
|
||||
{
|
||||
uint64_t long_ret;
|
||||
void *tmp = &long_ret;
|
||||
|
||||
*((atomic_ulong *)tmp) = atomic_load_explicit((atomic_ulong *)ptr, order);
|
||||
tmp += sizeof(atomic_ulong);
|
||||
ptr += sizeof(atomic_ulong);
|
||||
*((atomic_ulong *)tmp) = atomic_load_explicit((atomic_ulong *)ptr, order);
|
||||
|
||||
return long_ret;
|
||||
}
|
||||
|
||||
#endif /* __METAL_MICROBLAZE__H__ */
|
|
@ -0,0 +1,4 @@
|
|||
collect (PROJECT_LIB_HEADERS atomic.h)
|
||||
collect (PROJECT_LIB_HEADERS cpu.h)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file gcc/atomic.h
|
||||
* @brief GCC specific atomic primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_X86_64_ATOMIC__H__
|
||||
#define __METAL_X86_64_ATOMIC__H__
|
||||
|
||||
|
||||
#endif /* __METAL_X86_64_ATOMIC__H__ */
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file cpu.h
|
||||
* @brief CPU specific primatives
|
||||
*/
|
||||
|
||||
#ifndef __METAL_X86_64_CPU__H__
|
||||
#define __METAL_X86_64_CPU__H__
|
||||
|
||||
#define metal_cpu_yield() asm volatile("rep; nop")
|
||||
|
||||
#endif /* __METAL_X86_64_CPU__H__ */
|
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/shmem.c
|
||||
* @brief Generic libmetal shared memory handling.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <metal/assert.h>
|
||||
#include <metal/shmem.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
|
||||
int metal_shmem_register_generic(struct metal_generic_shmem *shmem)
|
||||
{
|
||||
/* Make sure that we can be found. */
|
||||
metal_assert(shmem->name && strlen(shmem->name) != 0);
|
||||
|
||||
/* Statically registered shmem regions cannot have a destructor. */
|
||||
metal_assert(!shmem->io.ops.close);
|
||||
|
||||
metal_list_add_tail(&_metal.common.generic_shmem_list,
|
||||
&shmem->node);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int metal_shmem_open_generic(const char *name, size_t size,
|
||||
struct metal_io_region **result)
|
||||
{
|
||||
struct metal_generic_shmem *shmem;
|
||||
struct metal_list *node;
|
||||
|
||||
metal_list_for_each(&_metal.common.generic_shmem_list, node) {
|
||||
shmem = metal_container_of(node, struct metal_generic_shmem, node);
|
||||
if (strcmp(shmem->name, name) != 0)
|
||||
continue;
|
||||
if (size > metal_io_region_size(&shmem->io))
|
||||
continue;
|
||||
*result = &shmem->io;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file shmem.h
|
||||
* @brief Shared memory primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SHMEM__H__
|
||||
#define __METAL_SHMEM__H__
|
||||
|
||||
#include <metal/io.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup shmem Shared Memory Interfaces
|
||||
* @{ */
|
||||
|
||||
/** Generic shared memory data structure. */
|
||||
struct metal_generic_shmem {
|
||||
const char *name;
|
||||
struct metal_io_region io;
|
||||
struct metal_list node;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Open a libmetal shared memory segment.
|
||||
*
|
||||
* Open a shared memory segment.
|
||||
*
|
||||
* @param[in] name Name of segment to open.
|
||||
* @param[in] size Size of segment.
|
||||
* @param[out] io I/O region handle, if successful.
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*
|
||||
* @see metal_shmem_create
|
||||
*/
|
||||
extern int metal_shmem_open(const char *name, size_t size,
|
||||
struct metal_io_region **io);
|
||||
|
||||
/**
|
||||
* @brief Statically register a generic shared memory region.
|
||||
*
|
||||
* Shared memory regions may be statically registered at application
|
||||
* initialization, or may be dynamically opened. This interface is used for
|
||||
* static registration of regions. Subsequent calls to metal_shmem_open() look
|
||||
* up in this list of pre-registered regions.
|
||||
*
|
||||
* @param[in] shmem Generic shmem structure.
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*/
|
||||
extern int metal_shmem_register_generic(struct metal_generic_shmem *shmem);
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
/**
|
||||
* @brief Open a statically registered shmem segment.
|
||||
*
|
||||
* This interface is meant for internal libmetal use within system specific
|
||||
* shmem implementations.
|
||||
*
|
||||
* @param[in] name Name of segment to open.
|
||||
* @param[in] size Size of segment.
|
||||
* @param[out] io I/O region handle, if successful.
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*/
|
||||
int metal_shmem_open_generic(const char *name, size_t size,
|
||||
struct metal_io_region **result);
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_SHMEM__H__ */
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file sleep.h
|
||||
* @brief Sleep primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SLEEP__H__
|
||||
#define __METAL_SLEEP__H__
|
||||
|
||||
#include <metal/system/@PROJECT_SYSTEM@/sleep.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup sleep Sleep Interfaces
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
* @brief delay in microseconds
|
||||
* delay the next execution in the calling thread
|
||||
* fo usec microseconds.
|
||||
*
|
||||
* @param[in] usec microsecond intervals
|
||||
* @return 0 on success, non-zero for failures
|
||||
*/
|
||||
static inline int metal_sleep_usec(unsigned int usec)
|
||||
{
|
||||
return __metal_sleep_usec(usec);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_SLEEP__H__ */
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file spinlock.h
|
||||
* @brief Spinlock primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SPINLOCK__H__
|
||||
#define __METAL_SPINLOCK__H__
|
||||
|
||||
#include <metal/atomic.h>
|
||||
#include <metal/cpu.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup spinlock Spinlock Interfaces
|
||||
* @{ */
|
||||
struct metal_spinlock {
|
||||
atomic_int v;
|
||||
};
|
||||
|
||||
/** Static metal spinlock initialization. */
|
||||
#define METAL_SPINLOCK_INIT {ATOMIC_VAR_INIT(0)}
|
||||
|
||||
/**
|
||||
* @brief Initialize a libmetal spinlock.
|
||||
* @param[in] slock Spinlock to initialize.
|
||||
*/
|
||||
static inline void metal_spinlock_init(struct metal_spinlock *slock)
|
||||
{
|
||||
atomic_store(&slock->v, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Acquire a spinlock.
|
||||
* @param[in] slock Spinlock to acquire.
|
||||
* @see metal_spinlock_release
|
||||
*/
|
||||
static inline void metal_spinlock_acquire(struct metal_spinlock *slock)
|
||||
{
|
||||
while (atomic_flag_test_and_set(&slock->v)) {
|
||||
metal_cpu_yield();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Release a previously acquired spinlock.
|
||||
* @param[in] slock Spinlock to release.
|
||||
* @see metal_spinlock_acquire
|
||||
*/
|
||||
static inline void metal_spinlock_release(struct metal_spinlock *slock)
|
||||
{
|
||||
atomic_flag_clear(&slock->v);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_SPINLOCK__H__ */
|
|
@ -0,0 +1,148 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file sys.h
|
||||
* @brief System primitives for libmetal.
|
||||
* @brief Top level include internal to libmetal library code.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SYS__H__
|
||||
#define __METAL_SYS__H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <metal/log.h>
|
||||
#include <metal/list.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \defgroup system Top Level Interfaces
|
||||
* @{ */
|
||||
|
||||
/** Physical address type. */
|
||||
typedef unsigned long metal_phys_addr_t;
|
||||
|
||||
/** Interrupt request number. */
|
||||
typedef int metal_irq_t;
|
||||
|
||||
/** Bad offset into shared memory or I/O region. */
|
||||
#define METAL_BAD_OFFSET ((unsigned long)-1)
|
||||
|
||||
/** Bad physical address value. */
|
||||
#define METAL_BAD_PHYS ((metal_phys_addr_t)-1)
|
||||
|
||||
/** Bad virtual address value. */
|
||||
#define METAL_BAD_VA ((void *)-1)
|
||||
|
||||
/** Bad IRQ. */
|
||||
#define METAL_BAD_IRQ ((metal_irq_t)-1)
|
||||
|
||||
/**
|
||||
* Initialization configuration for libmetal.
|
||||
*/
|
||||
struct metal_init_params {
|
||||
|
||||
/** log message handler (defaults to stderr). */
|
||||
metal_log_handler log_handler;
|
||||
|
||||
/** default log message level (defaults to emergency). */
|
||||
enum metal_log_level log_level;
|
||||
};
|
||||
|
||||
/**
|
||||
* System independent runtime state for libmetal. This is part of a system
|
||||
* specific singleton data structure (@see _metal).
|
||||
*/
|
||||
struct metal_common_state {
|
||||
/** Current log level. */
|
||||
enum metal_log_level log_level;
|
||||
|
||||
/** Current log handler (null for none). */
|
||||
metal_log_handler log_handler;
|
||||
|
||||
/** List of registered buses. */
|
||||
struct metal_list bus_list;
|
||||
|
||||
/** Generic statically defined shared memory segments. */
|
||||
struct metal_list generic_shmem_list;
|
||||
|
||||
/** Generic statically defined devices. */
|
||||
struct metal_list generic_device_list;
|
||||
};
|
||||
|
||||
struct metal_state;
|
||||
|
||||
#include <metal/system/@PROJECT_SYSTEM@/sys.h>
|
||||
|
||||
#ifndef METAL_INIT_DEFAULTS
|
||||
#define METAL_INIT_DEFAULTS \
|
||||
{ \
|
||||
.log_handler = metal_default_log_handler, \
|
||||
.log_level = METAL_LOG_INFO, \
|
||||
}
|
||||
#endif
|
||||
|
||||
/** System specific runtime data. */
|
||||
extern struct metal_state _metal;
|
||||
|
||||
/**
|
||||
* @brief Initialize libmetal.
|
||||
*
|
||||
* Initialize the libmetal library.
|
||||
*
|
||||
* @param[in] params Initialization params (@see metal_init_params).
|
||||
*
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*
|
||||
* @see metal_finish
|
||||
*/
|
||||
extern int metal_init(const struct metal_init_params *params);
|
||||
|
||||
/**
|
||||
* @brief Shutdown libmetal.
|
||||
*
|
||||
* Shutdown the libmetal library, and release all reserved resources.
|
||||
*
|
||||
* @see metal_init
|
||||
*/
|
||||
extern void metal_finish(void);
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
/**
|
||||
* @brief libmetal system initialization.
|
||||
*
|
||||
* This function initializes libmetal on Linux or Generic platforms. This
|
||||
* involves obtaining necessary pieces of system information (sysfs mount path,
|
||||
* page size, etc.).
|
||||
*
|
||||
* @param[in] params Initialization parameters (@see metal_init_params).
|
||||
* @return 0 on success, or -errno on failure.
|
||||
*/
|
||||
extern int metal_sys_init(const struct metal_init_params *params);
|
||||
|
||||
/**
|
||||
* @brief libmetal system shutdown.
|
||||
*
|
||||
* This function shuts down and releases resources held by libmetal Linux or
|
||||
* Generic platform layers.
|
||||
*
|
||||
* @see metal_sys_init
|
||||
*/
|
||||
extern void metal_sys_finish(void);
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_SYS__H__ */
|
|
@ -0,0 +1,3 @@
|
|||
add_subdirectory (${PROJECT_SYSTEM})
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,24 @@
|
|||
collect (PROJECT_LIB_HEADERS alloc.h)
|
||||
collect (PROJECT_LIB_HEADERS assert.h)
|
||||
collect (PROJECT_LIB_HEADERS cache.h)
|
||||
collect (PROJECT_LIB_HEADERS condition.h)
|
||||
collect (PROJECT_LIB_HEADERS io.h)
|
||||
collect (PROJECT_LIB_HEADERS irq.h)
|
||||
collect (PROJECT_LIB_HEADERS log.h)
|
||||
collect (PROJECT_LIB_HEADERS mutex.h)
|
||||
collect (PROJECT_LIB_HEADERS sleep.h)
|
||||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES condition.c)
|
||||
collect (PROJECT_LIB_SOURCES device.c)
|
||||
collect (PROJECT_LIB_SOURCES init.c)
|
||||
collect (PROJECT_LIB_SOURCES io.c)
|
||||
collect (PROJECT_LIB_SOURCES irq.c)
|
||||
collect (PROJECT_LIB_SOURCES shmem.c)
|
||||
collect (PROJECT_LIB_SOURCES time.c)
|
||||
|
||||
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE})
|
||||
add_subdirectory(${PROJECT_MACHINE})
|
||||
endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_MACHINE})
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/alloc.c
|
||||
* @brief FreeRTOS libmetal memory allocattion definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_ALLOC__H__
|
||||
#error "Include metal/alloc.h instead of metal/freertos/alloc.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_ALLOC__H__
|
||||
#define __METAL_FREERTOS_ALLOC__H__
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline void *metal_allocate_memory(unsigned int size)
|
||||
{
|
||||
return (pvPortMalloc(size));
|
||||
}
|
||||
|
||||
static inline void metal_free_memory(void *ptr)
|
||||
{
|
||||
vPortFree(ptr);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_ALLOC__H__ */
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file assert.h
|
||||
* @brief FreeRTOS assertion support.
|
||||
*/
|
||||
#ifndef __METAL_ASSERT__H__
|
||||
#error "Include metal/assert.h instead of metal/freertos/assert.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_ASSERT__H__
|
||||
#define __METAL_FREERTOS_ASSERT__H__
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/**
|
||||
* @brief Assertion macro for FreeRTOS applications.
|
||||
* @param cond Condition to evaluate.
|
||||
*/
|
||||
#define metal_sys_assert(cond) assert(cond)
|
||||
|
||||
#endif /* __METAL_FREERTOS_ASSERT__H__ */
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/cache.h
|
||||
* @brief FreeRTOS cache operation primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CACHE__H__
|
||||
#error "Include metal/cache.h instead of metal/freertos/cache.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_CACHE__H__
|
||||
#define __METAL_FREERTOS_CACHE__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern void metal_machine_cache_flush(void *addr, unsigned int len);
|
||||
extern void metal_machine_cache_invalidate(void *addr, unsigned int len);
|
||||
|
||||
static inline void __metal_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
metal_machine_cache_flush(addr, len);
|
||||
}
|
||||
|
||||
static inline void __metal_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
metal_machine_cache_invalidate(addr, len);
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_CACHE__H__ */
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/condition.c
|
||||
* @brief Generic libmetal condition variable handling.
|
||||
*/
|
||||
|
||||
#include <metal/condition.h>
|
||||
|
||||
int metal_condition_wait(struct metal_condition *cv,
|
||||
metal_mutex_t *m)
|
||||
{
|
||||
/* TODO: Implement condition variable for FreeRTOS */
|
||||
(void)cv;
|
||||
(void)m;
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/condition.h
|
||||
* @brief Generic condition variable primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_CONDITION__H__
|
||||
#error "Include metal/condition.h instead of metal/freertos/condition.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_CONDITION__H__
|
||||
#define __METAL_FREERTOS_CONDITION__H__
|
||||
|
||||
#include <metal/atomic.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct metal_condition {
|
||||
metal_mutex_t *m; /**< mutex.
|
||||
The condition variable is attached to
|
||||
this mutex when it is waiting.
|
||||
It is also used to check correctness
|
||||
in case there are multiple waiters. */
|
||||
|
||||
atomic_int v; /**< condition variable value. */
|
||||
};
|
||||
|
||||
/** Static metal condition variable initialization. */
|
||||
#define METAL_CONDITION_INIT { NULL, ATOMIC_VAR_INIT(0) }
|
||||
|
||||
static inline void metal_condition_init(struct metal_condition *cv)
|
||||
{
|
||||
/* TODO: Implement condition variable for FreeRTOS */
|
||||
(void)cv;
|
||||
return;
|
||||
}
|
||||
|
||||
static inline int metal_condition_signal(struct metal_condition *cv)
|
||||
{
|
||||
/* TODO: Implement condition variable for FreeRTOS */
|
||||
(void)cv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int metal_condition_broadcast(struct metal_condition *cv)
|
||||
{
|
||||
/* TODO: Implement condition variable for FreeRTOS */
|
||||
(void)cv;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_CONDITION__H__ */
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/device.c
|
||||
* @brief FreeRTOS device operations.
|
||||
*/
|
||||
|
||||
#include <metal/device.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
|
||||
int metal_generic_dev_sys_open(struct metal_device *dev)
|
||||
{
|
||||
struct metal_io_region *io;
|
||||
unsigned i;
|
||||
|
||||
/* map I/O memory regions */
|
||||
for (i = 0; i < dev->num_regions; i++) {
|
||||
io = &dev->regions[i];
|
||||
if (!io->size)
|
||||
break;
|
||||
metal_sys_io_mem_map(io);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/init.c
|
||||
* @brief FreeRTOS libmetal initialization.
|
||||
*/
|
||||
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
#include <metal/device.h>
|
||||
|
||||
struct metal_state _metal;
|
||||
|
||||
int metal_sys_init(const struct metal_init_params *params)
|
||||
{
|
||||
metal_unused(params);
|
||||
metal_bus_register(&metal_generic_bus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void metal_sys_finish(void)
|
||||
{
|
||||
metal_bus_unregister(&metal_generic_bus);
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/io.c
|
||||
* @brief FreeRTOS libmetal io operations
|
||||
*/
|
||||
|
||||
#include <metal/io.h>
|
||||
|
||||
void metal_sys_io_mem_map(struct metal_io_region *io)
|
||||
{
|
||||
unsigned long p;
|
||||
size_t psize;
|
||||
void *va;
|
||||
|
||||
va = io->virt;
|
||||
psize = io->size;
|
||||
if (psize) {
|
||||
if (psize >> io->page_shift)
|
||||
psize = (size_t)1 << io->page_shift;
|
||||
for (p = 0; p <= (io->size >> io->page_shift); p++) {
|
||||
metal_machine_io_mem_map(va, io->physmap[p],
|
||||
psize, io->mem_flags);
|
||||
va += psize;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (c) 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/io.h
|
||||
* @brief FreeRTOS specific io definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_IO__H__
|
||||
#error "Include metal/io.h instead of metal/freertos/io.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREEROTS_IO__H__
|
||||
#define __METAL_FREEROTS_IO__H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
/**
|
||||
* @brief memory mapping for an I/O region
|
||||
*/
|
||||
void metal_sys_io_mem_map(struct metal_io_region *io);
|
||||
|
||||
/**
|
||||
* @brief memory mapping
|
||||
*/
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREEROTS_IO__H__ */
|
|
@ -0,0 +1,282 @@
|
|||
/*
|
||||
* Copyright (c) 2016 - 2017, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/irq.c
|
||||
* @brief FreeRTOS libmetal irq definitions.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <metal/irq.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/log.h>
|
||||
#include <metal/mutex.h>
|
||||
#include <metal/list.h>
|
||||
#include <metal/utilities.h>
|
||||
#include <metal/alloc.h>
|
||||
|
||||
/** IRQ handlers descriptor structure */
|
||||
struct metal_irq_hddesc {
|
||||
metal_irq_handler hd; /**< irq handler */
|
||||
void *drv_id; /**< id to identify the driver
|
||||
of the irq handler */
|
||||
struct metal_device *dev; /**< device identifier */
|
||||
struct metal_list node; /**< node on irq handlers list */
|
||||
};
|
||||
|
||||
/** IRQ descriptor structure */
|
||||
struct metal_irq_desc {
|
||||
int irq; /**< interrupt number */
|
||||
struct metal_list hdls; /**< interrupt handlers */
|
||||
struct metal_list node; /**< node on irqs list */
|
||||
};
|
||||
|
||||
/** IRQ state structure */
|
||||
struct metal_irqs_state {
|
||||
struct metal_list irqs; /**< interrupt descriptors */
|
||||
metal_mutex_t irq_lock; /**< access lock */
|
||||
};
|
||||
|
||||
static struct metal_irqs_state _irqs = {
|
||||
.irqs = METAL_INIT_LIST(_irqs.irqs),
|
||||
.irq_lock = METAL_MUTEX_INIT(_irqs.irq_lock),
|
||||
};
|
||||
|
||||
int metal_irq_register(int irq,
|
||||
metal_irq_handler hd,
|
||||
struct metal_device *dev,
|
||||
void *drv_id)
|
||||
{
|
||||
struct metal_irq_desc *irq_p = NULL;
|
||||
struct metal_irq_hddesc *hdl_p;
|
||||
struct metal_list *node;
|
||||
unsigned int irq_flags_save;
|
||||
|
||||
if (irq < 0) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d need to be a positive number\n",
|
||||
__func__, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((drv_id == NULL) || (hd == NULL)) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d need drv_id and hd.\n",
|
||||
__func__, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Search for irq in list */
|
||||
metal_mutex_acquire(&_irqs.irq_lock);
|
||||
metal_list_for_each(&_irqs.irqs, node) {
|
||||
irq_p = metal_container_of(node, struct metal_irq_desc, node);
|
||||
|
||||
if (irq_p->irq == irq) {
|
||||
struct metal_list *h_node;
|
||||
|
||||
/* Check if drv_id already exist */
|
||||
metal_list_for_each(&irq_p->hdls, h_node) {
|
||||
hdl_p = metal_container_of(h_node,
|
||||
struct metal_irq_hddesc,
|
||||
node);
|
||||
|
||||
/* if drv_id already exist reject */
|
||||
if ((hdl_p->drv_id == drv_id) &&
|
||||
((dev == NULL) || (hdl_p->dev == dev))) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d already registered."
|
||||
"Will not register again.\n",
|
||||
__func__, irq);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
/* irq found and drv_id not used, get out of metal_list_for_each */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Either need to add handler to an existing list or to a new one */
|
||||
hdl_p = metal_allocate_memory(sizeof(struct metal_irq_hddesc));
|
||||
if (hdl_p == NULL) {
|
||||
metal_log(METAL_LOG_ERROR,
|
||||
"%s: irq %d cannot allocate mem for drv_id %d.\n",
|
||||
__func__, irq, drv_id);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
hdl_p->hd = hd;
|
||||
hdl_p->drv_id = drv_id;
|
||||
hdl_p->dev = dev;
|
||||
|
||||
/* interrupt already registered, add handler to existing list*/
|
||||
if ((irq_p != NULL) && (irq_p->irq == irq)) {
|
||||
irq_flags_save = metal_irq_save_disable();
|
||||
metal_list_add_tail(&irq_p->hdls, &hdl_p->node);
|
||||
metal_irq_restore_enable(irq_flags_save);
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: success, irq %d add drv_id %p \n",
|
||||
__func__, irq, drv_id);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* interrupt was not already registered, add */
|
||||
irq_p = metal_allocate_memory(sizeof(struct metal_irq_desc));
|
||||
if (irq_p == NULL) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d cannot allocate mem.\n",
|
||||
__func__, irq);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
irq_p->irq = irq;
|
||||
metal_list_init(&irq_p->hdls);
|
||||
metal_list_add_tail(&irq_p->hdls, &hdl_p->node);
|
||||
|
||||
irq_flags_save = metal_irq_save_disable();
|
||||
metal_list_add_tail(&_irqs.irqs, &irq_p->node);
|
||||
metal_irq_restore_enable(irq_flags_save);
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: success, added irq %d\n", __func__, irq);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* helper function for metal_irq_unregister() */
|
||||
static void metal_irq_delete_node(struct metal_list *node, void *p_to_free)
|
||||
{
|
||||
unsigned int irq_flags_save;
|
||||
|
||||
irq_flags_save=metal_irq_save_disable();
|
||||
metal_list_del(node);
|
||||
metal_irq_restore_enable(irq_flags_save);
|
||||
metal_free_memory(p_to_free);
|
||||
}
|
||||
|
||||
int metal_irq_unregister(int irq,
|
||||
metal_irq_handler hd,
|
||||
struct metal_device *dev,
|
||||
void *drv_id)
|
||||
{
|
||||
struct metal_irq_desc *irq_p;
|
||||
struct metal_list *node;
|
||||
|
||||
if (irq < 0) {
|
||||
metal_log(METAL_LOG_ERROR, "%s: irq %d need to be a positive number\n",
|
||||
__func__, irq);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Search for irq in list */
|
||||
metal_mutex_acquire(&_irqs.irq_lock);
|
||||
metal_list_for_each(&_irqs.irqs, node) {
|
||||
|
||||
irq_p = metal_container_of(node, struct metal_irq_desc, node);
|
||||
|
||||
if (irq_p->irq == irq) {
|
||||
struct metal_list *h_node, *h_prenode;
|
||||
struct metal_irq_hddesc *hdl_p;
|
||||
unsigned int delete_count = 0;
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: found irq %d\n",
|
||||
__func__, irq);
|
||||
|
||||
/* Search through handlers */
|
||||
metal_list_for_each(&irq_p->hdls, h_node) {
|
||||
hdl_p = metal_container_of(h_node,
|
||||
struct metal_irq_hddesc,
|
||||
node);
|
||||
|
||||
if (((hd == NULL) || (hdl_p->hd == hd)) &&
|
||||
((drv_id == NULL) || (hdl_p->drv_id == drv_id)) &&
|
||||
((dev == NULL) || (hdl_p->dev == dev))) {
|
||||
metal_log(METAL_LOG_DEBUG,
|
||||
"%s: unregister hd=%p drv_id=%p dev=%p\n",
|
||||
__func__, hdl_p->hd, hdl_p->drv_id, hdl_p->dev);
|
||||
h_prenode = h_node->prev;
|
||||
metal_irq_delete_node(h_node, hdl_p);
|
||||
delete_count++;
|
||||
h_node = h_prenode;
|
||||
}
|
||||
}
|
||||
|
||||
/* we did not find any handler to delete */
|
||||
if (!delete_count) {
|
||||
metal_log(METAL_LOG_DEBUG, "%s: No matching entry\n",
|
||||
__func__);
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOENT;
|
||||
|
||||
}
|
||||
|
||||
/* if interrupt handlers list is empty, unregister interrupt */
|
||||
if (metal_list_is_empty(&irq_p->hdls)) {
|
||||
metal_log(METAL_LOG_DEBUG,
|
||||
"%s: handlers list empty, unregister interrupt\n",
|
||||
__func__);
|
||||
metal_irq_delete_node(node, irq_p);
|
||||
}
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: success\n", __func__);
|
||||
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
metal_log(METAL_LOG_DEBUG, "%s: No matching IRQ entry\n", __func__);
|
||||
|
||||
metal_mutex_release(&_irqs.irq_lock);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
unsigned int metal_irq_save_disable(void)
|
||||
{
|
||||
sys_irq_save_disable();
|
||||
return 0;
|
||||
}
|
||||
|
||||
void metal_irq_restore_enable(unsigned int flags)
|
||||
{
|
||||
(void)flags;
|
||||
|
||||
sys_irq_restore_enable();
|
||||
}
|
||||
|
||||
void metal_irq_enable(unsigned int vector)
|
||||
{
|
||||
sys_irq_enable(vector);
|
||||
}
|
||||
|
||||
void metal_irq_disable(unsigned int vector)
|
||||
{
|
||||
sys_irq_disable(vector);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief default handler
|
||||
*/
|
||||
void metal_irq_isr(unsigned int vector)
|
||||
{
|
||||
struct metal_list *node;
|
||||
struct metal_irq_desc *irq_p;
|
||||
|
||||
metal_list_for_each(&_irqs.irqs, node) {
|
||||
irq_p = metal_container_of(node, struct metal_irq_desc, node);
|
||||
|
||||
if ((unsigned int)irq_p->irq == vector) {
|
||||
struct metal_list *h_node;
|
||||
struct metal_irq_hddesc *hdl_p;
|
||||
|
||||
metal_list_for_each(&irq_p->hdls, h_node) {
|
||||
hdl_p = metal_container_of(h_node,
|
||||
struct metal_irq_hddesc,
|
||||
node);
|
||||
|
||||
(hdl_p->hd)(vector, hdl_p->drv_id);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/irq.c
|
||||
* @brief FreeRTOS libmetal irq definitions.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_IRQ__H__
|
||||
#error "Include metal/irq.h instead of metal/freertos/irq.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_IRQ__H__
|
||||
#define __METAL_FREERTOS_IRQ__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief default interrupt handler
|
||||
* @param[in] vector interrupt vector
|
||||
*/
|
||||
void metal_irq_isr(unsigned int vector);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_IRQ__H__ */
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Linaro nor the names of its contributors may be used
|
||||
* to endorse or promote products derived from this software without
|
||||
* specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS 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 freertos/log.h
|
||||
* @brief FreeRTOS libmetal log handler definition.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_METAL_LOG__H__
|
||||
#error "Include metal/log.h instead of metal/freertos/log.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_LOG__H__
|
||||
#define __METAL_FREERTOS_LOG__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_LOG__H__ */
|
|
@ -0,0 +1,85 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/mutex.h
|
||||
* @brief FreeRTOS mutex primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_MUTEX__H__
|
||||
#error "Include metal/mutex.h instead of metal/freertos/mutex.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_MUTEX__H__
|
||||
#define __METAL_FREERTOS_MUTEX__H__
|
||||
|
||||
#include <metal/assert.h>
|
||||
#include "FreeRTOS.h"
|
||||
#include "semphr.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
SemaphoreHandle_t m;
|
||||
} metal_mutex_t;
|
||||
|
||||
/*
|
||||
* METAL_MUTEX_INIT - used for initializing an mutex elmenet in a static struct
|
||||
* or global
|
||||
*/
|
||||
#define METAL_MUTEX_INIT(m) { NULL }
|
||||
/*
|
||||
* METAL_MUTEX_DEFINE - used for defining and initializing a global or
|
||||
* static singleton mutex
|
||||
*/
|
||||
#define METAL_MUTEX_DEFINE(m) metal_mutex_t m = METAL_MUTEX_INIT(m)
|
||||
|
||||
static inline void __metal_mutex_init(metal_mutex_t *mutex)
|
||||
{
|
||||
metal_assert(mutex);
|
||||
mutex->m = xSemaphoreCreateMutex();
|
||||
metal_assert(mutex->m != NULL);
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_deinit(metal_mutex_t *mutex)
|
||||
{
|
||||
metal_assert(mutex && mutex->m != NULL);
|
||||
vSemaphoreDelete(mutex->m);
|
||||
mutex->m=NULL;
|
||||
}
|
||||
|
||||
static inline int __metal_mutex_try_acquire(metal_mutex_t *mutex)
|
||||
{
|
||||
metal_assert(mutex && mutex->m != NULL);
|
||||
return xSemaphoreTake(mutex->m, ( TickType_t ) 0 );
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_acquire(metal_mutex_t *mutex)
|
||||
{
|
||||
metal_assert(mutex && mutex->m != NULL);
|
||||
xSemaphoreTake(mutex->m, portMAX_DELAY);
|
||||
}
|
||||
|
||||
static inline void __metal_mutex_release(metal_mutex_t *mutex)
|
||||
{
|
||||
metal_assert(mutex && mutex->m != NULL);
|
||||
xSemaphoreGive(mutex->m);
|
||||
}
|
||||
|
||||
static inline int __metal_mutex_is_acquired(metal_mutex_t *mutex)
|
||||
{
|
||||
metal_assert(mutex && mutex->m != NULL);
|
||||
return (NULL == xSemaphoreGetMutexHolder(mutex->m)) ? 0 : 1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_MUTEX__H__ */
|
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright (c) 2015, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/shmem.c
|
||||
* @brief FreeRTOS libmetal shared memory handling.
|
||||
*/
|
||||
|
||||
#include <metal/shmem.h>
|
||||
|
||||
int metal_shmem_open(const char *name, size_t size,
|
||||
struct metal_io_region **io)
|
||||
{
|
||||
return metal_shmem_open_generic(name, size, io);
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Linaro Limited. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/sleep.h
|
||||
* @brief FreeRTOS sleep primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SLEEP__H__
|
||||
#error "Include metal/sleep.h instead of metal/freertos/sleep.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_SLEEP__H__
|
||||
#define __METAL_FREERTOS_SLEEP__H__
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
static inline int __metal_sleep_usec(unsigned int usec)
|
||||
{
|
||||
const TickType_t xDelay = usec / portTICK_PERIOD_MS;
|
||||
vTaskDelay(xDelay);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_SLEEP__H__ */
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/sys.h
|
||||
* @brief FreeRTOS system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/freertos/sys.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_SYS__H__
|
||||
#define __METAL_FREERTOS_SYS__H__
|
||||
|
||||
#include "./@PROJECT_MACHINE@/sys.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef METAL_MAX_DEVICE_REGIONS
|
||||
#define METAL_MAX_DEVICE_REGIONS 1
|
||||
#endif
|
||||
|
||||
/** Structure for FreeRTOS libmetal runtime state. */
|
||||
struct metal_state {
|
||||
|
||||
/** Common (system independent) data. */
|
||||
struct metal_common_state common;
|
||||
};
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
/**
|
||||
* @brief restore interrupts to state before disable_global_interrupt()
|
||||
*/
|
||||
void sys_irq_restore_enable(void);
|
||||
|
||||
/**
|
||||
* @brief disable all interrupts
|
||||
*/
|
||||
void sys_irq_save_disable(void);
|
||||
|
||||
#endif /* METAL_INTERNAL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_SYS__H__ */
|
|
@ -0,0 +1,5 @@
|
|||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES sys.c)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Linaro Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file generic/template/sys.c
|
||||
* @brief machine specific system primitives implementation.
|
||||
*/
|
||||
|
||||
#include <metal/io.h>
|
||||
#include <metal/sys.h>
|
||||
#include <metal/utilities.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void sys_irq_restore_enable(void)
|
||||
{
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void sys_irq_save_disable(void)
|
||||
{
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void sys_irq_enable(unsigned int vector)
|
||||
{
|
||||
metal_unused(vector);
|
||||
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void sys_irq_disable(unsigned int vector)
|
||||
{
|
||||
metal_unused(vector);
|
||||
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void metal_machine_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
metal_unused(addr);
|
||||
metal_unused(len);
|
||||
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void metal_machine_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
metal_unused(addr);
|
||||
metal_unused(len);
|
||||
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void metal_generic_default_poll(void)
|
||||
{
|
||||
/* Add implementation here */
|
||||
}
|
||||
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags)
|
||||
{
|
||||
metal_unused(pa);
|
||||
metal_unused(size);
|
||||
metal_unused(flags);
|
||||
|
||||
/* Add implementation here */
|
||||
|
||||
return va;
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (c) 2018, Linaro Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/template/sys.h
|
||||
* @brief freertos template system primitives for libmetal.
|
||||
*/
|
||||
|
||||
#ifndef __METAL_FREERTOS_SYS__H__
|
||||
#error "Include metal/sys.h instead of metal/freertos/@PROJECT_MACHINE@/sys.h"
|
||||
#endif
|
||||
|
||||
#ifndef __METAL_FREERTOS_TEMPLATE_SYS__H__
|
||||
#define __METAL_FREERTOS_TEMPLATE_SYS__H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef METAL_INTERNAL
|
||||
|
||||
void sys_irq_enable(unsigned int vector);
|
||||
|
||||
void sys_irq_disable(unsigned int vector);
|
||||
|
||||
#endif /* METAL_INTERNAL */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __METAL_FREERTOS_SYS__H__ */
|
|
@ -0,0 +1,20 @@
|
|||
/*
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/time.c
|
||||
* @brief freertos libmetal time handling.
|
||||
*/
|
||||
|
||||
#include <FreeRTOS.h>
|
||||
#include <task.h>
|
||||
#include <metal/time.h>
|
||||
|
||||
unsigned long long metal_get_timestamp(void)
|
||||
{
|
||||
return (unsigned long long)xTaskGetTickCount();
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
collect (PROJECT_LIB_HEADERS sys.h)
|
||||
|
||||
collect (PROJECT_LIB_SOURCES sys.c)
|
||||
|
||||
# vim: expandtab:ts=2:sw=2:smartindent
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* Copyright (c) 2014, Mentor Graphics Corporation
|
||||
* Copyright (c) 2016, Xilinx Inc. and Contributors. All rights reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
/*
|
||||
* @file freertos/zynq7/sys.c
|
||||
* @brief machine specific system primitives implementation.
|
||||
*/
|
||||
|
||||
#include <metal/compiler.h>
|
||||
#include <metal/io.h>
|
||||
#include <metal/sys.h>
|
||||
#include <stdint.h>
|
||||
#include "xil_cache.h"
|
||||
#include "xil_exception.h"
|
||||
#include "xil_mmu.h"
|
||||
#include "xscugic.h"
|
||||
|
||||
/* Translation table is 16K in size */
|
||||
#define ARM_AR_MEM_TTB_SIZE 16*1024
|
||||
|
||||
/* Each TTB descriptor covers a 1MB region */
|
||||
#define ARM_AR_MEM_TTB_SECT_SIZE 1024*1024
|
||||
|
||||
/* Mask off lower bits of addr */
|
||||
#define ARM_AR_MEM_TTB_SECT_SIZE_MASK (~(ARM_AR_MEM_TTB_SECT_SIZE-1UL))
|
||||
|
||||
/* default value setting for disabling interrupts */
|
||||
static unsigned int int_old_val = XIL_EXCEPTION_ALL;
|
||||
|
||||
void sys_irq_restore_enable(void)
|
||||
{
|
||||
Xil_ExceptionEnableMask(~int_old_val);
|
||||
}
|
||||
|
||||
void sys_irq_save_disable(void)
|
||||
{
|
||||
int_old_val = mfcpsr() & XIL_EXCEPTION_ALL;
|
||||
|
||||
if (XIL_EXCEPTION_ALL != int_old_val) {
|
||||
Xil_ExceptionDisableMask(XIL_EXCEPTION_ALL);
|
||||
}
|
||||
}
|
||||
|
||||
void metal_machine_cache_flush(void *addr, unsigned int len)
|
||||
{
|
||||
if (!addr && !len)
|
||||
Xil_DCacheFlush();
|
||||
else
|
||||
Xil_DCacheFlushRange((intptr_t)addr, len);
|
||||
}
|
||||
|
||||
void metal_machine_cache_invalidate(void *addr, unsigned int len)
|
||||
{
|
||||
if (!addr && !len)
|
||||
Xil_DCacheInvalidate();
|
||||
else
|
||||
Xil_DCacheInvalidateRange((intptr_t)addr, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief poll function until some event happens
|
||||
*/
|
||||
void metal_weak metal_generic_default_poll(void)
|
||||
{
|
||||
asm volatile("wfi");
|
||||
}
|
||||
|
||||
void *metal_machine_io_mem_map(void *va, metal_phys_addr_t pa,
|
||||
size_t size, unsigned int flags)
|
||||
{
|
||||
unsigned int section_offset;
|
||||
unsigned int ttb_addr;
|
||||
|
||||
if (!flags)
|
||||
return va;
|
||||
/* Ensure the virtual and physical addresses are aligned on a
|
||||
section boundary */
|
||||
pa &= ARM_AR_MEM_TTB_SECT_SIZE_MASK;
|
||||
|
||||
/* Loop through entire region of memory (one MMU section at a time).
|
||||
Each section requires a TTB entry. */
|
||||
for (section_offset = 0; section_offset < size;
|
||||
section_offset += ARM_AR_MEM_TTB_SECT_SIZE) {
|
||||
|
||||
/* Calculate translation table entry for this memory section */
|
||||
ttb_addr = (pa + section_offset);
|
||||
|
||||
/* Write translation table entry value to entry address */
|
||||
Xil_SetTlbAttributes(ttb_addr, flags);
|
||||
}
|
||||
|
||||
return va;
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue