TI-RSLK Module 4 - Lecture video part III - Software design using MSP432 - Debugging
In this module, you will develop and test software functions that will be used in the maze robot. The first function will convert ADC measurements from a sensor into distance to the wall, and the second function will take three distance measurements and classify the situation into the most likely scenario.
리소스
Hi Jon Valvano here. And in this video we're going to talk about debugging on the 432. In particular, the lecture is going to focus on some of the fundamental theories associated with debugging.
So in particular, in this lab, we're going to use or learn a technique called functional debugging, OK? Now functional debugging is just what it sounds. We're going to test a function. And in order to test it, we're going to deliver to it a set of inputs.
And then we're going to, in our minds, think about what the expected outputs are going to be. And then we're going to compare that to the actual outputs. And in that way we're going to be able to test whether our function behaved properly.
We're going to learn things like single stepping, and breakpoints, and observing inputs and outputs using the debugger. And one of the functions that you are going to test is this hyperbolic non-linear translation between a analog to digital converter. In particular, if you get a 7000, what we're expecting to get is 200 millimeters.
Now you won't have an actual A-to-D converter here this early in the class. But we're going to develop a piece of software. And then more importantly, teach you how to debug or test a small piece of that software. All right, let's get going.
So the whole idea of debugging fits into the following two concepts. One is to control the environment. And that is, I'm going to control two things. I'm going to control what software executes, in other words, where is my program executes. And two, I'm going to control what data it sees as its inputs.
And the second aspect of functional debugging is observability. In other words, can I see-- is it able to observe-- can I see the inputs. Can I know where my program is executing. And can I see the actual outputs. And so we will learn in this particular lab techniques using this debugger to be able to do exactly that-- these operations.
All right, so for instance, we're going to use a technique called stabilization. And stabilization is a technique that I can feed in a fixed-- in other words, I can specify, and determine, and set what the input values will be as my program executes. In other words, that's an aspect of debugging called control.
And one way to do it is to create a buffer, right here. So if you see this buffer right there, what we have here is a set of 16 possible numbers that your A-to-D converter in a subsequent lab might actually see. In other words, you might call the A-to-D converter and get the number 7,131. And then you're going to call this function right there. That's the function we're going to test.
So you can see here that I'm going to set the input value-- I'm going to fix the input value-- to a sequence of 16 possibilities. And I know what all of those possibilities are-- so 0, 1, 2, 3, 4, 5, 6, 7, and then 0, 1, 2, 3, 4, 5, 6, 7. And that 7,000, I'm expecting it to be converted into 196 millimeters.
And so what I'm going to do, is I'm going to set the input, call or test your function-- not the entire robot, but just that one function-- see what the answer is, and then compare, right here, the actual output to the expected output. And if your software is as good as mine, that difference is either going to be plus 1, minus 1, or 0. And we're going to call that good enough. What if your difference is greater than 1 or less than negative 1, we're going to classify that an error and say your program doesn't work.
And so this example of a main program is a stabilization for the function convert. So what this means is, because-- if your program doesn't work, and you go back and run it again, you can see that I'm going to get this same output for every input. And that's a process called determinism.
Now not all software is deterministic. But this particular function should be. In other words, if I call this-- run this again, and give it the exact same inputs, I'm going to get the exact same outputs and exact same number of errors. And what that means is if I make a change to this function and I run it again, then the change in the output is a function of that change in your software. And this is a very powerful result that we get by stabilizing my input.
All right, where did I get these values from? In particular, you can sort of see there's this, sort of, uniformly distributed between across the range of 100 millimeters up to 800 millimeters. That will be the typical range of the sensor, once we get there.
Other things we could have done is chosen values near the extremes. If we know how our clients use the system, we can choose values that are appropriate for our system, which is an example of what this is. Some of our clients will use things inappropriately. For example, what happens if you plug-in a 0. That should never happen, but you might test it.
What happens if I-- it's supposed to be a 14-bit number. What happens if I type in the 15-bit number? I can look at the behavior of my system for inappropriate inputs, as well as the appropriate ones.
The corner case is-- represents something which you know to be difficult. So for instance, if your system has a decision like this, where if it's greater than 100, whatever that input is, you'll do one thing. If that's less than or equal to 100, you'll do another thing. And so as the input goes from 99, 100, to 101 you know that even though I change the input between-- just by one, I'm expecting the output, the results, to be different in this-- at this barrier, at this corner. And so that represents what we call a corner case.
So in summary, we're going to work on it in this lab do functional debugging. And this is an example of a functional debugging process, where we know the inputs. We know the expected outputs. And then we measure-- we run the program, measure the outputs, and then compare the two.
Where do we get our test data? You can make it up. You could run your actual robot once, and use actual data, but use that same data over again. And so one way for us to generate data is to use what's called a test case or a test bank of possible input values, such that I can run that test bank over and over again, like I did in the previous example.
The other way is to look at my problem and establish what I would call corner cases, difficult cases. So you'll see the other program that you have to solve has set up for you a sequence of numbers that I know are difficult. And then ask your software to classify this scenario. And then check and see if your answer is correct. So in that way, you can verify your system works without testing all of the possible values.
So the other thing we can do about control is to execute-- is to determine what gets executed. And this is an example of a special test main, where rather than running the whole robot, I'm testing this one function right there. That's the function that you have to write in Lab 4. And we're going to test it.
If you do have a robot, one of the things you do set a breakpoint. And so what breakpoints are is you click on this line of code. And you say, hey, debugger, why don't you run to that spot. And so you can establish a breakpoint right there.
And so when you hit the go statement, it executes and executes. And then the first time it gets here, it stops. And then once it's stopped, now you can single step. And single step is to execute one line at a time.
If you do step over, this one line at a time one, one C line at a time. If it calls a function, it goes in. Step over is, it's one line. And if it sees a function, it excuse the entire function. That's what step over does.
Step in is sort of like step. If it gets to a function, it steps in and executes inside of the function call. Step out is a way that if you've done a step in-- so in other words, if you've got line 1, line 2, some function call, like 3. And over in the function you've got line A, line B-- so these lines represent lines of C code-- return.
And so if I do a step-- let's do step first. If I do a step, it goes step-- OK, so let's just go step, step, step, step, step, step, step. OK, so that's what step and step in will do.
Step over-- if I do a step over, it'll execute that. It'll execute this. And then next time I hit step over, it'll execute all of that, and end up here. So I hit it three times, and I got that spot.
Step out is if I happened to be right here in the function, if I did it with step out, it'll execute the rest of the function and return me to that spot. All right, so again, to control what gets executed, I can set up a test main. Or I can set breakpoints and execute to a certain spot. In order to establish the inputs, I can-- rather than collecting the inputs from the actual sensors-- the left, the center, and the right-- actual sensors-- I'm going to fetch the data out of an array.
All right, so we talked about control, so now talk about observability. Now it turns out in all-- most debuggers, including Code Composer Studio, there's something called a monitor window. So when I'm in the debugger, I can look at the global variables. I just click on it, and say, add it to the monitor window. And I can set up that monitor window to either refresh when I ask it or to refresh periodically-- so that's what I can do with globals.
Permanent variables I can look in a monitor window. There's a separate window for the locals. OK, so again, the debugger will let you see the local variables.
Now if you really know how your computer works, there might make sense to you look at the registers. So in particular, I can look at the stack pointer. And I can see where the stack is.
I could look at the program counter, see where it is. The link register-- this registers in your system-- R0 is the first parameter that you pass in. And R0 is the last parameter that-- the only parameter you pass back.
What'll happen in Lab 10-- this is Lab 4. But Lab 10, we're going to learn a process called dumping. And so I'm just going to take an array. And this array might be in RAM. It could be a small array. Or it might actually be in ROM. And it could be a big array.
And I'm going to, when it runs, put things into this array. It's called dumping. And the advantage of that is it's very fast.
And so while I'm-- those of you that have programmed before and know how to do either printf, or cout, or depending upon whatever your compiler is-- we're not going to do any of that in this class. Rather than printf, we're just going to dump it into an array. Now there is a printf.
And so if you want to printf, you can actually output to the UART. And if you have connected up your USB connector to your laptop, you can run a terminal program like PuTTY or even TExaSdisplay, and you can see output from the UART-- the serial port-- just like you would with printf.
Now it doesn't work well with a robot, because you need USB connected. So what we're going to do in the robot, if we don't have a USB and we don't have a print, we're going to hook things up to our robot that help us observe what it's doing. And one of the simplest ones is LEDs, because an LED doesn't make your robot not hit the wall. An LED doesn't help you decide what to do. It's just a little light.
And you can flash colors, and flash it on, flash it off, and use it to observe what your software is thinking. So a blue light might mean something. A green light might mean something else.
Lab 11 is a liquid crystal display. Now again, it doesn't help your robot hit-- not hit the wall. But it does help you see. So you can put things on the liquid crystal display, and look at the liquid crystal display as your robot's going around, and as a way to monitor-- to physically see what the software is thinking.
So again, there are two aspects of debugging. Control sets the inputs and what gets executed. And the observability-- in other words, if you've got the debugger, you can look in the monitor window. If it's running along the track, you can dump it into RAM, and then look at the RAM later. If you're not running on the robot, you could hook up the USB cable and look at the output of the serial port on your PC. But when you are running the robot, we're going to use things like light emitting diodes and liquid crystal displays in order to observe what our robot is thinking.
So in summary, this particular lab is about introduction to C programming. But more importantly, what I want you to be able to develop is a set of tools associated with the first aspect of debugging called functional debugging. And that means to test a function, we're going to give it a set of inputs. And then we're going to compare the expected output, given the input, to the actual output.
And to do that, I'm going to need to be able to control the execution that this function gets executed, and to set what its inputs are. And I'm going to be able to observe what it got. OK, so enjoy this lab. We'll see you next time.