Add In-Code Documentation Guidelines

The in-code Documentation Guidelines contains the best practices for
documenting code using Doxygen. The guidelines offer options for both
novice and expert developers to document their code in a compatible and
correct manner.
Fully marked and simplified templates are provided to ease the
documentation effort.
Examples taken directly from Tiny Mountain's code show the difference
clearly.
The .c files contained here are used for the examples only and do not
have any function within Tiny Mountain.
Finally, the doxygen.rst file was updated to include the new content.


Change-Id: I6a39a54feed5fa95f2f21545c3967ff0755d85ae
Signed-off-by: Rodrigo Caballero <rodrigo.caballero.abraham@intel.com>
This commit is contained in:
Rodrigo Caballero 2015-05-26 17:47:39 -05:00 committed by Anas Nashif
commit fb74cd4a79
14 changed files with 1256 additions and 1 deletions

View file

@ -23,4 +23,5 @@ This would be an example of referencing function
.. toctree::
:maxdepth: 2
doxygen_output.rst
doxygen_guidelines.rst
doxygen_output.rst

View file

@ -0,0 +1,44 @@
.. _In-Code Documentation Guidelines:
In-Code Documentation Guidelines
################################
Follow these guidelines to document your code using comments. We provide
examples on how to comment different parts of the code. Files,
functions, defines, structures, variables and type definitions must be
documented.
We have grouped the guidelines according to the object that is being
documented. Read the information regarding all elements carefully since
each type of object provides further details as to how to document the
code as a whole.
These simple rules apply to all the code that you wish to include in the
documentation:
#. Start and end a comment block with :literal:`/*!` and :literal:`*/`
#. Use \@ for all Doxygen special commands.
#. Files, functions, defines, structures, variables and type
definitions must have a brief description.
#. All comments must start with a capital letter and end in a period.
Even if the comment is a sentence fragment.
.. important::
Always use :literal:`/*!` This is a comment. :literal:`*/` if that comment should
become part of the documentation.
Use :literal:`/*` This comment won't appear in the documentation :literal:`*/` for
comments that you want in the code but not in the documentation.
.. toctree::
:maxdepth: 2
doxygen_guidelines_files.rst
doxygen_guidelines_functions.rst
doxygen_guidelines_variables.rst
doxygen_guidelines_defines.rst
doxygen_guidelines_structs.rst
doxygen_guidelines_typedefs.rst

View file

@ -0,0 +1,76 @@
.. _Define Documentation:
Define Documentation
####################
Defines are documented similarly as functions. There are some note
worthy differences:
* The best practice for defines requires the use of the **@def**
special command.
* Just as with functions we provide a full and a simplified template.
The simplified template is also accepted. The syntax used in the
simplified template should only be used if you are familiar with
Doxygen. If you are having problems getting the documentation to
generate properly use the full template.
Define Comment Templates
************************
Full template:
.. code-block:: c
/*! @def name_of_define
@brief Brief description of the define.
@details Multiple lines describing in detail what is the
purpose of the define and what it does.
*/
#define name_of_define
Simplified template:
.. code-block:: c
/*!
Brief description of the define.
Multiple lines describing in detail what is the
purpose of the define and what it does.
*/
#define name_of_define
Define Documentation Example
****************************
This simple example shows how to document a define with the least amount
of effort while still following the best practices.
Correct:
.. literalinclude:: phil_commented.h
:language: c
:lines: 46-54
:emphasize-lines: 2, 3, 5
:linenos:
Observe how each piece of information is clearly marked. There is no
confusion regarding to what part of the code the comment belongs thanks
to the @def on line 2.
Incorrect:
.. literalinclude:: ../../samples/microkernel/apps/philosophers/src/phil.h
:language: c
:lines: 42-47
:emphasize-lines: 2, 5
:linenos:
Observe that the comment does not start with
:literal:`/*!` and therefore Doxygen will ignore it.
The comment is ambiguous; it could apply to either the define or the #if.

