391 lines
12 KiB
C++
391 lines
12 KiB
C++
/*
|
|
* Project: EFC_Application
|
|
*
|
|
* FILE main.cpp
|
|
*
|
|
*/
|
|
#include <stdlib.h>
|
|
#include <stddef.h>
|
|
#include <stdint.h>
|
|
|
|
#include <FreeRTOS.h>
|
|
#include <task.h>
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
|
|
#include <UMLibrary/common/Result.hh>
|
|
|
|
#include <UMLibrary/configuration/AddProcessor.hpp>
|
|
#include <UMLibrary/configuration/software/AppBuilder.hh>
|
|
#include <UMLibrary/configuration/software/AppInfo.hh>
|
|
#include <UMLibrary/configuration/software/ApplicationConfigurator.hh>
|
|
#include <UMLibrary/configuration/software/CreateToBuilder.hpp>
|
|
|
|
#include <UMLibrary/systemic/ValueManager.hpp>
|
|
#include <UMLibrary/systemic/SystemException.hh>
|
|
#include <UMLibrary/systemic/Scheduler.hpp>
|
|
|
|
/* -------------------------------------------------------------------------- */
|
|
#include <Platform/Config.h>
|
|
|
|
#include <Platform/core/init/init.hpp>
|
|
|
|
#include <Platform/memory/MemoryRegions.hpp>
|
|
#include <Platform/memory/RtosMemoryResource.hpp>
|
|
#include <Platform/memory/StaticMemoryResource.hpp>
|
|
|
|
#include <Platform/rtos/task/InitTask.hpp>
|
|
#include <Platform/rtos/task/MainTask.hpp>
|
|
|
|
#include <Platform/driver/ipc/Ipc.hpp> // TODO Перенести в setup
|
|
|
|
#include <Platform/application/config/ParamStorage.hpp>
|
|
#include <Platform/application/config/ParamUnpack.hpp>
|
|
#include <Platform/application/info/AppInfo.hpp>
|
|
#include <Platform/application/info/DeviceInfo.hpp>
|
|
#include <Platform/application/setup/AppConfigurator.hpp>
|
|
#include <Platform/application/setup/Environment.hpp>
|
|
#include <Platform/application/setup/PeriphConfigurator.hpp>
|
|
#include <Platform/application/setup/StatusHerald.hpp>
|
|
#include <Platform/application/setup/Service.hpp>
|
|
#include <Platform/application/setup/AppBuilder.hpp>
|
|
|
|
#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<bool>::getDefault(),
|
|
systemic::ValueManager<float>::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
|