aboutsummaryrefslogtreecommitdiffstats
path: root/docs/source/libmaple/coding-standard.rst
diff options
context:
space:
mode:
authorbnewbold <bnewbold@robocracy.org>2014-08-27 17:36:11 -0400
committerbnewbold <bnewbold@robocracy.org>2014-08-27 17:42:22 -0400
commit34b766c9d5f778762069938c71e052fa40455d1c (patch)
tree3a2b77e636b222fecff6366218cf7845029afecf /docs/source/libmaple/coding-standard.rst
parent746d6fecf86572c9fe95dbbffdf541a8d3875dd0 (diff)
parentadd7e54ccaf61859874527feda2b51ea172ce697 (diff)
downloadlibrambutan-34b766c9d5f778762069938c71e052fa40455d1c.tar.gz
librambutan-34b766c9d5f778762069938c71e052fa40455d1c.zip
merge libmaple docs ("leaflabs-docs") into ./docs
In the past, libample documentation was forked out of this repository because the documentation had increased in scope. For the librambutan, and the rambutan project in general, we will try to keep documentation closer to the source code, so the librambutan-specific documentation should live here. Other sections of leaflabs-docs will be culled in a following commit. This merge attempts to maintain history by using a subtree strategy. Followed directions at: http://nuclearsquid.com/writings/subtree-merging-and-you/ Full history for files should be accessible using the "--follow" flag to git log, eg: git log --follow docs/source/adc.rst It should be possible to pull patches from leaflabs-docs with: git pull -s subtree leaflabs-docs master ... at least until the docs in this repository diverge significantly.
Diffstat (limited to 'docs/source/libmaple/coding-standard.rst')
-rw-r--r--docs/source/libmaple/coding-standard.rst422
1 files changed, 422 insertions, 0 deletions
diff --git a/docs/source/libmaple/coding-standard.rst b/docs/source/libmaple/coding-standard.rst
new file mode 100644
index 0000000..9ed56cc
--- /dev/null
+++ b/docs/source/libmaple/coding-standard.rst
@@ -0,0 +1,422 @@
+.. _libmaple-coding-standard:
+
+Coding Standard
+===============
+
+This page documents the coding standard for :ref:`libmaple`. It's
+intended as a guide for how you should structure any code you would
+like included into the LeafLabs releases of libmaple.
+
+LeafLabs team members are required to follow these when producing new
+code. Community contributors to libmaple are strongly encouraged to
+do so; following these rules will greatly increase the probability
+that your patches will be folded in.
+
+In general, follow this guide unless there's a very good reason not
+to. Laziness doesn't count as a good reason. Most, if not all, of
+these decisions are entirely arbitrary, but it's important for
+readability that we be consistent. (If you notice an inconsistency,
+you should fix it).
+
+Note that the file ``.dir-locals.el`` in the libmaple root directory
+already ensures that many of these standards are followed by default
+in Emacs (but not on Windows, where it would need to be named
+``_dir_locals.el``, and no way, man). There's also some elisp
+scattered about this file which will provide you additional help.
+
+Configuration for other editors (vim, etc.) would be nice!
+
+.. contents:: Contents
+ :local:
+
+License
+-------
+
+.. highlight:: scheme
+
+Put an MIT license at the beginning of the file (look at any of our
+source files for an example). Copyright should go either to you or to
+LeafLabs, LLC.
+
+Emacs: if you don't like seeing the license, you should use elide-head
+(which will hide it for you). You can use the following::
+
+ (require 'elide-head)
+ (setq programming-mode-hooks '(c-mode-hook c++-mode-hook))
+ (add-to-list 'elide-head-headers-to-hide
+ '("The MIT License" . "DEALINGS IN\n [*] THE SOFTWARE"))
+ (add-to-list 'elide-head-headers-to-hide
+ '("The MIT License" . "DEALINGS IN THE\n...SOFTWARE"))
+ (dolist (hook programming-mode-hooks)
+ (add-hook hook (lambda () (elide-head))))
+
+Whitespace
+----------
+
+TextMate users may find `this bundle
+<https://github.com/glennr/uber-glory-tmbundle>`_ useful for
+automatically converting tabs to spaces and removing trailing
+whitespace at save time.
+
+- 4 space indents (set in ``.dir-locals.el``).
+
+- Unix newlines.
+
+- No tab characters (set in ``.dir-locals.el``).
+
+- No trailing whitespace. For help getting this (and no tab
+ characters) done automatically in Emacs, you can use
+ `code-fascism.el <https://github.com/mbolivar/code-fascism>`_.
+
+- Files end in exactly one newline. The presence of a newline at EOF
+ is already done by ``c-require-final-newline`` in recent versions of
+ Emacs.
+
+- Exactly two newlines separate source paragraphs (you do separate
+ your code into paragraphs, don't you?).
+
+- The first line in a function is non-blank.
+
+.. highlight:: cpp
+
+- Exactly one space after ``if``, ``else``, ``for``, and ``while``,
+ before the following ``{`` or ``(``. One space before ``else``,
+ after the preceding ``}``. For example::
+
+ // This is good; we like this:
+ if (foo) {
+ while (quux) {
+ bar();
+ }
+ } else {
+ baz();
+ }
+
+ // THIS IS BAD! DON'T DO THIS:
+ if(foo){
+ while(quux){
+ bar();
+ }
+ }else{
+ baz();
+ }
+
+- Exactly one space in between binary arithmetic, logical, and
+ comparison operators and their operands. Examples::
+
+ // This is good:
+ int x = a + b * (c - d);
+ if (x != 0 && a > 7) {
+ SerialUSB.println(x);
+ }
+
+ // THIS IS BAD!
+ int x = a+b*(c-d);
+ if (x!=0 && a>7) {
+ SerialUSB.println(x);
+ }
+
+ // This is good:
+ uint32 adc_data = ADC1_BASE->DR;
+ SerialUSB.println(adc_data);
+
+ // THIS IS BAD!
+ uint32 adc_data = ADC1_BASE -> DR;
+ SerialUSB . println(adc_data);
+
+- No space between a unary operator and its operand. Examples::
+
+ // Good:
+ x++;
+
+ // BAD!
+ x ++;
+
+ // Good:
+ y = -x;
+
+ // BAD!
+ y = - x;
+
+- If you need to break up a long line:
+
+ * Prefer to break up long expressions after a binary operator. Example::
+
+ // Good:
+ if (some_really_long_conditional_wow_this_really_goes_on_forever ||
+ maybe_something_else_could_happen_too) {
+ ...
+ }
+
+ // BAD!
+ if (some_really_long_conditional_wow_this_really_goes_on_forever
+ || maybe_something_else_could_happen_too) {
+ ...
+ }
+
+ * When breaking up a function's arguments over multiple lines, align
+ the arguments on subsequent lines with the first argument.
+ Example::
+
+ // Good:
+ return_type value_i_got = function_with_a_really_long_name(argument1,
+ argument2,
+ argument3);
+
+ // BAD!
+ return_type value_i_got = function_with_a_really_long_name(argument1,
+ argument2,
+ argument3);
+
+ // BAD!
+ return_type value_i_got = function_with_a_really_long_name(argument1,
+ argument2,
+ argument3);
+
+- In function invocations, no space in between the function name and
+ the opening parenthesis. Example::
+
+ // Good:
+ SerialUSB.println("Hello, world!");
+
+ // BAD!
+ SerialUSB.println ("Hello, world!");
+
+- Don't indent C code within a conditionally-compiled ``extern "C"``
+ block. Example::
+
+ // Good:
+ #ifdef __cplusplus
+ extern "C"{
+ #endif
+
+ void some_c_function(void);
+
+ #ifdef __cplusplus
+ } // extern "C"
+ #endif
+
+ // BAD!
+ #ifdef __cplusplus
+ extern "C"{
+ #endif
+
+ void some_c_function(void);
+
+ #ifdef __cplusplus
+ } // extern "C"
+ #endif
+
+ Emacs does the "bad" behavior by default, which can be very
+ annoying. You can turn this off with ::
+
+ (defun c-mode-inextern-lang-hook ()
+ (setcdr (assq 'inextern-lang c-offsets-alist) '-))
+ (add-hook 'c-mode-hook c-mode-inextern-lang-hook)
+
+Comments
+--------
+
+.. highlight:: c++
+
+- Multi-line comments are pretty flexible. Any of these is fine::
+
+ /* Comment starts here.
+ * Continued lines have a '*' before them.
+ * The comment can end after the last line.
+ */
+
+ /* Comment starts here.
+ * The comment can end on the same line. */
+
+ /*
+ * You can also place a newline after the opening "/*".
+ */
+
+- Doxygen comments are multi-line comments that begin with ``/**``
+ instead.
+
+- Single-line comments are up to you.
+
+Braces
+------
+
+- Mostly `1TBS
+ <http://en.wikipedia.org/wiki/Indent_style#Variant:_1TBS>`_. The
+ only difference is that the opening brace of a function's definition
+ occurs exactly one space character after the closing parenthesis in
+ that function's parameter list. Example::
+
+ void func(void) {
+ ...
+ }
+
+Naming conventions
+------------------
+
+We'll handle the usual casing/underscore debate as follows.
+
+- First, ``Dont_Mix_Like_This``, because ``It_Looks_Really_Ugly``, ok?
+ [There's been some debate about this, and some exceptions are
+ already grandfathered in, so in order to settle it, let's call this
+ a "recommendation" instead of "requirement".]
+
+- Variables: Use underscores to separate words in C identifiers::
+
+ int some_example_name;
+
+ User-facing C++ variables should be camel cased
+ (``thisIsAnExample``, ``boardPWMPins``, etc.), for consistency with
+ the Arduino style. It's probably a good idea for you to case
+ non-user facing C++ variables in the C style; this will help
+ disambiguate what's part of the Wirish API and what's not.
+
+- Classes: Pascal case. So ``ThisIsAClassName``, but ``thisIsNot``,
+ ``this_is_not``, and ``Dont_You_DareTryANYTHING_STUPID``.
+
+- Functions: C functions are all lowercase, and words are separated by
+ underscores. C++ method names are camel cased.
+
+- Structs: Usually like variables (``adc_dev``, ``adc_reg_map``,
+ etc.), but it's not crucial. Don't feel obliged to put ``_t`` at
+ the end of the type name; we don't.
+
+- Macros and constants: all caps, separated by underscores. C++
+ variables with the ``const`` qualifier generally aren't considered
+ "constants" for the purposes of this rule; i.e., they are cased
+ according to the rules for variables. We make an exception for
+ ``PIN_MAP``, because it's the central Wirish data structure.
+
+- foo.h gets ``#ifdef``\ 'ed to ``_FOO_H_``.
+
+- Acronyms: The case of letters in an acronym is determined by the
+ case of the first letter in the acronym, which is determined by
+ following the above rules. Examples::
+
+ // Good:
+ void usb_func() { ... }
+ void frob_usb_disc() { ... }
+ class SomethingUSB {
+ void usbInit();
+ void initUSB();
+ };
+
+ // BAD:
+ class BadUsb { ... }; // say "GoodUSB" instead
+ void swizzle_USB_disc() { ... } // say "swizzle_usb_disc" instead
+
+Documentation
+-------------
+
+- Doxygen comments on every user-facing function and type.
+ Additionally, individually document the fields and enumerator values
+ of nontrivial user-facing structs and enums. See any register map
+ type's definition for an example.
+
+- For libmaple proper, you don't need comments for each register bit
+ definition, since that's just repeating information better obtained
+ by reading ST RM0008.
+
+- Doxygen comments generally only belong on types, functions,
+ etc. that are part of the public user-facing API.
+
+ This essentially means that if what you're writing is going to be
+ documented under http://leaflabs.com/docs/ (i.e., if there's `Sphinx
+ documentation <http://sphinx.pocoo.org/>`_ for it in the
+ `leaflabs-docs <https://github.com/leaflabs/leaflabs-docs>`_
+ repository), then you need to write Doxygen comments. Further,
+ those Sphinx docs should use Breathe to pull the Doxygen out. (For
+ more information on this, see the `leaflabs-docs README
+ <https://raw.github.com/leaflabs/leaflabs-docs/master/README>`_).
+
+ Because Breathe isn't totally mature yet, you won't always be able
+ to do this. In these cases, document the code "manually" using the
+ Sphinx `C and C++ domains
+ <http://sphinx.pocoo.org/domains.html#the-c-domain>`_. This should
+ be avoided if at all possible, since it creates a maintenance burden
+ of documenting things in two places at once, and makes it easier for
+ documentation to go stale.
+
+ If you do have to document something manually, put a comment in the
+ source file informing future maintainers about it, so they'll pay
+ extra attention when making changes.
+
+- When adding peripheral support, it would be nice if you put
+ longer-form comments into the libmaple ``notes/`` directory, with a
+ comment in the corresponding .h file referring to it. See the
+ :ref:`dac.h <libmaple-dac>` source for an example.
+
+ This lets us keep the source files relatively free of "introductory"
+ material, while allowing new readers a convenient starting point.
+ These longer-form notes also have a habit of turning into official,
+ user-facing documentation (or `wiki <http://wiki.leaflabs.com>`_
+ pages).
+
+- **For libmaple proper**, the convention is to document any
+ user-facing function at the point where it is defined. In
+ particular, this means you should document an externally-linked
+ function defined in a .c file in that .c file, not in the header
+ file where it is declared to the user.
+
+ **For Wirish**, the convention is to put the documentation in the
+ header file where the function is declared.
+
+General Formatting
+------------------
+
+.. highlight:: scheme
+
+- Keep it 80-column clean.
+
+ Emacs users: this means that the largest column number is 79. You
+ should turn on column number mode to help you out::
+
+ (column-number-mode 1)
+
+ You can get more help from `lineker-mode
+ <http://www.helsinki.fi/~sjpaavol/programs/lineker.el>`_. Just put
+ lineker.el somewhere in your load-path, and::
+
+ (require 'lineker)
+ (dolist (hook '(c-mode-hook c++-mode-hook))
+ (add-hook hook (lambda () (lineker-mode 1))))
+
+.. highlight:: cpp
+
+Language Features
+-----------------
+
+In libmaple proper, aim for C99 compatibility. Some GCC extensions
+are OK, but `don't get crazy <http://www.youtube.com/watch?v=jZkdcYlOn5M>`_.
+
+Explicitly approved GCC extensions:
+
+ * `asm volatile <http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html>`_
+
+ * `Nested functions <http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html>`_
+
+In Wirish, generally be very conservative when using C++ features that
+aren't part of C. We are forced to use C++ for Arduino compatibility
+(and the general Arduino style of conflating objects and libraries),
+but it's an angry beast, and we don't want to provoke it. **The
+mantra is "C with classes"**.
+
+Explicitly approved C++ features:
+
+ * Initializers that aren't constant; e.g. the ``gpio_dev*`` values
+ in a ``PIN_MAP``.
+
+ * Default arguments: e.g., the timeout argument in
+ :ref:`lang-waitforbuttonpress`.
+
+Explicitly forbidden C++ features:
+
+ * Templates
+
+Conditionally allowed C++ features:
+
+ * Operator overloading: Never allowed when it's just for style.
+ Probably fine when you're implementing a class that models a
+ mathematical structure, and you'd like to implement
+ e.g. ``operator+()``.
+