Programming – Jacob N Calvert https://jacobncalvert.com/blog-archive Tue, 19 May 2020 22:41:40 +0000 en-US hourly 1 https://wordpress.org/?v=6.0.17 https://jacobncalvert.com/blog-archive/wp-content/uploads/2018/02/cropped-icon-32x32.png Programming – Jacob N Calvert https://jacobncalvert.com/blog-archive 32 32 Kernel Design: Microkernel vs. Monolithic https://jacobncalvert.com/blog-archive/2020/05/19/kernel-design-microkernel-vs-monolithic/ https://jacobncalvert.com/blog-archive/2020/05/19/kernel-design-microkernel-vs-monolithic/#comments Tue, 19 May 2020 22:41:39 +0000 https://jacobncalvert.com/?p=683 Motivation This hotly debated topic has been around for decades, and it is just as alive today as it was 28 years ago. The truth is, there are fundamental differences in the theory which drives the design of a monolithic kernel versus a microkernel. In this post, I will extrapolate from my knowledge of various kernel designs to explore what these two primary types are, what their features, benefits, drawbacks and implications may be. I’ll also briefly explore the extension…

The post Kernel Design: Microkernel vs. Monolithic appeared first on Jacob N Calvert.

]]>
Motivation

This hotly debated topic has been around for decades, and it is just as alive today as it was 28 years ago. The truth is, there are fundamental differences in the theory which drives the design of a monolithic kernel versus a microkernel. In this post, I will extrapolate from my knowledge of various kernel designs to explore what these two primary types are, what their features, benefits, drawbacks and implications may be. I’ll also briefly explore the extension of the theories that drive these designs into “fringe” types of kernels (such as a nanokernel).

Key Concepts

Before hopping into the discussion about the differences between these two kernel archetypes, I need to lay out some key concepts which will help bound the discussion.

Userspace vs. Kernelspace

Broadly, userspace is considered to be “outside” of the kernel. Kernelspace is “inside.” The way this is typically implemented is through the use of multiple address spaces, aided by the hardware (MMU, MPU). This usually results in all userspace applications having believing they have the whole address space to themselves, while in reality the MMU is remapping some Virtual Addresses (VAs) to the real Physical Addresses (PAs). Actions in userspace cannot (well, SHOULD not) perturb the operation of the core kernel. Contrast this to kernelspace, wherein any part of the kernel is available to poke and tinker with from code running in this space.

This separation of spaces may also use other hardware features (Rings in x86-land, Exception Levels in ARM) to further represent the distinction and privilege of code running in each space.

Examples of userspace are your typical Linux application.

Examples of kernelspace are a Linux .ko kernel module.

Kernel-User Boundary

This boundary is the line which separates the userspace and kernelspace. Crossing this boundary involves a change in privilege level, and is often accomplished by invoking a system call. Why and when we cross this boundary is a key point of interest in the discussion of kernel design since it is usually an expensive operation.

Essential Operating System Functions

For the purpose of this discussion, I consider the following to be essential to any OS for it to be of any use.

  • Memory Management
    • Addresses needs of the kernel to map/unmap/remap Virtual Memories to Physical ones
  • Task/Process Management
    • Addresses needs of the kernel to handle multi-tasking
  • Inter-process Communication (IPC)
    • Addresses needs of kernel and applications to communicate via a common interface
  • Device Drivers
    • Addresses needs of applications to communicate with the outside world
  • Filesystems
    • Addresses needs of application and kernel to store/retrieve data via a common interface

Monolithic Kernels

Monolithic kernels and the essential properties which make it monolithic can be succinctly summed up in the following phrase:

Everything except the application exists in kernelspace.

In a monolithic kernel, all the essential components, and many other accessory components, live in kernelspace.

Figure 1. Monolithic Kernel

The design choice to bring all these functions and services into the kernelspace has several benefits, drawbacks, and implications.

Benefits

Since all the code that directly interacts with devices live in the same address space, moving data around is an inexpensive operation. Much of what happens in a system falls into this category, so you end up with a relatively speedy and snappy kernel implementation. For example, if two network devices are being bridged to transmit data from one network to another, and the network stacks and device drivers live in kernelspace, this operation can occur without any context change, saving time and increasing throughput.

Another benefit is that the userspace applications have a rich set of services which has a consistent interface available (usually the system call interface). This allows rich applications to be developed using a standard scheme.

Drawbacks

The same feature which is a benefit to monolithic kernels enabling speedy execution of kernelspace work, also is a drawback in some scenarios. If anything in kernelspace fails, it can potentially impact all of kernelspace. This is often addressed by having hardware enforced protections of kernelspace tasks as well as userspace tasks, which in many instances, ameliorates this issue.

Another drawback is that monolithic kernels must be updated atomically. They are typically tightly coupled and updates can be difficult to introduce.

Implications

If speed is a primary concern, monolithic kernels are good choices.

Microkernels

Microkernels are the minimalist brother to monolithic kernels. The essence of the microkernel can be summed up as:

Only the bare minimum to operate the kernel lives in kernelspace.

Nothing besides the minimal set of operations to consider the kernel operational resides in kernelspace in a microkernel. Many resources say this set is:

  • Memory Management
  • Process Management
  • IPC

I like to add one more to the list because I feel it is a critical resource in a real system: Interrupt Management. Either way, it is easily seen that the microkernel contains fewer components running in kernelspace, hence the “micro” name.

Figure 2. Microkernel

The services that were once part of the kernelspace in the monolithic design are now run as “servers” in the userspace. These servers interact with the applications and the other servers via IPC, which is facilitated by the kernel. This of course has benefits, drawbacks and implications as well.

Benefits

One obvious benefit over the monolithic kernel is that the servers can be taken online/offline independently of the kernel and a failure in one does not induce a system-wide failure necessarily.

Drawbacks

Similarly to the monolithic kernel, the primary benefit to a microkernel also has a drawback associated. Because each server runs in userspace and relies on IPC as a primary mechanism of communications, constant context switching into and out of kernel mode means microkernels are typically slower than their monolithic counterparts.

Another drawback is that not all expected services are going to be available on a microkernel since they are effectively decoupled from kernel execution.

Implications

If service independence is most important, a microkernel is a good choice.

Key Takeaways

There are some aspects of the two primary kernel types I didn’t dig into, and I want to address them specifically below.

Security

There is a strong case for both monolithic and microkernels in the security perspective. In this realm, the truth is that both designs have strengths and weaknesses, and the kernel’s design is only one aspect of the security posture of the system.

Safety

Like security, safety has a place in both micro and monolithic kernels. The safety of each relies more on the implementation and usage of the particular kernel rather than its design.

Absoluteness of Design

In today’s software architectures, we regularly see hybrids of these two concepts where we can meld the benefits of each in a blended fashion. This is a bit of a hot topic because when the lines are blurred it is harder to define what falls into each category. For examples of hybridization, see this article.

Extension of the Concepts

