Transcript for:
Custom Board Development with NRF Connect SDK

Hi everyone and welcome to this developer-oriented Nordic Tech webinar titled Adding Custom Board Support in NRF Connect SDK. So my name is Ali Aljani and I am a Developer Marketing Manager at Nordic Semiconductor. For the agenda of today's webinar, we aim here to cover the fundamental principles and best practices for seamlessly adding support for a custom board in NRF Connect SDK. We'll start by answering the question. What is a board in the context of NRF Connect SDK and Zephyr?

Then we'll move into the hardware support hierarchy in NRF Connect SDK and Zephyr. Understanding the structure of hardware support for the target chip is quite important when it comes to creating custom board support. After that, we will dive into mandatory, optional, and special use case board files.

we will also cover some special considerations when it comes to developing custom boards for the that are based on the nrf91 and nrf53 series finally you will have a hands-on demo showing how to build a custom board from scratch and in there we'll be using the nrfconnect for vs code extension which really helps a lot when it comes to converting hardware schematics to device 3 syntax as we will see in the demo part When developing applications with NRF Connect SDK, the concept of a board is really at the center of the development. A board is simply the target hardware you want to build an application for and then run an application on. It could be a development kit, a prototyping platform, a module, or your own PCB for your own product.

So a board describes your hardware, including the exact chip used, whether it's a SOC or SIP, the peripheral configurations of the chip, the component on your hardware design so things like sensors connectors external memories and so on and it's very important to remember that nrf connect sdk has high portability embedded in it and it's based on the zephyr arthur so the zephyr arthur is a core component in nrf connect sdk and in nrf connect sdk hardware it's it's not described using c header files no it's highly decoupled from the application hardware is really highly decoupled and it's done through the use of device tree and kconfig. So in practice, a board in terms of nrfconnect, sdk, and zephyr, it's basically a directory. It's a folder that contains several files, mainly device tree and kconfig, but there are other files that are used for special use cases, and there are optional files. And we will dive into these files in depth in this webinar. But back to the portability topic.

The concept of boards can help you make an application work on different type of hardwares, which we refer now as boards. So for instance, moving your code from one development kit, like the NR52-840DK to another one, let's say it's the NR52-833DK, can be really as straightforward as just changing the build target. And same applies when you move your application from a development kit to your own custom hardware. Now let's take a look at the...

hardware support hierarchy for the target chip or the target SOC or SIP and nrfconnect sdk uses the same hardware support hierarchy that's used by zephyr which is divided into layers and these layers the good news here is like most of these layers is provided by the sdk the only layer that you need to write for your own custom do your own custom hardware is the board layer so if we start from the board layer this is a specific SOC instance and it's peripheral in a concrete hardware specification again you need to write this for your own custom hardware while the SOC is the the SOC layer it's the exact system on chip or SIP that the board CPU is part of again this is provided by the SDK and what we have here is basically a full description of the address space of the chip available memory available peripherals and so on The SoC series is basically a smaller group of tightly related SoC. So think let's take an example of the we have like the nrf52 series the 53 series and the nrf91 series and then if we go one level kind of like wider which is the SoC family we have like the nrf family that's a wider group of associate with similar characteristics. A CPU core this is a particular CPU in a specific architecture.

So for example, let's say it's the ARM architecture, we have the CPU core of the M0, M4, M33, and so on. And what you find in here, again, this is provided by the SDK, what you find in here, you find things like the early boot up sequence and the context switch code, fault management, and so on. And finally, the architecture, this is a an instruction set architect architecture and so again this is also provided by the sdk we don't need to do anything about this and this is for architectures like arm risk 5 and x86 To better understand the hardware support hierarchy, let's take an example of an existing hardware. We picked here the NRF52A33 development kit. Let's start with the board files.

These are the focus of this whole webinar, and what you see on the right-hand side is the input needed to implement the board files, which is essentially the hardware schematic for the hardware at hand. which is the development kit in this case here the hardware schematic is usually developed by hardware engineers then software developers take the schematic and use them as a reference point to create the board files so here i'm providing the link to the exact location in our sdk github repository where the nrf52a33 development kit board files are defined so if we click here you can see the board files again we will dive into each one of these files in this webinar but if we take a quick look we'll see the first line will specify the exact variant of the SOC used and then you'll see a description of the available component on the board like things like LEDs buttons connectors and so on back to the presentation we'll move next to the soc soc series and soc family layer this is as i mentioned before is provided for you in the sdk and it was written by our software team they basically take the so our software team basically took the product specification of the stock and they converted into necessary file in the sdk so here we have the layer for the um uh another 52 8 What we have here is a complete description of the SOC, which CPU it uses, available memory, available RAM and flash, and the available peripherals. While the SoC series, we have basically grouping of all the NRF52 SOCs in one place.