View file

@ -0,0 +1,58 @@
.. _File Header Documentation:
File Header Documentation
#########################
Every .c, .h and .s file must contain a file header comment at the
beginning of the file. The file header must contain:
#. The filename. Use **@file** for Doxygen to auto-complete the
filename.
#. The brief description: A single line summarizing the contents of
the file. Use **@brief** to clearly mark the brief description.
#. The detailed description: One or multiple lines describing the
purpose of the file, how it works and any other pertinent
information such as copyrights, authors, etc.
.. note::
Doxygen has special commands for copyrights (@copyright), authors
(@author), and other important information. Please refer to the
`Doxygen documentation`_ for further details.
.. _Doxygen documentation: http://www.stack.nl/~dimitri/doxygen/manual/index.html
Examples
********
Correct:
* A file header with a single line description.
.. literalinclude:: hello_commented.c
:language: c
:lines: 1-5
:emphasize-lines: 1,2,4
:linenos:
* A file header with a larger description.
.. literalinclude:: phil_task_commented.c
:language: c
:lines: 1-10
:emphasize-lines: 5-8
:linenos:
Incorrect:
A file header without a detailed description.
.. literalinclude:: phil_fiber_commented.c
:language: c
:lines: 1-3
:emphasize-lines: 4
:linenos:

View file

@ -0,0 +1,149 @@
.. _Function Documentation:
Function Documentation
######################
Doxygen recognizes a wide variety of syntaxes and structures for the
function comments. The syntax described here is in not the only
possible one nor does it exhaust all possible options. If your
development needs the use of an option not described here use it. Use
the following syntax:
Function Comment Templates
**************************
The full template shows the best practices for documenting a function.
The simplified version shows the minimal acceptable amount of
documentation for a function. Use the simplified template only if you
are familiar with Doxygen and how it uses blank lines to recognize the
parts of the comment.
Full template:
.. code-block:: c
/*!
* @brief Short description of my_function().
*
* @details Longer multi-paragraph description.
* Use this longer description to provide details about the
* function's purpose, operation, limitations, etc.
*
* @param a This is the first parameter.
* @param b This is the second parameter.
*
* @return Information about the return value.
*
* @error
* Details about the possible error.
*
* @warning
* This would be a warning.
*/
my_function(int a, int b){}
Simplified template:
.. code-block:: c
/*!
* Short description of my_function().
*
* Longer multi-paragraph description.
* Use this longer description to provide details about the
* function's purpose, operation, limitations, etc.
*
* @param a This is the first parameter.
* @param b This is the second parameter.
*
* @return Information about the return value.
*/
my_function(int a, int b){}
.. important::
Ensure that there is **no** blank line between the comment block
and the function's signature. That way Doxygen can link the comment
to the function.
Function Documentation Examples
*******************************
Example 1
=========
Take the very simple function :c:func:`taskA()`:
.. literalinclude:: ../../samples/microkernel/apps/hello_world/src/hello.c
:language: c
:lines: 77-85
:emphasize-lines: 3, 6
:linenos:
The highlighted lines show comments that would not be added to the
documentation. That is unacceptable. The appropriate way to document
:c:func:`taskA()` is:
.. literalinclude:: hello_commented.c
:language: c
:lines: 97-110
:emphasize-lines: 5-7, 11, 13
:linenos:
The highlighted lines show how to reference the code from within a
comment block. The direct reference is optional and the comments on
lines 11 and 13 are not added to the documentation. This method allows
for easy maintenance of the code blocks and easy addition of further
details. It also helps maintain the 72 characters line length.
Example 2
=========
Take the more complex function hello_loop():
.. literalinclude:: ../../samples/microkernel/apps/hello_world/src/hello.c
:language: c
:lines: 56-76
:emphasize-lines: 1, 3-5, 7, 8, 13, 16
:linenos:
The function parameters have been documented using the correct Doxygen
command but notice line 1. The comment block was not started with
:literal:`/*!` and therefore Doxygen won't parse it correctly.
The parameters have been documented using the \\param command. This is
equivalent to using @param but incorrect according to these guidelines.
Restructured Text uses the \\ as the escape for special characters. In
order to avoid possible conflicts the \@ symbol must be used instead.
Notice that there is no blank line between the comment and the
function's signature, lines 7 and 8. This allows Doxygen to correctly
link the comment to the function.
Lines 13 and 16 contain two comments that won't be included by Doxygen
in the documentation. Use the brief description or the detailed
description inside the comment block to include that information.
Remember that variables have to be documented separately. See
:ref:`Variable Documentation` for more details.
.. literalinclude:: hello_commented.c
:language: c
:lines: 72-95
:emphasize-lines: 2, 4-7, 9-11, 19, 21
:linenos:
Comment blocks must have the following structure:
#. Brief description. See line 2.
#. Detailed description. See lines 4-7.
#. Parameter information. See lines 9-11.
#. Return information. Return information is optional for void
functions.
#. Other special commands. There is no specific order for any further
special commands.
The description of the actions referenced in lines 19 and 21 is part of
the detailed description in the comment block. The references shown in
lines 19 and 21 are optional.