By taking the concepts which drive the monolithic and particularly the microkernel design to extremes, we see some interesting outcomes. Take for instance the nanokernel. This is the extreme version of a microkernel, where additional services may not be available and the application must provide this all itself. This is tending towards being simply a hypervisor however, and may not be a microkernel at all. Another example is the exokernel where the hardware resources are basically un-abstracted completely, so the application must make all these decisions. Of note regarding exokernels, is that they have yet to be developed into a commercial-grade offering as of now, and are primarily a research concept.

The post Kernel Design: Microkernel vs. Monolithic appeared first on Jacob N Calvert.

]]>
https://jacobncalvert.com/blog-archive/2020/05/19/kernel-design-microkernel-vs-monolithic/feed/ 1
Better JTAG on the Cheap with the FT232H https://jacobncalvert.com/blog-archive/2020/03/05/better-jtag-on-the-cheap-with-the-ft232h/ https://jacobncalvert.com/blog-archive/2020/03/05/better-jtag-on-the-cheap-with-the-ft232h/#comments Thu, 05 Mar 2020 14:45:56 +0000 https://jacobncalvert.com/?p=653 A couple of weeks ago I wrote a post about using the FTDI FT232R as a cheap JTAG debugger. I’ve been using it for a bit now to play with my Raspberry Pi 3B, and now that my code size has grown, the FT232R is just too slow to cut it. Here’s a breakdown: on the FT232R, the max speed I can set the adapter to is 3MHz. This has given me a transfer speed (loading via GDB) of around…

The post Better JTAG on the Cheap with the FT232H appeared first on Jacob N Calvert.

]]>
A couple of weeks ago I wrote a post about using the FTDI FT232R as a cheap JTAG debugger. I’ve been using it for a bit now to play with my Raspberry Pi 3B, and now that my code size has grown, the FT232R is just too slow to cut it.

Here’s a breakdown: on the FT232R, the max speed I can set the adapter to is 3MHz. This has given me a transfer speed (loading via GDB) of around 3KB/s. Not too bad for small projects of only a few hundred KiB. But now my code size is approaching a ~5 MiB, the debug cycle was way too long… 5MiB @ 3KB/s = ~28mins to load… not good!

Still in my pursuit of a cheap JTAG debugger (I mean come on! It’s just a serial protocol!), I did buy something. The Adafruit FT232H breakout is exactly what I was looking for. At only $15 with Amazon Prime shipping, I was back to debugging at a reasonable speed in two days.

The FT232H breakout is about as barebones as it gets. The board breaks out untouched ACBUS0-ACBUS7 and ADBUS0-ADBUS7 to 0.10″ pitch headers. Since the FT232H has a single MPSSE channel, I can use this breakout to get faster JTAG speeds.

My configuration files from the previous post had to change a little to accommodate. I’ll break it down below in comments in the file because it’s a little bit cryptic.

#
# FTDI USB Hi-Speed to MPSSE Breakout from Adafruit
#
# This should work for any bare FT232H
#

# Setup driver type
adapter driver ftdi

# 30000 kHZ -> 30MHz
adapter speed 30000

# Using JTAG (also could be SWD)
transport select jtag

# Common PID for FT232H
ftdi_vid_pid 0x0403 0x6014

# Set sampling to allow higher clock speed
ftdi_tdo_sample_edge falling


# Layout
# On this breakout, the LEDs are on ACBUS8 and ACBUS9, can't assign them
# registers are <ACVALUE><ADVALUE> <ACCONFIG><ADCONFIG>
# so we set 0x0308 to mean only ACBUS nTRST and nSRST, ADBUS3 (TMS) asserted high
# and we set 0x000B to mean only AC3,AC2,AC0 outputs -> (TMS,TD0, TCK)
ftdi_layout_init 0x0308 0x000b

# Pins
# pin name      | func. |
# --------------|-------|
# ADBUS0        | TCK   |
# ADBUS1        | TDI   |
# ADBUS2        | TDO   |
# ADBUS3        | TMS   |
# ACBUS0        | nTRST |
# ACBUS1        | nSRST |
#---------------|-------|

# When data == oe -> pins are switched from output to input to give
# the tri state (L, H, Hi-Z) effect 
ftdi_layout_signal nTRST -data 0x0100 -oe 0x0100
ftdi_layout_signal nSRST -data 0x0200 -oe 0x0200

So now it is as simple as connecting the corresponding pins on this breakout to the RPi3, and running OpenOCD again.

With the increased throughput of this MPSSE-supported interface, I now get ~587KB/s. Much better! It only takes ~8s to load my image now.

The post Better JTAG on the Cheap with the FT232H appeared first on Jacob N Calvert.

]]>
https://jacobncalvert.com/blog-archive/2020/03/05/better-jtag-on-the-cheap-with-the-ft232h/feed/ 1
JTAG On the Cheap with the FTDI FT232R https://jacobncalvert.com/blog-archive/2020/02/04/jtag-on-the-cheap-with-the-ftdi-ft232r/ https://jacobncalvert.com/blog-archive/2020/02/04/jtag-on-the-cheap-with-the-ftdi-ft232r/#comments Tue, 04 Feb 2020 21:59:47 +0000 https://jacobncalvert.com/?p=620 JTAG 101 What is it? JTAG stands for the Joint Test Action Group, and the TAP or Test Access Port this group defined is one of the most (if not the most) common way to program and debug embedded devices and computers of all flavors. For the professional, JTAG devices are bountiful and usually not too much of a strain on the commercial budget. But for the hobbyist, things aren’t so peachy. A Segger J-Link EDU can be had for…

The post JTAG On the Cheap with the FTDI FT232R appeared first on Jacob N Calvert.

]]>
JTAG 101

What is it?

JTAG stands for the Joint Test Action Group, and the TAP or Test Access Port this group defined is one of the most (if not the most) common way to program and debug embedded devices and computers of all flavors. For the professional, JTAG devices are bountiful and usually not too much of a strain on the commercial budget. But for the hobbyist, things aren’t so peachy. A Segger J-Link EDU can be had for ~$70 USD shipped, but the full featured J-Link is still ~$400, which is more than I want to pay as a hobbyist.

What does it do?

The JTAG TAP port consists of a few standard signals which essentially give you complete control over the systems in the JTAG chain. The chain is exactly what it sounds like: multiple devices which support JTAG chaining can be chained up and accessed from a single JTAG port. Need that flash programmed? JTAG can do that. Need to debug that microcontroller? JTAG can do that too. Want to do both without switching out tools? Yep, JTAG can do it. See this helpful diagram at Wikipedia for a visual representation.

JTAG for the Hobbyist

Chances are that you’ve got an USB -> Serial cable or breakout board lying around somewhere in your hoard. Chances are also, that it’s based on the wildly popular FTDI FT232R or a similar FT232-esque chip which converts USB to RS232. If you’re lucky enough to have this essential piece of hobbyist equipment, you’ve got a USB->JTAG adapter waiting to be unlocked!

Enter OpenOCD

OpenOCD (Open On-chip Debugger) is a fantastic project which aims to create an open and extensible OCD solution for all, and lucky for us, this includes the hobbyist! The OpenOCD project defines interfaces between the common parts of the OCD process, such as the target board or device, the OCD device used, etc., and using these well-defined interfaces is able to create a modular system which can support many different targets and debuggers with only a configuration change. This is a simplification of how this works, but it is sufficient to understand what we want to do with it.

