예제 #1
0
        public MCUFamilyBuilder(BSPBuilder bspBuilder, FamilyDefinition definition)
        {
            bspBuilder.ExpandVariables(ref definition.PrimaryHeaderDir);
            bspBuilder.ExpandVariables(ref definition.StartupFileDir);

            if (definition.SmartSamples != null)
            {
                foreach (var simple in definition.SmartSamples)
                {
                    for (int count = 0; count < simple.AdditionalSources?.Count(); count++)
                    {
                        string addSource = simple.AdditionalSources[count];;
                        bspBuilder.ExpandAdditionalVariables(ref simple.AdditionalSources[count], definition.AdditionalSystemVars);
                    }
                }
            }

            BSP        = bspBuilder;
            Definition = definition;
            if (string.IsNullOrEmpty(definition.FamilySubdirectory))
            {
                FamilyFilePrefix = "";
            }
            else
            {
                FamilyFilePrefix = definition.FamilySubdirectory + "/";
            }
        }
예제 #2
0
        public FrameworkLocator(string sdkDir, string rulesDir)
        {
            _AllFilesInSDK    = Directory.GetFiles(sdkDir, "*", SearchOption.AllDirectories).Select(f => f.Substring(sdkDir.Length + 1).Replace('\\', '/')).ToArray();
            _FamilyDefinition = XmlTools.LoadObject <FamilyDefinition>(Path.Combine(rulesDir, "CommonFiles.xml"));

            _AllFrameworks = _FamilyDefinition.AdditionalFrameworks.Concat(_FamilyDefinition.AdditionalFrameworkTemplates.SelectMany(t => t.Expand())).ToArray();

#if UNUSED
            var allFiles       = File.ReadAllLines(@"e:\temp\libs.txt");
            var unresolvedLibs = allFiles.Where(f => DoLookupFrameworkIDForLibraryFile(f) == null).ToArray();
            Console.WriteLine($"Found {unresolvedLibs.Length} unresolved libraries:");
            foreach (var lib in unresolvedLibs)
            {
                Console.WriteLine("\t" + lib);
            }
#endif
        }
예제 #3
0
        public void GenerateRulesForFamily(FamilyDefinition family)
        {
            foreach (var fw in family.AdditionalFrameworks)
            {
                foreach (var job in fw.CopyJobs)
                {
                    string[] attrs = job.VendorSpecificAttributes?.Split('|');

                    if (attrs?.Contains("GenerateConditionsForPrebuiltLibraries") == true)
                    {
                        GenerateConditionsForPrebuiltLibraries(family, fw, job);
                    }
                    if (attrs?.Contains("GenerateConditionsForSubdirs") == true)
                    {
                        GenerateConditionsForSubdirs(family, fw, job);
                    }
                }
            }

            GenerateBLEFrameworks(family);
        }
예제 #4
0
        private void CreateMCUFamilyBuilders()
        {
            var mcuFamilyBuilders = new List <MCUFamilyBuilder>();

            foreach (var deviceDirectory in Directory.GetDirectories(Directories.InputDir + "\\" + DEVICES_FOLDER))
            {
                var deviceName = deviceDirectory.Substring(deviceDirectory.LastIndexOf(Path.DirectorySeparatorChar) + 1);

                if (deviceName[0] != 'M')
                {
                    throw new Exception("Unexpected device name");
                }

                var mcuFamilyName    = deviceName.Substring(1);
                var familyDefinition = new FamilyDefinition();
                familyDefinition.Name = mcuFamilyName;
                familyDefinition.FamilySubdirectory = mcuFamilyName;
                familyDefinition.PrimaryHeaderDir   = deviceDirectory;
                familyDefinition.Subfamilies        = new MCUClassifier[0];
                mcuFamilyBuilders.Add(new MCUFamilyBuilder(this, familyDefinition));
            }

            _mcuFamilyBuilders = mcuFamilyBuilders;
        }
예제 #5
0
 public STM32MP1FamilyBuilder(BSPBuilder bspBuilder, FamilyDefinition definition)
     : base(bspBuilder, definition)
 {
 }
예제 #6
0
 public NordicFamilyBuilder(BSPBuilder bspBuilder, FamilyDefinition definition)
     : base(bspBuilder, definition)
 {
 }
