Initial Release

This commit is contained in:
graham sanderson 2021-01-20 10:44:27 -06:00
commit 26653ea81e
404 changed files with 135614 additions and 0 deletions

5
.gitignore vendored Normal file
View File

@ -0,0 +1,5 @@
.idea
.vscode
cmake-*
.DS_Store
build

4
.gitmodules vendored Normal file
View File

@ -0,0 +1,4 @@
[submodule "tinyusb"]
path = lib/tinyusb
url = git@github.com:raspberrypi/tinyusb.git
branch = pico

47
CMakeLists.txt Normal file
View File

@ -0,0 +1,47 @@
cmake_minimum_required(VERSION 3.12)
if (NOT TARGET _pico_sdk_inclusion_marker)
add_library(_pico_sdk_inclusion_marker INTERFACE)
include(pico_sdk_init.cmake)
project(pico_sdk C CXX ASM)
if ("${CMAKE_BUILD_TYPE}" STREQUAL "Debug")
if (PICO_DEOPTIMIZED_DEBUG)
message("Using fully de-optimized debug build (set PICO_DEOPTIMIZED_DEBUG=0 to optimize)")
else()
message("Using regular optimized debug build (set PICO_DEOPTIMIZED_DEBUG=1 to de-optimize)")
endif()
endif()
pico_is_top_level_project(PICO_SDK_TOP_LEVEL_PROJECT)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 11)
if (NOT PICO_SDK_TOP_LEVEL_PROJECT)
set(PICO_SDK 1 PARENT_SCOPE)
endif()
# allow customization
add_sub_list_dirs(PICO_SDK_PRE_LIST_DIRS)
add_subdirectory(tools)
add_subdirectory(src)
add_compile_options(-Winline)
if (PICO_SDK_TOP_LEVEL_PROJECT AND NOT DEFINED PICO_SDK_TESTS_ENABLED)
set(PICO_SDK_TESTS_ENABLED 1)
endif()
if (PICO_SDK_TESTS_ENABLED)
add_subdirectory(test)
endif ()
set(PICO_SDK_TESTS_ENABLED "${PICO_SDK_TESTS_ENABLED}" CACHE INTERNAL "Enable build of SDK tests")
# allow customization
add_sub_list_dirs(PICO_SDK_POST_LIST_DIRS)
# add docs at the end, as we gather documentation dirs as we go
add_subdirectory(docs)
endif()

21
LICENSE.TXT Normal file
View File

@ -0,0 +1,21 @@
Copyright 2020 (c) 2020 Raspberry Pi (Trading) Ltd.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

160
README.md Normal file
View File

