CoIDE, STM32F103 and Semihosting

I have been a little quiet lately as I have been working on a few projects. One of these are some experiments with the CooCox CoIDE and a STM32F103 dev board that I picked up off EBay a while back.

As a quick background, I have generated the bulk of the test project(s) with STM32CubeMX, and then modified what I needed. It should be noted that STM has updated the StdPeripheral library with a new HAL Library, which I decided to use. CoIDE has a neat feature called “semihosting” which allows you to shoot debug messages back to the IDE via the JTAG interface, freeing up the UART for your application-specific use.

The problem comes when adding semihosting. You need to add the “Retarget printf” component as well as the “Semihosting”. A quick implementation of PrintChar() in the semihosting code:

#include <semihosting/semihosting.h>
 
void PrintChar(char c)
{
  SH_SendChar(c);
}

If you try and compile this, you get the following error:

[cc] Starting link
[cc] arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -g -nostartfiles -Wl,-Map=cdctest.map -O0 -Wl,--gc-sections -LC:\CooCox\CoIDE\configuration\ProgramData\cdctest -Wl,-TC:\CooCox\CoIDE\configuration\ProgramData\cdctest/arm-gcc-link.ld -g -o cdctest.elf ..\obj\stm32f1xx_hal_rcc_ex.o ..\obj\semihosting.o ..\obj\stm32f1xx_hal_pwr.o ..\obj\stm32f1xx_hal_can.o ..\obj\stm32f1xx_hal.o ..\obj\stm32f1xx_it.o ..\obj\stm32f1xx_hal_dac.o ..\obj\stm32f1xx_hal_gpio_ex.o ..\obj\stm32f1xx_hal_wwdg.o ..\obj\stm32f1xx_hal_cortex.o ..\obj\stm32f1xx_hal_crc.o ..\obj\stm32f1xx_hal_iwdg.o ..\obj\system_stm32f1xx.o ..\obj\stm32f1xx_hal_rcc.o ..\obj\stm32f1xx_hal_dac_ex.o ..\obj\stm32f1xx_hal_adc.o ..\obj\stm32f1xx_hal_i2s.o ..\obj\stm32f1xx_hal_smartcard.o ..\obj\stm32f1xx_hal_pcd.o ..\obj\stm32f1xx_hal_uart.o ..\obj\usbd_core.o ..\obj\main.o ..\obj\startup_stm32f103xb.o ..\obj\stm32f1xx_hal_usart.o ..\obj\stm32f1xx_hal_nor.o ..\obj\stm32f1xx_ll_usb.o ..\obj\printf.o ..\obj\stm32f1xx_hal_spi_ex.o ..\obj\stm32f1xx_hal_cec.o ..\obj\stm32f1xx_hal_hcd.o ..\obj\stm32f1xx_hal_flash.o ..\obj\stm32f1xx_hal_gpio.o ..\obj\stm32f1xx_hal_dma.o ..\obj\usbd_desc.o ..\obj\usbd_conf.o ..\obj\stm32f1xx_hal_adc_ex.o ..\obj\stm32f1xx_hal_irda.o ..\obj\stm32f1xx_hal_sd.o ..\obj\sh_cmd.o ..\obj\stm32f1xx_hal_spi.o ..\obj\syscalls.o ..\obj\stm32f1xx_hal_i2c.o ..\obj\stm32f1xx_hal_msp.o ..\obj\usb_ctrl.o ..\obj\stm32f1xx_hal_eth.o ..\obj\stm32f1xx_ll_fsmc.o ..\obj\usbd_cdc.o ..\obj\stm32f1xx_hal_rtc.o ..\obj\stm32f1xx_hal_tim.o ..\obj\stm32f1xx_hal_flash_ex.o ..\obj\usbd_ctlreq.o ..\obj\stm32f1xx_hal_pcd_ex.o ..\obj\usbd_cdc_if.o ..\obj\stm32f1xx_hal_nand.o ..\obj\usbd_ioreq.o ..\obj\stm32f1xx_hal_pccard.o ..\obj\stm32f1xx_hal_sram.o ..\obj\usb_device.o ..\obj\stm32f1xx_hal_rtc_ex.o ..\obj\stm32f1xx_hal_tim_ex.o ..\obj\stm32f1xx_ll_sdmmc.o -lm -lgcc -lc
[cc] c:/program files (x86)/gnu tools arm embedded/5.3 2016q1/bin/../lib/gcc/arm-none-eabi/5.3.1/../../../../arm-none-eabi/lib/armv7-m\libc.a(lib_a-impure.o):(.data._impure_ptr+0x0): multiple definition of `_impure_ptr'
[cc] ..\obj\printf.o:(.data+0x428): first defined here
[cc] collect2.exe: error: ld returned 1 exit status

It turns out that after a lot of googling, pulling out of hair and cursing, the answer is rather simple. It seems that the struct “r” and “_impure_ptr” are being redefined in printf.c; so we just need to comment them out from the printf.c file in our project:

#include <semihosting/semihosting.h>
 
void PrintChar(char c)
{
	SH_SendChar(c);
}
 
/** Required for proper compilation. */
//struct _reent r = {0, (FILE *) 0, (FILE *) 1, (FILE *) 0};
//struct _reent *_impure_ptr = &r;
 
...

Rebuild and problem solved.

Compilers Never Lie

Just a quick note about an annoying behaviour I found in the Ardunio IDE + compiler + toolchain. I was writing the following task scheduler and started off with the typical typedef of a function prototype:

typedef void (*callback_t)(void);

struct task_t {
 long interval;
 int lastScheduled;
 int nextScheduled;
 boolean oneShot;
 callback_t callback;
};

void setup() {
}

void loop() {
}

void addInterval(int intervalMicros, callback_t f) { 
}

void addOneShot(int delayMicros, callback_t f) {
}

This kept on throwing the following compilation errors in the IDE:

Scheduler:6: error: 'callback_t' has not been declared
Scheduler:7: error: 'callback_t' has not been declared

Weird, since there’s not even a USAGE of callable_t on those lines.  Sniffing a bit deeper, I found that the IDE actually pre-compiles my program (called a “sketch”) into a temporary .cpp file, which contained the following:

#line 1 "Scheduler.ino"

#include "Arduino.h"
void setup();
void loop();
void addInterval(int intervalMicros, callback_t f);
void addOneShot(int delayMicros, callback_t f);
void run();
#line 3
typedef void (*callback_t)(void);

struct task_t {
 long interval;
 int lastScheduled;
 int nextScheduled;
 boolean oneShot;
 callback_t callback;
};

void setup() {
}

void loop() {
}

void addInterval(int intervalMicros, callback_t f) {
}

void addOneShot(int delayMicros, callback_t f) {
}

Ah ha! The damn sketch “pre-compiler” was automatically forward declaring my two functions addInterval() and addOneShot() and this was creating an undefined forward usage of callback_t. Thank you Arduino IDE.

Meet Public Key Cryptography: Asymmetric Encryption for the rest of Us

Most people in computing-related fields will have heard of public key encryption. The goal of this article to shed some light on how it works and how it is used. Most of the focus will be on providing explanations and examples that do not involve the mathematics of asymmetric cryptography.

Terminology

First we need to quickly define some terms that might be new to you.

  • Encryption: the act of taking a readable piece of text and transforming it into a scrambled, unreadable text. This operation is always reversible.
  • Decryption: the act of taking a previously encrypted text and transforming it back into its original readable form.
  • Plain Text: text that is readable by either humans or computers and not encrypted in any way.
  • Cipher Text: the output of some encryption algorithm. This text is (if the encryption is good) not readable by anyone or anything.
  • Key: an object used to open a lock. In cryptography, “keys” are used to transform plain text to cipher text and cipher text to plain text.
  • Public Key: a very large integer that is paired mathematically with a unique private key.
  • Private Key: a very large integer that is paired mathematically with a unique public key.

What is Asymmetric Encryption?

Imagine a box with a lock on it which we will define as a “lock box”. The typical lock box may have a number of identical keys, any of which can lock or unlock the box. This is how typical, or “symmetric” encryption works: one key is used to both transform the plain text to and from a cipher text. In asymmetric encryption, you have to imagine two keys and a single lock box. One key can only unlock the lock box (we will call this our “private” key), while the second key can only lock the lock box (we will call this our “public” key). To send a message, first distribute the public key to the person we wish to communicate with; we will call this person Alice. Now suppose Alice wishes to send us a message. She will compose her message, and place it in the lock box, shut and lock the box with the public key we have given her. The lock box will be sent to us, and we will then open the lock box with the private key that we have. The bit that makes this work is that the public key, which in theory could be given to anyone, can only lock the lock box. So any message that is placed in the lock box can only be viewed by someone with the matching private key. If we wish to send a message to Alice, we would need to have her public key and lock box and the same process would occur.

Details and the Devil

Unfortunately, no exact physical representation of asymmetric encryption exists (to my knowledge). A real asymmetric encryption system uses only a public key and a private key pair; the public and private lock boxes are not used. Furthermore, the astute observer will notice that a single public-private key pair were used to communicate only in a single direction. This is due to some properties of asymmetric cryptography.

Public Key Encryption

Suppose Alice and Bob wish to use asymmetric cryptography. They each have a public and private key, and they have both exchanged their public keys. Each can do the following:

  • encrypt a message with the others public key
  • encrypt a message with their private key

The previous example used the first case, where Alice used our public key to send us a message. This works because only our private key will decrypt the message, so the message is safely encrypted and only the recipient can read it. However, if we had wanted to send a message back to Alice such that no one else could read it, we could not use our private key to encrypt it, as anyone with our public key could decrypt and read the message. We must always assume that public keys are available to everyone and anyone (indeed we want this to be the case as we will see later on), and that private keys must be kept absolutely secret and is never distributed.

Public Key Signing

This property of anyone being able to decrypt a message that we encrypt with our private is actually useful, just not for exchanging secret messages. It can be used to verify that a message could only have been sent by a specific individual. For example, suppose we wish to send a message to Alice (perhaps our physical mail address) but we can not be sure that Mallory will not intercept the message and change our address for his. Assuming that Alice has our public key, we could simply encrypt our mail address with our private key and then send it to Alice. She will then be able to decrypt it with our public key and get our mail address. And what about Mallory? Suppose he finds a way of intercepting our encrypted mail address message (and don’t forget, he can decrypt it since we assume he could have access to our public key just as Alice does), replaces it with his own mail address, encrypts that with his own private key and then forwards it to Alice such that she thinks it came from us. Alice will then, believing that the message came from us, attempt to decrypt it with our public key. This will fail and result in garbage since our public key will not decrypt Mallory’s message. Alice will then know that the message did not originate from us and will not trust the mail address that she received.

In Real Life

Asymmetric encryption is rarely (if ever) used to encrypt or sign whole messages; the computation cost is too high. For encryption, a symmetric key (remember that symmetric encryption uses a single key for both encrypting and decrypting, much like a physical key and lock) is generated by the sender (this is sometimes called a “session key” since it is usually valid only for the immediate message being exchanged between two individuals), and used to encrypt a message. The session key is then encrypted with the public key of the recipient and sent to the recipient along with the encrypted message (Note that these session keys are almost never sent between two parties over the wire; protocols like Diffie-Hellman key-exchange perform this function in a more secure fashion for interactive communications). The recipient will then decrypt the session key with their private key and will now be able to decrypt the message . Symmetric encryption is used to encrypt messages because they are very very fast when compared with asymmetric encryption and messages are typically fairly large (typical “large” keys are 1024 bits or 128 bytes versus messages that are typically greater than 512 bytes).

For signing, a hash of the message being sent is encrypted (or “signed”) with the private key of the sender. A hash is a one-way function that maps a block of data (the message in this case) to a unique numeric value. The message and signed hash are then sent to the recipient, who will then re-hash the message, and compare it to the decrypted hash (signature). If they match, then that message was sent by the sender.

Problems

There are a few problems with asymmetric encryption. The most glaring problem is how does an individual know that the public key they have actually belongs to who they think it does? This seems trivial; one just has to be given it by the owner of the public key. However, in real-life we may not know the recipient of a message or have had any prior contact with them before we wish to send them a message. This is where Public Key Infrastructure (PKI) comes into the discussion. This is a system that provides a mechanism for the distribution and storage of public keys. Key exchange is a complicated problem (and far, far outside the scope of this article), and there exists no fool-proof scheme that is convenient enough for the general public to use at this time.

Another major hurdle to adoption for this type of encryption and signing was hinted earlier: there is no good physical representation of asymmetric encryption, and so it is difficult for individuals to grasp how it actually works and how to use it correctly.

But perhaps the biggest problem with this (and many other forms of encryption) is that people don’t feel that their email to grandma is important enough to warrant the added complexity encryption brings. This view is changing slowly; until fairly recently the whole idea of “encrypted” web sites (such as your bank’s web site for example) was very abstract for the general population.

Conclusions

Asymmetric encryption serves two primary purposes: to encrypt messages and to sign message. For bi-directional communications, each participant must have their own public and private keys, and must have the public key of every participant that they wish to communicate with. Messages are never encrypted with asymmetric keys; they use a symmetric (session) key instead. Hopefully this article provides a bit of clarity on how asymmetric encryption technology can be used to aid in secure and trusted communication.

References

Using Assertion Checking

(Thank you to Fred Chouinard and Steven Pigeon for feedback on this post many moons ago)

The goal of this article is to briefly explain assertion checking. It will describe what an assertion is, why we want to use them, when and where they should be used and some pitfalls to watch out for. It will close with a small example of how to enable them for the Java platform.

What is an Assertion

An assertion is a special operation that instructs the compiler to perform a particular test, and if it fails, to crash and dump debugging information to either a window or the console. The programmer must provide the test to the compiler, and each language that supports assertions has its own syntax:

Java: assert( answer == 42 );
C++: assert( answer == 42 );
Python: assert answer == 42 'The answer to Life the Universe and Everything is NOT 42!'

Using Assertions

By default in Java, assertion checking is disabled. You can enable assertion checking at run time by simply adding the option -enableassertions or -ea. You can also enable/disable system class assertions by using either the -esa or -dsa options respectively.

We will take a look at assertions first with a quick example in C++. By default asserting checking should be enabled with g++ (make sure that you do NOT #define NDEBUG and that -DNDEBUG is not passed to g++ when compiling the following program:

#include <iostream>
#include <cassert>

void printNumber(int number)
{
    assert(number > 4); // all numbers < 5 do not deserve to be printed!
    std::cout << number << " is a worthy number to print!" << std::endl;
}

int main(int c, char* argv[])
{
    printNumber(7);
    printNumber(3);
    return 0;
}

Execute the following command:

helium$ g++ ./assertion.cpp && ./a.out

And you should get the following output:

7 is a worthy number to print!
Assertion failed: (number > 4), function printNumber, file ./assertion.cpp, line 7.
Abort trap

 

Why should we use Assertions

Assertions can be an easy and effective way of documenting the implicit assumptions that a programmer makes in the code about the state of the program/application/system at a given point in execution. For example, take the following code snippet:

...
foo = bar.getFoo();
assert( foo > 4 ); // because a minimum of 5 is a sane value
...

In this example, the programmer will also add conditional code (if/else-if/else) to handle the “weird” condition should it arise. So why should we add an assertion check? Assertions allow programmers to specify “crashpoints” or very clear points in the code that will crash “artificially” (due to the assertion failing) and indicate sooner rather than later that the program/application/system is in a state that it should not be. This, in turn, speeds up debugging and error tracing during the integration and testing phases of development.

 

When should we use Assertions

Some people think that one should check conditions all the time, so debugging/testing with assertions active and releasing without them is a rather silly idea. People that think like this generally point out that if you think it’s important enough to test now, your code should not only always be checking that condition, but it should also handle the condition gracefully ( i.e. release resources, close files, etc). And this is absolutely correct. I would go further and suggest that assertions are a complementary practice to this that allows a programmer to document and provide explicit assumptions about the program/application/system state (that essentially cost nothing as they will be removed in production code). This in turn will speed up the identification of bad assumptions in the code rather than tracing back an error when it emerges further up the execution stack (either via an explicit mechanism such as an exception or via a “weird” bug).

Generally, the rule I follow is: if my code can/should recover from an unexpected state, use an if statement to test/handle the condition. If my code cannot recover from the unexpected state or is not expected to recover from it, I test the state/assumption with an assert. This makes debugging easier as the assertion will help localize the problem quickly within the code. Even when assertions are used, testing without them must always be done: Test as you Fly, Fly as you Test.

For a more detailed treatise on using assertions (within Java specifically, but most of the concepts are fairly generic): http://java.sun.com/j2se/1.4.2/docs/guide/lang/assert.html

 

Concurrency and Assertions

When we delve into the world of concurrent code, the use of assertions takes on an entirely new importance. In an environment where program/application/system state can change unexpectedly at any time, assertions provide a simple and effective way to identify where a programmer’s assumptions of the state is incorrect. This technique can be especially useful when complex interactions between code components are occurring in different places at the same time.

 

Pitfalls and Booby Traps

When testing a condition, it is very important that the test itself does not modify the state. An example of this would be calling a method on object A that modifies the state of object A. This will mean that the assert is a required part of the code logic and will break the code when removed. Another important consideration is the time to execute the assertion. If a test takes a long amount of time (where test execution time will be application specific) it will affect how the code runs, especially in a concurrent environment.

 

Summary

In summary, assertions are an important complementary tool for programmers that helps locate bad assumptions in their code more quickly during development and testing. They also help document these assumptions in an explicit way when they might not normally have been. Assertion tests must never alter program/application/system state. When using assertions, programmers must always remember to test with assertions disabled ( “Test as you Fly, Fly as you Test” ).