2022-01-30 00:51:47 +01:00
#include "sdkconfig.h"
// esp-idf includes
2022-01-29 23:39:56 +01:00
#include <esp_log.h>
2022-01-30 00:51:47 +01:00
#include <freertos/FreeRTOS.h>
#if defined(CONFIG_ESP_TASK_WDT_PANIC) || defined(CONFIG_ESP_TASK_WDT)
#include <freertos/task.h>
#include <esp_task_wdt.h>
#endif
#ifdef CONFIG_APP_ROLLBACK_ENABLE
#include <esp_ota_ops.h>
#endif
#include <esp_heap_caps.h>
// Arduino includes
#include <esp32-hal-gpio.h>
// 3rdparty lib includes
#include <schedulertask.h>
#include <espchrono.h>
#include <espasyncota.h>
#include <espstrutils.h>
#include <esprandom.h>
#include <strutils.h>
// local includes
#include "config.h"
#include "debugconsole.h"
#include "taskmanager.h"
#include "ota.h"
#include "wifi.h"
using namespace std :: chrono_literals ;
2022-01-29 23:39:56 +01:00
namespace {
constexpr const char * const TAG = "MAIN" ;
2022-01-30 00:51:47 +01:00
espchrono :: millis_clock :: time_point lastLoopCount ;
int _loopCount {};
int loopCountTemp {};
2022-01-29 23:39:56 +01:00
} // namespace
2022-01-30 00:51:47 +01:00
const int & loopCount { _loopCount };
2022-01-29 23:39:56 +01:00
extern "C" void app_main ()
{
2022-01-30 00:51:47 +01:00
#if defined(CONFIG_ESP_TASK_WDT_PANIC) || defined(CONFIG_ESP_TASK_WDT)
{
const auto taskHandle = xTaskGetCurrentTaskHandle ();
if ( ! taskHandle )
{
ESP_LOGE ( TAG , "could not get handle to current main task!" );
}
else if ( const auto result = esp_task_wdt_add ( taskHandle ); result != ESP_OK )
{
ESP_LOGE ( TAG , "could not add main task to watchdog: %s" , esp_err_to_name ( result ));
}
}
bool wasPreviouslyUpdating {};
#endif
#ifdef CONFIG_APP_ROLLBACK_ENABLE
esp_ota_img_states_t ota_state ;
if ( const esp_partition_t * const running = esp_ota_get_running_partition ())
{
if ( const auto result = esp_ota_get_state_partition ( running , & ota_state ); result == ESP_ERR_NOT_FOUND )
ota_state = ESP_OTA_IMG_VALID ;
else if ( result != ESP_OK )
{
ESP_LOGE ( TAG , "esp_ota_get_state_partition() failed with %s" , esp_err_to_name ( result ));
ota_state = ESP_OTA_IMG_UNDEFINED ;
}
}
else
{
ESP_LOGE ( TAG , "esp_ota_get_running_partition() returned nullptr" );
ota_state = ESP_OTA_IMG_UNDEFINED ;
}
#endif
//init proper ref tick value for PLL (uncomment if REF_TICK is different than 1MHz)
//ESP_REG(APB_CTRL_PLL_TICK_CONF_REG) = APB_CLK_FREQ / REF_CLK_FREQ - 1;
pinMode ( 3 , INPUT_PULLUP );
if ( const auto result = configs . init ( "dmxnode" ); result != ESP_OK )
ESP_LOGE ( TAG , "config_init_settings() failed with %s" , esp_err_to_name ( result ));
for ( const auto & task : schedulerTasks )
task . setup ();
while ( true )
{
bool pushStats = espchrono :: ago ( lastLoopCount ) >= 1 s ;
if ( pushStats )
{
lastLoopCount = espchrono :: millis_clock :: now ();
_loopCount = loopCountTemp ;
loopCountTemp = 0 ;
}
loopCountTemp ++ ;
for ( auto & task : schedulerTasks )
{
task . loop ();
#if defined(CONFIG_ESP_TASK_WDT_PANIC) || defined(CONFIG_ESP_TASK_WDT)
if ( wasPreviouslyUpdating )
{
if ( const auto result = esp_task_wdt_reset (); result != ESP_OK )
ESP_LOGE ( TAG , "esp_task_wdt_reset() failed with %s" , esp_err_to_name ( result ));
//vPortYield();
vTaskDelay ( 1 );
}
#endif
}
if ( pushStats )
{
sched_pushStats ( memoryDebug == Fast );
}
if constexpr ( LOG_LOCAL_LEVEL >= ESP_LOG_WARN )
{
const auto free8 = heap_caps_get_free_size ( MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT );
if ( free8 < 25000 )
{
lastMemoryDebug = espchrono :: millis_clock :: now ();
ESP_LOGW ( TAG , "MEMORY heap8=%zd (largest block: %zd) heap32=%zd lps=%i" ,
free8 ,
heap_caps_get_largest_free_block ( MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT ),
heap_caps_get_free_size ( MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT ),
_loopCount
);
}
else if constexpr ( LOG_LOCAL_LEVEL >= ESP_LOG_INFO )
{
if ( memoryDebug != Off &&
espchrono :: ago ( lastMemoryDebug ) >= ( memoryDebug == Fast ? 100 ms : 1000 ms ))
{
lastMemoryDebug = espchrono :: millis_clock :: now ();
ESP_LOGI ( TAG , "MEMORY heap8=%zd (largest block: %zd) heap32=%zd lps=%i" ,
free8 ,
heap_caps_get_largest_free_block ( MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT ),
heap_caps_get_free_size ( MALLOC_CAP_INTERNAL | MALLOC_CAP_32BIT ),
_loopCount
);
}
}
}
#if defined(CONFIG_ESP_TASK_WDT_PANIC) || defined(CONFIG_ESP_TASK_WDT)
if ( const auto result = esp_task_wdt_reset (); result != ESP_OK )
ESP_LOGE ( TAG , "esp_task_wdt_reset() failed with %s" , esp_err_to_name ( result ));
if ( const auto isUpdating = otaClient . status () == OtaCloudUpdateStatus :: Updating ; isUpdating != wasPreviouslyUpdating )
{
wasPreviouslyUpdating = isUpdating ;
constexpr bool panic =
#ifdef CONFIG_ESP_TASK_WDT_PANIC
true
#else
false
#endif
;
const uint32_t timeout = isUpdating ?
CONFIG_ESP_TASK_WDT_TIMEOUT_S * 4 :
CONFIG_ESP_TASK_WDT_TIMEOUT_S ;
const auto result = esp_task_wdt_init ( CONFIG_ESP_TASK_WDT_TIMEOUT_S , panic );
ESP_LOG_LEVEL_LOCAL (( result == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR ), TAG , "esp_task_wdt_init() with new timeout %u returned: %s" , timeout , esp_err_to_name ( result ));
}
#endif
#ifdef CONFIG_APP_ROLLBACK_ENABLE
if ( ota_state == ESP_OTA_IMG_PENDING_VERIFY )
{
const auto result = esp_ota_mark_app_valid_cancel_rollback ();
ESP_LOG_LEVEL_LOCAL (( result == ESP_OK ? ESP_LOG_INFO : ESP_LOG_ERROR ), TAG , "esp_ota_mark_app_valid_cancel_rollback() returned: %s" , esp_err_to_name ( result ));
ota_state = ESP_OTA_IMG_VALID ;
}
#endif
//vPortYield();
vTaskDelay ( 1 );
}
2022-01-29 23:39:56 +01:00
}