Compare commits
1 Commits
master
...
feature/do
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82f62d1650 |
@ -15,6 +15,7 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake/)
|
|||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
list(APPEND CMAKE_CXX_FLAGS "-Wall -Wextra")
|
list(APPEND CMAKE_CXX_FLAGS "-Wall -Wextra")
|
||||||
|
|
||||||
|
option(WITH_DOCS "Enable building docs." OFF)
|
||||||
option(WITH_TESTS "Enable unit testing." OFF)
|
option(WITH_TESTS "Enable unit testing." OFF)
|
||||||
option(WITH_HAL "Enable the compiling and deployment of the HAL dependent sections." 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)
|
add_subdirectory(Tests)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(WITH_DOCS)
|
||||||
|
add_subdirectory(docs)
|
||||||
|
endif()
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
configure_file(skullc-config.cmake
|
configure_file(skullc-config.cmake
|
||||||
|
|||||||
@ -20,6 +20,17 @@ enum class ButtonPress : std::uint32_t
|
|||||||
LONG_PRESS
|
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>
|
template<typename G, typename H>
|
||||||
class Button
|
class Button
|
||||||
{
|
{
|
||||||
@ -27,7 +38,7 @@ public:
|
|||||||
using gpio = G;
|
using gpio = G;
|
||||||
using hal = H;
|
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_SHORT_PRESS = 50;
|
||||||
static constexpr std::uint32_t TIMEOUT_LONG_PRESS = 500;
|
static constexpr std::uint32_t TIMEOUT_LONG_PRESS = 500;
|
||||||
@ -37,6 +48,9 @@ public:
|
|||||||
: sw(sw)
|
: sw(sw)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the do.
|
||||||
|
*/
|
||||||
void update()
|
void update()
|
||||||
{
|
{
|
||||||
const bool is_pressed = sw.read();
|
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