Masters of Doom

28.10.2013 19:16

Recently I finished reading Masters of Doom by David Kushner. It came on my radar because of a post on Hacker News that said this was a book that inspired Alexis Ohanian and Steve Huffman to make Reddit.

The story follows John Carmack and John Romero from childhood, through the founding of id software, later successes and failures of games they developed and concludes with the founding of Armadillo Aerospace. Compared to other books I read about ups and downs of US start-up companies (like The Facebook Effect or Dreaming in Code) it presents a more personal view of people in it. It often goes into first-person details of how someone felt about other people or the way some project was going. That makes for an interesting description of dynamics in a team and how they led their lives. It also makes me wonder how much of these details can genuinely be learned through interviews and how much has been added later to make for a more interesting read.

While this part of the book is quite well written in my opinion, the author fails horribly at describing technical details or any of Carmack's many breakthroughs in computer graphics. Even though I knew beforehand many details of id game engines I was constantly baffled by their descriptions in the book and went several times to Wikipedia to check my memory (by the way, the best description of Carmack's smooth-scrolling trick in Commander Keen I could find is on this Wikipedia talk page). Even more puzzling is the wrong explanation of gamer slang telefrag. Thankfully only a small part of the content is dedicated to technical topics, but it makes me wonder how such mistakes could have happened when the author describes himself in the epilogue as a hacker that was himself involved in the gaming culture.

In the end I still enjoyed reading the book. It included many events I remember reading about in magazines years back and presented them from the other point of view. The story also gives a quite good time line of events and gives a genuine impression of the amazing speed at which advances in technology happened at that time.

According to the book, Doom was half-jokingly made to be the number one cause of decreased productivity in businesses around the world. If designers of Reddit took that as inspiration for their website you could certainly say their success was along the same lines.

Posted by Tomaž | Categories: Life | Comments »

OpenSC on Wheezy

27.10.2013 11:43

One of the things that broke for me on upgrade to Debian Wheezy was smartcard support in Iceweasel. I regularly use a Schlumberger Cryptoflex USB key to authenticate on websites using client-side SSL certificates, so fixing this was kind of important to me.

OpenSC documentation is a mess and from terse error messages it was hard to make heads or tails of what was actually broken. So here's what I had to do make authentication work again in the browser.

First, fixing the most obvious thing: with the introduction of multiarch the PKCS #11 module has moved from /usr/lib/opensc-pkcs11.so to /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so. This means you have to correct the path in Iceweasel. Go to Preferences, Advanced, Certificates, Security Devices and select the OpenSC module there. Click Unload to remove the module and then Load to load the module from the new path.

Also, you might have noticed that mozilla-opensc package was removed in Wheezy. I'm not sure if it was even required in the previous release, but it's definitely not needed now.

Second, the version of OpenSC shipped with Wheezy only supports accessing the smartcard readers through the pcscd daemon. You have to install the pcscd package or OpenSC will not detect any readers.

$ opensc-tool -l
# Detected readers (pcsc)
Nr.  Card  Features  Name
0    Yes             Axalto/Schlumberger/Gemalo egate token 00 00

Now for the tricky part. With the changes above, I still got a very helpful error message whenever I tried connecting to a secure website: A PKCS #11 module returned CKR_GENERAL_ERROR, indicating that an unrecoverable error has occurred. (Error code: sec_error_pkcs11_general_error).

sec_error_pkcs11_general_error message in Iceweasel

Running a test with the pkcs11-tool showed that there was something wrong with the signing operation:

$ OPENSC_DEBUG=9 pkcs11-tool --module /usr/lib/x86_64-linux-gnu/opensc-pkcs11.so -t -l
Using slot 1 with a present token (0x1)
Logging in to "OpenSC Card (tomaz)".
Please enter User PIN: 
C_SeedRandom() and C_GenerateRandom():
  seeding (C_SeedRandom) not supported
  seems to be OK
