 Hello everybody. Thank you for joining this talk. We are going to present TokoS, which is an embedded operating system fully written in Rust. First of all, a few words about us. We are Alex and Alex, myself, Alexander Radovic. I'm an assistant professor at the Polytechnic University in Bucharest. My field of expertise is in operating systems and compilers. I'm here together with Alex, my student. He's just graduated today with his bachelor's degree in engineering, and his project was presenting his contributions to TokoS just this morning. I'm sorry if we're making a bit of mistakes or something is not clear. It's 12 a.m. in Romania, so it was a long day for us. About half a year ago, I was searching for interesting projects that were written in Rust because of my interest in operating systems and system programming, and I stumbled upon TokoS. TokoS is a new embedded operating system which runs several applications concurrently on low power and low memory microcontrollers. This is somehow very interesting because it borrows more or less the architecture of Linux but applied to microcontrollers. I'm not the creator. I'm not affiliated with TokoS. I just loved the project and we, me and my team, contributed to it for the last six months. Okay, so a few facts about TokoS. It's a preemptive operating system. It was designed for Cortex-Ms, MCUs, and then it has been ported to RISC-5 because it's really growing architecture and as we saw in the keynote, more and more institutions are using RISC-5. What makes it really different from other embedded operating systems that I have worked with, it uses memory protection out of the box, so if your MCU knows or has a memory protection unit, your applications will have to obey it by default. In the other operating systems that I've worked with, this was an extra step that had to be taken. It borrows a lot from the architecture of general operating systems. The kernel is fully written in Rust and is compiled completely separate from the user space and applications are compiled separately, so you don't need the kernel to compile an app. Applications could be written in any language like C or Rust or anything that could compile to a binary and anything that supports a position-independent code. Before we dive in into TokoS components, I want to talk to you a little bit about Rust. Rust is a systems programming language designed by Mozilla. Its main purpose is to offer memory safety without the penalty of having a garbage collector. Rust uses the borrow checker at compile time for this and ownership, so programmers have to obey a lot of rules at compilation time. Imagine it's like having a language like Java or .NET, but without the overhead of a garbage collection or of a runtime. Due to the fact that it was designed as a systems programming language, from time to time when you're writing operating systems, you have to access direct memory addresses or you have to directly do some pointer arithmetic or you need to do some unsafe typecasts. These are generally forbidden in Rust, except that Rust provides a keyword which is called unsafe, and inside this unsafe block, the compiler will not check memory safety. You as a programmer are allowed to do whatever you want. It's like programming in C and C++ inside of Rust. Having said this, the TokoS kernel is completely written in Rust. It's made out of two components, the lower part which is the hardware abstraction layer. This is where you write platform dependent codes and small drivers that interact with the hardware. This part of the kernel does have some unsafe code because it's not possible to write it otherwise. On the top part of the kernel, we have the capsules. These are the drivers, it's just a different name for drivers. These drivers are completely hardware independent, so they should work on any microcontroller. They're not allowed to use the unsafe keyword, so the compiler will not compile the capsule and not compile the kernel if inside the capsule you have an unsafe keyword. They still reside inside the kernel and they talk to the lower part of the kernel through the hardware interface layer. On top of the kernel, we have the applications. These are written in any programming language and they talk to the kernel using the system calls and interface with the capsules like that. A better illustration of what I said is this picture which is from TokoS's GitHub. On the lower part, we have the hardware, the microcontroller with all the peripherals. The orange part are the drivers that are specific to each architecture, so interfacing the SPI, the I2C, the timers which are completely specific to any microcontrollers. This part has unsafe code. The TokoS team has done great efforts to minimize the number of unsafe lines that are written here, but there's no other way to do it. On top of this, you have the kernel, the actual kernel which handles memory allocation, scheduling, and provides a hardware interface layer. This still has some unsafe code. On the upper side of the kernel, you have the capsules which interact with each other, provide an API towards the application, and use the lower capsules through the hardware interface layer. These capsules cannot use unsafe code, so they are guaranteed at compile time that capsules cannot write into each other's memory and cannot influence each other in a way that it shouldn't be desired. Yes, the TokoS kernel still has some unsafe code, which is like writing code in C, but compared to other embedded operating systems where we have tens of thousands of lines of unsafe code, in TokoS, you have a small number of lines that have to be audited manually. On top of the kernel, in this example, you can see a C application, a Rust application, a service which could be written in any language, and an application that tries to bring down the kernel by doing some infinite loop, but because of TokoS's protection, this is really difficult for an application. Why did I start contributing to the project, and why did we find it really interesting? Well, these are the three things. First of all, it's the first embedded operating system that I see that is completely asynchronous. While applications can be preempted, the kernel cannot be preempted. A driver cannot make an infinite loop, or a driver cannot use a delay function. If it needs to wait for a peripheral, it needs to issue an action to the peripheral, give up the processor for an application, and whenever the peripheral finishes, it will signal the capsule via an interrupt, and the capsule can continue. This is like a comparison would be TokoS is for embedded operating systems, like what Node.js is for programming languages, so it's completely asynchronous. In Linux, the equivalent in user space would be the Async.io. Another interesting fact is that heap is not available to the kernel, so all the buffers that are available in the kernel have to be known at compile time. This gives us a lot of security, because the kernel cannot overflow memory, because all the memory space is known before, but it does create a problem when writing drivers, because some drivers really need to allocate some memory to store information about applications. This is handled through grants, and I'll talk about grants a little bit later. TokoS is rather new. They started in 2014. Boards that are supported in TokoS are divided in three categories, the stable category, and these boards are fully supported, all the peripherals work, so if you just want to build some applications on TokoS, I would strongly recommend using these boards. The second category is developmental boards. These boards are partially work, but there are still some peripherals and some functions that are not available. This is where I had a contribution by submitting the STM discovery boards, and Alex submitted the IMX RT board. If you want to develop TokoS and play a little bit with the kernel, these are the boards that I would recommend as well. There are also experimental boards, mostly risk five architecture, because it's rather new in TokoS. These boards work, but we expect some failures or some memory problems or some running problems with these boards. TokoS has been getting some momentum, and people are starting to look at it. Google has decided to use TokoS for OpenSK. OpenSK is a project from Google where you could build an USB stick for digital signatures, and there's a great effort from the TokoS developers to support TokoS and fully support OpenTitan. OpenTitan is a project that wants to provide an open source silicon root of trust for signature and encryption chips that you will find in the new appliances and computers. It's a consortium of several companies, and I really think TokoS is a really good option for it. So a little bit about applications. As I said, applications are compiled out of three, so you don't need the kernel of TokoS to compile an application. They compile to a standalone binary. It's not an else file, and we'll see that further on. If the microcontroller does have a memory protection unit, the application will have to obey it. So whenever the kernel switches to an application, it will program the memory protection unit so that the application can access only its memory. And this is really good, as I remember porting a JavaScript engine last year for Fiat TOS, and JavaScript is only a bit memory hungry, and we had a lot of stack overflows, our memory overflows, and the result was really unpredictable. It was really hard for us to debug and see what went wrong. TokoS applications do fault. So like Linux applications that segment fault, sorry, these applications fault. So if they try to write outside their memory, the MP will stop them, and you will get a really nice log with the fault, and we'll see how it looks like further on. It has a downside. Applications need to have relocatable codes, so the compiler needs to be able to do a positioning dependent code, and this has been a challenge mostly for RISC-5 architecture. And the thing that they somehow borrowed from Android, it seems like they borrowed it from Android, applications can expose services, and other applications can browse for those services and consume those services. And this is the model of inter-process communication that TokoS provides. If we look at the memory layout, you might notice that it's a little bit strange. Probably you are used to see the stack on the top, at the top of the memory. In case of TokoS, the application code is resized inside the flash. The stack is at the bottom part of the memory, so every application will have to specify upfront how much stack it wants to use. This is a decision made because it will prevent application from stack overflowing. So if they overflow the stack, what happens? The application will basically overflow the memory boundary, and the MPU will stop the application, and you will get a nice report that the application did some fault. If the stack were at the top of the memory, it would just override your heap, and that would lead to undefined behavior. On top of the stack, we have the data, then we have the heap, and at the top of the memory of an application, we have the grant. So as I said, the kernel is not able to dynamically allocate memory, so every capsule that needs to keep some information on a per application basis needs to declare upfront how much memory it needs to use for every application. This amount is the same. It doesn't matter what kind of application you run. On the technical side, they have to declare some structures in Rust. When an application is loaded, the kernel will sum up all the requirements from the capsules and add that memory space to the application memory. If the memory cannot be allocated, the application won't start. So it's like a transactional thing, so either the application starts and then there's enough memory for the kernel and the application to run. Either the application doesn't start because the kernel cannot allocate enough memory for its drivers. Another interesting fact is that TOQS uses real system calls. So in many embedded operating systems, system calls are just the function calls. In this case, TOQS uses the supervisor call instruction on ARM and the equivalent on RISC-5. It exposes five system calls out of which yield is the only one that is a blocking system call. So every process in TOQS has an event loop, basically a callback queue. So when a capsule needs to inform an application about an action, it will schedule a callback. Callbacks are not called while the application is running. Whenever the application calls the system called yield, the TOQS kernel will verify the queue if there is a callback function in the queue. It will call the callback function and then resume the application from the system call. This is very similar to a generator in Python. When your main function exits in the application, the RISC library will simply yield continuously. This is the only system call that can block an application. Subscribe. Subscribe allows an application to register a callback. It gets the capsule number. This is the ID of the driver and the TOQS kernel will redirect this subscribe call to the specified capsule and the pointer to a callback function and the user data. The command system call is similar to IOCTL from Linux. It will ask a driver, a specific driver to perform an action. The difference being that the result of the system call is not the result of the action, it's just an acknowledgement that the action will be performed. Allow provides a mechanism for applications to share a buffer with the driver. For instance, if you have a capsule that wants to read something from the flash or from the network, you will share a buffer with the driver. The driver will fill the buffer and then call you back that the buffer is filled. The last one is memory operation. This is targeted to the kernel. It's similar to BRK or SPRK from Linux. It does memory management, so it hires the heap or lowers the heap limit. Just to give you a quick idea on how a system call would work. First of all, you have the application. Let's say you want to take some accelerometer data. The first step will be to allow a buffer so that the accelerometer capsule can place the result inside the buffer. Afterwards, your application would have to subscribe so that it can get the call back when the buffer has been filled. The third item would be to send the command and the capsule will understand that it needs to perform the action. The capsule will interact with the lower level capsules and with the hardware, but the command system call will return immediately. Afterwards, your application will probably yield and wait for the call back when the data is available. This is a little bit more complicated, but offers you greater flexibility. About writing applications. For now, Liptox C is fully supported and this is the recommended way in writing applications. It's built on top of new Libc and Libc++. It has bindings for Lua and little VGL. It still has a problem with the RISC-5 architecture as the compiler is not able to generate the correct code for position independent. If you want to try programming in Rust, you could write applications in Rust. It's still a developmental library. It's in active development. It still has a big bug because there's a big compiler bug that prevents us in building a position-independent code the right way. I strongly suggest you to use C. Our small contribution to the project was to port the D-language that was my student, Theona Severin, which also graduated today, and she ported the D-language and enabled D-language for ARM and TokoS. Of course, without the garbage collection. You might have seen Yana this morning in the keynote. Her work was porting Jerascript to TokoS. Jerascript is a really performant JavaScript library. It's used by Fitbit in the watch's face. It works on TokoS. GPIO's buttons let timers work. We still have some issues with the memory protection because the memory protection unit is not as flexible as the one on your computer, so it imposes some memory alignment limitations and JavaScript is really memory hungry. When it comes to the executable, we won't have an ELF file. For TokoS, we have a tbf file. It contains a header which specifies how much stack and how much memory the application needs, and then the actual application binary. A really cool fact is that TokoS applications can be shipped with several architecture in the same file, in the tab file, Toko application bundle. This is more or less the same way Apple ships applications for the iPhone. You have several iPhone processors, and you have one binary that contains a small binary for each of them. For loading TokoS applications, you don't have to rewrite the whole flash. You can load on the microcontroller flash only the application. This is done by Tokloader, which is a small Python script that does this for you, and they even implement it in an app store. You could write Tokloader, the name of the app. It will download the tab files, select the correct architecture, and ship it to your microcontroller. This is a really cool feature, and I haven't seen this before in a microcontroller embedded system. I would like to ask Alex now to walk you through what it means to port a new board to TokoS. Alex, if you can take it from here. Yes, hello. This is the NXP IMX RT 1052 EVKB, the board that we managed to port to TokoS, and it features an ARM Cortex M7 CPU with a nominal frequency of 600 megahertz. This is actually an interesting board for us, because it also allows us to work on a side project of ours, which is to run WebAssembly code on top of TokoS in the user space. Also, I would like to use this opportunity to thank the NXP office in Romania for supporting this project with boards and also scholarships. Coming back to the board, the NXP EVKB offers user-controlled LED, a button, and also a motion sensor. These were used for testing the facilities that we implemented. Other notable facts, it has an Ethernet port and also 256 megabyte SD RAM. In our process to port TokoS for this board, we created support for a new architecture, the ARM Cortex M7, which was mostly based on the existing ARM Cortex M4, which was already supported by TokoS. We also managed to implement some of the core features for this board, which are, for example, the serial line for communicating with the board, the I2C peripheral, which was tested by using the motion sensor, and, for example, the GPIO, which was tested by using the user LED present on the board. Finally, we also ported the Rust library for the user space for this board. Now, let's take a look at what means to implement a feature in TokoS in the kernel. So the first part, we have to define the registers, for example, the structure of, for the general purpose registers in the right picture. After that, for each register that was defined, we have to define each component. For example, the prescale register in the left photo. After that, we map the structure of registers in the memory and implement the functions that are related to that feature. One of the major problems that we encountered during this process is that the IMXRT has a huge number of registers. For the input-output multiplexer controller, we had 154 registers. Yeah. In order to deploy an application, we have to use the MCU Expresso IDE and the SDK for this board, which are also normally used in order to program an application for this board. Then we import an SDK example like Hello World and then separately compile the Tok image, which will also have to contain the application that will run in the user space. And then drag and drop the application in the IDE, configure the debug to select our image, the Tok image, instead of the image that would be generated by the SDK example, and then just hit debug in order to program the device. We encountered quite a few problems throughout the development process. The major problem that we had was an issue with the system timer, which was mostly due to a wrong timer frequency. And we fixed this with a pull request, which is in the process of being accepted, which extends the functionality of the SysTik for the ARM Cortex-M processors. Other problems that we encountered, the compiler error in the Rust library, and also a bus error. We were actually implementing the fix for this. And right before we tried to create the pull request, it was already fixed by the Tok core team and patched in the upstream. We are now working on importing the full Cortex-M7 features. We have already implemented all 16 MPU regions. And we are working on supporting full cache features for this board. After that, we will implement the other features that were not touched yet, for example, the SPI and the Ethernet. And after that, we will take a look at the other devices from the IMXRT family, such as the 1060. If there is anyone in the audience from NXP, we would love to collaborate in order to better integrate this TokOS development project with the MSU Express so IDE. As for the moment, we are kind of doing a hack, like drag and dropping the Tok image inside of the IDE. Also, as Alex mentioned earlier in the presentation, TokOS provides an application called TokLoader, which helps you to program devices that are supported by boards that are supported by TokOS. So we are also planning on extending the support for the TokLoader in order to support the IMXRT board. For the demo, Alex? Yes, I need to get to the end here. Thank you, Alex so much. Before we have a demo, I would like to answer one of the questions. So the question is if there are any plans for app signing? Yes, there is a TokOS threat model, which you can find on the TokOS repository. And this has been already a discussion in adding a digital signature or a way of verifying that apps are legit, let's say, like that. I have another question, but that's one about the footprint, but I will answer it during the demo. So first of all, let's dive into this. I will share my screen. My screen should be visible. Alex, can you confirm that my screen is visible? Yes, it's visible. Just a few seconds. I will show you what I have here. So this is TokOS. This is the TokOS repository. As you can see, this is just a kernel, not a user space. We have an architecture folder with the processor architectures. We have a chips folder where we have a specific chip that contains one of the architecture and has the peripherals. And we have a board folder where we have the entry point of the kernel. For this example, I will use the Arduino Nano BLE. It has just been added this week as a supported board. And the reset handler of the CPU is basically the main or the entry point into the kernel. We also have a folder with the capsules or the drivers, a documentation folder, and the kernel folder where we can see several information, where the kernel resides, the scheduler, process loader, and so on and so forth. For the demo, I will use the Arduino board. So let me just unlock the phone if this would work. Okay, so you should be able to see my phone. So I have here an Arduino BLE board. It's about $30. You can buy it out of Amazon. It's hooked up to an LCD screen, a really nice small LCD screen over SPI, and it's not running anything at the moment. So the first step that I want to do is to flash the kernel. So I will enter the boards folder and choose nano, the nano board. And I would say make program and program. I will put the Arduino into flash mode and I still need to specify the port. This is a problem on the Mac. Somehow it does not detect automatically the port. So as you can see, it compiled the kernel. I already had it compiled. After the compilation coming back to the footprint, you can see here the size of the kernel. So this is about 90 kilobytes in text. The data is about 2 kilobytes. BSS is about 55. So the total memory footprint should be somewhere around 90 kilobytes of RAM and 90 kilobytes of flash. The kernel is flashed onto the CPU on the microcontroller. As you can see, it does nothing. So it's just a kernel. If we were to open a serial, a serial line, this is done with top loader listen. You can see it writes initialization complete, entering main loop, and that's it. Okay, so let's write an application. This is the user space for talk. I will use tiktok c. You can find new lib here, which is pre-compiled, lbgl, the luah library, the tiktok library, which provides the system columns and the user space for the capsules and the examples. I will take the blink example and this is how a talkwise program looks like. As you can see, it's more or less like a normal application that you would write for your computer. So there's nothing specific to the microcontroller. It's just the main and you use the normal function that you would use. So I'm just going to enter examples and blink. I will compile it. I will say make. As you can see, it compiled the application. It didn't need any kernel. So this is a normal C compiler and it built three architectures, the Cortex M0, Cortex M3, and Cortex M4 files. Also, we have a tbf file out of them. So how do we flash an application? We will use... Talkloader is not fully supported for Arduino. So we will use BOSAC. BOSAC is the normal Arduino bootloader. And as you can see, I will flash the Cortex M. The file is called Cortex M tbf. So I will simply flash only the tbf file, not the kernel. Again, I'll put the Arduino in the flashing mode. Start flashing. It was super fast. The application was really, really small. And as you can see, it flashes the LEDs. Once again, if we go into the Listener, we can see the device just started, but it's not writing anything on the screen. Now let's try a more difficult application, something with a screen. I have here an application that uses LVGL. It just writes loading, displays a gauge, and then says, hello, TokoS. I will go into LVGL. Okay. So this application was about one kilobytes of text, and it used about three kilobytes of memory. So add this to the kernel, and that is the footprint. In case of the screen, this will be a little bit larger because it has LVGL, about 60 kilobytes of RAM, and about nine kilobytes, sorry, nine kilobytes of RAM and 60 kilobytes of flash. We have built the application. Let's flash it. So I will use, again, Bulsack, and just go and flash the screen. So I will, instead of bling, I will write screen, sorry, not screen, LVGL. This is Cortex MTBF, and I would usually do this with Tokloader, but it's not supported yet for this. As you can see, flashing takes a little bit longer, and here we go. If we get lucky, yes, LEDs are, sorry, you can see the screen is working. Okay. So it's loading whenever it's finished. Yeah. The application was normal application. So if I want to flash two applications, I could do that. So what I have to do, I will accept this, and I will simply concatenate the Blink application and the LVGL application into one single file, which is called AppsTBF. This is done, and now let's flash it. We'll see an interesting thing here. Oh, I forgot to put the Arduino into flash mode. Here we go. You can see it's a little large, and surprise, the LEDs work. The screen, not so much. Oh, sorry. So the LEDs work, but the screen, not so much. My phone just, so what happened here, we're going to use Tokloader to listen, to see whatever the Arduino is saying. As you can see, due to the memory protection, you need alignment. Even though it had enough memory, it could not flash both, it could not start both applications. A trick that you could do is to concatenate them in a different order. So first the screen and then the LEDs. I just change the concatenation, flash it again, and here we go. This time, they should both work. So it started, as you can see, LEDs are flashing, and the application is running. Okay. So, yeah, switching back to Alex, if you can show us a little bit about the NXP. Yes. Just a second to share my screen. You have to close your share screen first. Oh, sorry. Sorry, Alex. Here you go. No problem. Okay. You should see my screen right now, right? Wow. I see it. Can you confirm, Alex? Okay. Yes, yes. I can see it. What we have here. Okay. Super. So what we have here is a simple application for the NXP board, which tests the a few facilities of the board. So in order to program it, I have hit make in order to compile the application. This is over the LibToxy library. So this is only the application from the user space. After this, we go back to the talk development folder. We make sure that the app variable points to the application that will be used as a user space application. For now, we have to put both the application and the kernel at the same time on the board, since the board is not supported by the talk loader. So I simply hit make program in order to get the binary file. After that, in my MCXpresso IDE, I have a simple SDK example, the Hello World. I drag and drop the talk image. Normally, what I would do, I would hit here the, enter the configuration mode to see if the application is mine, that will be programmed on the device. And now I press debug. Oh, just a second. I forgot to insert the board. Yes, it should see it. Okay. Okay. So it was copied on the device. Next step, we open a serial connection with the device. Oh, it's the other board. Okay. And then if I hit run, so it's a simple application which allows me to insert my name. And then I can turn on and off on LED. I will turn on the LED in order to, and I will stop sharing the screen so that you can see on my camera. Oh, I don't know if it's full screen. Okay. So the LED that was, okay, just a second. The board is connected. Sorry. Oh, okay. You see it? Okay. And if I go back to share screen, just a second, and back to the serial line. If I want to cause a fault, a hard fault, I simply press X. No, the board is connected. What happens? I have a, yeah. What happens is that I have on my Mac only USB-C. So the adapter is not fully working. Just a second. USB-C is not fully, not a standard yet. So. Yep. That the Apple decided to drop the USB ports. Okay. So if you can see a fault. So back here. Okay. If I press X to cause a hard fault, because the program runs in debug mode, first MCXPresso will take over and say, okay, you get a hard fault here. And if I press continue, I will get the output for the hard fault from the top OS operating system. So here, if I go up, it says where it hit kernel panic, and it also says the faulting memory address, which is 0800, because I created a more pointer and the same value to it. Also, if we want, we can see other information such as the values of the registers, the way the memory layout looks, and which regions from the MPU were used. I don't know if you want to add anything else to this, Alex. No, I, the thing is, like Alex can send me the binary right now, and I could run the same app on my Arduino board, and it would work exactly in the same way. Here, the kernel actually panicked because this is a debug mode, but there's a setting in TokoS. Alex, if you could unshare your screen, so I can share mine. Yes, of course. Yeah, there's a setting in TokoS, which, okay, that's just insuring is not working for me. Oh, sorry, it was a problem with the browser. Entire screen, okay. So getting back to my screen, you can see here, there's a setting, setting in TokoS about what to do if an application folds. One is panic. This is for development. So you can see the debug and the segmentation fold. The others are just terminate the app and stop it. And the third one is restart the app. So the system does not completely fail if an app actually fails. Yeah, that would be it. I still, I think we still have 10 minutes for questions. I have a question here, which says if capsules are grouped together to make efficient use of interrupt signals from hardware, in other words, is there a limit of a number of capsules we can use related to the number of interrupt signals? And no, as far as I know, you could use as many capsules you want. You do have to make some changes. I mean, interrupts are sent not to the capsule, but to the lower level. If you look at TokoS image, interrupts are in this orange part. So whenever hardware has an interrupt, it goes to this orange part. And this orange part sends it to a capsule. Technically, you can have one capsule connected to one mini driver here in the orange part. But TokoS supports what we call virtual drivers where you have a virtual capsule that talks to the lower level capsule and distributes the interrupt to upper layer capsules. So yeah, technically, that's okay. I have another question. What about running TokoS and something like the Raspberry Pi? We as the group in the Polytechnica are already working on this. We're trying to port it to Cortex-A. Technically, it would work. It means we need to add the chip and memory protection would be probably different. The first step would be to use simple memory protection with one-to-one mapping. And then, yeah, it should work. So probably in a year it should be okay. Sorry, I'm just seeing a static screen now. No demo. I don't know. This is something technical. Somebody said I would be interested in doing it. Okay. Sure, that would be really, really nice. So let's talk. If you can talk to us on Slack, that would be great. And I think I can reply to you. You have my email on the website, so just send me an email. That would be great. Yeah. Oh, I'll write an email. I saw your email now. Okay. How can you upgrade one app from multiple applications like Blink and Display? Upgrading an app. That's a little bit tricky. So for now, apps are located on the flash one after the other. So if the upgraded app has the same size as the previous version, that would work. Otherwise, yes, you would have to move the other app further on or closer to this one. But this is a work in progress. So the Tokai design team is thinking on how to improve this. For now, apps are just located in the flash one after the other. So upgrading one of them is difficult if that one app is not the last one. Okay. I don't know. I think I answered most of the questions here. If there are any other questions from the audience. Thomas, I'll write an email. Okay. If there are any other questions. I think we should wait because, yeah, there's another question. Nice work, guys. Thank you. As I said, we're not the main developers. We just contributed and played with it. So there's a big Tokai team working every day on the Tokai system. So we just contributed a little bit to the Tokai system. Okay. Alex, do you see any other question? Yeah. Thomas also replied, I would love to use with the Wasi WebAssembly. Yes. We are currently working as a side project to see if we can run WebAssembly on top of it. Yeah. Over Ross, that was the first try that way. I think with Wasi, we have the problem that we execute more. Sorry? No, no. Go on. Go on. So with Wasi, I think the problem was that Alex really tried the WebAssembly. The interpreter that we had, the executor, was technically non-dependent on the Rust standard library, but due to a bug in cargo, it would still try to link the standard library. So it was impossible for us to build it. Alex, you have more details on this, but... Yes. For the moment, there is only one module over Rust, which is able to interpret WebAssembly code that is not dependent on the standard library. And this one, as Alex said, has recursive dependencies on the standard library. So what that means is that it has a module which depends on standard library. And even if we specify that we compile with feature no STD, it still crashes. It's a cargo bug. And even in the latest cargo issue, it does not work. I tried the latest nightly version, and it did not work. What I think... Okay. Sorry. To answer Thomas' question about Node.js JavaScript, V8, that's a little bit big for what the microcontroller can do probably on the Raspberry Pi. It would work. But you can use Jerascript. So we tried Jerascript. It's a really optimized JavaScript machine. It's optimized for size. Fitbit is using it for its watches. I mean, it supports JavaScript 1.6, I think. And you can even write TypeScript and transpile it to ES5 and run it. We did this with Jerascript. The only problem is memory. But otherwise, it's working pretty well. Did you answer the question about how to upgrade one app from multiple applications like Blink and Display? Is that possible? Okay. Yes. Upgrading one is okay. If that's the last app, if it's an app in the middle, as long as it has the same size, that's fine. What you could do is basically pad so far the tbf file so that you would have space for further updates. But this is a work in progress. The talk question is working on solving this issue. Okay. Okay. And I don't know if we have any more questions here. Questions here. Thomas also added on which channel we will be on. I think on Slack, on the IoT channel. So I think you can just enter in the IoT channel right now. So I think it's two track Internet of Things. Yeah. Yeah. Slack IoT channel, yeah. Exactly. Okay. Well, if there aren't any other questions, I really hope we answered everything. Thank you so much for your attention. Once again, sorry if it was a little bit confusing or we made a mistake. It was 1 a.m. in the morning here. So thank you so much. And also, we hope that at least a bit of the demo was able to be seen for the person who did not did not manage to see it.