File/Function Headers
Every file/function must have a consistent comment header block!People have to read, understand and interact with your code. Writing clear and concise code goes a long way here, but you should also include at least one sentence about every function in your file to say what it does.
I never use Doxygen, but I've gotten in the habit of using Doxygen style comments as good practice since it includes everything you need to properly document a function right next to your source code, ensuring it's more likely to get updated as the code itself changes.
File Headers: The Bare Minimum
You must include at least a one or two line description of this file, ideally a full description, the author(s), and the license terms in every file. If relevant, a link to the associated product or datasheet should also be included.
The format doesn't need to use Doxygen style tags, but the above information must be included. An example of this is shown in the file header below for the TSL2561 light sensor:
/**************************************************************************/ /*! @file Adafruit_TSL2561.cpp @author K.Townsend (Adafruit Industries) @license BSD (see license.txt) Driver for the TSL2561 digital luminosity (light) sensors. Pick one up at http://www.adafruit.com/products/439 Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! @section HISTORY v2.0 - Rewrote driver for Adafruit_Sensor and Auto-Gain support, and added lux clipping check (returns 0 lux on sensor saturation) v1.0 - First release (previously TSL2561) */ /**************************************************************************/
Functions: The Bare Minimum
As an absolute minimum, you must include at least a few words describing every single function in your module. This applies to both public and private functions./**************************************************************************/ /*! Writes the specified number of bytes over I2C */ /**************************************************************************/ error_t pcf2129WriteBytes(uint8_t reg, uint8_t *p_buffer, size_t length) { // ... }
Public Functions: The Full Monty!
Comment every param on public functions, include an example if possible.
Doxygen style tags are not necessary, but the minimum amount of information should be included.
Why? Because it stink to try to decipher exactly what the range on a parameter is, what that obscure looking pointer thingy actually does or wants, etc.!
Bonus Points: Adding a 2-3 line example of how to use this function takes two minutes when you're knee-deep writing the code, but it's a huge favour to the future you as well as anyone who has to deal with your code in the future. A simple code sample allows you to quickly digest how a function is meant to work, and goes a long way to getting started with the code quickly.
/**************************************************************************/ /*! @brief Sets the time on the RTC to the supplied value @param[in] time The rtcTime_t variable containing the time to set @section EXAMPLE @code // Try to initialise the PCF2129 RTC if (pcf2129Init()) { printf("PCF2129 failed to initialise"); } else { // Set time to 10:04:00, 4 September 2012 (24-hour time) rtcTime_t time; rtcCreateTime(2012, RTC_MONTHS_SEPTEMBER, 4, 10, 4, 0, 0, &time); pcf2129SetTime(time); } @endcode */ /**************************************************************************/ error_t pcf2129SetTime(rtcTime_t time) { // ... }
Comment Blocks
Be consistent, and document key information in the code.While some safety standards like MISRA state that you must use full opening and closing comments even for single line comments ... /* one line of commenty stuff */ ... two forward-slashes ... // ... is fine and doesn't matter on any modern C compiler.
For large, complex comment blocks, I've personally ended up with the following styles, though these are just suggestions.
Register Tables
This comment block describes individual bits for a config register. You generally have to read the documentation thoroughly once writing the first draft of the driver, but you'll quickly forget those details, so a bit of extra effort here pays off when future you needs to come back to the code, or when someone else needs to pick it up and debug./* Set CONTROL1 register (0x00) ==================================================================== BIT Symbol Description Default --- ------ --------------------------------------------- ------- 7 EXT_TEST 0 = Normal mode, 1 = External clock test mode 0 6 -- RESERVED 5 STOP 0 = RTC clock runs, 1 = RTC clock stopped 0 4 TSF1 0 = No timestamp interrupt, 0 1 = Flag set when TS input is driven to an intermediate level between power supply and ground. (Flag must be cleared to clear interrupt.) 3 POR_OVRD 0 = Power on reset override disabled 0 1 = Power on reset override enabled 2 12_24 0 = 24 hour mode, 1 = 12 hour mode 0 1 MI 0 = Minute interrupt disabled, 1 = enabled 0 0 SI 0 = Second interrupt disabled, 1 = enabled 0 */ ASSERT_STATUS(pcf2129Write8(PCF2129_REG_CONTROL1, 0x00));
Config Setting/Macro Groups
I'm in the habit of creating a projectconfig.h file for every complex project I work on, and place all config settings and macros in this file.To keeps things organized, I've come up with the following format for these config values:
/*========================================================================= UART ----------------------------------------------------------------------- CFG_UART_BAUDRATE The default UART speed. This value is used when initialising UART, and should be a standard value like 57600, 9600, etc. NOTE: This value may be overridden if another value is stored in EEPROM! CFG_UART_BUFSIZE The length in bytes of the UART RX FIFO. This will determine the maximum number of received characters to store in memory. -----------------------------------------------------------------------*/ #define CFG_UART_BAUDRATE (115200) #define CFG_UART_BUFSIZE (256) /*=========================================================================*/
Documenting Resource Allocation
You can use these types of table to keep track of available pins or finite resources like EEPROM memory as follows, which is not only good practice for you but can help avoid problems later when other people interact with your code:/*========================================================================= EEPROM ----------------------------------------------------------------------- EEPROM is used to persist certain user modifiable values to make sure that these changes remain in effect after a reset or hard power-down. The addresses in EEPROM for these various system settings/values are defined below. The first 256 bytes of EEPROM are reserved for this (0x0000..0x00FF). CFG_EEPROM_SIZE The number of bytes available on the EEPROM CFG_EEPROM_RESERVED The last byte of reserved EEPROM memory EEPROM Address (0x0000..0x00FF) =============================== 0 1 2 3 4 5 6 7 8 9 A B C D E F 000x x x . . x x x x x x x x . . . . Chibi Node Addresses 001x . . . . . . . . . . . . . . . . 002x . . . . . . . . . . . . . . . . 003x . . . . . . . . . . . . . . . . 004x x x x x . . . . x x x x x x x x Accelerometer Cal Settings 005x x x x x x x x x x x x x x x x x 006x x x x x . . . . x x x x x x x x Magnetometer Cal Settings 007x x x x x x x x x x x x x x x x x 008x x x x x . . . . x x x x x x x x Gyroscope Cal Settings 009x x x x x x x x x x x x x x x x x 00Ax . . . . . . . . . . . . . . . . 00Bx . . . . . . . . . . . . . . . . 00Cx . . . . . . . . . . . . . . . . 00Dx . . . . . . . . . . . . . . . . 00Ex . . . . . . . . . . . . . . . . 00Fx . . . . . . . . . . . . . . . . -----------------------------------------------------------------------*/ #define CFG_EEPROM_SIZE (4032) #define CFG_EEPROM_RESERVED (0x00FF) // Protect the first 256 bytes of memory #define CFG_EEPROM_CHIBI_NODEADDR (uint16_t)(0x0000) // 2 #define CFG_EEPROM_CHIBI_IEEEADDR (uint16_t)(0x0004) // 8 #define CFG_EEPROM_SENSORS_CAL_ACCEL_CONFIG (uint16_t)(0x0040) // 2 #define CFG_EEPROM_SENSORS_CAL_ACCEL_SENSORID (uint16_t)(0x0042) // 2 #define CFG_EEPROM_SENSORS_CAL_ACCEL_X_SCALE (uint16_t)(0x0048) // 4 #define CFG_EEPROM_SENSORS_CAL_ACCEL_X_OFFSET (uint16_t)(0x004C) // 4 #define CFG_EEPROM_SENSORS_CAL_ACCEL_Y_SCALE (uint16_t)(0x0050) // 4 #define CFG_EEPROM_SENSORS_CAL_ACCEL_Y_OFFSET (uint16_t)(0x0054) // 4 #define CFG_EEPROM_SENSORS_CAL_ACCEL_Z_SCALE (uint16_t)(0x0058) // 4 #define CFG_EEPROM_SENSORS_CAL_ACCEL_Z_OFFSET (uint16_t)(0x005C) // 4 #define CFG_EEPROM_SENSORS_CAL_MAG_CONFIG (uint16_t)(0x0060) // 2 #define CFG_EEPROM_SENSORS_CAL_MAG_SENSORID (uint16_t)(0x0062) // 2 #define CFG_EEPROM_SENSORS_CAL_MAG_X_SCALE (uint16_t)(0x0068) // 4 #define CFG_EEPROM_SENSORS_CAL_MAG_X_OFFSET (uint16_t)(0x006C) // 4 #define CFG_EEPROM_SENSORS_CAL_MAG_Y_SCALE (uint16_t)(0x0070) // 4 #define CFG_EEPROM_SENSORS_CAL_MAG_Y_OFFSET (uint16_t)(0x0074) // 4 #define CFG_EEPROM_SENSORS_CAL_MAG_Z_SCALE (uint16_t)(0x0078) // 4 #define CFG_EEPROM_SENSORS_CAL_MAG_Z_OFFSET (uint16_t)(0x007C) // 4 #define CFG_EEPROM_SENSORS_CAL_GYRO_CONFIG (uint16_t)(0x0080) // 2 #define CFG_EEPROM_SENSORS_CAL_GYRO_SENSORID (uint16_t)(0x0082) // 2 #define CFG_EEPROM_SENSORS_CAL_GYRO_X_SCALE (uint16_t)(0x0088) // 4 #define CFG_EEPROM_SENSORS_CAL_GYRO_X_OFFSET (uint16_t)(0x008C) // 4 #define CFG_EEPROM_SENSORS_CAL_GYRO_Y_SCALE (uint16_t)(0x0090) // 4 #define CFG_EEPROM_SENSORS_CAL_GYRO_Y_OFFSET (uint16_t)(0x0094) // 4 #define CFG_EEPROM_SENSORS_CAL_GYRO_Z_SCALE (uint16_t)(0x0098) // 4 #define CFG_EEPROM_SENSORS_CAL_GYRO_Z_OFFSET (uint16_t)(0x009C) // 4 /*=========================================================================*/
/*========================================================================= GPIO INTERRUPTS ----------------------------------------------------------------------- This table shows where GPIO interrupts are mapped in this project (Note that the LPC11U and LPC13U use different names for the IRQ Handlers in the standard headers) Interrupt Location ------------------------------------------ ------------------------- PIN_INT0_IRQHandler - FLEX_INT0_IRQHandler chb_drvr.c PIN_INT1_IRQHandler - FLEX_INT1_IRQHandler pcf2129.c PIN_INT2_IRQHandler - FLEX_INT2_IRQHandler spi.c (cc3000) PIN_INT3_IRQHandler - FLEX_INT3_IRQHandler PIN_INT4_IRQHandler - FLEX_INT4_IRQHandler PIN_INT5_IRQHandler - FLEX_INT5_IRQHandler PIN_INT6_IRQHandler - FLEX_INT6_IRQHandler PIN_INT7_IRQHandler - FLEX_INT7_IRQHandler GINT0_IRQHandler GINT0_IRQHandler -----------------------------------------------------------------------*/ /*=========================================================================*/
Page last edited April 23, 2024
Text editor powered by tinymce.