Digests:
  all 4 digest functions seem to work
  MD5: OK
  SHA-1: OK
  RIPEMD160: OK
Signatures (currently only RSA signatures)
  testing key 0 (Private Key) 
... lots of debug output skipped ...
iso7816.c:103:iso7816_check_sw: Command incompatible with file structure
card-flex.c:1067:cryptoflex_compute_signature: Card returned error: -1200 (Card command failed)
sec.c:56:sc_compute_signature: returning with: -1200 (Card command failed)
card.c:330:sc_unlock: called
pkcs15-sec.c:380:sc_pkcs15_compute_signature: sc_compute_signature() failed: -1200 (Card command failed)
card.c:330:sc_unlock: called
reader-pcsc.c:548:pcsc_unlock: called
framework-pkcs15.c:2721:pkcs15_prkey_sign: Sign complete. Result -1200.
misc.c:59:sc_to_cryptoki_error_common: libopensc return value: -1200 (Card command failed)
pkcs11-object.c:691:C_SignFinal: C_SignFinal() = CKR_GENERAL_ERROR
error: PKCS11 function C_SignFinal failed: rv = CKR_GENERAL_ERROR (0x5)

Aborting.

This seems to be a bug in the 0.12.2-3 version of the opensc package. Luckily, this is fixed in 0.13.0-3 that is currently in Unstable. Upgrading is pretty trivial and doesn't depend on upgrading a lot of other packages on the system.

With this upgrade in place, everything works again for me as it did in Squeeze.

Update: You might want to also upgrade libpcsclite1 and pcscd to versions from Unstable (1.8.10-1). With versions from Wheezy I'm still occasionally getting errors.

Posted by Tomaž | Categories: Code | Comments »

Interleaved ADC mode on STM32F1

11.10.2013 15:49

Somewhat connected to my previous post, here's another feature of VESNA's microcontroller I discovered recently.

STM32F103's datasheet says that the chip includes three analog-to-digital converters. So far I never used more than one and while I never really thought about it, I kind of assumed that they are not really three independent hardware components.

As it turns out they really can work independently and even better, you can use two of them in tandem to achieve twice the sample rate of a single one. The documentation calls this fast interleaved dual ADC mode. Interestingly, this is something STMicroelectronics advertises on the first page of datasheets for their signal-processing Cortex-M4 series. But for Cortex-M3 line you have to dig through the reference manual to find a mention of this mode and even then there's not much specific information on how to use it.

In interleaved mode two converters work simultaneously with half of the conversion period out of phase. The means that first converter provides even samples while the second provides odd samples, as this figure from the manual shows:

Fast interleaved ADC mode illustration.

Regarding practicalities that are left out of the manual: both ADC1 and ADC2 must be configured for continuous conversion mode. They have to be set for external triggering (but you can use the SWSTART option to simulate it from software through ADC_CR2 register). This means that you can't trigger the conversion in the usual way by writing 1 to the ADON bit while the converter is already powered up.

The DMA transfer reads only from the ADC1 DR data register. You have to set 32-bit word length which will actually read out both ADC1 and ADC2 12-bit samples from the same register in kind of hackish way. Because of this the odd and even samples will have switched places in the DMA buffer. This is not really convenient if you want to process the data further on the microcontroller where you usually need samples ordered by time.

How well does it work? I was kind of skeptical, especially regarding trigger accuracy and calibration agreement between both converters. I did some preliminary measurements at 2 Msamples/s though and so far it looks very promising. Offset difference between converters appears to be around 0.6 digits. Trigger error is on the order of 10-3 times conversion rate which is excellent.

I've created a repository on GitHub that contains the code I used to test this (needs libopencm3). The repository also includes an iPython notebook if anyone wants to repeat the measurements or double-check my calculations.

Posted by Tomaž | Categories: Analog | Comments »

Undersampling with a microcontroller ADC