So back to the FT232R. This little chip can be re-configured to use the RS232 signals as bit-banged JTAG signals, and OpenOCD can drive it. Even better, once the OpenOCD agent is up and running, we can then use GDB to connect to and drive our debug efforts. This mode of operation is detailed over at their documentation site (hint: search for ft232r).

The OpenOCD tool can usually be installed with your package manager on Linux. I’m running Linux Mint, so I apt install’d openocd. When I ran the tool pointing to the ft232r config file, it complained that it was not a supported interface… so I guess we’ll build from source!

Building OpenOCD with the Right Interfaces

All we need to do is build OpenOCD from source with the right interfaces enabled and we can make it work. What follows next is my step-by-step on doing this. I’m doing this in /tmp just so I can recreate the steps I did earlier in my apps directory.

Grab the Source

Go get the source from the GitHub mirror here and drop it in a working directory. I would also read the README for any dependencies you didn’t have already on your machine.

jacob@jacob-aspire-mint:/tmp$ git clone https://github.com/ntfreak/openocd.git
Cloning into 'openocd'...
remote: Enumerating objects: 74, done.
remote: Counting objects: 100% (74/74), done.
remote: Compressing objects: 100% (53/53), done.
remote: Total 62845 (delta 36), reused 50 (delta 21), pack-reused 62771
Receiving objects: 100% (62845/62845), 24.17 MiB | 24.90 MiB/s, done.
Resolving deltas: 100% (51571/51571), done.
jacob@jacob-aspire-mint:/tmp$ 

Run the bootstrapper

This little piece of code essentially checks that your build environment is sane and you have all the tools needed to build OpenOCD. Output is below, you should come away with no errors.

