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.