diff --git a/tools/projmgr/include/ProjMgrParser.h b/tools/projmgr/include/ProjMgrParser.h index 3758a6473..3c6dbef59 100644 --- a/tools/projmgr/include/ProjMgrParser.h +++ b/tools/projmgr/include/ProjMgrParser.h @@ -209,6 +209,7 @@ struct TargetSetItem { * misc compiler controls, * platform processor * context map + * west defines */ struct BuildType { std::string compiler; @@ -228,6 +229,7 @@ struct BuildType { ProcessorItem processor; std::vector> variables; std::vector contextMap; + std::vector westDefs; }; /** @@ -452,6 +454,18 @@ struct GroupNode { TypeFilter type; }; +/** + * @brief west descriptor +*/ +struct WestDesc { + std::string projectId; + std::string app; + std::string board; + std::string device; + std::vector westDefs; + std::vector westOpt; +}; + /** * @brief context descriptor containing * cproject filename, @@ -460,6 +474,7 @@ struct GroupNode { struct ContextDesc { std::string cproject; TypeFilter type; + WestDesc west; }; /** @@ -506,6 +521,7 @@ typedef std::vector> TargetTypes; * target types, * target properties, * list of cprojects, + * list of west apps, * list of contexts descriptors, * list of packs, * cdefault enable switch, @@ -524,6 +540,7 @@ struct CsolutionItem { TargetTypes targetTypes; TargetType target; std::vector cprojects; + std::vector westApps; std::vector contexts; std::vector packs; bool enableCdefault; diff --git a/tools/projmgr/include/ProjMgrUtils.h b/tools/projmgr/include/ProjMgrUtils.h index 120d7de4f..de430adc1 100644 --- a/tools/projmgr/include/ProjMgrUtils.h +++ b/tools/projmgr/include/ProjMgrUtils.h @@ -321,6 +321,13 @@ class ProjMgrUtils { */ static const std::string NormalizeLineEndings(const std::string& in); + /** + * @brief convert board string to west board string + * @param board string + * @return output west board string + */ + static const std::string GetWestBoard(const std::string& board); + protected: /** * @brief get filtered list of contexts diff --git a/tools/projmgr/include/ProjMgrWorker.h b/tools/projmgr/include/ProjMgrWorker.h index 19939df8c..a2d9c9a75 100644 --- a/tools/projmgr/include/ProjMgrWorker.h +++ b/tools/projmgr/include/ProjMgrWorker.h @@ -429,6 +429,8 @@ struct DebuggerType { * load offset for generated binary * elf load mode * image only flag + * west options + * west on flag */ struct ContextItem { CdefaultItem* cdefault = nullptr; @@ -498,6 +500,8 @@ struct ContextItem { std::string loadOffset; std::string elfLoadMode; bool imageOnly = false; + WestDesc west; + bool westOn = false; }; /** @@ -509,6 +513,11 @@ static constexpr const char* PLM_STATUS_UPDATE_REQUIRED = "update required"; static constexpr const char* PLM_STATUS_UPDATE_RECOMMENDED = "update recommended"; static constexpr const char* PLM_STATUS_UPDATE_SUGGESTED = "update suggested"; +/** + * @brief west board variable +*/ +static constexpr const char* WEST_BOARD = "west-board"; + /** * @brief set policy for packs loading [latest|all|required] */ diff --git a/tools/projmgr/include/ProjMgrYamlParser.h b/tools/projmgr/include/ProjMgrYamlParser.h index 38f0a739e..e19d62207 100644 --- a/tools/projmgr/include/ProjMgrYamlParser.h +++ b/tools/projmgr/include/ProjMgrYamlParser.h @@ -27,6 +27,7 @@ static constexpr const char* YAML_ARGUMENTS = "arguments"; static constexpr const char* YAML_APID = "apid"; static constexpr const char* YAML_APIS = "apis"; static constexpr const char* YAML_API = "api"; +static constexpr const char* YAML_APP_PATH = "app-path"; static constexpr const char* YAML_ATOMIC = "atomic"; static constexpr const char* YAML_ATTR = "attr"; static constexpr const char* YAML_AUTO = "auto"; @@ -189,6 +190,7 @@ static constexpr const char* YAML_PROCESSORS = "processors"; static constexpr const char* YAML_PROCESSOR = "processor"; static constexpr const char* YAML_PROGRAMMING = "programming"; static constexpr const char* YAML_PROJECT = "project"; +static constexpr const char* YAML_PROJECT_ID = "project-id"; static constexpr const char* YAML_PROJECTS = "projects"; static constexpr const char* YAML_PROJECT_CONTEXT = "project-context"; static constexpr const char* YAML_PROJECT_TYPE = "project-type"; @@ -243,6 +245,9 @@ static constexpr const char* YAML_VARS = "vars"; static constexpr const char* YAML_VALUE = "value"; static constexpr const char* YAML_VERSION = "version"; static constexpr const char* YAML_WARNINGS = "warnings"; +static constexpr const char* YAML_WEST = "west"; +static constexpr const char* YAML_WEST_DEFS = "west-defs"; +static constexpr const char* YAML_WEST_OPT = "west-opt"; static constexpr const char* YAML_WHILE = "while"; static constexpr const char* YAML_WORKING_DIR = "working-dir"; diff --git a/tools/projmgr/schemas/common.schema.json b/tools/projmgr/schemas/common.schema.json index dd42038b7..b3825f787 100644 --- a/tools/projmgr/schemas/common.schema.json +++ b/tools/projmgr/schemas/common.schema.json @@ -406,6 +406,9 @@ }, { "type": "number" + }, + { + "type": "boolean" } ] } @@ -601,7 +604,8 @@ "target-set": { "$ref": "#/definitions/TargetSetsType" }, "undefine": { "$ref": "#/definitions/UndefinesType" }, "variables": { "$ref": "#/definitions/VariablesType" }, - "warnings": { "$ref": "#/definitions/WarningsType" } + "warnings": { "$ref": "#/definitions/WarningsType" }, + "west-defs": { "$ref": "#/definitions/DefinesType" } }, "additionalProperties": false, "required" : [ "type"] @@ -638,7 +642,8 @@ "processor": { "$ref": "#/definitions/ProcessorType" }, "undefine": { "$ref": "#/definitions/UndefinesType" }, "variables": { "$ref": "#/definitions/VariablesType" }, - "warnings": { "$ref": "#/definitions/WarningsType" } + "warnings": { "$ref": "#/definitions/WarningsType" }, + "west-defs": { "$ref": "#/definitions/DefinesType" } }, "additionalProperties": false, "required" : [ "type"] @@ -660,13 +665,13 @@ "pattern": "^.*[/]([^.+]*\\.cproject\\.(yml|yaml))$|^([^.+]+)\\.cproject\\.(yml|yaml)$", "description": "Path to the valid project file." }, + "west": { "$ref": "#/definitions/WestProjectType" }, "for-context": { "$ref": "#/definitions/ForContext" }, "not-for-context": { "$ref": "#/definitions/NotForContext" } }, "additionalProperties": false, - "allOf": [ - { "$ref": "#/definitions/TypeListMutualExclusion"}, - { "required": [ "project" ] } + "oneOf": [ + { "$ref": "#/definitions/TypeListMutualExclusion"} ] }, "ProcessorTrustzone": { @@ -1274,6 +1279,7 @@ "type": "object", "properties": { "cbuild": { "type": "string", "description": "Path to .cbuild.yml file." }, + "west": { "type": "boolean" }, "project": { "type": "string", "description": "Project name." }, "configuration": { "$ref": "#/definitions/BuildContext" }, "depends-on": { @@ -1427,7 +1433,8 @@ "licenses": { "type": "array", "items": { "$ref": "#/definitions/LicenseInfoType" } - } + }, + "west": { "$ref": "#/definitions/WestProjectType" } }, "additionalProperties": false }, @@ -2398,6 +2405,21 @@ "title": "optimize:\nDocumentation: https://open-cmsis-pack.github.io/cmsis-toolbox/YML-Input-Format/#load", "description": "Specifies the load mode for the project output or image file.", "enum": [ "image+symbols", "symbols", "image", "none" ] + }, + "WestProjectType": { + "title": "west:", + "description": "Enable West build orchestration wrapper for Zephyr projects.", + "type": "object", + "properties": { + "app-path": { "type": "string", "description": "Path to the application source directory." }, + "project-id": { "type": "string", "description": "Project identifier (default: last sub-dir name of app-path)." }, + "board": { "type": "string", "description": "Board name used for west build invocation (default: variable $west-board$)."}, + "device": { "$ref": "#/definitions/ProcessorNameType" }, + "west-defs": { "$ref": "#/definitions/DefinesType" }, + "west-opts": { "type": "string", "description": "Options for the west tool (default: empty)." } + }, + "additionalProperties": false, + "required": ["app-path"] } } } diff --git a/tools/projmgr/src/ProjMgr.cpp b/tools/projmgr/src/ProjMgr.cpp index 4a985eaa6..ac726c814 100644 --- a/tools/projmgr/src/ProjMgr.cpp +++ b/tools/projmgr/src/ProjMgr.cpp @@ -487,7 +487,7 @@ bool ProjMgr::PopulateContexts(void) { } // Check cproject separate folders and unique names const StrVec& cprojects = m_parser.GetCsolution().cprojects; - if (!IsSolutionImageOnly() && cprojects.empty()) { + if (!IsSolutionImageOnly() && cprojects.empty() && m_parser.GetCsolution().westApps.empty()) { ProjMgrLogger::Get().Error("projects not found", "", m_csolutionFile); return false; } diff --git a/tools/projmgr/src/ProjMgrCbuild.cpp b/tools/projmgr/src/ProjMgrCbuild.cpp index 475669f8b..6b0c96594 100644 --- a/tools/projmgr/src/ProjMgrCbuild.cpp +++ b/tools/projmgr/src/ProjMgrCbuild.cpp @@ -40,6 +40,7 @@ class ProjMgrCbuild : public ProjMgrCbuildBase { void SetBooksNode(YAML::Node node, const std::vector& books, const std::string& dir); void SetDebugConfigNode(YAML::Node node, const ContextItem* context); void SetPLMStatus(YAML::Node node, const ContextItem* context, const string& file); + void SetWestNode(YAML::Node node, const ContextItem* context); bool m_ignoreRteFileMissing; }; @@ -85,11 +86,11 @@ void ProjMgrCbuild::SetContextNode(YAML::Node contextNode, const ContextItem* co } SetBooksNode(contextNode[YAML_DEVICE_BOOKS], context->deviceBooks, context->directories.cbuild); SetDebugConfigNode(contextNode[YAML_DBGCONF], context); - if (!context->imageOnly) { + if (!context->imageOnly && !context->westOn) { SetProcessorNode(contextNode[YAML_PROCESSOR], context->targetAttributes); } SetPacksNode(contextNode[YAML_PACKS], context); - if (!context->imageOnly) { + if (!context->imageOnly && !context->westOn) { SetControlsNode(contextNode, context, context->controls.processed); vector defines; if (context->rteActiveTarget != nullptr) { @@ -108,7 +109,14 @@ void ProjMgrCbuild::SetContextNode(YAML::Node contextNode, const ContextItem* co } } SetOutputDirsNode(contextNode[YAML_OUTPUTDIRS], context); - SetOutputNode(contextNode[YAML_OUTPUT], context); + } + if (context->westOn) { + string outDir = context->directories.outdir; + RteFsUtils::NormalizePath(outDir, context->directories.cprj); + SetNodeValue(contextNode[YAML_OUTPUTDIRS][YAML_OUTPUT_OUTDIR], FormatPath(outDir, context->directories.cbuild)); + } + SetOutputNode(contextNode[YAML_OUTPUT], context); + if (!context->imageOnly && !context->westOn) { SetComponentsNode(contextNode[YAML_COMPONENTS], context); SetApisNode(contextNode[YAML_APIS], context); SetGeneratorsNode(contextNode[YAML_GENERATORS], context); @@ -117,6 +125,9 @@ void ProjMgrCbuild::SetContextNode(YAML::Node contextNode, const ContextItem* co SetConstructedFilesNode(contextNode[YAML_CONSTRUCTEDFILES], context); } SetLicenseInfoNode(contextNode[YAML_LICENSES], context); + if (context->westOn) { + SetWestNode(contextNode[YAML_WEST], context); + } } void ProjMgrCbuild::SetComponentsNode(YAML::Node node, const ContextItem* context) { @@ -590,3 +601,12 @@ bool ProjMgrYamlEmitter::GenerateCbuild(ContextItem* context, context->needRebuild = NeedRebuild(filename, rootNode); return WriteFile(rootNode, filename, context->name); } + +void ProjMgrCbuild::SetWestNode(YAML::Node node, const ContextItem* context) { + SetNodeValue(node[YAML_PROJECT_ID], context->west.projectId); + SetNodeValue(node[YAML_APP_PATH], FormatPath(context->west.app, context->directories.cbuild)); + SetNodeValue(node[YAML_BOARD], context->west.board); + SetNodeValue(node[YAML_DEVICE], context->west.device); + SetDefineNode(node[YAML_WEST_DEFS], context->west.westDefs); + SetNodeValue(node[YAML_WEST_OPT], context->west.westOpt); +} diff --git a/tools/projmgr/src/ProjMgrCbuildIdx.cpp b/tools/projmgr/src/ProjMgrCbuildIdx.cpp index 16977fc88..5b0dc938e 100644 --- a/tools/projmgr/src/ProjMgrCbuildIdx.cpp +++ b/tools/projmgr/src/ProjMgrCbuildIdx.cpp @@ -33,7 +33,7 @@ ProjMgrCbuildIdx::ProjMgrCbuildIdx(YAML::Node node, if (!processedContexts.empty()) { const auto& context = processedContexts.front(); SetNodeValue(node[YAML_DESCRIPTION], context->csolution->description); - if (!parser->GetCdefault().path.empty() && !context->imageOnly) { + if (!parser->GetCdefault().path.empty() && !context->imageOnly && !context->westOn) { SetNodeValue(node[YAML_CDEFAULT], FormatPath(parser->GetCdefault().path, directory)); } } @@ -44,7 +44,14 @@ ProjMgrCbuildIdx::ProjMgrCbuildIdx(YAML::Node node, SetNodeValue(node[YAML_OUTPUT_TMPDIR], FormatPath(parser->GetCsolution().directories.tmpdir, directory)); // Image Only flag - if (!processedContexts.empty() && processedContexts.front()->imageOnly) { + bool imageOnlySolution = true; + for (const auto& processedContext : processedContexts) { + if (!processedContext->imageOnly) { + imageOnlySolution = false; + break; + } + } + if (imageOnlySolution) { node[YAML_IMAGE_ONLY] = true; } @@ -134,6 +141,9 @@ ProjMgrCbuildIdx::ProjMgrCbuildIdx(YAML::Node node, const string& filename = context->directories.cprj + "/" + context->name + ".cbuild.yml"; const string& relativeFilename = fs::relative(filename, directory, ec).generic_string(); SetNodeValue(cbuildNode[YAML_CBUILD], relativeFilename); + if (context->westOn) { + cbuildNode[YAML_WEST] = true; + } if (context->cproject) { if (!context->imageOnly) { SetNodeValue(cbuildNode[YAML_PROJECT], context->cproject->name); diff --git a/tools/projmgr/src/ProjMgrUtils.cpp b/tools/projmgr/src/ProjMgrUtils.cpp index 34db2469b..2ae6ad586 100644 --- a/tools/projmgr/src/ProjMgrUtils.cpp +++ b/tools/projmgr/src/ProjMgrUtils.cpp @@ -498,3 +498,11 @@ const std::string ProjMgrUtils::NormalizeLineEndings(const std::string& in) { } return out; } + +const std::string ProjMgrUtils::GetWestBoard(const std::string& board) { + string westBoard = RteUtils::StripSuffix(RteUtils::StripPrefix(board, "::")); + std::transform(westBoard.begin(), westBoard.end(), westBoard.begin(), + [](unsigned char c) { return std::tolower(c); }); + std::replace(westBoard.begin(), westBoard.end(), '-', '_'); + return westBoard; +} diff --git a/tools/projmgr/src/ProjMgrWorker.cpp b/tools/projmgr/src/ProjMgrWorker.cpp index dc66328af..0f5e21771 100644 --- a/tools/projmgr/src/ProjMgrWorker.cpp +++ b/tools/projmgr/src/ProjMgrWorker.cpp @@ -84,16 +84,31 @@ void ProjMgrWorker::AddImageOnlyContext() { } bool ProjMgrWorker::AddContexts(ProjMgrParser& parser, ContextDesc& descriptor, const string& cprojectFile) { - error_code ec; ContextItem context; - std::map& cprojects = parser.GetCprojects(); - if (cprojects.find(cprojectFile) == cprojects.end()) { - ProjMgrLogger::Get().Error("cproject not parsed, adding context failed", "", cprojectFile); - return false; - } - context.cproject = &cprojects.at(cprojectFile); context.cdefault = &parser.GetCdefault(); context.csolution = &parser.GetCsolution(); + std::map& cprojects = parser.GetCprojects(); + if (cprojects.find(cprojectFile) != cprojects.end()) { + context.cproject = &cprojects.at(cprojectFile); + } else { + if (descriptor.west.app.empty()) { + ProjMgrLogger::Get().Error("cproject not parsed, adding context failed", "", cprojectFile); + return false; + } else { + context.cproject = &cprojects[descriptor.west.projectId]; + } + } + + // west app + if (!descriptor.west.app.empty()) { + context.westOn = true; + context.west = descriptor.west; + RteFsUtils::NormalizePath(context.west.app, context.csolution->directory); + context.cproject->output.baseName = "zephyr/zephyr"; + context.cproject->name = context.west.projectId; + context.cproject->output.type = { "elf", "hex" }; + CollectionUtils::PushBackUniquely(context.west.westDefs, "CONFIG_BUILD_OUTPUT_HEX=y"); + } // No build/target-types if (context.csolution->buildTypes.empty() && context.csolution->targetTypes.empty()) { @@ -2204,7 +2219,7 @@ bool ProjMgrWorker::ProcessConfigFiles(ContextItem& context) { } } // Linker script - if (context.outputTypes.elf.on) { + if (context.outputTypes.elf.on && !context.imageOnly && !context.westOn) { if (context.linker.autoGen) { if (!context.linker.script.empty()) { ProjMgrLogger::Get().Warn("conflict: automatic linker script generation overrules specified script '" + context.linker.script + "'", context.name); @@ -2863,6 +2878,10 @@ bool ProjMgrWorker::ProcessPrecedences(ContextItem& context, BoardOrDevice proce error |= true; } + if (!context.west.device.empty()) { + context.cproject->target.device = context.west.device; + } + StringCollection device = { &context.device, { @@ -2914,6 +2933,9 @@ bool ProjMgrWorker::ProcessPrecedences(ContextItem& context, BoardOrDevice proce context.variables[RteConstants::AS_PNAME] = deviceItem.pname; context.variables[RteConstants::AS_BNAME] = boardItem.name; context.variables[RteConstants::AS_COMPILER] = context.toolchain.name; + context.variables.insert({ WEST_BOARD, ProjMgrUtils::GetWestBoard(boardItem.name) }); + context.west.board = context.west.board.empty() ? context.variables.at(WEST_BOARD) : + RteUtils::ExpandAccessSequences(context.west.board, context.variables); // Add cdefault misc into csolution if (context.cdefault) { @@ -3129,6 +3151,10 @@ bool ProjMgrWorker::ProcessPrecedences(ContextItem& context, BoardOrDevice proce CollectionUtils::AddStringItemsUniquely(definesAsmRef, setup.definesAsm); } + // Merge west defines + CollectionUtils::AddStringItemsUniquely(context.west.westDefs, context.controls.target.westDefs); + CollectionUtils::AddStringItemsUniquely(context.west.westDefs, context.controls.build.westDefs); + // Includes vector projectAddPaths, projectDelPaths; CollectionUtils::AddStringItemsUniquely(projectAddPaths, context.controls.cproject.addpaths); @@ -5263,7 +5289,7 @@ bool ProjMgrWorker::ProcessOutputFilenames(ContextItem& context) { // set output filename for each required output type const string toolchain = affixesMap.find(context.toolchain.name) != affixesMap.end() ? context.toolchain.name : ""; if (context.outputTypes.elf.on) { - context.outputTypes.elf.filename = baseName + get<0>(affixesMap.at(toolchain)); + context.outputTypes.elf.filename = baseName + (context.westOn ? ".elf" : get<0>(affixesMap.at(toolchain))); } if (context.outputTypes.lib.on) { context.outputTypes.lib.filename = get<1>(affixesMap.at(toolchain)) + baseName + get<2>(affixesMap.at(toolchain)); diff --git a/tools/projmgr/src/ProjMgrYamlParser.cpp b/tools/projmgr/src/ProjMgrYamlParser.cpp index e1ee16adf..753c7daa6 100644 --- a/tools/projmgr/src/ProjMgrYamlParser.cpp +++ b/tools/projmgr/src/ProjMgrYamlParser.cpp @@ -831,11 +831,26 @@ bool ProjMgrYamlParser::ParseContexts(const YAML::Node& parent, CsolutionItem& c return false; } ParsePortablePath(projectsEntry, csolution.path, YAML_PROJECT, descriptor.cproject); - descriptor.cproject = RteFsUtils::RelativePath(fs::path(csolution.directory).append(descriptor.cproject).generic_string(), csolution.directory); if (!descriptor.cproject.empty()) { - csolution.contexts.push_back(descriptor); + descriptor.cproject = RteFsUtils::RelativePath(fs::path(csolution.directory).append(descriptor.cproject).generic_string(), csolution.directory); CollectionUtils::PushBackUniquely(csolution.cprojects, descriptor.cproject); } + if (projectsEntry[YAML_WEST].IsDefined()) { + const auto& westEntry = projectsEntry[YAML_WEST]; + WestDesc west; + ParsePortablePath(westEntry, csolution.path, YAML_APP_PATH, west.app); + ParseString(westEntry, YAML_PROJECT_ID, west.projectId); + ParseString(westEntry, YAML_BOARD, west.board); + ParseString(westEntry, YAML_DEVICE, west.device); + ParseDefine(westEntry[YAML_WEST_DEFS], west.westDefs); + ParseVectorOrString(westEntry, YAML_WEST_OPT, west.westOpt); + if (west.projectId.empty()) { + west.projectId = fs::path(west.app).filename().generic_string(); + } + descriptor.west = west; + CollectionUtils::PushBackUniquely(csolution.westApps, west.projectId); + } + csolution.contexts.push_back(descriptor); } } return true; @@ -972,6 +987,9 @@ bool ProjMgrYamlParser::ParseBuildType(const YAML::Node& parent, const string& f if (!ParseDefine(parent[YAML_DEFINE_ASM], buildType.definesAsm)) { return false; } + if (!ParseDefine(parent[YAML_WEST_DEFS], buildType.westDefs)) { + return false; + } ParseVector(parent, YAML_UNDEFINE, buildType.undefines); ParsePortablePaths(parent, file, YAML_ADDPATH, buildType.addpaths); ParsePortablePaths(parent, file, YAML_ADDPATH_ASM, buildType.addpathsAsm); @@ -1143,6 +1161,7 @@ const set projectsKeys = { YAML_PROJECT, YAML_FORCONTEXT, YAML_NOTFORCONTEXT, + YAML_WEST }; const set projectKeys = { @@ -1264,6 +1283,7 @@ const set targetTypeKeys = { YAML_VARIABLES, YAML_CONTEXT_MAP, YAML_TARGET_SET, + YAML_WEST_DEFS, }; const set buildTypeKeys = { @@ -1285,6 +1305,7 @@ const set buildTypeKeys = { YAML_MISC, YAML_VARIABLES, YAML_CONTEXT_MAP, + YAML_WEST_DEFS, }; const set outputDirsKeys = { @@ -1449,6 +1470,15 @@ const set executesKeys = { YAML_NOTFORCONTEXT, }; +const set westKeys = { + YAML_PROJECT_ID, + YAML_APP_PATH, + YAML_BOARD, + YAML_DEVICE, + YAML_WEST_DEFS, + YAML_WEST_OPT +}; + const map> sequences = { {YAML_PROJECTS, projectsKeys}, {YAML_TARGETTYPES, targetTypeKeys}, @@ -1474,6 +1504,7 @@ const map> mappings = { {YAML_OUTPUT, outputKeys}, {YAML_GENERATORS, generatorsKeys}, {YAML_RTE, rteKeys}, + {YAML_WEST, westKeys}, }; bool ProjMgrYamlParser::ValidateCdefault(const string& input, const YAML::Node& root) { diff --git a/tools/projmgr/test/data/WestSupport/core0/core0.cproject.yml b/tools/projmgr/test/data/WestSupport/core0/core0.cproject.yml new file mode 100644 index 000000000..23a38a38e --- /dev/null +++ b/tools/projmgr/test/data/WestSupport/core0/core0.cproject.yml @@ -0,0 +1 @@ +project: diff --git a/tools/projmgr/test/data/WestSupport/core1/core1.cproject.yml b/tools/projmgr/test/data/WestSupport/core1/core1.cproject.yml new file mode 100644 index 000000000..23a38a38e --- /dev/null +++ b/tools/projmgr/test/data/WestSupport/core1/core1.cproject.yml @@ -0,0 +1 @@ +project: diff --git a/tools/projmgr/test/data/WestSupport/ref/core0.Debug+CM0.cbuild.yml b/tools/projmgr/test/data/WestSupport/ref/core0.Debug+CM0.cbuild.yml new file mode 100644 index 000000000..dcc2458d4 --- /dev/null +++ b/tools/projmgr/test/data/WestSupport/ref/core0.Debug+CM0.cbuild.yml @@ -0,0 +1,41 @@ +build: + generated-by: csolution version 0.0.0 + solution: ../../../../solution.csolution.yml + project: ../../../../core0/core0.cproject.yml + context: core0.Debug+CM0 + compiler: AC6 + board: Keil::RteTest Dummy board:1.2.3 + board-pack: ARM::RteTest_DFP@0.2.0 + device: ARM::RteTest_ARMCM0_Dual:cm0_core0 + device-pack: ARM::RteTest_DFP@0.2.0 + device-books: + - name: http://infocenter.arm.com/help/topic/com.arm.doc.dui0497a/index.html + title: Cortex-M0 Device Generic Users Guide + dbgconf: + - file: ../../../../.cmsis/solution+CM0.dbgconf + version: 0.0.2 + packs: + - pack: ARM::RteTest_DFP@0.2.0 + path: ${CMSIS_PACK_ROOT}/ARM/RteTest_DFP/0.2.0 + output-dirs: + outdir: . + output: + - type: elf + file: zephyr/zephyr.elf + - type: hex + file: zephyr/zephyr.hex + licenses: + - license: + license-agreement: ${CMSIS_PACK_ROOT}/ARM/RteTest_DFP/0.2.0/Doc/license.txt + packs: + - pack: ARM::RteTest_DFP@0.2.0 + west: + project-id: core0 + app-path: ../../../../west/core0 + board: rtetest dummy board + device: :cm0_core0 + west-defs: + - CORE: 0 + - CONFIG_BUILD_OUTPUT_HEX: y + - TARGET-DEF: on + - CONFIG-DEBUG: y diff --git a/tools/projmgr/test/data/WestSupport/ref/core1.Debug+CM0.cbuild.yml b/tools/projmgr/test/data/WestSupport/ref/core1.Debug+CM0.cbuild.yml new file mode 100644 index 000000000..734b3d0e6 --- /dev/null +++ b/tools/projmgr/test/data/WestSupport/ref/core1.Debug+CM0.cbuild.yml @@ -0,0 +1,41 @@ +build: + generated-by: csolution version 0.0.0 + solution: ../../../../solution.csolution.yml + project: ../../../../core1/core1.cproject.yml + context: core1.Debug+CM0 + compiler: AC6 + board: Keil::RteTest Dummy board:1.2.3 + board-pack: ARM::RteTest_DFP@0.2.0 + device: ARM::RteTest_ARMCM0_Dual:cm0_core1 + device-pack: ARM::RteTest_DFP@0.2.0 + device-books: + - name: http://infocenter.arm.com/help/topic/com.arm.doc.dui0497a/index.html + title: Cortex-M0 Device Generic Users Guide + dbgconf: + - file: ../../../../.cmsis/solution+CM0.dbgconf + version: 0.0.2 + packs: + - pack: ARM::RteTest_DFP@0.2.0 + path: ${CMSIS_PACK_ROOT}/ARM/RteTest_DFP/0.2.0 + output-dirs: + outdir: . + output: + - type: elf + file: zephyr/zephyr.elf + - type: hex + file: zephyr/zephyr.hex + licenses: + - license: + license-agreement: ${CMSIS_PACK_ROOT}/ARM/RteTest_DFP/0.2.0/Doc/license.txt + packs: + - pack: ARM::RteTest_DFP@0.2.0 + west: + project-id: core1 + app-path: ../../../../west/core1 + board: rtetest dummy board + device: :cm0_core1 + west-defs: + - CORE: 1 + - CONFIG_BUILD_OUTPUT_HEX: y + - TARGET-DEF: on + - CONFIG-DEBUG: y diff --git a/tools/projmgr/test/data/WestSupport/ref/solution+CM0.cbuild-run.yml b/tools/projmgr/test/data/WestSupport/ref/solution+CM0.cbuild-run.yml new file mode 100644 index 000000000..60f07665d --- /dev/null +++ b/tools/projmgr/test/data/WestSupport/ref/solution+CM0.cbuild-run.yml @@ -0,0 +1,174 @@ +cbuild-run: + generated-by: csolution version 0.0.0 + solution: ../solution.csolution.yml + target-type: CM0 + target-set: + compiler: AC6 + board: Keil::RteTest Dummy board:1.2.3 + board-pack: ARM::RteTest_DFP@0.2.0 + device: ARM::RteTest_ARMCM0_Dual + device-pack: ARM::RteTest_DFP@0.2.0 + output: + - file: core0/CM0/Debug/zephyr/zephyr.elf + info: generate by core0.Debug+CM0 + type: elf + load: symbols + pname: cm0_core0 + - file: core0/CM0/Debug/zephyr/zephyr.hex + info: generate by core0.Debug+CM0 + type: hex + load: image + pname: cm0_core0 + - file: core1/CM0/Debug/zephyr/zephyr.elf + info: generate by core1.Debug+CM0 + type: elf + load: symbols + pname: cm0_core1 + - file: core1/CM0/Debug/zephyr/zephyr.hex + info: generate by core1.Debug+CM0 + type: hex + load: image + pname: cm0_core1 + system-resources: + memory: + - name: FLASH_DUAL + access: rx + start: 0x00000000 + size: 0x00080000 + pname: cm0_core0 + from-pack: ARM::RteTest_DFP@0.2.0 + - name: SRAM_DUAL + access: rwx + start: 0x80000000 + size: 0x00020000 + pname: cm0_core1 + from-pack: ARM::RteTest_DFP@0.2.0 + - name: IROM1 + access: rx + start: 0x00000000 + size: 0x00040000 + from-pack: ARM::RteTest_DFP@0.2.0 + - name: IRAM1 + access: rwx + start: 0x20000000 + size: 0x00020000 + from-pack: ARM::RteTest_DFP@0.2.0 + system-descriptions: + - file: ${CMSIS_PACK_ROOT}/ARM/RteTest_DFP/0.2.0/Device/ARM/SVD/ARMCM0.svd + type: svd + debugger: + name: CMSIS-DAP@pyOCD + protocol: swd + clock: 10000000 + dbgconf: ../.cmsis/solution+CM0.dbgconf + start-pname: cm0_core0 + gdbserver: + - port: 3333 + pname: cm0_core0 + - port: 3334 + pname: cm0_core1 + debug-vars: + vars: | + __var DbgMCU_CR = 0x00000007; // DBGMCU_CR: DBG_SLEEP, DBG_STOP, DBG_STANDBY + __var TraceClk_Pin = 0x00040002; // PE2 + __var TraceD0_Pin = 0x00040003; // PE3 + __var TraceD1_Pin = 0x00040004; // PE4 + debug-sequences: + - name: DebugDeviceUnlock + blocks: + - execute: | + Sequence("CheckID"); + - name: DebugCoreStart + blocks: + - execute: | + // Replication of Standard Functionality + Write32(0xE000EDF0, 0xA05F0001); // Enable Core Debug via DHCSR + - info: DbgMCU registers + execute: | + // Device Specific Debug Setup + Write32(0x40021018, Read32(0x40021018) | 0x00400000); // Set RCC_APB2ENR.DBGMCUEN + - name: CheckID + blocks: + - execute: | + __var pidr1 = 0; + __var pidr2 = 0; + __var jep106id = 0; + __var ROMTableBase = 0; + + __ap = 0; // AHB-AP + + ROMTableBase = ReadAP(0xF8) & ~0x3; + + pidr1 = Read32(ROMTableBase + 0x0FE4); + pidr2 = Read32(ROMTableBase + 0x0FE8); + jep106id = ((pidr2 & 0x7) << 4 ) | ((pidr1 >> 4) & 0xF); + - if: jep106id != 0x20 + execute: | + Query(0, "Incorrect ID! Abort connection", 1); + Message(2, "Incorrect ID! Abort connection."); + - while: (ReadDP(DP_CTRL_STAT) & 0xA0000000) != 0xA0000000 + timeout: 1000000 + - name: DebugPortStop + blocks: + - execute: | + __var connectionFlash = ( __connection & 0xF ) == 2 ; + __var FLASH_BASE = 0x40022000 ; + __var FLASH_CR = FLASH_BASE + 0x10 ; + __var OBL_LAUNCH_BIT = ( 1 << 13 ) ; + __var FLASH_CR_Value = 0 ; + __var DoDebugPortStop = 1 ; + __var DP_CTRL_STAT = 0x4 ; + __var DP_SELECT = 0x8 ; + - if: connectionFlash && DoDebugPortStop + execute: | + DoDebugPortStop = 0 ; + FLASH_CR_Value = Read32( FLASH_CR ) ; + __errorcontrol = 1 ; + // write OBL_LAUNCH bit (causes a reset) + Write32( FLASH_CR, FLASH_CR_Value | ( OBL_LAUNCH_BIT ) ) ; + __errorcontrol = 0 ; + - if: DoDebugPortStop + execute: | + // Switch to DP Register Bank 0 + WriteDP(DP_SELECT, 0x00000000); + // Power Down Debug port + WriteDP(DP_CTRL_STAT, 0x00000000); + programming: + - algorithm: ${CMSIS_PACK_ROOT}/ARM/RteTest_DFP/0.2.0/Device/ARM/Flash/CortexM4Dual.FLM + start: 0x000A0000 + size: 0x00020000 + ram-start: 0x000C0000 + ram-size: 0x00040000 + pname: cm0_core1 + - algorithm: ${CMSIS_PACK_ROOT}/ARM/RteTest_DFP/0.2.0/Device/ARM/Flash/FAMILY.FLM + start: 0x00000000 + size: 0x00040000 + ram-start: 0x20000000 + ram-size: 0x00020000 + debug-topology: + debugports: + - dpid: 0 + accessports: + - apid: 0 + index: 0 + datapatch: + - address: 0xE0040FCC + value: 0x00000011 + info: DEVTYPE + - address: 0xE0040FF0 + value: 0x0000000D + info: CIDR0 + - address: 0x1000FFFF + value: 0x000000CC + info: Family level datapatch + - dpid: 1 + accessports: + - apid: 1 + index: 0 + processors: + - pname: cm0_core0 + apid: 0 + reset-sequence: ResetSystem0 + - pname: cm0_core1 + apid: 1 + reset-sequence: ResetSystem1 diff --git a/tools/projmgr/test/data/WestSupport/ref/solution.cbuild-idx.yml b/tools/projmgr/test/data/WestSupport/ref/solution.cbuild-idx.yml new file mode 100644 index 000000000..e92345561 --- /dev/null +++ b/tools/projmgr/test/data/WestSupport/ref/solution.cbuild-idx.yml @@ -0,0 +1,27 @@ +build-idx: + generated-by: csolution version 0.0.0 + csolution: solution.csolution.yml + cbuild-run: out/solution+CM0.cbuild-run.yml + tmpdir: tmp + cprojects: + - cproject: core0/core0.cproject.yml + - cproject: core1/core1.cproject.yml + cbuilds: + - cbuild: out/core0/CM0/Debug/core0.Debug+CM0.cbuild.yml + west: true + project: core0 + configuration: .Debug+CM0 + messages: + info: + - solution.cbuild-pack.yml - file generated successfully + - solution+CM0.cbuild-run.yml - file generated successfully + - core0.Debug+CM0.cbuild.yml - file generated successfully + - cbuild: out/core1/CM0/Debug/core1.Debug+CM0.cbuild.yml + west: true + project: core1 + configuration: .Debug+CM0 + messages: + info: + - solution.cbuild-pack.yml - file generated successfully + - solution+CM0.cbuild-run.yml - file generated successfully + - core1.Debug+CM0.cbuild.yml - file generated successfully diff --git a/tools/projmgr/test/data/WestSupport/solution.csolution.yml b/tools/projmgr/test/data/WestSupport/solution.csolution.yml new file mode 100644 index 000000000..3f2c6f046 --- /dev/null +++ b/tools/projmgr/test/data/WestSupport/solution.csolution.yml @@ -0,0 +1,39 @@ +# yaml-language-server: $schema=https://raw.githubusercontent.com/Open-CMSIS-Pack/devtools/main/tools/projmgr/schemas/csolution.schema.json +solution: + + packs: + - pack: ARM::RteTest_DFP + + compiler: AC6 + + target-types: + - type: CM0 + board: RteTest Dummy board + west-defs: + - TARGET-DEF: on + target-set: + - set: + images: + - project-context: core0.Debug + - project-context: core1.Debug + + build-types: + - type: Debug + west-defs: + - CONFIG-DEBUG: y + + # List related projects. + projects: + - project: core0/core0.cproject.yml + west: + app-path: ./west/core0 + device: :cm0_core0 + west-defs: + - CORE: 0 + - project: core1/core1.cproject.yml + west: + app-path: ./west/core1 + project-id: core1 + device: :cm0_core1 + west-defs: + - CORE: 1 diff --git a/tools/projmgr/test/src/ProjMgrUnitTests.cpp b/tools/projmgr/test/src/ProjMgrUnitTests.cpp index 4a34d8f15..d4c9111cf 100644 --- a/tools/projmgr/test/src/ProjMgrUnitTests.cpp +++ b/tools/projmgr/test/src/ProjMgrUnitTests.cpp @@ -7160,3 +7160,23 @@ CMSIS-DAP@Arm-Debugger\n\ CMSIS-DAP@armdbg\n\ "))); } + +TEST_F(ProjMgrUnitTests, WestSupport) { + char* argv[5]; + const string& csolution = testinput_folder + "/WestSupport/solution.csolution.yml"; + argv[1] = (char*)"convert"; + argv[2] = (char*)csolution.c_str(); + argv[3] = (char*)"--active"; + argv[4] = (char*)"CM0"; + EXPECT_EQ(0, RunProjMgr(5, argv, m_envp)); + + ProjMgrTestEnv::CompareFile(testinput_folder + "/WestSupport/solution.cbuild-idx.yml", + testinput_folder + "/WestSupport/ref/solution.cbuild-idx.yml"); + ProjMgrTestEnv::CompareFile(testinput_folder + "/WestSupport/out/solution+CM0.cbuild-run.yml", + testinput_folder + "/WestSupport/ref/solution+CM0.cbuild-run.yml"); + ProjMgrTestEnv::CompareFile(testinput_folder + "/WestSupport/out/core0/CM0/Debug/core0.Debug+CM0.cbuild.yml", + testinput_folder + "/WestSupport/ref/core0.Debug+CM0.cbuild.yml"); + ProjMgrTestEnv::CompareFile(testinput_folder + "/WestSupport/out/core1/CM0/Debug/core1.Debug+CM0.cbuild.yml", + testinput_folder + "/WestSupport/ref/core1.Debug+CM0.cbuild.yml"); +} +