예제 #7
0
            /*
             *  As of February 2019, some of the STM32 software packages provide legacy versions of the regular HAL source files (e.g. stm32f1xx_hal_can.c) that are mutually exclusive
             *  with the regular versions of the same files. Instead of hardcoding the specific files for specific families, we detect it programmatically and generate the necessary
             *  rules on-the-fly in this function.
             */
            public void InsertLegacyHALRulesIfNecessary(FamilyDefinition fam, ReverseFileConditionBuilder reverseFileConditions)
            {
                var    halFramework = fam.AdditionalFrameworks.FirstOrDefault(f => f.ClassID == "com.sysprogs.arm.stm32.hal") ?? throw new Exception(fam.Name + " defines no HAL framework");
                var    primaryJob   = halFramework.CopyJobs.First();
                string srcDir       = primaryJob.SourceFolder + @"\Src";

                ExpandVariables(ref srcDir);
                if (!Directory.Exists(srcDir))
                {
                    throw new Exception($"The first job for the HAL framework for {fam.Name} does not correspond to the normal source collection");
                }

                var legacyDir = srcDir + @"\Legacy";

                if (Directory.Exists(legacyDir))
                {
                    var    fileNames   = Directory.GetFiles(legacyDir).Select(Path.GetFileName).ToArray();
                    string settingName = "com.sysprogs.stm32.legacy_hal_src";

                    List <string> moduleNames = new List <string>();

                    foreach (var file in fileNames)
                    {
                        if (!File.Exists(Path.Combine(legacyDir, file)))
                        {
                            throw new Exception($"{Path.Combine(legacyDir, file)} does not have a corresponding non-legacy file");
                        }

                        moduleNames.Add(Path.GetFileNameWithoutExtension(file.Substring(file.LastIndexOf('_') + 1)).ToUpper());
                        primaryJob.SimpleFileConditions = (primaryJob.SimpleFileConditions ?? new string[0]).Concat(new[]
                        {
                            $@"Src\\Legacy\\{file}: $${settingName}$$ == 1",
                            $@"Src\\{file}: $${settingName}$$ != 1",
                        }).ToArray();
                    }

                    if (halFramework.ConfigurableProperties == null)
                    {
                        halFramework.ConfigurableProperties = new PropertyList {
                            PropertyGroups = new List <PropertyGroup> {
                                new PropertyGroup()
                            }
                        }
                    }
                    ;

                    halFramework.ConfigurableProperties.PropertyGroups[0].Properties.Add(new PropertyEntry.Enumerated
                    {
                        UniqueID       = settingName,
                        Name           = "HAL Driver Sources for " + string.Join(" ,", moduleNames),
                        SuggestionList = new PropertyEntry.Enumerated.Suggestion[]
                        {
                            new PropertyEntry.Enumerated.Suggestion {
                                InternalValue = "", UserFriendlyName = "Default"
                            },
                            new PropertyEntry.Enumerated.Suggestion {
                                InternalValue = "1", UserFriendlyName = "Legacy"
                            }
                        }
                    });
                }

                Regex  rgLegacyDefineCheck = new Regex(@"#if( defined|def)[ \(]+(USE_LEGACY|USE_HAL_LEGACY)");
                string legacyDefineName    = null;

                foreach (var line in File.ReadAllLines(Directory.GetFiles(srcDir + @"\..\Inc", "stm32*hal_def.h")[0]))
                {
                    var m = rgLegacyDefineCheck.Match(line);
                    if (m.Success)
                    {
                        legacyDefineName = m.Groups[2].Value;
                    }
                }

                if (legacyDefineName != null)
                {
                    if (halFramework.ConfigurableProperties == null)
                    {
                        halFramework.ConfigurableProperties = new PropertyList {
                            PropertyGroups = new List <PropertyGroup> {
                                new PropertyGroup()
                            }
                        }
                    }
                    ;

                    halFramework.ConfigurableProperties.PropertyGroups[0].Properties.Add(new PropertyEntry.Boolean
                    {
                        UniqueID     = "com.sysprogs.bspoptions.stm32.hal_legacy",
                        Name         = "Support legacy HAL API",
                        ValueForTrue = legacyDefineName,
                        DefaultValue = true,
                    });

                    halFramework.CopyJobs[0].PreprocessorMacros += ";$$com.sysprogs.bspoptions.stm32.hal_legacy$$";

                    reverseFileConditions?.GetHandleForFramework(halFramework)?.AttachMinimalConfigurationValue("com.sysprogs.bspoptions.stm32.hal_legacy", "");
                }
            }
        }