View file

@ -0,0 +1,53 @@
.. _Structure Documentation:
Structure Documentation
#######################
Structures, or structs for short, require very little documentation.
Structs must be documented wherever they are defined. Basically,
structs only require a brief description detailing why they are needed.
Each variable that composes a struct must be commented. A fully
simplified syntax is therefore appropriate.
Structure Comments Template
***************************
Structs only have a simplified template:
.. literalinclude:: ex_struct_pre.c
:language: c
:lines: 1-11
:emphasize-lines: 8
:linenos:
Doxygen does not require any commands to recognize the different
comments. It does require that line 8 be left blank though.
Structure Documentation Example
*******************************
Correct:
.. literalinclude:: irq_test_common_commented.h
:language: c
:lines: 117-125
:emphasize-lines: 6
:linenos:
Make sure to start every comment with
:literal:`/*!` and end it with :literal:`*/`. Every comment must start
with a capital letter and end with a period.
Doxygen requires that line 6 is left blank. Ensure a blank line
separates each group of variable and comment.
Incorrect:
.. literalinclude:: ../../samples/include/irq_test_common.h
:language: c
:lines: 112-115
:emphasize-lines: 1
:linenos:
The struct has no documentation. Developers that want to expand its
functionality have no way of understanding why the struct is defined
this way nor what its components are.

View file

@ -0,0 +1,56 @@
.. _Type Definition Documentation:
Type Definition Documentation
#############################
The documentation of type definitions, typedefs for short, is a simple
but tricky matter. Typedefs are aliases for other types and as such
need to be well documented. Always document typedefs even if the
complex type it uses is documented already.
Type Definition Comment Template.
*********************************
Typedefs require a simple comment explaining why they are being used and
what type they are referencing.
.. code-block:: c
/*! Brief description with the type that is being used and why. */
typedef int t_ie;
No further explanation is needed regarding the type even if it is
complex. Each complex type must be documented where ever it was
defined. Doxygen connects the typedef and the complex type it uses
automatically.
Type Definition Documentation Example
*************************************
Correct:
.. literalinclude:: irq_test_common_commented.h
:language: c
:lines: 69-73
:emphasize-lines: 1, 3, 4
:linenos:
Lines 1 and 4 name the type that is being used and with what purpose.
Even if the purpose is the same, since the types are different, two
comments are needed. Leaving line 3 blank not only increases
readability but it also helps Doxygen link the comments to the typedefs
appropriately.
Incorrect:
.. literalinclude:: ../../samples/include/irq_test_common.h
:language: c
:lines: 67-72
:emphasize-lines: 3, 4
:linenos:
The comments on lines 3 and 4 offer little insight into the code's
behavior. Furthermore, they do not start with
:literal:`/*!` and end with :literal:`*/`. Doxygen won't add the
information to the documentation nor link it properly to the complex
type documentation.

