BSP430
20141115
Board Support Package for MSP430 microcontrollers
|
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.
BSP430's coding style may be obtained using the following Emacs ccmode style:
An acceptably close approximation can be had using the following Artistic Style (astyle) command line:
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.:
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.
BSP430
with or without prefix characters that indicate type information. The next section of the identifier encodes information about the BSP430 module to which it belongs.config
.i
is used for int
, ul
for unsigned long
, v
for void
, and h
for a HAL handle. The letter x
is used as a prefix for more complex types, such as const char *
.s
is a struct
, u
is a union
, e
is an enum
. h
indicates a handle for (pointer to) a HAL structure type; for example hBSP430halSERIAL is a typedef for a pointer to sBSP430halSERIAL. t
is used for any typedef for a normal type, such as tBSP430periphHandle.struct
, union
, and enum
type directly (i.e. not through a handle), those types should have typedef aliases that use the tag as the type name.e
._Hz
._ni
(_NI
for macros).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.
int
is the native type. Anybody using an MSP430 should know that this is a 16-bit value.unsigned int
is the type for any 16-bit peripheral registers.unsigned char
is the type for any 8-bit peripheral registers.char
as the core type.uint8_t
as codified in <stdint.h>
.const
qualifier.BSP430 places comparison operands which are lvalues on the right side of the operator, as with:
Yes, even if the conditional operator "couldn't possibly be mistyped" as an assignment operator. Up with it you must put.
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:
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:
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:
See also BSP430 Configuration for naming conventions and standards related overriding default configurations.
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:
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:
It may include additional material such as <bsp430/periph.h> but that should not be assumed.
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:
This technique allows use of:
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:
@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
.
A common practice, followed by Texas Instruments in their standard MSP430 MCU-specific headers, is to use code like:
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:
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:
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:
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.
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:
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:
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:
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:
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:
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:
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:
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:
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()
Produces:
Annotation to indicate that the function may enable interrupts and block due to an internal dependence on iBSP430consoleWaitForTxSpace_ni(). Example: cputchar()
Produces:
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:
Copyright 2012-2014, Peter A. Bigot