Embedded

View Original

458: Fiddling, DIY, and Cursing

Transcript from 458: Fiddling, DIY, and Cursing with Trond Snekvik, Christopher White, and Elecia White.

EW (00:00:06):

Hello and welcome to Embedded. I am Elecia White, alongside Christopher White. Our guest this week, BLE expert, VSCode expert, troll expert, possibly. We have Trond Snekvik on the show.

CW (00:00:24):

Hi Trond, thanks for joining us today.

TS (00:00:26):

Hey, thanks for having me.

EW (00:00:28):

Could you tell us about yourself, as if we met at lunch at, I do not know, electronica?

TS (00:00:36):

All right. Yep. My name is Trond Snekvik. I lead the Visual Studio Code team at Nordic Semiconductor. There are a bunch of TypeScripts in my current work, but I am actually an embedded developer. I have worked for Nordic for nine years now. I spent the first seven of them on the Bluetooth Mesh team, where we made the Bluetooth Mesh part of the nRF5 SDK and then later the nRF Connect SDK.

(00:01:01):

When I transitioned to working on the new SDK, I started making some small VSCode extensions, as a way to get familiar with the new languages and concepts. I ended up publishing them on the Visual Studio Marketplace.

(00:01:14):

At the same time, Nordic had a lot of internal developers who were a bit unhappy about the current tooling situation, so we started pushing for Nordic to publish an official VSCode extension. We eventually got our way, and after splitting my time between Bluetooth Mesh for a while and VSCode, I am now leading the VSCode team, and I have transitioned out of C programming altogether.

EW (00:01:45):

All right, so that covers the Bluetooth Mesh and the VSCode. Now let us talk about trolls. Are you ready for lightning round?

TS (00:01:54):

Yes.

CW (00:01:56):

What is the coolest place to visit in Trondheim?

TS (00:02:00):

Ooh, I think it is our cathedral, probably. We have the northernmost cathedral in the world, which we are very proud of. But if you go to Norway you should go and see the nature. Because the cities are- All cities have some unique thing that they are proud of, but the nature is really the thing to see in Norway.

EW (00:02:21):

You are named Trond, and you live in a city called Trondheim.

TS (00:02:25):

Yep.

EW (00:02:25):

Are you the only person there?

CW (00:02:27):

<laugh>

TS (00:02:29):

Yes, I am. It is me and two other Tronds.

EW (00:02:33):

<laugh> Is the city named after you?

TS (00:02:37):

I do not think I can claim that. "Trond" means a person from this region of Trøndelag, where Trondheim is the capital. So yeah, proper local guy.

CW (00:02:53):

Have you ever seen a troll?

TS (00:02:56):

I am afraid I am not allowed to talk about this.

CW (00:02:58):

<laugh> Okay.

EW (00:03:00):

Have you ever seen the aurora borealis?

TS (00:03:04):

Yes, we have that a few times every winter here in Trondheim, but if you go further north it is much more intense. I really recommend it.

EW (00:03:12):

Have you gone intentionally out to see it?

TS (00:03:17):

Yes, we do. It is great.

CW (00:03:19):

What is the best wireless protocol?

TS (00:03:23):

I have to say Bluetooth Mesh, do I not?

EW (00:03:25):

You do not have to. No, you really do not have to. It is just us. You can tell us the truth.

CW (00:03:30):

This will never air.

TS (00:03:30):

Oh, right. Okay, then. Then it is something else, yeah. No, I think depends a lot on what you do. I think Bluetooth Mesh is the best one for a certain use case.

EW (00:03:42):

If you could teach a college course, what would you want to teach?

TS (00:03:46):

I think in general, universities spend a bit too much time on theory and computer science, when what we really need is engineers. I think some practical hands-on development course, because they are always fun as well.

CW (00:04:01):

Going to go with the old standby, favorite fictional robot?

TS (00:04:06):

The right answer is R2-D2, is it not?

CW (00:04:09):

No, no.

EW (00:04:10):

No, you can say BB-8 as well.

TS (00:04:12):

Oh, I was actually going to say the mouse droids, then.

CW (00:04:15):

Oh, yeah. Okay.

TS (00:04:16):

Yeah, the RC cars with lunchboxes on them. They are nice.

EW (00:04:22):

Do you have a tip everyone should know?

TS (00:04:25):

Yeah, I think no one knows that you can select a piece of code in VSCode in your editor, and then there is a command that will stage it in your source control. Every time I do that, people are surprised, but it is such a great little feature and no one knows about it. So that is one. Select some text and then you can bind the keyboard shortcut to just stage it in Git, and it is off.

CW (00:04:49):

Oh, so it will add the file? Or will it make a commit for that?

TS (00:04:54):

Just the code you selected. So it will do essentially a git add --patch, I suppose, for the selected text.

CW (00:05:03):

Ohh. Okay. I am going to have to try that.

EW (00:05:05):

Okay, so you just add the part you selected and nothing else. Okay. I can see that. That would be kind of cool.

TS (00:05:12):

Yeah.

EW (00:05:12):

That would actually be really cool.

CW (00:05:15):

Especially for comments.

EW (00:05:16):

I was thinking more for files, that if people have different hardware, you do not have to check in the whole file.

TS (00:05:23):

It is true. I think for me, I get easily distracted. As soon as I see something that is not really the stuff I am working on, but I should just fix this really quickly, I will go and do that. And then my commit looks messy, if it is like ten things I thought, "I should fix this," in addition. So very handy, if you struggle with focus like I do.

EW (00:05:49):

You said that BLE Mesh was probably your favorite protocol. What cases does it work best under, and what cases is it not good for?

TS (00:06:02):

By far the best case, which is really what this was designed for, is controlling lights and reading sensor data from a network. So Bluetooth Mesh does not have a structured network in the same sense that Zigbee does, for instance. So all the devices can listen to anything around them, and repeat it.

(00:06:24):

So messages travel really fast. And it is very reliable, in that fashion, because if some node goes down, it is not going to be the center of a cluster or anything. Your message can just go through some other place, and it is going to go through your network in the quickest path possible. So that is easy to set up, and it does not break just because you swapped two light bulbs around, or anything like that.

(00:06:47):

So for light and light control, I think that it is excellent. I do not think any of the other protocols can beat for performance or usability.

CW (00:06:57):

I am pretty ignorant on BLE Mesh. Is it "BLE Mesh" or "Bluetooth Mesh"?

TS (00:07:04):

I think officially it is "Bluetooth Mesh."

CW (00:07:04):

Bluetooth Mesh.