@ -0,0 +1,160 @@
# Pico SDK
The Pico SDK provides the headers, libraries and build system
necessary to write programs for the RP2040 based devices such as the Raspberry Pi Pico
in C, C++ or assembly language.
The Pico SDK is designed to provide an API and programming environment that is familiar both to non-embedded C developers and embedded C developers alike.
A single program runs on the device at a time and startrs with a conventional `main()` method. Standard C/C++ libraries are supported along with
C level libraries/APIs for accessing all of the RP2040's hardware include PIO (Programmable IO)
Additionally the Pico SDK provides higher level libraries for dealing with timers, synchronization, USB (TinyUSB) and multi-core programming
along with various utilities.
The Pico SDK can be used to build anything from simple applications, full fledged runtime environments such as MicroPython, to low level software
such as RP2040's on chip bootrom itself.
Additional libraries/APIs that are not yet ready for inclusion in the Pico SDK can be found in [pico-extras](https://github.com/raspberrypi/pico-extras).
# Documentation
See [Getting Started with the Raspberry Pi Pico](https://rptl.io/pico-get-started) for information on how to setup your
hardware, IDE/environment and for how to build and debug software for the Raspberry Pi Pico
and other RP2040 based devices.
See [Pico C/C++ SDK](https://rptl.io/pico-c-sdk) to learn more about programming using the
Pico SDK, exploring more advanced features, and complete PDF based API documentation.
See [Online Pico SDK API docs](https://rptl.io/pico-doxygen) for HTML based API documentation.
# Example code
See [pico-examples](https://github.com/raspberrypi/pico-examples) for example code you can build.
# Quick-start your own project
These instructions are exteremly terse, and Linux based only. For detailed steps,
instructions for other platforms, and just in general, we recommend you see [Pico C/C++ SDK](https://rptl.io/pico-c-sdk)
1. Install CMake (at least version 3.12), and GCC cross compiler
```
sudo apt install cmake gcc-arm-none-eabi
```
1. Set up your project to point to use the Pico SDK
* By cloning the Pico SDK locally (most common)
1. `git clone` this Pico SDK repository
1. Copy [pico_sdk_import.cmake](https://github.com/raspberrypi/pico-sdk/blob/master/external/pico_sdk_import.cmake)
from the SDK into your project directory
2. Set `PICO_SDK_PATH` to the SDK location in your environment, or pass it (`-DPICO_SDK_PATH=`) to cmake later.
3. Setup a `CMakeLists.txt` like:
```cmake
cmake_minimum_required(VERSION 3.12)
# initialize the SDK based on PICO_SDK_PATH
# note: this must happen before project()
include(pico_sdk_import.cmake)
project(my_project)
# initialize the Pico SDK
pico_sdk_init()
# rest of your project
```
* With Pico SDK as a submodule
1. Clone the SDK as a submodule called `pico-sdk`
1. Setup a `CMakeLists.txt` like:
```cmake
cmake_minimum_required(VERSION 3.12)
# initialize pico_sdk from submodule
# note: this must happen before project()
include(pico-sdk/pico_sdk_init.cmake)
project(my_project)
# initialize the Pico SDK
pico_sdk_init()
# rest of your project
```
* With automatic download from github
1. Copy [pico_sdk_import.cmake](https://github.com/raspberrypi/pico-sdk/blob/master/external/pico_sdk_import.cmake)
from the SDK into your project directory
1. Setup a `CMakeLists.txt` like:
```cmake
cmake_minimum_required(VERSION 3.12)
# initialize pico_sdk from GIT
# (note this can come from environment, CMake cache etc)
set(PICO_SDK_FETCH_FROM_GIT on)
# pico_sdk_import.cmake is a single file copied from this SDK
# note: this must happen before project()
include(pico_sdk_import.cmake)
project(my_project)
# initialize the Pico SDK
pico_sdk_init()
# rest of your project
```
3. Setup a CMake build directory.
For example, if not using an IDE:
```
$ mkdir build
$ cd build
$ cmake ..
```
4. Write your code (see [pico-examples](https://github.com/raspberrypi/pico-examples) or the [Pico C/C++ SDK](https://rptl.io/pico-c-sdk) documentation
for more information)
About the simplest you can do is a single source file (e.g. hello_world.c)
```c
#include <stdio.h>
#include "pico/stdlib.h"
int main() {
setup_default_uart();
printf("Hello, world!\n");
return 0;
}
```
And add the following to your `CMakeLists.txt`:
```cmake
add_executable(hello_world
hello_world.c
)
# Add pico_stdlib library which aggregates commonly used features
target_link_libraries(hello_world pico_stdlib)
# create map/bin/hex/uf2 file in addition to ELF.
pico_add_extra_outputs(hello_world)
```
Note this example uses the default UART for _stdout_;
if you want ot use the default USB see the [hello-usb](https://github.com/raspberrypi/pico-examples/tree/master/hello_world/usb) example.
5. Make your target from the build directory you created.
```sh
$ make hello_world
```
6. You now have `hello_world.elf` to load via a debugger, or `hello_world.uf2` that can be installed and
run on your Raspberry Pi Pico via drag and drop.

View File

@ -0,0 +1,4 @@
# this is included because toolchain file sets SYSTEM_NAME=PICO
set_property(GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS FALSE)
set(CMAKE_EXECUTABLE_SUFFIX .elf)

View File

@ -0,0 +1,29 @@
# PICO_CMAKE_CONFIG: PICO_PLATFORM, platform to build for e.g. rp2040/host, default=rp2040 or environment value, group=build
if (DEFINED ENV{PICO_PLATFORM} AND (NOT PICO_PLATFORM))
set(PICO_PLATFORM $ENV{PICO_PLATFORM})
message("Using PICO_PLATFORM from environment ('${PICO_PLATFORM}')")
else()
if (NOT PICO_PLATFORM)
set(PICO_PLATFORM "rp2040")
pico_message("Defaulting PICO_PLATFORM to ${PICO_PLATFORM} since not specified.")
else()
message("PICO platform is ${PICO_PLATFORM}.")
endif()
endif ()
set(PICO_PLATFORM ${PICO_PLATFORM} CACHE STRING "PICO Build platform (e.g. rp2040, host)")
# PICO_CMAKE_CONFIG: PICO_CMAKE_RELOAD_PLATFORM_FILE, custom CMake file to use to set up the platform environment, default=none, group=build
set(PICO_CMAKE_PRELOAD_PLATFORM_FILE "" CACHE INTERNAL "")
set(PICO_CMAKE_PRELOAD_PLATFORM_DIR "${CMAKE_CURRENT_LIST_DIR}/preload/platforms" CACHE INTERNAL "")
if (NOT PICO_CMAKE_PRELOAD_PLATFORM_FILE)
set(PICO_CMAKE_PRELOAD_PLATFORM_FILE ${PICO_CMAKE_PRELOAD_PLATFORM_DIR}/${PICO_PLATFORM}.cmake CACHE INTERNAL "")
endif ()
if (NOT EXISTS "${PICO_CMAKE_PRELOAD_PLATFORM_FILE}")
message(FATAL_ERROR "${PICO_CMAKE_PRELOAD_PLATFORM_FILE} does not exist. \
Either specify a valid PICO_PLATFORM (or PICO_CMAKE_PRELOAD_PLATFORM_FILE).")
endif ()
include(${PICO_CMAKE_PRELOAD_PLATFORM_FILE})

View File

@ -0,0 +1,44 @@
# PICO_CMAKE_CONFIG: PICO_TOOLCHAIN_PATH, Path to search for compiler, default=none (i.e. search system paths), group=build
# Set your compiler path here if it's not in the PATH environment variable.
set(PICO_TOOLCHAIN_PATH "" CACHE INTERNAL "")
# Set a default build type if none was specified
set(default_build_type "Release")
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Defaulting build type to '${default_build_type}' since not specified.")
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build, options are: 'Debug', 'Release', 'MinSizeRel', 'RelWithDebInfo'." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS
"Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
if (CMAKE_BUILD_TYPE STREQUAL "Default")
error("Default build type is NOT supported")
endif()
# PICO_CMAKE_CONFIG: PICO_COMPILER, Optionally specifies a different compiler (other than pico_arm_gcc.cmake) - this is not yet fully supported, default=none, group=build
# If PICO_COMPILER is specified, set toolchain file to ${PICO_COMPILER}.cmake.
if (DEFINED PICO_COMPILER)
if (DEFINED CMAKE_TOOLCHAIN_FILE)
get_filename_component(toolchain "${CMAKE_TOOLCHAIN_FILE}" NAME_WE)
if (NOT "${PICO_COMPILER}" STREQUAL "${toolchain}")
message(WARNING "CMAKE_TOOLCHAIN_FILE is already defined to ${toolchain}.cmake, you\
need to delete cache and reconfigure if you want to switch compiler.")
endif ()
else ()
set(toolchain_dir "${CMAKE_CURRENT_LIST_DIR}/preload/toolchains")
set(toolchain_file "${toolchain_dir}/${PICO_COMPILER}.cmake")
if (EXISTS "${toolchain_file}")
set(CMAKE_TOOLCHAIN_FILE "${toolchain_file}" CACHE INTERNAL "")
else ()
# todo improve message
message(FATAL_ERROR "Toolchain file \"${PICO_COMPILER}.cmake\" does not exist, please\
select one from \"cmake/toolchains\" folder.")
endif ()
endif ()
endif ()
message("PICO compiler is ${PICO_COMPILER}")
unset(PICO_COMPILER CACHE)

28
cmake/pico_utils.cmake Normal file
View File

@ -0,0 +1,28 @@
function(pico_message param)
if (${ARGC} EQUAL 1)
message("${param}")
return()
endif ()
if (NOT ${ARGC} EQUAL 2)
message(FATAL_ERROR "Expect at most 2 arguments")
endif ()
message("${param}" "${ARGV1}")
endfunction()
macro(assert VAR MSG)
if (NOT ${VAR})
message(FATAL_ERROR "${MSG}")
endif ()
endmacro()
function(pico_find_in_paths OUT PATHS NAME)
foreach(PATH IN LISTS ${PATHS})
if (EXISTS ${PATH}/${NAME})
get_filename_component(FULLNAME ${PATH}/${NAME} ABSOLUTE)
set(${OUT} ${FULLNAME} PARENT_SCOPE)
return()
endif()
endforeach()
set(${OUT} "" PARENT_SCOPE)
endfunction()

View File

View File

@ -0,0 +1,7 @@
if (NOT (DEFINED PICO_COMPILER OR DEFINED CMAKE_TOOLCHAIN_FILE))
pico_message("Defaulting PICO platform compiler to pico_arm_gcc since not specified.")
set(PICO_COMPILER "pico_arm_gcc")
endif ()

View File

@ -0,0 +1 @@
include(${CMAKE_CURRENT_LIST_DIR}/pico/pico.cmake)

View File

@ -0,0 +1,31 @@
# Toolchain file is processed multiple times, however, it cannot access CMake cache on some runs.
# We store the search path in an environment variable so that we can always access it.
if (NOT "${PICO_TOOLCHAIN_PATH}" STREQUAL "")
set(ENV{PICO_TOOLCHAIN_PATH} "${PICO_TOOLCHAIN_PATH}")
endif ()
# Find the compiler executable and store its path in a cache entry ${compiler_path}.
# If not found, issue a fatal message and stop processing. PICO_TOOLCHAIN_PATH can be provided from
# commandline as additional search path.
function(pico_find_compiler compiler_path compiler_exe)
# Search user provided path first.
find_program(
${compiler_path} ${compiler_exe}
PATHS ENV PICO_TOOLCHAIN_PATH
PATH_SUFFIXES bin
NO_DEFAULT_PATH
)
# If not then search system paths.
if ("${${compiler_path}}" STREQUAL "${compiler_path}-NOTFOUND")
if (DEFINED ENV{PICO_TOOLCHAIN_PATH})
message(WARNING "PICO_TOOLCHAIN_PATH specified ($ENV{PICO_TOOLCHAIN_PATH}), but ${compiler_exe} not found there")
endif()
find_program(${compiler_path} ${compiler_exe})
endif ()
if ("${${compiler_path}}" STREQUAL "${compiler_path}-NOTFOUND")
set(PICO_TOOLCHAIN_PATH "" CACHE PATH "Path to search for compiler.")
message(FATAL_ERROR "Compiler '${compiler_exe}' not found, you can specify search path with\
\"PICO_TOOLCHAIN_PATH\".")
endif ()
endfunction()

View File

@ -0,0 +1,53 @@
# NOTE: THIS IS A WIP ONLY PICO_ARM_GCC IS CURRENTLY SUPPORTED
# todo there is probably a more "cmake" way of doing this going thru the standard path with our "PICO" platform
# i.e. CMake<Lang>Information and whatnot
include(${CMAKE_CURRENT_LIST_DIR}/find_compiler.cmake)
# include our Platform/pico.cmake
set(CMAKE_SYSTEM_NAME PICO)
set(CMAKE_SYSTEM_PROCESSOR cortex-m0plus)
# Find CLANG
pico_find_compiler(PICO_COMPILER_CC clang)
pico_find_compiler(PICO_COMPILER_CXX clang)
#pico_find_compiler(PICO_COMPILER_ASM armasm)
set(PICO_COMPILER_ASM "${PICO_COMPILER_CC}" CACHE INTERNAL "")
pico_find_compiler(PICO_OBJCOPY llvm-objcopy)
pico_find_compiler(PICO_OBJDUMP llvm-objdump)
# Specify the cross compiler.
set(CMAKE_C_COMPILER ${PICO_COMPILER_CC} CACHE FILEPATH "C compiler")
set(CMAKE_CXX_COMPILER ${PICO_COMPILER_CXX} CACHE FILEPATH "C++ compiler")
set(CMAKE_C_OUTPUT_EXTENSION .o)
# todo should we be including CMakeASMInformation anyway - i guess that is host side
set(CMAKE_ASM_COMPILER ${PICO_COMPILER_ASM} CACHE FILEPATH "ASM compiler")
set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
set(CMAKE_INCLUDE_FLAG_ASM "-I")
set(CMAKE_OBJCOPY ${PICO_OBJCOPY} CACHE FILEPATH "")
set(CMAKE_OBJDUMP ${PICO_OBJDUMP} CACHE FILEPATH "")
# Disable compiler checks.
set(CMAKE_C_COMPILER_FORCED TRUE)
set(CMAKE_CXX_COMPILER_FORCED TRUE)
# Add target system root to cmake find path.
get_filename_component(PICO_COMPILER_DIR "${PICO_COMPILER_CC}" DIRECTORY)
get_filename_component(CMAKE_FIND_ROOT_PATH "${PICO_COMPILER_DIR}" DIRECTORY)
# Look for includes and libraries only in the target system prefix.
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
include_directories(/usr/include/newlib)
# todo move to platform/Generix-xxx
set(ARM_CLANG_COMMON_FLAGS " --target=arm-none-eabi -mcpu=cortex-m0plus -mthumb")
set(CMAKE_C_FLAGS_INIT "${ARM_CLANG_COMMON_FLAGS}")
set(CMAKE_CXX_FLAGS_INIT "${ARM_CLANG_COMMON_FLAGS}")
set(CMAKE_ASM_FLAGS_INIT "${ARM_CLANG_COMMON_FLAGS}")
set(CMAKE_C_FLAGS_DEBUG_INIT "${ARM_CLANG_COMMON_FLAGS} -Og")
set(CMAKE_CXX_FLAGS_DEBUG_INIT "${ARM_CLANG_COMMON_FLAGS} -Og")

View File

@ -0,0 +1,52 @@
# NOTE: THIS IS A WIP ONLY PICO_ARM_GCC IS CURRENTLY SUPPORTED
# todo there is probably a more "cmake" way of doing this going thru the standard path with our "PICO" platform
# i.e. CMake<Lang>Information and whatnot
include(${CMAKE_CURRENT_LIST_DIR}/find_compiler.cmake)
# include our Platform/PICO.cmake
set(CMAKE_SYSTEM_NAME PICO)
set(CMAKE_SYSTEM_PROCESSOR cortex-m0plus)
# Find ARMClang.
pico_find_compiler(PICO_COMPILER_CC armclang)
pico_find_compiler(PICO_COMPILER_CXX armclang)
pico_find_compiler(PICO_COMPILER_ASM armasm)
set(PICO_COMPILER_ASM "${PICO_COMPILER_ASM}" CACHE INTERNAL "")
pico_find_compiler(PICO_OBJCOPY llvm-objcopy)
pico_find_compiler(PICO_OBJDUMP llvm-objdump)
# Specify the cross compiler.
set(CMAKE_C_COMPILER ${PICO_COMPILER_CC} CACHE FILEPATH "C compiler")
set(CMAKE_CXX_COMPILER ${PICO_COMPILER_CXX} CACHE FILEPATH "C++ compiler")
set(CMAKE_C_OUTPUT_EXTENSION .o)
# todo should we be including CMakeASMInformation anyway - i guess that is host side
set(CMAKE_ASM_COMPILER ${PICO_COMPILER_ASM} CACHE FILEPATH "ASM compiler")
set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
set(CMAKE_INCLUDE_FLAG_ASM "-I")
set(CMAKE_OBJCOPY ${PICO_OBJCOPY} CACHE FILEPATH "")
set(CMAKE_OBJDUMP ${PICO_OBJDUMP} CACHE FILEPATH "")
# Disable compiler checks.
set(CMAKE_C_COMPILER_FORCED TRUE)
set(CMAKE_CXX_COMPILER_FORCED TRUE)
# Add target system root to cmake find path.
get_filename_component(PICO_COMPILER_DIR "${PICO_COMPILER_CC}" DIRECTORY)
get_filename_component(CMAKE_FIND_ROOT_PATH "${PICO_COMPILER_DIR}" DIRECTORY)
# Look for includes and libraries only in the target system prefix.
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# todo move to platform/Generix-xxx
set(ARM_CLANG_COMMON_FLAGS " --cpu=Cortex-M0plus")
string(APPEND CMAKE_C_FLAGS_INIT "${ARM_CLANG_COMMON_FLAGS}")
string(APPEND CMAKE_CXX_FLAGS_INIT "${ARM_CLANG_COMMON_FLAGS}")
string(APPEND CMAKE_ASM_FLAGS_INIT "${ARM_CLANG_COMMON_FLAGS}")
string(APPEND CMAKE_C_FLAGS_DEBUG_INIT "${ARM_CLANG_COMMON_FLAGS} -Og")
string(APPEND CMAKE_CXX_FLAGS_DEBUG_INIT "${ARM_CLANG_COMMON_FLAGS} -Og")

View File

@ -0,0 +1,66 @@
# todo there is probably a more "cmake" way of doing this going thru the standard path with our "PICO" platform
# i.e. CMake<Lang>Information and whatnot
include(${CMAKE_CURRENT_LIST_DIR}/find_compiler.cmake)
# include our Platform/PICO.cmake
set(CMAKE_SYSTEM_NAME PICO)
set(CMAKE_SYSTEM_PROCESSOR cortex-m0plus)
if (NOT PICO_GCC_TRIPLE)
if (DEFINED ENV{PICO_GCC_TRIPLE})
set(PICO_GCC_TRIPLE $ENV{PICO_GCC_TRIPLE})
message("PICO_GCC_TRIPLE set from environment: $ENV{PICO_GCC_TRIPLE}")
else()
set(PICO_GCC_TRIPLE arm-none-eabi)
message("PICO_GCC_TRIPLE defaulted to arm-none-eabi")
endif()
endif()
# Find GCC for ARM.
pico_find_compiler(PICO_COMPILER_CC ${PICO_GCC_TRIPLE}-gcc)
pico_find_compiler(PICO_COMPILER_CXX ${PICO_GCC_TRIPLE}-g++)
set(PICO_COMPILER_ASM "${PICO_COMPILER_CC}" CACHE INTERNAL "")
pico_find_compiler(PICO_OBJCOPY ${PICO_GCC_TRIPLE}-objcopy)
pico_find_compiler(PICO_OBJDUMP ${PICO_GCC_TRIPLE}-objdump)
# Specify the cross compiler.
set(CMAKE_C_COMPILER ${PICO_COMPILER_CC} CACHE FILEPATH "C compiler")
set(CMAKE_CXX_COMPILER ${PICO_COMPILER_CXX} CACHE FILEPATH "C++ compiler")
set(CMAKE_C_OUTPUT_EXTENSION .o)
# todo should we be including CMakeASMInformation anyway - i guess that is host side
set(CMAKE_ASM_COMPILER ${PICO_COMPILER_ASM} CACHE FILEPATH "ASM compiler")
set(CMAKE_ASM_COMPILE_OBJECT "<CMAKE_ASM_COMPILER> <DEFINES> <INCLUDES> <FLAGS> -o <OBJECT> -c <SOURCE>")
set(CMAKE_INCLUDE_FLAG_ASM "-I")
set(CMAKE_OBJCOPY ${PICO_OBJCOPY} CACHE FILEPATH "")
set(CMAKE_OBJDUMP ${PICO_OBJDUMP} CACHE FILEPATH "")
# Disable compiler checks.
set(CMAKE_C_COMPILER_FORCED TRUE)
set(CMAKE_CXX_COMPILER_FORCED TRUE)
# Add target system root to cmake find path.
get_filename_component(PICO_COMPILER_DIR "${PICO_COMPILER_CC}" DIRECTORY)
get_filename_component(CMAKE_FIND_ROOT_PATH "${PICO_COMPILER_DIR}" DIRECTORY)
# Look for includes and libraries only in the target system prefix.
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
option(PICO_DEOPTIMIZED_DEBUG "Build debug builds with -O0" 0)
# todo move to platform/Generix-xxx
set(ARM_GCC_COMMON_FLAGS " -march=armv6-m -mcpu=cortex-m0plus -mthumb")
#set(ARM_GCC_COMMON_FLAGS " -mcpu=cortex-m0plus -mthumb")
foreach(LANG IN ITEMS C CXX ASM)
set(CMAKE_${LANG}_FLAGS_INIT "${ARM_GCC_COMMON_FLAGS}")
if (PICO_DEOPTIMIZED_DEBUG)
set(CMAKE_${LANG}_FLAGS_DEBUG_INIT "-O0")
else()
set(CMAKE_${LANG}_FLAGS_DEBUG_INIT "-Og")
endif()
set(CMAKE_${LANG}_LINK_FLAGS "-Wl,--build-id=none")
endforeach()

59
docs/CMakeLists.txt Normal file
View File

@ -0,0 +1,59 @@
find_package(Doxygen)
if (PICO_SDK_TOP_LEVEL_PROJECT AND ${DOXYGEN_FOUND})
set(PICO_BUILD_DOCS_DEFAULT 1)
endif()
option(PICO_BUILD_DOCS "Build HTML Doxygen docs" ${PICO_BUILD_DOCS_DEFAULT})
if (DEFINED ENV{PICO_EXAMPLES_PATH} AND NOT PICO_EXAMPLES_PATH)
set(PICO_EXAMPLES_PATH $ENV{PICO_EXAMPLES_PATH})
message("Using PICO_EXAMPLES_PATH from environment ('${PICO_EXAMPLES_PATH}')")
endif()
if(PICO_BUILD_DOCS)
if(NOT DOXYGEN_FOUND)
message(FATAL_ERROR "Doxygen is needed to build the documentation.")
endif()
include(ExternalProject)
if(PICO_EXAMPLES_PATH)
get_filename_component(PICO_EXAMPLES_PATH "${PICO_EXAMPLES_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (EXISTS ${PICO_EXAMPLES_PATH})
message("Documentation example code will come from ${PICO_EXAMPLES_PATH}")
else()
message(WARNING "Documentation example code configured to come from ${PICO_EXAMPLES_PATH}, but that path does not exist")
endif()
add_custom_target(doc-pico-examples)
else()
ExternalProject_Add(doc-pico-examples
GIT_REPOSITORY git@github.com:raspberrypi/pico-examples.git
GIT_TAG master
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
)
ExternalProject_Get_property(doc-pico-examples SOURCE_DIR)
ExternalProject_Get_property(doc-pico-examples GIT_REPOSITORY)
ExternalProject_Get_property(doc-pico-examples GIT_TAG)
set(PICO_EXAMPLES_PATH ${SOURCE_DIR})
message("Documentation example code will come from git repo ${GIT_REPOSITORY}, branch ${GIT_TAG}")
endif()
set(DOXY_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/doxygen")
set(DOXY_INPUT_DIRS "${PICO_DOXYGEN_PATHS}")
set(DOXY_EXCLUDE_DIRS "${PICO_DOXYGEN_EXCLUDE_PATHS}")
set(DOXY_EXAMPLE_DIR "${PICO_EXAMPLES_PATH}")
set(doxyfile_in ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in)
set(doxyfile ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
configure_file(${doxyfile_in} ${doxyfile} @ONLY)
add_custom_target(docs
COMMAND ${DOXYGEN_EXECUTABLE} ${doxyfile}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
COMMENT "Generating API documentation with Doxygen"
VERBATIM)
add_dependencies(docs doc-pico-examples)
endif()

64
docs/Doxyfile.in Normal file
View File

@ -0,0 +1,64 @@
PROJECT_NAME = "Pico SDK"
PROJECT_NUMBER = @VERSION_MAJOR@.@VERSION_MINOR@.@VERSION_PATCH@
#STRIP_FROM_PATH = @PROJECT_SOURCE_DIR@
STRIP_FROM_PATH = @DOXY_INPUT_DIRS@
# @PROJECT_BINARY_DIR@
#INPUT = @doxy_main_page@ \
# @PROJECT_SOURCE_DIR@ \
# @PROJECT_BINARY_DIR@
FILE_PATTERNS = *.h \
*.cpp \
*.c \
*.S \
*.s \
*.md
USE_MDFILE_AS_MAINPAGE = @PROJECT_SOURCE_DIR@/docs/mainpage.md
LAYOUT_FILE = @PROJECT_SOURCE_DIR@/docs/DoxygenLayout.xml
HTML_FOOTER = @PROJECT_SOURCE_DIR@/docs/footer.html
HTML_HEADER = @PROJECT_SOURCE_DIR@/docs/header.html
PROJECT_BRIEF = "Pico SDK documentation"
PROJECT_NUMBER = 1.0
OPTIMIZE_OUTPUT_FOR_C = YES
# HTML_EXTRA_STYLESHEET = @PROJECT_SOURCE_DIR@/docs/customdoxygen.css
HTML_EXTRA_STYLESHEET = @PROJECT_SOURCE_DIR@/docs/normalise.css @PROJECT_SOURCE_DIR@/docs/main.css @PROJECT_SOURCE_DIR@/docs/styles.css
HTML_EXTRA_FILES = @PROJECT_SOURCE_DIR@/docs/logo-mobile.svg @PROJECT_SOURCE_DIR@/docs/logo.svg @PROJECT_SOURCE_DIR@/docs/search.svg \
@PROJECT_SOURCE_DIR@/docs/main.js @PROJECT_SOURCE_DIR@/docs/pico.jpg @PROJECT_SOURCE_DIR@/docs/rp2040.png
GENERATE_TREEVIEW = YES # This is needed as it wraps the content area in an HTML tag that we need to use
HTML_COLORSTYLE_HUE = 350
HTML_COLORSTYLE_SAT = 200
HTML_COLORSTYLE_GAMMA = 150
GENERATE_LATEX = NO
GENERATE_XML = YES
GROUP_GRAPHS = NO
ALIASES += tag=@internal
ALIASES += end=@internal
OUTPUT_DIRECTORY = @DOXY_OUTPUT_DIR@
INPUT = @PROJECT_SOURCE_DIR@/docs/index.h @DOXY_INPUT_DIRS@ @PROJECT_SOURCE_DIR@/docs/
#EXCLUDE = @DOXY_EXCLUDE_DIRS@ @PROJECT_SOURCE_DIR@/src/rp2040
EXCLUDE = @DOXY_EXCLUDE_DIRS@
RECURSIVE = YES
EXAMPLE_PATH = @PICO_EXAMPLES_PATH@
# This is needed as we have a number of static inline functions that need to be documented.
EXTRACT_STATIC = YES
EXTRACT_ALL = NO
ALWAYS_DETAILED_SEC = NO
#REPEAT_BRIEF = NO
# Need these next options to ensure that functions with modifiers do not confuse the Doxygen parser.
# And any further function modifiers here.
MACRO_EXPANSION = YES
PREDEFINED = __not_in_flash_func(x) \
__time_critical_func(x) \
__not_in_flash(x)= \
__no_inline_not_in_flash(x)= \
__attribute__(x)=

246
docs/DoxygenLayout.xml Normal file
View File

@ -0,0 +1,246 @@
<doxygenlayout version="1.0">
<!-- Generated by doxygen 1.8.17 -->
<!-- Navigation index tabs for HTML output -->
<navindex>
<tab type="mainpage" visible="yes" title="Pico SDK Introduction"></tab>
<tab type="modules" visible="yes" title="SDK API Documentation" intro="These are the libraries supplied in the Pico SDK"/>
<tab type="user" url="@ref examples_page" visible="yes" title="Examples" intro="Links to SDK examples"/>
<tab type="usergroup" url="@ref weblinks_page" visible="yes" title="Additional Documentation" intro="Links to datasheets and documentation">
<tab type="user" url="https://rptl.io/pico-datasheet" visible="yes" title="Raspberry Pi Pico Datasheet" intro=""/>
<tab type="user" url="https://rptl.io/rp2040-datasheet" visible="yes" title="RP2040 Datasheet" intro=""/>
<tab type="user" url="https://rptl.io/rp2040-design" visible="yes" title="Hardware design with RP2040" intro=""/>
<tab type="user" url="https://rptl.io/pico-c-sdk" visible="yes" title="Pico C/C++ SDK" intro=""/>
<tab type="user" url="https://rptl.io/pico-micropython" visible="yes" title="Pico Python SDK" intro=""/>
<tab type="user" url="https://rptl.io/pico-get-started" visible="yes" title="Getting started with Raspberry Pi Pico" intro=""/>
</tab>
<tab type="usergroup" url="@ref weblinks_page" visible="yes" title="Web" intro="useful weblinks">
<tab type="user" url="https://www.raspberrypi.org/" visible="yes" title="Raspberry Pi Site" intro=""/>
<tab type="user" url="https://rptl.io/rp2040-get-started" visible="yes" title="Raspberry Pi Pico Page" intro=""/>
<tab type="user" url="https://www.raspberrypi.org/forums" visible="yes" title="Raspberry Pi Forums" intro=""/>
<tab type="user" url="https://github.com/raspberrypi/pico-sdk" visible="yes" title="Pico SDK on Github" intro=""/>
<tab type="user" url="https://github.com/raspberrypi/pico-examples" visible="yes" title="Pico Examples on Github" intro=""/>
<tab type="user" url="https://github.com/raspberrypi/pico-extras" visible="yes" title="Pico Extras on Github" intro=""/>
<tab type="user" url="https://github.com/raspberrypi/pico-playground" visible="yes" title="Pico Playground on Github" intro=""/>
<tab type="user" url="https://github.com/raspberrypi/pico-bootrom" visible="yes" title="Pico Bootrom on Github" intro=""/>
</tab>
<tab type="pages" visible="no" title="" intro=""/>
<tab type="namespaces" visible="yes" title="">
<tab type="namespacelist" visible="yes" title="" intro=""/>
<tab type="namespacemembers" visible="yes" title="" intro=""/>
</tab>
<tab type="interfaces" visible="yes" title="">
<tab type="interfacelist" visible="yes" title="" intro=""/>
<tab type="interfaceindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="interfacehierarchy" visible="yes" title="" intro=""/>
</tab>
<tab type="classes" visible="no" title="">
<tab type="classlist" visible="yes" title="" intro=""/>
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="hierarchy" visible="yes" title="" intro=""/>
<tab type="classmembers" visible="yes" title="" intro=""/>
</tab>
<tab type="structs" visible="yes" title="">
<tab type="structlist" visible="yes" title="" intro=""/>
<tab type="structindex" visible="$ALPHABETICAL_INDEX" title=""/>
</tab>
<tab type="exceptions" visible="yes" title="">
<tab type="exceptionlist" visible="yes" title="" intro=""/>
<tab type="exceptionindex" visible="$ALPHABETICAL_INDEX" title=""/>
<tab type="exceptionhierarchy" visible="yes" title="" intro=""/>
</tab>
<tab type="files" visible="no" title="">
<tab type="filelist" visible="yes" title="" intro=""/>
<tab type="globals" visible="yes" title="" intro=""/>
</tab>
<tab type="examples" visible="yes" title="" intro=""/>
</navindex>
<!-- Layout definition for a class page -->
<class>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<inheritancegraph visible="$CLASS_GRAPH"/>
<collaborationgraph visible="$COLLABORATION_GRAPH"/>
<memberdecl>
<nestedclasses visible="yes" title=""/>
<publictypes title=""/>
<services title=""/>
<interfaces title=""/>
<publicslots title=""/>
<signals title=""/>
<publicmethods title=""/>
<publicstaticmethods title=""/>
<publicattributes title=""/>
<publicstaticattributes title=""/>
<protectedtypes title=""/>
<protectedslots title=""/>
<protectedmethods title=""/>
<protectedstaticmethods title=""/>
<protectedattributes title=""/>
<protectedstaticattributes title=""/>
<packagetypes title=""/>
<packagemethods title=""/>
<packagestaticmethods title=""/>
<packageattributes title=""/>
<packagestaticattributes title=""/>
<properties title=""/>
<events title=""/>
<privatetypes title=""/>
<privateslots title=""/>
<privatemethods title=""/>
<privatestaticmethods title=""/>
<privateattributes title=""/>
<privatestaticattributes title=""/>
<friends title=""/>
<related title="" subtitle=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<enums title=""/>
<services title=""/>
<interfaces title=""/>
<constructors title=""/>
<functions title=""/>
<related title=""/>
<variables title=""/>
<properties title=""/>
<events title=""/>
</memberdef>
<allmemberslink visible="yes"/>
<usedfiles visible="$SHOW_USED_FILES"/>
<authorsection visible="yes"/>
</class>
<!-- Layout definition for a namespace page -->
<namespace>
<briefdescription visible="yes"/>
<memberdecl>
<nestednamespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<structs visible="yes" title=""/>
<exceptions visible="yes" title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection visible="yes"/>
</namespace>
<!-- Layout definition for a file page -->
<file> <tab type="modules" visible="yes" title="Libraries" intro="Here is a list of all the libraries supported in the Pico SDK"/>
<briefdescription visible="yes"/>
<includes visible="$SHOW_INCLUDE_FILES"/>
<includegraph visible="$INCLUDE_GRAPH"/>
<includedbygraph visible="$INCLUDED_BY_GRAPH"/>
<sourcelink visible="yes"/>
<memberdecl>
<interfaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<structs visible="yes" title=""/>
<exceptions visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<constantgroups visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<functions title=""/>
<variables title=""/>
</memberdef>
<authorsection/>
</file>
<!-- Layout definition for a group page -->
<group>
<briefdescription visible="yes"/>
<groupgraph visible="$GROUP_GRAPHS"/>
<memberdecl>
<nestedgroups visible="yes" title=""/>
<dirs visible="yes" title=""/>
<files visible="yes" title=""/>
<namespaces visible="yes" title=""/>
<classes visible="yes" title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
<membergroups visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
<memberdef>
<pagedocs/>
<inlineclasses title=""/>
<defines title=""/>
<typedefs title=""/>
<sequences title=""/>
<dictionaries title=""/>
<enums title=""/>
<enumvalues title=""/>
<functions title=""/>
<variables title=""/>
<signals title=""/>
<publicslots title=""/>
<protectedslots title=""/>
<privateslots title=""/>
<events title=""/>
<properties title=""/>
<friends title=""/>
</memberdef>
<authorsection visible="yes"/>
</group>
<!-- Layout definition for a directory page -->
<directory>
<briefdescription visible="yes"/>
<directorygraph visible="yes"/>
<memberdecl>
<dirs visible="yes"/>
<files visible="yes"/>
</memberdecl>
<detaileddescription title=""/>
</directory>
</doxygenlayout>

21
docs/examples.md Normal file
View File

@ -0,0 +1,21 @@
## 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.
- [RTC example](@ref rtc_example)
- [UART example](@ref uart_example)
- [ADC example](@ref adc_example)
- [I2C example](@ref i2c_example)
- [Clock example](@ref clock_example)
- [Timer example](@ref timer_example)
- [Flash programming example](@ref flash_example)
- [Watchdog example](@ref watchdog_example)
- [Divider example](@ref divider_example)
- [PWM example](@ref pwm_example)
- [Multicore example](@ref multicore_example)
- [Reset example](@ref reset_example)
All examples are "Copyright (c) 2020 Raspberry Pi (Trading) Ltd", and are released under a 3-Clause BSD licence. Briefly, this means you are free to use the example code
as long as you retain the copyright notice. Full details on the licence can be found [here](https://opensource.org/licenses/BSD-3-Clause).

5
docs/footer.html Normal file
View File

@ -0,0 +1,5 @@
<script src="main.js"></script>
</body>
</html>

61
docs/header.html Normal file
View File

@ -0,0 +1,61 @@
<!-- HTML header for doxygen 1.8.20-->
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=9"/>
<meta name="generator" content="Doxygen $doxygenversion"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<!--BEGIN PROJECT_NAME--><title>$projectname: $title</title><!--END PROJECT_NAME-->
<!--BEGIN !PROJECT_NAME--><title>$title</title><!--END !PROJECT_NAME-->
<!-- <link href="$relpath^tabs.css" rel="stylesheet" type="text/css"/> -->
<script type="text/javascript" src="$relpath^jquery.js"></script>
<script type="text/javascript" src="$relpath^dynsections.js"></script>
$treeview
$search
$mathjax
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap" rel="stylesheet">
<link href="$relpath^$stylesheet" rel="stylesheet" type="text/css" />
$extrastylesheet
</head>
<body>
<div class="navigation-mobile">
<div class="logo--mobile">
<a href="/"><img src="logo-mobile.svg" alt="Raspberry Pi"></a>
</div>
<div class="navigation-toggle">
<span class="line-1"></span>
<span class="line-2">
<p>Menu Toggle</p>
</span>
<span class="line-3"></span>
</div>
</div>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div class="logo">
<a href="$relpath^index.html"> <img src="logo.svg" alt="Raspberry Pi"></a>
</div>
<div class="navigation-footer">
<img src="logo-mobile.svg" alt="Raspberry Pi">
<a href="https://www.raspberrypi.org/" target="_blank">By Raspberry Pi (Trading) Ltd</a>
</div>
<!-- <div class="search">
<form>
<input type="search" name="search" id="search" placeholder="Search">
<input type="submit" value="Search">
</form>
</div> -->

86
docs/index.h Normal file
View File

@ -0,0 +1,86 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
// Here to organize documentation order
/**
* \defgroup hardware Hardware APIs
* This group of libraries provides a thin and efficient C API / abstractions to access the RP2040 hardware without having to read and write
* hardware registers directly.
* @{
* \defgroup hardware_adc hardware_adc
* \defgroup hardware_base hardware_base
* \defgroup hardware_claim hardware_claim
* \defgroup hardware_clocks hardware_clocks
* \defgroup hardware_divider hardware_divider
* \defgroup hardware_dma hardware_dma
* \defgroup hardware_flash hardware_flash
* \defgroup hardware_gpio hardware_gpio
* \defgroup hardware_i2c hardware_i2c
* \defgroup hardware_interp hardware_interp
* \defgroup hardware_irq hardware_irq
* \defgroup hardware_pio hardware_pio
* \defgroup hardware_pll hardware_pll
* \defgroup hardware_pwm hardware_pwm
* \defgroup hardware_resets hardware_resets
* \defgroup hardware_rtc hardware_rtc
* \defgroup hardware_spi hardware_spi
* \defgroup hardware_sync hardware_sync
* \defgroup hardware_timer hardware_timer
* \defgroup hardware_uart hardware_uart
* \defgroup hardware_vreg hardware_vreg
* \defgroup hardware_watchdog hardware_watchdog
* \defgroup hardware_xosc hardware_xosc
* @}
*
* \defgroup high_level High Level APIs
* This group of libraries provide higher level functionality that isn't hardware related or provides a richer
* set of functionality above the basic hardware interfaces
* @{
* \defgroup pico_multicore pico_multicore
* \defgroup pico_stdlib pico_stdlib
* \defgroup pico_sync pico_sync
* \defgroup pico_time pico_time
* \defgroup pico_util pico_util
* @}
*
* \defgroup third_party Third-party Libraries
* Third party libraries for implementing high level functionality.
* @{
* \defgroup tinyusb_device tinyusb_device
* \defgroup tinyusb_host tinyusb_host
* @}
*
* \defgroup runtime Runtime Infrastructure
* Libraries that are used to provide efficient implementation of certain
* language level and C library functions, as well as CMake INTERFACE libraries
* abstracting the compilation and link steps in the SDK
* @{
* \defgroup boot_stage2 boot_stage2
* \defgroup pico_base pico_base
* \defgroup pico_bit_ops pico_bit_ops
* \defgroup pico_bootrom pico_bootrom
* \defgroup pico_cxx_options pico_cxx_options
* \defgroup pico_divider pico_divider
* \defgroup pico_double pico_double
* \defgroup pico_float pico_float
* \defgroup pico_int64_ops pico_int64_ops
* \defgroup pico_malloc pico_malloc
* \defgroup pico_mem_ops pico_mem_ops
* \defgroup pico_platform pico_platform
* \defgroup pico_printf pico_printf
* \defgroup pico_runtime pico_runtime
* \defgroup pico_stdio pico_stdio
* \defgroup pico_standard_link pico_standard_link
* @}
*
* \defgroup misc External API Headers
* Headers for interfaces that are shared with code outside of the SDK
* @{
* \defgroup boot_picoboot boot_picoboot
* \defgroup boot_uf2 boot_uf2
* @}
*/

17
docs/logo-mobile.svg Normal file
View File

@ -0,0 +1,17 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="570" height="720">
<path d="m 158.375,1.65625 c -3.6193,0.1123192 -7.51715,1.4493266 -11.9375,4.9375 C 135.61054,2.4174496 125.11041,0.9665612 115.71875,9.46875 101.22489,7.5879922 96.508461,11.469494 92.9375,16 89.754953,15.934135 69.118652,12.72793 59.65625,26.84375 35.874602,24.030329 28.359472,40.831625 36.875,56.5 c -4.856911,7.518955 -9.889503,14.947226 1.46875,29.28125 -4.018006,7.983514 -1.527431,16.64403 7.9375,27.125 -2.497857,11.2226 2.412077,19.14086 11.21875,25.3125 -1.64709,15.35756 14.083505,24.28743 18.78125,27.46875 1.803677,8.94868 5.56291,17.3927 23.53125,22.0625 2.96323,13.3361 13.76206,15.63906 24.21875,18.4375 -34.561929,20.08954 -64.20067,46.52266 -64,111.375 l -5.0625,9.03125 C 15.337882,350.69604 -20.316547,428.16001 35.4375,491.125 c 3.641871,19.70838 9.749589,33.86396 15.1875,49.53125 8.133834,63.13058 61.21763,92.69161 75.21875,96.1875 20.51653,15.62812 42.36818,30.45672 71.9375,40.84375 27.87515,28.74946 58.07388,39.7064 88.4375,39.6875 0.44515,-2.8e-4 0.89853,0.005 1.34375,0 30.36363,0.0189 60.56235,-10.93804 88.4375,-39.6875 29.56932,-10.38703 51.42097,-25.21563 71.9375,-40.84375 14.00112,-3.49589 67.08492,-33.05692 75.21875,-96.1875 5.43791,-15.66729 11.54562,-29.82287 15.1875,-49.53125 55.75404,-62.96499 20.09961,-140.42896 -19.53125,-164.53125 L 513.75,317.5625 c 0.20067,-64.85234 -29.43807,-91.28546 -64,-111.375 10.45669,-2.79844 21.25552,-5.1014 24.21875,-18.4375 17.96834,-4.6698 21.72758,-13.11382 23.53125,-22.0625 4.69775,-3.18132 20.42834,-12.11119 18.78125,-27.46875 8.80668,-6.17164 13.71661,-14.0899 11.21875,-25.3125 9.46494,-10.48097 11.9555,-19.141487 7.9375,-27.125 C 546.79575,71.447226 541.76316,64.018955 536.90625,56.5 545.42178,40.831625 537.90665,24.030329 514.125,26.84375 504.6626,12.72793 484.0263,15.934135 480.84375,16 477.27279,11.469494 472.55636,7.587992 458.0625,9.46875 448.67084,0.96656132 438.17071,2.41745 427.34375,6.59375 414.48455,-3.5536631 405.97149,4.580454 396.25,7.65625 380.67615,2.568472 377.11698,9.5371578 369.46875,12.375 352.4935,8.7869238 347.33315,16.598532 339.1875,24.84375 l -9.46875,-0.1875 c -25.61054,15.093115 -38.33378,45.825501 -42.84375,61.625 -4.51206,-15.801979 -17.20647,-46.534542 -42.8125,-61.625 l -9.46875,0.1875 C 226.4481,16.598532 221.28775,8.7869235 204.3125,12.375 196.66427,9.5371583 193.1051,2.5684729 177.53125,7.65625 c -6.37973,-2.0184911 -12.24667,-6.2144276 -19.15625,-6 z" style="fill:#000000" />
<path d="m 107.39184,68.055583 c 67.94767,35.031357 107.44689,63.368967 129.08717,87.504467 -11.08235,44.41759 -68.89638,46.44464 -90.03559,45.19858 4.32842,-2.01474 7.93988,-4.42778 9.22051,-8.13574 -5.30449,-3.76981 -24.11289,-0.39719 -37.24363,-7.77416 5.04407,-1.04499 7.40348,-2.06302 9.76289,-5.78542 -12.40571,-3.9567 -25.76862,-7.36642 -33.627746,-13.92116 4.241253,0.0524 8.201156,0.9488 13.740366,-2.89271 -11.111694,-5.98819 -22.969108,-10.73351 -32.18139,-19.88738 5.745213,-0.14063 11.939452,-0.0568 13.740371,-2.16953 -10.17044,-6.30068 -18.751242,-13.30787 -25.853592,-20.97215 8.039979,0.97052 11.435284,0.13478 13.378782,-1.26556 -7.687795,-7.87419 -17.417559,-14.52319 -22.056911,-24.22644 5.969606,2.057484 11.431249,2.84506 15.36752,-0.180795 -2.612365,-5.893453 -13.805413,-9.369618 -20.248967,-23.141676 6.284359,0.609377 12.949606,1.371108 14.282753,0 C 61.802068,58.517346 56.796919,51.835885 51.887978,44.913906 65.338021,44.714177 85.715734,44.966253 84.792549,43.82914 l -8.31654,-8.497335 c 13.137617,-3.537241 26.580651,0.568164 36.339661,3.615887 4.38186,-3.457681 -0.0776,-7.82998 -5.42383,-12.294015 11.16496,1.490646 21.25382,4.057389 30.37345,7.593362 4.87238,-4.399329 -3.16389,-8.798658 -7.05098,-13.197987 17.24936,3.272568 24.55716,7.87068 31.81981,12.47481 5.26935,-5.050799 0.30166,-9.343299 -3.2543,-13.740371 13.00566,4.817048 19.70478,11.035551 26.75756,17.175463 2.39119,-3.227053 6.07494,-5.592408 1.62715,-13.378781 9.23416,5.322725 16.18926,11.59506 21.33374,18.621817 5.71336,-3.637941 3.40387,-8.613023 3.43509,-13.197987 9.59665,7.806516 15.68687,16.11395 23.14168,24.226443 1.50169,-1.093437 2.81661,-4.80171 3.97747,-10.666867 22.89539,22.211815 55.24591,78.158241 8.31654,100.340861 C 207.95028,109.95728 160.25292,86.016909 107.39184,68.055583 z" style="fill:#75a928" />
<path d="M 467.92487,68.055583 C 399.9772,103.08694 360.47798,131.42455 338.8377,155.56005 c 11.08235,44.41759 68.89638,46.44464 90.03559,45.19858 -4.32842,-2.01474 -7.93988,-4.42778 -9.22051,-8.13574 5.30449,-3.76981 24.11289,-0.39719 37.24363,-7.77416 -5.04407,-1.04499 -7.40348,-2.06302 -9.76289,-5.78542 12.40571,-3.9567 25.76862,-7.36642 33.62775,-13.92116 -4.24126,0.0524 -8.20116,0.9488 -13.74037,-2.89271 11.11169,-5.98819 22.96911,-10.73351 32.18139,-19.88738 -5.74521,-0.14063 -11.93945,-0.0568 -13.74037,-2.16953 10.17044,-6.30068 18.75124,-13.30787 25.85359,-20.97215 -8.03998,0.97052 -11.43528,0.13478 -13.37878,-1.26556 7.68779,-7.87419 17.41756,-14.52319 22.05691,-24.22644 -5.96961,2.057484 -11.43125,2.84506 -15.36752,-0.180795 2.61237,-5.893453 13.80541,-9.369618 20.24897,-23.141676 -6.28436,0.609377 -12.94961,1.371108 -14.28276,0 2.92231,-11.888563 7.92746,-18.570024 12.8364,-25.492003 -13.45004,-0.199729 -33.82775,0.05235 -32.90457,-1.084766 l 8.31654,-8.497335 c -13.13762,-3.537241 -26.58065,0.568164 -36.33966,3.615887 -4.38186,-3.457681 0.0776,-7.82998 5.42383,-12.294015 -11.16496,1.490646 -21.25382,4.057389 -30.37345,7.593362 -4.87238,-4.399329 3.16389,-8.798658 7.05098,-13.197987 -17.24936,3.272568 -24.55716,7.87068 -31.81981,12.47481 -5.26935,-5.050799 -0.30166,-9.343299 3.2543,-13.740371 -13.00566,4.817048 -19.70478,11.035551 -26.75756,17.175463 -2.39119,-3.227053 -6.07494,-5.592408 -1.62715,-13.378781 -9.23416,5.322725 -16.18926,11.59506 -21.33374,18.621817 -5.71336,-3.637941 -3.40387,-8.613023 -3.43509,-13.197987 -9.59665,7.806516 -15.68687,16.11395 -23.14168,24.226443 -1.50169,-1.093437 -2.81661,-4.80171 -3.97747,-10.666867 -22.89539,22.211815 -55.24591,78.158241 -8.31654,100.340861 39.91877,-32.94716 87.61613,-56.887531 140.47721,-74.848857 z" style="fill:#75a928" />
<path d="m 365.2046,521.84937 a 71.956154,66.532318 0 1 1 -143.91231,0 71.956154,66.532318 0 1 1 143.91231,0 z" transform="matrix(1.131107,0,0,1.1280497,-43.139135,-68.310983)" style="fill:#bc1142" />
<path d="m 262.84091,276.64774 a 61.875,28.125 0 1 1 -123.75,0 61.875,28.125 0 1 1 123.75,0 z" transform="matrix(0.76741684,-1.1613112,2.171115,1.4224368,-560.88858,217.68859)" style="fill:#bc1142" />
<path d="m 262.84091,276.64774 a 61.875,28.125 0 1 1 -123.75,0 61.875,28.125 0 1 1 123.75,0 z" transform="matrix(-0.76741684,-1.1613112,-2.171115,1.4224368,1134.8288,213.68859)" style="fill:#bc1142" />
<path d="M 72.910253,342.0878 C 109.32447,332.33088 85.201845,492.72431 55.576871,479.56357 22.990103,453.35089 12.493801,376.58814 72.910253,342.0878 z" style="fill:#bc1142" />
<path d="m 493.67828,340.0878 c -36.41422,-9.75692 -12.2916,150.63651 17.33338,137.47577 32.58677,-26.21268 43.08307,-102.97543 -17.33338,-137.47577 z" style="fill:#bc1142" />
<path d="m 369.97158,220.6534 c 62.83486,-10.61013 115.11594,26.72229 113.01138,94.85796 -2.06693,26.12112 -136.15872,-90.96907 -113.01138,-94.85796 z" style="fill:#bc1142" />
<path d="M 196.35975,218.6534 C 133.52489,208.04327 81.24381,245.37569 83.34837,313.51136 85.4153,339.63248 219.50709,222.54229 196.35975,218.6534 z" style="fill:#bc1142" />
<path d="m 286.61932,202.75568 c -37.50259,-0.97548 -73.49548,27.83418 -73.58158,44.54443 -0.10462,20.30426 29.6512,41.09266 73.83726,41.62035 45.12305,0.32321 73.91561,-16.64049 74.0611,-37.59409 0.16484,-23.73996 -41.03879,-48.93744 -74.31678,-48.57069 z" style="fill:#bc1142" />
<path d="m 288.90937,619.11675 c 32.69744,-1.42711 76.57083,10.53196 76.6568,26.39598 0.5427,15.4052 -39.78969,50.21055 -78.82634,49.53765 -40.42729,1.74391 -80.06908,-33.11559 -79.54951,-45.19859 -0.60506,-17.71593 49.226,-31.54796 81.71905,-30.73504 z" style="fill:#bc1142" />
<path d="m 168.13874,525.10369 c 23.2791,28.04573 33.89066,77.31899 14.46355,91.84353 -18.37917,11.08784 -63.01228,6.52162 -94.736237,-39.05157 -21.395052,-38.24168 -18.637584,-77.15663 -3.615887,-88.58924 22.464424,-13.68429 57.173424,4.79902 83.888574,35.79728 z" style="fill:#bc1142" />
<path d="m 405.0209,516.21177 c -25.18682,29.50165 -39.21227,83.30951 -20.83785,100.6428 17.56828,13.46361 64.7292,11.58162 99.56566,-36.75574 25.29599,-32.46471 16.82013,-86.68225 2.37077,-101.07511 -21.46408,-16.60213 -52.27691,4.64489 -81.09858,37.18805 z" style="fill:#bc1142" />
</svg>

After

Width:  |  Height:  |  Size: 8.7 KiB

213
docs/logo.svg Normal file
View File

@ -0,0 +1,213 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 24.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
viewBox="0 0 231.43986 61.396812"
xml:space="preserve"
sodipodi:docname="logo.svg"
width="231.43987"
height="61.39682"
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"><metadata
id="metadata6202"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
id="defs6200">
</defs><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1081"
id="namedview6198"
showgrid="false"
inkscape:zoom="3.1460265"
inkscape:cx="146.61494"
inkscape:cy="35.501241"
inkscape:window-x="0"
inkscape:window-y="32"
inkscape:window-maximized="1"
inkscape:current-layer="Layer_1" />
<style
type="text/css"
id="style6081">
.st0{enable-background:new ;}
.st1{fill:#1E1E1E;}
.st2{fill:#C31C4A;}
.st3{fill:#6ABF4B;}
</style>
<g
id="g6332"
transform="matrix(0.63209031,0,0,0.63209031,-0.16434348,-45.049552)"><g
transform="translate(-73.51,57.850753)"
style="enable-background:new"
id="g6105"
class="st0">
<path
style="fill:#1e1e1e"
inkscape:connector-curvature="0"
id="path6083"
d="M 85.34,42.72 H 80.21 V 54.16 H 73.77 V 22.91 h 11.61 c 3.69,0 6.54,0.82 8.54,2.47 2,1.65 3.01,3.97 3.01,6.98 0,2.13 -0.46,3.91 -1.38,5.33 -0.92,1.42 -2.32,2.56 -4.2,3.4 l 6.76,12.77 v 0.3 H 91.2 Z M 80.21,37.5 h 5.2 c 1.62,0 2.87,-0.41 3.76,-1.23 0.89,-0.82 1.33,-1.96 1.33,-3.4 0,-1.47 -0.42,-2.63 -1.26,-3.48 -0.84,-0.84 -2.12,-1.27 -3.85,-1.27 h -5.17 v 9.38 z"
class="st1" />
<path
style="fill:#1e1e1e"
inkscape:connector-curvature="0"
id="path6085"
d="m 114.88,54.16 c -0.29,-0.56 -0.49,-1.25 -0.62,-2.08 -1.5,1.67 -3.46,2.51 -5.86,2.51 -2.28,0 -4.16,-0.66 -5.66,-1.98 -1.5,-1.32 -2.24,-2.98 -2.24,-4.98 0,-2.46 0.91,-4.35 2.74,-5.67 1.83,-1.32 4.46,-1.98 7.91,-2 H 114 v -1.33 c 0,-1.07 -0.28,-1.93 -0.83,-2.58 -0.55,-0.64 -1.42,-0.97 -2.61,-0.97 -1.04,0 -1.86,0.25 -2.46,0.75 -0.59,0.5 -0.89,1.19 -0.89,2.06 h -6.2 c 0,-1.35 0.42,-2.59 1.25,-3.74 0.83,-1.15 2,-2.04 3.52,-2.69 1.52,-0.65 3.22,-0.98 5.11,-0.98 2.86,0 5.13,0.72 6.82,2.16 1.68,1.44 2.52,3.46 2.52,6.06 v 10.1 c 0.01,2.2 0.32,3.87 0.92,5 v 0.37 z m -5.13,-4.31 c 0.92,0 1.76,-0.2 2.53,-0.61 0.77,-0.41 1.35,-0.96 1.72,-1.64 v -4 h -2.32 c -3.11,0 -4.76,1.07 -4.96,3.22 l -0.02,0.36 c 0,0.77 0.27,1.41 0.82,1.91 0.54,0.51 1.29,0.76 2.23,0.76 z"
class="st1" />
<path
style="fill:#1e1e1e"
inkscape:connector-curvature="0"
id="path6087"
d="m 137.57,47.74 c 0,-0.76 -0.38,-1.36 -1.13,-1.79 -0.75,-0.44 -1.96,-0.83 -3.62,-1.17 -5.52,-1.16 -8.29,-3.51 -8.29,-7.04 0,-2.06 0.85,-3.78 2.57,-5.16 1.71,-1.38 3.95,-2.07 6.71,-2.07 2.95,0 5.31,0.69 7.07,2.08 1.77,1.39 2.65,3.19 2.65,5.41 h -6.2 c 0,-0.89 -0.29,-1.62 -0.86,-2.2 -0.57,-0.58 -1.47,-0.87 -2.68,-0.87 -1.04,0 -1.85,0.24 -2.43,0.71 -0.57,0.47 -0.86,1.07 -0.86,1.8 0,0.69 0.33,1.24 0.98,1.66 0.65,0.42 1.75,0.79 3.3,1.09 1.55,0.3 2.85,0.65 3.91,1.04 3.28,1.2 4.92,3.28 4.92,6.25 0,2.12 -0.91,3.83 -2.73,5.14 -1.82,1.31 -4.17,1.96 -7.04,1.96 -1.95,0 -3.67,-0.35 -5.18,-1.04 -1.51,-0.69 -2.69,-1.65 -3.55,-2.85 -0.86,-1.21 -1.29,-2.52 -1.29,-3.92 h 5.88 c 0.06,1.1 0.46,1.95 1.22,2.53 0.76,0.59 1.77,0.88 3.05,0.88 1.19,0 2.09,-0.23 2.69,-0.68 0.61,-0.44 0.91,-1.03 0.91,-1.76 z"
class="st1" />
<path
style="fill:#1e1e1e"
inkscape:connector-curvature="0"
id="path6089"
d="m 168.51,42.76 c 0,3.58 -0.81,6.44 -2.44,8.6 -1.62,2.15 -3.82,3.23 -6.58,3.23 -2.35,0 -4.24,-0.82 -5.69,-2.45 v 10.95 h -6.2 V 30.93 h 5.75 l 0.21,2.28 c 1.5,-1.8 3.46,-2.71 5.88,-2.71 2.86,0 5.09,1.06 6.68,3.18 1.59,2.12 2.38,5.04 2.38,8.76 z m -6.21,-0.45 c 0,-2.16 -0.38,-3.83 -1.15,-5 -0.77,-1.17 -1.88,-1.76 -3.34,-1.76 -1.95,0 -3.28,0.75 -4.01,2.23 v 9.51 c 0.76,1.53 2.11,2.3 4.06,2.3 2.96,0 4.44,-2.43 4.44,-7.28 z"
class="st1" />
<path
style="fill:#1e1e1e"
inkscape:connector-curvature="0"
id="path6091"
d="m 193.28,42.76 c 0,3.72 -0.79,6.62 -2.38,8.71 -1.59,2.08 -3.81,3.12 -6.65,3.12 -2.52,0 -4.53,-0.97 -6.03,-2.9 l -0.28,2.47 h -5.58 V 21.19 h 6.2 v 11.83 c 1.43,-1.67 3.31,-2.51 5.65,-2.51 2.83,0 5.06,1.04 6.67,3.12 1.61,2.08 2.42,5.01 2.42,8.79 v 0.34 z m -6.2,-0.45 c 0,-2.35 -0.37,-4.06 -1.12,-5.14 -0.74,-1.08 -1.85,-1.62 -3.33,-1.62 -1.98,0 -3.33,0.81 -4.08,2.43 v 9.17 c 0.76,1.63 2.13,2.45 4.12,2.45 2,0 3.32,-0.99 3.95,-2.96 0.31,-0.96 0.46,-2.39 0.46,-4.33 z"
class="st1" />
<path
style="fill:#1e1e1e"
inkscape:connector-curvature="0"
id="path6093"
d="m 207.8,54.59 c -3.41,0 -6.18,-1.04 -8.32,-3.13 -2.14,-2.09 -3.21,-4.87 -3.21,-8.35 v -0.6 c 0,-2.33 0.45,-4.42 1.35,-6.26 0.9,-1.84 2.18,-3.26 3.83,-4.25 1.65,-0.99 3.54,-1.49 5.66,-1.49 3.18,0 5.68,1 7.5,3.01 1.82,2.01 2.74,4.84 2.74,8.52 v 2.53 h -14.79 c 0.2,1.52 0.81,2.73 1.81,3.65 1,0.92 2.29,1.37 3.83,1.37 2.39,0 4.26,-0.87 5.6,-2.6 l 3.05,3.41 c -0.93,1.32 -2.19,2.34 -3.78,3.08 -1.58,0.74 -3.34,1.11 -5.27,1.11 z m -0.71,-19.08 c -1.23,0 -2.23,0.42 -3,1.25 -0.77,0.83 -1.26,2.03 -1.47,3.58 h 8.63 v -0.5 c -0.03,-1.38 -0.4,-2.45 -1.12,-3.2 -0.71,-0.76 -1.73,-1.13 -3.04,-1.13 z"
class="st1" />
<path
style="fill:#1e1e1e"
inkscape:connector-curvature="0"
id="path6095"
d="m 233.92,36.75 c -0.84,-0.12 -1.59,-0.17 -2.23,-0.17 -2.35,0 -3.89,0.79 -4.62,2.38 v 15.2 h -6.21 V 30.93 h 5.86 l 0.17,2.77 c 1.25,-2.13 2.97,-3.2 5.17,-3.2 0.69,0 1.33,0.09 1.93,0.28 z"
class="st1" />
<path
style="fill:#1e1e1e"
inkscape:connector-curvature="0"
id="path6097"
d="m 249.96,36.75 c -0.84,-0.12 -1.59,-0.17 -2.23,-0.17 -2.35,0 -3.88,0.79 -4.62,2.38 v 15.2 h -6.2 V 30.93 h 5.86 l 0.17,2.77 c 1.25,-2.13 2.97,-3.2 5.17,-3.2 0.69,0 1.33,0.09 1.93,0.28 z"
class="st1" />
<path
style="fill:#1e1e1e"
inkscape:connector-curvature="0"
id="path6099"
d="m 262,45.38 4.29,-14.45 h 6.66 l -9.34,26.83 -0.51,1.22 c -1.39,3.03 -3.68,4.55 -6.87,4.55 -0.9,0 -1.82,-0.14 -2.75,-0.41 v -4.7 l 0.95,0.02 c 1.17,0 2.05,-0.18 2.63,-0.54 0.58,-0.36 1.03,-0.95 1.36,-1.78 l 0.73,-1.91 -8.14,-23.29 h 6.68 z"
class="st1" />
<path
style="fill:#1e1e1e"
inkscape:connector-curvature="0"
id="path6101"
d="m 293.2,43.15 v 11.01 h -6.44 V 22.91 h 12.19 c 2.35,0 4.41,0.43 6.19,1.29 1.78,0.86 3.15,2.08 4.11,3.66 0.96,1.58 1.44,3.38 1.44,5.4 0,3.06 -1.05,5.48 -3.14,7.25 -2.09,1.77 -5,2.65 -8.71,2.65 h -5.64 z m 0,-5.22 h 5.75 c 1.7,0 3,-0.4 3.9,-1.2 0.89,-0.8 1.34,-1.95 1.34,-3.44 0,-1.53 -0.45,-2.77 -1.35,-3.71 -0.9,-0.94 -2.15,-1.43 -3.74,-1.46 h -5.9 z"
class="st1" />
<path
style="fill:#1e1e1e"
inkscape:connector-curvature="0"
id="path6103"
d="m 314.66,24.92 c 0,-0.93 0.31,-1.7 0.93,-2.3 0.62,-0.6 1.47,-0.9 2.54,-0.9 1.06,0 1.9,0.3 2.53,0.9 0.63,0.6 0.94,1.37 0.94,2.3 0,0.94 -0.32,1.72 -0.96,2.32 -0.64,0.6 -1.48,0.9 -2.52,0.9 -1.04,0 -1.89,-0.3 -2.52,-0.9 -0.62,-0.6 -0.94,-1.37 -0.94,-2.32 z m 6.59,29.24 h -6.23 V 30.93 h 6.23 z"
class="st1" />
</g><g
transform="translate(-73.51,57.850753)"
style="enable-background:new"
id="g6115"
class="st0">
<path
style="fill:#1e1e1e"
inkscape:connector-curvature="0"
id="path6107"
d="m 352.17,41.43 v 12.73 h -2.64 V 22.91 h 10.65 c 3.25,0 5.81,0.83 7.7,2.49 1.88,1.66 2.82,3.94 2.82,6.85 0,2.93 -0.91,5.2 -2.72,6.79 -1.81,1.59 -4.43,2.39 -7.87,2.39 z m 0,-2.23 h 8.01 c 2.56,0 4.52,-0.61 5.86,-1.83 1.35,-1.22 2.02,-2.92 2.02,-5.1 0,-2.16 -0.67,-3.89 -2.01,-5.17 -1.34,-1.28 -3.24,-1.94 -5.7,-1.97 h -8.18 z"
class="st1" />
<path
style="fill:#1e1e1e"
inkscape:connector-curvature="0"
id="path6109"
d="m 375.85,24.23 c 0,-0.48 0.16,-0.89 0.47,-1.23 0.32,-0.33 0.74,-0.5 1.29,-0.5 0.55,0 0.98,0.17 1.3,0.5 0.32,0.33 0.48,0.74 0.48,1.23 0,0.48 -0.16,0.89 -0.48,1.22 -0.32,0.33 -0.75,0.49 -1.3,0.49 -0.55,0 -0.97,-0.16 -1.29,-0.49 -0.31,-0.33 -0.47,-0.74 -0.47,-1.22 z m 3.03,29.93 H 376.3 V 30.93 h 2.58 z"
class="st1" />
<path
style="fill:#1e1e1e"
inkscape:connector-curvature="0"
id="path6111"
d="m 394.44,52.42 c 1.79,0 3.29,-0.5 4.5,-1.51 1.21,-1.01 1.86,-2.32 1.96,-3.92 h 2.47 c -0.07,1.42 -0.52,2.71 -1.33,3.88 -0.82,1.17 -1.9,2.08 -3.25,2.74 -1.35,0.66 -2.8,0.99 -4.35,0.99 -3.05,0 -5.46,-1.06 -7.25,-3.18 -1.79,-2.12 -2.67,-4.97 -2.67,-8.54 V 42.1 c 0,-2.29 0.4,-4.31 1.2,-6.08 0.8,-1.77 1.95,-3.12 3.45,-4.08 1.5,-0.96 3.24,-1.44 5.25,-1.44 2.55,0 4.65,0.76 6.3,2.28 1.65,1.52 2.54,3.51 2.65,5.99 h -2.47 c -0.11,-1.82 -0.77,-3.28 -1.96,-4.4 -1.2,-1.12 -2.7,-1.67 -4.52,-1.67 -2.32,0 -4.12,0.84 -5.4,2.51 -1.28,1.67 -1.92,4.02 -1.92,7.04 V 43 c 0,2.96 0.64,5.27 1.92,6.93 1.28,1.66 3.09,2.49 5.42,2.49 z"
class="st1" />
<path
style="fill:#1e1e1e"
inkscape:connector-curvature="0"
id="path6113"
d="m 407.08,42.21 c 0,-2.23 0.43,-4.24 1.3,-6.03 0.87,-1.79 2.09,-3.18 3.67,-4.18 1.58,-0.99 3.37,-1.49 5.38,-1.49 3.09,0 5.6,1.08 7.51,3.25 1.91,2.17 2.88,5.04 2.88,8.62 v 0.54 c 0,2.25 -0.43,4.27 -1.3,6.06 -0.87,1.79 -2.09,3.18 -3.66,4.15 -1.57,0.97 -3.37,1.46 -5.39,1.46 -3.08,0 -5.58,-1.08 -7.5,-3.25 -1.92,-2.17 -2.89,-5.04 -2.89,-8.62 z m 2.58,0.7 c 0,2.78 0.72,5.06 2.16,6.84 1.44,1.78 3.32,2.67 5.66,2.67 2.32,0 4.2,-0.89 5.64,-2.67 1.44,-1.78 2.16,-4.13 2.16,-7.05 v -0.49 c 0,-1.77 -0.33,-3.4 -0.99,-4.87 -0.66,-1.47 -1.58,-2.62 -2.77,-3.42 -1.19,-0.81 -2.55,-1.21 -4.08,-1.21 -2.29,0 -4.16,0.9 -5.6,2.69 -1.45,1.8 -2.17,4.15 -2.17,7.05 v 0.46 z"
class="st1" />
</g><path
style="fill:#c31c4a"
inkscape:connector-curvature="0"
id="path6117"
d="m 274.43,121.33075 c -6.39,0 -11.58,-5.2 -11.58,-11.58 V 82.850753 c 0,-6.39 5.2,-11.58 11.58,-11.58 h 80.4 c 6.39,0 11.58,5.2 11.58,11.58 v 26.799997 c 0,6.39 -5.2,11.58 -11.58,11.58 h -79.02 z m -1.33,-2.86 h 81.73 c 4.86,0 8.82,-3.96 8.82,-8.82 V 82.850753 c 0,-4.86 -3.96,-8.82 -8.82,-8.82 h -80.4 c -4.86,0 -8.82,3.96 -8.82,8.82 v 26.899997 c 0,4.41 3.25,8.07 7.49,8.72 z"
class="st2" /></g><g
id="g6350"
transform="matrix(0.84770507,0,0,0.84770507,0.18908311,-61.910993)"><path
inkscape:connector-curvature="0"
id="path6161"
d="m 5.2185549,138.93075 c -1.61,-0.46 -2.78,-1.03 -3.51,-1.7 -0.73000003,-0.67 -1.10000003,-1.51 -1.10000003,-2.5 0,-1.12 0.45000003,-2.05 1.34000003,-2.78 0.89,-0.73 2.06,-1.1 3.49,-1.1 0.98,0 1.85,0.19 2.61,0.57 0.76,0.38 1.36,0.9 1.78,1.56 0.4200001,0.66 0.6300001,1.39 0.6300001,2.18 H 8.5785549 c 0,-0.86 -0.27,-1.54 -0.82,-2.03 -0.55,-0.49 -1.32,-0.74 -2.31,-0.74 -0.92,0 -1.65,0.2 -2.16,0.61 -0.52,0.41 -0.78,0.97 -0.78,1.7 0,0.58 0.25,1.07 0.74,1.47 0.49,0.4 1.33,0.77 2.51,1.1 1.18,0.33 2.11,0.7 2.77,1.1 0.66,0.4 1.16,0.87 1.4800001,1.4 0.32,0.53 0.48,1.16 0.48,1.88 0,1.15 -0.45,2.08 -1.3500001,2.77 -0.9,0.69 -2.1,1.04 -3.6,1.04 -0.98,0 -1.89,-0.19 -2.73,-0.56 -0.84,-0.37 -1.5,-0.89 -1.96000003,-1.54 -0.46,-0.65 -0.69,-1.39 -0.69,-2.22 H 2.0385549 c 0,0.86 0.32,1.54 0.95,2.04 0.63,0.5 1.48,0.75 2.54,0.75 0.99,0 1.75,-0.2 2.28,-0.61 0.53,-0.41 0.79,-0.95 0.79,-1.65 0,-0.7 -0.24,-1.24 -0.73,-1.62 -0.49,-0.38 -1.37,-0.75 -2.65,-1.12 z" /><path
inkscape:connector-curvature="0"
id="path6163"
d="m 12.898555,145.26075 v -14.22 h 4.01 c 1.24,0 2.33,0.27 3.28,0.82 0.95,0.55 1.68,1.33 2.2,2.33 0.52,1 0.78,2.17 0.79,3.48 v 0.91 c 0,1.34 -0.26,2.52 -0.78,3.53 -0.52,1.01 -1.26,1.78 -2.22,2.32 -0.96,0.54 -2.08,0.82 -3.35,0.83 z m 1.87,-12.68 v 11.15 h 1.97 c 1.45,0 2.57,-0.45 3.37,-1.35 0.8,-0.9 1.21,-2.18 1.21,-3.84 v -0.83 c 0,-1.62 -0.38,-2.87 -1.14,-3.77 -0.76,-0.9 -1.83,-1.35 -3.23,-1.36 z" /><path
inkscape:connector-curvature="0"
id="path6165"
d="m 29.618555,138.65075 -1.74,1.81 v 4.8 h -1.88 v -14.22 h 1.88 v 7.03 l 6.32,-7.03 h 2.27 l -5.6,6.28 6.04,7.94 h -2.25 z" /><path
inkscape:connector-curvature="0"
id="path6167"
d="m 43.498555,145.26075 v -14.22 h 4.01 c 1.24,0 2.33,0.27 3.28,0.82 0.95,0.55 1.68,1.33 2.2,2.33 0.52,1 0.78,2.17 0.79,3.48 v 0.91 c 0,1.34 -0.26,2.52 -0.78,3.53 -0.52,1.01 -1.26,1.78 -2.22,2.32 -0.96,0.54 -2.08,0.82 -3.35,0.83 z m 1.88,-12.68 v 11.15 h 1.97 c 1.45,0 2.57,-0.45 3.37,-1.35 0.8,-0.9 1.21,-2.18 1.21,-3.84 v -0.83 c 0,-1.62 -0.38,-2.87 -1.14,-3.77 -0.76,-0.9 -1.83,-1.35 -3.23,-1.36 z" /><path
inkscape:connector-curvature="0"
id="path6169"
d="m 55.858555,139.88075 c 0,-1.04 0.2,-1.97 0.61,-2.79 0.41,-0.82 0.97,-1.46 1.7,-1.91 0.73,-0.45 1.55,-0.67 2.49,-0.67 1.44,0 2.6,0.5 3.49,1.49 0.89,0.99 1.33,2.32 1.33,3.97 v 0.13 c 0,1.03 -0.2,1.95 -0.59,2.77 -0.39,0.82 -0.96,1.45 -1.69,1.91 -0.73,0.46 -1.57,0.68 -2.52,0.68 -1.43,0 -2.59,-0.5 -3.48,-1.49 -0.89,-0.99 -1.33,-2.31 -1.33,-3.96 v -0.13 z m 1.81,0.22 c 0,1.17 0.27,2.11 0.82,2.82 0.55,0.71 1.27,1.06 2.18,1.06 0.92,0 1.65,-0.36 2.19,-1.08 0.54,-0.72 0.81,-1.73 0.81,-3.02 0,-1.16 -0.27,-2.1 -0.83,-2.82 -0.56,-0.72 -1.28,-1.08 -2.19,-1.08 -0.89,0 -1.61,0.35 -2.16,1.06 -0.55,0.71 -0.82,1.74 -0.82,3.06 z" /><path
inkscape:connector-curvature="0"
id="path6171"
d="m 71.978555,143.98075 c 0.64,0 1.21,-0.2 1.69,-0.59 0.48,-0.39 0.75,-0.88 0.8,-1.46 h 1.71 c -0.03,0.61 -0.24,1.18 -0.62,1.73 -0.38,0.55 -0.9,0.98 -1.54,1.31 -0.64,0.33 -1.32,0.49 -2.04,0.49 -1.44,0 -2.58,-0.48 -3.43,-1.44 -0.85,-0.96 -1.27,-2.27 -1.27,-3.94 v -0.3 c 0,-1.03 0.19,-1.94 0.57,-2.74 0.38,-0.8 0.92,-1.42 1.63,-1.87 0.71,-0.45 1.54,-0.66 2.5,-0.66 1.19,0 2.17,0.35 2.95,1.06 0.78,0.71 1.2,1.63 1.25,2.76 h -1.71 c -0.05,-0.68 -0.31,-1.25 -0.78,-1.68 -0.47,-0.43 -1.04,-0.66 -1.72,-0.66 -0.92,0 -1.63,0.33 -2.13,0.99 -0.5,0.66 -0.76,1.62 -0.76,2.87 v 0.34 c 0,1.22 0.25,2.16 0.75,2.81 0.5,0.65 1.22,0.98 2.15,0.98 z" /><path
inkscape:connector-curvature="0"
id="path6173"
d="m 84.728555,144.22075 c -0.7,0.83 -1.73,1.24 -3.1,1.24 -1.13,0 -1.98,-0.33 -2.57,-0.98 -0.59,-0.65 -0.89,-1.62 -0.89,-2.91 v -6.88 h 1.81 v 6.83 c 0,1.6 0.65,2.4 1.95,2.4 1.38,0 2.3,-0.51 2.75,-1.54 v -7.69 h 1.81 v 10.57 h -1.72 z" /><path
inkscape:connector-curvature="0"
id="path6175"
d="m 90.928555,134.70075 0.05,1.17 c 0.77,-0.91 1.82,-1.37 3.13,-1.37 1.48,0 2.48,0.57 3.02,1.7 0.35,-0.51 0.81,-0.92 1.37,-1.23 0.56,-0.31 1.23,-0.47 1.999995,-0.47 2.32,0 3.5,1.23 3.53,3.68 v 7.08 h -1.81 v -6.97 c 0,-0.75 -0.17,-1.32 -0.52,-1.69 -0.35,-0.37 -0.92,-0.56 -1.739995,-0.56 -0.67,0 -1.23,0.2 -1.67,0.6 -0.44,0.4 -0.7,0.94 -0.77,1.62 v 7.01 h -1.82 v -6.92 c 0,-1.54 -0.75,-2.3 -2.26,-2.3 -1.19,0 -2,0.5 -2.43,1.51 v 7.71 h -1.79 v -10.57 z" /><path
inkscape:connector-curvature="0"
id="path6177"
d="m 111.14855,145.46075 c -1.43,0 -2.6,-0.47 -3.5,-1.41 -0.9,-0.94 -1.35,-2.2 -1.35,-3.77 v -0.33 c 0,-1.05 0.2,-1.98 0.6,-2.81 0.4,-0.83 0.96,-1.47 1.68,-1.93 0.72,-0.46 1.5,-0.7 2.34,-0.7 1.37,0 2.44,0.45 3.2,1.36 0.76,0.91 1.14,2.2 1.14,3.89 v 0.75 h -7.16 c 0.03,1.04 0.33,1.88 0.91,2.52 0.58,0.64 1.32,0.96 2.22,0.96 0.64,0 1.18,-0.13 1.62,-0.39 0.44,-0.26 0.83,-0.61 1.16,-1.04 l 1.1,0.86 c -0.86,1.36 -2.19,2.04 -3.96,2.04 z m -0.23,-9.47 c -0.73,0 -1.34,0.27 -1.84,0.8 -0.5,0.53 -0.8,1.27 -0.92,2.23 h 5.29 v -0.14 c -0.05,-0.92 -0.3,-1.63 -0.74,-2.13 -0.44,-0.5 -1.03,-0.76 -1.79,-0.76 z" /><path
inkscape:connector-curvature="0"
id="path6179"
d="m 119.06855,134.70075 0.06,1.33 c 0.81,-1.02 1.86,-1.52 3.16,-1.52 2.23,0 3.36,1.26 3.38,3.78 v 6.98 h -1.81 v -6.99 c -0.01,-0.76 -0.18,-1.33 -0.52,-1.69 -0.34,-0.36 -0.87,-0.55 -1.6,-0.55 -0.59,0 -1.1,0.16 -1.54,0.47 -0.44,0.31 -0.79,0.72 -1.04,1.23 v 7.53 h -1.81 v -10.57 z" /><path
inkscape:connector-curvature="0"
id="path6181"
d="m 130.84855,132.14075 v 2.56 h 1.97 v 1.4 h -1.97 v 6.56 c 0,0.42 0.09,0.74 0.26,0.95 0.17,0.21 0.48,0.32 0.9,0.32 0.21,0 0.5,-0.04 0.86,-0.12 v 1.46 c -0.48,0.13 -0.94,0.19 -1.39,0.19 -0.81,0 -1.42,-0.24 -1.83,-0.73 -0.41,-0.49 -0.62,-1.18 -0.62,-2.08 v -6.55 h -1.92 v -1.4 h 1.92 v -2.56 z" /><path
inkscape:connector-curvature="0"
id="path6183"
d="m 141.44855,145.26075 c -0.1,-0.21 -0.19,-0.58 -0.25,-1.11 -0.84,0.87 -1.84,1.31 -3.01,1.31 -1.04,0 -1.9,-0.29 -2.56,-0.88 -0.66,-0.59 -1,-1.34 -1,-2.24 0,-1.1 0.42,-1.96 1.25,-2.56 0.83,-0.6 2.01,-0.91 3.53,-0.91 h 1.76 v -0.83 c 0,-0.63 -0.19,-1.13 -0.57,-1.51 -0.38,-0.38 -0.93,-0.56 -1.67,-0.56 -0.64,0 -1.18,0.16 -1.62,0.49 -0.44,0.33 -0.65,0.72 -0.65,1.18 h -1.82 c 0,-0.53 0.19,-1.04 0.56,-1.53 0.37,-0.49 0.88,-0.88 1.52,-1.17 0.64,-0.29 1.35,-0.43 2.11,-0.43 1.22,0 2.17,0.3 2.86,0.91 0.69,0.61 1.05,1.45 1.07,2.51 v 4.86 c 0,0.97 0.12,1.74 0.37,2.31 v 0.16 z m -3,-1.37 c 0.57,0 1.1,-0.15 1.61,-0.44 0.51,-0.29 0.88,-0.67 1.1,-1.14 v -2.17 h -1.42 c -2.21,0 -3.32,0.65 -3.32,1.94 0,0.57 0.19,1.01 0.57,1.33 0.38,0.32 0.87,0.48 1.46,0.48 z" /><path
inkscape:connector-curvature="0"
id="path6185"
d="m 148.25855,132.14075 v 2.56 h 1.97 v 1.4 h -1.97 v 6.56 c 0,0.42 0.09,0.74 0.26,0.95 0.17,0.21 0.48,0.32 0.9,0.32 0.21,0 0.5,-0.04 0.86,-0.12 v 1.46 c -0.48,0.13 -0.94,0.19 -1.39,0.19 -0.81,0 -1.42,-0.24 -1.83,-0.73 -0.41,-0.49 -0.62,-1.18 -0.62,-2.08 v -6.55 h -1.92 v -1.4 h 1.92 v -2.56 z" /><path
inkscape:connector-curvature="0"
id="path6187"
d="m 152.34855,131.89075 c 0,-0.29 0.09,-0.54 0.27,-0.74 0.18,-0.2 0.44,-0.3 0.8,-0.3 0.36,0 0.62,0.1 0.8,0.3 0.18,0.2 0.27,0.45 0.27,0.74 0,0.29 -0.09,0.54 -0.27,0.73 -0.18,0.19 -0.45,0.29 -0.8,0.29 -0.35,0 -0.62,-0.1 -0.8,-0.29 -0.18,-0.19 -0.27,-0.43 -0.27,-0.73 z m 1.95,13.37 h -1.81 v -10.56 h 1.81 z" /><path
inkscape:connector-curvature="0"
id="path6189"
d="m 156.70855,139.88075 c 0,-1.04 0.2,-1.97 0.61,-2.79 0.41,-0.82 0.97,-1.46 1.7,-1.91 0.73,-0.45 1.55,-0.67 2.49,-0.67 1.44,0 2.6,0.5 3.49,1.49 0.89,0.99 1.33,2.32 1.33,3.97 v 0.13 c 0,1.03 -0.2,1.95 -0.59,2.77 -0.39,0.82 -0.96,1.45 -1.69,1.91 -0.73,0.46 -1.57,0.68 -2.52,0.68 -1.43,0 -2.59,-0.5 -3.48,-1.49 -0.89,-0.99 -1.33,-2.31 -1.33,-3.96 v -0.13 z m 1.82,0.22 c 0,1.17 0.27,2.11 0.82,2.82 0.55,0.71 1.27,1.06 2.18,1.06 0.92,0 1.65,-0.36 2.19,-1.08 0.54,-0.72 0.81,-1.73 0.81,-3.02 0,-1.16 -0.28,-2.1 -0.83,-2.82 -0.55,-0.72 -1.28,-1.08 -2.19,-1.08 -0.89,0 -1.61,0.35 -2.16,1.06 -0.55,0.71 -0.82,1.74 -0.82,3.06 z" /><path
inkscape:connector-curvature="0"
id="path6191"
d="m 170.30855,134.70075 0.06,1.33 c 0.81,-1.02 1.86,-1.52 3.16,-1.52 2.23,0 3.36,1.26 3.38,3.78 v 6.98 h -1.81 v -6.99 c -0.01,-0.76 -0.18,-1.33 -0.52,-1.69 -0.34,-0.36 -0.87,-0.55 -1.6,-0.55 -0.59,0 -1.1,0.16 -1.54,0.47 -0.44,0.31 -0.79,0.72 -1.04,1.23 v 7.53 h -1.81 v -10.57 z" /></g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

101
docs/main.css Normal file
View File

@ -0,0 +1,101 @@
/************************/
/* GENERAL */
/************************/
body {
color: #1e1e1e;
}
h1, h2, h3, h4, h5, h6, p, a, li, span, blockquote, input, textarea, select, label {
font-family: 'Roboto', sans-serif !important;
}
p {
/* font-size: 16px;
line-height: 25px;
margin-bottom: 20px;*/
}
a {
text-decoration: none;
color: inherit;
}
/* Sidebar */
#top {
background-color: #F5F5F5;
width: 275px;
position: fixed;
top: 0;
bottom: 0;
left: 0;
height: auto !important;
overflow: auto;
padding: 25px;
box-sizing: border-box;
display: flex;
flex-direction: column;
}
@media (max-width: 1012px) {
#top {
box-shadow: 5px 0px 10px 0px rgba(0,0,0,0.25);
position: fixed;
z-index: 9999;
left: -100%;
width: 450px;
background-color: #F5F5F5;
transition: 0.2s left;
}
}
@media (max-width: 767px) {
#top {
width: calc(100% - 50px);
padding: 20px;
}
}
@media (max-width: 1012px) {
#top.open {
left: 0;
}
}
/* Content */
#doc-content {
padding: 25px 50px 25px 290px;
margin: 0 !important;
height: auto !important;
}
@media (max-width: 1012px) {
#doc-content {
padding: 110px 40px 40px 40px;
}
}
@media (max-width: 767px) {
#doc-content {
padding: 90px 20px 50px 20px;
}
}
/* Hide the default doxygen stuff that we dont want */
.ui-resizable-handle {
display: none !important;
}
#nav-sync {
display: none !important;
}
#nav-tree {
height: 100% !important;
background: none;
overflow: auto;
padding: 35px;
box-sizing: border-box;
}
#nav-path, #side-nav {
display: none !important;
}

17
docs/main.js Normal file
View File

@ -0,0 +1,17 @@
$(document).ready(function() {
// Trigger the mobile navigation
$(document).on('click', '.navigation-toggle', function (event) {
event.preventDefault();
$(this).toggleClass('clicked');
$('#top').toggleClass('open');
});
// Add a class to all <li>'s with children
$('#main-nav ul li > ul').parent().addClass('hasChildren');
$('#main-nav .has-submenu').removeClass('has-submenu');
$('#main-nav .sm').removeClass('sm');
$('#main-nav .sm-dox').removeClass('sm-dox');
$('#main-nav #main-menu').removeAttr('data-smartmenus-id');
$('#main-nav #main-menu').removeAttr('id');
});

31
docs/mainpage.md Normal file
View File

@ -0,0 +1,31 @@
# Pico SDK
The Pico SDK (Software Development Kit) provides the headers, libraries and build system necessary to write programs for the RP2040 based devices such as the Raspberry Pi Pico in C, C++ or assembly language. The Pico SDK is designed to provide an API and programming environment that is familiar both to non-embedded C developers and embedded C developers alike.
A single program runs on the device at a time with a conventional main() method. Standard C/C++ libraries are supported along with APIs for accessing the RP2040s hardware, including DMA, IRQs, and the wide variety fixed function peripherals and PIO (Programmable IO).
Additionally the Pico SDK provides higher level libraries for dealing with timers, USB, synchronization and multi-core programming, along with additional high level functionality built using PIO such as audio. The Pico SDK can be used to build anything from simple applications, full fledged runtime environments such as MicroPython, to low level software such as the RP2040s on chip bootrom itself.
This documentation is generated from the Pico SDK source tree using Doxygen. It provides basic information on the APIs used for each library, but does not provide usage information. Please refer to the Databooks for usage and more technical information.
## SDK Design
The RP2040 is a powerful chip, however it is an embedded environment, so both RAM, and program space are at premium. Additionally the trade offs between performance and other factors (e.g. edge case error handling, runtime vs compile time configuration) are necessarily much more visible to the developer than they might be on other higher level platforms.
The intention within the SDK has been for features to just work out of the box, with sensible defaults, but also to give the developer as much control and power as possible (if they want it) to fine tune every aspect of the application they are building and the libraries used.
## The build system
The Pico SDK uses CMake to manage the build. CMake is widely supported by IDEs (Integrated Development Environments), and allows a simple specification of the build (via CMakeLists.txt files), from which CMake can generate a build system (for use by `make`, `ninja` or other build tools) customized for the platform and by any configuration variables the developer chooses for a list of configuration variables).
Apart from being a widely used build system for C/C++ development, CMake is fundamental to the way the Pico SDK is structured, and how applications are configured and built.
The Pico SDK builds an executable which is bare metal, i.e. it includes the entirety of the code needed to run on the device (other than floating point and other optimized code contained in the bootrom within the RP2040).
## Examples
This SDK contains a number of example code fragments. An index of these examples can be found [here](@ref examples_page)

447
docs/normalise.css Normal file
View File

@ -0,0 +1,447 @@
/*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */
/* Document
========================================================================== */
/**
* 1. Correct the line height in all browsers.
* 2. Prevent adjustments of font size after orientation changes in
* IE on Windows Phone and in iOS.
*/
html {
line-height: 1.15; /* 1 */
-ms-text-size-adjust: 100%; /* 2 */
-webkit-text-size-adjust: 100%; /* 2 */
}
/* Sections
========================================================================== */
/**
* Remove the margin in all browsers (opinionated).
*/
body {
margin: 0;
}
/**
* Add the correct display in IE 9-.
*/
article,
aside,
footer,
header,
nav,
section {
display: block;
}
/**
* Correct the font size and margin on `h1` elements within `section` and
* `article` contexts in Chrome, Firefox, and Safari.
*/
h1 {
font-size: 145%;
margin: 0.67em 0;
}
/* Grouping content
========================================================================== */
/**
* Add the correct display in IE 9-.
* 1. Add the correct display in IE.
*/
figcaption,
figure,
main { /* 1 */
display: block;
}
/**
* Add the correct margin in IE 8.
*/
figure {
margin: 1em 40px;
}
/**
* 1. Add the correct box sizing in Firefox.
* 2. Show the overflow in Edge and IE.
*/
hr {
box-sizing: content-box; /* 1 */
height: 0; /* 1 */
overflow: visible; /* 2 */
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
pre {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/* Text-level semantics
========================================================================== */
/**
* 1. Remove the gray background on active links in IE 10.
* 2. Remove gaps in links underline in iOS 8+ and Safari 8+.
*/
a {
background-color: transparent; /* 1 */
-webkit-text-decoration-skip: objects; /* 2 */
}
/**
* 1. Remove the bottom border in Chrome 57- and Firefox 39-.
* 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari.
*/
abbr[title] {
border-bottom: none; /* 1 */
text-decoration: underline; /* 2 */
text-decoration: underline dotted; /* 2 */
}
/**
* Prevent the duplicate application of `bolder` by the next rule in Safari 6.
*/
b,
strong {
font-weight: inherit;
}
/**
* Add the correct font weight in Chrome, Edge, and Safari.
*/
b,
strong {
font-weight: bolder;
}
/**
* 1. Correct the inheritance and scaling of font size in all browsers.
* 2. Correct the odd `em` font sizing in all browsers.
*/
code,
kbd,
samp {
font-family: monospace, monospace; /* 1 */
font-size: 1em; /* 2 */
}
/**
* Add the correct font style in Android 4.3-.
*/
dfn {
font-style: italic;
}
/**
* Add the correct background and color in IE 9-.
*/
mark {
background-color: #ff0;
color: #000;
}
/**
* Add the correct font size in all browsers.
*/
small {
font-size: 80%;
}
/**
* Prevent `sub` and `sup` elements from affecting the line height in
* all browsers.
*/
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
/* Embedded content
========================================================================== */
/**
* Add the correct display in IE 9-.
*/
audio,
video {
display: inline-block;
}
/**
* Add the correct display in iOS 4-7.
*/
audio:not([controls]) {
display: none;
height: 0;
}
/**
* Remove the border on images inside links in IE 10-.
*/
img {
border-style: none;
}
/**
* Hide the overflow in IE.
*/
svg:not(:root) {
overflow: hidden;
}
/* Forms
========================================================================== */
/**
* 1. Change the font styles in all browsers (opinionated).
* 2. Remove the margin in Firefox and Safari.
*/
button,
input,
optgroup,
select,
textarea {
font-family: sans-serif; /* 1 */
font-size: 100%; /* 1 */
line-height: 1.15; /* 1 */
margin: 0; /* 2 */
}
/**
* Show the overflow in IE.
* 1. Show the overflow in Edge.
*/
button,
input { /* 1 */
overflow: visible;
}
/**
* Remove the inheritance of text transform in Edge, Firefox, and IE.
* 1. Remove the inheritance of text transform in Firefox.
*/
button,
select { /* 1 */
text-transform: none;
}
/**
* 1. Prevent a WebKit bug where (2) destroys native `audio` and `video`
* controls in Android 4.
* 2. Correct the inability to style clickable types in iOS and Safari.
*/
button,
html [type="button"], /* 1 */
[type="reset"],
[type="submit"] {
-webkit-appearance: button; /* 2 */
}
/**
* Remove the inner border and padding in Firefox.
*/
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
/**
* Restore the focus styles unset by the previous rule.
*/
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
/**
* Correct the padding in Firefox.
*/
fieldset {
padding: 0.35em 0.75em 0.625em;
}
/**
* 1. Correct the text wrapping in Edge and IE.
* 2. Correct the color inheritance from `fieldset` elements in IE.
* 3. Remove the padding so developers are not caught out when they zero out
* `fieldset` elements in all browsers.
*/
legend {
box-sizing: border-box; /* 1 */
color: inherit; /* 2 */
display: table; /* 1 */
max-width: 100%; /* 1 */
padding: 0; /* 3 */
white-space: normal; /* 1 */
}
/**
* 1. Add the correct display in IE 9-.
* 2. Add the correct vertical alignment in Chrome, Firefox, and Opera.
*/
progress {
display: inline-block; /* 1 */
vertical-align: baseline; /* 2 */
}
/**
* Remove the default vertical scrollbar in IE.
*/
textarea {
overflow: auto;
}
/**
* 1. Add the correct box sizing in IE 10-.
* 2. Remove the padding in IE 10-.
*/
[type="checkbox"],
[type="radio"] {
box-sizing: border-box; /* 1 */
padding: 0; /* 2 */
}
/**
* Correct the cursor style of increment and decrement buttons in Chrome.
*/
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
/**
* 1. Correct the odd appearance in Chrome and Safari.
* 2. Correct the outline style in Safari.
*/
[type="search"] {
-webkit-appearance: textfield; /* 1 */
outline-offset: -2px; /* 2 */
}
/**
* Remove the inner padding and cancel buttons in Chrome and Safari on macOS.
*/
[type="search"]::-webkit-search-cancel-button,
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
/**
* 1. Correct the inability to style clickable types in iOS and Safari.
* 2. Change font properties to `inherit` in Safari.
*/
::-webkit-file-upload-button {
-webkit-appearance: button; /* 1 */
font: inherit; /* 2 */
}
/* Interactive
========================================================================== */
/*
* Add the correct display in IE 9-.
* 1. Add the correct display in Edge, IE, and Firefox.
*/
details, /* 1 */
menu {
display: block;
}
/*
* Add the correct display in all browsers.
*/
summary {
display: list-item;
}
/* Scripting
========================================================================== */
/**
* Add the correct display in IE 9-.
*/
canvas {
display: inline-block;
}
/**
* Add the correct display in IE.
*/
template {
display: none;
}
/* Hidden
========================================================================== */
/**
* Add the correct display in IE 10-.
*/
[hidden] {
display: none;
}

BIN
docs/pico.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

BIN
docs/rp2040.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

1
docs/search.svg Normal file
View File

@ -0,0 +1 @@
<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" viewBox="0 0 29 29" xml:space="preserve"><style type="text/css">.st0{fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:10;} .st1{fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;} .st2{fill:none;stroke:#000000;stroke-miterlimit:10;} .st3{fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:10;stroke-dasharray:1.7411,1.7411;} .st4{fill:none;stroke:#000000;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:2.0261,4.0522;}</style><circle class="st0" cx="11.854" cy="11.854" r="9" fill="none" stroke="#000" stroke-miterlimit="10" stroke-width="2"/><path class="st1" fill="none" stroke="#000" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="2" d="M18.451 18.451l7.695 7.695"/><metadata><rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#" xmlns:dc="http://purl.org/dc/elements/1.1/"><rdf:Description about="https://iconscout.com/legal#licenses" dc:title="search,find,magnifier,glass,magnify" dc:description="search,find,magnifier,glass,magnify" dc:publisher="Iconscout" dc:date="2017-10-04" dc:format="image/svg+xml" dc:language="en"><dc:creator><rdf:Bag><rdf:li>Jemis Mali</rdf:li></rdf:Bag></dc:creator></rdf:Description></rdf:RDF></metadata></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

703
docs/styles.css Normal file
View File

@ -0,0 +1,703 @@
.logo {
margin-bottom: 30px;
}
@media (max-width: 1012px) {
.logo {
display: none;
}
}
.logo--mobile {
display: none;
}
@media (max-width: 1012px) {
.logo--mobile {
display: block;
box-sizing: border-box;
max-width: 35px;
position: absolute;
z-index: 10;
top: 50%;
left: 40px;
transform: translateY(-50%);
}
.logo--mobile img {
width: 100%;
}
}
@media (max-width: 767px) {
.logo--mobile {
left: 20px;
}
}
.navigation-footer {
margin-top: auto;
order: 3;
color: #CA4F62;
display: flex;
align-items: center;
}
@media (max-width: 1012px) {
.navigation-footer {
margin-top: 50px;
}
}
.navigation-footer img {
height: 35px;
}
.navigation-footer a {
font-size: .9em;
margin-left: 10px;
}
/* Search Box */
#MSearchBox {
border-radius: 5px;
margin-top: 0px;
margin-bottom: 15px;
background: none;
background-color: white;
position: relative;
border-radius: 0;
box-shadow: none;
width: 100%;
}
#MSearchBox .right {
display: none;
}
#MSearchBox .left {
width: 100%;
height: auto;
left: 0;
}
#MSearchBox img {
position: absolute;
z-index: 1;
top: 4px;
left: 0px;
}
#MSearchBox input[type=text] {
position: inherit;
padding: 16px 15px 14px 30px;
border: 0;
box-sizing: border-box;
background: none;
background-color: white;
width: 100%;
margin: 0;
box-sizing: border-box;
font-family: 'Roboto', sans-serif;
font-size: 0.9em;
}
#MSearchSelectWindow {
position: fixed;
top: 145px !important;
left: 35px !important;
border: solid 1px #d4d4d4;
border-radius: 0;
box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.25);
background-color: white;
}
#MSearchSelectWindow .SelectItem {
font-family: 'Roboto', sans-serif;
padding: 1px 25px 1px 6px;
}
#MSearchSelectWindow .SelectionMark {
color: black;
}
#MSearchSelectWindow .SelectItem:hover {
background-color: #CA4F62;
}
#MSearchResultsWindow {
position: fixed;
top: 145px !important;
left: 35px !important;
border: solid 1px #d4d4d4;
border-radius: 0;
box-shadow: 0px 3px 5px 0px rgba(0,0,0,0.25);
background-color: white;
}
.SRSymbol {
color: #CA4F62;
}
/* Main Navigation */
#main-nav ul {
list-style-type: none;
margin: 0;
padding: 0;
}
#main-nav > ul {
display: flex;
flex-direction: column;
}
#main-nav > ul > li > a {
font-weight: normal;
font-size: 18px;
}
#main-nav > ul > li {
position: relative;
padding-bottom: 20px;
flex: 1;
order: 2;
}
#main-nav > ul > li:last-child {
order: 1;
float: none !important;
}
#main-nav ul li a {
display: block;
}
#main-nav ul li.hasChildren > a:hover[aria-expanded="false"] {
text-decoration: none;
}
#main-nav ul li a:hover {
text-decoration: underline;
color: #CA4F62;
}
#main-nav ul ul li {
position: relative;
padding-bottom: 10px;
}
#main-nav ul li.hasChildren > a[aria-expanded="false"]:after {
position: absolute;
content: "+";
/*top: -1px;*/
right: -2px;
line-height: 20px;
font-size: 20px;
}
#main-nav li ul {
padding-left: 5px;
display: none;
padding-top: 15px;
/*padding-bottom: 15px;*/
}
@media (max-width: 1012px) {
#main-nav > ul > li.hasChildren:after {
top: 9px;
}
#main-nav > ul > li {
padding-bottom: 0px;
}
#main-nav > ul > li:first-child {
border-top: 1px solid rgba(0,0,0,0.2);
}
#main-nav > ul > li {
padding: 10px 0;
border-bottom: 1px solid rgba(0,0,0,0.2);
}
#main-nav > ul > li:last-child {
padding: 10px 0;
}
#main-nav > ul > li ul {
padding-bottom: 10px;
}
}
/* Page Header */
div.header {
background: none;
padding: 0px;
margin-bottom: 20px;
border-bottom: none;
}
div.header .headertitle {
padding: 0;
}
div.header .title {
margin: 0;
}
div.header .summary {
font-size: 13px;
padding: 9px 0 0 0;
width: auto;
}
@media (max-width: 767px) {
div.header .summary {
text-align: left;
margin-bottom: 20px;
}
}
div.header .summary a:hover {
color: #CA4F62;
}
div.header .ingroups {
font-size: 13px;
width: auto;
font-weight: normal;
}
/* Floating labels */
span.mlabels {
margin: 0;
margin-left: 10px;
}
span.mlabel {
margin: 0;
margin-left: 10px;
border: solid 1px #CA4F62;
background-color: #CA4F62;
padding: 3px 5px;
font-weight: normal;
}
/* Content area */
div.contents {
padding: 0;
margin: 0px;
margin-bottom: 20px;
}
div.contents ul li {
margin-bottom: 10px;
}
div.contents ul li:last-child {
margin-bottom: 0px;
}
div.toc {
padding: 0;
padding-bottom: 20px;
background-color: transparent;
border: none;
box-sizing: border-box;
float: none;
width: 100%;
margin: 0;
border-radius: 0;
}
@media (max-width: 767px) {
div.toc {
//
}
}
div.toc h3 {
margin: 0;
margin-bottom: 5px;
color: black;
font: 400 14px/22px Roboto,sans-serif;
font-weight: bold;
}
div.toc ul {
margin: 0;
}
div.toc ul li {
margin-left: 0 !important;
padding-left: 15px !important;
font: 400 14px/22px Roboto,sans-serif;
}
div.toc li ul {
padding-left: 10px;
padding-top: 7px;
}
/* Group Headers */
h2.groupheader {
border-bottom: solid 1px #d4d4d4;
color: black;
margin: 0px;
margin-top: 30px;
padding: 10px 0;
}
tr.heading h2 {
margin: 0px;
}
/* Tables */
table.memberdecls {
margin-top: 30px;
/*margin-bottom: 30px;*/
}
table.memberdecls td.memSeparator {
line-height: 0;
font-size: 0;
border-bottom: 1px solid #d4d4d4;
}
table.memberdecls td.memItemLeft {
padding: 7px 15px 4px 15px;
background-color: #f5f5f5;
}
table.memberdecls td.memItemRight {
padding: 7px 15px 4px 15px;
background-color: #f5f5f5;
}
table.memberdecls td.mdescLeft {
padding: 7px 15px 4px 15px;
background-color: #f5f5f5;
}
table.memberdecls td.mdescRight {
padding: 7px 15px 4px 15px;
background-color: #f5f5f5;
}
table.params .paramname {
color: black;
}
table.markdownTable td, table.markdownTable th {
border: 1px solid #d4d4d4;
padding: 3px 7px;
color: black;
}
table.markdownTable th.markdownTableHeadLeft, table.markdownTable th.markdownTableHeadRight, table.markdownTable th.markdownTableHeadCenter, table.markdownTable th.markdownTableHeadNone {
background-color: #f5f5f5;
color: black;
padding: 3px 7px;
}
div.contents .fragment {
border: solid 1px #CA4F62;
padding: 20px;
border-radius: 4px;
}
div.contents .line {
line-height: 15px;
}
.memtitle {
margin-top: 10px;
border-top: solid 1px #d4d4d4;
border-left: solid 1px #d4d4d4;
border-right: solid 1px #d4d4d4;
background: none;
background-color: #f5f5f5;
padding: 8px 10px;
font-weight: bold;
font-size: 18px;
}
.memtitle .permalink a, .memtitle .permalink a:visited {
color: black;
}
.memtitle .permalink a:hover {
text-decoration: none;
}
.memitem {
margin: 0;
box-shadow: none;
}
.memitem.glow {
box-shadow: 0 0 15px #CA4F62;
}
.memitem .memproto {
box-shadow: none;
background: none;
background-color: #f5f5f5;
border-top: solid 1px #d4d4d4;
border-left: solid 1px #d4d4d4;
border-right: solid 1px #d4d4d4;
color: black;
padding: 8px 10px;
}
.memitem .memproto .memname {
margin-left: 0;
}
.memitem .memdoc {
box-shadow: none;
background: none;
border-bottom: solid 1px #d4d4d4;
border-left: solid 1px #d4d4d4;
border-right: solid 1px #d4d4d4;
padding: 10px 12px;
}
/* General links? */
a.el {
font-weight: normal;
}
a.el {
color: #CA4F62;
}
a.el:visited {
color: #CA4F62;
}
a.el:hover {
color: #CA4F62;
}
div.contents a {
color: #CA4F62;
}
div.contents a:visited {
color: #CA4F62;
}
div.contents a:hover {
color: #CA4F62;
}
/* Highlighted effect */
h1.glow, h2.glow, h3.glow, h4.glow, h5.glow, h6.glow {
text-shadow: 0 0 15px #CA4F62;
}
/* Directory */
div.directory {
margin: 20px 0px;
border-top: 1px solid #d4d4d4;
border-bottom: 1px solid #d4d4d4;
}
div.directory .levels {
font-size: 13px;
padding: 8px 0;
}
div.directory .levels span:hover {
color: #CA4F62;
}
table.directory {
/*width: 100%;*/
}
table.directory tr.even {
background-color: #f5f5f5;
}
table.directory td.entry {
padding: 8px 6px;
vertical-align: middle;
box-sizing: border-box;
}
table.directory td.desc {
padding: 8px 6px;
vertical-align: middle;
box-sizing: border-box;
}
/* Icons */
.iconfopen, .icondoc {
margin: 0;
}
dl.reflist dt {
box-shadow: none;
background-color: #F5F5F5;
border-top: solid 1px #d4d4d4;
border-left: solid 1px #d4d4d4;
border-right: solid 1px #d4d4d4;
padding: 10px;
}
dl.reflist dd {
box-shadow: none;
background: none;
border-bottom: solid 1px #d4d4d4;
border-left: solid 1px #d4d4d4;
border-right: solid 1px #d4d4d4;
padding: 10px;
}
/* Standard arrow icon? */
.arrow {
color: #d4d4d4;
width: auto;
height: auto;
margin: 0 5px;
}
.icona {
height: auto;
width: auto;
margin-right: 8px;
}
.icona .icon {
font-family: 'Roboto', sans-serif;
margin: 0;
background-color: #CA4F62;
padding: 1px;
font-weight: normal;
}
/* horizontal ruler */
hr {
border: none;
border-top: 1px solid #d4d4d4;
margin-top: 20px;
margin-bottom: 20px;
}
/* Notes */
dl.warning {
margin: 0px;
padding: 0px;
padding-left: 10px;
}
dl.note {
margin: 0px;
padding: 0px;
padding-left: 10px;
}
dl.attention {
margin: 0px;
padding: 0px;
padding-left: 10px;
}
dl.todo {
margin: 0px;
padding: 0px;
padding-left: 10px;
}
dl dt, dl dt a.el {
font-weight: bold;
}
dl dd {
margin: 0px;
}
table.fieldtable {
box-shadow: none;
border: 1px solid #d4d4d4;
}
table.fieldtable th {
background: none;
background-color: #F5F5F5;
border-bottom: 1px solid #d4d4d4;
color: black;
font-size: 100%;
font-weight: bold;
}
table.fieldtable td.fieldname, table.fieldtable td.fielddoc {
border-bottom: 1px solid #d4d4d4;
border-right: 1px solid #d4d4d4;
vertical-align: middle;
}
div.qindex {
background-color: #F5F5F5;
border: none;
text-align: center;
padding: 8px 0;
}
table.classindex div.ah {
font-family: 'Roboto', sans-serif;
margin: 0;
background: none;
background-color: #CA4F62;
padding: 1px;
font-weight: normal;
border: none;
box-shadow: none;
border-radius: 0;
padding: 3px;
}
table.classindex td {
padding: 3px 6px;
vertical-align: middle;
font-size: 14px;
}
table.classindex table td {
padding: 0;
vertical-align: middle;
}
div.textblock h2 {
border-bottom: solid 1px #d4d4d4;
padding-bottom: 10px;
}
.navigation-mobile {
display: none;
background-color: #F5F5F5;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 70px;
}
@media (max-width: 1012px) {
.navigation-mobile {
display: block;
}
}
.navigation-toggle {
cursor: pointer;
width: 44px;
height: 44px;
margin-right: 20px;
position: absolute;
right: 0;
top: 50%;
transform: translateY(-50%);
bottom: 5%;
z-index: 50;
display: none;
}
@media (max-width: 1012px) {
.navigation-toggle {
display: block;
}
}
@media (max-width: 767px) {
.navigation-toggle {
margin-right: 0px;
}
}
.navigation-toggle span {
display: block;
text-indent: -9999px;
position: absolute;
height: 2px;
left: 10px;
right: 10px;
background-color: #CA4F62;
border-radius: 1px;
transition: 0.15s all;
}
.line-1 {
top: 14px;
}
.line-2 {
top: 50%;
margin-top: -1px;
}
.line-3 {
bottom: 14px;
}
.navigation-toggle.clicked .line-1 {
transform: rotate(45deg);
top: 21px;
}
.navigation-toggle.clicked .line-2 {
opacity: 0;
}
.navigation-toggle.clicked .line-3 {
transform: rotate(-45deg);
bottom: 21px;
}

