Skip to Content

Ctags for the nRF5 SDK

Ctags is a well-known utility which generates an index of functions, variables, and other constructs for a set of source files. This index, referred to as a tags file, may be used by text editors or other tools to efficiently locate the indexed items. A common example is looking up the definition of a function from a line where it is called. Ctags has built-in support for a large number of languages, but it does not implement a full language parser and may sometimes be confused.

The nRF5 SDK

Nordic Semiconductor produces excellent wireless SoCs in their nRF51 and nRF52 product lines. These chips are provided with precompiled and linked binaries implementing wireless protocols such as ANT or BLE. From application code, this functionality is accessed via supervisor calls, essentially software interrupts, which are conveniently wrapped up as normal functions defined in the nRF5 SDK.

Because these functions simply execute a special instruction to transfer execution to the provided binary, Nordic defines them using a preprocessor macro:

#define SVCALL(number, return_type, signature)          \
  __attribute__((naked))                                \
  static return_type signature                          \
  {                                                     \
    __asm(                                              \
        "svc %0\n"                                      \
        "bx lr" : : "i" (number) : "r0"                 \
    );                                                  \
  }

The result is a function with the specified prototype which executes the SVC instruction and then returns. As an example, the function

uint32_t sd_ble_enable(uint32_t * p_app_ram_base)
{
  ...
}

would be defined using

SVCALL(SD_BLE_ENABLE, uint32_t, sd_ble_enable(uint32_t * p_app_ram_base));

This works very well, but Ctags does not process macros and thus cannot index any of these functions by default.

Ctags Regex

Fortunately Ctags supports tag generation using custom regular expressions. Here is what I added to my Ctags arguments to index the SVCALL functions:

--regex-c++="/^[ \t]*SVCALL([^,]*,[ \t]*){2}([^\( \t]*)/\2/d,definition/"

This option specifies a regular expression which matches lines containing SVCALL and outputs each function name as a “definition” tag.

Pattern Explanation
[ \t]* matches any leading whitespace
SVCALL matches the SVCALL macro name
([^,]*,[ \t]*){2} matches the first two arguments to the macro
([^\( \t]*) matches text up to an open parenthesis or whitespace
\2 references the second () group, the function name
d,definition specifies the kind of tag to generate

The resulting tags file makes working with the nRF5 SDK much easier. For example, I am able to quickly search for functions with Vim + CtrlP.