TS (00:07:06):

Yeah. But it is built on top of BLE.

CW (00:07:09):

How long has it been around? And is it something-

EW (00:07:14):

How long has it been functional?

CW (00:07:15):

Well, I have several dumb questions that I am stacking. How long has it been around? And is it something that rides on top of existing Bluetooth? And it is just like we need this firmware, or is it a completely new radio set up and all of that?

EW (00:07:28):

I think it is just a new stack, but I will let him answer.

CW (00:07:30):

I am asking.

TS (00:07:33):

Yeah, I think development was started in 2014 or 2015, but it did not go public until, I want to say 2018, but do not quote me on that. So it has been around since then.

(00:07:48):

It was designed to work with existing hardware. So if you had a BLE device in the field, it could do mesh just with its existing capabilities. So it introduces nothing new below the GAP layer, as they call it. It is all advertisements and scanning, and that is all it is ever doing. Everything fits inside an advertisement packet. Every device is both an advertiser and a scanner at the same time.

EW (00:08:18):

With Zigbee, if you do not have it set up, you end up with cascades of messages going in circles. How do you prevent that?

TS (00:08:31):

It has two mechanisms for that. First is "time to live"-

EW (00:08:34):

Yeah. That one is important.

TS (00:08:34):

Which I think every protocol like this probably has. It also has a network cache. So by best effort, the devices will keep a cache of the latest n number of messages that they have seen. If they see n message again, they will not relay that one.

(00:08:52):

So all in all, the loops are super rare. If you get any loops like that, at the worst it will die when the TTL is used up, but nothing else. It usually means that you should have spent those extra 30 bytes on your network cache.

EW (00:09:13):

BLE was always intended to be a low power protocol.

TS (00:09:18):

Yeah.

EW (00:09:18):

But Mesh is an "always on" thing.

TS (00:09:22):

It is.

CW (00:09:23):

It is for lights. Plenty of powerful lights.

TS (00:09:27):

Yeah. Compared to classic Bluetooth, it is still low power. But it is definitely the- I do not think you could find a way to make BLE use more power, than you do with Bluetooth Mesh. Scanning and advertising, even though it is RX and TX, it uses about the same amount of current in the radio peripheral anyway. So it is basically on all the time, and you are drawing, with modern parts, somewhere between two and five milliamps, just constantly. It fits well with lighting, like that is nothing if you put it in a light bulb.

(00:10:06):

But there are modes to put low power nodes in, as well, where if you have a light switch that is on battery, or even on some sort of energy harvesting device, it can send messages without scanning continuously. It can elect something they have officially named a "friend node" in the network, which is very cute. So your friend will take care of the incoming messages for you, store them in the queue. And then when you feel you have the energy, you can ask your friend to give you all the messages it has received for you, for a while. So it is like having your neighbor keeping your mail for you.

EW (00:10:46):

For a firmware update, do you go over the mesh?

TS (00:10:49):

Yes, and this is something that is on its way into the specification now. It is public that it is on its way in. I think right now it is still not ratified, like an official spec is done, stamped, and gone through the organization. But yeah, they have added an official DFU Service type of layer on top of it, where you can organize it with having devices spread the DFU around in your mesh.

(00:11:22):

So you can set up a device to quickly receive the update from your phone or your connected device somehow. And then it can spend all night making sure all the other devices have them. Then you can trigger a simultaneous upgrade on your entire network.

CW (00:11:43):

Does this mesh protocol run anything like spanning tree, or any routing protocol, to establish the graph of the mesh, and find loop-free routes? Or is it just a free-for-all, and we send things everywhere?

EW (00:11:56):

Cannot be a free for all.

CW (00:11:57):

Well, you know.

EW (00:11:58):

That is true.

CW (00:11:58):

That would be my first naive implementation, was broadcast free-for-all.

EW (00:12:02):

Stars to stars.

TS (00:12:04):

Yeah, it is pretty naive. There is a routing-like mechanism that is also coming in. Actually I backed out of the mesh work, before I got to see how that actually works. But as far as I know, it is pretty similar to the routing in 15.4 devices. It will figure out, have a small list of routes, where they know whether they are about to send something up the tree or down the tree.

CW (00:12:35):

Okay.

EW (00:12:38):

One of our listeners, Thomas, says, "Hi," and asks, "How many Mesh stacks have you written now?"

TS (00:12:45):

Oh, I know who this is. Yeah. Thomas and I worked on the Mesh team with the nRF5 SDK, I think. The answer is I think four. I wrote- I actually did- The topic of my master's thesis before I joined Nordic full-time was Bluetooth Mesh as well. So I made two proprietary network protocols with Bluetooth as part of that. One of them is very naive, but it kind of works. We published the source code for it, and it is actually gone into real products. But I think now that Bluetooth Mesh has [Bluetooth] mesh proper, it is more of a curiosity and a nice little demo.

EW (00:13:34):

There are many naive ways to create mesh networks, mainly because it is a really hard problem. Are there two or three things that, as you learned them, you really wish you would known at the beginning?

TS (00:13:52):

All the time, really. Especially with the ones that I did myself for my thesis. The first one was naive. The second one was overly complex, and it just did all kinds of clustering and all kinds of stuff that kind of works, until you poke it.

(00:14:14):

So going back to the more naive of just everyone sees everything and can forward if they choose to, and seeing that actually working, and it does not matter if it is not super power efficient or anything. That was almost a disappointment for me, because I spent so much time trying to solve problems that did not actually need solving.

CW (00:14:38):

One more dumb question for me. Is Bluetooth Mesh Thread? Or is that something else?

TS (00:14:45):

That is something else, yeah. Thread is [802.]15.4, so it is like Zigbee but not quite Zigbee. Bluetooth Mesh is an entire different thing on its own, and it does not operate with the same IP address system that those protocols do.

CW (00:15:05):

Okay. I have devices that have Bluetooth, but I guess they also have Thread radios or something. Okay. How many of these competing IoT mesh radio protocols are there now?

TS (00:15:19):

Yeah, good question. There are way too many. Companies like Nordic need to try and do all of them, until we figure out who is coming out on top. So we are not that competitive internally, but there is the Zigbee team, there is the Thread team, and there is the Bluetooth Mesh team.

(00:15:37):

We all wanted our stuff to win, and for a while there, five years ago, it looked like we were in a race and by the end of 2019 there was going to be one protocol to rule them all. Turns out the situation is more like that xkcd, with there is no one protocol to rule them all, it is just now there are 15.

EW (00:16:04):