30
docs/weblinks_page.md Normal file
View File

@ -0,0 +1,30 @@
## Documentation and datasheets {#weblinks_page}
The full documentation for the RP2040 and Raspberry Pi Pico board can be found at the following links
- [RP2040 Datasheet](https://rptl.io/rp2040-datasheet)
- [Raspberry Pi Pico datasheet](https://rptl.io/pico-datasheet)
- [Hardware Design with the RP2040](https://rptl.io/rp2040-design)
- [Pico C/C++ SDK](https://rptl.io/pico-c-sdk)
- [Pico Python SDK](https://rptl.io/pico-micropython)
- [Getting Started with Raspberry Pi Pico](https://rptl.io/pico-get-started)
### Weblinks
At Raspberry Pi we have a very community based attitude to help. We run a very popular and busy forum where you can ask questions about any aspect of the Raspberry Pi ecosystem, including the Raspberry Pi Pico.
You can find our forums at the [following link](https://www.raspberrypi.org/forums).
For the main Raspberry Pi website, [see here](https://www.raspberrypi.org)
For the Raspberry Pi Pico page, [see here](https://rptl.io/rp2040-get-started)
### Github
All the source code for the Pico SDK, examples and other libraries can be found on Github.
- [Pico C/C++ SDK](https://github.com/raspberrypi/pico-sdk)
- [Pico Examples](https://github.com/raspberrypi/pico-examples)
- [Pico Extras - Libraries under development](https://github.com/raspberrypi/pico-extras)
- [Pico Playground - Examples that use Pico Extras](https://github.com/raspberrypi/pico-playground)
- [Pico Bootrom source code](https://github.com/raspberrypi/pico-bootrom)

62
external/pico_sdk_import.cmake vendored Normal file
View File

@ -0,0 +1,62 @@
# This is a copy of <PICO_SDK_PATH>/external/pico_sdk_import.cmake
# This can be dropped into an external project to help locate this SDK
# It should be include()ed prior to project()
if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH))
set(PICO_SDK_PATH $ENV{PICO_SDK_PATH})
message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT))
set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT})
message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')")
endif ()
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH))
set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH})
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
endif ()
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the PICO SDK")
set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of PICO SDK from git if not otherwise locatable")
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
if (NOT PICO_SDK_PATH)
if (PICO_SDK_FETCH_FROM_GIT)
include(FetchContent)
set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR})
if (PICO_SDK_FETCH_FROM_GIT_PATH)
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
endif ()
FetchContent_Declare(
pico_sdk
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
GIT_TAG master
)
if (NOT pico_sdk)
message("Downloading PICO SDK")
FetchContent_Populate(pico_sdk)
set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR})
endif ()
set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE})
else ()
message(FATAL_ERROR
"PICO SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git."
)
endif ()
endif ()
get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}")
if (NOT EXISTS ${PICO_SDK_PATH})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found")
endif ()
set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake)
if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE})
message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the PICO SDK")
endif ()
set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the PICO SDK" FORCE)
include(${PICO_SDK_INIT_CMAKE_FILE})