jacob@jacob-aspire-mint:/tmp/openocd$ ./bootstrap 
+ aclocal
+ libtoolize --automake --copy
+ autoconf
+ autoheader
+ automake --gnu --add-missing --copy
configure.ac:26: installing './compile'
configure.ac:37: installing './config.guess'
configure.ac:37: installing './config.sub'
configure.ac:16: installing './install-sh'
configure.ac:16: installing './missing'
Makefile.am:46: warning: wildcard $(srcdir: non-POSIX variable name
Makefile.am:46: (probably a GNU make extension)
Makefile.am: installing './INSTALL'
Makefile.am: installing './depcomp'
Makefile.am:23: installing './mdate-sh'
Makefile.am:23: installing './texinfo.tex'
Setting up submodules
Submodule 'jimtcl' (http://repo.or.cz/r/jimtcl.git) registered for path 'jimtcl'
Submodule 'src/jtag/drivers/libjaylink' (http://repo.or.cz/r/libjaylink.git) registered for path 'src/jtag/drivers/libjaylink'
Submodule 'tools/git2cl' (http://repo.or.cz/r/git2cl.git) registered for path 'tools/git2cl'
Cloning into '/tmp/openocd/jimtcl'...
warning: redirecting to https://repo.or.cz/r/jimtcl.git/
Cloning into '/tmp/openocd/src/jtag/drivers/libjaylink'...
warning: redirecting to https://repo.or.cz/r/libjaylink.git/
Cloning into '/tmp/openocd/tools/git2cl'...
warning: redirecting to https://repo.or.cz/r/git2cl.git/
Submodule path 'jimtcl': checked out 'a9bf5975fd0f89974d689a2d9ebd0873c8d64787'
Submodule path 'src/jtag/drivers/libjaylink': checked out 'f73ad5e667ae8b26a52b847c603fdadaabf302a6'
Submodule path 'tools/git2cl': checked out '8373c9f74993e218a08819cbcdbab3f3564bbeba'
Generating build system...
libtoolize: putting auxiliary files in AC_CONFIG_AUX_DIR, 'build-aux'.
libtoolize: copying file 'build-aux/config.guess'
libtoolize: copying file 'build-aux/config.sub'
libtoolize: copying file 'build-aux/install-sh'
libtoolize: copying file 'build-aux/ltmain.sh'
libtoolize: putting macros in AC_CONFIG_MACRO_DIRS, 'm4'.
libtoolize: copying file 'm4/libtool.m4'
libtoolize: copying file 'm4/ltoptions.m4'
libtoolize: copying file 'm4/ltsugar.m4'
libtoolize: copying file 'm4/ltversion.m4'
libtoolize: copying file 'm4/lt~obsolete.m4'
configure.ac:42: installing 'build-aux/ar-lib'
configure.ac:37: installing 'build-aux/compile'
configure.ac:30: installing 'build-aux/missing'
Makefile.am: installing './INSTALL'
libjaylink/Makefile.am: installing 'build-aux/depcomp'
Bootstrap complete. Quick build instructions:
./configure ....
jacob@jacob-aspire-mint:/tmp/openocd$ 

Run the configure script

This is where we determine that we want the FTDI FT232R to be supported. We do this by adding a flag to the configure line. Output is cut short in the middle because it’s quite long, but the important part is at the end.

jacob@jacob-aspire-mint:/tmp/openocd$ ./configure --enable-ft232r 
checking for makeinfo... no
configure: WARNING: Info documentation will not be built.
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /bin/mkdir -p
checking for gawk... gawk

[ ... snip ... ]

libjaylink configuration summary:
 - Package version ................ 0.2.0-git-f73ad5e
 - Library version ................ 0:0:0
 - Installation prefix ............ /usr/local
 - Building on .................... x86_64-pc-linux-gnu
 - Building for ................... x86_64-pc-linux-gnu

Enabled transports:
 - USB ............................ yes
 - TCP ............................ yes



OpenOCD configuration summary
--------------------------------------------------
MPSSE mode of FTDI based devices        yes (auto)
ST-Link Programmer                      yes (auto)
TI ICDI JTAG Programmer                 yes (auto)
Keil ULINK JTAG Programmer              yes (auto)
Altera USB-Blaster II Compatible        yes (auto)
Bitbang mode of FT232R based devices    yes
Versaloon-Link JTAG Programmer          yes (auto)
TI XDS110 Debug Probe                   yes (auto)
OSBDM (JTAG only) Programmer            yes (auto)
eStick/opendous JTAG Programmer         yes (auto)
Andes JTAG Programmer                   yes (auto)
USBProg JTAG Programmer                 no
Raisonance RLink JTAG Programmer        no
Olimex ARM-JTAG-EW Programmer           no
CMSIS-DAP Compliant Debugger            no
Cypress KitProg Programmer              no
Altera USB-Blaster Compatible           no
ASIX Presto Adapter                     no
OpenJTAG Adapter                        no
SEGGER J-Link Programmer                yes (auto)

Build it

Finally, we build it. Again, I’m snipping the output down to size, but you should end up with an executable binary in src/ called openocd. This final step doesn’t take long (on my machine only about 45s).

jacob@jacob-aspire-mint:/tmp/openocd$ make
Makefile:4634: warning: overriding recipe for target 'check-recursive'
Makefile:4045: warning: ignoring old recipe for target 'check-recursive'
cat src/helper/startup.tcl src/jtag/startup.tcl src/target/startup.tcl src/server/startup.tcl src/flash/startup.tcl | ./src/helper/bin2char.sh > src/startup_tcl.inc || { rm -f src/startup_tcl.inc; false; }
cp src/jtag/drivers/minidriver_imp.h src/jtag/minidriver_imp.h
make  all-recursive
make[1]: Entering directory '/tmp/openocd'
Makefile:4634: warning: overriding recipe for target 'check-recursive'
Makefile:4045: warning: ignoring old recipe for target 'check-recursive'
Making all in jimtcl
make[2]: Entering directory '/tmp/openocd/jimtcl'


[ ... snip ... ]

libtool: link: ranlib src/.libs/libopenocd.a
libtool: link: rm -fr src/.libs/libopenocd.lax src/.libs/libopenocd.lax
libtool: link: ( cd "src/.libs" && rm -f "libopenocd.la" && ln -s "../libopenocd.la" "libopenocd.la" )
depbase=`echo src/main.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`;\
gcc -DHAVE_CONFIG_H -I.   -I./src -I./src -I./src/helper -DPKGDATADIR=\"/usr/local/share/openocd\" -DBINDIR=\"/usr/local/bin\" -I./jimtcl -I./jimtcl  -Wall -Wstrict-prototypes -Wformat-security -Wshadow -Wextra -Wno-unused-parameter -Wbad-function-cast -Wcast-align -Wredundant-decls -Werror -g -O2 -MT src/main.o -MD -MP -MF $depbase.Tpo -c -o src/main.o src/main.c &&\
mv -f $depbase.Tpo $depbase.Po
/bin/bash ./libtool  --tag=CC   --mode=link gcc -Wall -Wstrict-prototypes -Wformat-security -Wshadow -Wextra -Wno-unused-parameter -Wbad-function-cast -Wcast-align -Wredundant-decls -Werror -g -O2   -o src/openocd src/main.o src/libopenocd.la  ./jimtcl/libjim.a  -ldl 
libtool: link: gcc -Wall -Wstrict-prototypes -Wformat-security -Wshadow -Wextra -Wno-unused-parameter -Wbad-function-cast -Wcast-align -Wredundant-decls -Werror -g -O2 -o src/openocd src/main.o  src/.libs/libopenocd.a -lusb-1.0 -lm ./jimtcl/libjim.a -ldl
make[2]: Leaving directory '/tmp/openocd'
make[1]: Leaving directory '/tmp/openocd'

Testing OpenOCD

Now that we have a binary, we need to test it out and see if it works. My target for today is a Raspberry Pi 3 B. We first need to gather some info about our target, i.e., the Raspberry Pi 3. We need to know which pins on the GPIO header correspond to which JTAG signals.

First let’s grab the BCM2835 pinout reference. (Side note: we use the BCM2835 reference because there is no BCM2837 reference, and it seems the pinouts are roughly the same.) This will tell us what each GPIO pin does. Some of the GPIOs are only designated for one singular function, whereas many other GPIOs are multi-function, and their function is software programmable. These alternate functions are designated ALT on the reference material. I used the reference over at e-Linux because I find the table easy to read. Searching the table, we find the JTAG signals we’re interested in (TRST, TCK, TMS, TDI, TDO) are assigned in the range of GPIOs 22-27 for the ALT4 function. Next we want to pull up the schematic of our Raspberry Pi 3 B, and see what each of those map to on the GPIO header. I’ve created the table below to keep things straight.

JTAG SignalBCM283x GPIO #Raspberry Pi 3B J8 Pin #
TRSTGPIO22P15
TCKGPIO25P22
TMSGPIO27P13
TDIGPIO26P37
TDOGPIO24P18
GNDmanyP6

Once we’ve got these figured out we’ve got to prep the Pi for JTAG usage. This is the simplest part in the whole setup. On the Pi’s SD card, add the following line to the config.txt.

enable_jtag_gpio=1

Finally, we’re ready to hook up our JTAG debugger. Looking in the documentation for the OpenOCD FT232R configuration, we find the following table which shows us which RS232 signals correspond to which JTAG signals. We need to (powered down of course!) hook up our FT232R module/cable and Pi accordingly, and don’t forget the ground wire!


    - RXD(5) - TDI
    - TXD(1) - TCK
    - RTS(3) - TDO
    - CTS(11) - TMS
    - DTR(2) - TRST
    - DCD(10) - SRST 

Once things are hooked up, we need to setup our configuration for the OpenOCD tool. The default config from the ft232r.cfg is sufficient for the interface, but I wanted to add one item and to get us debugging we need to tell OpenOCD how to connect to the Pi and its four cores. I’ve based my rpi3b.cfg config off of a fellow GitHub contributor’s config but made some modifications.

ft232r.cfg

adapter driver ft232r
adapter speed 3000
ft232r_restore_serial 0x15

I modified the ft232r.cfg to increase the adapter speed to 3M (3000 kHz) and to restore the port config when OpenOCD is done so the adapter can be used as a serial device again.

rpi3b.cfg

transport select jtag

adapter speed 3000

reset_config trst_and_srst

jtag_ntrst_delay 500

if { [info exists CHIPNAME] } {
  set _CHIPNAME $CHIPNAME
} else {
  set _CHIPNAME rpi3
}

if { [info exists DAP_TAPID] } {
   set _DAP_TAPID $DAP_TAPID
} else {
   set _DAP_TAPID 0x4ba00477
}

jtag newtap $_CHIPNAME tap -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_DAP_TAPID -enable
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.tap

set _TARGETNAME $_CHIPNAME.a53
set _CTINAME $_CHIPNAME.cti

set DBGBASE {0x80010000 0x80012000 0x80014000 0x80016000}
set CTIBASE {0x80018000 0x80019000 0x8001a000 0x8001b000}
set _cores 4

for { set _core 0 } { $_core < $_cores } { incr _core } {

    cti create $_CTINAME.$_core -dap $_CHIPNAME.dap -ap-num 0 \
        -ctibase [lindex $CTIBASE $_core]

    target create $_TARGETNAME.$_core aarch64 \
        -dap $_CHIPNAME.dap -coreid $_core \
        -dbgbase [lindex $DBGBASE $_core] -cti $_CTINAME.$_core

    $_TARGETNAME.$_core configure -event reset-assert-post "aarch64 dbginit"
}

Putting it All Together

Now we have all the pieces we need to debug using our JTAG adapter. Let’s begin!

jacob@jacob-aspire-mint:/opt/apps/openocd$ sudo ./src/openocd -f ./ft232r.cfg -f ./rpi3b.cfg 
Open On-Chip Debugger 0.10.0+dev-01047-g09ac9ab1 (2020-02-04-09:11)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.org/doc/doxygen/bugs.html
Info : only one transport option; autoselect 'jtag'
FT232R restore serial: 0x0015 (enabled)

Warn : Transport "jtag" was already selected
Info : Listening on port 6666 for tcl connections
Info : Listening on port 4444 for telnet connections
Info : clock speed 3000 kHz
Info : JTAG tap: rpi3.tap tap/device found: 0x4ba00477 (mfg: 0x23b (ARM Ltd.), part: 0xba00, ver: 0x4)
Info : rpi3.a53.0: hardware has 6 breakpoints, 4 watchpoints
Info : rpi3.a53.1: hardware has 6 breakpoints, 4 watchpoints
Info : rpi3.a53.2: hardware has 6 breakpoints, 4 watchpoints
Info : rpi3.a53.3: hardware has 6 breakpoints, 4 watchpoints
Info : Listening on port 3333 for gdb connections
Info : Listening on port 3334 for gdb connections
Info : Listening on port 3335 for gdb connections
Info : Listening on port 3336 for gdb connections

Now we’re cooking! You can connect GDB up to each core, debug that way, or use the OpenOCD interface, see below:

OpenOCD Interface

acob@jacob-aspire-mint:/tmp/openocd$ telnet localhost 4444
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Open On-Chip Debugger
> halt
rpi3.a53.3 cluster 0 core 3 multi core
target halted in AArch64 state due to debug-request, current mode: EL3H
cpsr: 0x000003cd pc: 0x20001c
MMU: disabled, D-Cache: disabled, I-Cache: disabled
> targets
    TargetName         Type       Endian TapName            State       
--  ------------------ ---------- ------ ------------------ ------------
 0  rpi3.a53.0         aarch64    little rpi3.tap           running
 1  rpi3.a53.1         aarch64    little rpi3.tap           running
 2  rpi3.a53.2         aarch64    little rpi3.tap           running
 3* rpi3.a53.3         aarch64    little rpi3.tap           halted

> reg
===== Aarch64 registers
(0) x0 (/64): 0x0000000000000003 (dirty)
(1) x1 (/64): 0x00000000C1000000
(2) x2 (/64)
(3) x3 (/64)
(4) x4 (/64)
(5) x5 (/64)
(6) x6 (/64)
(7) x7 (/64)
(8) x8 (/64)

[ ... snip ... ]

GDB Interface

jacob@jacob-aspire-mint:/tmp/openocd$ aarch64-none-elf-gdb
GNU gdb (GNU Toolchain for the A-profile Architecture 9.2-2019.12 (arm-9.10)) 8.3.0.20190709-git
Copyright (C) 2019 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "--host=x86_64-pc-linux-gnu --target=aarch64-none-elf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://bugs.linaro.org/>.
Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.

For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) target remote :3333
Remote debugging using :3333
warning: No executable has been specified and target does not support
determining executable automatically.  Try using the "file" command.
0x0000000000200028 in ?? ()
(gdb) si
0x000000000020002c in ?? ()
(gdb) si
0x0000000000200074 in ?? ()
(gdb) si
0x0000000000200078 in ?? ()
(gdb) 

Wrapping Up

Now we have a JTAG solution that can debug many, many flavors of processors and microcontrollers given the right configuration. It becomes even more useful if your FT232R module supports selecting the logic level voltage like mine does. See below for some pros and cons of this approach.

Pros

This is a quick and dirty way to get a JTAG adapter at no cost if you’ve already got these FTDI chips laying around. It’s quick and fully configurable (check out the OpenOCD config pages for all it can do) and makes a great debugger.

Cons

Since we are bit-banging our way to success here, it is a bit on the slow side. It’s not unusable, but it is slower than a native interface. If you don’t have one of these chips already at your disposal, I’d opt for one of the FT232H or better yet the FT2232H, both of which have an MPSSE engine which greatly improves emulation.

The post JTAG On the Cheap with the FTDI FT232R appeared first on Jacob N Calvert.

]]>
https://jacobncalvert.com/blog-archive/2020/02/04/jtag-on-the-cheap-with-the-ftdi-ft232r/feed/ 8
Building a Customized Linux Image for Raspberry Pi with Yocto + Docker Support https://jacobncalvert.com/blog-archive/2019/12/22/building-a-customized-linux-image-for-raspberry-pi-with-yocto-docker-support/ https://jacobncalvert.com/blog-archive/2019/12/22/building-a-customized-linux-image-for-raspberry-pi-with-yocto-docker-support/#respond Sun, 22 Dec 2019 06:49:50 +0000 https://jacobncalvert.com/?p=581 Motivation I recently stumbled upon HypriotOS while looking for Docker-ready distributions for my Raspberry Pi 3B+. I flashed this onto and SD card and started playing around with it. It works incredibly well, but I noticed that it was built for armv7l which is a 32-bit implementation. Since the Raspberry Pi 3B+ has a 4x core Cortex-A53 which is 64 bit, I wanted to make use of the 64 bit processor! I’ve worked with Yocto before (in fact, my day…

The post Building a Customized Linux Image for Raspberry Pi with Yocto + Docker Support appeared first on Jacob N Calvert.

]]>
Motivation