Yeah. Bluetooth Mesh and Zigbee can run on the same radio. So it is the same hardware, right?

TS (00:16:11):

It is in Nordic devices, but it is not automatically the same way, because the frequency modulation scheme is different between the two. So we have two versions of the nRF52 out, one is the 52832, the other is the 840 which came a bit later. It is only the 840 that can do both of these. The 832 can only do the BLE frequency modulation.

EW (00:16:41):

I have a whole bunch of questions about Bluetooth, but I think we invited you on the show to talk about VSCode.

CW (00:16:45):

We have got plenty of time.

EW (00:16:47):

I know, but I want to get back to the VSCode, otherwise I am going to get lost in Bluetooth because I really do have a ton more questions.

CW (00:16:55):

We can come back to that.

EW (00:16:56):

Okay. So VSCode. In your introduction you said you made some tools for yourself, and you put them on the...

CW (00:17:07):

Extension store.

EW (00:17:08):

Extension store Microsoft thingamabob. And then Nordic said, "Hey, that thing you are doing off work time, we want it. So come head this team." Is that kind of how it happened?

TS (00:17:22):

Kind of, yeah. I did this in the evenings. I wanted to learn TypeScript, and I have always been fiddling with the IDE configuration. I used to work in Vim and I learned Vimscript and fought the uphill battle that is trying to add extensions in Vim. But yeah, so I ended up doing them partially because it was a fun project that got quick results. Especially compared to doing C development languages like TypeScript, you can see results on such a different timeframe. That was very inspiring.

(00:18:09):

So yeah, I ended up doing this. Then at the same time we were several- We actually found in the office that none of the developers internally were actually using the tooling we were telling our customers to use.

EW (00:18:26):

<gasp> Shock!

TS (00:18:27):

That is not unexpected. I think everyone- Well I am going to fire some shots here, but everyone who has tried to use some sort of Eclipse clone thing handed out by their software vendor, will eventually say, "These guys have never actually felt this pain, have they?"

EW (00:18:53):

I want to cough and say a bunch of names, but I would have too many names to say, and I cannot cough for that long continuously.

CW (00:18:59):

<laugh>

TS (00:19:02):

Yeah. Nordic was one of them. I meant, we were not any better. We did not use the tools ourselves. A big part of that was because the tools were centered around application development, and we did SDK development. Normally you would not- You would build it with an application, but the application is not the point. So we were not in the target demographic for the tooling itself.

(00:19:32):

We saw that everyone was actually using VSCode. We could walk around the office and just on the screens there would be perhaps 10% would be in some sort of terminal, Vim or Emacs thing. Then another 10% would actually be using the tooling we told our customers to use. And then the rest would be in VSCode or Sublime.

(00:19:53):

So we saw that and said, "This is nonsense. We are all spending a bunch of time setting up, fiddling, with the VSCode configuration, and probably our customers are as well." So we went to product management, and they said "Yeah, in the feedback we are getting from customers, they are basically saying the same thing you guys are seeing here, where a lot of people will only call the command line API for the vendor tooling. That is not just with the stuff we provided, but any tooling. Then they edit the stuff in VSCode and they will go into the editor, whatever it it is, and hit compile, look at the error, and then go back and edit it in VSCode."

EW (00:20:43):

Mm-hmm. I do this. Yes.

CW (00:20:44):

Well you can have a little shell in VSCodes, you are still in VSCode. You just have your command line in a little panel, right? So that is an IDE, is it not? It is integrated! <laugh>

EW (00:20:55):

It is embarrassing to swap between STM32CubeIDE and VSCode. Always. Is it not? They have separate key commands. It is just irritating. But yes. Okay. So everybody else is irritated, and you have solved the problem.

CW (00:21:11):

<laugh>

TS (00:21:12):

Well. <laugh> Well I would not go that far. The extensions I have added for myself were DeviceTree and Kconfig. They are the configuration languages used in Zephyr for configuring software, which is the Kconfig one. And then configuring the hardware or software's view of the hardware itself, which is DeviceTree.

(00:21:36):

I had not spent- I have never been interested in rebuilding the Linux kernel or any of this. So both of these were unfamiliar to me. I had not touched them before, so I thought I would try making extensions to do syntax highlighting for them first. And then I found that, even with the syntax highlighting, I struggled to write this, so I will add some verification there as well, and get some error squiggles, if I fail to use the exact syntax DeviceTree needs to write out a number. So it just evolved from there, but it was always just those two languages.

(00:22:21):

The actual bigger problem is managing your builds, and making sure that IntelliSense works and knows about your application, and setting up debugging. So there was still a ton of stuff missing when I had done my thing. But luckily we had managed to get the project running internally, to just make a prototype of what an extension like that would look like, where you manage your builds and you set up debugging automatically. There is less fiddling, less DIY and cursing. So that is really the centerpiece.

(00:22:58):

The extensions I made, they are now absorbed into the group of extensions that we offer, but they are not center stage. They are just supporting extensions. We spend most of our time on what started out as just a small prototype project, and turned into the orchestration of the configuration, which is really the centerpiece of the extensions today.

EW (00:23:31):

But you were a Vim guy. And there were wars. I remember the great battle of, I do not know, I need to make something up here about Emacs and VIM, and I am not going to, so just fix this one later.

CW (00:23:42):

Well Emacs won.

EW (00:23:46):

So how did VSCode work? I mean it comes from Microsoft. How did Vim people go to VSCode?

CW (00:23:55):

Did they?

TS (00:23:57):

Well I did. <laugh>

CW (00:23:58):

Okay. <laugh>

TS (00:24:01):

I found that the stuff I wanted Vim to be- I wanted Vim to be an IDE. That is what I actually needed. The shortcuts are cool. The ergonomics of Vim is just far superior to VSCode. Even when you do VSCode properly with using multiple cursors, instead of search and replace, and all these things just moving around in the code, I still prefer Vim. I actually write my commit messages in a Vim instance in the terminal in VSCode.

CW (00:24:34):

I thought everybody did that.

TS (00:24:37):

It is good to hear. Yeah.

CW (00:24:40):

For some reason I only use Vim for any commit messages <laugh>. That is the only use I have for it. Elecia, her eyes were boggling at some of the things you were saying there, multiple cursors and- I think there is a class of developer like myself, and maybe Elecia, that we get a window and some arrow keys and we are pretty much okay, and we do not think much beyond that. Maybe we learn a few keyboard shortcuts.

EW (00:25:07):

Well, because I do not like to use the mouse. But, yeah.

CW (00:25:09):

