General
In the deep-embedded field isolating and understanding errors can be a big pain – less breakpoints and complex hardware drivers can lead to frustration. To help developers out in this field semf delivers a staightforward solution for error tracking which is optimized for low ROM and RAM.
Features
- Fast error isolation
- Functional safety compatible
- Easy expandability
- Advanced error tracking in combination with the FlashLogger
Functionality
To isolate an error fast an semf::Error is uniquely defined by a class ID
and a class specific ErrorCode
. The unique class ID can be found in the error.h file.
enum ClassID : uint32_t
{
SectionHardwareBegin = 0x08000000,
SectionAnaloginBegin,
Stm32AnalogIn,
SectionHardwareEnd = 0x0FFFFFFF,
SectionUserBegin = 0x10000000,
SectionUserEnd = 0xFFFFFFFF
}
The class spesific ErrorCodes
are listed in each specific class. For example in the Logger class where classes have a generic error signal
.
class Logger
{
enum class ErrorCode : uint8_t
{
AddEntry_IsBusy = 0,
AddEntry_PayloadIsNullptr,
AddEntry_NotInitialized,
};
Signal<Error> error;
In the implementation for every error case an Error object will be emitted by the error signal.
bool Logger::addEntry(Entry& entry)
{
if (m_busy)
{
onError(Error(kSemfClassId, static_cast(ErrorCode::AddEntry_IsBusy)));
return false;
}
}
To catch all error signals it is recomended to have an onError slot in the application and connect the error signals as shown in the user code example below.
User Application Example
To use the semf error handling functionality in an user application the following steps are recommended.
Add a file where all application components / classes are listed. semf has a predefined begin and end value for the unique class IDs.
#include <cstdio>
enum class UserClasses : uint32_t
{
Begin = static_cast(semf::Error::ClassID::SectionUserBegin),
Component0_Begin,
Component0_Class0,
Component0_Class1,
Component0_Class2,
Component0_End,
End = semf::Error::ClassID::SectionUserEnd
};
Create components which have their own ErrorCodes
, classId
and error signal
class Class0
{
public:
enum class ErrorCode : uint8_t
{
Foo_InvalidParameter = 0
};
void foo(void* param)
{
if (param == nullptr)
{
error(
semf::Error(
static_cast<uint32_t
>(kClassId),
static_cast<uint8_t
>(ErrorCode::Foo_InvalidParameter)));
}
}
private:
static constexpr ClassId kClassId = Component0_Class0;
};
Class for representing errors. Every error should have a unique source code. As a user feel encourage...
Connect the error signals
to an onError slot
in the application where the error signals will be processed.
class Application
{
public:
void init()
{
m_obj.error.clear()
m_obj.error.connect(this, &Application::onError);
m_obj.foo(nullptr);
}
private:
{
}
Component0_Class0 m_obj;
};
uint8_t errorCode() const
Returns the error code from the error.
uint32_t classId() const
Returns the class id from the error.
#define SEMF_SLOT(name, className, object, function,...)
Creates a semf slot.