I recently stumbled upon HypriotOS while looking for Docker-ready distributions for my Raspberry Pi 3B+. I flashed this onto and SD card and started playing around with it. It works incredibly well, but I noticed that it was built for armv7l which is a 32-bit implementation. Since the Raspberry Pi 3B+ has a 4x core Cortex-A53 which is 64 bit, I wanted to make use of the 64 bit processor! I’ve worked with Yocto before (in fact, my day job uses Yocto), so I decided I’d build my own. For more on containers, see my other blog posts on what it is, what it can be used for, and how to use it.

Process

Prerequisites

Yocto is a build, not a distribution, so it is quite resource intensive. I would suggest having at least 60GB free disk space, and a quad core machine at a minimum. You’ll also need a Linux installation, and the build essentials installed (git, gcc, etc.).

EDIT: Checking the disk usage after the builds shows around 55GB used. On a 2C4T Intel Core i5 it took about 2H to build.

Project Setup

First, create a working directory and clone all the piece-parts we need to build.

mkdir rpi3bplus-build-yocto
cd rpi3bplus-build-yocto
git clone git://git.yoctoproject.org/poky
git clone git://git.openembedded.org/meta-openembedded
git clone git://git.yoctoproject.org/meta-raspberrypi
git clone git://git.yoctoproject.org/meta-virtualization 

Next create the project and add the base layers.

source poky/oe-init-build-env rpi64
bitbake-layers add-layer ../meta-raspberrypi
bitbake-layers add-layer ../meta-openembedded/meta-oe
bitbake-layers add-layer ../meta-openembedded/meta-python
bitbake-layers add-layer ../meta-openembedded/meta-perl
bitbake-layers add-layer ../meta-openembedded/meta-networking
bitbake-layers add-layer ../meta-openembedded/meta-filesystems
bitbake-layers add-layer ../meta-virtualization

Edit the conf/local.conf file sections as needed:

MACHINE ??= "raspberrypi3-64"
CORE_IMAGE_EXTRA_INSTALL += "kernel-modules htop openssh iperf3 docker-ce bash ntp "

INHERIT += "extrausers"

EXTRA_USERS_PARAMS += " useradd pi; \
                       usermod  -p 'raspberry' pi; \
                       usermod  -a -G sudo pi; \
                       usermod -P root root; "

DISTRO_FEATURES_append = " virtualization"

Next we will build the image. This will take a while depending on how beefy your build machine is.