1
lib/tinyusb Submodule

@ -0,0 +1 @@
Subproject commit e0aa405d19e35dbf58cf502b8106455c1a3c2a5c

54
pico_sdk_init.cmake Normal file
View File

@ -0,0 +1,54 @@
# Initialize the PICO SDK
# This file must be included prior to the project() call
if (_PICO_SDK_INIT)
return()
endif ()
set(_PICO_SDK_INIT 1)
function(pico_is_top_level_project VAR)
string(TOLOWER ${CMAKE_CURRENT_LIST_DIR} __list_dir)
string(TOLOWER ${CMAKE_SOURCE_DIR} __source_dir)
if (__source_dir STREQUAL __list_dir)
set(${VAR} 1 PARENT_SCOPE)
else()
set(${VAR} 0 PARENT_SCOPE)
endif()
endfunction()
if (NOT PICO_SDK_PATH)
set(PICO_SDK_PATH ${CMAKE_CURRENT_LIST_DIR})
endif ()
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 Pico SDK" FORCE)
list(APPEND CMAKE_MODULE_PATH ${PICO_SDK_PATH}/cmake)
include(${CMAKE_CURRENT_LIST_DIR}/pico_sdk_version.cmake)
include(pico_utils)
message("Pico SDK is located at ${CMAKE_CURRENT_LIST_DIR}")
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
include(pico_pre_load_toolchain)
macro(pico_sdk_init)
if (NOT CMAKE_PROJECT_NAME)
message(WARNING "pico_sdk_init() should be called after the project is created (and languages added)")
endif()
add_subdirectory(${PICO_SDK_PATH} pico_sdk)
endmacro()
macro(add_sub_list_dirs var)
foreach(LIST_DIR IN LISTS ${var})
get_filename_component(SHORT_NAME "${LIST_DIR}" NAME)
message("Including custom CMakeLists.txt ${SHORT_NAME}")
add_subdirectory(${LIST_DIR} ${SHORT_NAME})
endforeach()
endmacro()

12
pico_sdk_version.cmake Normal file
View File

@ -0,0 +1,12 @@
# PICO_BUILD_DEFINE: PICO_SDK_VERSION_MAJOR, SDK major version number, type=int, pico_base
# PICO_CONFIG: PICO_SDK_VERSION_MAJOR, SDK major version number, type=int, pico_base
set(PICO_SDK_VERSION_MAJOR 1)
# PICO_BUILD_DEFINE: PICO_SDK_VERSION_MINOR, SDK minor version number, type=int, pico_base
# PICO_CONFIG: PICO_SDK_VERSION_MINOR, SDK minor version number, type=int, pico_base
set(PICO_SDK_VERSION_MINOR 0)
# PICO_BUILD_DEFINE: PICO_SDK_VERSION_REVISION, SDK version revision, type=int, pico_base
# PICO_CONFIG: PICO_SDK_VERSION_REVISION, SDK version revision, type=int, pico_base
set(PICO_SDK_VERSION_REVISION 0)
# 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
set(PICO_SDK_VERSION_STRING "${PICO_SDK_VERSION_MAJOR}.${PICO_SDK_VERSION_MINOR}.${PICO_SDK_VERSION_REVISION}")

89
src/CMakeLists.txt Normal file
View File