View file

@ -0,0 +1,71 @@
.. _Variable Documentation:
Variable Documentation
######################
Variables are the smallest element that requires documentation. As such
only a brief description is required detailing the purpose of the
variable. Only significant variables have to be documented. A
significant variable is a variable that adds functionality to a
component. Review the `Variable Documentation Examples`_ to understand
what constitutes a significant variable.
Variable Comment Template
*************************
.. code-block:: c
/*! Brief description of singificant_variable's purpose. */
int significant_variable;
Variable Documentation Examples
*******************************
Example 1
=========
This example shows a function that has been fully documented following
the best practices.
.. literalinclude:: phil_fiber_commented.c
:language: c
:lines: 110-168
:emphasize-lines: 15, 18, 21-23, 25, 31
:linenos:
Lines 15 and 18 show the documentation for two variables. Notice the
blank line 17. That line is necessary not only to increase the clarity
of the code but also to avoid Doxygen not determining properly where
the comment belongs.
Lines 21-23 show another acceptable way to document two variables with a
similar function. Notice that only one of the variables is documented,
the first one. The argument can be made that **kmutex_t f2** is no
longer a significant variable because it does not add any functionality
that has not been described for **kmutex_t f1**.
Lines 25 and 31 show us a different situation. Although both variables
are of the same type and very similar, they have different purposes.
Therefore both have to be documented and the difference between them
must be noted.
Example 2
=========
Variables outside of functions have to be documented as well.
.. literalinclude:: hello_commented.c
:language: c
:lines: 133-140
:emphasize-lines: 1, 4, 7
:linenos:
As you can see the syntax of the comment does not change. Always start
the comment with :literal:`/*!` and end it with :literal:`*/`. Remember
to begin with a capital letter and end with a period, even if the
comment is only a sentence fragment.
Notice that the variable comments also apply for more complex types like
structs. The comments on lines 4 and 7 apply only to the specific
variable and not to the whole struct. Complex types must be documented
wherever they are defined. See :ref:`Structure Documentation` and
:ref:`Type Definition Documentation` for further details.

View file

@ -0,0 +1,11 @@
/*! @brief Brief description of struct pre.
*
* Detailed description of struct pre. Optional
* */
struct pre {
/*! Variable g brief description. */
int g;
/*! Variable h brief description. */
int h;
};

View file

