public static HardwareRegisterSet[] GenerateFamilyPeripheralRegisters(string PeripheralHeaderFile, RegisterParserConfiguration cfg, RegisterParserErrors errors, BSPGenerationTools.CortexCore atCore)
        {
            string file = File.ReadAllText(PeripheralHeaderFile);

            Dictionary<string, ulong> registerset_addresses = ProcessRegisterSetAddresses(PeripheralHeaderFile, file, cfg, errors);
            Dictionary<string, KeyValuePair<string, string>> registerset_names = ProcessRegisterSetNames(file);// (name, (type, addr))
            Dictionary<string, string> nested_types;
            Dictionary<string, HardwareRegisterSet> registerset_types = ProcessRegisterSetTypes(file, out nested_types);
            Dictionary<string, List<HardwareSubRegister>> subregisters = ProcessSubregisters(file, PeripheralHeaderFile, cfg, errors);

            // Process registers and register sets

            List<HardwareRegisterSet> sets = new List<HardwareRegisterSet>();
            KnownValueDatabase knonwValues = new KnownValueDatabase();

            Dictionary<string, string> dict_repeat_reg_addr = new Dictionary<string, string>();

            HardwareRegisterSet regCore = null;
            string aFileCore = "";

            switch (atCore)
            {
                case BSPGenerationTools.CortexCore.M0:
                    aFileCore = Path.Combine(DirCoreReg, "core_M0.xml");
                    break;
                case BSPGenerationTools.CortexCore.M0Plus:
                    aFileCore = Path.Combine(DirCoreReg, "core_M0Plus.xml");
                    break;
                case BSPGenerationTools.CortexCore.M3:
                    aFileCore = Path.Combine(DirCoreReg, "core_M3.xml");
                    break;
                case BSPGenerationTools.CortexCore.M4:
                    aFileCore = Path.Combine(DirCoreReg, "core_M4.xml");
                    break;
                case BSPGenerationTools.CortexCore.M7:
                    aFileCore = Path.Combine(DirCoreReg, "core_M7.xml");
                    break;
                default:
                  throw new Exception("Unsupported core type");

            }
            regCore = XmlTools.LoadObject<HardwareRegisterSet>(aFileCore);
            sets.Add(regCore);

            foreach (var set in registerset_names)
            {
                string set_name = set.Key;
                string set_type = set.Value.Key;
                ulong set_addr;
                if (!registerset_addresses.TryGetValue(set.Value.Value, out set_addr))
                {
                    if (set.Value.Value == "USB")
                        continue;
                    throw new Exception("Cannot find base address for " + set.Value.Value);
                }
                if (registerset_addresses.ContainsKey(set_name + "1") && (set_addr == registerset_addresses[set_name + "1"]))
                    continue;// Ignore generic aliases

                if (!registerset_types.ContainsKey(set.Value.Key))
                {
                    if (set.Value.Key == "HASH_DIGEST" || set.Value.Key == "HRTIM" || set.Value.Key == "HRTIM_TIM")
                        continue;
                    if(set.Value.Key == "DMA_request")
                        continue;
                    throw new Exception("Unknown set type: " + set.Value.Key);

                }

                List<HardwareRegister> registers = new List<HardwareRegister>(DeepCopy(registerset_types[set.Value.Key]).Registers);

                for (int i = 0; i < registers.Count;i++ )
                {
                    var register = registers[i];

                    string hex_offset = register.Address;
                    if (!string.IsNullOrEmpty(hex_offset))
                    {
                        ulong offset = ParseHex(hex_offset);
                        hex_offset = register.Address = FormatToHex((set_addr + offset));
                    }
                    else
                        throw new Exception("Register address not specified!");

                    if (!nested_types.ContainsKey(set_type + "_" + register.Name))
                        if (!dict_repeat_reg_addr.ContainsKey(register.Address))
                            dict_repeat_reg_addr[register.Address] = set_name + "_" + register.Name;
                        else if (!(set_name.StartsWith("FMC_") && dict_repeat_reg_addr[register.Address].StartsWith("FSMC_")) &&
                                !(set_name.StartsWith("ADC") && dict_repeat_reg_addr[register.Address].StartsWith("ADC1")) &&
                                 !(set_name.StartsWith("DAC") && dict_repeat_reg_addr[register.Address].StartsWith("DAC")) &&
                                 !(set_name.StartsWith("COMP") && dict_repeat_reg_addr[register.Address].StartsWith("COMP")) &&
                                (set_type != "SC_UART") && (set_type != "SC_SPI") && (set_type != "SC_I2C") && (set_type != "COMP") && (set_type != "OPAMP") && (set_type != "OPAMP_Common"))// This register is removed later on anyway as it is an either/or thing
                                                                                                                                                             //        throw new Exception("Register address for " + set_name + "_" + register.Name + " is already used by " + dict_repeat_reg_addr[register.Address] + "!");
                            Console.WriteLine("560 PrepReg throw new Exception(Register address for " + set_name + "_" + register.Name + " is already used by " + dict_repeat_reg_addr[register.Address] + "!");

                    if (subregisters.ContainsKey(set_type + "_" + register.Name))
                    {
                        // Do some cleanup on the subregisters - remove all subregisters with the same size as the register itself and the same name as the register
                        List<HardwareSubRegister> subreg_to_clean = subregisters[set_type + "_" + register.Name];
                        for (int j = 0; j < subreg_to_clean.Count; j++)
                        {
                            HardwareSubRegister subreg_clean = subreg_to_clean[j];
                            if ((subreg_clean.Name == register.Name) && (subreg_clean.SizeInBits == register.SizeInBits))
                            {
                                subreg_to_clean.RemoveAt(j);
                                j--;
                                Debug.WriteLine("Removed unnecessary subregister at " + register.Name);
                            }
                        }

                        if (subreg_to_clean.Count > 0)
                            register.SubRegisters = subreg_to_clean.ToArray();
                    }
                    else if (nested_types.ContainsKey(set_type + "_" + register.Name))
                    {
                        string reg_name = register.Name;
                        HardwareRegister[] registers2 = registerset_types[nested_types[set_type + "_" + reg_name]].Registers;
                        registers.Remove(register);
                        i--;

                        foreach (var register2 in registers2)
                        {
                            HardwareRegister register2_cpy = DeepCopy(register2);

                            string hex_offset2 = register2_cpy.Address;
                            if (!string.IsNullOrEmpty(register.Address) && !string.IsNullOrEmpty(hex_offset2))
                            {
                                ulong offset = ParseHex(register.Address);
                                ulong offset2 = ParseHex(hex_offset2);
                                register2_cpy.Address = FormatToHex((offset + offset2));
                            }

                            if (subregisters.ContainsKey(nested_types[set_type + "_" + reg_name] + "_" + register2_cpy.Name))
                                register2_cpy.SubRegisters = subregisters[nested_types[set_type + "_" + reg_name] + "_" + register2_cpy.Name].ToArray();
                            else if (((nested_types[set_type + "_" + reg_name] != "CAN_TxMailBox")) && // Does not have any subregisters for any of its registers
                                ((nested_types[set_type + "_" + reg_name] != "CAN_FilterRegister")) && // Does not have any subregisters for any of its registers
                                ((nested_types[set_type + "_" + reg_name] != "CAN_FIFOMailBox"))) // Does not have any subregisters for any of its registers
                                throw new Exception("No subregisters found for register " + register2_cpy.Name + "!");

                            register2_cpy.Name = reg_name + "_" + register2_cpy.Name; // Make nested name to collapse the hierarchy

                            registers.Insert(i, register2_cpy);
                            if (!dict_repeat_reg_addr.ContainsKey(register2_cpy.Address))
                                dict_repeat_reg_addr[register2_cpy.Address] = set_name + "_" + register2_cpy.Name;
                            else
                                throw new Exception("Register address for" + set_name + "_" + register2_cpy.Name + " is already used by " + dict_repeat_reg_addr[register2_cpy.Address] + "!");
                            i++;
                        }
                    }
                    else if (set_type.StartsWith("HRTIM"))
                    {
                        List<HardwareSubRegister> subregs;
                        if (subregisters.TryGetValue("HRTIM_" + register.Name, out subregs))
                            register.SubRegisters = subregs.ToArray();
                        else if (register.Name.EndsWith("UPR"))
                            continue;
                        else
                            errors.AddError(new RegisterParserErrors.MissingSubregisterDefinitions { FileName = PeripheralHeaderFile, SetName = set_name, RegisterName = register.Name });
                    }
                    else if ((set_name == "DAC") && (register.Name == "DHR12R2"))//Header BUG: subregister definition missing
                    {
                        register.SubRegisters = new HardwareSubRegister[] {
                            new HardwareSubRegister { Name = "DACC2DHR", FirstBit = 0, SizeInBits = 12 }
                        };
                    }
                    else if ((set_name == "DAC") && (register.Name == "DHR12L2"))//Header BUG: subregister definition missing
                    {
                        register.SubRegisters = new HardwareSubRegister[] {
                            new HardwareSubRegister { Name = "DACC2DHR", FirstBit = 4, SizeInBits = 12 }
                        };
                    }
                    else if ((set_name == "DAC") && (register.Name == "DHR8R2"))//Header BUG: subregister definition missing
                    {
                        register.SubRegisters = new HardwareSubRegister[] {
                            new HardwareSubRegister { Name = "DACC2DHR", FirstBit = 0, SizeInBits = 8 }
                        };
                    }
                    else if ((set_name == "DAC") && (register.Name == "DHR12RD"))//Header BUG: subregister definition missing
                    {
                        register.SubRegisters = new HardwareSubRegister[] {
                            new HardwareSubRegister { Name = "DACC1DHR", FirstBit = 0, SizeInBits = 12 },
                            new HardwareSubRegister { Name = "DACC2DHR", FirstBit = 16, SizeInBits = 12 }
                        };
                    }
                    else if ((set_name == "DAC") && (register.Name == "DHR12LD"))//Header BUG: subregister definition missing
                    {
                        register.SubRegisters = new HardwareSubRegister[] {
                            new HardwareSubRegister { Name = "DACC1DHR", FirstBit = 4, SizeInBits = 12 },
                            new HardwareSubRegister { Name = "DACC2DHR", FirstBit = 20, SizeInBits = 12 }
                        };
                    }
                    else if ((set_name == "DAC") && (register.Name == "DHR8RD"))//Header BUG: subregister definition missing
                    {
                        register.SubRegisters = new HardwareSubRegister[] {
                            new HardwareSubRegister { Name = "DACC1DHR", FirstBit = 0, SizeInBits = 8 },
                            new HardwareSubRegister { Name = "DACC2DHR", FirstBit = 8, SizeInBits = 8 }
                        };
                    }
                    else if ((set_name == "DAC") && (register.Name == "DOR2"))//Header BUG: subregister definition missing
                    {
                        register.SubRegisters = new HardwareSubRegister[] {
                            new HardwareSubRegister { Name = "DACC2DOR", FirstBit = 0, SizeInBits = 12 }
                        };
                    }
                    else if ((set_type == "USB_OTG") && (register.Name == "HNPTXSTS"))//Header BUG: subregister definition missing
                    {
                        register.SubRegisters = new HardwareSubRegister[] {
                            new HardwareSubRegister { Name = "NPTXQTOP", FirstBit = 24, SizeInBits = 7 },
                            new HardwareSubRegister { Name = "NPTQXSAV", FirstBit = 16, SizeInBits = 8 },
                            new HardwareSubRegister { Name = "NPTXFSAV", FirstBit = 0, SizeInBits = 16 }
                        };
                    }
                    else if (((set_name == "FLASH") && ((register.Name == "KEYR2") || (register.Name == "SR2") || (register.Name == "CR2") || (register.Name == "AR2"))))// Reuse subregisters from non-2 FLASH registers
                        register.SubRegisters = subregisters[set_type + "_" + register.Name.Substring(0, register.Name.Length - 1)].ToArray();
                    else if ((set_name.StartsWith("GPIO") && ((register.Name == "BSRRL") || (register.Name == "BSRRH"))))// Reuse subregisters from BSRR defs
                        register.SubRegisters = subregisters[set_type + "_" + register.Name.Substring(0, register.Name.Length - 1)].ToArray();
                    else if (((set_name.StartsWith("DMA1_Stream") || (set_name.StartsWith("DMA2_Stream"))) && (register.Name == "CR")))// Reuse subregisters from DMA_SxCR defs
                        register.SubRegisters = subregisters["DMA_SxCR"].ToArray();
                    else if (((set_name.StartsWith("DMA1_Stream") || (set_name.StartsWith("DMA2_Stream"))) && (register.Name == "NDTR")))// Reuse subregisters from DMA_SxCNDTR defs
                        register.SubRegisters = subregisters["DMA_SxCNDTR"].ToArray();
                    else if (((set_name.StartsWith("DMA1_Stream") || (set_name.StartsWith("DMA2_Stream"))) && (register.Name == "FCR")))// Reuse subregisters from DMA_SxFCR defs
                        register.SubRegisters = subregisters["DMA_SxFCR"].ToArray();
                    else if ((set_name == "OPAMP") && (register.Name == "CSR"))// Reuse subregisters from OPAMPx_CSR defs
                        register.SubRegisters = subregisters["OPAMPx_CSR"].ToArray();
                    else if ((set_name.StartsWith("OPAMP")) && (register.Name == "CSR"))// Reuse subregisters from OPAMPx_CSR defs
                        register.SubRegisters = subregisters[set_name + "_" + register.Name].ToArray();
                    else if ((set_name.StartsWith("EXTI")) && (register.Name == "IMR2"))// Reuse subregisters
                        register.SubRegisters = subregisters["EXTI_IMR"].ToArray();
                    else if ((set_name.StartsWith("EXTI")) && (register.Name == "EMR2"))// Reuse subregisters
                        register.SubRegisters = subregisters["EXTI_EMR"].ToArray();
                    else if ((set_name.StartsWith("EXTI")) && (register.Name == "RTSR2"))// Reuse subregisters
                        register.SubRegisters = subregisters["EXTI_RTSR"].ToArray();
                    else if ((set_name.StartsWith("EXTI")) && (register.Name == "FTSR2"))// Reuse subregisters
                        register.SubRegisters = subregisters["EXTI_FTSR"].ToArray();
                    else if ((set_name.StartsWith("EXTI")) && (register.Name == "SWIER2"))// Reuse subregisters
                        register.SubRegisters = subregisters["EXTI_SWIER"].ToArray();
                    else if ((set_name.StartsWith("EXTI")) && (register.Name == "PR2"))// Reuse subregisters
                        register.SubRegisters = subregisters["EXTI_PR"].ToArray();
                    else if ((set_name.StartsWith("EXTI")) && (register.Name.StartsWith("TSR")))// Reuse subregisters
                        register.SubRegisters = subregisters["EXTI_TSR"].ToArray();
                    else if ((set_name.StartsWith("EXTI")) && (register.Name.StartsWith("CR")))// Reuse subregisters
                        register.SubRegisters = subregisters["EXTI_CR"].ToArray();
                    else if ((set_name.StartsWith("ADC1_2")))// Reuse subregisters
                        register.SubRegisters = subregisters["ADC12_" + register.Name].ToArray();
                    else if ((set_name.StartsWith("ADC1_")))// Reuse subregisters
                        register.SubRegisters = subregisters["ADC_" + register.Name].ToArray();
                    else if ((set_name.StartsWith("ADC12_")))// Reuse subregisters
                        register.SubRegisters = subregisters["ADC_" + register.Name].ToArray();
                    else if ((set_name.StartsWith("ADC3_4")))// Reuse subregisters
                        register.SubRegisters = subregisters["ADC34_" + register.Name].ToArray();
                    else if (((set_type == "SAI_Block")))// Reuse subregisters
                        register.SubRegisters = subregisters["SAI_x" + register.Name].ToArray();
                    else if (((set_type == "LTDC_Layer")))// Reuse subregisters
                        register.SubRegisters = subregisters["LTDC_Lx" + register.Name].ToArray();
                    else if (((set_type == "LCD") && (register.Name.StartsWith("RAM"))))// Reuse subregisters
                        register.SubRegisters = subregisters["LCD_RAM"].ToArray();
                    else if (((set_type == "PWR") && ((register.Name == "WAKEPAR") || (register.Name == "WAKEPBR") || (register.Name == "WAKEPCR"))))// Reuse subregisters
                        register.SubRegisters = subregisters["PWR_WAKEPxR"].ToArray();
                    else if ((((set_type == "SC_UART") || (set_type == "SC_SPI") || (set_type == "SC_I2C")) && (register.Name == "DR")))// Reuse subregisters
                        register.SubRegisters = subregisters["SC_DR"].ToArray();
                    else if ((((set_type == "SC_UART") || (set_type == "SC_SPI") || (set_type == "SC_I2C")) && (register.Name == "CR")))// Reuse subregisters
                        register.SubRegisters = subregisters["SC_CR"].ToArray();
                    else if ((((set_type == "SC_SPI") || (set_type == "SC_I2C")) && (register.Name == "CRR1")))// Reuse subregisters
                        register.SubRegisters = subregisters["SC_CRR1"].ToArray();
                    else if ((((set_type == "SC_SPI") || (set_type == "SC_I2C")) && (register.Name == "CRR2")))// Reuse subregisters
                        register.SubRegisters = subregisters["SC_CRR2"].ToArray();
                    else if (((set_type == "USB_OTG") && (register.Name == "GRXSTSR")))// Reuse subregisters
                        register.SubRegisters = subregisters["USB_OTG_GRXSTSP"].ToArray();
                    else if (((set_type == "USB_OTG") && (register.Name == "DIEPTXF0_HNPTXFSIZ")))// Reroute subregisters
                        register.SubRegisters = subregisters["USB_OTG_DIEPTXF"].ToArray();
                    else if (((set_type == "USB_OTG") && (register.Name.StartsWith("DIEPTXF"))))// Reuse subregisters
                        register.SubRegisters = subregisters["USB_OTG_DIEPTXF"].ToArray();
                    else if (set_type == "DFSDM_Channel" || set_type == "DFSDM_Filter")
                    {
                        List<HardwareSubRegister> subregs;
                        if (subregisters.TryGetValue("DFSDM_" + register.Name, out subregs))
                            register.SubRegisters = subregs.ToArray();
                        else if (register.Name == "CHWDATAR")
                            continue;
                        else
                        {
                            errors.AddError(new RegisterParserErrors.MissingSubregisterDefinitions { FileName = PeripheralHeaderFile, SetName = set_name, RegisterName = register.Name });
                            continue;
                        }
                    }
                    else if (set_type.StartsWith("FSMC_Bank") || set_type.StartsWith("FMC_Bank"))
                    {
                        List<HardwareSubRegister> subregs;
                        if (subregisters.TryGetValue("FMC_" + register.Name, out subregs))
                            register.SubRegisters = subregs.ToArray();
                        else if (subregisters.TryGetValue("FSMC_" + register.Name, out subregs))
                            register.SubRegisters = subregs.ToArray();
                        else if (subregisters.TryGetValue("FMC_" + register.Name.TrimEnd('1', '2', '3', '4', '5', '6') + "x", out subregs))
                            register.SubRegisters = subregs.ToArray();
                        else if (subregisters.TryGetValue("FSMC_" + register.Name.TrimEnd('1', '2', '3', '4', '5', '6') + "x", out subregs))
                            register.SubRegisters = subregs.ToArray();
                        else
                            continue;
                    }
                    else if (cfg.IsKnownRegisterWithoutSubregisters(set_name, set_type, register.Name))
                        continue;
                    else if (set_type == "SPI" && register.Name == "I2SPR")
                        continue;   //Bug: one header is missing the definition
                    else if (set_type == "RCC" && register.Name == "CRRCR")
                        continue;   //Bug: one header is missing the definition stm32l041xx.h
                    else if (set_type == "DCMI" && ( register.Name == "RISR" || register.Name == "MISR"))
                        continue;
                    else if (subregisters.ContainsKey(set_name + "_" + register.Name))
                    {
                        register.SubRegisters = subregisters[set_name + "_" + register.Name].ToArray();
                    }
                    else
                    {
                        errors.AddError(new RegisterParserErrors.MissingSubregisterDefinitions { FileName = PeripheralHeaderFile, SetName = set_name, RegisterName = register.Name });
                        continue;
                    }
                }

                knonwValues.AttachKnownValues(set_name, registers);

                // Check subregister first bits, they should be <= register size
                foreach (var s in sets)
                {
                    foreach (var r in s.Registers)
                    {
                        if(r.SubRegisters != null)
                            foreach (var sr in r.SubRegisters)
                            {
                                if (sr.FirstBit >= r.SizeInBits)
                                    throw new Exception("Subregister " + sr.Name + " first bit is out of range!");
                            }
                    }
                }

                sets.Add(new HardwareRegisterSet
                    {
                        UserFriendlyName = set_name,
                        ExpressionPrefix = set_name + "->",
                        Registers = registers.ToArray()
                    }
                );
            }

            return sets.ToArray();
        }
        private static Dictionary<string, ulong> ProcessRegisterSetAddresses(string fn, string file, RegisterParserConfiguration cfg, RegisterParserErrors err)
        {
            Dictionary<string, ulong> addresses = new Dictionary<string, ulong>();

            Regex memory_map_begin_regex = new Regex(@"/\*\* \@addtogroup Peripheral_memory_map\r\n(.*)\r\n(.*)");
            Regex memory_map_begin_regex2 = new Regex(@"/\*\* \r\n  \* \@brief Peripheral_memory_map");
            Regex rgComment = new Regex(@"^[ \t]*/\*[^/]+\*/[ \t]*$");
            var m_begin = memory_map_begin_regex.Match(file);
            if (!m_begin.Success)
                m_begin = memory_map_begin_regex2.Match(file);
            if (!m_begin.Success)
                throw new Exception("Cannot find peripheral memory map");

            string[] lines = file.Substring(m_begin.Index + m_begin.Groups[0].Length).Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);

            for (int i = 0; i < lines.Length; i++)
            {
                string line = lines[i].TrimEnd('\r');

                if (line == "\r" ||
                    line.StartsWith("#if defined (STM32F40_41xxx)") ||
                    line.StartsWith("#endif /* STM32F40_41xxx */") ||
                    line.StartsWith("#if defined (STM32F427_437xx) || defined (STM32F429_439xx)") ||
                    line.StartsWith("#endif /* STM32F427_437xx ||  STM32F429_439xx */") ||
                    line.StartsWith("  */") ||
                    line.StartsWith("#define USB_OTG_EP_REG_SIZE") ||
                    line.StartsWith("#define USB_OTG_HOST_CHANNEL_SIZE") ||
                    line.StartsWith("#define USB_OTG_FIFO_SIZE") ||
                    line.StartsWith("#define FLASH_END") ||
                    line.StartsWith("#define CCMDATARAM_END ") ||
                    line.StartsWith("#define DATA_EEPROM")
                    || line.StartsWith("#define FLASH_EEPROM_END")
                    || line.StartsWith("#define FLASH_BANK1_END")
                    || line.StartsWith("#define FLASH_BANK2_END")
                    || line.StartsWith("#define USB_PMAADDR")
                    || line.StartsWith("#define SRAM_BASE")
                   || line.StartsWith("#define SRAM_BB_BASE")
                    || line.StartsWith("#define SRAM_SIZE_MAX")
                    )
                    continue;

                if (line.StartsWith("/**"))
                    break;

                if (rgComment.IsMatch(line) || string.IsNullOrWhiteSpace(line))
                    continue;

                Regex defineRegex = new Regex(@"#define[ ]+([^ ]*)[ ]+([^ \t].*)");
                var m = defineRegex.Match(line);
                if (m.Success)
                {
                    var macroName = m.Groups[1].Value;
                    var value = m.Groups[2].Value;
                    int idx = value.IndexOf("/*");
                    if (idx != -1)
                        value = value.Substring(0, idx);
                    value = value.Trim();

                    if (macroName.EndsWith("_BASE"))
                    {
                        string regset_name = macroName.Substring(0, macroName.Length - "_BASE".Length);
                        Regex base_addr_regex = new Regex(@"\(\(([^\(\)]*)\)([^\(\)]*)\)");//#define PERIPH_BASE           ((uint32_t)0x40000000U)
                        m = base_addr_regex.Match(value);
                        if (!m.Success && !value.Contains("+"))
                            m = Regex.Match(value, @"()(0x[0-9A-FU]+)");//#define PERIPH_BASE           0x40000000U
                        if (m.Success)
                        {
                            string addr = m.Groups[2].Value;
                            addresses[regset_name] = ParseHex(addr);
                            continue;
                        }

                        Regex base_addr_equals_regex = new Regex(@"[\(]?([^ ]*)_BASE[\)]?(\r|$)");
                        m = base_addr_equals_regex.Match(value);
                        if (m.Success)
                        {
                            string regset2_name = m.Groups[1].Value;
                            if (addresses.ContainsKey(regset2_name))// && addresses.ContainsKey(regset_name))
                                addresses[regset_name] = addresses[regset2_name];
                            else
                            {
                                if (!addresses.ContainsKey(regset_name))
                                    Console.WriteLine("ERR1153 !addresses.ContainsKey(regset2_name) " + regset_name);
                                if (!addresses.ContainsKey(regset2_name))
                                    Console.WriteLine("ERR1154 !addresses.ContainsKey(regset2_name) " + regset2_name);
                            }
                            continue;
                        }

                        Regex typed_base_addr_equals_plus_regex = new Regex(@"\({2}[^()]+\)\(([^ ]*)_BASE[ ]+\+[ ]+(.*)\){2}");
                        m = typed_base_addr_equals_plus_regex.Match(value);
                        if (m.Success)
                        {
                            string regset2_name = m.Groups[1].Value;
                            string addr = m.Groups[2].Value;
                            addresses[regset_name] = addresses[regset2_name] + ParseHex(addr);

                            continue;
                        }
                        int s = 0;
                        if (line.Contains("#define APBPERIPH_BASE"))
                            s++;
                        Regex base_addr_equals_plus_regex = new Regex(@"\(([^ ]*)_BASE[ ]+\+[ ]+(.*)\)");
                        m = base_addr_equals_plus_regex.Match(value);
                        if (m.Success)
                        {
                            string regset2_name = m.Groups[1].Value;
                            string addr = m.Groups[2].Value;
                            if (addresses.ContainsKey(regset2_name))//&& addresses.ContainsKey(regset_name))
                                addresses[regset_name] = addresses[regset2_name] + ParseHex(addr);
                            else
                            {
                             if (!addresses.ContainsKey(regset2_name))
                                    Console.WriteLine("1180 Per Reg!addresses.ContainsKey(regset2_name" + regset2_name + s);

                            }
                            continue;
                        }

                        Regex base_addr_base_regex = new Regex(@"([^ ]+)_BASE");
                        m = base_addr_base_regex.Match(value);
                        if (m.Success)
                         {
                          string prevRegset = m.Groups[1].Value;
                          addresses[regset_name] = addresses[prevRegset.TrimStart('(')];

                          continue;
                         }
                    }
                    else if (cfg.IsBaseAddrDefinitionIgnored(macroName))
                        continue;
                }

                err.AddError(new RegisterParserErrors.UnexpectedBaseAddressDefinition { FileName = fn, LineContents = line });
            }

            return addresses;
        }
        private static Dictionary<string, List<HardwareSubRegister>> ProcessSubregisters(string fileContents, string fileName, RegisterParserConfiguration cfg, RegisterParserErrors errors)
        {
            Dictionary<string, List<HardwareSubRegister>> result = new Dictionary<string, List<HardwareSubRegister>>();
            Dictionary<string, uint> aDefPosDict = new Dictionary<string, uint>();

            // Process subregisters
            Regex rgSubregisterList = new Regex(@"/\*[!]?[<]?[\*]+[ ]+Bit[s]? definition [genric ]*for ([^_ ]*)_([^ ]*)[ ]+register[ ]+[*]+/[ ]*");
            Regex rgSubregisterListWildcard = new Regex(@"/\*+ +Bit definition for ([A-Z0-9a-z]+)_([A-Z0-9a-z]+) \(x *=[^()]+\) +register +\*+/");
            Regex rgSubregisterListWildcard2 = new Regex(@"/\*+ +Bit definition for ([A-Z0-9a-z]+)_([A-Z0-9a-z]+) registers? +\(x *=[^()]+\) +\*+/");
            Regex rbSubregisterListEth = new Regex(@"/\*+[ ]+Bit definition for (.*) [Rr]egister[ ]+[1-9]*[ ]*\*+/");
            Regex rbSubregisterListUsb = new Regex(@"/\*+ +([^ ]+ .*) register bits? definitions +\*+/", RegexOptions.IgnoreCase);
            Regex bit_def_regex = new Regex(@"#define[ ]+([^ \(\)]*)[ \t]+[,]?[ ]*\(\(([^\(\)]*)\)([0-9A-Fa-fx]*)[U]?\)[ ]*(/\*)?(!<)?[ ]*([^\*/]*)(\*/)?");

            string[] lines = fileContents.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
            int nextLine = 0;
            bool insideIgnoredBlock = false;
            for (;;)
            {
                if (nextLine >= lines.Length)
                    break;
                string line = lines[nextLine++];

                foreach (var patch in cfg.LinePatches)
                    if (patch.Apply(ref line))
                        break;

                Match m;
                RegisterID thisReg;
                if ((m = rgSubregisterList.Match(line)).Success)
                    thisReg = new RegisterID(m.Groups[1].Value, m.Groups[2].Value);
                else if (((m = rgSubregisterListWildcard.Match(line)).Success) || ((m = rgSubregisterListWildcard2.Match(line)).Success))
                    thisReg = new RegisterID(m.Groups[1].Value, m.Groups[2].Value);
                else if (((m = rbSubregisterListEth.Match(line)).Success) || (m = rbSubregisterListUsb.Match(line)).Success)
                {
                    var m4 = bit_def_regex.Match(lines[nextLine]);
                    if (!m4.Success)
                        m4 = Regex.Match(lines[nextLine], @"#define[ \t]+([\w\d]+)[ \t]+([0-9A-Fa-fx]*)[U]?");
                    if (!m4.Success)
                        errors.AddError(new RegisterParserErrors.BadBitDefinition { LineContents = line, LineNumber = nextLine - 1, FileName = fileName });

                    string subreg_def = m4.Groups[1].Value;
                    int index = subreg_def.IndexOf("_");
                    if (index <= 0)
                    {
                        errors.AddError(new RegisterParserErrors.BadBitDefinition { LineContents = line, LineNumber = nextLine - 1, FileName = fileName });
                        continue;
                    }
                    string regSet = subreg_def.Substring(0, index);
                    subreg_def = subreg_def.Substring(index + 1);
                    index = subreg_def.IndexOf("_");
                    if (index <= 0)
                    {
                        errors.AddError(new RegisterParserErrors.BadBitDefinition { LineContents = line, LineNumber = nextLine - 1, FileName = fileName });
                        continue;
                    }

                    thisReg = new RegisterID(regSet, subreg_def.Substring(0, index));
                }
                else
                {
                    if (line.StartsWith("/**") && (line.Contains("Bit definition") || line.Contains("Bits definition")))
                    {
                        if (cfg.IsBlockDefinitionIgnored(line))
                            insideIgnoredBlock = true;
                        else
                            errors.AddError(new RegisterParserErrors.BadBitDefinition { LineContents = line, LineNumber = nextLine - 1, FileName = fileName });
                    }

                    if (line.StartsWith("#define")
                        && line.Contains("0x")
                        && !line.Contains("CLEAR_REG")
                        && !line.Contains("USB_EP")
                        && !line.Contains("FLASH_FKEY")
                        && !line.Contains("FLASH_KEY")
                        && !line.Contains("EXTI_EMR")
                        && !line.Contains("FLASH_OPTKEY")
                        && !line.Contains("(USB_BASE +")
                        && !line.Contains("RTC_BKP_NUMBER")
                        && !line.Contains("USB_ISTR")
                        && !line.Contains("USB_LPMCSR")
                        && !line.Contains("USB_DADDR")
                        && !line.Contains("USB_BASE")
                        && !line.Contains("USB_CNTR")
                        && !line.Contains("USB_BCDR")
                        && !line.Contains("USB_FNR")
                        && !line.Contains("USB_PMAADDR")
                        && !line.Contains("define HRTIM_")  //Not much formal system in comments to parse. Currently ignoring.
                        )
                    {
                        if (result.Count > 0 && !insideIgnoredBlock)
                            errors.AddError(new RegisterParserErrors.BadSubregisterDefinition { FileName = fileName, LineContents = line, LineNumber = nextLine - 1 });
                    }

                    continue;
                }

                if (thisReg.RegName.Contains("/"))
                {
                    int idx = thisReg.RegName.IndexOf('/');
                    thisReg = new RegisterID(thisReg.SetName, thisReg.RegName.Substring(0, idx).TrimEnd('1', '2', '3', '4'));
                }

                insideIgnoredBlock = false;

                //Apply name adjustment rules
                if ((thisReg.SetName == "DMA") && ((thisReg.RegName.Substring(0, thisReg.RegName.Length - 1) == "CCR") || (thisReg.RegName.Substring(0, thisReg.RegName.Length - 1) == "CNDTR") || (thisReg.RegName.Substring(0, thisReg.RegName.Length - 1) == "CPAR") || (thisReg.RegName.Substring(0, thisReg.RegName.Length - 1) == "CMAR")))// Header BUG: DMA_Channel defs not DMA defs
                    thisReg = new RegisterID("DMA_Channel", thisReg.RegName.Substring(0, thisReg.RegName.Length - 1));
                else
                {
                    foreach (var rule in cfg.RegisterSetRenameRules)
                    {
                        if (rule.Apply(ref thisReg))
                            break;
                    }
                }

                var subregisters = new List<HardwareSubRegister>();

                for (;;)
                {
                    if (nextLine >= lines.Length)
                        break;
                    line = lines[nextLine++];

                    foreach (var patch in cfg.SubregisterLinePatches)
                        if (patch.Apply(ref line))
                            break;
                    string subreg_name = "";
                    string reg_type = "";
                    string address_offset = "";
                    bool aParseOk = false;
                    m = bit_def_regex.Match(line);
                    if (!m.Success)
                    {
                        m = Regex.Match(line, @"#define[ \t]+([\w]+)[ \t]+[\(]?([\w]+)[\)]?");
                        if (m.Success && !m.Groups[1].Value.EndsWith("_Pos") && !m.Groups[1].Value.EndsWith("_Msk") && !line.Contains("<<"))
                        {
                            subreg_name = m.Groups[1].Value;
                            if (subreg_name == "RTC_BKP_NUMBER")
                                continue;

                            reg_type = "uint32_t";
                            if (m.Groups[2].Value.StartsWith("0x"))
                            {
                                address_offset = m.Groups[2].Value.Replace("U", "");//#define GPIO_OTYPER_OT_0                (0x00000001U)
                                aDefPosDict[m.Groups[1].Value] = UInt32.Parse(address_offset.Replace("x", ""), System.Globalization.NumberStyles.AllowHexSpecifier);
                            }
                            else
                            {
                                if (aDefPosDict.ContainsKey(m.Groups[2].Value))
                                {
                                    address_offset = FormatToHex(aDefPosDict[m.Groups[2].Value]);

                                    // for Legacy defines */
                                    aDefPosDict[m.Groups[1].Value] = aDefPosDict[m.Groups[2].Value];
                                } else
                                    if (Regex.IsMatch(m.Groups[2].Value, "(0x[0-9A-FU]+)"))
                                       aDefPosDict.Add(m.Groups[1].Value, (uint)ParseHex(m.Groups[2].Value));
                                    else {
                                            Console.WriteLine("No Hex value:{0}, : {1}", m.Groups[1].Value, m.Groups[2].Value);
                                           continue;
                                       }
                            }
                                aParseOk = true;
                            }
                    }
                    else
                    {
                         subreg_name = m.Groups[1].Value;
                         reg_type = m.Groups[2].Value;
                         address_offset = m.Groups[3].Value;
                        if (!aDefPosDict.ContainsKey(m.Groups[1].Value))
                            aDefPosDict.Add(m.Groups[1].Value, (uint)ParseHex(m.Groups[3].Value));
                         aParseOk = true;
                    }

                    if (aParseOk)
                    {
                        string shortSubregName;
                        if (cfg.IsSubregisterIgnored(subreg_name))
                            continue;

                        //Checks to see if any known values were missed from the above filters
                        if (subreg_name.EndsWith("_RST") ||
                            subreg_name.EndsWith("HSI") ||
                            subreg_name.EndsWith("HSE") ||
                            subreg_name.EndsWith("LSI") ||
                            subreg_name.EndsWith("MSI") ||
                            subreg_name.EndsWith("PLL") ||
                            subreg_name.EndsWith("_NOCLOCK") ||
                            subreg_name.EndsWith("_SYSCLK") ||
                            subreg_name.EndsWith("KEY")
                            )
                        {
                            if (subreg_name != "MACTMR_CR_EN" &&
                                subreg_name != "MACTMR_CR_RST" &&
                                subreg_name != "ADC_DMACR_RST" &&
                                subreg_name != "RTC_WPR_KEY" &&
                                subreg_name != "IWDG_KR_KEY" &&
                                subreg_name != "SCB_AIRCR_VECTKEY" &&
                                subreg_name != "HASH_CR_LKEY" &&
                                subreg_name != "WDG_KR_KEY" &&
                                !subreg_name.StartsWith("RCC_CFGR_") &&
                                subreg_name != "FLASH_OPTR_SRAM2_RST")
                            {
                                throw new Exception("Potential missed known subregister value!");
                            }
                        }

                        int offset, size;
                        try
                        {
                            ExtractFirstBitAndSize(ParseHex(address_offset), out size, out offset);
                        }
                        catch(Exception ex)
                        {
                            errors.AddError(new RegisterParserErrors.BitmaskNotSequential { FileName = fileName, LineContents = line, LineNumber = nextLine - 1 });
                            continue;
                        }

                        string desc = m.Groups[6].Value.TrimEnd();

                        if (subreg_name.StartsWith(thisReg.SubregisterPrefix))
                            shortSubregName = subreg_name.Substring(thisReg.SubregisterPrefix.Length);
                        else
                        {
                            if (cfg.IsMismatchingSubregisterIgnored(subreg_name))
                                continue;

                            if (!cfg.ApplySubregisterRenameRules(ref thisReg, subreg_name, out shortSubregName))
                            {
                                errors.AddError(new RegisterParserErrors.UnexpectedSubregisterName { FileName = fileName, LineContents = line, LineNumber = nextLine - 1, SubregName = subreg_name });
                                continue;
                            }
                        }

                        if (subregisters.Find(x => ((x.Name == shortSubregName) && (x.FirstBit == offset) && (x.SizeInBits == size))) != null)
                        {
                            Debug.WriteLine("Duplicate subregister not added: " + thisReg.SubregisterPrefix + shortSubregName);
                        }
                        else
                        {
                            subregisters.Add(new HardwareSubRegister
                            {
                                Name = shortSubregName,
                                SizeInBits = size,
                                FirstBit = offset,
                            });
                        }

                    }
                    else
                    {
                        //                        if (line.StartsWith("#define") && line.Contains("0x") && !line.Contains("CLEAR_REG"))
                        if (line.StartsWith("#define") && line.Contains("0x") && !line.Contains("CLEAR_REG") && !line.Contains("_Pos"))
                            errors.AddError(new RegisterParserErrors.BadSubregisterDefinition { FileName = fileName, LineContents = line, LineNumber = nextLine - 1 });
                        else if (line.Contains("/*                         USB Device General registers                       */"))
                            break;
                        else if (line.StartsWith("/*******") || line.Contains("Bit definition") || line.StartsWith("/*!<Common registers */"))
                            break;
                        else
                        {
                            var m1 = Regex.Match(line, @"#define[ \t]+([\w]+_Pos)[ \t]+\(([0-9A-Fa-f]+)U\)");
                            if (m1.Success)
                                aDefPosDict[m1.Groups[1].Value] = UInt32.Parse(m1.Groups[2].Value);
                            else
                            {
                                m1 = Regex.Match(line, @"#define[ \t]+([\w]+)[ \t]+\(0x([0-9A-Fa-fx]+)U << ([\w]+)\)");
                                if (m1.Success)
                                {
                                    UInt32 aValueMask = UInt32.Parse(m1.Groups[2].Value, System.Globalization.NumberStyles.AllowHexSpecifier);
                                    aValueMask = aValueMask << (int)aDefPosDict[m1.Groups[3].Value];
                                    aDefPosDict[m1.Groups[1].Value] = aValueMask;
                                }
                            }
                        }
                    }
                }

                result[thisReg.ToString()] = subregisters;
                subregisters = new List<HardwareSubRegister>();

                nextLine--;
            }

            //Remove useless subregisters that just define a numbered bit of another subregister value
            Regex numbered_name_regex = new Regex(@"(.*)_[0-9]+");
            foreach (var list in result.Values)
            {
                for (int i = 0; i < list.Count;i++ )
                {
                    var element = list[i];
                    var m = numbered_name_regex.Match(element.Name);
                    if (m.Success && (list.Find(x => (x.Name == m.Groups[1].Value)) != null) && (element.SizeInBits == 1))
                    {
                        //Debug.WriteLine("Removed bit definition " + element.Name);
                        list.Remove(element);
                        i--;
                    }
                }
            }

            return result;
        }
