The readers of this blog have certainly noticed that EmbeddedGurus is no longer active.
But the State-Space blog is not dead! The blog has been migrated to state-machine.com, where it will continue. Please check it out!
If you’d like to understand how Object-Oriented Programming (OOP) really works under the hood, here is a free video course for you:
OOP part-1: Encapsulation: This first lesson on Object-Oriented Programming (OOP) introduces the concept of Encapsulation, which is the ability to package data and functions together into classes. You’ll see how you can emulate Encapsulation in C, what kind of code is generated, and how to debug such code. Next, you will translate the C design into C++ using a class and again you inspect the generated code to compare it with C. Finally, you will see how Encapsulation relates to concurrent programming with an RTOS.
OOP part-2: Inheritance: This second lesson on Object-Oriented Programming (OOP) introduces the concept of Inheritance, which is a mechanism for reusing common attributes and operations among classes. You’ll see how you can emulate Iheritance in C, what kind of code is generated, and how to debug such code. Next, you will translate the C design into C++ using a class and again you inspect the generated code to compare it with C. Finally, you will see how to *think* about inheritance and not to confuse it with class composition.
OOP part-3: Polymorphism in C++: This third lesson on Object-Oriented Programming (OOP) introduces the concept of Polymorphism, which is a uniquely object-oriented concept that has no direct analog in a traditional procedural language like C. Therefore the plan for this lesson is reversed compared to previous two lessons in that you will first see what poloymorphism is and you will reverse-engineer its inner workins in C++. You will see the benefits of polymorphism and understand its overheads. You will put this knowledge to the test in the next lesson, where you will implement polymorphism in C.
If you’d like to understand how a Real-Time Operating System (RTOS) really works, here is a free video course for you:
RTOS part-1: In this first lesson on RTOS you will see how to extend the foreground/background architecture from the previous lesson, so that you can have multiple background loops running seemingly simultaneously:
RTOS part-2: In this second lesson on RTOS you will see how to automate the context switch process. Specifically, in this lesson, you will start building your own minimal RTOS that will implement the manual context switch procedure that you worked out in the previous lesson:
RTOS part-3: This third lesson on Real-Time Operating System (RTOS) shows how to automate the scheduling process. Specifically, in this lesson you will implement the simple round robin scheduler that runs threads in a circular order. Along the way, you will add several improvements to the MiROS RTOS and you will see how fast it runs:
RTOS part-4: This forth lesson on Real-Time Operating System (RTOS) shows how to replace the horribly inefficient polling for events with efficient BLOCKING of threads. Specifically, in this lesson you will add a blocking delay function to the MiROS RTOS and you’ll learn about some far-reaching implications of thread blocking on the RTOS design:
RTOS part-5: This fifth lesson on RTOS I’ll finally address the real-time aspect in the “Real-Time Operating System” name. Specifically, in this lesson you will augment the MiROS RTOS with a preemptive, priority-based scheduler, which can be mathematically proven to meet real-time deadlines under certain conditions:
RTOS part-6: This sixth lesson on RTOS talks about the RTOS mechanisms for synchronization and communication among concurrent threads. Such mechanisms are the most complex elements of any RTOS, and are generally really tricky to develop by yourself. For that reason, this lesson replaces the toy MiROS RTOS with the professional-grade QXK RTOS included in the QP/C framework, parts of which have been used since lesson 21. The lesson demonstrates the process of porting an existing application to a different RTOS, and once this is done, explains semaphores and shows how they work in practice:
RTOS part-7: This seventh lesson on RTOS talks about sharing resources among concurrent threads, and about the RTOS mechanisms for protecting such shared resources. First you see what can happen if you share resources without any protection, and then you get introduced to the “mutual exclusion mechanisms” for protecting the shared resources. Specifically, you learn about: critical sections, resource semaphores, selective scheduler locking, and mutexes. You also learn about the second-order problems caused by these mechanisms, such as unbounded prioroty inversion. Finally, you learn how to prevent these second-order effects by priority-ceiling protocol and priority-inheritance protocol.
In this installment of my “Embedded Toolbox” series, I would like to share with you the free source code cleanup utility called QClean for cleaning whitespace in your source files, header files, makefiles, linker scripts, etc.
You probably wonder why you might need such a utility? In fact, the common thinking is that compilers (C, C++, etc.) ignore whitespace anyway, so why bother? But, as a professional software developer you should not ignore whitespace, because it can cause all sorts of problems, some of them illustrated in the figure below:
Note: The problems caused by whitespace in the source code are particularly insidious, because you don’t see the culprit. By using an automated whitespace cleanup utility you can save yourself hours of frustration and significantly improve your code quality.
QClean is a simple and blazingly fast command-line utility to automatically clean whitespace in your source code. QClean is deployed as natively compiled executable and is located in the QTools Collection (in the sub-directory qtools/bin
). QClean is also available in portable source code and can be adapted and re-compiled on all desktop platforms (Windows, POSIX –Linux, MacOS).
Typically, you invoke QClean from a command-line prompt without any parameters. In that case, QClean will cleanup white space in the current directory and recursively in all its sub-directories.
Note: If you have added the qtools/bin/ directory to your
PATH
environment variable (see Installing QTools), you can runqclean
directly from your terminal window.
As you can see in the screen shot above, QClean processes the files and prints out the names of the cleaned up files. Also, you get information as to what has been cleaned, for example, “Trail-WS” means that trailing whitespace has been cleaned up. Other possibilities are: “CR” (cleaned up DOS/Windows (CR) end-of-lines), “LF” (cleaned up Unix (LF) end-of-lines), and “Tabs” (replaced Tabs with spaces).
QClean takes the following command-line parameters:
PARAMETER | DEFAULT | COMMENT |
---|---|---|
[root-dir] |
. |
root directory to clean (relative or absolute) |
OPTIONS | ||
-h |
help (show help message and exit) | |
-q |
query only (no cleanup when -q present) | |
-r |
check also read-only files | |
-l[limit] |
80 | line length limit (not checked when -l absent) |
QClean fixes the following whitespace problems:
-l
option, default 80 characters per line).QClean can optionally check the code for long lines of code that exceed a specified limit (80 characters by default) to reduce the need to either wrap the long lines (which destroys indentation), or the need to scroll the text horizontally. (All GUI usability guidelines universally agree that horizontal scrolling of text is always a bad idea.) In practice, the source code is very often copied-and-pasted and then modified, rather than created from scratch. For this style of editing, it’s very advantageous to see simultaneously and side-by-side both the original and the modified copy. Also, differencing the code is a routinely performed action of any VCS (Version Control System) whenever you check-in or merge the code. Limiting the line length allows to use the horizontal screen real estate much more efficiently for side-by-side-oriented text windows instead of much less convenient and error-prone top-to-bottom differencing.
QClean applies the following rules for cleaning the whitespace depending on the file types:
FILE TYPE | END-OF-LINE | TRAILING WS | TABS | LONG-LINES |
---|---|---|---|---|
.c |
Unix (LF) | remove | remove | check |
.h |
Unix (LF) | remove | remove | check |
.cpp |
Unix (LF) | remove | remove | check |
.hpp |
Unix (LF) | remove | remove | check |
.s |
Unix (LF) | remove | remove | check |
.asm |
Unix (LF) | remove | remove | check |
.lnt |
Unix (LF) | remove | remove | check |
.txt |
DOS (CR,LF) | remove | remove | don’t check |
.md |
DOS (CR,LF) | remove | remove | don’t check |
.bat |
DOS (CR,LF) | remove | remove | don’t check |
.ld |
Unix (LF) | remove | remove | check |
.tcl |
Unix (LF) | remove | remove | check |
.py |
Unix (LF) | remove | remove | check |
.java |
Unix (LF) | remove | remove | check |
Makefile |
Unix (LF) | remove | leave | check |
.mak |
Unix (LF) | remove | leave | check |
.html |
Unix (LF) | remove | remove | don’t check |
.htm |
Unix (LF) | remove | remove | don’t check |
.php |
Unix (LF) | remove | remove | don’t check |
.dox |
Unix (LF) | remove | remove | don’t check |
.m |
Unix (LF) | remove | remove | check |
The cleanup rules specified in the table above can be easily customized by editing the array l_fileTypes
in the qclean/source/main.c
file. Also, you can change the Tab sizeby modifying the TAB_SIZE
constant (currently set to 4) as well as the default line-limit by modifying the LINE_LIMIT
constant (currently set to 80) at the top of the the qclean/source/main.c
file. Of course, after any such modification, you need to re-build the QClean executable and copy it into the qtools/bin directory.
Note: For best code portability, QClean enforces the consistent use of the specified End-Of-Line convention (typically Unix (LF)), regardless of the native EOL of the platform. The DOS/Windows EOL convention (CR,LF) is typically not applied because it causes compilation problems on Unix-like systems (Specifically, the C preprocessor doesn’t correctly parse the multi-line macros.) On the other hand, most DOS/Windows compilers seem to tolerate the Unix EOL convention without problems.
QClean is very simple to use (no parameters are needed in most cases) and is fast (it can easily cleanup hundreds of files per second). All this is designed so that you can use QClean frequently. In fact, the use of QClean after editing your code should become part of your basic hygiene–like washing hands after going to the bathroom.
Like any craftsman, I have accumulated quite a few tools during my embedded software development career. Some of them proved to me more useful than others. And these generally useful tools ended up in my Embedded Toolbox. In this blog, I’d like to share some of my tools with you. Today, I’d like to start with my cross-platform Programmer’s Calculator called QCalc.
I’m sure that you already have your favorite calculator online or on your smartphone. But can your calculator accept complete expressions in the C-syntax, which you can cut-and-paste directly to and from your embedded code? How many buttons do you need to push to see your result in decimal, hex and binary? Well, QCalc can do this with less hassle than anything else I’ve seen out there. I begin with describing QCalc features and then I tell you how to download and launch it.
The most important feature of QCalc is that it accepts expressions in the C-syntax – with the same operands and precedence rules as in the C or C++ source code. Among others, the expressions can contain all bit-wise operators (<<, >>, |, &, ^, ~) as well as mixed decimal, hexadecimal and even binary constants. QCalc is also a powerful floating-point scientific calculator and supports all mathematical functions (sin(), cos(), tan(), exp(), ln(), …). Some examples of acceptable expressions are:
((0xBEEF << 16) | 1280) & ~0xFF
– binary operators, mixed hex and decimal numbers
($1011 << 24) | (1280 >> 8) ^ 0xFFF0
– mixed binary, dec and hex numbers
(1234 % 55) + 4321/33
– remainder, integer division
pow(sin($pi),2) + pow(cos($pi),2)
– scientific floating-point calculations, pi-constant
($0111 & $GPIO_EXTIPINSELL_EXTIPINSEL0_MASK) << ($GPIO_EXTIPINSELL_EXTIPINSEL1_SHIFT * 12)
– (see user-defined variables)
NOTE: QCalc internally uses the Tcl command expr to evaluate the expressions. Please refer to the documentation of the Tcl expr command for more details of supported syntax and features.
If the result of expression evaluation is integer (as opposed to floating point), QCalc automatically displays the result in hexadecimal and binary formats (see QCalc GUI). For better readability the hex display shows a comma between the two 16-bit half-words (e.g., 0xDEAD,BEEF
). Similarly, the binary output shows a comma between the four 8-bit bytes (e.g., 0b11011110,10101101,10111110,11101111
).
As the extension to the C-syntax, QCalc supports binary numbers in the range from 0-15 (0b0000-0b1111). These binary constants are represented as $0000
, $0001
, $0010
,…, $1110
, and $1111
and can be mixed into expressions. Here are a few examples of such expressions:
($0110 << 14) & 0xDEADBEEF
($0010 | $1000) * 123
QCalc remembers the history of up to 8 most recently entered expressions. You can recall and navigate the history of previously entered expressions by pressing the Up / Down keys.
QCalc stores the result of the last computation in the $ans variable (note the dollar sign $
in front of the variable name). Here are some examples of expressions with the $ans
variable:
1/$ans
– find the inverse of the last computation
log($ans)/log(2)
– find log-base-2 of the last computation
QCalc allows you also to define any number of your own user variables. To set a variable, you simply type the expression =alpha
in the user input field. This will define the variable alpha
and assign it the value of the last computation ($ans
). Subsequently, you can use your alpha
variable in expressions by typing $alpha
(note the dollar sign $
in front of the variable name). Here is example of defining and using variable $GPIO_BASE
:
0xE000E000
– set some value into $ans
=GPIO_BASE
– define user variable GPIO_BASE
and set it to $ans
$GPIO_BASE + 0x400
– use the variable $GPIO_BASE
in an expression
Note: The names of user variables are case-sensitive.
Expressions that you enter into QCalc might have all kinds of errors: syntax errors, computation errors (e.g., division by zero), undefined variable errors, etc. In all these cases, QCalc responds with the Error
message and the explanation of the error:
QCalc is included in the open source QTools Collection, which you cad freely download from SourceForge or GitHub. Once you install QTools, QCalc is located in the sub-directory qtools/bin/
and consists of a single file qcalc.tcl
. To launch QCalc, you need to open this file with the wish Tk interpreter.
NOTE: The wish Tk interpreter is included in the QTools Collection for Windows and is also pre-installed in most Linux distributions.
You use QCalc by typing (or pasting) an expression in the user input field and pressing the Enter key to evaluate the expression. You can conveniently edit any expression already inside the user input field, and you can recall the previous expressions by means of the Up/Down keys. You can also resize the QCalc window to see more or less of the input field.
The wish Tk interpreter is conveniently provided in the same qtools/bin/
directory as the qcalc.tcl
script. The directory contains also a shortcut qcalc
, which you can copy to your desktop.
Most Linux distributions contain the Tk interpreter, which you can use to launch QCalc. You can do this either from a terminal, by typin wish $QTOOLS/qcalc.tcl &
or by creating a shortcut to wish
with the command-line argument $QTOOLS/qcalc.tcl
.