예제 #1
0
        private static IEnumerable <MCUDefinitionWithPredicate> ParsePeripheralRegisters(string dir, MCUFamilyBuilder fam, string specificDevice, ParseReportWriter writer)
        {
            var mainClassifier = fam.Definition.Subfamilies.First(f => f.IsPrimary);
            List <MCUDefinitionWithPredicate> result = new List <MCUDefinitionWithPredicate>();

            Console.Write("Parsing {0} registers using the new parsing logic...", fam.Definition.Name);
            foreach (var fn in Directory.GetFiles(dir, "*.h"))
            {
                string subfamily            = Path.GetFileNameWithoutExtension(fn);
                string subfamilyForMatching = subfamily;
                if (subfamily.Length != 11 && subfamily.Length != 12)
                {
                    if (subfamily.EndsWith("_cm4", StringComparison.InvariantCultureIgnoreCase))
                    {
                        //This is a header file for the Cortex-M4 core of an STM32MP1 device
                        subfamilyForMatching = subfamily.Substring(0, subfamily.Length - 4);
                    }
                    else
                    {
                        continue;
                    }
                }

                if (specificDevice != null && subfamily != specificDevice)
                {
                    continue;
                }

                var r = new MCUDefinitionWithPredicate
                {
                    MCUName        = subfamily,
                    RegisterSets   = PeripheralRegisterGenerator2.GeneratePeripheralRegisterDefinitionsFromHeaderFile(fn, fam.MCUs[0].Core, writer),
                    MatchPredicate = m => StringComparer.InvariantCultureIgnoreCase.Compare(mainClassifier.TryMatchMCUName(m.Name), subfamilyForMatching) == 0,
                };

                result.Add(r);
            }

            Console.WriteLine("done");
            return(result);
        }
