Example #1
0
        static StartupFileGenerator.InterruptVectorTable GenerateStartupFile(string pDir, string pFBase)
        {
            var vectorTable = new StartupFileGenerator.InterruptVectorTable
            {
                FileName = "startup_" + pFBase + "x.c",
                Vectors  = StartupFileGenerator.ParseInterruptVectors(Path.Combine(pDir, "arm_startup_" + pFBase + ".s"),
                                                                      "^__Vectors",
                                                                      @"__Vectors_End",
                                                                      @"^[ \t]+DCD[ \t]+([^ \t]+)[ \t]+; *([^ \t].*)$",
                                                                      @"^[ \t]+DCD[ \t]+([^ \t]+)$",
                                                                      @"^[ \t]+;.*",
                                                                      null,
                                                                      1,
                                                                      2),
            };

            if (pFBase.ToLower() == "nrf51")
            {
                vectorTable.AdditionalResetHandlerLines = new string[]
                {
                    "asm volatile(\".equ NRF_POWER_RAMON_ADDRESS,0x40000524\");",
                    "asm volatile(\".equ NRF_POWER_RAMON_RAMxON_ONMODE_Msk,3\");",
                    "asm volatile(\"LDR     R0, =NRF_POWER_RAMON_ADDRESS\");",
                    "asm volatile(\"LDR     R2, [R0]\");",
                    "asm volatile(\"MOVS    R1, #NRF_POWER_RAMON_RAMxON_ONMODE_Msk\");",
                    "asm volatile(\"ORR     R2, R2, R1\");",
                    "asm volatile(\"STR     R2, [R0]\");",
                };
            }

            vectorTable.Vectors = new StartupFileGenerator.InterruptVector[] { new StartupFileGenerator.InterruptVector {
                                                                                   Name = "_estack"
                                                                               } }.Concat(vectorTable.Vectors).ToArray();

            vectorTable.MatchPredicate = m => m.Name.StartsWith(pFBase);
            return(vectorTable);
        }
Example #2
0
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                throw new Exception("Usage: nrf5x.exe <Nordic SW package directory>");
            }
            bool usingIoTSDK = false;

            /*            if (Directory.Exists(Path.Combine(args[0], @"components\iot\ble_6lowpan")))
             *          {
             *              usingIoTSDK = true;
             *              Console.WriteLine("Detected IoT SDK");
             *          }*/

            if (usingIoTSDK)
            {
                bspBuilder = new NordicBSPBuilder(new BSPDirectories(args[0], @"..\..\Output", @"..\..\rules_iot"));
                bspBuilder.SoftDevices.Add(new NordicBSPBuilder.SoftDevice("s1xx_iot", 0x1f000, 0x2800, "nrf52", "IoT", bspBuilder.Directories.InputDir));
            }
            else
            {
                bspBuilder = new NordicBSPBuilder(new BSPDirectories(args[0], @"..\..\Output", @"..\..\rules"));
                bspBuilder.SoftDevices.Add(new NordicBSPBuilder.SoftDevice("S132", "nrf52832.*", null, bspBuilder.Directories.InputDir));
                bspBuilder.SoftDevices.Add(new NordicBSPBuilder.SoftDevice("S140", "nrf52840.*", null, bspBuilder.Directories.InputDir));
                bspBuilder.SoftDevices.Add(new NordicBSPBuilder.SoftDevice("S112", "nrf52810.*", null, bspBuilder.Directories.InputDir));
            }
            List <MCUBuilder> devices = new List <MCUBuilder>();

#if NRF51_SUPPORT
            if (!usingIoTSDK)
            {
                foreach (string part in new string[] { "nRF51822", "nRF51422" })
                {
                    devices.Add(new MCUBuilder {
                        Name = part + "_XXAA", FlashSize = 256 * 1024, RAMSize = 16 * 1024, Core = CortexCore.M0
                    });
                    devices.Add(new MCUBuilder {
                        Name = part + "_XXAB", FlashSize = 128 * 1024, RAMSize = 16 * 1024, Core = CortexCore.M0
                    });
                    devices.Add(new MCUBuilder {
                        Name = part + "_XXAC", FlashSize = 256 * 1024, RAMSize = 32 * 1024, Core = CortexCore.M0
                    });
                }
            }