So if you click here. we're going to see all the available socks within the nrf52 on the other hand in the soc family we have other series not only the nr52 we have the nrf53 nrf91 and so on so basically the nrf52 was a subdirectory within the soc family so this is back to the page that i showed you before moving next to the cpu core and architecture layers as a developer for custom board you don't really need to worry about the cpu core and the architecture layers since it's already provided for you in the sdk again this will these two layers will contain something called architecture specific code so these are like low level things like early boot up sequence fault management and so on and for the case of the nrf52a33 it's going to have the arm cortex m4 core and of course that's that's the arm architecture um i know it's on drivers so in addition to the hardware support hierarchy for the target sock where the application will be running the drivers are also needed when it's needed it's needed when you have external components like Sensors, for example, connected to your SOC peripherals. So peripherals like I2C, SPI, and so on.

Drivers will reside actually outside of the board file. So they're not going to be inside the board directory. They have dedicated locations within NRF Connect SDK and Zephyr.

And here I'm kind of like providing you with the link to where they are defined in the GitHub repository. So the good news here, there is already a long list of already implemented drivers for things like sensors. Nevertheless, if you have a component on your custom board that has no driver yet, neither in Zephyr or in NrfConnect SDK, you would need to implement it. The drivers are usually specified using the compatible.

property in the device 3 file for the children nodes of the peripheral where the components are connected so here I'm showing you an example of the micro bit version 2 device 3 the micro bit version 2 uses the nlf52a33 SOC as the application SOC and connected to its I2C peripheral is an LSM 303 AGR sensor from ST so that's physically connected to the board this sensor has both accelerometer and magnetometer and the drivers are already available in the SDK so here in the compatible we're specifying two types of drivers if you find the first one implement it if you didn't find the find the first one try to find the other one but both these exist in the SDK and again here I'm providing you with three examples of boards where you have external where you have components come connected to the peripherals of the sock and these components are sensors and the examples are basically the micro bit version 2 thingy 53 and the thingy 91 let's now actually switch gears to board files and before we start talking about the board files you Let's cover some key points related to naming your custom board and also where to create the board directory. So let's start with naming. Basically you need to give your board a unique name. You could run west boards in the terminal.

That could be your nrfconnect terminal if you're using nrfconnect for visual studio code. To list all already taken names for boards. You basically can't name your custom board with a name that's already taken. When naming your custom board there are also some recommended conventions that are good to follow. It's recommended that your board name include the name of the SOC, the target SOC that you're using on your board.

Also you need to specify the target in case your board has multiple targets. We will dive into this later in this webinar when we discuss chips that have multi-core or or have support for trusted firmware M your board will basically have a human readable name and that's something completely up to you to decide on so you could decide on whatever you want to name your board and for instance let's suppose we have we want to make a new board called dev academy and this dev academy board will have the nrf52a33 soc as the application soc that's where we're going to run our nrfconnect sdk or zephyr application then it's highly recommended that we call our board dev academy space nrf52 833 in addition to this human readable name your board will also have a board id okay so the board id is usually the lower curse the the lower case version of your human readable name and also will substitute any space with underscore and this is what we can pass to west to build an application for for your board it will also be the entry in the add build configuration window in nrf connect for visual studio code where we select the build target and build an application. In addition to the board ID, your board will also have a K-config symbol associated with it.

And it's usually the uppercase version of your human readable name preceded with the word board underscore. Now, let's move to where we define our custom board. so there are three options to where to kind of like store the board files or create this board directory these options uh have kind of like varying implication the first option is in a day in a dedicated directory which is out of three we and we call it out of three by out of three i mean it's out of the nrfconnect sdk and zephyr and basically you will need to pass the custom board directory whatever you created let's say you are on a Windows machine somewhere on the route kind of like on the C Drive in a specific directory you need to pass that to the build system right so this method is recommended if you are developing a closed source product and you want to control access to the board files this is the method by the way that we will cover in the hands-on demo you could also create the board definitions the board files in a board folder in your application this is usually suitable for prototyping and debugging and then there is this upstream in zephyr approach and you usually select this path if you are developing a development kit, a module, a reference design, a prototyping platform, and you want to make your board definition public and available to all. Be aware that using this path may also apply if you're designing an open source product.

So let's say you are working on an open source smartwatch, you want to make it public to all developers and all the community, you can also choose this path. Remember that with this path, which is defining your board and pushing it to upstream Zephyr that you need to provide documentation for your board and Zephyr maintainers will need to review and approve your board files pull request when we choose the options of RF3 board you need to point the build system to the custom board root directory why because by default the build system in RF you connect sdk go to specific folders to look for board definition namely this is the installation of the sdk and it goes in zephyr boards and then of course we're mainly focusing on arm boards it will look for boards in this directory and also it will look in the nrf repo directory so this is the same installation path of the sdk here and the directory nrf boards are these are kind of like the default locations where the build system look for boards so for that if we have a board which is out of three it's not in these directories we need to tell the the build system where where where the board definition are so basically we need to update the board underscore root and we have three ways to do it so if you're using an RF connect for visual studio code you can just go to file preference settings extension and RF connect and there is the board route where you select where your board definition out of three board definitions are this is I'll demonstrate this in the demo or you can when you invoke West build from the terminal you can just pass this and specify the location and also possible that you use you specify the custom board location and the CMake that list These are all possible ways to kind of like point your build system to your RFT board definitions. Let's talk now about board files.

