/* * This method extracts the subregister macros defined as follows * #define ADC_ISR_ADRDY_Pos (0U) #define ADC_ISR_ADRDY_Msk (0x1U << ADC_ISR_ADRDY_Pos) * */ private NamedSubregister[] ExtractNewStyleSubregisters(ParsedHeaderFile parsedFile, PreprocessorMacro[] newStyleMacros) { List <NamedSubregister> result = new List <NamedSubregister>(); Dictionary <string, int> positionsByName = new Dictionary <string, int>(); Dictionary <string, int> bitCountsByName = new Dictionary <string, int>(); var resolver = new BasicExpressionResolver(false); foreach (var macro in newStyleMacros) { var expression = parsedFile.ResolveMacrosRecursively(macro.Value); var value = resolver.ResolveAddressExpression(expression); string key = macro.Name.Substring(0, macro.Name.Length - 4); if (value == null) { continue; } if (macro.Name.EndsWith("_Pos")) { positionsByName[key] = (int)value.Value; } else if (macro.Name.EndsWith("_Msk")) { if (!ExtractFirstBitAndSize(value.Value, out var size, out var firstBit)) { _ReportWriter.HandleInvalidNewStyleBitMask(macro.Name, value.Value); } else { bitCountsByName[key] = size; } } }
private static DiscoveredPeripheral[] LocateStructsReferencedInBaseExpressions(ParsedHeaderFile parsedFile) { List <DiscoveredPeripheral> structs = new List <DiscoveredPeripheral>(); /* * We are looking for preprocessor macros like the one below: * #define TIM3 ((TIM_TypeDef *) TIM3_BASE) * * This is done by looping over ALL preprocessor macros defined in the source file and pick the ones that refer to typedef-ed structs. * Then we recursively resolve the macro definition, getting something like ((TIM_TypeDef*)(((uint32_t)0x40000000U)+0x00000400)). * * Finally, we use a very simple parser to compute that address defined in this macro and to verify that it's being cast to * the correct type. * * Once we have computed the address and confirmed its type, we can reliably conclude that a peripheral defined by that struct is * present at the specified address. */ var resolver = new BasicExpressionResolver(true); foreach (var macro in parsedFile.PreprocessorMacros.Values) { foreach (var token in macro.Value) { if (token.Type == CppTokenizer.TokenType.Identifier && parsedFile.Structures.TryGetValue(token.Value, out var obj)) { var addressExpression = parsedFile.ResolveMacrosRecursively(macro.Value); if (addressExpression.Count(t => t.Value == "*") == 0) { continue; //Not an address } BasicExpressionResolver.TypedInteger addr; try { addr = resolver.ResolveAddressExpression(addressExpression); } catch (BasicExpressionResolver.UnexpectedNonNumberException ex) { if (ex.Token.Value == "SDMMC_BASE") { continue; //Known bug in STM32H7. The value is used, but not defined anywhere } if (ex.Token.Value == "LCD_BASE" || ex.Token.Value == "JPGDEC_BASE") { continue; //Known bug in STM32MP1. The value is used, but not defined anywhere } if (ex.Token.Value == "LTDC_Layer2_BASE") { continue; } throw; } if (addr.Type?.First().Value == obj.Name) { structs.Add(new DiscoveredPeripheral { ResolvedBaseAddress = addr.Value, Structure = obj, Name = macro.Name, Registers = TranslateStructureFieldsToRegisters(obj, parsedFile) }); } else { //We have found a preprocessor macro referencing one of the typedefs, but not resolving to its type. This needs investigation. Debugger.Break(); } break; } } } return(structs.ToArray()); }