#endif


            devices.Add(new MCUBuilder {
                Name = "nRF52832_XXAA", FlashSize = 512 * 1024, RAMSize = 64 * 1024, Core = CortexCore.M4, StartupFile = "$$SYS:BSP_ROOT$$/nRF5x/components/toolchain/gcc/gcc_startup_nrf52.S"
            });
            devices.Add(new MCUBuilder {
                Name = "nRF52840_XXAA", FlashSize = 1024 * 1024, RAMSize = 256 * 1024, Core = CortexCore.M4, StartupFile = "$$SYS:BSP_ROOT$$/nRF5x/components/toolchain/gcc/gcc_startup_nrf52840.S"
            });
            devices.Add(new MCUBuilder {
                Name = "nRF52810_XXAA", FlashSize = 192 * 1024, RAMSize = 24 * 1024, Core = CortexCore.M4_NOFPU, StartupFile = "$$SYS:BSP_ROOT$$/nRF5x/components/toolchain/gcc/gcc_startup_nrf52810.S"
            });

            List <MCUFamilyBuilder> allFamilies = new List <MCUFamilyBuilder>();
            foreach (var fn in Directory.GetFiles(bspBuilder.Directories.RulesDir + @"\Families", "*.xml"))
            {
                allFamilies.Add(new NordicFamilyBuilder(bspBuilder, XmlTools.LoadObject <FamilyDefinition>(fn)));
            }

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

            List <EmbeddedFramework>             frameworks  = new List <EmbeddedFramework>();
            List <MCUFamilyBuilder.CopiedSample> exampleDirs = new List <MCUFamilyBuilder.CopiedSample>();

            bool noPeripheralRegisters = true;

            List <MCUFamily> familyDefinitions = new List <MCUFamily>();
            List <MCU>       mcuDefinitions    = new List <MCU>();

            var           commonPseudofamily = new MCUFamilyBuilder(bspBuilder, XmlTools.LoadObject <FamilyDefinition>(bspBuilder.Directories.RulesDir + @"\CommonFiles.xml"));
            var           flags        = new ToolFlags();
            List <string> projectFiles = new List <string>();
            commonPseudofamily.CopyFamilyFiles(ref flags, projectFiles);
            flags = flags.Merge(commonPseudofamily.Definition.CompilationFlags);

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

            foreach (var fam in allFamilies)
            {
                fam.GenerateLinkerScripts(false);
                Console.WriteLine("Processing " + fam.Definition.Name + " family...");
                string famBase = fam.Definition.Name.Substring(0, 5).ToLower();

                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);
                    }
                }

                List <Framework> bleFrameworks = new List <Framework>();
                foreach (var line in File.ReadAllLines(bspBuilder.Directories.RulesDir + @"\BLEFrameworks.txt"))
                {
                    int    idx  = line.IndexOf('|');
                    string dir  = line.Substring(0, idx);
                    string desc = line.Substring(idx + 1);

                    string id = Path.GetFileName(dir);
                    if (!id.StartsWith("ble_"))
                    {
                        id = "ble_" + id;
                    }

                    if (dir.StartsWith("services\\", StringComparison.CurrentCultureIgnoreCase))
                    {
                        id = "ble_svc_" + id.Substring(4);
                    }

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

                fam.Definition.AdditionalFrameworks = fam.Definition.AdditionalFrameworks.Concat(bleFrameworks).ToArray();

                // Starting from SDK 14.0 we use the original Nordic startup files & linker scripts as they contain various non-trivial logic
#if GENERATE_STARTUP_FILES
                StartupFileGenerator.InterruptVectorTable[] aStartupVectors;
                if (usingIoTSDK)
                {
                    aStartupVectors = new StartupFileGenerator.InterruptVectorTable[] {
                        GenerateStartupFile(fam.Definition.StartupFileDir, "nRF52")
                    }
                }
                ;
                else
                {
                    aStartupVectors = new StartupFileGenerator.InterruptVectorTable[] {
                        GenerateStartupFile(fam.Definition.StartupFileDir, "nRF51"),
                        GenerateStartupFile(fam.Definition.StartupFileDir, "nRF52")
                    }
                };

                fam.AttachStartupFiles(aStartupVectors);
#endif

                //  SVD Files
                var aMcuDef1 = (new MCUDefinitionWithPredicate[] { SVDParser.ParseSVDFile(Path.Combine(fam.Definition.PrimaryHeaderDir, "nRF51.svd"), "nRF51") });
                aMcuDef1[0].MatchPredicate = m => m.Name.StartsWith("nRF51");

                var aMcuDef2 = (new MCUDefinitionWithPredicate[] { SVDParser.ParseSVDFile(Path.Combine(fam.Definition.PrimaryHeaderDir, "nRF52.svd"), "nRF52") });
                aMcuDef2[0].MatchPredicate = m => m.Name.StartsWith("nRF52");

                fam.AttachPeripheralRegisters(aMcuDef1.Concat(aMcuDef2));

                var famObj = fam.GenerateFamilyObject(true);

                famObj.AdditionalSourceFiles = LoadedBSP.Combine(famObj.AdditionalSourceFiles, projectFiles.Where(f => !MCUFamilyBuilder.IsHeaderFile(f)).ToArray());
                famObj.AdditionalHeaderFiles = LoadedBSP.Combine(famObj.AdditionalHeaderFiles, projectFiles.Where(f => MCUFamilyBuilder.IsHeaderFile(f)).ToArray());

                famObj.AdditionalSystemVars = LoadedBSP.Combine(famObj.AdditionalSystemVars, commonPseudofamily.Definition.AdditionalSystemVars);
                famObj.CompilationFlags     = famObj.CompilationFlags.Merge(flags);

                familyDefinitions.Add(famObj);
                fam.GenerateLinkerScripts(false);

                SysVarEntry suffixEntry = null;

                foreach (var mcu in fam.MCUs)
                {
                    var mcuDef = mcu.GenerateDefinition(fam, bspBuilder, !noPeripheralRegisters, false, MCUFamilyBuilder.CoreSpecificFlags.All & ~MCUFamilyBuilder.CoreSpecificFlags.PrimaryMemory);

                    if (mcu.Name.StartsWith("nRF52832"))
                    {
                        //Although documented as a legacy definition, skipping this breaks fds_internal_defs.h
                        mcuDef.CompilationFlags.PreprocessorMacros = mcuDef.CompilationFlags.PreprocessorMacros.Concat(new[] { "NRF52" }).ToArray();
                    }

                    var compatibleSoftdevs = new[]
                    {
                        new PropertyEntry.Enumerated.Suggestion {
                            InternalValue = "nosoftdev", UserFriendlyName = "None"
                        }
                    }
                    .Concat(bspBuilder.SoftDevices.Where(sd => sd.IsCompatible(mcu.Name))
                            .SelectMany(s => new[]
                    {
                        new PropertyEntry.Enumerated.Suggestion {
                            InternalValue = s.Name, UserFriendlyName = s.UserFriendlyName
                        },
                        new PropertyEntry.Enumerated.Suggestion {
                            InternalValue = s.Name + "_reserve", UserFriendlyName = $"{s.UserFriendlyName} (programmed separately)"
                        }
                    }))
                    .ToArray();

                    if (mcuDef.ConfigurableProperties == null)
                    {
                        mcuDef.ConfigurableProperties = new PropertyList {
                            PropertyGroups = new List <PropertyGroup>()
                        }
                    }
                    ;
                    mcuDef.ConfigurableProperties.PropertyGroups.Add(new PropertyGroup
                    {
                        Properties = new List <PropertyEntry>
                        {
                            new PropertyEntry.Enumerated
                            {
                                UniqueID          = NordicBSPBuilder.SoftdevicePropertyID,
                                Name              = "Softdevice",
                                DefaultEntryIndex = 1,
                                SuggestionList    = compatibleSoftdevs,
                            }
                        }
                    });

                    if (mcu.Name.StartsWith("nRF52") && !mcu.Name.StartsWith("nRF52810"))
                    {
                        var prop = mcuDef.ConfigurableProperties.PropertyGroups[0].Properties.Find(p => p.UniqueID == "com.sysprogs.bspoptions.arm.floatmode") as PropertyEntry.Enumerated;
                        var idx  = Array.FindIndex(prop.SuggestionList, p => p.UserFriendlyName == "Hardware");
                        prop.DefaultEntryIndex = idx;
                        prop.SuggestionList[idx].UserFriendlyName = "Hardware (required when using a softdevice)";   //Otherwise the system_nrf52.c file won't initialize the FPU and the internal initialization of the softdevice will later fail.
                    }

                    string defaultConfig;
                    if (mcu.Name.StartsWith("nRF52840"))
                    {
                        defaultConfig = "pca10056/s140";
                    }
                    else if (mcu.Name.StartsWith("nRF52810"))
                    {
                        defaultConfig = "pca10040e/s112";
                    }
                    else
                    {
                        defaultConfig = "pca10040/s132";
                    }

                    suffixEntry = new SysVarEntry {
                        Key = "com.sysprogs.nordic.default_config_suffix", Value = defaultConfig
                    };
                    mcuDef.AdditionalSystemVars = LoadedBSP.Combine(mcuDef.AdditionalSystemVars, new SysVarEntry[] { suffixEntry });

                    mcuDefinitions.Add(mcuDef);
                }

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

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

                foreach (var sample in fam.CopySamples(null, new SysVarEntry[] { new SysVarEntry {
                                                                                     Key = "com.sysprogs.nordic.default_config_suffix", Value = "pca10040e/s112"
                                                                                 } }))
                {
                    exampleDirs.Add(sample);
                }
            }

            const string softdevExpression = "$$com.sysprogs.bspoptions.nrf5x.softdevice$$";

            foreach (var softdev in bspBuilder.SoftDevices)
            {
                condFlags.Add(new ConditionalToolFlags
                {
                    FlagCondition = new Condition.Equals {
                        Expression = softdevExpression, ExpectedValue = softdev.Name + "_reserve"
                    },
                    Flags = new ToolFlags
                    {
                        PreprocessorMacros = familyDefinitions.First().CompilationFlags.PreprocessorMacros.Where(f => f.Contains(softdevExpression)).Select(f => f.Replace(softdevExpression, softdev.Name)).ToArray(),
                        IncludeDirectories = familyDefinitions.First().CompilationFlags.IncludeDirectories.Where(f => f.Contains(softdevExpression)).Select(f => f.Replace(softdevExpression, softdev.Name)).ToArray()
                    }
                });
            }

            bspBuilder.GenerateSoftdeviceLibraries();

            Console.WriteLine("Building BSP archive...");
            string strPackageID, strPackageDesc, strPAckVersion;
            if (usingIoTSDK)
            {
                strPackageID   = "com.sysprogs.arm.nordic.nrf5x-iot";
                strPackageDesc = "Nordic NRF52 IoT";
                strPAckVersion = "0.9";

                foreach (var mcu in mcuDefinitions)
                {
                    mcu.UserFriendlyName = mcu.ID + " (IoT)";
                }
            }
            else
            {
                strPackageID   = "com.sysprogs.arm.nordic.nrf5x";
                strPackageDesc = "Nordic NRF52x Devices";
                strPAckVersion = "14.2R2";
            }

            BoardSupportPackage bsp = new BoardSupportPackage
            {
                PackageID            = strPackageID,
                PackageDescription   = strPackageDesc,
                GNUTargetID          = "arm-eabi",
                GeneratedMakFileName = "nrf5x.mak",
                MCUFamilies          = familyDefinitions.ToArray(),
                SupportedMCUs        = mcuDefinitions.ToArray(),
                Frameworks           = frameworks.ToArray(),
                Examples             = exampleDirs.Where(s => !s.IsTestProjectSample).Select(s => s.RelativePath).ToArray(),
                TestExamples         = exampleDirs.Where(s => s.IsTestProjectSample).Select(s => s.RelativePath).ToArray(),
                PackageVersion       = strPAckVersion,
                FileConditions       = bspBuilder.MatchedFileConditions.ToArray(),
                MinimumEngineVersion = "5.0",
                ConditionalFlags     = condFlags.ToArray(),
                InitializationCodeInsertionPoints = commonPseudofamily.Definition.InitializationCodeInsertionPoints,
            };

            bspBuilder.Save(bsp, true, false);
        }
    }