So the board files are generally classified into either they're mandatory, you must have them, and these are kconfig files and device tree files of your target board. And there are also optional and special use case files. We will... touch upon each one of these files in the following slides so the board files need to reside in a directory this directory and by the way this devacademy underscore nrf52a33 this is basically a placeholder for your own board name so you basically replace this with your own board name and this directory will need to reside in a folder that is basically named after your target soc architecture so this is going to be arm for the nrf91 nrf53 nrf52 and nrf51 and then this will need to sit in an upper directory called boards and when we're going to use the nrfconnect for visual studio code extension it will actually create this folder for us when we use the wizard to create a new board wizard but if you want to do it manually this folder structure you need to follow it And these are the mandatory files, basically, three kconfig files and one or more device tree files. Device tree files, basically, you can structure them in the hierarchy so you can have basically multiple files.

When it comes to the optional and special use case files, so up until here, these five files are mandatory. And then we have some other files. these are CMake, C file, YAML and documentation let's quickly just talk about them I'll dive into each one of them in depth this one you use basically your if your board has flash and debug support this is how you can configure it the CMake list.txt and optional some special use case c file this is if you have a hardware that requires special initialization and configuration so basically you want to run some specific function pre or post kernel due to moxes or some hardware configuration this is where you can do it in the board directory and i'll show you an example later the documentation absolutely optional if your board is out of tree absolutely necessary if you want to make your board definition public if you want to push it upstream in zephyr and make it accessible to all then you must provide these documentation and kind of like pictures of your board K-Config, this will allow you to create a K-Config options menu. So this is something that the users of your board can use things like GUI config or menu config or Nordic K-Config graphical interface to set options on your board. This is the file that you need to create to create these options.

Revisions, these files here. Sorry, this one is the name of your board.yaml. This is for the support for the... twister test framework in zephyr and nrf connect sdk revisions are quite interesting so let's say you made some changes to your hardware schematic you made basically new hardware revision you no longer need to kind of like make a new board definition a new board directory no you can just keep the old one but then here you specify in revision.cmake you have two three divisions and then you specify them and then these files will be applied for the selected revision as an overlay as an overlay for the device tree and as fragments for the kconfig and you also have the option to create your own bindings now let's talk about the mandatory kconfig files three files the first file is kconfig.board this file basically make a boolean kconfig symbol for your board So remember that's going to be usually your human readable name in uppercase and then spaces which is by underscore preceded by the word board underscore.

And then this is a Boolean K config symbol. And then here you provide kind of like a description for this symbol. And you also need to specify dependency to the SOC hardware support layer through the depends on keyword. All...

mandatory kconfig files will be created to you if you're using the create a new board wizard and nrf connect for visual studio code extension so what you see here is is kind of like a screenshot of the already kind of like filled out template by the by the wizard but if you create them from scratch if you're not using the extension you need to create these files these three files pre-k config files are mandatory the next file is kconfig.defconfig So this kind of like specific format you need to follow kconfig.devconfig This is board specific default values for the kconfig option So they only apply basically they need to be placed inside if and if that's a must and what you put if the board kconfig symbol is set you apply now these default values to these symbols these symbols are already defined either in nrfconnect SDK or in or in Zephyr so when the kconfig symbol is set for the board apply now these default so basically when this is set now the board kind of like symbol and the SDK will be set to the target kind of like the build target of your board the the second option that you see here this is basically the bluetooth controller which is enabled to support for uh soc native bluetooth low energy controller implementation and it's only enabled by the way if the prg.conf kind of like select config underscore bt so once you the application say hey i actually want to use bluetooth low energy please set the default to the controller to the kind of like native implementation you have two different implementation so this kind of like set the native implementation here and it's reason why it's added by the wizard here it's basically because we selected the nrf52a33 as the target SOC and that's widely used for Bluetooth low energy implementation the last file last mandatory kconfig file is the it's a very important file and it's It's the name of your board underscore defconfig and this is basically a kconfig fragment that is merged as is into the final build of any application built for the specified board. So any application you build no matter what it is even if you have nothing in the prg.conf these kconfig symbols will be applied. There are some rules here of what you put here and what you shouldn't put here.

what you must put in this file is basically support the the hardware support for the series the support for the SOC and then you enable the kconfig symbol here as well so these three things are mandatory for convenient you also could enable GPIO and serial so you can you have several examples in the SDK that you can run out of the box So things like GPIO and serial console, if the board has RTT support, you enable it. As a rule, the board, kind of like devconfig, it shouldn't enable a lot. Because if you enable a lot of things here, it means any application will enable all of these things, even if it needs it or not. So that's going to make the binaries created for the board a bit big, unnecessary.

As a rule of thumb, it's the application configuration responsibility to configure what is needed. What you have here is basically the bare kind of like minimal. It's very important to remember that.

And this, again, is also created by the wizard, by the create a new board wizard in NRF Connect for Visual Studio Code. So with that, we are done with the kind of like mandatory kconfig files. Kconfig files are kind of like focused on...

