diff --git a/firmware/ec/coding_style_guide b/firmware/ec/coding_style_guide new file mode 100644 index 0000000000..ac6d9447fa --- /dev/null +++ b/firmware/ec/coding_style_guide @@ -0,0 +1,369 @@ + +OpenCellular Coding Style +========================= + +We follow Linux Kernel coding style with following exceptions. + +Exceptions: +---------- + +o 4-space indentation +o Typedef enums and structs +o indent case labels + switch (suffix) { + case 'G': + case 'g': + mem <<= 30; + break; + case 'M': + case 'm': + mem <<= 20; + break; + case 'K': + case 'k': + mem <<= 10; + /* fall through */ + default: + break; + } + +Additions: +--------- + +o Non-public functions (functions not exported in header for use by other + modules) should be static +o Unless absolutely necessary, global variables within a module should be static +o Avoid using forward declarations, just #include headers when possible +o Static variables of the form s_variableName +o Non-static functions of the form ModuleName_functionName() +o File names + o C and header files in same directory + o ModuleName.c/h + o All directory names should be lowercase, with underscores added as + needed to improve readability (e.g. my_complex_directory/Foo.h) +o Hex values are upper-case: 0xFB +o Unless size doesn't matter, use fixed-width types defined in + (uint32_t, int8_t, etc.) +o Enums + o ALL_CAPS, start with enum name (within reason) for namespacing/readability + typedef enum SbdFlowControl { + SBD_FLOW_CONTROL_DISABLED = 0, + SBD_FLOW_CONTROL_HW = 3, + SBD_FLOW_CONTROL_SW = 4, + SBD_FLOW_CONTROL_ALL = 6 + } SbdFlowControl; + typedef enum AtLineType { + AT_LINE_TYPE_RESPONSE = 0, + AT_LINE_TYPE_CMD_ECHO, + + COUNT_AT_LINE_TYPE + } AtLineType; + + o #includes should be in alphabetical order & logically separated: + /* Module header[s] */ + … + /* stdlib headers */ + … + /* TI includes */ + … + /* OC includes */ + o Wrap functions like this: + ReturnType ReallyLongFunctionName(Type par_name1, Type par_name2, + Type par_name3) + { + DoSomething(); + ... + } + + ReturnType ReallyReallyReallyLongFunctionNameThatJustWillNotFit( + Type par_name1, /* double indent */ + Type par_name2, + Type par_name3) + { + DoSomething(); /* regular indent */ + ... + } + +o No spaces after end of line +o No blank lines at the end of file +o Each file should have description of what it does, which function it contains + etc. +o Each function should describe what operation it execute on the parameters and + what it returns. If there are any parameter overloaded, specify it clearly. +o No dead code. +o Function shouldn't be more than one page. +o Central exiting of function +o Use /* */ for comments. Multiple lines: + /* + * + */ +o MACROS are NOT to define functions. MACROS shouldn't effect control or effect + registers or changes the system states. + + +Sample Code: +----------- + +ExampleModule.h +/* + * Copyright 2004-present Facebook. All Rights Reserved. + * + * See Canonical Style Documents at: + * + * TODO: reference style document + * + * Example header that demonstrates our current C style. The goal of this + * code, while nonsensical, is to show a visual example of as many of our + * style rules/guidelines as possible. + * + * Note the #include order: stdlib includes, TI includes, then OpenCellular + * includes in quotes (""). Each group should be in alphabetical order. + * Additionally, we only want to include the headers necessary for the + * interfaces/structs/enums in the header, everything else should be in the + * source file + */ + +/* TODO: what do we want to do for #include guards? #pragma once doesn't have + * namespacing issues and is generally faster, but not guaranteed to be portable + */ +#ifndef EXAMPLEMODULE_H_ +#define EXAMPLEMODULE_H_ + +/* stdlib includes */ +#include +#include + +/* OC includes */ +#include "some_project_folder/SomeDependency.h" + +/* + * Initializes the module and stuff + */ +void ExampleModule_init(void); + +/* + * Takes lots of arguments, but doesn't do much that's useful with them. + * + * @param count an integer input (by value) + * @param value an enum input (by value) + * @param name a string input (by const-ref) + * @param outVal output integer arg (by pointer) + * + * @return true if function succeeds, false otherwise + */ +bool ExampleModule_funcWithManyArgs(int64_t count, + EnumType value, + const char *name, + uint32_t *outVal); + + +/* + * Another useless function + * + * @param param1 first example integer (by value) + * @param param2 second example integer (by value) + * @param param3 third example integer (by const-ref) + */ +void ExampleModule_methodThatHasAReallyLongNameOhCrapImRunningOutOfSpace( + int param1, + bool param2, + const uint32_t *param3); + +#endif /* EXAMPLEMODULE_H_ */ +ExampleModule.c +/* + * Copyright 2004-present Facebook. All Rights Reserved. + * + * See additional comments in: ExampleModule.h + * + * Note the #include order: First our related .h file, then the same + * order as we'd do elsewhere (see ExampleModule.h). + * + * This file is formatted with clang-format -i + */ + +#include "ExampleModule.h" + +/* stdlib includes */ +#include +#include +#include + +/* TI includes */ +#include +#include + +/* OC includes */ +#include "drivers/Power.h" +#include "drivers/Rf.h" +#include "helpers/Memory.h" +#include "helpers/Array.h" + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) + +typedef enum SampleState { + SAMPLE_STATE_INIT, + SAMPLE_STATE_RUN, + SAMPLE_STATE_IDK, + + COUNT_SAMPLE_STATE +} SampleState; + +typedef struct UselessConfig { + uint32_t someInt; /*!< Sample comment on member */ + int8_t otherValue; /*!< This looks important */ + SampleState state; /*!< All your base are belong to us */ + struct UselessConfig *next; /*!< Pointer to next item in list */ +} UselessConfig; + +static SampleState s_myUselessConfig = { + .someInt = 5, + .state = SAMPLE_STATE_INIT +}; + +static SampleState s_simpleInitSample = { .otherValue = 2 }; + +static uint32_t s_someStaticVariable; + +/* Array Initializer List Example */ +static const uint32_t sampleTable[COUNT_SAMPLE_STATE] = { + [SAMPLE_STATE_INIT] = 6, + [SAMPLE_STATE_RUN] = 42, + [SAMPLE_STATE_IDK ] = 0xFACEB00C +}; + +static const uint8_t anotherArray[] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 + 0x07, 0x08, 0x09, 0x0A, 0x0B }; + +/* TODO: How do we want to comment on functions? Having a full header block + * might be a bit overkill since we're planning on doing doxygen comments in + * the header. Some sort of comment to make it easier to see the beginning of + * new functions might be nice though. Not sure how we want to document static + * functions either - probably don't need to be as strict as for public + * functions + */ +void ExampleModule_init(void) +{ + s_myUselessConfig.state = SAMPLE_STATE_RUN; +} + +/******************************************************************************* + * This additional comment is not in the javadoc style, as it's supposed to + * describe more concrete implementation details. Any comments that may be + * useful to the class API "customer" (as opposed to someone who might modify + * this class) should instead be in JavaDoc style in ExampleCode.h. + ******************************************************************************/ +/* TODO: should this be MapLookup instead? */ +static uint32_t mapLookup(SampleState state, bool uselessParam) +{ + if (state < COUNT_SAMPLE_STATE) { + return sampleTable[state]; + } + return -1; +} + +const uin32_t ExampleModule_methodThatHasALongNameOhCrapImRunningOutOfSpace( + int param1, + bool param2, + const uint32_t *param3) +{ + return; +} + +/* TODO: not sure for sure how we want to do wrapping parameters. I'm on the + * fence between this style (FB & Google) vs. what I wrote above in the document + */ +bool ExampleModule_funcWithManyArgs(int64_t count, + EnumType value, + const char *name, + uint32_t *outVal) +{ + /* + * The body of this function is used to demonstrate common code constructs + * so that the indentation, braces, and spacing styles for them are + * immediately apparent. + */ + + /* + * This section demonstrates different kinds of if() blocks, including + * long/short if() blocks, complicated if() expressions, and validity + * checks on pointer/handle variables. + */ + if (count < 0) { + ++count; + } else if (count == 0) { + --count; + } else { + count *= 2; + } + + if (strlen(name) < 20 && + !strcmp(name, "some string that I made up") && + (count < 0 || count > 5)) { + *outVal += count; + } + + if (name) { + count += strlen(name); + } + + int64_t *realPtr = NULL; + if (!realPtr) { + realPtr = malloc(sizeof(*realPtr)); + } + + /* This section demonstrates looping constructs. */ + for (int64_t i = 0; i < count; ++i) { + *outVal *= 2; + } + + int i = 10; + while (i > 0) { + --i; + } + + do { + ++i; + } while (i <= 10); + + /* + * This section demonstrates formatting for switch statments + */ + switch (s_myUselessConfig.state) { + case SAMPLE_STATE_INIT: + s_myUselessConfig.state = SAMPLE_STATE_RUN; + break; + case SAMPLE_STATE_RUN: { + uint32_t i = s_someStaticVariable - 1; + printf("Doing stuff %d", i); + break; + } + case SAMPLE_STATE_IDK: + default: + break; + } + + /* + * This section demonstrates formatting for basic expressions, operators, + * and initializations. + */ + char s[] = "startValue"; + size_t someSize = sizeof(*realPtr); + int val = count / 2; + count = (count + val) & ((val << 3) + count * val); + uint32_t *samplePtr = &s_someStaticVariable; + SampleState zeroInitializedStruct = {}; + + /* Multiple variables of same type */ + /* TODO: allow multiple vars on one line? eg. int var1, var2, var3 */ + int var1; + int *var2; + int *var3; + + var1 = 2; + var2 = &var1; + var3 = var2; + + return true; +} +