/* * Project: EFC_Application * * FILE main.cpp * */ #include #include #include #include #include /* -------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include #include /* -------------------------------------------------------------------------- */ #include #include #include #include #include #include #include #include // TODO Перенести в setup #include #include #include #include #include #include #include #include #include #include #include "Motor/Motor.h" /* -------------------------------------------------------------------------- */ #ifdef CPU1 #include "autoconfig_cpu1.hh" #else #include "autoconfig_cpu2.hh" #endif #include "autoadd.hh" /* -------------------------------------------------------------------------- */ #ifdef CPU1 #include "Platform/core/boot/CmBoot.hpp" #include "Platform/core/boot/Cpu2Boot.hpp" platform::core::CmBoot::Action handleCmBoot(platform::core::CmBoot::Status status, void* param); platform::core::Cpu2Boot::Action handleCpu2Boot(platform::core::Cpu2Boot::Status status, void* param); #endif // CPU1 /* -------------------------------------------------------------------------- */ platform::memory::RtosMemoryResource rtos_heap_mr( (HeapRegion) { RTOS_HEAP0_START, RTOS_HEAP0_SIZE } ); platform::memory::StaticMemoryResource app_ls_heap_mr( (HeapRegion) { APP_HEAP0_START, APP_HEAP0_SIZE } ); platform::memory::StaticMemoryResource app_gs_heap_mr( (HeapRegion) { APP_HEAP1_START, APP_HEAP1_SIZE } ); /* -------------------------------------------------------------------------- */ static platform::rtos::InitTask init_task; static platform::rtos::MainTask main_task; /* -------------------------------------------------------------------------- */ static void app_builder_teardown() { platform::application::config::ParamStorage::drop(); platform::application::info::AppInfo::drop(); platform::application::info::DeviceInfo::drop(); // platform::driver::Ipc::lock(); } /* * Инициализация ВСЕГО */ void platform::rtos::InitTask::process(void* param) { std::srand(xTaskGetTickCount()); { InitMotor(); ///< FIXME: инициализация от Секлюцкого } /* Чтение и разбор конфигурации */ { using namespace platform::application; /* Таблицы инициализаторов конфигурации */ { const bool app_info_init = info::AppInfo::init(rtos_heap_mr, PROJECT_CAP_APP_INFO_RECORDS); if (!app_info_init) std::abort(); const bool dev_info_init = info::DeviceInfo::init(rtos_heap_mr, PROJECT_CAP_DEVICE_INFO_RECORDS); if (!dev_info_init) std::abort(); } /* Получение и распаковка таблицы параметров конфигурации */ { /* // TODO Аппаратный доступ к хранилищу настроек IMemoryAccess auto param_storage_init = config::ParamStorage::init(config_file, sram_heap_mr); if (param_storage_init.isErr()) std::abort(); auto& param_storage = *param_storage_init.unwrap(); auto param_unpack_init = config::ParamUnpack(param_storage, info::AppInfo(), info::DeviceInfo()).unpack(); if (param_unpack_init.isErr()) std::abort(); */ } } /** Создание окружения времени выполнения */ configuration::Environment* environment = nullptr; { using namespace platform::application; using namespace configuration; /** Параметры платформы */ const EnvironmentCapacity env_capacity = { .signals_capacity = PROJECT_NUM_SIGNALS, .statuses_capacity = PROJECT_NUM_STATUSES, .resources_capacity = PROJECT_NUM_OBJECTS, .num_of_param_providers = PROJECT_NUM_PARPROVIDERS, .num_of_scheduler = PROJECT_NUM_PROCSCHEDULERS, }; /** Ресурсы памяти */ std::pmr::memory_resource& object_mr = app_gs_heap_mr; std::pmr::memory_resource& data_mr = app_gs_heap_mr; std::pmr::memory_resource& setup_mr = app_ls_heap_mr; /** Обработчик ошибок */ static char exc_data_buffer[PROJECT_EXCEPTION_DATA_BUFFER_SIZE]; systemic::ExceptionHandler exception_handler(exc_data_buffer, sizeof(exc_data_buffer)); /** Глобальный объект окружения */ Result< Environment*, setup::EnvironmentError > environment_setup = setup::Environmnet( app_gs_heap_mr, /* env_mr */ app_gs_heap_mr, /* table_mr */ app_gs_heap_mr, /* local_mr */ object_mr, data_mr, setup_mr, systemic::ResourceHolder::getDefault(), systemic::ValueManager::getDefault(), systemic::ValueManager::getDefault(), exception_handler, env_capacity ); environment = environment_setup.unwrap(); environment->platform_info = &setup::StatusHerald::platformInfo; } /** Инстанцирование базовых ресурсов */ { using namespace platform::application; /** Планировщик приложения */ { typedef systemic::Scheduler< PROJECT_APP_SCHEDULER_ID > AppProcessor; configuration::addProcessor< AppProcessor >( 1. / (float) PROJECT_APP_SCHEDULER_FREQ, PROJECT_APP_SCHEDULER_NUM_PROCESS, *environment, app_ls_heap_mr, app_ls_heap_mr ); } /** Межпроцессорное взаимодействие */ { platform::driver::Ipc::init(); } /** Сервисный обмен */ { Result< void, setup::ServiceError > service_setup = setup::Service(app_ls_heap_mr); if (service_setup.isErr()) std::abort(); } } /** Сборка платформенных инициализаторов */ { using namespace platform::application; using namespace configuration::software; /* Создание фабрики инициализаторов */ Result< periph::PeriphConfigurator*, setup::PeriphConfiguratorError > configurator_setup = setup::PeriphConfigurator( app_ls_heap_mr, app_ls_heap_mr, ::platform::application::periph::periph_initializer_list_size ); periph::PeriphConfigurator& configurator = *configurator_setup.unwrap(); /* Регистрация инициализаторов */ ::platform::application::periph::add(configurator); /* Сборка инициализаторов */ info::DeviceInfo::Initializers initializers = info::DeviceInfo::getInitializers(); info::DeviceInfo::InitializerIterator initializer_iter = initializers.begin(); for (; initializer_iter != initializers.end(); ++initializer_iter) { info::DeviceInfo::InitializerInfo initializer_info = *initializer_iter; if (!configurator.build(initializer_info, *environment)) std::abort(); } } /* Сборка библиотечных инициализаторов */ { using namespace platform::application; using namespace configuration::software; /* Создание фабрики инициализаторов */ Result< ApplicationConfigurator*, setup::AppConfiguratorError > configurator_setup = setup::AppConfigurator( app_ls_heap_mr, app_ls_heap_mr, ::application::info::application_initializer_list_size ); ApplicationConfigurator& configurator = *configurator_setup.unwrap(); /* Создание процедуры сборки инициализаторов */ const size_t build_items_num = info::AppInfo::getInitializers().getSize(); Result< AppBuilder*, setup::AppBuilderError > app_builder_setup = setup::AppBuilder( app_ls_heap_mr, build_items_num, *environment, PROJECT_APP_SCHEDULER_ID, app_builder_teardown ); AppBuilder& app_builder = *app_builder_setup.unwrap(); /* Регистрация инициализаторов */ ::application::autoadd(configurator); /* Добавление инициализаторов в список сборки */ info::AppInfo::Initializers initializers = info::AppInfo::getInitializers(); info::AppInfo::InitializerIterator initializer_iter = initializers.begin(); for (; initializer_iter != initializers.end(); ++initializer_iter) { CreateToBuilder(configurator, app_builder)(*initializer_iter); } } #ifdef CPU1 platform::core::Cpu2Boot::boot(handleCpu2Boot, NULL); platform::core::CmBoot::boot(handleCmBoot, NULL); #endif // CPU1 /* Запуск основного потока */ main_task.handle = xTaskCreateStatic( main_task.func, main_task.name, main_task.depth, NULL, main_task.prio, main_task.stack, &main_task.desc ); if (main_task.handle == nullptr) std::abort(); vTaskDelete(nullptr); } void platform::rtos::MainTask::process(void* param) { for (;;) { TickType_t timestamp = xTaskGetTickCount(); try { systemic::Scheduler< PROJECT_APP_SCHEDULER_ID >::runOnce(); } catch(std::exception& e) { } vTaskDelayUntil(×tamp, pdMS_TO_TICKS(1)); } } std::pmr::memory_resource* default_mr = &app_ls_heap_mr; /* * * Main * */ int main(void) { if (!platform::core::init()) std::abort(); const BaseType_t init_task_status = xTaskCreate( init_task.func, init_task.name, init_task.depth, NULL, init_task.prio, &init_task.handle ); if (init_task_status != pdPASS) std::abort(); vTaskStartScheduler(); return 0; } #ifdef CPU1 platform::core::Cpu2Boot::Action handleCpu2Boot(platform::core::Cpu2Boot::Status status, void* param) { using namespace platform::core; return (status == Cpu2Boot::StatusOk) ? Cpu2Boot::ActionNone : Cpu2Boot::ActionResetDevice; } platform::core::CmBoot::Action handleCmBoot(platform::core::CmBoot::Status status, void* param) { using namespace platform::core; return (status == platform::core::CmBoot::StatusOk) ? CmBoot::ActionNone : CmBoot::ActionResetDevice; } #endif // CPU1