예제 #8
0
        private void GenerateConditionsForSubdirs(FamilyDefinition family, Framework fw, CopyJob job)
        {
            HashSet <string> explicitlyMentionedDirectories = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase);
            HashSet <string> excludedSubdirectories         = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase);

            foreach (var cond in job.SmartFileConditions ?? new string[0])
            {
                var def = SmartPropertyDefinition.Parse(cond, null);
                foreach (var item in def.Items)
                {
                    int idx = item.Key.IndexOf('\\');
                    if (idx != -1)
                    {
                        explicitlyMentionedDirectories.Add(item.Key.Substring(0, idx));
                    }
                }
            }

            Regex rgExcludedSubdir = new Regex(@"-([^\\]+)\\\*$");

            foreach (var cond in (job.FilesToCopy + ";" + job.ProjectInclusionMask).Split(';'))
            {
                var m = rgExcludedSubdir.Match(cond);
                if (m.Success)
                {
                    excludedSubdirectories.Add(m.Groups[1].Value);
                }
            }

            List <string> generatedSmartFileConditions = new List <string>();

            foreach (var dir in Directory.GetDirectories(_Builder.ExpandVariables(job.SourceFolder)))
            {
                string name = Path.GetFileName(dir);
                if (explicitlyMentionedDirectories.Contains(name))
                {
                    continue;
                }
                if (excludedSubdirectories.Contains(name))
                {
                    continue;
                }

                generatedSmartFileConditions.Add($"-{name}|{name}\\\\.*");

                if (!_FrameworkConditions.TryGetValue(fw.ID, out var conditions))
                {
                    _FrameworkConditions[fw.ID] = conditions = new GeneratedFrameworkConditions {
                        TargetPath = $"$$SYS:BSP_ROOT$$/{family.FamilySubdirectory}/{job.TargetFolder}".Replace('\\', '/')
                    }
                }
                ;

                conditions.ConditionalSubdirectories.Add(name);
            }

            job.SmartFileConditions = (job.SmartFileConditions ?? new string[0]).Concat(generatedSmartFileConditions).OrderBy(c => c.ToLower().TrimStart('-')).ToArray();
        }

        void GenerateBLEFrameworks(FamilyDefinition family)
        {
            List <Framework> bleFrameworks = new List <Framework>();
            string           famBase       = family.Name.Substring(0, 5).ToLower();

            HashSet <string> discoveredSubdirs = new HashSet <string>();
            string           baseDir           = Path.Combine(family.PrimaryHeaderDir, @"..\..\..\components\ble");

            foreach (var subdir in Directory.GetDirectories(baseDir))
            {
                discoveredSubdirs.Add(Path.GetFileName(subdir));
            }
            foreach (var subdir in Directory.GetDirectories(Path.Combine(baseDir, "ble_services")))
            {
                discoveredSubdirs.Add(Path.Combine("ble_services", Path.GetFileName(subdir)));
            }

            foreach (var name in new[] { "ble_services", "common", "peer_manager", "nrf_ble_gatt" })
            {
                discoveredSubdirs.Remove(name);
            }

            foreach (var dir in discoveredSubdirs)
            {
                string desc = FetchDescriptionFromDirectory(Path.Combine(baseDir, dir)) ?? throw new Exception("Failed to load description of " + dir);

                if (desc.StartsWith("BLE"))
                {
                    desc = desc.Substring(3).Trim();
                }

                string virtualFolderName = "BLE " + desc;
                desc = "Bluetooth LE - " + desc;

                string id = Path.GetFileName(dir);

                if (id.StartsWith("experimental_"))
                {
                    id = id.Substring(13);
                }

                if (!id.StartsWith("ble_") && !id.StartsWith("nrf_ble"))
                {
                    id = "ble_" + id;
                }

                /*if (dir.StartsWith("ble_services\\", StringComparison.CurrentCultureIgnoreCase))
                 * {
                 *  int idx = id.IndexOf("ble_");
                 *  if (idx == -1)
                 *      id = "ble_svc_" + id;
                 *  else
                 *      id = id.Insert(idx + 4, "svc_");
                 * }*/

                bleFrameworks.Add(new Framework
                {
                    Name              = string.Format("{0} ({1})", desc, Path.GetFileName(dir)),
                    ID                = "com.sysprogs.arm.nordic." + famBase + "." + id,
                    ClassID           = "com.sysprogs.arm.nordic.nrfx." + id,
                    ProjectFolderName = virtualFolderName,
                    DefaultEnabled    = false,
                    CopyJobs          = new CopyJob[]
                    {
                        new CopyJob
                        {
                            SourceFolder = Path.Combine(baseDir, dir),
                            TargetFolder = @"components\ble\" + dir,
                            FilesToCopy  = "-*_nrf51.c;*.c;*.h",
                        }
                    }
                });
            }

            family.AdditionalFrameworks = family.AdditionalFrameworks.Concat(bleFrameworks).OrderBy(fw => fw.Name).ToArray();
        }
