BSP430  20141115
Board Support Package for MSP430 microcontrollers
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
BSP430 Coding Style

Table of Contents

The coding style for BSP430 is primarily the one the author converged to over the last twenty-five years, but has a few lingering influences from FreeRTOS.

Indentation and Syntactic Style

BSP430's coding style may be obtained using the following Emacs ccmode style:

(c-add-style "pab"
'("gnu"
(indent-tabs-mode . nil) ; No tabs in the source
(c-offsets-alist
(case-label . 2) ; Indent the case labels
)))

An acceptably close approximation can be had using the following Artistic Style (astyle) command line:

astyle \
--options=none \
--style=1tbs \
--indent=spaces=2 \
--indent-switches \
--pad-header \
--max-instatement-indent=60 \
-r \
'*.c' \
'*.h' \
'*.inc'

Note in particular that the one-true-brace-style expects single statements in loop, if and else bodies to be enclosed in braces, e.g.:

if (condition) {
f1();
} else {
f2();
}

Identifiers and Naming Conventions

Care is taken in BSP430 to conform to the rules for C regarding global identifiers; in particular, underscores may not appear at the start of an identifier (including macro parameters), and certain suffixes like _t are reserved.

Type Selection

Except where a data type is used as part of an interface to an external system or to reflect a specific intent, native types are used.

Miscellaneous

Comparison Operands

BSP430 places comparison operands which are lvalues on the right side of the operator, as with:

if (4 <= len) {
/* Too long */
}

Yes, even if the conditional operator "couldn't possibly be mistyped" as an assignment operator. Up with it you must put.

Function Return Values

Where a function implements an operation that may succeed or fail, that state reflected in the return value following standard POSIX conventions: a zero indicates a successful execution and a negative value indicates an error. Where useful information about a successful result may be expressed as a non-negative value (e.g., the number of bytes successfully transmitted), that may be included in the return value.

This is often counter-intuitive to programmers unfamiliar with POSIX, but the correct test to see whether the I2C addresses were successfully set is indeed:

if (0 == iBSP430serialI2CsetAddresses_rh(i2c, oa, sa)) {
/* Success here... */
}

Critical Sections (Not-Interruptible and Resource Held)

Statements that temporarily change interrupt enabled state should be enclosed in do ... while(0); blocks as shown in the documentation for BSP430_CORE_SAVED_INTERRUPT_STATE or in more complex situations like h_resource_ex.

The single-iteration loop construct used in these cases is strictly redundant but serves a purpose similar to the requirement for braces around single statements: it highlights that the content is conceptually a block with entry and exit operations and encourages the maintainer to read beyond a single statement to understand its context. It also simplifies control flow by allowing break to be used to jump to the end of the critical section. It is encouraged but not required when the protected statements are inherently within a scoped block anyway, as with:

if (0 == iBSP430consoleResourceClaim_ni()) {
rv = iBSP430consoleInitialize_rh_ni();
(void)iBSP430consoleResourceRelease_ni();
}

Include Files

Protection Against Nested Inclusion

Include file protection symbols encode the path by which the include file is normally accessed, with non-alphanumeric characters replaced by underscores and the resulting token expressed in upper case. For example, the protection sequence for <bsp430/platform/exp430fr5739/platform.h> is:

#ifndef BSP430_PLATFORM_EXP430FR5739_PLATFORM_H
#define BSP430_PLATFORM_EXP430FR5739_PLATFORM_H
/* ... */
#endif /* BSP430_PLATFORM_EXP430FR5739_PLATFORM_H */

Standard Order for Include Files

See also BSP430 Configuration for naming conventions and standards related overriding default configurations.

Header Files (*.h)

Every header file that does not include another BSP430 header file must include <bsp430/core.h> first to ensure the necessary preprocessor directives that are affected by bsp430_config.h are applied in the standard order. (It is not strictly necessary to do this if the first file included is another BSP430 header, but it does not hurt to do so and it helps with consistency.)

<bsp430/core.h> may be expected to include the following external material:

#include <msp430.h> /* MSP430 MCU-specific information */
#include <stdint.h> /* Size-annotated integral types (uint8_t) */
#include <stddef.h> /* NULL and size_t */
Note
At this time, infrastructure header files should not introduce a dependency on <bsp430/platform.h>. While it should be safe to do this, <bsp430/platform.h> resolves default values that might otherwise be affected by subsequent activities. (At one point BSP430 permitted configuration options to be undefined and redefined to a different value; it was in <bsp430/platform.h> that the options value would finally be applied, making subsequent redefinition problematic. That approach is not currently used, but it should not be precluded in case it becomes necessary in the future.)
Implementation Files (*.c)

Every implementation file should include <bsp430/platform.h> first to ensure that platform-specific overrides have been evaluated and are available to override defaults in other headers.

<bsp430/platform.h> may be expected to include the following external material:

#include <msp430.h> /* MSP430 MCU-specific information */
#include <bsp430/core.h> /* Core BSP430 headers and declarations */

It may include additional material such as <bsp430/periph.h> but that should not be assumed.

Preprocessor Feature Tests

See also BSP430 Configuration for naming conventions and standards related to feature tests.

Where a macro value is used for conditional compilation, the state of being true is determined with the following pattern:

#if (FEATURE_FLAG - 0)
/* Feature is enabled */
#else /* MACRO_VALUE */
/* Feature is not enabled */
#endif /* MACRO_VALUE */

This technique allows use of:

#define FEATURE_FLAG 0

to denote that the feature is being explicitly disabled. Developers of application or infrastructure code should ensure that any feature test flag has a definition to either 1 or 0 (or to an expression that will evaluate to either a true or false value when used within a preprocessor condition). The documentation explicitly marks macro definitions that are expected to have such values with the @cppflag annotation in the documentation block, which will produce:

C Preprocessor Only:
This macro may have a value that restricts its use to C preprocessor conditional directives.
Note
While other macros may be documented to have true or false values that are valid in both code and preprocessor expressions, macros with the @cppflag may have values that include preprocessor operators like defined which restrict their use to preprocessor directives.

The ability to explicitly disable features that default to being enabled is critical and requires a value-based comparison. The subtraction of 0 in the conditional expression allows syntactic correctness when somebody inappropriately defines the feature flag with no value: such a case is equivalent to disabling the feature. For consistency these tests should be enclosed in parentheses. The syntax also makes clear that the code was not intended to be #ifdef FEATURE_FLAG.

Warning
When features identified with null macro definitions are processed according to the BSP430 standard conditional directives, they are interpreted as being turned off, not on.

A common practice, followed by Texas Instruments in their standard MSP430 MCU-specific headers, is to use code like:

#define __MSP430_HAS_USCI_B0__

with a null expansion to the macro. Here is simply the existence of a definition, not its value, that indicates a feature is present.

The correct way of detecting features when interoperating with external libraries using the null-definition style is:

#if defined(__MSP430_HAS_USCI_B0__) && (configBSP430_HAL_USCI_B0 - 0)
/* Function is available and feature is enabled */
#else /* USCI_B0 */
/* Function is missing or feature is disabled */
#endif /* USCI_B0 */

The short-hand #ifdef may be used instead of the defined() test if no further conditions are required, but is discouraged for consistency.

In a very few cases, a configFEATURE_FOO flag is a request to supply a specific resource such as BSP430_FOO_PERIPH_HANDLE; an example is configBSP430_PERIPH_EXPOSED_CLOCKS which causes BSP430_PERIPH_EXPOSED_CLOCKS to be defined. If the platform is unable to provide the resource, it will leave the handle macro undefined. When there is no independent reason to provide a FEATURE_FOO flag, success of the configuration request should be tested by:

#if defined(BSP430_FOO_PERIPH_HANDLE)
#endif /* FOO */

The documentation for configFEATURE_FOO and BSP430_FOO_PERIPH_HANDLE will include the @affects and @dependency annotations respectively, to indicate when this alternative success test should being used and what macro to test.

When a macro defines a parameter affecting behavior or selection of resource that is not a flag and the value may be overridden by the user, its documentation should include the @defaulted annotation. The value should be provided in a way that respects prior definitions:

#ifndef BSP430_FOO_PARAMETER
#define BSP430_FOO_PARAMETER 42
#endif /* BSP430_FOO_PARAMETER */

Documentation Expectations

BSP430 uses Doxygen for architectural and API documentation. The following macros are used in API documentation to highlight expectations of particular macros, variables, and functions.

@defaulted

Annotation to indicate that the value provided by the infrastructure may be overridden by an application. The overriding value is normally provided through bsp430_config.h. Example: BSP430_CLOCK_NOMINAL_MCLK_HZ

Produces:

Defaulted:
The value here is superseded by previously encountered definitions.

@dependentvalue

Annotation to highlight that the value provided by the infrastructure is dependent on other settings in a complex manner. Normally used for configuration flags for dependent features. Example: configBSP430_UPTIME_TIMER_HAL_CC0_ISR.

Produces:

Dependent Value:
The value is dependent on other settings.

@platformvalue

Annotation to indicate that the macro is only defined after <bsp430/platform.h> is included, and that the value of the macro is platform-dependent. This may be combined with @defaulted if the value may be overridden. It differs from @platformdep in that the latter may be referenced without including <bsp430/platform.h>. Example: BSP430_CLOCK_LFXT1_XCAP

Produces:

Platform-Based Value:
Undefined here; include <bsp430/platform.h> to obtain the correct value of this macro.

@platformdep

Annotation to indicate that the value of the macro depends on platform information (such as the type of peripheral providing the clock abstraction), so the value displayed in the documentation may not be correct. This may be combined with @defaulted if the value may be overridden. It differs from @platformvalue in that the value is dependent only on the header in which it is declared so may be used without including <bsp430/platform.h>. Example: BSP430_CLOCK_IS_FAULTED_NI

Produces:

Platform-Specific Value:
The value here is an example, and may differ from the actual value used depending on platform information.

@deprecated

Annotation to note that a function or capability has been superseded by an alternative that should be used in new code. Such annotations should indicate a date by which the deprecated capability may be expected to be removed.

Produces:

Deprecated:

@affects

Annotation to note that the setting for the given macro affects one or more other settings. Normally used for configBSP430_FOO which determines the value of BSP430_FOO which uses the companion @dependency annotation. Example: configBSP430_PLATFORM_SPIN_FOR_JUMPER

Produces:

Affects:
resource links

@dependency

Annotation to note that the setting for the given macro is affected by the one or more other settings. Normally used for BSP430_FOO when the value depends on configBSP430_FOO which uses the companion @affects annotation. Example: BSP430_PLATFORM_SPIN_FOR_JUMPER

Produces:

Dependency:
resource links

@cppflag

Annotation to indicate that the value of a macro may include preprocessor operations such as defined(BSP430_FOO), so may be used only within preprocessor directives. Example: configBSP430_HAL_PORT1_ISR

Produces:

C Preprocessor Only:
This macro may have a value that restricts its use to C preprocessor conditional directives.

@blocking

Annotation to indicate that a function that normally runs with interrupts disabled may enable interrupts and block until conditions allow it to return. Example: iBSP430consoleWaitForTxSpace_ni()

Todo:
This should be reflected in the function name when the non-interruptable and resource lock frameworks are revised.

Produces:

Warning
This function may enable interrupts and sleep until its completion conditions are met.

@consoleoutput

Annotation to indicate that the function may enable interrupts and block due to an internal dependence on iBSP430consoleWaitForTxSpace_ni(). Example: cputchar()

Produces:

Warning
This function may enable interrupts and sleep if interrupt-driven console transmission is enabled. See Interrupts and Console Operations.

@resource

Annotation to indicate that the function or data should only be invoked or accessed when a particular resource is held. The resource may be implicit, but normally it should be explicitly identified with this annotation. The annotation applies both to functions that require the resource be held before they are invoked, and functions that must internally acquire and release the resource. Example: cgetchar(), cgetchar_rh()

Produces:

Resource required:
resource_identifier

Copyright 2012-2014, Peter A. Bigot