This commit is contained in:
parent
3b2b535ad5
commit
82f62d1650
@ -15,6 +15,7 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
list(APPEND CMAKE_CXX_FLAGS "-Wall -Wextra")
|
||||
|
||||
option(WITH_DOCS "Enable building docs." OFF)
|
||||
option(WITH_TESTS "Enable unit testing." OFF)
|
||||
option(WITH_HAL "Enable the compiling and deployment of the HAL dependent sections." OFF)
|
||||
|
||||
@ -29,6 +30,10 @@ if(WITH_TESTS)
|
||||
add_subdirectory(Tests)
|
||||
endif()
|
||||
|
||||
if(WITH_DOCS)
|
||||
add_subdirectory(docs)
|
||||
endif()
|
||||
|
||||
## Install
|
||||
|
||||
configure_file(skullc-config.cmake
|
||||
|
||||
@ -20,6 +20,17 @@ enum class ButtonPress : std::uint32_t
|
||||
LONG_PRESS
|
||||
};
|
||||
|
||||
/**
|
||||
* A class to abstract a button!
|
||||
*
|
||||
* Usage example:
|
||||
* @code
|
||||
* int a = 4;
|
||||
* @endcode
|
||||
*
|
||||
* @tparam G The class to use for GPIO. Must have members @c set(bool).
|
||||
* @tparam H The HAL class to use.
|
||||
*/
|
||||
template<typename G, typename H>
|
||||
class Button
|
||||
{
|
||||
@ -27,7 +38,7 @@ public:
|
||||
using gpio = G;
|
||||
using hal = H;
|
||||
|
||||
gpio sw;
|
||||
gpio sw; ///< A switch instance.
|
||||
|
||||
static constexpr std::uint32_t TIMEOUT_SHORT_PRESS = 50;
|
||||
static constexpr std::uint32_t TIMEOUT_LONG_PRESS = 500;
|
||||
@ -37,6 +48,9 @@ public:
|
||||
: sw(sw)
|
||||
{}
|
||||
|
||||
/**
|
||||
* Does the do.
|
||||
*/
|
||||
void update()
|
||||
{
|
||||
const bool is_pressed = sw.read();
|
||||
|
||||
40
Utility/Inc/utility_assert.hpp
Normal file
40
Utility/Inc/utility_assert.hpp
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* utility_assert.hpp
|
||||
*
|
||||
* Created on: Jun 25, 2021
|
||||
* Author: erki
|
||||
*/
|
||||
|
||||
#ifndef UTILITY_INC_UTILITY_ASSERT_HPP_
|
||||
#define UTILITY_INC_UTILITY_ASSERT_HPP_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
__attribute__((weak)) void SkullC_AssertHandler(const char* file, int line, const char* func, const char* failed_expr)
|
||||
{
|
||||
}
|
||||
|
||||
void __assert_func(const char* file, int line, const char* func, const char* failed_expr)
|
||||
{
|
||||
#ifdef SKULLC_UTILITY_ASSERT_TO_ERRORHANDLER
|
||||
Error_Handler();
|
||||
#else
|
||||
__disable_irq();
|
||||
__asm("bkpt");
|
||||
|
||||
#ifdef SKULLC_UTILITY_ASSERT_CUSTOM_HANDLER
|
||||
SkullC_AssertHandler(file, line, func, failed_expr);
|
||||
#endif
|
||||
|
||||
while (1)
|
||||
;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* UTILITY_INC_UTILITY_ASSERT_HPP_ */
|
||||
7
cmake/FindSphinx.cmake
Normal file
7
cmake/FindSphinx.cmake
Normal file
@ -0,0 +1,7 @@
|
||||
find_program(SPHINX_EXECUTABLE
|
||||
NAMES sphinx-build
|
||||
DOC "Path to sphinx-build executable")
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_package_handle_Standard_args(Sphinx "Failed to find sphinx-build executable" SPHINX_EXECUTABLE)
|
||||
44
docs/CMakeLists.txt
Normal file
44
docs/CMakeLists.txt
Normal file
@ -0,0 +1,44 @@
|
||||
find_package(Doxygen REQUIRED)
|
||||
find_package(Sphinx REQUIRED)
|
||||
|
||||
file(GLOB_RECURSE PERIPHERALS_HEADERS ${CMAKE_SOURCE_DIR}/Peripherals/Inc/*.hpp)
|
||||
|
||||
set(DOXYGEN_INPUT_DIR "${PROJECT_SOURCE_DIR}/Threads/Inc ${PROJECT_SOURCE_DIR}/Peripherals/Inc ${PROJECT_SOURCE_DIR}/Utility/Inc")
|
||||
set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}/docs/doxygen)
|
||||
set(DOXYGEN_INDEX_FILE ${CMAKE_CURRENT_SOURCE_DIR}/html/index.html)
|
||||
set(DOXYFILE_IN ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in)
|
||||
set(DOXYFILE_OUT ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile)
|
||||
|
||||
#Replace variables inside @@ with the current values
|
||||
configure_file(${DOXYFILE_IN} ${DOXYFILE_OUT} @ONLY)
|
||||
|
||||
file(MAKE_DIRECTORY ${DOXYGEN_OUTPUT_DIR}) #Doxygen won't create this for us
|
||||
add_custom_command(OUTPUT ${DOXYGEN_INDEX_FILE}
|
||||
DEPENDS ${PERIPHERALS_HEADERS}
|
||||
COMMAND ${DOXYGEN_EXECUTABLE} ${DOXYFILE_OUT}
|
||||
MAIN_DEPENDENCY ${DOXYFILE_OUT} ${DOXYFILE_IN}
|
||||
COMMENT "Generating docs")
|
||||
|
||||
add_custom_target(Doxygen ALL DEPENDS ${DOXYGEN_INDEX_FILE})
|
||||
|
||||
set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/docs/sphinx)
|
||||
set(SPHINX_INDEX_FILE ${SPHINX_BUILD}/index.html)
|
||||
set(SPHINX_SOURCE_LIST
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/index.rst
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/peripherals.rst
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/utility.rst
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/threads.rst
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT ${SPHINX_INDEX_FILE}
|
||||
COMMAND
|
||||
${SPHINX_EXECUTABLE} -b html
|
||||
-Dbreathe_projects.SkullC=${DOXYGEN_OUTPUT_DIR}/xml
|
||||
${SPHINX_SOURCE} ${SPHINX_BUILD}
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
|
||||
DEPENDS ${SPHINX_SOURCE_LIST} ${PERIPHERALS_HEADERS}
|
||||
MAIN_DEPENDENCY ${SPHINX_SOURCE}/conf.py
|
||||
COMMENT "Generating documentation with Sphinx")
|
||||
|
||||
add_custom_target(Sphinx ALL DEPENDS ${SPHINX_INDEX_FILE})
|
||||
2579
docs/Doxyfile.in
Normal file
2579
docs/Doxyfile.in
Normal file
File diff suppressed because it is too large
Load Diff
57
docs/conf.py
Normal file
57
docs/conf.py
Normal file
@ -0,0 +1,57 @@
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
# import os
|
||||
# import sys
|
||||
# sys.path.insert(0, os.path.abspath('.'))
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'SkullC'
|
||||
copyright = '2021, Erki (Skull132)'
|
||||
author = 'Erki (Skull132)'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
"breathe"
|
||||
]
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
|
||||
# -- Options for breathe plugin -----------------------------------------------
|
||||
|
||||
breathe_default_project = "SkullC"
|
||||
50
docs/index.rst
Normal file
50
docs/index.rst
Normal file
@ -0,0 +1,50 @@
|
||||
.. SkullC documentation master file, created by
|
||||
sphinx-quickstart on Wed Jul 7 13:46:52 2021.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to SkullC's documentation!
|
||||
==================================
|
||||
|
||||
**SkullC** is a C++17 library, composed of various modules, meant for **embedded software** development. The code is presently
|
||||
licensed under MIT and can be freely found in `the Git repository here <https://git.skullnet.me/erki/skullc-peripherals>`_.
|
||||
|
||||
The library contains abstractions for commonly used peripheral devices, general utility functions, and an abstraction over
|
||||
FreeRTOS for RTOS based programming. A lot of it is developed as I go, with some components having more questionable design
|
||||
as others (since some are implemented as thought-exercises at first). This also speaks about API stability: things may change.
|
||||
|
||||
Most of this library has been tested and built for the STM32 boards. Though in theory, the code is not reliant on any specific
|
||||
HAL and can be expanded to work on any system for which you implement the required interfaces.
|
||||
|
||||
Contents
|
||||
--------
|
||||
|
||||
You will find 3 large modules here.
|
||||
|
||||
The :doc:`peripherals` contains both abstractions over the ST HAL and various other peripheral devices, such as IMUs,
|
||||
displays, etc.
|
||||
|
||||
The :doc:`utility` contains various "software" helpers, abstractions, etcetera, that don't necessarily interface with
|
||||
hardware, but in general provide helpful tools for embedded development. This includes logging functionality, a drawing
|
||||
abstraction, and so forth.
|
||||
|
||||
The :doc:`threads` is a set of various C++ abstractions over FreeRTOS. With the key highlight being an implementation of
|
||||
a signalling system, and the actor model of asynchronous processing.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
The library is made to be as build-tool agnostic as possible. All modules can simply be dropped into whatever IDE/project
|
||||
structure you have, and then used. No major configuration is necessary. Most modules are header-only, some require additional
|
||||
source files to be compiled and linked.
|
||||
|
||||
For development use, cmake is used to enable unit testing (and should also function for integration with cmake projects).
|
||||
Conan and catch2 are additional dependencies for unit testing and CI work.
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
:caption: Contents:
|
||||
|
||||
peripherals.rst
|
||||
utility.rst
|
||||
threads.rst
|
||||
161
docs/peripherals.rst
Normal file
161
docs/peripherals.rst
Normal file
@ -0,0 +1,161 @@
|
||||
Peripherals Module
|
||||
==================
|
||||
|
||||
The peripherals module contains various external devices for which (hopefully) reusable abstractions have been created.
|
||||
All interfacing with hardware is done through static dispatch: hardware wrappers are to be passed in as copy-constructible
|
||||
handle objects, with the objects themselves being specified as template parameters. This includes a static HAL object,
|
||||
should the class need generic HAL features, like a delay function.
|
||||
|
||||
HAL Abstraction
|
||||
---------------
|
||||
|
||||
As mentioned earlier, the HAL gets abstracted with simple wrapper classes that are passed into the consuming object as
|
||||
template parameters. There's a special class to encapsulate more static HAL functions, such as delays, which is referred
|
||||
to as the "static HAL" struct.
|
||||
|
||||
An example implementation of mildly fleshed out HAL abstraction can be found in the "Peripherals::Hal::St" namespace.
|
||||
|
||||
To make peripheral devices reusable and also configurable, the library composes all HAL-dependencies as templated members.
|
||||
A few common interfaces have come from this, specifically the GPIO and Serial interfaces. Along with the static HAL itself.
|
||||
Requirements for these common classes can be outlined as follows:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// A class for statically composing "static" features of a HAL.
|
||||
struct StaticHal
|
||||
{
|
||||
static std::uint32_t getMillis();
|
||||
static void delay(const std::uint32_t milliseconds);
|
||||
static void delayUs(const std::uint32_t micros);
|
||||
static void enableInterrupts();
|
||||
static void disableInterrupts();
|
||||
};
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// A common serial interface, for sending and receiving data.
|
||||
struct SerialInterface
|
||||
{
|
||||
bool transmit(std::uint8_t* data, const std::uint32_t data_len);
|
||||
template<typename Td, std::size_t N>
|
||||
bool transmit(std::array<Td, N>& array);
|
||||
|
||||
bool receive(std::uint8_t* data, const std::uint32_t data_len);
|
||||
template<typename Td, std::size_t N>
|
||||
bool receive(std::array<Td, N>& array);
|
||||
};
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
// A common GPIO interface.
|
||||
struct Gpio
|
||||
{
|
||||
void set(const bool& state);
|
||||
void toggle();
|
||||
bool read() const;
|
||||
};
|
||||
|
||||
Usage Notes
|
||||
-----------
|
||||
|
||||
It would be recommended to type-def whatever configurations you use, and go from there. The peripherals themselves should
|
||||
be passed around as pointers or references -- they don't typically play well with copy constructors. And really, one object
|
||||
per physical peripheral should exist.
|
||||
|
||||
It should also be noted that **constructors for peripherals can be non-trivial**. (Peripherals in this case being the non-HAL
|
||||
ones.) They will do initialization in there, so that the object is usable right after successful construction. This means
|
||||
you have to ensure that HAL setup is completed *before* the instances are constructed. Having them as global instances
|
||||
will be affected by this, a quick fix is to just dynamically allocate them. Or use other means of deferred construction.
|
||||
|
||||
A few examples follow, based on the STM32 HAL.
|
||||
|
||||
Using a simple main, where the constructor is placed after all of the init functions:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
#include <peripherals_button.hpp>
|
||||
#include <peripherals_hal_st.hpp>
|
||||
|
||||
using Button
|
||||
= Peripherals::Button<Peripherals::Hal::St::Gpio, Peripherals::Hal::St::StaticHal>;
|
||||
|
||||
void useButton(Button& b);
|
||||
|
||||
int main() {
|
||||
HAL_Init();
|
||||
SystemClock_Config();
|
||||
|
||||
MX_GPIO_Init();
|
||||
|
||||
Button b1({ BTN_GPIO_Port, BTN_Pin, false });
|
||||
|
||||
while (true) {
|
||||
useButton(b1);
|
||||
}
|
||||
}
|
||||
|
||||
Using a scenario where the class instance is kept as a global. In this case, dynamic allocation is used to achieve proper
|
||||
constructor order:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
#include <peripherals_button.hpp>
|
||||
#include <peripherals_hal_st.hpp>
|
||||
|
||||
using Button
|
||||
= Peripherals::Button<Peripherals::Hal::St::Gpio, Peripherals::Hal::St::StaticHal>;
|
||||
|
||||
Button* b1;
|
||||
|
||||
void useButton(Button& b);
|
||||
|
||||
int main() {
|
||||
HAL_Init();
|
||||
SystemClock_Config();
|
||||
|
||||
MX_GPIO_Init();
|
||||
|
||||
b1 = new Button({ BTN_GPIO_Port, BTN_Pin, false });
|
||||
|
||||
while (true) {
|
||||
useButton(*b1);
|
||||
}
|
||||
}
|
||||
|
||||
Using the StaticPointer class from the Utility module of this library is also a way of deferring the construction, while
|
||||
maintaining complete static allocation:
|
||||
|
||||
.. code-block:: c++
|
||||
|
||||
#include <peripherals_button.hpp>
|
||||
#include <peripherals_hal_st.hpp>
|
||||
#include <utility_staticpointer.hpp>
|
||||
|
||||
using Button
|
||||
= Peripherals::Button<Peripherals::Hal::St::Gpio, Peripherals::Hal::St::StaticHal>;
|
||||
|
||||
Utility::StaticPointer<Button> b1;
|
||||
|
||||
void useButton(Button& b);
|
||||
|
||||
int main() {
|
||||
HAL_Init();
|
||||
SystemClock_Config();
|
||||
|
||||
MX_GPIO_Init();
|
||||
|
||||
b1.setup({ BTN_GPIO_Port, BTN_Pin, false });
|
||||
|
||||
while (true) {
|
||||
useButton(*b1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Public Members
|
||||
--------------
|
||||
|
||||
.. doxygennamespace:: Peripherals
|
||||
:content-only:
|
||||
:undoc-members:
|
||||
:members:
|
||||
4
docs/threads.rst
Normal file
4
docs/threads.rst
Normal file
@ -0,0 +1,4 @@
|
||||
Threads Module
|
||||
==============
|
||||
|
||||
asdasd
|
||||
4
docs/utility.rst
Normal file
4
docs/utility.rst
Normal file
@ -0,0 +1,4 @@
|
||||
Utility Module
|
||||
==============
|
||||
|
||||
szdf
|
||||
Loading…
x
Reference in New Issue
Block a user