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:
Graham Sanderson 2021-06-03 10:46:02 -05:00 committed by GitHub
commit bfcbefafc5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
184 changed files with 25748 additions and 1095 deletions

3
.gitmodules vendored
View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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()

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -1,12 +1,14 @@
# 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)
add_library(_pico_sdk_pre_init_marker INTERFACE)
function(pico_is_top_level_project VAR)
string(TOLOWER ${CMAKE_CURRENT_LIST_DIR} __list_dir) string(TOLOWER ${CMAKE_CURRENT_LIST_DIR} __list_dir)
string(TOLOWER ${CMAKE_SOURCE_DIR} __source_dir) string(TOLOWER ${CMAKE_SOURCE_DIR} __source_dir)
if (__source_dir STREQUAL __list_dir) if (__source_dir STREQUAL __list_dir)
@ -14,41 +16,79 @@ function(pico_is_top_level_project VAR)
else() else()
set(${VAR} 0 PARENT_SCOPE) set(${VAR} 0 PARENT_SCOPE)
endif() endif()
endfunction() endfunction()
if (NOT PICO_SDK_PATH) 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()
if (NOT PICO_SDK_PATH)
set(PICO_SDK_PATH ${CMAKE_CURRENT_LIST_DIR}) set(PICO_SDK_PATH ${CMAKE_CURRENT_LIST_DIR})
endif () endif ()
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
set(PICO_SDK_PATH ${CMAKE_CURRENT_LIST_DIR} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) set(PICO_SDK_PATH ${CMAKE_CURRENT_LIST_DIR} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE)
list(APPEND CMAKE_MODULE_PATH ${PICO_SDK_PATH}/cmake) list(APPEND CMAKE_MODULE_PATH ${PICO_SDK_PATH}/cmake)
include(${CMAKE_CURRENT_LIST_DIR}/pico_sdk_version.cmake) include(${CMAKE_CURRENT_LIST_DIR}/pico_sdk_version.cmake)
include(pico_utils) include(pico_utils)
message("PICO_SDK_PATH is ${CMAKE_CURRENT_LIST_DIR}") message("PICO_SDK_PATH is ${CMAKE_CURRENT_LIST_DIR}")
include(pico_pre_load_platform) include(pico_pre_load_platform)
# todo perhaps this should be included by the platform instead? # We want to configure correct toolchain prior to project load
# We want to configure correct toolchain prior to project load # todo perhaps this should be included by the platform instead?
include(pico_pre_load_toolchain) include(pico_pre_load_toolchain)
macro(pico_sdk_init) macro(pico_sdk_init)
if (NOT CMAKE_PROJECT_NAME) if (NOT CMAKE_PROJECT_NAME)
message(WARNING "pico_sdk_init() should be called after the project is created (and languages added)") message(WARNING "pico_sdk_init() should be called after the project is created (and languages added)")
endif() endif()
add_subdirectory(${PICO_SDK_PATH} pico-sdk) add_subdirectory(${PICO_SDK_PATH} pico-sdk)
endmacro() pico_is_top_level_project(ISTOP)
endmacro()
macro(add_sub_list_dirs var) macro(add_sub_list_dirs var)
foreach(LIST_DIR IN LISTS ${var}) foreach(LIST_DIR IN LISTS ${var})
get_filename_component(SHORT_NAME "${LIST_DIR}" NAME) get_filename_component(SHORT_NAME "${LIST_DIR}" NAME)
message("Including custom CMakeLists.txt ${SHORT_NAME}") pico_message_debug("Including custom CMakeLists.txt ${SHORT_NAME}")
add_subdirectory(${LIST_DIR} ${SHORT_NAME}) add_subdirectory(${LIST_DIR} ${SHORT_NAME})
endforeach() endforeach()
endmacro() 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()

View File

@ -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

View File

@ -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
@ -87,3 +117,5 @@ function(pico_add_doxygen_exclude SOURCE_DIR)
endfunction() endfunction()
include(${PICO_PLATFORM_CMAKE_FILE}) include(${PICO_PLATFORM_CMAKE_FILE})
pico_promote_common_scope_vars()

