Exercise 2

Customizing the application

During application development, it can be useful to customize aspects of the nRF Connect SDK for your specific application, without modifying the SDK files itself.

In this exercise, we will customize our application by adding custom files, configurations, and modifying the devicetree.

Exercise steps

Adding custom files

1. Create a .c file and a .h file in the same location as the main.c file, let’s call them myfunction.c and myfunction.h.

2. Define the function sum() in the myfunction.c file and make sure to include the header file.

#include "myfunction.h"

int sum(int a, int b){
    return a+b;

Then declare the function in the myfunction.h header file.


int sum(int a, int b);


The first two lines and the last lines are called include guards.


Include guards: A construct, in this case, a macro, that is used to avoid the problem of double inclusion, which happens if the header file is included twice thereby rendering the contents invalid.

3. To include the custom files in the build, we use the CMake function target_sources(). Add the following line to CMakeLists.txt

4. Now that the files are included in the build, we just need to include the header file in main.c to run the function.

#include "myfunction.h"

Alter main() to run the function that we have defined.

void main(void)
	int a = 3, b = 4;
		printk("The sum of %d and %d is %d\n\r", a, b, sum(a,b));

5. Build and flash the application to your board and you should see the following output.

Adding custom configurations

6. Now let’s define our own config that will determine if our custom files get included in the build or not. To do this, create a file called Kconfig in the application directory (the same location as CMakeLists.txt and prj.conf).

Make sure the file does not have a file extension. Depending on your editor, an extension may be added by default and has to be removed manually.

The first line sources Kconfig.zephyr, which is necessary when defining a new Kconfig file. The next three lines define the configuration CONFIG_MYFUNCTION as a boolean variable and sets its default value to n.

7. In CMakeLists.txt, we want the addition of the custom files to be conditional. Change the last line to use the function target_sources_ifdef(), like this:

The build will now only include the custom files if CONFIG_MYFUNCTION is enabled.

The reason for this is to limit the size of your application. Modules and subsystems are only included in the build when you enable the relevant configuration, allowing you to keep the application as small as you wish.

8. Lastly, enable the config by adding the following line to prj.conf:

9. If we disable this configuration now, the build will fail. Therefore, when using conditional includes like this, it is good practice to add a check in the main.c file, like below:

void main(void)
	int a = 3, b = 4;
			printk("MYFUNCTION not enabled\r\n");
		printk("The sum of %d and %d is %d\n\r", a, b, sum(a,b));

In this case, the application will not call the function unless the config is enabled, meaning the function is included in the build.

10. Try disabling the config in prj.conf, then build and flash the application. You should see the following output:

10.1 In the prj.conf file, change line 1 to CONFIG_MYFUNCTION=n

10.2 Build and flash the application as you have done previously. Reset the board upon flashing as the error message is only printed once at the very beginning.

Modifying the devicetree

In this exercise, we will customize our device’s devicetree only for this application by changing the baud rate at which information is sent to the console.

11. Create an overlay file in the application directory (the same location as CMakeLists.txt and prj.conf) with the name of the board you’re using, in our case nrf52833dk_nrf52833.overlay.


In nRF Connect for VS Code, in the Details View, there is an option to create an overlay file with the correct board name for you, see the image below. This function also lets you view all the nodes in the devicetree and will add in the correct syntax for you.

12. We want to change the baud rate for the UART instance used when printing to console, which is UART0. The baud rate is the property current-speed in the nrf-uart binding, which is defined and specified in nrf-uart-common.yaml lines 16-38. Add the following to the overlay file, which can be found in the root directory of the application, to change this property:

Other common things to change in the devicetree are the pins used by peripherals (rx, tx, cts, etc.), the status (okay, disabled) or the binding (nrf-spim, nrf-spis).

13. Build and flash the sample to the board.

To confirm that the devicetree was changed, we can view the compiled devicetree output. Click the icon to the right of the Devicetree View to Show Compiled DeivceTree Output, see image below to the left. This will reveal the full compiled devicetree on the right side of the window, see image below to the right. This file can also be found at the path fund_less3_exer2/build/zephyr/zephyr.dts

Search for the node-name uart0 (1) and find the node in the devicetree (2). Here we can see that the current-speed has been changed to the value set in the overlay file (3).

Devicetree View
Compiled devicetree output

14. Observe that the serial terminal doesn’t have any output. This is because we changed the baud rate, so the serial terminal is trying to read the log output at the wrong speed.

15. Close the window and open another session where you use the correct speed that was set in the overlay file, see image below. Now observe that the log is being printed like normal.

Changing speed in PuTTY

The solution for this exercise can be found in the GitHub repository, lesson3/fund_less3_exer2_solution of whichever version directory you are using (v2.x.x or v1.6.0-v1.9.1)

Register an account
Already have an account? Log in
(All fields are required unless specified optional)

Forgot your password?
Enter your email address, and we will send a link to reset your password.