hsk_libs-dev  163:b63ae088cc97
High Speed Karlsruhe XC878 library collection
 All Data Structures Files Functions Variables Typedefs Macros Groups Pages
Coding Conventions and Guidelines

This section describes the coding style used in these libraries.

The term member in this section applies to functions, globals, structs, unions, typedefs and defines of the current library.

Code/Comment Indention

Use 8 spaces wide real tabs when working with the code or documentation. This is my (kami) personal preference, and thus has found its way into more than 10000 lines of HSK code. It won't be changed just because you prefer 4 spaces wide tabs or tabs converted to spaces (you sicko!).

keil_configuration_Editor.png
Keil µVision Editor tab of the configuration dialogue

General Comment Guidlines

Every member is to be documented in one of the following manners:

/**
* <brief>
*/
<member>
/**
* <brief>
*
* <description>
*/
<member>
  • <brief>
    • A short, single sentence description of the member
  • <description>
    • A detailed description of the member

List Formatting

Descriptions may contain syntactical sugar such as lists:

This is a list:
        - List entry 0
        - List entry 1 is wider than 80 characters, including the tabular
          indention and thus needs to cover multiple lines
                - List entry 1.0
        - List entry 2

Every list entry is indented by 1 tab per level. In multiple line entries the successive lines are indented 2 spaces to align them with the first line.

Unless it is a keyword the first word of a list entry needs to be a capital letter. Entries do not end with a full stop.

Tables

The syntax for tables is:

| Heading 0     | Heading 1
|---------------|--------------
| Row 0, col 0  | Row 0, col 1
| Row 1, col 0  | Row 1, col 1

The resulting table looks like this:

Heading 0 Heading 1
Row 0, col 0 Row 0, col 1
Row 1, col 0 Row 1, col 1

Use a colons in the seperator row to align columns:

| Heading Left  | Heading Centre        | Heading Right
|:--------------|:---------------------:|--------------:
| Left          | Centre                | Right
Heading Left Heading Centre Heading Right
Left Centre Right
Note
Take care to obey the Code/Comment Indention guidelines, using the wrong tab width looks especially disturbing in the plain text version of a table.

Inline Comments

Inline comments not intended to appear in the documentation can take one of the following shapes.
Compact:

/* <comment> */

Multiline compact:

/* <comment line 0>
* <comment line 1> */

Significant:

/*
* <comment>
*/

Function Documentation

Every parameter of a member function and the return value if present need JavaDoc style @param and @return documentations in their descriptions:

/**
* <brief>
*
* <description>
*
* @param <parameter>
* <parameter description>
* @return
* <return value description>
*/

Return Values

Use @retval to document return values with logical instead of numerical meanings:

@retval 0
        The operation failed
@retval 1
        The operation succeeded

The resulting documentation takes the following appearance:

Return values
0The operation failed
1The operation succeeded

Public and Private Functions

The documentation to public functions belongs into the .h file. All functions that have a prototype in the header file are considered public, private functions are those, which are only used internally in the .c file.

If a function is public additional documentation may be placed in the .c file, it will only show up in the developers' manual.

Inline comments within functions may appear in JavaDoc style, in that case they are also appended to the function documentation of the developers' manual.

Private functions should be marked with @private at the end of their documentation block.

Grouping Documentation

In some cases a set of documented members belong together, such as a set of defines for a certain function parameter. In such a cases the members can be grouped:

/**
* \defgroup TRI_STATE Tri-State States
*
* Defines in this group represent one of the tri-state states
*
* @{
*/
/**
* Tri state off.
*/
#define TRI_STATE_OFF 0
/**
* Tri state on.
*/
#define TRI_STATE_ON 1
/**
* Tri state high impedance.
*/
#define TRI_STATE_Z 2
/**
* @}
*/

Groups are listed in the Modules chapter.

File Naming and Documentation

Three different file type suffixes are used in the construction of these libraries, .c for C files, .h for header files and .isr for headers that only contain ISR prototypes.

The following naming conventions exist for each file:

hsk_<category>/hsk_<name>.<suffix>
  • <category>
    • The library category, often identical to name, but not necessarily so
  • <name>
    • The name of the library
  • <suffix>
    • The file type suffix

Headers

Be greedy. Only members, which are required to use a library should be listed in header files.