But then there are these super beings who learn all the esoteric features of editing, and they can integrate their mind into the IDE. I did not even know what "multiple cursors" means, and I have been doing this for 40 years. No, not 40. How long?

EW (00:25:26):

You can actually start saying 40, as long as you do not count the unpaid time, for that first ten years of unpaid time.

CW (00:25:34):

Anyway. But to derail slightly, I am going to boil that to a question. Are there things that we should know about in editors, that we really are not using?

TS (00:25:43):

It is hard not to say multiple cursors right now, is it not?

CW (00:25:46):

Okay. That is fine. I do not know what that is.

EW (00:25:47):

Tell us about multiple cursors.

TS (00:25:49):

Okay, sure. Yeah, so if you select the word, you can press Ctrl+D I think in VSCode, and if you keep pressing Ctrl+D, it is going to find the next word that is the same thing, and that will add it as a cursor. And then if you have four instances of a function name in the same file, you can rename the function this way.

CW (00:26:11):

Ohhh. Okay. I think I have accidentally used this. Yes.

TS (00:26:14):

Yeah.

EW (00:26:15):

I have definitely used it. I did not- Okay, yes. But I just thought of it as some fancy search and replace sort of thing.

TS (00:26:21):

It can be that. And then you can start, like if you have a massive array of structs or something that you need to add a prefix to all of them, you can start doing stuff like that. So it is really a fancy visual search and replace everything.

CW (00:26:40):

Okay. But you can also insert it at multiple places. So it is not just search and replace. Once you search, you can insert. Yeah.

TS (00:26:48):

Yeah, true. And you can add, I think if you hold down the Alt key and click around, you will add a cursor at every place you click as well.

CW (00:26:57):

See, that is cool!

EW (00:26:58):

<laugh> Yes.

TS (00:26:59):

Yeah. Now you can add ten cursors, and write code ten times faster.

CW (00:27:05):

That is having 10X developers. This is it! I have done it! All right, back to the extensions. I am sorry.

TS (00:27:15):

All right, I think I have forgotten where we were.

CW (00:27:16):

Yeah, me too.

EW (00:27:16):

Well, actually let me start with the extensions. I know that a lot of people make a color theme, as the very first VSCode extension. That seems to be the "Hello, World!" of just getting something into the Microsoft extension world. How hard is that?

TS (00:27:39):

It is not terribly hard, but you need to do it. Yeah, actually the color themes are fairly easy. They are a massive JSON file, and then you just look in their documentation and it will say this, "A function name in C, is defined by this ID." And then you just put in that ID in the JSON file and give it a CSS style color thing, and you are done. Now all your function names are pink or blue or whatever you want.

(00:28:14):

Those are static and fairly simple, but they are completely separate from the other mechanisms that you would add in extensions. So you have those, and then you have the syntax highlighting. So that is where I started, really, with trying to make syntax highlighting for Kconfig.

EW (00:28:33):

And for a GCC map file.

TS (00:28:36):

Yeah, true. Yeah, so that as well. That is a series of regex just over and over again with nested scopes and everything. That one is a bit- It is easy to do something at first, and then you have to fix all the corner cases that you missed. People will keep making issues on your GitHub repo for years and years about these corner cases that you miss. I am still fixing those.

(00:29:05):

The map files are very- They are not bad. So the ones I made for map files, I do not think I have updated that in two years now, because map files are proper, good and proper. They look the same every time, and they have some sections that basically look the same, as long as you made them with GCC.

EW (00:29:26):

And they always look horrible.

TS (00:29:28):

Yeah, they do.

EW (00:29:30):

I mean, even with highlighting. What I really want is something more graphical, but I need to do that myself.

TS (00:29:37):

Ideally it would output in Yamo or some format like that, so that you could process it through something, and present it and filter it the right way. But it does not seem- It is not going to happen, I think it is pretty safe to say.

EW (00:29:54):

Because what these highlighters are, are text to text. You are highlighting text, you are not making pictures out of things.

TS (00:30:02):

Yeah, true. So it is all about identifying scopes and everything, but obviously with languages like C, or even worse C++, it is all contextual. Like the bracket left in C++ can both be the start of a template definition, and the start of a shift left operation.

EW (00:30:27):

And a less than.

TS (00:30:29):

Yeah, that is true. Yeah, that is the simpler one. Yeah, so it is all done with regex as well and then it is nested stuff, so those can get pretty complex eventually. But getting some color in there, and having some basics in text highlighting, is not too hard. You do not have to do any TypeScript, or any of the other massive realms of development, is what it feels like from the outside.

EW (00:30:55):

And you have an RST highlighter, which is reStructured Text or something like that? I found it recently as something that was competing with Markdown and I frowned at it, because Markdown is awesome. Why have something else?

CW (00:31:10):

<laugh>

TS (00:31:12):

Yeah, I know we are right. Making that one as well- Since I made the syntax highlighting thing for it, I am close enough that I am allowed to say that that is not the great language.

EW (00:31:27):

<laugh> Well good.

TS (00:31:28):

When we have Markdown, I get that you would choose to use this. It has some nice macro syntaxes and some nice ways of structuring tables, but why would you not use Markdown?

EW (00:31:43):

So those are the easy ones. Those are the ones that if somebody was motivated, they could make their own theme, and put up a couple of highlighters pretty easily. Because those are files you can find online. and copy and edit and do what you want. And then as soon as things get complicated, you can just throw it to the sharks, and run away.

CW (00:32:02):

And it is descriptive. It is not code.

EW (00:32:06):

Right. And at any time what you are looking at, is the output of what your thing is doing. You are not compiling and changing things. And you are not telling people to install other things.

TS (00:32:17):

True. Yeah.

EW (00:32:18):

Okay. The DeviceTree, this is something Zephyr specific, right?

TS (00:32:24):

Well, it actually came from Linux. So they found I think, like I said, I have not done a lot of Linux stuff, but my impression is before DeviceTree, you would write all these board support packages for Linux. It would be basically a bunch of the same drivers, and it was a big mess.

(00:32:44):

Then they found, "What if we make a description language for hardware?" And then if your hardware has an SPI bus at this address, you will describe it in DeviceTree, instead of compiling a library over again, with a different address from the one you stole it from.

(00:33:05):

So it is description of hardware from the software perspective, and in Linux it compiles into this little binary that goes into the runtime. When the SPI driver initializes, it will figure out that the hardware address it needs to talk to is at this address, and then a bunch of other details about it. And it will do that at runtime. So you can use the same driver compiled once, but use different configurations for different hardware underneath, to a certain degree here.