Software configurations while device tree files on the other hand they describe the schematic we describe hardware so they're basically the hardware description in device tree format that represent the schematic of your board and we call this file which is basically your board name target name DTS we call we call it the board level device tree file because it described the board the first thing it described it described the specific instance of the SOC used this is done by basically specifying the compatible property and also including the device tree files for the SOC use that's already provided for you in the SDK in the SOC kind of like hardware support layer the board this file the board level file will describe things also like components on your board buttons, sensors, LEDs, communication peripherals, and so on. Flash partitioning is usually also done in this file, and you could have it in a separate file, and that's why what I mean that you can structure it into multiple files. So sometimes things like flash partitioning, you can put it in the board level device tree file, or you can create another file, name it whatever you like, and then include it in this file. So through this include mechanism you can structure things the way the way you want Pin mapping lately it's done in a separate file and that's by convention so still you can use it here but conventionally you create a separate file for it and that file need to have a dash pin controller so the board name dash pin control dot dtsi that's kind of like will be dedicated to pin planning pin planning or pin mapping of your board peripherals again here the tooling that we have in nrfconnect for visual studio code it provides a lot of automation so it will we will see that in the demo it will really simplify populating these files by simply using the gui or or some enhanced editor features will really simplify writing these files now the next thing that i want to cover are the uh Optional and special use case files. I touched upon these things before, but let's cover them more here.

So board.cmake, we use this file to add flash and debug support if the board actually supports it. So you can specify using a glink, what's the frequency, and it's usually done using a West kind of like extension commands. There is some documentation here you can follow and there are a lot of examples and samples that shows you that the cmake list.txt that's basically will allow you to add source files to be executed pre or post kernel so this is in case where your hardware needs some special kind of like configuration or initialization it uses some some muxes and you you want to have some code executed that's specific to this board either pre or post kernel and here I'm providing you some example on how it's done there are some so this is the case in this file here and now this one so I'm providing you the CMake list the TXT example of the nrf52 840 dongle and then you see here that we're kind of like telling the build system to include this file and then if you go to the board that see We see That this function is actually called using the sysinit Prekernel so this is a way where you can insert Customization code that's related to your board back to the presentation the documentation and the pictures and so on these are mandatory only if you want to push your board definitions upstream in zephyr they're optional if you if you have out of three board kconfig as i mentioned before gives you the flexibility of creating a board kconfig menu the yaml is intended for the test runner the twister and with that i can move to revisions so revisions are interesting so in case you you will be creating a new hardware revisions for your board in other words when you decide to modify your schematic and make a new pcb you don't have to create a new board definition a new board directory no all you need to do is to add the modifications inside the bolt folder itself by adding three files so you'll add a dot com for the changes related to the software and dot overlay for the actual schematic changes so the the overlay is basically a device tree kind of like an overlay and there is the revision that cmake and that's basically control how the build system matches the board at revision that the user can pass using either west or using the gui the in nrf connect for visual studio code So when you have these three files added, this option will be activated. And also you can pass it in using the West CLI method.

And again, it's a very neat way to support hardware revisions. You just kind of like cover all these changes in these two files. And then this controls how many revisions you have.

And there is an example. There are many examples. So if you just search in the board examples that I will show you in the next slide. you just search for this file this file or is already is only included when you have rigid revisions you'll see a lot of examples that uses uh board revisions and here i'm providing the case of the nrf uh 92160dk where we have two revisions there is an old revision and new revision and then you can capture the changes in the schematic in the overlay and if there are any changes in the software they'll be captured in the dot com file Let's talk about available board definitions in NRF Connect SDK. There are many, so there are around 500, more than 560 board directories or board definitions in the SDK, and they're usually, as I mentioned before, for development kits, prototyping platforms like the Thingy 53 or Thingy 91, and reference designs.

