Merge pull request #472 from raspberrypi/release.1.2.0
SDK 1.2.0 release; see release notes for details
This commit is contained in:
commit
bfcbefafc5
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -1,4 +1,3 @@
|
|||||||
[submodule "tinyusb"]
|
[submodule "tinyusb"]
|
||||||
path = lib/tinyusb
|
path = lib/tinyusb
|
||||||
url = https://github.com/raspberrypi/tinyusb.git
|
url = https://github.com/hathach/tinyusb.git
|
||||||
branch = pico
|
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
|
# Note: this CMakeLists.txt can be used as a top-level CMakeLists.txt for the SDK itself. For all other uses
|
||||||
|
# it is included as a subdirectory via the pico_sdk_init() method provided by pico_sdk_init.cmake
|
||||||
if (NOT TARGET _pico_sdk_inclusion_marker)
|
if (NOT TARGET _pico_sdk_inclusion_marker)
|
||||||
add_library(_pico_sdk_inclusion_marker INTERFACE)
|
add_library(_pico_sdk_inclusion_marker INTERFACE)
|
||||||
|
# This is a no-op unless we are the top-level CMakeLists.txt
|
||||||
include(pico_sdk_init.cmake)
|
include(pico_sdk_init.cmake)
|
||||||
|
|
||||||
project(pico_sdk C CXX ASM)
|
project(pico_sdk C CXX ASM)
|
||||||
@ -24,6 +28,7 @@ if (NOT TARGET _pico_sdk_inclusion_marker)
|
|||||||
|
|
||||||
# allow customization
|
# allow customization
|
||||||
add_sub_list_dirs(PICO_SDK_PRE_LIST_DIRS)
|
add_sub_list_dirs(PICO_SDK_PRE_LIST_DIRS)
|
||||||
|
add_sub_list_files(PICO_SDK_PRE_LIST_FILES)
|
||||||
|
|
||||||
add_subdirectory(tools)
|
add_subdirectory(tools)
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
@ -32,6 +37,7 @@ if (NOT TARGET _pico_sdk_inclusion_marker)
|
|||||||
|
|
||||||
# allow customization
|
# allow customization
|
||||||
add_sub_list_dirs(PICO_SDK_POST_LIST_DIRS)
|
add_sub_list_dirs(PICO_SDK_POST_LIST_DIRS)
|
||||||
|
add_sub_list_files(PICO_SDK_POST_LIST_FILES)
|
||||||
|
|
||||||
if (PICO_SDK_TOP_LEVEL_PROJECT AND NOT DEFINED PICO_SDK_TESTS_ENABLED)
|
if (PICO_SDK_TOP_LEVEL_PROJECT AND NOT DEFINED PICO_SDK_TESTS_ENABLED)
|
||||||
set(PICO_SDK_TESTS_ENABLED 1)
|
set(PICO_SDK_TESTS_ENABLED 1)
|
||||||
@ -44,5 +50,9 @@ if (NOT TARGET _pico_sdk_inclusion_marker)
|
|||||||
|
|
||||||
# add docs at the end, as we gather documentation dirs as we go
|
# add docs at the end, as we gather documentation dirs as we go
|
||||||
add_subdirectory(docs)
|
add_subdirectory(docs)
|
||||||
|
|
||||||
|
if (NOT PICO_SDK_TOP_LEVEL_PROJECT)
|
||||||
|
pico_promote_common_scope_vars()
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ The Raspberry Pi Pico SDK (henceforth the SDK) provides the headers, libraries a
|
|||||||
necessary to write programs for the RP2040-based devices such as the Raspberry Pi Pico
|
necessary to write programs for the RP2040-based devices such as the Raspberry Pi Pico
|
||||||
in C, C++ or assembly language.
|
in C, C++ or assembly language.
|
||||||
|
|
||||||
The SDK is designed to provide an API and programming environment that is familiar both to non-embedded C developers and embedded C developers alike.
|
The SDK is designed to provide an API and programming environment that is familiar both to non-embedded C developers and embedded C developers alike.
|
||||||
A single program runs on the device at a time and starts with a conventional `main()` method. Standard C/C++ libraries are supported along with
|
A single program runs on the device at a time and starts with a conventional `main()` method. Standard C/C++ libraries are supported along with
|
||||||
C level libraries/APIs for accessing all of the RP2040's hardware include PIO (Programmable IO).
|
C level libraries/APIs for accessing all of the RP2040's hardware include PIO (Programmable IO).
|
||||||
|
|
||||||
@ -38,7 +38,7 @@ instructions for other platforms, and just in general, we recommend you see [Ras
|
|||||||
|
|
||||||
1. Install CMake (at least version 3.13), and GCC cross compiler
|
1. Install CMake (at least version 3.13), and GCC cross compiler
|
||||||
```
|
```
|
||||||
sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi
|
sudo apt install cmake gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib
|
||||||
```
|
```
|
||||||
1. Set up your project to point to use the Raspberry Pi Pico SDK
|
1. Set up your project to point to use the Raspberry Pi Pico SDK
|
||||||
|
|
||||||
|
@ -36,8 +36,8 @@ if (DEFINED PICO_COMPILER)
|
|||||||
select one from \"cmake/toolchains\" folder.")
|
select one from \"cmake/toolchains\" folder.")
|
||||||
endif ()
|
endif ()
|
||||||
endif ()
|
endif ()
|
||||||
|
message("PICO compiler is ${PICO_COMPILER}")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
message("PICO compiler is ${PICO_COMPILER}")
|
|
||||||
unset(PICO_COMPILER CACHE)
|
unset(PICO_COMPILER CACHE)
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ if (NOT PICO_GCC_TRIPLE)
|
|||||||
message("PICO_GCC_TRIPLE set from environment: $ENV{PICO_GCC_TRIPLE}")
|
message("PICO_GCC_TRIPLE set from environment: $ENV{PICO_GCC_TRIPLE}")
|
||||||
else()
|
else()
|
||||||
set(PICO_GCC_TRIPLE arm-none-eabi)
|
set(PICO_GCC_TRIPLE arm-none-eabi)
|
||||||
message("PICO_GCC_TRIPLE defaulted to arm-none-eabi")
|
#pico_message_debug("PICO_GCC_TRIPLE defaulted to arm-none-eabi")
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
find_package(Doxygen)
|
find_package(Doxygen QUIET)
|
||||||
if (PICO_SDK_TOP_LEVEL_PROJECT AND ${DOXYGEN_FOUND})
|
if (PICO_SDK_TOP_LEVEL_PROJECT AND ${DOXYGEN_FOUND})
|
||||||
set(PICO_BUILD_DOCS_DEFAULT 1)
|
set(PICO_BUILD_DOCS_DEFAULT 1)
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
## Examples Index {#examples_page}
|
## Examples Index {#examples_page}
|
||||||
|
|
||||||
This page links to the various example code fragments in this documentation. For more complete examples, please see the pico_examples repository, which contains complete buildable projects.
|
This page links to the various example code fragments in this documentation. For more complete examples, please see the [pico-examples](https://github.com/raspberrypi/pico-examples) repository, which contains complete buildable projects.
|
||||||
|
|
||||||
- [RTC example](@ref rtc_example)
|
- [RTC example](@ref rtc_example)
|
||||||
- [UART example](@ref uart_example)
|
- [UART example](@ref uart_example)
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
* \defgroup hardware_clocks hardware_clocks
|
* \defgroup hardware_clocks hardware_clocks
|
||||||
* \defgroup hardware_divider hardware_divider
|
* \defgroup hardware_divider hardware_divider
|
||||||
* \defgroup hardware_dma hardware_dma
|
* \defgroup hardware_dma hardware_dma
|
||||||
|
* \defgroup hardware_exception hardware_exception
|
||||||
* \defgroup hardware_flash hardware_flash
|
* \defgroup hardware_flash hardware_flash
|
||||||
* \defgroup hardware_gpio hardware_gpio
|
* \defgroup hardware_gpio hardware_gpio
|
||||||
* \defgroup hardware_i2c hardware_i2c
|
* \defgroup hardware_i2c hardware_i2c
|
||||||
|
@ -25,7 +25,6 @@ The SDK builds an executable which is bare metal, i.e. it includes the entirety
|
|||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
|
||||||
This SDK contains a number of example code fragments. An index of these examples can be found [here](@ref examples_page)
|
This SDK documentation contains a number of example code fragments. An index of these examples can be found [here](@ref examples_page). These examples, and any other source code included in this documentation, is Copyright © 2020 Raspberry Pi (Trading) Ltd. and licensed under the [3-Clause BSD](https://opensource.org/licenses/BSD-3-Clause) license.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 11c23f88bf42f64ce14b8a7b0b2a4e207dc4dd12
|
Subproject commit d49938d0f5052bce70e55c652b657c0a6a7e84fe
|
@ -1,54 +1,94 @@
|
|||||||
# Initialize the Raspberry Pi Pico SDK
|
# Pre-initialize the Raspberry Pi Pico SDK, setting up the platform and toolchain and some CMake utility functions
|
||||||
# This file must be included prior to the project() call
|
# This file must be included prior to the project() call
|
||||||
|
|
||||||
if (_PICO_SDK_INIT)
|
# Note: this file is perhaps named badly, as it provides a method pico_sdk_init which
|
||||||
return()
|
# the enclosing project calls LATER to actually "initialize" the SDK (by including the CMakeLists.txt from this
|
||||||
endif ()
|
# same directory)
|
||||||
set(_PICO_SDK_INIT 1)
|
|
||||||
|
|
||||||
function(pico_is_top_level_project VAR)
|
if (NOT TARGET _pico_sdk_pre_init_marker)
|
||||||
string(TOLOWER ${CMAKE_CURRENT_LIST_DIR} __list_dir)
|
add_library(_pico_sdk_pre_init_marker INTERFACE)
|
||||||
string(TOLOWER ${CMAKE_SOURCE_DIR} __source_dir)
|
|
||||||
if (__source_dir STREQUAL __list_dir)
|
|
||||||
set(${VAR} 1 PARENT_SCOPE)
|
|
||||||
else()
|
|
||||||
set(${VAR} 0 PARENT_SCOPE)
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
if (NOT PICO_SDK_PATH)
|
function(pico_is_top_level_project VAR)
|
||||||
set(PICO_SDK_PATH ${CMAKE_CURRENT_LIST_DIR})
|
string(TOLOWER ${CMAKE_CURRENT_LIST_DIR} __list_dir)
|
||||||
endif ()
|
string(TOLOWER ${CMAKE_SOURCE_DIR} __source_dir)
|
||||||
|
if (__source_dir STREQUAL __list_dir)
|
||||||
|
set(${VAR} 1 PARENT_SCOPE)
|
||||||
|
else()
|
||||||
|
set(${VAR} 0 PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
function(pico_message_debug MESSAGE)
|
||||||
|
# The log-level system was added in CMake 3.15.
|
||||||
|
if(${CMAKE_VERSION} VERSION_LESS "3.15.0")
|
||||||
|
message(${MESSAGE})
|
||||||
|
else()
|
||||||
|
message(DEBUG ${MESSAGE})
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
|
|
||||||
set(PICO_SDK_PATH ${CMAKE_CURRENT_LIST_DIR} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
|
if (NOT PICO_SDK_PATH)
|
||||||
|
set(PICO_SDK_PATH ${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
endif ()
|
||||||
|
|
||||||
list(APPEND CMAKE_MODULE_PATH ${PICO_SDK_PATH}/cmake)
|
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
|
||||||
|
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/pico_sdk_version.cmake)
|
set(PICO_SDK_PATH ${CMAKE_CURRENT_LIST_DIR} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
|
||||||
include(pico_utils)
|
|
||||||
|
|
||||||
message("PICO_SDK_PATH is ${CMAKE_CURRENT_LIST_DIR}")
|
list(APPEND CMAKE_MODULE_PATH ${PICO_SDK_PATH}/cmake)
|
||||||
|
|
||||||
include(pico_pre_load_platform)
|
include(${CMAKE_CURRENT_LIST_DIR}/pico_sdk_version.cmake)
|
||||||
|
include(pico_utils)
|
||||||
|
|
||||||
# todo perhaps this should be included by the platform instead?
|
message("PICO_SDK_PATH is ${CMAKE_CURRENT_LIST_DIR}")
|
||||||
# We want to configure correct toolchain prior to project load
|
|
||||||
include(pico_pre_load_toolchain)
|
|
||||||
|
|
||||||
macro(pico_sdk_init)
|
include(pico_pre_load_platform)
|
||||||
if (NOT CMAKE_PROJECT_NAME)
|
|
||||||
message(WARNING "pico_sdk_init() should be called after the project is created (and languages added)")
|
|
||||||
endif()
|
|
||||||
add_subdirectory(${PICO_SDK_PATH} pico-sdk)
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
macro(add_sub_list_dirs var)
|
# We want to configure correct toolchain prior to project load
|
||||||
foreach(LIST_DIR IN LISTS ${var})
|
# todo perhaps this should be included by the platform instead?
|
||||||
get_filename_component(SHORT_NAME "${LIST_DIR}" NAME)
|
include(pico_pre_load_toolchain)
|
||||||
message("Including custom CMakeLists.txt ${SHORT_NAME}")
|
|
||||||
add_subdirectory(${LIST_DIR} ${SHORT_NAME})
|
|
||||||
endforeach()
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
|
macro(pico_sdk_init)
|
||||||
|
if (NOT CMAKE_PROJECT_NAME)
|
||||||
|
message(WARNING "pico_sdk_init() should be called after the project is created (and languages added)")
|
||||||
|
endif()
|
||||||
|
add_subdirectory(${PICO_SDK_PATH} pico-sdk)
|
||||||
|
pico_is_top_level_project(ISTOP)
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(add_sub_list_dirs var)
|
||||||
|
foreach(LIST_DIR IN LISTS ${var})
|
||||||
|
get_filename_component(SHORT_NAME "${LIST_DIR}" NAME)
|
||||||
|
pico_message_debug("Including custom CMakeLists.txt ${SHORT_NAME}")
|
||||||
|
add_subdirectory(${LIST_DIR} ${SHORT_NAME})
|
||||||
|
endforeach()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(add_sub_list_files var)
|
||||||
|
foreach(LIST_FILE IN LISTS ${var})
|
||||||
|
pico_message_debug("Including custom CMake file ${LIST_FILE}")
|
||||||
|
include(${LIST_FILE})
|
||||||
|
endforeach()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
macro(pico_register_common_scope_var NAME)
|
||||||
|
if (NOT ${NAME} IN_LIST PICO_PROMOTE_COMMON_SCOPE_VARS)
|
||||||
|
list(APPEND PICO_PROMOTE_COMMON_SCOPE_VARS ${NAME})
|
||||||
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
set(PICO_PROMOTE_COMMON_SCOPE_VARS
|
||||||
|
PICO_INCLUDE_DIRS
|
||||||
|
PICO_SDK_POST_LIST_DIRS
|
||||||
|
PICO_SDK_POST_LIST_FILES
|
||||||
|
PICO_CONFIG_HEADER_FILES
|
||||||
|
PICO_RP2040_CONFIG_HEADER_FILES
|
||||||
|
)
|
||||||
|
|
||||||
|
macro(pico_promote_common_scope_vars)
|
||||||
|
set(PICO_PROMOTE_COMMON_SCOPE_VARS ${PICO_PROMOTE_COMMON_SCOPE_VARS} PARENT_SCOPE)
|
||||||
|
foreach(VAR IN LISTS PICO_PROMOTE_COMMON_SCOPE_VARS)
|
||||||
|
SET(${VAR} ${${VAR}} PARENT_SCOPE)
|
||||||
|
endforeach()
|
||||||
|
endmacro()
|
||||||
|
endif()
|
||||||
|
@ -3,13 +3,12 @@
|
|||||||
set(PICO_SDK_VERSION_MAJOR 1)
|
set(PICO_SDK_VERSION_MAJOR 1)
|
||||||
# PICO_BUILD_DEFINE: PICO_SDK_VERSION_MINOR, SDK minor version number, type=int, group=pico_base
|
# PICO_BUILD_DEFINE: PICO_SDK_VERSION_MINOR, SDK minor version number, type=int, group=pico_base
|
||||||
# PICO_CONFIG: PICO_SDK_VERSION_MINOR, SDK minor version number, type=int, group=pico_base
|
# PICO_CONFIG: PICO_SDK_VERSION_MINOR, SDK minor version number, type=int, group=pico_base
|
||||||
set(PICO_SDK_VERSION_MINOR 1)
|
set(PICO_SDK_VERSION_MINOR 2)
|
||||||
# PICO_BUILD_DEFINE: PICO_SDK_VERSION_REVISION, SDK version revision, type=int, group=pico_base
|
# PICO_BUILD_DEFINE: PICO_SDK_VERSION_REVISION, SDK version revision, type=int, group=pico_base
|
||||||
# PICO_CONFIG: PICO_SDK_VERSION_REVISION, SDK version revision, type=int, group=pico_base
|
# PICO_CONFIG: PICO_SDK_VERSION_REVISION, SDK version revision, type=int, group=pico_base
|
||||||
set(PICO_SDK_VERSION_REVISION 2)
|
set(PICO_SDK_VERSION_REVISION 0)
|
||||||
# PICO_BUILD_DEFINE: PICO_SDK_VERSION_PRE_RELEASE_ID, optional SDK pre-release version identifier, type=string, group=pico_base
|
# PICO_BUILD_DEFINE: PICO_SDK_VERSION_PRE_RELEASE_ID, optional SDK pre-release version identifier, type=string, group=pico_base
|
||||||
# PICO_CONFIG: PICO_SDK_VERSION_PRE_RELEASE_ID, optional SDK pre-release version identifier, type=string, group=pico_base
|
# PICO_CONFIG: PICO_SDK_VERSION_PRE_RELEASE_ID, optional SDK pre-release version identifier, type=string, group=pico_base
|
||||||
#set(PICO_SDK_VERSION_PRE_RELEASE_ID develop)
|
|
||||||
|
|
||||||
# PICO_BUILD_DEFINE: PICO_SDK_VERSION_STRING, SDK version, type=string, group=pico_base
|
# PICO_BUILD_DEFINE: PICO_SDK_VERSION_STRING, SDK version, type=string, group=pico_base
|
||||||
# PICO_CONFIG: PICO_SDK_VERSION_STRING, SDK version, type=string, group=pico_base
|
# PICO_CONFIG: PICO_SDK_VERSION_STRING, SDK version, type=string, group=pico_base
|
||||||
|
@ -11,10 +11,12 @@ if (NOT EXISTS "${PICO_PLATFORM_CMAKE_FILE}")
|
|||||||
Either specify a valid PICO_PLATFORM (or PICO_PLATFORM_CMAKE_FILE).")
|
Either specify a valid PICO_PLATFORM (or PICO_PLATFORM_CMAKE_FILE).")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
# Initialize board related build/compile settings
|
||||||
include(${CMAKE_CURRENT_LIST_DIR}/board_setup.cmake)
|
include(${CMAKE_CURRENT_LIST_DIR}/board_setup.cmake)
|
||||||
|
|
||||||
# todo add option to disable skip flag
|
# call add_subdirectory(subdir) unless SKIP_SUBDIR evaluates to true
|
||||||
function(pico_add_subdirectory subdir)
|
function(pico_add_subdirectory subdir)
|
||||||
|
# todo add option to disable skip flag
|
||||||
string(TOUPPER ${subdir} subdir_upper)
|
string(TOUPPER ${subdir} subdir_upper)
|
||||||
set(replace_flag SKIP_${subdir_upper})
|
set(replace_flag SKIP_${subdir_upper})
|
||||||
if (NOT ${replace_flag})
|
if (NOT ${replace_flag})
|
||||||
@ -22,12 +24,15 @@ function(pico_add_subdirectory subdir)
|
|||||||
else ()
|
else ()
|
||||||
message("Not including ${subdir} because ${replace_flag} defined.")
|
message("Not including ${subdir} because ${replace_flag} defined.")
|
||||||
endif ()
|
endif ()
|
||||||
|
pico_promote_common_scope_vars()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
# add a link option to wrap the given function name; i.e. -Wl:wrap=FUNCNAME for gcc
|
||||||
function(pico_wrap_function TARGET FUNCNAME)
|
function(pico_wrap_function TARGET FUNCNAME)
|
||||||
target_link_options(${TARGET} INTERFACE "LINKER:--wrap=${FUNCNAME}")
|
target_link_options(${TARGET} INTERFACE "LINKER:--wrap=${FUNCNAME}")
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
# add map file generation for the given target
|
||||||
function(pico_add_map_output TARGET)
|
function(pico_add_map_output TARGET)
|
||||||
get_target_property(target_type ${TARGET} TYPE)
|
get_target_property(target_type ${TARGET} TYPE)
|
||||||
if ("EXECUTABLE" STREQUAL "${target_type}")
|
if ("EXECUTABLE" STREQUAL "${target_type}")
|
||||||
@ -37,11 +42,23 @@ function(pico_add_map_output TARGET)
|
|||||||
endif ()
|
endif ()
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
# create a hardware_NAME_headers target (see pico_pico_simple_hardware_headers_target)
|
||||||
|
# create a hardware_NAME target (see pico_pico_simple_hardware_target)
|
||||||
macro(pico_simple_hardware_target NAME)
|
macro(pico_simple_hardware_target NAME)
|
||||||
pico_simple_hardware_headers_target(${NAME})
|
pico_simple_hardware_headers_target(${NAME})
|
||||||
pico_simple_hardware_impl_target(${NAME})
|
pico_simple_hardware_impl_target(${NAME})
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
# create an INTERFACE library named target, and define LIB_TARGET=1 (upper case) as a compile option
|
||||||
|
function(pico_add_impl_library target)
|
||||||
|
add_library(${target} INTERFACE)
|
||||||
|
string(TOUPPER ${target} TARGET_UPPER)
|
||||||
|
target_compile_definitions(${target} INTERFACE LIB_${TARGET_UPPER}=1)
|
||||||
|
endfunction()
|
||||||
|
|
||||||
|
# create an INTERFACE library named hardware_NAME_headers INTERFACE library if it doesn't already exist,
|
||||||
|
# and add include/ relative to the calling directory to the includes.
|
||||||
|
# and hardware_structs and hardware_claim as dependencies of the library
|
||||||
macro(pico_simple_hardware_headers_target NAME)
|
macro(pico_simple_hardware_headers_target NAME)
|
||||||
if (NOT TARGET hardware_${NAME}_headers)
|
if (NOT TARGET hardware_${NAME}_headers)
|
||||||
add_library(hardware_${NAME}_headers INTERFACE)
|
add_library(hardware_${NAME}_headers INTERFACE)
|
||||||
@ -54,8 +71,15 @@ macro(pico_simple_hardware_headers_target NAME)
|
|||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
# create an INTERFACE library named hardware_NAME if it doesn't exist, along with a hardware_NAME_headers
|
||||||
|
# INTERFACE library that it depends on. The hardware_NAME_headers library add include/ relative to
|
||||||
|
# and pico_base_headers, and harddware_structs as a dependency of the library
|
||||||
macro(pico_simple_hardware_headers_only_target NAME)
|
macro(pico_simple_hardware_headers_only_target NAME)
|
||||||
if (NOT TARGET hardware_${NAME})
|
if (NOT TARGET hardware_${NAME})
|
||||||
|
# Choosing not to add LIB_HARDWARE_ defines to avoid command line bloat pending a need (they aren't
|
||||||
|
# super interesting except to determine functionality as they are mostly passive accessors, however
|
||||||
|
# they could be useful to determine if the header is available.
|
||||||
|
# pico_add_sdk_impl_library(hardware_${NAME})
|
||||||
add_library(hardware_${NAME} INTERFACE)
|
add_library(hardware_${NAME} INTERFACE)
|
||||||
|
|
||||||
target_include_directories(hardware_${NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
|
target_include_directories(hardware_${NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
|
||||||
@ -66,8 +90,14 @@ macro(pico_simple_hardware_headers_only_target NAME)
|
|||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
|
# create an INTERFACE library named hardware_NAME if it doesn't exist, dependent on a pre-existing hardware_NAME_headers
|
||||||
|
# INTERFACE library and pico_platform. The file NAME.c relative to the caller is added to the C sources for the hardware_NAME
|
||||||
macro(pico_simple_hardware_impl_target NAME)
|
macro(pico_simple_hardware_impl_target NAME)
|
||||||
if (NOT TARGET hardware_${NAME})
|
if (NOT TARGET hardware_${NAME})
|
||||||
|
# Choosing not to add LIB_HARDWARE_ defines to avoid command line bloat pending a need (they aren't
|
||||||
|
# super interesting except to determine functionality as they are mostly passive accessors, however
|
||||||
|
# they could be useful to determine if the header is available.
|
||||||
|
# pico_add_sdk_impl_library(hardware_${NAME})
|
||||||
add_library(hardware_${NAME} INTERFACE)
|
add_library(hardware_${NAME} INTERFACE)
|
||||||
|
|
||||||
target_sources(hardware_${NAME} INTERFACE
|
target_sources(hardware_${NAME} INTERFACE
|
||||||
@ -86,4 +116,6 @@ function(pico_add_doxygen_exclude SOURCE_DIR)
|
|||||||
set(PICO_DOXYGEN_EXCLUDE_PATHS "${PICO_DOXYGEN_EXCLUDE_PATHS} ${SOURCE_DIR}" CACHE INTERNAL "")
|
set(PICO_DOXYGEN_EXCLUDE_PATHS "${PICO_DOXYGEN_EXCLUDE_PATHS} ${SOURCE_DIR}" CACHE INTERNAL "")
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
include(${PICO_PLATFORM_CMAKE_FILE})
|
include(${PICO_PLATFORM_CMAKE_FILE})
|
||||||
|
|
||||||
|
pico_promote_common_scope_vars()
|
@ -15,6 +15,11 @@
|
|||||||
// For board detection
|
// For board detection
|
||||||
#define ADAFRUIT_FEATHER_RP2040
|
#define ADAFRUIT_FEATHER_RP2040
|
||||||
|
|
||||||
|
// On some samples, the xosc can take longer to stabilize than is usual
|
||||||
|
#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER
|
||||||
|
#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64
|
||||||
|
#endif
|
||||||
|
|
||||||
//------------- UART -------------//
|
//------------- UART -------------//
|
||||||
#ifndef PICO_DEFAULT_UART
|
#ifndef PICO_DEFAULT_UART
|
||||||
#define PICO_DEFAULT_UART 0
|
#define PICO_DEFAULT_UART 0
|
||||||
|
@ -15,6 +15,11 @@
|
|||||||
// For board detection
|
// For board detection
|
||||||
#define ADAFRUIT_ITSYBITSY_RP2040
|
#define ADAFRUIT_ITSYBITSY_RP2040
|
||||||
|
|
||||||
|
// On some samples, the xosc can take longer to stabilize than is usual
|
||||||
|
#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER
|
||||||
|
#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64
|
||||||
|
#endif
|
||||||
|
|
||||||
//------------- UART -------------//
|
//------------- UART -------------//
|
||||||
#ifndef PICO_DEFAULT_UART
|
#ifndef PICO_DEFAULT_UART
|
||||||
#define PICO_DEFAULT_UART 0
|
#define PICO_DEFAULT_UART 0
|
||||||
@ -80,7 +85,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PICO_FLASH_SIZE_BYTES
|
#ifndef PICO_FLASH_SIZE_BYTES
|
||||||
#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
|
#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// All boards have B1 RP2040
|
// All boards have B1 RP2040
|
||||||
|
@ -15,6 +15,11 @@
|
|||||||
// For board detection
|
// For board detection
|
||||||
#define ADAFRUIT_QTPY_RP2040
|
#define ADAFRUIT_QTPY_RP2040
|
||||||
|
|
||||||
|
// On some samples, the xosc can take longer to stabilize than is usual
|
||||||
|
#ifndef PICO_XOSC_STARTUP_DELAY_MULTIPLIER
|
||||||
|
#define PICO_XOSC_STARTUP_DELAY_MULTIPLIER 64
|
||||||
|
#endif
|
||||||
|
|
||||||
//------------- UART -------------//
|
//------------- UART -------------//
|
||||||
#ifndef PICO_DEFAULT_UART
|
#ifndef PICO_DEFAULT_UART
|
||||||
#define PICO_DEFAULT_UART 1
|
#define PICO_DEFAULT_UART 1
|
||||||
@ -25,7 +30,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PICO_DEFAULT_UART_RX_PIN
|
#ifndef PICO_DEFAULT_UART_RX_PIN
|
||||||
#define PICO_DEFAULT_UART_RX_PIN 9
|
#define PICO_DEFAULT_UART_RX_PIN 5
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//------------- LED -------------//
|
//------------- LED -------------//
|
||||||
@ -79,7 +84,7 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PICO_FLASH_SIZE_BYTES
|
#ifndef PICO_FLASH_SIZE_BYTES
|
||||||
#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
|
#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// All boards have B1 RP2040
|
// All boards have B1 RP2040
|
||||||
|
88
src/boards/include/boards/arduino_nano_rp2040_connect.h
Normal file
88
src/boards/include/boards/arduino_nano_rp2040_connect.h
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
// -----------------------------------------------------
|
||||||
|
// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
|
||||||
|
// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
|
||||||
|
// -----------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef _BOARDS_ARDUINO_NANO_RP2040_CONNECT_H
|
||||||
|
#define _BOARDS_ARDUINO_NANO_RP2040_CONNECT_H
|
||||||
|
|
||||||
|
// For board detection
|
||||||
|
#define ARDUINO_NANO_RP2040_CONNECT
|
||||||
|
|
||||||
|
//------------- UART -------------//
|
||||||
|
#ifndef PICO_DEFAULT_UART
|
||||||
|
#define PICO_DEFAULT_UART 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DEFAULT_UART_TX_PIN
|
||||||
|
#define PICO_DEFAULT_UART_TX_PIN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DEFAULT_UART_RX_PIN
|
||||||
|
#define PICO_DEFAULT_UART_RX_PIN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------- LED -------------//
|
||||||
|
#ifndef PICO_DEFAULT_LED_PIN
|
||||||
|
#define PICO_DEFAULT_LED_PIN 6
|
||||||
|
#endif
|
||||||
|
// no PICO_DEFAULT_WS2812_PIN
|
||||||
|
|
||||||
|
//------------- I2C -------------//
|
||||||
|
#ifndef PICO_DEFAULT_I2C
|
||||||
|
#define PICO_DEFAULT_I2C 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DEFAULT_I2C_SDA_PIN
|
||||||
|
#define PICO_DEFAULT_I2C_SDA_PIN 12
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DEFAULT_I2C_SCL_PIN
|
||||||
|
#define PICO_DEFAULT_I2C_SCL_PIN 13
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------- SPI -------------//
|
||||||
|
#ifndef PICO_DEFAULT_SPI
|
||||||
|
#define PICO_DEFAULT_SPI 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DEFAULT_SPI_TX_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_TX_PIN 7
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DEFAULT_SPI_RX_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_RX_PIN 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DEFAULT_SPI_SCK_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_SCK_PIN 6
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//------------- FLASH -------------//
|
||||||
|
|
||||||
|
#define PICO_BOOT_STAGE2_CHOOSE_AT25SF128A 1
|
||||||
|
|
||||||
|
#ifndef PICO_FLASH_SPI_CLKDIV
|
||||||
|
#define PICO_FLASH_SPI_CLKDIV 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_FLASH_SIZE_BYTES
|
||||||
|
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// All boards have B1 RP2040
|
||||||
|
#ifndef PICO_FLOAT_SUPPORT_ROM_V1
|
||||||
|
#define PICO_FLOAT_SUPPORT_ROM_V1 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DOUBLE_SUPPORT_ROM_V1
|
||||||
|
#define PICO_DOUBLE_SUPPORT_ROM_V1 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -14,6 +14,9 @@
|
|||||||
#ifndef _BOARDS_PICO_H
|
#ifndef _BOARDS_PICO_H
|
||||||
#define _BOARDS_PICO_H
|
#define _BOARDS_PICO_H
|
||||||
|
|
||||||
|
// For board detection
|
||||||
|
#define RASPBERRYPI_PICO
|
||||||
|
|
||||||
// --- UART ---
|
// --- UART ---
|
||||||
#ifndef PICO_DEFAULT_UART
|
#ifndef PICO_DEFAULT_UART
|
||||||
#define PICO_DEFAULT_UART 0
|
#define PICO_DEFAULT_UART 0
|
||||||
|
@ -15,18 +15,7 @@
|
|||||||
// For board detection
|
// For board detection
|
||||||
#define PIMORONI_KEYBOW2040
|
#define PIMORONI_KEYBOW2040
|
||||||
|
|
||||||
#ifndef PICO_DEFAULT_UART
|
// --- BOARD SPECIFIC ---
|
||||||
#define PICO_DEFAULT_UART 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PICO_DEFAULT_UART_TX_PIN
|
|
||||||
#define PICO_DEFAULT_UART_TX_PIN 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PICO_DEFAULT_UART_RX_PIN
|
|
||||||
#define PICO_DEFAULT_UART_RX_PIN 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef KEYBOW2040_I2C_SDA_PIN
|
#ifndef KEYBOW2040_I2C_SDA_PIN
|
||||||
#define KEYBOW2040_I2C_SDA_PIN 4
|
#define KEYBOW2040_I2C_SDA_PIN 4
|
||||||
#endif
|
#endif
|
||||||
@ -111,6 +100,42 @@
|
|||||||
#define KEYBOW2040_NUM_SWITCHES_PINS 16
|
#define KEYBOW2040_NUM_SWITCHES_PINS 16
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// --- UART ---
|
||||||
|
#ifndef PICO_DEFAULT_UART
|
||||||
|
#define PICO_DEFAULT_UART 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DEFAULT_UART_TX_PIN
|
||||||
|
#define PICO_DEFAULT_UART_TX_PIN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DEFAULT_UART_RX_PIN
|
||||||
|
#define PICO_DEFAULT_UART_RX_PIN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- LED ---
|
||||||
|
// no PICO_DEFAULT_LED_PIN
|
||||||
|
// no PICO_DEFAULT_WS2812_PIN
|
||||||
|
|
||||||
|
// --- I2C ---
|
||||||
|
#ifndef PICO_DEFAULT_I2C
|
||||||
|
#define PICO_DEFAULT_I2C 0
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_I2C_SDA_PIN
|
||||||
|
#define PICO_DEFAULT_I2C_SDA_PIN KEYBOW2040_I2C_SDA_PIN
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_I2C_SCL_PIN
|
||||||
|
#define PICO_DEFAULT_I2C_SCL_PIN KEYBOW2040_I2C_SCL_PIN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- SPI ---
|
||||||
|
// no PICO_DEFAULT_SPI
|
||||||
|
// no PICO_DEFAULT_SPI_SCK_PIN
|
||||||
|
// no PICO_DEFAULT_SPI_TX_PIN
|
||||||
|
// no PICO_DEFAULT_SPI_RX_PIN
|
||||||
|
// no PICO_DEFAULT_SPI_CSN_PIN
|
||||||
|
|
||||||
|
// --- FLASH ---
|
||||||
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
||||||
|
|
||||||
#ifndef PICO_FLASH_SPI_CLKDIV
|
#ifndef PICO_FLASH_SPI_CLKDIV
|
||||||
@ -122,7 +147,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// All boards have B1 RP2040
|
// All boards have B1 RP2040
|
||||||
|
|
||||||
#ifndef PICO_FLOAT_SUPPORT_ROM_V1
|
#ifndef PICO_FLOAT_SUPPORT_ROM_V1
|
||||||
#define PICO_FLOAT_SUPPORT_ROM_V1 0
|
#define PICO_FLOAT_SUPPORT_ROM_V1 0
|
||||||
#endif
|
#endif
|
||||||
|
83
src/boards/include/boards/pimoroni_pga2040.h
Normal file
83
src/boards/include/boards/pimoroni_pga2040.h
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
// -----------------------------------------------------
|
||||||
|
// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
|
||||||
|
// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
|
||||||
|
// -----------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef _BOARDS_PIMORONI_PGA2040_H
|
||||||
|
#define _BOARDS_PIMORONI_PGA2040_H
|
||||||
|
|
||||||
|
// For board detection
|
||||||
|
#define PIMORONI_PGA2040
|
||||||
|
|
||||||
|
// --- UART ---
|
||||||
|
#ifndef PICO_DEFAULT_UART
|
||||||
|
#define PICO_DEFAULT_UART 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DEFAULT_UART_TX_PIN
|
||||||
|
#define PICO_DEFAULT_UART_TX_PIN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DEFAULT_UART_RX_PIN
|
||||||
|
#define PICO_DEFAULT_UART_RX_PIN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- LED ---
|
||||||
|
// no PICO_DEFAULT_LED_PIN
|
||||||
|
// no PICO_DEFAULT_WS2812_PIN
|
||||||
|
|
||||||
|
// --- I2C ---
|
||||||
|
#ifndef PICO_DEFAULT_I2C
|
||||||
|
#define PICO_DEFAULT_I2C 0
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_I2C_SDA_PIN
|
||||||
|
#define PICO_DEFAULT_I2C_SDA_PIN 4
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_I2C_SCL_PIN
|
||||||
|
#define PICO_DEFAULT_I2C_SCL_PIN 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- SPI ---
|
||||||
|
#ifndef PICO_DEFAULT_SPI
|
||||||
|
#define PICO_DEFAULT_SPI 0
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_SCK_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_SCK_PIN 18
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_TX_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_TX_PIN 19
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_RX_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_RX_PIN 16
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_CSN_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_CSN_PIN 17
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- FLASH ---
|
||||||
|
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
||||||
|
|
||||||
|
#ifndef PICO_FLASH_SPI_CLKDIV
|
||||||
|
#define PICO_FLASH_SPI_CLKDIV 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_FLASH_SIZE_BYTES
|
||||||
|
#define PICO_FLASH_SIZE_BYTES (8 * 1024 * 1024)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// All boards have B1 RP2040
|
||||||
|
#ifndef PICO_FLOAT_SUPPORT_ROM_V1
|
||||||
|
#define PICO_FLOAT_SUPPORT_ROM_V1 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DOUBLE_SUPPORT_ROM_V1
|
||||||
|
#define PICO_DOUBLE_SUPPORT_ROM_V1 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
96
src/boards/include/boards/pimoroni_picolipo_16mb.h
Normal file
96
src/boards/include/boards/pimoroni_picolipo_16mb.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
// -----------------------------------------------------
|
||||||
|
// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
|
||||||
|
// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
|
||||||
|
// -----------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef _BOARDS_PIMORONI_PICOLIPO_16MB_H
|
||||||
|
#define _BOARDS_PIMORONI_PICOLIPO_16MB_H
|
||||||
|
|
||||||
|
// For board detection
|
||||||
|
#define PIMORONI_PICOLIPO_16MB
|
||||||
|
|
||||||
|
// --- BOARD SPECIFIC ---
|
||||||
|
#ifndef PICOLIPO_USER_SW_PIN
|
||||||
|
#define PICOLIPO_USER_SW_PIN 23
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICOLIPO_VBUS_DETECT_PIN
|
||||||
|
#define PICOLIPO_VBUS_DETECT_PIN 24
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICOLIPO_BAT_SENSE_PIN
|
||||||
|
#define PICOLIPO_BAT_SENSE_PIN 29
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- UART ---
|
||||||
|
#ifndef PICO_DEFAULT_UART
|
||||||
|
#define PICO_DEFAULT_UART 0
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_UART_TX_PIN
|
||||||
|
#define PICO_DEFAULT_UART_TX_PIN 0
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_UART_RX_PIN
|
||||||
|
#define PICO_DEFAULT_UART_RX_PIN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- LED ---
|
||||||
|
#ifndef PICO_DEFAULT_LED_PIN
|
||||||
|
#define PICO_DEFAULT_LED_PIN 25
|
||||||
|
#endif
|
||||||
|
// no PICO_DEFAULT_WS2812_PIN
|
||||||
|
|
||||||
|
// --- I2C ---
|
||||||
|
#ifndef PICO_DEFAULT_I2C
|
||||||
|
#define PICO_DEFAULT_I2C 0
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_I2C_SDA_PIN
|
||||||
|
#define PICO_DEFAULT_I2C_SDA_PIN 4
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_I2C_SCL_PIN
|
||||||
|
#define PICO_DEFAULT_I2C_SCL_PIN 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- SPI ---
|
||||||
|
#ifndef PICO_DEFAULT_SPI
|
||||||
|
#define PICO_DEFAULT_SPI 0
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_SCK_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_SCK_PIN 18
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_TX_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_TX_PIN 19
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_RX_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_RX_PIN 16
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_CSN_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_CSN_PIN 17
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- FLASH ---
|
||||||
|
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
||||||
|
|
||||||
|
#ifndef PICO_FLASH_SPI_CLKDIV
|
||||||
|
#define PICO_FLASH_SPI_CLKDIV 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_FLASH_SIZE_BYTES
|
||||||
|
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// All boards have B1 RP2040
|
||||||
|
#ifndef PICO_FLOAT_SUPPORT_ROM_V1
|
||||||
|
#define PICO_FLOAT_SUPPORT_ROM_V1 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DOUBLE_SUPPORT_ROM_V1
|
||||||
|
#define PICO_DOUBLE_SUPPORT_ROM_V1 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
96
src/boards/include/boards/pimoroni_picolipo_4mb.h
Normal file
96
src/boards/include/boards/pimoroni_picolipo_4mb.h
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
// -----------------------------------------------------
|
||||||
|
// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
|
||||||
|
// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
|
||||||
|
// -----------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef _BOARDS_PIMORONI_PICOLIPO_4MB_H
|
||||||
|
#define _BOARDS_PIMORONI_PICOLIPO_4MB_H
|
||||||
|
|
||||||
|
// For board detection
|
||||||
|
#define PIMORONI_PICOLIPO_4MB
|
||||||
|
|
||||||
|
// --- BOARD SPECIFIC ---
|
||||||
|
#ifndef PICOLIPO_USER_SW_PIN
|
||||||
|
#define PICOLIPO_USER_SW_PIN 23
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICOLIPO_VBUS_DETECT_PIN
|
||||||
|
#define PICOLIPO_VBUS_DETECT_PIN 24
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICOLIPO_BAT_SENSE_PIN
|
||||||
|
#define PICOLIPO_BAT_SENSE_PIN 29
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- UART ---
|
||||||
|
#ifndef PICO_DEFAULT_UART
|
||||||
|
#define PICO_DEFAULT_UART 0
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_UART_TX_PIN
|
||||||
|
#define PICO_DEFAULT_UART_TX_PIN 0
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_UART_RX_PIN
|
||||||
|
#define PICO_DEFAULT_UART_RX_PIN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- LED ---
|
||||||
|
#ifndef PICO_DEFAULT_LED_PIN
|
||||||
|
#define PICO_DEFAULT_LED_PIN 25
|
||||||
|
#endif
|
||||||
|
// no PICO_DEFAULT_WS2812_PIN
|
||||||
|
|
||||||
|
// --- I2C ---
|
||||||
|
#ifndef PICO_DEFAULT_I2C
|
||||||
|
#define PICO_DEFAULT_I2C 0
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_I2C_SDA_PIN
|
||||||
|
#define PICO_DEFAULT_I2C_SDA_PIN 4
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_I2C_SCL_PIN
|
||||||
|
#define PICO_DEFAULT_I2C_SCL_PIN 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- SPI ---
|
||||||
|
#ifndef PICO_DEFAULT_SPI
|
||||||
|
#define PICO_DEFAULT_SPI 0
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_SCK_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_SCK_PIN 18
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_TX_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_TX_PIN 19
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_RX_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_RX_PIN 16
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_CSN_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_CSN_PIN 17
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- FLASH ---
|
||||||
|
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
||||||
|
|
||||||
|
#ifndef PICO_FLASH_SPI_CLKDIV
|
||||||
|
#define PICO_FLASH_SPI_CLKDIV 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_FLASH_SIZE_BYTES
|
||||||
|
#define PICO_FLASH_SIZE_BYTES (4 * 1024 * 1024)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// All boards have B1 RP2040
|
||||||
|
#ifndef PICO_FLOAT_SUPPORT_ROM_V1
|
||||||
|
#define PICO_FLOAT_SUPPORT_ROM_V1 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DOUBLE_SUPPORT_ROM_V1
|
||||||
|
#define PICO_DOUBLE_SUPPORT_ROM_V1 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
@ -15,16 +15,21 @@
|
|||||||
// For board detection
|
// For board detection
|
||||||
#define PIMORONI_PICOSYSTEM
|
#define PIMORONI_PICOSYSTEM
|
||||||
|
|
||||||
|
// --- BOARD SPECIFIC ---
|
||||||
#ifndef PICOSYSTEM_VBUS_DETECT_PIN
|
#ifndef PICOSYSTEM_VBUS_DETECT_PIN
|
||||||
#define PICOSYSTEM_VBUS_DETECT_PIN 2
|
#define PICOSYSTEM_VBUS_DETECT_PIN 2
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICOSYSTEM_LCD_SPI
|
||||||
|
#define PICOSYSTEM_LCD_SPI 0
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef PICOSYSTEM_LCD_RESET_PIN
|
#ifndef PICOSYSTEM_LCD_RESET_PIN
|
||||||
#define PICOSYSTEM_LCD_RESET_PIN 4
|
#define PICOSYSTEM_LCD_RESET_PIN 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PICOSYSTEM_LCD_CS_PIN
|
#ifndef PICOSYSTEM_LCD_CSN_PIN
|
||||||
#define PICOSYSTEM_LCD_CS_PIN 5
|
#define PICOSYSTEM_LCD_CSN_PIN 5
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef PICOSYSTEM_LCD_SCLK_PIN
|
#ifndef PICOSYSTEM_LCD_SCLK_PIN
|
||||||
@ -103,6 +108,7 @@
|
|||||||
#define PICOSYSTEM_BAT_SENSE_PIN 26
|
#define PICOSYSTEM_BAT_SENSE_PIN 26
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// --- UART ---
|
||||||
#ifndef PICO_DEFAULT_UART
|
#ifndef PICO_DEFAULT_UART
|
||||||
#define PICO_DEFAULT_UART 0
|
#define PICO_DEFAULT_UART 0
|
||||||
#endif
|
#endif
|
||||||
@ -115,15 +121,30 @@
|
|||||||
#define PICO_DEFAULT_UART_RX_PIN 1
|
#define PICO_DEFAULT_UART_RX_PIN 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// --- LED ---
|
||||||
// Included so basic examples will work, and set it to the green LED
|
// Included so basic examples will work, and set it to the green LED
|
||||||
#ifndef PICO_DEFAULT_LED_PIN
|
#ifndef PICO_DEFAULT_LED_PIN
|
||||||
#define PICO_DEFAULT_LED_PIN PICOSYSTEM_LED_G_PIN
|
#define PICO_DEFAULT_LED_PIN PICOSYSTEM_LED_G_PIN
|
||||||
#endif
|
#endif
|
||||||
|
// no PICO_DEFAULT_WS2812_PIN
|
||||||
|
|
||||||
#ifndef PICO_DEFAULT_LED_PIN_INVERTED
|
#ifndef PICO_DEFAULT_LED_PIN_INVERTED
|
||||||
#define PICO_DEFAULT_LED_PIN_INVERTED 1
|
#define PICO_DEFAULT_LED_PIN_INVERTED 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// --- I2C ---
|
||||||
|
//no PICO_DEFAULT_I2C
|
||||||
|
//no PICO_DEFAULT_I2C_SDA_PIN
|
||||||
|
//no PICO_DEFAULT_I2C_SCL_PIN
|
||||||
|
|
||||||
|
// --- SPI ---
|
||||||
|
// no PICO_DEFAULT_SPI
|
||||||
|
// no PICO_DEFAULT_SPI_SCK_PIN
|
||||||
|
// no PICO_DEFAULT_SPI_TX_PIN
|
||||||
|
// no PICO_DEFAULT_SPI_RX_PIN
|
||||||
|
// no PICO_DEFAULT_SPI_CSN_PIN
|
||||||
|
|
||||||
|
// --- FLASH ---
|
||||||
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
||||||
|
|
||||||
#ifndef PICO_FLASH_SPI_CLKDIV
|
#ifndef PICO_FLASH_SPI_CLKDIV
|
||||||
@ -135,7 +156,6 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// All boards have B1 RP2040
|
// All boards have B1 RP2040
|
||||||
|
|
||||||
#ifndef PICO_FLOAT_SUPPORT_ROM_V1
|
#ifndef PICO_FLOAT_SUPPORT_ROM_V1
|
||||||
#define PICO_FLOAT_SUPPORT_ROM_V1 0
|
#define PICO_FLOAT_SUPPORT_ROM_V1 0
|
||||||
#endif
|
#endif
|
||||||
|
@ -15,18 +15,7 @@
|
|||||||
// For board detection
|
// For board detection
|
||||||
#define PIMORONI_TINY2040
|
#define PIMORONI_TINY2040
|
||||||
|
|
||||||
#ifndef PICO_DEFAULT_UART
|
// --- BOARD SPECIFIC ---
|
||||||
#define PICO_DEFAULT_UART 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PICO_DEFAULT_UART_TX_PIN
|
|
||||||
#define PICO_DEFAULT_UART_TX_PIN 0
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef PICO_DEFAULT_UART_RX_PIN
|
|
||||||
#define PICO_DEFAULT_UART_RX_PIN 1
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef TINY2040_LED_R_PIN
|
#ifndef TINY2040_LED_R_PIN
|
||||||
#define TINY2040_LED_R_PIN 18
|
#define TINY2040_LED_R_PIN 18
|
||||||
#endif
|
#endif
|
||||||
@ -67,15 +56,59 @@
|
|||||||
#define TINY2040_NUM_ADC_PINS 4
|
#define TINY2040_NUM_ADC_PINS 4
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// --- UART ---
|
||||||
|
#ifndef PICO_DEFAULT_UART
|
||||||
|
#define PICO_DEFAULT_UART 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DEFAULT_UART_TX_PIN
|
||||||
|
#define PICO_DEFAULT_UART_TX_PIN 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef PICO_DEFAULT_UART_RX_PIN
|
||||||
|
#define PICO_DEFAULT_UART_RX_PIN 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- LED ---
|
||||||
// Included so basic examples will work, and set it to the green LED
|
// Included so basic examples will work, and set it to the green LED
|
||||||
#ifndef PICO_DEFAULT_LED_PIN
|
#ifndef PICO_DEFAULT_LED_PIN
|
||||||
#define PICO_DEFAULT_LED_PIN TINY2040_LED_G_PIN
|
#define PICO_DEFAULT_LED_PIN TINY2040_LED_G_PIN
|
||||||
#endif
|
#endif
|
||||||
|
// no PICO_DEFAULT_WS2812_PIN
|
||||||
|
|
||||||
#ifndef PICO_DEFAULT_LED_PIN_INVERTED
|
#ifndef PICO_DEFAULT_LED_PIN_INVERTED
|
||||||
#define PICO_DEFAULT_LED_PIN_INVERTED 1
|
#define PICO_DEFAULT_LED_PIN_INVERTED 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// --- I2C ---
|
||||||
|
#ifndef PICO_DEFAULT_I2C
|
||||||
|
#define PICO_DEFAULT_I2C 1
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_I2C_SDA_PIN
|
||||||
|
#define PICO_DEFAULT_I2C_SDA_PIN 2
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_I2C_SCL_PIN
|
||||||
|
#define PICO_DEFAULT_I2C_SCL_PIN 3
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- SPI ---
|
||||||
|
#ifndef PICO_DEFAULT_SPI
|
||||||
|
#define PICO_DEFAULT_SPI 0
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_SCK_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_SCK_PIN 6
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_TX_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_TX_PIN 7
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_RX_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_RX_PIN 4
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_CSN_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_CSN_PIN 5
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// --- FLASH ---
|
||||||
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
||||||
|
|
||||||
#ifndef PICO_FLASH_SPI_CLKDIV
|
#ifndef PICO_FLASH_SPI_CLKDIV
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
#ifndef _BOARDS_SPARKFUN_MICROMOD_H
|
#ifndef _BOARDS_SPARKFUN_MICROMOD_H
|
||||||
#define _BOARDS_SPARKFUN_MICROMOD_H
|
#define _BOARDS_SPARKFUN_MICROMOD_H
|
||||||
|
|
||||||
|
// For board detection
|
||||||
|
#define SPARKFUN_MICROMOD
|
||||||
|
|
||||||
#ifndef PICO_DEFAULT_UART
|
#ifndef PICO_DEFAULT_UART
|
||||||
#define PICO_DEFAULT_UART 0
|
#define PICO_DEFAULT_UART 0
|
||||||
#endif
|
#endif
|
||||||
@ -46,6 +49,23 @@
|
|||||||
#define PICO_DEFAULT_I2C_SCL_PIN 5
|
#define PICO_DEFAULT_I2C_SCL_PIN 5
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// --- SPI ---
|
||||||
|
#ifndef PICO_DEFAULT_SPI
|
||||||
|
#define PICO_DEFAULT_SPI 0
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_SCK_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_SCK_PIN 22
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_TX_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_TX_PIN 23
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_RX_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_RX_PIN 20
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_CSN_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_CSN_PIN 21
|
||||||
|
#endif
|
||||||
|
|
||||||
// spi flash
|
// spi flash
|
||||||
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
||||||
|
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
#ifndef _BOARDS_SPARKFUN_PROMICRO_H
|
#ifndef _BOARDS_SPARKFUN_PROMICRO_H
|
||||||
#define _BOARDS_SPARKFUN_PROMICRO_H
|
#define _BOARDS_SPARKFUN_PROMICRO_H
|
||||||
|
|
||||||
|
// For board detection
|
||||||
|
#define SPARKFUN_PROMICRO
|
||||||
|
|
||||||
#ifndef PICO_DEFAULT_UART
|
#ifndef PICO_DEFAULT_UART
|
||||||
#define PICO_DEFAULT_UART 0
|
#define PICO_DEFAULT_UART 0
|
||||||
#endif
|
#endif
|
||||||
@ -46,6 +49,23 @@
|
|||||||
#define PICO_DEFAULT_I2C_SCL_PIN 17
|
#define PICO_DEFAULT_I2C_SCL_PIN 17
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// --- SPI ---
|
||||||
|
#ifndef PICO_DEFAULT_SPI
|
||||||
|
#define PICO_DEFAULT_SPI 0
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_SCK_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_SCK_PIN 22
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_TX_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_TX_PIN 23
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_RX_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_RX_PIN 20
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_CSN_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_CSN_PIN 21
|
||||||
|
#endif
|
||||||
|
|
||||||
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
||||||
|
|
||||||
#ifndef PICO_FLASH_SPI_CLKDIV
|
#ifndef PICO_FLASH_SPI_CLKDIV
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
#ifndef _BOARDS_SPARKFUN_THINGPLUS_H
|
#ifndef _BOARDS_SPARKFUN_THINGPLUS_H
|
||||||
#define _BOARDS_SPARKFUN_THINGPLUS_H
|
#define _BOARDS_SPARKFUN_THINGPLUS_H
|
||||||
|
|
||||||
|
// For board detection
|
||||||
|
#define SPARKFUN_THINGPLUS
|
||||||
|
|
||||||
#ifndef PICO_DEFAULT_UART
|
#ifndef PICO_DEFAULT_UART
|
||||||
#define PICO_DEFAULT_UART 0
|
#define PICO_DEFAULT_UART 0
|
||||||
#endif
|
#endif
|
||||||
@ -42,6 +45,21 @@
|
|||||||
#define PICO_DEFAULT_I2C_SCL_PIN 7
|
#define PICO_DEFAULT_I2C_SCL_PIN 7
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// --- SPI ---
|
||||||
|
#ifndef PICO_DEFAULT_SPI
|
||||||
|
#define PICO_DEFAULT_SPI 0
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_SCK_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_SCK_PIN 2
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_TX_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_TX_PIN 3
|
||||||
|
#endif
|
||||||
|
#ifndef PICO_DEFAULT_SPI_RX_PIN
|
||||||
|
#define PICO_DEFAULT_SPI_RX_PIN 4
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// spi flash
|
// spi flash
|
||||||
|
|
||||||
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
#define PICO_BOOT_STAGE2_CHOOSE_W25Q080 1
|
||||||
@ -54,7 +72,7 @@
|
|||||||
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
|
#define PICO_FLASH_SIZE_BYTES (16 * 1024 * 1024)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// The thing plus has a SD Card.
|
// The thing plus has a SD Card.
|
||||||
#define PICO_SD_CLK_PIN 14
|
#define PICO_SD_CLK_PIN 14
|
||||||
#define PICO_SD_CMD_PIN 15
|
#define PICO_SD_CMD_PIN 15
|
||||||
#define PICO_SD_DAT0_PIN 12
|
#define PICO_SD_DAT0_PIN 12
|
||||||
|
@ -12,6 +12,9 @@
|
|||||||
#ifndef _BOARDS_VGABOARD_H
|
#ifndef _BOARDS_VGABOARD_H
|
||||||
#define _BOARDS_VGABOARD_H
|
#define _BOARDS_VGABOARD_H
|
||||||
|
|
||||||
|
// For board detection
|
||||||
|
#define RASPBERRYPI_VGABOARD
|
||||||
|
|
||||||
// Audio pins. I2S BCK, LRCK are on the same pins as PWM L/R.
|
// Audio pins. I2S BCK, LRCK are on the same pins as PWM L/R.
|
||||||
// - When outputting I2S, PWM sees BCK and LRCK, which should sound silent as
|
// - When outputting I2S, PWM sees BCK and LRCK, which should sound silent as
|
||||||
// they are constant duty cycle, and above the filter cutoff
|
// they are constant duty cycle, and above the filter cutoff
|
||||||
|
@ -13,4 +13,6 @@ if (NOT PICO_BARE_METAL)
|
|||||||
pico_add_subdirectory(pico_stdlib)
|
pico_add_subdirectory(pico_stdlib)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
pico_add_doxygen(${CMAKE_CURRENT_LIST_DIR})
|
pico_add_doxygen(${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
|
||||||
|
pico_promote_common_scope_vars()
|
@ -1,40 +1,13 @@
|
|||||||
if (NOT TARGET pico_base_headers)
|
if (NOT TARGET pico_base_headers)
|
||||||
# build the auto gen config headers
|
|
||||||
|
|
||||||
set(header_content "// AUTOGENERATED FROM PICO_CONFIG_HEADER_FILES and then PICO_<PLATFORM>_CONFIG_HEADER_FILES\n// DO NOT EDIT!\n")
|
|
||||||
string(TOUPPER ${PICO_PLATFORM} PICO_PLATFORM_UPPER)
|
|
||||||
|
|
||||||
macro(add_header_content_from_var VAR)
|
|
||||||
set(header_content "${header_content}\n\n// based on ${VAR}:\n")
|
|
||||||
foreach(var IN LISTS ${VAR})
|
|
||||||
set(header_content "${header_content}\n#include \"${var}\"")
|
|
||||||
endforeach()
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
# PICO_CMAKE_CONFIG: PICO_CONFIG_HEADER_FILES, List of extra header files to include from pico/config.h for all platforms, type=list, default="", group=pico_base
|
|
||||||
add_header_content_from_var(PICO_CONFIG_HEADER_FILES)
|
|
||||||
|
|
||||||
# PICO_CMAKE_CONFIG: PICO_CONFIG_RP2040_HEADER_FILES, List of extra header files to include from pico/config.h for rp2040 platform, type=list, default="", group=pico_base
|
|
||||||
# PICO_CMAKE_CONFIG: PICO_CONFIG_HOST_HEADER_FILES, List of extra header files to include from pico/config.h for host platform, type=list, default="", group=pico_base
|
|
||||||
add_header_content_from_var(PICO_${PICO_PLATFORM_UPPER}_CONFIG_HEADER_FILES)
|
|
||||||
|
|
||||||
file(GENERATE
|
|
||||||
OUTPUT ${CMAKE_BINARY_DIR}/generated/pico_base/pico/config_autogen.h
|
|
||||||
CONTENT "${header_content}"
|
|
||||||
)
|
|
||||||
|
|
||||||
configure_file( include/pico/version.h.in ${CMAKE_BINARY_DIR}/generated/pico_base/pico/version.h)
|
|
||||||
|
|
||||||
add_library(pico_base_headers INTERFACE)
|
add_library(pico_base_headers INTERFACE)
|
||||||
target_include_directories(pico_base_headers INTERFACE include ${CMAKE_BINARY_DIR}/generated/pico_base)
|
target_include_directories(pico_base_headers INTERFACE include ${CMAKE_BINARY_DIR}/generated/pico_base)
|
||||||
|
|
||||||
foreach(DIR IN LISTS PICO_INCLUDE_DIRS)
|
|
||||||
target_include_directories(pico_base_headers INTERFACE ${DIR})
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
# PICO_BUILD_DEFINE: PICO_BOARD, Name of board, type=string, default=CMake PICO_BOARD variable, group=pico_base
|
# PICO_BUILD_DEFINE: PICO_BOARD, Name of board, type=string, default=CMake PICO_BOARD variable, group=pico_base
|
||||||
target_compile_definitions(pico_base_headers INTERFACE
|
target_compile_definitions(pico_base_headers INTERFACE
|
||||||
PICO_BOARD="${PICO_BOARD}")
|
PICO_BOARD="${PICO_BOARD}")
|
||||||
|
|
||||||
target_link_libraries(pico_base_headers INTERFACE pico_platform_headers)
|
target_link_libraries(pico_base_headers INTERFACE pico_platform_headers)
|
||||||
|
|
||||||
|
list(APPEND PICO_SDK_POST_LIST_FILES ${CMAKE_CURRENT_LIST_DIR}/generate_config_header.cmake)
|
||||||
|
pico_promote_common_scope_vars()
|
||||||
endif()
|
endif()
|
29
src/common/pico_base/generate_config_header.cmake
Normal file
29
src/common/pico_base/generate_config_header.cmake
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
# build the auto gen config headers
|
||||||
|
|
||||||
|
set(header_content "// AUTOGENERATED FROM PICO_CONFIG_HEADER_FILES and then PICO_<PLATFORM>_CONFIG_HEADER_FILES\n// DO NOT EDIT!\n")
|
||||||
|
string(TOUPPER ${PICO_PLATFORM} PICO_PLATFORM_UPPER)
|
||||||
|
|
||||||
|
macro(add_header_content_from_var VAR)
|
||||||
|
set(header_content "${header_content}\n\n// based on ${VAR}:\n")
|
||||||
|
foreach(var IN LISTS ${VAR})
|
||||||
|
set(header_content "${header_content}\n#include \"${var}\"")
|
||||||
|
endforeach()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# PICO_CMAKE_CONFIG: PICO_CONFIG_HEADER_FILES, List of extra header files to include from pico/config.h for all platforms, type=list, default="", group=pico_base
|
||||||
|
add_header_content_from_var(PICO_CONFIG_HEADER_FILES)
|
||||||
|
|
||||||
|
# PICO_CMAKE_CONFIG: PICO_CONFIG_RP2040_HEADER_FILES, List of extra header files to include from pico/config.h for rp2040 platform, type=list, default="", group=pico_base
|
||||||
|
# PICO_CMAKE_CONFIG: PICO_CONFIG_HOST_HEADER_FILES, List of extra header files to include from pico/config.h for host platform, type=list, default="", group=pico_base
|
||||||
|
add_header_content_from_var(PICO_${PICO_PLATFORM_UPPER}_CONFIG_HEADER_FILES)
|
||||||
|
|
||||||
|
file(GENERATE
|
||||||
|
OUTPUT ${CMAKE_BINARY_DIR}/generated/pico_base/pico/config_autogen.h
|
||||||
|
CONTENT "${header_content}"
|
||||||
|
)
|
||||||
|
|
||||||
|
configure_file( ${CMAKE_CURRENT_LIST_DIR}/include/pico/version.h.in ${CMAKE_BINARY_DIR}/generated/pico_base/pico/version.h)
|
||||||
|
|
||||||
|
foreach(DIR IN LISTS PICO_INCLUDE_DIRS)
|
||||||
|
target_include_directories(pico_base_headers INTERFACE ${DIR})
|
||||||
|
endforeach()
|
@ -2,7 +2,11 @@ add_library(pico_binary_info_headers INTERFACE)
|
|||||||
|
|
||||||
target_include_directories(pico_binary_info_headers INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
|
target_include_directories(pico_binary_info_headers INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
|
||||||
|
|
||||||
add_library(pico_binary_info INTERFACE)
|
if (COMMAND pico_add_platform_library)
|
||||||
|
pico_add_platform_library(pico_binary_info)
|
||||||
|
else()
|
||||||
|
add_library(pico_binary_info INTERFACE)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(pico_binary_info INTERFACE pico_binary_info_headers)
|
target_link_libraries(pico_binary_info INTERFACE pico_binary_info_headers)
|
||||||
|
|
||||||
|
@ -44,15 +44,15 @@ extern "C" {
|
|||||||
// respective INTERFACE libraries, so these defines are set if the library
|
// respective INTERFACE libraries, so these defines are set if the library
|
||||||
// is included for the target executable
|
// is included for the target executable
|
||||||
|
|
||||||
#if PICO_STDIO_UART
|
#if LIB_PICO_STDIO_UART
|
||||||
#include "pico/stdio_uart.h"
|
#include "pico/stdio_uart.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PICO_STDIO_USB
|
#if LIB_PICO_STDIO_USB
|
||||||
#include "pico/stdio_usb.h"
|
#include "pico/stdio_usb.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if PICO_STDIO_SEMIHOSTING
|
#if LIB_PICO_STDIO_SEMIHOSTING
|
||||||
#include "pico/stdio_semihosting.h"
|
#include "pico/stdio_semihosting.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ if (NOT TARGET pico_sync_headers)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT TARGET pico_sync_core)
|
if (NOT TARGET pico_sync_core)
|
||||||
add_library(pico_sync_core INTERFACE)
|
pico_add_impl_library(pico_sync_core)
|
||||||
target_sources(pico_sync_core INTERFACE
|
target_sources(pico_sync_core INTERFACE
|
||||||
${CMAKE_CURRENT_LIST_DIR}/lock_core.c
|
${CMAKE_CURRENT_LIST_DIR}/lock_core.c
|
||||||
)
|
)
|
||||||
@ -13,7 +13,7 @@ if (NOT TARGET pico_sync_core)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT TARGET pico_sync_sem)
|
if (NOT TARGET pico_sync_sem)
|
||||||
add_library(pico_sync_sem INTERFACE)
|
pico_add_impl_library(pico_sync_sem)
|
||||||
target_sources(pico_sync_sem INTERFACE
|
target_sources(pico_sync_sem INTERFACE
|
||||||
${CMAKE_CURRENT_LIST_DIR}/sem.c
|
${CMAKE_CURRENT_LIST_DIR}/sem.c
|
||||||
)
|
)
|
||||||
@ -21,7 +21,7 @@ if (NOT TARGET pico_sync_sem)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT TARGET pico_sync_mutex)
|
if (NOT TARGET pico_sync_mutex)
|
||||||
add_library(pico_sync_mutex INTERFACE)
|
pico_add_impl_library(pico_sync_mutex)
|
||||||
target_sources(pico_sync_mutex INTERFACE
|
target_sources(pico_sync_mutex INTERFACE
|
||||||
${CMAKE_CURRENT_LIST_DIR}/mutex.c
|
${CMAKE_CURRENT_LIST_DIR}/mutex.c
|
||||||
)
|
)
|
||||||
@ -29,7 +29,7 @@ if (NOT TARGET pico_sync_mutex)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT TARGET pico_sync_critical_section)
|
if (NOT TARGET pico_sync_critical_section)
|
||||||
add_library(pico_sync_critical_section INTERFACE)
|
pico_add_impl_library(pico_sync_critical_section)
|
||||||
target_sources(pico_sync_critical_section INTERFACE
|
target_sources(pico_sync_critical_section INTERFACE
|
||||||
${CMAKE_CURRENT_LIST_DIR}/critical_section.c
|
${CMAKE_CURRENT_LIST_DIR}/critical_section.c
|
||||||
)
|
)
|
||||||
@ -37,7 +37,7 @@ if (NOT TARGET pico_sync_critical_section)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT TARGET pico_sync)
|
if (NOT TARGET pico_sync)
|
||||||
add_library(pico_sync INTERFACE)
|
pico_add_impl_library(pico_sync)
|
||||||
target_link_libraries(pico_sync INTERFACE pico_sync_sem pico_sync_mutex pico_sync_critical_section pico_sync_core)
|
target_link_libraries(pico_sync INTERFACE pico_sync_sem pico_sync_mutex pico_sync_critical_section pico_sync_core)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
@ -10,15 +10,18 @@
|
|||||||
static_assert(sizeof(critical_section_t) == 8, "");
|
static_assert(sizeof(critical_section_t) == 8, "");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void critical_section_init(critical_section_t *critsec) {
|
void critical_section_init(critical_section_t *crit_sec) {
|
||||||
critical_section_init_with_lock_num(critsec, (uint)spin_lock_claim_unused(true));
|
critical_section_init_with_lock_num(crit_sec, (uint)spin_lock_claim_unused(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
void critical_section_init_with_lock_num(critical_section_t *critsec, uint lock_num) {
|
void critical_section_init_with_lock_num(critical_section_t *crit_sec, uint lock_num) {
|
||||||
lock_init(&critsec->core, lock_num);
|
crit_sec->spin_lock = spin_lock_instance(lock_num);
|
||||||
__mem_fence_release();
|
__mem_fence_release();
|
||||||
}
|
}
|
||||||
|
|
||||||
void critical_section_deinit(critical_section_t *critsec) {
|
void critical_section_deinit(critical_section_t *crit_sec) {
|
||||||
spin_lock_unclaim(spin_lock_get_num(critsec->core.spin_lock));
|
spin_lock_unclaim(spin_lock_get_num(crit_sec->spin_lock));
|
||||||
|
#ifndef NDEBUG
|
||||||
|
crit_sec->spin_lock = (spin_lock_t *)-1;
|
||||||
|
#endif
|
||||||
}
|
}
|
@ -22,11 +22,12 @@ extern "C" {
|
|||||||
* from the other core, and from (higher priority) interrupts on the same core. It does the former
|
* from the other core, and from (higher priority) interrupts on the same core. It does the former
|
||||||
* using a spin lock and the latter by disabling interrupts on the calling core.
|
* using a spin lock and the latter by disabling interrupts on the calling core.
|
||||||
*
|
*
|
||||||
* Because interrupts are disabled by this function, uses of the critical_section should be as short as possible.
|
* Because interrupts are disabled when a critical_section is owned, uses of the critical_section
|
||||||
|
* should be as short as possible.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct __packed_aligned critical_section {
|
typedef struct __packed_aligned critical_section {
|
||||||
lock_core_t core;
|
spin_lock_t *spin_lock;
|
||||||
uint32_t save;
|
uint32_t save;
|
||||||
} critical_section_t;
|
} critical_section_t;
|
||||||
|
|
||||||
@ -38,16 +39,16 @@ typedef struct __packed_aligned critical_section {
|
|||||||
* critical sections, however if you do so you *must* use \ref critical_section_init_with_lock_num
|
* critical sections, however if you do so you *must* use \ref critical_section_init_with_lock_num
|
||||||
* to ensure that the spin lock's used are different.
|
* to ensure that the spin lock's used are different.
|
||||||
*
|
*
|
||||||
* \param critsec Pointer to critical_section structure
|
* \param crit_sec Pointer to critical_section structure
|
||||||
*/
|
*/
|
||||||
void critical_section_init(critical_section_t *critsec);
|
void critical_section_init(critical_section_t *crit_sec);
|
||||||
|
|
||||||
/*! \brief Initialise a critical_section structure assigning a specific spin lock number
|
/*! \brief Initialise a critical_section structure assigning a specific spin lock number
|
||||||
* \ingroup critical_section
|
* \ingroup critical_section
|
||||||
* \param critsec Pointer to critical_section structure
|
* \param crit_sec Pointer to critical_section structure
|
||||||
* \param lock_num the specific spin lock number to use
|
* \param lock_num the specific spin lock number to use
|
||||||
*/
|
*/
|
||||||
void critical_section_init_with_lock_num(critical_section_t *critsec, uint lock_num);
|
void critical_section_init_with_lock_num(critical_section_t *crit_sec, uint lock_num);
|
||||||
|
|
||||||
/*! \brief Enter a critical_section
|
/*! \brief Enter a critical_section
|
||||||
* \ingroup critical_section
|
* \ingroup critical_section
|
||||||
@ -55,20 +56,32 @@ void critical_section_init_with_lock_num(critical_section_t *critsec, uint lock_
|
|||||||
* If the spin lock associated with this critical section is in use, then this
|
* If the spin lock associated with this critical section is in use, then this
|
||||||
* method will block until it is released.
|
* method will block until it is released.
|
||||||
*
|
*
|
||||||
* \param critsec Pointer to critical_section structure
|
* \param crit_sec Pointer to critical_section structure
|
||||||
*/
|
*/
|
||||||
static inline void critical_section_enter_blocking(critical_section_t *critsec) {
|
static inline void critical_section_enter_blocking(critical_section_t *crit_sec) {
|
||||||
critsec->save = spin_lock_blocking(critsec->core.spin_lock);
|
crit_sec->save = spin_lock_blocking(crit_sec->spin_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Release a critical_section
|
/*! \brief Release a critical_section
|
||||||
* \ingroup critical_section
|
* \ingroup critical_section
|
||||||
*
|
*
|
||||||
* \param critsec Pointer to critical_section structure
|
* \param crit_sec Pointer to critical_section structure
|
||||||
*/
|
*/
|
||||||
static inline void critical_section_exit(critical_section_t *critsec) {
|
static inline void critical_section_exit(critical_section_t *crit_sec) {
|
||||||
spin_unlock(critsec->core.spin_lock, critsec->save);
|
spin_unlock(crit_sec->spin_lock, crit_sec->save);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief De-Initialise a critical_section created by the critical_section_init method
|
||||||
|
* \ingroup critical_section
|
||||||
|
*
|
||||||
|
* This method is only used to free the associated spin lock allocated via
|
||||||
|
* the critical_section_init method (it should not be used to de-initialize a spin lock
|
||||||
|
* created via critical_section_init_with_lock_num). After this call, the critical section is invalid
|
||||||
|
*
|
||||||
|
* \param crit_sec Pointer to critical_section structure
|
||||||
|
*/
|
||||||
|
void critical_section_deinit(critical_section_t *crit_sec);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -8,26 +8,183 @@
|
|||||||
#define _PICO_LOCK_CORE_H
|
#define _PICO_LOCK_CORE_H
|
||||||
|
|
||||||
#include "pico.h"
|
#include "pico.h"
|
||||||
|
#include "pico/time.h"
|
||||||
#include "hardware/sync.h"
|
#include "hardware/sync.h"
|
||||||
|
|
||||||
|
/** \file lock_core.h
|
||||||
|
* \defgroup lock_core lock_core
|
||||||
|
* \ingroup pico_sync
|
||||||
|
* \brief base synchronization/lock primitive support
|
||||||
|
*
|
||||||
|
* Most of the pico_sync locking primitives contain a lock_core_t structure member. This currently just holds a spin
|
||||||
|
* lock which is used only to protect the contents of the rest of the structure as part of implementing the synchronization
|
||||||
|
* primitive. As such, the spin_lock member of lock core is never still held on return from any function for the primitive.
|
||||||
|
*
|
||||||
|
* \ref critical_section is an exceptional case in that it does not have a lock_core_t and simply wraps a spin lock, providing
|
||||||
|
* methods to lock and unlock said spin lock.
|
||||||
|
*
|
||||||
|
* lock_core based structures work by locking the spin lock, checking state, and then deciding whether they additionally need to block
|
||||||
|
* or notify when the spin lock is released. In the blocking case, they will wake up again in the future, and try the process again.
|
||||||
|
*
|
||||||
|
* By default the SDK just uses the processors' events via SEV and WEV for notification and blocking as these are sufficient for
|
||||||
|
* cross core, and notification from interrupt handlers. However macros are defined in this file that abstract the wait
|
||||||
|
* and notify mechanisms to allow the SDK locking functions to effectively be used within an RTOS or other environment.
|
||||||
|
*
|
||||||
|
* When implementing an RTOS, it is desirable for the SDK synchronization primitives that wait, to block the calling task (and immediately yield),
|
||||||
|
* and those that notify, to wake a blocked task which isn't on processor. At least the wait macro implementation needs to be atomic with the protecting
|
||||||
|
* spin_lock unlock from the callers point of view; i.e. the task should unlock the spin lock when it starts its wait. Such implementation is
|
||||||
|
* up to the RTOS integration, however the macros are defined such that such operations are always combined into a single call
|
||||||
|
* (so they can be perfomed atomically) even though the default implementation does not need this, as a WFE which starts
|
||||||
|
* following the corresponding SEV is not missed.
|
||||||
|
*/
|
||||||
|
|
||||||
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_LOCK_CORE, Enable/disable assertions in the lock core, type=bool, default=0, group=pico_sync
|
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_LOCK_CORE, Enable/disable assertions in the lock core, type=bool, default=0, group=pico_sync
|
||||||
#ifndef PARAM_ASSERTIONS_ENABLED_LOCK_CORE
|
#ifndef PARAM_ASSERTIONS_ENABLED_LOCK_CORE
|
||||||
#define PARAM_ASSERTIONS_ENABLED_LOCK_CORE 0
|
#define PARAM_ASSERTIONS_ENABLED_LOCK_CORE 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/** \file lock_core.h
|
/** \file lock_core.h
|
||||||
* \ingroup pico_sync
|
* \ingroup lock_core
|
||||||
*
|
*
|
||||||
* Base implementation for locking primitives protected by a spin lock
|
* Base implementation for locking primitives protected by a spin lock. The spin lock is only used to protect
|
||||||
|
* access to the remaining lock state (in primitives using lock_core); it is never left locked outside
|
||||||
|
* of the function implementations
|
||||||
*/
|
*/
|
||||||
typedef struct lock_core {
|
struct lock_core {
|
||||||
// spin lock protecting this lock's state
|
// spin lock protecting this lock's state
|
||||||
spin_lock_t *spin_lock;
|
spin_lock_t *spin_lock;
|
||||||
|
|
||||||
// note any lock members in containing structures need not be volatile;
|
// note any lock members in containing structures need not be volatile;
|
||||||
// they are protected by memory/compiler barriers when gaining and release spin locks
|
// they are protected by memory/compiler barriers when gaining and release spin locks
|
||||||
} lock_core_t;
|
};
|
||||||
|
|
||||||
|
typedef struct lock_core lock_core_t;
|
||||||
|
|
||||||
|
/*! \brief Initialise a lock structure
|
||||||
|
* \ingroup lock_core
|
||||||
|
*
|
||||||
|
* Inititalize a lock structure, providing the spin lock number to use for protecting internal state.
|
||||||
|
*
|
||||||
|
* \param core Pointer to the lock_core to initialize
|
||||||
|
* \param lock_num Spin lock number to use for the lock. As the spin lock is only used internally to the locking primitive
|
||||||
|
* method implementations, this does not need to be globally unique, however could suffer contention
|
||||||
|
*/
|
||||||
void lock_init(lock_core_t *core, uint lock_num);
|
void lock_init(lock_core_t *core, uint lock_num);
|
||||||
|
|
||||||
|
#ifndef lock_owner_id_t
|
||||||
|
/*! \brief type to use to store the 'owner' of a lock.
|
||||||
|
* \ingroup lock_core
|
||||||
|
* By default this is int8_t as it only needs to store the core number or -1, however it may be
|
||||||
|
* overridden if a larger type is required (e.g. for an RTOS task id)
|
||||||
|
*/
|
||||||
|
#define lock_owner_id_t int8_t
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef LOCK_INVALID_OWNER_ID
|
||||||
|
/*! \brief marker value to use for a lock_owner_id_t which does not refer to any valid owner
|
||||||
|
* \ingroup lock_core
|
||||||
|
*/
|
||||||
|
#define LOCK_INVALID_OWNER_ID ((lock_owner_id_t)-1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef lock_get_caller_owner_id
|
||||||
|
/*! \brief return the owner id for the caller
|
||||||
|
* \ingroup lock_core
|
||||||
|
* By default this returns the calling core number, but may be overridden (e.g. to return an RTOS task id)
|
||||||
|
*/
|
||||||
|
#define lock_get_caller_owner_id() ((lock_owner_id_t)get_core_num())
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef lock_internal_spin_unlock_with_wait
|
||||||
|
/*! \brief Atomically unlock the lock's spin lock, and wait for a notification.
|
||||||
|
* \ingroup lock_core
|
||||||
|
*
|
||||||
|
* _Atomic_ here refers to the fact that it should not be possible for a concurrent lock_internal_spin_unlock_with_notify
|
||||||
|
* to insert itself between the spin unlock and this wait in a way that the wait does not see the notification (i.e. causing
|
||||||
|
* a missed notification). In other words this method should always wake up in response to a lock_internal_spin_unlock_with_notify
|
||||||
|
* for the same lock, which completes after this call starts.
|
||||||
|
*
|
||||||
|
* In an ideal implementation, this method would return exactly after the corresponding lock_internal_spin_unlock_with_notify
|
||||||
|
* has subsequently been called on the same lock instance, however this method is free to return at _any_ point before that;
|
||||||
|
* this macro is _always_ used in a loop which locks the spin lock, checks the internal locking primitive state and then
|
||||||
|
* waits again if the calling thread should not proceed.
|
||||||
|
*
|
||||||
|
* By default this macro simply unlocks the spin lock, and then performs a WFE, but may be overridden
|
||||||
|
* (e.g. to actually block the RTOS task).
|
||||||
|
*
|
||||||
|
* \param lock the lock_core for the primitive which needs to block
|
||||||
|
* \param save the uint32_t value that should be passed to spin_unlock when the spin lock is unlocked. (i.e. the `PRIMASK`
|
||||||
|
* state when the spin lock was acquire
|
||||||
|
*/
|
||||||
|
#define lock_internal_spin_unlock_with_wait(lock, save) spin_unlock((lock)->spin_lock, save), __wfe()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef lock_internal_spin_unlock_with_notify
|
||||||
|
/*! \brief Atomically unlock the lock's spin lock, and send a notification
|
||||||
|
* \ingroup lock_core
|
||||||
|
*
|
||||||
|
* _Atomic_ here refers to the fact that it should not be possible for this notification to happen during a
|
||||||
|
* lock_internal_spin_unlock_with_wait in a way that that wait does not see the notification (i.e. causing
|
||||||
|
* a missed notification). In other words this method should always wake up any lock_internal_spin_unlock_with_wait
|
||||||
|
* which started before this call completes.
|
||||||
|
*
|
||||||
|
* In an ideal implementation, this method would wake up only the corresponding lock_internal_spin_unlock_with_wait
|
||||||
|
* that has been called on the same lock instance, however it is free to wake up any of them, as they will check
|
||||||
|
* their condition and then re-wait if necessary/
|
||||||
|
*
|
||||||
|
* By default this macro simply unlocks the spin lock, and then performs a SEV, but may be overridden
|
||||||
|
* (e.g. to actually un-block RTOS task(s)).
|
||||||
|
*
|
||||||
|
* \param lock the lock_core for the primitive which needs to block
|
||||||
|
* \param save the uint32_t value that should be passed to spin_unlock when the spin lock is unlocked. (i.e. the PRIMASK
|
||||||
|
* state when the spin lock was acquire)
|
||||||
|
*/
|
||||||
|
#define lock_internal_spin_unlock_with_notify(lock, save) spin_unlock((lock)->spin_lock, save), __sev()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef lock_internal_spin_unlock_with_best_effort_wait_or_timeout
|
||||||
|
/*! \brief Atomically unlock the lock's spin lock, and wait for a notification or a timeout
|
||||||
|
* \ingroup lock_core
|
||||||
|
*
|
||||||
|
* _Atomic_ here refers to the fact that it should not be possible for a concurrent lock_internal_spin_unlock_with_notify
|
||||||
|
* to insert itself between the spin unlock and this wait in a way that the wait does not see the notification (i.e. causing
|
||||||
|
* a missed notification). In other words this method should always wake up in response to a lock_internal_spin_unlock_with_notify
|
||||||
|
* for the same lock, which completes after this call starts.
|
||||||
|
*
|
||||||
|
* In an ideal implementation, this method would return exactly after the corresponding lock_internal_spin_unlock_with_notify
|
||||||
|
* has subsequently been called on the same lock instance or the timeout has been reached, however this method is free to return
|
||||||
|
* at _any_ point before that; this macro is _always_ used in a loop which locks the spin lock, checks the internal locking
|
||||||
|
* primitive state and then waits again if the calling thread should not proceed.
|
||||||
|
*
|
||||||
|
* By default this simply unlocks the spin lock, and then calls \ref best_effort_wfe_or_timeout
|
||||||
|
* but may be overridden (e.g. to actually block the RTOS task with a timeout).
|
||||||
|
*
|
||||||
|
* \param lock the lock_core for the primitive which needs to block
|
||||||
|
* \param save the uint32_t value that should be passed to spin_unlock when the spin lock is unlocked. (i.e. the PRIMASK
|
||||||
|
* state when the spin lock was acquire)
|
||||||
|
* \param until the \ref absolute_time_t value
|
||||||
|
* \return true if the timeout has been reached
|
||||||
|
*/
|
||||||
|
#define lock_internal_spin_unlock_with_best_effort_wait_or_timeout(lock, save, until) ({ \
|
||||||
|
spin_unlock((lock)->spin_lock, save); \
|
||||||
|
best_effort_wfe_or_timeout(until); \
|
||||||
|
})
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef sync_internal_yield_until_before
|
||||||
|
/*! \brief yield to other processing until some time before the requested time
|
||||||
|
* \ingroup lock_core
|
||||||
|
*
|
||||||
|
* This method is provided for cases where the caller has no useful work to do
|
||||||
|
* until the specified time.
|
||||||
|
*
|
||||||
|
* By default this method does nothing, however it can be overridden (for example by an
|
||||||
|
* RTOS which is able to block the current task until the scheduler tick before
|
||||||
|
* the given time)
|
||||||
|
*
|
||||||
|
* \param until the \ref absolute_time_t value
|
||||||
|
*/
|
||||||
|
#define sync_internal_yield_until_before(until) ((void)0)
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -28,12 +28,17 @@ extern "C" {
|
|||||||
*
|
*
|
||||||
* See \ref critical_section.h for protecting access between multiple cores AND IRQ handlers
|
* See \ref critical_section.h for protecting access between multiple cores AND IRQ handlers
|
||||||
*/
|
*/
|
||||||
|
|
||||||
typedef struct __packed_aligned mutex {
|
typedef struct __packed_aligned mutex {
|
||||||
lock_core_t core;
|
lock_core_t core;
|
||||||
int8_t owner; //! core number or -1 for unowned
|
lock_owner_id_t owner; //! owner id LOCK_INVALID_OWNER_ID for unowned
|
||||||
|
uint8_t recursion_state; //! 0 means non recursive (owner or unowned)
|
||||||
|
//! 1 is a maxed out recursive lock
|
||||||
|
//! 2-254 is an owned lock
|
||||||
|
//! 255 is an un-owned lock
|
||||||
} mutex_t;
|
} mutex_t;
|
||||||
|
|
||||||
|
#define MAX_RECURSION_STATE ((uint8_t)255)
|
||||||
|
|
||||||
/*! \brief Initialise a mutex structure
|
/*! \brief Initialise a mutex structure
|
||||||
* \ingroup mutex
|
* \ingroup mutex
|
||||||
*
|
*
|
||||||
@ -41,6 +46,15 @@ typedef struct __packed_aligned mutex {
|
|||||||
*/
|
*/
|
||||||
void mutex_init(mutex_t *mtx);
|
void mutex_init(mutex_t *mtx);
|
||||||
|
|
||||||
|
/*! \brief Initialise a recursive mutex structure
|
||||||
|
* \ingroup mutex
|
||||||
|
*
|
||||||
|
* A recursive mutex may be entered in a nested fashion by the same owner
|
||||||
|
*
|
||||||
|
* \param mtx Pointer to mutex structure
|
||||||
|
*/
|
||||||
|
void recursive_mutex_init(mutex_t *mtx);
|
||||||
|
|
||||||
/*! \brief Take ownership of a mutex
|
/*! \brief Take ownership of a mutex
|
||||||
* \ingroup mutex
|
* \ingroup mutex
|
||||||
*
|
*
|
||||||
@ -51,13 +65,15 @@ void mutex_init(mutex_t *mtx);
|
|||||||
*/
|
*/
|
||||||
void mutex_enter_blocking(mutex_t *mtx);
|
void mutex_enter_blocking(mutex_t *mtx);
|
||||||
|
|
||||||
/*! \brief Check to see if a mutex is available
|
/*! \brief Attempt to take ownership of a mutex
|
||||||
* \ingroup mutex
|
* \ingroup mutex
|
||||||
*
|
*
|
||||||
* Will return true if the mutex is unowned, false otherwise
|
* If the mutex wasn't owned, this will claim the mutex and return true.
|
||||||
|
* Otherwise (if the mutex was already owned) this will return false and the
|
||||||
|
* calling core will *NOT* own the mutex.
|
||||||
*
|
*
|
||||||
* \param mtx Pointer to mutex structure
|
* \param mtx Pointer to mutex structure
|
||||||
* \param owner_out If mutex is owned, and this pointer is non-zero, it will be filled in with the core number of the current owner of the mutex
|
* \param owner_out If mutex was already owned, and this pointer is non-zero, it will be filled in with the core number of the current owner of the mutex
|
||||||
*/
|
*/
|
||||||
bool mutex_try_enter(mutex_t *mtx, uint32_t *owner_out);
|
bool mutex_try_enter(mutex_t *mtx, uint32_t *owner_out);
|
||||||
|
|
||||||
@ -75,6 +91,20 @@ bool mutex_try_enter(mutex_t *mtx, uint32_t *owner_out);
|
|||||||
*/
|
*/
|
||||||
bool mutex_enter_timeout_ms(mutex_t *mtx, uint32_t timeout_ms);
|
bool mutex_enter_timeout_ms(mutex_t *mtx, uint32_t timeout_ms);
|
||||||
|
|
||||||
|
/*! \brief Wait for mutex with timeout
|
||||||
|
* \ingroup mutex
|
||||||
|
*
|
||||||
|
* Wait for up to the specific time to take ownership of the mutex. If the calling
|
||||||
|
* core can take ownership of the mutex before the timeout expires, then true will be returned
|
||||||
|
* and the calling core will own the mutex, otherwise false will be returned and the calling
|
||||||
|
* core will *NOT* own the mutex.
|
||||||
|
*
|
||||||
|
* \param mtx Pointer to mutex structure
|
||||||
|
* \param timeout_us The timeout in microseconds.
|
||||||
|
* \return true if mutex now owned, false if timeout occurred before mutex became available
|
||||||
|
*/
|
||||||
|
bool mutex_enter_timeout_us(mutex_t *mtx, uint32_t timeout_us);
|
||||||
|
|
||||||
/*! \brief Wait for mutex until a specific time
|
/*! \brief Wait for mutex until a specific time
|
||||||
* \ingroup mutex
|
* \ingroup mutex
|
||||||
*
|
*
|
||||||
@ -84,7 +114,7 @@ bool mutex_enter_timeout_ms(mutex_t *mtx, uint32_t timeout_ms);
|
|||||||
* core will *NOT* own the mutex.
|
* core will *NOT* own the mutex.
|
||||||
*
|
*
|
||||||
* \param mtx Pointer to mutex structure
|
* \param mtx Pointer to mutex structure
|
||||||
* \param until The time after which to return if the core cannot take owner ship of the mutex
|
* \param until The time after which to return if the core cannot take ownership of the mutex
|
||||||
* \return true if mutex now owned, false if timeout occurred before mutex became available
|
* \return true if mutex now owned, false if timeout occurred before mutex became available
|
||||||
*/
|
*/
|
||||||
bool mutex_enter_block_until(mutex_t *mtx, absolute_time_t until);
|
bool mutex_enter_block_until(mutex_t *mtx, absolute_time_t until);
|
||||||
@ -129,6 +159,29 @@ static inline bool mutex_is_initialzed(mutex_t *mtx) {
|
|||||||
*/
|
*/
|
||||||
#define auto_init_mutex(name) static __attribute__((section(".mutex_array"))) mutex_t name
|
#define auto_init_mutex(name) static __attribute__((section(".mutex_array"))) mutex_t name
|
||||||
|
|
||||||
|
/*! \brief Helper macro for static definition of recursive mutexes
|
||||||
|
* \ingroup mutex
|
||||||
|
*
|
||||||
|
* A recursive mutex defined as follows:
|
||||||
|
*
|
||||||
|
* ```c
|
||||||
|
* auto_init_recursive_mutex(my_mutex);
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* Is equivalent to doing
|
||||||
|
*
|
||||||
|
* ```c
|
||||||
|
* static mutex_t my_mutex;
|
||||||
|
*
|
||||||
|
* void my_init_function() {
|
||||||
|
* recursive_mutex_init(&my_mutex);
|
||||||
|
* }
|
||||||
|
* ```
|
||||||
|
*
|
||||||
|
* But the initialization of the mutex is performed automatically during runtime initialization
|
||||||
|
*/
|
||||||
|
#define auto_init_recursive_mutex(name) static __attribute__((section(".mutex_array"))) mutex_t name = { .recursion_state = MAX_RECURSION_STATE }
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -90,11 +90,38 @@ void sem_acquire_blocking(semaphore_t *sem);
|
|||||||
* return false, otherwise it will return true.
|
* return false, otherwise it will return true.
|
||||||
*
|
*
|
||||||
* \param sem Pointer to semaphore structure
|
* \param sem Pointer to semaphore structure
|
||||||
* \param timeout_ms Time to wait to acquire the semaphore, in ms.
|
* \param timeout_ms Time to wait to acquire the semaphore, in milliseconds.
|
||||||
* \return false if timeout reached, true if permit was acquired.
|
* \return false if timeout reached, true if permit was acquired.
|
||||||
*/
|
*/
|
||||||
bool sem_acquire_timeout_ms(semaphore_t *sem, uint32_t timeout_ms);
|
bool sem_acquire_timeout_ms(semaphore_t *sem, uint32_t timeout_ms);
|
||||||
|
|
||||||
|
/*! \brief Acquire a permit from a semaphore, with timeout
|
||||||
|
* \ingroup sem
|
||||||
|
*
|
||||||
|
* This function will block and wait if no permits are available, until the
|
||||||
|
* defined timeout has been reached. If the timeout is reached the function will
|
||||||
|
* return false, otherwise it will return true.
|
||||||
|
*
|
||||||
|
* \param sem Pointer to semaphore structure
|
||||||
|
* \param timeout_us Time to wait to acquire the semaphore, in microseconds.
|
||||||
|
* \return false if timeout reached, true if permit was acquired.
|
||||||
|
*/
|
||||||
|
bool sem_acquire_timeout_us(semaphore_t *sem, uint32_t timeout_us);
|
||||||
|
|
||||||
|
/*! \brief Wait to acquire a permit from a semaphore until a specific time
|
||||||
|
* \ingroup sem
|
||||||
|
*
|
||||||
|
* This function will block and wait if no permits are available, until the
|
||||||
|
* specified timeout time. If the timeout is reached the function will
|
||||||
|
* return false, otherwise it will return true.
|
||||||
|
*
|
||||||
|
* \param sem Pointer to semaphore structure
|
||||||
|
* \param until The time after which to return if the sem is not available.
|
||||||
|
* \return true if permit was acquired, false if the until time was reached before
|
||||||
|
* acquiring.
|
||||||
|
*/
|
||||||
|
bool sem_acquire_block_until(semaphore_t *sem, absolute_time_t until);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -7,37 +7,53 @@
|
|||||||
#include "pico/mutex.h"
|
#include "pico/mutex.h"
|
||||||
#include "pico/time.h"
|
#include "pico/time.h"
|
||||||
|
|
||||||
#if !PICO_NO_HARDWARE
|
static void mutex_init_internal(mutex_t *mtx, uint8_t recursion_state) {
|
||||||
static_assert(sizeof(mutex_t) == 8, "");
|
lock_init(&mtx->core, next_striped_spin_lock_num());
|
||||||
#endif
|
mtx->owner = LOCK_INVALID_OWNER_ID;
|
||||||
|
mtx->recursion_state = recursion_state;
|
||||||
|
__mem_fence_release();
|
||||||
|
}
|
||||||
|
|
||||||
void mutex_init(mutex_t *mtx) {
|
void mutex_init(mutex_t *mtx) {
|
||||||
lock_init(&mtx->core, next_striped_spin_lock_num());
|
mutex_init_internal(mtx, 0);
|
||||||
mtx->owner = -1;
|
}
|
||||||
__mem_fence_release();
|
|
||||||
|
void recursive_mutex_init(mutex_t *mtx) {
|
||||||
|
mutex_init_internal(mtx, MAX_RECURSION_STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __time_critical_func(mutex_enter_blocking)(mutex_t *mtx) {
|
void __time_critical_func(mutex_enter_blocking)(mutex_t *mtx) {
|
||||||
assert(mtx->core.spin_lock);
|
assert(mtx->core.spin_lock);
|
||||||
bool block = true;
|
|
||||||
do {
|
do {
|
||||||
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
|
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
|
||||||
if (mtx->owner < 0) {
|
lock_owner_id_t caller = lock_get_caller_owner_id();
|
||||||
mtx->owner = (int8_t)get_core_num();
|
if (mtx->owner == LOCK_INVALID_OWNER_ID) {
|
||||||
block = false;
|
mtx->owner = caller;
|
||||||
|
if (mtx->recursion_state) {
|
||||||
|
assert(mtx->recursion_state == MAX_RECURSION_STATE);
|
||||||
|
mtx->recursion_state--;
|
||||||
|
}
|
||||||
|
} else if (mtx->owner == caller && mtx->recursion_state > 1) {
|
||||||
|
mtx->recursion_state--;
|
||||||
|
} else {
|
||||||
|
lock_internal_spin_unlock_with_wait(&mtx->core, save);
|
||||||
|
// spin lock already unlocked, so loop again
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
spin_unlock(mtx->core.spin_lock, save);
|
spin_unlock(mtx->core.spin_lock, save);
|
||||||
if (block) {
|
break;
|
||||||
__wfe();
|
} while (true);
|
||||||
}
|
|
||||||
} while (block);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool __time_critical_func(mutex_try_enter)(mutex_t *mtx, uint32_t *owner_out) {
|
bool __time_critical_func(mutex_try_enter)(mutex_t *mtx, uint32_t *owner_out) {
|
||||||
bool entered;
|
bool entered;
|
||||||
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
|
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
|
||||||
if (mtx->owner < 0) {
|
lock_owner_id_t caller = lock_get_caller_owner_id();
|
||||||
mtx->owner = (int8_t)get_core_num();
|
if (mtx->owner == LOCK_INVALID_OWNER_ID) {
|
||||||
|
mtx->owner = lock_get_caller_owner_id();
|
||||||
|
entered = true;
|
||||||
|
} else if (mtx->owner == caller && mtx->recursion_state > 1) {
|
||||||
|
mtx->recursion_state--;
|
||||||
entered = true;
|
entered = true;
|
||||||
} else {
|
} else {
|
||||||
if (owner_out) *owner_out = (uint32_t) mtx->owner;
|
if (owner_out) *owner_out = (uint32_t) mtx->owner;
|
||||||
@ -51,29 +67,47 @@ bool __time_critical_func(mutex_enter_timeout_ms)(mutex_t *mtx, uint32_t timeout
|
|||||||
return mutex_enter_block_until(mtx, make_timeout_time_ms(timeout_ms));
|
return mutex_enter_block_until(mtx, make_timeout_time_ms(timeout_ms));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool __time_critical_func(mutex_enter_timeout_us)(mutex_t *mtx, uint32_t timeout_us) {
|
||||||
|
return mutex_enter_block_until(mtx, make_timeout_time_us(timeout_us));
|
||||||
|
}
|
||||||
|
|
||||||
bool __time_critical_func(mutex_enter_block_until)(mutex_t *mtx, absolute_time_t until) {
|
bool __time_critical_func(mutex_enter_block_until)(mutex_t *mtx, absolute_time_t until) {
|
||||||
assert(mtx->core.spin_lock);
|
assert(mtx->core.spin_lock);
|
||||||
bool block = true;
|
|
||||||
do {
|
do {
|
||||||
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
|
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
|
||||||
if (mtx->owner < 0) {
|
lock_owner_id_t caller = lock_get_caller_owner_id();
|
||||||
mtx->owner = (int8_t)get_core_num();
|
if (mtx->owner == LOCK_INVALID_OWNER_ID) {
|
||||||
block = false;
|
mtx->owner = caller;
|
||||||
}
|
} else if (mtx->owner == caller && mtx->recursion_state > 1) {
|
||||||
spin_unlock(mtx->core.spin_lock, save);
|
mtx->recursion_state--;
|
||||||
if (block) {
|
} else {
|
||||||
if (best_effort_wfe_or_timeout(until)) {
|
if (lock_internal_spin_unlock_with_best_effort_wait_or_timeout(&mtx->core, save, until)) {
|
||||||
|
// timed out
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
// not timed out; spin lock already unlocked, so loop again
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} while (block);
|
spin_unlock(mtx->core.spin_lock, save);
|
||||||
return true;
|
return true;
|
||||||
|
} while (true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void __time_critical_func(mutex_exit)(mutex_t *mtx) {
|
void __time_critical_func(mutex_exit)(mutex_t *mtx) {
|
||||||
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
|
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
|
||||||
assert(mtx->owner >= 0);
|
assert(mtx->owner != LOCK_INVALID_OWNER_ID);
|
||||||
mtx->owner = -1;
|
if (!mtx->recursion_state) {
|
||||||
__sev();
|
mtx->owner = LOCK_INVALID_OWNER_ID;
|
||||||
spin_unlock(mtx->core.spin_lock, save);
|
lock_internal_spin_unlock_with_notify(&mtx->core, save);
|
||||||
}
|
} else {
|
||||||
|
mtx->recursion_state++;
|
||||||
|
assert(mtx->recursion_state);
|
||||||
|
if (mtx->recursion_state == MAX_RECURSION_STATE) {
|
||||||
|
mtx->owner = LOCK_INVALID_OWNER_ID;
|
||||||
|
lock_internal_spin_unlock_with_notify(&mtx->core, save);
|
||||||
|
} else {
|
||||||
|
spin_unlock(mtx->core.spin_lock, save);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -19,64 +19,61 @@ int __time_critical_func(sem_available)(semaphore_t *sem) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void __time_critical_func(sem_acquire_blocking)(semaphore_t *sem) {
|
void __time_critical_func(sem_acquire_blocking)(semaphore_t *sem) {
|
||||||
bool block = true;
|
|
||||||
do {
|
do {
|
||||||
uint32_t save = spin_lock_blocking(sem->core.spin_lock);
|
uint32_t save = spin_lock_blocking(sem->core.spin_lock);
|
||||||
if (sem->permits > 0) {
|
if (sem->permits > 0) {
|
||||||
sem->permits--;
|
sem->permits--;
|
||||||
__sev();
|
lock_internal_spin_unlock_with_notify(&sem->core, save);
|
||||||
block = false;
|
break;
|
||||||
}
|
}
|
||||||
spin_unlock(sem->core.spin_lock, save);
|
lock_internal_spin_unlock_with_wait(&sem->core, save);
|
||||||
if (block) {
|
} while (true);
|
||||||
__wfe();
|
|
||||||
}
|
|
||||||
} while (block);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool __time_critical_func(sem_acquire_timeout_ms)(semaphore_t *sem, uint32_t timeout_ms) {
|
bool __time_critical_func(sem_acquire_timeout_ms)(semaphore_t *sem, uint32_t timeout_ms) {
|
||||||
bool block = true;
|
return sem_acquire_block_until(sem, make_timeout_time_ms(timeout_ms));
|
||||||
absolute_time_t target = nil_time;
|
}
|
||||||
|
|
||||||
|
bool __time_critical_func(sem_acquire_timeout_us)(semaphore_t *sem, uint32_t timeout_us) {
|
||||||
|
return sem_acquire_block_until(sem, make_timeout_time_us(timeout_us));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool __time_critical_func(sem_acquire_block_until)(semaphore_t *sem, absolute_time_t until) {
|
||||||
do {
|
do {
|
||||||
uint32_t save = spin_lock_blocking(sem->core.spin_lock);
|
uint32_t save = spin_lock_blocking(sem->core.spin_lock);
|
||||||
if (sem->permits > 0) {
|
if (sem->permits > 0) {
|
||||||
sem->permits--;
|
sem->permits--;
|
||||||
__sev();
|
lock_internal_spin_unlock_with_notify(&sem->core, save);
|
||||||
block = false;
|
return true;
|
||||||
}
|
}
|
||||||
spin_unlock(sem->core.spin_lock, save);
|
if (lock_internal_spin_unlock_with_best_effort_wait_or_timeout(&sem->core, save, until)) {
|
||||||
if (block) {
|
return false;
|
||||||
if (is_nil_time(target)) {
|
|
||||||
target = make_timeout_time_ms(timeout_ms);
|
|
||||||
}
|
|
||||||
if (best_effort_wfe_or_timeout(target)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} while (block);
|
} while (true);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo this should really have a blocking variant for when permits are maxed out
|
// todo this should really have a blocking variant for when permits are maxed out
|
||||||
bool __time_critical_func(sem_release)(semaphore_t *sem) {
|
bool __time_critical_func(sem_release)(semaphore_t *sem) {
|
||||||
bool rc;
|
|
||||||
uint32_t save = spin_lock_blocking(sem->core.spin_lock);
|
uint32_t save = spin_lock_blocking(sem->core.spin_lock);
|
||||||
int32_t count = sem->permits;
|
int32_t count = sem->permits;
|
||||||
if (count < sem->max_permits) {
|
if (count < sem->max_permits) {
|
||||||
sem->permits = (int16_t)(count + 1);
|
sem->permits = (int16_t)(count + 1);
|
||||||
__sev();
|
lock_internal_spin_unlock_with_notify(&sem->core, save);
|
||||||
rc = true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
rc = false;
|
spin_unlock(sem->core.spin_lock, save);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
spin_unlock(sem->core.spin_lock, save);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __time_critical_func(sem_reset)(semaphore_t *sem, int16_t permits) {
|
void __time_critical_func(sem_reset)(semaphore_t *sem, int16_t permits) {
|
||||||
assert(permits >= 0 && permits <= sem->max_permits);
|
assert(permits >= 0 && permits <= sem->max_permits);
|
||||||
uint32_t save = spin_lock_blocking(sem->core.spin_lock);
|
uint32_t save = spin_lock_blocking(sem->core.spin_lock);
|
||||||
if (permits > sem->permits) __sev();
|
if (permits > sem->permits) {
|
||||||
sem->permits = permits;
|
sem->permits = permits;
|
||||||
spin_unlock(sem->core.spin_lock, save);
|
lock_internal_spin_unlock_with_notify(&sem->core, save);
|
||||||
|
} else {
|
||||||
|
sem->permits = permits;
|
||||||
|
spin_unlock(sem->core.spin_lock, save);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ if (NOT TARGET pico_time_headers)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT TARGET pico_time)
|
if (NOT TARGET pico_time)
|
||||||
add_library(pico_time INTERFACE)
|
pico_add_impl_library(pico_time)
|
||||||
|
|
||||||
target_sources(pico_time INTERFACE
|
target_sources(pico_time INTERFACE
|
||||||
${CMAKE_CURRENT_LIST_DIR}/time.c
|
${CMAKE_CURRENT_LIST_DIR}/time.c
|
||||||
|
@ -5,12 +5,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include "pico.h"
|
#include "pico.h"
|
||||||
#include "pico/time.h"
|
#include "pico/time.h"
|
||||||
#include "pico/util/pheap.h"
|
#include "pico/util/pheap.h"
|
||||||
#include "hardware/sync.h"
|
#include "pico/sync.h"
|
||||||
|
|
||||||
const absolute_time_t ABSOLUTE_TIME_INITIALIZED_VAR(nil_time, 0);
|
const absolute_time_t ABSOLUTE_TIME_INITIALIZED_VAR(nil_time, 0);
|
||||||
const absolute_time_t ABSOLUTE_TIME_INITIALIZED_VAR(at_the_end_of_time, INT64_MAX);
|
const absolute_time_t ABSOLUTE_TIME_INITIALIZED_VAR(at_the_end_of_time, INT64_MAX);
|
||||||
@ -37,6 +38,7 @@ typedef struct alarm_pool {
|
|||||||
PHEAP_DEFINE_STATIC(default_alarm_pool_heap, PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS);
|
PHEAP_DEFINE_STATIC(default_alarm_pool_heap, PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS);
|
||||||
static alarm_pool_entry_t default_alarm_pool_entries[PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS];
|
static alarm_pool_entry_t default_alarm_pool_entries[PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS];
|
||||||
static uint8_t default_alarm_pool_entry_ids_high[PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS];
|
static uint8_t default_alarm_pool_entry_ids_high[PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS];
|
||||||
|
static lock_core_t sleep_notifier;
|
||||||
|
|
||||||
static alarm_pool_t default_alarm_pool = {
|
static alarm_pool_t default_alarm_pool = {
|
||||||
.heap = &default_alarm_pool_heap,
|
.heap = &default_alarm_pool_heap,
|
||||||
@ -81,6 +83,7 @@ void alarm_pool_init_default() {
|
|||||||
alarm_pool_post_alloc_init(&default_alarm_pool,
|
alarm_pool_post_alloc_init(&default_alarm_pool,
|
||||||
PICO_TIME_DEFAULT_ALARM_POOL_HARDWARE_ALARM_NUM);
|
PICO_TIME_DEFAULT_ALARM_POOL_HARDWARE_ALARM_NUM);
|
||||||
}
|
}
|
||||||
|
lock_init(&sleep_notifier, PICO_SPINLOCK_ID_TIMER);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,11 +279,11 @@ static void alarm_pool_dump_key(pheap_node_id_t id, void *user_data) {
|
|||||||
#if PICO_ON_DEVICE
|
#if PICO_ON_DEVICE
|
||||||
printf("%lld (hi %02x)", to_us_since_boot(get_entry(pool, id)->target), *get_entry_id_high(pool, id));
|
printf("%lld (hi %02x)", to_us_since_boot(get_entry(pool, id)->target), *get_entry_id_high(pool, id));
|
||||||
#else
|
#else
|
||||||
printf("%ld", to_us_since_boot(get_entry(pool, id)->target));
|
printf(PRIu64, to_us_since_boot(get_entry(pool, id)->target));
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int64_t repeating_timer_callback(__unused alarm_id_t id, __unused void *user_data) {
|
static int64_t repeating_timer_callback(__unused alarm_id_t id, void *user_data) {
|
||||||
repeating_timer_t *rt = (repeating_timer_t *)user_data;
|
repeating_timer_t *rt = (repeating_timer_t *)user_data;
|
||||||
assert(rt->alarm_id == id);
|
assert(rt->alarm_id == id);
|
||||||
if (rt->callback(rt)) {
|
if (rt->callback(rt)) {
|
||||||
@ -318,8 +321,9 @@ void alarm_pool_dump(alarm_pool_t *pool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
|
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
|
||||||
static int64_t sev_callback(__unused alarm_id_t id, __unused void *user_data) {
|
static int64_t sleep_until_callback(__unused alarm_id_t id, __unused void *user_data) {
|
||||||
__sev();
|
uint32_t save = spin_lock_blocking(sleep_notifier.spin_lock);
|
||||||
|
lock_internal_spin_unlock_with_notify(&sleep_notifier, save);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -338,13 +342,17 @@ void sleep_until(absolute_time_t t) {
|
|||||||
absolute_time_t t_before;
|
absolute_time_t t_before;
|
||||||
update_us_since_boot(&t_before, t_before_us);
|
update_us_since_boot(&t_before, t_before_us);
|
||||||
if (absolute_time_diff_us(get_absolute_time(), t_before) > 0) {
|
if (absolute_time_diff_us(get_absolute_time(), t_before) > 0) {
|
||||||
if (add_alarm_at(t_before, sev_callback, NULL, false) >= 0) {
|
if (add_alarm_at(t_before, sleep_until_callback, NULL, false) >= 0) {
|
||||||
// able to add alarm for just before the time
|
// able to add alarm for just before the time
|
||||||
while (!time_reached(t_before)) {
|
while (!time_reached(t_before)) {
|
||||||
__wfe();
|
uint32_t save = spin_lock_blocking(sleep_notifier.spin_lock);
|
||||||
|
lock_internal_spin_unlock_with_wait(&sleep_notifier, save);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
// hook in case we're in RTOS; note we assume using the alarm pool is better always if available.
|
||||||
|
sync_internal_yield_until_before(t);
|
||||||
#endif
|
#endif
|
||||||
// now wait until the exact time
|
// now wait until the exact time
|
||||||
busy_wait_until(t);
|
busy_wait_until(t);
|
||||||
@ -354,13 +362,17 @@ void sleep_us(uint64_t us) {
|
|||||||
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
|
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
|
||||||
sleep_until(make_timeout_time_us(us));
|
sleep_until(make_timeout_time_us(us));
|
||||||
#else
|
#else
|
||||||
if (us >> 32u) {
|
if (us < PICO_TIME_SLEEP_OVERHEAD_ADJUST_US) {
|
||||||
busy_wait_until(make_timeout_time_us(us));
|
busy_wait_us(us);
|
||||||
} else {
|
} else {
|
||||||
busy_wait_us_32(us);
|
// hook in case we're in RTOS; note we assume using the alarm pool is better always if available.
|
||||||
|
absolute_time_t t = make_timeout_time_us(us - PICO_TIME_SLEEP_OVERHEAD_ADJUST_US);
|
||||||
|
sync_internal_yield_until_before(t);
|
||||||
|
|
||||||
|
// then wait the rest of thw way
|
||||||
|
busy_wait_until(t);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sleep_ms(uint32_t ms) {
|
void sleep_ms(uint32_t ms) {
|
||||||
@ -370,7 +382,7 @@ void sleep_ms(uint32_t ms) {
|
|||||||
bool best_effort_wfe_or_timeout(absolute_time_t timeout_timestamp) {
|
bool best_effort_wfe_or_timeout(absolute_time_t timeout_timestamp) {
|
||||||
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
|
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
|
||||||
alarm_id_t id;
|
alarm_id_t id;
|
||||||
id = add_alarm_at(timeout_timestamp, sev_callback, NULL, false);
|
id = add_alarm_at(timeout_timestamp, sleep_until_callback, NULL, false);
|
||||||
if (id <= 0) {
|
if (id <= 0) {
|
||||||
tight_loop_contents();
|
tight_loop_contents();
|
||||||
return time_reached(timeout_timestamp);
|
return time_reached(timeout_timestamp);
|
||||||
|
@ -5,7 +5,7 @@ if (NOT TARGET pico_util_headers)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT TARGET pico_util)
|
if (NOT TARGET pico_util)
|
||||||
add_library(pico_util INTERFACE)
|
pico_add_impl_library(pico_util)
|
||||||
target_sources(pico_util INTERFACE
|
target_sources(pico_util INTERFACE
|
||||||
${CMAKE_CURRENT_LIST_DIR}/datetime.c
|
${CMAKE_CURRENT_LIST_DIR}/datetime.c
|
||||||
${CMAKE_CURRENT_LIST_DIR}/pheap.c
|
${CMAKE_CURRENT_LIST_DIR}/pheap.c
|
||||||
|
@ -10,6 +10,11 @@
|
|||||||
#include "pico.h"
|
#include "pico.h"
|
||||||
#include "hardware/sync.h"
|
#include "hardware/sync.h"
|
||||||
|
|
||||||
|
// PICO_CONFIG: PICO_QUEUE_MAX_LEVEL, Maintain a field for the highest level that has been reached by a queue, type=bool, default=0, advanced=true, group=queue
|
||||||
|
#ifndef PICO_QUEUE_MAX_LEVEL
|
||||||
|
#define PICO_QUEUE_MAX_LEVEL 0
|
||||||
|
#endif
|
||||||
|
|
||||||
/** \file queue.h
|
/** \file queue.h
|
||||||
* \defgroup queue queue
|
* \defgroup queue queue
|
||||||
* Multi-core and IRQ safe queue implementation.
|
* Multi-core and IRQ safe queue implementation.
|
||||||
@ -22,13 +27,18 @@
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "pico/lock_core.h"
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
spin_lock_t *lock;
|
lock_core_t core;
|
||||||
uint8_t *data;
|
uint8_t *data;
|
||||||
uint16_t wptr;
|
uint16_t wptr;
|
||||||
uint16_t rptr;
|
uint16_t rptr;
|
||||||
uint16_t element_size;
|
uint16_t element_size;
|
||||||
uint16_t element_count;
|
uint16_t element_count;
|
||||||
|
#if PICO_QUEUE_MAX_LEVEL
|
||||||
|
uint16_t max_level;
|
||||||
|
#endif
|
||||||
} queue_t;
|
} queue_t;
|
||||||
|
|
||||||
/*! \brief Initialise a queue with a specific spinlock for concurrency protection
|
/*! \brief Initialise a queue with a specific spinlock for concurrency protection
|
||||||
@ -85,12 +95,38 @@ static inline uint queue_get_level_unsafe(queue_t *q) {
|
|||||||
* \return Number of entries in the queue
|
* \return Number of entries in the queue
|
||||||
*/
|
*/
|
||||||
static inline uint queue_get_level(queue_t *q) {
|
static inline uint queue_get_level(queue_t *q) {
|
||||||
uint32_t save = spin_lock_blocking(q->lock);
|
uint32_t save = spin_lock_blocking(q->core.spin_lock);
|
||||||
uint level = queue_get_level_unsafe(q);
|
uint level = queue_get_level_unsafe(q);
|
||||||
spin_unlock(q->lock, save);
|
spin_unlock(q->core.spin_lock, save);
|
||||||
return level;
|
return level;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Returns the highest level reached by the specified queue since it was created
|
||||||
|
* or since the max level was reset
|
||||||
|
* \ingroup queue
|
||||||
|
*
|
||||||
|
* \param q Pointer to a queue_t structure, used as a handle
|
||||||
|
* \return Maximum level of the queue
|
||||||
|
*/
|
||||||
|
#if PICO_QUEUE_MAX_LEVEL
|
||||||
|
static inline uint queue_get_max_level(queue_t *q) {
|
||||||
|
return q->max_level;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! \brief Reset the highest level reached of the specified queue.
|
||||||
|
* \ingroup queue
|
||||||
|
*
|
||||||
|
* \param q Pointer to a queue_t structure, used as a handle
|
||||||
|
*/
|
||||||
|
#if PICO_QUEUE_MAX_LEVEL
|
||||||
|
static inline void queue_reset_max_level(queue_t *q) {
|
||||||
|
uint32_t save = spin_lock_blocking(q->core.spin_lock);
|
||||||
|
q->max_level = queue_get_level_unsafe(q);
|
||||||
|
spin_unlock(q->core.spin_lock, save);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/*! \brief Check if queue is empty
|
/*! \brief Check if queue is empty
|
||||||
* \ingroup queue
|
* \ingroup queue
|
||||||
*
|
*
|
||||||
@ -127,7 +163,7 @@ static inline bool queue_is_full(queue_t *q) {
|
|||||||
* If the queue is full this function will return immediately with false, otherwise
|
* If the queue is full this function will return immediately with false, otherwise
|
||||||
* the data is copied into a new value added to the queue, and this function will return true.
|
* the data is copied into a new value added to the queue, and this function will return true.
|
||||||
*/
|
*/
|
||||||
bool queue_try_add(queue_t *q, void *data);
|
bool queue_try_add(queue_t *q, const void *data);
|
||||||
|
|
||||||
/*! \brief Non-blocking removal of entry from the queue if non empty
|
/*! \brief Non-blocking removal of entry from the queue if non empty
|
||||||
* \ingroup queue
|
* \ingroup queue
|
||||||
@ -163,7 +199,7 @@ bool queue_try_peek(queue_t *q, void *data);
|
|||||||
*
|
*
|
||||||
* If the queue is full this function will block, until a removal happens on the queue
|
* If the queue is full this function will block, until a removal happens on the queue
|
||||||
*/
|
*/
|
||||||
void queue_add_blocking(queue_t *q, void *data);
|
void queue_add_blocking(queue_t *q, const void *data);
|
||||||
|
|
||||||
/*! \brief Blocking remove entry from queue
|
/*! \brief Blocking remove entry from queue
|
||||||
* \ingroup queue
|
* \ingroup queue
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include "pico/util/queue.h"
|
#include "pico/util/queue.h"
|
||||||
|
|
||||||
void queue_init_with_spinlock(queue_t *q, uint element_size, uint element_count, uint spinlock_num) {
|
void queue_init_with_spinlock(queue_t *q, uint element_size, uint element_count, uint spinlock_num) {
|
||||||
q->lock = spin_lock_instance(spinlock_num);
|
lock_init(&q->core, spinlock_num);
|
||||||
q->data = (uint8_t *)calloc(element_count + 1, element_size);
|
q->data = (uint8_t *)calloc(element_count + 1, element_size);
|
||||||
q->element_count = (uint16_t)element_count;
|
q->element_count = (uint16_t)element_count;
|
||||||
q->element_size = (uint16_t)element_size;
|
q->element_size = (uint16_t)element_size;
|
||||||
@ -30,69 +30,90 @@ static inline uint16_t inc_index(queue_t *q, uint16_t index) {
|
|||||||
if (++index > q->element_count) { // > because we have element_count + 1 elements
|
if (++index > q->element_count) { // > because we have element_count + 1 elements
|
||||||
index = 0;
|
index = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if PICO_QUEUE_MAX_LEVEL
|
||||||
|
uint16_t level = queue_get_level_unsafe(q);
|
||||||
|
if (level > q->max_level) {
|
||||||
|
q->max_level = level;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return index;
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool queue_try_add(queue_t *q, void *data) {
|
static bool queue_add_internal(queue_t *q, const void *data, bool block) {
|
||||||
bool success = false;
|
do {
|
||||||
uint32_t flags = spin_lock_blocking(q->lock);
|
uint32_t save = spin_lock_blocking(q->core.spin_lock);
|
||||||
if (queue_get_level_unsafe(q) != q->element_count) {
|
if (queue_get_level_unsafe(q) != q->element_count) {
|
||||||
memcpy(element_ptr(q, q->wptr), data, q->element_size);
|
memcpy(element_ptr(q, q->wptr), data, q->element_size);
|
||||||
q->wptr = inc_index(q, q->wptr);
|
q->wptr = inc_index(q, q->wptr);
|
||||||
success = true;
|
lock_internal_spin_unlock_with_notify(&q->core, save);
|
||||||
}
|
return true;
|
||||||
spin_unlock(q->lock, flags);
|
}
|
||||||
if (success) __sev();
|
if (block) {
|
||||||
return success;
|
lock_internal_spin_unlock_with_wait(&q->core, save);
|
||||||
|
} else {
|
||||||
|
spin_unlock(q->core.spin_lock, save);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool queue_remove_internal(queue_t *q, void *data, bool block) {
|
||||||
|
do {
|
||||||
|
uint32_t save = spin_lock_blocking(q->core.spin_lock);
|
||||||
|
if (queue_get_level_unsafe(q) != 0) {
|
||||||
|
memcpy(data, element_ptr(q, q->rptr), q->element_size);
|
||||||
|
q->rptr = inc_index(q, q->rptr);
|
||||||
|
lock_internal_spin_unlock_with_notify(&q->core, save);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (block) {
|
||||||
|
lock_internal_spin_unlock_with_wait(&q->core, save);
|
||||||
|
} else {
|
||||||
|
spin_unlock(q->core.spin_lock, save);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool queue_peek_internal(queue_t *q, void *data, bool block) {
|
||||||
|
do {
|
||||||
|
uint32_t save = spin_lock_blocking(q->core.spin_lock);
|
||||||
|
if (queue_get_level_unsafe(q) != 0) {
|
||||||
|
memcpy(data, element_ptr(q, q->rptr), q->element_size);
|
||||||
|
lock_internal_spin_unlock_with_notify(&q->core, save);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (block) {
|
||||||
|
lock_internal_spin_unlock_with_wait(&q->core, save);
|
||||||
|
} else {
|
||||||
|
spin_unlock(q->core.spin_lock, save);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool queue_try_add(queue_t *q, const void *data) {
|
||||||
|
return queue_add_internal(q, data, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool queue_try_remove(queue_t *q, void *data) {
|
bool queue_try_remove(queue_t *q, void *data) {
|
||||||
bool success = false;
|
return queue_remove_internal(q, data, false);
|
||||||
uint32_t flags = spin_lock_blocking(q->lock);
|
|
||||||
if (queue_get_level_unsafe(q) != 0) {
|
|
||||||
memcpy(data, element_ptr(q, q->rptr), q->element_size);
|
|
||||||
q->rptr = inc_index(q, q->rptr);
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
spin_unlock(q->lock, flags);
|
|
||||||
if (success) __sev();
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool queue_try_peek(queue_t *q, void *data) {
|
bool queue_try_peek(queue_t *q, void *data) {
|
||||||
bool success = false;
|
return queue_peek_internal(q, data, false);
|
||||||
uint32_t flags = spin_lock_blocking(q->lock);
|
|
||||||
if (queue_get_level_unsafe(q) != 0) {
|
|
||||||
memcpy(data, element_ptr(q, q->rptr), q->element_size);
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
spin_unlock(q->lock, flags);
|
|
||||||
return success;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void queue_add_blocking(queue_t *q, void *data) {
|
void queue_add_blocking(queue_t *q, const void *data) {
|
||||||
bool done;
|
queue_add_internal(q, data, true);
|
||||||
do {
|
|
||||||
done = queue_try_add(q, data);
|
|
||||||
if (done) break;
|
|
||||||
__wfe();
|
|
||||||
} while (true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void queue_remove_blocking(queue_t *q, void *data) {
|
void queue_remove_blocking(queue_t *q, void *data) {
|
||||||
bool done;
|
queue_remove_internal(q, data, true);
|
||||||
do {
|
|
||||||
done = queue_try_remove(q, data);
|
|
||||||
if (done) break;
|
|
||||||
__wfe();
|
|
||||||
} while (true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void queue_peek_blocking(queue_t *q, void *data) {
|
void queue_peek_blocking(queue_t *q, void *data) {
|
||||||
bool done;
|
queue_peek_internal(q, data, true);
|
||||||
do {
|
|
||||||
done = queue_try_peek(q, data);
|
|
||||||
if (done) break;
|
|
||||||
__wfe();
|
|
||||||
} while (true);
|
|
||||||
}
|
}
|
||||||
|
@ -32,4 +32,6 @@ endmacro()
|
|||||||
set(PICO_HOST_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "")
|
set(PICO_HOST_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "")
|
||||||
function(pico_define_boot_stage2 NAME)
|
function(pico_define_boot_stage2 NAME)
|
||||||
add_executable(${NAME} ${PICO_HOST_DIR}/boot_stage2.c)
|
add_executable(${NAME} ${PICO_HOST_DIR}/boot_stage2.c)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
|
pico_promote_common_scope_vars()
|
@ -78,7 +78,7 @@ static inline int32_t hw_divider_s32_remainder_wait() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t hw_divider_u32_quotient(uint32_t a, uint32_t b) {
|
static inline uint32_t hw_divider_u32_quotient(uint32_t a, uint32_t b) {
|
||||||
return b ? (a / b) : -1;
|
return b ? (a / b) : (uint32_t)(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t hw_divider_u32_remainder(uint32_t a, uint32_t b) {
|
static inline uint32_t hw_divider_u32_remainder(uint32_t a, uint32_t b) {
|
||||||
|
@ -27,6 +27,10 @@ void gpio_set_pulls(uint gpio, bool up, bool down) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gpio_set_irqover(uint gpio, uint value) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void gpio_set_outover(uint gpio, uint value) {
|
void gpio_set_outover(uint gpio, uint value) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -39,6 +43,31 @@ void gpio_set_oeover(uint gpio, uint value) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void gpio_set_input_hysteresis_enabled(uint gpio, bool enabled){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool gpio_is_input_hysteresis_enabled(uint gpio){
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_set_slew_rate(uint gpio, enum gpio_slew_rate slew){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum gpio_slew_rate gpio_get_slew_rate(uint gpio){
|
||||||
|
return GPIO_SLEW_RATE_FAST;
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpio_set_drive_strength(uint gpio, enum gpio_drive_strength drive){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum gpio_drive_strength gpio_get_drive_strength(uint gpio){
|
||||||
|
return GPIO_DRIVE_STRENGTH_4MA;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void gpio_set_irq_enabled(uint gpio, uint32_t events, bool enable) {
|
void gpio_set_irq_enabled(uint gpio, uint32_t events, bool enable) {
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -115,4 +144,4 @@ void gpio_set_input_enabled(uint gpio, bool enable) {
|
|||||||
|
|
||||||
void gpio_init_mask(uint gpio_mask) {
|
void gpio_init_mask(uint gpio_mask) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -27,6 +27,17 @@ enum gpio_function {
|
|||||||
GPIO_FUNC_NULL = 0xf,
|
GPIO_FUNC_NULL = 0xf,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum gpio_slew_rate {
|
||||||
|
GPIO_SLEW_RATE_SLOW = 0, ///< Slew rate limiting enabled
|
||||||
|
GPIO_SLEW_RATE_FAST = 1 ///< Slew rate limiting disabled
|
||||||
|
};
|
||||||
|
|
||||||
|
enum gpio_drive_strength {
|
||||||
|
GPIO_DRIVE_STRENGTH_2MA = 0, ///< 2 mA nominal drive strength
|
||||||
|
GPIO_DRIVE_STRENGTH_4MA = 1, ///< 4 mA nominal drive strength
|
||||||
|
GPIO_DRIVE_STRENGTH_8MA = 2, ///< 8 mA nominal drive strength
|
||||||
|
GPIO_DRIVE_STRENGTH_12MA = 3 ///< 12 mA nominal drive strength
|
||||||
|
};
|
||||||
|
|
||||||
#define GPIO_OUT 1
|
#define GPIO_OUT 1
|
||||||
#define GPIO_IN 0
|
#define GPIO_IN 0
|
||||||
@ -50,6 +61,8 @@ void gpio_disable_pulls(uint gpio);
|
|||||||
|
|
||||||
void gpio_set_pulls(uint gpio, bool up, bool down);
|
void gpio_set_pulls(uint gpio, bool up, bool down);
|
||||||
|
|
||||||
|
void gpio_set_irqover(uint gpio, uint value);
|
||||||
|
|
||||||
void gpio_set_outover(uint gpio, uint value);
|
void gpio_set_outover(uint gpio, uint value);
|
||||||
|
|
||||||
void gpio_set_inover(uint gpio, uint value);
|
void gpio_set_inover(uint gpio, uint value);
|
||||||
@ -58,6 +71,18 @@ void gpio_set_oeover(uint gpio, uint value);
|
|||||||
|
|
||||||
void gpio_set_input_enabled(uint gpio, bool enable);
|
void gpio_set_input_enabled(uint gpio, bool enable);
|
||||||
|
|
||||||
|
void gpio_set_input_hysteresis_enabled(uint gpio, bool enabled);
|
||||||
|
|
||||||
|
bool gpio_is_input_hysteresis_enabled(uint gpio);
|
||||||
|
|
||||||
|
void gpio_set_slew_rate(uint gpio, enum gpio_slew_rate slew);
|
||||||
|
|
||||||
|
enum gpio_slew_rate gpio_get_slew_rate(uint gpio);
|
||||||
|
|
||||||
|
void gpio_set_drive_strength(uint gpio, enum gpio_drive_strength drive);
|
||||||
|
|
||||||
|
enum gpio_drive_strength gpio_get_drive_strength(uint gpio);
|
||||||
|
|
||||||
// Configure a GPIO for direct input/output from software
|
// Configure a GPIO for direct input/output from software
|
||||||
void gpio_init(uint gpio);
|
void gpio_init(uint gpio);
|
||||||
|
|
||||||
|
@ -24,7 +24,7 @@ struct termios _tty;
|
|||||||
static tcflag_t _res_oflg = 0;
|
static tcflag_t _res_oflg = 0;
|
||||||
static tcflag_t _res_lflg = 0;
|
static tcflag_t _res_lflg = 0;
|
||||||
|
|
||||||
void _resetty(void) {
|
void _resettty(void) {
|
||||||
if (!isatty(STDIN_FILENO))
|
if (!isatty(STDIN_FILENO))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ void _inittty(void) {
|
|||||||
tcsetattr(STDIN_FILENO, TCSANOW, &_tty);
|
tcsetattr(STDIN_FILENO, TCSANOW, &_tty);
|
||||||
|
|
||||||
fcntl(STDIN_FILENO, F_SETFL, FNONBLOCK);
|
fcntl(STDIN_FILENO, F_SETFL, FNONBLOCK);
|
||||||
atexit(_resetty);
|
atexit(_resettty);
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
@ -88,10 +88,18 @@ size_t uart_is_readable(uart_inst_t *uart) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Write len bytes directly from src to the UART
|
// Write len bytes directly from src to the UART
|
||||||
//void uart_write_blocking(uart_inst_t uart, const uint8_t *src, size_t len);
|
void uart_write_blocking(uart_inst_t *uart, const uint8_t *src, size_t len) {
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
uart_putc(uart, src[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Read len bytes directly from the UART to dst
|
// Read len bytes directly from the UART to dst
|
||||||
//void uart_read_blocking(uart_inst_t uart, uint8_t *dst, size_t len);
|
void uart_read_blocking(uart_inst_t *uart, uint8_t *dst, size_t len) {
|
||||||
|
for (size_t i = 0; i < len; i++) {
|
||||||
|
dst[i] = uart_getc(uart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// UART-specific operations and aliases
|
// UART-specific operations and aliases
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
add_library(pico_bit_ops INTERFACE)
|
pico_add_impl_library(pico_bit_ops)
|
||||||
|
|
||||||
target_sources(pico_bit_ops INTERFACE
|
target_sources(pico_bit_ops INTERFACE
|
||||||
${CMAKE_CURRENT_LIST_DIR}/bit_ops.c)
|
${CMAKE_CURRENT_LIST_DIR}/bit_ops.c)
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
add_library(pico_divider INTERFACE)
|
pico_add_impl_library(pico_divider)
|
||||||
|
|
||||||
target_sources(pico_divider INTERFACE
|
target_sources(pico_divider INTERFACE
|
||||||
${CMAKE_CURRENT_LIST_DIR}/divider.c)
|
${CMAKE_CURRENT_LIST_DIR}/divider.c)
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
if (NOT TARGET pico_multicore)
|
if (NOT TARGET pico_multicore)
|
||||||
add_library(pico_multicore INTERFACE)
|
pico_add_impl_library(pico_multicore)
|
||||||
|
|
||||||
target_include_directories(pico_multicore INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
|
target_include_directories(pico_multicore INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
|
||||||
endif()
|
endif()
|
||||||
|
@ -20,11 +20,13 @@ void multicore_launch_core1_raw(void (*entry)(void), uint32_t *sp, uint32_t vect
|
|||||||
|
|
||||||
bool multicore_fifo_rvalid(void);
|
bool multicore_fifo_rvalid(void);
|
||||||
bool multicore_fifo_wready(void);
|
bool multicore_fifo_wready(void);
|
||||||
void multicore_fifo_push(uint32_t data);
|
void multicore_fifo_push_blocking(uint32_t data);
|
||||||
|
bool multicore_fifo_push_timeout_us(uint32_t data, uint64_t timeout_us);
|
||||||
uint32_t multicore_fifo_pop_blocking();
|
uint32_t multicore_fifo_pop_blocking();
|
||||||
|
bool multicore_fifo_pop_timeout_us(uint64_t timeout_us, uint32_t *out);
|
||||||
void multicore_fifo_drain(void);
|
void multicore_fifo_drain(void);
|
||||||
void multicore_fifo_clear_irq(void);
|
void multicore_fifo_clear_irq(void);
|
||||||
int32_t multicore_fifo_get_status(void);
|
uint32_t multicore_fifo_get_status(void);
|
||||||
|
|
||||||
// call this from the lockout victim thread
|
// call this from the lockout victim thread
|
||||||
void multicore_lockout_victim_init(void);
|
void multicore_lockout_victim_init(void);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
# This file may be included directly by a build to get common SDK macros and types
|
||||||
|
|
||||||
if (NOT TARGET pico_platform_headers)
|
if (NOT TARGET pico_platform_headers)
|
||||||
add_library(pico_platform_headers INTERFACE)
|
add_library(pico_platform_headers INTERFACE)
|
||||||
|
|
||||||
@ -11,7 +13,11 @@ if (NOT TARGET pico_platform_headers)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (NOT TARGET pico_platform)
|
if (NOT TARGET pico_platform)
|
||||||
add_library(pico_platform INTERFACE)
|
if (COMMAND pico_add_platform_library)
|
||||||
|
pico_add_platform_library(pico_platform)
|
||||||
|
else()
|
||||||
|
add_library(pico_platform INTERFACE)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_sources(pico_platform INTERFACE
|
target_sources(pico_platform INTERFACE
|
||||||
${CMAKE_CURRENT_LIST_DIR}/platform_base.c
|
${CMAKE_CURRENT_LIST_DIR}/platform_base.c
|
||||||
@ -22,4 +28,4 @@ endif()
|
|||||||
|
|
||||||
function(pico_add_platform_library TARGET)
|
function(pico_add_platform_library TARGET)
|
||||||
target_link_libraries(pico_platform INTERFACE ${TARGET})
|
target_link_libraries(pico_platform INTERFACE ${TARGET})
|
||||||
endfunction()
|
endfunction()
|
||||||
|
@ -36,6 +36,10 @@ extern "C" {
|
|||||||
//int running_on_fpga() { return false; }
|
//int running_on_fpga() { return false; }
|
||||||
extern void tight_loop_contents();
|
extern void tight_loop_contents();
|
||||||
|
|
||||||
|
#ifndef __STRING
|
||||||
|
#define __STRING(x) #x
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef _MSC_VER
|
#ifndef _MSC_VER
|
||||||
#ifndef __noreturn
|
#ifndef __noreturn
|
||||||
#define __noreturn __attribute((noreturn))
|
#define __noreturn __attribute((noreturn))
|
||||||
@ -77,10 +81,6 @@ extern void tight_loop_contents();
|
|||||||
#define __CONCAT(x,y) x ## y
|
#define __CONCAT(x,y) x ## y
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef __STRING
|
|
||||||
#define __STRING(x) #x
|
|
||||||
#endif()
|
|
||||||
|
|
||||||
#define __thread __declspec( thread )
|
#define __thread __declspec( thread )
|
||||||
|
|
||||||
#define PICO_WEAK_FUNCTION_DEF(x) __pragma(comment(linker, __STRING(/alternatename:_##x=_##x##__weak)));
|
#define PICO_WEAK_FUNCTION_DEF(x) __pragma(comment(linker, __STRING(/alternatename:_##x=_##x##__weak)));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
if (NOT TARGET pico_printf)
|
if (NOT TARGET pico_printf)
|
||||||
add_library(pico_printf INTERFACE)
|
pico_add_impl_library(pico_printf)
|
||||||
function(pico_set_printf_implementation)
|
function(pico_set_printf_implementation)
|
||||||
endfunction()
|
endfunction()
|
||||||
endif()
|
endif()
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
if (NOT TARGET pico_stdio)
|
if (NOT TARGET pico_stdio)
|
||||||
add_library(pico_stdio INTERFACE)
|
pico_add_impl_library(pico_stdio)
|
||||||
|
|
||||||
target_include_directories(pico_stdio INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
|
target_include_directories(pico_stdio INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
|
||||||
|
|
||||||
target_sources(pico_stdio INTERFACE
|
target_sources(pico_stdio INTERFACE
|
||||||
${CMAKE_CURRENT_LIST_DIR}/stdio.c
|
${CMAKE_CURRENT_LIST_DIR}/stdio.c
|
||||||
)
|
)
|
||||||
add_library(pico_stdio_usb INTERFACE)
|
pico_add_impl_library(pico_stdio_usb)
|
||||||
add_library(pico_stdio_uart INTERFACE)
|
pico_add_impl_library(pico_stdio_uart)
|
||||||
add_library(pico_stdio_semihosting INTERFACE)
|
pico_add_impl_library(pico_stdio_semihosting)
|
||||||
|
|
||||||
function(pico_enable_stdio_uart)
|
function(pico_enable_stdio_uart)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
if (NOT TARGET pico_stdlib)
|
if (NOT TARGET pico_stdlib)
|
||||||
add_library(pico_stdlib INTERFACE)
|
pico_add_impl_library(pico_stdlib)
|
||||||
|
|
||||||
target_sources(pico_stdlib INTERFACE
|
target_sources(pico_stdlib INTERFACE
|
||||||
${CMAKE_CURRENT_LIST_DIR}/stdlib.c
|
${CMAKE_CURRENT_LIST_DIR}/stdlib.c
|
||||||
|
@ -4,3 +4,5 @@ pico_add_subdirectory(hardware_structs)
|
|||||||
|
|
||||||
pico_add_doxygen(${CMAKE_CURRENT_LIST_DIR})
|
pico_add_doxygen(${CMAKE_CURRENT_LIST_DIR})
|
||||||
pico_add_doxygen_exclude(${CMAKE_CURRENT_LIST_DIR}/hardware_regs) # very very big
|
pico_add_doxygen_exclude(${CMAKE_CURRENT_LIST_DIR}/hardware_regs) # very very big
|
||||||
|
|
||||||
|
pico_promote_common_scope_vars()
|
@ -585,24 +585,9 @@
|
|||||||
// matching interrupt clear register. The unmasked raw versions of
|
// matching interrupt clear register. The unmasked raw versions of
|
||||||
// these bits are available in the IC_RAW_INTR_STAT register.
|
// these bits are available in the IC_RAW_INTR_STAT register.
|
||||||
#define I2C_IC_INTR_STAT_OFFSET _u(0x0000002c)
|
#define I2C_IC_INTR_STAT_OFFSET _u(0x0000002c)
|
||||||
#define I2C_IC_INTR_STAT_BITS _u(0x00003fff)
|
#define I2C_IC_INTR_STAT_BITS _u(0x00001fff)
|
||||||
#define I2C_IC_INTR_STAT_RESET _u(0x00000000)
|
#define I2C_IC_INTR_STAT_RESET _u(0x00000000)
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Field : I2C_IC_INTR_STAT_R_MASTER_ON_HOLD
|
|
||||||
// Description : See IC_RAW_INTR_STAT for a detailed description of
|
|
||||||
// R_MASTER_ON_HOLD bit.
|
|
||||||
//
|
|
||||||
// Reset value: 0x0
|
|
||||||
// 0x0 -> R_MASTER_ON_HOLD interrupt is inactive
|
|
||||||
// 0x1 -> R_MASTER_ON_HOLD interrupt is active
|
|
||||||
#define I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_RESET _u(0x0)
|
|
||||||
#define I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_BITS _u(0x00002000)
|
|
||||||
#define I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_MSB _u(13)
|
|
||||||
#define I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_LSB _u(13)
|
|
||||||
#define I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_ACCESS "RO"
|
|
||||||
#define I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_VALUE_INACTIVE _u(0x0)
|
|
||||||
#define I2C_IC_INTR_STAT_R_MASTER_ON_HOLD_VALUE_ACTIVE _u(0x1)
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
// Field : I2C_IC_INTR_STAT_R_RESTART_DET
|
// Field : I2C_IC_INTR_STAT_R_RESTART_DET
|
||||||
// Description : See IC_RAW_INTR_STAT for a detailed description of
|
// Description : See IC_RAW_INTR_STAT for a detailed description of
|
||||||
// R_RESTART_DET bit.
|
// R_RESTART_DET bit.
|
||||||
@ -805,24 +790,9 @@
|
|||||||
// register is active low; a value of 0 masks the interrupt,
|
// register is active low; a value of 0 masks the interrupt,
|
||||||
// whereas a value of 1 unmasks the interrupt.
|
// whereas a value of 1 unmasks the interrupt.
|
||||||
#define I2C_IC_INTR_MASK_OFFSET _u(0x00000030)
|
#define I2C_IC_INTR_MASK_OFFSET _u(0x00000030)
|
||||||
#define I2C_IC_INTR_MASK_BITS _u(0x00003fff)
|
#define I2C_IC_INTR_MASK_BITS _u(0x00001fff)
|
||||||
#define I2C_IC_INTR_MASK_RESET _u(0x000008ff)
|
#define I2C_IC_INTR_MASK_RESET _u(0x000008ff)
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Field : I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_READ_ONLY
|
|
||||||
// Description : This M_MASTER_ON_HOLD_read_only bit masks the R_MASTER_ON_HOLD
|
|
||||||
// interrupt in IC_INTR_STAT register.
|
|
||||||
//
|
|
||||||
// Reset value: 0x0
|
|
||||||
// 0x0 -> MASTER_ON_HOLD interrupt is masked
|
|
||||||
// 0x1 -> MASTER_ON_HOLD interrupt is unmasked
|
|
||||||
#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_READ_ONLY_RESET _u(0x0)
|
|
||||||
#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_READ_ONLY_BITS _u(0x00002000)
|
|
||||||
#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_READ_ONLY_MSB _u(13)
|
|
||||||
#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_READ_ONLY_LSB _u(13)
|
|
||||||
#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_READ_ONLY_ACCESS "RO"
|
|
||||||
#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_READ_ONLY_VALUE_ENABLED _u(0x0)
|
|
||||||
#define I2C_IC_INTR_MASK_M_MASTER_ON_HOLD_READ_ONLY_VALUE_DISABLED _u(0x1)
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
// Field : I2C_IC_INTR_MASK_M_RESTART_DET
|
// Field : I2C_IC_INTR_MASK_M_RESTART_DET
|
||||||
// Description : This bit masks the R_RESTART_DET interrupt in IC_INTR_STAT
|
// Description : This bit masks the R_RESTART_DET interrupt in IC_INTR_STAT
|
||||||
// register.
|
// register.
|
||||||
@ -1023,25 +993,9 @@
|
|||||||
// Unlike the IC_INTR_STAT register, these bits are not masked so
|
// Unlike the IC_INTR_STAT register, these bits are not masked so
|
||||||
// they always show the true status of the DW_apb_i2c.
|
// they always show the true status of the DW_apb_i2c.
|
||||||
#define I2C_IC_RAW_INTR_STAT_OFFSET _u(0x00000034)
|
#define I2C_IC_RAW_INTR_STAT_OFFSET _u(0x00000034)
|
||||||
#define I2C_IC_RAW_INTR_STAT_BITS _u(0x00003fff)
|
#define I2C_IC_RAW_INTR_STAT_BITS _u(0x00001fff)
|
||||||
#define I2C_IC_RAW_INTR_STAT_RESET _u(0x00000000)
|
#define I2C_IC_RAW_INTR_STAT_RESET _u(0x00000000)
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Field : I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD
|
|
||||||
// Description : Indicates whether master is holding the bus and TX FIFO is
|
|
||||||
// empty. Enabled only when I2C_DYNAMIC_TAR_UPDATE=1 and
|
|
||||||
// IC_EMPTYFIFO_HOLD_MASTER_EN=1.
|
|
||||||
//
|
|
||||||
// Reset value: 0x0
|
|
||||||
// 0x0 -> MASTER_ON_HOLD interrupt is inactive
|
|
||||||
// 0x1 -> MASTER_ON_HOLD interrupt is active
|
|
||||||
#define I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD_RESET _u(0x0)
|
|
||||||
#define I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD_BITS _u(0x00002000)
|
|
||||||
#define I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD_MSB _u(13)
|
|
||||||
#define I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD_LSB _u(13)
|
|
||||||
#define I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD_ACCESS "RO"
|
|
||||||
#define I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD_VALUE_INACTIVE _u(0x0)
|
|
||||||
#define I2C_IC_RAW_INTR_STAT_MASTER_ON_HOLD_VALUE_ACTIVE _u(0x1)
|
|
||||||
// -----------------------------------------------------------------------------
|
|
||||||
// Field : I2C_IC_RAW_INTR_STAT_RESTART_DET
|
// Field : I2C_IC_RAW_INTR_STAT_RESTART_DET
|
||||||
// Description : Indicates whether a RESTART condition has occurred on the I2C
|
// Description : Indicates whether a RESTART condition has occurred on the I2C
|
||||||
// interface when DW_apb_i2c is operating in Slave mode and the
|
// interface when DW_apb_i2c is operating in Slave mode and the
|
||||||
@ -1839,8 +1793,8 @@
|
|||||||
//
|
//
|
||||||
// The values in this register are in units of ic_clk period. The
|
// The values in this register are in units of ic_clk period. The
|
||||||
// value programmed in IC_SDA_TX_HOLD must be greater than the
|
// value programmed in IC_SDA_TX_HOLD must be greater than the
|
||||||
// minimum hold time in each mode one cycle in master mode, seven
|
// minimum hold time in each mode (one cycle in master mode, seven
|
||||||
// cycles in slave mode for the value to be implemented.
|
// cycles in slave mode) for the value to be implemented.
|
||||||
//
|
//
|
||||||
// The programmed SDA hold time during transmit (IC_SDA_TX_HOLD)
|
// The programmed SDA hold time during transmit (IC_SDA_TX_HOLD)
|
||||||
// cannot exceed at any time the duration of the low part of scl.
|
// cannot exceed at any time the duration of the low part of scl.
|
||||||
|
@ -190,7 +190,7 @@
|
|||||||
// set to 0xaa0 + div where
|
// set to 0xaa0 + div where
|
||||||
// div = 0 divides by 32
|
// div = 0 divides by 32
|
||||||
// div = 1-31 divides by div
|
// div = 1-31 divides by div
|
||||||
// any other value sets div=0 and therefore divides by 32
|
// any other value sets div=31
|
||||||
// this register resets to div=16
|
// this register resets to div=16
|
||||||
// 0xaa0 -> PASS
|
// 0xaa0 -> PASS
|
||||||
#define ROSC_DIV_OFFSET _u(0x00000010)
|
#define ROSC_DIV_OFFSET _u(0x00000010)
|
||||||
@ -208,7 +208,7 @@
|
|||||||
#define ROSC_PHASE_RESET _u(0x00000008)
|
#define ROSC_PHASE_RESET _u(0x00000008)
|
||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Field : ROSC_PHASE_PASSWD
|
// Field : ROSC_PHASE_PASSWD
|
||||||
// Description : set to 0xaa0
|
// Description : set to 0xaa
|
||||||
// any other value enables the output with shift=0
|
// any other value enables the output with shift=0
|
||||||
#define ROSC_PHASE_PASSWD_RESET _u(0x00)
|
#define ROSC_PHASE_PASSWD_RESET _u(0x00)
|
||||||
#define ROSC_PHASE_PASSWD_BITS _u(0x00000ff0)
|
#define ROSC_PHASE_PASSWD_BITS _u(0x00000ff0)
|
||||||
@ -260,7 +260,7 @@
|
|||||||
// -----------------------------------------------------------------------------
|
// -----------------------------------------------------------------------------
|
||||||
// Field : ROSC_STATUS_BADWRITE
|
// Field : ROSC_STATUS_BADWRITE
|
||||||
// Description : An invalid value has been written to CTRL_ENABLE or
|
// Description : An invalid value has been written to CTRL_ENABLE or
|
||||||
// CTRL_FREQ_RANGE or FRFEQA or FREQB or DORMANT
|
// CTRL_FREQ_RANGE or FREQA or FREQB or DIV or PHASE or DORMANT
|
||||||
#define ROSC_STATUS_BADWRITE_RESET _u(0x0)
|
#define ROSC_STATUS_BADWRITE_RESET _u(0x0)
|
||||||
#define ROSC_STATUS_BADWRITE_BITS _u(0x01000000)
|
#define ROSC_STATUS_BADWRITE_BITS _u(0x01000000)
|
||||||
#define ROSC_STATUS_BADWRITE_MSB _u(24)
|
#define ROSC_STATUS_BADWRITE_MSB _u(24)
|
||||||
|
6807
src/rp2040/hardware_regs/include/hardware/regs/usb_device_dpram.h
Normal file
6807
src/rp2040/hardware_regs/include/hardware/regs/usb_device_dpram.h
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -62,80 +62,73 @@ typedef struct {
|
|||||||
// references to these in I2C register header; these are *fixed* values,
|
// references to these in I2C register header; these are *fixed* values,
|
||||||
// set at hardware design time):
|
// set at hardware design time):
|
||||||
|
|
||||||
// SLAVE_INTERFACE_TYPE .............. 0
|
|
||||||
// REG_TIMEOUT_WIDTH ................. 4
|
|
||||||
// REG_TIMEOUT_VALUE ................. 8
|
|
||||||
// IC_ULTRA_FAST_MODE ................ 0x0
|
// IC_ULTRA_FAST_MODE ................ 0x0
|
||||||
// IC_UFM_TBUF_CNT_DEFAULT ........... 0x8
|
// IC_UFM_TBUF_CNT_DEFAULT ........... 0x8
|
||||||
|
// IC_UFM_SCL_LOW_COUNT .............. 0x0008
|
||||||
// IC_UFM_SCL_HIGH_COUNT ............. 0x0006
|
// IC_UFM_SCL_HIGH_COUNT ............. 0x0006
|
||||||
// IC_TX_TL .......................... 0x0
|
// IC_TX_TL .......................... 0x0
|
||||||
// IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0
|
// IC_TX_CMD_BLOCK ................... 0x1
|
||||||
// IC_SS_SCL_LOW_COUNT ............... 0x01d6
|
|
||||||
// IC_HAS_DMA ........................ 0x1
|
// IC_HAS_DMA ........................ 0x1
|
||||||
// IC_RX_FULL_GEN_NACK ............... 0x0
|
// IC_HAS_ASYNC_FIFO ................. 0x0
|
||||||
// IC_CLOCK_PERIOD ................... 100
|
|
||||||
// IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1
|
|
||||||
// IC_SMBUS_ARP ...................... 0x0
|
// IC_SMBUS_ARP ...................... 0x0
|
||||||
// IC_FIRST_DATA_BYTE_STATUS ......... 0x1
|
// IC_FIRST_DATA_BYTE_STATUS ......... 0x1
|
||||||
// IC_INTR_IO ........................ 0x1
|
// IC_INTR_IO ........................ 0x1
|
||||||
// IC_MASTER_MODE .................... 0x1
|
// IC_MASTER_MODE .................... 0x1
|
||||||
// IC_DEFAULT_ACK_GENERAL_CALL ....... 0x0
|
// IC_DEFAULT_ACK_GENERAL_CALL ....... 0x1
|
||||||
// IC_INTR_POL ....................... 0x1
|
// IC_INTR_POL ....................... 0x1
|
||||||
// IC_OPTIONAL_SAR ................... 0x0
|
// IC_OPTIONAL_SAR ................... 0x0
|
||||||
// IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055
|
// IC_DEFAULT_TAR_SLAVE_ADDR ......... 0x055
|
||||||
// IC_DEFAULT_SLAVE_ADDR ............. 0x055
|
// IC_DEFAULT_SLAVE_ADDR ............. 0x055
|
||||||
// IC_DEFAULT_HS_SPKLEN .............. 0x1
|
// IC_DEFAULT_HS_SPKLEN .............. 0x1
|
||||||
// IC_FS_SCL_HIGH_COUNT .............. 0x003c
|
// IC_FS_SCL_HIGH_COUNT .............. 0x0006
|
||||||
// IC_HS_SCL_LOW_COUNT ............... 0x0010
|
// IC_HS_SCL_LOW_COUNT ............... 0x0008
|
||||||
// IC_DEVICE_ID_VALUE ................ 0x0
|
// IC_DEVICE_ID_VALUE ................ 0x0
|
||||||
// IC_10BITADDR_MASTER ............... 0x0
|
// IC_10BITADDR_MASTER ............... 0x0
|
||||||
// IC_CLK_FREQ_OPTIMIZATION .......... 0x0
|
// IC_CLK_FREQ_OPTIMIZATION .......... 0x0
|
||||||
// IC_DEFAULT_FS_SPKLEN .............. 0xf
|
// IC_DEFAULT_FS_SPKLEN .............. 0x7
|
||||||
// IC_ADD_ENCODED_PARAMS ............. 0x1
|
// IC_ADD_ENCODED_PARAMS ............. 0x0
|
||||||
// IC_DEFAULT_SDA_HOLD ............... 0x000001
|
// IC_DEFAULT_SDA_HOLD ............... 0x000001
|
||||||
// IC_DEFAULT_SDA_SETUP .............. 0x64
|
// IC_DEFAULT_SDA_SETUP .............. 0x64
|
||||||
// IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0
|
// IC_AVOID_RX_FIFO_FLUSH_ON_TX_ABRT . 0x0
|
||||||
// SLVERR_RESP_EN .................... 0
|
// IC_CLOCK_PERIOD ................... 100
|
||||||
|
// IC_EMPTYFIFO_HOLD_MASTER_EN ....... 1
|
||||||
// IC_RESTART_EN ..................... 0x1
|
// IC_RESTART_EN ..................... 0x1
|
||||||
// IC_TX_CMD_BLOCK ................... 0x1
|
// IC_TX_CMD_BLOCK_DEFAULT ........... 0x0
|
||||||
// HC_REG_TIMEOUT_VALUE .............. 0
|
// IC_BUS_CLEAR_FEATURE .............. 0x0
|
||||||
// IC_BUS_CLEAR_FEATURE .............. 0x1
|
|
||||||
// IC_CAP_LOADING .................... 100
|
// IC_CAP_LOADING .................... 100
|
||||||
// IC_HAS_ASYNC_FIFO ................. 0x0
|
// IC_FS_SCL_LOW_COUNT ............... 0x000d
|
||||||
// IC_FS_SCL_LOW_COUNT ............... 0x0082
|
|
||||||
// APB_DATA_WIDTH .................... 32
|
// APB_DATA_WIDTH .................... 32
|
||||||
// IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff
|
// IC_SDA_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff
|
||||||
// IC_SLV_DATA_NACK_ONLY ............. 0x1
|
// IC_SLV_DATA_NACK_ONLY ............. 0x1
|
||||||
// IC_10BITADDR_SLAVE ................ 0x0
|
// IC_10BITADDR_SLAVE ................ 0x0
|
||||||
// IC_TX_BUFFER_DEPTH ................ 32
|
|
||||||
// IC_DEFAULT_UFM_SPKLEN ............. 0x1
|
|
||||||
// IC_CLK_TYPE ....................... 0x0
|
// IC_CLK_TYPE ....................... 0x0
|
||||||
// IC_TX_CMD_BLOCK_DEFAULT ........... 0x0
|
|
||||||
// IC_SMBUS_UDID_MSB ................. 0x0
|
// IC_SMBUS_UDID_MSB ................. 0x0
|
||||||
// IC_SMBUS_SUSPEND_ALERT ............ 0x0
|
// IC_SMBUS_SUSPEND_ALERT ............ 0x0
|
||||||
// IC_HS_SCL_HIGH_COUNT .............. 0x0006
|
// IC_HS_SCL_HIGH_COUNT .............. 0x0006
|
||||||
// IC_SLV_RESTART_DET_EN ............. 0x1
|
// IC_SLV_RESTART_DET_EN ............. 0x1
|
||||||
// IC_SMBUS .......................... 0x1
|
// IC_SMBUS .......................... 0x0
|
||||||
// IC_STAT_FOR_CLK_STRETCH ........... 0x1
|
|
||||||
// IC_MAX_SPEED_MODE ................. 0x2
|
|
||||||
// IC_OPTIONAL_SAR_DEFAULT ........... 0x0
|
// IC_OPTIONAL_SAR_DEFAULT ........... 0x0
|
||||||
// IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0
|
// IC_PERSISTANT_SLV_ADDR_DEFAULT .... 0x0
|
||||||
// IC_USE_COUNTS ..................... 0x1
|
// IC_USE_COUNTS ..................... 0x0
|
||||||
// IC_RX_BUFFER_DEPTH ................ 32
|
// IC_RX_BUFFER_DEPTH ................ 16
|
||||||
// IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff
|
// IC_SCL_STUCK_TIMEOUT_DEFAULT ...... 0xffffffff
|
||||||
// IC_RX_FULL_HLD_BUS_EN ............. 0x1
|
// IC_RX_FULL_HLD_BUS_EN ............. 0x1
|
||||||
// IC_SLAVE_DISABLE .................. 0x1
|
// IC_SLAVE_DISABLE .................. 0x1
|
||||||
// IC_RX_TL .......................... 0x0
|
// IC_RX_TL .......................... 0x0
|
||||||
// IC_DEVICE_ID ...................... 0x0
|
// IC_DEVICE_ID ...................... 0x0
|
||||||
// IC_HC_COUNT_VALUES ................ 0x0
|
// IC_HC_COUNT_VALUES ................ 0x0
|
||||||
// I2C_DYNAMIC_TAR_UPDATE ............ 1
|
// I2C_DYNAMIC_TAR_UPDATE ............ 0
|
||||||
// IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff
|
// IC_SMBUS_CLK_LOW_MEXT_DEFAULT ..... 0xffffffff
|
||||||
// IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff
|
// IC_SMBUS_CLK_LOW_SEXT_DEFAULT ..... 0xffffffff
|
||||||
// IC_HS_MASTER_CODE ................. 0x1
|
// IC_HS_MASTER_CODE ................. 0x1
|
||||||
// IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff
|
// IC_SMBUS_RST_IDLE_CNT_DEFAULT ..... 0xffff
|
||||||
// IC_UFM_SCL_LOW_COUNT .............. 0x0008
|
|
||||||
// IC_SMBUS_UDID_HC .................. 0x1
|
|
||||||
// IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff
|
// IC_SMBUS_UDID_LSB_DEFAULT ......... 0xffffffff
|
||||||
// IC_SS_SCL_HIGH_COUNT .............. 0x0190
|
// IC_SS_SCL_HIGH_COUNT .............. 0x0028
|
||||||
|
// IC_SS_SCL_LOW_COUNT ............... 0x002f
|
||||||
|
// IC_MAX_SPEED_MODE ................. 0x2
|
||||||
|
// IC_STAT_FOR_CLK_STRETCH ........... 0x0
|
||||||
|
// IC_STOP_DET_IF_MASTER_ACTIVE ...... 0x0
|
||||||
|
// IC_DEFAULT_UFM_SPKLEN ............. 0x1
|
||||||
|
// IC_TX_BUFFER_DEPTH ................ 16
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -17,7 +17,7 @@ typedef struct {
|
|||||||
io_ro_32 gpio_hi_in;
|
io_ro_32 gpio_hi_in;
|
||||||
uint32_t _pad;
|
uint32_t _pad;
|
||||||
|
|
||||||
io_wo_32 gpio_out;
|
io_rw_32 gpio_out;
|
||||||
io_wo_32 gpio_set;
|
io_wo_32 gpio_set;
|
||||||
io_wo_32 gpio_clr;
|
io_wo_32 gpio_clr;
|
||||||
io_wo_32 gpio_togl;
|
io_wo_32 gpio_togl;
|
||||||
@ -27,7 +27,7 @@ typedef struct {
|
|||||||
io_wo_32 gpio_oe_clr;
|
io_wo_32 gpio_oe_clr;
|
||||||
io_wo_32 gpio_oe_togl;
|
io_wo_32 gpio_oe_togl;
|
||||||
|
|
||||||
io_wo_32 gpio_hi_out;
|
io_rw_32 gpio_hi_out;
|
||||||
io_wo_32 gpio_hi_set;
|
io_wo_32 gpio_hi_set;
|
||||||
io_wo_32 gpio_hi_clr;
|
io_wo_32 gpio_hi_clr;
|
||||||
io_wo_32 gpio_hi_togl;
|
io_wo_32 gpio_hi_togl;
|
||||||
|
@ -79,6 +79,7 @@ typedef struct {
|
|||||||
} usb_device_dpram_t;
|
} usb_device_dpram_t;
|
||||||
|
|
||||||
static_assert(sizeof(usb_device_dpram_t) == USB_DPRAM_MAX, "");
|
static_assert(sizeof(usb_device_dpram_t) == USB_DPRAM_MAX, "");
|
||||||
|
static_assert(offsetof(usb_device_dpram_t, epx_data) == 0x180, "");
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
// 4K of DPSRAM at beginning. Note this supports 8, 16, and 32 bit accesses
|
// 4K of DPSRAM at beginning. Note this supports 8, 16, and 32 bit accesses
|
||||||
@ -108,6 +109,7 @@ typedef struct {
|
|||||||
} usb_host_dpram_t;
|
} usb_host_dpram_t;
|
||||||
|
|
||||||
static_assert(sizeof(usb_host_dpram_t) == USB_DPRAM_MAX, "");
|
static_assert(sizeof(usb_host_dpram_t) == USB_DPRAM_MAX, "");
|
||||||
|
static_assert(offsetof(usb_host_dpram_t, epx_data) == 0x180, "");
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
io_rw_32 dev_addr_ctrl;
|
io_rw_32 dev_addr_ctrl;
|
||||||
|
@ -10,6 +10,7 @@ pico_add_subdirectory(hardware_adc)
|
|||||||
pico_add_subdirectory(hardware_clocks)
|
pico_add_subdirectory(hardware_clocks)
|
||||||
pico_add_subdirectory(hardware_dma)
|
pico_add_subdirectory(hardware_dma)
|
||||||
pico_add_subdirectory(hardware_divider)
|
pico_add_subdirectory(hardware_divider)
|
||||||
|
pico_add_subdirectory(hardware_exception)
|
||||||
pico_add_subdirectory(hardware_flash)
|
pico_add_subdirectory(hardware_flash)
|
||||||
pico_add_subdirectory(hardware_gpio)
|
pico_add_subdirectory(hardware_gpio)
|
||||||
pico_add_subdirectory(hardware_i2c)
|
pico_add_subdirectory(hardware_i2c)
|
||||||
@ -53,6 +54,7 @@ if (NOT PICO_BARE_METAL)
|
|||||||
pico_add_subdirectory(pico_stdio_semihosting)
|
pico_add_subdirectory(pico_stdio_semihosting)
|
||||||
pico_add_subdirectory(pico_stdio_uart)
|
pico_add_subdirectory(pico_stdio_uart)
|
||||||
|
|
||||||
|
pico_add_subdirectory(cmsis)
|
||||||
pico_add_subdirectory(tinyusb)
|
pico_add_subdirectory(tinyusb)
|
||||||
pico_add_subdirectory(pico_stdio_usb)
|
pico_add_subdirectory(pico_stdio_usb)
|
||||||
|
|
||||||
@ -70,3 +72,5 @@ endif()
|
|||||||
set(CMAKE_EXECUTABLE_SUFFIX "${CMAKE_EXECUTABLE_SUFFIX}" PARENT_SCOPE)
|
set(CMAKE_EXECUTABLE_SUFFIX "${CMAKE_EXECUTABLE_SUFFIX}" PARENT_SCOPE)
|
||||||
|
|
||||||
pico_add_doxygen(${CMAKE_CURRENT_LIST_DIR})
|
pico_add_doxygen(${CMAKE_CURRENT_LIST_DIR})
|
||||||
|
|
||||||
|
pico_promote_common_scope_vars()
|
285
src/rp2_common/boot_stage2/boot2_at25sf128a.S
Normal file
285
src/rp2_common/boot_stage2/boot2_at25sf128a.S
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Second stage boot code
|
||||||
|
// Copyright (c) 2019-2021 Raspberry Pi (Trading) Ltd.
|
||||||
|
// SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
//
|
||||||
|
// Device: Adesto AT25SF128A
|
||||||
|
// Based on W25Q080 code: main difference is the QE bit is being set
|
||||||
|
// via command 0x31
|
||||||
|
//
|
||||||
|
// Description: Configures AT25SF128A to run in Quad I/O continuous read XIP mode
|
||||||
|
//
|
||||||
|
// Details: * Check status register 2 to determine if QSPI mode is enabled,
|
||||||
|
// and perform an SR2 programming cycle if necessary.
|
||||||
|
// * Use SSI to perform a dummy 0xEB read command, with the mode
|
||||||
|
// continuation bits set, so that the flash will not require
|
||||||
|
// 0xEB instruction prefix on subsequent reads.
|
||||||
|
// * Configure SSI to write address, mode bits, but no instruction.
|
||||||
|
// SSI + flash are now jointly in a state where continuous reads
|
||||||
|
// can take place.
|
||||||
|
// * Jump to exit pointer passed in via lr. Bootrom passes null,
|
||||||
|
// in which case this code uses a default 256 byte flash offset
|
||||||
|
//
|
||||||
|
// Building: * This code must be position-independent, and use stack only
|
||||||
|
// * The code will be padded to a size of 256 bytes, including a
|
||||||
|
// 4-byte checksum. Therefore code size cannot exceed 252 bytes.
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "pico/asm_helper.S"
|
||||||
|
#include "hardware/regs/addressmap.h"
|
||||||
|
#include "hardware/regs/ssi.h"
|
||||||
|
#include "hardware/regs/pads_qspi.h"
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Config section
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// It should be possible to support most flash devices by modifying this section
|
||||||
|
|
||||||
|
// The serial flash interface will run at clk_sys/PICO_FLASH_SPI_CLKDIV.
|
||||||
|
// This must be a positive, even integer.
|
||||||
|
// The bootrom is very conservative with SPI frequency, but here we should be
|
||||||
|
// as aggressive as possible.
|
||||||
|
|
||||||
|
#ifndef PICO_FLASH_SPI_CLKDIV
|
||||||
|
#define PICO_FLASH_SPI_CLKDIV 4
|
||||||
|
#endif
|
||||||
|
#if PICO_FLASH_SPI_CLKDIV & 1
|
||||||
|
#error PICO_FLASH_SPI_CLKDIV must be even
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Define interface width: single/dual/quad IO
|
||||||
|
#define FRAME_FORMAT SSI_CTRLR0_SPI_FRF_VALUE_QUAD
|
||||||
|
|
||||||
|
// For W25Q080 this is the "Read data fast quad IO" instruction:
|
||||||
|
#define CMD_READ 0xeb
|
||||||
|
|
||||||
|
// "Mode bits" are 8 special bits sent immediately after
|
||||||
|
// the address bits in a "Read Data Fast Quad I/O" command sequence.
|
||||||
|
// On W25Q080, the four LSBs are don't care, and if MSBs == 0xa, the
|
||||||
|
// next read does not require the 0xeb instruction prefix.
|
||||||
|
#define MODE_CONTINUOUS_READ 0x20
|
||||||
|
|
||||||
|
// The number of address + mode bits, divided by 4 (always 4, not function of
|
||||||
|
// interface width).
|
||||||
|
#define ADDR_L 8
|
||||||
|
|
||||||
|
// How many clocks of Hi-Z following the mode bits. For W25Q080, 4 dummy cycles
|
||||||
|
// are required.
|
||||||
|
#define WAIT_CYCLES 4
|
||||||
|
|
||||||
|
// If defined, we will read status reg, compare to SREG_DATA, and overwrite
|
||||||
|
// with our value if the SR doesn't match.
|
||||||
|
// We do a two-byte write to SR1 (01h cmd) rather than a one-byte write to
|
||||||
|
// SR2 (31h cmd) as the latter command isn't supported by WX25Q080.
|
||||||
|
// This isn't great because it will remove block protections.
|
||||||
|
// A better solution is to use a volatile SR write if your device supports it.
|
||||||
|
#define PROGRAM_STATUS_REG
|
||||||
|
|
||||||
|
#define CMD_WRITE_ENABLE 0x06
|
||||||
|
#define CMD_READ_STATUS 0x05
|
||||||
|
#define CMD_READ_STATUS2 0x35
|
||||||
|
#define CMD_WRITE_STATUS 0x01
|
||||||
|
#define CMD_WRITE_STATUS2 0x31
|
||||||
|
#define SREG_DATA 0x02 // Enable quad-SPI mode
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
// Start of 2nd Stage Boot Code
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
.syntax unified
|
||||||
|
.cpu cortex-m0plus
|
||||||
|
.thumb
|
||||||
|
|
||||||
|
.section .text
|
||||||
|
|
||||||
|
// The exit point is passed in lr. If entered from bootrom, this will be the
|
||||||
|
// flash address immediately following this second stage (0x10000100).
|
||||||
|
// Otherwise it will be a return address -- second stage being called as a
|
||||||
|
// function by user code, after copying out of XIP region. r3 holds SSI base,
|
||||||
|
// r0...2 used as temporaries. Other GPRs not used.
|
||||||
|
.global _stage2_boot
|
||||||
|
.type _stage2_boot,%function
|
||||||
|
.thumb_func
|
||||||
|
_stage2_boot:
|
||||||
|
push {lr}
|
||||||
|
|
||||||
|
// Set pad configuration:
|
||||||
|
// - SCLK 8mA drive, no slew limiting
|
||||||
|
// - SDx disable input Schmitt to reduce delay
|
||||||
|
|
||||||
|
ldr r3, =PADS_QSPI_BASE
|
||||||
|
movs r0, #(2 << PADS_QSPI_GPIO_QSPI_SCLK_DRIVE_LSB | PADS_QSPI_GPIO_QSPI_SCLK_SLEWFAST_BITS)
|
||||||
|
str r0, [r3, #PADS_QSPI_GPIO_QSPI_SCLK_OFFSET]
|
||||||
|
ldr r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET]
|
||||||
|
movs r1, #PADS_QSPI_GPIO_QSPI_SD0_SCHMITT_BITS
|
||||||
|
bics r0, r1
|
||||||
|
str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD0_OFFSET]
|
||||||
|
str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD1_OFFSET]
|
||||||
|
str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD2_OFFSET]
|
||||||
|
str r0, [r3, #PADS_QSPI_GPIO_QSPI_SD3_OFFSET]
|
||||||
|
|
||||||
|
ldr r3, =XIP_SSI_BASE
|
||||||
|
|
||||||
|
// Disable SSI to allow further config
|
||||||
|
movs r1, #0
|
||||||
|
str r1, [r3, #SSI_SSIENR_OFFSET]
|
||||||
|
|
||||||
|
// Set baud rate
|
||||||
|
movs r1, #PICO_FLASH_SPI_CLKDIV
|
||||||
|
str r1, [r3, #SSI_BAUDR_OFFSET]
|
||||||
|
|
||||||
|
// Set 1-cycle sample delay. If PICO_FLASH_SPI_CLKDIV == 2 then this means,
|
||||||
|
// if the flash launches data on SCLK posedge, we capture it at the time that
|
||||||
|
// the next SCLK posedge is launched. This is shortly before that posedge
|
||||||
|
// arrives at the flash, so data hold time should be ok. For
|
||||||
|
// PICO_FLASH_SPI_CLKDIV > 2 this pretty much has no effect.
|
||||||
|
|
||||||
|
movs r1, #1
|
||||||
|
movs r2, #SSI_RX_SAMPLE_DLY_OFFSET // == 0xf0 so need 8 bits of offset significance
|
||||||
|
str r1, [r3, r2]
|
||||||
|
|
||||||
|
|
||||||
|
// On QSPI parts we usually need a 01h SR-write command to enable QSPI mode
|
||||||
|
// (i.e. turn WPn and HOLDn into IO2/IO3)
|
||||||
|
#ifdef PROGRAM_STATUS_REG
|
||||||
|
program_sregs:
|
||||||
|
#define CTRL0_SPI_TXRX \
|
||||||
|
(7 << SSI_CTRLR0_DFS_32_LSB) | /* 8 bits per data frame */ \
|
||||||
|
(SSI_CTRLR0_TMOD_VALUE_TX_AND_RX << SSI_CTRLR0_TMOD_LSB)
|
||||||
|
|
||||||
|
ldr r1, =(CTRL0_SPI_TXRX)
|
||||||
|
str r1, [r3, #SSI_CTRLR0_OFFSET]
|
||||||
|
|
||||||
|
// Enable SSI and select slave 0
|
||||||
|
movs r1, #1
|
||||||
|
str r1, [r3, #SSI_SSIENR_OFFSET]
|
||||||
|
|
||||||
|
// Check whether SR needs updating
|
||||||
|
movs r0, #CMD_READ_STATUS2
|
||||||
|
bl read_flash_sreg
|
||||||
|
movs r2, #SREG_DATA
|
||||||
|
cmp r0, r2
|
||||||
|
beq skip_sreg_programming
|
||||||
|
|
||||||
|
// Send write enable command
|
||||||
|
movs r1, #CMD_WRITE_ENABLE
|
||||||
|
str r1, [r3, #SSI_DR0_OFFSET]
|
||||||
|
|
||||||
|
// Poll for completion and discard RX
|
||||||
|
bl wait_ssi_ready
|
||||||
|
ldr r1, [r3, #SSI_DR0_OFFSET]
|
||||||
|
|
||||||
|
// Send status write command followed by data bytes
|
||||||
|
movs r1, #CMD_WRITE_STATUS2
|
||||||
|
str r1, [r3, #SSI_DR0_OFFSET]
|
||||||
|
str r2, [r3, #SSI_DR0_OFFSET]
|
||||||
|
|
||||||
|
bl wait_ssi_ready
|
||||||
|
ldr r1, [r3, #SSI_DR0_OFFSET]
|
||||||
|
ldr r1, [r3, #SSI_DR0_OFFSET]
|
||||||
|
ldr r1, [r3, #SSI_DR0_OFFSET]
|
||||||
|
|
||||||
|
// Poll status register for write completion
|
||||||
|
1:
|
||||||
|
movs r0, #CMD_READ_STATUS
|
||||||
|
bl read_flash_sreg
|
||||||
|
movs r1, #1
|
||||||
|
tst r0, r1
|
||||||
|
bne 1b
|
||||||
|
|
||||||
|
skip_sreg_programming:
|
||||||
|
|
||||||
|
// Disable SSI again so that it can be reconfigured
|
||||||
|
movs r1, #0
|
||||||
|
str r1, [r3, #SSI_SSIENR_OFFSET]
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Currently the flash expects an 8 bit serial command prefix on every
|
||||||
|
// transfer, which is a waste of cycles. Perform a dummy Fast Read Quad I/O
|
||||||
|
// command, with mode bits set such that the flash will not expect a serial
|
||||||
|
// command prefix on *subsequent* transfers. We don't care about the results
|
||||||
|
// of the read, the important part is the mode bits.
|
||||||
|
|
||||||
|
dummy_read:
|
||||||
|
#define CTRLR0_ENTER_XIP \
|
||||||
|
(FRAME_FORMAT /* Quad I/O mode */ \
|
||||||
|
<< SSI_CTRLR0_SPI_FRF_LSB) | \
|
||||||
|
(31 << SSI_CTRLR0_DFS_32_LSB) | /* 32 data bits */ \
|
||||||
|
(SSI_CTRLR0_TMOD_VALUE_EEPROM_READ /* Send INST/ADDR, Receive Data */ \
|
||||||
|
<< SSI_CTRLR0_TMOD_LSB)
|
||||||
|
|
||||||
|
ldr r1, =(CTRLR0_ENTER_XIP)
|
||||||
|
str r1, [r3, #SSI_CTRLR0_OFFSET]
|
||||||
|
|
||||||
|
movs r1, #0x0 // NDF=0 (single 32b read)
|
||||||
|
str r1, [r3, #SSI_CTRLR1_OFFSET]
|
||||||
|
|
||||||
|
#define SPI_CTRLR0_ENTER_XIP \
|
||||||
|
(ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Address + mode bits */ \
|
||||||
|
(WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \
|
||||||
|
(SSI_SPI_CTRLR0_INST_L_VALUE_8B \
|
||||||
|
<< SSI_SPI_CTRLR0_INST_L_LSB) | /* 8-bit instruction */ \
|
||||||
|
(SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_1C2A /* Send Command in serial mode then address in Quad I/O mode */ \
|
||||||
|
<< SSI_SPI_CTRLR0_TRANS_TYPE_LSB)
|
||||||
|
|
||||||
|
ldr r1, =(SPI_CTRLR0_ENTER_XIP)
|
||||||
|
ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET) // SPI_CTRL0 Register
|
||||||
|
str r1, [r0]
|
||||||
|
|
||||||
|
movs r1, #1 // Re-enable SSI
|
||||||
|
str r1, [r3, #SSI_SSIENR_OFFSET]
|
||||||
|
|
||||||
|
movs r1, #CMD_READ
|
||||||
|
str r1, [r3, #SSI_DR0_OFFSET] // Push SPI command into TX FIFO
|
||||||
|
movs r1, #MODE_CONTINUOUS_READ // 32-bit: 24 address bits (we don't care, so 0) and M[7:4]=1010
|
||||||
|
str r1, [r3, #SSI_DR0_OFFSET] // Push Address into TX FIFO - this will trigger the transaction
|
||||||
|
|
||||||
|
// Poll for completion
|
||||||
|
bl wait_ssi_ready
|
||||||
|
|
||||||
|
// The flash is in a state where we can blast addresses in parallel, and get
|
||||||
|
// parallel data back. Now configure the SSI to translate XIP bus accesses
|
||||||
|
// into QSPI transfers of this form.
|
||||||
|
|
||||||
|
movs r1, #0
|
||||||
|
str r1, [r3, #SSI_SSIENR_OFFSET] // Disable SSI (and clear FIFO) to allow further config
|
||||||
|
|
||||||
|
// Note that the INST_L field is used to select what XIP data gets pushed into
|
||||||
|
// the TX FIFO:
|
||||||
|
// INST_L_0_BITS {ADDR[23:0],XIP_CMD[7:0]} Load "mode bits" into XIP_CMD
|
||||||
|
// Anything else {XIP_CMD[7:0],ADDR[23:0]} Load SPI command into XIP_CMD
|
||||||
|
configure_ssi:
|
||||||
|
#define SPI_CTRLR0_XIP \
|
||||||
|
(MODE_CONTINUOUS_READ /* Mode bits to keep flash in continuous read mode */ \
|
||||||
|
<< SSI_SPI_CTRLR0_XIP_CMD_LSB) | \
|
||||||
|
(ADDR_L << SSI_SPI_CTRLR0_ADDR_L_LSB) | /* Total number of address + mode bits */ \
|
||||||
|
(WAIT_CYCLES << SSI_SPI_CTRLR0_WAIT_CYCLES_LSB) | /* Hi-Z dummy clocks following address + mode */ \
|
||||||
|
(SSI_SPI_CTRLR0_INST_L_VALUE_NONE /* Do not send a command, instead send XIP_CMD as mode bits after address */ \
|
||||||
|
<< SSI_SPI_CTRLR0_INST_L_LSB) | \
|
||||||
|
(SSI_SPI_CTRLR0_TRANS_TYPE_VALUE_2C2A /* Send Address in Quad I/O mode (and Command but that is zero bits long) */ \
|
||||||
|
<< SSI_SPI_CTRLR0_TRANS_TYPE_LSB)
|
||||||
|
|
||||||
|
ldr r1, =(SPI_CTRLR0_XIP)
|
||||||
|
ldr r0, =(XIP_SSI_BASE + SSI_SPI_CTRLR0_OFFSET)
|
||||||
|
str r1, [r0]
|
||||||
|
|
||||||
|
movs r1, #1
|
||||||
|
str r1, [r3, #SSI_SSIENR_OFFSET] // Re-enable SSI
|
||||||
|
|
||||||
|
// Bus accesses to the XIP window will now be transparently serviced by the
|
||||||
|
// external flash on cache miss. We are ready to run code from flash.
|
||||||
|
|
||||||
|
// Pull in standard exit routine
|
||||||
|
#include "boot2_helpers/exit_from_boot2.S"
|
||||||
|
|
||||||
|
// Common functions
|
||||||
|
#include "boot2_helpers/wait_ssi_ready.S"
|
||||||
|
#ifdef PROGRAM_STATUS_REG
|
||||||
|
#include "boot2_helpers/read_flash_sreg.S"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
.global literals
|
||||||
|
literals:
|
||||||
|
.ltorg
|
||||||
|
|
||||||
|
.end
|
@ -44,6 +44,16 @@
|
|||||||
#endif
|
#endif
|
||||||
#define _BOOT_STAGE2_SELECTED
|
#define _BOOT_STAGE2_SELECTED
|
||||||
#endif
|
#endif
|
||||||
|
// PICO_CONFIG: PICO_BOOT_STAGE2_CHOOSE_AT25SF128A, Select boot2_at25sf128a as the boot stage 2 when no boot stage 2 selection is made by the CMake build, type=bool, default=0, group=boot_stage2
|
||||||
|
#ifndef PICO_BOOT_STAGE2_CHOOSE_AT25SF128A
|
||||||
|
#define PICO_BOOT_STAGE2_CHOOSE_AT25SF128A 0
|
||||||
|
#elif PICO_BOOT_STAGE2_CHOOSE_AT25SF128A
|
||||||
|
#ifdef _BOOT_STAGE2_SELECTED
|
||||||
|
#error multiple boot stage 2 options chosen
|
||||||
|
#endif
|
||||||
|
#define _BOOT_STAGE2_SELECTED
|
||||||
|
#endif
|
||||||
|
|
||||||
// PICO_CONFIG: PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H, Select boot2_generic_03h as the boot stage 2 when no boot stage 2 selection is made by the CMake build, type=bool, default=1, group=boot_stage2
|
// PICO_CONFIG: PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H, Select boot2_generic_03h as the boot stage 2 when no boot stage 2 selection is made by the CMake build, type=bool, default=1, group=boot_stage2
|
||||||
#if defined(PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H) && PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H
|
#if defined(PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H) && PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H
|
||||||
#ifdef _BOOT_STAGE2_SELECTED
|
#ifdef _BOOT_STAGE2_SELECTED
|
||||||
@ -65,6 +75,8 @@
|
|||||||
#define _BOOT_STAGE2 boot2_w25q080
|
#define _BOOT_STAGE2 boot2_w25q080
|
||||||
#elif PICO_BOOT_STAGE2_CHOOSE_W25X10CL
|
#elif PICO_BOOT_STAGE2_CHOOSE_W25X10CL
|
||||||
#define _BOOT_STAGE2 boot2_w25x10cl
|
#define _BOOT_STAGE2 boot2_w25x10cl
|
||||||
|
#elif PICO_BOOT_STAGE2_CHOOSE_AT25SF128A
|
||||||
|
#define _BOOT_STAGE2 boot2_at25sf128a
|
||||||
#elif !defined(PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H) || PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H
|
#elif !defined(PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H) || PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H
|
||||||
#undef PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H
|
#undef PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H
|
||||||
#define PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H 1
|
#define PICO_BOOT_STAGE2_CHOOSE_GENERIC_03H 1
|
||||||
|
66
src/rp2_common/cmsis/CMakeLists.txt
Normal file
66
src/rp2_common/cmsis/CMakeLists.txt
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
# Deferring this config until we decide how to include other CMSIS libraries... it is likely that we always want to use the stub version of the core
|
||||||
|
# at least if the vendor/device is RaspberryPi/RP2040...
|
||||||
|
|
||||||
|
## PICO_CMAKE_CONFIG: PICO_CMSIS_PATH, directory to locate CMSIS installation, default="included stub CORE only impl", group=build
|
||||||
|
#if (DEFINED PICO_CMSIS_PATH)
|
||||||
|
# set(PICO_CMSIS_PATH "${PICO_CMSIS_PATH}" CACHE PATH "Path to the CMSIS tree to use with Raspberry Pi Pico SDK")
|
||||||
|
# message("Using specified PICO_CMSIS_PATH for CMSIS ('${PICO_CMSIS_PATH}')")
|
||||||
|
#elseif (DEFINED ENV{PICO_CMSIS_PATH})
|
||||||
|
# set(PICO_CMSIS_PATH $ENV{PICO_CMSIS_PATH})
|
||||||
|
# message("Using PICO_CMSIS_PATH from environment for CMSIS ('${PICO_CMSIS_PATH}')")
|
||||||
|
#endif()
|
||||||
|
#
|
||||||
|
## PICO_CMAKE_CONFIG: PICO_CMSIS_VENDOR, vendor name for CMSIS, default="RaspberryPi", group=build
|
||||||
|
#if (DEFINED PICO_CMSIS_VENDOR)
|
||||||
|
# set(PICO_CMSIS_VENDOR "${PICO_CMSIS_VENDOR}" CACHE STRING "CMSIS vendor name to use")
|
||||||
|
# message("Using specified PICO_CMSIS_VENDOR for CMSIS ('${PICO_CMSIS_VENDOR}')")
|
||||||
|
#elseif (DEFINED ENV{PICO_CMSIS_VENDOR})
|
||||||
|
# set(PICO_CMSIS_VENDOR $ENV{PICO_CMSIS_VENDOR})
|
||||||
|
# message("Using PICO_CMSIS_VENDOR from environment for CMSIS ('${PICO_CMSIS_VENDOR}')")
|
||||||
|
#else()
|
||||||
|
# set(PICO_CMSIS_VENDOR RaspberryPi)
|
||||||
|
#endif()
|
||||||
|
#
|
||||||
|
## PICO_CMAKE_CONFIG: PICO_CMSIS_DEVICE, device name for CMSIS, default="RP2040", group=build
|
||||||
|
#if (DEFINED PICO_CMSIS_DEVICE)
|
||||||
|
# set(PICO_CMSIS_DEVICE "${PICO_CMSIS_DEVICE}" CACHE STRING "CMSIS device name to use")
|
||||||
|
# message("Using specified PICO_CMSIS_DEVICE for CMSIS ('${PICO_CMSIS_DEVICE}')")
|
||||||
|
#elseif (DEFINED ENV{PICO_CMSIS_DEVICE})
|
||||||
|
# set(PICO_CMSIS_DEVICE $ENV{PICO_CMSIS_DEVICE})
|
||||||
|
# message("Using PICO_CMSIS_DEVICE from environment for CMSIS ('${PICO_CMSIS_DEVICE}')")
|
||||||
|
#else()
|
||||||
|
# set(PICO_CMSIS_DEVICE RP2040)
|
||||||
|
#endif()
|
||||||
|
#
|
||||||
|
#if (PICO_CMSIS_PATH AND EXISTS ${PICO_CMSIS_PATH}/CMSIS/Core/${PICO_CMSIS_VENDOR}/${PICO_CMSIS_DEVICE})
|
||||||
|
# message("CMSIS Core found for path ${PICO_CMSIS_PATH}, vendor ${PICO_CMSIS_VENDOR}, device ${PICO_CMSIS_DEVICE}")
|
||||||
|
# set(PICO_CMSIS_CORE_PATH ${PICO_CMSIS_PATH}/CMSIS/Core)
|
||||||
|
#elseif (PICO_CMSIS_VENDOR STREQUAL "RaspberryPi" AND PICO_CMSIS_DEVICE STREQUAL "RP2040")
|
||||||
|
# set(PICO_CMSIS_CORE_PATH ${CMAKE_CURRENT_LIST_DIR}/stub)
|
||||||
|
#elseif (PICO_CMSIS_PATH)
|
||||||
|
# message(WARNING "CMSIS core not found in ${PICO_CMSIS_PATH} for vendor ${PICO_CMSIS_VENDOR}, device ${PICO_CMSIS_DEVICE}")
|
||||||
|
# set(PICO_CMSIS_CORE_PATH)
|
||||||
|
#else()
|
||||||
|
# message(WARNING "Non-standard vendor ${PICO_CMSIS_VENDOR} amd device ${PICO_CMSIS_DEVICE} specified, but PICO_CMSIS_PATH was not set")
|
||||||
|
#endif()
|
||||||
|
|
||||||
|
# ... using these 3 lines instead
|
||||||
|
set(PICO_CMSIS_CORE_PATH ${CMAKE_CURRENT_LIST_DIR}/stub)
|
||||||
|
set(PICO_CMSIS_VENDOR RaspberryPi)
|
||||||
|
set(PICO_CMSIS_DEVICE RP2040)
|
||||||
|
|
||||||
|
if (PICO_CMSIS_CORE_PATH)
|
||||||
|
pico_add_impl_library(cmsis_core)
|
||||||
|
target_sources(cmsis_core INTERFACE
|
||||||
|
${PICO_CMSIS_CORE_PATH}/CMSIS/Device/${PICO_CMSIS_VENDOR}/${PICO_CMSIS_DEVICE}/Source/system_${PICO_CMSIS_DEVICE}.c
|
||||||
|
)
|
||||||
|
target_include_directories(cmsis_core INTERFACE
|
||||||
|
${PICO_CMSIS_CORE_PATH}/CMSIS/Core/Include
|
||||||
|
${PICO_CMSIS_CORE_PATH}/CMSIS/Device/${PICO_CMSIS_VENDOR}/${PICO_CMSIS_DEVICE}/Include
|
||||||
|
)
|
||||||
|
target_link_libraries(cmsis_core INTERFACE hardware_clocks pico_platform)
|
||||||
|
|
||||||
|
list(APPEND PICO_RP2040_CONFIG_HEADER_FILES ${CMAKE_CURRENT_LIST_DIR}/include/cmsis/rename_exceptions.h)
|
||||||
|
pico_promote_common_scope_vars()
|
||||||
|
endif()
|
||||||
|
|
53
src/rp2_common/cmsis/include/cmsis/rename_exceptions.h
Normal file
53
src/rp2_common/cmsis/include/cmsis/rename_exceptions.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CMSIS_RENAME_EXCEPTIONS_H
|
||||||
|
#define _CMSIS_RENAME_EXCEPTIONS_H
|
||||||
|
|
||||||
|
#if LIB_CMSIS_CORE
|
||||||
|
// PICO_CONFIG: PICO_CMSIS_RENAME_EXCEPTIONS, Whether to rename SDK exceptions such as isr_nmi to their CMSIS equivalent i.e. NMI_Handler, type=bool, default=1, group=cmsis_core
|
||||||
|
|
||||||
|
// Note that since this header is included at the config stage, if you wish to override this you should do so via build compiler define
|
||||||
|
#ifndef PICO_CMSIS_RENAME_EXCEPTIONS
|
||||||
|
#define PICO_CMSIS_RENAME_EXCEPTIONS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if PICO_CMSIS_RENAME_EXCEPTIONS
|
||||||
|
#define isr_nmi NMI_Handler
|
||||||
|
#define isr_hardfault HardFault_Handler
|
||||||
|
#define isr_svcall SVC_Handler
|
||||||
|
#define isr_pendsv PendSV_Handler
|
||||||
|
#define isr_systick SysTick_Handler
|
||||||
|
#define isr_irq0 TIMER_IRQ_0_Handler
|
||||||
|
#define isr_irq1 TIMER_IRQ_1_Handler
|
||||||
|
#define isr_irq2 TIMER_IRQ_2_Handler
|
||||||
|
#define isr_irq3 TIMER_IRQ_3_Handler
|
||||||
|
#define isr_irq4 PWM_IRQ_WRAP_Handler
|
||||||
|
#define isr_irq5 USBCTRL_IRQ_Handler
|
||||||
|
#define isr_irq6 XIP_IRQ_Handler
|
||||||
|
#define isr_irq7 PIO0_IRQ_0_Handler
|
||||||
|
#define isr_irq8 PIO0_IRQ_1_Handler
|
||||||
|
#define isr_irq9 PIO1_IRQ_0_Handler
|
||||||
|
#define isr_irq10 PIO1_IRQ_1_Handler
|
||||||
|
#define isr_irq11 DMA_IRQ_0_Handler
|
||||||
|
#define isr_irq12 DMA_IRQ_1_Handler
|
||||||
|
#define isr_irq13 IO_IRQ_BANK0_Handler
|
||||||
|
#define isr_irq14 IO_IRQ_QSPI_Handler
|
||||||
|
#define isr_irq15 SIO_IRQ_PROC0_Handler
|
||||||
|
#define isr_irq16 SIO_IRQ_PROC1_Handler
|
||||||
|
#define isr_irq17 CLOCKS_IRQ_Handler
|
||||||
|
#define isr_irq18 SPI0_IRQ_Handler
|
||||||
|
#define isr_irq19 SPI1_IRQ_Handler
|
||||||
|
#define isr_irq20 UART0_IRQ_Handler
|
||||||
|
#define isr_irq21 UART1_IRQ_Handler
|
||||||
|
#define isr_irq22 ADC_IRQ_FIFO_Handler
|
||||||
|
#define isr_irq23 I2C0_IRQ_Handler
|
||||||
|
#define isr_irq24 I2C1_IRQ_Handler
|
||||||
|
#define isr_irq25 RTC_IRQ_Handler
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
#endif /* _CMSIS_RENAME_EXCEPTIONS_H */
|
885
src/rp2_common/cmsis/stub/CMSIS/Core/Include/cmsis_armcc.h
Normal file
885
src/rp2_common/cmsis/stub/CMSIS/Core/Include/cmsis_armcc.h
Normal file
@ -0,0 +1,885 @@
|
|||||||
|
/**************************************************************************//**
|
||||||
|
* @file cmsis_armcc.h
|
||||||
|
* @brief CMSIS compiler ARMCC (Arm Compiler 5) header file
|
||||||
|
* @version V5.2.1
|
||||||
|
* @date 26. March 2020
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2020 Arm Limited. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CMSIS_ARMCC_H
|
||||||
|
#define __CMSIS_ARMCC_H
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 400677)
|
||||||
|
#error "Please use Arm Compiler Toolchain V4.0.677 or later!"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CMSIS compiler control architecture macros */
|
||||||
|
#if ((defined (__TARGET_ARCH_6_M ) && (__TARGET_ARCH_6_M == 1)) || \
|
||||||
|
(defined (__TARGET_ARCH_6S_M ) && (__TARGET_ARCH_6S_M == 1)) )
|
||||||
|
#define __ARM_ARCH_6M__ 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined (__TARGET_ARCH_7_M ) && (__TARGET_ARCH_7_M == 1))
|
||||||
|
#define __ARM_ARCH_7M__ 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined (__TARGET_ARCH_7E_M) && (__TARGET_ARCH_7E_M == 1))
|
||||||
|
#define __ARM_ARCH_7EM__ 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* __ARM_ARCH_8M_BASE__ not applicable */
|
||||||
|
/* __ARM_ARCH_8M_MAIN__ not applicable */
|
||||||
|
/* __ARM_ARCH_8_1M_MAIN__ not applicable */
|
||||||
|
|
||||||
|
/* CMSIS compiler control DSP macros */
|
||||||
|
#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
|
||||||
|
#define __ARM_FEATURE_DSP 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* CMSIS compiler specific defines */
|
||||||
|
#ifndef __ASM
|
||||||
|
#define __ASM __asm
|
||||||
|
#endif
|
||||||
|
#ifndef __INLINE
|
||||||
|
#define __INLINE __inline
|
||||||
|
#endif
|
||||||
|
#ifndef __STATIC_INLINE
|
||||||
|
#define __STATIC_INLINE static __inline
|
||||||
|
#endif
|
||||||
|
#ifndef __STATIC_FORCEINLINE
|
||||||
|
#define __STATIC_FORCEINLINE static __forceinline
|
||||||
|
#endif
|
||||||
|
#ifndef __NO_RETURN
|
||||||
|
#define __NO_RETURN __declspec(noreturn)
|
||||||
|
#endif
|
||||||
|
#ifndef __USED
|
||||||
|
#define __USED __attribute__((used))
|
||||||
|
#endif
|
||||||
|
#ifndef __WEAK
|
||||||
|
#define __WEAK __attribute__((weak))
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED
|
||||||
|
#define __PACKED __attribute__((packed))
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED_STRUCT
|
||||||
|
#define __PACKED_STRUCT __packed struct
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED_UNION
|
||||||
|
#define __PACKED_UNION __packed union
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT32 /* deprecated */
|
||||||
|
#define __UNALIGNED_UINT32(x) (*((__packed uint32_t *)(x)))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT16_WRITE
|
||||||
|
#define __UNALIGNED_UINT16_WRITE(addr, val) ((*((__packed uint16_t *)(addr))) = (val))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT16_READ
|
||||||
|
#define __UNALIGNED_UINT16_READ(addr) (*((const __packed uint16_t *)(addr)))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT32_WRITE
|
||||||
|
#define __UNALIGNED_UINT32_WRITE(addr, val) ((*((__packed uint32_t *)(addr))) = (val))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT32_READ
|
||||||
|
#define __UNALIGNED_UINT32_READ(addr) (*((const __packed uint32_t *)(addr)))
|
||||||
|
#endif
|
||||||
|
#ifndef __ALIGNED
|
||||||
|
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||||
|
#endif
|
||||||
|
#ifndef __RESTRICT
|
||||||
|
#define __RESTRICT __restrict
|
||||||
|
#endif
|
||||||
|
#ifndef __COMPILER_BARRIER
|
||||||
|
#define __COMPILER_BARRIER() __memory_changed()
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ######################### Startup and Lowlevel Init ######################## */
|
||||||
|
|
||||||
|
#ifndef __PROGRAM_START
|
||||||
|
#define __PROGRAM_START __main
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __INITIAL_SP
|
||||||
|
#define __INITIAL_SP Image$$ARM_LIB_STACK$$ZI$$Limit
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __STACK_LIMIT
|
||||||
|
#define __STACK_LIMIT Image$$ARM_LIB_STACK$$ZI$$Base
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __VECTOR_TABLE
|
||||||
|
#define __VECTOR_TABLE __Vectors
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __VECTOR_TABLE_ATTRIBUTE
|
||||||
|
#define __VECTOR_TABLE_ATTRIBUTE __attribute__((used, section("RESET")))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* ########################### Core Function Access ########################### */
|
||||||
|
/** \ingroup CMSIS_Core_FunctionInterface
|
||||||
|
\defgroup CMSIS_Core_RegAccFunctions CMSIS Core Register Access Functions
|
||||||
|
@{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Enable IRQ Interrupts
|
||||||
|
\details Enables IRQ interrupts by clearing the I-bit in the CPSR.
|
||||||
|
Can only be executed in Privileged modes.
|
||||||
|
*/
|
||||||
|
/* intrinsic void __enable_irq(); */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Disable IRQ Interrupts
|
||||||
|
\details Disables IRQ interrupts by setting the I-bit in the CPSR.
|
||||||
|
Can only be executed in Privileged modes.
|
||||||
|
*/
|
||||||
|
/* intrinsic void __disable_irq(); */
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Get Control Register
|
||||||
|
\details Returns the content of the Control Register.
|
||||||
|
\return Control Register value
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE uint32_t __get_CONTROL(void)
|
||||||
|
{
|
||||||
|
register uint32_t __regControl __ASM("control");
|
||||||
|
return(__regControl);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Set Control Register
|
||||||
|
\details Writes the given value to the Control Register.
|
||||||
|
\param [in] control Control Register value to set
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void __set_CONTROL(uint32_t control)
|
||||||
|
{
|
||||||
|
register uint32_t __regControl __ASM("control");
|
||||||
|
__regControl = control;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Get IPSR Register
|
||||||
|
\details Returns the content of the IPSR Register.
|
||||||
|
\return IPSR Register value
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE uint32_t __get_IPSR(void)
|
||||||
|
{
|
||||||
|
register uint32_t __regIPSR __ASM("ipsr");
|
||||||
|
return(__regIPSR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Get APSR Register
|
||||||
|
\details Returns the content of the APSR Register.
|
||||||
|
\return APSR Register value
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE uint32_t __get_APSR(void)
|
||||||
|
{
|
||||||
|
register uint32_t __regAPSR __ASM("apsr");
|
||||||
|
return(__regAPSR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Get xPSR Register
|
||||||
|
\details Returns the content of the xPSR Register.
|
||||||
|
\return xPSR Register value
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE uint32_t __get_xPSR(void)
|
||||||
|
{
|
||||||
|
register uint32_t __regXPSR __ASM("xpsr");
|
||||||
|
return(__regXPSR);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Get Process Stack Pointer
|
||||||
|
\details Returns the current value of the Process Stack Pointer (PSP).
|
||||||
|
\return PSP Register value
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE uint32_t __get_PSP(void)
|
||||||
|
{
|
||||||
|
register uint32_t __regProcessStackPointer __ASM("psp");
|
||||||
|
return(__regProcessStackPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Set Process Stack Pointer
|
||||||
|
\details Assigns the given value to the Process Stack Pointer (PSP).
|
||||||
|
\param [in] topOfProcStack Process Stack Pointer value to set
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void __set_PSP(uint32_t topOfProcStack)
|
||||||
|
{
|
||||||
|
register uint32_t __regProcessStackPointer __ASM("psp");
|
||||||
|
__regProcessStackPointer = topOfProcStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Get Main Stack Pointer
|
||||||
|
\details Returns the current value of the Main Stack Pointer (MSP).
|
||||||
|
\return MSP Register value
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE uint32_t __get_MSP(void)
|
||||||
|
{
|
||||||
|
register uint32_t __regMainStackPointer __ASM("msp");
|
||||||
|
return(__regMainStackPointer);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Set Main Stack Pointer
|
||||||
|
\details Assigns the given value to the Main Stack Pointer (MSP).
|
||||||
|
\param [in] topOfMainStack Main Stack Pointer value to set
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void __set_MSP(uint32_t topOfMainStack)
|
||||||
|
{
|
||||||
|
register uint32_t __regMainStackPointer __ASM("msp");
|
||||||
|
__regMainStackPointer = topOfMainStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Get Priority Mask
|
||||||
|
\details Returns the current state of the priority mask bit from the Priority Mask Register.
|
||||||
|
\return Priority Mask value
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE uint32_t __get_PRIMASK(void)
|
||||||
|
{
|
||||||
|
register uint32_t __regPriMask __ASM("primask");
|
||||||
|
return(__regPriMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Set Priority Mask
|
||||||
|
\details Assigns the given value to the Priority Mask Register.
|
||||||
|
\param [in] priMask Priority Mask
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void __set_PRIMASK(uint32_t priMask)
|
||||||
|
{
|
||||||
|
register uint32_t __regPriMask __ASM("primask");
|
||||||
|
__regPriMask = (priMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
|
||||||
|
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Enable FIQ
|
||||||
|
\details Enables FIQ interrupts by clearing the F-bit in the CPSR.
|
||||||
|
Can only be executed in Privileged modes.
|
||||||
|
*/
|
||||||
|
#define __enable_fault_irq __enable_fiq
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Disable FIQ
|
||||||
|
\details Disables FIQ interrupts by setting the F-bit in the CPSR.
|
||||||
|
Can only be executed in Privileged modes.
|
||||||
|
*/
|
||||||
|
#define __disable_fault_irq __disable_fiq
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Get Base Priority
|
||||||
|
\details Returns the current value of the Base Priority register.
|
||||||
|
\return Base Priority register value
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE uint32_t __get_BASEPRI(void)
|
||||||
|
{
|
||||||
|
register uint32_t __regBasePri __ASM("basepri");
|
||||||
|
return(__regBasePri);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Set Base Priority
|
||||||
|
\details Assigns the given value to the Base Priority register.
|
||||||
|
\param [in] basePri Base Priority value to set
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void __set_BASEPRI(uint32_t basePri)
|
||||||
|
{
|
||||||
|
register uint32_t __regBasePri __ASM("basepri");
|
||||||
|
__regBasePri = (basePri & 0xFFU);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Set Base Priority with condition
|
||||||
|
\details Assigns the given value to the Base Priority register only if BASEPRI masking is disabled,
|
||||||
|
or the new value increases the BASEPRI priority level.
|
||||||
|
\param [in] basePri Base Priority value to set
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void __set_BASEPRI_MAX(uint32_t basePri)
|
||||||
|
{
|
||||||
|
register uint32_t __regBasePriMax __ASM("basepri_max");
|
||||||
|
__regBasePriMax = (basePri & 0xFFU);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Get Fault Mask
|
||||||
|
\details Returns the current value of the Fault Mask register.
|
||||||
|
\return Fault Mask register value
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE uint32_t __get_FAULTMASK(void)
|
||||||
|
{
|
||||||
|
register uint32_t __regFaultMask __ASM("faultmask");
|
||||||
|
return(__regFaultMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Set Fault Mask
|
||||||
|
\details Assigns the given value to the Fault Mask register.
|
||||||
|
\param [in] faultMask Fault Mask value to set
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void __set_FAULTMASK(uint32_t faultMask)
|
||||||
|
{
|
||||||
|
register uint32_t __regFaultMask __ASM("faultmask");
|
||||||
|
__regFaultMask = (faultMask & (uint32_t)1U);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
|
||||||
|
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Get FPSCR
|
||||||
|
\details Returns the current value of the Floating Point Status/Control register.
|
||||||
|
\return Floating Point Status/Control register value
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE uint32_t __get_FPSCR(void)
|
||||||
|
{
|
||||||
|
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
|
||||||
|
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
|
||||||
|
register uint32_t __regfpscr __ASM("fpscr");
|
||||||
|
return(__regfpscr);
|
||||||
|
#else
|
||||||
|
return(0U);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Set FPSCR
|
||||||
|
\details Assigns the given value to the Floating Point Status/Control register.
|
||||||
|
\param [in] fpscr Floating Point Status/Control value to set
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void __set_FPSCR(uint32_t fpscr)
|
||||||
|
{
|
||||||
|
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
|
||||||
|
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
|
||||||
|
register uint32_t __regfpscr __ASM("fpscr");
|
||||||
|
__regfpscr = (fpscr);
|
||||||
|
#else
|
||||||
|
(void)fpscr;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*@} end of CMSIS_Core_RegAccFunctions */
|
||||||
|
|
||||||
|
|
||||||
|
/* ########################## Core Instruction Access ######################### */
|
||||||
|
/** \defgroup CMSIS_Core_InstructionInterface CMSIS Core Instruction Interface
|
||||||
|
Access to dedicated instructions
|
||||||
|
@{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief No Operation
|
||||||
|
\details No Operation does nothing. This instruction can be used for code alignment purposes.
|
||||||
|
*/
|
||||||
|
#define __NOP __nop
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Wait For Interrupt
|
||||||
|
\details Wait For Interrupt is a hint instruction that suspends execution until one of a number of events occurs.
|
||||||
|
*/
|
||||||
|
#define __WFI __wfi
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Wait For Event
|
||||||
|
\details Wait For Event is a hint instruction that permits the processor to enter
|
||||||
|
a low-power state until one of a number of events occurs.
|
||||||
|
*/
|
||||||
|
#define __WFE __wfe
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Send Event
|
||||||
|
\details Send Event is a hint instruction. It causes an event to be signaled to the CPU.
|
||||||
|
*/
|
||||||
|
#define __SEV __sev
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Instruction Synchronization Barrier
|
||||||
|
\details Instruction Synchronization Barrier flushes the pipeline in the processor,
|
||||||
|
so that all instructions following the ISB are fetched from cache or memory,
|
||||||
|
after the instruction has been completed.
|
||||||
|
*/
|
||||||
|
#define __ISB() __isb(0xF)
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Data Synchronization Barrier
|
||||||
|
\details Acts as a special kind of Data Memory Barrier.
|
||||||
|
It completes when all explicit memory accesses before this instruction complete.
|
||||||
|
*/
|
||||||
|
#define __DSB() __dsb(0xF)
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Data Memory Barrier
|
||||||
|
\details Ensures the apparent order of the explicit memory operations before
|
||||||
|
and after the instruction, without ensuring their completion.
|
||||||
|
*/
|
||||||
|
#define __DMB() __dmb(0xF)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Reverse byte order (32 bit)
|
||||||
|
\details Reverses the byte order in unsigned integer value. For example, 0x12345678 becomes 0x78563412.
|
||||||
|
\param [in] value Value to reverse
|
||||||
|
\return Reversed value
|
||||||
|
*/
|
||||||
|
#define __REV __rev
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Reverse byte order (16 bit)
|
||||||
|
\details Reverses the byte order within each halfword of a word. For example, 0x12345678 becomes 0x34127856.
|
||||||
|
\param [in] value Value to reverse
|
||||||
|
\return Reversed value
|
||||||
|
*/
|
||||||
|
#ifndef __NO_EMBEDDED_ASM
|
||||||
|
__attribute__((section(".rev16_text"))) __STATIC_INLINE __ASM uint32_t __REV16(uint32_t value)
|
||||||
|
{
|
||||||
|
rev16 r0, r0
|
||||||
|
bx lr
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Reverse byte order (16 bit)
|
||||||
|
\details Reverses the byte order in a 16-bit value and returns the signed 16-bit result. For example, 0x0080 becomes 0x8000.
|
||||||
|
\param [in] value Value to reverse
|
||||||
|
\return Reversed value
|
||||||
|
*/
|
||||||
|
#ifndef __NO_EMBEDDED_ASM
|
||||||
|
__attribute__((section(".revsh_text"))) __STATIC_INLINE __ASM int16_t __REVSH(int16_t value)
|
||||||
|
{
|
||||||
|
revsh r0, r0
|
||||||
|
bx lr
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Rotate Right in unsigned value (32 bit)
|
||||||
|
\details Rotate Right (immediate) provides the value of the contents of a register rotated by a variable number of bits.
|
||||||
|
\param [in] op1 Value to rotate
|
||||||
|
\param [in] op2 Number of Bits to rotate
|
||||||
|
\return Rotated value
|
||||||
|
*/
|
||||||
|
#define __ROR __ror
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Breakpoint
|
||||||
|
\details Causes the processor to enter Debug state.
|
||||||
|
Debug tools can use this to investigate system state when the instruction at a particular address is reached.
|
||||||
|
\param [in] value is ignored by the processor.
|
||||||
|
If required, a debugger can use it to store additional information about the breakpoint.
|
||||||
|
*/
|
||||||
|
#define __BKPT(value) __breakpoint(value)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Reverse bit order of value
|
||||||
|
\details Reverses the bit order of the given value.
|
||||||
|
\param [in] value Value to reverse
|
||||||
|
\return Reversed value
|
||||||
|
*/
|
||||||
|
#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
|
||||||
|
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
|
||||||
|
#define __RBIT __rbit
|
||||||
|
#else
|
||||||
|
__attribute__((always_inline)) __STATIC_INLINE uint32_t __RBIT(uint32_t value)
|
||||||
|
{
|
||||||
|
uint32_t result;
|
||||||
|
uint32_t s = (4U /*sizeof(v)*/ * 8U) - 1U; /* extra shift needed at end */
|
||||||
|
|
||||||
|
result = value; /* r will be reversed bits of v; first get LSB of v */
|
||||||
|
for (value >>= 1U; value != 0U; value >>= 1U)
|
||||||
|
{
|
||||||
|
result <<= 1U;
|
||||||
|
result |= value & 1U;
|
||||||
|
s--;
|
||||||
|
}
|
||||||
|
result <<= s; /* shift when v's highest bits are zero */
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Count leading zeros
|
||||||
|
\details Counts the number of leading zeros of a data value.
|
||||||
|
\param [in] value Value to count the leading zeros
|
||||||
|
\return number of leading zeros in value
|
||||||
|
*/
|
||||||
|
#define __CLZ __clz
|
||||||
|
|
||||||
|
|
||||||
|
#if ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
|
||||||
|
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief LDR Exclusive (8 bit)
|
||||||
|
\details Executes a exclusive LDR instruction for 8 bit value.
|
||||||
|
\param [in] ptr Pointer to data
|
||||||
|
\return value of type uint8_t at (*ptr)
|
||||||
|
*/
|
||||||
|
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||||
|
#define __LDREXB(ptr) ((uint8_t ) __ldrex(ptr))
|
||||||
|
#else
|
||||||
|
#define __LDREXB(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint8_t ) __ldrex(ptr)) _Pragma("pop")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief LDR Exclusive (16 bit)
|
||||||
|
\details Executes a exclusive LDR instruction for 16 bit values.
|
||||||
|
\param [in] ptr Pointer to data
|
||||||
|
\return value of type uint16_t at (*ptr)
|
||||||
|
*/
|
||||||
|
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||||
|
#define __LDREXH(ptr) ((uint16_t) __ldrex(ptr))
|
||||||
|
#else
|
||||||
|
#define __LDREXH(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint16_t) __ldrex(ptr)) _Pragma("pop")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief LDR Exclusive (32 bit)
|
||||||
|
\details Executes a exclusive LDR instruction for 32 bit values.
|
||||||
|
\param [in] ptr Pointer to data
|
||||||
|
\return value of type uint32_t at (*ptr)
|
||||||
|
*/
|
||||||
|
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||||
|
#define __LDREXW(ptr) ((uint32_t ) __ldrex(ptr))
|
||||||
|
#else
|
||||||
|
#define __LDREXW(ptr) _Pragma("push") _Pragma("diag_suppress 3731") ((uint32_t ) __ldrex(ptr)) _Pragma("pop")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief STR Exclusive (8 bit)
|
||||||
|
\details Executes a exclusive STR instruction for 8 bit values.
|
||||||
|
\param [in] value Value to store
|
||||||
|
\param [in] ptr Pointer to location
|
||||||
|
\return 0 Function succeeded
|
||||||
|
\return 1 Function failed
|
||||||
|
*/
|
||||||
|
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||||
|
#define __STREXB(value, ptr) __strex(value, ptr)
|
||||||
|
#else
|
||||||
|
#define __STREXB(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief STR Exclusive (16 bit)
|
||||||
|
\details Executes a exclusive STR instruction for 16 bit values.
|
||||||
|
\param [in] value Value to store
|
||||||
|
\param [in] ptr Pointer to location
|
||||||
|
\return 0 Function succeeded
|
||||||
|
\return 1 Function failed
|
||||||
|
*/
|
||||||
|
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||||
|
#define __STREXH(value, ptr) __strex(value, ptr)
|
||||||
|
#else
|
||||||
|
#define __STREXH(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief STR Exclusive (32 bit)
|
||||||
|
\details Executes a exclusive STR instruction for 32 bit values.
|
||||||
|
\param [in] value Value to store
|
||||||
|
\param [in] ptr Pointer to location
|
||||||
|
\return 0 Function succeeded
|
||||||
|
\return 1 Function failed
|
||||||
|
*/
|
||||||
|
#if defined(__ARMCC_VERSION) && (__ARMCC_VERSION < 5060020)
|
||||||
|
#define __STREXW(value, ptr) __strex(value, ptr)
|
||||||
|
#else
|
||||||
|
#define __STREXW(value, ptr) _Pragma("push") _Pragma("diag_suppress 3731") __strex(value, ptr) _Pragma("pop")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Remove the exclusive lock
|
||||||
|
\details Removes the exclusive lock which is created by LDREX.
|
||||||
|
*/
|
||||||
|
#define __CLREX __clrex
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Signed Saturate
|
||||||
|
\details Saturates a signed value.
|
||||||
|
\param [in] value Value to be saturated
|
||||||
|
\param [in] sat Bit position to saturate to (1..32)
|
||||||
|
\return Saturated value
|
||||||
|
*/
|
||||||
|
#define __SSAT __ssat
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Unsigned Saturate
|
||||||
|
\details Saturates an unsigned value.
|
||||||
|
\param [in] value Value to be saturated
|
||||||
|
\param [in] sat Bit position to saturate to (0..31)
|
||||||
|
\return Saturated value
|
||||||
|
*/
|
||||||
|
#define __USAT __usat
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Rotate Right with Extend (32 bit)
|
||||||
|
\details Moves each bit of a bitstring right by one bit.
|
||||||
|
The carry input is shifted in at the left end of the bitstring.
|
||||||
|
\param [in] value Value to rotate
|
||||||
|
\return Rotated value
|
||||||
|
*/
|
||||||
|
#ifndef __NO_EMBEDDED_ASM
|
||||||
|
__attribute__((section(".rrx_text"))) __STATIC_INLINE __ASM uint32_t __RRX(uint32_t value)
|
||||||
|
{
|
||||||
|
rrx r0, r0
|
||||||
|
bx lr
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief LDRT Unprivileged (8 bit)
|
||||||
|
\details Executes a Unprivileged LDRT instruction for 8 bit value.
|
||||||
|
\param [in] ptr Pointer to data
|
||||||
|
\return value of type uint8_t at (*ptr)
|
||||||
|
*/
|
||||||
|
#define __LDRBT(ptr) ((uint8_t ) __ldrt(ptr))
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief LDRT Unprivileged (16 bit)
|
||||||
|
\details Executes a Unprivileged LDRT instruction for 16 bit values.
|
||||||
|
\param [in] ptr Pointer to data
|
||||||
|
\return value of type uint16_t at (*ptr)
|
||||||
|
*/
|
||||||
|
#define __LDRHT(ptr) ((uint16_t) __ldrt(ptr))
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief LDRT Unprivileged (32 bit)
|
||||||
|
\details Executes a Unprivileged LDRT instruction for 32 bit values.
|
||||||
|
\param [in] ptr Pointer to data
|
||||||
|
\return value of type uint32_t at (*ptr)
|
||||||
|
*/
|
||||||
|
#define __LDRT(ptr) ((uint32_t ) __ldrt(ptr))
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief STRT Unprivileged (8 bit)
|
||||||
|
\details Executes a Unprivileged STRT instruction for 8 bit values.
|
||||||
|
\param [in] value Value to store
|
||||||
|
\param [in] ptr Pointer to location
|
||||||
|
*/
|
||||||
|
#define __STRBT(value, ptr) __strt(value, ptr)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief STRT Unprivileged (16 bit)
|
||||||
|
\details Executes a Unprivileged STRT instruction for 16 bit values.
|
||||||
|
\param [in] value Value to store
|
||||||
|
\param [in] ptr Pointer to location
|
||||||
|
*/
|
||||||
|
#define __STRHT(value, ptr) __strt(value, ptr)
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief STRT Unprivileged (32 bit)
|
||||||
|
\details Executes a Unprivileged STRT instruction for 32 bit values.
|
||||||
|
\param [in] value Value to store
|
||||||
|
\param [in] ptr Pointer to location
|
||||||
|
*/
|
||||||
|
#define __STRT(value, ptr) __strt(value, ptr)
|
||||||
|
|
||||||
|
#else /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
|
||||||
|
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Signed Saturate
|
||||||
|
\details Saturates a signed value.
|
||||||
|
\param [in] value Value to be saturated
|
||||||
|
\param [in] sat Bit position to saturate to (1..32)
|
||||||
|
\return Saturated value
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline)) __STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat)
|
||||||
|
{
|
||||||
|
if ((sat >= 1U) && (sat <= 32U))
|
||||||
|
{
|
||||||
|
const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
|
||||||
|
const int32_t min = -1 - max ;
|
||||||
|
if (val > max)
|
||||||
|
{
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
else if (val < min)
|
||||||
|
{
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Unsigned Saturate
|
||||||
|
\details Saturates an unsigned value.
|
||||||
|
\param [in] value Value to be saturated
|
||||||
|
\param [in] sat Bit position to saturate to (0..31)
|
||||||
|
\return Saturated value
|
||||||
|
*/
|
||||||
|
__attribute__((always_inline)) __STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat)
|
||||||
|
{
|
||||||
|
if (sat <= 31U)
|
||||||
|
{
|
||||||
|
const uint32_t max = ((1U << sat) - 1U);
|
||||||
|
if (val > (int32_t)max)
|
||||||
|
{
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
else if (val < 0)
|
||||||
|
{
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (uint32_t)val;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ((defined (__ARM_ARCH_7M__ ) && (__ARM_ARCH_7M__ == 1)) || \
|
||||||
|
(defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
|
||||||
|
|
||||||
|
/*@}*/ /* end of group CMSIS_Core_InstructionInterface */
|
||||||
|
|
||||||
|
|
||||||
|
/* ################### Compiler specific Intrinsics ########################### */
|
||||||
|
/** \defgroup CMSIS_SIMD_intrinsics CMSIS SIMD Intrinsics
|
||||||
|
Access to dedicated SIMD instructions
|
||||||
|
@{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) )
|
||||||
|
|
||||||
|
#define __SADD8 __sadd8
|
||||||
|
#define __QADD8 __qadd8
|
||||||
|
#define __SHADD8 __shadd8
|
||||||
|
#define __UADD8 __uadd8
|
||||||
|
#define __UQADD8 __uqadd8
|
||||||
|
#define __UHADD8 __uhadd8
|
||||||
|
#define __SSUB8 __ssub8
|
||||||
|
#define __QSUB8 __qsub8
|
||||||
|
#define __SHSUB8 __shsub8
|
||||||
|
#define __USUB8 __usub8
|
||||||
|
#define __UQSUB8 __uqsub8
|
||||||
|
#define __UHSUB8 __uhsub8
|
||||||
|
#define __SADD16 __sadd16
|
||||||
|
#define __QADD16 __qadd16
|
||||||
|
#define __SHADD16 __shadd16
|
||||||
|
#define __UADD16 __uadd16
|
||||||
|
#define __UQADD16 __uqadd16
|
||||||
|
#define __UHADD16 __uhadd16
|
||||||
|
#define __SSUB16 __ssub16
|
||||||
|
#define __QSUB16 __qsub16
|
||||||
|
#define __SHSUB16 __shsub16
|
||||||
|
#define __USUB16 __usub16
|
||||||
|
#define __UQSUB16 __uqsub16
|
||||||
|
#define __UHSUB16 __uhsub16
|
||||||
|
#define __SASX __sasx
|
||||||
|
#define __QASX __qasx
|
||||||
|
#define __SHASX __shasx
|
||||||
|
#define __UASX __uasx
|
||||||
|
#define __UQASX __uqasx
|
||||||
|
#define __UHASX __uhasx
|
||||||
|
#define __SSAX __ssax
|
||||||
|
#define __QSAX __qsax
|
||||||
|
#define __SHSAX __shsax
|
||||||
|
#define __USAX __usax
|
||||||
|
#define __UQSAX __uqsax
|
||||||
|
#define __UHSAX __uhsax
|
||||||
|
#define __USAD8 __usad8
|
||||||
|
#define __USADA8 __usada8
|
||||||
|
#define __SSAT16 __ssat16
|
||||||
|
#define __USAT16 __usat16
|
||||||
|
#define __UXTB16 __uxtb16
|
||||||
|
#define __UXTAB16 __uxtab16
|
||||||
|
#define __SXTB16 __sxtb16
|
||||||
|
#define __SXTAB16 __sxtab16
|
||||||
|
#define __SMUAD __smuad
|
||||||
|
#define __SMUADX __smuadx
|
||||||
|
#define __SMLAD __smlad
|
||||||
|
#define __SMLADX __smladx
|
||||||
|
#define __SMLALD __smlald
|
||||||
|
#define __SMLALDX __smlaldx
|
||||||
|
#define __SMUSD __smusd
|
||||||
|
#define __SMUSDX __smusdx
|
||||||
|
#define __SMLSD __smlsd
|
||||||
|
#define __SMLSDX __smlsdx
|
||||||
|
#define __SMLSLD __smlsld
|
||||||
|
#define __SMLSLDX __smlsldx
|
||||||
|
#define __SEL __sel
|
||||||
|
#define __QADD __qadd
|
||||||
|
#define __QSUB __qsub
|
||||||
|
|
||||||
|
#define __PKHBT(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0x0000FFFFUL) | \
|
||||||
|
((((uint32_t)(ARG2)) << (ARG3)) & 0xFFFF0000UL) )
|
||||||
|
|
||||||
|
#define __PKHTB(ARG1,ARG2,ARG3) ( ((((uint32_t)(ARG1)) ) & 0xFFFF0000UL) | \
|
||||||
|
((((uint32_t)(ARG2)) >> (ARG3)) & 0x0000FFFFUL) )
|
||||||
|
|
||||||
|
#define __SMMLA(ARG1,ARG2,ARG3) ( (int32_t)((((int64_t)(ARG1) * (ARG2)) + \
|
||||||
|
((int64_t)(ARG3) << 32U) ) >> 32U))
|
||||||
|
|
||||||
|
#define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2))
|
||||||
|
|
||||||
|
#endif /* ((defined (__ARM_ARCH_7EM__) && (__ARM_ARCH_7EM__ == 1)) ) */
|
||||||
|
/*@} end of group CMSIS_SIMD_intrinsics */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __CMSIS_ARMCC_H */
|
1467
src/rp2_common/cmsis/stub/CMSIS/Core/Include/cmsis_armclang.h
Normal file
1467
src/rp2_common/cmsis/stub/CMSIS/Core/Include/cmsis_armclang.h
Normal file
File diff suppressed because it is too large
Load Diff
1893
src/rp2_common/cmsis/stub/CMSIS/Core/Include/cmsis_armclang_ltm.h
Normal file
1893
src/rp2_common/cmsis/stub/CMSIS/Core/Include/cmsis_armclang_ltm.h
Normal file
File diff suppressed because it is too large
Load Diff
283
src/rp2_common/cmsis/stub/CMSIS/Core/Include/cmsis_compiler.h
Normal file
283
src/rp2_common/cmsis/stub/CMSIS/Core/Include/cmsis_compiler.h
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
/**************************************************************************//**
|
||||||
|
* @file cmsis_compiler.h
|
||||||
|
* @brief CMSIS compiler generic header file
|
||||||
|
* @version V5.1.0
|
||||||
|
* @date 09. October 2018
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2018 Arm Limited. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CMSIS_COMPILER_H
|
||||||
|
#define __CMSIS_COMPILER_H
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arm Compiler 4/5
|
||||||
|
*/
|
||||||
|
#if defined ( __CC_ARM )
|
||||||
|
#include "cmsis_armcc.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arm Compiler 6.6 LTM (armclang)
|
||||||
|
*/
|
||||||
|
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) && (__ARMCC_VERSION < 6100100)
|
||||||
|
#include "cmsis_armclang_ltm.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Arm Compiler above 6.10.1 (armclang)
|
||||||
|
*/
|
||||||
|
#elif defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6100100)
|
||||||
|
#include "cmsis_armclang.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* GNU Compiler
|
||||||
|
*/
|
||||||
|
#elif defined ( __GNUC__ )
|
||||||
|
#include "cmsis_gcc.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IAR Compiler
|
||||||
|
*/
|
||||||
|
#elif defined ( __ICCARM__ )
|
||||||
|
#include <cmsis_iccarm.h>
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TI Arm Compiler
|
||||||
|
*/
|
||||||
|
#elif defined ( __TI_ARM__ )
|
||||||
|
#include <cmsis_ccs.h>
|
||||||
|
|
||||||
|
#ifndef __ASM
|
||||||
|
#define __ASM __asm
|
||||||
|
#endif
|
||||||
|
#ifndef __INLINE
|
||||||
|
#define __INLINE inline
|
||||||
|
#endif
|
||||||
|
#ifndef __STATIC_INLINE
|
||||||
|
#define __STATIC_INLINE static inline
|
||||||
|
#endif
|
||||||
|
#ifndef __STATIC_FORCEINLINE
|
||||||
|
#define __STATIC_FORCEINLINE __STATIC_INLINE
|
||||||
|
#endif
|
||||||
|
#ifndef __NO_RETURN
|
||||||
|
#define __NO_RETURN __attribute__((noreturn))
|
||||||
|
#endif
|
||||||
|
#ifndef __USED
|
||||||
|
#define __USED __attribute__((used))
|
||||||
|
#endif
|
||||||
|
#ifndef __WEAK
|
||||||
|
#define __WEAK __attribute__((weak))
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED
|
||||||
|
#define __PACKED __attribute__((packed))
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED_STRUCT
|
||||||
|
#define __PACKED_STRUCT struct __attribute__((packed))
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED_UNION
|
||||||
|
#define __PACKED_UNION union __attribute__((packed))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT32 /* deprecated */
|
||||||
|
struct __attribute__((packed)) T_UINT32 { uint32_t v; };
|
||||||
|
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT16_WRITE
|
||||||
|
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
|
||||||
|
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void*)(addr))->v) = (val))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT16_READ
|
||||||
|
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
|
||||||
|
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT32_WRITE
|
||||||
|
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
|
||||||
|
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT32_READ
|
||||||
|
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
|
||||||
|
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
|
||||||
|
#endif
|
||||||
|
#ifndef __ALIGNED
|
||||||
|
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||||
|
#endif
|
||||||
|
#ifndef __RESTRICT
|
||||||
|
#define __RESTRICT __restrict
|
||||||
|
#endif
|
||||||
|
#ifndef __COMPILER_BARRIER
|
||||||
|
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
|
||||||
|
#define __COMPILER_BARRIER() (void)0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TASKING Compiler
|
||||||
|
*/
|
||||||
|
#elif defined ( __TASKING__ )
|
||||||
|
/*
|
||||||
|
* The CMSIS functions have been implemented as intrinsics in the compiler.
|
||||||
|
* Please use "carm -?i" to get an up to date list of all intrinsics,
|
||||||
|
* Including the CMSIS ones.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ASM
|
||||||
|
#define __ASM __asm
|
||||||
|
#endif
|
||||||
|
#ifndef __INLINE
|
||||||
|
#define __INLINE inline
|
||||||
|
#endif
|
||||||
|
#ifndef __STATIC_INLINE
|
||||||
|
#define __STATIC_INLINE static inline
|
||||||
|
#endif
|
||||||
|
#ifndef __STATIC_FORCEINLINE
|
||||||
|
#define __STATIC_FORCEINLINE __STATIC_INLINE
|
||||||
|
#endif
|
||||||
|
#ifndef __NO_RETURN
|
||||||
|
#define __NO_RETURN __attribute__((noreturn))
|
||||||
|
#endif
|
||||||
|
#ifndef __USED
|
||||||
|
#define __USED __attribute__((used))
|
||||||
|
#endif
|
||||||
|
#ifndef __WEAK
|
||||||
|
#define __WEAK __attribute__((weak))
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED
|
||||||
|
#define __PACKED __packed__
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED_STRUCT
|
||||||
|
#define __PACKED_STRUCT struct __packed__
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED_UNION
|
||||||
|
#define __PACKED_UNION union __packed__
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT32 /* deprecated */
|
||||||
|
struct __packed__ T_UINT32 { uint32_t v; };
|
||||||
|
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT16_WRITE
|
||||||
|
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
|
||||||
|
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT16_READ
|
||||||
|
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
|
||||||
|
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT32_WRITE
|
||||||
|
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
|
||||||
|
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT32_READ
|
||||||
|
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
|
||||||
|
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
|
||||||
|
#endif
|
||||||
|
#ifndef __ALIGNED
|
||||||
|
#define __ALIGNED(x) __align(x)
|
||||||
|
#endif
|
||||||
|
#ifndef __RESTRICT
|
||||||
|
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
|
||||||
|
#define __RESTRICT
|
||||||
|
#endif
|
||||||
|
#ifndef __COMPILER_BARRIER
|
||||||
|
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
|
||||||
|
#define __COMPILER_BARRIER() (void)0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* COSMIC Compiler
|
||||||
|
*/
|
||||||
|
#elif defined ( __CSMC__ )
|
||||||
|
#include <cmsis_csm.h>
|
||||||
|
|
||||||
|
#ifndef __ASM
|
||||||
|
#define __ASM _asm
|
||||||
|
#endif
|
||||||
|
#ifndef __INLINE
|
||||||
|
#define __INLINE inline
|
||||||
|
#endif
|
||||||
|
#ifndef __STATIC_INLINE
|
||||||
|
#define __STATIC_INLINE static inline
|
||||||
|
#endif
|
||||||
|
#ifndef __STATIC_FORCEINLINE
|
||||||
|
#define __STATIC_FORCEINLINE __STATIC_INLINE
|
||||||
|
#endif
|
||||||
|
#ifndef __NO_RETURN
|
||||||
|
// NO RETURN is automatically detected hence no warning here
|
||||||
|
#define __NO_RETURN
|
||||||
|
#endif
|
||||||
|
#ifndef __USED
|
||||||
|
#warning No compiler specific solution for __USED. __USED is ignored.
|
||||||
|
#define __USED
|
||||||
|
#endif
|
||||||
|
#ifndef __WEAK
|
||||||
|
#define __WEAK __weak
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED
|
||||||
|
#define __PACKED @packed
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED_STRUCT
|
||||||
|
#define __PACKED_STRUCT @packed struct
|
||||||
|
#endif
|
||||||
|
#ifndef __PACKED_UNION
|
||||||
|
#define __PACKED_UNION @packed union
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT32 /* deprecated */
|
||||||
|
@packed struct T_UINT32 { uint32_t v; };
|
||||||
|
#define __UNALIGNED_UINT32(x) (((struct T_UINT32 *)(x))->v)
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT16_WRITE
|
||||||
|
__PACKED_STRUCT T_UINT16_WRITE { uint16_t v; };
|
||||||
|
#define __UNALIGNED_UINT16_WRITE(addr, val) (void)((((struct T_UINT16_WRITE *)(void *)(addr))->v) = (val))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT16_READ
|
||||||
|
__PACKED_STRUCT T_UINT16_READ { uint16_t v; };
|
||||||
|
#define __UNALIGNED_UINT16_READ(addr) (((const struct T_UINT16_READ *)(const void *)(addr))->v)
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT32_WRITE
|
||||||
|
__PACKED_STRUCT T_UINT32_WRITE { uint32_t v; };
|
||||||
|
#define __UNALIGNED_UINT32_WRITE(addr, val) (void)((((struct T_UINT32_WRITE *)(void *)(addr))->v) = (val))
|
||||||
|
#endif
|
||||||
|
#ifndef __UNALIGNED_UINT32_READ
|
||||||
|
__PACKED_STRUCT T_UINT32_READ { uint32_t v; };
|
||||||
|
#define __UNALIGNED_UINT32_READ(addr) (((const struct T_UINT32_READ *)(const void *)(addr))->v)
|
||||||
|
#endif
|
||||||
|
#ifndef __ALIGNED
|
||||||
|
#warning No compiler specific solution for __ALIGNED. __ALIGNED is ignored.
|
||||||
|
#define __ALIGNED(x)
|
||||||
|
#endif
|
||||||
|
#ifndef __RESTRICT
|
||||||
|
#warning No compiler specific solution for __RESTRICT. __RESTRICT is ignored.
|
||||||
|
#define __RESTRICT
|
||||||
|
#endif
|
||||||
|
#ifndef __COMPILER_BARRIER
|
||||||
|
#warning No compiler specific solution for __COMPILER_BARRIER. __COMPILER_BARRIER is ignored.
|
||||||
|
#define __COMPILER_BARRIER() (void)0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#else
|
||||||
|
#error Unknown compiler.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __CMSIS_COMPILER_H */
|
||||||
|
|
2177
src/rp2_common/cmsis/stub/CMSIS/Core/Include/cmsis_gcc.h
Normal file
2177
src/rp2_common/cmsis/stub/CMSIS/Core/Include/cmsis_gcc.h
Normal file
File diff suppressed because it is too large
Load Diff
968
src/rp2_common/cmsis/stub/CMSIS/Core/Include/cmsis_iccarm.h
Normal file
968
src/rp2_common/cmsis/stub/CMSIS/Core/Include/cmsis_iccarm.h
Normal file
@ -0,0 +1,968 @@
|
|||||||
|
/**************************************************************************//**
|
||||||
|
* @file cmsis_iccarm.h
|
||||||
|
* @brief CMSIS compiler ICCARM (IAR Compiler for Arm) header file
|
||||||
|
* @version V5.2.0
|
||||||
|
* @date 28. January 2020
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
//
|
||||||
|
// Copyright (c) 2017-2019 IAR Systems
|
||||||
|
// Copyright (c) 2017-2019 Arm Limited. All rights reserved.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License")
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
//
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __CMSIS_ICCARM_H__
|
||||||
|
#define __CMSIS_ICCARM_H__
|
||||||
|
|
||||||
|
#ifndef __ICCARM__
|
||||||
|
#error This file should only be compiled by ICCARM
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma system_include
|
||||||
|
|
||||||
|
#define __IAR_FT _Pragma("inline=forced") __intrinsic
|
||||||
|
|
||||||
|
#if (__VER__ >= 8000000)
|
||||||
|
#define __ICCARM_V8 1
|
||||||
|
#else
|
||||||
|
#define __ICCARM_V8 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ALIGNED
|
||||||
|
#if __ICCARM_V8
|
||||||
|
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||||
|
#elif (__VER__ >= 7080000)
|
||||||
|
/* Needs IAR language extensions */
|
||||||
|
#define __ALIGNED(x) __attribute__((aligned(x)))
|
||||||
|
#else
|
||||||
|
#warning No compiler specific solution for __ALIGNED.__ALIGNED is ignored.
|
||||||
|
#define __ALIGNED(x)
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Define compiler macros for CPU architecture, used in CMSIS 5.
|
||||||
|
*/
|
||||||
|
#if __ARM_ARCH_6M__ || __ARM_ARCH_7M__ || __ARM_ARCH_7EM__ || __ARM_ARCH_8M_BASE__ || __ARM_ARCH_8M_MAIN__
|
||||||
|
/* Macros already defined */
|
||||||
|
#else
|
||||||
|
#if defined(__ARM8M_MAINLINE__) || defined(__ARM8EM_MAINLINE__)
|
||||||
|
#define __ARM_ARCH_8M_MAIN__ 1
|
||||||
|
#elif defined(__ARM8M_BASELINE__)
|
||||||
|
#define __ARM_ARCH_8M_BASE__ 1
|
||||||
|
#elif defined(__ARM_ARCH_PROFILE) && __ARM_ARCH_PROFILE == 'M'
|
||||||
|
#if __ARM_ARCH == 6
|
||||||
|
#define __ARM_ARCH_6M__ 1
|
||||||
|
#elif __ARM_ARCH == 7
|
||||||
|
#if __ARM_FEATURE_DSP
|
||||||
|
#define __ARM_ARCH_7EM__ 1
|
||||||
|
#else
|
||||||
|
#define __ARM_ARCH_7M__ 1
|
||||||
|
#endif
|
||||||
|
#endif /* __ARM_ARCH */
|
||||||
|
#endif /* __ARM_ARCH_PROFILE == 'M' */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Alternativ core deduction for older ICCARM's */
|
||||||
|
#if !defined(__ARM_ARCH_6M__) && !defined(__ARM_ARCH_7M__) && !defined(__ARM_ARCH_7EM__) && \
|
||||||
|
!defined(__ARM_ARCH_8M_BASE__) && !defined(__ARM_ARCH_8M_MAIN__)
|
||||||
|
#if defined(__ARM6M__) && (__CORE__ == __ARM6M__)
|
||||||
|
#define __ARM_ARCH_6M__ 1
|
||||||
|
#elif defined(__ARM7M__) && (__CORE__ == __ARM7M__)
|
||||||
|
#define __ARM_ARCH_7M__ 1
|
||||||
|
#elif defined(__ARM7EM__) && (__CORE__ == __ARM7EM__)
|
||||||
|
#define __ARM_ARCH_7EM__ 1
|
||||||
|
#elif defined(__ARM8M_BASELINE__) && (__CORE == __ARM8M_BASELINE__)
|
||||||
|
#define __ARM_ARCH_8M_BASE__ 1
|
||||||
|
#elif defined(__ARM8M_MAINLINE__) && (__CORE == __ARM8M_MAINLINE__)
|
||||||
|
#define __ARM_ARCH_8M_MAIN__ 1
|
||||||
|
#elif defined(__ARM8EM_MAINLINE__) && (__CORE == __ARM8EM_MAINLINE__)
|
||||||
|
#define __ARM_ARCH_8M_MAIN__ 1
|
||||||
|
#else
|
||||||
|
#error "Unknown target."
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__ARM_ARCH_6M__) && __ARM_ARCH_6M__==1
|
||||||
|
#define __IAR_M0_FAMILY 1
|
||||||
|
#elif defined(__ARM_ARCH_8M_BASE__) && __ARM_ARCH_8M_BASE__==1
|
||||||
|
#define __IAR_M0_FAMILY 1
|
||||||
|
#else
|
||||||
|
#define __IAR_M0_FAMILY 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __ASM
|
||||||
|
#define __ASM __asm
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __COMPILER_BARRIER
|
||||||
|
#define __COMPILER_BARRIER() __ASM volatile("":::"memory")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __INLINE
|
||||||
|
#define __INLINE inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __NO_RETURN
|
||||||
|
#if __ICCARM_V8
|
||||||
|
#define __NO_RETURN __attribute__((__noreturn__))
|
||||||
|
#else
|
||||||
|
#define __NO_RETURN _Pragma("object_attribute=__noreturn")
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __PACKED
|
||||||
|
#if __ICCARM_V8
|
||||||
|
#define __PACKED __attribute__((packed, aligned(1)))
|
||||||
|
#else
|
||||||
|
/* Needs IAR language extensions */
|
||||||
|
#define __PACKED __packed
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __PACKED_STRUCT
|
||||||
|
#if __ICCARM_V8
|
||||||
|
#define __PACKED_STRUCT struct __attribute__((packed, aligned(1)))
|
||||||
|
#else
|
||||||
|
/* Needs IAR language extensions */
|
||||||
|
#define __PACKED_STRUCT __packed struct
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __PACKED_UNION
|
||||||
|
#if __ICCARM_V8
|
||||||
|
#define __PACKED_UNION union __attribute__((packed, aligned(1)))
|
||||||
|
#else
|
||||||
|
/* Needs IAR language extensions */
|
||||||
|
#define __PACKED_UNION __packed union
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __RESTRICT
|
||||||
|
#if __ICCARM_V8
|
||||||
|
#define __RESTRICT __restrict
|
||||||
|
#else
|
||||||
|
/* Needs IAR language extensions */
|
||||||
|
#define __RESTRICT restrict
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __STATIC_INLINE
|
||||||
|
#define __STATIC_INLINE static inline
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __FORCEINLINE
|
||||||
|
#define __FORCEINLINE _Pragma("inline=forced")
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __STATIC_FORCEINLINE
|
||||||
|
#define __STATIC_FORCEINLINE __FORCEINLINE __STATIC_INLINE
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __UNALIGNED_UINT16_READ
|
||||||
|
#pragma language=save
|
||||||
|
#pragma language=extended
|
||||||
|
__IAR_FT uint16_t __iar_uint16_read(void const *ptr)
|
||||||
|
{
|
||||||
|
return *(__packed uint16_t*)(ptr);
|
||||||
|
}
|
||||||
|
#pragma language=restore
|
||||||
|
#define __UNALIGNED_UINT16_READ(PTR) __iar_uint16_read(PTR)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef __UNALIGNED_UINT16_WRITE
|
||||||
|
#pragma language=save
|
||||||
|
#pragma language=extended
|
||||||
|
__IAR_FT void __iar_uint16_write(void const *ptr, uint16_t val)
|
||||||
|
{
|
||||||
|
*(__packed uint16_t*)(ptr) = val;;
|
||||||
|
}
|
||||||
|
#pragma language=restore
|
||||||
|
#define __UNALIGNED_UINT16_WRITE(PTR,VAL) __iar_uint16_write(PTR,VAL)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __UNALIGNED_UINT32_READ
|
||||||
|
#pragma language=save
|
||||||
|
#pragma language=extended
|
||||||
|
__IAR_FT uint32_t __iar_uint32_read(void const *ptr)
|
||||||
|
{
|
||||||
|
return *(__packed uint32_t*)(ptr);
|
||||||
|
}
|
||||||
|
#pragma language=restore
|
||||||
|
#define __UNALIGNED_UINT32_READ(PTR) __iar_uint32_read(PTR)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __UNALIGNED_UINT32_WRITE
|
||||||
|
#pragma language=save
|
||||||
|
#pragma language=extended
|
||||||
|
__IAR_FT void __iar_uint32_write(void const *ptr, uint32_t val)
|
||||||
|
{
|
||||||
|
*(__packed uint32_t*)(ptr) = val;;
|
||||||
|
}
|
||||||
|
#pragma language=restore
|
||||||
|
#define __UNALIGNED_UINT32_WRITE(PTR,VAL) __iar_uint32_write(PTR,VAL)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __UNALIGNED_UINT32 /* deprecated */
|
||||||
|
#pragma language=save
|
||||||
|
#pragma language=extended
|
||||||
|
__packed struct __iar_u32 { uint32_t v; };
|
||||||
|
#pragma language=restore
|
||||||
|
#define __UNALIGNED_UINT32(PTR) (((struct __iar_u32 *)(PTR))->v)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __USED
|
||||||
|
#if __ICCARM_V8
|
||||||
|
#define __USED __attribute__((used))
|
||||||
|
#else
|
||||||
|
#define __USED _Pragma("__root")
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __WEAK
|
||||||
|
#if __ICCARM_V8
|
||||||
|
#define __WEAK __attribute__((weak))
|
||||||
|
#else
|
||||||
|
#define __WEAK _Pragma("__weak")
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __PROGRAM_START
|
||||||
|
#define __PROGRAM_START __iar_program_start
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __INITIAL_SP
|
||||||
|
#define __INITIAL_SP CSTACK$$Limit
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __STACK_LIMIT
|
||||||
|
#define __STACK_LIMIT CSTACK$$Base
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __VECTOR_TABLE
|
||||||
|
#define __VECTOR_TABLE __vector_table
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __VECTOR_TABLE_ATTRIBUTE
|
||||||
|
#define __VECTOR_TABLE_ATTRIBUTE @".intvec"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __ICCARM_INTRINSICS_VERSION__
|
||||||
|
#define __ICCARM_INTRINSICS_VERSION__ 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if __ICCARM_INTRINSICS_VERSION__ == 2
|
||||||
|
|
||||||
|
#if defined(__CLZ)
|
||||||
|
#undef __CLZ
|
||||||
|
#endif
|
||||||
|
#if defined(__REVSH)
|
||||||
|
#undef __REVSH
|
||||||
|
#endif
|
||||||
|
#if defined(__RBIT)
|
||||||
|
#undef __RBIT
|
||||||
|
#endif
|
||||||
|
#if defined(__SSAT)
|
||||||
|
#undef __SSAT
|
||||||
|
#endif
|
||||||
|
#if defined(__USAT)
|
||||||
|
#undef __USAT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "iccarm_builtin.h"
|
||||||
|
|
||||||
|
#define __disable_fault_irq __iar_builtin_disable_fiq
|
||||||
|
#define __disable_irq __iar_builtin_disable_interrupt
|
||||||
|
#define __enable_fault_irq __iar_builtin_enable_fiq
|
||||||
|
#define __enable_irq __iar_builtin_enable_interrupt
|
||||||
|
#define __arm_rsr __iar_builtin_rsr
|
||||||
|
#define __arm_wsr __iar_builtin_wsr
|
||||||
|
|
||||||
|
|
||||||
|
#define __get_APSR() (__arm_rsr("APSR"))
|
||||||
|
#define __get_BASEPRI() (__arm_rsr("BASEPRI"))
|
||||||
|
#define __get_CONTROL() (__arm_rsr("CONTROL"))
|
||||||
|
#define __get_FAULTMASK() (__arm_rsr("FAULTMASK"))
|
||||||
|
|
||||||
|
#if ((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
|
||||||
|
(defined (__FPU_USED ) && (__FPU_USED == 1U)) )
|
||||||
|
#define __get_FPSCR() (__arm_rsr("FPSCR"))
|
||||||
|
#define __set_FPSCR(VALUE) (__arm_wsr("FPSCR", (VALUE)))
|
||||||
|
#else
|
||||||
|
#define __get_FPSCR() ( 0 )
|
||||||
|
#define __set_FPSCR(VALUE) ((void)VALUE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __get_IPSR() (__arm_rsr("IPSR"))
|
||||||
|
#define __get_MSP() (__arm_rsr("MSP"))
|
||||||
|
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||||
|
(!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
|
||||||
|
// without main extensions, the non-secure MSPLIM is RAZ/WI
|
||||||
|
#define __get_MSPLIM() (0U)
|
||||||
|
#else
|
||||||
|
#define __get_MSPLIM() (__arm_rsr("MSPLIM"))
|
||||||
|
#endif
|
||||||
|
#define __get_PRIMASK() (__arm_rsr("PRIMASK"))
|
||||||
|
#define __get_PSP() (__arm_rsr("PSP"))
|
||||||
|
|
||||||
|
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||||
|
(!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
|
||||||
|
// without main extensions, the non-secure PSPLIM is RAZ/WI
|
||||||
|
#define __get_PSPLIM() (0U)
|
||||||
|
#else
|
||||||
|
#define __get_PSPLIM() (__arm_rsr("PSPLIM"))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __get_xPSR() (__arm_rsr("xPSR"))
|
||||||
|
|
||||||
|
#define __set_BASEPRI(VALUE) (__arm_wsr("BASEPRI", (VALUE)))
|
||||||
|
#define __set_BASEPRI_MAX(VALUE) (__arm_wsr("BASEPRI_MAX", (VALUE)))
|
||||||
|
#define __set_CONTROL(VALUE) (__arm_wsr("CONTROL", (VALUE)))
|
||||||
|
#define __set_FAULTMASK(VALUE) (__arm_wsr("FAULTMASK", (VALUE)))
|
||||||
|
#define __set_MSP(VALUE) (__arm_wsr("MSP", (VALUE)))
|
||||||
|
|
||||||
|
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||||
|
(!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
|
||||||
|
// without main extensions, the non-secure MSPLIM is RAZ/WI
|
||||||
|
#define __set_MSPLIM(VALUE) ((void)(VALUE))
|
||||||
|
#else
|
||||||
|
#define __set_MSPLIM(VALUE) (__arm_wsr("MSPLIM", (VALUE)))
|
||||||
|
#endif
|
||||||
|
#define __set_PRIMASK(VALUE) (__arm_wsr("PRIMASK", (VALUE)))
|
||||||
|
#define __set_PSP(VALUE) (__arm_wsr("PSP", (VALUE)))
|
||||||
|
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||||
|
(!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
|
||||||
|
// without main extensions, the non-secure PSPLIM is RAZ/WI
|
||||||
|
#define __set_PSPLIM(VALUE) ((void)(VALUE))
|
||||||
|
#else
|
||||||
|
#define __set_PSPLIM(VALUE) (__arm_wsr("PSPLIM", (VALUE)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __TZ_get_CONTROL_NS() (__arm_rsr("CONTROL_NS"))
|
||||||
|
#define __TZ_set_CONTROL_NS(VALUE) (__arm_wsr("CONTROL_NS", (VALUE)))
|
||||||
|
#define __TZ_get_PSP_NS() (__arm_rsr("PSP_NS"))
|
||||||
|
#define __TZ_set_PSP_NS(VALUE) (__arm_wsr("PSP_NS", (VALUE)))
|
||||||
|
#define __TZ_get_MSP_NS() (__arm_rsr("MSP_NS"))
|
||||||
|
#define __TZ_set_MSP_NS(VALUE) (__arm_wsr("MSP_NS", (VALUE)))
|
||||||
|
#define __TZ_get_SP_NS() (__arm_rsr("SP_NS"))
|
||||||
|
#define __TZ_set_SP_NS(VALUE) (__arm_wsr("SP_NS", (VALUE)))
|
||||||
|
#define __TZ_get_PRIMASK_NS() (__arm_rsr("PRIMASK_NS"))
|
||||||
|
#define __TZ_set_PRIMASK_NS(VALUE) (__arm_wsr("PRIMASK_NS", (VALUE)))
|
||||||
|
#define __TZ_get_BASEPRI_NS() (__arm_rsr("BASEPRI_NS"))
|
||||||
|
#define __TZ_set_BASEPRI_NS(VALUE) (__arm_wsr("BASEPRI_NS", (VALUE)))
|
||||||
|
#define __TZ_get_FAULTMASK_NS() (__arm_rsr("FAULTMASK_NS"))
|
||||||
|
#define __TZ_set_FAULTMASK_NS(VALUE)(__arm_wsr("FAULTMASK_NS", (VALUE)))
|
||||||
|
|
||||||
|
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||||
|
(!defined (__ARM_FEATURE_CMSE) || (__ARM_FEATURE_CMSE < 3)))
|
||||||
|
// without main extensions, the non-secure PSPLIM is RAZ/WI
|
||||||
|
#define __TZ_get_PSPLIM_NS() (0U)
|
||||||
|
#define __TZ_set_PSPLIM_NS(VALUE) ((void)(VALUE))
|
||||||
|
#else
|
||||||
|
#define __TZ_get_PSPLIM_NS() (__arm_rsr("PSPLIM_NS"))
|
||||||
|
#define __TZ_set_PSPLIM_NS(VALUE) (__arm_wsr("PSPLIM_NS", (VALUE)))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __TZ_get_MSPLIM_NS() (__arm_rsr("MSPLIM_NS"))
|
||||||
|
#define __TZ_set_MSPLIM_NS(VALUE) (__arm_wsr("MSPLIM_NS", (VALUE)))
|
||||||
|
|
||||||
|
#define __NOP __iar_builtin_no_operation
|
||||||
|
|
||||||
|
#define __CLZ __iar_builtin_CLZ
|
||||||
|
#define __CLREX __iar_builtin_CLREX
|
||||||
|
|
||||||
|
#define __DMB __iar_builtin_DMB
|
||||||
|
#define __DSB __iar_builtin_DSB
|
||||||
|
#define __ISB __iar_builtin_ISB
|
||||||
|
|
||||||
|
#define __LDREXB __iar_builtin_LDREXB
|
||||||
|
#define __LDREXH __iar_builtin_LDREXH
|
||||||
|
#define __LDREXW __iar_builtin_LDREX
|
||||||
|
|
||||||
|
#define __RBIT __iar_builtin_RBIT
|
||||||
|
#define __REV __iar_builtin_REV
|
||||||
|
#define __REV16 __iar_builtin_REV16
|
||||||
|
|
||||||
|
__IAR_FT int16_t __REVSH(int16_t val)
|
||||||
|
{
|
||||||
|
return (int16_t) __iar_builtin_REVSH(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define __ROR __iar_builtin_ROR
|
||||||
|
#define __RRX __iar_builtin_RRX
|
||||||
|
|
||||||
|
#define __SEV __iar_builtin_SEV
|
||||||
|
|
||||||
|
#if !__IAR_M0_FAMILY
|
||||||
|
#define __SSAT __iar_builtin_SSAT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __STREXB __iar_builtin_STREXB
|
||||||
|
#define __STREXH __iar_builtin_STREXH
|
||||||
|
#define __STREXW __iar_builtin_STREX
|
||||||
|
|
||||||
|
#if !__IAR_M0_FAMILY
|
||||||
|
#define __USAT __iar_builtin_USAT
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define __WFE __iar_builtin_WFE
|
||||||
|
#define __WFI __iar_builtin_WFI
|
||||||
|
|
||||||
|
#if __ARM_MEDIA__
|
||||||
|
#define __SADD8 __iar_builtin_SADD8
|
||||||
|
#define __QADD8 __iar_builtin_QADD8
|
||||||
|
#define __SHADD8 __iar_builtin_SHADD8
|
||||||
|
#define __UADD8 __iar_builtin_UADD8
|
||||||
|
#define __UQADD8 __iar_builtin_UQADD8
|
||||||
|
#define __UHADD8 __iar_builtin_UHADD8
|
||||||
|
#define __SSUB8 __iar_builtin_SSUB8
|
||||||
|
#define __QSUB8 __iar_builtin_QSUB8
|
||||||
|
#define __SHSUB8 __iar_builtin_SHSUB8
|
||||||
|
#define __USUB8 __iar_builtin_USUB8
|
||||||
|
#define __UQSUB8 __iar_builtin_UQSUB8
|
||||||
|
#define __UHSUB8 __iar_builtin_UHSUB8
|
||||||
|
#define __SADD16 __iar_builtin_SADD16
|
||||||
|
#define __QADD16 __iar_builtin_QADD16
|
||||||
|
#define __SHADD16 __iar_builtin_SHADD16
|
||||||
|
#define __UADD16 __iar_builtin_UADD16
|
||||||
|
#define __UQADD16 __iar_builtin_UQADD16
|
||||||
|
#define __UHADD16 __iar_builtin_UHADD16
|
||||||
|
#define __SSUB16 __iar_builtin_SSUB16
|
||||||
|
#define __QSUB16 __iar_builtin_QSUB16
|
||||||
|
#define __SHSUB16 __iar_builtin_SHSUB16
|
||||||
|
#define __USUB16 __iar_builtin_USUB16
|
||||||
|
#define __UQSUB16 __iar_builtin_UQSUB16
|
||||||
|
#define __UHSUB16 __iar_builtin_UHSUB16
|
||||||
|
#define __SASX __iar_builtin_SASX
|
||||||
|
#define __QASX __iar_builtin_QASX
|
||||||
|
#define __SHASX __iar_builtin_SHASX
|
||||||
|
#define __UASX __iar_builtin_UASX
|
||||||
|
#define __UQASX __iar_builtin_UQASX
|
||||||
|
#define __UHASX __iar_builtin_UHASX
|
||||||
|
#define __SSAX __iar_builtin_SSAX
|
||||||
|
#define __QSAX __iar_builtin_QSAX
|
||||||
|
#define __SHSAX __iar_builtin_SHSAX
|
||||||
|
#define __USAX __iar_builtin_USAX
|
||||||
|
#define __UQSAX __iar_builtin_UQSAX
|
||||||
|
#define __UHSAX __iar_builtin_UHSAX
|
||||||
|
#define __USAD8 __iar_builtin_USAD8
|
||||||
|
#define __USADA8 __iar_builtin_USADA8
|
||||||
|
#define __SSAT16 __iar_builtin_SSAT16
|
||||||
|
#define __USAT16 __iar_builtin_USAT16
|
||||||
|
#define __UXTB16 __iar_builtin_UXTB16
|
||||||
|
#define __UXTAB16 __iar_builtin_UXTAB16
|
||||||
|
#define __SXTB16 __iar_builtin_SXTB16
|
||||||
|
#define __SXTAB16 __iar_builtin_SXTAB16
|
||||||
|
#define __SMUAD __iar_builtin_SMUAD
|
||||||
|
#define __SMUADX __iar_builtin_SMUADX
|
||||||
|
#define __SMMLA __iar_builtin_SMMLA
|
||||||
|
#define __SMLAD __iar_builtin_SMLAD
|
||||||
|
#define __SMLADX __iar_builtin_SMLADX
|
||||||
|
#define __SMLALD __iar_builtin_SMLALD
|
||||||
|
#define __SMLALDX __iar_builtin_SMLALDX
|
||||||
|
#define __SMUSD __iar_builtin_SMUSD
|
||||||
|
#define __SMUSDX __iar_builtin_SMUSDX
|
||||||
|
#define __SMLSD __iar_builtin_SMLSD
|
||||||
|
#define __SMLSDX __iar_builtin_SMLSDX
|
||||||
|
#define __SMLSLD __iar_builtin_SMLSLD
|
||||||
|
#define __SMLSLDX __iar_builtin_SMLSLDX
|
||||||
|
#define __SEL __iar_builtin_SEL
|
||||||
|
#define __QADD __iar_builtin_QADD
|
||||||
|
#define __QSUB __iar_builtin_QSUB
|
||||||
|
#define __PKHBT __iar_builtin_PKHBT
|
||||||
|
#define __PKHTB __iar_builtin_PKHTB
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* __ICCARM_INTRINSICS_VERSION__ == 2 */
|
||||||
|
|
||||||
|
#if __IAR_M0_FAMILY
|
||||||
|
/* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */
|
||||||
|
#define __CLZ __cmsis_iar_clz_not_active
|
||||||
|
#define __SSAT __cmsis_iar_ssat_not_active
|
||||||
|
#define __USAT __cmsis_iar_usat_not_active
|
||||||
|
#define __RBIT __cmsis_iar_rbit_not_active
|
||||||
|
#define __get_APSR __cmsis_iar_get_APSR_not_active
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
|
||||||
|
(defined (__FPU_USED ) && (__FPU_USED == 1U)) ))
|
||||||
|
#define __get_FPSCR __cmsis_iar_get_FPSR_not_active
|
||||||
|
#define __set_FPSCR __cmsis_iar_set_FPSR_not_active
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __INTRINSICS_INCLUDED
|
||||||
|
#error intrinsics.h is already included previously!
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <intrinsics.h>
|
||||||
|
|
||||||
|
#if __IAR_M0_FAMILY
|
||||||
|
/* Avoid clash between intrinsics.h and arm_math.h when compiling for Cortex-M0. */
|
||||||
|
#undef __CLZ
|
||||||
|
#undef __SSAT
|
||||||
|
#undef __USAT
|
||||||
|
#undef __RBIT
|
||||||
|
#undef __get_APSR
|
||||||
|
|
||||||
|
__STATIC_INLINE uint8_t __CLZ(uint32_t data)
|
||||||
|
{
|
||||||
|
if (data == 0U) { return 32U; }
|
||||||
|
|
||||||
|
uint32_t count = 0U;
|
||||||
|
uint32_t mask = 0x80000000U;
|
||||||
|
|
||||||
|
while ((data & mask) == 0U)
|
||||||
|
{
|
||||||
|
count += 1U;
|
||||||
|
mask = mask >> 1U;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
__STATIC_INLINE uint32_t __RBIT(uint32_t v)
|
||||||
|
{
|
||||||
|
uint8_t sc = 31U;
|
||||||
|
uint32_t r = v;
|
||||||
|
for (v >>= 1U; v; v >>= 1U)
|
||||||
|
{
|
||||||
|
r <<= 1U;
|
||||||
|
r |= v & 1U;
|
||||||
|
sc--;
|
||||||
|
}
|
||||||
|
return (r << sc);
|
||||||
|
}
|
||||||
|
|
||||||
|
__STATIC_INLINE uint32_t __get_APSR(void)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__asm("MRS %0,APSR" : "=r" (res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (!((defined (__FPU_PRESENT) && (__FPU_PRESENT == 1U)) && \
|
||||||
|
(defined (__FPU_USED ) && (__FPU_USED == 1U)) ))
|
||||||
|
#undef __get_FPSCR
|
||||||
|
#undef __set_FPSCR
|
||||||
|
#define __get_FPSCR() (0)
|
||||||
|
#define __set_FPSCR(VALUE) ((void)VALUE)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#pragma diag_suppress=Pe940
|
||||||
|
#pragma diag_suppress=Pe177
|
||||||
|
|
||||||
|
#define __enable_irq __enable_interrupt
|
||||||
|
#define __disable_irq __disable_interrupt
|
||||||
|
#define __NOP __no_operation
|
||||||
|
|
||||||
|
#define __get_xPSR __get_PSR
|
||||||
|
|
||||||
|
#if (!defined(__ARM_ARCH_6M__) || __ARM_ARCH_6M__==0)
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __LDREXW(uint32_t volatile *ptr)
|
||||||
|
{
|
||||||
|
return __LDREX((unsigned long *)ptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __STREXW(uint32_t value, uint32_t volatile *ptr)
|
||||||
|
{
|
||||||
|
return __STREX(value, (unsigned long *)ptr);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */
|
||||||
|
#if (__CORTEX_M >= 0x03)
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __RRX(uint32_t value)
|
||||||
|
{
|
||||||
|
uint32_t result;
|
||||||
|
__ASM volatile("RRX %0, %1" : "=r"(result) : "r" (value));
|
||||||
|
return(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __set_BASEPRI_MAX(uint32_t value)
|
||||||
|
{
|
||||||
|
__asm volatile("MSR BASEPRI_MAX,%0"::"r" (value));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define __enable_fault_irq __enable_fiq
|
||||||
|
#define __disable_fault_irq __disable_fiq
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* (__CORTEX_M >= 0x03) */
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __ROR(uint32_t op1, uint32_t op2)
|
||||||
|
{
|
||||||
|
return (op1 >> op2) | (op1 << ((sizeof(op1)*8)-op2));
|
||||||
|
}
|
||||||
|
|
||||||
|
#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
|
||||||
|
(defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __get_MSPLIM(void)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||||
|
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
|
||||||
|
// without main extensions, the non-secure MSPLIM is RAZ/WI
|
||||||
|
res = 0U;
|
||||||
|
#else
|
||||||
|
__asm volatile("MRS %0,MSPLIM" : "=r" (res));
|
||||||
|
#endif
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __set_MSPLIM(uint32_t value)
|
||||||
|
{
|
||||||
|
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||||
|
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
|
||||||
|
// without main extensions, the non-secure MSPLIM is RAZ/WI
|
||||||
|
(void)value;
|
||||||
|
#else
|
||||||
|
__asm volatile("MSR MSPLIM,%0" :: "r" (value));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __get_PSPLIM(void)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||||
|
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
|
||||||
|
// without main extensions, the non-secure PSPLIM is RAZ/WI
|
||||||
|
res = 0U;
|
||||||
|
#else
|
||||||
|
__asm volatile("MRS %0,PSPLIM" : "=r" (res));
|
||||||
|
#endif
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __set_PSPLIM(uint32_t value)
|
||||||
|
{
|
||||||
|
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||||
|
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
|
||||||
|
// without main extensions, the non-secure PSPLIM is RAZ/WI
|
||||||
|
(void)value;
|
||||||
|
#else
|
||||||
|
__asm volatile("MSR PSPLIM,%0" :: "r" (value));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __TZ_get_CONTROL_NS(void)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__asm volatile("MRS %0,CONTROL_NS" : "=r" (res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __TZ_set_CONTROL_NS(uint32_t value)
|
||||||
|
{
|
||||||
|
__asm volatile("MSR CONTROL_NS,%0" :: "r" (value));
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __TZ_get_PSP_NS(void)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__asm volatile("MRS %0,PSP_NS" : "=r" (res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __TZ_set_PSP_NS(uint32_t value)
|
||||||
|
{
|
||||||
|
__asm volatile("MSR PSP_NS,%0" :: "r" (value));
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __TZ_get_MSP_NS(void)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__asm volatile("MRS %0,MSP_NS" : "=r" (res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __TZ_set_MSP_NS(uint32_t value)
|
||||||
|
{
|
||||||
|
__asm volatile("MSR MSP_NS,%0" :: "r" (value));
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __TZ_get_SP_NS(void)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__asm volatile("MRS %0,SP_NS" : "=r" (res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
__IAR_FT void __TZ_set_SP_NS(uint32_t value)
|
||||||
|
{
|
||||||
|
__asm volatile("MSR SP_NS,%0" :: "r" (value));
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __TZ_get_PRIMASK_NS(void)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__asm volatile("MRS %0,PRIMASK_NS" : "=r" (res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __TZ_set_PRIMASK_NS(uint32_t value)
|
||||||
|
{
|
||||||
|
__asm volatile("MSR PRIMASK_NS,%0" :: "r" (value));
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __TZ_get_BASEPRI_NS(void)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__asm volatile("MRS %0,BASEPRI_NS" : "=r" (res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __TZ_set_BASEPRI_NS(uint32_t value)
|
||||||
|
{
|
||||||
|
__asm volatile("MSR BASEPRI_NS,%0" :: "r" (value));
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __TZ_get_FAULTMASK_NS(void)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__asm volatile("MRS %0,FAULTMASK_NS" : "=r" (res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __TZ_set_FAULTMASK_NS(uint32_t value)
|
||||||
|
{
|
||||||
|
__asm volatile("MSR FAULTMASK_NS,%0" :: "r" (value));
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __TZ_get_PSPLIM_NS(void)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||||
|
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
|
||||||
|
// without main extensions, the non-secure PSPLIM is RAZ/WI
|
||||||
|
res = 0U;
|
||||||
|
#else
|
||||||
|
__asm volatile("MRS %0,PSPLIM_NS" : "=r" (res));
|
||||||
|
#endif
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __TZ_set_PSPLIM_NS(uint32_t value)
|
||||||
|
{
|
||||||
|
#if (!(defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) && \
|
||||||
|
(!defined (__ARM_FEATURE_CMSE ) || (__ARM_FEATURE_CMSE < 3)))
|
||||||
|
// without main extensions, the non-secure PSPLIM is RAZ/WI
|
||||||
|
(void)value;
|
||||||
|
#else
|
||||||
|
__asm volatile("MSR PSPLIM_NS,%0" :: "r" (value));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __TZ_get_MSPLIM_NS(void)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__asm volatile("MRS %0,MSPLIM_NS" : "=r" (res));
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __TZ_set_MSPLIM_NS(uint32_t value)
|
||||||
|
{
|
||||||
|
__asm volatile("MSR MSPLIM_NS,%0" :: "r" (value));
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */
|
||||||
|
|
||||||
|
#endif /* __ICCARM_INTRINSICS_VERSION__ == 2 */
|
||||||
|
|
||||||
|
#define __BKPT(value) __asm volatile ("BKPT %0" : : "i"(value))
|
||||||
|
|
||||||
|
#if __IAR_M0_FAMILY
|
||||||
|
__STATIC_INLINE int32_t __SSAT(int32_t val, uint32_t sat)
|
||||||
|
{
|
||||||
|
if ((sat >= 1U) && (sat <= 32U))
|
||||||
|
{
|
||||||
|
const int32_t max = (int32_t)((1U << (sat - 1U)) - 1U);
|
||||||
|
const int32_t min = -1 - max ;
|
||||||
|
if (val > max)
|
||||||
|
{
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
else if (val < min)
|
||||||
|
{
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
__STATIC_INLINE uint32_t __USAT(int32_t val, uint32_t sat)
|
||||||
|
{
|
||||||
|
if (sat <= 31U)
|
||||||
|
{
|
||||||
|
const uint32_t max = ((1U << sat) - 1U);
|
||||||
|
if (val > (int32_t)max)
|
||||||
|
{
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
else if (val < 0)
|
||||||
|
{
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (uint32_t)val;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (__CORTEX_M >= 0x03) /* __CORTEX_M is defined in core_cm0.h, core_cm3.h and core_cm4.h. */
|
||||||
|
|
||||||
|
__IAR_FT uint8_t __LDRBT(volatile uint8_t *addr)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__ASM volatile ("LDRBT %0, [%1]" : "=r" (res) : "r" (addr) : "memory");
|
||||||
|
return ((uint8_t)res);
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint16_t __LDRHT(volatile uint16_t *addr)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__ASM volatile ("LDRHT %0, [%1]" : "=r" (res) : "r" (addr) : "memory");
|
||||||
|
return ((uint16_t)res);
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __LDRT(volatile uint32_t *addr)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__ASM volatile ("LDRT %0, [%1]" : "=r" (res) : "r" (addr) : "memory");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __STRBT(uint8_t value, volatile uint8_t *addr)
|
||||||
|
{
|
||||||
|
__ASM volatile ("STRBT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __STRHT(uint16_t value, volatile uint16_t *addr)
|
||||||
|
{
|
||||||
|
__ASM volatile ("STRHT %1, [%0]" : : "r" (addr), "r" ((uint32_t)value) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __STRT(uint32_t value, volatile uint32_t *addr)
|
||||||
|
{
|
||||||
|
__ASM volatile ("STRT %1, [%0]" : : "r" (addr), "r" (value) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* (__CORTEX_M >= 0x03) */
|
||||||
|
|
||||||
|
#if ((defined (__ARM_ARCH_8M_MAIN__ ) && (__ARM_ARCH_8M_MAIN__ == 1)) || \
|
||||||
|
(defined (__ARM_ARCH_8M_BASE__ ) && (__ARM_ARCH_8M_BASE__ == 1)) )
|
||||||
|
|
||||||
|
|
||||||
|
__IAR_FT uint8_t __LDAB(volatile uint8_t *ptr)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__ASM volatile ("LDAB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
|
||||||
|
return ((uint8_t)res);
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint16_t __LDAH(volatile uint16_t *ptr)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__ASM volatile ("LDAH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
|
||||||
|
return ((uint16_t)res);
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __LDA(volatile uint32_t *ptr)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__ASM volatile ("LDA %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __STLB(uint8_t value, volatile uint8_t *ptr)
|
||||||
|
{
|
||||||
|
__ASM volatile ("STLB %1, [%0]" :: "r" (ptr), "r" (value) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __STLH(uint16_t value, volatile uint16_t *ptr)
|
||||||
|
{
|
||||||
|
__ASM volatile ("STLH %1, [%0]" :: "r" (ptr), "r" (value) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT void __STL(uint32_t value, volatile uint32_t *ptr)
|
||||||
|
{
|
||||||
|
__ASM volatile ("STL %1, [%0]" :: "r" (ptr), "r" (value) : "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint8_t __LDAEXB(volatile uint8_t *ptr)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__ASM volatile ("LDAEXB %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
|
||||||
|
return ((uint8_t)res);
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint16_t __LDAEXH(volatile uint16_t *ptr)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__ASM volatile ("LDAEXH %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
|
||||||
|
return ((uint16_t)res);
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __LDAEX(volatile uint32_t *ptr)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__ASM volatile ("LDAEX %0, [%1]" : "=r" (res) : "r" (ptr) : "memory");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __STLEXB(uint8_t value, volatile uint8_t *ptr)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__ASM volatile ("STLEXB %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __STLEXH(uint16_t value, volatile uint16_t *ptr)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__ASM volatile ("STLEXH %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
__IAR_FT uint32_t __STLEX(uint32_t value, volatile uint32_t *ptr)
|
||||||
|
{
|
||||||
|
uint32_t res;
|
||||||
|
__ASM volatile ("STLEX %0, %2, [%1]" : "=r" (res) : "r" (ptr), "r" (value) : "memory");
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* __ARM_ARCH_8M_MAIN__ or __ARM_ARCH_8M_BASE__ */
|
||||||
|
|
||||||
|
#undef __IAR_FT
|
||||||
|
#undef __IAR_M0_FAMILY
|
||||||
|
#undef __ICCARM_V8
|
||||||
|
|
||||||
|
#pragma diag_default=Pe940
|
||||||
|
#pragma diag_default=Pe177
|
||||||
|
|
||||||
|
#define __SXTB16_RORn(ARG1, ARG2) __SXTB16(__ROR(ARG1, ARG2))
|
||||||
|
|
||||||
|
#endif /* __CMSIS_ICCARM_H__ */
|
39
src/rp2_common/cmsis/stub/CMSIS/Core/Include/cmsis_version.h
Normal file
39
src/rp2_common/cmsis/stub/CMSIS/Core/Include/cmsis_version.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/**************************************************************************//**
|
||||||
|
* @file cmsis_version.h
|
||||||
|
* @brief CMSIS Core(M) Version definitions
|
||||||
|
* @version V5.0.4
|
||||||
|
* @date 23. July 2019
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2019 ARM Limited. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined ( __ICCARM__ )
|
||||||
|
#pragma system_include /* treat file as system include file for MISRA check */
|
||||||
|
#elif defined (__clang__)
|
||||||
|
#pragma clang system_header /* treat file as system include file */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __CMSIS_VERSION_H
|
||||||
|
#define __CMSIS_VERSION_H
|
||||||
|
|
||||||
|
/* CMSIS Version definitions */
|
||||||
|
#define __CM_CMSIS_VERSION_MAIN ( 5U) /*!< [31:16] CMSIS Core(M) main version */
|
||||||
|
#define __CM_CMSIS_VERSION_SUB ( 4U) /*!< [15:0] CMSIS Core(M) sub version */
|
||||||
|
#define __CM_CMSIS_VERSION ((__CM_CMSIS_VERSION_MAIN << 16U) | \
|
||||||
|
__CM_CMSIS_VERSION_SUB ) /*!< CMSIS Core(M) version number */
|
||||||
|
#endif
|
1087
src/rp2_common/cmsis/stub/CMSIS/Core/Include/core_cm0plus.h
Normal file
1087
src/rp2_common/cmsis/stub/CMSIS/Core/Include/core_cm0plus.h
Normal file
File diff suppressed because it is too large
Load Diff
275
src/rp2_common/cmsis/stub/CMSIS/Core/Include/mpu_armv7.h
Normal file
275
src/rp2_common/cmsis/stub/CMSIS/Core/Include/mpu_armv7.h
Normal file
@ -0,0 +1,275 @@
|
|||||||
|
/******************************************************************************
|
||||||
|
* @file mpu_armv7.h
|
||||||
|
* @brief CMSIS MPU API for Armv7-M MPU
|
||||||
|
* @version V5.1.1
|
||||||
|
* @date 10. February 2020
|
||||||
|
******************************************************************************/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2017-2020 Arm Limited. All rights reserved.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#if defined ( __ICCARM__ )
|
||||||
|
#pragma system_include /* treat file as system include file for MISRA check */
|
||||||
|
#elif defined (__clang__)
|
||||||
|
#pragma clang system_header /* treat file as system include file */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef ARM_MPU_ARMV7_H
|
||||||
|
#define ARM_MPU_ARMV7_H
|
||||||
|
|
||||||
|
#define ARM_MPU_REGION_SIZE_32B ((uint8_t)0x04U) ///!< MPU Region Size 32 Bytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_64B ((uint8_t)0x05U) ///!< MPU Region Size 64 Bytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_128B ((uint8_t)0x06U) ///!< MPU Region Size 128 Bytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_256B ((uint8_t)0x07U) ///!< MPU Region Size 256 Bytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_512B ((uint8_t)0x08U) ///!< MPU Region Size 512 Bytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_1KB ((uint8_t)0x09U) ///!< MPU Region Size 1 KByte
|
||||||
|
#define ARM_MPU_REGION_SIZE_2KB ((uint8_t)0x0AU) ///!< MPU Region Size 2 KBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_4KB ((uint8_t)0x0BU) ///!< MPU Region Size 4 KBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_8KB ((uint8_t)0x0CU) ///!< MPU Region Size 8 KBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_16KB ((uint8_t)0x0DU) ///!< MPU Region Size 16 KBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_32KB ((uint8_t)0x0EU) ///!< MPU Region Size 32 KBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_64KB ((uint8_t)0x0FU) ///!< MPU Region Size 64 KBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_128KB ((uint8_t)0x10U) ///!< MPU Region Size 128 KBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_256KB ((uint8_t)0x11U) ///!< MPU Region Size 256 KBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_512KB ((uint8_t)0x12U) ///!< MPU Region Size 512 KBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_1MB ((uint8_t)0x13U) ///!< MPU Region Size 1 MByte
|
||||||
|
#define ARM_MPU_REGION_SIZE_2MB ((uint8_t)0x14U) ///!< MPU Region Size 2 MBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_4MB ((uint8_t)0x15U) ///!< MPU Region Size 4 MBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_8MB ((uint8_t)0x16U) ///!< MPU Region Size 8 MBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_16MB ((uint8_t)0x17U) ///!< MPU Region Size 16 MBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_32MB ((uint8_t)0x18U) ///!< MPU Region Size 32 MBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_64MB ((uint8_t)0x19U) ///!< MPU Region Size 64 MBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_128MB ((uint8_t)0x1AU) ///!< MPU Region Size 128 MBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_256MB ((uint8_t)0x1BU) ///!< MPU Region Size 256 MBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_512MB ((uint8_t)0x1CU) ///!< MPU Region Size 512 MBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_1GB ((uint8_t)0x1DU) ///!< MPU Region Size 1 GByte
|
||||||
|
#define ARM_MPU_REGION_SIZE_2GB ((uint8_t)0x1EU) ///!< MPU Region Size 2 GBytes
|
||||||
|
#define ARM_MPU_REGION_SIZE_4GB ((uint8_t)0x1FU) ///!< MPU Region Size 4 GBytes
|
||||||
|
|
||||||
|
#define ARM_MPU_AP_NONE 0U ///!< MPU Access Permission no access
|
||||||
|
#define ARM_MPU_AP_PRIV 1U ///!< MPU Access Permission privileged access only
|
||||||
|
#define ARM_MPU_AP_URO 2U ///!< MPU Access Permission unprivileged access read-only
|
||||||
|
#define ARM_MPU_AP_FULL 3U ///!< MPU Access Permission full access
|
||||||
|
#define ARM_MPU_AP_PRO 5U ///!< MPU Access Permission privileged access read-only
|
||||||
|
#define ARM_MPU_AP_RO 6U ///!< MPU Access Permission read-only access
|
||||||
|
|
||||||
|
/** MPU Region Base Address Register Value
|
||||||
|
*
|
||||||
|
* \param Region The region to be configured, number 0 to 15.
|
||||||
|
* \param BaseAddress The base address for the region.
|
||||||
|
*/
|
||||||
|
#define ARM_MPU_RBAR(Region, BaseAddress) \
|
||||||
|
(((BaseAddress) & MPU_RBAR_ADDR_Msk) | \
|
||||||
|
((Region) & MPU_RBAR_REGION_Msk) | \
|
||||||
|
(MPU_RBAR_VALID_Msk))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MPU Memory Access Attributes
|
||||||
|
*
|
||||||
|
* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
|
||||||
|
* \param IsShareable Region is shareable between multiple bus masters.
|
||||||
|
* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
|
||||||
|
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
|
||||||
|
*/
|
||||||
|
#define ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable) \
|
||||||
|
((((TypeExtField) << MPU_RASR_TEX_Pos) & MPU_RASR_TEX_Msk) | \
|
||||||
|
(((IsShareable) << MPU_RASR_S_Pos) & MPU_RASR_S_Msk) | \
|
||||||
|
(((IsCacheable) << MPU_RASR_C_Pos) & MPU_RASR_C_Msk) | \
|
||||||
|
(((IsBufferable) << MPU_RASR_B_Pos) & MPU_RASR_B_Msk))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MPU Region Attribute and Size Register Value
|
||||||
|
*
|
||||||
|
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
|
||||||
|
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
|
||||||
|
* \param AccessAttributes Memory access attribution, see \ref ARM_MPU_ACCESS_.
|
||||||
|
* \param SubRegionDisable Sub-region disable field.
|
||||||
|
* \param Size Region size of the region to be configured, for example 4K, 8K.
|
||||||
|
*/
|
||||||
|
#define ARM_MPU_RASR_EX(DisableExec, AccessPermission, AccessAttributes, SubRegionDisable, Size) \
|
||||||
|
((((DisableExec) << MPU_RASR_XN_Pos) & MPU_RASR_XN_Msk) | \
|
||||||
|
(((AccessPermission) << MPU_RASR_AP_Pos) & MPU_RASR_AP_Msk) | \
|
||||||
|
(((AccessAttributes) & (MPU_RASR_TEX_Msk | MPU_RASR_S_Msk | MPU_RASR_C_Msk | MPU_RASR_B_Msk))) | \
|
||||||
|
(((SubRegionDisable) << MPU_RASR_SRD_Pos) & MPU_RASR_SRD_Msk) | \
|
||||||
|
(((Size) << MPU_RASR_SIZE_Pos) & MPU_RASR_SIZE_Msk) | \
|
||||||
|
(((MPU_RASR_ENABLE_Msk))))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MPU Region Attribute and Size Register Value
|
||||||
|
*
|
||||||
|
* \param DisableExec Instruction access disable bit, 1= disable instruction fetches.
|
||||||
|
* \param AccessPermission Data access permissions, allows you to configure read/write access for User and Privileged mode.
|
||||||
|
* \param TypeExtField Type extension field, allows you to configure memory access type, for example strongly ordered, peripheral.
|
||||||
|
* \param IsShareable Region is shareable between multiple bus masters.
|
||||||
|
* \param IsCacheable Region is cacheable, i.e. its value may be kept in cache.
|
||||||
|
* \param IsBufferable Region is bufferable, i.e. using write-back caching. Cacheable but non-bufferable regions use write-through policy.
|
||||||
|
* \param SubRegionDisable Sub-region disable field.
|
||||||
|
* \param Size Region size of the region to be configured, for example 4K, 8K.
|
||||||
|
*/
|
||||||
|
#define ARM_MPU_RASR(DisableExec, AccessPermission, TypeExtField, IsShareable, IsCacheable, IsBufferable, SubRegionDisable, Size) \
|
||||||
|
ARM_MPU_RASR_EX(DisableExec, AccessPermission, ARM_MPU_ACCESS_(TypeExtField, IsShareable, IsCacheable, IsBufferable), SubRegionDisable, Size)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MPU Memory Access Attribute for strongly ordered memory.
|
||||||
|
* - TEX: 000b
|
||||||
|
* - Shareable
|
||||||
|
* - Non-cacheable
|
||||||
|
* - Non-bufferable
|
||||||
|
*/
|
||||||
|
#define ARM_MPU_ACCESS_ORDERED ARM_MPU_ACCESS_(0U, 1U, 0U, 0U)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MPU Memory Access Attribute for device memory.
|
||||||
|
* - TEX: 000b (if shareable) or 010b (if non-shareable)
|
||||||
|
* - Shareable or non-shareable
|
||||||
|
* - Non-cacheable
|
||||||
|
* - Bufferable (if shareable) or non-bufferable (if non-shareable)
|
||||||
|
*
|
||||||
|
* \param IsShareable Configures the device memory as shareable or non-shareable.
|
||||||
|
*/
|
||||||
|
#define ARM_MPU_ACCESS_DEVICE(IsShareable) ((IsShareable) ? ARM_MPU_ACCESS_(0U, 1U, 0U, 1U) : ARM_MPU_ACCESS_(2U, 0U, 0U, 0U))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MPU Memory Access Attribute for normal memory.
|
||||||
|
* - TEX: 1BBb (reflecting outer cacheability rules)
|
||||||
|
* - Shareable or non-shareable
|
||||||
|
* - Cacheable or non-cacheable (reflecting inner cacheability rules)
|
||||||
|
* - Bufferable or non-bufferable (reflecting inner cacheability rules)
|
||||||
|
*
|
||||||
|
* \param OuterCp Configures the outer cache policy.
|
||||||
|
* \param InnerCp Configures the inner cache policy.
|
||||||
|
* \param IsShareable Configures the memory as shareable or non-shareable.
|
||||||
|
*/
|
||||||
|
#define ARM_MPU_ACCESS_NORMAL(OuterCp, InnerCp, IsShareable) ARM_MPU_ACCESS_((4U | (OuterCp)), IsShareable, ((InnerCp) >> 1U), ((InnerCp) & 1U))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MPU Memory Access Attribute non-cacheable policy.
|
||||||
|
*/
|
||||||
|
#define ARM_MPU_CACHEP_NOCACHE 0U
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MPU Memory Access Attribute write-back, write and read allocate policy.
|
||||||
|
*/
|
||||||
|
#define ARM_MPU_CACHEP_WB_WRA 1U
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MPU Memory Access Attribute write-through, no write allocate policy.
|
||||||
|
*/
|
||||||
|
#define ARM_MPU_CACHEP_WT_NWA 2U
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MPU Memory Access Attribute write-back, no write allocate policy.
|
||||||
|
*/
|
||||||
|
#define ARM_MPU_CACHEP_WB_NWA 3U
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Struct for a single MPU Region
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
uint32_t RBAR; //!< The region base address register value (RBAR)
|
||||||
|
uint32_t RASR; //!< The region attribute and size register value (RASR) \ref MPU_RASR
|
||||||
|
} ARM_MPU_Region_t;
|
||||||
|
|
||||||
|
/** Enable the MPU.
|
||||||
|
* \param MPU_Control Default access permissions for unconfigured regions.
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void ARM_MPU_Enable(uint32_t MPU_Control)
|
||||||
|
{
|
||||||
|
__DMB();
|
||||||
|
MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
|
||||||
|
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
|
||||||
|
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
|
||||||
|
#endif
|
||||||
|
__DSB();
|
||||||
|
__ISB();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Disable the MPU.
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void ARM_MPU_Disable(void)
|
||||||
|
{
|
||||||
|
__DMB();
|
||||||
|
#ifdef SCB_SHCSR_MEMFAULTENA_Msk
|
||||||
|
SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
|
||||||
|
#endif
|
||||||
|
MPU->CTRL &= ~MPU_CTRL_ENABLE_Msk;
|
||||||
|
__DSB();
|
||||||
|
__ISB();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Clear and disable the given MPU region.
|
||||||
|
* \param rnr Region number to be cleared.
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void ARM_MPU_ClrRegion(uint32_t rnr)
|
||||||
|
{
|
||||||
|
MPU->RNR = rnr;
|
||||||
|
MPU->RASR = 0U;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Configure an MPU region.
|
||||||
|
* \param rbar Value for RBAR register.
|
||||||
|
* \param rsar Value for RSAR register.
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void ARM_MPU_SetRegion(uint32_t rbar, uint32_t rasr)
|
||||||
|
{
|
||||||
|
MPU->RBAR = rbar;
|
||||||
|
MPU->RASR = rasr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Configure the given MPU region.
|
||||||
|
* \param rnr Region number to be configured.
|
||||||
|
* \param rbar Value for RBAR register.
|
||||||
|
* \param rsar Value for RSAR register.
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void ARM_MPU_SetRegionEx(uint32_t rnr, uint32_t rbar, uint32_t rasr)
|
||||||
|
{
|
||||||
|
MPU->RNR = rnr;
|
||||||
|
MPU->RBAR = rbar;
|
||||||
|
MPU->RASR = rasr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Memcopy with strictly ordered memory access, e.g. for register targets.
|
||||||
|
* \param dst Destination data is copied to.
|
||||||
|
* \param src Source data is copied from.
|
||||||
|
* \param len Amount of data words to be copied.
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void ARM_MPU_OrderedMemcpy(volatile uint32_t* dst, const uint32_t* __RESTRICT src, uint32_t len)
|
||||||
|
{
|
||||||
|
uint32_t i;
|
||||||
|
for (i = 0U; i < len; ++i)
|
||||||
|
{
|
||||||
|
dst[i] = src[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Load the given number of MPU regions from a table.
|
||||||
|
* \param table Pointer to the MPU configuration table.
|
||||||
|
* \param cnt Amount of regions to be configured.
|
||||||
|
*/
|
||||||
|
__STATIC_INLINE void ARM_MPU_Load(ARM_MPU_Region_t const* table, uint32_t cnt)
|
||||||
|
{
|
||||||
|
const uint32_t rowWordSize = sizeof(ARM_MPU_Region_t)/4U;
|
||||||
|
while (cnt > MPU_TYPE_RALIASES) {
|
||||||
|
ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), MPU_TYPE_RALIASES*rowWordSize);
|
||||||
|
table += MPU_TYPE_RALIASES;
|
||||||
|
cnt -= MPU_TYPE_RALIASES;
|
||||||
|
}
|
||||||
|
ARM_MPU_OrderedMemcpy(&(MPU->RBAR), &(table->RBAR), cnt*rowWordSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -0,0 +1,109 @@
|
|||||||
|
/*************************************************************************//**
|
||||||
|
* @file RP2040.h
|
||||||
|
* @brief CMSIS-Core(M) Device Peripheral Access Layer Header File for
|
||||||
|
* Device RP2040
|
||||||
|
* @version V1.0.0
|
||||||
|
* @date 5. May 2021
|
||||||
|
*****************************************************************************/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2021 Arm Limited. All rights reserved.
|
||||||
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CMSIS_RP2040_H_
|
||||||
|
#define _CMSIS_RP2040_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* =========================================================================================================================== */
|
||||||
|
/* ================ Interrupt Number Definition ================ */
|
||||||
|
/* =========================================================================================================================== */
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
/* ======================================= ARM Cortex-M0+ Specific Interrupt Numbers ======================================= */
|
||||||
|
Reset_IRQn = -15, /*!< -15 Reset Vector, invoked on Power up and warm reset */
|
||||||
|
NonMaskableInt_IRQn = -14, /*!< -14 Non maskable Interrupt, cannot be stopped or preempted */
|
||||||
|
HardFault_IRQn = -13, /*!< -13 Hard Fault, all classes of Fault */
|
||||||
|
SVCall_IRQn = -5, /*!< -5 System Service Call via SVC instruction */
|
||||||
|
PendSV_IRQn = -2, /*!< -2 Pendable request for system service */
|
||||||
|
SysTick_IRQn = -1, /*!< -1 System Tick Timer */
|
||||||
|
/* =========================================== RP2040 Specific Interrupt Numbers =========================================== */
|
||||||
|
TIMER_IRQ_0_IRQn = 0, /*!< 0 TIMER_IRQ_0 */
|
||||||
|
TIMER_IRQ_1_IRQn = 1, /*!< 1 TIMER_IRQ_1 */
|
||||||
|
TIMER_IRQ_2_IRQn = 2, /*!< 2 TIMER_IRQ_2 */
|
||||||
|
TIMER_IRQ_3_IRQn = 3, /*!< 3 TIMER_IRQ_3 */
|
||||||
|
PWM_IRQ_WRAP_IRQn = 4, /*!< 4 PWM_IRQ_WRAP */
|
||||||
|
USBCTRL_IRQ_IRQn = 5, /*!< 5 USBCTRL_IRQ */
|
||||||
|
XIP_IRQ_IRQn = 6, /*!< 6 XIP_IRQ */
|
||||||
|
PIO0_IRQ_0_IRQn = 7, /*!< 7 PIO0_IRQ_0 */
|
||||||
|
PIO0_IRQ_1_IRQn = 8, /*!< 8 PIO0_IRQ_1 */
|
||||||
|
PIO1_IRQ_0_IRQn = 9, /*!< 9 PIO1_IRQ_0 */
|
||||||
|
PIO1_IRQ_1_IRQn = 10, /*!< 10 PIO1_IRQ_1 */
|
||||||
|
DMA_IRQ_0_IRQn = 11, /*!< 11 DMA_IRQ_0 */
|
||||||
|
DMA_IRQ_1_IRQn = 12, /*!< 12 DMA_IRQ_1 */
|
||||||
|
IO_IRQ_BANK0_IRQn = 13, /*!< 13 IO_IRQ_BANK0 */
|
||||||
|
IO_IRQ_QSPI_IRQn = 14, /*!< 14 IO_IRQ_QSPI */
|
||||||
|
SIO_IRQ_PROC0_IRQn = 15, /*!< 15 SIO_IRQ_PROC0 */
|
||||||
|
SIO_IRQ_PROC1_IRQn = 16, /*!< 16 SIO_IRQ_PROC1 */
|
||||||
|
CLOCKS_IRQ_IRQn = 17, /*!< 17 CLOCKS_IRQ */
|
||||||
|
SPI0_IRQ_IRQn = 18, /*!< 18 SPI0_IRQ */
|
||||||
|
SPI1_IRQ_IRQn = 19, /*!< 19 SPI1_IRQ */
|
||||||
|
UART0_IRQ_IRQn = 20, /*!< 20 UART0_IRQ */
|
||||||
|
UART1_IRQ_IRQn = 21, /*!< 21 UART1_IRQ */
|
||||||
|
ADC_IRQ_FIFO_IRQn = 22, /*!< 22 ADC_IRQ_FIFO */
|
||||||
|
I2C0_IRQ_IRQn = 23, /*!< 23 I2C0_IRQ */
|
||||||
|
I2C1_IRQ_IRQn = 24, /*!< 24 I2C1_IRQ */
|
||||||
|
RTC_IRQ_IRQn = 25 /*!< 25 RTC_IRQ */
|
||||||
|
} IRQn_Type;
|
||||||
|
|
||||||
|
/* =========================================================================================================================== */
|
||||||
|
/* ================ Processor and Core Peripheral Section ================ */
|
||||||
|
/* =========================================================================================================================== */
|
||||||
|
|
||||||
|
/* ========================== Configuration of the ARM Cortex-M0+ Processor and Core Peripherals =========================== */
|
||||||
|
#define __CM0PLUS_REV 0x0001U /*!< CM0PLUS Core Revision */
|
||||||
|
#define __NVIC_PRIO_BITS 2 /*!< Number of Bits used for Priority Levels */
|
||||||
|
#define __Vendor_SysTickConfig 0 /*!< Set to 1 if different SysTick Config is used */
|
||||||
|
#define __VTOR_PRESENT 1 /*!< Set to 1 if CPU supports Vector Table Offset Register */
|
||||||
|
#define __MPU_PRESENT 1 /*!< MPU present */
|
||||||
|
#define __FPU_PRESENT 0 /*!< FPU present */
|
||||||
|
|
||||||
|
/** @} */ /* End of group Configuration_of_CMSIS */
|
||||||
|
|
||||||
|
#include "core_cm0plus.h" /*!< ARM Cortex-M0+ processor and core peripherals */
|
||||||
|
#include "system_RP2040.h" /*!< RP2040 System */
|
||||||
|
|
||||||
|
#ifndef __IM /*!< Fallback for older CMSIS versions */
|
||||||
|
#define __IM __I
|
||||||
|
#endif
|
||||||
|
#ifndef __OM /*!< Fallback for older CMSIS versions */
|
||||||
|
#define __OM __O
|
||||||
|
#endif
|
||||||
|
#ifndef __IOM /*!< Fallback for older CMSIS versions */
|
||||||
|
#define __IOM __IO
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _CMSIS_RP2040_H */
|
@ -0,0 +1,65 @@
|
|||||||
|
/*************************************************************************//**
|
||||||
|
* @file system_RP2040.h
|
||||||
|
* @brief CMSIS-Core(M) Device Peripheral Access Layer Header File for
|
||||||
|
* Device RP2040
|
||||||
|
* @version V1.0.0
|
||||||
|
* @date 5. May 2021
|
||||||
|
*****************************************************************************/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2021 Arm Limited. All rights reserved.
|
||||||
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _CMSIS_SYSTEM_RP2040_H
|
||||||
|
#define _CMSIS_SYSTEM_RP2040_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Exception / Interrupt Handler Function Prototype
|
||||||
|
*/
|
||||||
|
typedef void(*VECTOR_TABLE_Type)(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief System Clock Frequency (Core Clock)
|
||||||
|
*/
|
||||||
|
extern uint32_t SystemCoreClock;
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Setup the microcontroller system.
|
||||||
|
|
||||||
|
Initialize the System and update the SystemCoreClock variable.
|
||||||
|
*/
|
||||||
|
extern void SystemInit (void);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Update SystemCoreClock variable.
|
||||||
|
|
||||||
|
Updates the SystemCoreClock with current core Clock retrieved from cpu registers.
|
||||||
|
*/
|
||||||
|
extern void SystemCoreClockUpdate (void);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _CMSIS_SYSTEM_RP2040_H */
|
@ -0,0 +1,52 @@
|
|||||||
|
/*************************************************************************//**
|
||||||
|
* @file system_RP2040.c
|
||||||
|
* @brief CMSIS-Core(M) Device Peripheral Access Layer Header File for
|
||||||
|
* Device RP2040
|
||||||
|
* @version V1.0.0
|
||||||
|
* @date 5. May 2021
|
||||||
|
*****************************************************************************/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2009-2021 Arm Limited. All rights reserved.
|
||||||
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the License); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an AS IS BASIS, WITHOUT
|
||||||
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "RP2040.h"
|
||||||
|
#include "hardware/clocks.h"
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
System Core Clock Variable
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
uint32_t SystemCoreClock; /* System Clock Frequency (Core Clock)*/
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
System Core Clock function
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
void SystemCoreClockUpdate (void)
|
||||||
|
{
|
||||||
|
SystemCoreClock = clock_get_hz(clk_sys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------
|
||||||
|
System initialization function
|
||||||
|
*---------------------------------------------------------------------------*/
|
||||||
|
void __attribute__((constructor)) SystemInit (void)
|
||||||
|
{
|
||||||
|
SystemCoreClockUpdate();
|
||||||
|
}
|
201
src/rp2_common/cmsis/stub/CMSIS/LICENSE.txt
Normal file
201
src/rp2_common/cmsis/stub/CMSIS/LICENSE.txt
Normal file
@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright {yyyy} {name of copyright owner}
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
@ -88,6 +88,15 @@ static inline void adc_select_input(uint input) {
|
|||||||
hw_write_masked(&adc_hw->cs, input << ADC_CS_AINSEL_LSB, ADC_CS_AINSEL_BITS);
|
hw_write_masked(&adc_hw->cs, input << ADC_CS_AINSEL_LSB, ADC_CS_AINSEL_BITS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Get the currently selected ADC input channel
|
||||||
|
* \ingroup hardware_adc
|
||||||
|
*
|
||||||
|
* \return The currently selected input channel. 0...3 are GPIOs 26...29 respectively. Input 4 is the onboard temperature sensor.
|
||||||
|
*/
|
||||||
|
static inline uint adc_get_selected_input(void) {
|
||||||
|
return (adc_hw->cs & ADC_CS_AINSEL_BITS) >> ADC_CS_AINSEL_LSB;
|
||||||
|
}
|
||||||
|
|
||||||
/*! \brief Round Robin sampling selector
|
/*! \brief Round Robin sampling selector
|
||||||
* \ingroup hardware_adc
|
* \ingroup hardware_adc
|
||||||
*
|
*
|
||||||
|
@ -84,7 +84,7 @@ typedef ioptr const const_ioptr;
|
|||||||
* \param addr Address of writable register
|
* \param addr Address of writable register
|
||||||
* \param mask Bit-mask specifying bits to set
|
* \param mask Bit-mask specifying bits to set
|
||||||
*/
|
*/
|
||||||
inline static void hw_set_bits(io_rw_32 *addr, uint32_t mask) {
|
__force_inline static void hw_set_bits(io_rw_32 *addr, uint32_t mask) {
|
||||||
*(io_rw_32 *) hw_set_alias_untyped((volatile void *) addr) = mask;
|
*(io_rw_32 *) hw_set_alias_untyped((volatile void *) addr) = mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,7 +94,7 @@ inline static void hw_set_bits(io_rw_32 *addr, uint32_t mask) {
|
|||||||
* \param addr Address of writable register
|
* \param addr Address of writable register
|
||||||
* \param mask Bit-mask specifying bits to clear
|
* \param mask Bit-mask specifying bits to clear
|
||||||
*/
|
*/
|
||||||
inline static void hw_clear_bits(io_rw_32 *addr, uint32_t mask) {
|
__force_inline static void hw_clear_bits(io_rw_32 *addr, uint32_t mask) {
|
||||||
*(io_rw_32 *) hw_clear_alias_untyped((volatile void *) addr) = mask;
|
*(io_rw_32 *) hw_clear_alias_untyped((volatile void *) addr) = mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,7 +104,7 @@ inline static void hw_clear_bits(io_rw_32 *addr, uint32_t mask) {
|
|||||||
* \param addr Address of writable register
|
* \param addr Address of writable register
|
||||||
* \param mask Bit-mask specifying bits to invert
|
* \param mask Bit-mask specifying bits to invert
|
||||||
*/
|
*/
|
||||||
inline static void hw_xor_bits(io_rw_32 *addr, uint32_t mask) {
|
__force_inline static void hw_xor_bits(io_rw_32 *addr, uint32_t mask) {
|
||||||
*(io_rw_32 *) hw_xor_alias_untyped((volatile void *) addr) = mask;
|
*(io_rw_32 *) hw_xor_alias_untyped((volatile void *) addr) = mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +120,7 @@ inline static void hw_xor_bits(io_rw_32 *addr, uint32_t mask) {
|
|||||||
* \param values Bits values
|
* \param values Bits values
|
||||||
* \param write_mask Mask of bits to change
|
* \param write_mask Mask of bits to change
|
||||||
*/
|
*/
|
||||||
inline static void hw_write_masked(io_rw_32 *addr, uint32_t values, uint32_t write_mask) {
|
__force_inline static void hw_write_masked(io_rw_32 *addr, uint32_t values, uint32_t write_mask) {
|
||||||
hw_xor_bits(addr, (*addr ^ values) & write_mask);
|
hw_xor_bits(addr, (*addr ^ values) & write_mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,2 @@
|
|||||||
add_library(hardware_claim INTERFACE)
|
pico_simple_hardware_target(claim)
|
||||||
target_include_directories(hardware_claim INTERFACE include)
|
|
||||||
target_sources(hardware_claim INTERFACE
|
|
||||||
${CMAKE_CURRENT_LIST_DIR}/claim.c)
|
|
||||||
|
|
||||||
target_link_libraries(hardware_claim INTERFACE hardware_sync)
|
target_link_libraries(hardware_claim INTERFACE hardware_sync)
|
@ -14,22 +14,13 @@ void hw_claim_unlock(uint32_t save) {
|
|||||||
spin_unlock(spin_lock_instance(PICO_SPINLOCK_ID_HARDWARE_CLAIM), save);
|
spin_unlock(spin_lock_instance(PICO_SPINLOCK_ID_HARDWARE_CLAIM), save);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hw_is_claimed(uint8_t *bits, uint bit_index) {
|
inline bool hw_is_claimed(const uint8_t *bits, uint bit_index) {
|
||||||
bool rc;
|
return (bits[bit_index >> 3u] & (1u << (bit_index & 7u)));
|
||||||
uint32_t save = hw_claim_lock();
|
|
||||||
if (bits[bit_index >> 3u] & (1u << (bit_index & 7u))) {
|
|
||||||
rc = false;
|
|
||||||
} else {
|
|
||||||
bits[bit_index >> 3u] |= (uint8_t)(1u << (bit_index & 7u));
|
|
||||||
rc = true;
|
|
||||||
}
|
|
||||||
hw_claim_unlock(save);
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void hw_claim_or_assert(uint8_t *bits, uint bit_index, const char *message) {
|
void hw_claim_or_assert(uint8_t *bits, uint bit_index, const char *message) {
|
||||||
uint32_t save = hw_claim_lock();
|
uint32_t save = hw_claim_lock();
|
||||||
if (bits[bit_index >> 3u] & (1u << (bit_index & 7u))) {
|
if (hw_is_claimed(bits, bit_index)) {
|
||||||
panic(message, bit_index);
|
panic(message, bit_index);
|
||||||
} else {
|
} else {
|
||||||
bits[bit_index >> 3u] |= (uint8_t)(1u << (bit_index & 7u));
|
bits[bit_index >> 3u] |= (uint8_t)(1u << (bit_index & 7u));
|
||||||
@ -42,7 +33,7 @@ int hw_claim_unused_from_range(uint8_t *bits, bool required, uint bit_lsb, uint
|
|||||||
uint32_t save = hw_claim_lock();
|
uint32_t save = hw_claim_lock();
|
||||||
int found_bit = -1;
|
int found_bit = -1;
|
||||||
for(uint bit=bit_lsb; bit <= bit_msb; bit++) {
|
for(uint bit=bit_lsb; bit <= bit_msb; bit++) {
|
||||||
if (!(bits[bit >> 3u] & (1u << (bit & 7u)))) {
|
if (!hw_is_claimed(bits, bit)) {
|
||||||
bits[bit >> 3u] |= (uint8_t)(1u << (bit & 7u));
|
bits[bit >> 3u] |= (uint8_t)(1u << (bit & 7u));
|
||||||
found_bit = (int)bit;
|
found_bit = (int)bit;
|
||||||
break;
|
break;
|
||||||
@ -57,7 +48,7 @@ int hw_claim_unused_from_range(uint8_t *bits, bool required, uint bit_lsb, uint
|
|||||||
|
|
||||||
void hw_claim_clear(uint8_t *bits, uint bit_index) {
|
void hw_claim_clear(uint8_t *bits, uint bit_index) {
|
||||||
uint32_t save = hw_claim_lock();
|
uint32_t save = hw_claim_lock();
|
||||||
assert(bits[bit_index >> 3u] & (1u << (bit_index & 7u)));
|
assert(hw_is_claimed(bits, bit_index));
|
||||||
bits[bit_index >> 3u] &= (uint8_t) ~(1u << (bit_index & 7u));
|
bits[bit_index >> 3u] &= (uint8_t) ~(1u << (bit_index & 7u));
|
||||||
hw_claim_unlock(save);
|
hw_claim_unlock(save);
|
||||||
}
|
}
|
||||||
|
@ -65,10 +65,10 @@ int hw_claim_unused_from_range(uint8_t *bits, bool required, uint bit_lsb, uint
|
|||||||
* The resource ownership is indicated by the bit_index bit in an array of bits.
|
* The resource ownership is indicated by the bit_index bit in an array of bits.
|
||||||
*
|
*
|
||||||
* \param bits pointer to an array of bits (8 bits per byte)
|
* \param bits pointer to an array of bits (8 bits per byte)
|
||||||
* \param bit_index resource to unclaim (bit index into array of bits)
|
* \param bit_index resource to check (bit index into array of bits)
|
||||||
* \return true if the resource is claimed
|
* \return true if the resource is claimed
|
||||||
*/
|
*/
|
||||||
bool hw_is_claimed(uint8_t *bits, uint bit_index);
|
bool hw_is_claimed(const uint8_t *bits, uint bit_index);
|
||||||
|
|
||||||
/*! \brief Atomically unclaim a resource
|
/*! \brief Atomically unclaim a resource
|
||||||
* \ingroup hardware_claim
|
* \ingroup hardware_claim
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
pico_simple_hardware_target(clocks)
|
pico_simple_hardware_target(clocks)
|
||||||
|
|
||||||
target_link_libraries(hardware_clocks INTERFACE
|
target_link_libraries(hardware_clocks INTERFACE
|
||||||
|
hardware_gpio
|
||||||
|
hardware_irq
|
||||||
hardware_resets
|
hardware_resets
|
||||||
hardware_watchdog
|
|
||||||
hardware_xosc
|
|
||||||
hardware_pll
|
hardware_pll
|
||||||
# not currently used by clocks.c, but sensibly bundled here
|
# not currently used by clocks.c, but sensibly bundled here
|
||||||
# as changing frequencies may require upping voltage
|
# as changing frequencies may require upping voltage
|
||||||
hardware_vreg
|
hardware_vreg
|
||||||
|
hardware_watchdog
|
||||||
|
hardware_xosc
|
||||||
)
|
)
|
@ -7,7 +7,6 @@
|
|||||||
#include "pico.h"
|
#include "pico.h"
|
||||||
#include "hardware/regs/clocks.h"
|
#include "hardware/regs/clocks.h"
|
||||||
#include "hardware/platform_defs.h"
|
#include "hardware/platform_defs.h"
|
||||||
#include "hardware/resets.h"
|
|
||||||
#include "hardware/clocks.h"
|
#include "hardware/clocks.h"
|
||||||
#include "hardware/watchdog.h"
|
#include "hardware/watchdog.h"
|
||||||
#include "hardware/pll.h"
|
#include "hardware/pll.h"
|
||||||
@ -71,6 +70,8 @@ bool clock_configure(enum clock_index clk_index, uint32_t src, uint32_t auxsrc,
|
|||||||
// propagating when changing aux mux. Note it would be a really bad idea
|
// propagating when changing aux mux. Note it would be a really bad idea
|
||||||
// to do this on one of the glitchless clocks (clk_sys, clk_ref).
|
// to do this on one of the glitchless clocks (clk_sys, clk_ref).
|
||||||
else {
|
else {
|
||||||
|
// Disable clock. On clk_ref and clk_sys this does nothing,
|
||||||
|
// all other clocks have the ENABLE bit in the same position.
|
||||||
hw_clear_bits(&clock->ctrl, CLOCKS_CLK_GPOUT0_CTRL_ENABLE_BITS);
|
hw_clear_bits(&clock->ctrl, CLOCKS_CLK_GPOUT0_CTRL_ENABLE_BITS);
|
||||||
if (configured_freq[clk_index] > 0) {
|
if (configured_freq[clk_index] > 0) {
|
||||||
// Delay for 3 cycles of the target clock, for ENABLE propagation.
|
// Delay for 3 cycles of the target clock, for ENABLE propagation.
|
||||||
@ -102,6 +103,8 @@ bool clock_configure(enum clock_index clk_index, uint32_t src, uint32_t auxsrc,
|
|||||||
tight_loop_contents();
|
tight_loop_contents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Enable clock. On clk_ref and clk_sys this does nothing,
|
||||||
|
// all other clocks have the ENABLE bit in the same position.
|
||||||
hw_set_bits(&clock->ctrl, CLOCKS_CLK_GPOUT0_CTRL_ENABLE_BITS);
|
hw_set_bits(&clock->ctrl, CLOCKS_CLK_GPOUT0_CTRL_ENABLE_BITS);
|
||||||
|
|
||||||
// Now that the source is configured, we can trust that the user-supplied
|
// Now that the source is configured, we can trust that the user-supplied
|
||||||
@ -109,7 +112,7 @@ bool clock_configure(enum clock_index clk_index, uint32_t src, uint32_t auxsrc,
|
|||||||
clock->div = div;
|
clock->div = div;
|
||||||
|
|
||||||
// Store the configured frequency
|
// Store the configured frequency
|
||||||
configured_freq[clk_index] = freq;
|
configured_freq[clk_index] = (uint32_t)(((uint64_t) src_freq << 8) / div);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -149,9 +152,6 @@ void clocks_init(void) {
|
|||||||
// PLL USB: 12 / 1 = 12MHz * 40 = 480 MHz / 5 / 2 = 48MHz
|
// PLL USB: 12 / 1 = 12MHz * 40 = 480 MHz / 5 / 2 = 48MHz
|
||||||
/// \end::pll_settings[]
|
/// \end::pll_settings[]
|
||||||
|
|
||||||
reset_block(RESETS_RESET_PLL_SYS_BITS | RESETS_RESET_PLL_USB_BITS);
|
|
||||||
unreset_block_wait(RESETS_RESET_PLL_SYS_BITS | RESETS_RESET_PLL_USB_BITS);
|
|
||||||
|
|
||||||
/// \tag::pll_init[]
|
/// \tag::pll_init[]
|
||||||
pll_init(pll_sys, 1, 1500 * MHZ, 6, 2);
|
pll_init(pll_sys, 1, 1500 * MHZ, 6, 2);
|
||||||
pll_init(pll_usb, 1, 480 * MHZ, 5, 2);
|
pll_init(pll_usb, 1, 480 * MHZ, 5, 2);
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
add_library(hardware_divider INTERFACE)
|
pico_simple_hardware_headers_only_target(divider)
|
||||||
target_sources(hardware_divider INTERFACE ${CMAKE_CURRENT_LIST_DIR}/divider.S)
|
target_sources(hardware_divider INTERFACE ${CMAKE_CURRENT_LIST_DIR}/divider.S)
|
||||||
target_include_directories(hardware_divider INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
|
|
||||||
target_link_libraries(hardware_divider INTERFACE hardware_structs)
|
target_link_libraries(hardware_divider INTERFACE hardware_structs)
|
@ -0,0 +1,68 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hardware/regs/addressmap.h"
|
||||||
|
#include "hardware/regs/sio.h"
|
||||||
|
|
||||||
|
#if SIO_DIV_CSR_READY_LSB == 0
|
||||||
|
.equ SIO_DIV_CSR_READY_SHIFT_FOR_CARRY, 1
|
||||||
|
#else
|
||||||
|
need to change SHIFT above
|
||||||
|
#endif
|
||||||
|
#if SIO_DIV_CSR_DIRTY_LSB == 1
|
||||||
|
.equ SIO_DIV_CSR_DIRTY_SHIFT_FOR_CARRY, 2
|
||||||
|
#else
|
||||||
|
need to change SHIFT above
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// SIO_BASE ptr in r2; pushes r4-r7, lr to stack
|
||||||
|
// requires that division started at least 2 cycles prior to the start of the macro
|
||||||
|
.macro save_div_state_and_lr
|
||||||
|
// originally we did this, however a) it uses r3, and b) the push takes 6 cycles, b)
|
||||||
|
// any IRQ which uses the divider will necessarily put the data back, which will
|
||||||
|
// immediately make it ready
|
||||||
|
//
|
||||||
|
// // ldr r3, [r2, #SIO_DIV_CSR_OFFSET]
|
||||||
|
// // // wait for results as we can't save signed-ness of operation
|
||||||
|
// // 1:
|
||||||
|
// // lsrs r3, #SIO_DIV_CSR_READY_SHIFT_FOR_CARRY
|
||||||
|
// // bcc 1b
|
||||||
|
|
||||||
|
// 6 cycles
|
||||||
|
push {r4, r5, r6, r7, lr}
|
||||||
|
// note we must read quotient last, and since it isn't the last reg, we'll not use ldmia!
|
||||||
|
ldr r4, [r2, #SIO_DIV_UDIVIDEND_OFFSET]
|
||||||
|
ldr r5, [r2, #SIO_DIV_UDIVISOR_OFFSET]
|
||||||
|
ldr r7, [r2, #SIO_DIV_REMAINDER_OFFSET]
|
||||||
|
ldr r6, [r2, #SIO_DIV_QUOTIENT_OFFSET]
|
||||||
|
.endm
|
||||||
|
|
||||||
|
// restores divider state from r4-r7, then pops them and pc
|
||||||
|
.macro restore_div_state_and_return
|
||||||
|
// writing sdividend (r4), sdivisor (r5), quotient (r6), remainder (r7) in that order
|
||||||
|
//
|
||||||
|
// it is worth considering what happens if we are interrupted
|
||||||
|
//
|
||||||
|
// after writing r4: we are DIRTY and !READY
|
||||||
|
// ... interruptor using div will complete based on incorrect inputs, but dividend at least will be
|
||||||
|
// saved/restored correctly and we'll restore the rest ourselves
|
||||||
|
// after writing r4, r5: we are DIRTY and !READY
|
||||||
|
// ... interruptor using div will complete based on possibly wrongly signed inputs, but dividend, divisor
|
||||||
|
// at least will be saved/restored correctly and and we'll restore the rest ourselves
|
||||||
|
// after writing r4, r5, r6: we are DIRTY and READY
|
||||||
|
// ... interruptor using div will dividend, divisor, quotient registers as is (what we just restored ourselves),
|
||||||
|
// and we'll restore the remainder after the fact
|
||||||
|
|
||||||
|
// note we are not use STM not because it can be restarted due to interrupt which is harmless, more because this is 1 cycle IO space
|
||||||
|
// and so 4 reads is cheaper (and we don't have to adjust r2)
|
||||||
|
// note also, that we must restore via UDIVI* rather than SDIVI* to prevent the quotient/remainder being negated on read based
|
||||||
|
// on the signs of the inputs
|
||||||
|
str r4, [r2, #SIO_DIV_UDIVIDEND_OFFSET]
|
||||||
|
str r5, [r2, #SIO_DIV_UDIVISOR_OFFSET]
|
||||||
|
str r7, [r2, #SIO_DIV_REMAINDER_OFFSET]
|
||||||
|
str r6, [r2, #SIO_DIV_QUOTIENT_OFFSET]
|
||||||
|
pop {r4, r5, r6, r7, pc}
|
||||||
|
.endm
|
@ -39,6 +39,11 @@ int dma_claim_unused_channel(bool required) {
|
|||||||
return hw_claim_unused_from_range((uint8_t*)&_claimed, required, 0, NUM_DMA_CHANNELS-1, "No DMA channels are available");
|
return hw_claim_unused_from_range((uint8_t*)&_claimed, required, 0, NUM_DMA_CHANNELS-1, "No DMA channels are available");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool dma_channel_is_claimed(uint channel) {
|
||||||
|
check_dma_channel_param(channel);
|
||||||
|
return hw_is_claimed((uint8_t *) &_claimed, channel);
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
|
|
||||||
void print_dma_ctrl(dma_channel_hw_t *channel) {
|
void print_dma_ctrl(dma_channel_hw_t *channel) {
|
||||||
|
@ -34,8 +34,12 @@ extern "C" {
|
|||||||
* * Memory to memory
|
* * Memory to memory
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// this is not defined in generated dreq.h
|
// these are not defined in generated dreq.h
|
||||||
#define DREQ_FORCE 63
|
#define DREQ_DMA_TIMER0 DMA_CH0_CTRL_TRIG_TREQ_SEL_VALUE_TIMER0
|
||||||
|
#define DREQ_DMA_TIMER1 DMA_CH0_CTRL_TRIG_TREQ_SEL_VALUE_TIMER1
|
||||||
|
#define DREQ_DMA_TIMER2 DMA_CH0_CTRL_TRIG_TREQ_SEL_VALUE_TIMER2
|
||||||
|
#define DREQ_DMA_TIMER3 DMA_CH0_CTRL_TRIG_TREQ_SEL_VALUE_TIMER3
|
||||||
|
#define DREQ_FORCE DMA_CH0_CTRL_TRIG_TREQ_SEL_VALUE_PERMANENT
|
||||||
|
|
||||||
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_DMA, Enable/disable DMA assertions, type=bool, default=0, group=hardware_dma
|
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_DMA, Enable/disable DMA assertions, type=bool, default=0, group=hardware_dma
|
||||||
#ifndef PARAM_ASSERTIONS_ENABLED_DMA
|
#ifndef PARAM_ASSERTIONS_ENABLED_DMA
|
||||||
@ -94,6 +98,16 @@ void dma_channel_unclaim(uint channel);
|
|||||||
*/
|
*/
|
||||||
int dma_claim_unused_channel(bool required);
|
int dma_claim_unused_channel(bool required);
|
||||||
|
|
||||||
|
/*! \brief Determine if a dma channel is claimed
|
||||||
|
* \ingroup hardware_dma
|
||||||
|
*
|
||||||
|
* \param channel the dma channel
|
||||||
|
* \return true if the channel is claimed, false otherwise
|
||||||
|
* \see dma_channel_claim
|
||||||
|
* \see dma_channel_claim_mask
|
||||||
|
*/
|
||||||
|
bool dma_channel_is_claimed(uint channel);
|
||||||
|
|
||||||
/** \brief DMA channel configuration
|
/** \brief DMA channel configuration
|
||||||
* \defgroup channel_config channel_config
|
* \defgroup channel_config channel_config
|
||||||
* \ingroup hardware_dma
|
* \ingroup hardware_dma
|
||||||
@ -353,7 +367,7 @@ static inline void dma_channel_set_read_addr(uint channel, const volatile void *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Set the DMA initial read address
|
/*! \brief Set the DMA initial write address
|
||||||
* \ingroup hardware_dma
|
* \ingroup hardware_dma
|
||||||
*
|
*
|
||||||
* \param channel DMA channel
|
* \param channel DMA channel
|
||||||
@ -409,7 +423,8 @@ static inline void dma_channel_configure(uint channel, const dma_channel_config
|
|||||||
* \param read_addr Sets the initial read address
|
* \param read_addr Sets the initial read address
|
||||||
* \param transfer_count Number of transfers to make. Not bytes, but the number of transfers of channel_config_set_transfer_data_size() to be sent.
|
* \param transfer_count Number of transfers to make. Not bytes, but the number of transfers of channel_config_set_transfer_data_size() to be sent.
|
||||||
*/
|
*/
|
||||||
inline static void __attribute__((always_inline)) dma_channel_transfer_from_buffer_now(uint channel, void *read_addr,
|
inline static void __attribute__((always_inline)) dma_channel_transfer_from_buffer_now(uint channel,
|
||||||
|
const volatile void *read_addr,
|
||||||
uint32_t transfer_count) {
|
uint32_t transfer_count) {
|
||||||
// check_dma_channel_param(channel);
|
// check_dma_channel_param(channel);
|
||||||
dma_channel_hw_t *hw = dma_channel_hw_addr(channel);
|
dma_channel_hw_t *hw = dma_channel_hw_addr(channel);
|
||||||
@ -424,7 +439,7 @@ inline static void __attribute__((always_inline)) dma_channel_transfer_from_buff
|
|||||||
* \param write_addr Sets the initial write address
|
* \param write_addr Sets the initial write address
|
||||||
* \param transfer_count Number of transfers to make. Not bytes, but the number of transfers of channel_config_set_transfer_data_size() to be sent.
|
* \param transfer_count Number of transfers to make. Not bytes, but the number of transfers of channel_config_set_transfer_data_size() to be sent.
|
||||||
*/
|
*/
|
||||||
inline static void dma_channel_transfer_to_buffer_now(uint channel, void *write_addr, uint32_t transfer_count) {
|
inline static void dma_channel_transfer_to_buffer_now(uint channel, volatile void *write_addr, uint32_t transfer_count) {
|
||||||
dma_channel_hw_t *hw = dma_channel_hw_addr(channel);
|
dma_channel_hw_t *hw = dma_channel_hw_addr(channel);
|
||||||
hw->write_addr = (uintptr_t) write_addr;
|
hw->write_addr = (uintptr_t) write_addr;
|
||||||
hw->al1_transfer_count_trig = transfer_count;
|
hw->al1_transfer_count_trig = transfer_count;
|
||||||
@ -464,7 +479,7 @@ static inline void dma_channel_abort(uint channel) {
|
|||||||
while (dma_hw->abort & (1ul << channel)) tight_loop_contents();
|
while (dma_hw->abort & (1ul << channel)) tight_loop_contents();
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Enable single DMA channel interrupt 0
|
/*! \brief Enable single DMA channel's interrupt via DMA_IRQ_0
|
||||||
* \ingroup hardware_dma
|
* \ingroup hardware_dma
|
||||||
*
|
*
|
||||||
* \param channel DMA channel
|
* \param channel DMA channel
|
||||||
@ -479,7 +494,7 @@ static inline void dma_channel_set_irq0_enabled(uint channel, bool enabled) {
|
|||||||
hw_clear_bits(&dma_hw->inte0, 1u << channel);
|
hw_clear_bits(&dma_hw->inte0, 1u << channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Enable multiple DMA channels interrupt 0
|
/*! \brief Enable multiple DMA channels' interrupts via DMA_IRQ_0
|
||||||
* \ingroup hardware_dma
|
* \ingroup hardware_dma
|
||||||
*
|
*
|
||||||
* \param channel_mask Bitmask of all the channels to enable/disable. Channel 0 = bit 0, channel 1 = bit 1 etc.
|
* \param channel_mask Bitmask of all the channels to enable/disable. Channel 0 = bit 0, channel 1 = bit 1 etc.
|
||||||
@ -493,7 +508,7 @@ static inline void dma_set_irq0_channel_mask_enabled(uint32_t channel_mask, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Enable single DMA channel interrupt 1
|
/*! \brief Enable single DMA channel's interrupt via DMA_IRQ_1
|
||||||
* \ingroup hardware_dma
|
* \ingroup hardware_dma
|
||||||
*
|
*
|
||||||
* \param channel DMA channel
|
* \param channel DMA channel
|
||||||
@ -508,7 +523,7 @@ static inline void dma_channel_set_irq1_enabled(uint channel, bool enabled) {
|
|||||||
hw_clear_bits(&dma_hw->inte1, 1u << channel);
|
hw_clear_bits(&dma_hw->inte1, 1u << channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! \brief Enable multiple DMA channels interrupt 0
|
/*! \brief Enable multiple DMA channels' interrupts via DMA_IRQ_1
|
||||||
* \ingroup hardware_dma
|
* \ingroup hardware_dma
|
||||||
*
|
*
|
||||||
* \param channel_mask Bitmask of all the channels to enable/disable. Channel 0 = bit 0, channel 1 = bit 1 etc.
|
* \param channel_mask Bitmask of all the channels to enable/disable. Channel 0 = bit 0, channel 1 = bit 1 etc.
|
||||||
@ -522,6 +537,105 @@ static inline void dma_set_irq1_channel_mask_enabled(uint32_t channel_mask, bool
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! \brief Enable single DMA channel interrupt on either DMA_IRQ_0 or DMA_IRQ_1
|
||||||
|
* \ingroup hardware_dma
|
||||||
|
*
|
||||||
|
* \param irq_index the IRQ index; either 0 or 1 for DMA_IRQ_0 or DMA_IRQ_1
|
||||||
|
* \param channel DMA channel
|
||||||
|
* \param enabled true to enable interrupt via irq_index for specified channel, false to disable.
|
||||||
|
*/
|
||||||
|
static inline void dma_irqn_set_channel_enabled(uint irq_index, uint channel, bool enabled) {
|
||||||
|
invalid_params_if(DMA, irq_index > 1);
|
||||||
|
if (irq_index) {
|
||||||
|
dma_channel_set_irq1_enabled(channel, enabled);
|
||||||
|
} else {
|
||||||
|
dma_channel_set_irq0_enabled(channel, enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Enable multiple DMA channels' interrupt via either DMA_IRQ_0 or DMA_IRQ_1
|
||||||
|
* \ingroup hardware_dma
|
||||||
|
*
|
||||||
|
* \param irq_index the IRQ index; either 0 or 1 for DMA_IRQ_0 or DMA_IRQ_1
|
||||||
|
* \param channel_mask Bitmask of all the channels to enable/disable. Channel 0 = bit 0, channel 1 = bit 1 etc.
|
||||||
|
* \param enabled true to enable all the interrupts specified in the mask, false to disable all the interrupts specified in the mask.
|
||||||
|
*/
|
||||||
|
static inline void dma_irqn_set_channel_mask_enabled(uint irq_index, uint32_t channel_mask, bool enabled) {
|
||||||
|
invalid_params_if(DMA, irq_index > 1);
|
||||||
|
if (irq_index) {
|
||||||
|
dma_set_irq1_channel_mask_enabled(channel_mask, enabled);
|
||||||
|
} else {
|
||||||
|
dma_set_irq0_channel_mask_enabled(channel_mask, enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Determine if a particular channel is a cause of DMA_IRQ_0
|
||||||
|
* \ingroup hardware_dma
|
||||||
|
*
|
||||||
|
* \param channel DMA channel
|
||||||
|
* \return true if the channel is a cause of DMA_IRQ_0, false otherwise
|
||||||
|
*/
|
||||||
|
static inline bool dma_channel_get_irq0_status(uint channel) {
|
||||||
|
check_dma_channel_param(channel);
|
||||||
|
return dma_hw->ints0 & (1u << channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Determine if a particular channel is a cause of DMA_IRQ_1
|
||||||
|
* \ingroup hardware_dma
|
||||||
|
*
|
||||||
|
* \param channel DMA channel
|
||||||
|
* \return true if the channel is a cause of DMA_IRQ_1, false otherwise
|
||||||
|
*/
|
||||||
|
static inline bool dma_channel_get_irq1_status(uint channel) {
|
||||||
|
check_dma_channel_param(channel);
|
||||||
|
return dma_hw->ints1 & (1u << channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Determine if a particular channel is a cause of DMA_IRQ_N
|
||||||
|
* \ingroup hardware_dma
|
||||||
|
*
|
||||||
|
* \param irq_index the IRQ index; either 0 or 1 for DMA_IRQ_0 or DMA_IRQ_1
|
||||||
|
* \param channel DMA channel
|
||||||
|
* \return true if the channel is a cause of the DMA_IRQ_N, false otherwise
|
||||||
|
*/
|
||||||
|
static inline bool dma_irqn_get_channel_status(uint irq_index, uint channel) {
|
||||||
|
invalid_params_if(DMA, irq_index > 1);
|
||||||
|
check_dma_channel_param(channel);
|
||||||
|
return (irq_index ? dma_hw->ints1 : dma_hw->ints0) & (1u << channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_0
|
||||||
|
* \ingroup hardware_dma
|
||||||
|
*
|
||||||
|
* \param channel DMA channel
|
||||||
|
*/
|
||||||
|
static inline void dma_channel_acknowledge_irq0(uint channel) {
|
||||||
|
check_dma_channel_param(channel);
|
||||||
|
hw_set_bits(&dma_hw->ints0, (1u << channel));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_1
|
||||||
|
* \ingroup hardware_dma
|
||||||
|
*
|
||||||
|
* \param channel DMA channel
|
||||||
|
*/
|
||||||
|
static inline void dma_channel_acknowledge_irq1(uint channel) {
|
||||||
|
check_dma_channel_param(channel);
|
||||||
|
hw_set_bits(&dma_hw->ints1, (1u << channel));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! \brief Acknowledge a channel IRQ, resetting it as the cause of DMA_IRQ_N
|
||||||
|
* \ingroup hardware_dma
|
||||||
|
*
|
||||||
|
* \param irq_index the IRQ index; either 0 or 1 for DMA_IRQ_0 or DMA_IRQ_1
|
||||||
|
* \param channel DMA channel
|
||||||
|
*/
|
||||||
|
static inline void dma_irqn_acknowledge_channel(uint irq_index, uint channel) {
|
||||||
|
invalid_params_if(DMA, irq_index > 1);
|
||||||
|
check_dma_channel_param(channel);
|
||||||
|
hw_set_bits(irq_index ? &dma_hw->ints1 : &dma_hw->ints0, (1u << channel));
|
||||||
|
}
|
||||||
|
|
||||||
/*! \brief Check if DMA channel is busy
|
/*! \brief Check if DMA channel is busy
|
||||||
* \ingroup hardware_dma
|
* \ingroup hardware_dma
|
||||||
*
|
*
|
||||||
|
1
src/rp2_common/hardware_exception/CMakeLists.txt
Normal file
1
src/rp2_common/hardware_exception/CMakeLists.txt
Normal file
@ -0,0 +1 @@
|
|||||||
|
pico_simple_hardware_target(exception)
|
65
src/rp2_common/hardware_exception/exception.c
Normal file
65
src/rp2_common/hardware_exception/exception.c
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "hardware/exception.h"
|
||||||
|
#include "hardware/regs/m0plus.h"
|
||||||
|
#include "hardware/platform_defs.h"
|
||||||
|
#include "hardware/structs/scb.h"
|
||||||
|
|
||||||
|
#include "pico/mutex.h"
|
||||||
|
#include "pico/assert.h"
|
||||||
|
|
||||||
|
#ifndef exception_is_compile_time_default
|
||||||
|
static bool exception_is_compile_time_default(exception_handler_t handler) {
|
||||||
|
extern char __default_isrs_start;
|
||||||
|
extern char __default_isrs_end;
|
||||||
|
return ((uintptr_t)handler) >= (uintptr_t)&__default_isrs_start &&
|
||||||
|
((uintptr_t)handler) < (uintptr_t)&__default_isrs_end;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline exception_handler_t *get_vtable(void) {
|
||||||
|
return (exception_handler_t *) scb_hw->vtor;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void set_raw_exception_handler_and_restore_interrupts(enum exception_number num, exception_handler_t handler, uint32_t save) {
|
||||||
|
// update vtable (vtable_handler may be same or updated depending on cases, but we do it anyway for compactness)
|
||||||
|
get_vtable()[16 + num] = handler;
|
||||||
|
__dmb();
|
||||||
|
restore_interrupts(save);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void check_exception_param(__unused enum exception_number num) {
|
||||||
|
invalid_params_if(EXCEPTION, num < NMI_EXCEPTION || num >=0);
|
||||||
|
}
|
||||||
|
|
||||||
|
exception_handler_t exception_get_vtable_handler(enum exception_number num) {
|
||||||
|
check_exception_param(num);
|
||||||
|
return get_vtable()[16 + num];
|
||||||
|
}
|
||||||
|
|
||||||
|
exception_handler_t exception_set_exclusive_handler(enum exception_number num, exception_handler_t handler) {
|
||||||
|
check_exception_param(num);
|
||||||
|
#if !PICO_NO_RAM_VECTOR_TABLE
|
||||||
|
uint32_t save = save_and_disable_interrupts();
|
||||||
|
exception_handler_t current = exception_get_vtable_handler(num);
|
||||||
|
hard_assert(handler == current || exception_is_compile_time_default(current));
|
||||||
|
set_raw_exception_handler_and_restore_interrupts(num, handler, save);
|
||||||
|
#else
|
||||||
|
panic_unsupported();
|
||||||
|
#endif
|
||||||
|
return current;
|
||||||
|
}
|
||||||
|
|
||||||
|
void exception_restore_handler(enum exception_number num, exception_handler_t original_handler) {
|
||||||
|
hard_assert(exception_is_compile_time_default(original_handler));
|
||||||
|
#if !PICO_NO_RAM_VECTOR_TABLE
|
||||||
|
uint32_t save = save_and_disable_interrupts();
|
||||||
|
set_raw_exception_handler_and_restore_interrupts(num, original_handler, save);
|
||||||
|
#else
|
||||||
|
panic_unsupported();
|
||||||
|
#endif
|
||||||
|
}
|
106
src/rp2_common/hardware_exception/include/hardware/exception.h
Normal file
106
src/rp2_common/hardware_exception/include/hardware/exception.h
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-3-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _HARDWARE_EXCEPTION_H_
|
||||||
|
#define _HARDWARE_EXCEPTION_H_
|
||||||
|
|
||||||
|
#include "pico.h"
|
||||||
|
#include "hardware/address_mapped.h"
|
||||||
|
#include "hardware/regs/m0plus.h"
|
||||||
|
|
||||||
|
/** \file exception.h
|
||||||
|
* \defgroup hardware_exception hardware_exception
|
||||||
|
*
|
||||||
|
* Methods for setting processor exception handlers
|
||||||
|
*
|
||||||
|
* Exceptions are identified by a \ref exception_num which is a number from -15 to -1; these are the numbers relative to
|
||||||
|
* the index of the first IRQ vector in the vector table. (i.e. vector table index is exception_num plus 16)
|
||||||
|
*
|
||||||
|
* There is one set of exception handlers per core, so the exception handlers for each core as set by these methods are independent.
|
||||||
|
*
|
||||||
|
* \note That all exception APIs affect the executing core only (i.e. the core calling the function).
|
||||||
|
*/
|
||||||
|
|
||||||
|
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_EXCEPTION, Enable/disable assertions in the exception module, type=bool, default=0, group=hardware_exception
|
||||||
|
#ifndef PARAM_ASSERTIONS_ENABLED_EXCEPTION
|
||||||
|
#define PARAM_ASSERTIONS_ENABLED_EXCEPTION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*! \brief Exception number definitions
|
||||||
|
*
|
||||||
|
* Note for consistency with irq numbers, these numbers are defined to be negative. The VTABLE index is
|
||||||
|
* the number here plus 16.
|
||||||
|
*
|
||||||
|
* Name | Value | Exception
|
||||||
|
* ---------------------|-------|----------
|
||||||
|
* NMI_EXCEPTION | -14 | Non Maskable Interrupt
|
||||||
|
* HARDFAULT_EXCEPTION | -13 | HardFault
|
||||||
|
* SVCALL_EXCEPTION | -5 | SV Call
|
||||||
|
* PENDSV_EXCEPTION | -2 | Pend SV
|
||||||
|
* SYSTICK_EXCEPTION | -1 | System Tick
|
||||||
|
*
|
||||||
|
* \ingroup hardware_exception
|
||||||
|
*/
|
||||||
|
enum exception_number {
|
||||||
|
NMI_EXCEPTION = -14, /* Non Maskable Interrupt */
|
||||||
|
HARDFAULT_EXCEPTION = -13, /* HardFault Interrupt */
|
||||||
|
SVCALL_EXCEPTION = -5, /* SV Call Interrupt */
|
||||||
|
PENDSV_EXCEPTION = -2, /* Pend SV Interrupt */
|
||||||
|
SYSTICK_EXCEPTION = -1, /* System Tick Interrupt */
|
||||||
|
};
|
||||||
|
|
||||||
|
/*! \brief Exception handler function type
|
||||||
|
* \ingroup hardware_exception
|
||||||
|
*
|
||||||
|
* All exception handlers should be of this type, and follow normal ARM EABI register saving conventions
|
||||||
|
*/
|
||||||
|
typedef void (*exception_handler_t)(void);
|
||||||
|
|
||||||
|
/*! \brief Set the exception handler for an exception on the executing core.
|
||||||
|
* \ingroup hardware_exception
|
||||||
|
*
|
||||||
|
* This method will assert if an exception handler has been set for this exception number on this core via
|
||||||
|
* this method, without an intervening restore via exception_restore_handler.
|
||||||
|
*
|
||||||
|
* \note this method may not be used to override an exception handler that was specified at link time by
|
||||||
|
* providing a strong replacement for the weakly defined stub exception handlers. It will assert in this case too.
|
||||||
|
*
|
||||||
|
* \param num Exception number
|
||||||
|
* \param handler The handler to set
|
||||||
|
* \see exception_number
|
||||||
|
*/
|
||||||
|
exception_handler_t exception_set_exclusive_handler(enum exception_number num, exception_handler_t handler);
|
||||||
|
|
||||||
|
/*! \brief Restore the original exception handler for an exception on this core
|
||||||
|
* \ingroup hardware_exception
|
||||||
|
*
|
||||||
|
* This method may be used to restore the exception handler for an exception on this core to the state
|
||||||
|
* prior to the call to exception_set_exclusive_handler(), so that exception_set_exclusive_handler()
|
||||||
|
* may be called again in the future.
|
||||||
|
*
|
||||||
|
* \param num Exception number \ref exception_nums
|
||||||
|
* \param original_handler The original handler returned from \ref exception_set_exclusive_handler
|
||||||
|
* \see exception_set_exclusive_handler()
|
||||||
|
*/
|
||||||
|
void exception_restore_handler(enum exception_number, exception_handler_t original_handler);
|
||||||
|
|
||||||
|
/*! \brief Get the current exception handler for the specified exception from the currently installed vector table
|
||||||
|
* of the execution core
|
||||||
|
* \ingroup hardware_exception
|
||||||
|
*
|
||||||
|
* \param num Exception number
|
||||||
|
* \return the address stored in the VTABLE for the given exception number
|
||||||
|
*/
|
||||||
|
exception_handler_t exception_get_vtable_handler(enum exception_number num);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user