Developing larger projects

As projects deliver more functionality and require "more number of lines of code" to achieve their goal, they require much more effort to develop and debug them. For larger projects, the code must be well organized and modular. Otherwise, it becomes challenging to test and debug it. Imagine a project that can be implemented using 200 lines of code. Let us call the difficulty to debug this code D. If the project gets bigger and needs 400 lines of code, the difficulty in debugging is usually much higher than 2*D unless the code is modular and well-organized. To this end, functions should have clear and relatively small objectives. You have to try to test functions individually as much as possible and certainly test each part as you build them. 

Let us consider project 1, which needs all the LEDs and the buttons on the two boards for its functionality. The first step is to create the Hardware Abstraction Layer for all the underlying hardware you need. Each piece of hardware will need at least two sets of HAL functions: 1) initialization and configuration functions and 2) functions that provide the functionality of the hardware. For the buttons and LED HAL, these functions are as follows:

1) function to initialize the digital i/o to work with the LED or the button

2) functions to turn on or turn off or toggle the LED light and functions that read the status of a button

Your goal should be writing the HAL functions and test them one by one and making sure they all work. This, of course, means writing code in your main function that has to be deleted before your final code is developed. In other words, as you test different functions, you keep writing pieces of "tester" code that you will eventually delete. For the example of project 1, an excellent way to test your HAL functions is to use a code similar to the code for ButtonLED_HALReg:

        if (SwitchStatus_Launchpad_Button1() != PRESSED)

            TurnOff_Launchpad_LED1();

        else

            TurnOn_Launchpad_LED1();

Once you develop the HAL for LED2_red, for example, you can replace the functions for LED1 with the LED2_red to make sure you have initialized it right, and your HAL functions are working correctly. Similarly, you can test for all other LEDs and Button2 of the Launchpad and the two buttons of the BoosterPack. One of the main reasons HAL functions may not work as expected is that the initialization of the hardware is not done correctly. Sometimes, you might have written the right initialization function, but you have forgotten to call it in your main!! So, pay careful attention to that. 

If you have a HAL with proper names and useful comments that are all fully tested, you have a strong foundation for your project. Like a house that will never become stable if its foundation is not well built, you can never have a successful project without a well-developed HAL.

Another step that you can work in parallel to developing your HAL is to break your top-level project into smaller parts. Think of various FSMs that can help build your project and draw them on the paper. Build these FSMs using C code, use structs to pack different variables related to your application that are better kept together. Write psuedo-code on paper or as a comment section project and then, turn them into real code. 

Regardless of how you add lines of code to your project, make sure you compile your code regularly. You should compile your code after you add a certain number of lines of code to your project, either by writing or copy-pasting. This number depends on your programming skills. If you are not very skilled, we recommend no more than 10-15 lines of code before you hit the compile button. When dealing with compilation issues, consider the fact that many times the compilation error manifests itself several lines of code below where the problem is. So, do not get fixated on the line where the error seems to be. Also, pay careful attention to all the warnings. Some warnings are OK to ignore. However, some warnings can be pointing to issues that result in fatal errors in your code. We recommend that you try to resolve all the warnings except the ones that are marked as a compiler or package versions being different. When you get a warning or compilation error that you are not sure how to resolve, we recommend searching online for answers. The web is typically a useful resource for such things. If you are still not successful, feel free to put your question on Piazza. More often than not, your friends have faced similar issues and respond to you before instructors do. 

As you develop your error-free, warning-free code, do not assume the project will work flawlessly just because it does not have compilation errors, and your HAL works fine. Instead, try to create small testers that check the functionality of some of your functions before you put everything together. Generally, the smaller the part that you are testing it is, the more comfortable for you to figure out what has gone wrong when you need to debug the code. Use the methods you have learned in HW2 and HW3: putting breakpoints, observing variables, etc. to debug your functions when they do not behave as you wish. 

Please be aware that the instructional team, including ULAs, GTAs, and instructors, do not intend to debug your code for you. It is challenging to debug someone else's code, especially if the code is not well organized and well written. Instead, the instructional team intends to teach you the concepts mentioned in this document: how to build a modular code, how to test different pieces, and how to debug using CCS. The instructional team can also help you with learning the underlying concepts such as 1) pointers, 2) structs, 3) enums, 4) bit manipulation, 5) static variables, etc. They will use the examples discussed in class, such as the ones mentioned below, to review the concepts for you. 

https://github.com/VT-Introduction-to-Embedded-systems/programmimng_pointers_struct.git


https://github.com/VT-Introduction-to-Embedded-systems/macro_enum_typedef.git


https://github.com/VT-Introduction-to-Embedded-systems/fsm_example.git