@ -0,0 +1,89 @@
cmake_policy(SET CMP0079 NEW) # allow inserting of dependencies into our INTERFACE libraries
set(PICO_PLATFORM_CMAKE_FILE "" CACHE INTERNAL "")
set(PICO_DOXYGEN_PATHS "" CACHE INTERNAL "") # generated each time
if (NOT PICO_PLATFORM_CMAKE_FILE)
set(PICO_PLATFORM_CMAKE_FILE ${CMAKE_CURRENT_LIST_DIR}/${PICO_PLATFORM}.cmake CACHE INTERNAL "")
endif ()
if (NOT EXISTS "${PICO_PLATFORM_CMAKE_FILE}")
message(FATAL_ERROR "${PICO_PLATFORM_CMAKE_FILE} does not exist. \
Either specify a valid PICO_PLATFORM (or PICO_PLATFORM_CMAKE_FILE).")
endif ()
include(${CMAKE_CURRENT_LIST_DIR}/board_setup.cmake)
# todo add option to disable skip flag
function(pico_add_subdirectory subdir)
string(TOUPPER ${subdir} subdir_upper)
set(replace_flag SKIP_${subdir_upper})
if (NOT ${replace_flag})
add_subdirectory(${subdir})
else ()
message("Not including ${subdir} because ${replace_flag} defined.")
endif ()
endfunction()
function(pico_wrap_function TARGET FUNCNAME)
target_link_options(${TARGET} INTERFACE "LINKER:--wrap=${FUNCNAME}")
endfunction()
function(pico_add_map_output TARGET)
get_target_property(target_type ${TARGET} TYPE)
if ("EXECUTABLE" STREQUAL "${target_type}")
target_link_options(${TARGET} PRIVATE "LINKER:-Map=$<TARGET_PROPERTY:NAME>${CMAKE_EXECUTABLE_SUFFIX}.map")
else ()
target_link_options(${TARGET} INTERFACE "LINKER:-Map=$<TARGET_PROPERTY:NAME>${CMAKE_EXECUTABLE_SUFFIX}.map")
endif ()
endfunction()
macro(pico_simple_hardware_target NAME)
pico_simple_hardware_headers_target(${NAME})
pico_simple_hardware_impl_target(${NAME})
endmacro()
macro(pico_simple_hardware_headers_target NAME)
if (NOT TARGET hardware_${NAME}_headers)
add_library(hardware_${NAME}_headers INTERFACE)
target_include_directories(hardware_${NAME}_headers INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
target_link_libraries(hardware_${NAME}_headers INTERFACE pico_base_headers)
if (NOT PICO_NO_HARDWARE)
target_link_libraries(hardware_${NAME}_headers INTERFACE hardware_structs hardware_claim)
endif()
endif()
endmacro()
macro(pico_simple_hardware_headers_only_target NAME)
if (NOT TARGET hardware_${NAME})
add_library(hardware_${NAME} INTERFACE)
target_include_directories(hardware_${NAME} INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
target_link_libraries(hardware_${NAME} INTERFACE pico_base_headers)
if (NOT PICO_NO_HARDWARE)
target_link_libraries(hardware_${NAME} INTERFACE hardware_structs)
endif()
endif()
endmacro()
macro(pico_simple_hardware_impl_target NAME)
if (NOT TARGET hardware_${NAME})
add_library(hardware_${NAME} INTERFACE)
target_sources(hardware_${NAME} INTERFACE
${CMAKE_CURRENT_LIST_DIR}/${NAME}.c
)
target_link_libraries(hardware_${NAME} INTERFACE hardware_${NAME}_headers pico_platform)
endif()
endmacro()
function(pico_add_doxygen SOURCE_DIR)
set(PICO_DOXYGEN_PATHS "${PICO_DOXYGEN_PATHS} ${SOURCE_DIR}" CACHE INTERNAL "")
endfunction()
function(pico_add_doxygen_exclude SOURCE_DIR)
set(PICO_DOXYGEN_EXCLUDE_PATHS "${PICO_DOXYGEN_EXCLUDE_PATHS} ${SOURCE_DIR}" CACHE INTERNAL "")
endfunction()
include(${PICO_PLATFORM_CMAKE_FILE})

31
src/board_setup.cmake Normal file
View File

@ -0,0 +1,31 @@
# PICO_CMAKE_CONFIG: PICO_BOARD, The board name being built for. This is overridable from the user environment, type=string, default=rp2040, group=build
if (DEFINED ENV{PICO_BOARD})
set(PICO_BOARD $ENV{PICO_BOARD})
message("Using PICO_BOARD from environment ('${PICO_BOARD}')")
else()
if (NOT PICO_BOARD)
set(PICO_BOARD "pico")
pico_message("Defaulting PICO target board to ${PICO_BOARD} since not specified.")
else()
message("PICO target board is ${PICO_BOARD}.")
endif()
endif()
set(PICO_BOARD ${PICO_BOARD} CACHE STRING "PICO target board (e.g. pico)")
# PICO_CMAKE_CONFIG: PICO_BOARD_CMAKE_DIRS, Directors to look for <PICO_BOARD>.cmake in. This is overridable from the user environment, type=list, default="", group=build
if (DEFINED ENV{PICO_BOARD_CMAKE_DIRS})
set(PICO_BOARD_CMAKE_DIRS $ENV{PICO_BOARD_CMAKE_DIRS})
message("Using PICO_BOARD_CMAKE_DIRS from environment ('${PICO_BOARD_CMAKE_DIRS}')")
endif()
list(APPEND PICO_BOARD_CMAKE_DIRS ${CMAKE_CURRENT_LIST_DIR}/boards)
pico_find_in_paths(PICO_BOARD_CMAKE_FILE PICO_BOARD_CMAKE_DIRS ${PICO_BOARD}.cmake)
if (EXISTS "${PICO_BOARD_CMAKE_FILE}")
message("Using CMake board configuration from ${PICO_BOARD_CMAKE_FILE}")
include(${PICO_BOARD_CMAKE_FILE} board_config)
else()
include(boards/generic_board.cmake)
endif()
list(APPEND PICO_INCLUDE_DIRS ${CMAKE_CURRENT_LIST_DIR}/boards/include) # so boards/foo.h can be explicitly included

View File

@ -0,0 +1,23 @@
# For boards without their own cmake file, simply include a header
# PICO_CMAKE_CONFIG: PICO_BOARD_HEADER_DIRS, Directors to look for <PICO_BOARD>.h in. This is overridable from the user environment, type=list, default="", group=build
if (DEFINED ENV{PICO_BOARD_HEADER_DIRS})
set(PICO_BOARD_HEADER_DIRS $ENV{PICO_BOARD_HEADER_DIRS})
message("Using PICO_BOARD_HEADER_DIRS from environment ('${PICO_BOARD_HEADER_DIRS}')")
endif()
set(PICO_BOARD_HEADER_DIRS ${PICO_BOARD_HEADER_DIRS} CACHE STRING "PICO board header directories")
list(APPEND PICO_BOARD_HEADER_DIRS ${CMAKE_CURRENT_LIST_DIR}/include/boards)
pico_find_in_paths(PICO_BOARD_HEADER_FILE PICO_BOARD_HEADER_DIRS ${PICO_BOARD}.h)
if (EXISTS ${PICO_BOARD_HEADER_FILE})
message("Using board configuration from ${PICO_BOARD_HEADER_FILE}")
list(APPEND PICO_CONFIG_HEADER_FILES ${PICO_BOARD_HEADER_FILE})
else()
set(msg "Unable to find definition of board '${PICO_BOARD}' (specified by PICO_BOARD):\n")
list(JOIN PICO_BOARD_HEADER_DIRS ", " DIRS)
string(CONCAT msg ${msg} " Looked for ${PICO_BOARD}.h in ${DIRS} (additional paths specified by PICO_BOARD_HEADER_DIRS)\n")
list(JOIN PICO_BOARD_CMAKE_DIRS ", " DIRS)
string(CONCAT msg ${msg} " Looked for ${PICO_BOARD}.cmake in ${DIRS} (additional paths specified by PICO_BOARD_CMAKE_DIRS)")
message(FATAL_ERROR ${msg})
endif()

View File

@ -0,0 +1,15 @@
/*
* 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_NONE_H
#define _BOARDS_NONE_H
#endif

View File

@ -0,0 +1,52 @@
/*
* 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
// -----------------------------------------------------
// This header may be included by other board headers as "boards/pico.h"
#ifndef _BOARDS_PICO_H
#define _BOARDS_PICO_H
#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
#ifndef PICO_DEFAULT_LED_PIN
#define PICO_DEFAULT_LED_PIN 25
#endif
#ifndef PICO_FLASH_SPI_CLKDIV
#define PICO_FLASH_SPI_CLKDIV 2
#endif
#ifndef PICO_FLASH_SIZE_BYTES
#define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024)
#endif
// Drive high to force power supply into PWM mode (lower ripple on 3V3 at light loads)
#define PICO_SMPS_MODE_PIN 23
#ifndef PICO_FLOAT_SUPPORT_ROM_V1
#define PICO_FLOAT_SUPPORT_ROM_V1 1
#endif
#ifndef PICO_DOUBLE_SUPPORT_ROM_V1
#define PICO_DOUBLE_SUPPORT_ROM_V1 1
#endif
#endif

View File

@ -0,0 +1,104 @@
/*
* 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_VGABOARD_H
#define _BOARDS_VGABOARD_H
#ifndef PICO_DEFAULT_UART
#define PICO_DEFAULT_UART 1
#endif
#ifndef PICO_DEFAULT_UART_TX_PIN
#define PICO_DEFAULT_UART_TX_PIN 20
#endif
#ifndef PICO_DEFAULT_UART_RX_PIN
#define PICO_DEFAULT_UART_RX_PIN 21
#endif
#ifndef PICO_DEFAULT_LED_PIN
#define PICO_DEFAULT_LED_PIN 25 // same as Pico
#endif
// 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
// they are constant duty cycle, and above the filter cutoff
// - When outputting PWM, I2S DIN should be low, so I2S should remain silent.
#define VGABOARD_I2S_DIN_PIN 26
#define VGABOARD_I2S_BCK_PIN 27
#define VGABOARD_I2S_LRCK_PIN 28
#define VGABOARD_PWM_L_PIN 28
#define VGABOARD_PWM_R_PIN 27
#define VGABOARD_VGA_COLOR_PIN_BASE 0
#define VGABOARD_VGA_SYNC_PIN_BASE 16
// Note DAT2/3 are shared with UART TX/RX (pull jumpers off header to access
// UART pins and disconnect SD DAT2/3)
#define VGABOARD_SD_CLK_PIN 5
#define VGABOARD_SD_CMD_PIN 18
#define VGABOARD_SD_DAT0_PIN 19
// Note buttons are shared with VGA colour LSBs -- if using VGA, you can float
// the pin on VSYNC assertion and sample on VSYNC deassertion
#define VGABOARD_BUTTON_A_PIN 0
#define VGABOARD_BUTTON_B_PIN 6
#define VGABOARD_BUTTON_C_PIN 11
#ifndef PICO_SCANVIDEO_COLOR_PIN_BASE
#define PICO_SCANVIDEO_COLOR_PIN_BASE VGABOARD_VGA_COLOR_PIN_BASE
#endif
#ifndef PICO_SCANVIDEO_SYMC_PIN_BASE
#define PICO_SCANVIDEO_SYNC_PIN_BASE VGABOARD_VGA_SYNC_PIN_BASE
#endif
#ifndef PICO_SD_CLK_PIN
#define PICO_SD_CLK_PIN VGABOARD_SD_CLK_PIN
#endif
#ifndef PICO_SD_CMD_PIN
#define PICO_SD_CMD_PIN VGABOARD_SD_CMD_PIN
#endif
#ifndef PICO_SD_DAT0_PIN
#define PICO_SD_DAT0_PIN VGABOARD_SD_DAT0_PIN
#endif
#define PICO_AUDIO_I2S_DATA_PIN VGABOARD_I2S_DIN_PIN
#define PICO_AUDIO_I2S_CLOCK_PIN_BASE VGABOARD_I2S_BCK_PIN
#define PICO_AUDIO_PWM_L_PIN VGABOARD_PWM_L_PIN
#define PICO_AUDIO_PWM_R_PIN VGABOARD_PWM_R_PIN
#ifndef PICO_FLASH_SPI_CLKDIV
#define PICO_FLASH_SPI_CLKDIV 2
#endif
#ifndef PICO_FLASH_SIZE_BYTES
#define PICO_FLASH_SIZE_BYTES (2 * 1024 * 1024)
#endif
// Drive high to force power supply into PWM mode (lower ripple on 3V3 at light loads)
#define PICO_SMPS_MODE_PIN 23
#ifndef PICO_FLOAT_SUPPORT_ROM_V1
#define PICO_FLOAT_SUPPORT_ROM_V1 1
#endif
#ifndef PICO_DOUBLE_SUPPORT_ROM_V1
#define PICO_DOUBLE_SUPPORT_ROM_V1 1
#endif
#define PICO_VGA_BOARD
#endif

16
src/common/CMakeLists.txt Normal file
View File

@ -0,0 +1,16 @@
pico_add_subdirectory(boot_picoboot)
pico_add_subdirectory(boot_uf2)
pico_add_subdirectory(pico_base)
# PICO_CMAKE_CONFIG: PICO_BARE_METAL, Flag to exclude anything except base headers from the build, type=bool, default=0, group=build
if (NOT PICO_BARE_METAL)
pico_add_subdirectory(pico_bit_ops)
pico_add_subdirectory(pico_binary_info)
pico_add_subdirectory(pico_divider)
pico_add_subdirectory(pico_sync)
pico_add_subdirectory(pico_time)
pico_add_subdirectory(pico_util)
pico_add_subdirectory(pico_stdlib)
endif()
pico_add_doxygen(${CMAKE_CURRENT_LIST_DIR})

3
src/common/README.md Normal file
View File

@ -0,0 +1,3 @@
This directory code that is common to all builds regardless of `PICO_PLATFORM`. It is a mix
of common header files, or high level functionality built entirely using `hardware_` or `pico_` libraries provided
by the actual target `PICO_PLATFORM``

View File

@ -0,0 +1,2 @@
add_library(boot_picoboot_headers INTERFACE)
target_include_directories(boot_picoboot_headers INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _BOOT_PICOBOOT_H
#define _BOOT_PICOBOOT_H
#include <stdint.h>
#include <stdbool.h>
#include <assert.h>
#ifndef NO_PICO_PLATFORM
#include "pico/platform.h"
#endif
/** \file picoboot.h
* \defgroup boot_picoboot boot_picoboot
*
* Header file for the PICOBOOT USB interface exposed by an RP2040 in BOOTSEL mode.
*/
#define PICOBOOT_MAGIC 0x431fd10bu
// --------------------------------------------
// CONTROL REQUESTS FOR THE PICOBOOT INTERFACE
// --------------------------------------------
// size 0 OUT - unstall EPs and reset
#define PICOBOOT_IF_RESET 0x41
// size 16 IN - return the status of the last command
#define PICOBOOT_IF_CMD_STATUS 0x42
// --------------------------------------------------
// COMMAND REQUESTS SENT TO THE PICOBOOT OUT ENDPOINT
// --------------------------------------------------
//
// picoboot_cmd structure of size 32 is sent to OUT endpoint
// transfer_length bytes are transferred via IN/OUT
// device responds on success with 0 length ACK packet set via OUT/IN
// device may stall the transferring endpoint in case of error
enum picoboot_cmd_id {
PC_EXCLUSIVE_ACCESS = 0x1,
PC_REBOOT = 0x2,
PC_FLASH_ERASE = 0x3,
PC_READ = 0x84, // either RAM or FLASH
PC_WRITE = 5, // either RAM or FLASH (does no erase)
PC_EXIT_XIP = 0x6,
PC_ENTER_CMD_XIP = 0x7,
PC_EXEC = 0x8,
PC_VECTORIZE_FLASH = 0x9
};
enum picoboot_status {
PICOBOOT_OK = 0,
PICOBOOT_UNKNOWN_CMD = 1,
PICOBOOT_INVALID_CMD_LENGTH = 2,
PICOBOOT_INVALID_TRANSFER_LENGTH = 3,
PICOBOOT_INVALID_ADDRESS = 4,
PICOBOOT_BAD_ALIGNMENT = 5,
PICOBOOT_INTERLEAVED_WRITE = 6,
PICOBOOT_REBOOTING = 7,
PICOBOOT_UNKNOWN_ERROR = 8,
};
struct __packed picoboot_reboot_cmd {
uint32_t dPC; // 0 means reset into bootrom
uint32_t dSP;
uint32_t dDelayMS;
};
// used for EXEC, VECTORIZE_FLASH
struct __packed picoboot_address_only_cmd {
uint32_t dAddr;
};
// used for READ, WRITE, FLASH_ERASE
struct __packed picoboot_range_cmd {
uint32_t dAddr;
uint32_t dSize;
};
enum picoboot_exclusive_type {
NOT_EXCLUSIVE = 0,
EXCLUSIVE,
EXCLUSIVE_AND_EJECT
};
struct __packed picoboot_exclusive_cmd {
uint8_t bExclusive;
};
// little endian
struct __packed __aligned(4) picoboot_cmd {
uint32_t dMagic;
uint32_t dToken; // an identifier for this token to correlate with a status response
uint8_t bCmdId; // top bit set for IN
uint8_t bCmdSize; // bytes of actual data in the arg part of this structure
uint16_t _unused;
uint32_t dTransferLength; // length of IN/OUT transfer (or 0) if none
union {
uint8_t args[16];
struct picoboot_reboot_cmd reboot_cmd;
struct picoboot_range_cmd range_cmd;
struct picoboot_address_only_cmd address_only_cmd;
struct picoboot_exclusive_cmd exclusive_cmd;
};
};
static_assert(32 == sizeof(struct picoboot_cmd), "picoboot_cmd must be 32 bytes big");
struct __packed __aligned(4) picoboot_cmd_status {
uint32_t dToken;
uint32_t dStatusCode;
uint8_t bCmdId;
uint8_t bInProgress;
uint8_t _pad[6];
};
static_assert(16 == sizeof(struct picoboot_cmd_status), "picoboot_cmd_status must be 16 bytes big");
#endif

View File

@ -0,0 +1,2 @@
add_library(boot_uf2_headers INTERFACE)
target_include_directories(boot_uf2_headers INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _BOOT_UF2_H
#define _BOOT_UF2_H
#include <stdint.h>
#include <assert.h>
/** \file uf2.h
* \defgroup boot_uf2 boot_uf2
*
* Header file for the UF2 format supported by an RP2040 in BOOTSEL mode.
*/
#define UF2_MAGIC_START0 0x0A324655u
#define UF2_MAGIC_START1 0x9E5D5157u
#define UF2_MAGIC_END 0x0AB16F30u
#define UF2_FLAG_NOT_MAIN_FLASH 0x00000001u
#define UF2_FLAG_FILE_CONTAINER 0x00001000u
#define UF2_FLAG_FAMILY_ID_PRESENT 0x00002000u
#define UF2_FLAG_MD5_PRESENT 0x00004000u
#define RP2040_FAMILY_ID 0xe48bff56
struct uf2_block {
// 32 byte header
uint32_t magic_start0;
uint32_t magic_start1;
uint32_t flags;
uint32_t target_addr;
uint32_t payload_size;
uint32_t block_no;
uint32_t num_blocks;
uint32_t file_size; // or familyID;
uint8_t data[476];
uint32_t magic_end;
};
static_assert(sizeof(struct uf2_block) == 512, "uf2_block not sector sized");
#endif

View File

@ -0,0 +1,40 @@
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)
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
target_compile_definitions(pico_base_headers INTERFACE
PICO_BOARD="${PICO_BOARD}")
target_link_libraries(pico_base_headers INTERFACE pico_platform_headers)
endif()

View File

@ -0,0 +1,23 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PICO_H_
#define PICO_H_
/** \file pico.h
* \defgroup pico_base pico_base
*
* Core types and macros for the Pico SDK. This header is intended to be included by all source code
*/
#include "pico/types.h"
#include "pico/version.h"
#include "pico/config.h"
#include "pico/platform.h"
#include "pico/assert.h"
#include "pico/error.h"
#endif

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_ASSERT_H
#define _PICO_ASSERT_H
#include "pico/types.h"
#ifdef __cplusplus
#include <cassert>
extern "C" {
#else
#include <assert.h>
#endif
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLE_ALL, Global assert enable, type=bool, default=0, group=pico_base
// PICO_CONFIG: PARAM_ASSERTIONS_DISABLE_ALL, Global assert disable, type=bool, default=0, group=pico_base
#ifndef PARAM_ASSERTIONS_ENABLE_ALL
#define PARAM_ASSERTIONS_ENABLE_ALL 0
#endif
#ifndef PARAM_ASSERTIONS_DISABLE_ALL
#define PARAM_ASSERTIONS_DISABLE_ALL 0
#endif
#define PARAM_ASSERTIONS_ENABLED(x) ((PARAM_ASSERTIONS_ENABLED_ ## x || PARAM_ASSERTIONS_ENABLE_ALL) && !PARAM_ASSERTIONS_DISABLE_ALL)
#define invalid_params_if(x, test) ({if (PARAM_ASSERTIONS_ENABLED(x)) assert(!(test));})
#define valid_params_if(x, test) ({if (PARAM_ASSERTIONS_ENABLED(x)) assert(test);})
#define hard_assert_if(x, test) ({if (PARAM_ASSERTIONS_ENABLED(x)) hard_assert(!(test));})
#ifdef NDEBUG
extern void hard_assertion_failure();
static inline void hard_assert(bool condition, ...) {
if (!condition)
hard_assertion_failure();
}
#else
#define hard_assert assert
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,21 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef PICO_CONFIG_H_
#define PICO_CONFIG_H_
// -----------------------------------------------------
// NOTE: THIS HEADER IS ALSO INCLUDED BY ASSEMBLER SO
// SHOULD ONLY CONSIST OF PREPROCESSOR DIRECTIVES
// OR USE #ifndef __ASSEMBLER__ guards
// -------------
// PICO_CONFIG_HEADER_FILES and then PICO_SDK_<PLATFORM>_CONFIG_INCLUDE_FILES
// entries are dumped in order at build time into this generated header
#include "pico/config_autogen.h"
#endif

View File

@ -0,0 +1,21 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_ERROR_H
#define _PICO_ERROR_H
/*!
* Common return codes from pico_sdk methods that return a status
*/
enum {
PICO_OK = 0,
PICO_ERROR_NONE = 0,
PICO_ERROR_TIMEOUT = -1,
PICO_ERROR_GENERIC = -2,
PICO_ERROR_NO_DATA = -3,
};
#endif

View File

@ -0,0 +1,79 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_TYPES_H
#define _PICO_TYPES_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
typedef unsigned int uint;
#ifdef NDEBUG
/*! \typedef absolute_time_t
\brief An opaque 64 bit timestamp in microseconds
The type is used instead of a raw uint64_t to prevent accidentally passing relative times or times in the wrong
time units where an absolute time is required. It is equivalent to uint64_t in release builds.
\see to_us_since_boot
\see update_us_since_boot
*/
typedef uint64_t absolute_time_t;
/*! fn to_us_since_boot
* \brief convert an absolute_time_t into a number of microseconds since boot.
* \param t the number of microseconds since boot
* \return an absolute_time_t value equivalent to t
*/
static inline uint64_t to_us_since_boot(absolute_time_t t) {
return t;
}
/*! fn update_us_since_boot
* \brief update an absolute_time_t value to represent a given number of microseconds since boot
* \param t the absolute time value to update
* \param us_since_boot the number of microseconds since boot to represent
*/
static inline void update_us_since_boot(absolute_time_t *t, uint64_t us_since_boot) {
*t = us_since_boot;
}
#define ABSOLUTE_TIME_INITIALIZED_VAR(name, value) name = value
#else
typedef struct {
uint64_t _private_us_since_boot;
} absolute_time_t;
static inline uint64_t to_us_since_boot(absolute_time_t t) {
return t._private_us_since_boot;
}
static inline void update_us_since_boot(absolute_time_t *t, uint64_t us_since_boot) {
t->_private_us_since_boot = us_since_boot;
}
#define ABSOLUTE_TIME_INITIALIZED_VAR(name, value) name = {value}
#endif
/** \struct datetime_t
* \ingroup util_datetime
* \brief Structure containing date and time information
*
* When setting an RTC alarm, set a field to -1 tells
* the RTC to not match on this field
*/
typedef struct {
int16_t year; ///< 0..4095
int8_t month; ///< 1..12, 1 is January
int8_t day; ///< 1..28,29,30,31 depending on month
int8_t dotw; ///< 0..6, 0 is Sunday
int8_t hour; ///< 0..23
int8_t min; ///< 0..59
int8_t sec; ///< 0..59
} datetime_t;
#endif

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
// ---------------------------------------
// THIS FILE IS AUTOGENERATED; DO NOT EDIT
// ---------------------------------------
#ifndef _PICO_VERSION_H
#define _PICO_VERSION_H
#define PICO_SDK_VERSION_MAJOR ${PICO_SDK_VERSION_MAJOR}
#define PICO_SDK_VERSION_MINOR ${PICO_SDK_VERSION_MINOR}
#define PICO_SDK_VERSION_REVISION ${PICO_SDK_VERSION_REVISION}
#define PICO_SDK_VERSION_STRING "${PICO_SDK_VERSION_STRING}"
#endif

View File

@ -0,0 +1,30 @@
add_library(pico_binary_info_headers INTERFACE)
target_include_directories(pico_binary_info_headers INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
add_library(pico_binary_info INTERFACE)
target_link_libraries(pico_binary_info INTERFACE pico_binary_info_headers)
function(pico_set_program_name TARGET name)
# PICO_BUILD_DEFINE: PICO_PROGRAM_NAME, value passed to pico_set_program_name, type=string, default=none, group=pico_binary_info
target_compile_definitions(${TARGET} PRIVATE -DPICO_PROGRAM_NAME="${name}")
endfunction()
function(pico_set_program_description TARGET description)
# since this is the command line, we will remove newlines
string(REPLACE "\n" " " description ${description})
string(REPLACE "\"" "\\\"" description ${description})
# PICO_BUILD_DEFINE: PICO_PROGRAM_DESCRIPTION, value passed to pico_set_program_description, type=string, default=none, group=pico_binary_info
target_compile_definitions(${TARGET} PRIVATE -DPICO_PROGRAM_DESCRIPTION="${description}")
endfunction()
function(pico_set_program_url TARGET url)
# PICO_BUILD_DEFINE: PICO_PROGRAM_URL, value passed to pico_set_program_url, type=string, default=none, group=pico_binary_info
target_compile_definitions(${TARGET} PRIVATE -DPICO_PROGRAM_URL="${url}")
endfunction()
function(pico_set_program_version TARGET version)
# PICO_BUILD_DEFINE: PICO_PROGRAM_VERSION_STRING, value passed to pico_set_program_version, type=string, default=none, group=pico_binary_info
target_compile_definitions(${TARGET} PRIVATE -DPICO_PROGRAM_VERSION_STRING="${version}")
endfunction()

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_BINARY_INFO_H
#define _PICO_BINARY_INFO_H
/**
* Binary info is intended for embedding machine readable information with the binary in FLASH.
*
* Example uses include:
*
* - Program identification / information
* - Pin layouts
* - Included features
* - Identifying flash regions used as block devices/storage
*/
#include "pico/binary_info/defs.h"
#include "pico/binary_info/structure.h"
#if PICO_ON_DEVICE
#include "pico/binary_info/code.h"
#endif
#endif

View File

@ -0,0 +1,139 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_BINARY_INFO_CODE_H
#define _PICO_BINARY_INFO_CODE_H
#include "pico.h"
#include "pico/binary_info/structure.h"
#if !PICO_NO_BINARY_INFO
#define __bi_decl(name, bi, section_prefix, attr) static const attr __attribute__((section(section_prefix __STRING(name)))) struct _binary_info_core *name = bi
#define __bi_lineno_var_name __CONCAT(__bi_, __LINE__)
#define __bi_ptr_lineno_var_name __CONCAT(__bi_ptr, __LINE__)
#define __bi_enclosure_check_lineno_var_name __CONCAT(_error_bi_is_missing_enclosing_decl_,__LINE__)
#define __bi_mark_enclosure static const __unused int __bi_enclosure_check_lineno_var_name=0;
#if !defined(__GNUC__) || __cplusplus || __GNUC__ >= 8
#define __bi_enclosure_check(x) (x + __bi_enclosure_check_lineno_var_name)
#else
// skip the version check on older GCC non C++, as it doesn't compile.. this is only here to catch the
// user accidentally forgetting to enclose the binary item with bi_decl
#define __bi_enclosure_check(x) (x)
#endif
/**
* Declare some binary information that will be included if the contain source file/line is compiled into the binary
*/
#define bi_decl(_decl) __bi_mark_enclosure _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.keep.", __used);
/**
* Declare some binary information that will be included if the function containing the decl is linked into the binary.
* The SDK uses --gc-sections, so functions that are never called will be removed by the linker, and any associated
* binary information declared this way will also be stripped
*/
#define bi_decl_if_func_used(_decl) ({__bi_mark_enclosure _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.", ); *(volatile uint8_t *)&__bi_ptr_lineno_var_name;});
#define bi_decl_with_attr(_decl, _attr) __bi_mark_enclosure _attr _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.keep.", __used);
#define bi_decl_if_func_used_with_attr(_decl, _attr) ({__bi_mark_enclosure _attr _decl; __bi_decl(__bi_ptr_lineno_var_name, &__bi_lineno_var_name.core, ".binary_info.", ); *(volatile uint8_t *)&__bi_ptr_lineno_var_name;});
#else
#define __bi_decl(bi, name, attr)
#define bi_decl_with_attr(_decl, _attr)
#define bi_decl(_decl)
#define bi_decl_if_func_used_with_attr(_decl, _attr) ((void)0);
#define bi_decl_if_func_used(_decl) ((void)0);
#endif
#define bi_int(_tag, _id, _value) \
static const struct _binary_info_id_and_int __bi_lineno_var_name = { \
.core = { \
.type = __bi_enclosure_check(BINARY_INFO_TYPE_ID_AND_INT), \
.tag = _tag, \
},\
.id = _id, \
.value = _value \
};
#define bi_string(_tag, _id, _value) \
static const struct _binary_info_id_and_string __bi_lineno_var_name = { \
.core = { \
.type = __bi_enclosure_check(BINARY_INFO_TYPE_ID_AND_STRING), \
.tag = _tag, \
},\
.id = _id, \
.value = _value, \
}
#define bi_block_device(_tag, _name, _address, _size, _extra, _flags) \
static const struct _binary_info_block_device __bi_lineno_var_name = { \
.core = { \
.type = __bi_enclosure_check(BINARY_INFO_TYPE_BLOCK_DEVICE), \
.tag = _tag, \
},\
.name = _name, \
.address = _address, \
.size = _size, \
.extra = _extra, \
.flags = _flags, \
}
#define __bi_encoded_pins_with_func(_encoding) \
static const struct _binary_info_pins_with_func __bi_lineno_var_name = { \
.core = { \
.type = __bi_enclosure_check(BINARY_INFO_TYPE_PINS_WITH_FUNC), \
.tag = BINARY_INFO_TAG_RASPBERRY_PI, \
},\
.pin_encoding = _encoding \
}
#define __bi_pins_with_name(_mask, _label) \
static const struct _binary_info_pins_with_name __bi_lineno_var_name = { \
.core = { \
.type = __bi_enclosure_check(BINARY_INFO_TYPE_PINS_WITH_NAME), \
.tag = BINARY_INFO_TAG_RASPBERRY_PI, \
},\
.pin_mask = _mask, \
.label = _label \
}
#define __bi_named_group(_parent_tag, _parent_id, _group_tag, _group_id, _label, _flags) \
static const struct _binary_info_named_group __bi_lineno_var_name = { \
.core = { \
.type = __bi_enclosure_check(BINARY_INFO_TYPE_NAMED_GROUP), \
.tag = _parent_tag, \
},\
.parent_id = _parent_id, \
.group_tag = _group_tag, \
.flags = _flags, \
.group_id = _group_id, \
.label = _label \
}
#define bi_binary_end(end) bi_int(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_BINARY_END, end)
#define bi_program_name(name) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_NAME, name)
#define bi_program_description(description) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_DESCRIPTION, description)
#define bi_program_version_string(version_string) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_VERSION_STRING, version_string)
#define bi_program_build_date_string(date_string) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_BUILD_DATE_STRING, date_string)
#define bi_program_url(url) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_URL, url)
// multiple of these may be added
#define bi_program_feature(feature) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_FEATURE, feature)
#define bi_program_build_attribute(attr) bi_string(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_BUILD_ATTRIBUTE, attr)
#define bi_program_feature_group(tag, id, name) __bi_named_group(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_FEATURE, tag, id, name, 0)
#define bi_program_feature_group_with_flags(tag, id, name, flags) __bi_named_group(BINARY_INFO_TAG_RASPBERRY_PI, BINARY_INFO_ID_RP_PROGRAM_FEATURE, tag, id, name, flags)
#define bi_1pin_with_func(p0, func) __bi_encoded_pins_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 7) | ((p0) << 12))
#define bi_2pins_with_func(p0, p1, func) __bi_encoded_pins_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 7) | ((p1) << 12) | ((p1) << 17))
#define bi_3pins_with_func(p0, p1, p2, func) __bi_encoded_pins_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 7) | ((p1) << 12) | ((p2) << 17) | ((p2) << 22))
#define bi_4pins_with_func(p0, p1, p2, p3, func) __bi_encoded_pins_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 7) | ((p1) << 12) | ((p2) << 17) | ((p3) << 22) | ((p3) << 27))
#define bi_5pins_with_func(p0, p1, p2, p3, p4, func) __bi_encoded_pins_with_func(BI_PINS_ENCODING_MULTI | ((func << 3)) | ((p0) << 7) | ((p1) << 12) | ((p2) << 17) | ((p3) << 22) | ((p4) << 27))
#define bi_pin_range_with_func(plo, phi, func) __bi_encoded_pins_with_func(BI_PINS_ENCODING_RANGE | ((func << 3)) | ((plo) << 7) | ((phi) << 12))
#define bi_pin_mask_with_name(pmask, label) __bi_pins_with_name((pmask), (label))
// names are sperated by | ... i.e. "name1|name2|name3"
#define bi_pin_mask_with_names(pmask, label) __bi_pins_with_name((pmask), (label))
#define bi_1pin_with_name(p0, name) bi_pin_mask_with_name(1u << (p0), name)
#define bi_2pins_with_names(p0, name0, p1, name1) bi_pin_mask_with_names((1u << (p0)) | (1u << (p1)), name0 "|" name1)
#define bi_3pins_with_names(p0, name0, p1, name1, p2, name2) bi_pin_mask_with_names((1u << (p0)) | (1u << (p1)) | (1u << (p2)), name0 "|" name1 "|" name2)
#define bi_4pins_with_names(p0, name0, p1, name1, p2, name2, p3, name3) bi_pin_mask_with_names((1u << (p0)) | (1u << (p1)) | (1u << (p2)) | (1u << (p3)), name0 "|" name1 "|" name2 "|" name3)
#endif

View File

@ -0,0 +1,43 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_BINARY_INFO_DEFS_H
#define _PICO_BINARY_INFO_DEFS_H
// this file is for pre-processor definitions only
// should be found within the first 256 bytes of the real binary (i.e. after the flash second stage if a flash binary)
//
// Note the layout is:
//
// addr : BINARY_INFO_MARKER_START
// addr+0x04 : __binary_info_start
// addr+0x08 : __binary_info_end
// addr+0x0c : __address_mapping_table
// addr+0x10 | BINARY_INFO_MARKER_END
//
// __binary_info_start to __binary_info_end are the start, end (non inclusive) of an array
// of pointers to binary_info_t structures
//
// __address_mapping_table is an array of the following items:
//
// uint32_t source_addr_start
// uint32_t dest_addr_start
// uint32_t dest_addr_end
//
// representing a mapping from the stored address in the binary/flash to addresses at runtime.
// The linker will store pointers within the binary using their runtime values, however because of
// "AT" mapping in the link script these addresses actually correspond to a different address in the binary
// image. This mapping (which in the case of crt0.S is simply the data copy table used at initialization
// to copy data into it's runtime location) can be used by picotool or others to reverse the mapping to find data
// within the binary.
//
// Note the above array is terminated with a NULL source_addr_start
#define BINARY_INFO_MARKER_START 0x7188ebf2
#define BINARY_INFO_MARKER_END 0xe71aa390
#endif

View File

@ -0,0 +1,150 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_BINARY_INFO_STRUCTURE_H
#define _PICO_BINARY_INFO_STRUCTURE_H
// NOTE: This file may be included by non SDK code, so does not use SDK includes
// NOTE: ALL CHANGES MUST BE BACKWARDS COMPATIBLE
#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h>
#ifndef __packed
#define __packed __attribute__((packed))
#endif
typedef struct _binary_info_core binary_info_t;
#define BINARY_INFO_TYPE_RAW_DATA 1
#define BINARY_INFO_TYPE_SIZED_DATA 2
#define BINARY_INFO_TYPE_BINARY_INFO_LIST_ZERO_TERMINATED 3
#define BINARY_INFO_TYPE_BSON 4
#define BINARY_INFO_TYPE_ID_AND_INT 5
#define BINARY_INFO_TYPE_ID_AND_STRING 6
// traditional block device
#define BINARY_INFO_TYPE_BLOCK_DEVICE 7
#define BINARY_INFO_TYPE_PINS_WITH_FUNC 8
#define BINARY_INFO_TYPE_PINS_WITH_NAME 9
#define BINARY_INFO_TYPE_PINS_WITH_NAMES 9
#define BINARY_INFO_TYPE_NAMED_GROUP 10
// note plan is to reserve c1 = 0->31 for "collision tags"; i.e.
// for which you should always use random IDs with the binary_info,
// giving you 4 + 8 + 32 = 44 bits to avoid collisions
#define BINARY_INFO_MAKE_TAG(c1, c2) ((((uint)c2&0xffu)<<8u)|((uint)c1&0xffu))
// Raspberry Pi defined. do not use
#define BINARY_INFO_TAG_RASPBERRY_PI BINARY_INFO_MAKE_TAG('R','P')
#define BINARY_INFO_ID_RP_PROGRAM_NAME 0x02031c86
#define BINARY_INFO_ID_RP_PROGRAM_VERSION_STRING 0x11a9bc3a
#define BINARY_INFO_ID_RP_PROGRAM_BUILD_DATE_STRING 0x9da22254
#define BINARY_INFO_ID_RP_BINARY_END 0x68f465de
#define BINARY_INFO_ID_RP_PROGRAM_URL 0x1856239a
#define BINARY_INFO_ID_RP_PROGRAM_DESCRIPTION 0xb6a07c19
#define BINARY_INFO_ID_RP_PROGRAM_FEATURE 0xa1f4b453
#define BINARY_INFO_ID_RP_PROGRAM_BUILD_ATTRIBUTE 0x4275f0d3
#define BINARY_INFO_ID_RP_SDK_VERSION 0x5360b3ab
#define BINARY_INFO_ID_RP_PICO_BOARD 0xb63cffbb
#if PICO_ON_DEVICE
#define bi_ptr_of(x) x *
#else
#define bi_ptr_of(x) uint32_t
#endif
typedef struct __packed _binary_info_core {
uint16_t type;
uint16_t tag;
} binary_info_core_t;
typedef struct __packed _binary_info_raw_data {
struct _binary_info_core core;
uint8_t bytes[1];
} binary_info_raw_data_t;
typedef struct __packed _binary_info_sized_data {
struct _binary_info_core core;
uint32_t length;
uint8_t bytes[1];
} binary_info_sized_data_t;
typedef struct __packed _binary_info_list_zero_terminated {
struct _binary_info_core core;
bi_ptr_of(binary_info_t) list;
} binary_info_list_zero_terminated_t;
typedef struct __packed _binary_info_id_and_int {
struct _binary_info_core core;
uint32_t id;
int32_t value;
} binary_info_id_and_int_t;
typedef struct __packed _binary_info_id_and_string {
struct _binary_info_core core;
uint32_t id;
bi_ptr_of(const char) value;
} binary_info_id_and_string_t;
typedef struct __packed _binary_info_block_device {
struct _binary_info_core core;
bi_ptr_of(const char) name; // optional static name (independent of what is formatted)
uint32_t address;
uint32_t size;
bi_ptr_of(binary_info_t) extra; // additional info
uint16_t flags;
} binary_info_block_device_t;
#define BI_PINS_ENCODING_RANGE 1
#define BI_PINS_ENCODING_MULTI 2
typedef struct __packed _binary_info_pins_with_func {
struct _binary_info_core core;
// p4_5 : p3_5 : p2_5 : p1_5 : p0_5 : func_4 : 001_3 //individual pins p0,p1,p2,p3,p4 ... if fewer than 5 then duplicate p
// phi_5 : plo_5 : func_4 : 010_3 // pin range plo-phi inclusive
uint32_t pin_encoding;
} binary_info_pins_with_func_t;
typedef struct __packed _binary_info_pins_with_name {
struct _binary_info_core core;
uint32_t pin_mask;
bi_ptr_of(const char) label;
} binary_info_pins_with_name_t;
#define BI_NAMED_GROUP_SHOW_IF_EMPTY 0x0001 // default is to hide
#define BI_NAMED_GROUP_SEPARATE_COMMAS 0x0002 // default is newlines
#define BI_NAMED_GROUP_SORT_ALPHA 0x0004 // default is no sort
#define BI_NAMED_GROUP_ADVANCED 0x0008 // if set, then only shown in say info -a
typedef struct __packed _binary_info_named_group {
struct _binary_info_core core;
uint32_t parent_id;
uint16_t flags;
uint16_t group_tag;
uint32_t group_id;
bi_ptr_of(const char) label;
} binary_info_named_group_t;
enum {
BINARY_INFO_BLOCK_DEV_FLAG_READ =
1 << 0, // if not readable, then it is basically hidden, but tools may choose to avoid overwriting it
BINARY_INFO_BLOCK_DEV_FLAG_WRITE = 1 << 1,
BINARY_INFO_BLOCK_DEV_FLAG_REFORMAT = 1 << 2, // may be reformatted..
BINARY_INFO_BLOCK_DEV_FLAG_PT_UNKNOWN = 0 << 4, // unknown free to look
BINARY_INFO_BLOCK_DEV_FLAG_PT_MBR = 1 << 4, // expect MBR
BINARY_INFO_BLOCK_DEV_FLAG_PT_GPT = 2 << 4, // expect GPT
BINARY_INFO_BLOCK_DEV_FLAG_PT_NONE = 3 << 4, // no partition table
};
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,5 @@
if (NOT TARGET pico_bit_ops_headers)
add_library(pico_bit_ops_headers INTERFACE)
target_include_directories(pico_bit_ops_headers INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
target_link_libraries(pico_bit_ops_headers INTERFACE pico_base_headers)
endif()

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_BIT_OPS_H
#define _PICO_BIT_OPS_H
#include "pico.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \file bit_ops.h
* \defgroup pico_bit_ops pico_bit_ops
*
* Optimized bit manipulation functions.
* Additionally provides replacement implementations of the compiler built-ins __builtin_popcount, __builtin_clz
* and __bulitin_ctz
*/
/*! \brief Reverse the bits in a 32 bit word
* \ingroup pico_bit_ops
*
* \param bits 32 bit input
* \return the 32 input bits reversed
*/
uint32_t __rev(uint32_t bits);
/*! \brief Reverse the bits in a 64 bit double word
* \ingroup pico_bit_ops
*
* \param bits 64 bit input
* \return the 64 input bits reversed
*/
uint64_t __revll(uint64_t bits);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,5 @@
if (NOT TARGET pico_divider_headers)
add_library(pico_divider_headers INTERFACE)
target_include_directories(pico_divider_headers INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
target_link_libraries(pico_divider_headers INTERFACE pico_base_headers)
endif()

View File

@ -0,0 +1,322 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_DIVIDER_H_
#define _PICO_DIVIDER_H_
#include "pico.h"
#include "hardware/divider.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* \defgroup pico_divider pico_divider
* Optimized 32 and 64 bit division functions accelerated by the RP2040 hardware divider.
* Additionally provides integration with the C `/` and `%` operators
*/
/** \file pico/divider.h
* \brief High level APIs including combined quotient and remainder functions for 32 and 64 bit accelerated by the hardware divider
* \ingroup pico_divider
*
* These functions all call __aeabi_idiv0 or __aebi_ldiv0 on division by zero
* passing the largest applicably signed value
*
* Functions with unsafe in their name do not save/restore divider state, so are unsafe to call from interrupts. Unsafe functions are slightly faster.
*/
/**
* \brief Integer divide of two signed 32-bit values
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \return quotient
*/
int32_t div_s32s32(int32_t a, int32_t b);
/**
* \brief Integer divide of two signed 32-bit values, with remainder
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \param [out] rem The remainder of dividend/divisor
* \return Quotient result of dividend/divisor
*/
static inline int32_t divmod_s32s32_rem(int32_t a, int32_t b, int32_t *rem) {
divmod_result_t r = hw_divider_divmod_s32(a, b);
*rem = to_remainder_s32(r);
return to_quotient_s32(r);
}
/**
* \brief Integer divide of two signed 32-bit values
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \return quotient in low word/r0, remainder in high word/r1
*/
divmod_result_t divmod_s32s32(int32_t a, int32_t b);
/**
* \brief Integer divide of two unsigned 32-bit values
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \return Quotient
*/
uint32_t div_u32u32(uint32_t a, uint32_t b);
/**
* \brief Integer divide of two unsigned 32-bit values, with remainder
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \param [out] rem The remainder of dividend/divisor
* \return Quotient result of dividend/divisor
*/
static inline uint32_t divmod_u32u32_rem(uint32_t a, uint32_t b, uint32_t *rem) {
divmod_result_t r = hw_divider_divmod_u32(a, b);
*rem = to_remainder_u32(r);
return to_quotient_u32(r);
}
/**
* \brief Integer divide of two unsigned 32-bit values
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \return quotient in low word/r0, remainder in high word/r1
*/
divmod_result_t divmod_u32u32(uint32_t a, uint32_t b);
/**
* \brief Integer divide of two signed 64-bit values
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \return Quotient
*/
int64_t div_s64s64(int64_t a, int64_t b);
/**
* \brief Integer divide of two signed 64-bit values, with remainder
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \param [out] rem The remainder of dividend/divisor
* \return Quotient result of dividend/divisor
*/
int64_t divmod_s64s64_rem(int64_t a, int64_t b, int64_t *rem);
/**
* \brief Integer divide of two signed 64-bit values
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \return quotient in result (r0,r1), remainder in regs (r2, r3)
*/
int64_t divmod_s64s64(int64_t a, int64_t b);
/**
* \brief Integer divide of two unsigned 64-bit values
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \return Quotient
*/
uint64_t div_u64u64(uint64_t a, uint64_t b);
/**
* \brief Integer divide of two unsigned 64-bit values, with remainder
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \param [out] rem The remainder of dividend/divisor
* \return Quotient result of dividend/divisor
*/
uint64_t divmod_u64u64_rem(uint64_t a, uint64_t b, uint64_t *rem);
/**
* \brief Integer divide of two signed 64-bit values
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \return quotient in result (r0,r1), remainder in regs (r2, r3)
*/
uint64_t divmod_u64u64(uint64_t a, uint64_t b);
// -----------------------------------------------------------------------
// these "unsafe" functions are slightly faster, but do not save the divider state,
// so are not generally safe to be called from interrupts
// -----------------------------------------------------------------------
/**
* \brief Unsafe integer divide of two signed 32-bit values
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \return quotient
*
* Do not use in interrupts
*/
int32_t div_s32s32_unsafe(int32_t a, int32_t b);
/**
* \brief Unsafe integer divide of two signed 32-bit values, with remainder
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \param [out] rem The remainder of dividend/divisor
* \return Quotient result of dividend/divisor
*
* Do not use in interrupts
*/
int32_t divmod_s32s32_rem_unsafe(int32_t a, int32_t b, int32_t *rem);
/**
* \brief Unsafe integer divide of two unsigned 32-bit values
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \return quotient in low word/r0, remainder in high word/r1
*
* Do not use in interrupts
*/
int64_t divmod_s32s32_unsafe(int32_t a, int32_t b);
/**
* \brief Unsafe integer divide of two unsigned 32-bit values
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \return Quotient
*
* Do not use in interrupts
*/
uint32_t div_u32u32_unsafe(uint32_t a, uint32_t b);
/**
* \brief Unsafe integer divide of two unsigned 32-bit values, with remainder
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \param [out] rem The remainder of dividend/divisor
* \return Quotient result of dividend/divisor
*
* Do not use in interrupts
*/
uint32_t divmod_u32u32_rem_unsafe(uint32_t a, uint32_t b, uint32_t *rem);
/**
* \brief Unsafe integer divide of two unsigned 32-bit values
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \return quotient in low word/r0, remainder in high word/r1
*
* Do not use in interrupts
*/
uint64_t divmod_u32u32_unsafe(uint32_t a, uint32_t b);
/**
* \brief Unsafe integer divide of two signed 64-bit values
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \return Quotient
*
* Do not use in interrupts
*/
int64_t div_s64s64_unsafe(int64_t a, int64_t b);
/**
* \brief Unsafe integer divide of two signed 64-bit values, with remainder
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \param [out] rem The remainder of dividend/divisor
* \return Quotient result of dividend/divisor
*
* Do not use in interrupts
*/
int64_t divmod_s64s64_rem_unsafe(int64_t a, int64_t b, int64_t *rem);
/**
* \brief Unsafe integer divide of two signed 64-bit values
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \return quotient in result (r0,r1), remainder in regs (r2, r3)
*
* Do not use in interrupts
*/
int64_t divmod_s64s64_unsafe(int64_t a, int64_t b);
/**
* \brief Unsafe integer divide of two unsigned 64-bit values
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \return Quotient
*
* Do not use in interrupts
*/
uint64_t div_u64u64_unsafe(uint64_t a, uint64_t b);
/**
* \brief Unsafe integer divide of two unsigned 64-bit values, with remainder
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \param [out] rem The remainder of dividend/divisor
* \return Quotient result of dividend/divisor
*
* Do not use in interrupts
*/
uint64_t divmod_u64u64_rem_unsafe(uint64_t a, uint64_t b, uint64_t *rem);
/**
* \brief Unsafe integer divide of two signed 64-bit values
* \ingroup pico_divider
*
* \param a Dividend
* \param b Divisor
* \return quotient in result (r0,r1), remainder in regs (r2, r3)
*
* Do not use in interrupts
*/
uint64_t divmod_u64u64_unsafe(uint64_t a, uint64_t b);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,11 @@
if (NOT TARGET pico_stdlib_headers)
add_library(pico_stdlib_headers INTERFACE)
target_include_directories(pico_stdlib_headers INTERFACE include)
target_link_libraries(pico_stdlib_headers INTERFACE
hardware_gpio
hardware_uart
hardware_divider
pico_time
pico_util
)
endif()

View File

@ -0,0 +1,130 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_STDLIB_H
#define _PICO_STDLIB_H
#include "pico.h"
#include "pico/stdio.h"
#include "pico/time.h"
#include "hardware/gpio.h"
#include "hardware/uart.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \file stdlib.h
* \defgroup pico_stdlib pico_stdlib
*
* Aggregation of a core subset of Pico SDK libraries used by most executables along with some additional
* utility methods. Including pico_stdlib gives you everything you need to get a basic program running
* which prints to stdout or flashes a LED
*
* This library aggregates:
* - @ref hardware_uart
* - @ref hardware_gpio
* - @ref pico_binary_info
* - @ref pico_runtime
* - @ref pico_platform
* - @ref pico_printf
* - @ref pico_stdio
* - @ref pico_standard_link
* - @ref pico_util
*
* There are some basic default values used by these functions that will default to
* usable values, however, they can be customised in a board definition header via
* config.h or similar
*/
// Note PICO_STDIO_UART, PICO_STDIO_USB, PICO_STDIO_SEMIHOSTING are set by the
// respective INTERFACE libraries, so these defines are set if the library
// is included for the target executable
#if PICO_STDIO_UART
#include "pico/stdio_uart.h"
#endif
#if PICO_STDIO_USB
#include "pico/stdio_usb.h"
#endif
#if PICO_STDIO_SEMIHOSTING
#include "pico/stdio_semihosting.h"
#endif
/*! \brief Set up the default UART and assign it to the default GPIO's
* \ingroup pico_stdlib
*
* By default this will use UART 0, with TX to pin GPIO 0,
* RX to pin GPIO 1, and the baudrate to 115200
*
* Calling this method also initializes stdin/stdout over UART if the
* @ref pico_stdio_uart library is linked.
*
* Defaults can be changed using configuration defines,
* PICO_DEFAULT_UART_INSTANCE,
* PICO_DEFAULT_UART_BAUD_RATE
* PICO_DEFAULT_UART_TX_PIN
* PICO_DEFAULT_UART_RX_PIN
*/
void setup_default_uart();
/*! \brief Initialise the system clock to 48MHz
* \ingroup pico_stdlib
*
* Set the system clock to 48MHz, and set the peripheral clock to match.
*/
void set_sys_clock_48mhz();
/*! \brief Initialise the system clock
* \ingroup pico_stdlib
*
* \param vco_freq The voltage controller oscillator frequency to be used by the SYS PLL
* \param post_div1 The first post divider for the SYS PLL
* \param post_div2 The second post divider for the SYS PLL.
*
* See the PLL documentation in the datasheet for details of driving the PLLs.
*/
void set_sys_clock_pll(uint32_t vco_freq, uint post_div1, uint post_div2);
/*! \brief Check if a given system clock frequency is valid/attainable
* \ingroup pico_stdlib
*
* \param freq_khz Requested frequency
* \param vco_freq_out On success, the voltage controller oscillator frequeucny to be used by the SYS PLL
* \param post_div1_out On success, The first post divider for the SYS PLL
* \param post_div2_out On success, The second post divider for the SYS PLL.
* @return true if the frequency is possible and the output parameters have been written.
*/
bool check_sys_clock_khz(uint32_t freq_khz, uint *vco_freq_out, uint *post_div1_out, uint *post_div2_out);
/*! \brief Attempt to set a system clock frequency in khz
* \ingroup pico_stdlib
*
* Note that not all clock frequencies are possible; it is preferred that you
* use src/rp2_common/hardware_clocks/scripts/vcocalc.py to calculate the parameters
* for use with set_sys_clock_pll
*
* \param freq_khz Requested frequency
* \param required if true then this function will assert if the frequency is not attainable.
* \return true if the clock was configured
*/
static inline bool set_sys_clock_khz(uint32_t freq_khz, bool required) {
uint vco, postdiv1, postdiv2;
if (check_sys_clock_khz(freq_khz, &vco, &postdiv1, &postdiv2)) {
set_sys_clock_pll(vco, postdiv1, postdiv2);
return true;
} else if (required) {
panic("System clock of %u kHz cannot be exactly achieved", freq_khz);
}
return false;
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,44 @@
if (NOT TARGET pico_sync_headers)
add_library(pico_sync_headers INTERFACE)
target_include_directories(pico_sync_headers INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
target_link_libraries(pico_sync_headers INTERFACE hardware_sync pico_time)
endif()
if (NOT TARGET pico_sync_core)
add_library(pico_sync_core INTERFACE)
target_sources(pico_sync_core INTERFACE
${CMAKE_CURRENT_LIST_DIR}/lock_core.c
)
target_link_libraries(pico_sync_core INTERFACE pico_sync_headers)
endif()
if (NOT TARGET pico_sync_sem)
add_library(pico_sync_sem INTERFACE)
target_sources(pico_sync_sem INTERFACE
${CMAKE_CURRENT_LIST_DIR}/sem.c
)
target_link_libraries(pico_sync_sem INTERFACE pico_sync_core pico_time)
endif()
if (NOT TARGET pico_sync_mutex)
add_library(pico_sync_mutex INTERFACE)
target_sources(pico_sync_mutex INTERFACE
${CMAKE_CURRENT_LIST_DIR}/mutex.c
)
target_link_libraries(pico_sync_mutex INTERFACE pico_sync_core pico_time)
endif()
if (NOT TARGET pico_sync_critical_section)
add_library(pico_sync_critical_section INTERFACE)
target_sources(pico_sync_critical_section INTERFACE
${CMAKE_CURRENT_LIST_DIR}/critical_section.c
)
target_link_libraries(pico_sync_critical_section INTERFACE pico_sync_core pico_time)
endif()
if (NOT TARGET pico_sync)
add_library(pico_sync INTERFACE)
target_link_libraries(pico_sync INTERFACE pico_sync_sem pico_sync_mutex pico_sync_critical_section pico_sync_core)
endif()

View File

@ -0,0 +1,24 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "pico/critical_section.h"
#if !PICO_NO_HARDWARE
static_assert(sizeof(critical_section_t) == 8, "");
#endif
void critical_section_init(critical_section_t *critsec) {
critical_section_init_with_lock_num(critsec, spin_lock_claim_unused(true));
}
void critical_section_init_with_lock_num(critical_section_t *critsec, uint lock_num) {
lock_init(&critsec->core, lock_num);
__mem_fence_release();
}
void critical_section_deinit(critical_section_t *critsec) {
spin_lock_unclaim(spin_lock_get_num(critsec->core.spin_lock));
}

View File

@ -0,0 +1,75 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PLATFORM_CRITICAL_SECTION_H
#define _PLATFORM_CRITICAL_SECTION_H
#include "pico/lock_core.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \file critical_section.h
* \defgroup critical_section critical_section
* \ingroup pico_sync
* \brief Critical Section API for short-lived mutual exclusion safe for IRQ and multi-core
*
* A critical section is non-reentrant, and provides mutual exclusion using a spin-lock to prevent access
* 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.
*
* Because interrupts are disabled by this function, uses of the critical_section should be as short as possible.
*/
typedef struct __packed_aligned critical_section {
lock_core_t core;
uint32_t save;
} critical_section_t;
/*! \brief Initialise a critical_section structure allowing the system to assign a spin lock number
* \ingroup critical_section
*
* The critical section is initialized ready for use, and will use a (possibly shared) spin lock
* number assigned by the system. Note that in general it is unlikely that you would be nesting
* 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.
*
* \param critsec Pointer to critical_section structure
*/
void critical_section_init(critical_section_t *critsec);
/*! \brief Initialise a critical_section structure assigning a specific spin lock number
* \ingroup critical_section
* \param critsec Pointer to critical_section structure
* \param lock_num the specific spin lock number to use
*/
void critical_section_init_with_lock_num(critical_section_t *critsec, uint lock_num);
/*! \brief Enter a critical_section
* \ingroup critical_section
*
* If the spin lock associated with this critical section is in use, then this
* method will block until it is released.
*
* \param critsec Pointer to critical_section structure
*/
static inline void critical_section_enter_blocking(critical_section_t *critsec) {
critsec->save = spin_lock_blocking(critsec->core.spin_lock);
}
/*! \brief Release a critical_section
* \ingroup critical_section
*
* \param critsec Pointer to critical_section structure
*/
static inline void critical_section_exit(critical_section_t *critsec) {
spin_unlock(critsec->core.spin_lock, critsec->save);
}
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,28 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_LOCK_CORE_H
#define _PICO_LOCK_CORE_H
#include "pico.h"
#include "hardware/sync.h"
/** \file lock_core.h
* \ingroup pico_sync
*
* Base implementation for locking primitives protected by a spin lock
*/
typedef struct lock_core {
// spin lock protecting this lock's state
spin_lock_t *spin_lock;
// note any lock members in containing structures need not be volatile;
// they are protected by memory/compiler barriers when gaining and release spin locks
} lock_core_t;
void lock_init(lock_core_t *core, uint lock_num);
#endif

View File

@ -0,0 +1,136 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PLATFORM_MUTEX_H
#define _PLATFORM_MUTEX_H
#include "pico/lock_core.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \file mutex.h
* \defgroup mutex mutex
* \ingroup pico_sync
* \brief Mutex API for non IRQ mutual exclusion between cores
*
* Mutexes are application level locks usually used protecting data structures that might be used by
* multiple cores. Unlike critical sections, the mutex protected code is not necessarily
* required/expected to complete quickly, as no other sytemwide locks are held on account of a locked mutex.
*
* Because they are not re-entrant on the same core, blocking on a mutex should never be done in an IRQ
* handler. It is valid to call \ref mutex_try_enter from within an IRQ handler, if the operation
* that would be conducted under lock can be skipped if the mutex is locked (at least by the same core).
*
* See \ref critical_section.h for protecting access between multiple cores AND IRQ handlers
*/
typedef struct __packed_aligned mutex {
lock_core_t core;
bool owned;
int8_t owner;
} mutex_t;
/*! \brief Initialise a mutex structure
* \ingroup mutex
*
* \param mtx Pointer to mutex structure
*/
void mutex_init(mutex_t *mtx);
/*! \brief Take ownership of a mutex
* \ingroup mutex
*
* This function will block until the calling core can claim ownership of the mutex.
* On return the caller core owns the mutex
*
* \param mtx Pointer to mutex structure
*/
void mutex_enter_blocking(mutex_t *mtx);
/*! \brief Check to see if a mutex is available
* \ingroup mutex
*
* Will return true if the mutex is unowned, false otherwise
*
* \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
*/
bool mutex_try_enter(mutex_t *mtx, uint32_t *owner_out);
/*! \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_ms The timeout in milliseconds.
* \return true if mutex now owned, false if timeout occurred before mutex became available
*/
bool mutex_enter_timeout_ms(mutex_t *mtx, uint32_t timeout_ms);
/*! \brief Wait for mutex until a specific time
* \ingroup mutex
*
* Wait until 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 until The time after which to return if the core cannot take owner ship of the mutex
* \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);
/*! \brief Release ownership of a mutex
* \ingroup mutex
*
* \param mtx Pointer to mutex structure
*/
void mutex_exit(mutex_t *mtx);
/*! \brief Test for mutex initialised state
* \ingroup mutex
*
* \param mtx Pointer to mutex structure
* \return true if the mutex is initialised, false otherwise
*/
static inline bool mutex_is_initialzed(mutex_t *mtx) {
return mtx->core.spin_lock != 0;
}
/*! \brief Helper macro for static definition of mutexes
* \ingroup mutex
*
* A mutex defined as follows:
*
* ```c
* auto_init_mutex(my_mutex);
* ```
*
* Is equivalent to doing
*
* ```c
* static mutex_t my_mutex;
*
* void my_init_function() {
* mutex_init(&my_mutex);
* }
* ```
*
* But the initialization of the mutex is performed automatically during runtime initialization
*/
#define auto_init_mutex(name) static __attribute__((section(".mutex_array"))) mutex_t name
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PLATFORM_SEM_H
#define _PLATFORM_SEM_H
#include "pico/lock_core.h"
/** \file sem.h
* \defgroup sem sem
* \ingroup pico_sync
* \brief Semaphore API for restricting access to a resource
*
* A semaphore holds a number of available permits. `sem_acquire` methods will acquire a permit if available
* (reducing the available count by 1) or block if the number of available permits is 0.
* \ref sem_release() increases the number of available permits by one potentially unblocking a `sem_acquire` method.
*
* Note that \ref sem_release() may be called an arbitrary number of times, however the number of available
* permits is capped to the max_permit value specified during semaphore initialization.
*
* Although these semaphore related functions can be used from IRQ handlers, it is obviously preferable to only
* release semaphores from within an IRQ handler (i.e. avoid blocking)
*/
#ifdef __cplusplus
extern "C" {
#endif
typedef struct __packed_aligned semaphore {
struct lock_core core;
int16_t permits;
int16_t max_permits;
} semaphore_t;
/*! \brief Initialise a semaphore structure
* \ingroup sem
*
* \param sem Pointer to semaphore structure
* \param initial_permits How many permits are initially acquired
* \param max_permits Total number of permits allowed for this semaphore
*/
void sem_init(semaphore_t *sem, int16_t initial_permits, int16_t max_permits);
/*! \brief Return number of available permits on the semaphore
* \ingroup sem
*
* \param sem Pointer to semaphore structure
* \return The number of permits available on the semaphore.
*/
int sem_available(semaphore_t *sem);
/*! \brief Release a permit on a semaphore
* \ingroup sem
*
* Increases the number of permits by one (unless the number of permits is already at the maximum).
* A blocked `sem_acquire` will be released if the number of permits is increased.
*
* \param sem Pointer to semaphore structure
* \return true if the number of permits available was increased.
*/
bool sem_release(semaphore_t *sem);
/*! \brief Reset semaphore to a specific number of available permits
* \ingroup sem
*
* Reset value should be from 0 to the max_permits specified in the init function
*
* \param sem Pointer to semaphore structure
* \param permits the new number of available permits
*/
void sem_reset(semaphore_t *sem, int16_t permits);
/*! \brief Acquire a permit from the semaphore
* \ingroup sem
*
* This function will block and wait if no permits are available.
*
* \param sem Pointer to semaphore structure
*/
void sem_acquire_blocking(semaphore_t *sem);
/*! \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_ms Time to wait to acquire the semaphore, in ms.
* \return false if timeout reached, true if permit was acquired.
*/
bool sem_acquire_timeout_ms(semaphore_t *sem, uint32_t timeout_ms);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,19 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_SYNC_H
#define _PICO_SYNC_H
/** \file pico/sync.h
* \defgroup pico_sync pico_sync
* Synchronization primitives and mutual exclusion
*/
#include "pico/sem.h"
#include "pico/mutex.h"
#include "pico/critical_section.h"
#endif

View File

@ -0,0 +1,13 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "pico/lock_core.h"
void lock_init(lock_core_t *core, uint lock_num) {
assert(lock_num >= 0 && lock_num < NUM_SPIN_LOCKS);
core->spin_lock = spin_lock_instance(lock_num);
}

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "pico/mutex.h"
#include "pico/time.h"
#if !PICO_NO_HARDWARE
static_assert(sizeof(mutex_t) == 8, "");
#endif
void mutex_init(mutex_t *mtx) {
lock_init(&mtx->core, next_striped_spin_lock_num());
__mem_fence_release();
}
void __time_critical_func(mutex_enter_blocking)(mutex_t *mtx) {
assert(mtx->core.spin_lock);
bool block = true;
do {
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
if (!mtx->owned) {
mtx->owned = true;
mtx->owner = get_core_num();
block = false;
}
spin_unlock(mtx->core.spin_lock, save);
if (block) {
__wfe();
}
} while (block);
}
bool __time_critical_func(mutex_try_enter)(mutex_t *mtx, uint32_t *owner_out) {
bool entered;
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
if (!mtx->owned) {
mtx->owned = true;
mtx->owner = get_core_num();
entered = true;
} else {
if (owner_out) *owner_out = mtx->owner;
entered = false;
}
spin_unlock(mtx->core.spin_lock, save);
return entered;
}
bool __time_critical_func(mutex_enter_timeout_ms)(mutex_t *mtx, uint32_t timeout_ms) {
return mutex_enter_block_until(mtx, make_timeout_time_ms(timeout_ms));
}
bool __time_critical_func(mutex_enter_block_until)(mutex_t *mtx, absolute_time_t until) {
assert(mtx->core.spin_lock);
bool block = true;
do {
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
if (!mtx->owned) {
mtx->owned = true;
mtx->owner = get_core_num();
block = false;
}
spin_unlock(mtx->core.spin_lock, save);
if (block) {
if (best_effort_wfe_or_timeout(until)) {
return false;
}
}
} while (block);
return true;
}
void __time_critical_func(mutex_exit)(mutex_t *mtx) {
uint32_t save = spin_lock_blocking(mtx->core.spin_lock);
assert(mtx->owned);
mtx->owned = 0;
#ifndef NDEBUG
mtx->owner = -1;
#endif
__sev();
spin_unlock(mtx->core.spin_lock, save);
}

View File

@ -0,0 +1,82 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "pico/sem.h"
#include "pico/time.h"
void sem_init(semaphore_t *sem, int16_t initial_permits, int16_t max_permits) {
lock_init(&sem->core, next_striped_spin_lock_num());
sem->permits = initial_permits;
sem->max_permits = max_permits;
__mem_fence_release();
}
int __time_critical_func(sem_available)(semaphore_t *sem) {
return *(volatile typeof(sem->permits) *) &sem->permits;
}
void __time_critical_func(sem_acquire_blocking)(semaphore_t *sem) {
bool block = true;
do {
uint32_t save = spin_lock_blocking(sem->core.spin_lock);
if (sem->permits > 0) {
sem->permits--;
__sev();
block = false;
}
spin_unlock(sem->core.spin_lock, save);
if (block) {
__wfe();
}
} while (block);
}
bool __time_critical_func(sem_acquire_timeout_ms)(semaphore_t *sem, uint32_t timeout_ms) {
bool block = true;
absolute_time_t target = nil_time;
do {
uint32_t save = spin_lock_blocking(sem->core.spin_lock);
if (sem->permits > 0) {
sem->permits--;
__sev();
block = false;
}
spin_unlock(sem->core.spin_lock, save);
if (block) {
if (is_nil_time(target)) {
target = make_timeout_time_ms(timeout_ms);
}
if (best_effort_wfe_or_timeout(target)) {
return false;
}
}
} while (block);
return true;
}
// todo this should really have a blocking variant for when permits are maxed out
bool __time_critical_func(sem_release)(semaphore_t *sem) {
bool rc;
uint32_t save = spin_lock_blocking(sem->core.spin_lock);
int32_t count = sem->permits;
if (count < sem->max_permits) {
sem->permits = count + 1;
__sev();
rc = true;
} else {
rc = false;
}
spin_unlock(sem->core.spin_lock, save);
return rc;
}
void __time_critical_func(sem_reset)(semaphore_t *sem, int16_t permits) {
assert(permits >= 0 && permits <= sem->max_permits);
uint32_t save = spin_lock_blocking(sem->core.spin_lock);
if (permits > sem->permits) __sev();
sem->permits = permits;
spin_unlock(sem->core.spin_lock, save);
}

View File

@ -0,0 +1,16 @@
if (NOT TARGET pico_time_headers)
add_library(pico_time_headers INTERFACE)
target_include_directories(pico_time_headers INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
target_link_libraries(pico_time_headers INTERFACE hardware_timer)
endif()
if (NOT TARGET pico_time)
add_library(pico_time INTERFACE)
target_sources(pico_time INTERFACE
${CMAKE_CURRENT_LIST_DIR}/time.c
${CMAKE_CURRENT_LIST_DIR}/timeout_helper.c)
target_link_libraries(pico_time INTERFACE pico_time_headers pico_sync pico_util)
endif()

View File

@ -0,0 +1,692 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_TIME_H
#define _PICO_TIME_H
#include "pico.h"
#include "hardware/timer.h"
#ifdef __cplusplus
extern "C" {
#endif
/** \file time.h
* \defgroup pico_time pico_time
*
* API for accurate timestamps, sleeping, and time based callbacks
*
* \note The functions defined here provide a much more powerful and user friendly wrapping around the
* low level hardware timer functionality. For these functions (and any other Pico SDK functionality
* e.g. timeouts, that relies on them) to work correctly, the hardware timer should not be modified. i.e. it is expected
* to be monotonically increasing once per microsecond. Fortunately there is no need to modify the hardware
* timer as any functionality you can think of that isn't already covered here can easily be modelled
* by adding or subtracting a constant value from the unmodified hardware timer.
*
* \sa \ref hardware_timer
*/
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_TIME, Enable/disable assertions in the time module, type=bool, default=0, group=pico_time
#ifndef PARAM_ASSERTIONS_ENABLED_TIME
#define PARAM_ASSERTIONS_ENABLED_TIME 0
#endif
// PICO_CONFIG: PICO_TIME_SLEEP_OVERHEAD_ADJUST_US, How many microseconds to wake up early (and then busy_wait) to account for timer overhead when sleeping in low power mode, type=int, default=6, group=pico_time
#ifndef PICO_TIME_SLEEP_OVERHEAD_ADJUST_US
#define PICO_TIME_SLEEP_OVERHEAD_ADJUST_US 6
#endif
/*!
* \defgroup timestamp timestamp
* \ingroup pico_time
* \brief Timestamp functions relating to points in time (including the current time)
*
* These are functions for dealing with timestamps (i.e. instants in time) represented by the type absolute_time_t. This opaque
* type is provided to help prevent accidental mixing of timestamps and relative time values.
*/
/*! \brief Return a representation of the current time.
* \ingroup timestamp
*
* Returns an opaque high fidelity representation of the current time sampled during the call.
*
* \return the absolute time (now) of the hardware timer
*
* \sa absolute_time_t
* \sa sleep_until()
* \sa time_us_64()
*/
static inline absolute_time_t get_absolute_time() {
absolute_time_t t;
update_us_since_boot(&t, time_us_64());
return t;
}
static inline uint32_t us_to_ms(uint64_t us) {
if (us >> 32u) {
return (uint32_t)(us / 1000u);
} else {
return ((uint32_t)us) / 1000u;
}
}
/*! fn to_ms_since_boot
* \ingroup timestamp
* \brief Convert a timestamp into a number of milliseconds since boot.
* \param t an absolute_time_t value to convert
* \return the number of microseconds since boot represented by t
* \sa to_us_since_boot
*/
static inline uint32_t to_ms_since_boot(absolute_time_t t) {
uint64_t us = to_us_since_boot(t);
return us_to_ms(us);
}
/*! \brief Return a timestamp value obtained by adding a number of microseconds to another timestamp
* \ingroup timestamp
*
* \param t the base timestamp
* \param us the number of microseconds to add
* \return the timestamp representing the resulting time
*/
static inline absolute_time_t delayed_by_us(const absolute_time_t t, uint64_t us) {
absolute_time_t t2;
uint64_t base = to_us_since_boot(t);
uint64_t delayed = base + us;
if (delayed < base) {
delayed = (uint64_t)-1;
}
update_us_since_boot(&t2, delayed);
return t2;
}
/*! \brief Return a timestamp value obtained by adding a number of milliseconds to another timestamp
* \ingroup timestamp
*
* \param t the base timestamp
* \param ms the number of milliseconds to add
* \return the timestamp representing the resulting time
*/
static inline absolute_time_t delayed_by_ms(const absolute_time_t t, uint32_t ms) {
absolute_time_t t2;
uint64_t base = to_us_since_boot(t);
uint64_t delayed = base + ms * 1000ull;
if (delayed < base) {
delayed = (uint64_t)-1;
}
update_us_since_boot(&t2, delayed);
return t2;
}
/*! \brief Convenience method to get the timestamp a number of microseconds from the current time
* \ingroup timestamp
*
* \param us the number of microseconds to add to the current timestamp
* \return the future timestamp
*/
static inline absolute_time_t make_timeout_time_us(uint64_t us) {
return delayed_by_us(get_absolute_time(), us);
}
/*! \brief Convenience method to get the timestamp a number of milliseconds from the current time
* \ingroup timestamp
*
* \param ms the number of milliseconds to add to the current timestamp
* \return the future timestamp
*/
static inline absolute_time_t make_timeout_time_ms(uint32_t ms) {
return delayed_by_ms(get_absolute_time(), ms);
}
/*! \brief Return the difference in microseconds between two timestamps
* \ingroup timestamp
*
* \param from the first timestamp
* \param to the second timestamp
* \return the number of microseconds between the two timestamps (positive if `to` is after `from`)
*/
static inline int64_t absolute_time_diff_us(absolute_time_t from, absolute_time_t to) {
return to_us_since_boot(to) - to_us_since_boot(from);
}
/*! \brief The timestamp representing the end of time; no timestamp is after this
* \ingroup timestamp
*/
extern const absolute_time_t at_the_end_of_time;
/*! \brief The timestamp representing a null timestamp
* \ingroup timestamp
*/
extern const absolute_time_t nil_time;
/*! \brief Determine if the given timestamp is nil
* \ingroup timestamp
* \param t the timestamp
* \return true if the timestamp is nil
* \sa nil_time()
*/
static inline bool is_nil_time(absolute_time_t t) {
return !to_us_since_boot(t);
}
/*!
* \defgroup sleep sleep
* \ingroup pico_time
* \brief Sleep functions for delaying execution in a lower power state.
*
* These functions allow the calling core to sleep. This is a lower powered sleep; waking and re-checking time on every processor
* event (WFE)
*
* \note These functions should not be called from an IRQ handler.
*
* \note Lower powered sleep requires use of the \link alarm_pool_get_default default alarm pool\endlink which may
* be disabled by the #PICO_TIME_DEFAULT_ALARM_POOL_DISABLED define or currently full in which case these functions
* become busy waits instead.
*
* \note Whilst \a sleep_ functions are preferable to \a busy_wait functions from a power perspective, the \a busy_wait equivalent function
* may return slightly sooner after the target is reached.
*
* \sa busy_wait_until() \sa busy_wait_us() \sa busy_wait_us_32()
*/
/*! \brief Wait until after the given timestamp to return
* \ingroup sleep
*
* \note This method attempts to perform a lower power (WFE) sleep
*
* \param target the time after which to return
* \sa sleep_us()
* \sa busy_wait_until()
* */
void sleep_until(absolute_time_t target);
/*! \brief Wait for the given number of microseconds before returning
* \ingroup sleep
*
* \note This method attempts to perform a lower power (WFE) sleep
*
* \param us the number of microseconds to sleep
* \sa busy_wait_us()
*/
void sleep_us(uint64_t us);
/*! \brief Wait for the given number of milliseconds before returning
* \ingroup sleep
*
* \note This method attempts to perform a lower power sleep (using WFE) as much as possible.
*
* \param ms the number of milliseconds to sleep
*/
void sleep_ms(uint32_t ms);
/*! \brief Helper method for blocking on a timeout
* \ingroup sleep
*
* This method will return in response to a an event (as per __wfe) or
* when the target time is reached, or at any point before.
*
* This method can be used to implement a lower power polling loop waiting on
* some condition signalled by an event (__sev()).
*
* This is called \a best_effort because under certain circumstances (notably the default timer pool
* being disabled or full) the best effort is simply to return immediately without a __wfe, thus turning the calling
* code into a busy wait.
*
* Example usage:
* ```c
* bool my_function_with_timeout_us(uint64_t timeout_us) {
* absolute_time_t timeout_time = make_timeout_time_us(timeout_us);
* do {
* // each time round the loop, we check to see if the condition
* // we are waiting on has happened
* if (my_check_done()) {
* // do something
* return true;
* }
* // will try to sleep until timeout or the next processor event
* } while (!best_effort_wfe_or_timeout(timeout_time));
* return false; // timed out
* }
* ```
*
* @param timeout_timestamp the timeout time
* @return true if the target time is reached, false otherwise
*/
bool best_effort_wfe_or_timeout(absolute_time_t timeout_timestamp);
/*!
* \defgroup alarm alarm
* \ingroup pico_time
* \brief Alarm functions for scheduling future execution
*
* Alarms are added to alarm pools, which may hold a certain fixed number of active alarms. Each alarm pool
* utilizes one of four underlying hardware alarms, thus you may have up to four alarm pools. An alarm pool
* calls (except when the callback would happen before or during being set) the callback on the core from which
* the alarm pool was created. Callbacks are called from the hardware alarm IRQ handler, so care must
* be taken in their implementation.
*
* A default pool is created the core specified by PICO_TIME_DEFAULT_ALARM_POOL_HARDWARE_ALARM_NUM
* on core 0, and may be used by the method variants that take no alarm pool parameter.
*
* \sa struct alarm_pool
* \sa hardware_timer
*/
// PICO_CONFIG: PICO_TIME_DEFAULT_ALARM_POOL_DISABLED, Disable the default alarm pool, type=bool, default=0, advanced=true, group=pico_time
#ifndef PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
/*!
* \brief If 1 then the default alarm pool is disabled (so no hardware alarm is claimed for the pool)
*
* \note Setting to 1 may cause some code not to compile as default timer pool related methods are removed
*
* \note When the default alarm pool is disabled, \a sleep_ methods and timeouts are no longer lower powered
* (they become \a busy_wait_)
*
* \ingroup alarm
* \sa #PICO_TIME_DEFAULT_ALARM_POOL_HARDWARE_ALARM_NUM
* \sa alarm_pool_get_default()
*/
#define PICO_TIME_DEFAULT_ALARM_POOL_DISABLED 0
#endif
// PICO_CONFIG: PICO_TIME_DEFAULT_ALARM_POOL_HARDWARE_ALARM_NUM, Select which HW alarm is used for the default alarm pool, min=0, max=3, default=3, advanced=true, group=pico_time
#ifndef PICO_TIME_DEFAULT_ALARM_POOL_HARDWARE_ALARM_NUM
/*!
* \brief Selects which hardware alarm is used for the default alarm pool
* \ingroup alarm
* \sa alarm_pool_get_default()
*/
#define PICO_TIME_DEFAULT_ALARM_POOL_HARDWARE_ALARM_NUM 3
#endif
// PICO_CONFIG: PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS, Selects the maximum number of concurrent timers in the default alarm pool, min=0, max=255, default=16, advanced=true, group=pico_time
#ifndef PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS
/*!
* \brief Selects the maximum number of concurrent timers in the default alarm pool
* \ingroup alarm
*
* \note For implementation reasons this is limited to PICO_PHEAP_MAX_ENTRIES which defaults to 255
* \sa #PICO_TIME_DEFAULT_ALARM_POOL_HARDWARE_ALARM_NUM
* \sa alarm_pool_get_default()
*/
#define PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS 16
#endif
/**
* \brief The identifier for an alarm
*
* \note this identifier is signed because -1 is used as an error condition when creating alarms
*
* \note alarm ids may be reused, however for convenience the implementation makes an attempt to defer
* reusing as long as possible. You should certainly expect it to be hundreds of ids before one is
* reused, although in most cases it is more. Nonetheless care must still be taken when cancelling
* alarms or other functionality based on alarms when the alarm may have expired, as eventually
* the alarm id may be reused for another alarm.
*
* \ingroup alarm
*/
typedef int32_t alarm_id_t; // note this is signed because we use -1 as a meaningful error value
/**
* \brief User alarm callback
* \ingroup alarm
* \param id the alarm_id as returned when the alarm was added
* \param user_data the user data passed when the alarm was added
* \return <0 to reschedule the same alarm this many us from the time the alarm was previously scheduled to fire
* \return >0 to reschedule the same alarm this many us from the time this method returns
* \return 0 to not reschedule the alarm
*/
typedef int64_t (*alarm_callback_t)(alarm_id_t id, void *user_data);
typedef struct alarm_pool alarm_pool_t;
/**
* \brief Create the default alarm pool (if not already created or disabled)
* \ingroup alarm
*/
void alarm_pool_init_default();
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
/*!
* \brief The default alarm pool used when alarms are added without specifying an alarm pool,
* and also used by the Pico SDK to support lower power sleeps and timeouts.
*
* \ingroup alarm
* \sa #PICO_TIME_DEFAULT_ALARM_POOL_HARDWARE_ALARM_NUM
*/
alarm_pool_t *alarm_pool_get_default();
#endif
/**
* \brief Create an alarm pool
*
* The alarm pool will call callbacks from an alarm IRQ Handler on the core of this function is called from.
*
* In many situations there is never any need for anything other than the default alarm pool, however you
* might want to create another if you want alarm callbacks on core 1 or require alarm pools of
* different priority (IRQ priority based preemption of callbacks)
*
* \note This method will hard assert if the hardware alarm is already claimed.
*
* \ingroup alarm
* \param hardware_alarm_num the hardware alarm to use to back this pool
* \param max_timers the maximum number of timers
* \note For implementation reasons this is limited to PICO_PHEAP_MAX_ENTRIES which defaults to 255
* \sa alarm_pool_get_default()
* \sa hardware_claiming
*/
alarm_pool_t *alarm_pool_create(uint hardware_alarm_num, uint max_timers);
/**
* \brief Return the hardware alarm used by an alarm pool
* \ingroup alarm
* \param pool the pool
* \return the hardware alarm used by the pool
*/
uint alarm_pool_hardware_alarm_num(alarm_pool_t *pool);
/**
* \brief Destroy the alarm pool, cancelling all alarms and freeing up the underlying hardware alarm
* \ingroup alarm
* \param pool the pool
* \return the hardware alarm used by the pool
*/
void alarm_pool_destroy(alarm_pool_t *pool);
/*!
* \brief Add an alarm callback to be called at a specific time
* \ingroup alarm
*
* Generally the callback is called as soon as possible after the time specified from an IRQ handler
* on the core the alarm pool was created on. If the callback is in the past or happens before
* the alarm setup could be completed, then this method will optionally call the callback itself
* and then return a return code to indicate that the target time has passed.
*
* \note It is safe to call this method from an IRQ handler (including alarm callbacks), and from either core.
*
* @param pool the alarm pool to use for scheduling the callback (this determines which hardware alarm is used, and which core calls the callback)
* @param time the timestamp when (after which) the callback should fire
* @param callback the callback function
* @param user_data user data to pass to the callback function
* @param fire_if_past if true, this method will call the callback itself before returning 0 if the timestamp happens before or during this method call
* @return >0 the alarm id
* @return 0 the target timestamp was during or before this method call (whether the callback was called depends on fire_if_past)
* @return -1 if there were no alarm slots available
*/
alarm_id_t alarm_pool_add_alarm_at(alarm_pool_t *pool, absolute_time_t time, alarm_callback_t callback, void *user_data, bool fire_if_past);
/*!
* \brief Add an alarm callback to be called after a delay specified in microseconds
* \ingroup alarm
*
* Generally the callback is called as soon as possible after the time specified from an IRQ handler
* on the core the alarm pool was created on. If the callback is in the past or happens before
* the alarm setup could be completed, then this method will optionally call the callback itself
* and then return a return code to indicate that the target time has passed.
*
* \note It is safe to call this method from an IRQ handler (including alarm callbacks), and from either core.
*
* @param pool the alarm pool to use for scheduling the callback (this determines which hardware alarm is used, and which core calls the callback)
* @param us the delay (from now) in microseconds when (after which) the callback should fire
* @param callback the callback function
* @param user_data user data to pass to the callback function
* @param fire_if_past if true, this method will call the callback itself before returning 0 if the timestamp happens before or during this method call
* @return >0 the alarm id
* @return 0 the target timestamp was during or before this method call (whether the callback was called depends on fire_if_past)
* @return -1 if there were no alarm slots available
*/
static inline alarm_id_t alarm_pool_add_alarm_in_us(alarm_pool_t *pool, uint64_t us, alarm_callback_t callback, void *user_data, bool fire_if_past) {
return alarm_pool_add_alarm_at(pool, delayed_by_us(get_absolute_time(), us), callback, user_data, fire_if_past);
}
/*!
* \brief Add an alarm callback to be called after a delay specified in milliseconds
* \ingroup alarm
*
* Generally the callback is called as soon as possible after the time specified from an IRQ handler
* on the core the alarm pool was created on. If the callback is in the past or happens before
* the alarm setup could be completed, then this method will optionally call the callback itself
* and then return a return code to indicate that the target time has passed.
*
* \note It is safe to call this method from an IRQ handler (including alarm callbacks), and from either core.
*
* @param pool the alarm pool to use for scheduling the callback (this determines which hardware alarm is used, and which core calls the callback)
* @param ms the delay (from now) in milliseconds when (after which) the callback should fire
* @param callback the callback function
* @param user_data user data to pass to the callback function
* @param fire_if_past if true, this method will call the callback itself before returning 0 if the timestamp happens before or during this method call
* @return >0 the alarm id
* @return 0 the target timestamp was during or before this method call (whether the callback was called depends on fire_if_past)
* @return -1 if there were no alarm slots available
*/
static inline alarm_id_t alarm_pool_add_alarm_in_ms(alarm_pool_t *pool, uint32_t ms, alarm_callback_t callback, void *user_data, bool fire_if_past) {
return alarm_pool_add_alarm_at(pool, delayed_by_ms(get_absolute_time(), ms), callback, user_data, fire_if_past);
}
/*!
* \brief Cancel an alarm
* \ingroup alarm
* \param pool the alarm_pool containing the alarm
* \param alarm_id the alarm
* \return true if the alarm was cancelled, false if it didn't exist
* \sa alarm_id_t for a note on reuse of IDs
*/
bool alarm_pool_cancel_alarm(alarm_pool_t *pool, alarm_id_t alarm_id);
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
/*!
* \brief Add an alarm callback to be called at a specific time
* \ingroup alarm
*
* Generally the callback is called as soon as possible after the time specified from an IRQ handler
* on the core of the default alarm pool (generally core 0). If the callback is in the past or happens before
* the alarm setup could be completed, then this method will optionally call the callback itself
* and then return a return code to indicate that the target time has passed.
*
* \note It is safe to call this method from an IRQ handler (including alarm callbacks), and from either core.
*
* @param time the timestamp when (after which) the callback should fire
* @param callback the callback function
* @param user_data user data to pass to the callback function
* @param fire_if_past if true, this method will call the callback itself before returning 0 if the timestamp happens before or during this method call
* @return >0 the alarm id
* @return 0 the target timestamp was during or before this method call (whether the callback was called depends on fire_if_past)
* @return -1 if there were no alarm slots available
*/
static inline alarm_id_t add_alarm_at(absolute_time_t time, alarm_callback_t callback, void *user_data, bool fire_if_past) {
return alarm_pool_add_alarm_at(alarm_pool_get_default(), time, callback, user_data, fire_if_past);
}
/*!
* \brief Add an alarm callback to be called after a delay specified in microseconds
* \ingroup alarm
*
* Generally the callback is called as soon as possible after the time specified from an IRQ handler
* on the core of the default alarm pool (generally core 0). If the callback is in the past or happens before
* the alarm setup could be completed, then this method will optionally call the callback itself
* and then return a return code to indicate that the target time has passed.
*
* \note It is safe to call this method from an IRQ handler (including alarm callbacks), and from either core.
*
* @param us the delay (from now) in microseconds when (after which) the callback should fire
* @param callback the callback function
* @param user_data user data to pass to the callback function
* @param fire_if_past if true, this method will call the callback itself before returning 0 if the timestamp happens before or during this method call
* @return >0 the alarm id
* @return 0 the target timestamp was during or before this method call (whether the callback was called depends on fire_if_past)
* @return -1 if there were no alarm slots available
*/
static inline alarm_id_t add_alarm_in_us(uint64_t us, alarm_callback_t callback, void *user_data, bool fire_if_past) {
return alarm_pool_add_alarm_in_us(alarm_pool_get_default(), us, callback, user_data, fire_if_past);
}
/*!
* \brief Add an alarm callback to be called after a delay specified in milliseconds
* \ingroup alarm
*
* Generally the callback is called as soon as possible after the time specified from an IRQ handler
* on the core of the default alarm pool (generally core 0). If the callback is in the past or happens before
* the alarm setup could be completed, then this method will optionally call the callback itself
* and then return a return code to indicate that the target time has passed.
*
* \note It is safe to call this method from an IRQ handler (including alarm callbacks), and from either core.
*
* @param ms the delay (from now) in milliseconds when (after which) the callback should fire
* @param callback the callback function
* @param user_data user data to pass to the callback function
* @param fire_if_past if true, this method will call the callback itself before returning 0 if the timestamp happens before or during this method call
* @return >0 the alarm id
* @return 0 the target timestamp was during or before this method call (whether the callback was called depends on fire_if_past)
* @return -1 if there were no alarm slots available
*/
static inline alarm_id_t add_alarm_in_ms(uint32_t ms, alarm_callback_t callback, void *user_data, bool fire_if_past) {
return alarm_pool_add_alarm_in_ms(alarm_pool_get_default(), ms, callback, user_data, fire_if_past);
}
/*!
* \brief Cancel an alarm from the default alarm pool
* \ingroup alarm
* \param alarm_id the alarm
* \return true if the alarm was cancelled, false if it didn't exist
* \sa alarm_id_t for a note on reuse of IDs
*/
static inline bool cancel_alarm(alarm_id_t alarm_id) {
return alarm_pool_cancel_alarm(alarm_pool_get_default(), alarm_id);
}
#endif
/*!
* \defgroup repeating_timer repeating_timer
* \ingroup pico_time
* \brief Repeating Timer functions for simple scheduling of repeated execution
*
* \note The regular \a alarm_ functionality can be used to make repeating alarms (by return non zero from the callback),
* however these methods abstract that further (at the cost of a user structure to store the repeat delay in (which
* the alarm framework does not have space for).
*/
typedef struct repeating_timer repeating_timer_t;
/**
* \brief Callback for a repeating timer
* \ingroup repeating_timer
* \param rt repeating time structure containing information about the repeating time. user_data is of primary important to the user
* \return true to continue repeating, false to stop.
*/
typedef bool (*repeating_timer_callback_t)(repeating_timer_t *rt);
/**
* \brief Information about a repeating timer
* \ingroup repeating_timer
* \return
*/
struct repeating_timer {
int64_t delay_us;
alarm_pool_t *pool;
alarm_id_t alarm_id;
repeating_timer_callback_t callback;
void *user_data;
};
/*!
* \brief Add a repeating timer that is called repeatedly at the specified interval in microseconds
* \ingroup repeating_timer
*
* Generally the callback is called as soon as possible after the time specified from an IRQ handler
* on the core the alarm pool was created on. If the callback is in the past or happens before
* the alarm setup could be completed, then this method will optionally call the callback itself
* and then return a return code to indicate that the target time has passed.
*
* \note It is safe to call this method from an IRQ handler (including alarm callbacks), and from either core.
*
* @param pool the alarm pool to use for scheduling the repeating timer (this determines which hardware alarm is used, and which core calls the callback)
* @param delay_us the repeat delay in microseconds; if >0 then this is the delay between one callback ending and the next starting; if <0 then this is the negative of the time between the starts of the callbacks. The value of 0 is treated as 1
* @param callback the repeating timer callback function
* @param user_data user data to pass to store in the repeating_timer structure for use by the callback.
* @param out the pointer to the user owned structure to store the repeating timer info in. BEWARE this storage location must outlive the repeating timer, so be careful of using stack space
* @return false if there were no alarm slots available to create the timer, true otherwise.
*/
bool alarm_pool_add_repeating_timer_us(alarm_pool_t *pool, int64_t delay_us, repeating_timer_callback_t callback, void *user_data, repeating_timer_t *out);
/*!
* \brief Add a repeating timer that is called repeatedly at the specified interval in milliseconds
* \ingroup repeating_timer
*
* Generally the callback is called as soon as possible after the time specified from an IRQ handler
* on the core the alarm pool was created on. If the callback is in the past or happens before
* the alarm setup could be completed, then this method will optionally call the callback itself
* and then return a return code to indicate that the target time has passed.
*
* \note It is safe to call this method from an IRQ handler (including alarm callbacks), and from either core.
*
* @param pool the alarm pool to use for scheduling the repeating timer (this determines which hardware alarm is used, and which core calls the callback)
* @param delay_ms the repeat delay in milliseconds; if >0 then this is the delay between one callback ending and the next starting; if <0 then this is the negative of the time between the starts of the callbacks. The value of 0 is treated as 1 microsecond
* @param callback the repeating timer callback function
* @param user_data user data to pass to store in the repeating_timer structure for use by the callback.
* @param out the pointer to the user owned structure to store the repeating timer info in. BEWARE this storage location must outlive the repeating timer, so be careful of using stack space
* @return false if there were no alarm slots available to create the timer, true otherwise.
*/
static inline bool alarm_pool_add_repeating_timer_ms(alarm_pool_t *pool, int32_t delay_ms, repeating_timer_callback_t callback, void *user_data, repeating_timer_t *out) {
return alarm_pool_add_repeating_timer_us(pool, delay_ms * (int64_t)1000, callback, user_data, out);
}
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
/*!
* \brief Add a repeating timer that is called repeatedly at the specified interval in microseconds
* \ingroup repeating_timer
*
* Generally the callback is called as soon as possible after the time specified from an IRQ handler
* on the core of the default alarm pool (generally core 0). If the callback is in the past or happens before
* the alarm setup could be completed, then this method will optionally call the callback itself
* and then return a return code to indicate that the target time has passed.
*
* \note It is safe to call this method from an IRQ handler (including alarm callbacks), and from either core.
*
* @param delay_us the repeat delay in microseconds; if >0 then this is the delay between one callback ending and the next starting; if <0 then this is the negative of the time between the starts of the callbacks. The value of 0 is treated as 1
* @param callback the repeating timer callback function
* @param user_data user data to pass to store in the repeating_timer structure for use by the callback.
* @param out the pointer to the user owned structure to store the repeating timer info in. BEWARE this storage location must outlive the repeating timer, so be careful of using stack space
* @return false if there were no alarm slots available to create the timer, true otherwise.
*/
static inline bool add_repeating_timer_us(int64_t delay_us, repeating_timer_callback_t callback, void *user_data, repeating_timer_t *out) {
return alarm_pool_add_repeating_timer_us(alarm_pool_get_default(), delay_us, callback, user_data, out);
}
/*!
* \brief Add a repeating timer that is called repeatedly at the specified interval in milliseconds
* \ingroup repeating_timer
*
* Generally the callback is called as soon as possible after the time specified from an IRQ handler
* on the core of the default alarm pool (generally core 0). If the callback is in the past or happens before
* the alarm setup could be completed, then this method will optionally call the callback itself
* and then return a return code to indicate that the target time has passed.
*
* \note It is safe to call this method from an IRQ handler (including alarm callbacks), and from either core.
*
* @param delay_ms the repeat delay in milliseconds; if >0 then this is the delay between one callback ending and the next starting; if <0 then this is the negative of the time between the starts of the callbacks. The value of 0 is treated as 1 microsecond
* @param callback the repeating timer callback function
* @param user_data user data to pass to store in the repeating_timer structure for use by the callback.
* @param out the pointer to the user owned structure to store the repeating timer info in. BEWARE this storage location must outlive the repeating timer, so be careful of using stack space
* @return false if there were no alarm slots available to create the timer, true otherwise.
*/
static inline bool add_repeating_timer_ms(int32_t delay_ms, repeating_timer_callback_t callback, void *user_data, repeating_timer_t *out) {
return alarm_pool_add_repeating_timer_us(alarm_pool_get_default(), delay_ms * (int64_t)1000, callback, user_data, out);
}
#endif
/**
* \brief Cancel a repeating timer
* \ingroup repeating_timer
* \param timer the repeating timer to cancel
* \return true if the repeating timer was cancelled, false if it didn't exist
* \sa alarm_id_t for a note on reuse of IDs
*/
bool cancel_repeating_timer(repeating_timer_t *timer);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_TIMEOUT_HELPER_H
#define _PICO_TIMEOUT_HELPER_H
#include "pico/time.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct timeout_state {
absolute_time_t next_timeout;
uint64_t param;
} timeout_state_t;
typedef bool (*check_timeout_fn)(timeout_state_t *ts);
check_timeout_fn init_single_timeout_until(timeout_state_t *ts, absolute_time_t target);
check_timeout_fn init_per_iteration_timeout_us(timeout_state_t *ts, uint64_t per_iteration_timeout_us);
#ifdef __cplusplus
}
#endif
#endif

361
src/common/pico_time/time.c Normal file
View File

@ -0,0 +1,361 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include "pico.h"
#include "pico/time.h"
#include "pico/util/pheap.h"
#include "hardware/sync.h"
#include "hardware/gpio.h"
CU_REGISTER_DEBUG_PINS(core)
CU_SELECT_DEBUG_PINS(core)
const absolute_time_t ABSOLUTE_TIME_INITIALIZED_VAR(nil_time, 0);
// use LONG_MAX not ULONG_MAX so we don't have sign overflow in time diffs
const absolute_time_t ABSOLUTE_TIME_INITIALIZED_VAR(at_the_end_of_time, ULONG_MAX);
typedef struct alarm_pool_entry {
absolute_time_t target;
alarm_callback_t callback;
void *user_data;
} alarm_pool_entry_t;
typedef struct alarm_pool {
pheap_t *heap;
spin_lock_t *lock;
alarm_pool_entry_t *entries;
// one byte per entry, used to provide more longevity to public IDs than heap node ids do
// (this is increment every time the heap node id is re-used)
uint8_t *entry_ids_high;
alarm_id_t alarm_in_progress; // this is set during a callback from the IRQ handler... it can be cleared by alarm_cancel to prevent repeats
uint8_t hardware_alarm_num;
} alarm_pool_t;
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
static alarm_pool_t *default_alarm_pool;
#endif
static alarm_pool_t *pools[NUM_TIMERS];
void alarm_pool_init_default() {
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
// allow multiple calls for ease of use from host tests
if (!default_alarm_pool) {
default_alarm_pool = alarm_pool_create(PICO_TIME_DEFAULT_ALARM_POOL_HARDWARE_ALARM_NUM,
PICO_TIME_DEFAULT_ALARM_POOL_MAX_TIMERS);
}
#endif
}
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
alarm_pool_t *alarm_pool_get_default() {
assert(default_alarm_pool);
return default_alarm_pool;
}
#endif
static inline alarm_pool_entry_t *get_entry(alarm_pool_t *pool, pheap_node_id_t id) {
assert(id && id <= pool->heap->max_nodes);
return pool->entries + id - 1;
}
static inline uint8_t *get_entry_id_high(alarm_pool_t *pool, pheap_node_id_t id) {
assert(id && id <= pool->heap->max_nodes);
return pool->entry_ids_high + id - 1;
}
bool timer_pool_entry_comparator(void *user_data, pheap_node_id_t a, pheap_node_id_t b) {
alarm_pool_t *pool = (alarm_pool_t *)user_data;
return to_us_since_boot(get_entry(pool, a)->target) < to_us_since_boot(get_entry(pool, b)->target);
}
static inline alarm_id_t make_public_id(uint8_t id_high, pheap_node_id_t id) {
return ((uint)id_high << 8u * sizeof(id)) | id;
}
static alarm_id_t add_alarm_under_lock(alarm_pool_t *pool, absolute_time_t time, alarm_callback_t callback,
void *user_data, alarm_id_t reuse_id, bool create_if_past, bool *missed) {
alarm_id_t id;
if (reuse_id) {
assert(!ph_contains(pool->heap, reuse_id));
id = reuse_id;
} else {
id = ph_new_node(pool->heap);
}
if (id) {
alarm_pool_entry_t *entry = get_entry(pool, id);
entry->target = time;
entry->callback = callback;
entry->user_data = user_data;
DEBUG_PINS_SET(core, 1);
if (id == ph_insert(pool->heap, id)) {
bool is_missed = hardware_alarm_set_target(pool->hardware_alarm_num, time);
if (is_missed && !create_if_past) {
ph_delete(pool->heap, id);
}
if (missed) *missed = is_missed;
}
}
return id;
}
static void alarm_pool_alarm_callback(uint alarm_num) {
// note this is called from timer IRQ handler
alarm_pool_t *pool = pools[alarm_num];
bool again;
do {
absolute_time_t now = get_absolute_time();
alarm_callback_t callback = NULL;
absolute_time_t target = nil_time;
void *user_data = NULL;
uint8_t id_high;
again = false;
uint32_t save = spin_lock_blocking(pool->lock);
pheap_node_id_t next_id = ph_peek_head(pool->heap);
if (next_id) {
alarm_pool_entry_t *entry = get_entry(pool, next_id);
if (absolute_time_diff_us(now, entry->target) <= 0) {
// we reserve the id in case we need to re-add the timer
pheap_node_id_t __unused removed_id = ph_remove_head_reserve(pool->heap, true);
assert(removed_id == next_id); // will be true under lock
target = entry->target;
callback = entry->callback;
user_data = entry->user_data;
assert(callback);
id_high = *get_entry_id_high(pool, next_id);
pool->alarm_in_progress = make_public_id(id_high, removed_id);
} else {
if (hardware_alarm_set_target(alarm_num, entry->target)) {
again = true;
}
}
}
spin_unlock(pool->lock, save);
if (callback) {
DEBUG_PINS_SET(core, 4);
DEBUG_PINS_CLR(core, 1);
DEBUG_PINS_CLR(core, 4);
int64_t repeat = callback(make_public_id(id_high, next_id), user_data);
save = spin_lock_blocking(pool->lock);
// todo think more about whether we want to keep calling
if (repeat < 0 && pool->alarm_in_progress) {
assert(pool->alarm_in_progress == make_public_id(id_high, next_id));
add_alarm_under_lock(pool, delayed_by_us(target, -repeat), callback, user_data, next_id, true, NULL);
} else if (repeat > 0 && pool->alarm_in_progress) {
assert(pool->alarm_in_progress == make_public_id(id_high, next_id));
add_alarm_under_lock(pool, delayed_by_us(get_absolute_time(), repeat), callback, user_data, next_id,
true, NULL);
} else {
// need to return the id to the heap
ph_add_to_free_list(pool->heap, next_id);
(*get_entry_id_high(pool, next_id))++; // we bump it for next use of id
}
pool->alarm_in_progress = 0;
spin_unlock(pool->lock, save);
again = true;
}
} while (again);
}
// note the timer is create with IRQs on this core
alarm_pool_t *alarm_pool_create(uint hardware_alarm_num, uint max_timers) {
hardware_alarm_claim(hardware_alarm_num);
hardware_alarm_cancel(hardware_alarm_num);
hardware_alarm_set_callback(hardware_alarm_num, alarm_pool_alarm_callback);
alarm_pool_t *pool = (alarm_pool_t *)malloc(sizeof(alarm_pool_t));
pool->lock = spin_lock_instance(next_striped_spin_lock_num());
pool->heap = ph_create(max_timers, timer_pool_entry_comparator, pool);
pool->entries = (alarm_pool_entry_t *)calloc(max_timers, sizeof(alarm_pool_entry_t));
pool->entry_ids_high = (uint8_t *)calloc(max_timers, sizeof(uint8_t));
pool->hardware_alarm_num = hardware_alarm_num;
pools[hardware_alarm_num] = pool;
return pool;
}
void alarm_pool_destroy(alarm_pool_t *pool) {
assert(pools[pool->hardware_alarm_num] == pool);
pools[pool->hardware_alarm_num] = NULL;
// todo clear out timers
ph_destroy(pool->heap);
hardware_alarm_set_callback(pool->hardware_alarm_num, NULL);
hardware_alarm_unclaim(pool->hardware_alarm_num);
free(pool->entry_ids_high);
free(pool->entries);
free(pool);
}
alarm_id_t alarm_pool_add_alarm_at(alarm_pool_t *pool, absolute_time_t time, alarm_callback_t callback,
void *user_data, bool fire_if_past) {
bool missed = false;
uint public_id;
do {
uint8_t id_high = 0;
uint32_t save = spin_lock_blocking(pool->lock);
pheap_node_id_t id = add_alarm_under_lock(pool, time, callback, user_data, 0, false, &missed);
if (id) id_high = *get_entry_id_high(pool, id);
spin_unlock(pool->lock, save);
if (!id) {
return -1;
}
public_id = missed ? 0 : make_public_id(id_high, id);
if (missed && fire_if_past) {
int64_t repeat = callback(public_id, user_data);
if (!repeat) {
public_id = 0;
break;
} else if (repeat < 0) {
time = delayed_by_us(time, -repeat);
} else {
time = delayed_by_us(get_absolute_time(), repeat);
}
} else {
break;
}
} while (true);
return public_id;
}
bool alarm_pool_cancel_alarm(alarm_pool_t *pool, alarm_id_t alarm_id) {
bool rc = false;
uint32_t save = spin_lock_blocking(pool->lock);
pheap_node_id_t id = (pheap_node_id_t) alarm_id;
if (ph_contains(pool->heap, id)) {
assert(alarm_id != pool->alarm_in_progress); // it shouldn't be in the heap if it is in progress
// check we have the right high value
uint8_t id_high = (uint8_t)((uint)alarm_id >> 8u * sizeof(pheap_node_id_t));
if (id_high == *get_entry_id_high(pool, id)) {
rc = ph_delete(pool->heap, id);
// note we don't bother to remove the actual hardware alarm timeout...
// it will either do callbacks or not depending on other alarms, and reset the next timeout itself
assert(rc);
}
} else {
if (alarm_id == pool->alarm_in_progress) {
// make sure the alarm doesn't repeat
pool->alarm_in_progress = 0;
}
}
spin_unlock(pool->lock, save);
return rc;
}
uint alarm_pool_hardware_alarm_num(alarm_pool_t *pool) {
return pool->hardware_alarm_num;
}
static void alarm_pool_dump_key(pheap_node_id_t id, void *user_data) {
alarm_pool_t *pool = (alarm_pool_t *)user_data;
#if PICO_ON_DEVICE
printf("%lld (hi %02x)", to_us_since_boot(get_entry(pool, id)->target), *get_entry_id_high(pool, id));
#else
printf("%ld", to_us_since_boot(get_entry(pool, id)->target));
#endif
}
static int64_t repeating_timer_callback(alarm_id_t id, void *user_data) {
repeating_timer_t *rt = (repeating_timer_t *)user_data;
if (rt->callback(rt)) {
return rt->delay_us;
} else {
rt->alarm_id = 0;
return 0;
}
}
bool alarm_pool_add_repeating_timer_us(alarm_pool_t *pool, int64_t delay_us, repeating_timer_callback_t callback, void *user_data, repeating_timer_t *out) {
if (!delay_us) delay_us = 1;
out->pool = pool;
out->callback = callback;
out->delay_us = delay_us;
out->user_data = user_data;
out->alarm_id = alarm_pool_add_alarm_at(pool, make_timeout_time_us(delay_us >= 0 ? delay_us : -delay_us), repeating_timer_callback, out, true);
return out->alarm_id > 0;
}
bool cancel_repeating_timer(repeating_timer_t *timer) {
bool rc = false;
if (timer->alarm_id) {
rc = alarm_pool_cancel_alarm(timer->pool, timer->alarm_id);
timer->alarm_id = 0;
}
return rc;
}
void alarm_pool_dump(alarm_pool_t *pool) {
uint32_t save = spin_lock_blocking(pool->lock);
ph_dump(pool->heap, alarm_pool_dump_key, pool);
spin_unlock(pool->lock, save);
}
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
static int64_t sev_callback(alarm_id_t id, void *user_data) {
__sev();
return 0;
}
#endif
void sleep_until(absolute_time_t t) {
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
uint64_t t_us = to_us_since_boot(t);
uint64_t t_before_us = t_us - PICO_TIME_SLEEP_OVERHEAD_ADJUST_US;
// needs to work in the first PICO_TIME_SLEEP_OVERHEAD_ADJUST_US of boot
if (t_before_us > t_us) t_before_us = 0;
absolute_time_t t_before;
update_us_since_boot(&t_before, t_before_us);
if (absolute_time_diff_us(get_absolute_time(), t_before) > 0) {
if (add_alarm_at(t_before, sev_callback, NULL, false) >= 0) {
// able to add alarm for just before the time
while (!time_reached(t_before)) {
__wfe();
}
}
}
#endif
// now wait until the exact time
busy_wait_until(t);
}
void sleep_us(uint64_t us) {
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
sleep_until(make_timeout_time_us(us));
#else
if (us >> 32u) {
busy_wait_until(make_timeout_time_us(us));
} else {
busy_wait_us_32(us);
}
#endif
}
void sleep_ms(uint32_t ms) {
sleep_us(ms * 1000ull);
}
bool best_effort_wfe_or_timeout(absolute_time_t timeout_timestamp) {
#if !PICO_TIME_DEFAULT_ALARM_POOL_DISABLED
alarm_id_t id;
id = add_alarm_at(timeout_timestamp, sev_callback, NULL, false);
if (id <= 0) {
tight_loop_contents();
return time_reached(timeout_timestamp);
} else {
__wfe();
// we need to clean up if it wasn't us that caused the wfe; if it was this will be a noop.
cancel_alarm(id);
return time_reached(timeout_timestamp);
}
#else
tight_loop_contents();
return time_reached(timeout_timestamp);
#endif
}

View File

@ -0,0 +1,30 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "pico/timeout_helper.h"
static bool check_single_timeout_us(timeout_state_t *ts) {
return time_reached(ts->next_timeout);
}
check_timeout_fn init_single_timeout_until(timeout_state_t *ts, absolute_time_t target) {
ts->next_timeout = target;
return check_single_timeout_us;
}
static bool check_per_iteration_timeout_us(timeout_state_t *ts) {
if (time_reached(ts->next_timeout)) {
return true;
}
ts->next_timeout = make_timeout_time_us(ts->param);
return false;
}
check_timeout_fn init_per_iteration_timeout_us(timeout_state_t *ts, uint64_t per_iteration_timeout_us) {
ts->next_timeout = make_timeout_time_us(per_iteration_timeout_us);
ts->param = per_iteration_timeout_us;
return check_per_iteration_timeout_us;
}

View File

@ -0,0 +1,15 @@
if (NOT TARGET pico_util_headers)
add_library(pico_util_headers INTERFACE)
target_include_directories(pico_util_headers INTERFACE ${CMAKE_CURRENT_LIST_DIR}/include)
target_link_libraries(pico_util_headers INTERFACE pico_base_headers hardware_sync)
endif()
if (NOT TARGET pico_util)
add_library(pico_util INTERFACE)
target_sources(pico_util INTERFACE
${CMAKE_CURRENT_LIST_DIR}/datetime.c
${CMAKE_CURRENT_LIST_DIR}/pheap.c
${CMAKE_CURRENT_LIST_DIR}/queue.c
)
target_link_libraries(pico_util INTERFACE pico_util_headers)
endif()

View File

@ -0,0 +1,41 @@
#include "pico/util/datetime.h"
#include <stdio.h>
static const char *DATETIME_MONTHS[12] = {
"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"
};
static const char *DATETIME_DOWS[7] = {
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
};
void datetime_to_str(char *buf, uint buf_size, const datetime_t *t) {
snprintf(buf,
buf_size,
"%s %d %s %d:%02d:%02d %d",
DATETIME_DOWS[t->dotw],
t->day,
DATETIME_MONTHS[t->month - 1],
t->hour,
t->min,
t->sec,
t->year);
};

View File

@ -0,0 +1,4 @@
/**
* \defgroup pico_util pico_util
* \brief Useful data structures and utility functions
*/

View File

@ -0,0 +1,27 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_DATETIME_H
#define _PICO_DATETIME_H
#include "pico.h"
/** \file datetime.h
* \defgroup util_datetime datetime
* \brief Date/Time formatting
* \ingroup pico_util
*/
/*! \brief Convert a datetime_t structure to a string
* \ingroup util_datetime
*
* \param buf character buffer to accept generated string
* \param buf_size The size of the passed in buffer
* \param t The datetime to be converted.
*/
void datetime_to_str(char *buf, uint buf_size, const datetime_t *t);
#endif

View File

@ -0,0 +1,155 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _PICO_UTIL_PHEAP_H
#define _PICO_UTIL_PHEAP_H
#include "pico.h"
#ifdef __cplusplus
extern "C" {
#endif
// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_PHEAP, Enable/disable assertions in the pheap module, type=bool, default=0, group=pico_util
#ifndef PARAM_ASSERTIONS_ENABLED_PHEAP
#define PARAM_ASSERTIONS_ENABLED_PHEAP 0
#endif
/**
* \file pheap.h
* \defgroup util_pheap pheap
* Pairing Heap Implementation
* \ingroup pico_util
*
* pheap defines a simple pairing heap. the implementation simply tracks array indexes, it is up to
* the user to provide storage for heap entries and a comparison function.
*
* NOTE: this class is not safe for concurrent usage. It should be externally protected. Furthermore
* if used concurrently, the caller needs to protect around their use of the returned id.
* for example, ph_remove_head returns the id of an element that is no longer in the heap.
*
* The user can still use this to look at the data in their companion array, however obviously further operations
* on the heap may cause them to overwrite that data as the id may be reused on subsequent operations
*
*/
// PICO_CONFIG: PICO_PHEAP_MAX_ENTRIES, Maximum number of entries in the pheap, min=1, max=65534, default=255, group=pico_util
#ifndef PICO_PHEAP_MAX_ENTRIES
#define PICO_PHEAP_MAX_ENTRIES 255
#endif
// public heap_node ids are numbered from 1 (0 means none)
#if PICO_PHEAP_MAX_ENTRIES < 256
typedef uint8_t pheap_node_id_t;
#elif PICO_PHEAP_MAX_ENTRIES < 65535
typedef uint16_t pheap_node_id_t;
#else
#error invalid PICO_PHEAP_MAX_ENTRIES
#endif
typedef struct pheap_node {
pheap_node_id_t child, sibling, parent;
} pheap_node_t;
// return true if a < b in natural order
typedef bool (*pheap_comparator)(void *user_data, pheap_node_id_t a, pheap_node_id_t b);
typedef struct pheap {
pheap_node_t *nodes;
pheap_comparator comparator;
void *user_data;
pheap_node_id_t max_nodes;
pheap_node_id_t root_id;
// we remove from head and add to tail to stop reusing the same ids
pheap_node_id_t free_head_id;
pheap_node_id_t free_tail_id;
} pheap_t;
pheap_t *ph_create(uint max_nodes, pheap_comparator comparator, void *user_data);
void ph_clear(pheap_t *heap);
void ph_destroy(pheap_t *heap);
static inline pheap_node_t *ph_get_node(pheap_t *heap, pheap_node_id_t id) {
assert(id && id <= heap->max_nodes);
return heap->nodes + id - 1;
}
static void ph_add_child_node(pheap_t *heap, pheap_node_id_t parent_id, pheap_node_id_t child_id) {
pheap_node_t *n = ph_get_node(heap, parent_id);
assert(parent_id);
assert(child_id);
assert(parent_id != child_id);
pheap_node_t *c = ph_get_node(heap, child_id);
c->parent = parent_id;
if (!n->child) {
n->child = child_id;
} else {
c->sibling = n->child;
n->child = child_id;
}
}
static pheap_node_id_t ph_merge_nodes(pheap_t *heap, pheap_node_id_t a, pheap_node_id_t b) {
if (!a) return b;
if (!b) return a;
if (heap->comparator(heap->user_data, a, b)) {
ph_add_child_node(heap, a, b);
return a;
} else {
ph_add_child_node(heap, b, a);
return b;
}
}
static inline pheap_node_id_t ph_new_node(pheap_t *heap) {
if (!heap->free_head_id) return 0;
pheap_node_id_t id = heap->free_head_id;
heap->free_head_id = ph_get_node(heap, id)->sibling;
if (!heap->free_head_id) heap->free_tail_id = 0;
return id;
}
// note this will callback the comparator for the node
// returns the (new) root of the heap
static inline pheap_node_id_t ph_insert(pheap_t *heap, pheap_node_id_t id) {
assert(id);
pheap_node_t *hn = ph_get_node(heap, id);
hn->child = hn->sibling = hn->parent = 0;
heap->root_id = ph_merge_nodes(heap, heap->root_id, id);
return heap->root_id;
}
static inline pheap_node_id_t ph_peek_head(pheap_t *heap) {
return heap->root_id;
}
pheap_node_id_t ph_remove_head_reserve(pheap_t *heap, bool reserve);
static inline pheap_node_id_t ph_remove_head(pheap_t *heap) {
return ph_remove_head_reserve(heap, false);
}
static inline bool ph_contains(pheap_t *heap, pheap_node_id_t id) {
return id == heap->root_id || ph_get_node(heap, id)->parent;
}
bool ph_delete(pheap_t *heap, pheap_node_id_t id);
static inline void ph_add_to_free_list(pheap_t *heap, pheap_node_id_t id) {
assert(id && !ph_contains(heap, id));
if (heap->free_tail_id) {
ph_get_node(heap, heap->free_tail_id)->sibling = id;
}
heap->free_tail_id = id;
}
void ph_dump(pheap_t *heap, void (*dump_key)(pheap_node_id_t, void *), void *user_data);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,184 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _UTIL_QUEUE_H
#define _UTIL_QUEUE_H
#include "pico.h"
#include "hardware/sync.h"
/** \file queue.h
* \defgroup queue queue
* Multi-core and IRQ safe queue implementation.
*
* Note that this queue stores values of a specified size, and pushed values are copied into the queue
* \ingroup pico_util
*/
typedef struct {
spin_lock_t *lock;
uint8_t *data;
uint16_t wptr;
uint16_t rptr;
uint16_t element_size;
uint16_t element_count;
} queue_t;
/*! \brief Initialise a queue with a specific spinlock for concurrency protection
* \ingroup queue
*
* \param q Pointer to a queue_t structure, used as a handle
* \param element_size Size of each value in the queue
* \param element_count Maximum number of entries in the queue
* \param spinlock_num The spin ID used to protect the queue
*/
void queue_init_with_spinlock(queue_t *q, uint element_size, uint element_count, uint spinlock_num);
/*! \brief Initialise a queue, allocating a (possibly shared) spinlock
* \ingroup queue
*
* \param q Pointer to a queue_t structure, used as a handle
* \param element_size Size of each value in the queue
* \param element_count Maximum number of entries in the queue
*/
static inline void queue_init(queue_t *q, uint element_size, uint element_count) {
return queue_init_with_spinlock(q, element_size, element_count, next_striped_spin_lock_num());
}
/*! \brief Destroy the specified queue.
* \ingroup queue
*
* \param q Pointer to a queue_t structure, used as a handle
*
* Does not deallocate the queue_t structure itself.
*/
void queue_free(queue_t *q);
/*! \brief Unsafe check of level of the specified queue.
* \ingroup queue
*
* \param q Pointer to a queue_t structure, used as a handle
* \return Number of entries in the queue
*
* This does not use the spinlock, so may return incorrect results if the
* spin lock is not externally locked
*/
static inline uint queue_get_level_unsafe(queue_t *q) {
int32_t rc = (int32_t)q->wptr - (int32_t)q->rptr;
if (rc < 0) {
rc += + q->element_count + 1;
}
return rc;
}
/*! \brief Check of level of the specified queue.
* \ingroup queue
*
* \param q Pointer to a queue_t structure, used as a handle
* \return Number of entries in the queue
*/
static inline uint queue_get_level(queue_t *q) {
uint32_t save = spin_lock_blocking(q->lock);
uint level = queue_get_level_unsafe(q);
spin_unlock(q->lock, save);
return level;
}
/*! \brief Check if queue is empty
* \ingroup queue
*
* \param q Pointer to a queue_t structure, used as a handle
* \return true if queue is empty, false otherwise
*
* This function is interrupt and multicore safe.
*/
static inline bool queue_is_empty(queue_t *q) {
return queue_get_level(q) == 0;
}
/*! \brief Check if queue is full
* \ingroup queue
*
* \param q Pointer to a queue_t structure, used as a handle
* \return true if queue is full, false otherwise
*
* This function is interrupt and multicore safe.
*/
static inline bool queue_is_full(queue_t *q) {
return queue_get_level(q) == q->element_count;
}
// nonblocking queue access functions:
/*! \brief Non-blocking add value queue if not full
* \ingroup queue
*
* \param q Pointer to a queue_t structure, used as a handle
* \param data Pointer to value to be copied into the queue
* \return true if the value was added
*
* 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.
*/
bool queue_try_add(queue_t *q, void *data);
/*! \brief Non-blocking removal of entry from the queue if non empty
* \ingroup queue
*
* \param q Pointer to a queue_t structure, used as a handle
* \param data Pointer to the location to receive the removed value
* \return true if a value was removed
*
* If the queue is not empty function will copy the removed value into the location provided and return
* immediately with true, otherwise the function will return immediately with false.
*/
bool queue_try_remove(queue_t *q, void *data);
/*! \brief Non-blocking peek at the next item to be removed from the queue
* \ingroup queue
*
* \param q Pointer to a queue_t structure, used as a handle
* \param data Pointer to the location to receive the peeked value
* \return true if there was a value to peek
*
* If the queue is not empty this function will return immediately with true with the peeked entry
* copied into the location specified by the data parameter, otherwise the function will return false.
*/
bool queue_try_peek(queue_t *q, void *data);
// blocking queue access functions:
/*! \brief Blocking add of value to queue
* \ingroup queue
*
* \param q Pointer to a queue_t structure, used as a handle
* \param data Pointer to value to be copied into 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);
/*! \brief Blocking remove entry from queue
* \ingroup queue
*
* \param q Pointer to a queue_t structure, used as a handle
* \param data Pointer to the location to receive the removed value
*
* If the queue is empty this function will block until a value is added.
*/
void queue_remove_blocking(queue_t *q, void *data);
/*! \brief Blocking peek at next value to be removed from queue
* \ingroup queue
*
* \param q Pointer to a queue_t structure, used as a handle
* \param data Pointer to the location to receive the peeked value
*
* If the queue is empty function will block until a value is added
*/
void queue_peek_blocking(queue_t *q, void *data);
#endif

View File

@ -0,0 +1,130 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <stdlib.h>
#include "pico/util/pheap.h"
pheap_t *ph_create(uint max_nodes, pheap_comparator comparator, void *user_data) {
invalid_params_if(PHEAP, !max_nodes || max_nodes >= (1u << sizeof(pheap_node_id_t)));
pheap_t *heap = calloc(1, sizeof(pheap_t));
heap->max_nodes = max_nodes;
heap->comparator = comparator;
heap->nodes = calloc(max_nodes, sizeof(pheap_node_t));
heap->user_data = user_data;
ph_clear(heap);
return heap;
}
void ph_clear(pheap_t *heap) {
heap->root_id = 0;
heap->free_head_id = 1;
heap->free_tail_id = heap->max_nodes;
for(uint i = 1; i < heap->max_nodes; i++) {
ph_get_node(heap, i)->sibling = i + 1;
}
ph_get_node(heap, heap->max_nodes)->sibling = 0;
}
void ph_destroy(pheap_t *heap) {
free(heap->nodes);
free(heap);
}
pheap_node_id_t ph_merge_two_pass(pheap_t *heap, pheap_node_id_t id) {
if (!id || !ph_get_node(heap, id)->sibling) {
return id;
} else {
pheap_node_id_t a, b, new_node;
a = id;
b = ph_get_node(heap, id)->sibling;
new_node = ph_get_node(heap, b)->sibling;
ph_get_node(heap, a)->sibling = ph_get_node(heap, b)->sibling = 0;
return ph_merge_nodes(heap, ph_merge_nodes(heap, a, b), ph_merge_two_pass(heap, new_node));
}
}
static pheap_node_id_t ph_remove_any_head(pheap_t *heap, pheap_node_id_t root_id, bool reserve) {
assert(root_id);
// printf("Removing head %d (parent %d sibling %d)\n", root_id, ph_get_node(heap, root_id)->parent, ph_get_node(heap, root_id)->sibling);
assert(!ph_get_node(heap, root_id)->sibling);
assert(!ph_get_node(heap, root_id)->parent);
pheap_node_id_t new_root_id = ph_merge_two_pass(heap, ph_get_node(heap, root_id)->child);
if (!reserve) {
if (heap->free_tail_id) {
ph_get_node(heap, heap->free_tail_id)->sibling = root_id;
}
heap->free_tail_id = root_id;
}
if (new_root_id) ph_get_node(heap, new_root_id)->parent = 0;
ph_get_node(heap, root_id)->sibling = 0;
return new_root_id;
}
pheap_node_id_t ph_remove_head_reserve(pheap_t *heap, bool reserve) {
pheap_node_id_t old_root_id = ph_peek_head(heap);
heap->root_id = ph_remove_any_head(heap, old_root_id, reserve);
return old_root_id;
}
#include <stdio.h>
bool ph_delete(pheap_t *heap, pheap_node_id_t id) {
// 1) trivial cases
if (!id) return false;
if (id == heap->root_id) {
ph_remove_head(heap);
return true;
}
// 2) unlink the node from the tree
pheap_node_t *node = ph_get_node(heap, id);
if (!node->parent) return false; // not in tree
pheap_node_t *parent = ph_get_node(heap, node->parent);
if (parent->child == id) {
parent->child = node->sibling;
} else {
pheap_node_id_t prev_sibling_id = parent->child;
bool __unused found = false;
do {
pheap_node_t *prev_sibling = ph_get_node(heap, prev_sibling_id);
if (prev_sibling->sibling == id) {
prev_sibling->sibling = node->sibling;
found = true;
break;
}
prev_sibling_id = prev_sibling->sibling;
} while (prev_sibling_id);
assert(found);
}
node->sibling = node->parent = 0;
// ph_dump(heap, NULL, NULL);
// 3) remove it from the head of its own subtree
pheap_node_id_t new_sub_tree = ph_remove_any_head(heap, id, false);
assert(new_sub_tree != heap->root_id);
heap->root_id = ph_merge_nodes(heap, heap->root_id, new_sub_tree);
return true;
}
static uint ph_dump_node(pheap_t *heap, pheap_node_id_t id, void (*dump_key)(pheap_node_id_t, void *), void *user_data, uint indent) {
uint count = 0;
if (id) {
count++;
for (uint i = 0; i < indent * 2; i++) {
putchar(' ');
}
pheap_node_t *node = ph_get_node(heap, id);
printf("%d (c=%d s=%d p=%d) ", id, node->child, node->sibling, node->parent);
if (dump_key) dump_key(id, user_data);
printf("\n");
count += ph_dump_node(heap, node->child, dump_key, user_data, indent + 1);
count += ph_dump_node(heap, node->sibling, dump_key, user_data, indent);
}
return count;
}
void ph_dump(pheap_t *heap, void (*dump_key)(pheap_node_id_t, void *), void *user_data) {
uint count = ph_dump_node(heap, heap->root_id, dump_key, user_data, 0);
printf("node_count %d\n", count);
}

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdlib.h>
#include <string.h>
#include "pico/util/queue.h"
void queue_init_with_spinlock(queue_t *q, uint element_size, uint element_count, uint spinlock_num) {
q->lock = spin_lock_instance(spinlock_num);
q->data = (uint8_t *)calloc(element_count + 1, element_size);
q->element_count = element_count;
q->element_size = element_size;
q->wptr = 0;
q->rptr = 0;
}
void queue_free(queue_t *q) {
free(q->data);
}
static inline void *element_ptr(queue_t *q, uint index) {
assert(index <= q->element_count);
return q->data + index * q->element_size;
}
static inline uint16_t inc_index(queue_t *q, uint16_t index) {
if (++index > q->element_count) { // > because we have element_count + 1 elements
index = 0;
}
return index;
}
bool queue_try_add(queue_t *q, void *data) {
bool success = false;
uint32_t flags = spin_lock_blocking(q->lock);
if (queue_get_level_unsafe(q) != q->element_count) {
memcpy(element_ptr(q, q->wptr), data, q->element_size);
q->wptr = inc_index(q, q->wptr);
success = true;
}
spin_unlock(q->lock, flags);
if (success) __sev();
return success;
}
bool queue_try_remove(queue_t *q, void *data) {
bool success = false;
uint32_t flags = spin_lock_blocking(q->lock);
if (queue_get_level_unsafe(q) != 0) {
memcpy(data, element_ptr(q, q->rptr), q->element_size);
q->rptr = inc_index(q, q->rptr);
success = true;
}
spin_unlock(q->lock, flags);
if (success) __sev();
return success;
}
bool queue_try_peek(queue_t *q, void *data) {
bool success = 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) {
bool done;
do {
done = queue_try_add(q, data);
if (done) break;
__wfe();
} while (true);
}
void queue_remove_blocking(queue_t *q, void *data) {
bool done;
do {
done = queue_try_remove(q, data);
if (done) break;
__wfe();
} while (true);
}
void queue_peek_blocking(queue_t *q, void *data) {
bool done;
do {
done = queue_try_peek(q, data);
if (done) break;
__wfe();
} while (true);
}

10
src/host.cmake Normal file
View File

@ -0,0 +1,10 @@
# For targeting the host for testing purposes
function(pico_add_extra_outputs TARGET)
endfunction()
set(PICO_NO_HARDWARE "1" CACHE INTERNAL "")
set(PICO_ON_DEVICE "0" CACHE INTERNAL "")
add_subdirectory(common)
add_subdirectory(host)

28
src/host/CMakeLists.txt Normal file
View File

@ -0,0 +1,28 @@
pico_add_subdirectory(hardware_divider)
pico_add_subdirectory(hardware_gpio)
pico_add_subdirectory(hardware_sync)
pico_add_subdirectory(hardware_timer)
pico_add_subdirectory(hardware_uart)
pico_add_subdirectory(pico_bit_ops)
pico_add_subdirectory(pico_divider)
pico_add_subdirectory(pico_multicore)
pico_add_subdirectory(pico_platform)
pico_add_subdirectory(pico_printf)
pico_add_subdirectory(pico_stdio)
pico_add_subdirectory(pico_stdlib)
pico_add_doxygen(${CMAKE_CURRENT_LIST_DIR})
macro(pico_set_float_implementation TARGET IMPL)
endmacro()
macro(pico_set_double_implementation TARGET IMPL)
endmacro()
macro(pico_set_boot_stage2 TARGET IMPL)
endmacro()
set(PICO_HOST_DIR "${CMAKE_CURRENT_LIST_DIR}" CACHE INTERNAL "")
function(pico_define_boot_stage2 NAME)
add_executable(${NAME} ${PICO_HOST_DIR}/boot_stage2.c)
endfunction()

14
src/host/README.md Normal file
View File

@ -0,0 +1,14 @@
This is a basic set of replacement library implementations sufficient to get simple applications
running on your computer (Raspberry Pi OS, Linux, macOS or Windows using Cygwin or Windows Subsystem for Linux).
It is selected by `PICO_PLATFORM=host` in your CMake build
This can be extremely useful for testing and debugging higher level application code, or porting code which is not yet small enough
to run on the RP2040 device itself.
This base level host library provides a minimal environment to compile programs, but is likely sufficient for programs
that don't access hardware directly.
It is possible however to inject additional SDK library implementations/simulations to provide
more complete functionality. For an example of this see the [pico-host-sdl](https://github.com/raspberrypi/pico-host-sdl)
which uses the SDL2 library to add additional library support for pico_multicore, timers/alarms in pico-time and
pico-audio/pico-scanvideo from [pico-extras](https://github.com/raspberrypi/pico-extras)

1
src/host/boot_stage2.c Normal file
View File

@ -0,0 +1 @@
// empty

View File

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

View File

@ -0,0 +1,9 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "hardware/divider.h"
__thread uint64_t hw_divider_result_threadlocal;

View File

@ -0,0 +1,122 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef _HARDWARE_DIVIDER_H
#define _HARDWARE_DIVIDER_H
#include "pico/types.h"
typedef uint64_t divmod_result_t;
static inline int __sign_of(int32_t v) {
return v > 0 ? 1 : (v < 0 ? -1 : 0);
}
// divides unsigned values a by b... (a/b) returned in low 32 bits, (a%b) in high 32 bits... results undefined for b==0
static inline uint64_t hw_divider_divmod_u32(uint32_t a, uint32_t b) {
if (!b) return (((uint64_t)a)<<32u) | (uint32_t)(-1); // todo check this
return (((uint64_t)(a%b))<<32u) | (a/b);
}
// divides signed values a by b... (a/b) returned in low 32 bits, (a%b) in high 32 bits... results undefined for b==0
static inline uint64_t hw_divider_divmod_s32(int32_t a, int32_t b) {
if (!b) return (((uint64_t)a)<<32u) | (uint32_t)(-__sign_of(a));
return (((uint64_t)(a%b))<<32u) | (uint32_t)(a/b);
}
extern __thread divmod_result_t hw_divider_result_threadlocal;
static inline void hw_divider_divmod_s32_start(int32_t a, int32_t b) {
hw_divider_result_threadlocal = hw_divider_divmod_s32(a, b);
}
static inline void hw_divider_divmod_u32_start(uint32_t a, uint32_t b) {
hw_divider_result_threadlocal = hw_divider_divmod_u32(a, b);
}
static inline divmod_result_t hw_divider_result_wait() {
return hw_divider_result_threadlocal;
}
static inline uint64_t hw_divider_result_nowait() {
return hw_divider_result_threadlocal;
}
inline static uint32_t to_quotient_u32(unsigned long long int r) {
return (uint32_t) r;
}
inline static int32_t to_quotient_s32(unsigned long long int r) {
return (int32_t)(uint32_t)r;
}
inline static uint32_t to_remainder_u32(unsigned long long int r) {
return (uint32_t)(r >> 32u);
}
inline static int32_t to_remainder_s32(unsigned long long int r) {
return (int32_t)(r >> 32u);
}
static inline uint32_t hw_divider_u32_quotient_wait() {
return to_quotient_u32(hw_divider_result_wait());
}
static inline uint32_t hw_divider_u32_remainder_wait() {
return to_remainder_u32(hw_divider_result_wait());
}
static inline int32_t hw_divider_s32_quotient_wait() {
return to_quotient_s32(hw_divider_result_wait());
}
static inline int32_t hw_divider_s32_remainder_wait() {
return to_remainder_s32(hw_divider_result_wait());
}
static inline uint32_t hw_divider_u32_quotient(uint32_t a, uint32_t b) {
return b ? (a / b) : -1;
}
static inline uint32_t hw_divider_u32_remainder(uint32_t a, uint32_t b) {
return b ? (a % b) : a;
}
static inline int32_t hw_divider_s32_quotient(int32_t a, int32_t b) {
return b ? (a / b) : -__sign_of(a);
}
static inline int32_t hw_divider_s32_remainder(int32_t a, int32_t b) {
return b ? (a % b) : a;
}
static inline uint32_t hw_divider_u32_quotient_inlined(uint32_t a, uint32_t b) {
return hw_divider_u32_quotient(a,b);
}
static inline uint32_t hw_divider_u32_remainder_inlined(uint32_t a, uint32_t b) {
return hw_divider_u32_remainder(a,b);
}
static inline int32_t hw_divider_s32_quotient_inlined(int32_t a, int32_t b) {
return hw_divider_s32_quotient(a,b);
}
static inline int32_t hw_divider_s32_remainder_inlined(int32_t a, int32_t b) {
return hw_divider_s32_remainder(a,b);
}
typedef uint64_t hw_divider_state_t;
static inline void hw_divider_save_state(hw_divider_state_t *dest) {
*dest = hw_divider_result_threadlocal;
}
static inline void hw_divider_restore_state(hw_divider_state_t *src) {
hw_divider_result_threadlocal = *src;
}
#endif // _HARDWARE_DIVIDER_H

View File

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

View File

@ -0,0 +1,118 @@
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include "hardware/gpio.h"
// todo weak or replace? probably weak
void gpio_set_function(uint gpio, enum gpio_function fn) {
}
void gpio_pull_up(uint gpio) {
}
void gpio_pull_down(uint gpio) {
}
void gpio_disable_pulls(uint gpio) {
}
void gpio_set_pulls(uint gpio, bool up, bool down) {
}
void gpio_set_outover(uint gpio, uint value) {
}
void gpio_set_inover(uint gpio, uint value) {
}
void gpio_set_oeover(uint gpio, uint value) {
}
void gpio_set_irq_enabled(uint gpio, uint32_t events, bool enable) {
}
void gpio_acknowledge_irq(uint gpio, uint32_t events) {
}
void gpio_init(uint gpio) {
}
PICO_WEAK_FUNCTION_DEF(gpio_get)
bool PICO_WEAK_FUNCTION_IMPL_NAME(gpio_get)(uint gpio) {
return 0;
}
uint32_t gpio_get_all() {
return 0;
}
void gpio_set_mask(uint32_t mask) {
}
void gpio_clr_mask(uint32_t mask) {
}
void gpio_xor_mask(uint32_t mask) {
}
void gpio_put_masked(uint32_t mask, uint32_t value) {
}
void gpio_put_all(uint32_t value) {
}
void gpio_put(uint gpio, int value) {
}
void gpio_set_dir_out_masked(uint32_t mask) {
}
void gpio_set_dir_in_masked(uint32_t mask) {
}
void gpio_set_dir_masked(uint32_t mask, uint32_t value) {
}
void gpio_set_dir_all_bits(uint32_t value) {
}
void gpio_set_dir(uint gpio, bool out) {
}
void gpio_debug_pins_init() {
}
void gpio_set_input_enabled(uint gpio, bool enable) {
}
void gpio_init_mask(uint gpio_mask) {
}

Some files were not shown because too many files have changed in this diff Show More