예제 #9
0
        private void GenerateConditionsForPrebuiltLibraries(FamilyDefinition family, Framework fw, CopyJob job)
        {
            var srcDir       = Path.GetFullPath(_Builder.ExpandVariables(job.SourceFolder));
            var allLibraries = Directory.GetFiles(srcDir, "*.a", SearchOption.AllDirectories)
                               .Select(l => l.Substring(srcDir.Length).TrimStart('\\')).ToArray();

            var conditions = new[]
            {
                new PrebuiltLibraryCondition("hard-float", "com.sysprogs.bspoptions.arm.floatmode", "-mfloat-abi=hard", "soft-float"),
                new PrebuiltLibraryCondition("no-interrupts", "com.sysprogs.bspoptions.nrf5x.interrupts", "no"),
                new PrebuiltLibraryCondition("short-wchar", "com.sysprogs.bspoptions.nrf5x.wchar", "-fshort-wchar"),
            };

            Dictionary <string, PrebuiltLibraryCondition> conditionsByFolder = new Dictionary <string, PrebuiltLibraryCondition>();

            foreach (var cond in conditions)
            {
                conditionsByFolder[cond.Folder] = cond;
                if (cond.InverseFolder != null)
                {
                    conditionsByFolder[cond.InverseFolder] = cond;
                }
            }

            foreach (var grp in allLibraries.GroupBy(l => l.Substring(0, l.IndexOf('\\')), StringComparer.InvariantCultureIgnoreCase))
            {
                HashSet <PrebuiltLibraryCondition> allConditionsInGroup = new HashSet <PrebuiltLibraryCondition>();
                List <ConstructedLibraryCondition> libs = new List <ConstructedLibraryCondition>();

                foreach (var lib in grp)
                {
                    List <string> components   = lib.Split('\\').ToList();
                    int           libComponent = components.IndexOf("lib");
                    if (libComponent < 0)
                    {
                        throw new Exception($"Cannot build a list of conditional folders. {lib} does not contain 'lib' in the path.");
                    }

                    components.RemoveRange(0, libComponent + 1);

                    string cortexPrefix = "cortex-";
                    if (!components[0].StartsWith(cortexPrefix))
                    {
                        throw new Exception($"Relative path to {lib} does not start with 'cortex-'");
                    }

                    string cortexCore = components[0].Substring(cortexPrefix.Length);

                    components.RemoveAt(0);
                    components.RemoveAt(components.Count - 1);

                    foreach (var cmp in components)
                    {
                        if (!conditionsByFolder.TryGetValue(cmp, out var cond))
                        {
                            throw new Exception($"Don't know how to map '{cmp}' to a prebuilt library condition");
                        }

                        allConditionsInGroup.Add(cond);
                    }

                    libs.Add(new ConstructedLibraryCondition {
                        Library = $"$$SYS:BSP_ROOT$$/{family.FamilySubdirectory}/{job.TargetFolder}/" + lib.Replace('\\', '/'), PathComponents = components.ToArray(), Core = cortexCore
                    });
                }

                foreach (var lib in libs)
                {
                    List <Condition> finalConditions = new List <Condition>();
                    finalConditions.Add(new Condition.Equals {
                        Expression = "$$com.sysprogs.bspoptions.nrf5x.cortex$$", ExpectedValue = lib.Core
                    });
                    foreach (var usedCond in allConditionsInGroup)
                    {
                        var eqCond = new Condition.Equals {
                            Expression = $"$${usedCond.Variable}$$", ExpectedValue = usedCond.Value
                        };
                        if (lib.PathComponents.Contains(usedCond.Folder))
                        {
                            finalConditions.Add(eqCond);
                        }
                        else
                        {
                            finalConditions.Add(new Condition.Not {
                                Argument = eqCond
                            });
                        }
                    }

                    FileCondition cond = new FileCondition
                    {
                        FilePath           = lib.Library,
                        ConditionToInclude = new Condition.And
                        {
                            Arguments = finalConditions.ToArray()
                        }
                    };

                    _Builder.AddFileCondition(cond);
                }
            }
        }