08.10.2013 16:05

Analog-to-digital converters on microcontrollers aren't usually meant for high-frequency signals. The most common use case is a temperature sensor or something slow moving like that where you don't need a really high sample rate. At best you might want to sample audio signals. VESNA for instance has an ARM STM32F103 microcontroller that does at most 1 Msample/s.

The digital bandwidth of this ADC is limited to 500 kHz, half of its sampling frequency as per Shannon sampling theorem. However the theorem also says that you can undersample a band limited signal that is centered around an arbitrarily high frequency. In practice of course, you are limited with the analog bandwidth of the signal path in front of the analog-to-digital conversion.

The analog bandwidth isn't specified anywhere in the datasheets (at least nowhere I could find it). So I attempted to measure it using a signal generator and a simple bias circuit in front of an analog input pin of the microcontroller.

Circuit used to measure ADC analog bandwidth.

VESNA core board with a coaxial cable attachment.

The ADC was set to the maximum settings possible.

f_{adc} = 14 \mathrm{MHz}
f_{s} = 1 \mathrm{MHz}
t_{s} = 1.5 \mathrm{cycles} = 0.11 \mathrm{\mu s}

Below is an amplitude Bode plot of the system I measured:

Gain versus frequency plot for ADC on STM32F103

This shows that the -3 dB frequency is surprisingly high, at around 42 MHz. This is not something I expected - I thought the roll-off would start not much beyond the Nyquist frequency. Also, the specified sampling time of 0.11 μs gave me the impression that the analog bandwidth would be below 10 MHz. Actually, above 10 MHz the attenuation I saw might as well come from stray capacitances in the circuit and not from the converter itself.

Also interesting is the slight dip in amplitude between fs and 2fs. I'm not sure what is happening there. It is reproducible over two different microcontrollers.

If these measurements are correct this makes for interesting possibilities of using the ADC on VESNA for sampling band-limited high-frequency signals.

Posted by Tomaž | Categories: Analog | Comments »

time_t on embedded systems

03.10.2013 18:44

Recently I got pointed to this slide deck from Theo de Raadt on moving to a 64-bit type for representing time in OpenBSD. It addresses ways of overcoming the limitation of the way Unix-based systems represent time. Among other things it also mentions the proliferation of the POSIX standard into the domain of embedded systems and the problematic combination of the timer overflow in the not-so-far future and the particularly long life cycles of such systems.

One interesting observation he makes is that applications often do arithmetic on the clock (for instance when calculating timeouts) and that might produce bugs even before the clock itself overflows. So things will probably start breaking well before the January 2038 deadline.

Regarding embedded systems I would like to add that this problem most likely affects a much larger set than those running POSIX-like operating systems.

One reason is that most systems that are programmed in C use the standard C library. While the C standard itself doesn't dictate how time is stored, all of the most common library implementations come from the POSIX world and bring in its definition of time_t as a signed 32-bit counter for the number of seconds from 1 January 1970. For instance, software on VESNA uses newlib. Its clock used to count seconds from 1 January 2012, but that was later changed to the standard POSIX time for the sake of simplicity of using built-in time-handling functions in the C library.

The other reason is that embedded systems often rely on hardware counters to keep the clock. ARM microcontrollers from STM for example have a 32-bit counter in the RTC peripheral. As far as I know it is a true 32-bit counter, meaning it has one more usable digit than the signed 32-bit time_t in POSIX (which adds another 68 years to its lifetime). However, there is no simple way around this limitation in software. You could start using a software counter instead, but that can potentially change response times to other interrupts that might be critical on a microcontroller system. I don't want to even imagine retrofitting that to a system that hasn't been touched in years and might control something big and expensive.

Anyway, for the moment I will go with the prevalent belief that code running on VESNA won't be around for that long and plan to book a holiday in the southern hemisphere for 2038.

Posted by Tomaž | Categories: Code | Comments »