For example, we have the NRF Desktop reference design, which is a complete reference design, both hardware and software, for a wireless keyboard, a wireless mouse, and a... a wireless gaming mouse and these kind of like board definition there they come from two different location one from zephyr and these are actually the majority and here's the link where you can find them specifically the arm boards and they include both nordic and non-nordic based boards the other source where we have a board definition is from the sdk nrf repository when you install the sdk you'll find them in this directory so whatever wherever you have installed the sdk folder and rf boards arm you'll find these boards there and it includes only nordic based boards in this location and they're very useful specifically when creating a custom board as either a sample to see how things are done for a similar board that uses the same SoC as the one you're planning to use on your board or in the case of multi-core SoCs or cores that support trusted firmware M which is the focus of the next slides you can use them actually as a starting point so instead of using the wizard that I'll cover in the demo when you have these kind of like complex SoCs it's actually better to start copying a sample and remain renaming things and modifying things as kind of like we cover the core purpose of each file let's talk now about the special considerations for the nrf91 and nrf53 series so the main focus here is to cover some core concepts related to defining custom boards for the nrf53 and nrf91 based devices in terms of custom board definitions a significant difference between the nrf52 series and the nrf53 and 91 series on the other hand is the type of architecture and CPU they used so the 52 implements the RMV 7M and has a Cortex M4 CPU this is what we see on this row it has only one user programmable core it has no support to trust zone hardware while on the other hand if NRF53 and NRF91 they implement the RMV 8M architecture and has the Cortex M33 the nrf53 has two user programmable cores so that's a multi-target you have two targets you can run an application on and it has support for trust zone hardware support the nrf91 same as the 53 same cpu and architecture but it's only one user programmable core and it still supports zone hardware so Let's talk about Trusted Firmware M because Trusted Firmware M will create a multi-target for your SOC or SIP and then Trusted Firmware M is basically a blueprint for constructing a secure processing environment SPE tailored for ARM and profile architectures. So Trusted Firmware M relies on the principle of security through separation. This is to safeguard sensitive credentials and code. so you have these sensitive information in the secure processing environment and then you provide to the non-secure processing environment which is your application limited and controlled apis to access them and both the nrf53 and rf91 series they they implement trusted firmware m and this means that you have the possibility of two targets one is the ns and then here you actually utilize Trusted Firmware M because you're utilizing security by separation or the other option which is not using the Trusted Firmware M by running your application on the complete kind of like as a one single image with full privilege we will see this in the following slide so option one which is when you use TFM and you enforce security by separation in this case trusted firmware m would run in the secure processing environment okay while the application run in the non-secure processing environment and then hence the application will be built for the underscore ns it might be sound uh unintuitive that to get the security you build for the ns but the idea here is that you separate You separate, you enforce security by separation, having trusted firmware as the secure element and then your application, you basically give it some limited APIs to access these credential information and the security service.

option two sorry option two is you simply do not use trusted firmware m so here you don't have security by separation you run the application as a single image with full access privilege and then you see the build target is the one without NS. So when you have Trusted Firmware M, whether it's for the 91 series or the NRF53 series, the application core, you need to define two device tree files and two potential configurations for these two separate processing environments. in addition to that there is a special case of the nrf53 series specifically the nrf5340 SOC here we have two fully programmable cores so you have the application core which can also run tfm so you have the same story as before either you don't use tfm so tfm is disabled and then you just have complete your application has complete access privilege or you use trusted firmware m so this the trusted firmer M would be running in the secure processing environment while the application will be running in the non-secure processing environment.

In addition to that, you have another core which is usually prefixed by underscore CPU net where you can flash applications on. So here you have multi-target for the TFM support and also multi-target on the core. And then when it comes to creating custom board definitions, since there are multiple files that describe the different domains, it's actually actually better to use the the board files for the RF5340DK or the thingy 53 or the same thing for the 91 as a starting point and then you copy it and rename the necessary K config to match your own custom board rather than building it using the wizard because here you'll be dealing with with with multiple files each one each of these files is for a certain domain or a processing environment or a core in the case of the 53 okay so let's start with the hands-on demo where we will create a custom board definition from scratch for a board that is based on the nrf52 series and we will use the nrf52a33 SOC as a an example but again the the instructions and the steps will be very similar to any other 52 series the board that we will create we will assume that it is very similar to the nrf-52 a33 development kit and the schematics these are the starting point to create your board files are actually available online on the product page for the dk so if you go to the nr52 a33 development kit and then downloads you'll find it here that's where i got the schematics from we'll just assume that the development the the new board the what we will call it dev academy nr 52 833 that's our new board it's not gonna have arduino shield that's kind of like the difference here just so we can have enough time to cover most of the key things here so first thing to do is to create a board a folder where we will store these board files and it's always a good idea to store these folders as close as possible to your root directory so i am on windows i'll create a new folder called my boards and that's going to be an empty folder and we need to have visual studio code open with an rf connect for visual studio code extension installed and set up and also the sdk and tool chain need to be set up and it's actually now possible to set up the sdk and tool chain from within the extension and it's already done here so since this is going to be an out of tree board you need to tell the build system and where to find these board definitions because it looks for certain places as we discussed before and one of the methods that we discussed is is done from within vs code there are different options available i'll show you the one which is done from within vs code but if you check the slides there are different ways preferences settings and then you select nrf connect and then there is this board board routes you need to add the new directory there and we're done with the kind of like pointing the build system to the new uh to like in addition to the existing places to also look to look here and now we were ready to create our uh board files and we will use this wizard this wizard as we discussed uh in the presentation it's a perfect to use with the single core devices so the for the 52 and and the 51 it's it's it can really make the process very simple for the 91 and 53 you're actually better by just copying a directory of a board that's similar to your hardware and then start renaming things but still you can take advantage from the nice editors you have in Visual Studio Code and the device 3 visual editor that you will use later so click here and then first thing it prompts you is to provide a human readable name for your board and we said we're gonna call it dev Academy and then nrf50 52833 again this is completely up to you what do you name your board and then we hit enter and then it will tell you that you need to provide a board id this is the board id that will be passed to west and it will be available in the gui when we add build configuration it simply took the human readable name and converted into lowercase and substituted spaces with underscore can just leave it as is here it's a very important step to select the exact variant of the sip or the sock you're using and as we saw in the schematic it's this one and then where you want to store the board files well in the directory we created before and then provide your company name in my case it's going to be nordic semi con conductor enter and then if we take a look now at um let's add a board directory which is here you can see it actually created this board structure that i mentioned before which is board name of the architecture and then the name of the board add and we see here that we have both a mandatory file and and some optional or special use cases files so we can start by the mandatory kconfig files we have the kconfig.board where the kconfig symbol is defined as a boolean and then there's description and there's a depends on for the soc kind of like support support which is the exact variant we used and we don't need to do anything to this template it's perfect and then the next file is the defconf the kconfig.defconf and again as we mentioned before this is going to set default value in the sdk and zephyr and it's always includes in an if statement with the kconfig symbol for your for your kconfig for your board we don't need to do anything here as well and then the the name of your board underscore defconfig this is where we said that this is going to be a kconfig fragment that's included in any application built for your board and it's already kind of like filled the mandatory parts okay with the MPU because there is MPU here and then stack protections already filled out in the template since we have an interface MCU in the in the schematic and this support RTT and it's also a good idea to have and this interface MCU provide us with a debug and USB to UART conversion it's better to include the the software configuration to enable the drivers needed here so so I'll add some K configs here you can see like I'm enabled an RTT enabled GPIO the serial drivers and the console and also the pin control the pin reset this is actually in the future is not needed it will be deprecated just so you know and so these are the three mandatory K config files it's it's almost it's complete okay you Let's take a look at the other files which is the board.cmake again this one is for supporting debugging and flashing and you can just leave the template provided by the wizard as is we don't need to modify anything here. and the we have also for the twister test it's again you don't need to do anything here the last file is the device 3 file we will dive heavily in this file so you can see the first thing it does it's include the the soc level um kind of like a description so if you click here you go to the kind of like the available memory and flash and if you go to the uh parent uh you can see it lists you all the available peripherals and their address space so it's kind of like there's an inheritance already done for you we still need to work on this file heavily to add and enable kind of like things like buttons and and leds because it's in the board so for us we can do that manually through the editor or we can use the nice visual editor device 3 visual editor but the Device tree visual editor requires you to have a build.

