 Just so you guys know, I want you to try to keep the hardware in the kits until the second half. It's a little bit different. I usually run this a lot more time constrained, and I try to jump people onto the hardware, but I actually want you to try to pay attention to me. Crazy thought. Because the hardware is far more interesting than I am, and I'll completely lose you. The prerequisites included Linux, like the top of 100 gigabytes, like all this stuff in the brand. And other than that, you just talk to beyond about getting the hardware. There's Wi-Fi in here. It shouldn't be required for that. Believe it or not, I get to cheat. The hardware is more interesting than I am, so I'll try to bore you to... I was supposed to push this latest version of Akin-Kreidner, a Skunkworks thing. At this point, yeah, I just spent 90 states to allow me to just focus on it completely. Benefit for TI is obviously people's focus, and all the kids and everything, so they're all public. The basic structure, other big, picked up these boards, brand new, closer to the development of myself, exercising the bacon that takes mostly, and then take a step back and talk to what I expect. I consider and talk about the cool things that people have made out of Eagles for a week. Just get a lot of people to dive into the lab where you'll get started and do all the stuff that I did yourself. Questions about, if it's possible, how many of you have already done good Linux before? Good, has a top Linux, makes money, foundation. So you make it, you want to call that. And where a lot of our community sits around is industrial automation type of task. Some meet a lot of people that do, that build a lot of industrial systems and stuff using. So, inspiration about how we want to go about that comes from my own personal, what way back when, when I got into a computer, in front of that computer, and you know, the life of things that you could do on a computer, it was all extremely hackable. If I could do anything I wanted to, except take a sledgehammer to it. Or she didn't actually want me to take a screwdriver to it at that time either, but you know, that came later on. But you know, because she could take all of her important stuff and put it away in the safe, I'm gonna miss work by using that computer. So, want to get inspiration. And for me, I got into, I couldn't use the computer without typing in programs. You actually had to sit there and type them in in order to get the computer to actually do anything. So I wanted to play a casino game and I had that sort of osmosis here, typing these things in. Oh, I understand what some of this is actually saying. Just some of this, the odds for cheating at all the casino games. And you know, my dad never knew one. I was always winning. That's because I changed the code. And it really got me going about computers, all of my video jacks, following these. So I want to try to, what's reproduced for other people of any age, but in this, so much to learn now, right? You know, they don't use computers anymore, right? They teach them how to use office programs. And you know, it's using computers and not actually understanding anything about how they actually work or what they do. And there's a lot of ground to cover and a lot of intimidation factor. But we really choose to focus on Linux, a lot of which because of the way it's maintained. I think a lot of you may know it's maintained with this thing called Git, which keeps all the version history. Every time somebody makes like a line of, a change in a line of code, it's documented in the Git repo as a patch. And so we can go back and explore all that history. And it's really trying to understand where all these things come from. Having that documented history is a huge point of building understanding. So we can understand about elevator algorithms. You know, why do people introduce new ones and on all the crazy fun things that make up an operating system and really make up modern computing. You really want to understand computers as they are today. Making things affordable means that it's hackable, taking out the critical information that you can't live without. Somebody crashes the hard drive, making it where you're not scared of breaking it. It's replaceable. Making sure things are open all the way from boot. If you're attending all the different talks, you're gonna be doing the run, actually compiling the boot loaders and actually building it from mainline open source. Boot loaders right from the very beginning. You can understand things very early in the system. Getting to high level languages, I think is really important for building understanding. I really like what a lot of people are doing with microcontrollers today. And it's interesting to see some of them actually start to integrate high level languages in the target. But the nice thing about Linux is you basically, whatever language you want, it's there, right? If you want Python, if you want Ruby, whatever that kind of fits your cognitive model that you can be productive in and understand, you can approach it with that. Still straight, if you're doing anything embedded, learn C. How many of you have programmed in C in the past? Yeah. So, you know, that's the language you have to know, but the others are important and useful as well. Some of them. And to motivate people with hardware, right? It's hard to compete with this idea of halo. Or like if somebody wants to create an application today, they're doing things on just their desktop computers, right? They see very, very rich experiences that are very, very hard to reproduce. It's really, augment, yes, there's some great tool engines and stuff that kind of help, but it's hard for them to sit down and create their first program and have it be halo. Where it's not so hard for blinking in LED, or maybe turning a motor, starting to get some things, interactions of the physical role to kind of be that drug that hooks people on to computing, so they want to understand more. Sort of vision is to try to get things as simple to play with electronics as creating a web page. It's a company, how many of you have written HTML? You know, it's easy. And we'd like to try to fill in enough gaps so that making with electronics can be that way. One of our big beliefs about starting a Beagle, for us it's just kind of, being on somebody else's platform, I think is an important enablement for us. You know, yes, we can put apps on our computer or apps on our phone, but it's really somebody else's platform and it's got a multitask and all the things that it's also supposed to do for a phone, whereas if we make it an embedded appliance, we can really dedicate it to the task that we want it to do and not have it be distracted with other things. It can do what we want, where we want, how we want it, and we're in control. So I think that creating apps is great, but better to create an appliance that actually makes the technology more welcoming in your life rather than an extra distraction or an extra burden. And to do all of that with open source as the catalyst. So open source helps enable collaboration on what's a pretty big problem, I think, when we look at what the scope of Beagle board is trying to solve, we're not gonna solve it ourselves. So collaborating on the problem of making embedded computing easier, making it more complete in what you can do, and it allows people to come in, by doing everything and very much in the open, it allows people to come in and kind of understand where you're at and get engaged and improve on the basics. Everybody can make a difference. So hopefully we're gonna recruit many of you over the next three days. Yes? There are github.com slash e-a-l-e, and then it's flash slides. If you go into there, there's each of the different presentations, there's slides, so this is the Pocket Beagle presentation. Are you doing USB sticks? I don't know if it'll have the latest. Okay, so these slides will be on the USB stick. I think, I hear myself on the microphone now. Who would do the audio here? Is Tom walk out? No, they're complaining about a buzz. He turned up my game. Maybe I should move the mic closer. Sure, but yeah, if I'm louder on the mic. What's the Wi-Fi? Pasadena is the password, there you go. All lowercase. So that's kind of the vision, but we're still a ways from saying that making with electronic disease is making a webpage, right? And there are things that we could kind of try to jump to the end point a little bit to try to make things closer, but not far enough along to say, like if we want to just boot to the browser and kind of make that be the user's experience, it's just too limiting for people today and there's too many places where the people that we're collaborating with are moving in different vectors in different, different places. So instead of just doing, jumping to a developer solution, here's your ready prompt, right? On this computer, we boot into to Debian, right? So we've got a huge community of people helping to advance the state of the software and a lot of different ways. And actually doing like making the programming itself being collaborative, there's a lot of different projects that have tried to create examples on like user space interfaces, all these sensors, right? So a lot of the problem we're trying to solve is being able to control motors, read sensors, talk to different things. There's a lot of different places where people kind of go off and do some of the stuff on their own. The place where there's really great collaboration, the place where we can actually all really work together is the Linux kernel, right? It's very organized. We want to talk to a new device. A lot of people have this instinct to go and create a user space thing that goes and talks to it or to otherwise kind of find a way around it. But if we put it in the kernel, we all have it. And then we have it on every platform that Linux runs on, which as you know is massive, right? So rather than trying to make a Beagle library to go and talk to different sensors and motors and different things, where we really are successful at collaborating is when it goes into the kernel. And as we get into some of the programming details, you kind of see some of the hacks and trade-offs where you kind of do some stuff in user space and kind of do some stuff in the kernel. And there's really not one amazing development environment today for what you want to do because a lot of it serves to get really the main specific pretty quick. So some people are really happy with Command Line SSH for doing development. I happen to like the Cloud 9 IDE. It gets me into the browser where I can actually run VI in my web browser. But there's Node Red, there's Pure Data, SuperCloud, all these graphical programming tools, LabVIEW, MATLAB. But all of these are possible to do with Beagle, right? So these are all different ways that you could be doing embedded development. Scratch and block leave, more about learning, but potentially you could make some physically interactive things even with high-level graphical programming tools like that. And the different, the domain-specific approaches, so we find a lot of people in our community are going and they have other distros or other things focused on what they're trying to do, like machine kit is a mill controlling. So people use it for controlling mills but also things like laser cutters or pick-and-place machines. And things like there's different PLC software frameworks so people doing this latter type of programming is something that a lot of people know in an industrial control system. So people have like toolkits for that. And then when you look at like how to actually do the physical interconnect stuff, there's a whole bunch of different approaches for that. The add-on boards for BeagleBone are called CAPES. We're kind of leaning towards calling the add-on for the Pocket Beagle Pocket CAPES, Mini CAPES. And then, but there's all sorts of other standards like Microbots we'll talk more about. There's the Grove, which is this four wire connectors for I2C and URs and GPIOs and analogs. There's PMOD, which has a bug, right? There's dozens and dozens of these out there. And then there's like when you start trying to build up all the other stuff around it, there's a whole lot of different approaches. So those are kind of some of the barriers that kind of keep us, you know, from kind of just like solving the problem as a whole, trying to give one a single point solution. But we don't wanna try to go and solve all of those problems ourselves either. What we wanna do is try to engage developers that's in the open source community to go and try to address all those needs. We try to get engaged where we really think we can help. We work with seed so that if you have a BeagleBone Blue, they have little adapter cables. You can directly connect the Grove connectors to the connectors on the BeagleBone Blue. There's pass cables for that. We made Pocket Beagle so that you actually, the pinouts are such that you can place two micro bus clicks on it. And there's over three, so each of these has like, you know, hundreds of different add-on things that you can censor and control that you can add on, either the Grove system or the micro bus system. The Pocket Beagle, you can connect those directly. And then we have a growing ecosystem of people making derivative hardware and actually like working with us to make sure our software images run on that target hardware so that people have a common developer experience and kind of take that to different platforms, things like the BeagleLogic, which is essentially a logic analyzer built around a Beagle. There's a new 3D printer controller coming out called Revolve that should be launching later this month. That's based around a Beagle, but has all the stuff for doing machine control for 3D printers or mills. Integrated into it. So that's kind of how we generally try to approach, there's some of the things that we do to try to approach the problems that we're trying to solve. And so back in 2008, we started the original Beagle board and that was $150, our goal was to try to get it down to below 100, so we managed to do it at 150, and then we updated it with a higher speed processor in 2010 with the Beagle board XM. Also in 2000, I think it's 2011, we launched that white board, which is the Beagle bone. And that one was launched at $89. And then the Beagle bone black was launched in 2013, and we were able to get it down to $45 at initial launch. And that was really the big difference was getting from building in batches of 10,000 to getting our first order for 100,000 boards. So what really helped us right there was the launch of the Raspberry Pi, which built a lot of attention for single board computers. And so it actually increased the demand for Beagle bones quite a bit. We've taken the base Beagle bone design, we worked with a company of table systems to put the bulk of it into a system and package, and we were launched a Beagle bone black wireless at $69, and fortunately it's a little bit more expensive, but it has the wifi built in and it's using the SIP. But we took that base design and we integrated everything that you need for robotics control and then created early last year the Beagle bone blue. And it skipped in actually 2016, we launched the Beagle board X15, but it wasn't until kind of mid last year that it actually started being available in quantities. So that's the really high end board PCI Express, it's got data, it's got two gigabytes of RAM, it's got a dual gigabit ethernet to USB three on it, so it's got all kind of the everything in the kitchen sink thrown in there. So we've got that as kind of our desktop replacement line, like Beagle board is a kind of like fanless, low power desktop replacement style to get you kind of into embedded development. And the Beagle bones are in this mint tin form factor, so it's all the sides of an outwits mint tin and maintaining that form factor with the cape support. So we're also doing some things specifically on application areas where we see a lot of users like mobile robotics, it's a huge application area. So we put the motor controllers in here, battery management, so that there's Wi-Fi and Bluetooth, and there's sensors on here, so it's got the accelerometer gyro, compass and everything that are all built in there. That's a ready to go flight controller, essentially. And then the new cool fun thing is the pocket Beagle. So again, working with the folks at our table on the packaging, they took it down from a 27 millimeter package down to a 21 millimeter package, and we just stripped everything away to make the pocket Beagle. So, what were our objectives with making the pocket Beagle? We wanted to get it a lot simpler. So actually leveraging how much stuff is inside that system and package, it actually makes creating a Linux computer really easy because it's almost all integrated. Essentially, you could probably dead bug one and make it run because all you need is a crystal, power and power can be very pretty flexible because it has its own integrated power management. So you could take a LiPo battery and just connect up to it and a crystal and you need some sort of boot medium, right? So you need some way to feed it data. It has a lot of, you need to kind of bootstrap the, the, there's pins that set what the boot mode is, to be able to pull those in some direction to tell it what boot mode it is and it's gonna go off-chip to try to fetch its code to run a boot and that's all you need. It's got the RAM integrated, it's got the power management integrated processor, all the decoupling caps and everything you need. So we wanted to try to make pocket Beagle really leverage that simplicity and demonstrate that simplicity. Make it something where people can actually take it and really modify the design, right? Really open it up to having a richer ecosystem of people making more targeted things like the 3D printer board or the Beagle logic. And the, we also wanted to simplify the user experience. One of the biggest headaches for users with starting with the Beagle loan is it's too flexible. And so what I mean there is the, each of the different pins on the header, there's a pin mark. So each of the digital pins can have one of eight different functions. And in order to set those functions, you may have to write a little bit of device tree code or mess with a bunch of scripts and all of the instructions have kind of changed. So it can be complicated to start doing that IO because it's, you know, the defaults aren't well known and so you have to kind of try to work your way and to try to get it configured the way you want it. So with the Pocket Beagle experience, we put right on the still screen and said, okay, this is the function that's gonna boot up and run at startup and you could just start interacting with it. So we kind of predefined the functions. Yes, you can still overwrite them and we'll overwrite them here in this class and change it so it's still flexible. We wanted to try to make it as simple experience as possible. I really wanted to try to improve the flexibility. We put USB on the headers now because that's a nice way to do a lot of expansion on board. Signal integrity, you know, when you go across there, it can be a challenge, but we've not had any real issues. You know, a lot of people have been able to successfully make USB connections on add on board or Pocket Cape. And you know, one of the other challenges with the BeagleBone Black was that we reused between the original BeagleBone and the BeagleBone Black, we used some of the pins on the header actually on the board itself for the LCD interface, for the HDMI interface and for the EMMC flash that were both added between the white and the black and that meant that you had to disable those in order to use those pins. When nothing on the Pocket Beagle is actually consumed on the board, they're all free for you to use in their mode. So no on-board board consumption. And we also didn't put the header on there by default. All your boards are gonna have headers soldered on them, but if you buy a board, it won't have a header on it. It'll be just the bare seat. You can put the headers on top or bottom or even if you wanted to, you can solder it directly onto another PCB. You can actually just reflow it onto another PCB without even a header if you wanted. I mentioned adding the support for the two-click boards that the pinout and the spacing is such that you can place two clicks onto those boards and I'll show off some of those later. Stuck with the Mint 10 theme, just went from the large Mint 10 to the small Mint 10. We have my, so now we've, so the Pocket Beagle is in the size of this Mint 10. That's where it gets its form factor from. Because this is, I don't know if you've seen survival kits built on the Mint 10. So the theme here is that computing is a necessary part of survival. This is part of, this is your survival kit. So this is something that goes in your survival kit. And we try to get things down low as cost as possible. There are a lot of cheap Linux computers out there. There's a lot of cheap Linux computers out there that are sold below cost. Pocket Beagle is not one of those. Everybody in the chain makes a little bit of money. Yes, we don't want them to get too greedy, make too much money. Yes, but if it's the end of the day, if they're not making money, they might stop making it someday. And I don't want that to happen, right? We're built for longevity. So the price isn't gonna go crazy. It should stay around that $25 point for 10, 20 years. So people can actually choose to use that, create courses like this and use them and reuse them for years, things in universities and things like, we wanna make sure these are available for everybody. And if you decide to create some training, you're not gonna be wondering how am I gonna get boards now because they stopped making them because they weren't making any money out of them. So this is sustainable. It's not you go into, yes, Micro Center was selling them for $20, but that's not where it's at. So, but it's not that you go places, you can only buy one, maybe you're familiar with another Linux board out there, you can only buy one of, unless you buy the $70 kit. Anyway, key features, it's a gigahertz ARM Corechecks 8, 8 processor, so it's ARM V7, still 32 bit processor. But it runs at a gigahertz, it's dual issues, super scalar. It's reasonably quick. It's not gonna blaze new trails, but it is far exceeds what you need for most embedded industrial type of applications. The really cool thing, of course, that's kept this processor around for a really long time is that it's got these other micro-controllers in it. The two 32 bit peer use are really, really powerful and flexible, they give you single cycle access IOPEN, and they don't have any tasks that they're doing while you're running Linux, they're doing whatever they're supposed to be doing in hard real time without distraction. So they're there, and a lot of people forgot really fancy cool ways to do things with it, they create other types of protocols that they implement, soft peripherals. They get them to do a whole lot of stuff. I need to speed up a little bit. There's a Corechecks M3 in there as well, not a lot of people program it, but it's there for power and security. You could do all sorts of other things with it. It's got 512 megabytes of RAM, it's got USB and a whole boatload of stuff and the expansion connectors that we'll talk more about. This is what the Pocket Beagle looks like. There's a couple of headers, you have the Boot Medium off the Micro-SEE, I talked about the Boot Config on there before, those are the resistor packs that tells it what mode to come up in. There's the clock, the crystal. There's a power button, so if you're power up off a battery, you actually need to press the power button to tell it to come up. If you press the power button while it's running, it creates a system event to tell it to shut down. So it'll be shut down gracefully. If you hold the power button for 10, 12 seconds, it'll do a hardware shutdown. So the PMIC that will detect it if it tells long enough will actually shut down directly rather than waiting for the software to do it. The USB is on the go. There's four user LEDs, a power LED and not a whole lot of other stuff. There's no backside component. So it's all one side assembly. This is what the backside looks like. I mentioned earlier about the silk screen defining the different functions. You'll see things like, here's my spy port. It's got chip select, clock and everything. There's another one. I will mention that which chip select isn't actually noted there. It happens to be chip select one on spy one and chip select zero on spy zero. If it's meant to be a GPIO pin by default, there's the GPIO, the eternal GPIO number. So you can just directly reference that there. The UARTs are used and their port number and the transmitter C pin. There's analog pins on here. These are all 1.8 volts noted right there in the silk screen. There's a couple of analog pins that have resistor dividers and are connected up to GPIOs as well to do 3.3 volts. Part of that is to provide the micro bus compatibility since it needs analog and GPIO and 3.3 building on the same pen for some of the clicks. There is a mistake on the silk screen. That actually should be GPIO 44. My fault, bad email. Same reason you don't have USB hubs, bad email. Anyway, this is more the detailed view kind of showing some of the more useful things. Each pin actually has eight different modes, but I think we've summarized the most critical ones to just looking at three of the different modes for the pins. So the analog pins are dedicated but there are some other pins that are more flexible. Like if you wanted to use a quadrature encoder, it's available on like quadrature encoder two is available. There's the A, where's the B for, here's the B for quadrature encoder two. You can do hardware pulse counting. If you want feedback for motor position, there's the PRU pin that has the ultra latency. The PRU can actually access either way directly through its GPIOs or through, it can go through the on-ship peripheral bus and actually connect all the GPIOs or all the peripherals for that matter as well. Ethernet is not brought out. So that's not broken out at all on the expansion header. Part of my thinking was that I wanted to reserve it so that if we did any derivatives, I wasn't making, potentially having people consume those pins on an add-on board. So none of the like the EMMC signals were largely not brought out. So if we wanted to do a version with flash, we wouldn't have to break the header compatibility and as well as the Ethernet signals, we wanted to use those for something else. So I avoid bringing those out. I can't flip the slides, oh, slow flipping slides. Okay, it seems to get stuck on that slide for some reason. So this is the basic pin out of the micro bus. So this is from the micro bus standard. You can see that it's got an S5 port, an I2C port, a UR, PWM analog, all these things as they're kind of their standard to announce. There's over 300 different boards that match this configuration. And the way we did the headers is it mapped out to two of these on our pin headers. So if you look at the inner rows on each side, those directly map out to micro bus. So you can put one click on that side and one click on this side. They're both, they're done from the top. Some debate whether or not we've, some thought of whether we should put them on top or bottom and looking back on it, maybe I'll probably would have flipped it over. But my sensibility at the time was to keep all the components facing the same direction. So bacon bits. So that is this add on board. So I have one of the kits. It is a pocket beagle on the bottom and a bacon bits pocket cape on top. That was designed specifically for this class. When did we start this development? Like maybe Michael, you, so Michael back there designed the pocket, the bacon bits. When did you get started? Like eight weeks ago, six, eight weeks? Yeah, so maybe five, six weeks. I picked up the board Tuesday. So, but this is all done specifically for this class. We started looking at like, okay, we want to wire this up and that up in order to talk about these all the different types of interfaces. It just looked like it was gonna be a lot cheaper for us to put it everything on a board and build it and you wouldn't have to worry about loose wires running all around. You should be able to plug it in and go. And that was essentially the same concept as the bacon cape that's set on the Beacon Black that Dave Andrews had designed. So the name bacon bits was discovered. And bacon also came from another board that was called a beacon. Which is just, you kind of gave you something really quick to just hack an RGB LED in order to start learning some embedded Linux stuff that Dave Andrews had designed. And then when he wanted to come up with something a little bit more complete as a cape, he decided that, well, dogs love bacon. So, it's the bacon cape. And now we have the bacon bits. And so it provides us a common target for talking to all these different cool buses and avoid buying a whole bunch of different modules. So these are the key features. It includes the USB to zero. So you can see the boot console. So you can even see things that are coming up your zero, right at boot. It has a USB host port on it using the USB on there because we don't have that host port built in to the pocket vehicle itself because we reserve it for expansion. It satisfies it by bringing a USB host port. It remaps, so it also brings out the power reset button so you can do a hardware reset. And because the cape covers up the power button, it also puts the power button on top so you can reach it. Thankfully, it goes to the header. There's also another, there's a third button, which is the GPIO push button. It's the one, when you get your board, it's the one closest to the seven-segment LED. So that's the one you wanna hit. It's the one next to the seven-segment LED and not the other two. Otherwise, you're gonna have to wait for your code to reload. There's a thumb wheel on there for doing interactions with ADC. There's a tricolor, a big tricolor LED that's currently going blue for me that is connected to PWM pins. So you can learn about PWMs. There's the seven-segment LEDs are controlled by a spy device so you can learn how to do spy. And then there's an accelerometer connected up over I squared C. So you get to learn how to do all of those different interfaces with this one board. Cool? I've got some stuff in here in the slides that I think is gonna help for some reference. But I'm gonna kinda go back and forth with actually showing you some of this stuff working. I think I'll actually just do it right here rather than... So this is where the GPIO button is connected. It's connected to P233. It's got a pull-up on it, which is really not necessary because there's pull-ups within the processor. You can turn those on and off, but it avoids you from needing to configure it. So if I go to... I'll show you later how to get into this, but I wanted to just show you some actual live interactions with the board for each of these different interfaces. Let me hide the rest of this stuff for now. So just say that I'm logged in, right? Because I happen to be using my web browser. I'm now logged into the board. There's this tool called config10. We said it was P233. So I can use configPIN to give me some basic information about that PIN. Are you asking me a question? Well, it depends on that amount. I mean, it's designed to handle that amount of current for sitting at them. I wouldn't drive more than five milliamps. I wouldn't make your design do more than five milliamps on these IOs. So if you just think about it as that, that's kind of where I put the limit. Left edge. Good? All right. So P233 is where the button is placed. I can see that. So I can go to, in Linux, everything is a file. And that's an exaggeration, but part of what the kernel does in terms of abstraction is it gives you some standard interfaces. Read, write, control, and IOC dole, right? They're kind of how you talk to devices. And those things can ultimately map to the directory structure so that I can read and write these devices just through virtual files. So SysFS, have you ever heard of SysFS used to SysFS? A bunch of you haven't. So SysFS is a virtual file system. There's nothing sitting on my disk itself. It's not on the microSD card. It's just something in RAM. So I'm only talking to the kernel by talking anything to the Sys directory. I can get a list of some of the different things that are mounted. So some things when I get mounted in locations. In Linux, there's a single hierarchy for a, like there's a single root hierarchy for any environment. So like there's one, in any place, there's only one root. There's only one slash. And everything builds on top of slash. So mounts tells me like what is going on top of slash. So, and also tells me what slash is, right? I can find, should be able to find the root file system somewhere. Here we go, dev. So devmcblock0 partition one is my root file system, right? That's the disk that I'm actually running as my root file system. And it's mounting other types of things on that. I've got a SysFS entry that's handled by the kernel mounted at slash disk. Anyway, so that's just talking to the kernel. When I read and write these files, it's not actually touching the disk. Like, so it's not having the kernel talk to the disk, it's having the kernel talk to other hardware. So there's a GPO class, a Sys class GPO. And we saw, let me do this config pin thing again. So config pin is a purely Beagle specific app, but it gives you some useful information about the different IO pins. And here I'm just using it for quick reference, right? So it's telling me that the kernel GPO ID is 45. So I need to kind of map those two together because I was looking at that location. So inside of that directory, I'll see a number of other files, including direction. We should see that direction is in and I'm not pressing the button. Anybody guess what the value should be? Okay, I didn't hear anybody said zero. You're right, one. It should be one. That's what we got one. Good. So that's because of that pull up, right? So the voltage should be sitting at that 3.3 volts. And then when that reads over that IO pin, I'm seeing that the value is in fact a one. Now if I press this button, that should ground that pin, right? So it's shorting the connection between the IO pin and ground when I'm pressing this button, right? So it's a normally open button. When I press it, it closes it, it shorts it to ground. The voltage should now be zero. Voltage should be zero and the GPO value will read back back to zero. Yay, we're at a GPIO. You had your first hardware, you know, real world hardware interaction. But that's pretty significant, right? And Linux makes that really easy by turning everything into a file. The hard part, right, for us was just mapping the numbers, right, figuring out what the IO pin maps to actually into the software. So GPO 45 into the Linux kernel. Well, that was easy. Let's try a little bit harder one. So this is the thumb wheel. I mean, if I'm doing my demos, I wanna do one other trick because this is gonna help me on this next time. I wanna introduce you to this program called watch. So watch is just going to continuously issue this command over and over again so I can see, so the command I want it to do is value. So watch is gonna clear the screen and run this command every so often. I don't know exactly how often, I don't remember, it's like every 0.1 seconds, apparently. So every 10th of a second, and it's gonna keep running that read the cat. Cat is the program that's just reading the file. And so you have your familiar with Linux, I don't have to say that, but now if I press the button, it goes to zero, I release the button, it goes to one. I wanted to do watch on the GPIO because when I started doing the analog, it gets to be more interesting. All right, because we're gonna be changing it constantly. Now this one I'm just gonna kind of jump, there's, where that happens to live is in the subsystem called IIO. That's the, it's literally the industrial IO subsystem in Linux. So analog to digital converters, a lot of the sensors, a lot of those things live in this IIO world. So a whole lot of things are gonna come up for you in IO. It's a really interesting subsystem to learn more about. So I'm gonna look at what devices are in IO, and I'm looked at, I only have one. That's my only, my only IO device currently installed. I look at the directory, and it looks pretty straightforward right, because there's a number of different in voltage raw signal or file. Now I think that's a little bit of a misnomer. Just so I put in a little extra note in here, connected to P119, that happens to be AIM-0. All right, so if you looked at the header map, this one I don't have a nice, maybe config pin might tell me that actually. I don't know if config pin will tell me that. P1, was it P119? Oh it does, it tells me it's AIM-0. So config pin would have told me this anyway, but I actually put that one on the slide. So that's zero. So the one I wanna look at is in voltage zero raw. Now I think it's a bit of a misnomer, because it's actually just, right now what the driver's doing is actually giving it the 12-bit A to D. So you have a 12-bit number going from zero to 4095. At 4095 you're at 1.8 volts, at zero you're at zero volts. So you just divide by, the division to convert the scale to 4096. So 4095 being the maximum value. So if I, obviously I don't wanna sit here and turn that. So I wanna just do watch, run that watch command. I don't have to keep typing every time I wanna see the value change. So now I can turn the scroll wheel. So I'm gonna turn all the way to one way, 4095. Turn the wheel all the way the other way. We'll watch it changing as it's going. And it goes down to zero, right. Cool. So now we've done the ADC. Questions? Is this the type of stuff you were hoping to see and learn a little bit about? Yeah? Hope I'm getting into the meat of stuff right here. That just, if it's not I'm concerned. If this isn't the meat of what you really were hoping to see. Now this one's a little bit, again a little bit more complicated, right? So the last two have just been inputs or just reading a file. There's an existing driver handling it. Here there are drivers for the RGB LED. But just sit there and try to poke everything at the command line. There's a whole bunch of different steps. And if we wouldn't allow this, we'll try to spend some time. I'll actually try to walk you through some of all those individual steps that go on. But I'm gonna jump up to JavaScript here. And I don't know why I have that one before. Oh yeah I do. So these are the labs that are checked in during this EL code. PWM, there we go. I don't know if my font's readable back there. Not, can you see the screen at all? That's too small, I'll make it bigger. So here I'm gonna use JavaScript. And all of this is still just doing essentially the same stuff that I was showing you. Peek and poking, reading and writing files. But here I'm just using JavaScript to do all the reading and writing of files for me. And it kind of understands some of the different things it has to set up in order to actually enable the PWM. And there's actually a bug in my code as well that we get to see. So this is my program. I'm gonna actually run it from the command line. So it's in, I put it in the EL, there we go, EL code. And it's in the Resources Pocket Beagle when you go and look at the GitHub. So I'm gonna use Node, which is a JavaScript interpreter. Everybody knows from the command lines, the first word is just the, I don't have to tell you how to use that. So Node is the interpreter that I'm gonna run. And PWMJS is the program, so it's this program. That program is going to set each of the different pins to be analog outputs, which is just terminology for a PWM. And then this analog writes function. This analog writes function takes first argument as a pin. The second argument is a value between zero and one to say what the duty cycle of the PWM output is gonna be. Now the first time I run it, I think it should fail. Cause there's a, what has to happen is when we have to enable the PWM, initially it's permissions come up as root only. And I'm actually running this as the Debian user. Did it just work for me? Oh, it just worked. How beautiful is that? So initially that it comes up as a root user. So we've created a Udev role. How many of you know what Udev? Some bunch of you aren't. So Udev is a way that the kernel can notify user space of device attachments. All right, so things that have changed state. So it can notify user space so that you can do things like run script. And so what we've set up in the default distro is when the PWM devices, when you enable one and all the other stuff shows up in the SysFS directories for it, it all comes up initially as root. We have Udev role that actually runs a script to change the permissions to make it accessible by Debian. The JavaScript code doesn't have a good point where it waits for that. So it'll try to go and access the directories that are supposed to be created. And sometimes the first time you run it, they're not available, they're not accessible as the Debian user. So that's just something to be aware of when you're running these little JavaScript apps with the PWM, that there's a bit of a race condition because that Udev role has to run to change all the permissions so that you can actually get access to Debian. That kind of makes sense? Okay, in the labs, we can kind of dive a little bit deeper into it. Actually, I'm over my time from beginning of the lab. Are you just waiting? I'm gonna wrap this up real quick. I'm gonna do a couple more interfaces that I'm gonna show you and then I'm gonna turn it over to you to actually do some hands-on and I'll show you how to get started with your board. Let me just do a couple more of these before I flip it over. I will notice that, I will note, that Michael, I'll point this out to you live here now, the red and green are swapped. So because a different LED was used in what shows up on the schematic, red and green are actually swapped. So just be aware, found that out in writing, actually writing code, yes. Why is there PWM red and PWM red alt? The, we had some debate in making the board whether or not we could just use those microcontrollers to control one of the, essentially, one of the levels for the LED because I wanted to try to save that pen to make the, we could still add a click board. But we, anyway, we did it without being clicked board support because we, the non-alt is a hardware PWM. The one's actually being used, let me flip back to the slide so I can answer your question there better. The one is actually, you see, there's a no-pop on the alt. So there's actually not connected. So the one that's actually connected is the one that's on P2, pin one. That pin happens to be used by the micro bus header. So it prevents you from being able to use a connected, a click that uses that pin. So we just built it as a, so Michael just added it as an option, but it's all populated so it's just the red one that's using. So there's also a seven-segment shift register. So similar to the way everything else in Linux is exposed to this file, there's also this thing called spydev. So here's where all the different pin connections are. So this thing looks like a spy device, an SPI device, and the protocol, the wire protocol is essentially a data bit per clock. So you'll have a clock that goes up and down and then you'll provide data out on the pins. The MOTI and MISO terms, that's master out, slave in, and master in, slave out. That's the direction of the data line. So there's one data line going from the processor to this device, and there's another data line coming from this device back to the processor. We won't be using the return data line for this example, but we need to toggle the clock, and the chip select tells it that this device is currently active. You could potentially have multiple devices on the same spy bus, but each of them would need to have their own chips like to tell them when they're active. It also tells you when you're starting a command. So if you get to the chip select falls low, you know that you're actually starting and you're starting a new command. So I've got some more examples in here. I'm gonna show you, let me open spydev.out. So this is, the spy device, we don't have a Udev role to make it accessible by Debian right now. If you want to use spydev, which is the user space interface to the spy controller, then you'd have to run it as root. And so each of these different slash X lines, that's the commands that you wanna write to the controller. So you have to look at the datasheet for that spy device and try to figure out what that is. So the first one is essentially the address of the controller. You always put 40 on this particular spy device. The next one is the address within the controller itself, so which register you're writing inside that controller, and then the third byte is the data value. So the four different commands that I've got up there, the first two turn on the output for each of the different groups. So they're grouped in groups of eight. So the first one turns on the output to the first eight 10s and the next one turns on the output to the next eight 10s. And then the last two commands actually set the value on those 10s. So if this works right, I should be displaying the value zero, zero, because you set the IO 10s here to zero in order to turn on the LED. I know for one thing I checked in the wrong version because I didn't have this as bin bash, but best laid plans, right? So I've got a little bit of demo items here. So one of the things I haven't pointed out is what config 10 is actually doing underneath the scenes a little bit. If you, well, you could use config 10. So it provides information, but you can also use it to actually set the pinmux mode. If I did something like config 10 dash, let me query P225, it says it's in spy chip select mode. I can actually use it to change it as well. I can go config 10 and set it to GPIO, right? And the valid modes, the valid modes, you can get them with the dash i. So that's the list of the different modes that you can use. The way it's actually doing it is there's another thing, it gets exported to the sysfs entries, which are these pinmux helpers that we have loaded that we use to try to switch the different modes, right? So there are these files where the state of the pinmux is actually kept in there. A helper function, a device driver that we can use to change those different modes. So these functions are setting the different pinmodes. That number's wrong. Yeah, wow, how did this code get checked in? The chip select is 31, and that turned off in certain mode somehow. So a chip select is 31, s clock is 29, and most is 25. That will probably make a world of difference, and it did. I've now got my zero zero on the display, right? So I've now done a user space spydev access. I also have another example in here. We'll save that all for the lab. Let me finish up the lecture. We got another 10 minutes beyond, so for the break, you wanna do another 10, 15 minutes in the break? Yeah, that's perfect. When we come back, we should be ready to do the lab. Please come back, because now you actually get to play with the hardware. Yeah, yeah, I will, absolutely. I'll do that right now, actually. It's the one called Pocket Beagle. Straight from where? SSH? Yeah, you don't have to go to, you don't have to use the ID. Yeah, it just gives you. Oh, where'd that file go? Hmm, sure. I just saved it, exported it, and I don't know where it went. That's probably not good. Okay, we put it in the right direction. Oh, that's really wonky. Right, that's what we're having trouble with. They were far from perfect. No, it's great. No, that's not good. No, no, it's the opposite. Oh, you're right, okay. I just be responsible by forcing it, is that the? I don't know, I think Tom was trying to make a point, but I think you just made your point. So, yeah, basically, it should work. Okay, cool. Yeah. Basically, it's a drill pin, drill pin, right? What's the meaning of that? It's offering you some pre-downloaded files. No, no, the disk should be all set up and ready to go. What's the stuff for the lab? You need, like, Linux. You need to have Linux. I have Linux, yeah. Okay, and I don't think so. Okay. Yeah, you don't need a VM for this. If you have Linux, you can just run everything, install it natively. Okay. And I'm not gonna have you install any stuff. I think for the other classes, they will. Okay, thank you. Everything I'm doing is on the board, as well. Do you have anything built in to debounce it? Anything built in to debounce it. Like, if it's a different momentary choice, what's it going to be done? There's, you can do software debouncing in the Linux kernel. I don't think Michael put any, we talked about putting in, like, a cap or something to kind of smooth it out. It depends, yeah, absolutely. And it just depends if you need that clean of a signal. It's really, I do a lot of just GPO keys with zero debounce and with just regular buttons, I use the internal pull-ups and I haven't had any problem with just using that directly to generate key event. E-ALE, E-ALE. So why are my power not, why are? Well, is everybody back now? No, everybody is back. Everybody back and everybody have kits. Well, we're working on the kits now. That's what it is. Hi there. Yes, I know. Did you register? Pre-registered? Yeah. Okay, you then, the guy you want to clean. He's on his knees, or he's bent down in the back. Everybody who paid for the kit, yes, though, anybody? Anybody not have their kit, who paid for it? Okay, we got one person back there. We have one person right there. Okay, thank you. Maybe, well, they left their computers, so we think they're gonna be back for too long. Maybe when you're started, we'll catch them up. So inside your kit, I don't, I needed a slide for this. Inside your kit is the pocket beagle with headers soldered on, so it doesn't normally come like that. A bacon bit, mini cape or pocket cape. There's also an SD card that should already be inserted. That's also something that doesn't normally come with the pocket beagle, so the micro SD card is added to this kit. There may also be an SD card adapter. You'll have a baggie back behind with two USB cables. One for the pocket beagle, the other one's for the bacon bit. So you can interface this to your report. So as you talk to the debug console on the, on the beagle for this, we won't be using the second USB cable or the USB connection on the bacon bit, so we're only gonna be connecting up over the USB on the pocket beagle itself. So on the bottom board is the two stack. You don't wanna connect these things hot. There's a potential for frying, it's very unlikely, but I would encourage you, especially if you're new to hardware, to always power off the hardware before making any modifications of connecting up the board. USB, you can hot plug, it's designed for hot plugging, but for connecting the daughter board, leave it unpowered, connect it together. The orientation, I don't have a good orientation picture, but the micro USB's go in opposite direction. So the thing that I use when I'm connecting this to determine it, there's actually a silk screen on here that has the numbers one and one and two and those match to the numbers one, the number one on the headers on the pocket beagle. So that's how I figured out the orientation is just matching up the silk screen and lining them up. We can get started in things with just the pocket beagle, but if you wanna connect up the bacon bits, feel free. So the developer experience is a little bit like this. We provide, beagle board provides Debian Images, built by Robert Nelson, which you can get at beagleboard.org slash latest images or this short vanity URL. We do everything, we try to enable everything to be self-hosted. A lot of people do professional development, a lot of different ways, cross-building, you know what you're gonna learn, a lot of cross-building and the rest of these days, but for the rest of this class itself, we're gonna use the self-hosted tools. There's tools on there for both the arms, both of the arms, the A8 and the M3. We won't do any M3 code and the PRU. And there's libraries for the various high-level languages. The maintainer of the Python, Adafruit underscore BBIO library, which is the general Python libraries in the back wearing the purple shirt works at Oshpark, Drufasini. So if you have any questions about the Python library, see him. If you have any questions about the JavaScript library, see me. If you have questions on Go or a billion other different languages, there's other people. There's scripts for doing a bunch of common tests. We're gonna walk through some of ops scripts and then there's sources on there if you're going to ops source once you're logged in and there's servers running on there for getting access. So again, the way we look at doing development here is a single cable that that USB cable is gonna power to provide a network connection as well as giving the interface for developing. I know it's been worth it to switch into PDF. But you can of course add network and a whole bunch of different ways and get untethered. So normally I would say the first step is to download an image. So in addition to the two USB cables, you also have a USB to SD card adapter in there. That's what allows you, you're gonna plug it when you don't have to do it today because the SD card's a pre-program. But when you go home, you wanna get the latest image. You go and download the image off of, this is the latest images site. Then you use a tool. I like Etcher with Linux. You can also just do DD, which is a block by block copy of the image, but you need to uncompress the image first. First of all, I just teach people use Etcher kind of all-in-one. It helps try to prevent you from overriding your own hard drive with the image. It won't expose your hard drive as one of the options to select. With DD, and you have to run it as root, you can very much do that if you specify the wrong disk image, you're overriding your hard drive and while your host computer won't run anymore. You lost it, so bad news, don't do that. Use Etcher if you're at all squeamish. And it takes the compressed images and it writes those to the SD card itself. And then once you've got that SD card programmed, this is where we're actually gonna actually start doing the steps together, right? So the SD card is actually inserted. It's okay to plug in your pocket beagle. So one into the USB cable into your computer, the other into the pocket beagle. And with or without the cape, the bacon bits connected because it's useful just to get into the ID and kind of poke around with some of that stuff first. You can always unplug it. Some people always do a soft shutdown to make sure they don't have any corrupt files. I always just pull the power. It's an EXT4 file system. It's pretty robust. I almost never have any, oh, I've never had any problems. I'm only occasionally to hear problems of people corrupting the EXT file system. And so I would just pull the plug when I'm done. So you can always pull the plug, connect the cape and reboot it. But anyway, we wanna get booted up because what we wanna really solve in here for you, that's kind of the first real lab problem for you to solve is to connect up to the USB network. So the way this whole thing looks is it looks over the USB connection, it looks like there's a network device on the Beagle and there's a network device on your computer. So that's what it looks like to your desktop computer. So when you plug it in, it's gonna think that you've connected a network device. So it'll have an adapter and it's gonna try to say, oh, well, it's plugged into a network so I'm gonna do a DHCP request in order to try to get my IP address. That's what your computer should normally do when you have a new Ethernet adapter. Some of your computers may not be configured to do that automatically. So that's where having this nice interaction point is good because we can look at your system and say, okay, let's tell it to actually go in DHCP on that new adapter. And then over that network, so the pocket Beagle is the one providing the IP address. So it has a fixed address. It's just always gonna hand you the same address. There's actually two of them because for working with different operating systems, there's some of them work with different types of network devices better. But anyway, the one that we want is the 192.168.6.1 for our computer and 6.2 for the pocket Beagle. And the pocket Beagle will give your computer that 192.168.6.1 address. And it'll keep for itself 192.168.6.1. So when you connected to it, did anybody see a flash drive show up? Some sort of no, no. Some people saw it, some people didn't. If you didn't see this, it won't happen immediately. It needs for Linux to boot up. There's enough bloat at this point that it probably could take a minute or so to boot up, if it's taking more than a minute if it's taking too long. But it could be a minute or so to get that. And the device will show up. You can open that up and click the read me. I thought it was pretty obvious for people to read read me but apparently a lot of people don't read read me. Which is why we also have another copy of the same file on there called start. Just the exact same file. Just encourage you even more. Is there another word we can come up with to get you to open up the file? Open or die, I like that one. So open up that one. So that's on the left hand side over there for you is that opened up that start.htm or read me.htm. Which is really just gonna tell you to type in this magic address into your browser. If everything just worked, the network adapter showed up and you got your IP address to your computer. You should just be able to type in this magic address 192.168.6.2. And it should be there. And all the other words are just ways of trying to debug if that didn't just happen for you. It should just magically happen. Has anybody already been able to browse to 192.168.6.2? The number of you have. So the magic number is too small on the screen. Let me, so that's the other one. So there's two, if you're using a Windows machine, it's gonna be seven. Or a Linux machine will also see seven as well. Linux machine will actually see both of them. The 192.168.7.2 and 192.168.6.2. Linux will see both of them. So the one is an Rindus driver that loads nicely on Windows. The other one's a CDC driver that loads nicely on Mac. And also Linux, but on newer Linux kernels, you'll actually see both of them. It'll also have the driver that automatically gets loaded for our Rindus. In the browser. Yes. You can SSH into it. You can also go over the serial port, which you'll be doing. There's a virtual serial port. There's a number of different ways. The magic number is in the readme. So if you haven't heard it, the 192.168.6.2 yet, it's in the readme. So when you plug it in, you should see that flash drive. Things like people are kind of, who is not, I know you haven't gotten the network access. Who else has not gotten the network access up yet? So we have a number of people. Let me give everybody else something to do, which is to open the IDE. So the only trick, right now the trick to opening the IDE is to put colon 3000 after the IP address. So you put colon 3000 and you get into the IDE, you get to the shell. Yes, SSH is really simple. For people that are on other crazy things and not smart enough to use Linux hosts, this gives them a way to get in real easy. Who would not have network connections? I'm sorry. So it's running devian. Did the network device chill out? Can you just go to your... Oh, we do need to share the network device? Cause you're running in a VM, okay. Yeah, it doesn't need to know, there's a little secret for it's own size. Yeah, it's probably gonna be on the other side. You did? Yeah, I mean it's probably gonna be on the other side. Oh, but it only, but it needs to do each of the devices. So there's, that's only the mass storage device. There's also a serial device. There's also a network device. When you, the VM needs to export each of them individually. For my stuff, why does it say not connected? Maybe you can disconnect it from the VM, you know. That or the VM might be getting in the way. But it didn't even say, it said there was no cable connected. So the, it saw it in and maybe it took it away to the VM. So where's the control for the VM that says what devices are in which? The other thing is, is for my stuff, you don't need Linux. You can just take it out of the VM and just use the Mac. Okay, let's just, just shut down your VM. And we'll just, we'll just use your Mac first. And you can, you can move ahead with that. And then we can worry about your VM for the next class. Are you, are you gonna do the same? Okay. Anybody else not getting a network? So the people having network problems is the VM so far. Anybody else having network problems getting connected? Right. That's good. So your network connection. So the magic at this point is just to, well I shouldn't, I shouldn't do it for you because I wanna, you won't remember. But that's, you can click that and it'll take you, you actually click that link. It's actually, yeah, you can click right there and it'll take you in, just waiting and there it goes. Who else is not in the ID at this point? You just got here. Okay, if you signed up for the class, make sure you get a board from, from in back. Okay. Yeah, I'm gonna, I'm gonna go ahead and move on but I think you should be able to, to catch up just following the readme. So there's, there's, there's a lot going on here with this USB thing. So I, I, I slow down and try to spend some time on this. I think it's kind of novel and fun and interesting. But, but there's certain integration challenges. So what's happened, what's happening here is that we're using a gadget driver on the Linux, so that you have your, the Pocket Beagle is a Linux computer but it's running on gadget drivers and gadgets is just a term that Linux uses for things that aren't the host, right? There's a device, right? There's a device or the slave. And we can emulate, emulate a whole bunch of different types of devices. So Linux has a huge selection of, of gadget drivers. And in this case we're running a multifunction gadget on top, so we can actually load a whole bunch of different types of gadgets kind of layered underneath it. And, you know, so all these different gadgets, most of them fall into classes. So there's classes like mass storage for USB memory disk or a camera for your webcam or audio for your, for, for speakers or printers, hid for your keyboard or USB keyboards or mine. So you can actually, you could, if you wanted to, you could do key injection and have your Pocket Beagle look like a keyboard and drive things on your host computer. Look, I can mouse and take it over. It's, it's very, very possible. So leave, leave it as an exercise, leave that as a longer exercise for the reader. There's some, some great Python scripts for doing exactly that. The session on USB is gonna talk more about the, the, the USB technology and some of those. It's, I believe it is gonna cover some of the gadgets and the host drivers as well. So some, some of the drivers that are available, but I haven't, I haven't looked over that presentation yet. So by default, we actually set up three gadgets. So there's a mass storage gadget that sets up that readme. So there's a, there's a file on the, in the, in the, the, the disk of the system. It shares that file and makes it look like a disk on your host computer. And that serves up the readme. There's a virtual peer report we can actually, which is useful in case you have any of the networking problems on your host. Actually that's a good workaround. You can actually log in over the virtual serial connection and kind of peek and poke on the device and kind of try to figure out both ends. And then there's the virtual network that we're using. I don't want to, I've got a whole bunch of stuff in here on booting that's really, really useful, but I'm not gonna, I'm not gonna do that stuff now. I did want to show, I want to go some things on the tour here before diving into the programming. So let's look around the IDE a bit. Mine looks a little bit different because I have some of the EL code installed. Oh, that was also playing with the Python scripts for doing HID stuff. But you should have something that largely looks like this. So in the, the bottom is the command line. So this is, this is running Tmux. I don't know how many of you run Tmux or like it's like screen, but it's kind of a modern version of screen. So it's running that here in your browser. So it's curses, cursors. It's Tmux is what we're running. I don't know what curses, I know what curses is. I don't know what curses is. Anyway, so there's a Tmux window in here and every time you, you could open up new shelves in this, you could do a new terminal and you can open up new Tmux sessions in here. And then you've got the text editor pane and then a file for it. All of this is mounted on the disk at varlib cloud nine. So that's, that's where it, that's where it sees where cloud nine is pointing. And so we've got a number of examples thrown in there. Was there a question before I go on there from there? You need to log in as Debian and the password is temp password, T-E-M-P-P-W-D. And if you happen to go over the, like if I, let me log out. This is the serial session. If you happen to connect up to the serial session, it'll actually tell you on the console what the password is. So yeah, I'm just, just for future reference. Let me, what's the magic for increasing the size? What is it? Control plus? Anyway, that's over the serial. This is screen, right? So I got, I got, I got to the serial terminal by using screen, right? I could use pseudo screen and then the name of the device that showed up. I found the device by doing a dmessage grep tty. Well, that was too much junk in my log. So Chromium is over, is overrunning my log. Anyway, we don't need to do that. So the text editor allows you to kind of see things really quickly. There's also, there's a run button up here. So there's a number of different, I'm gonna show some of the hidden files here. So, so hidden file. There's this integration here with C9 for these runners so I can actually define what, when I click run for different file types, what it does. It's kind of a fun integration with IDE. And you'll see an auto run folder there's a daemon running. If you drop a script in that folder, it'll run it on boot. So for people really, really unfamiliar with Linux, it gives them a nice handy way of just running scripts on boot up. And then there's the examples. Under the examples, we're gonna, we're gonna look at the pocketbeagle and there's a number of JavaScript examples in there that you can run. The other thing I want you to look at is under extras. There's this, there's kind of to try to turn you loose on the lab. There's this bacon cape lab. And I haven't finished transitioning all of these labs from Beaglemon Black and the bacon cape into the pocketbeagle yet. But I think that it should be something with the information that we've given that should be fairly straightforward for you to actually go and do. So we can see, you can see different ways that you can go and access all these, the different interfaces through there. So those are the two things I want to highlight for you. Examples, examples, extras, bacon cape, bacon cape lab. And then the other one is this, anything's in the pocketbeagle directory. So we'll go and do, the other item that we have is the code that we checked in through the Yale. But so those won't be on your drive. So I'm trying to point to things that you can, but we can reproduce them. So the first one is there's a push button demo, an example. I'm sorry, so this is examples of pocketbeagle. There's pushbutton.js. Able to find that okay? But the button is wrong, right? The button is wrong, right? So we need to go back to our slide and maybe this will work better. Oh, there it is. I got lucky. The button is P233, not P233. It's just a generic example. It's not to save that. If you put a dot or a dash, those will work as well. It also doesn't care about K. And you can click run. Unfortunately, node takes a really long time to start up. But when it says interrupt handler attached, you can see now I can press the button and we'll see the volume toggle. Yeah, so if you haven't, if you don't have your bacon bits attached, that's to go ahead and, you did the important thing, which I wanted you to do without the bacon bits, which is to get into the IDE. You should now be able to unplug and connect your bacon bits and get back into the IDE. Okay, now everybody's asking orientation. The orientation, the silk screen match and match up, but the easiest way visually is the micro-USB go in opposite direction. I'm sorry, the micro-USB connectors go in opposite directions. So there's a micro-USB on the bacon bits and there's a micro-USB on the pocket beagle. So the micro-USB should go opposite of each other. The big host connector goes on top of the micro-USB on the pocket beagle and the micro-USB connection goes the opposite side. I don't know, I'd have to ask GHI. GHI soldered these together and I think they must have hand soldered the headers. I don't know. I don't think it'll load up. Michael, have you looked at how the things map? If we plug it in backwards, it's not gonna hurt anything, is it? It could. The power in grounds actually are symmetric, I think when you flip it, except for the one ground for USB. Because of the way they're lined for clicks, they're actually symmetric when you flip them around. I doubt anything's gonna happen bad, but I don't know. So I had to go, to find the right value, I actually had to go back to the schematic of the board design. So the first thing I would notice if I tried to run something and I wasn't seeing the GPIO moving, am I actually using the right one? And so it's useful to kind of do some stuff back from our command line stuff. So I'm going to show you some of the JavaScript stuff hands on. But go back to config pin, right? So if we do, there's a handful of things to check when you're doing GPIO. Like one is that the right GPIO, but it's exported as a GPIO. And then you want to do things like, we found out earlier, this is GPIO 45, so we need to recheck that. But there's a direction value. You're not gonna, if the direction was out, you wouldn't be able to read it. So that's a useful thing to check as direction. The pinmux is usually, if you're connected up to the right pin and you're not seeing the value change, usually the issue is the pinmux. So in this case, we've got the config pin helper. We know from the schematic that it's connected up to pin P233. And so we can look, sorry, is it dead? Dash Q checks what the current mode is, dash I gives the information. So we can see that that's GPIO ID, kernel ID 45. So we can double check that. It does not save if you press run. I really quickly press control S after changing it. So if you change it and you click run, it won't save it. You lost connection? Did you unplug it first? Yeah, so it's gonna have to reboot. Not rebooting? It, you're not seated well. Yeah, you have to push, the bacon bits has to be pushed in to the pocket beagle pretty hard. Well, you're gonna lose connection when you unplug it. Did you, so you're just actively using it? Oh, did you press the wrong button? So there's three buttons. Yeah, I forgot to recover that again because I mentioned it earlier in the lecture, but there's three buttons on here. The one closest to the seven-segment LED is that user button, the GPIO button. The one below that is the power button and the one below that is the reset button. So if you press either of the two that aren't the user button, that user button, either of those two will cause it to lose connection and reboot. The middle one is the power button. If you just tap it once, it will shut down gracefully, but it will shut down and immediately terminate the active session. Of course, the reset, there's nothing graceful about that. That's just going to immediately reset the board. Helpful buttons, but also a little bit of a risk factor for this type of lab. If you wanted to go in by SSH, so if you wanted to go in by SSH, so SSH, Debian, that's kind of distracting. It's the .8.6.2, the password T-E-M-P-P-W-D. So everything is in varlib, cloud nine, and then you go into examples, and then the overall thing, the overall labs I'd like you to kind of look at here is an extra as bacon cape. There's a PDF here, and there's a number of scripts, but all of these need to essentially be changed to go along with the new hardware. If you don't have the schematic, I have all the relevant information pushed in my slides. Has everybody been able to download the slides at this point? I did a PDF version now as well. So it's github.com slash E-A-L-E, and then slash slide. There's also a number of solutions under slash code, apocabeeble.pdf. I see some blinking LEDs, that makes me happy. Because at this point, I need to try to figure out if I want to slow down or speed up because I can show you some other cool stuff in here. Speed up? Oh, that's great. Yeah, no, there's, I would say everybody, there's a hash beagle. If you're on IRC, is IRC okay? Or do you want Slack? IRC, so I'd say hash beagle on FreeNode. There's also, be on the E-A-L, IRC channel, be on, is the E-A-L-E channel open for everybody? Or just developers? Okay, so actually that's probably a better one. So for this week, if you want to chat live, I'd say on FreeNode, there's E-A-L-E, so IRC.FreeNode.net? Okay, oh, I love being able to paste. People are hearing. Okay, can you hear me better now without the buzz? Yeah. Yay, thank you very much. Appreciate that, guys. Great, down a little bit up here. Yes, we can turn down a little bit. If you're doing chat, this is a great place to try to collaborate, get some problems involved. This is a really great way to, if you haven't done IRC, this is a really great way to interact with the beagle community following on. The hash beagle, we think it's a little bit light today, I don't know, but there's usually like around 300 people. So maybe they're all traveling, leaving stuff virtually on, but hash beagle is a great way to get some support. I tried to idle in it, you see, even here while I was presenting, I had it up there, so. But E-A-L has probably been specific to these labs, so a little bit loud, but I'll speak softly. So, okay, we want to try to speed up a little bit to show some other cool things. I'm just gonna go through. So if you're looking, if you can clone the code, that would be really, really helpful, but you can see the PWM solution there for fade. There's a similar thing under examples, I can't even speak quietly on this. Under the different tasks there about fading a PWM. There's also this, you saw that we updated the seven segment LEDs through using spy devs. You could also just bit bang them purely with GPIOs. And so, you could use the shift out function within JavaScript to essentially software emulate spy. I can't even speak loud enough to not get feedback. Do you have a volume for someone in your background? No. So whatever, okay, whatever, I'd like to try this, that's much, much better, thank you. I want to try to go over some, well, why you've got the live boards and you can ask questions. I just full screens my console so that you can, it's a little bit better. I don't even, that's the size, a little bit of my font. Just obnoxiously large and full size it again. I don't know how to change, is this an option? Okay, background color, make it darker. All right, so there is under splash OPT. There's a number of different directories. Really useful stuff in scripts. So under scripts, under tools, there's, once you get a network connection, so you should be able to do an internet connection sharing from your host and get the IP address from the Pocket Beagle. I've been struggling to do that with Ubuntu. No problem with my Mac, but anyway, I don't have that set to show you. But it's like, after you write the SD card images, if you have an SD card that's larger than what your, then the four gig is what the images are sized for. So you have an eight gig SD card. You might want to do something like pseudo-grow partition. That's what I do is when it's reboots, it's going to resize the partition. So there's a number of really helpful scripts like that in here. So it's a really growth partition, a really important one to know is when you're reporting issues to the community is version. So it fetches a whole bunch of different typical configuration information for the system. Like when the image was built, which version of U-boot you have installed, which version of the kernel that you're running. And then there's this interesting thing with overlays. So even though, I forget how deep to go into overlays, but so the, all the hardware is defined to Linux using this thing called device tree. So it gives Linux an idea of what the hardware system looks like, what things are connected up to it. There's other ways to do that, but device tree is the primary way that we do that. There's a device tree definition for pocket beagle. In fact, under upstairs, we're running the 4.9 kernel, what am I typing wrong? Flash at the beginning, that would break it. 335X pocket beagle. This is, that's the name of the device tree source. So when everything boots up, so U-boot is the first thing to run, and it goes and reads a device tree file out of a slash boot. And the output of this source file is what it reads. And then it reads the kernel. So the boot load, or U-boot, reads both this device tree and the kernel, and it provides that device tree to the kernel to tell the kernel what the hardware looks like. So if we wanted to dynamically change the, if we wanted to change the hardware from what it is by default, just the base board, then editing this device tree is one approach that we could take. So you can see here in the file, there's everything, oh, there's an include file here in this one, but we see things like the spy, we have connected up to this. This is how spy dev is loaded. So it enables these spy dev channels that creates the user space interface to spy. There's all those pinmuxes, those drivers for the pinmux controls, that's where all these drivers are loaded and they're configured. So everything gets set up through device tree. So it's really, it's useful to kind of, over time you're gonna have to learn how to edit device trees, just work in a place. You're going to have to. If only there was a doc. So the, there's a number of other useful sources here, but this is a nice way to actually run and edit the live ones. I could actually edit this and make, and make and pseudo make install, and it would overwrite my, I'm gonna just invoke this because I'm brave. So, and I didn't know it's all good source. So the, this will actually build all the device trees for all the different types of boards that this image can run with, plus some others that it can't. And it'll put it into the appropriate location in the boot folder so that the boot loader can get to it. Hey there, both the, probably be gone. A lot of the hardware, we don't want to try to edit the main file every time. So UBoot actually has the ability to edit the device tree live as it boots. So there's actually a way that you can get UBoot to make edits to it. So I've got additional files. You'll see this other repo called db.org overlays, and those are device tree overlays for the Beagles, for all the BeagleBoard.org boards, PB, and there's a number of these different ones for Pocket Beagle. So if you see the PB at the beginning, not necessarily all of them are gonna have PB at the beginning, but a lot of them do. You'll see that these are these overlays files for these different out on board. So these are the clicks I keep talking about. So they look like this. So if I wanted to say add ethernet to my Pocket Beagle, I could use the ethernet click because I've got an overlay for it. And I connected to either, it can connect, it needs SPI. So I've got an overlay for SPI one, and I've got an overlay for SPI zero. So depending on which way I place it, I need it to pick that correct overlay. And there's this file, a full of environment variables that U-boot reads on boot up. So in this case, I've added one overlay to enable the PRU, which is those microcontrollers. They're not enabled by default. So I've added that in the overlay. But you'll see a number of these places where you have U-boot overlay address. Those are defined more for the BeagleBoard black, but you can, on Pocket Beagle, you can put them right into here. You can just replace this file, remove the hash at the beginning that's for comment, and put it in here in a file that you want to load. So we saw the name of the file was, let's see, well, copy that. I could remove that, oh, we'll paste that here. And now on boot, it would change the description of the hardware, U-boot would actually take that extra little chunk of device tree information and put it in there so it now see, Linux would see that that was in the system after it booted. So that would just boot up and I would have ethernet on my Pocket Beagle now, and there's a whole bunch of other ones that you can add. Yes, yeah, there's a great talk that was done at the last ELC, well, this is an ELC, but that embedded Linux conference on U-boot overlays. I don't know that I have anything that can really dive you in too quickly, but we can look, what you can do is look at a file. I think maybe that's a slash boot slash uenv.txt. So let's look at one of those files to get an idea of what it looks like. So you kind of have to know a little bit of seeing a little bit of device tree to begin with, but there's, at the beginning, you'll see this extra slash plugin that's telling you that it's meant to overlay an existing device tree, and then you'll see these fragments and this overlay specification, right? So first of all, you have to understand what a device tree is. You understand what a device tree is. So let's focus on what a device tree is and what that looks like, and then go from there to overlays. And again, pull up one. I don't think it's a common one. So it's a textual description. So this actually gets run through a compiler and put into a binary form that is essentially just a bunch of, it's just to produce a structured data set. So that structured data defines the peripherals that are gonna be instantiated by the kernel. So we say we have things like we have memory, right? So we have memory and it lives between these addresses physically on the computer. So Linux discovers that it has memory through this mechanism. So it says I've got 512 megabytes of memory. And every peripheral, everything in the system is done out like this. So I have an I squared C controller, right? Not even the devices, I have an I squared C controller. You'd see, well that's the pinmuxes before I get even to the, right? So I have an I squared C controller and I specify what's clock frequencies. This is actually referencing elsewhere, but everything in the system is described to the kernel through this set of data. So you specify what it is and then you provide the different parameters underneath it. So like the others, here's an I squared C device. There's the E problem that's living within the SIP. So there's a 4K non-volatile memory inside the SIP on an I squared C bus. So within I squared C, I would say that this compatible line, this tells Linux which driver to load. So it's gonna pull out and run that driver and then it's gonna use all these different parameters. Here the register says that it's an I squared C offset 50 and then it's providing additional base information. So it's actually defining that the data that lives in this address range is called baseboard data. And what the details are, let me show you something on the web. What the details are for that. I only want to have one browser. www.kernel.org doc. In the kernel documentation, there's a device tree and binding. So all the different types of things that you can instantiate like the EEPROM will give you a description of how you would specify that in the device tree file, right? So what on earth am I supposed to put into this? Well you look up the documentation for the device tree for that driver. If you don't have to read the driver itself, hopefully somebody provided you with decent documentation. That's really small print. But the important thing is that it shows you what the different compatible lines are that you need to provide and what are the different parameters that you need to provide to that driver. So that's all in the kernel documentation folder. Under documentation device tree and then binding. So that's it. Sort of a base field to what a device tree is. Very much not pocket beagle specific so I didn't really plan to cover it a lot, right? So it's because I wanted to try to get you to the different pocket beagle specifics. But we've done some things here to try to make editing device trees and using device trees on pocket beagle easier. We included the source for these overlays. So an overlay is something that patches a device tree. So let's use one I wrote because I might understand it a little bit better. So for instance, so we installed all those pinmux helpers and stuff. So in the case of I'm adding something on, the pinmux helper actually gets in the way of me taking over that pin. So what I can actually do is something with an overlay but I create a fragment. I target it at this OCP is the on-ship peripheral of the processor where these devices have been instantiated in the existing device tree. And I said, I created an overlay and for each of these items, I overwrite their status with disabled. So now when the kernel boots, it actually won't load these pinmux drivers by doing this. So yeah, so I patch the device tree before the kernel even boots because this happens in the boot loader and you boot. There's also a way to modify while it's running live but maybe I shouldn't move quite that fast. Anyway, so that, I disabled those, all those different purple and then I add, I also disabled the spy that the user space spy driver because I want to load a particular SPI driver. In this case, the Solomon SSE 1306 which is an LCD controller driver. And I say what pins I want to load. So the important part here though is that I'm able to modify the tree before it gets loaded in the boot loader. So I have the big tree that describes all my hardware but now I've got something I've done different because I've added this other board on. I want to change that overall description to better represent my hardware so I have to make an overlay for it. And the syntax is largely the same except we're targeting certain, we can either target the root to add stuff wholly new or if I'm targeting a certain subsystem, I'm putting it under SPI. I need to do that to point to that data structure that I'm going to modify. Absolutely, it can, well it happens, it depends on where it reaches that point when it's kernel boot up, where it loads that driver. So it could potentially happen very quickly. I've seen cases where people can make the kernel load in tens of milliseconds, that's like 100 milliseconds, let's say 100 milliseconds. But that's very, very, very, very specialized. Typically you're going to be in order of half a second or so, or a few seconds. It's not going to be milliseconds typically, it's going to be seconds typically. The boot loader is really where you want to put it if you need it really quickly. Modify the U-boot source and you can set pinmux settings there and GPIO settings there. Yes, that's a good question. He's got example folder on bb.org overlays, where the previous, the bacon cape overlay, not the bacon bits, but the old bacon cape overlay was given as one of his examples. Actually these things, more of an example is using the board, come to think of it. I would look at the bacon cape overlay. So this is what the bacon one looks like. It's done for BeagleBone Black, so not for Pocket Beagle. There will be some changes relative to what it's actually patching, right? Because it's not patching the BeagleBone Black based device tree, it's patching the Pocket Beagle based device tree. Not yet. No, I wrote one for the accelerometer and I think I know what the bug is because they change accelerometers between rev one and rev zero and rev one. What was the other question? So you really need a device tree class. One of the foundations, literally we do a bit on many kinds of conferences and they always show you sort of 50 minutes of like one second payment over how something should be done still in device tree. The second thing is the documentation is supposed to have actually done the work. However, there's one thing I will tell you and that is that the BeagleBone support and what they do is they are actually following some part of the decision that's in what cover during the meeting, I imagine future meeting next year at scale. The other thing is that tomorrow we are doing a partially IPeracy in fact first part of this. Oh yeah, you're not on the mic. But I'm gonna cover it this time. Certainly you will find that a number of the people that are speaking for you during this seminar are in fact trainers in it. What's my time check? Okay, good deal, good. All right, so I'm gonna try to give you a little bit more example on device tree. This is a rich enough topic that it's worked a little bit more time. I do have an example that didn't work. I mentioned when I got the rev one board that worked on the rev zero. So I'm gonna try to patch it because Michael told me that what happened was they swapped the device from an, let me show you what the device tree looks like. From the eight, the free scale MMA, oh that red is really hard to read. Eight, four, five, two to the eight, eight, four, five, three. This code is checked in to the code GitHub repo. I'm just making some changes to what's inside there. So you will have this example as part of the EL code. And so what I've done here is I've targeted the iSquad C2. I wish I could tell you about this magic. This is magic food that I copy repeatedly and it screams if I don't. I have almost no understanding, a very vague idea of what that is actually doing. The parameters, you know what, you know what. I know the answer to that. Yeah. Yes, yes, okay. So maybe I'll just scan next to you so my voice gets picked up. So address cells and slide cells, is that what we're talking about? Yes. I'm sorry, I was only bear with paying attention. So address cells and slide cells have to do with how things are understood in subsequent child nodes. This is a child node here. Okay, and you'll see that there's a number of things in an array, an array of angle brackets like this. And inside you have a number of values. Those values are all 32 bit numbers by default. Okay, and they always come in essentially groupings of address and then, sorry, yeah, addresses and then the number of data. And the number of cells or entries in the array that are addressed, the number that are values that are then data are specified by those two pieces of metadata. So the address cells in this case tells us that we have one cell or one entry in the array that is address and zero data. Okay, so what this means in this case for this particular device is the registered value and that's what reg stands for because we all like to shorten things down to the least amount of piping, is that this is the one C version of the address for this particular thing is one C. If it was a CPU, typically we go zero, one, two, three, four, the address just indicates the actual thing. If it is a memory maps device, you will find also that the address typically is the address of the thing that you're dealing with, the size tells you the size of the data versus if it's a register range, what that happens to be. The other thing I will point out briefly, and it is a rule, but it is not always enforced, although newer versions of the tools are supposed to enforce it, is the first address is also used as a unit address in the actual node name. So you'll see that we have a name and then we have app and then the number of the specificity like the register address, they're both one C, the contrast is a bit hard to see, with red on black, but essentially that's the deal. Address health and size health, it actually took me a really long time to learn that because again, the documentation is terrible. You'll also often see a label printed out ahead of this. So if you wanna reference these things later on with overlays, you don't have to have a label but it makes it a whole lot easier because that's what's being specified here with this Ambersand target. If somewhere over there, there was a label around the node. So you can add labels to the nodes. Often the node names and the node labels are the same, but that's not at all required. They live in a different name space, right? So the label name space is global, whereas the node name is local, right? So that's yes. Yes, the Ambersand is referencing a label. Where is the file at? What file? It's under, so on the GitHub, EL and code. If you go under resources, Pocket Beagle, I'm gonna check in a newer version after this, but you'll see this, iTourCXL.dts. This is a broken one that I was in the process of trying to figure out. Anyway, that's the file I'm editing. I've already changed it from that. We're gonna try this live here. I'm gonna see if this works. So I've got another little shell script in here that's going to, so we talked about how to do it in Uboot, right? You specify Uboot underscore overlay. You define one of those variables and the Uboot will have this, the scripts that run in Uboot will book that and load those overlays and patch the device tree live. Well, the kernel also has a live patching mechanism that's exposed through config.fs. So if you go to the directory syskernel, config, device tree overlays, you can actually create your own overlays and modify the device tree while the kernel is running live. So the process that you follow is to make a directory. When you make a directory, some files will show up underneath it magically because it's not a real file, right? It's just an interface to the kernel. And what I'm doing in this script is I'm actually compiling that device tree source and I just write to it directly. So this is the DTC, is the device tree compiler. And I write the output into this DTBO file or the overlay file that just directly writes it to the kernel. So I feed the source into the compiler into the kernel. Yeah, it's four dots. I don't remember where it went. I think we had to backport the patch into four dots. This is running four dot nine. I think it was like four dot 11 or so that they introduced the overlay capability. That Pentelus introduced it. That is absolutely magic. So, yes, you can create the overlays and load them in real time. I wasn't expecting this to work, so I'm super excited. So usually the demo, I just go the other direction. So this is actually reading accelerometer values and I can see now they're limited in the number of bits relative to the other device. So there's the top axis is the X axis. So if I tilt it to the left, we can see it goes negative. If I tilt it to the right, you see it goes positive nearest maximum to one G value. And then the Z, if it's laying flat, you see it's kind of maximum. That's the third value. Maximum out at Z, sitting around one G. If I move it up and down, you can see it changes sitting around one G. If I flip it over, it should be about negative that value. And the same with Y, right? So Y is this direction and then upside down is that way. So we're able to follow those patterns of the changing numbers. A little bit difficult to follow everything going on at once, but it's reading the accelerometer now. So it's loaded the Linux driver for the accelerometer that's on the board. And then it automatically creates these. So the driver exposes the values, the accelerometer values as virtual files. Let me cancel out of this. In the kernel. Yes, there's a C kernel driver that knows how to read and write that accelerometer already. You'll learn how to do that in the next couple of days. But so yes, that driver's already written. And most of the time, like most of the time when you want to add stuff, it's already somewhere there. You just have to figure out how to get it loaded. Because the kernel is just chock full of interfaces for all the sorts of stuff. Like, you know, this is a different accelerometer that was on the previous revision. I changed the version number and boom. It came up. It just depends on how you compile the kernel. In our case, they're mostly modules. So if you want to find out what modules are loaded, you can do ls-mod. And you can see that module was dynamically loaded. It's not pre-built into the kernel here. It was loaded. What Bein was saying was that there's a future tool for forcing that app to be something particularly tied to it so that it's useful. Yeah, but that's news to me. As far as I know, it's arbitrary. The ad does have some meaning for indexing, because you can essentially have multiple indexes of the same thing. So the ad is meaningful, but what the actual number is, I don't think it's meaningful. It's that reg value that's really meaningful. So in that script, I remember I looked earlier at the SysBus IO devices, and there was only one of them. So when we loaded this I squared C accelerometer driver, it created this other interface. And you can see all the different types of things that it has in terms of data that it's providing from the accelerometer, including things like Excel, raw, X values, right? And I just added that, again, that same trick with the watch in order to print all those values out in here. So I don't have to keep typing it in over and over and over again to read those values. I can just get them to display on the screen. So the terminal buffer, I'm absolutely posting the script. Hopefully you can, I'll go ahead and make sure it's in, I'll make sure to post the script. Let me show this on the here. So the, here's the shell script. That's too hard to read. So the, so it reads, so the overlay is in this magic config FS directory, right? This kernel config device tree overlay. So I make the accelerometer directory, that's to say that I want to provide you with a new overlay. So I do that make directory. And then here I'm writing it into the DTBO file. Right, so when I create the accelerometer directory, creates a DTBO. Let me show you one more part of that because kernel debug config, kernel config device tree. It's not on the pocket. The code, these code examples are not on the pocket beagle. I'll put them in for future builds, but they're not there right now. So it creates, so when I created that Excel directory, it created these other files. So DTBO pass status automatically. So if we kept status right now, we'll see that it actually says that the device tree overlay has been applied. So before I output that device tree overlay into this file, its status would have been, I don't remember what it says its status is before, but it wouldn't be applied. Now the device tree source, so here I point to this i2cexcel.dts file. That's in this repo as well. But I've made a change to it. The big change being this model number here changed. I also just removed the interrupts. So we're just pulling the accelerometer at this point. There is hardware, you can configure hardware for doing the interrupts. I never actually finished figuring out all the stuff, all the magic food I needed to put in here to specify the interrupts. So I was just using it by pulling. So I changed that from a two to a three and then removed those two. And I'll check that in shortly. Yeah, I wish I had a nice way to wrap this up, but this live kernel interface is very much the same way to kind of do the same, what's done with files that are specified here. So we're taking these overlays and here we're telling the bootloader to apply them while it's booting. The other way, we're just telling the kernel to hack them in while it's running. Cool, so if I specified that file here in the overlays, then every time I boot it up, that accelerometer interface will be loaded. I'm gonna make sure I cover everything. I've got some details in the slides about the bootloader. This to me is useful information to try to understand a little bit more. There are some pointers here also to the patches, for the bootloader that we applied outside of mainline to try to handle. I currently, our application of overlays in U-boot isn't part of mainline U-boot. That's a Beagle. The way that we're applying these overlay patches in U-boot, so the mainline U-boot has the ability to apply patches, but the fact that we use these environment variables to specify the files and apply those overlay patches, that we specifically patch that into U-boot. So if you run a mainline U-boot, you would have to take some other steps to try to tell it to apply the overlay in U-boot rather than just specifying that environment variable. Make sense? All right. Other things I wanna make sure the device tree configs in. There's another really handy tool called shellpins. So if you run a script device, there's a purl script that I think is really handy. It's really designed for Beagle on black, but it's still really useful because it just gives you the summary of all the pins and what their current mode is, including what driver is currently controlling the pinmux. So under op-script-device-bone, shellpins.pl, shell-pins.pl, it's largely the same information that you can get from configpins. The nice thing is it just outputs in a table and kind of scans across all the pins that would normally be on the Beaglebone black headers. Then you can get a more complete set by adding dash V. This parses some debug files that are provided by the kernel to specify what the current pinmux mode is. But I'll tell you that the RX, so each of the pinmux controllers, if you see RX, that means the receivers are enabled, it's kind of weird. You can disable receiving on any of the IO pins, on any of the digital IO pins, that's a flag. The other things you can do are you can change the slew rate. So the fast, you'll see fast or slow. I think everything's set to fast slew rate, so it'll change the drive strength. If you have any noise issues on a board, you wanna lower the drive strength because you just don't need the transitions to be so quick, you could actually change it to a slow slew rate. That may be something useful for GPIOs on a board. Up or down tells you whether or not a pull up or a pull down is enabled on the pin. So the internal pull up or pull down within the chip itself. The number there tells you the MUX mode. So the number says, so each of the different pinmuxes can be either between zero, one, two, three, four, five, six or seven, to say which mode is being selected on that pin, whether if you're routing out the PRU signal or the GPIO signal or the SPI signal on that pin. And then you've got a description of what the active mode is. So if it's in PRU mode, if it's a SPI mode, that's all baked into that show pin script. It's been used quite a bit. The big thing for it right now is it's for Beagle and Black. So if you look at the descriptions of the pins on the far left, they're not gonna reflect. It's not, it could be, yeah, there's opportunity for manual error there, but it's extracting the data that it's reading live from the kernel, the parameter values, but it's just doing table lookups to the specific. Which one? You have to do purl in front of it. Yeah, it doesn't have the... Somebody needs to chmod it. So the last thing I think I want to try to expose you guys to is the PRU. So those extra little microcontrollers really messed up my view here. Where can I grab it? Can't find a place to grab to expand this. I don't think I'm cutting off anything too important. Because I know what you said, it's cutting off stuff on the left. Can't grow this for some reason. So there's, under examples, examples, extras, PRU. I've put a couple of examples there for you. But I've got a modified version, a little run, we can run that version first though, examples, extras, PRU. You'll see this, hello pru.pruc. And it may not come up syntax highlighted for you by default. In the lower right, you can select C, you can select the syntax highlighting mode, so the syntax is at C. But I've given it a weird name, because I talked earlier about the IDE having this ability to have these runners that can go off and execute scripts when you say you wanna run a particular project. So I used a different file extension here to tell it how to go and run a PRU C program. This puts a single C program, you know, compiles it and runs it on one of those target CPUs. Just remembering one thing for you guys though, that it won't run for you by default because of the overlay stuff. I've got a script, no I've got it, I'm sorry, I've got a command. If you're in this readme, if you look at this readme, there's something you can cut and paste, which is this magic set line right here. And if everybody can get to this website or not, but in the PRU examples, there's a long set line. All this is doing is editing that slash boot slash uenv.txt file to load a particular overlay because I wanna load the overlay to enable the PRU. This is the EL code repo. The path is resources pocket beagle and then you just scroll down. The readme renders on the page. Once you run that set line, you need to reboot and that'll enable the PRUs for you. And if you understand said, you can just do what it says. You don't actually have to run said, but for folks that don't, I just try to make it easy to cut and paste. And I kinda go through the different examples that I'm gonna throw here and they read me anyway. From that, you can just click in this IDE. Once you get the file up, you can actually just click run. You have to expand this. T-E-M-P-P-W-D. Good question. Brilliant. Good idea. T-E-M-P-P-W-D. So it's now running. And so what that is doing is actually this user three LED is now being toggled by the PRU. So it's a separate processor that's actually going through the on-chip peripheral bus and toggling the GPIO for that pen. It's a remote proc. It's the new one. And so I'm trying to give everybody a sample C template that you can follow. I've got a bunch of crazy if-deft in here, but this code is actually pretty simple. The main routine, if you wanna get to the on-chip peripheral, you need to set this bit. This control bit. So just copy that line any time you need to get to the on-chip peripheral. Any application if you wanna try to go outside of the PRU subsystem with your accesses. That otherwise it standboxes it, the PRU, the hardware standboxes them. And then I've got a silly for loop. This could just be a while one. And I'm doing GPIO set so that that is a memory mapped register defined up here. So the hardware for the GPIOs is controlled with set and clear registers. The advantage of that is you can do apply masks. You can update up to 32 GPIOs at a time using masks. Or you can select only certain ones to be updated. So instead of having to do a read, modify, write, you just write to either the set or clear and you use a one for the bits that you wanna change or a zero for bits that you don't want to change. So if you wanna clear it, you set the register bit to one in clear and that's how you clear it. That make sense? You write a one to set a zero? Maybe a little confusing. But the code here is that's what it's doing. It's writing those memory mapped registers. It's on the disk. It's examples, extras, peer you. Examples, extras, peer you, hello, peer you. And the other files that are kind of making this magic work are in the directory that are just kind of more boiler, also just boilerplate. This line is disabled right now but if you wanted to, there's the GPIOs that are part of the peer you rather than the on-chip peripheral GPIOs. I'll try to repeat this a few times in different ways to make it make sense. So the peer you itself has GPIO outputs that the pinmux can select to put them in peer you mode and then the peer you's in charge of those pins or you can have the pins go to the GPIO which is the whole chip on-chip peripherals GPIOs. So these registers are changing that whole chip GPIOs, right? So the same things that you'd be changing from the arm. If you want to change the GPIOs for the peer you itself ones that are under its control you just use the R31 registers. R31 is for reading, R30 is for writing. They're directly mapped to processor registers. So even though this is a line of C this is an intrinsic that specifies the actual register within the processor. So you can actually create, you can create zero overhead loops that's gonna create 100 megahertz wave form output if you wanted because you can just do an XOR of a bit and do it in an infinite loop. So you're toggling a bit at 200 megahertz. And so people use this to create all sorts of cool things like like BeagleLogic where he's grabbing the values of 16 data lines and shoving them off into shared memory for analysis by Sigrock. It's a familiar Sigrock. So you can actually make, you can turn your Pocket Beagle into a logic analyzer if you want, all right? So with the GUI and everything. So I've got an additional modified version but this should hopefully get you the idea that you can write your own C code to run on those processors. There's a linker command file in here and a make file. So this make file is what does the compilation, right? It's just when you click the run button, it runs that make file. What was the question? It won't work. The way it's done right now is that you have to specify two environment variables. So I'll run it from the command line now because I've got another version. I've got another version in the EL examples that actually comprehends the bacon cape, bacon bits cape. Yeah, the one closest, it's toggling the blue LED closest to the USB, not the one inside. The one inside is doing a heartbeat pattern but if you see it, it should be toggling the one closest to the USB connector. If not, it's not running. It says it loaded in RAM. So I've got another script that says run RGB pure U. So it does the one other step which is making sure that the muxes are set properly. Of course for that one, for the LED, it's not really using the muxes because it's just using the, it's already muxed for GPIO. But for one, for a couple of these, a couple of the RGB LED pins are actually connected to pins that can be pure U output. And so I've got a modified version of the code that also sets those pure U outputs. And it's gonna go through, you can just run it. But here's the thing about the make file is that you have to specify target which is the program you wanna build and then pure U in and specify the pure U number. If it's pure U zero or one that you want it to run on. So instead of, you can't just run make from the command line you need to have those variables set. So if it's muxed to the pure U, you can toggle it at, you know, it's five nanosecond latency from the command, right? So you can, you can literally sit there and make a hundred megahertz waveform. If you were to do a tightest possible loop on the pure U that toggled the GPIO, so it's probably an eighth or a tenth of that. Yeah, yeah. There's gonna be some jitter when you go outside to this, because it's gotta get, it still has to get clock synchronized. So there will be a little bit of jitter and there's also other bus activity when you go to the on-ship peripheral. It's going into shared buses that could, you know, could take a gigahertz cycle or so of priority over the pure U accessing it. So yeah, it's definitely, you know, like a hundred nanoseconds is good enough, which is pretty good. If you can live with a hundred nanoseconds, you can go off. So this should be, yeah, okay. So I'm just, I'm doing the decay thing and I go through each of the different LEDs, the different colors, and just flash them faster and faster. So I do red, you know, red, green, blue, and then white. So that example as part is there as a script running from the command line in the examples provided on the GitHub. What was the rest of your question? The biggest thing is to make sure that you need to make sure that disabled ones are able to keep up with all the peripherals from the pure U. If you wanted to do, if you wanted to use the PWMs or the, you know, the SPI or the accuracy or any of those peripherals from the pure U, they're very practical to use. Now just make sure you disable access from the, from the Linux so that they're not stomping on each other trying to write your registers. The peripherals are pretty well-isolated. I mean, if you start changing clocks and the system clocks or other things like that, that's going to have some real impact. But if you just use the SPI one controller, I mean, that's largely independent. You have to kind of look at the individual peripheral and some respects. Like if you end up using a channel of a PWM, that's obviously going to conflict because even though there's multiple channels, they're still controlled by the same overall, you know, clock management and stuff that's going on for, for that pure U, that whole, whole pure U, I mean, the PWM peripheral. So you mostly just need to apply some common sense. Is there a question back here? So at the OCP, the L3 I don't believe is fully cross-barred. I think there's, it's going to be just block. Yeah, so it's, it's, there's cross-bars for memory, but not for the on-chip peripheral. Yeah, they have their own, they have their own, their own target RAM. They have a shared memory area between them. But they can't actually access the DDR. So they, you know, just like they can access all the on-chip peripherals, they can access the DDR. And so it's really, like what you, usually to communicate with them, you'll just memory map the, the, the register, the memory space of the pure U's from the arm. Because the arm can see the memory spaces of each of the pure U's, including their shared memory. And you would just kind of dedicate a region to write messages from the arm, like each way. And you would just, you just map that with the DevMIM. And I wanted to try to provide a simple example for that. There's also in the kernel, there's a provision for messaging called RP Message. That's very dependent on what you're, if you're trying to, as far as, you know, cache coherency between the two CPUs, if you're going off-chip, usually, I would just say message on-chip. Don't, don't, don't try to go through the caches. I don't know what the exact cache concurrent coherency issues would be going off-chip. But for, for like, large bulk memory sharing, it should work fine. Just synchronize off, you know, elsewhere. I would synchronize in the internal memory. Then the, the code? Yeah. So the EL code will actually all, the code's going to be on the USB 6 tomorrow. Tomorrow or the slides in the code are all going to be on the USB 6? No. Sometime before the end of the week. So if you keep coming to these classes, you'll eventually get the, the sticks. I was trying to, I'm on my rep-up slide. So you'll get the USB sticks that'll have the code on it, including, well, I'm going to commit these changes today. So it'll be on, the, the changes that we made here live will be on the sticks. And they're all on the GitHub. So github.com slash e-a-l-e. If you go to Code Resources Pocket Beagle, and I'm going to update the README as well with instructions that are, that are completely up to date for, for running all the different examples. Just, just a couple of quick plugs. This is, this, hopefully you guys are going to learn so much this week. You're going to be amazing contributors and you want to, you know, contribute some things back to Beagle board. These are kind of those critical projects that mentioned BB art overlays. This is where all those click boards need support. They need love. They need overlays. Image builder is, is how we put together the whole Debian image. If you need to make any changes, you want other packages included. You want to trim some stuff up. This is the place. And lastly, all those live examples that you see on the, the left-hand side. Those all live in Bone 101. That's the, the repo where those all get maintained and copied and there. You can see those as the update and contribute changes and share your beautiful knowledge. We've already used our time for questions, so thank you. Well, Bobby, I just wanted to go first. I'm just like to silly flip. Getting things like the USB keys and stuff done. I just think you're preparing with us. Hopefully you had a lot of fun and all the extra information that Jason brought today which was very much appreciated. We're now going to break into the next talk which I believe is that, is it two o'clock? Yeah, it's two o'clock, okay. And that's actually my talk. We're going to talk to you about kernel modules and tables in kernel. If you're doing that, mom, be out on the board itself. The USB keys are going to come eventually. Please don't leave. We're here till Saturday evening. Please don't leave. Dale, we're coming to find one of us to get the USB keys. All I can promise is that we will have some writing before the end of Saturday. Okay, and part of the problem is because literally we're all mad. You kind of finished this talk. There was a lot of very last minute issues as we just worked around, so I apologize for that. But we do have a few things for everybody. If not, all of the information will be on the website. It will be in GitHub. It will be on the e-linux linky. Certainly, if you want to know for sure what's going on, we will also email everybody on the mailing list that's on the e-mail website. Let's do find out for the e-mail list that everyone has found you. You'll really tell you what's going on on that mailing list, okay. So as long as you put your name in there somewhere, we will get the information to you. And like I said, your file will be on the website as well if you don't get the USB keys. Otherwise, great for an hour. I'll see you back here at the second colonel's manual. Thanks again. My God, you went into the weeds so fast. Everybody loved it, so that definitely shows where we have to go on the computer. The device tree was really high in my list, and it's a frustrating thing that we didn't have. We didn't cover it? Well, the thing is, the device tree is often covered with these things. The i4c, the SPI, and USB stuff specifically is never covered, so that's why it's really not covered for that, but it's so hard to do. But honestly, just to speak of both, both the stuff is still the best in the world. So as far as, you know, everybody's fighting in the world, it's still the best in the world. Because Panto basically still has everything on it. That's awesome. Panto, we're in the corner right over there. It's definitely used a little bit of a system that you need to understand what's going on. Yeah, he's a little frustrated in the device tree, so. I think probably somebody else is a little better. I would love to, but I'm actually going to skip lunch, so I'm almost done, but I have to get my last minute. I don't know if we're going to get our video, but I can't even read what's on the screen from my screen, is there a camera? Some of the snippets of this could be... The video is already online. If you can't read the screen, you're probably not going to be able to see it from the... You will be able to actually read it from the video. And the reason is, we do picture and picture, so we have to capture it. You've got to capture this. We've captured that. We're actually capturing that. So it looks beautiful, just because of that. Yeah, but I was just going to tell you, it's going to be right there. And by the way, a lot of people have to do that as well. It's really hard in this scenario to get it big enough. Hi. Yeah. I don't know if this one's going to be bad. We're still actually supposed to be bad. We're just going to read it. We're just supposed to read whether or not this one is being correct or not. I don't want to talk to the venue again. I'm not going to go to the venue again. I'm not going to go to the venue again. Yeah, but not the other two, because the other two buttons will pose it to reboot. Did you change it from P3 to P33? P2, 33? P2 underscores P3. Yes. Yeah, it shouldn't work. It's running. It just says one. It probably just keeps printing out the number one. Just make sure to get the right LED. That's the trick. Get the right button. That's the LED. Did that slide change it? All the changes are live in the code, right? I don't know if the device tree stuff is still a little vague. I wouldn't worry too much about it at this phase, if it's a little. Actually, what I'm more worried about is the documentation of what will be the Python and JavaScript to make the thing this stuff. I think it's about to go forward. Good. If they're all updated. Oh, yeah. For sure. Yeah, I need to have the code on the board. You can do internet connection sharing and share the network back. Well, I thought I knew what to do because up until Tuesday, I was using a Mac. And I switched to a Linux laptop on Tuesday. So, and I can't figure out how to get Ubuntu to do internet connection sharing. But I can figure out how to do it with a Mac. Probably, I've never done it with Windows, but, I mean, I. But the, there are sort of people who don't get connected. So you've got USP drivers that actually get out. Yeah. Is there a gateway? Well, you just need to do internet connection sharing. So you just, it looks like a network connection on this side. So, yes, they can get out to the internet if you bridge it. You just need to use your laptop to bridge it. Otherwise, you can connect up a USB Wi-Fi dongle. So, to the bacon base, you connect up a Wi-Fi dongle, and go that way. I need to make a bio break. I'm sorry to run out. OK. I'll be back. Pardon me. Oh, it's over there. How do we go? I don't know. It's good? Huh? I felt like the audience was pretty well engaged. And I was, and that. Oh. Go to the bathroom. Yeah. Just a little bit of a delay here. My laptop decided it wanted to reboot. So, we have the EL stickers here, and I was going to hand them out a bit later, but at the end of each thing here, if you guys can pass them down to the other people. Oh, there. That would be great. Hopefully, I've given everyone enough. There we go. There we go. Sorry. Oh, do you want to? OK. I should have some more, but slight technical difficulties, and I just wanted to make sure that's working. I was just working on some labs for us for later on, and unfortunately, it looks like my document just got lost. So, I have to do that during the break before we get onto the lab section. That's fine. As you can tell, a lot of these things have been done last minute. We've tried very hard to get all these things finished, but we've had a number of minutes, issues, and other things happening throughout our instructor, group of instructors. So, I apologize for any roughness, and I hope you still enjoy our program we're doing this week. My name is B.N. Webster. I'm an embedded consultant. I work for a company called Converse Encode. However, I do a lot of contracting, including contracting the Linux Foundation for both writing courseware surrounding Linux, specifically embedded Linux, as well as being instructor for the Linux Foundation. So, I spend quite a lot of my time talking about these sorts of things to people like you. So, what I do is what I call engineering-facing work. In other words, my users are engineers, and that's because I like talking to engineers. The rest of the world is insane. So, this is a whole lot more fun. I've been doing this sort of thing, well, I've been in the industry for close to 25 years. Started off in telecom, moved to data com, more or less optical. Oh, gracious. The gaming industry, I've done some defense work, medical, automotive, lots of different areas. However, always at the systems level, always engineering-facing, always doing things from board bring up through boot loaders, through kernels, drivers, compilers, various tools, libraries. I don't go much above that, even though I've done that work, I like stopping there. User-facing stuff is something other people are better at than me. But anything below that area is probably something that I've either worked on or worked with somebody on. So, that's why I really like a lot of this low-level stuff. And the developer, the app tool was one of the things that I worked early on and other things along those lines. Questions you can ask. Today we're going to be talking about something that's rather interesting. I've been using Linux since the early 90s. And I've been doing it professionally and not behind the scenes because a lot of us use Linux despite the fact that we were supposed to be using Solaris or HPX or Windows on the machine under our desks or dual-booted. I've been using it professionally since the late 90s and took a few more years than that. And part of it was because I didn't entirely understand this whole kernel module thing. I would make a lot of my changes to the kernel proper, reboot it, test things and go back and doing things. So, modules are actually your gateway to the rest of the kernel and that's what we're going to talk about. Who here has actually written a kernel module before? A couple people. What the heck is a kernel module? What does it do exactly? Why do we have it? So the big thing to get across to people about modules, a lot of people think that drivers are modules. Like a driver and a module, same thing. The fact is that all the module is, it's a way of getting information into the kernel. That's it. It's just bytes, a payload of bytes that goes into the kernel. That payload can carry whatever you want. Now, it could be a driver, but it could also be a library. It could just be a string. It could be a K probe. It doesn't matter. Whatever you want to put into the kernel is what goes in there. And the neat thing about modules is not only can you put them into the kernel, but you can pull them back out again. Now, that sounds funny that I said that, but in fact, adding code to a running kernel is easy. Removing it from a running kernel is actually a lot harder. And so we're not talking kernel patching here. We're actually talking about adding code dynamically into various systems. So there's actually quite a lot of infrastructure and checking that has to happen before we pull code out so we don't crash our computers. The other thing that modules are used for is for automatically loading only the drivers we need. So most of you right now, just looking around the room, have PCs. Many of you also have Macs like I have. But the thing about all these machines is they're essentially the same. They're all Intel boxes, some of them might be AMD, but they're all Intel boxes. They are roughly the same, right? There's a lot of ACPI glue and other things that make them look roughly the same. However, they are quite different. And there are things that, there's different controllers for graphics and for sounds and for lots of little bits and pieces. And we don't need to have all of those drivers in all the time. These days we'd have a kernel that had everything compiled in. These days if we did that, we'd run out of memory in a lot of machines, right? So we only load what we need. And so what we do is we build them as modules and then we use the initial RAM disk, a little memory-based RAM disk, and we load our modules from that. And so this means that we can dynamically figure what we need and only load what we need. That means we minimize the amount of memory that's actually used in the kernel. Part of the problem is because of the memory model, the way the kernel works. Kernel memory is what's called non-pageable. What that basically means is like a real-time operating system when you allocate memory, it's there forever. So we cannot use that memory for other things. In user space, of course, memory pages in and out all the time. But we have to be careful about kernel memory because literally nobody else can use it. This is different than some other operating systems, but it has pluses and minuses. So automatically loading driver is good. It also allows us to have more than one kind of driver where we load one or the other. Typically you can't load more than one because as soon as you take over a piece of hardware, another driver coming along could cause problems. It also allows us, of course, to architect our kernel in a very modular way so we can actually make things happen appropriately. So from an architecture perspective, it works really well. In the early days, whenever we wanted to make changes to the kernel, you had to do it sort of the normal way you would expect. You'd make your kernel changes, you'd recompile, you'd reinstall, you'd reboot. It would fail. You'd go back to your old kernel and you'd keep doing that until it worked. And that was kind of slow. Eventually we had things like VirtualBox and VMs, basically hypervisors. And this allowed us to basically reboot the VMs. And I'm sure everyone here, or many people here, are using VMs. They're very nice in many ways. And they're really great for working in kernel code because, of course, when you reboot, you can reboot faster. In other words, your failures are less awful. However, working in modules is even better. And that's because the vast majority of mistakes that you are going to make, you can undo by removing the module. Now, if you overwrite the wrong piece of memory or do something dumb, you're going to cause problems. Now, in this class today, we're going to be doing some labs a little bit later where we're actually going to add code to the kernel. We're not going to be doing anything too horrible, but do bear in mind that the code that you add to the kernel has the ability to pretty much do whatever you want. Once you're inside the kernel, there are some checks and balances, but in our particular case there are none. In this particular situation, we're not using any kind of extra security infrastructures that can prevent things. So pretty much if you misstep, you're going to kill your computer. So it's a very powerful way of looking at the world. It's also a very dangerous way of looking at the world, but it's a lot of fun as a result. Anyway, modules are great because you can add and remove them. It tries to protect you very much from doing the wrong thing. So again, as it says here, aren't modules and drivers the same things? Well, the thing to remember is this. Most drivers are written as modules because it's easy, because we can do our work without having to reboot all the time. Developers, especially good developers, are fundamentally lazy. We want to do as little work as possible to get as much done as possible. And if you're not lazy, you're doing it wrong. So the great thing is that writing something as a module, and there's only a few places in the currently we can't do this. But if you write it as a module, not only can you write it the lazy way, but you can also make it so it's modular and dynamically loaded later if it's not there. You can pull it out. You can mess around with hardware by pulling it up, putting it back in again. There's lots of really great ways. And on top of that, by making it a module, you're using a very modular design, and in fact your code is better as well. So there's lots of really good value there. If you look at the wireless stack, this is a really good example of where the 802.11 wireless stack was originally baked into every single driver. And eventually they realized, you know what, it's all the same. And they made essentially a library module that implemented just the 802.11 stack and then everybody had their own extra pieces. You just depend on that one module and away you go. This is the thing, most drivers are modules. Not all modules are drivers. So that's the thing to remember. And again, like I said, it's just a payload. It's a bunch of bytes that you're putting into the kernel. That's it. It can do whatever you want. You can just put like a giant string in there if you want to. It wouldn't do anything useful, but you could do it. And yeah, as it says down here, you can implement driver, library code, K probe, pretty much whatever you can dream of that makes sense to put in there you can do. And there's all sorts of really crazy things that you can come up with I'm sure. So here's a very simple module. It's off to the side here. It's a little hard to see. Unfortunately, the height is not great. But I want to walk through this here. So I think people at the back are going to have a harder time seeing it. But this is a simple module as you can possibly put together. It does absolutely nothing except print K. And print K is the way that we can print things off to the kernel buffer. So let's look at it in a lot of depth here. Over these points over here on the right. The first thing is if you look at the top you see there's two include files. There's linux module.h and linux module.init.h. And the thing to remember is these are things we'll tell you what the rest of the file is doing. The first thing is module.h. This means it's a module. This brings in all the machinery to do the kinds of things we're about to talk about. The next one, init. This means it has initialization software in it or routines in it. And the thing about the init code is it again provides the machinery we're about to talk about that allows us to automatically load things and unload things and do the appropriate things that's in the middle here. So all the machinery we're about to talk about in these two header files. Looking at modules the next thing typically to do is to go to the very bottom of the file. And that's because this is the conventional place to put metadata. And the metadata we have at the bottom largely starts with module underscore something. Now there's two things that you probably should put in there. Everything else is optional, but there's lots of other metadata beyond this. But those two pieces are module author so we know who to be upset with when it doesn't work. That's you by the way. And module license. And the license is important for later. The license basically ties into the internal linker which is used during intsmod. We'll talk more about licenses later. But you'll notice that we put gplv2 in there. This isn't a political statement. It's just that we will find out later on that there are certain things that don't work unless you actually have it using a compatible gplv2 license. So that's sort of the default spot for most people writing code. Unless you have a really good reason not to. There's six licenses that we can use that are gpl compatible. We will talk about that in the future slide. So next, immediately above it, you'll see we have module init and module exit. And again, this will be easier to read in the slides. I was trying to upload them just before this, but apparently everybody came in and the internet just slowed down to nothing. Sadly, they're sitting on my laptop. Right when my laptop rebooted, I was trying to upload them and that's probably what caused it to go over the edge. Anyway, so module init and module exit, these two macros tell they're part of what compiles modules in such a way that those two function pointers are indicated as being the initialization code and the exit code for this module. So it doesn't matter what we call the init and exit code. As long as we ultimately tell the system, this is my init code. This is what gets run when I'm initialized. When I'm removed, this is the code that needs to run. So it's just the starting point, just the function pointers. These are the two routines up here and it's my init, in this case, and my exit. The names don't matter. They really have to match down here. Notice there's a couple of things here. First of all, they're both static functions. Who can tell me what a static function doesn't see? That's the best answer. There's a few that are close, but basically it changes the scope. It's no one good global. It would be what's considered global to the file but statically scoped so it doesn't go beyond the file. So yes, scoped to the file is correct. And so what this essentially means is that when we link this into other code, essentially we cannot use these beyond the edge of the compilable object, the file. The reason why that is is because we don't care about other people calling this code directly. Who calls this stuff? The initialization system. How does the initialization system do it? By function pointer. So the name actually doesn't matter. Now, because you're good programmers, you're going to give it a unique name, ideally in your own namespace. If you're writing a driver on foo, you call it foo underscore init. However, because it's static, it largely doesn't matter. The next thing you'll notice is between these two is that one has a return code and the other one doesn't. So initialization code as an int as a return code avoid has a null return code. So in the case of an exit, we actually don't care about the return code. Why? Because literally if exit codes are only called in a situation where you need to guarantee that the exit code will succeed. There's no such thing as a failure in exit code. Because exit code is protected by using a reference count. And if the reference count is at zero, you are saying in your contract with the kernel that the exit code will run successfully. So you have to architect your exit code so it will work appropriately. You should still check your error codes because, again, good programmers do that, but literally you cannot report them to anything the exit code is still going to finish. In this code on the other hand, lots of failures can happen. That's important. So I'm sure everyone here has done some programming before, not necessarily on a UNIX or Linux. It's slightly different depending on your operating system you're used to. What is success as far as a return code is in UNIX? Right, and that's because the return code means no error. So zero means no error. Error codes are what typically? Positive or negative? They're negative. And again, that's just convention. That's just the way it is. You'll notice that it's a signed integer that we have. Positive numbers are typically things like sizes and so on and so forth. So zero is success. Negative number is an error. And we have a series of error numbers that are defined in user space that the C libraries use, and the kernel uses exactly the same ones. In fact, that's where the C library gets a lot of its error codes. They're shared between the two of them. It means if you have an error in your code you should throw one of those, not throw a rather, return one of those negative error numbers in your code. Why? Because the rest of the kernel will understand what it means and when it goes back into user space, because presumably you've triggered it from a C routine, it will understand what it means. And the ideal situation is it will then spit out your error in English or French or Greek or whatever you've got your language set to because again, the C library is internationalized. So the really cool thing is that by returning the appropriate error number, guess what? Something useful gets sent back to your user space engineer, which of course is you when you're writing your code. So the error code is important. So unless you return zero, your module actually doesn't get inserted. So when you insert your code, you run your init code, it returns non-zero, it throws away the memory you just added. So what does this mean? In the kernel, it's not like user space. In user space, if you open a file, you allocate memory, you do something that uses up resources, and then you terminate your program. What happens? It's all cleaned up, right? All the files are closed, the memories are turned to the kernel and so on and so forth. That's not true in the kernel. So if you allocate or put something together or reserve something in the init code before you return an error code, you need to undo all that stuff. So keep your init code really simple, but you'll find that when you're messing around with things, you'll do something complicated. Just remember that anything that you don't clean up in your init code, you're going to lose. Or potentially, if it's something really important, you're going to crash your machine. If you allocate something that deals with code in your module and then your module goes away, when somebody follows that pointer, guess what? Non-pageable memory, you're going to crash. That's the way the thing works. I'll take questions, but just in a second after I go through a few more things. So in this case, we're just doing a print k, and then we're returning zero. Nothing too exciting. Again, in our exit code, we're just doing a print k just so you can see it actually happen. We use this in the labs to make this work properly. So next thing, we've got these little things here, underscore, underscore init, and underscore, underscore exit. And these are actually kind of clever. These actually use what are called attributes. Now, attributes are not something that are in the C standard. However, there's something that everybody implements and they allow you to actually attach metadata to symbols. Symbols, of course, are either functions or variables or what have you. In this particular case, these are telling the kernel where to put these symbols into the linker, different sections of the file. And I'll show you that file in a second. Underscore and init will add this specific piece of code which is usually stored in the .txt portion of the else file. It instead puts it in a separate section. I'm just going to go to the next slide for a second. This is what an else file module, this is what your module looks like. This is an else file. You'll see we have different sections. Okay, we've got text, init text, exit text, RO data, data. This is read-only data. This is data. Text incidentally is called text even though it's binary because really computers, of course, were interpreters and therefore code with text. These days, of course, it's just a residual thing that we still use. But you'll see we have init text and exit text. And this is what these two entries do. Basically this means this function, this symbol, is going to be put not into the text section but into the init text section. The exit code is not going to go into the text section but into the exit text section. Now this is pretty interesting. Bear in mind that every piece of code ultimately is loaded into memory. Everything that's loaded into memory is done page at a time and this has to do with how memory and hardware works. So it's not always the case but pages are usually on the order of 4k in size. So this doesn't look very efficient, does it? We've got very little code here and yet we have three pages already. We've got text, we've got init text, we've got exit text. That seems like a silly idea. However, it's actually quite clever. So obviously the regular code has to go into the kernel. We can't run it otherwise. However, for the initialization text, do we need our initialization code after we've initialized our module? No. We're never going to call it again. We only initialize once. So remember I said it's non-pageable in memory? I know we have a ton of memory on big systems now but on our embedded systems, even a gig, it's not a lot. It doesn't go very far. So the more memory we can reclaim the better. So after a successful module initialization or at the end of system initialization in the case of a built-in, initialization memory is freed. So this is kind of handy. So if it's in its own page, with only things you need at initialization time, guess what? You can just reclaim it. That's all good. Now, module code. Module code can be built as a module or it can be built as what's called a built-in. In other words, it can be put into the kernel to always be there. Now the thing I have is obviously in the case of initialization code, at boot time once we're finished with initialization we can clean up that memory. That's fine. However, do we need exit code in a built-in situation? Why don't we need exit code? We're never going to call it, right? We can't remove that code. It's built into the kernel. So should we link it into the kernel and waste memory? No. So what do we do? When we link the kernel we throw it away. So we built it as a built-in. This exit code just is never linked. It's compiled. It doesn't get linked. The great thing about this is in the early days of modules we had to put if, then, else, everywhere. Like if, you know, if-desk module, blah, blah, blah. It meant a lot of weird code that had to be done. In this case, look how clean it is. Just by designating something as exit, it gets used appropriately. Designating things as init makes things appropriate and so on. And we don't only do this for initialization code. We can do it for data, other functions, as long as we understand that everything marked in it is going away after initialization. It will not be there in a built-in situation. So let's talk about some theoreticals here. Can initialization code call regular code? In other words, just the normal code that's in the kernel? Okay, I'm seeing nods. Yes. I mean, that makes sense, right? We have to be able to initialize ourselves. Can regular code call initialization code? That'd be bad, right? What happens if you call memory that's not there in the kernel? Remember, we're not pageable. So if we hit a page fault handler in the kernel, because something's not there, we die. Okay, so regular code calls initialization code and we're past initialization, obviously bad things will happen. Or worse, something else might be there and we'll be running random code. Okay, that's bad too. So regular code cannot call initialization code. Can exit code call regular code? Yeah, right? Otherwise we can't exit. We need those pieces of code to exit. Can regular code call exit code? Well, if you load it as a module, that's actually fine. It will work incidentally. In the case of a built-in, you'll crash your machine. So in both cases, this is what's called a section mismatch. And you'll find at the end of building a module, there's a step called ModPost. ModPost will point out these section mismatches. If you see a section mismatch, look for those kinds of problems. It'll actually tear apart your symbol table and actually look for those kinds of problems. So the reason why I like this code is it's so incredibly simple, but it actually shows you a lot of things that are there and happening behind the scenes. And we can actually work through the module, the macros that implement these things and such. We won't, but you can actually go even deeper than this, which is kind of interesting. Okay, but that's essentially the template that you always start with. In fact, that's what our first slide will be, is building this and playing with some of the utilities for adding and removing code from our kernel. Now, I think there was a question. I think over here first. No, that's a good question. That actually happens a lot. No, your exit code is never, it's brought into memory, but you have to clean up everything you're in it code. I should have repeated the previous question. I will repeat this one. However, the question was basically, is the compiler smart enough to know what is in it and what is exit code so that it does the appropriate thing? And the answer is no. Compilers generally can do a lot of things. They cannot guess at things like that, nor would you really want it to. You have to explicitly label them with attributes to indicate what's in it and what isn't. It will check afterwards to see whether or not you've made a mistake as a section mismatch, but if code is only ever called as an init situation, it can't flag that. From its perspective, it's a single compilation unit. I mean, it would be potentially possible to prove static analysis and such to figure that information out at this time. This is how we do it. That's that over here. So exit code is only called in a situation where we can guaranteed remove a module. So there's a reference count on the system. The reference count of zero means nobody references any memory in our module. So whenever we actually do two things, and we'll show this a bit later when we talk about LS mod, there's two kinds of dependencies. There's explicit and implicit dependencies on a module. They both increase the reference count. But when the reference count is zero, theoretically nobody references our memory, and therefore it's safe to remove it. So theoretically assuming you haven't made a mistake that hasn't increased the reference counter, theoretically it's always safe to call your exit code. And usually you also make sure that by essentially doing the appropriate blocking calls and such to make sure the things you're dealing with are appropriately dealt with. But you have to write your exit code in such a way that it succeeds. Any other questions? So again, these are the important parts of an ELF file. It's important to understand that a kernel object or a module is just an ELF file. It just has a few extra bits in it. I've actually removed those extra sections. But again, you'll just see that we have text, which is regular code. Our initialization and exit text. We also have things like read-only data that's put there by the kernel. Initialized data down here and a few other things is BSS and a bunch of other things as well. And again, you'll see that we have things like alignment information, how big things are, and other things like that, the offset into the file. So lots of really good things. I got that with the obj dump. So again, you can mark two different kinds of initialization. You can mark both initialization data and initialization functions. Now being a bit of a compiler geek, I just want to point a few things out here. You'll notice that for a variable here, you'll notice that we have the underscore and underscore knit data at the end. So here we've got the specifier, we've got the actual type, we have the name of the symbol, and then we have the attribute at the end. This is because attributes are left associatives. In other words, they deal with the thing to the left. So strictly speaking, it belongs here. Now the reason why this is is because we are saying this symbol is initialization data, which is what we want to say. Now down here you'll see we actually say void underscore and knit some function whatever. This however is actually associating with the type. Now the way compilers work, usually, is that if you mess around with the return type, it of course drags the function along with it into that section. So making any part of a function and knit in this case will drag the whole thing along with it. Now in the case of GCC, it will in fact work that way. So by putting a knit there, in fact it will put some function into the appropriate section of the linker. However, clang, which is one of the things I've worked on in the past, clang in fact follows a stricter definition of how these kinds of things work. It sticks to purely left associative, except in this one situation. And that's because so many GCC people write code like this because it's pretty, and I'm not being facetious that they prefer it there, they think it looks nicer. The way it actually, where it actually belongs is here. Okay, after the return type, and I have to say it doesn't look right there. That's because we're used to having it over here. Now, in the case of clang, clang does not allow you to put attributes on types, only on symbols. However, they have an override. In this particular case, this is so common that in fact what they do is they make it right associative in this particular situation. Okay, so in the case of a function, they've got some weird code to make it work around. Again, what you'll find is in the kernel code, this is sometimes over here, right? And worse than that, sometimes you've got a knit somewhere in the middle of a type. If you say const init, pardon me, const underscorner for init int, you're actually putting the attribute in the middle of a type. const int is the type. Keep your types together, put your init, attributes at the end. Okay, otherwise you're going to break compilers by clang. Okay, so this is the agreed upon way that we do things in the kernel. Again, strictly speaking, this should be over here, but the kernel developers have decided they prefer having it over there. Again, just not in the middle of a type. All right? Now, if you actually built things as a built-in, you'll probably see something that looks like this at boot time. There's your print k time off to the side. Here it says it's freeing unused memory. And here it's freeing some memory immediately after you usually see init starting up, right? The user space starts. But this is essentially all of the kernel, the module init memory that is being freed at boot time. Okay, and again, it's not that much memory these days, but unembedded, that's still quite a lot. Was there a question? Let's by hand go up, okay, fair enough. All right, let's talk licensing now. Again, we have a license that we apply per module. We'll see why in just a second. But there's actually six different licenses. Well, actually strictly speaking, it's one license with some extra bits. But six different variations that we can use that actually make it compatible with the global license that's on the Linux kernel code, which is GPLv2. Essentially, if you were not one of these six licenses, you were considered to be not GPL compatible, and therefore proprietary. Now, strictly speaking, that isn't necessarily the case. However, as far as the kernel is concerned, you're not GPL compliant, and therefore it won't do certain things with you. And again, we'll see in a second why. So GPL, GPLv2, there's a distinction. GPL means GPLv2 or newer. So it means if the kernel ever gets changed to GPLv3 or who knows, V4, it gets dragged along with it. So in this case, you're just saying it's GPL something. But it's at least GPLv2. In the case of specifying V2, it means it's V2 and V2 only. If somebody ever wants to change the kernel's license, they're going to have to come and ask you, as a copyright holder, are you okay moving to this new license? So it's a very specific license. GPL additional rights, this allows you to say V2 plus some extra things. So you're allowed to add your own addendums to GPL, and that's what this means essentially. So it's not strictly V2, it's V2 and some extra bits. There's also three dual licenses that you can do. Dual BST GPL, dual MPLs, GPL and dual MIT GPL. BST, MPL and MIT are similar in their ability to allow you to use that code in a commercial context. But otherwise you're saying you have a choice between using one or the other license. And in most cases, when you use it as a part of the kernel, of course you're choosing the GPLv2 side of that equation. Pretty much everything else is considered non-GPL and therefore proprietary. So strictly speaking one could argue that it's not proprietary but from the kernel's perspective it's not free. Now if you go down to the side here, you'll see we've got another column that's tainted. Taint is actually kind of interesting. It was added at a time where originally when the kernel came out, proprietary code was okay in the kernel I should say. And the reason was because driver writers would write proprietary drivers. So proprietary drivers would essentially came from the fact that everybody else is doing the same thing. When you've got a Windows machine, you've got proprietary drivers. And so everyone was in that kind of mindset. And so initially people were okay with it. But the problem that we have is that when a module or other, when a kernel dies, where did it die? If it died in a place where you can get kernel access or memory, in other words the code for things, great. But the problem is that if you've got uncontrolled code in your kernel, what caused the kernel to crash? Was it the code that's in the publicly available part of the kernel? Or was it in the proprietary code? Was it one of your modules that they don't know about? So we needed a way to basically figure out what was going on in the kernel when it crashed. And if you actually look in your an oops statement, in other words the crash dump for your kernel, it will actually indicate what sorts of things that you've actually done to your kernel over time that are saved in such a way that when the kernel developer that looks at it and goes, well actually you had something going on here, try to recreate the problem without this load and get back to me. Because too many people were wasting their time on solving problems in a module when it ended up being their graphics driver from the proprietary vendor that who knows what they're doing. And it's not bad, the graphics driver is great. You can play games on it, you can do all sorts of neat 3D stuff, it's all great. The problem is we don't know what it's doing to the rest of the kernel. It's purely a saving time and trying to get stuff done issue. So taint bits were added. And taint bits are kind of fun. So the original taint bit was the proprietary module taint bit. So as you can see here, in fact we actually go just beyond the edge of a 16-bit value. There's actually 32 taint bits. At the moment we only use roughly half of them. The first one indicates that you have a proprietary module loaded. So the very first time you load a module that's proprietary it will mark the proprietary taint bits in the module and globally in the kernel. Even if you remove the module, the taint bit is still set. Okay, that's the same with all taint bits. Next one, forced module. So it turns out you can load a module normally into a regular kernel. If you have kernel version magic turned on you can actually load an older kernel module into a newer kernel assuming that the ABI of the kernel didn't change, or the API I suppose. However, you can force that. If you know for a fact that the ABI change that's happened doesn't strictly affect what you're doing you can say stick it in there anyways. The problem that we have here however is one where you know that there's a potential bad thing. You've been told there's a potential bad thing but you've still done it. So in this case a taint bit is set because essentially you're doing something that is kind of dangerous. Just making sure about the time. I like to tell the story about Binky the Bear at this point. Anybody know of Binky? Nobody? Okay, so when I was graduating university there was a polar bear in Alaska at the zoo. His name was Binky. Look it up, it's on Wikipedia. There's actually videos in YouTube too. So Binky was a polar bear. Has anybody met a polar bear here before? They eat whatever they come across because there's not a lot of food up north. So in other words they eat humans because we're just meat on two feet. So essentially what happened was at this zoo they had a fence. So they had Binky in the thing. They then had these bars to keep the polar bear back then. They then had another fence to do not cross. And then they had a third fence over here. So the whole idea was to see Binky, you were standing behind three different fences. Makes sense. Everyone's safe, right? Polar bears are cute. They're really fuzzy and everyone likes them. They drink Coke on TV. They do all sorts of really neat stuff. So what do people do? They climb over the first fence. They climb over the second fence. They take pictures sometimes through the last fence. So what happened essentially was a tourist from the Southern U.S. went up to there and she decided to get a picture of the polar bear who was sleeping. And she climbed over both fences, stuck her arms through the fence, take a picture, look back, look back, and Binky was right there trying to pull her through the fence. And so they managed to get her away and there's footage of people basically beating at the polar bear with some wood around and so on and so forth to try and get it to let go. And she was hospitalized, she lived, but the problem was that a number of people were calling for the bear to be put down. It attacked a human. That's usually the bar for having an animal destroyed. All the locals sort of said, polar bear, of course it attacked her. Seriously? So what I like to tell this story is that these are all Binky situations. There's three fences telling you not to do this. When you say force load a module, you're going right up to the bars and you're saying, I dare you to crash. So if you crash at this point, it's your own fault. That's where we set the tank bit. And there's all sorts of these kinds of Darwinian events throughout here. TPU out of spec. If you're overclocking your CPU. Again, you've crossed some senses here. Forced RM mod. Remember I said your reference count has to be zero? You can actually do an RM mod minus F. You can force the removal. This is sometimes useful because you made a mistake. You allocated something that you should, you forgot to deallocate or what have you. And there's ways around that, but maybe it's easier than rebooting just to force remove the module. Maybe you know better. So I'll just tell you right now in my entire career I've known better twice every other time my kernels crashed. So again, we will set that tank bit because you've done something that's inadvisable. Again, rebooting takes a long time. People are lazy, whatever else. Give it a try. But you can actually turn on and off forced module removal when you build your kernel. Machine check. If you get an MCE, it's a hardware problem. It isn't something you did, but literally your kernel is that much closer to failure than a hardware problem of some sort. Bad page. Bad memory. Again, same kind of problem. Taint user. You can set tank bits from user space. Taint die. In the case of different kinds of things dying inside the kernel, that one's set. Overridden ACPI table. Again, you're not reading the manual. You're saying, oh no, I think it should be done this way instead. Again, sometimes there's bugs and so on. Taint worn. Okay, so something happened that might be a problem. Might not be, but you set the tape bit anyway. And that's where we stopped after that. The next one is tank crap, because it was for everything else. You did something that was awful. Taint crap. Okay, they didn't want to define any more tank bits because they could go on forever. Okay, so you did something dumb, the crap that was set. However, a few more things have been added in the last few years, and in fact, every few kernel versions, in fact, a new one's been added, in fact, there's a 17th one that's been added down here that I removed because I forget what it means. And here, in this case, they mean firmware in the sense of boot firmware. So this is the next 86 boot firmware thing. In other words, again, you're working around a specific problem. You're not following the written manual. More or less, again, you're crossing senses. This is one we're going to actually set today. The Taint OOT module, or out of tree module. We're going to be building some modules out of the kernel tree. Again, uncontrolled code. You're putting code in from you that the other developers can't necessarily see. Unsigned modules, we have a signed kernel now. So if you have a signed kernel and you're allowed to put unsigned kernel code into the kernel, guess what? Taint bit is set. Soft lockup. This is where CPU, basically, on a multi-CPU system, basically locks up and then sometimes can come back again. But again, there's been a potential problem with the scheduler, with hardware. Who knows? Again, we're marketing a problem. Live patching. This is kind of a neat thing. We can actually live patch running code. This is something I did in telecom years and years ago at Nortel Networks. Because you don't want to reboot a telephone switch because 911 goes down and other things it gets you fined. We have this now in the Linux kernel as for a couple of years. Again, we are actually changing running code. This isn't just a module. We're actually taking portions of the code that are actually doing stuff right now, and we're changing it. And we typically do this to get around really difficult security problems. However, again, we are massively moving on from what is normal in the kernel. We're doing some terrible things. Again, this is not a long-term thing. This is a get me to the next maintenance window thing. But again, taint bit set. And last, taint ox. There's a number of auxiliary situations where this taint bit is set. We had a couple of questions over here. If you have the original signing key for your kernel, yes. And if you are the person making your kernel, you presumably have that key. If, however, you are adding a module to a vendor kernel, some of you are running an Ubuntu kernel or a Fedora kernel. If you have access to that key, so does every other virus and hacker in the world, and that's not very useful. So essentially, by adding a module to your Ubuntu kernel or your Fedora kernel, basically you're tainting your kernel. You're putting code in there that you can't sign. Does that make sense? There's another question over here too? Yeah. So the taint bits are just informational. Nothing reads them except you and your UPS messages. So you could have every single taint bit set. And if you're still running, it's basically a miracle. Because quite frankly, it's very likely you've done something horrible enough that Polar Bear has got you. But literally, if all of them actually didn't matter, maybe your MCE was for something you don't care about. The bad page was memory you never touch, which is unlikely. But there are situations where it is possible. It's highly unlikely. But just because a taint bit is set doesn't mean a problem has occurred. Again, today we are going to set these two bits because essentially we do not have the signing key for the kernel we're using, nor do we build the entry. Okay? Exporting symbols. You'll notice that everything was essentially statically exported. And what that essentially means is if you actually want to have dependencies between modules, you actually have to explicitly export them. And the way we do this is first, by understanding how we implement this, there's several linkers involved when we actually build a kernel. There's the obviously C linker, right? And the C linker essentially does the initial act of putting the kernel together in a built-in situation. It will take multiple pieces of C code and make it into modules, because although in most cases it's one file to one module, in various situations we have multiple C files. Okay? To build the module, you're using the linker that comes with binutil. However, when you're putting a module into the kernel, when you're actually linking those two together, there's actually a linker in the kernel that does that work. And that kernel, as a result, can enforce certain things, things like licenses, things like making sure the appropriate things happen, that ABIs match, and so on and so forth. So the in-kernel linker is actually pretty smart. So what this essentially means is that most kernel code, in fact, is static. We actually make it all static in the C situation, because quite frankly, as far as the kernel is concerned, everything is static unless you explicitly export it. And so in that case, you actually have to use the export symbol macro. And it doesn't matter whether it's a function or a piece of data, you actually tell the symbol table for the module, I want other people to be able to see this as a symbol. Now, obviously, in this case, you need to choose a unique name. This is going to go into the global symbol table. Now, what this normally means is it's generally the name of your subsystem or the name of your module underscore something, just to be really safe. Okay, but you could, in fact, in horrible situations, in fact, provide something that was named something nothing to do with your module. And in the case of debugging, this is actually kind of an authentic occurrence. The fascinating thing about systems programming and writing viruses is that the skill sets overlap. There's a lot of very similar techniques used in both situations. This one is entirely legitimate. The other one is, who knows? Export symbol GPL. This is how we actually indicate that a symbol is GPL only. What this means is it will only link to other GPL code. Now, this isn't used a lot, but there are a number of internal powerful APIs that will only work with other GPL symbols, good modules. And what this means, essentially, is if your module is not GPL, it will not, in fact, link to certain subsystems within the kernel. So this is actually kind of an interesting thing because you're essentially saying anybody who wants to use my code has to play by the same rules I'm playing by. Now, the really fascinating thing about this is this is primarily used by free software advocates to say I'd really like this code only to be used in situations where, amongst other things, companies are following the GPL entirely. In practice, I always argue this is something that companies should be using. Why should they do that? They are releasing their code under GPL so other people can use it. By setting it as a symbol of GPL, they're basically making it so that all of their competitors also have to play under the same rules. So it's actually quite interesting. In this particular case, this is actually quite an interesting thing for a company to do to make sure that everybody else is playing on the same level playing field. By not using this one, by using this one up here, in fact, people can write it as a proprietary module that uses your interface. Maybe that's fine. That's all good. If you don't want it to be, you can make your symbol GPL instead. You can also do this, GPL Future. So if you've changed your mind, let's say it's an exported symbol but you'd like to make it GPL, there is a code to follow and that code is you warn people that's what you're going to do. So what you do is you first market as being symbol GPL Future. What this means is it will still work and you will get a warning in your kernel log that in fact it will be GPL in the future. This gives people time to see the problem and actually work around it or solve the problem or change their license or negotiate with you not to do it or whatever. So usually it's two versions of the kernel as the accepted one before you move it to GPL. Now, some of you, certainly in the embedded world, might be using vendor kernels. You might go from a really old kernel that skips many different intervening kernels. Okay, this is a problem. This is one of the reasons why using vendor kernels is dangerous. Tracking mainline and actually having somebody track mainline means you will catch these problems as they happen. When I say problems, changes I should say. They're not strictly, they're only problems because you have to react to them. There's a bunch of other export symbol ones. I didn't provide them all here but there's things to do with per-CPU variables and a bunch of other stuff, unused variables and so on. But there's more than just these three. These three are just probably the most useful of all the ones that are there. K-Build. So in the case of K-Build, this is the actual build system that the kernel uses. It's rather popular and in fact, it's so popular that these days almost every other embedded code base uses it, except for one. Open embedded and therefore the Yocto project do not use it. U-Boot, UC-Lib C, Busybox, Crosstool, obviously the kernel, Buildroot, everybody else uses K-Build and the reason is because everybody wants to use menu config. That's a menu system that comes up and you can choose what you want to do and so on. We're about to talk about it. It means your sub-directory is kind of very simple make files. You don't have to write very complicated things. You just list what you want. Again, we'll look at that in just a second. The configuration is very simple. It uses something called K-Config to define what your variables are, how they work, what they do, some help and so on. And more than menu config, there are actually several other graphical environments that allow you to modify your configuration options that are stored in a file called .config in your top-level build directory. So menu config is merely the one I will show you because it is the most common. It's perhaps not the prettiest or the most mouse-oriented one. However, it will work over SSH and everybody supports it. It's the de facto everyone does. The other ones do similar things, but they don't always work depending on what subsystem you're on. So if you learn menu config, it will work everywhere. And it's based on end curses, just in case people want to know. So this is basically how K-Build works. You've got a .config file in it you have a bunch of different config operations, config key-value pairs, rather. In the curbs, they always start with config underscore something. Always in caps. And we then make them equal, usually Y for yes or build this thing in. M for module. In other words, build it as a module, which is what we're showing you in this example. If you do not set it to anything, it just becomes nothing, an empty string. However, some variables are set to numbers. Some are set to strings. There's a number of things you can do. You can do lists and so on. In your make file, it becomes very simple. They start looking a little bit like this. There are several different lists in the kernel, obj y and obj m. Everything in the list obj y is a built in. Everything in the list obj m is a module. However, you will notice that we have config foo up here and we have obj dash config foo down here. Because this is an m, we have foo.o being added to the obj m list. Therefore, we built as a module. It's a very simple mechanism, but this allows us to do is we can set this to a yes, we can set it to an m, or we can set it to nothing, which is a no. This allows us to configure how our kernel is going to be put together. Again, we can statically always add things. In this case, we're always saying bar is always a built in. Down here, you'll see that in fact we're using it as a way of selecting a directory. What that means is we will actually recurse into that directory and look at configuration options within that. How do we know that? It ends in a slash. In other words, if this is set to no, we don't even walk into that directory. This is why certain subdirectories and menu config disappear when other things aren't set. Okay? Kconfig. Kconfig is the language that we use to define what ultimately works in Kbuild. It actually allows you to define a number of attributes based on those configuration options. Again, in the kernel, they're always config something. In other things like build root or busybox or br for build root, busybox for busybox and so on and so forth. But you get the type, the default value, there's different health values you can set, dependencies. When you turn a configuration option on, what else gets selected at the same time? There's conditional selects and other kinds of things like that. This looks basically like this. Here's a very simple and silly contrived example. Kconfig foo. In this case, it defines the kconfig underscore foo value. Notice that the prefix doesn't matter. We don't put that in there. Okay? So that's implicit by Kbuild that it's kconfig underscore. In this case, it's a tri-state. We could have made it a bool, we could have made it a string, we could have made it a number. In the case of a tri-state, it means yes, no, or module. Okay? And you'll see at the end, I'm missing a double quote here, this is the one-liner description. This is what you see in menu config when you wander down. It's a very short, I sometimes call this the Twitter version of the help. Okay? It's a very, very short, very useless, not very helpful, but enough information to know what the thing does. We have our default after this. In this case, we've made it default M. We've said it depends on blah. This means that kconfig blah must be set in order for kconfig foo to even show up. Okay? So that's the first thing. We also have a select foo. No particular reason I ran out of other names. This means that foo is turned on. So kconfig foo is automatically set to whatever kconfig foo is set to. Now, a foo is already a yes, and you make foo a module good enough. But if it was no before, it will be made an M at the same time. Okay? And down here, we have select bar if not baz. Okay? So the condition I was talking about, this will select bar only if baz isn't set. So it's a rather complicated one, but essentially we can actually set up a series of this conflicts with that by using this kind of thing. And it can be rather complicated. You can say and, or this, that, the other thing, and so forth. So there's a whole mechanism for making sure that if you set a particular thing, the appropriate other things are set, it selects certain things, and won't run in certain situations because there's a whole description for this. Documentation for this is all in the kernel BigD documentation directory. It gets into way more detail than I'm talking about. Finally, we have help. And help basically has a multi-line description of what the help is. And then the next config stanza starts when it finds the word config on the first line. Notice help is indented in. The reason why that is, is because white space doesn't matter. It's because if it has the word config it's the next configuration option. Okay? So the question was basically, does the pen set blah? No, what it means is blah must be set for foo to even be in contention. Will it warn you that you have this but not that? No, it will not. Food just merely will not show up in there. Now you can actually search for foo and it will actually tell you that it's set to a particular value for the dependencies. You'll see that dependencies aren't met. But there isn't something to tell you that it won't be there because it doesn't know that you want it. But again, very simple, very contrived example. This is menu config. When you walk in this you'll see we have a number of different things in here. I'll talk you through it. The next slide I talk about all the things I'm about to say. But here you'll see that we have a highlighted area. If you use the up and down arrows to see but there's a plus here it means you can keep going down the page. The left and right arrows will take you across these buttons or tabs or whatever you want to call them across the bottom. Select allows you to change things. Exit of course will take you up to the previous level or will actually exit the tool. Save and load allow you to save or load .config files. Personally I never use these. And then help will tell you the help for that specific item you're currently on. Now you'll see a couple of things here. One is that we have these dash dash arrow things here. These means these are submenus. You'll see that we have some stars in square brackets. These are Booleans. So it's either on or off. You'll also see that we have a star up here with a dash on either side. You probably can't see that but trust me it's there. The dash means basically this is selected and you cannot change that. This is set by somebody else. In this particular case it's probably set by the architecture for instance. If they were angle brackets these are tri-states. And if you have round brackets like this it's a string basically that you can change to whatever you want. How do you actually change the value as well? Most people will go down to it and use the space bar and that will toggle. If it's on it goes off. If it's a tri-state it will go off module on. It will go from no, m, s, y. However if you want to be really lazy and you just want to go to what you want to be at y, m, and n will also take you to that appropriate thing. Again usually just space bars faster. The enter key is how you get into a submenu. The way you get out of a submenu is you go to exit and it will pop back up again. Now at one point, and there's a few people in the back that have been doing this as long as me, at one point people remembered where everything was in the kernel menu. However in any particular slice of the kernel that you're looking at you will find that there's on the order of 3,000 options. Most of them are hidden though. So it's 3,000 visible options. There's over 10,000 actual configuration options in the kernel. And they move because people think that they should be in different places. They're hard to find and so on. Remember where exactly everything is really isn't possible anymore. It moves around a lot, almost nobody does this. Instead what you can do is you can do a search. How many of you know VI? Pretty much everybody. How does one do a search in VI? Slash. Guess how we do search in menu config? Slash, exactly. So you put slash in there. It doesn't matter about case. It doesn't matter about putting the config part in. Search for the string that you're looking for it will show you the help block of all possible combinations. Just for time reasons, I won't actually demo that for you at this point. But you will find that there are little numbers next to each one of the locations in that search. It will go 1 through 0 and then it will go A through Z and so on and so forth. Now the interesting thing is this. It used to be that you do the search it would show you where it was in the menu system and then you'd actually have to go and find it. You'd go to the appropriate subdirectories and then you'd have to look through the list. Which is not sorted by the way. So you'd have to look through the entire list to find it. So some bright bulb decided that this was kind of silly but there are numbers in there. So the cool thing is that if you see that number next to something you just press the number of the letter and it will jump straight to the value that you're looking for. And it means everybody's got lazy and we don't even know where things are even more now because we always use search to find things. So whenever you're configuring your kernel or one other of the other system just use search. You'll find what you're looking for. Things are mostly named in a consistent fashion and if there's more than one option that it finds basically we'll list all of them there appropriately. Okay. So next let's see now here. So the next thing is building a module in a tree. So how do you do this? And this is the ultimate way that you want to deal with things and you do this by essentially adding your code appropriately in the appropriate sub directory. You add yourself appropriately into the kconfig that you're looking for and what have you. You then make sure that your configuration is set up appropriately in your .config file usually it's your menu config and then you build your kernel. But building everything in kernel is a bit of a pain. It's a lot of problems and as kernels change of course you've got to bring things along with you and so on. Most people do their work out of tree just to make things easier unless you're an actual kernel developer in which case a lot of people just work in tree all the time. But everybody else works out of tree because it's easier. And the way you build out of tree is this. You use this line right here make capital C and then a directory and then M equals and then a directory and then modules. And the way this works is rather clever. This case should be kroot not root I'm sorry. This actually gives you the path to your headers. It doesn't have to be called kroot it just made it so it fit on the line. And the trick is this if you actually look at your kernel headers that you're building against for the kernel your original static headers they're what are called dynamic headers they're built by the build system. When you prepare or build configured headers it's actually building those dynamic files. So things like version.h autoconfig.h and so on. However the build system that was used to build the kernel is also here. When you build a module you have to use the same compiler the same setup, the same settings the same compiler options as the kernel otherwise it doesn't work. So the whole build system is here the configuration file is here and everything. So when you configure your headers your static headers, your dynamic headers you've got config file, the make file all the scripts that were used all the options that were sent to the compiler all the same. Because in the past when we had to do this manually we got it wrong most of the time. So over here we know how to build the kernel and therefore modules for this kernel. Over here we have our module. But we don't have the build system. So how does that work? We use minus capital C to jump. In other words this does a change over to the kernel directory. However we need to remember where our module is. So what we do is we set m equals and this is short had in hand for kbuild underscore module but that's too much typing so m equals. And PWD of course at the command line gives you the current directory that you're in. So what this does is it saves where it came from m equals and then changes directory over here and runs make modules but to build the code that's over there. It basically uses the make file over there to build things but using the configuration that's over here. Because it's easier. Literally because it's easier. You don't care where it goes in the past. You can build against multiple different kernel versions. Basically by building something out of tree you are building it in such a way that it doesn't have to be sent to a particular kernel or necessarily be upstreamed. Now that last part is bad and you ideally want to upstream everything but you can't always and sometimes it's big and complicated enough that building it in tree all the time means that you can't use it with random kernel that you want to use it for. So if you only ever do your work in kernel that means that's the only kernel it will work with. Building it out of tree gives you more options. Cross-compiling modules. That's for natively compiling. Or on your host. If you want to cross-build from one machine to run on another you do this by setting two values. The architecture variable or arch and cross-compile. It doesn't look a bit like this. You still have to set your root and your M if you're doing it out of tree but you have to set your arch equals whatever the architecture is. Now realistically most of us build on x8664. Why? Because it's fast and relatively cheap for the power that you get. And so arch equals arm. This is literally the name of the architecture you want to build for. If you look in the kernel code there's a directory called arch and under it there's a number of subdirectories. This is the appropriate subdirector you want to build against. In this case we're building 32-bit arm. Cross-compile equals and this is a triplet. So it's called a triplet. Arm Linux can be either IHS. This is just a random one I chose. It's the one that my compiler tends to use right now. You'll notice there's a dash at the end. If you look in the make file it literally puts dollar cross-compiling in front of GCC and LD and AR and so on and so forth. So by specifying Arm Linux, you name it IHS- it means when you use the compiler it will be dash GCC. What does a triplet mean? Well just really quickly the triplet basically tells you the architecture you're building for. Arm. The kernel or system you're building for in this case we're not using what's called a bare compiler. In other words we're not going straight on to bare hardware. We're going to an operating system. In this case Linux. So it's understanding it's on a Linux system. The GNU-ABI-IHS is a little bit more complicated. This actually tells us the runtime that we're using. The GNU part tells us we're using strictly speaking GLIB-C. That's what it means. People have taken this to mean different things. In some cases people say it's the GNU operating environment. But literally it's effectively GLIB-C and all those other bits and pieces. The EAB-I part is because Arm has changed its ABI or its application binary interface over time. Guess what the old one is called? Anyone's EAB-I? The old one is? Oh ABI. Why old ABI? Normally we're better at naming. But anyway that's how that works. EAB-I is the extended ABI. Pretty much everybody uses that now. You'll notice on the ARH 64 or 64-bit Arm we don't say EAB-I, why? Because there is no EAB-I. It's only EAB-I. Here we have to specify that we're using EAB-I and HF stands for hard float. In the past we had to do soft floating point because not everybody had a floating point operation unit. These days everybody has an FPU. So essentially it's faster for us to do that. This basically is the big grab bag that tells us what is our user space running system that we're doing. But anyway that's how we cross-compile a module. You do have to have the same compiler that was used to build the kernel in the first place. Okay so for installing a module. For installing a module. So essentially the way this works is if you use the command install at the command line does anybody know what install does? Install is a smart copy that's exactly right. It copies the file from here to there with a specific mode. And a specific user and so on and so forth. So install is a copy. The problem with modules is we have two concepts. We have an install and we have an insert. A lot of people think of intsmod as being install. It's not, it's an insert. So when we say modules install what are we doing? We are copying our modules into the pardon me this should be lib. I will fix this in the slides. lib modules uname minus r this is the revision of your kernel. So all of your modules live under lib modules and the revision of your kernel. And under that it can be found by certain utilities. For instance modprobe. We will talk about that in a few slides. But when you install a module you are literally going from here to there that's all. Nothing to do with the kernel. It's merely a copy operation. So again you will see that we are doing a make but we are doing a modules install. Now this has to be done as root. Why? Because lib modules is only written to by root. As a normal user you cannot build as root. We always build the kernel as a regular user but we install modules as root. Intsmod this is the first of the commands to actually deal with putting code into the kernel. Again it does an insert so it takes the module not an install which is a lateral move insert. It takes a file and puts it into kernel memory. I am moving that above because kernel memory is at the top of memory. And of course it causes the internal linker to add it appropriately. It adds it to the symbol table. It links it in all the appropriate places and so on. And the way you do this is you use of course as root you call intsmod and the file name rather of the module. And that can include the path or not depending on where it is. There are options you can add after and so on. But to do intsmod something.co is usually what you use. Now it is worth noting that quite often we will talk about module names and file names. Module names are the file name typically without the .co. The reason is because KO indicates a file and that it is a kernel object or module. However once it is in the kernel name anymore we call it by the module name. By convention they are the same. There are a few situations where they are not. But in general they match. Other tools don't like using file names. In other words you don't put the .co at the end. However people are lazy again and so if you leave the KO on it it often still works. It will just automatically take anything after the . away. What does this mean? Your modules can't have a . in it. If you insert a module with a . in it's name you are going to be having a bad day. LSMOD allows you to list which modules are currently loaded. Here you will see there are a few things. The first thing is that the very top module on the list it was loaded the most recently. The very bottom of the list was what was loaded first. Everything else is piled on top. Part of this is because of the data structure that is used as a linked list. Adding it to the beginning of the list is very efficient. The other thing is of course it shows you that in fact you are stacking modules on top of modules. Typically you have to remove things from the top of the list before you can move things from below based on dependencies. The way we see that is first of all you see we have the name of the module. We have the size of the module and bytes. We then have the reference count. Notice the reference count here is a 1 and there is no list. There is another module. That module is further down here. You will see down here we have a 2. This is the difference between implicit and explicit dependencies. Okay? In the case of an implicit dependency in this particular case our UIO code used a symbol from UIOP drive GenIRQ and by using that symbol it didn't say I depend on that module it merely said I want to use this symbol. The system that built the module in the first place realized that there is in fact a dependency there and in fact marked that as being a dependency such that when the module is loaded it listed which other module needed to be removed before we could be removed. So it is merely there for our convenience. Okay? Why implicit? Because the compiler and the build system figured it out. Okay? However, we also have explicit dependencies. Now these are harder to deal with because they are done at run time and so we don't actually have any symbol names or module names to look things up. Essentially those are just slow things down. So in these particular situations where these numbers are it usually means that a couple of things have happened but mostly it means somebody has a pointer into our memory. Who is that? We'd have to look the memory table and figure it out forensically. When you open a file for instance your file operations are cached in the i-nodes so that the next time you do an operation it's faster and other things like that. So when you open a file you'll see on a driver for instance you'll see its reference count goes up and when you close it it goes down again. For instance. This is why when the reference count is non-zero you cannot remove a module. Okay? So those are explicit dependencies. Our mod of course you use the name of the module to remove it so again it's sudo rm-mod and then foo. In this particular case rm-mod can in fact remove more than one module but it will do it in the order that you specify. Okay? So in other words if you have this module it depends on this module being loaded and you try to remove this module and then this module it won't work. If you do it this way around it'll work just fine. Okay? So the order matters as long as you have it correct it's really dumb it says this and this and this and this. Okay? Wrong order won't work. Depmod. Depmod is there to figure out dependencies. This is a bit that actually as you install modules will in fact build a number of databases. Again I haven't shown you all of them. I've shown you some. There's actually .bin versions of a bunch of these so that you have binary faster lookup versions that live under again under lib modules you name minus r and they're built by Depmod appropriately. We'll just talk about these five files or whatever text files you can look at them. The first one lets us know what alias is so that we can essentially ask for things by alias and then the appropriate modules loaded. We can do this by configuration of ModProbe. We have our built-in modules. Any built-in symbols that we have in the kernel we need to know where they come from and which modules are there. It's in there. Modules depth tells us our dependencies between modules. Modules order tells us the order in which case they need to be loaded. I've usually done it for built-ins and so on. We also have module symbols. This lists all symbols for all modules again so we can figure out dependencies. There's a few others but those are the nature ones. Finally we have ModProbe. ModProbe is a SMARC intsmod. Essentially what it does is it allows us to intsmod a module and what ModProbe will first do is figure out all dependencies satisfied for this module. If not, it will go and satisfy those dependencies for us. To load all pre-dependencies it will also allow you to deal with options. Normally you have to specify your options at the intsmod time. For ModProbe you can do that or you can set them up in files which we're about to look at in these two places either in ModProbe.com or in a series of .comp files so that every time you load the modules those are always set. It makes them persistent. Finally, ModProbe is how we tend to load things like drivers. When we need to make sure something's there we do a ModProbe of the thing and it happens. Just really fast before we get to the break which I should have done ages ago. If you intsmod a module twice what would you expect to happen? You can't insert it the second time why because it's already there. What if you ModProbe something twice? Why will it work? I've heard several different things you're basically all right together and the reason is essentially is because the question is different. In the case of insert it's saying will you please put this into memory? If it's already there of course it's an error. In the case of ModProbe what you're saying is is this satisfied? Have I satisfied this constraint? If you ModProbe something and then ModProbe a second time it's like super I have nothing to do. Yes, it's good. And this is how essentially the dependency system works. Is this dependency set? Yes. This one is too. Good. Let's load. Second time through it's just everybody. Everyone's a yes. And so for you to have to load drivers it's very helpful. It doesn't have to check whether something's already there. It's just ModProbe that it takes care of it. You're good to go. Excellent. Let's keep going. Okay, so it's a different thing. It's just for ModProbe you have to install modules first. With Insmod you can put them wherever you want to. Okay, for gosh sakes if you're building a product Insmod is not to be used in those situations. Install your modules, use ModProbe. Insmod is really intended only for people that are building code. It's meant for us. In far too many embedded devices where they insmod modules from weird places in the file system. Okay, don't do that. It's purely a development tool. ModProbe is the right way to go. Finally, in ModProbe configuration let's look at a foo.com file here. There's a few things you can do. You can look it up if you do a man of ModProbe.d. It'll show you all the different things you can do. But you can blacklist particular modules that they won't automatically load. This is great when you have more than one option for drivers. You can blacklist the ones you don't want. You can set options. So for the module called blah in this case we're setting multiple options. We can also alias things. So you can basically say, I want the sound system. What's the sound system? Well, somebody's aliased it appropriately so the right thing gets loaded. Oh, I'm sorry, a couple more. ModInfo allows us to show the metadata for a particular module. This is a very simple one. It shows you the licenses and dependencies where you're built-in tree, version magic. Any parameters are listed afterwards. And so on. So that's a bit longer than I wanted it to be but do we have any questions before we take a quick break and then hopefully come back and play with some labs? We had a lot of questions during it so let's take a quick bio break. I will do my best to come up with re-create my labs and we'll go on from there. Are we okay? We have people in this room. Sweet. As long as you're cool with that I'm just letting you know. The real problem is I don't want to push out anybody who's paid by having people who come in and sit down. Agreed. Agreed. Again, we handled that poorly and next year we have to say you must sign up for... Pre-registration required. That would have been smart too. We could have easily done that. I don't mind if people listen. I just wanted to make sure that you were okay with that. I didn't think it was a problem either. I was just more concerned about people who paid by having a seat. That's the most important one. I've told lots of people that if they want to say that's cool but if we run out of seats they have to leave. That's pretty much what I've said. I just wanted to make sure that I get a count in your job. That's really cool. I agree. But I need to start reading my labs again. I lost everything. Right before I had them all done and they're gone. It crashed. Well, that'll take us almost to the end because it's at four. This goes until four. So 10 minutes, 15 minutes tops. Agreed. No, I'm afraid we're completely out of them. The problem, unfortunately, we had to limit it to 50 slots and we sold out this morning. We will have them online for sale in the future but we're not there yet. We actually weren't sure we were going to sell out but you're like the 10th or 11th person to ask. I apologize. If you look at this, you'll see at the very bottom we have a Hello module loaded at. Okay, and this is in fact the print K that was in the module code. Unfortunately, most of the beginning of this walkthrough of course was not mic'd. So that's no fun. Anyway, so that's how that works. How do we remove it now? Well, we do this by doing this to do RM mod trivial and if you like command line completion you'll notice that RM mod on a mod probe based system using bash in fact it's bash completion which is kind of nice. On your average embedded system that's only using busy box you won't have that option. So in this case I'm taking advantage of a fully functional system and of course I can now remove it. Again, if I do de-message and in this case I'm just going to run it through tail to give you the last little bit of a try. Okay, that's pretty much it. Okay, let's try this one more time here. We're going to do a make clean and this time what we're going to do is we are going to copy trivial.c and we're going to copy it to second.c and what we're going to do is inside trivial.c we're going to add a new entry and maybe I'm going to do it from over here so I can see what I'm doing. Okay, so what I'm doing is I'm adding a function in trivial.c in such a way that it can be loaded from the other module. So here we have where is it here? What is going on? So you see we now have this updating screen in a very strange way. We have something here that says foo, it's a foo module and I have no idea why it's updating like that. Let's maybe get out and come back in again. Alright, well these are in different lines in my file in any case the whole idea is that foo is going to do a print k and you'll notice I have not made it static. Okay, that's the most important part. Now what we're going to do in the other module which is second is now in the init code here before we do the return and again it looks like the flow is a bit different. I'm actually going to make the change in my from my laptop here again just so I can see what's going on. Okay, here I'm going to reload the file. You'll see here that I've done a couple of things. The very first thing, oh wow that's really strange. Let's maybe cap the file, maybe the editors doing some funny things to the there's two things I want to point out. The very first thing here is that I have declared a function called foo and it happens to match what is in the other one. Normally it would do this in a header file but I'm being lazy. You wouldn't do this in real life. Next you'll see that I'm calling that function down here. Now as long as everything matches it's all good. Now, strictly speaking this is a very simple function so I actually didn't need to declare it. It merely would have caused a warning but it's good practice. So in this particular case that's all I have to do and then of course provide the function in the other file. And again in a way that theoretically it should work. Except for one thing that I didn't think of. And that is in fact we need to extern it. Again trivial dot c. In fact it can be static thinking about it. But I have to do an export symbol. Because again we need to tell the internal linker about it so it works appropriately. You'll see here that I've actually been able to make it static and I've called export symbol in order to make the appropriate function work. So what I'm going to do now is I'm going to whoopsies build it. And so I'll get out of here and I'll do a make. So the thing about externing is you only need to do externing for something where it's stored. So for a variable. Functions we provide prototypes all the time without externing. So you don't need to extern function pointers. I do unfortunately need to add this to the make file. So let's just quickly edit that and for some reason silly things. So let's do the build. Here we're going to make. This will be the last of this because that function isn't a oh isn't a prototype. Yeah. I'll just get rid of that. Again we're not relying on the we're not relying on the compiler linker to do this. So it can be static. The fact that we are exporting it using export symbol is sufficient. It's just that the compiler itself gets gets messed up. So I'm making a mistake of some sort that I am not seeing trivial. I shouldn't have to. It isn't a prototype. Nobody is seeing if you don't need to provide it in this particular case. I guess the kernel does. Oh we will try that then. You're probably great. Yep. The function version isn't a prototype. Void foo. Okay. Sadly we're out of time anyway so it doesn't matter. All I wanted to show you here was that in fact when you build the two together this is what happens when you try to root code on camera. All I wanted to show you was that when you have modules and one depends on the other when you insmod them out of order you get an error. That's pretty much all I wanted to show you. Once we install them and then use modpro it would have automatically loaded them into the appropriate order. Okay. Anyway that's it for today. Unfortunately we've just run out of time and we need to get on to the next presenter. The next talk that we're giving is on Uboot. But otherwise for those of you who are here to see modules in KBuild I hope I answered your questions. I hope you know more about modules in KBuild and I hope this now brings you into the ability to write your first kernel code. Yeah. And we have a couple of questions. I'll take two questions and we're going to have to move on. So it'll be under user source by default. That's where the package puts it. No you have to install the package first. So the package, yeah. Yeah. Nothing. We're going to give you those on a USB stick. So yeah, it's nothing you need to do. Okay. So the next talk is momentarily. One, two, three, four. And I'll make adjustments that's necessary so we get a good level. Okay? Thank you. Can I ask you to do another favor and wear another mic? Yes. I mean it's going to be recorded by the conference so you can just get the recording from the conference. Yeah, it's going to be recorded. Okay, thanks. Okay, I'm starting. Speaking of which, do we have an interview tonight first? This is Meric from That's Right. He's been working on Youboot for a really long time and he's here today to talk about Youboot. So he's going to be able to talk about Youboot legal but just generally how to do it the right way. So, if you're talking to Youboot, that's the right way. Yeah, can you actually hear me? If I... It's probably not on. It says on, but it does say on, doesn't it? Yeah, I don't see. Test. One, two, three. Okay, so it has to be... Is this better? What about now? That's one, two, three. What about now? One, two, three? Yeah, I mean if I have it like here then it's working but it's like... Yeah, anyway, so I guess I'll be talking like that for a while. Let's get to the Youboot talk. Just like BN said, I'm a software engineer. I work on Youboot, Linux, open and beat it. And this is the stuff I work on mainly. I'm a maintainer in those three projects, one way or the other. In Youboot I do USB. I do SOGFPGA, RENASAS stuff. Yeah, and both active maintainers there. Can you just assemble it for me? I can do that. I can do this. I'm going to put it right here. Let's see if it's in... Yeah. Test. One, two, three. Hello. Test, one, two, three. Test, one, two, three. Yeah, absolutely. Where is it actually? Yeah, go ahead. Let me look at it for a second. No, that's in good shape. I know what's happening. It's pointing away from you. Yeah. Whatever. How is it now? Can you hear me? One, two, three. Yeah, test, one, two, three. Does it work? Test, one, two, three. Yeah, there we go. Test, one, two, three. Okay, yeah, well... Oh, yeah, this is so much better. Super, thanks. Yeah, so I wanted to start with a slide about booting a computer. So basically what happens when you turn on the device which you have on your desk is that there's some sort of power sequencing happening in the CPU obviously but then the CPU has to end up somewhere in the memory which is called the reset vector and in that place in memory there has to be some initial code. Now this will be your first stage bootloader. It's nowadays going to be in the chip because the technology is just advanced so significantly that people want to boot from something else like a little flash. So there is some sort of bootloader buried in the chip which does the initialization of the platform and then loads the next stage bootloader from some external media which can be like SD cards or it can be USB, it can be whatever, something more complex. Usually this second bootloader is loaded into an on-chip RAM. The pocket eagle the MLO it's loaded into the on-chip RAM executes it and that again the initialization of the platform usually brings up the DRAM up the Uboot is proper into the DRAM executes Uboot in the DRAM and after that Uboot loads the Linux kernel into the DRAM executes Linux kernel and Linux kernel does its thing again. So this is basically the multi-stage loading which happens today on a contemporary platform. It didn't have to be it wasn't like that every time back in the past it usually happened to be that the CPU core had the address was directly routed to the part of the chip and you just attach the barrel of flash and the CPU could just directly boot it from the barrel of flash. So your first code running on the core was something you controlled nowadays it's not like so. So the first replaceable code on the Pocket Beagle is Uboot and I would like to talk about this today. So Uboot is a bootloader it does the one thing it does it can load the next stage and execute it which usually is Linux, it can be anything else, it can be VST whatever, doesn't matter but it can also be used as a really good debug tool and boot monitor. That means like Uboot can start the Linux kernel right and then you will not see it again but it can also drop into Uboot shell where you can like poke registers operate buses and so on, debug your platform which is really useful not only if you are like trying out new hardware but also when you have like your platform for example out of manufacturing you want to check out quickly or not. And I would like to show you how to use that Uboot shell and really like how to poke the hardware test out everything. So first of all, this is how Uboot looks like. If you power up a system what you see here is the Uboot SVL that's the Uboot tree loader and that just loads the Uboot dropper from the in this case SD card into DRAM after initializing it and then it starts the Uboot dropper the way you can identify that these things start it is by them just printing out on the serial console that they are running this print the Uboot SVL and Uboot information is like the first thing Uboot prints out on the serial console to notify you that hey, I'm running like at this point everything still works. What else do you see here? Uboot itself Uboot dropper will print which CPU it is running on how much Tiki RAM you have it will also print the board name which is somewhere down here right in case you are getting or trying to get support from the Uboot community you should include definitely the Uboot version in case you have some extra patches you should include that information as well that you have some extra patches you should definitely include which board you are using now, once you get through the entire Uboot boot log you will get to the auto boot countdown the Uboot will be running this countdown if it reaches zero it will just do the default boot action if you interrupt the boot countdown it will drop into the Uboot shell minor note on the Uboot SPL versus Uboot there are three different things actually which you can build out of the Uboot sources nowadays you will usually meet only the Uboot SPL and the Uboot proper and what that means is that with modern platforms the first thing that happens or that can be loaded is some sort of small piece of code like tens of kilobytes big which has to initialize DRAM so you would get this for that and is able to build like a stripped down version of Uboot which will do the DRAM initialization and then chain load the Uboot proper, this is what the Uboot SPL is there is also possibility to build even smaller version of Uboot which is the Uboot TPL you will likely never run into that but just so you know it exists it usually is present on devices which have like Samsung one end and we are talking about like unit of kilobytes big artifact built from Uboot sources which basically is responsible for loading like the Uboot SPL into the on-chip RAM executing that and then Uboot SPL is responsible for initializing the DRAM loading Uboot proper into the DRAM and executing Uboot proper so on some specific devices you may also have to use the Uboot TPL but usually you are never going to run into that one so that's it for the interaction into Uboot now I would like to show you some commands which are useful in Uboot first useful command is echo which allows you to print whatever some string it doesn't interpret any control sequences except for C control sequence which says do not print new lines otherwise it doesn't behave like the shell echo which does support interpretation of the control sequences the other thing is health command this is really useful because even if you get like completely alien platform which you have no idea about what it can do if it runs Uboot if you get into the Uboot shell you can just do health it will print you all the commands of the Uboot support so you'll know what you can do with that Uboot now you can also do like health command which will give you more detailed information on that command and this is useful even if you are like confident with Uboot but you just don't remember what's the order of like arguments for specific command you can just do like health command and get this information in this case it's like health which you can see in here so what can we do we can stop the USB we can reset the USB bus stop it we can get the USB 3 listing we can get USB test mode running that sort of stuff so you can get like a detailed health if you need further help you can look into the Uboot documentation which is in the Uboot sources you can see it down below here also in case you have some specific question you can visit the Uboot IRC it's on 3.0 hash Uboot I mean if you ask questions please wait at least like a while don't just immediately leave because no one responded to your question quickly the people maybe like in Europe you know just ask at the time when they are asleep okay they just cannot reply and if no one really replies on the IRC which usually doesn't happen but it can just ask in the Uboot mail list so that is for getting health now getting for board info even if you have like a board which you know about just want to check what the board is about is done using the bdinfo command in here the interesting parts are DRAM information here so basically Uboot is using just physical addresses and in case you need some sort of memory with which you can operate on the Uboot shell you just run bdinfo look at the memory layout you see okay there is a DRAM it starts at 8000 on this board what is that yeah here it starts at 8000 with 8000 big and this is the idea which you can use for whatever you want loading files experimentation whatever it is just a small detail that Uboot itself will allocate itself at the end of the DRAM so you should probably avoid like the last 16 or so megabytes of DRAM because otherwise you can put up the Uboot or its structures and bad things will happen the system will become either unstable or it will hang or something like that so like using most of the DRAM is okay it's just the last couple of megabytes which are not okay you can also see at what location Uboot itself actually relocates it it's the reloc address somewhere down here I actually have to look it up yeah the reloc adder at the relocation address which Uboot placed its code but this does not take into account Maloch area which is like above that and Uboot stack which is also above the Maloch area you should like round it up a little and then avoid that piece of memory I mean you have plenty you have like 512 megs of memory anyways there's some other interesting stuff in here Ethernet address which is like the current Ethernet address we can't really make use of that on the Booked Beagle but I mean because you have a board which has actual Ethernet then yeah the current Ethernet address is also in this list thing alright so now that you know what your memory layout looks like you can also do something with the memory like read it write it for that we have the memory dump which is in the comments MW and MD well they allow you to access both DRAM and device registers and device registers can be sensitive to access with they also support of access which allow you to select like how wide the access to the register should be we support byte what else do we have here board access which is 16 bit long that's the default that's the 32 bit and quad on 64 bit platforms which is 64 bit access by default the MD the memory dump will read 64 words of data but you can specify how much data you actually want to read out from the memory that's an argument to the MD another trick is MD and some address potentially some amount of data and then it will dump that much data if you press enter one more time it will dump one more time that many data again so like you can do like MD some address okay but I want to read some more enter will read some more and so on this way you can keep dumping the memory you can actually see it at the end here so this is just a matter of pressing enter here okay you can also use these commands to access device registers in this example here I'm using it to toggle the blue LEDs on the pocket beagle board so what I do is first I just dump registers of the GPIO controller this is something I fished out of the data sheet for the OMAC chip so I noted that address 4804C130 there is GPIO controller direction registers then there is input register then there is output register and value register something like that so I said the direction register here most of them are inputs the two zero are outpads that's the four LEDs then I can set the outpad value register using the MW command to just turn on the LEDs you can just try it on the pocket beagle yourself you will see that the blue LEDs come up now this particular mask I'm using here are converted to like these face masks here and just these four specific bits which are connected to the same GPIOs which control the LEDs on the pocket beagle there are a couple of additional commands which allow you to spoke around with memory which are not that well known and are less used it's memory modify this command if you run it on some sort of address will reach out the value on that address you can run it on the command line and ask you which value you want to store to that address so if you supply a value it will store it to that address if you just press enter it will do nothing and automatically increment the address if you supply minus then it will go like one address but four so this might be interesting if you want to interactively operate with some sort of register or something also NM which doesn't do the automatic increment of the address so you can basically do something like NM 0x4804 C13 C C13C this will allow you to change the GPIO controller output register and then you can just specify different values and toggle different LEDs or off with that? this is just syntax highlighting which went wrong sorry about that it's probably just chill syntax highlighting yeah but this example is just showing that you can do the NM on some sort of address it will read out that address you can specify something if you don't specify any value here it will just skip the address and this is basically the LED example done using the memory modify command oh and if you specify Q then you can just exit from the command okay last two commands which are kinda useful, CP is memory copy the same thing applies as on the memory dump and memory fright and CMP is memory compare now this is useful if you are debugging stuff like you are reading data through some sort of bus and you want to be sure that when you read the data twice that the data are exactly the same for that you can use the CMP command in case the data are the same the CMP command will tell you so in case they are different the CMP command will tell you that there is this sort of offset that offset the data are different these are the tools for manipulating the memory and checking the memory but what I would like to look at next is the UBOOT shell so UBOOT actually has two types of shell which you might run into nowadays by default it should be the hash shell which is like much more modern much more sensible shell but there used to be a shell version before that in UBOOT and it was really painful to use that so you might have run into this and the experience was probably not so pleasant hopefully nowadays you will just run into the hash which is imported from busy books some time ago but anyways if it's a pain in the... then you are running the old one pretty much you will notice severe limitations of the shell if you try to do something what's that? behave like a bone shell then you are quite a simple test in that for example I believe TAP completion didn't work on the previous one so you can try that one for example anyway I am still focused on the hash shell because this is what is enabled on the beagle as well anyways and I would like to talk about that one similar to what you are used to with your bone shell on your regular PC and also it does support environment it does support environment persistency you can have scripts in the environment in addition to values so that's what the UBOOT shell does now the UBOOT environment is pretty much what you know from your standard shell storage but there are a couple of details to it first of all the default environment so the default key values are stored in the UBOOT binary that's the default environment but on most of the boards there will be some sort of dedicated UBOOT environment storage so that when you save the UBOOT environment it will be stored in this additional environment storage and when you power cycle the board whatever you had in your environment if you save that it will not get lost but it will get loaded from this storage UBOOT always has a life copy of the environment which is in the RAM but unless you explicitly save it into the storage it will get lost so you can kind of change the life copy of the UBOOT environment do whatever you want with it if you reset the board then all those changes will be lost unless you explicitly store it so you can experiment with the UBOOT environment whatever you want you can do to it and then just reset the board and you will start from scratch which is probably convenient at this point now to operate the UBOOT environment there are a couple of commands for that print the environment content if you just run it like so without any arguments it will dump the entire environment on the pocket beagle the environment is quite rich so if you run like printend it will be just really really long list you can also just say ok printend specific environment variable and it will just print that one for example printend arc will print arm because arc is arm there might be a bit of a confusion about printend and end print so the situation is as such recently we decided to consolidate everything under the end command so you should be using like end print end save end whatever this is the modern way to do it obviously for compatibility sake and because you will see it all everywhere on the internet there are legacy aliases like printend saveend so that's just to clarify the situation so ok now we can print the environment great you can also access the environment as a variable so if you do like echo dollar arc like you see at the bottom it will also print arm so whatever is in the environment whatever keys are in the environment you can access them this way as variables now if you want to modify the environment you can use setend just setend name of the variable and then the content or a hence set that is an alias for that you can also do like 3d questions if you want to pull the user for some information using askend and you can also if you have some sort of like long script in the environment you just use the edit end and you can kind of move left and right in that script tweak it then when you hit enter this environment variable will be adjusted so you can use those and finally if you did some changes to your environment you want to make them persistent so you can use saveend this will just commit it into the environment storage now in case you want to undo that stuff if you want to just get back to the default environment you can use just like fdefault-a this will reset the local copy of the environment if you want to make this persistent then you can do like fdefault-a and then follow it by saveend so that's the environment access yeah there is not you would probably have to do that yourself on the remote machine side there is not patches are welcome yeah okay so anyway that's pretty much for all the environment variables you can also use the run command to store scripts in the environment so if you have like environment variable which you set to like echo hello and then you do run name of the other environment variable it will run just the script in this case if you do like run foo it will print hello because that content of the environment variable is just evaluated as script you can also chain multiple of these commands using the semicolon operator that's just like you know it from the shell just like you know it from the shell it just ignores the return value of the previous command so it will just run those commands one after the other in this case hello world it will print hello as the run command but yeah there is one pain point here which is the u-boot environment variable people keep running into this one if you do like if you want to set some sort of script in the u-boot environment which is accessing variables it just so happens that you will run into this first case where the line 2 is immediately evaluated and then you wonder okay well why is it printing like something which I do not want yeah because it is immediately evaluated that foo variable there now to work around it the best way to do it is just to use the single quotes around the entire script content when you're setting it into the u-boot variable just like it is done here at the end that's probably the best practice around it you can escape the dollar sign but then if you start chaining the command you will have to start escaping the semicolons and all the other dollar signs so when you have more complex script difficult using the single quotes around the entire script is just so much easier so there is that another thing is you would have a couple of variables which have special meaning ver will always contain the version of the u-boot bootloader so if you want to inquire for example your customer okay which version of u-boot are you running you can just tell them okay either run the ver command or do like printend ver and you will immediately get the latest information which version he's running if you have multiple like standard input path possibilities you can configure those using the std and std out std adder variables if you set that variable it is immediately triggering the change in the input out path so be careful about that interesting variable is load address so if you are loading any sort of data from anywhere this will be the default load address and u-boot will load those data I'll get to loading commands in a bit now once the loading is done u-boot will set the file size variable and that will be the amount of data that u-boot loaded so like if you load for example a file from smmc and you want to print it you can do like md whatever dollar file size and it will print exactly the amount of bytes that was loaded so this is the automatic variable which is useful, really useful it is also useful if you want to write to a flash storage when you downloaded some file from let's say tftp and you want to write the exact amount of bytes then you can just use the file size boot command is the default boot command so in case you have this auto boot countdown when you just start it up if the countdown counts to zero it will run this boot command which is the default command which is executed then and it's usually meant to stop the Linux kernel boot arcs Linux kernel boot arguments interesting variable is preboot now this will be useful for example if you do some sort of commissioning this is a script which is executed before the auto boot even kicks in so in case you have something which needs to be done at that point you can put it into the preboot environment and it can be useful if you have it built into your default environment and then in the preboot you do your one time thing for example one time provisioning of the port and then set on preboot to clear it from the environment and then save and to write the environment into the system so the next time when the system reboots there will be no preboot variable and it will just not do this provisioning action anymore then there are a couple of variables which are used to configure network IP address matmask server IP pth adder for MAC addresses and finally there is one last command which I would like to share with you about for manipulating the environment which is set expert this might not be present on all the systems but it's really like an environment manipulation like Swiss army knife sort of device so this one allows you to well it allows you to do basically three things one is load memory content into uboot variables another thing which allows you to do is automatic operations both on uboot variables and on memory addresses which can be useful like if you are doing for example loops which need to ball some sort of bit somewhere in memory or whatever you know you can do like plus minus bit the standard multiplication division and you can do also bitwise operations which is useful and in case you have regex support in uboot then they also allow you to do basic regular expressions so you can like have a variable in the uboot environment and apply basic substitution on it for example including like back references and this sort of stuff it's all there so that's what you can do with an environment but with the uboot shell you can also do conditional stuff basic things like true false commands return 0 for true false returns non-zero it also has return value so we can have uboot check for that and we also support the dollar question mark variable which prints the return value of the previous command we also do support the shell if conditional where you can provide whatever if command then do some operation else do some other operation that this one we also support the short-term for conditional expressions with the or or and this is also supported here is some example of that so if true echo call hello will print hello obviously so there is that we support test command so we can like use the standard shell test command which allows you to do like arithmetic comparison and string comparison this is all supported as well you can use it in the if command so like if test something something then do something this is supported there is one small detail about that is we do not support if negation that means like if not something then do something is not supported but what you can do is like something then do true else do whatever your desired operation is we support for loop iteration over the list of elements that just like you know from the bond shell for loop while loop is also supported this example here will run indefinitely so you can like press control C to abort this while loop this one and that is pretty much for the input shell there are also hardware manipulation commands here is the GPIO command which you can use to manipulate the GPIO pins on your board we support reading out the GPIO input which by the way also has a return value so we can do like if GPIO input some number of the GPIO then do some action this is also possible you can set the GPIO you can clear the GPIO you can toggle GPIOs using this command so if you need to poke GPIOs in the input environment you can just do that I2C commands commands for accessing the I2C bus on the pocket beagle you have actually multiple I2C buses if you do like I2C bus you will see the list you will have three of them and you can use the I2C command to operate the devices on those buses I2C DAV allows you to select which bus you want to access you can access only one at a time so you have to always like switch with I2C DAV and then you can do something like I2C MV to write memory or MD to dump memory convenient is I2C probe it allows you to like probe the bus for devices which are sitting on the I2C bus one thing about the I2C probe is that it can confuse some old I2C devices so I2C by default it's not bus which you can probe nowadays it works mostly but there can be some devices which will just be confused by this like probe action so be careful about using this one and I2C speed you can set up the I2C speed for example here I'm accessing the accelerometer actually on the back on the escape so I'm setting I2C bus to 2 because the accelerometer is on bus 2 and then I2C probe I see there is just one device the accelerometer okay I can just read the registers using the I2C MW I specify that it's supposed to be chip 1C because that's the I2C address of the accelerometer and I'm reading from 0, 8 bytes and this is what I get out of it yeah success I did manage to read some data out of it okay so that's for hardware poking commands next thing loading from storage so you can access different kinds of storage SATA, SDMMC NAND whatever you can have a dedicated command to access the raw storage and its common properties but you can also load from file system maybe you have the file system on like SATA DMMC USB sticks whatever so for that you can use the load command or ls command to list that storage device there used to be times before this generic interface was available where did have dedicated command for listing XFS listing VFADFS so you might run into ubooth which will have like these commands XLS, XLOAD, this sort of stuff but nowadays the modern way to do it is just with ls and load the generic interface which detects the file system here's an example of loading file from SDMMC so what I do here is first there's a lot of extra stuff but first I re-scan the MMC so that I have all the latest information from the controller then I'm looking at the partition table I see that I have only one partition in here which is of type Linux there is probably X file system on that I can list the MMC in this case it's controller 0 partition 1 I see that there is some sort of file it's perfect I can load the file to load address which is the default load address I'm just specifying it there and then I can dump the content of the file and I'm using the file size here because ubooth conveniently set that up for me to just exactly dump the amount of bytes that the file has we won't be able to exercise this one loading from network but ubooth has a network stack in it it's UDP only it doesn't support DCP but this is not that limiting and it significantly reduces size so this allows us to use ICMP obviously, ARP and then we can use TFDP we can use NFS over UDP we can use DHCP to obtain information from the network in order to use the Ubooth network stack you need to set up a couple of properties obviously you need to configure your network in case your vendor does not provide you with any way to obtain MAC address you might need to set that one up as well and then you can start just using ping to test whether the network connectivity works, you can TFDP download files from your TFDP server or you can just use DHCP to obtain IP address information and then download the files that's how loading from network works now if everything else fails and you just have no way to get files into the Ubooth you can still use load yes which is which allows you to load files over serial line so the way this works is you would support multiple of these protocols actually we support Xmodem yesmodem and Kermit and in this example I'm using the EA modem so you just do like loadie you can specify also an address here to which you want to load the stuff and then in your terminal emulator you just say ok send over ymodem this file and you would be receiving the file and storing it to that address it is useful in case your internet for example doesn't work for some reason then you still want to yeah but I can just look it up if you want ok but that's a valid question actually I would like to look it up thanks so you can just load stuff over serial and I would like you to actually try this one out now finally it's bootloader right so you probably want to boot the kernel but even this is not that easy because if we have like a fillet in the Linux kernel format on ARM you will find that image which is the raw one which is basically a the Linux kernel image with a decompressor it's pushed together you just put it into the RAM and basically set a couple of registers just jump to it and the Linux kernel starts loading there is no protection against Petra now in the times of old there was an attempt to solve this problem and the U image came up which is like U boot image but it's been legacy since forever because it's like just an envelope for a file so there is CRC32 and there are a couple of metadata in that U image which say like where that image should be loaded what's the entry point and a couple of information about that image but the CRC32 is just today it's too weak it's useless so this has been legacy but there has been image format which supersedes that and that's the fifth image which is like a multi component device tree based image format basically I'll use to provide some sort of device tree specification and pull in blocks like the Linux kernel the device tree blocks and then have configurations which say ok this kernel goes together with this device tree and you will know how to interpret that including device tree and so on and you can bundle any amount of blocks you can configure different checks some algorithms and so on so this sort of flexibility is what the fifth image is all about in case you're building some sort of embedded device definitely look at the fifth image because this is what you want to deliver in the field now using the kernel it really depends on which image format you have that use different commands for that so for the images we use boot set for uimages and fit images we use boot m you just specify like the image address in case of the boot set you might need to specify also device tree location if your machine is device tree capable and you can specify also in the address there we go on app64 you have boot e because for some reason boot set was not good enough so we have to use that one and here's an example of booting the kernel so first of all we need to set some boot orcs because otherwise the kernel would not know where to send the serial output then we just load the vm linux we load the device tree and then use boot set somewhere around here to start the kernel with the device tree address and then the kernel starts booting so it's that easy to boot a kernel on the vehicle now speaking of device tree you would also be able to manipulate the device tree using the device tree command so when you load the device tree from your storage into the RAM the fdt adder pointed to that address of the fdt in the RAM and then you can modify the fdt in the RAM in case you want to modify it you need to first do fdt raise size because whatever you just loaded into the RAM is like the flat on the device tree blob and there is no extra space so if you want to add nodes you first need to do fdt raise size to have you boot just add some extra space for your new nodes once you do that if you want to do fdt print to print whatever is in the device tree you can do fdt set to add new nodes into the device tree and all that is done on that device tree blob which you loaded into RAM so if you don't boot that with a Linux kernel and that blob the Linux kernel will be given this modified device tree blob so if you want to experiment with tweaking the device tree yeah so what you can do is you load your device tree into the RAM in uboot then you use this fdt command to like point uboot hey here is the device tree and now the fdt command will be able to tweak the device tree or like add new stuff to it remove stuff from it yeah you have to load the device tree manually into RAM so the way booting the Linux kernel with device tree works is that you load the kernel into RAM load the device tree into RAM and then you say assuming that it's a Zed image then you say ok so jump here but with these registers with these encode registers which point to here in the RAM where the device tree is sitting and the kernel will boot it will start executing and the first couple of instructions in the kernel just say ok if these registers are set to these specific values then this kernel is being booted with device tree capable bootloader and the device tree is telling me hey the bootloader is telling me like the kernel the device tree is somewhere in RAM and I should use that address for the device tree location so yeah you have to do it explicitly yourself like load everything into the RAM and then say boot Linux device tree yeah the bootloader is passing some sort of register settings to the kernel and the kernel is interpreting those early on in the boot it could also be that the bootloader will pass a tag to the kernel at which point the kernel is likely not running with device tree so this is what happens like in the old times when ARM was being used without device tree yeah here's an example of for the fit image content so this is like the device tree describing the fit image where you can see here is the kernel blob being pulled into the kernel section you can specify a lot of properties your name where the kernel should be loaded was the entry point of it here I use hash algorithm for this kernel section which is like CRT32 but I can have like secure hash algorithm 1, 256 whatever I can also have like this section digitally signed to prevent tampering here is an FDT section which is pulling in device tree it's an ARM device tree with again CRT32 and then there is configuration section ultimately here which is tying together this kernel and the device tree again it can have a different checksum algorithm it doesn't in this example now if I have this sort of fit image source file I can compile it with MK image it will generate the blob which I can then boot M on the machine and the blob will contain the kernel image the device tree and people will know where to put those and where to start those so the final bit is getting the UBIT sources you can get them from the Git repo here in this specific tweak from a maintainer you are in touch with a maintainer he might point you to one of these forks which are the maintainer trees both of that is available through both Git and ICDPS protocol in case you were trying to clone UBIT sources recently it could be that you had some trouble because we just replaced the server so I think last week the server could be that you were not able to get easy access to these repos that should not be fixed there are also sources for the UBIT available on that USB stick you have now if you want to build the sources clone them export architecture for which you are building in this case this would be ARM export your cross compiler prefix which will be like ARM Linux or ARM known whatever and then make your board Defconfig and make the board Defconfig in this case is going to be like a M335X Pocket Beagle Defconfig you can check if the Defconfig is present in the config directory so it has to be there otherwise you wouldn't be able to configure the UBIT and then just make it it will generate the UBIT binary for the Pocket Beagle that's UBIT IMG and the MLO and that's it for the intro part do you have any questions this might have been a little bit too much yeah oh yeah you do like safe end then this will write it into the storage so there is this environment storage partition whatever depends on how your board is set up into which the environment will be stored and this will be persistent at that point so if you do safe end it will be made persistent and it will be a local snapshot of the environment any other questions if you can disable the autoboot it will still check yeah I usually set it to like really long value when I do development but I do not think you can disable it from the UBIT shell you have to tweak the UBOOT itself there should be some configuration option to disable autoboot but I would have to look it up what that is try something boot delay to minus 1 that might actually work quick break back to the last 10 minutes then we are going to go to the lab do you have some labs do you have some labs to be able to try yeah absolutely so there is a practical part when we come back we will do the practical part of the board incidentally you can play around with the UBOOT a little does everyone have their beagle accessible was that yeah I will help you okay BN the people who left didn't have board yeah there is a question about windows don't worry you are doing great yeah someone will help you within a bit yeah okay so task zero just drop into the serial board to get into the UBOOT shell see if you can do stuff like version or help if you can access that super that is task zero I will give you a couple of minutes for that so if you are getting bored let me know the slides are organized so that alright before you start discussing stuff and the slides are organized so that there is always some sort of task here which you should do and then on the next slide there is a solution for that okay so task one is just to drop into the UBOOT prompt task two is to conveniently load content into your UBOOT environment using the load y command please try it out this way you can kind of develop your UBOOT script and then load y them into the UBOOT environment so you will have always a sort of local copy of whatever you created for the UBOOT so that will be task one zero and one are nothing exciting do you all have actually access to these latest slides okay if you don't have access to them they are on the EAL github repo so please download the latest slides in case you get bored you can start moving forward with a subsequent task and if you have a problem with task zero or task one raise your hand and let me know if you need assistance so you can just create your text file that contains like key equals some sort of value yeah exactly just save it as a text file and then use the load y to load it into the UBOOT and then import to import that file yeah actually if you look into the slides like a couple of slides before that you will just find an example of it you can kind of put it together and it should be easy on the next slide there is also an example yeah in the github there is a latest slide loading environment over serial port into UBOOT loading the environment yeah just like key in a minute set in no just using loading oh loading the file yeah over serial port and then import that content into your UBOOT environment you can have like your custom scripts written on your PC and then just import them into the UBOOT environment conveniently so who of you actually is in the UBOOT shell right now can you raise your hand for the rest of you do you have some problems with that or do you need some assistance yeah just get there yeah yeah but you are now in the on renex so if you reboot yeah if you reboot then eventually you will get like this this sort of out pad this is what you will get so then just press space and this will drop you into the UBOOT shell I think yeah or you can just press the reset button on the on the board there is like one in the middle one of these three buttons yeah just try all three of them something happened there super so I figured I should explain task one a little bit more so the idea here is that use the load e-command to load some sort of file containing environment and import it into your UBOOT environment so that you can conveniently this way import UBOOT script yeah yeah no there is not but you can like use shift page up shift page down I think so should work maybe it is the terminal emulator property what are you using for the terminal emulator what was that can you help up with yeah going up and down there is like escape something like that I think it was like control A escape escape like escape and then you can go page up page down okay oh did something happen maybe you too can kind of cooperate and figure it out yeah oh that is the one yeah oh cool nice so yeah so here is the question did you manage to get this loady working with the Y modem at all yeah so the question is what are we supposed to do with this task so what I would like you to do is prepare a text file which contains the uboot environment that means like a key and a value doubles in that text file then use loady to load that into memory and then import to import that uboot environment this is what I would like you to do here in this one what was that I don't have an example text file but you can create one that's this sort of yeah yeah and you can probably also put some sort of script that like you know foo equals echo bar something like that this is kind of how it should look like so if this is readable you can just create a random file then use loady and send it over to imodem when you finish loading you can just do md.b load address file size load it and then use import to import this environment file this is what I would like you to do to try this sort of thing what's that what's that yeah in the linux command line you just like use the cat command which means read from standard input until you type eof do you have a linux machine I do run you shell in your linux machine oh no I'm in your development machine