View File

@ -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

View File

@ -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

View File

@ -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

View 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

View File

@ -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

View File

@ -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

View 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

View 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

View 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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -14,3 +14,5 @@ if (NOT PICO_BARE_METAL)
endif() endif()
pico_add_doxygen(${CMAKE_CURRENT_LIST_DIR}) pico_add_doxygen(${CMAKE_CURRENT_LIST_DIR})
pico_promote_common_scope_vars()

View File

@ -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()

View 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()

View File

@ -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)

View File

@ -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

View File

@ -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()

View File

@ -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
} }

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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) {
mtx->recursion_state--;
} else {
if (lock_internal_spin_unlock_with_best_effort_wait_or_timeout(&mtx->core, save, until)) {
// timed out
return false;
} else {
// not timed out; spin lock already unlocked, so loop again
continue;
}
} }
spin_unlock(mtx->core.spin_lock, save); spin_unlock(mtx->core.spin_lock, save);
if (block) {
if (best_effort_wfe_or_timeout(until)) {
return false;
}
}
} while (block);
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;
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); spin_unlock(mtx->core.spin_lock, save);
}
}
} }

View File

@ -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) {
if (is_nil_time(target)) {
target = make_timeout_time_ms(timeout_ms);
}
if (best_effort_wfe_or_timeout(target)) {
return false; return false;
} }
} } while (true);
} while (block);
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); spin_unlock(sem->core.spin_lock, save);
return rc; return false;
}
} }
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;
lock_internal_spin_unlock_with_notify(&sem->core, save);
} else {
sem->permits = permits; sem->permits = permits;
spin_unlock(sem->core.spin_lock, save); spin_unlock(sem->core.spin_lock, save);
}
} }

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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 (block) {
if (success) __sev(); lock_internal_spin_unlock_with_wait(&q->core, save);
return success; } else {
spin_unlock(q->core.spin_lock, save);
return false;
}
} while (true);
} }
bool queue_try_remove(queue_t *q, void *data) { static bool queue_remove_internal(queue_t *q, 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) != 0) { if (queue_get_level_unsafe(q) != 0) {
memcpy(data, element_ptr(q, q->rptr), q->element_size); memcpy(data, element_ptr(q, q->rptr), q->element_size);
q->rptr = inc_index(q, q->rptr); q->rptr = inc_index(q, q->rptr);
success = true; lock_internal_spin_unlock_with_notify(&q->core, save);
return true;
} }
spin_unlock(q->lock, flags); if (block) {
if (success) __sev(); lock_internal_spin_unlock_with_wait(&q->core, save);
return success; } 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) {
return queue_remove_internal(q, data, false);
} }
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);
} }

View File

@ -33,3 +33,5 @@ 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()

View File

@ -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) {

View File

@ -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) {
} }

View File

@ -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);

View File

@ -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

View File

@ -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)

View File

@ -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)

View File

@ -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()

View File

@ -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);

View File

@ -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)
if (COMMAND pico_add_platform_library)
pico_add_platform_library(pico_platform)
else()
add_library(pico_platform INTERFACE) 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

View File

@ -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)));

View File

@ -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()

View File

@ -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()

View File

@ -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

View File

@ -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()

View File

@ -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.

View File

@ -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)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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()

View 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

View File

@ -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

View 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()

View 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 */

View 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 */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View 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 */

File diff suppressed because it is too large Load Diff

View 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__ */

View 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

File diff suppressed because it is too large Load Diff

View 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

View File

@ -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 */

View File

@ -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 */

View File

@ -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();
}

View 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.

View File

@ -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
* *

View File

@ -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);
} }

View File

@ -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)

View File

@ -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);
} }

View File

@ -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

View File

@ -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
) )

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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) {

View File

@ -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
* *

View File

@ -0,0 +1 @@
pico_simple_hardware_target(exception)

View 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
}

View 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