@ -0,0 +1,203 @@
/*! @file
@brief Hello World Demo
A Hello World demo for the Nanokernel and the Microkernel.
*/
/*
* Copyright (c) 2012-2014 Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*! CONFIG_MICROKERNEL
The microkernel hello world demo has two tasks that use semaphores
and sleeps to take turns printing a greeting message at a
controlled rate.*/
/*! #else || CONFIG_NANOKERNEL
* The nanokernel hello world demo has a task and a fiber that use
* semaphores and timers to take turns printing a greeting message at
* a controlled rate.
*/
/*!
@def SLEEPTICKS (SLEEPTIME * sys_clock_ticks_per_sec / 1000)
@brief Compute equivalence in ticks.
*/
/*!
@def SLEEPTIME
@brief Specify delay between greetings (in ms).
*/
#if defined(CONFIG_STDOUT_CONSOLE)
#include <stdio.h>
#define PRINT printf
#else
#include <misc/printk.h>
#define PRINT printk
#endif
#ifdef CONFIG_MICROKERNEL
#include <vxmicro.h>
#define SLEEPTIME 500
#define SLEEPTICKS (SLEEPTIME * sys_clock_ticks_per_sec / 1000)
/*!
@brief A loop saying hello.
@details
Actions:
-# Ouputs "Hello World!".
-# Waits, then lets another task run.
@param taskname The task's identification string.
@param mySem The task's semaphore.
@param otherSem The other task's semaphore.
*/
void helloLoop(const char *taskname, ksem_t mySem, ksem_t otherSem)
{
while (1)
{
task_sem_take_wait (mySem);
PRINT ("%s: Hello World!\n", taskname); /* Action 1 */
task_sleep (SLEEPTICKS); /* Action 2 */
task_sem_give (otherSem);
}
}
/*!
@brief Exchanges Hello messages with taskB.
@details
Actions:
-# taskA gives its own semaphore, thus it says hello right away.
-# Calls function helloLoop, thus taskA exchanges hello messages with taskB.
*/
void taskA(void)
{
task_sem_give (TASKASEM); /* Action 1 */
helloLoop (__FUNCTION__, TASKASEM, TASKBSEM); /* Action 2 */
}
/*!
@brief Exchanges Hello messages with taskA.
Actions:
-# Calls function helloLoop, thus taskB exchanges hello messages with taskA.
*/
void taskB(void)
{
helloLoop (__FUNCTION__, TASKBSEM, TASKASEM); /* Action 1 */
}
#else
#include <nanokernel.h>
#include <nanokernel/cpu.h>
#define SLEEPTIME 500
#define SLEEPTICKS (SLEEPTIME * sys_clock_ticks_per_sec / 1000)
#define STACKSIZE 2000
/*! Declares a stack for a fiber with a size of 2000.*/
char fiberStack[STACKSIZE];
/*! Declares a nanokernel semaphore for a task. */
struct nano_sem nanoSemTask;
/*! Declares a nanokernel semaphore for a fiber.*/
struct nano_sem nanoSemFiber;
/*!
@brief Defines the turns taken by the tasks in the fiber.
Actions:
-# Initializes semaphore.
-# Initializes timer.
-# Waits for task, then runs.
-# Outputs "Hello World!".
-# Waits, then yields to another task.
*/
void fiberEntry(void) {
struct nano_timer timer;
uint32_t data[2] = { 0, 0 };
nano_sem_init(&nanoSemFiber); /* Action 1 */
nano_timer_init(&timer, data); /* Action 2 */
while (1) {
nano_fiber_sem_take_wait(&nanoSemFiber); /* Action 3 */
PRINT("%s: Hello World!\n", __FUNCTION__); /* Action 4 */
nano_fiber_timer_start(&timer, SLEEPTICKS); /* Action 5 */
nano_fiber_timer_wait(&timer);
nano_fiber_sem_give(&nanoSemTask);
}
}
/*!
@brief Implements the Hello demo.
Actions:
-# Outputs "hello".
-# Waits, then signals fiber's semaphore.
-# Waits on fiber to yield.
*/
void main(void) {
struct nano_timer timer;
uint32_t data[2] = { 0, 0 };
task_fiber_start(&fiberStack[0], STACKSIZE, (nano_fiber_entry_t) fiberEntry,
0, 0, 7, 0);
nano_sem_init(&nanoSemTask);
nano_timer_init(&timer, data);
while (1) {
PRINT("%s: Hello World!\n", __FUNCTION__); /* Action 1 */
nano_task_timer_start(&timer, SLEEPTICKS); /* Action 2 */
nano_task_timer_wait(&timer);
nano_task_sem_give(&nanoSemFiber);
nano_task_sem_take_wait(&nanoSemTask); /* Action 3 */
}
}
#endif

View file

