ETLCPP / etl

Embedded Template Library
https://www.etlcpp.com
MIT License
2.05k stars 373 forks source link

Possible to provide my own ETL_ASSERT? #794

Closed basprins closed 7 months ago

basprins commented 7 months ago

Hi, I recently provided the ETL_CHECK_PUSH_POP definition as compiler argument, so that I get direct feedback when I encounter a bug where some container is pushing outside its bounds.

This works perfectly, but.... I am running on a microcontroller, which runs FreeRTOS, and has a watchdog enabled. What I typically do in case of hard errors is assert a certain state in my own macro (project_assert). This macro will:

So what I need, is a way to define the ETL_ASSERT in my code, so that I can hook it up to my project_assert. Looking at the error_handler.h there is no way to do this, because every branch in the #if #elseif #else creates the macro.

I will just "hack" it in by removing the default provided empty ETL_ASSERT macro's, and provide my own instead. But something tells me I am not the only one that requires this, so I probably just overlooked the obvious already existing solution to achieve the same :).

Could you guide me a bit here?

Thx

jwellbelove commented 7 months ago

You could use the 'log' configuration of the ETL_ASSERT and get the error handler to send the ETL exception to your handler. There you can 1) write error code to flash 2) disable all interrupts (which effectively results in the watchdog thread never executing again) 3) enter an endless loop, and wait for the watchdog to reset the CPU

Simplified code

#define ETL_LOG_ERRORS

#include "etl/error_handler.h"

//*****************************************************************************
struct ErrorLog
{
    void Log(const etl::exception& e)
    {
        WriteErrorCodeToFlash(e);
        DisableAllInterrupts();
        EnterEndlessLoop();
    }
};

//*****************************************************************************
int main()
{
  static ErrorLog errorLog;

  etl::error_handler::set_callback<ErrorLog, errorLog, &ErrorLog::Log>();

  StartApplication();
}
basprins commented 7 months ago

Life save! Thank you very much, was completely looking in the wrong places!!

jwellbelove commented 7 months ago

BTW, the handler doesn't have to be a class member function. It can also be a standard global or static function.

void Log(const etl::exception& e)
{
  WriteErrorCodeToFlash(e)
  DisableAllInterrupts();
  EnterEndlessLoop();
}

etl::error_handler::set_callback<Log>();
basprins commented 7 months ago

That was exactly what i did :)