(00:33:42):

In Zephyr, it is almost the same, but to save space it is static. So it will generate all these static variables for you. Or actually they are pre-processor defines, and then you will use a macro system to reference the nodes through this.

(00:34:01):

So the drivers are structured this way, where you can define if you have two nodes on an SPI bus, and they are both environment sensors for instance, you can add them to your DeviceTree code. Zephyr will have a driver for it, most of the time. It will just instantiate two instances of the driver with each of the- In the SPI bus case, it will take the enable pin and map it to the right one automatically, based on this static configuration.

EW (00:34:38):

When working with microprocessors, not Linux, is this DeviceTree more about the processor and where it puts the SPI bus? Or more about the board and what is on the board, like a humidity sensor?

TS (00:34:55):

I think it is in the middle. It is the board as seen from the processor. So it will not know about what size capacitor you have put to reduce noise on the peripheral that you have there. But it will know exactly what wires are connected to the peripheral, because that goes straight into the processor.

(00:35:19):

It is like you are standing on the board with a flashlight, and you can shine light on all the peripherals that you can see from the processor, but whatever is behind them is hidden from you, and you do not really need to know it most of the time.

EW (00:35:39):

Okay. Maybe I am going to ask that again. Some pins have alternate functions, that they can be used as GPIO or SPI pins or clocks or whatever. Does the DeviceTree know how to set up those pins so I can just say, "Connect me to this SPI driver to this humidity sensor"? Or do I have to do all of the pin configuration, and then...

CW (00:36:08):

And then DeviceTree.

EW (00:36:08):

And then the DeviceTree does the higher level stuff?

TS (00:36:13):

No, you would actually define the pin configuration stuff in DeviceTree statically. There is a concept that arrived last year, which is "pin control." Oh, there were variations of pin control in Zephyr for a long time, and they vendor specific. So they tried to standardize this into pin control, where you can have multiple states for each pin.

(00:36:37):

So say that you have an SPI bus, but sometimes it is an I2C bus, or something on the same pin, and you control it with some chip enable pin, then you can define that in pin control as well, and set up these states too if you want.

(00:36:56):

So if your pins are asleep most of the time, you can set up a sleep state where your pins are disconnected from any sensing input. And then you can at runtime switch between the states that are defined statically, but swappable while your code is running.

EW (00:37:16):

And this is for Zephyr, which is an RTOS, which I guess we probably should have noted long ago. But if you are still here, and you made it through that first discussion of BLE Mesh, we are going to assume that Zephyr was on your list anyway. Anyway. Is this only for Zephyr? Has Nordic gone full Zephyr? You did not always need Zephyr to run the Nordic chips.

TS (00:37:41):

That is true. Nordic actually is full Zephyr now.

EW (00:37:44):

Oh. Okay. Cool.

TS (00:37:47):

Yeah, well you can still download the nRF5 SDK. I think the distinction we are making is, if you are making a new design, do not use the nRF5 SDK. But if you have already spent a bunch of time, and you have a design and it is already running on the nRF5 SDK-

EW (00:38:06):

But I finally learned the nRF5 SDK. Yeah, no. Sorry. Go ahead.

CW (00:38:11):

<laugh>

TS (00:38:12):

Yeah, so all the new chips we will be putting out will be on the nRF Connect SDK. It is based on Zephyr. It is not quite- It is technically a fork of Zephyr, with a bunch of stuff on top, but we keep the fork pretty closely integrated.

(00:38:33):

And then with Zephyr's Quest management system, you can combine multiple Git repositories into one system, that is not defined by Git submodules. We extend it through that, really. So from the outside, Zephyr looks like it is baked into, it is like the foundation of, the nRF Connect SDK. But really the nRF Connect SDK is a fairly- Codewise, it is organized as a separate repository, that depends on Zephyr.

EW (00:39:10):

Was that a big shift? It sounds like a huge shift, because- Yes. But was it? Or had you already been creeping towards Zephyr for years?

TS (00:39:23):

No, it was a huge shift. It was engineer driven, the whole process. So we were- I think in 2018 when we started, when we made the nRF Connect SDK repo, and set everything up. We already had nRF51 and 52 in its two variants, and we were going to add more hardware at the time. We now have the nRF53 and the nRF91 as well.

(00:39:55):

We spent a bunch of effort trying to get hardware support for all of these in the nRF5 SDK. So we looked around and saw we need some common code base here, some way to abstract us. Otherwise we will have to triple our software department every time we add a new chip.

(00:40:24):

For us, Zephyr seems like the answer. It is run by the Linux Foundation. It was already well underway, it was not quite that, well not zero, when we started contributing to it. But yeah, we genuinely think this is- Going open source like this, and having a collaborative project like that, will benefit not just Nordic but our customers as well in the long run.

CW (00:40:51):

We have done a couple of shows on Zephyr, so we will put those in the links if people want to...

EW (00:40:56):

Yeah, they were older shows. We should do a new show on Zephyr sometime soon, because it has changed a lot.

CW (00:41:03):

I feel like they were within the last year, but my sense of time has probably ceased to be accurate. I think that is really cool. I think getting away from what a lot of vendors have done historically, with very proprietary stacks all the way from the IDE down to the HAL. It can only be good for everybody.

TS (00:41:32):

I think so. I am seeing this from the software tools perspective of the organization, but we are trying to be more open. I think especially with the IDE situation, vendors have generally used IDEs as a way of getting locked in, thinking that if we just-

EW (00:41:56):

Yes. Grrr.

TS (00:41:58):

Yeah, if you spend enough time in an Eclipse clone, you will be unable to write code in another environment.

CW (00:42:07):

<laugh> Well, I might be unable to write code anywhere, is what happens to me. <laugh>

TS (00:42:12):

Yeah. That is success. Yeah. So the overall idea as seen from my perspective in the Visual Studio Code team here, is we are trying to be open, and we are trying to make Zephyr the best RTOS and environment for completing your products out there. At the same time, we are trying to make Nordic the best vendor for Zephyr.

(00:42:42):

Both of those approaches means that we are going to- We are spending all our effort doing stuff that is aligned with what our customers actually want. We are pulling in the same direction. We are not trying to force you into some lock-in, by making it hard for you to leave. We are trying to make you want to stay with us, because we are actively trying to help you.

EW (00:43:11):

Again, I want to cough a long list of names for people I am looking at. But, no. No, we will be good.

(00:43:19):