@ -0,0 +1,182 @@
/* irq-test-common.h - IRQ utilities for tests */
/*
* Copyright (c) 2014 Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
DESCRIPTION
Interrupt stuff, abstracted across CPU architectures.
*/
#ifndef _IRQ_TEST_COMMON__H_
#define _IRQ_TEST_COMMON__H_
/* defines */
#if defined(VXMICRO_ARCH_x86)
#define IRQ_PRIORITY 3
#elif defined(VXMICRO_ARCH_arm)
#if defined(CONFIG_CPU_CORTEXM)
#define IRQ_PRIORITY _EXC_PRIO(3)
#endif /* CONFIG_CPU_CORTEXM */
#endif
/*
* NUM_SW_IRQS must be defined before this file is included, and it
* currently only supports 1 or 2 as valid values.
*/
#if !defined(NUM_SW_IRQS)
#error NUM_SW_IRQS must be defined before including irq-test-common.h
#elif NUM_SW_IRQS < 1 || NUM_SW_IRQS > 2
#error NUM_SW_IRQS only supports 1 or 2 IRQs
#endif
#if defined(VXMICRO_ARCH_x86)
static NANO_CPU_INT_STUB_DECL(nanoIntStub1);
#if NUM_SW_IRQS >= 2
static NANO_CPU_INT_STUB_DECL(nanoIntStub2);
#endif /* NUM_SW_IRQS >= 2 */
#endif
/*! Declares a void-void function pointer to test the ISR. */
typedef void (*vvfn)(void);
/*! Declares a void-void_pointer function pointer to test the ISR. */
typedef void (*vvpfn)(void *);
#if defined(VXMICRO_ARCH_x86)
/*
* Opcode for generating a software interrupt. The ISR associated with each
* of these software interrupts will call either nano_isr_lifo_put() or
* nano_isr_lifo_get(). The imm8 data in the opcode sequence will need to be
* filled in after calling irq_connect().
*/
static char sw_isr_trigger_0[] =
{
0xcd, /* OPCODE: INT imm8 */
0x00, /* imm8 data (vector to trigger) filled in at runtime */
0xc3 /* OPCODE: RET (near) */
};
#if NUM_SW_IRQS >= 2
static char sw_isr_trigger_1[] =
{
/* same as above */
0xcd,
0x00,
0xc3
};
#endif /* NUM_SW_IRQS >= 2 */
#elif defined(VXMICRO_ARCH_arm)
#if defined(CONFIG_CPU_CORTEXM)
#include <nanokernel.h>
static inline void sw_isr_trigger_0(void)
{
_NvicSwInterruptTrigger(0);
}
#if NUM_SW_IRQS >= 2
static inline void sw_isr_trigger_1(void)
{
_NvicSwInterruptTrigger(1);
}
#endif /* NUM_SW_IRQS >= 2 */
#endif /* CONFIG_CPU_CORTEXM */
#endif
/*! Defines the ISR initialization information. */
struct isrInitInfo
{
/*! Declares the void-void function pointer for the ISR. */
vvpfn isr[2];
/*! Declares a space for the information. */
void *arg[2];
};
/*******************************************************************************
*
* initIRQ - init interrupts
*
*/
static int initIRQ
(
struct isrInitInfo *i
)
{
#if defined(VXMICRO_ARCH_x86)
int vector; /* vector to which interrupt is connected */
if (i->isr[0])
{
vector = irq_connect (NANO_SOFT_IRQ, IRQ_PRIORITY, i->isr[0],
i->arg[0], nanoIntStub1);
if (-1 == vector)
{
return -1;
}
sw_isr_trigger_0[1] = vector;
}
#if NUM_SW_IRQS >= 2
if (i->isr[1])
{
vector = irq_connect (NANO_SOFT_IRQ, IRQ_PRIORITY, i->isr[1],
i->arg[1], nanoIntStub2);
if (-1 == vector)
{
return -1;
}
sw_isr_trigger_1[1] = vector;
}
#endif /* NUM_SW_IRQS >= 2 */
#elif defined(VXMICRO_ARCH_arm)
#if defined(CONFIG_CPU_CORTEXM)
if (i->isr[0])
{
(void) irq_connect (0, IRQ_PRIORITY, i->isr[0], i->arg[0]);
irq_enable (0);
}
if (i->isr[1])
{
(void) irq_connect (1, IRQ_PRIORITY, i->isr[1], i->arg[1]);
irq_enable (1);
}
#endif /* CONFIG_CPU_CORTEXM */
#endif /* VXMICRO_ARCH_x86 */
return 0;
}
#endif /* _IRQ_TEST_COMMON__H_ */