Esempio n. 4
0
        private static IEnumerable<MCUDefinitionWithPredicate> ParsePeripheralRegisters(string dir, MCUFamilyBuilder fam)
        {
            var mainClassifier = fam.Definition.Subfamilies.First(f => f.IsPrimary);
            List<Task<MCUDefinitionWithPredicate>> tasks = new List<Task<MCUDefinitionWithPredicate>>();
            Console.Write("Parsing {0} registers in background threads", fam.Definition.Name);
            RegisterParserErrors errors = new RegisterParserErrors();

            foreach (var fn in Directory.GetFiles(dir, "*.h"))
            {
                string subfamily = Path.GetFileNameWithoutExtension(fn);
                if (subfamily.Length != 11 && subfamily.Length != 12)
                    continue;

                /*if (subfamily != "stm32f301x8")
                 continue;*/

                Func<MCUDefinitionWithPredicate> func = () =>
                    {
                        RegisterParserConfiguration cfg = XmlTools.LoadObject<RegisterParserConfiguration>(fam.BSP.Directories.RulesDir + @"\PeripheralRegisters.xml");
                        var r = new MCUDefinitionWithPredicate
                            {
                                MCUName = subfamily,
                                RegisterSets = PeripheralRegisterGenerator.GenerateFamilyPeripheralRegisters(fn, cfg, errors,fam.MCUs[0].Core),
                                MatchPredicate = m => StringComparer.InvariantCultureIgnoreCase.Compare(mainClassifier.TryMatchMCUName(m.Name), subfamily) == 0,
                            };
                        Console.Write(".");
                        return r;
                    };

            //  func();
              tasks.Add(Task.Run(func));
            }

               Task.WaitAll(tasks.ToArray());
            var errorCnt = errors.ErrorCount;
            if (errorCnt != 0)
            {
                throw new Exception("Found " + errorCnt + " errors while parsing headers");

                //   for (int i = 0; i < errors.ErrorCount;i++)
                //     Console.WriteLine("\n er  " + i + "  -  " + errors.DetalErrors(i));

            }

            Console.WriteLine("done");
            return from r in tasks select r.Result;
        }