예제 #2
0
        static void Main(string[] args)
        {
            var regKey   = Registry.CurrentUser.CreateSubKey(@"SOFTWARE\Sysprogs\BSPGenerators\STM32");
            var sdkRoot  = regKey.GetValue("SDKRoot") as string ?? throw new Exception("Please specify STM32 SDK root via registry");
            var cubeRoot = regKey.GetValue("CubeMXRoot") as string ?? throw new Exception("Please specify STM32CubeMX location via registry");

            if (args.Contains("/fetch"))
            {
                //This will load the latest SDK list from the STM32CubeMX directory and will fetch/unpack them to our SDKRoot directory.
                //Before running this, ensure the STM32CubeMX has the up-to-date SDK definitions (using the 'check for update' function), as
                //otherwise the BSP generator will fetch the old versions.

                SDKFetcher.FetchLatestSDKs(sdkRoot, cubeRoot);
            }

            string       rulesetName = args.FirstOrDefault(a => a.StartsWith("/rules:"))?.Substring(7) ?? STM32Ruleset.Classic.ToString();
            STM32Ruleset ruleset     = Enum.GetValues(typeof(STM32Ruleset))
                                       .OfType <STM32Ruleset>()
                                       .First(v => StringComparer.InvariantCultureIgnoreCase.Compare(v.ToString(), rulesetName) == 0);

            ///If the MCU list format changes again, create a new implementation of the IDeviceListProvider interface, switch to using it, but keep the old one for reference & easy comparison.
            IDeviceListProvider provider = new DeviceListProviders.CubeProvider();

            var bspBuilder = new STM32BSPBuilder(new BSPDirectories(sdkRoot, @"..\..\Output\" + rulesetName, @"..\..\rules\" + rulesetName), cubeRoot);

            Directory.CreateDirectory(@"..\..\Logs");
            using (var wr = new ParseReportWriter(@"..\..\Logs\registers.log"))
            {
                var devices = provider.LoadDeviceList(bspBuilder);
                if (devices.Where(d => d.FlashSize == 0 && !d.Name.StartsWith("STM32MP1")).Count() > 0)
                {
                    throw new Exception($"Some deviceshave FLASH Size({devices.Where(d => d.FlashSize == 0).Count()})  = 0 ");
                }

                List <MCUFamilyBuilder> allFamilies = new List <MCUFamilyBuilder>();
                string extraFrameworksFile          = Path.Combine(bspBuilder.Directories.RulesDir, "FrameworkTemplates.xml");
                if (!File.Exists(extraFrameworksFile) && File.Exists(Path.ChangeExtension(extraFrameworksFile, ".txt")))
                {
                    extraFrameworksFile = Path.Combine(bspBuilder.Directories.RulesDir, File.ReadAllText(Path.ChangeExtension(extraFrameworksFile, ".txt")));
                }

                Dictionary <string, STM32SDKCollection.SDK> sdksByVariable = bspBuilder.SDKList.SDKs.ToDictionary(s => $"$$STM32:{s.Family}_DIR$$");
                List <STM32SDKCollection.SDK> referencedSDKs = new List <STM32SDKCollection.SDK>();

                foreach (var fn in Directory.GetFiles(bspBuilder.Directories.RulesDir + @"\families", "*.xml"))
                {
                    var fam = XmlTools.LoadObject <FamilyDefinition>(fn);

                    if (File.Exists(extraFrameworksFile))
                    {
                        int    idx     = fam.PrimaryHeaderDir.IndexOf('\\');
                        string baseDir = fam.PrimaryHeaderDir.Substring(0, idx);
                        if (!baseDir.StartsWith("$$STM32:"))
                        {
                            throw new Exception("Invalid base directory. Please recheck the family definition.");
                        }

                        string baseFamName = fam.Name;
                        if (baseFamName.EndsWith("_M4"))
                        {
                            baseFamName = baseFamName.Substring(0, baseFamName.Length - 3);
                        }

                        referencedSDKs.Add(sdksByVariable[baseDir]);

                        var dict = new Dictionary <string, string>
                        {
                            { "STM32:FAMILY_EX", fam.Name },
                            { "STM32:FAMILY", baseFamName },
                            { "STM32:FAMILY_DIR", baseDir },
                        };

                        var extraFrameworkFamily = XmlTools.LoadObject <FamilyDefinition>(extraFrameworksFile);

                        //USB host/device libraries are not always compatible between different device families. Hence we need to ship separate per-family copies of those.
                        var expandedExtraFrameworks = extraFrameworkFamily.AdditionalFrameworks.Select(fw =>
                        {
                            fw.ID   = VariableHelper.ExpandVariables(fw.ID, dict);
                            fw.Name = VariableHelper.ExpandVariables(fw.Name, dict);
                            fw.RequiredFrameworks     = ExpandVariables(fw.RequiredFrameworks, dict);
                            fw.IncompatibleFrameworks = ExpandVariables(fw.IncompatibleFrameworks, dict);
                            foreach (var job in fw.CopyJobs)
                            {
                                job.SourceFolder          = VariableHelper.ExpandVariables(job.SourceFolder, dict);
                                job.TargetFolder          = VariableHelper.ExpandVariables(job.TargetFolder, dict);
                                job.AdditionalIncludeDirs = VariableHelper.ExpandVariables(job.AdditionalIncludeDirs, dict);
                            }

                            return(fw);
                        });

                        //Furthermore, some families do not include a USB host peripheral and hence do not contain a USB Host library. We need to skip it automatically.
                        var extraFrameworksWithoutMissingFolders = expandedExtraFrameworks.Where(fw => fw.CopyJobs.Count(j =>
                        {
                            string expandedJobSourceDir = j.SourceFolder;
                            bspBuilder.ExpandVariables(ref expandedJobSourceDir);
                            return(!Directory.Exists(expandedJobSourceDir));
                        }) == 0);

                        fam.AdditionalFrameworks = fam.AdditionalFrameworks.Concat(extraFrameworksWithoutMissingFolders).ToArray();
                    }

                    bspBuilder.InsertLegacyHALRulesIfNecessary(fam, bspBuilder.ReverseFileConditions);
                    switch (ruleset)
                    {
                    case STM32Ruleset.STM32WB:
                        allFamilies.Add(new STM32WBFamilyBuilder(bspBuilder, fam));
                        break;

                    case STM32Ruleset.STM32MP1:
                        allFamilies.Add(new STM32MP1FamilyBuilder(bspBuilder, fam));
                        break;

                    case STM32Ruleset.Classic:
                    default:
                        allFamilies.Add(new STM32ClassicFamilyBuilder(bspBuilder, fam));
                        break;
                    }
                }

                var rejects = BSPGeneratorTools.AssignMCUsToFamilies(devices, allFamilies);

                if (rejects.Count > 0 && ruleset == STM32Ruleset.Classic)
                {
                    Console.WriteLine("Globally unsupported MCUs:");
                    foreach (var r in rejects)
                    {
                        Console.WriteLine("\t{0}", r.Name);
                    }
                }

                List <MCUFamily>                     familyDefinitions = new List <MCUFamily>();
                List <MCU>                           mcuDefinitions    = new List <MCU>();
                List <EmbeddedFramework>             frameworks        = new List <EmbeddedFramework>();
                List <MCUFamilyBuilder.CopiedSample> exampleDirs       = new List <MCUFamilyBuilder.CopiedSample>();

                bool   noPeripheralRegisters = args.Contains("/noperiph");
                string specificDeviceForDebuggingPeripheralRegisterGenerator = args.FirstOrDefault(a => a.StartsWith("/periph:"))?.Substring(8);

                var commonPseudofamily = new MCUFamilyBuilder(bspBuilder, XmlTools.LoadObject <FamilyDefinition>(bspBuilder.Directories.RulesDir + @"\CommonFiles.xml"));
                foreach (var fw in commonPseudofamily.GenerateFrameworkDefinitions())
                {
                    frameworks.Add(fw);
                }

                List <ConditionalToolFlags> allConditionalToolFlags = new List <ConditionalToolFlags>();

                foreach (var fam in allFamilies)
                {
                    bspBuilder.GetMemoryMcu(fam);
                    var rejectedMCUs = fam.RemoveUnsupportedMCUs(true);
                    if (rejectedMCUs.Length != 0)
                    {
                        Console.WriteLine("Unsupported {0} MCUs:", fam.Definition.Name);
                        foreach (var mcu in rejectedMCUs)
                        {
                            Console.WriteLine("\t{0}", mcu.Name);
                        }
                    }

                    fam.AttachStartupFiles(ParseStartupFiles(fam.Definition.StartupFileDir, fam));
                    if (!noPeripheralRegisters)
                    {
                        fam.AttachPeripheralRegisters(ParsePeripheralRegisters(fam.Definition.PrimaryHeaderDir, fam, specificDeviceForDebuggingPeripheralRegisterGenerator, wr),
                                                      throwIfNotFound: specificDeviceForDebuggingPeripheralRegisterGenerator == null);
                    }

                    familyDefinitions.Add(fam.GenerateFamilyObject(MCUFamilyBuilder.CoreSpecificFlags.All, true));
                    fam.GenerateLinkerScripts(false);

                    foreach (var mcu in fam.MCUs)
                    {
                        mcuDefinitions.Add(mcu.GenerateDefinition(fam, bspBuilder, !noPeripheralRegisters && specificDeviceForDebuggingPeripheralRegisterGenerator == null));
                    }

                    foreach (var fw in fam.GenerateFrameworkDefinitions())
                    {
                        frameworks.Add(fw);
                    }

                    foreach (var sample in fam.CopySamples())
                    {
                        exampleDirs.Add(sample);
                    }

                    if (fam.Definition.ConditionalFlags != null)
                    {
                        allConditionalToolFlags.AddRange(fam.Definition.ConditionalFlags);
                    }
                }

                foreach (var sample in commonPseudofamily.CopySamples(null, allFamilies.Where(f => f.Definition.AdditionalSystemVars != null).SelectMany(f => f.Definition.AdditionalSystemVars)))
                {
                    exampleDirs.Add(sample);
                }

                var prioritizer = new SamplePrioritizer(Path.Combine(bspBuilder.Directories.RulesDir, "SamplePriorities.txt"));
                exampleDirs.Sort((a, b) => prioritizer.Prioritize(a.RelativePath, b.RelativePath));

                var bsp = XmlTools.LoadObject <BoardSupportPackage>(Path.Combine(bspBuilder.Directories.RulesDir, "BSPTemplate.xml"));

                bsp.MCUFamilies    = familyDefinitions.ToArray();
                bsp.SupportedMCUs  = mcuDefinitions.ToArray();
                bsp.Frameworks     = frameworks.ToArray();
                bsp.Examples       = exampleDirs.Where(s => !s.IsTestProjectSample).Select(s => s.RelativePath).ToArray();
                bsp.TestExamples   = exampleDirs.Where(s => s.IsTestProjectSample).Select(s => s.RelativePath).ToArray();
                bsp.PackageVersion = bspBuilder.SDKList.BSPVersion;
                bsp.FileConditions = bspBuilder.MatchedFileConditions.ToArray();
                bsp.InitializationCodeInsertionPoints = commonPseudofamily.Definition.InitializationCodeInsertionPoints;
                bsp.ConditionalFlags = allConditionalToolFlags.ToArray();

                bspBuilder.SDKList.SDKs = referencedSDKs.Distinct().ToArray();
                XmlTools.SaveObject(bspBuilder.SDKList, Path.Combine(bspBuilder.BSPRoot, "SDKVersions.xml"));

                bspBuilder.ValidateBSP(bsp);

                bspBuilder.ReverseFileConditions.SaveIfConsistent(bspBuilder.Directories.OutputDir, bspBuilder.ExportRenamedFileTable(), ruleset == STM32Ruleset.STM32WB);

                File.Copy(@"..\..\stm32_compat.h", Path.Combine(bspBuilder.BSPRoot, "stm32_compat.h"), true);
                Console.WriteLine("Saving BSP...");
                bspBuilder.Save(bsp, true);
            }
        }
예제 #3
0
        public static HardwareRegisterSet[] GeneratePeripheralRegisterDefinitionsFromHeaderFile(string peripheralHeaderFile, CortexCore core, ParseReportWriter reportWriter)
        {
            using (var handle = reportWriter.BeginParsingFile(peripheralHeaderFile))
            {
                var parser     = new HeaderFileParser(peripheralHeaderFile, handle);
                var parsedFile = parser.ParseHeaderFile();

                if (core == CortexCore.M4 && parsedFile.PreprocessorMacros.TryGetValue("HSEM_COMMON", out var hsem))
                {
                    /*
                     * This is the only relevant use of #ifdef in the STM32 headers:
                     *
                     #if defined(CORE_CM4)
                     #define HSEM_COMMON         ((HSEM_Common_TypeDef *) (HSEM_BASE + 0x110UL))
                     #else
                     #define HSEM_COMMON         ((HSEM_Common_TypeDef *) (HSEM_BASE + 0x100UL))
                     #endif
                     *
                     * Currently, instead of fully parsing it, we just patch it manually for the M4 core.
                     */

                    for (int i = 0; i < hsem.Value.Length; i++)
                    {
                        if (hsem.Value[i].Value == "0x100UL")
                        {
                            hsem.Value[i].Value = "0x110UL";
                        }
                    }
                }

                var peripherals       = LocateStructsReferencedInBaseExpressions(parsedFile);
                var subregisterParser = new PeripheralSubregisterParser(handle);

                subregisterParser.AttachSubregisterDefinitions(parsedFile, peripherals);

                List <HardwareRegisterSet> sets = new List <HardwareRegisterSet>();
                string coreFile = $@"../../../CoreReg/OutCorexx/core_{core}.xml";
                if (core != CortexCore.Invalid)
                {
                    if (!File.Exists(coreFile))
                    {
                        throw new Exception("Unknown ARM core: " + core);
                    }

                    sets.Add(XmlTools.LoadObject <HardwareRegisterSet>(coreFile));
                }

                foreach (var peripheral in peripherals)
                {
                    sets.Add(new HardwareRegisterSet
                    {
                        Registers        = peripheral.Registers.Select(r => r.ToHardwareRegister(peripheral)).ToArray(),
                        UserFriendlyName = peripheral.Name,
                        ExpressionPrefix = peripheral.Name + "->",
                    });
                }

                return(sets.ToArray());
            }
        }