View file

@ -0,0 +1,60 @@
/*! @file
* @brief Dining philosophers header file.
*
* Collects the includes and defines needed to implement the dining philosophers
* example.
*/
/*
* Copyright (c) 2012-2014 Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* Needed includes. */
#if defined(CONFIG_STDOUT_CONSOLE)
#include <stdio.h>
#else
#include <misc/printk.h>
#endif
/*!
@def N_PHILOSOPHERS
@brief Defines the number of philosophers.
@details Multiple tasks do printfs and they may conflict.
Uses puts() instead of printf() to avoid conflicts.
*/
#define N_PHILOSOPHERS 6
#if defined(CONFIG_STDOUT_CONSOLE)
#define PRINTF(...) {char output[256]; sprintf(output, __VA_ARGS__); puts(output);}
#else
#define PRINTF(...) printk(__VA_ARGS__)
#endif

View file

@ -0,0 +1,166 @@
/*! @file
* @brief Solution to the dining philosophers problem using fibers.
*/
/*
* Copyright (c) 2012-2014 Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* includes */
#ifdef CONFIG_NANOKERNEL
/* For the nanokernel. */
#include <nanokernel.h>
#include "phil.h"
#else
/* For the microkernel. */
#include <vxmicro.h>
#include "phil.h"
#endif
#include <nanokernel/cpu.h> //!< Used to be know as: irq_lock/irq_unlock
/* defines */
#ifdef CONFIG_NANOKERNEL
/* For the nanokernel. */
#define FORK(x) &forks[x]
#define TAKE(x) nano_fiber_sem_take_wait(x)
#define GIVE(x) nano_fiber_sem_give(x)
#define RANDDELAY(x) myDelay(((nano_node_tick_get_32() * ((x) +1)) & 0x1f) + 1)
#else
/* For the microkernel. */
#define FORK(x) forks[x]
#define TAKE(x) task_mutex_lock_wait(x)
#define GIVE(x) task_mutex_unlock(x)
#define RANDDELAY(x) myDelay(((task_node_tick_get_32() * ((x) +1)) & 0x1f) + 1)
#endif
#define PRINT(x,y) myPrint(x,y)
#ifdef CONFIG_NANOKERNEL
/* For the nanokernel. */
extern struct nano_sem forks[N_PHILOSOPHERS];
#else
/* For the microkernel. */
kmutex_t forks[] = { forkMutex0, forkMutex1, forkMutex2, forkMutex3, forkMutex4,
forkMutex5 };
#endif
/*!
* @brief Prints a philosopher's state.
*
* @param id A philosopher's ID.
* @param str A string, either EATING or THINKING.
*
* @return N/A
*/
static void myPrint(int id,
char *str
) {
PRINTF("\x1b[%d;%dHPhilosopher %d %s\n", id + 1, 1, id, str);
}
/*!
* @brief Waits for a number of ticks to elapse.
*
* @param ticks Number of ticks to delay.
*
* @return N/A
*/
static void myDelay(int ticks
) {
#ifdef CONFIG_MICROKERNEL
task_sleep (ticks);
#else
struct nano_timer timer;
nano_timer_init(&timer, (void *) 0);
nano_fiber_timer_start(&timer, ticks);
nano_fiber_timer_wait(&timer);
#endif
}
/*!
* @brief Entry point to a philosopher's thread.
*
* @details This routine runs as a task in the microkernel environment
* and as a fiber in the nanokernel environment.
*
* Actions:
* -# Always takes the lowest fork first.
* -# Prints out either Eating or Thinking.
*
* @return Not applicable.
*/
void philEntry(void) {
#ifdef CONFIG_NANOKERNEL
/*! Declares a fork for the nanokernel. */
struct nano_sem *f1;
/*! Declares a second fork for the nanokernel. */
struct nano_sem *f2;
#else
/*! Declares a fork for the microkernel. */
kmutex_t f1;
kmutex_t f2;
#endif
/*! Declares the current philosopher's ID. */
static int myId;
/*! Declares an interrupt lock level.*/
int pri = irq_lock();
/*! Declares the next philosopher's ID. */
int id = myId++;
irq_unlock(pri);
if ((id + 1) != N_PHILOSOPHERS) { /* A1 */
f1 = FORK(id);
f2 = FORK(id + 1);
} else {
f1 = FORK(0);
f2 = FORK(id);
}
while (1) { /* A2 */
TAKE(f1);
TAKE(f2);
PRINT(id, "EATING ");
RANDDELAY(id);
GIVE(f2);
GIVE(f1);
PRINT(id, "THINKING");
RANDDELAY(id);
}
}

