[MUSIC] So this lecture, we'll talk about a comparison between Python and C, C++. Because Python is what we're going to be using with the Raspberry Pi. C, C++, we'll be using with the Arduino. Also we'll talk a little more detail just to understand the contrast. We'll talk about the tool chain, the software tool chain. All the tools that go into taking a high level piece of code, and getting the eventual machine code. We'll just look at that whole picture, cuz it ends up looking a little different for one versus the other. So, Python is an interpreted language. It's a scripting language, but that's also an interpreted language. It's high level language. It's easier to work with, because it's interpreted. So there are certain things the programmer does not have to deal with, like the type of variables. Is it an integer, is it in floating point, is it a string, you don't have to worry about that in Python. Python figures that all out based on how you use the code, ow you use the variable. So at run time, while it's executing and doing an interpretation, it can figure that out. Other things too, like memory management, in C, C++ you have to deal with that. You have to say, look, I need more space. There's a function called malloc, you can allocate more space, I need more memory for this variable. Python, you don't have to say that, it'll just make it for you,right. And when you're done with it, it'll get rid of it. So where in C you, have to make it explicitly, and you have to, as a programmer, have to know oh, now I'm done with it, let me free that memory. So there are a lot of these burdens, these programming burdens, that you don't have to deal with in a language like Python, because the interpreter is there take care of it for you at run time. Now comparing that to C, C++. C and C++, they're related languages. Actually, C is Is a subset of C++. So C came first, C++ came second. C++ is a super set, so C++ does everything that C does. So if you have a C++ compiler, it'll compile any C code. But C and C++ are compiled languages. So you write the code, you compile it once, and then you get an executable, which is machine code plus extra information. And you only execute the machine code. You don't have to do the interpretation at run time. So as a result C, C++ programs are generally a lot faster than Python programs, but the programmer has to deal with a lot more details. Now, dealing with a lot of details is hard. But when it comes to embedded systems, it's often useful because sometimes, not just sometimes, often the programmer, an intelligent programmer, can write code more efficiently than the Python interpreter can. Okay, so the programmer, knowing something about what the behavior they expect, they can write their C, C++ code in such a way that it runs a lot faster than the Python interpreter could ever predict, cuz the Python interpreter, it's dumb compared to a human, right. A human can know something more about the context in which the software is being used. So in C and C++ are commonly using embedded systems. Outside of embedded systems, you see them used less. Maybe Java is favored, or something like that. But because of the level of control that you get with C, C++, they are much more commonly used in embedded systems. So compilation, this is what compilation looks like roughly. At the top, you've got, say, some regular C code, and actually that code is pretty generic. You can have a = b + c in any number of languages, Java, Python, they look all very similar. Except for the semi-colon at the end, that could've been Python, right? So you get the high level language at the top. And in the end, you wanna get what you see at the bottom, a sequence of zeros and ones that represent the instructions. So, what happens is if you look at that top instruction, it's actually broken down into a set of smaller steps, of smaller behaviors. So that instruction a = b + c, it's not just an add instruction, it's not just an add that'll be performed. First you gotta get the b variable, you gotta get the c variable, you gotta add, and then you gotta put the result back. So, maybe b and c are in memory somewhere, and a has to go to memory. So first, you gotta load a from memory, or load b from memory, rather. Then load c from memory. Then do the add, then store the result back in memory for a. And that's why you got four instructions in there in the middle. You got four what you call, assembly instructions. So the compiler will make assembly instructions. The lw is load word, so it'll load b into memory, then the next lw loads c into memory, specifically into the registers, r1 and r2. Then the add takes r1 and r2, adds them, put the results in r3. And then that last instruction, sw, store word, that takes what's in r3 and puts that back into memory, wherever you want a to go. So that one high level instruction breaks down to four simpler assembly level instructions. And then the assembler takes each of those four instructions, and converts it into a sequence of zeroes and ones. So you can see, at the bottom you see actually one instruction, just the add instruction. But presumably, you would have four instructions, four sequences of zero and ones just like that, to correspond to each one of the four assembly instructions. So that's the process of compilation, a very simple version of it. But you take the high level language, in the end, you get a sequence of zeros and ones that represent the instructions that need to be performed. And those zeros and ones are what get interpreted by the microcontroller. So this is a high level view of your standard tool chain, software tool chain. A tool chain is basically a term that is used in embedded systems a lot, and in IoT devices a lot. It describes the sequence of tools, of software tools, that you have to use in order to convert a program that you code into an executable program on the platform. So, if we look at this picture, we start with the host up at the top left. The host is laptop, desktop, whatever it is that you're actually writing the code on. So, you write you code on the host using some text editor, it doesn't really matter which one. Then, and this is actually a compile tool chain. So you write your code, let's assume it's C, the C code comes out of the host, goes into a compiler. So the compiler, actually I should have said here, this is what's called a cross compiler. So a cross compiler is a compiler, it takes the C code, and coverts into an assembly code, okay. But the assembly code is for the target platform. So the target platform is whatever microprocessor you're targeting. So let's say I'm using an Arduino, right? The processor on there is gonna be an AVR ATmega processor. So the compiler that is a cross compiler, it'll compile and make assembly code that works for that AVR ATmega processor. So the compiler makes that, then that code goes to an assembler and gets an object file that's generated, which is actually machine code. Again, for the target platform, for the AVR ATmega whatever it is. And so the OBJ file, the object file, that has the machine code plus extra debugging information and other assorted information in there, but it has the machine code. Now, you'll notice there's a path on the top from the host into the assembler assembly code. You could write assembly code directly. So you could write C code, which is what we'll do. You could also write assembly code directly. We will not do that, but you could, and that would get merged in at the assembly phase. So then once you get the object file, the object file, that describes all the code that you wrote. But remember that we're using library functions all the time. And we haven't done this yet, but in our code, you always wanna use library functions to handle complicated tasks. Now, library functions are really just functions that are prewritten, but you didn't write them. You just call the function. You just write the name of the function, and that code gets executed. So, all those library functions have to get integrated into your program at some point, and that's what the linker does. So the linker, we don't see this in the picture, but the linker, it has access to all the libraries. And the linker basically takes the library's code and inserts it into your code at the appropriate places. It creates links between your code and the library code that you use. And then the output of the linker is gonna be some executable program. Now, the standard path that we're going to use is from the linker to the programmer, which then goes to micrprocessor. So the programmer, what that does, is it takes the executable code and copies it, writes it from the host machine onto the microprocessor, usually into the flash memory of the microprocessor. Because in order for the microprocessor to actually execute the code, the code has to be sitting on there on its memory. So that's what the programmer does, and that actually goes on via USB cable for us, right? The programmer will take the code, send it across the USB cable, and write it into the target, say Arduino for us, or Raspberry Pi, or whatever it is. So that's the programmer. There can also be another path, a debugging path, where if you're using a debugger, which is a little more sophisticated than what we're going to deal with, you can take the executable and write it into the target platform and write debug code in there too, and control it during execution. You can set break points and things like that. We won't cover that right now. Thank you. [MUSIC]