bitbake core-image-minimal
Parsing recipes: 100% |########################################################################################################################################################################################################| Time: 0:02:16
Parsing of 2540 .bb files complete (0 cached, 2540 parsed). 3827 targets, 140 skipped, 0 masked, 0 errors.
NOTE: Resolving any missing task queue dependencies

Build Configuration:
BB_VERSION           = "1.44.0"
BUILD_SYS            = "x86_64-linux"
NATIVELSBSTRING      = "universal"
TARGET_SYS           = "aarch64-poky-linux"
MACHINE              = "raspberrypi3-64"
DISTRO               = "poky"
DISTRO_VERSION       = "3.0"
TUNE_FEATURES        = "aarch64 cortexa53 crc"
TARGET_FPU           = ""
meta                 
meta-poky            
meta-yocto-bsp       = "master:6bb4a252199cfd5d44ad7ab6fc4118c80a1aae92"
meta-raspberrypi     = "master:a0a5d3848e76b7f90ef8e42c56211da78db1c7ba"
meta-oe              
meta-python          
meta-perl            
meta-networking      
meta-filesystems     = "master:d9f3e6dbed8e5d96f2069280f0a566af89afb2fa"
meta-virtualization  = "master:5fb77ae4c4e1015e40257f9e59e16c497e30c53c"

After a couple of hours, you will have a completed, ready to flash SD Image at <build>/rpi3bplus-build-yocto/rpi64/tmp/deploy/images/raspberrypi3-64/core-image-minimal-raspberrypi3-64.rpi-sdimg which you can burn to an SD card with:

dd if=./core-image-minimal-raspberrypi3-64.rpi-sdimg of=/dev/sdX status=progress

Your image should boot up and docker will be running!

NOTE: You will manually have to set the date to pull from Docker registries over HTTPS because the certification validation will fail otherwise. We could add and configure NTP to fix the but… for another day. Use:

date "+%d-%m-%C%y %H:%M:%S" -s "2019-12-22 00:30:01"

There is one last thing you’ll want to do. You’ll want to use GParted or similar tool to enlarge your filesystem partition to take up the rest of your SD card so you will have some room for container images. You need to do this because the default SD Image builder script only provides enough space for the root filesystem and no more. In my configuration it ended up being ~300MB, so I expanded it take up the remaining ~59GB. See example below:

Results

As it turns out, I have a system that can build and run 64-bit Docker images and is pretty darn slim. Here’s a screenshot of htop running.. only 12 processes – not bad!

Some Metrics

The is the minimal image and it has 12 processes, with an incredibly low footprint. I loaded up an Ubuntu container and installed iperf3, then ran a test to my laptop. I was impressed to find the following result:

[ ID] Interval           Transfer     Bandwidth       Retr
[  5]   0.00-10.13  sec   116 MBytes  96.0 Mbits/sec    9             sender
[  5]   0.00-10.13  sec   113 MBytes  93.8 Mbits/sec                  receiver

Even running that test, the load on the Pi was:

root@raspberrypi3-64:~# cat /proc/loadavg 
0.05 0.22 0.19 1/141 2125
root@raspberrypi3-64:~# 

Downloads

The post Building a Customized Linux Image for Raspberry Pi with Yocto + Docker Support appeared first on Jacob N Calvert.

]]>
https://jacobncalvert.com/blog-archive/2019/12/22/building-a-customized-linux-image-for-raspberry-pi-with-yocto-docker-support/feed/ 0
Hacking a Smart Outlet https://jacobncalvert.com/blog-archive/2019/11/17/hacking-a-smart-outlet/ https://jacobncalvert.com/blog-archive/2019/11/17/hacking-a-smart-outlet/#respond Mon, 18 Nov 2019 02:15:20 +0000 https://jacobncalvert.com/?p=497 IoT Everywhere Everything, and I mean everything is “smart” these days. Everyone has heard of the Internet of Things, and we are living through the emergence of some incredibly revolutionary connectivity. Some pretty cool and useful concepts have come out of it, admittedly, but there’s also some drawbacks. I really enjoy the idea of having smart outlets that I can command with my voice, and there are outlets-a-plenty on Amazon, but can I trust them? I’ve decided to use my…

The post Hacking a Smart Outlet appeared first on Jacob N Calvert.

]]>
IoT Everywhere

Everything, and I mean everything is “smart” these days. Everyone has heard of the Internet of Things, and we are living through the emergence of some incredibly revolutionary connectivity. Some pretty cool and useful concepts have come out of it, admittedly, but there’s also some drawbacks.

I really enjoy the idea of having smart outlets that I can command with my voice, and there are outlets-a-plenty on Amazon, but can I trust them? I’ve decided to use my engineering skills to put a one of these outlets to the test.

Project Plan

Test Subject

I purchased a pack of Etekcity Smart Plugs which claim to be Alexa-enabled, and feature energy monitoring.

Test Plan

I want to test many aspects about the smart plug, so I laid out a test plan of tests I want to run.

  • Record the network traffic coming and going from the device (couldn’t complete, see below)
  • Pop open the device, see what hardware is under the hood
  • Write some custom firmware for the device

Project Execution

Preparation

These devices generally work in the following way:

  1. Connect to the device while it’s acting as an Access Point (AP)
  2. Configure the device via a proprietary app
  3. Device transitions from AP to Station Mode and connects to your local network
  4. User connects Alexa/Google/etc services to device

When I started to look at the app for these devices, I decided against installing and using it per the user documentation. Here’s why.

The app for setting up the plug required the following permissions:

  • Camera
  • Contacts
  • Location
  • Call logs
  • Phone
  • Storage
  • way, way more.

See the screenshot below for the full list.

So right off the bat, I decided to not install this app, simply because it had way, way too many permission oddities.

Opening the Device Up

I unpackaged these units and immediately noticed that there’s nary a screw anywhere. Upon closer inspection, you could see a thin line where the unit was clamshelled together. I grabbed my tools (a skinny flat-head screwdriver and a 3D printer sharpened spatula) and started poking for the release tabs.

After prodding the device for a few moments, I heard the distinctive “pop” of a plastic catch tab unclasping. I was able to raise up the edge of the clamshell and began working my way around the unit. Within seconds, the unit was open and the guts were exposed.

Inside face/inside of front of unit

Jackpot!

The first thing I noticed was that the WiFi module is labeled as an ESP01! Very fortuitous for me since there is so much open source goodness out there the ESP8266 and ESP8285. Next up is figuring out how to flash this device. Others I’ve looked at hid the traces for the TX, RX, and GPIO0 on the backside, so after the module was soldered on, it was pretty much inaccessible. Not so, with this guy! There were test points on the PCB, perfectly labeled for everything I needed: TX, RX, GPIO0, 5V and GND.

Inside of unit / PCB View

I tacked on some temporary wires as shown in the photo and connected to my laptop via a USB-TTL Serial cable. My cable is a 3.3V logic cable with 5V on the VCC wire, so I powered the chip from my cable as well.

I opened picocom and set the baud rate to 115200, and voila! I had terminal output. Regrettably, I didn’t capture the terminal output, but it mentioned some version numbers, the ESP SDK version, and had the classic boot up text from the ESP01.