View file

@ -0,0 +1,125 @@
/*! @file
* @brief An implementation of a solution to the dining philosophers problem
* for both the nano- and microkernel.
*
* This particular implementation uses 6 fibers or tasks of
* different priority, semaphores and timers. The implementation demostrates
* fibers and semaphores in the nanokernel and tasks and timers in the
* microkernel.
*/
/*
* Copyright (c) 2012-2014 Wind River Systems, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2) Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3) Neither the name of Wind River Systems nor the names of its contributors
* may be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/* includes */
#ifdef CONFIG_NANOKERNEL
#include <nanokernel.h>
#include "phil.h"
#else
#include <vxmicro.h>
#include "phil.h"
#endif
/* defines */
#define DEMO_DESCRIPTION \
"\x1b[2J\x1b[15;1H" \
"Demo Description\n" \
"----------------\n" \
"An implementation of a solution to the Dining Philosophers problem\n" \
"(a classic multi-thread synchronization problem). This particular\n" \
"implementation demonstrates the usage of multiple (6) %s\n" \
"of differing priorities and the %s semaphores and timers."
#ifdef CONFIG_NANOKERNEL
#define STSIZE 1024
extern void philEntry (void); //!< External function.
char philStack[N_PHILOSOPHERS][STSIZE];//!< Declares a global stack of size 1024.
struct nano_sem forks[N_PHILOSOPHERS];//!< Declares global semaphore forks for the number of philosophers.
#endif /* CONFIG_NANOKERNEL */
#ifdef CONFIG_NANOKERNEL
/*!
* @brief The nanokernel entry point.
*
* Actions:
* -# Starts one fiber per philosopher.
* -# Waits forever.
* @return Does not return.
*/
int main (void)
{
int i;
PRINTF (DEMO_DESCRIPTION, "fibers", "nanokernel");
for (i = 0; i < N_PHILOSOPHERS; i++)
{
nano_sem_init (&forks[i]);
nano_task_sem_give (&forks[i]);
}
/* A1 */
for (i = 0; i < N_PHILOSOPHERS; i++)
task_fiber_start (&philStack[i][0], STSIZE,
(nano_fiber_entry_t) philEntry, 0, 0, 6, 0);
/* A2 */
while (1)
{
extern void nano_cpu_idle (void);
nano_cpu_idle ();
}
}
#else
/*!
* @brief Starts the dining philosophers demo of the microkernel.
*
* This function starts the dining philosophers demo and
* then waits forever.
* @return Does not return.
*/
void philDemo(void) {
PRINTF(DEMO_DESCRIPTION, "tasks", "microkernel");
task_group_start(PHI);
while (1) {
task_sleep(10000);
}
}
#endif