Header files in this project should avoid including other headers. There are two exceptions to that rule, headers containing a define to generate code might have to include headers for the generated code and headers. The second exception are ISR Headers.

Every header file begins with a JavaDoc style comment:

/** \file
* HSK <brief> headers
*
* <description>
*
* @author <author tag>
*/
  • <brief>
    • A descriptive title such as "Analog Digital Conversion" this description appears in the file list, nouns, verbs and adjectives in the brief should start with capital letters
  • <description>
    • A text containing all the necessary information to use the provided functions
  • <author tag>
  • <iso date>
    • The ISO 8601 date (YYYY-MM-DD) of the last edit

The next block contains the traditional header opening:

#ifndef _<FILE>_
#define _<FILE>_
  • <FILE>
    • The file name with the following translation '[:lower:].' '[:upper:]_', e.g. hsk_isr.h becomes HSK_ISR_H

The #ifndef block is closed at the end of the header file with:

#endif /* _<FILE>_ */

Prototypes etc. belong within the block.

C Files

Like header files every C file starts with a JavaDoc style comment:

/** \file
* HSK <brief> implementation
*
* <description>
*
* @author <author tag>
*/
  • <brief>
    • Should be the same title as in the header file
  • <description>
    • Instead of how to use the library this should make mention of all things of interest, when working on the implementation
  • <author tag>

The first include in a C file is the Infineon/XC878.h header, followed by the own header file. The next (optional) include block contains all the required C library headers. The final include block includes the headers of other libraries. The following example is from hsk_adc.c:

#include <Infineon/XC878.h>
#include "hsk_adc.h"
#include <string.h> /* memset() */
#include "../hsk_isr/hsk_isr.h"

Comments for public members of a C file do not need to be copied from the header.

ISR Headers

The ISR headers exist solely for an oddity of SDCC. All interrupts must be visible from the context of the main() function.

Every implementation providing an interrupt has has to provide a .isr file. The file should just contain a very plain list of prototypes, the following examples is from hsk_timer01.isr:

#ifndef _HSK_TIMER01_ISR_
#define _HSK_TIMER01_ISR_
void ISR_hsk_timer0(void) interrupt 1 using 1;
void ISR_hsk_timer1(void) interrupt 3 using 1;
#endif /* _HSK_TIMER01_ISR_ */

The .isr file should be included from the header file of the library providing it as well as from the header files of all libraries using that library.

The file should be included in the following manner:

/*
* ISR prototypes for SDCC.
*/
#ifdef SDCC
#include "hsk_timer01.isr"
#endif /* SDCC */

Member Naming Conventions

All members except defines have the same structure of context prefix. Contexts can be nested, each level of context is separated by an underscore. Member names following the underscore separated context are camel case. The root context is always the library, subcontexts need to have a central concept or data structure that defines them.

Defines are always specified in capitals. Thus all separation in the names of defines is done by underscore. Public defines have the library name without HSK as a prefix.

Public Example

This subsection explains the naming conventions in public scope (i.e. in a header file) using the example of the hsk_can library.

Public defines are provided to interpret return values or to specify possible parameters:

#define CAN_ERROR 0xff
#define CAN0_IO_P10_P11 0
#define CAN1_IO_P01_P02 4

Typedefs give primitive data types a meaningful name for use in a certain context. This library has functions that work on CAN nodes and functions that work on message objects:

typedef ubyte hsk_can_node;
typedef ubyte hsk_can_msg;

The CAN nodes are the central structure of the library. Functions in the hsk_can context always take a node as the first parameter:

void hsk_can_init(const ubyte pins, const ulong __xdata baud);
void hsk_can_enable(const hsk_can_node node);

Other functions work around the concepts of messages and message data, which are represented in their context prefixes:

void hsk_can_msg_getData(const hsk_can_msg msg,
ubyte * const msgdata);
void hsk_can_data_setSignal(ubyte * const msg, const bool endian,
const bool sign, const ubyte bitPos,
const char bitCount, const ulong idata value);

Defines

In the private context only a few rules apply to naming defines.

If defines are named after registers or bits from the µC manual, their original spelling should be preserved, even if it means including non-capital letters:

#define NBTRx 0x0084

Apart from that special naming conventions for defines only apply to register bits. Every register bit definition is prefixed by BIT. Bit fields also specify a count:

#define BIT_RXSEL 0
#define CNT_RXSEL 3