You need to build an application for it to be able to parse these things. So what I will do next now is I'm going to add an application. The application will compile, but if you actually try to run it, it's not going to run because we didn't finish configuring the device tree stuff.

So I'll just add a new application and then I'll select a very simple application, which is the hello world. It's just a simple main that prints the board name. the purpose here is for us to have the device 3 visual editor be able to parse all these files because it cannot work unless you have a built application so that's why I'm doing it at this step and then location where we store the application is a good location we'll call it hello world and it will prompt us if you want to add it to the workspace yes please add it to the workspace And then we have an unbuilt application.

If you click on here to create a new build configuration, and by the way you can also build it from the command line. If you just open here and you click here and you select the nrf connect you can also build it. And what we see here, we see like there's a new tab says custom boards and if you click on it you will see that the newly added board is actually here.

Build the configuration. I'll speed up this process so we can right jump into the device tree filling okay so the build is complete and we can see that when we see this output in the terminal and we're ready now to use the device3 visual editor but it's good to kind of like see the board directory so you can see it pick the directory where we defined our own custom board and you can also see that if you hover here it gives you the file it's gonna going to visualize and also from the terminal output so if you click on the device 3 visual editor again this is a visualization of your device 3 files and if we click here and it will show us the file that it's kind of like it's based on and of course this one is inheriting from the soc file and if we make them side by side so you can see what's going on and um very neat way to kind of like populate the device tree file is to use the visual editor you can also do do it directly so i'll start first by enabling the gpio it's not enabled as you can see we don't see the gpio and also do the LEDs and buttons first so to the SOC node and then if you go down look for the GPIO you can see GPIO see one side ticket here you can see the device tree syntax is being populated for us and same story here if I remove this line you can see that the the editor the graphical interface is updated accordingly now let's start with the LEDs so for the LEDs um if we take the schematic we can see that the leds are connected to pin 13 14 15 and 16 and the leds are connected to the other end to vdd so we need to actually make them active low so to add leds to the board you need to add them to the root directory and here you need to select leds so gpio leds and then let's just call them LEDs, let's add, and we can see they've been added here. And now let's add some children here.

So children node, so click here. What do you want to call this thing? So let's call it LED underscore zero. And then we said the first one is connected to pin 13. add so you can see it's added for us in here i can add a label to it a label um to the to this child node so let's call it led0 you can see it's added here and then I can also add if you click here this will actually parse the binding to figure out what available properties and one of the available property is the label property and here we can give it a human read green LED let's call it zero you know these are so you can give it just a human readable label to be easy kind of like this thing trouble but then you can see it's added here and again we said we want to make this another pull up we need to or pull down we need to make it active low so if you click here you can see this thing is updated now I think I've done this one and let's do the rest so you can do use the visual editor or you can just use the text editor so we have four need to have four give me this error because it says this already defined it will fix that now so this is one one and then this is 14 this is one this is two two this is 15 and this is two and then this is three we like indexing from zero 16 and this is 3 okay so we're done with the LEDs let's move next to the buttons the buttons same story we add them as a to the as children to the root node so here select GPIO keys GPIO keys and then here let's call them buttons and then add And then here what I want to do is to add children node as well.