One of the really hard problems with tooling teams, is that you have multiple different kinds of users. You have your internal users, which we have mentioned tend to not always use the external user customer interfaces, because they want different things. But then you have external users who want access to everything, whether they need it or not, "You should not be touching that!"

(00:43:45):

And then you have the other users that are just like, "I am developing a product and it is hard enough! I do not want to know anything that I do not need to know, that involves this processor. I just want to work on my algorithm. Leave me alone with the microprocessor."

CW (00:44:03):

"I want to install this IDE, and it already knows my board exists. I want to click on the board and you have it all set up."

EW (00:44:10):

"And I miss IAR and I would be willing to pay for it, because it was nice to just click on something and be done. And not have to dork around with launch files and tasks.json."

CW (00:44:23):

Or being able to cut and paste debug information.

TS (00:44:25):

<laugh>

CW (00:44:25):

Or use more than one CPU core.

EW (00:44:29):

Not having to look at the GDB command, and wonder how to get rid of all of that random text that just keeps flowing by, because you are already-

TS (00:44:39):

Are we leading to a question here?

EW (00:44:40):

Oh, yes, sorry. You end up with a wide range of people who use your tools, and that range is hard to satisfy. How do you prioritize the different kinds of users? Do you identify them differently? Do you curse them differently? I do not know.

TS (00:45:03):

Yeah, we do identify them differently, and I think you have covered the identities that we have used here. So definitely the internal developers, it is the same as the problem that I said earlier, where the tooling is made for developing applications, and the internal developers are making an SDK. We still have that problem, but we are able to support them a lot better now. First of all, because we understand the problem.

(00:45:34):

My entire role in this project is defined by, I was frustrated when I tried to develop SDKs with the tooling that we had. Now I am here. So we tried to mix that background that we have, where when I was trying to add this API it really annoyed me that I could not do this and that. So I am going to add a feature that helps with this nut.

(00:46:03):

But then obviously- At Nordic, I think we are 1600 employees now. So our user base is like 99% is going to be our customers. So for that, we try to prioritize the customers. None of the stuff we do actually matters, if our customers are not shipping code faster or getting their product out the door. That is the entire point of the software department.

(00:46:41):

We try to prioritize them, but it is a lot harder when we are not customers ourselves. So we try to get around that by having workshops. We recently hired a new developer on the VSCode team. He just finished his application project, which he did where he was basically assuming the role of a customer and making a little product.

(00:47:09):

In this case, he made just a sensor device that would over Bluetooth tell a device with a servo to wave when the accelerometer waved. So super simple project. But seeing the stuff he struggles with and using the tool ourself and feeling that pain, to me that feels like the only right way to do this. Along with of course listening to feedback from the users.

CW (00:47:41):

We used to call that "dogfooding" in Cisco.

TS (00:47:45):

Yeah.

CW (00:47:46):

I do not really like the term, but...

TS (00:47:48):

It is a bit gross. But yeah, we have called it that as well. When I was developing for Bluetooth Mesh, we were making APIs. APIs are kind of similar. There are so many levels of control a user might want, and you will never be able to satisfy all of them, without confusing the rest. Nothing like that where you are designing for a user, especially a developer, nothing like that is really finished, until you have tried it and failed and fixed the problems that you experienced while trying it.

EW (00:48:35):

You have people on your tools team now, that- And you are the lead of the tools team, partially because this started out something you did external to Nordic. But you also did a thesis on BLE Mesh and deep embedded code over many years. How is it going being in charge of a tools team, and not playing with the microprocessor?

TS (00:49:06):

Yeah, ideally I would immediately say that I miss C, and I miss some of the development and everything about it. But ironically, the tooling for a language like TypeScript is very nice.

EW (00:49:26):

He does not miss us at all.

TS (00:49:28):

I do. I miss some of it.

CW (00:49:30):

Hey, I have been doing Python for two years. Do not look at me. <laugh>

TS (00:49:33):

Oh yeah. Well for me, on the Bluetooth Mesh project we were able to help some customers bring their product to life in a way that is closer to where I am now, in a way. But I also feel like I am able to help more people, because the stuff I do now is not just for the users of the Bluetooth Mesh stack. It is a significant part of our customers working towards that, but now we have made it so that they all have to use our VSCode extensions to a certain degree. Or at least they have to see if they are going to use it or ignore it.

(00:50:20):

So along with a more pleasant development environment, of not having to flash your device to try the thing you just did, and spending a week writing a feature and fixing memory bugs, I actually enjoy it a lot to do this. I try to not lose contact with the embedded stuff. I can still imagine myself going back to embedded development, later in my career.

EW (00:50:58):

Could you get together with Uri over at Wokwi, and make a Nordic simulator that runs in VSCode for me?

TS (00:51:08):

Oh, I really want to. It is really great. So yeah, we would like to. I think that is all I have got right now. Having that running and if you can run that, even if we could get to a point where you do not have to wait for two weeks for DigiKey to ship you the development port, you can start trying out our SDK right now. I think that would be a good place for us to be.

(00:51:41):

Yeah. It is a cool project. I think there are several cool projects almost like it. I would like to try and integrate with them, especially if this is something where it helps developers, and you can write code faster by doing it.

CW (00:52:01):

Closing the gap between the niceties of application development, and all the tools they get, and where embedded has historically been. That would be so great.

EW (00:52:11):

The last ten years have been great.

CW (00:52:13):

They have been so much better. The last ten years have had more progress than I think has ever happened in the embedded development world. But still. There is still a gap!

EW (00:52:23):

There is still a gap.

TS (00:52:26):

Yeah, there is. So yeah, I mean we are all using- Well, it is possible to use C11 now. That is progress.

EW (00:52:38):

It is 2023! We should not be saying C11 is progress.

CW (00:52:42):

Hey, C99 was progress for some people in 2020.

EW (00:52:50):

<laugh> I have a couple of listener questions. Benny says, "Functions such as BLE Mesh tend to be complicated to use." That was kind of an understatement. "Nordic provides samples, but it is not easy to adapt these into another codebase. Do you have some best practices or recommendations for trying to integrate these functionalities into my project?" Could you summarize everything I need to know in about 45 seconds?

CW (00:53:18):

Yeah, great!

TS (00:53:22):

<laugh> No.

EW (00:53:25):

Where do we get started?

TS (00:53:28):

I think the samples are the place to get started in nRF SDK and any SDK like it. This is actually something we are actively discussing with the VSCode extension, and Nordic SDK in general. This is one of the hardest problem, and hardest problems to deal with, because you have to deal with them early, before you are super comfortable with everything about the environment and the SDK.

