Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
BasedOnStyle: Mozilla
Language: Cpp
UseTab: Never
AlwaysBreakAfterReturnType: None
AlwaysBreakAfterDefinitionReturnType: None
AllowShortFunctionsOnASingleLine: None
FixNamespaceComments: true
SpacesBeforeTrailingComments: 2
ColumnLimit: 80
11 changes: 11 additions & 0 deletions .github/workflows/0.0.1.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
name: 🚀 Deploy 0.0.1

on:
workflow_dispatch:

jobs:
deploy:
uses: libhal/ci/.github/workflows/[email protected]
with:
version: 0.0.1
secrets: inherit
39 changes: 39 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright 2024 Khalil Estell
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

name: ✅ CI

on:
workflow_dispatch:
pull_request:
push:
branches:
- main
schedule:
- cron: "0 12 * * 0"

jobs:
ci:
uses: libhal/ci/.github/workflows/[email protected]
secrets: inherit

deploy_cortex-m4f_check:
uses: libhal/ci/.github/workflows/[email protected]
with:
arch: cortex-m4f
os: baremetal
compiler: gcc
compiler_version: 12.3
compiler_package: arm-gnu-toolchain
secrets: inherit
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@
*.exe
*.out
*.app

build/**
CMakeUserPresets.json
48 changes: 48 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Copyright 2024 Khalil Estell
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

cmake_minimum_required(VERSION 3.15)

project(libhal-exceptions LANGUAGES CXX)


if("${RUNTIME}" STREQUAL "ARM_CORTEX_GCC")
set(SOURCE_LIST src/builtin/gcc/impl.cpp)
elseif("${RUNTIME}" STREQUAL "ARM_CORTEX_ESTELL")
set(SOURCE_LIST
src/arm_cortex/estell/exception.cpp
src/arm_cortex/estell/wrappers.cpp
)
else()
message(FATAL "Invalid Exception RUNTIME: '${RUNTIME}' provided!")
endif()

libhal_make_library(
LIBRARY_NAME libhal-exceptions

SOURCES
src/control.cpp
${SOURCE_LIST}
)

if(NOT ${CMAKE_CROSSCOMPILING})
libhal_unit_test(
LIBRARY_NAME libhal-exceptions

SOURCES
src/control.cpp
tests/main.test.cpp
${SOURCE_LIST}
)
endif()
120 changes: 120 additions & 0 deletions conanfile.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
# Copyright 2024 Khalil Estell
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from conan import ConanFile
from conan.tools.cmake import CMake, CMakeDeps, CMakeToolchain, cmake_layout
from conan.tools.files import copy
from conan.tools.build import check_min_cppstd
from conan.errors import ConanInvalidConfiguration
import os

required_conan_version = ">=2.0.14"


class libhal_exceptions_conan(ConanFile):
name = "libhal-exceptions"
license = "Apache-2.0"
url = "https://github.com/conan-io/conan-center-index"
homepage = "https://github.com/libhal/libhal-exceptions"
description = (
"Exception handling runtime support for the libhal ecosystem.")
topics = ("exceptions", "error", "terminate", "unexpected")
settings = "compiler", "build_type", "os", "arch"
generators = "CMakeDeps", "CMakeToolchain", "VirtualBuildEnv"
exports_sources = ("include/*", "tests/*", "LICENSE",
"CMakeLists.txt", "src/*")
options = {
"default_allocator": [True, False],
"runtime": [
"builtin",
"estell",
]
}
default_options = {
"default_allocator": True,
"runtime": "builtin",
}

@property
def _min_cppstd(self):
return "20"

@property
def _compilers_minimum_version(self):
return {
"gcc": "11",
"clang": "14",
}

@property
def _is_arm_cortex(self):
return str(self.settings.arch).startswith("cortex-")

@property
def _runtime_select(self):
if self._is_arm_cortex() and self.options.runtime == "builtin":
return "ARM_CORTEX_GCC"
elif self._is_arm_cortex() and self.options.runtime == "estell":
return "ARM_CORTEX_ESTELL"

def validate(self):
if self.settings.get_safe("compiler.cppstd"):
check_min_cppstd(self, self._min_cppstd)

# Remove this when Estell impl is ready for beta testing
if self.options.runtime != "builtin":
raise ConanInvalidConfiguration(
"Only the 'builtin' exception runtime is supported currently")

def layout(self):
cmake_layout(self)

def build_requirements(self):
self.tool_requires("cmake/3.27.1")
self.tool_requires("libhal-cmake-util/[^4.0.3]")
self.test_requires("boost-ext-ut/1.1.9")

def build(self):
cmake = CMake(self)
cmake.configure(variables={"RUNTIME": "ARM_CORTEX_GCC"})
cmake.build()

def package(self):
copy(self,
"LICENSE",
dst=os.path.join(self.package_folder, "licenses"),
src=self.source_folder)
copy(self,
"*.h",
dst=os.path.join(self.package_folder, "include"),
src=os.path.join(self.source_folder, "include"))
copy(self,
"*.hpp",
dst=os.path.join(self.package_folder, "include"),
src=os.path.join(self.source_folder, "include"))

cmake = CMake(self)
cmake.install()

def package_info(self):
self.cpp_info.libs = ["libhal-exceptions"]
self.cpp_info.set_property("cmake_target_name", "libhal::exceptions")

# Keep this for now, will update this for the runtime select
if self._is_arm_cortex:
self.cpp_info.exelinkflags = [
"-Wl,--wrap=__cxa_allocate_exception",
"-Wl,--wrap=__cxa_free_exception",
"-Wl,--wrap=__cxa_call_unexpected",
]
1 change: 0 additions & 1 deletion include/exceptions.hpp

This file was deleted.

119 changes: 119 additions & 0 deletions include/libhal-exceptions/control.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// Copyright 2024 Khalil Estell
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#pragma once

#include <cstddef>
#include <cstdint>
#include <exception>
#include <span>

namespace hal {
/**
* @brief Interface for an object that allocates memory specifically for
* exceptions
*
*/
class exception_allocator
{
public:
/**
* @brief Allocate/retrieve memory for the exception object allocation
*
* If memory has run out, this function must return an empty span.
*
* @param p_size - Amount of memory to be allocated
* @return std::span<std::uint8_t> - block of memory equal to or greater than
* the size of p_size or and empty span if no memory is available.
*/
std::span<std::uint8_t> allocate(std::size_t p_size) noexcept
{
return do_allocate(p_size);
}

/**
* @brief Deallocate the memory for the exception object
*
* @param p_exception_object - pointer to the allocated exception object
*/
void deallocate(void* p_exception_object) noexcept
{
do_deallocate(p_exception_object);
}

virtual ~exception_allocator() = default;

private:
virtual std::span<std::uint8_t> do_allocate(std::size_t p_size) noexcept = 0;
virtual void do_deallocate(void* p_exception_object) noexcept = 0;
};