So if I click on button Click here and then name of the new node. Let's call this one Button underscore zero and then for the GPIO for these buttons we can see these buttons are connected to an end to the ground so we need to actually pull up and then also make them active low and they're connected to pin 11 12, 24, 25. So 11, 12, 24, 25. So this is going to be 11 add. And you can see now the GUI has been populated.

And then what do you want to do here? We want to pull up okay that did the pull up and then this one we need to make it active low right and i can also add the label property so again this will parse the binding for this compatible and there is a label property and we can call this one push button switch to zero and then add and you can see it's done for me here so I can do the same trick of copy and paste so I can take this one oh let me just add a label forgot to add a label to the note so for that I just need to click here and then call it button zero without the underscore enter and now I'm ready to copy it so I can do the remaining so this one is one one and this one is actually uh pin the 12 we said yeah 12 we're doing one time 24 and then 25 and then this one is one two two two and then and then sorry this one is three and then three and we're done with the buttons Okay, we're done with buttons and LEDs. Let's move to peripherals.

So we have on the schematic an interface MCU that does among other things USB to UART conversion. So we have UART peripheral that you will need to enable. It's not enabled by default in the SoC kind of like device tree we need to enable it and then we need to kind of like pin map it to these peripherals sorry these pins so this is called pin mapping and it's usually the task of the pin control to do that for you so you have this flexibility to choose any digital I or for any digital kind of like pins for your peripherals and it's done through the pin control the it's usually done in a separate file which is usually the name of your board dash pin control so we need to create this file ourselves it's not created in the wizard in this version so we need to create it ourselves so in the board directory this is the board board directory opening this Visual Studio Code you can also open it directly from the explorer click here and then specify the name of your board dash pin control dot dtsi enter and then in here you need to reference the pin control node that's a must and then again in this directory you can create any optional or special use case file so we have actually Let's say we want to create a kconfig menu where we enable the DCDC regulator that is on the SOSC.

And since basically the schematic contains the needed hardware for it, which is the LF filter, so we can do that as well here. That's not related to the pin mapping. This is just to show you that we can easily create these files here.

And then we can see. we're enabling this by default and the user will have this in the menu in the kconfig menu, GUIConfig or the one that we provide and it's enabled by default and they can switch it off if they want to so just show you how you can add these files easily in the board directory now back to the pin kind of like pin control and the UART kind of like peripheral what we need to do now in the pin control is defined states usually have two states an operational state which is called default state and then the sleep mode state where the device when it's put to sleep what do you want to apply so for that we need to kind of like define these states and then assign the pins and ports for that kind of like peripheral and then they should be these states need to be defined as children to the pin control and then you can see here this is the name of the peripheral and then the tx is the pin that expects and then the name of the port and then the name of the pin and I'm grouping these two because they need a pull up and then everything in the sleep mode it's gonna have the low power enabled property and again these properties are defined in the binding of the pin control and of course I need to include this file now that's why I'm getting these errors I need to include this file in the board level device tree so if I go back to the board level device tree I need to add an include line at the beginning here that says please include the pin mapping so I'm back here into this file I can add it at this line okay now what I need to do next is in this file I need to go to the peripheral some of these peripherals are enabled in the SOC level, especially the ones related to the radio. And then here, what I need to do is look for the UART, enable the UART, and you can see it's been added at the end. And then also here, I can, I'm sorry, I just need to move this one here a bit.

I can actually click on it and I can add the properties. So for example, I can add the speed. Let's say current speed.

And then I can select the 105, 200 and then add. And then how do I do now the pin mapping of this peripheral to these defined states? It's very simple.

All you need to do is actually define three properties. The first one is called the pin. You can see it already helped us with these states. And zero is equal to... then let's actually have this here so the first one that I want to set is the default one which is this one so put it here make sure you have the add symbol and then you add here and then the other state is the so this is this the zero is the operational state the default state the one is sleep state and then we need to kind of like name these states so you need to use the pin control name and then they're basically the default and then comma the sleep okay and it's done for us if we go back now to the to the DTS we can see that the pins has been set so these are you art underscore TX Rx RTS CTS is set you can see the states where we apply the low power mode okay let's move to I2C so let's say the I2C peripheral we will pin map it to these two pins so need to go to the pin control and then add it as a inside as children to the pin control node so inside here add these pin assignment and you can see here we have only two pins the sda and scl gonna connect it to 26 and 27 there is no kind of like pull up or pull down driving and the low power mode we need to add it here and also it's good to mention that when you define the pin mapping you need to use this structure so you need to use this macro and then this is basically going to create an array so basically follow the helper macros that's provided to you in the SDK and back to the DTS file so we'll use I2C0 we need to look at this one is I2C0 enable it you can see it's added here and then same story we need to use pin controller 0 to set the default And then this is going to be I2C0, I2C0, and then I2C0 as well as here.