On the less fortuitous side, I couldn’t see any other chips (like the one used for energy monitoring), so I suppose they are on the opposite side of the PCB, which is molded into the shell.

Flashing the Device

I had all the right inputs, but would it flash? The answer was yes! I fired up the Arduino IDE and wrote a simple Hello, World app, and performed the flashing procedure: pull GPIO0 low, apply power, let GPIO0 float, begin flashing.

Without any fuss and to my surprise, the unit flashed without delay. I now had a working smart plug unit that I could flash very easily! I wrote up some custom firmware that allowed over-the-air (OTA) updates and removed my temp wires.

Removed temporary wires, ready for reassembly

Custom Firmware

After a few iterations of writing “probing” apps and loading it onto the device, I figured out that the pinout from the ESP01 was the following (irrelavent pins ignored):

Pin #Function
0Flash
4Relay (Active High)
5Blue LED (Active High)
12Pulsed Energy Monitor (Voltage)
13Pulsed Energy Monitor (Power or Current??)
14Front Panel Switch (High => Switch Pushed)
16Amber LED (Active High)

Of these pins, I knew how to use most right away. It was those energy monitoring pins I couldn’t figure out. Since I didn’t know how to understand the output, and I didn’t know what IC was generating the output, I couldn’t really make use of it. I noted a few characteristics about the signals however:

  1. The signal on P12 stayed constant in time. I measured the low and high pulse duration, and they were the same (within 1 uS).
  2. The signal on P13 was constant low when the relay was inactive, and toggled when there was a device connected and the relay was active.

From these observations, I made the assumption that P12 was the voltage pin, and P13 must be current or power. I also made the assumption that the signal must be a 50% DC signal which varies in frequency only. Using a pin change interrupt I was able to verify this assumption.

Now that I understood the signal profile, I needed to understand how to convert it to something usable. I had to do a lot of Googling around, but I stumbled upon a forum which showed many of these cheap WiFi outlets use a Chinese chip HLW8012. There’s only a Chinese language datasheet available for the HLW8012 on the web, but again, a little Googling revealed this guy’s website which is in English! He had a ton of useful information on his website, and it corroborated the signals I was observing, so I again made the assumption that this is the right chip.

Using the formulas outline on the last website I found, I was able to turn the P12 signal pulse width into a voltage, and verify that it was pretty darn close using my Kill-a-Watt. ( I highly recommend these little devices, they are super useful if you like to tinker). I got values that were ± 0.75% and so I concluded this was the right chip. Next was determining if the P13 pulse was a power or current. Since it stopped with the opening of the relay and started with the closing of the relay, it could have been both. From the previous website, the poster noted that the HL8012 chip had two outputs, CF and CF1. One of the inputs (SEL) made one output switch between voltage and current, and the other was always power. There was my answer! If the output on P12 was constant regardless of load, and I’d been able to get a voltage from the readings which was fairly accurate, then the other has to be power. Converting the P13 pulse to power also jived with my Kill-a-Watt’s readings (although with a little worse accuracy, it is ± 3% by my best estimation).

First Release

When I had identified how to operate all the parts of this little device, I set about writing a firmware load which enabled all the uses I desired. I ended up with the following feature-set in my first release:

  • Alexa integration via Phillips Hue emulation
  • Over-the-Air updates for touch-free updating
  • Web Interface
    • Device Control
    • Device debug information
    • Device Energy Monitoring graphs
  • LED indication for device state
  • Button interface for manual on/off
ESP Smart Switch Web Interface

Wrapping Up

I only accomplished 2 of my 3 stated goals, but I did have a ton of fun doing it! At the end of the day, I’ve got two functional smart outlets with energy monitoring which have custom firmware. By virtue of using custom firmware, I can control what is needed to control the device as well, so no shady apps with too many permissions. I liked these so much, and they were so easy to customize, I have decided to ordered 4 more for around the house!

The post Hacking a Smart Outlet appeared first on Jacob N Calvert.

]]>
https://jacobncalvert.com/blog-archive/2019/11/17/hacking-a-smart-outlet/feed/ 0
Enterprise Service Buses and Middleware https://jacobncalvert.com/blog-archive/2018/03/14/enterprise-service-buses-and-middleware/ https://jacobncalvert.com/blog-archive/2018/03/14/enterprise-service-buses-and-middleware/#respond Wed, 14 Mar 2018 16:33:48 +0000 http://jacobncalvert.com/?p=214 Distributed computing is the new norm.   Multi-service architectures surround us daily. Our computing needs are served from many different independently operated services, and all implemented using different underlying technologies. When these independent units bring only one small service or set of services, it is called a microservice. While there is still some industry discussion about the exact properties of a microservice, one thing can be agreed upon: microservice-based systems enforce modular design by default. This begs the question, if…

The post Enterprise Service Buses and Middleware appeared first on Jacob N Calvert.

]]>
Distributed computing is the new norm.

 

Multi-service architectures surround us daily. Our computing needs are served from many different independently operated services, and all implemented using different underlying technologies. When these independent units bring only one small service or set of services, it is called a microservice. While there is still some industry discussion about the exact properties of a microservice, one thing can be agreed upon: microservice-based systems enforce modular design by default. This begs the question, if my services are decoupled and modular, how do they communicate effectively to create an entire system that performs something useful?

Enterprise Service Buses and Middleware

The solution to this problem is a connector software which acts as a message routing bus. The Enterprise Service Bus (ESB), often simplified as Middleware (although Middleware is not always an ESB), allows these decoupled services to talk to each other in a language and medium-neutral way. For instance, if you have a Service-Oriented Architecture (SOA) comprised of services written in different languages, with a few plug ‘n play components, but they all need to share data, a language-neutral ESB is in order.

Many of the commercial ESBs are written as a publisher-subscriber (PubSub) system. This allows the individual services to subscribe to the types of messages it is interested in knowing about. The ESB or Middleware is responsible for managing the “channels” and relaying the published messages to the right subscribers. The Middleware or ESB provider will usually provide a connector for many languages making it easy to interface your services to the ESB. If the connector is not provided, the specification will usually be provided so that you can implement your own connector. This allows an SOA system to communicate without worrying about the transport mechanism of its messages.

 

It’s easy to see that ESBs can be found nearly everywhere in technology. In fact, many of the most common services we use today can be loosely classified as an ESB. Perhaps I’ll start a project soon to build an ESB and see how it goes?

Thanks for reading!

 

 

The post Enterprise Service Buses and Middleware appeared first on Jacob N Calvert.

]]>
https://jacobncalvert.com/blog-archive/2018/03/14/enterprise-service-buses-and-middleware/feed/ 0
Binary bit fields and flags https://jacobncalvert.com/blog-archive/2014/08/02/binary-bit-fields-and-flags/ https://jacobncalvert.com/blog-archive/2014/08/02/binary-bit-fields-and-flags/#respond Sat, 02 Aug 2014 07:29:53 +0000 http://jacobncalvert.com/?p=168 If you’ve used any legacy C libraries before, you’ve probably used these things called bit fields, even if you didn’t know what they were. Bit fields are a way to efficiently store multiple boolean values in one or more bytes. If you can imagine an 8 bit integer as binary, each bit would have to be either a 1 or a 0, corresponding to an “On” or “Off” value. With just one 8 bit variable, you can store 8 on/off…