/**
* @brief Set the global exception allocator function
*
* More details on how you should use this API to come in the future.
*
* @param p_allocator - exception memory allocator implementation
*/
void set_exception_allocator(exception_allocator& p_allocator) noexcept;

/**
* @brief Set the terminate handler
*
* @param p_terminate_handler - new global terminate handler
*/
std::terminate_handler set_terminate(
std::terminate_handler p_terminate_handler) noexcept;

/**
* @brief Get the terminate handler
*
* @return std::terminate_handler - the currently set terminate handler
*/
std::terminate_handler get_terminate() noexcept;

/**
* @brief Simple single threaded exception allocator
*
* @tparam size - size of the exception object memory buffer. If this is set too
* small (less than 128 bytes), then it is likely that the memory will not be
* enough for any exception runtime and will result in terminate being called.
*/
template<size_t size>
class single_thread_exception_allocator : public exception_allocator
{
public:
single_thread_exception_allocator() = default;
~single_thread_exception_allocator() override = default;

private:
std::span<std::uint8_t> do_allocate(std::size_t p_size) noexcept override
{
if (m_allocated || p_size > m_buffer.size()) {
return {};
}
m_allocated = true;
return m_buffer;
}

void do_deallocate(
[[maybe_unused]] void* p_exception_object) noexcept override
{
m_allocated = false;
}

std::array<std::uint8_t, size> m_buffer{};
bool m_allocated = false;
};
} // namespace hal
Loading