And it should be resolved. Now, if you go to the visual editor, you're going to see it set up here. The states are set up here.

One thing to point out here. is that the GUI can also help you add nodes easily. So let's say you now have connected a BME sensor.

You can just let's say it's the BME 280 and then let's say it's at register. 28 you add it can actually add it for you here and even the GUI will be updated with that sensor so that's not the case uh my hardware but just wanted to point out that it's also possible to do it from the GUI and the same story you can do for the SPI if you want to enable SPI just add the let's actually do it I know I'm a little bit over time but I think these are useful so and I'm gonna use the SPI one not the SPI zero simply because the SPI you can see you see it shares the same address base address as the accuracy it's the same serial box so you can't use them at the same time but I can use the other SPI this one sorry this one and then here I can do the same strategy of this one is going to be SPI1, SPI1. All right. Very simple to add peripherals. SPI1 and then SPI1.

And again, you can also use kind of like add components here by clicking. It will parse the available drivers that support SPI and you can use the same way and it will add it as children to the node of the peripheral that your component or sensor is connected to. Let's also do the PWM and I'm going to connect the PWM to the LED 0. So here again inside the parent pin control add the pin mapping. So here are the pin mapping. I'm going to connect it to pin 13, connect it to the LED 0. And here, go back to here.

We need to add a PWM and basically enable it. So let's go to the PWM 0. enable it and then here I can follow the same strategy as I done in the other peripherals define the pin control and then name it as simply PWM0 PWM0 and then PWM0 Since this is going to be PWM that's connected to LED, I need to add that to the root directory. So I need to basically click here. That's the root node.

And then here I'm going to select PWM LEDs. And I'm going to call this basically PWM LEDs without this thing. So add.

And then in here I can add, you can see it's added as a child node to the root directory. and then here I can either use the GUI or the editor to add the channel and the polarity I can actually click here and then name of the node I will call this node PWM underscore LED underscore zero which channel it's gonna detect it and then the kind of like interval let's use millisecond and I'm gonna set it to 20 and then let's just invert the polarity I think this will add it yeah yeah it's inverted and I can also add a node sorry a label to this node so I can click here and call it pwm led 0 And it's done. Now I'm basically done with the peripherals that I want to configure. So basically what I was playing with is the DTS, the pin control file, and then the visual editor actually helped me.

If I look at the SOC, it's now. configured you can see in here it's a multi-assignment so that's why we have this so we're using this both as a led zero and also as a drive to the PWM and I can test later on with various samples that these things actually work but before actually going there we need to add some more things we need to have the chosen kind of like property populated now what do we actually do in the chosen the chosen node property are used to kind of like configure system or system or subsystem wide values so these values are referenced by the different software modules you configure usually through the dt underscore chosen so inside let's say the uart console there is a dt chosen that looks for this definition if you don't have them defined in your board file you'll get some errors so i'm going to add actually three chosen values and this is for the console and for the shell and for the mcu manager it doesn't mean that we're going to include the shell and and kind of like the software it just if you enable them they will pick these default values and then what left to me is the aliases now the aliases is is something that we need to have so that we have comparability with existing samples so and so samples actually look for certain device tree nodes and it's good to add these aliases they need to be added by the way inside the node the root node and And some of the names is basically to kind of like have aliases to these nodes. So all the samples can have a consistent naming when referencing these nodes. Okay, so we're done with the board definition. We can actually close these files.

And now let's do testing. So I'll rebuild this application since we modified the device tree and the kconfig. And you can just press on here and it will do a pristine build. for you because it will notice the changes in the device tree and the output files and you can see here that it picks the right board directory speed up this part because I don't know over time and now the build is complete and just let me just show you the source code for the application it's simply print hello world and the build target so I have here connected the hardware and then I'm gonna actually open the terminal this is kind of like also a test the console and and serial driver flash and then if all goes well I should see hello world the name of the board printed on the terminal here and you can see here hello world and then the build target that I have Since we don't have any more time, I would also recommend that when you build your own custom board, you try different samples applications.

So for this case, I would recommend trying the PWM. The samples were the Bluetooth LE. radio is used so for example the um the peripheral lbs or the peripheral uarts and also if you want to try a zigbee and thread you need to so the radio knows for the Bluetooth low energy is already enabled by default but if you want to try ZigBee and Thread you need to enable the IEEE 802.154 node and then also set the chosen property and that's basically it for the demo part okay and at the end of the webinar i wanted to provide some resources for you so there is the nordic developer academy it's free online courses available to you at any time and from everywhere there is a dedicated course for the sdk and zephyr so if you're completely new i totally recommend this course And if you want to dive into protocols, wireless protocols like Bluetooth Low Energy or cellular, we have dedicated courses for these protocols.

And there is new courses coming very soon. And this webinar content actually is going to be a dedicated lesson that covers more in-depth kind of like scenarios coming as well on Dev Academy. And there's also some really useful guides from the Zephyr. project, the Zafar Arthas project. Till the end, we'll take some Q&A.