(00:53:54):

There are never any- No one makes the, I do not know, environment sensor device, and all it is doing is talking to that single API in the driver and printing it to the screen. The samples are all like that, but no products are like that.

EW (00:54:14):

But the samples need to be like that, because it is a complicated system. You need to simplify it down to something I can understand. But Benny is right. If I can understand it, it is probably not what I am really building as a product, because anybody can-

CW (00:54:28):

If I can understand it, it is probably too simple.

EW (00:54:29):

Exactly! <laugh>

TS (00:54:35):

Yeah. So yeah, the samples need to be like that. And I think often the harder- Especially with more complex samples, where you pull in the network stack and stuff like that, you need to do so much other stuff, before you get to the core of the thing the sample wants to show you.

(00:54:52):

So if you are with Bluetooth Mesh for instance, you would need to provision the device, because it does not have a non-secure mode. It is security is enforced. You have to add keys to your device. You have to add it to your network. There is an authentication procedure. All this stuff has to go into every sample, in order to get to the point where the sample shows you, "Oh, if you send this 'Blink the LED' message, it is going to blink the LED."

(00:55:23):

If you are not familiar with the APIs, you will have such a hard time just wading through all the code in there, just to get to the stuff you actually want to see. Filtering that out is daunting. So even the simple samples for a complex enough system, they will be hard to understand as well.

(00:55:45):

First, you have to find two samples, that do almost the stuff you want to do. And then you have to figure out all the stuff that it is doing, that you do not actually care about. And mentally at least, filter that out, and then start combining it.

(00:55:57):

Yeah, it gets complex and it is something we- Ideally we would like to be better at this at Nordic, because it is a friction point. It is a point where new users especially get into trouble, and you just cannot get around it either. You have to dive into it like this. We do not really know fully how to fix it. Perhaps it is not a fixable problem. But at least we can try and make the experience as pleasant as possible.

EW (00:56:37):

It is a really hard problem. I have not used the Nordic products for a few years, like five, seven, maybe only four. But I have used the TI Zigbee and BLE stack recently, so I am in a slog on them.

(00:57:02):

But I do recall Nordic having similar problems, in that I had the example that did what I wanted to do with modifying the GATT. Then I had the example with the DFU. They actually were both pretty good examples, but when I combined them, they had been written by different people at different times with slightly different approaches. So combining them led to weird problems with what parts of the SDK I was using.

(00:57:38):

And of course, as a user coming into this not knowing what is important, I have to support both of these, because I cannot tell which one is crucial. And it is like you want to keep around your old examples, because it is important that people see the old examples. Not everybody is going to be on the latest. But you also want all of your examples to be self-consistent all the time. I do not see how you can solve both those problems.

TS (00:58:06):

Yeah, it is tricky. One thing that helps a bit from our perspective here, is trying to classify different types of applications that we show the customers. So samples will typically demonstrate some very specific concepts, and we have put those in the samples folder.

(00:58:29):

We also have different, like a demo, here is a big project. We just call them applications. So we have an asset tracker application, that shows basically a full product. It is going to fit on a dev kit, or one of our more fun boards. But in the end, it is like a full, "Here is how we integrated the Bluetooth and the sensor API together." You would get the callback from the sensor saying, "I have data." And then you would put that into the Bluetooth API that says, "Store this data in the GATT table."

(00:59:07):

We think there might be room for more. There might be other types of applications we could do here, where- I am curious about template applications, and having starting points which are not a demo. They are not printing to the console, they are not trying to blink something. They are just starting points. They will have like enable advertising in Bluetooth, but they will not start sending dummy battery data over it. They are just blank starting points saying, "This is the stuff you need. You do not have to delete anything. You do not have to filter it."

EW (00:59:48):

Yeah.

TS (00:59:48):

Yeah. We can still improve on this from the SDK's perspective. We are trying to see if we can do something about that.

EW (01:00:02):

It is a tough problem. Okay. Let us see. More user questions.

CW (01:00:06):

Listeners.

EW (01:00:06):

Yes, listener questions.

CW (01:00:12):

We do not have users.

EW (01:00:14):

Jonathan asks what it is like to be a software developer working at a chip company, with the majority of other folks writing firmware. He also says that you are great, and you are very helpful on the Nordic DevZone and Zephyr Discord.

TS (01:00:29):

Oh, thanks. Yeah, Nordic is still a hardware company, and always sell this hardware. Even being a software developer working on the SDK, you are still in a minority in a silicon vendor type company. So the difference going to tooling is not that big, except my users or- Yeah, I do not have listeners. I have users.

EW (01:00:58):

<laugh>

TS (01:00:58):

I meet my users at the coffee machine sometimes, and they will tell me, "Yeah, I tried your debugging thing that you just made, and it does not work, man, please fix it." So I think that is the biggest difference from when we are in a department that is in the minority, anyway. The biggest difference transitioning into tooling, is that my users are at the coffee machine.

(01:01:26):

If I am lucky, they will tell me what is broken. If I am not lucky, they will just say, "Hello," and then walk away saying, "Oh, that guy does not- He should have gone with Vim instead."

EW (01:01:40):

<laugh> You had a question for us. I think about development set up?

TS (01:01:44):

Yeah. You guys are working as consultants. I am sure you have way too many development environments. How do you deal with that as consultants?

CW (01:01:58):

Most of the time, for most of the clients I have had- I work on Macs. I like Macs as computers. But unfortunately, even though GCC and everything, and JTAG servers, all the stuff you need to do embedded development, works on Macs, most clients tend to not be set up that way with their toolchain.

(01:02:19):

So most of the time I have got a whole collection of VMs running Windows, or sometimes Linux, with the toolchains running on those. I will, depending on my mood, have VSCode running natively in there, or VSCode on my Mac and do file sharing stuff. Less often Mac, because it can get-

EW (01:02:40):

VSCode SSL is awesome!

CW (01:02:42):

SS? Yeah. VSCode remote SSH.

EW (01:02:44):

Thank you.

CW (01:02:46):

We will often use that for various uses. Lately, since I have been doing Python stuff, that is more friendly for Mac. But the targets I am using, tend to be high powered embedded devices still, so I am doing remote SSH into there. It is kind of a mess, like you might expect.

(01:03:04):

My wish is that more stuff could be done natively. Or that more companies support more client companies, not vendor companies. More client companies would support Mac toolchain natively, because it would make my life easier. But it is not that big a deal. The VMs tend to be fine, even though I have these windows.

EW (01:03:24):

We are there to support them.

