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