Programming tiny delays on MCU

Recently I got interested in electronics and bought myself a STM32VL-Discovery board. It’s really cheap (got for about 10€ from Farnell) and compared to Arduino packs a lot more processing power and features.

Prior to that I had zero experience in electronics and embedded system programming.

After I got pass the obligatory led-blinking projects, I thought I am ready to take on something more complex and bought a 2-line LCD module.

Looking at the tutorials (mostly Arduino related) and specs I came to realize that I need to make delays in microsecond or even nanosecond scale. I had previously used millisecond-accurate delays in my led-blinking projects and it was rather simple – I had to just configure the sys-tick timer to interrupt every millisecond and decrement a counter in interrupt handler.

The trick to make small delays lies in the fact that every instruction that the MCU processes takes some time. It depends on the speed of the MCU how much exactly. For instance – my STM32VL-Discovery runs at 24Mhz. This means that it executes 24000000 instructions per second.

In case you are too lazy to look it up from the Wikipedia here’s what a nanosecond is:

  • 1 second (s) is 1000 milliseconds
  • 1 millisecond (ms) is 1000 microseconds
  • 1 microsecond (µs) is 1000 nanoseconds
  • 1 nanosecond (ns) is 1000 picosends

This means that 1 second consists of 109 nanoseconds. So to calculate how many nanoseconds it takes for a 24Mhz MCU to execute one instruction:
109/24000000=41,66666666666666666666…

Meaning it takes roughly 42 nanoseconds to execute a single instruction. Meaning this is the smallest delay this particular MCU is able to make.

Now to actually MAKE that 42-nanosecond delay in a program you need something called NOP-instruction. Depending on the platform/compiler/libraries you are using, this can be written (in C) as:

__nop();

or

__ASM volatile (“nop”);

or

__no_operation();

I personally am using CMSIS library and it takes care of choosing the right syntax when I use a macro:

NOP();

Anyway the rest is easy.
Just keep in mind not to wrap your NOP’s to a function because the function call (and return) consume also MCU cycles and the overhead can be tricky to calculate because of how the compiler optimizes the final result.
On the subject of compiler optimizations there is a small possibility that your compiler might optimize away those NOP’s because from the compilers point of view they do nothing.  So you MIGHT need to lower your compiler optimization level to keep your NOP’s in place.

Calling FMS admin API methods with PHP

There is a rather simple way of getting status info from a running Flash Media Server. This can be used to draw graphs with Cacti for instance.

First make sure the admin API over HTTP is enabled in /opt/adobe/fms/conf/fms.ini

USERS.HTTPCOMMAND_ALLOW = true

Then enable the methods you need or use a keyword “All” in /opt/adobe/fms/conf/Users.xml

<AdminServer>
    <HTTPCommands>
        ...
        <Allow>All</Allow>
        <Deny></Deny>
        <Order>Deny,Allow</Order>
    </HTTPCommands>
</AdminServer>

Here is a working example of how to get the number of active connections with PHP (you need php-XML module to run this).

<?php
$adminUser='admin';
$adminPassw='SuperSecretPassword';

$xml=new DomDocument();
$url="http://localhost:1111/admin/getServerStats?auser=$adminUser&apswd=$adminPassw";
$xml->load($url);
$connected=getTagContents('connected',$xml);

printf("There are currently %d active connections on the server\n",$connected);

function getTagContents($tagName,$dom) {
    $node=$dom->getElementsByTagName($tagName)->item(0);
    return $node->nodeValue;
}
?>

In the example above I just extract a single value out of a returned XML that looks something like this:

<result>
    <level>status</level>
    <code>NetConnection.Call.Success</code>
    <timestamp>Thu 28 Apr 2011 11:59:24 AM EEST</timestamp>
    <data>
        <launchTime>Tue 26 Apr 2011 07:29:32 PM EEST</launchTime>
        <uptime>145792</uptime>
        <cpus>2</cpus>
        <cpu_Usage>0</cpu_Usage>
        <num_cores>1</num_cores>
        <memory_Usage>4</memory_Usage>
        <physical_Mem>98799616</physical_Mem>
        <io>
            <msg_in>1008000</msg_in>
            <msg_out>190805</msg_out>
            <msg_dropped>0</msg_dropped>
            <bytes_in>423676178</bytes_in>
            <bytes_out>3904886327</bytes_out>
            <reads>434063</reads>
            <writes>168869</writes>
            <bw_in>0</bw_in>
            <bw_out>0</bw_out>
            <total_connects>72</total_connects>
            <total_disconnects>69</total_disconnects>
            <connected>3</connected>
            <rtmp_connects>4</rtmp_connects>
            <rtmfp_connects>0</rtmfp_connects>
            <normal_connects>0</normal_connects>
            <virtual_connects>1</virtual_connects>
            <group_connects>3</group_connects>
            <service_connects>0</service_connects>
            <service_requests>0</service_requests>
            <admin_connects>0</admin_connects>
            <debug_connects>0</debug_connects>
            <total_threads>168</total_threads>
            <working_threads>2</working_threads>
            <swf_verification_attempts>0</swf_verification_attempts>
            <swf_verification_exceptions>0</swf_verification_exceptions>
            <swf_verification_failures>0</swf_verification_failures>
            <swf_verification_unsupported_rejects>0</swf_verification_unsupported_rejects>
            <swf_verification_matches>0</swf_verification_matches>
            <swf_verification_remote_misses>0</swf_verification_remote_misses>
            <server_bytes_in>0</server_bytes_in>
            <server_bytes_out>0</server_bytes_out>
            <rtmfp_lookups>0</rtmfp_lookups>
            <rtmfp_remote_lookups>0</rtmfp_remote_lookups>
            <rtmfp_remote_lookup_requests>0</rtmfp_remote_lookup_requests>
            <rtmfp_redirects>0</rtmfp_redirects>
            <rtmfp_remote_redirects>0</rtmfp_remote_redirects>
            <rtmfp_remote_redirect_requests>0</rtmfp_remote_redirect_requests>
            <rtmfp_forwards>0</rtmfp_forwards>
            <rtmfp_remote_forwards>0</rtmfp_remote_forwards>
            <rtmfp_remote_forward_requests>0</rtmfp_remote_forward_requests>
        </io>
    </data>
</result>

If you decide to pull status info from remote servers then keep in mind that it is not the best idea to make the admin API port world-accessible. Also be aware that the password is passed in plain text on the URL!

A better alternative might be to limit admin API calls to localhost and pass the needed values to your monitoring server over SNMP.

Compiling Strobe Media Playback using command line

The developers of Strobe Media Playback are rather vague about how to compile the source code. This article tries to list all the steps needed to get a working SWF on any modern OS.

Here is a list of things you will need to make the magic happen:

  • Java JDK 6
  • Apache Ant
  • Adobe Flex SDK 4
  • FlexUnit 4
  • Ant Contrib

First make sure you have Java (JDK 6) installed on your OS.
Next get Apache Ant from http://ant.apache.org/bindownload.cgi (I used v1.8.2 for this article) or if you are running some OS with central software repositories (Linux, FreeBSD, etc), then install using the tools provided with it (yum, pkg_add, apt-get, etc).
When setting up Apache Ant on a Windows machine make sure you add the bin directory to PATH variable of the system.

Then go and download the Strobe Media Playback source from http://sourceforge.net/projects/smp.adobe/files/ (for this article I used v1.5.1). Uncompress the downloaded file and at the root of the uncompressed source directory create the following subdirectories:

./buildtools/
./buildtools/libs/
./buildtools/sdks/
./buildtools/sdks/4.1.0/

Now lets populate the ./buildtools folder with some… umm build tools obviously… duh…

Go and download Flex 4 SDK from http://opensource.adobe.com/wiki/display/flexsdk/Download+Flex+4 (for this article I used v4.1.0.16076). Uncompress the files into the ./buildtools/sdks/4.1.0/ subdirectory.

Now we’ll need something called ANT Contrib. Version 1.0b3 to be precise. Uncompress the archive and move the ant-contrib-1.0b3.jar file to ./buildtools/libs/

Finally something called FlexUnit… from the download page choose the stable release FlexUnit (4.0 SDK). Uncompress the the archive and move flexUnitTasks-4.0.0.jar to ./buildtools/libs/

If using Windows, then now you can execute the “src\build.bat compile.strobe”.

For unix-like OS-es you need to create a shell script ./src/compile.strobe, like:

#!/bin/bash
BUILD_TOOLS=”..\buildtools”
/usr/bin/ant \
-lib ${BUILD_TOOLS}\sdks\4.1.0\lib \
-lib ${BUILD_TOOLS}\sdks\4.1.0\ant\lib \
-lib ${BUILD_TOOLS}\libs \
compile.strobe

If you don’t have bash, then just tweak the script a bit to match the conventions of your favourite shell.

If you look inside ./src/build.xml, you’ll notice that there are many other build targets besides “compile.strobe”. Haven’t yet worked out how to make them all work… will post an update when I do.

Debug build for Flash Player 10.1