The post Binary bit fields and flags appeared first on Jacob N Calvert.

]]>
If you’ve used any legacy C libraries before, you’ve probably used these things called bit fields, even if you didn’t know what they were.

Bit fields are a way to efficiently store multiple boolean values in one or more bytes. If you can imagine an 8 bit integer as binary, each bit would have to be either a 1 or a 0, corresponding to an “On” or “Off” value. With just one 8 bit variable, you can store 8 on/off values for your program. The syntax on how to set, unset, and retrieve these values can be a little confusing however. The method for using these helpful little bit fields involves some binary math with the binary operators AND, OR, and NOT. In C based languages these are written as &, |, and, ~, respectively. I’ll give an example in C that will hopefully make this math clearer. First we need to define some values as our flags. Each flag has to have a value that is a power of 2. For example:

enum FLAGS
{
	FLAG_A = 0x01,// 1
	FLAG_B = 0X02,// 2
	FLAG_C = 0X04,// 4
	FLAG_D = 0X08,// 8
	FLAG_E = 0X10,// 16
	FLAG_F = 0X20 // 32

	// so on and so forth
};

These could just as easily be written as the actual integer values, however I’ll stick to HEX notation for this example. Next we need a variable of at least 6 bits to hold our flags’ on or off state. Let’s use an integer type, and set all the flags to “Off.”

static int THE_OPTION = 0x00;

Now we’re ready to set, unset, and test some flags! To set the option to “On” for a certain flag, we must turn the bit “On” in our variable. To do this we use the OR operation. I explain why in the example below.

FLAG_C = 4, in 8-bit binary this is 00000100
THE_OPTION = 0, in 8-bit binary	    00000000

if we OR them:

THE_OPTION |= FLAG_C

the binary math looks like:

	00000000
OR	00000100
-------------
	00000100

This is a simple example but the point holds. To apply a flag, we apply the OR operator. To remove an option, we use the AND operator.

THE_OPTION = 0B00000100; //binary notation for 4

THE_OPTION &= ~FLAG_C; // THE_OPTION AND-EQUALS NOT FLAG_C

the binary math looks like:

	00000100
AND	11111011
-------------
	00000000

To check the status of a flag in THE_OPTION, one can simply check:

if(THE_OPTION & FLAG_F)
{
	//do things
}

These can also be chained, for instance

#include "stdio.h"
enum FLAGS
{
	FLAG_A = 0x01,// 1
	FLAG_B = 0X02,// 2
	FLAG_C = 0X04,// 4
	FLAG_D = 0X08,// 8
	FLAG_E = 0X10,// 16
	FLAG_F = 0X20 // 32

	// so on and so forth
};

static int THE_OPTION = 0x00;
void test_options()
{
	char line[512], *p;
	p = &line;
	p += sprintf(p,"THE_OPTION contains ");
	if(FLAG_A & THE_OPTION)
	{
		p += sprintf(p, "FLAG_A and ");
	}
	if(FLAG_B & THE_OPTION)
	{
		p += sprintf(p, "FLAG_B and ");
	}
	if(FLAG_C & THE_OPTION)
	{
		p += sprintf(p, "FLAG_C and ");
	}
	if(FLAG_D & THE_OPTION)
	{
		p += sprintf(p, "FLAG_D and ");
	}
	if(FLAG_E & THE_OPTION)
	{
		p += sprintf(p, "FLAG_E and ");
	}
	if(FLAG_F & THE_OPTION)
	{
		p += sprintf(p, "FLAG_F and ");
	}
	printf("%s, that is all.\n", line);
}
int main()
{

	THE_OPTION = (FLAG_A | FLAG_C | FLAG_F);
	test_options();

	THE_OPTION &= ~FLAG_A;
	test_options();

	THE_OPTION &= ~(FLAG_C | FLAG_F);
	test_options();

	THE_OPTION = 0XFF;
	test_options();
	return 0;
}



That will print

THE_OPTION contains FLAG_A and FLAG_C and FLAG_F and , that is all.
THE_OPTION contains FLAG_C and FLAG_F and , that is all.
THE_OPTION contains , that is all.
THE_OPTION contains FLAG_A and FLAG_B and FLAG_C and FLAG_D and FLAG_E and FLAG_F and , that is all.

This post is by no means an exhaustive list of the ways bit fields can be used, however these are the basic ways you can use them. Bit fields are a good choice in applications where memory is limited, or there are lots of boolean data points that need to be stored since one 32 bit variable can hold all the same data as 32 bool types in C. I hope this post was clear and somewhat educational! If you have anything to add send me some mail over on the contact page!

The post Binary bit fields and flags appeared first on Jacob N Calvert.

]]>
https://jacobncalvert.com/blog-archive/2014/08/02/binary-bit-fields-and-flags/feed/ 0
C++ 2014: auto return deduction and more! https://jacobncalvert.com/blog-archive/2014/07/15/c-2014-auto-return-deduction-and-more/ https://jacobncalvert.com/blog-archive/2014/07/15/c-2014-auto-return-deduction-and-more/#respond Wed, 16 Jul 2014 01:50:53 +0000 http://jacobncalvert.com/?p=172 The new C++ standard-in-the-making codenamed C++1y, has some great new features. The most standout addition in my opinion is the ‘return type deduction’ feature which allows functions to use ‘auto’ return types that will be deduced at runtime. There are a few limits on this functionality however. Recursion can only happen if there is at least one return statement that can be evaluated to a non-auto type. For example: // this factorial works auto factorial(int i) { if(i == 0…

The post C++ 2014: auto return deduction and more! appeared first on Jacob N Calvert.

]]>
The new C++ standard-in-the-making codenamed C++1y, has some great new features.

The most standout addition in my opinion is the ‘return type deduction’ feature which allows functions to use ‘auto’ return types that will be deduced at runtime. There are a few limits on this functionality however. Recursion can only happen if there is at least one return statement that can be evaluated to a non-auto type. For example:

// this factorial works
auto factorial(int i)
{
    if(i == 0 || i == 1)
    {
        return 1;
    }
    else
    {
        return i * factorial(i-1);
    }
}
// this one will not
auto factorial2(int i)
{
    if(i > 1)
    {
        return i * factorial(i-1);
    }
    else
    {
        return 1;
    }
}


This feature is very neat and somewhat ‘Pythonic.’ In C++11 the lambda feature already allows this auto typing but in C++14 it will be available to all functions.
Another notable addition to C++ in the latest upcoming release is the introduction of binary literals. With this, you can explicitly specify binary numbers with syntax like:

int nine = 0B1001;


There are many, many more language features being added in C++14; too many to note in detail. Check out more at the Wikipedia article for C++1y or at the standards status page for C++.

The post C++ 2014: auto return deduction and more! appeared first on Jacob N Calvert.

]]>
https://jacobncalvert.com/blog-archive/2014/07/15/c-2014-auto-return-deduction-and-more/feed/ 0