/*
         *  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;
                    }
                }
            }
Beispiel #2
0
        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());
        }