Changes between Version 3 and Version 4 of Developer/Coding/Doxygen_for_BSPs


Ignore:
Timestamp:
Jan 6, 2016, 5:06:18 PM (4 years ago)
Author:
Ralph Holmes
Comment:

Fix links; improve formatting.

Legend:

Unmodified
Added
Removed
Modified
  • Developer/Coding/Doxygen_for_BSPs

    v3 v4  
    11= Doxygen Recommendations for BSPs =
    22
    3 
    43RTEMS contains well over a hundred [wiki:TBR/Website/Board_Support_Packages Board Support Packages (BSPs)], across over 20 different [wiki:TBR/UserManual/SupportedCPUs CPU Architectures]. What this means is that there is a lot of hardware dependent code that gets written, and that adding Doxygen to properly document it all can be a very complicated task.
    54
     
    76
    87Feel free to skip around and skim parts of this.
     8
    99= BSP Basics =
    1010
    11 Embedded development is hard. Different CPUs have different instructions for doing the same thing, and different boards will have all sorts of different hardware that require unique drivers and interfaces. RTEMS handles this by having discrete packages, BSPs, to encapsulate code to accommodate for unique hardware. BSPs seek to implement the Hardware-Software interface. This, in a nutshell, is one of the [wiki:TBR/Website/Mission_Statement core purposes] of RTEMS: To abstract (as much as is possible) away from the physical hardware and provide a standards compliant real-time environment for the embedded developer. If you think about it, the operating system on your normal computer serves a very similar purpose.
     11Embedded development is hard. Different CPUs have different instructions for doing the same thing, and different boards will have all sorts of different hardware that require unique drivers and interfaces. RTEMS handles this by having discrete packages, BSPs, to encapsulate code to accommodate for unique hardware. BSPs seek to implement the Hardware-Software interface. This, in a nutshell, is one of the [wiki:Mission_Statement core purposes] of RTEMS: To abstract (as much as is possible) away from the physical hardware and provide a standards compliant real-time environment for the embedded developer. If you think about it, the operating system on your normal computer serves a very similar purpose.
     12 
    1213= Common Features Found In BSPs =
    1314
    1415Although the actual implementation code will differ between BSPs, all BSPs will share some degree of common functionality. This is because that no matter what exact hardware you have, you need some basic features implemented in order to have a real time system you can develop on. Some of the most common shared features across most boards include:
    15 
    1616
    1717 *  '''console''': is technically the serial driver for the BSP rather than just a console driver, it deals with the board UART (i.e. serial devices)
     
    2929
    3030Note that there is no guarantee a particular BSP will implement all of these features, or even some of them. These are just the most common ones to look for. RTEMS follows a standardized naming convention for the BSP sub directories, so you should be able to tell in most cases what has been implemented on the BSP level and what has not.
     31
    3132= Shared Features =
    3233
    3334Some of the RTEMS executive is hardware independent and can be abstracted so that the same piece of code can be shared across multiple CPU architectures, or across multiple boards on the same architecture. This is done so that chunks of software can be reused, as well as aiding in reducing the development and debugging time for implementing new BSPs. This greatly aids the developer, but as someone seeking to document this code, this can make your life a little bit harder. It is hard to tell by looking at the directory of a BSP which features have simply been left out and which features are being implemented by using shared code from either from the architecture (../shared) or the base libbsp directory (../../shared). You may be looking at the BSP headers and notice that you have an irq.h, but no irq.c implementing it, or you might even be missing both. You know that the processor has interrupt support somehow, but where is it? The easiest way to figure this out is by looking at the Makefile.am for a BSP. We'll detail this process more in a bit. 
     35
    3436= Rationale =
    3537
    3638As someone adding documentation and not doing actual development work, you might think it is not necessary to know some of the in and outs of BSPs. In actuality, this information will prove to be very useful. Doxygen documentation works by grouping things and their components (i.e. functions and other definitions), and by having brief descriptions of what each group does. You can't know what to look for or know how to group it or know how to describe it without some basic knowledge of what a BSP is. For more information on any of the above or BSPs in general, check out the [http://rtems.org/onlinedocs/doc-current/share/rtems/html/bsp_howto/index.html BSP Development Guide].
     39
    3740= The Structure of the libbsp directory =
    3841
     
    105108}}}
    106109
    107 
    108110In short, BSPs will use the following directories:
    109111 *  c/src/lib/libbsp/'''''shared'''''                        <- code used that is shared by all BSPs
     
    111113 *  c/src/lib/libbsp/'''''CPU'''''/'''''BSP'''''             <- code unique to this BSP
    112114
    113 
    114 
    115115As you can see, libbsp has a very logical and easy to understand structure to it. The documentation generated by Doxygen should attempt to match this structure as closely as possible. We want an overarching parent group to serve the same purpose as the libbsp directory. In it, we want groups for each CPU architecture and a group for the shared files. We then want groups for each BSP. Breaking our documentation up into discrete groups like this will greatly simplify the process and make the documentation much easier to go through. By learning about the existing structure of the libbsp directory, we get an idea of how we should structure the Doxygen groups we create. More on this in the next section.
     116
    116117= Doxygen =
    117118
     
    119120
    120121In addition to this, check out the page on [wiki:Developer/Coding/Doxygen Doxygen Recommendations], which also contains a fair amount of information that will not be covered here.
     122
    121123= Doxygen Basics =
    122124
     
    124126
    125127The core component of Doxygen (that we care about right now at least) is what's called a '''group''', or '''module'''. These are used to add structure and associate groups of files that serve a similar purpose or implement the same thing.
     128
    126129= Doxygen Headers =
    127 
    128130
    129131Doxygen is always found in a special Doxygen comment block, known as a '''Doxygen header'''. In RTEMS, this block comes in the form of a multiline comment with some included Doxygen commands, which are preceded by the '@' tag. Take a look at this Doxygen header that declares the arm_raspberrypi module, which houses the documentation in the BSP for the Raspberry Pi.
     
    142144}}}
    143145
    144 You see a few commands here that we'll cover in the following sections. Briefly, the @defgroup command declares a new group, the @ingroup command nests this group as a submodule of some other group (in this case bsp_arm), and the @brief command provides a brief description of what this group is.
    145 = The @defgroup Command =
     146You see a few commands here that we'll cover in the following sections. Briefly, the @defgroup command declares a new group, the @ingroup command nests this group as a submodule of some other group (in this case bsp_arm), and the @brief command provides a brief description of what this group is.
     147
     148= The @defgroup Command =
     149
    146150The @defgroup command is used to declare new groups or modules. Think "define group". The syntax of this command is as follows:
     151
    147152{{{
    148153@defgroup <group name> <group description>
    149154}}}
     155
    150156The group name is the name used by Doxygen elsewhere to reference this group. The group description is what is displayed when the end user navigates to this module in the resulting documentation. The group description is a couple words formatted as how it would be in a table of contents. This part is what actually shows up in the documentation, when the user navigates to this group's module, this description will be the modules name.
    151157
     
    153159
    154160The @defgroup command is used only to define ''structure''. No actual documentation is generated as a result of its use. We must @ingroup things to the group we declare in order to create documentation. Even though it does not generate visible documentation, the @defgroup command is still very important. We use it in a way that seeks to emulate the structure of the libbsp directory itself. We do this by creating a hierarchy of groups for each CPU architecture and each BSP.
     161
    155162= The @ingroup Command =
    156163
    157164The @ingroup command is used to add 'things' to already declared groups or modules. These 'things' can either be other groups, or files themselves. The syntax of the @ingroup command is as follows:
     165
    158166{{{
    159167@ingroup <group name>
    160168}}}
     169
    161170The group name is the actual name, not description, of the group you want to add yourself to. Remember that group name was the second argument passed to the @defgroup command.
    162171
     
    164173
    165174@ingroup is found within all Doxygen headers, along with an @brief statement. There are two types of Doxygen headers, which we will go over after we see a description of the @brief command.
     175
    166176= The @brief Command =
    167177
    168178The @brief command is used to give either a)  a brief description in the form of an entry as you would see it in a table of contents (i.e. Capitalized, only a couple of words) or b) a brief topic sentence giving a basic idea of what the group does. The reason you have two uses for the brief command is that it is used differently in the two types of Doxygen headers, as we will see shortly. The syntax of the brief command is self evident, but included for the sake of completion:
     179
    169180{{{
    170181@brief <Table of Contents entry '''or''' Topic Sentence>
    171182}}}
     183
    172184= The Two Types of Doxygen Headers =
    173185
     
    210222
    211223For more examples of Doxygen structure and syntax, refer to BSPs found within the arm architecture, the lpc32xx and raspberrypi BSPs are particularly well documented. A good way to quickly learn more is by tweaking some Doxygen in a file, then regenerating the html, and seeing what has changed.
     224
    212225= Generating Documentation =
    213226
    214 Doxygen is a documentation generator, and as such, we must generate the actual html documentation to see the results of our work. This is a very good way to check your work, and see if the resulting structure and organization was what you had intended. The best way to do this is to simply run the [https://github.com/joelsherrill/gci_tasks/blob/master/2013/doxygen_c_header_tasks/validate/do_doxygendo_doxygen do_doxygen script]. To use the script:
    215 
    216 # Make sure Doxygen is installed
    217 # The environment needs to have the root directory of rtems set in the variable r so that $r prints the path to rtems, and the script takes as argument a relative directory from there to generate the doxygen, for example to generate the doxygen for all of libbsp you would do:
     227Doxygen is a documentation generator, and as such, we must generate the actual html documentation to see the results of our work. This is a very good way to check your work, and see if the resulting structure and organization was what you had intended. The best way to do this is to simply run the [https://github.com/joelsherrill/gci_tasks/blob/master/2015/doxygen_c_header_tasks/validate/do_doxygen do_doxygen script]. To use the script:
     228
     229Make sure Doxygen is installed. Also, the environment needs to have the root directory of RTEMS set in the variable `r` so that `$r` prints the path to RTEMS, and the script takes as argument a relative directory from there to generate the doxygen, for example to generate the doxygen for all of libbsp you would do:
     230
    218231{{{
    219232export r=~/rtems
    220233./do_doxygen c/src/lib/libbsp
    221234}}}
     235
    222236= Doxygen in libbsp =
    223237
    224238Now that we've covered the basics of Doxygen, the basics of BSPs and the structure of the libbsp directory, actually adding new Doxygen to libbsp will be much easier than it was before. We will cover a set of rules and conventions that you should follow when adding Doxygen to this directory, and include some tips and tricks.
     239
    225240= Group Naming Conventions =
    226241
     
    237252 *  '''raspberrypi_interrupt''' This is the group for code handling interrupts on the Raspberry Pi platform. Because this code and the group that envelops it is Raspberry Pi dependent, we prefix our name with a "'''raspberrypi'''", indicating this group is nested within the raspberrypi group.= Structure Conventions =
    238253
    239 This covers where, when, and why you should place the second type of Doxygen header. Remember that our goal is to have the structure of the documentation to match the organization of the libbsp directory as closely as possible. We accomplish this by creating groups for each cpu architecture, each BSP, and each shared directory. These groups are nested as appropriate in order to achieve a hierarchy similar to that of libbsp. The arm_raspberrypi group would be nested within the bsp_arm group, for example.
     254This covers where, when, and why you should place the second type of Doxygen header. Remember that our goal is to have the structure of the documentation to match the organization of the libbsp directory as closely as possible. We accomplish this by creating groups for each cpu architecture, each BSP, and each shared directory. These groups are nested as appropriate in order to achieve a hierarchy similar to that of libbsp. The arm_raspberrypi group would be nested within the bsp_arm group, for example.
     255
    240256== Where to place @defgroup ==
    241257
    242 Remember how I said it really doesn't matter where you place the @defgroup? Well, it does and it doesn't. It would be chaotic to place these anywhere, and almost impossible to tell when you have a @defgroup and when you don't, so we do have some rules in place to guide where you should place these.
     258Remember how I said it really doesn't matter where you place the @defgroup? Well, it does and it doesn't. It would be chaotic to place these anywhere, and almost impossible to tell when you have a @defgroup and when you don't, so we do have some rules in place to guide where you should place these.
     259
    243260=== @defgroups for CPU Architectures and Shared Directories ===
    244261
    245262The standardized place for these is within a special doxygen.h file placed within the particular architectures shared directory. This doxygen.h file exists solely for this purpose, to provide a standard place to house the group definitions for CPU architectures and the shared directory for that architecture. This is done because there is no single file that all architectures share, so it would be impossible to declare a standardized location for architecture declarations without the creation of a new file. This also allows others to quickly determine if the group for a particular architecture has already been defined or not. Lets look at the doxygen.h for the arm architecture as an example, found at arm/shared/doxygen.h:
     263
    246264{{{
    247265 /**
     
    265283The doxygen.h contains only 2 Doxygen headers, both of which are of the second type. One header is used to create the groups for the arm architecture '''bsp_arm''', nesting it as part of the bsp_kit group, and the other creates an '''arm_shared''' group to house the code that is shared across all BSPs of this architecture. Because these are the second type of Doxygen header, where we place them does not matter. This allows us to place them in a standard doxygen.h file, and the end user is non the wiser. Note that this .h file should never be included by a .c file, and that the only group declarations that should be placed here are the declarations for the CPU Architecture group and the shared group.
    266284
    267 There is also a doxygen.h file that exists at the root libbsp/shared directory, to @defgroup the the parent '''bsp_kit''' group (the only group to not be nested within any other groups) and to @defgroup the '''bsp_shared''' group, to serve as the holder for the libbsp/shared directory. 
     285There is also a doxygen.h file that exists at the root libbsp/shared directory, to @defgroup the the parent '''bsp_kit''' group (the only group to not be nested within any other groups) and to @defgroup the '''bsp_shared''' group, to serve as the holder for the libbsp/shared directory.
    268286
    269287If the architecture in which the BSP you are tasked with does not have one of these files already, you will need to copy the format of the file here, replacing the '''arm''' with whatever the CPU Architecture you are working with is. Name this file doxygen.h, and place it in the shared directory for that architecture.
    270288
    271 The only groups you should ever add to this CPU group would be groups for specific BSPs and a group for the shared directory.
     289The only groups you should ever add to this CPU group would be groups for specific BSPs and a group for the shared directory.
     290
    272291=== @defgroups for BSPs ===
    273292
     
    275294
    276295The group for a BSP should '''always''' be nested within the group for the CPU architecture it uses. This means that the Doxygen header for defining a BSP group should always look something like this:
     296
    277297{{{
    278298 /**
     
    284304  */
    285305}}}
     306
    286307=== @defgroups for Everything Else ===
    287308
    288309Never be afraid to add more structure! Once the basic CPU and BSP group hierarchy is established, what we're left with is all the sub directories and implementation code. Whether working within a shared directory for a CPU architecture, or within a BSP directory, you should always be looking for associations you can make to group files together by. Your goal should be to avoid @ingroup-ing files directly to the cpu_shared group and the cpu_bsp group as much as possible, you want to find more groups you can nest within these groups, and then @ingroup files to those groups. Here are some things to look for:
     310
    289311==== Look Common Features Implemented ====
    290312
     
    294316
    295317Examples of this are found within the '''arm_raspberrypi''' group, which contains nested subgroups like '''raspberry_interrupt''' to group files responsible for handling interrupts, '''raspberrypi_usart''' to group files responsible for implementing USART support, and many other subgroups.
     318
    296319==== Check out the Makefile ====
    297320
    298321When working within a BSP, take a look at the Makefile.am. Often times, you will find that the original developer of the code has outlined the groups nicely for you already, with comments and titles before including source files to be built. Also, this is often the only way to tell which features a BSP simply does not implement, and which features a BSP borrows from either the architecture's shared group, or the libbsp shared group.
     322
    299323==== Start with a .h, and look for files that include it ====
    300324
    301325You should end up with a @defgroup for ''most'' .h files. Some .h files are related and will not have independent groups, but most provide interfaces for different features and should have their own group defined. Declare a group for the header, then use cscope to find the files that include this header, and try to determine where the implementation code for prototypes are found. These are the files you should @ingroup.
     326
    302327==== Files with similar names ====
    303328
     
    305330
    306331Remember, your goal is to @defgroup as much as you can. The only files you should be @ingroup-ing directly to the BSP group or the shared group are files that don't cleanly fit into any other group.
     332
    307333== Where to place @ingroup ==
    308334
     
    311337 * If you are working within an architecture's shared directory, @ingroup should be adding things either to the *architecture*_shared group, or some sub group of it.
    312338 * If you are working within a BSP directory, @ingroup should be adding things to either the *architecture_*bsp* group, or some sub group of it.
     339
    313340=== @ingroup in the first type of Doxygen Header ===
    314341
    315342Remember that in the first type of Doxygen header, we are adding files to groups. This type of header should always be at the top of the file. You should be adding files that are associated in some way to the same groups. That is to say, if three different .h files provide an interface allowing interrupt support, they should be a part of the same group. Some good ways to associate files were outlined above.
     343
    316344=== @ingroup in the second type of Doxygen Header ===
    317345
     
    319347
    320348When nesting groups, try to match the structure of libbsp as closely as possible. For example, if a group is defined to associate all files that provide for a real time clock for the raspberrypi, nest it within the arm_raspberrypi group.
     349
    321350=== @ingroup for shared code ===
    322351