Example #3
0
        static void Main(string[] args)
        {
            if (args.Length < 1)
            {
                throw new Exception("Usage: nrf5x.exe <Nordic SW package directory>");
            }
            bool usingIoTSDK = false;

            if (Directory.Exists(Path.Combine(args[0], @"components\iot\ble_6lowpan")))
            {
                usingIoTSDK = true;
                Console.WriteLine("Detected IoT SDK");
            }

            NordicBSPBuilder bspBuilder;

            if (usingIoTSDK)
            {
                bspBuilder = new NordicBSPBuilder(new BSPDirectories(args[0], @"..\..\Output", @"..\..\rules_iot"));
                bspBuilder.SoftDevices.Add(new NordicBSPBuilder.SoftDevice("s1xx_iot", 0x1f000, 0x2800, "nrf52", "IoT"));
            }
            else
            {
                bspBuilder = new NordicBSPBuilder(new BSPDirectories(args[0], @"..\..\Output", @"..\..\rules"));
                bspBuilder.SoftDevices.Add(new NordicBSPBuilder.SoftDevice("S130", 0x1b000, 0x13c8, "nrf51", "Bluetooth LE Universal"));
                bspBuilder.SoftDevices.Add(new NordicBSPBuilder.SoftDevice("S132", 0x20000, 0x2168, "nrf52832", "Bluetooth LE"));
                bspBuilder.SoftDevices.Add(new NordicBSPBuilder.SoftDevice("S140", 0x21000, 0x2780, "nrf52840", "Bluetooth LE"));
            }
            List <MCUBuilder> devices = new List <MCUBuilder>();

            if (!usingIoTSDK)
            {
                foreach (string part in new string[] { "nRF51822", "nRF51422" })
                {
                    devices.Add(new MCUBuilder {
                        Name = part + "_XXAA", FlashSize = 256 * 1024, RAMSize = 16 * 1024, Core = CortexCore.M0
                    });
                    devices.Add(new MCUBuilder {
                        Name = part + "_XXAB", FlashSize = 128 * 1024, RAMSize = 16 * 1024, Core = CortexCore.M0
                    });
                    devices.Add(new MCUBuilder {
                        Name = part + "_XXAC", FlashSize = 256 * 1024, RAMSize = 32 * 1024, Core = CortexCore.M0
                    });
                }
            }

            devices.Add(new MCUBuilder {
                Name = "nRF52832_XXAA", FlashSize = 512 * 1024, RAMSize = 64 * 1024, Core = CortexCore.M4
            });
            devices.Add(new MCUBuilder {
                Name = "nRF52840_XXAA", FlashSize = 1024 * 1024, RAMSize = 256 * 1024, Core = CortexCore.M4
            });

            List <MCUFamilyBuilder> allFamilies = new List <MCUFamilyBuilder>();

            foreach (var fn in Directory.GetFiles(bspBuilder.Directories.RulesDir + @"\Families", "*.xml"))
            {
                allFamilies.Add(new MCUFamilyBuilder(bspBuilder, XmlTools.LoadObject <FamilyDefinition>(fn)));
            }

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

            List <EmbeddedFramework>             frameworks  = new List <EmbeddedFramework>();
            List <MCUFamilyBuilder.CopiedSample> exampleDirs = new List <MCUFamilyBuilder.CopiedSample>();

            bool noPeripheralRegisters = true;

            List <MCUFamily> familyDefinitions = new List <MCUFamily>();
            List <MCU>       mcuDefinitions    = new List <MCU>();

            var           commonPseudofamily = new MCUFamilyBuilder(bspBuilder, XmlTools.LoadObject <FamilyDefinition>(bspBuilder.Directories.RulesDir + @"\CommonFiles.xml"));
            var           flags        = new ToolFlags();
            List <string> projectFiles = new List <string>();

            commonPseudofamily.CopyFamilyFiles(ref flags, projectFiles);
            flags = flags.Merge(commonPseudofamily.Definition.CompilationFlags);

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

            foreach (var fam in allFamilies)
            {
                Console.WriteLine("Processing " + fam.Definition.Name + " family...");
                string famBase = fam.Definition.Name.Substring(0, 5).ToLower();

                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);
                    }
                }

                List <Framework> bleFrameworks = new List <Framework>();
                foreach (var line in File.ReadAllLines(bspBuilder.Directories.RulesDir + @"\BLEFrameworks.txt"))
                {
                    int    idx  = line.IndexOf('|');
                    string dir  = line.Substring(0, idx);
                    string desc = line.Substring(idx + 1);

                    string id = Path.GetFileName(dir);
                    if (!id.StartsWith("ble_"))
                    {
                        id = "ble_" + id;
                    }

                    if (dir.StartsWith("services\\", StringComparison.CurrentCultureIgnoreCase))
                    {
                        id = "ble_svc_" + id.Substring(4);
                    }

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

                fam.Definition.AdditionalFrameworks = fam.Definition.AdditionalFrameworks.Concat(bleFrameworks).ToArray();
                // Startup Files
                StartupFileGenerator.InterruptVectorTable[] aStartupVectors;
                if (usingIoTSDK)
                {
                    aStartupVectors = new StartupFileGenerator.InterruptVectorTable[] {
                        GenerateStartupFile(fam.Definition.StartupFileDir, "nRF52")
                    }
                }
                ;
                else
                {
                    aStartupVectors = new StartupFileGenerator.InterruptVectorTable[] {
                        GenerateStartupFile(fam.Definition.StartupFileDir, "nRF51"),
                        GenerateStartupFile(fam.Definition.StartupFileDir, "nRF52")
                    }
                };

                fam.AttachStartupFiles(aStartupVectors);
                //  SVD Files
                var aMcuDef1 = (new MCUDefinitionWithPredicate[] { SVDParser.ParseSVDFile(Path.Combine(fam.Definition.PrimaryHeaderDir, "nRF51.svd"), "nRF51") });
                aMcuDef1[0].MatchPredicate = m => m.Name.StartsWith("nRF51");

                var aMcuDef2 = (new MCUDefinitionWithPredicate[] { SVDParser.ParseSVDFile(Path.Combine(fam.Definition.PrimaryHeaderDir, "nRF52.svd"), "nRF52") });
                aMcuDef2[0].MatchPredicate = m => m.Name.StartsWith("nRF52");

                fam.AttachPeripheralRegisters(aMcuDef1.Concat(aMcuDef2));

                var famObj = fam.GenerateFamilyObject(true);

                famObj.AdditionalSourceFiles = LoadedBSP.Combine(famObj.AdditionalSourceFiles, projectFiles.Where(f => !MCUFamilyBuilder.IsHeaderFile(f)).ToArray());
                famObj.AdditionalHeaderFiles = LoadedBSP.Combine(famObj.AdditionalHeaderFiles, projectFiles.Where(f => MCUFamilyBuilder.IsHeaderFile(f)).ToArray());

                famObj.AdditionalSystemVars = LoadedBSP.Combine(famObj.AdditionalSystemVars, commonPseudofamily.Definition.AdditionalSystemVars);
                famObj.CompilationFlags     = famObj.CompilationFlags.Merge(flags);

                familyDefinitions.Add(famObj);
                fam.GenerateLinkerScripts(false);

                SysVarEntry defaultConfigFolder51 = new SysVarEntry {
                    Key = "com.sysprogs.nordic.default_config_suffix", Value = "pca10040/s132"
                };                                                                                                                                 // s132_pca10036" };
                SysVarEntry defaultConfigFolder52 = new SysVarEntry {
                    Key = "com.sysprogs.nordic.default_config_suffix", Value = "pca10028/s130"
                };                                                                                                                                 // s130_pca10028" };

                foreach (var mcu in fam.MCUs)
                {
                    var mcuDef = mcu.GenerateDefinition(fam, bspBuilder, !noPeripheralRegisters);
                    var compatibleSoftdevs = new PropertyEntry.Enumerated.Suggestion[] { new PropertyEntry.Enumerated.Suggestion {
                                                                                             InternalValue = "nosoftdev", UserFriendlyName = "None"
                                                                                         } }.Concat(bspBuilder.SoftDevices.Where(sd => sd.IsCompatible(mcu.Name)).Select(s => new PropertyEntry.Enumerated.Suggestion {
                        InternalValue = s.Name, UserFriendlyName = s.UserFriendlyName
                    })).ToArray();

                    if (mcuDef.ConfigurableProperties == null)
                    {
                        mcuDef.ConfigurableProperties = new PropertyList {
                            PropertyGroups = new List <PropertyGroup>()
                        }
                    }
                    ;
                    mcuDef.ConfigurableProperties.PropertyGroups.Add(new PropertyGroup
                    {
                        Properties = new List <PropertyEntry>
                        {
                            new PropertyEntry.Enumerated
                            {
                                UniqueID          = NordicBSPBuilder.SoftdevicePropertyID,
                                Name              = "Softdevice",
                                DefaultEntryIndex = 1,
                                SuggestionList    = compatibleSoftdevs,
                            }
                        }
                    });

                    if (mcu.Name.StartsWith("nRF52"))
                    {
                        var prop = mcuDef.ConfigurableProperties.PropertyGroups[0].Properties.Find(p => p.UniqueID == "com.sysprogs.bspoptions.arm.floatmode") as PropertyEntry.Enumerated;
                        var idx  = Array.FindIndex(prop.SuggestionList, p => p.UserFriendlyName == "Hardware");
                        prop.DefaultEntryIndex = idx;
                        prop.SuggestionList[idx].UserFriendlyName = "Hardware (required when using a softdevice)";   //Otherwise the system_nrf52.c file won't initialize the FPU and the internal initialization of the softdevice will later fail.

                        mcuDef.AdditionalSystemVars = LoadedBSP.Combine(mcuDef.AdditionalSystemVars, new SysVarEntry[] { defaultConfigFolder51 });
                    }
                    else
                    {
                        mcuDef.AdditionalSystemVars = LoadedBSP.Combine(mcuDef.AdditionalSystemVars, new SysVarEntry[] { defaultConfigFolder52 });
                    }

                    mcuDefinitions.Add(mcuDef);
                }

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

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

                foreach (var sample in fam.CopySamples(null, new SysVarEntry[] { defaultConfigFolder51 }))
                {
                    exampleDirs.Add(sample);
                }
                //                var prioritizer = new SamplePrioritizer(Path.Combine(bspBuilder.Directories.RulesDir, "SamplePriorities.txt"));
                //                exampleDirs.Sort((a, b) => prioritizer.Prioritize(a.RelativePath, b.RelativePath));
            }
            bspBuilder.GenerateSoftdeviceLibraries();

            Console.WriteLine("Building BSP archive...");
            string strPackageID, strPackageDesc, strPAckVersion;

            if (usingIoTSDK)
            {
                strPackageID   = "com.sysprogs.arm.nordic.nrf5x-iot";
                strPackageDesc = "Nordic NRF52 IoT";
                strPAckVersion = "0.9";

                foreach (var mcu in mcuDefinitions)
                {
                    mcu.UserFriendlyName = mcu.ID + " (IoT)";
                }
            }
            else
            {
                strPackageID   = "com.sysprogs.arm.nordic.nrf5x";
                strPackageDesc = "Nordic NRF5x Devices";
                strPAckVersion = "13.0-alpha";
            }

            BoardSupportPackage bsp = new BoardSupportPackage
            {
                PackageID            = strPackageID,
                PackageDescription   = strPackageDesc,
                GNUTargetID          = "arm-eabi",
                GeneratedMakFileName = "nrf5x.mak",
                MCUFamilies          = familyDefinitions.ToArray(),
                SupportedMCUs        = mcuDefinitions.ToArray(),
                Frameworks           = frameworks.ToArray(),
                Examples             = exampleDirs.Where(s => !s.IsTestProjectSample).Select(s => s.RelativePath).ToArray(),
                TestExamples         = exampleDirs.Where(s => s.IsTestProjectSample).Select(s => s.RelativePath).ToArray(),
                PackageVersion       = strPAckVersion,
                FileConditions       = bspBuilder.MatchedFileConditions.ToArray(),
                MinimumEngineVersion = "5.0",
                ConditionalFlags     = condFlags.ToArray(),
            };

            bspBuilder.Save(bsp, true);
        }
    }
}