MotorControlModuleSDFM_TMS3.../Projects/EFC_Application/main.cpp

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(&timestamp, 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