CW (01:03:27):

Well I do not care!

EW (01:03:27):

<laugh>

CW (01:03:27):

They would feel better, if they were using Macs. So it is better for them too.

EW (01:03:36):

I however, am a native Windows user-

CW (01:03:38):

And I will add, most of the client companies are using Macs. They are all using Macs!

EW (01:03:43):

Yes.

CW (01:03:43):

They are also using Windows VMs, because nobody wants an actual Windows laptop.

EW (01:03:53):

I do not use VMs as much. I tend to just go ahead and use my system, which has problems if I need Python 2.0, which I always do. And I use WSL on Windows a lot. But I also have a lot of hardware these days, and different programmers. So I have a SEGGER, I have an infinite variety of ST-LINKs, CCS whatever, TI XDS something, Black Magic-

CW (01:04:28):

Cypress had their own thing.

EW (01:04:29):

Cypress had their own thing. That was small, it was not too bad. And then I have what I feel like is every wireless dongle that is made. I think I have two different Nordic ones, but I do not know if they actually do different Nordic things. I think one is just very old.

CW (01:04:45):

And I keep three boxes of dev boards near my desk. That does not count the garage hoard, which has more dev boxes, although those are all getting pretty old.

(01:05:01):

I think those are mostly Z80s at this point.

TS (01:05:04):

<laugh>

EW (01:05:05):

I did order an nRF thingy 52 to play with.

TS (01:05:11):

Yep.

EW (01:05:11):

That looks pretty cute. And most of my other new dev boards are STM M4Fs of one variety or another. Oh, I got a bunch of M0s too, M0+s, for a low power thing.

TS (01:05:30):

Do you find that the communication with the hardware works okay, from a virtual machine setup? Or does it add even more complexity to this matrix?

CW (01:05:41):

Yeah, I have never had a problem.

EW (01:05:44):

I have had a problem, which is why I run natively.

CW (01:05:46):

I have never had a problem. <laugh>

EW (01:05:49):

I still have a problem. I still have a problem with WSL and GDB sometimes, so that is fun. Or ST-LINK WSL is unhappy, so I end up using VSCode to compile in WSL, and Windows to load my-

CW (01:06:07):

Oh my God!

TS (01:06:08):

Look, just-

EW (01:06:08):

But now that it is in VSCode it is just two buttons. Once I get it set up it is fine.

CW (01:06:13):

Yeah. Once again, set up is the key.

EW (01:06:16):

But it was pretty irritating to try to ST-LINK. How do I do the command line? I still do not really- I end up opening the ST stuff to erase the chip when I need to do a full erase, because I do not know the command line for that. I do not really care.

CW (01:06:31):

I say I have not had a problem, but that is because I use Parallels on Mac for virtual machines, and it is excellent. I have tried VirtualBox. I have seen you try to use VirtualBox. And I do not know if that thing does not work very well.

EW (01:06:46):

It works pretty well. Just do not mess with the USB very much.

CW (01:06:48):

VMware used to work until about five years ago, when I think they sold most of, or got rid of most of their developers, and it has not been good. So there is only really one good VM platform.

EW (01:06:57):

You cannot sell developers.

CW (01:06:59):

Who knows what happens these days.

EW (01:07:00):

Or users or listeners.

CW (01:07:02):

Anyway, to your question, it is a mess.

TS (01:07:06):

Yeah, okay. Yep. That is to be expected, I suppose.

EW (01:07:13):

Let us see. What compilers do you have installed these days? We both have Cypress. I have ModusToolbox and the older one.

CW (01:07:24):

Oh, I do not- That client is over, so I uninstalled all that stuff.

EW (01:07:28):

You uninstall these things?

CW (01:07:29):

Yeah, I take that virtual machine, and I move it to an external hard drive. And then I put it in the "Raiders of the Lost Ark" warehouse, and then I never see it again.

EW (01:07:38):

That makes sense. Yes. All right.

CW (01:07:44):

I only have GDB stuff I think, and maybe STMCube right now.

EW (01:07:50):

I have Code Composer and the Cypress stuff. I have VSCode set up to do STM things, and Python things for different clients. I have a ROS set up.

CW (01:08:08):

Why? <laugh> You need to learn delete stuff. That is the

EW (01:08:13):

Because someday somebody else is going to want me to use Robot Operating System, and I will go back to Gazebo and it will be fun.

CW (01:08:19):

But the install you have is eight years old by then, and you will have to install it again, anyway. Back to our guest. <laugh>

TS (01:08:25):

<laugh>

EW (01:08:27):

ROS Kinetic forever, man! Okay. Back to our guest. It has been wonderful to have you. Do you have any thoughts you would like to leave us with?

CW (01:08:34):

<laugh>

TS (01:08:36):

Yep, I think for companies like Nordic, our success is really just depending on the success of our customers. So if you guys do not ship your devices on time, we do not make any money either. And the software department that we have in like our tools department, only exists to make sure that our customers are able to ship products.

(01:09:01):

So if we are doing something that is getting in your way or really annoying you, I think we much rather want to hear about it, than you guys just giving up and then taking whatever editor, for instance, that you would rather use and not telling us. Even if the feedback is, "This is all garbage, and you should start over," tell us, instead of not telling us, but telling yourself this, and muttering to yourself about it.

(01:09:33):

Yeah, we really just want to get feedback, because we do not develop applications ourselves. We make the SDK, and we are basically making the SDK. So we really rely on feedback from our actual users using the stuff we are putting out, to feedback into that team and improve it. We are really grateful to hear any positive or negative feedback like that.

EW (01:09:57):

Well folks, you have heard it here. Quit your muttering, and tell all your problems to Trond.

TS (01:10:03):

<laugh> Yes.

EW (01:10:08):

Our guest has been Trond Snekvik, Staff Software Engineer at Nordic Semiconductor. If you want to look at these Extensions, you can find them at Nordic Semiconductor under the Marketplace part of Visual Studio. There will be links in the show notes, of course.

CW (01:10:22):

Thanks, Trond.

TS (01:10:23):

Thanks.

EW (01:10:24):

Thank you to Christopher for producing and co-hosting. Thank you to our Patreon listener Slack group for their questions. And of course, thank you for listening. You can always contact us at show@embedded.fm or hit the contact link on embedded.fm. We might pass along some of your notes to Trond. Probably. Especially the nice ones.

(01:10:44):

But now a quote to leave you with, from Henrik Ibsen. "It is a liberation to know that the act of spontaneous courage is yet possible in this world. An act that has something of unconditional beauty."