STM32 performance test or how fast you can serve input signal

Finally, i decided to try stm32, before i wrote firmwares only for AVR mega family (from now, when i say AVR MCU, i mean AVR mega family MCU), and was scared by tonns of code that you need for simply led blinking on STM32 MCU.
Now i can say, that programming of STM32 not so hard as it looks first time. After i understand logical structure of MCU core and how it work, it become easy.
OK, it was prelude.

Every time when i see comparison between AVR and STM32/STM8 MCU’s i faced with next arguments:
STM MCU’s have lower price, when they have more RAM, FLASH, GPIO pins and work frequency. Looks sweet. Today i want to tell the story about work frequency.

More than the operating frequency of the MCU, the faster it can handle events. STM32 MCU’s have maximum work frequency more than 20MHz (72MHz for STM32F103 that i have), when AVR MCU’s have only 20MHz. Is 72MHz a lot of or not? Two week ago i wanted to know, is it enough ~200MHz of STM32F4 to handle 10MSPS ADC on not? Two weeks ago i think ‘may be’. Now i think ‘not enought’.

Last Friday evening i blow the dust from oscilloscope and made little research.
My basic code poll pin, by software, configured for input and set same signal on output pin, the code is there:

while(1) {
         if( GPIOB->IDR & GPIO_IDR_IDR10 ) {
                        GPIOB->BSRR = GPIO_BSRR_BS8;
         } else {
                        GPIOB->BSRR = GPIO_BSRR_BR8;
         }
}

How many time MCU need to set same level on GPIO pin as on input pin?  May be 140nS (near 10 clocks on 72MHz) will enought?
stm32_delay_O0

Nope. 480ns. It near 34 cycles. The period of 480ns has frequency of 2MHz, may be i forgot to change speed of gpio port?

stm32_debug_toggle_pin_50MHz

Nope. May be i forgot to switch on external quartz or forgot to configure PLL?

stm32_debug_pll

Nope. Hmm, may be optimization can help? Let’s try to switch on -O3:

stm32_delay_O3

Much better, 170 ns. MCU need near 12 cycles, to detect signal and change state of one GPIO speed. Do not forget, MCU just pooling one pin and change state of another, it do not do valuable work.Okay, but what the maximum speed you can get, if you will just change the state of GPIO pin?
Is it possible to hit theoretical maximum of 50MHz (max clock speed of GPIO ports on STM32F103):

stm32_toggle_pin

Just 6MHz. Let me switch on optimization for you:
stm32_toggle_pin_serial_0
Looks like there only 36MHz, let’s look on the code:

stm32_debug_toggle_pin_O3
I can’t see why they can’t reach 50MHz. If you look on disassembler view, you can see, that MCU just store different values on constant address.
In fairness i must to say, if you set cursors on oscilloscope in different manner, you can achieve 50MHz:

stm32_toggle_pin_serial_1
It is hard to say what way of measurement is wrong, i think the second, because first time it is easy to see time of 2 periods. Without a doubt, the second way STM advertising department would have liked more.
BONUS:
A picture where is while cycle occurs:
stm32_toggle_pin_serial_burst

Pulseview compilation

Half year ago i wanted to make device that can be used to clone ski pass. I thought that ski passes use RFID 125kHz. First i bought itead module RDM6300 but it turned out that it can only read tags, so i bought  EM4095 chip. At this time i also noticed, that most ski passes use MIFARE tags that operated at 13MHz.
Anyway i want to complete this project and build device that can read and write 125kHz tags (really there is to many different tags that operate on 125kHz and uses different protocols, so i want to start with EM4100 tags).That tags use manchester encoding to transfer data, also tags can use different bitrate. It is easy task to encode data into manchester, but it’s really pain in the ass if you want to decode them and does not know bitrate.
I have clone of saleae logic analizer so i decided to practice with decode manchester with libsigrokdecode. Sigrok have ‘official’ gui for libsigrok and libsigrokdecode called Pulseview.
I found that debian wheezy have old libsigrok and do not have pulseview at all, after that i decided to build sigrok and pulseview from scratch. It is really not easy quest, because additionally to libsigrok, libsigrokdecode you need to compile old libusb and libvisa.
Finally when i compiled all that stuff, i faced with errors when i tried to compile pulseview with decoders support.

First, libsigrokdecode need Python >= 3.0, Python.h placed in python3.2/Python.h, so you need to change it into libsigrokdecode.h:

./include/libsigrokdecode/libsigrokdecode.h:#include <python3.2/Python.h> /* First, so we avoid a _POSIX_C_SOURCE warning. */

Second, if you will got that error:

[ 40%] Building CXX object CMakeFiles/pulseview.dir/pv/view/decodetrace.cpp.o
/var/tmp/sigrok/pulseview/pv/view/decodetrace.cpp: In member function ‘virtual void pv::view::DecodeTrace::paint_mid(QPainter&, int, int)’:
/var/tmp/sigrok/pulseview/pv/view/decodetrace.cpp:203:3: error: ‘hash_combine’ is not a member of ‘boost’
/var/tmp/sigrok/pulseview/pv/view/decodetrace.cpp:204:3: error: ‘hash_combine’ is not a member of ‘boost’
/var/tmp/sigrok/pulseview/pv/view/decodetrace.cpp:205:3: error: ‘hash_combine’ is not a member of ‘boost’
make[2]: *** [CMakeFiles/pulseview.dir/pv/view/decodetrace.cpp.o] Error 1

Then you need to add “#include <boost/functional/hash.hpp>” into /var/tmp/sigrok/pulseview/pv/view/decodetrace.cpp

Third,  if you got that:

CMakeFiles/pulseview.dir/pv/data/decoderstack.cpp.o: In function `pv::data::DecoderStack::decode_proc(boost::shared_ptr<pv::data::Logic>)':
/var/tmp/sigrok/pulseview/pv/data/decoderstack.cpp:267: undefined reference to `srd_session_new'
/var/tmp/sigrok/pulseview/pv/data/decoderstack.cpp:283: undefined reference to `srd_inst_stack'

You need to add -lsigrokdecode into CMakeFiles/pulseview.dir/link.txt

I spent too many time to compile that stuff, so i decided to place here archive with complete libsigrok, libsigrokdecode, libvisa, libusb, sigrok and pulseview. I compiled it with preffix /opt/sigrok, so if you want to use it, place that stuff into /opt and run like that:

LD_LIBRARY_PATH=/opt/sigrok/lib /opt/sigrok/bin/pulseview

Enjoy: sigrok.tar
md5: 7bbb1d434959848c741230fe90a590c5 /tmp/sigrok.tar.gz
PS
Also you must install  libboost-thread.

Arduino keyManager

Few months ago i started to developing iron for waxing my snowboard. Last season i bought regular iron and used it, but it can set temperature only in wide range, did not have overheat protection and can melt the base of the board. In university i learned of 8bit avr mcu, but all firmwares that we wrote, we wrote on ASM. Now it is my hobby and i decided to try C/C++ programming, early at school i wrote on C, but forget to many about C language, so now, after many years without practice, i decided to try arduino.
When i wrote arduino sketches i did not found library to manage keys. I wanted event based library that can produce events when key pressed, when key long pressed and when key released, also it must have program debounce.
Early to manage keys i just wrote tonnes of code right in sketches, but when sketches grow up, they started to looks like a crap, so i develop my own library.
They far away from to be excellent ( i am not very familiar with C, not to mention C + +), but they work.
Now code of the library have mixed russian and english comments ( hope i will change it in future ).
I tried to write library fast as possible and using minimal resources, because of that (and because i do not know C++ well) there to many hard coded defines for delay values in keyManager.h (debounce time, time to long press detection and time to regenerate long press event). I feel it is possible to make library better with C++ templates, but i did not found time to learn it well.
Last words, before i show example, library designed to be used with pull up keys, ie when key pressed, digitalRead() must return LOW.
I turned arduino blink example to work with key manager. There are two keys, one switched off the led, another on switch it on.

// Include library header
 #include <keyManager.h>
 
#define led 13
#define off_pin 10
#define on_pin 11
 
// Create keyManager objects, when you create key object, they
// initialize key pin as input 
keyManager on_key( on_pin, true );
keyManager off_key( off_pin, true );
 
void setup() {
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
}
 
// Led state
uint8_t led_state = 0;
 
void loop() {
// This is main part, process() function must run at least once in every 255 micro seconds
// process() function is heart of the library based on FSM, they process
// key state changes and generate events
  on_key.process();
  off_key.process();
 
// Light led if on key pressed
  if( on_key.isPressed() ) {
    digitalWrite(led, HIGH);
    led_state = HIGH;
  }
// Swich off if right key pressed
  if( off_key.isPressed() ) {
    digitalWrite(led, LOW);    
    led_state = LOW;
  }
 
// If any key pressed long, led will change the state
  if( on_key.isLongPressed() || off_key.isLongPressed()  ) {
    if( led_state == LOW ) {
      led_state = HIGH;
    } else {
      led_state = LOW;
    }
    digitalWrite(led, led_state);
  }
}

Second argument of:

keyManager on_key( on_pin, true );

Select how keys will be driven. When argument is ‘true’ keys will managed in ‘event mode’ it means, that isPressed() will return true only once until you did no release key and did not press it again. Same for isReleased().
isLongPressed() will return ‘true’ first time, when key will be pressed longer than defined in keyManager.h (by default 1.5 sec) and after every repeat delay if key will not released (by default 0.1 sec).
Event generated every time when key changed their state, there is function isEvent() to check that. isEvent() return true until event will not received by isPressed(), isLongPressed() or isReleased(). In another words that functions will clear event flag after picked up their event.
keyManager can work in another mode, when second argument is ‘false’, functions isPressed(), isLongPressed() and isReleased() will not clear event flag, they return true every time when key in their state. Event flag will generated as before, but can be cleared only with clearEvent() function.
Now library use 4 bytes of ram to manage single button. In future i want reduce ram that used by timers, add more examples and simplify delays configuration.

There is link to github: https://github.com/IvanBayan/arduino-keyManager

How to use angled brackets in WP-Syntax

I often use WP-Syntax plugin for syntax highlighting. When i used angled brackets or ‘&’ symbol or something like that i recieved next garbage:

$ echo fail 2&gt;&amp;1 &gt;/dev/null

It happened because wp-syntax tried to escape special symbols, but <pre> tag says wordpress to show symbols as it passed into that tag. Early, before publishing i switched from visual into text mode and changed all that garbage into what i want. But solution is to add  escaped option into <pre> tag, <pre lang=”bash” escaped=”true”>, now same block will look like i expected:

$ echo congrat 2>&1 >/dev/null

Enjoy!

Zram

Few months ago, i tried very cool feature called ‘zram’. It is linux kernel module that allow to create compressed block devices into memory, it can be used for creating compressed fs in ram  (/tmp for example) or for swap.
May be you think, that in context of swap, it is dumb to keeping  memory pages in memory when OS need that memory. =) But compress and store pages in memory is faster than write it onto disk, in most cases memory pages can be heavily compressed, that will help OS to free RAM, if you have SSD it will save life of your disk, also you can continue using swap on disk. If you want to keep you swap partition on-line, you must give higher priority for swap in zram, when zram will full, OS will started to using swap on disk.

I used that init.d script for debian, but i changed it to use not  a whole RAM for zram devices, but half of all memory (in worst case, when pages can not be compressed, zram will use only half of my memory). If you want to do same modification, just change echo $((mem_total / num_cpus )) to echo $((mem_total / num_cpus / 2)) in that script.
Without modifications this script will slice you memory by number of CPU core in your system, create swaps on that slices and attach it to your system with priority 100 (usualy swap partitions have priority -1).
I made simple test of compression ratio for zram:
Detached one of my swaps:

$ sudo swapoff /dev/zram3

Created core file of iceweasel process and wrote it into zram:

$ pgrep -lf icewea
3375 sh -c /usr/bin/iceweasel
3376 /usr/bin/iceweasel
$ gcore 3376
[Thread debugging using libthread_db enabled]
[New Thread 0x7f7c0b9fd700 (LWP 8455)]
...blablabla...
0x00007f7c62a57c13 in poll () from /lib/libc.so.6
Saved corefile core.3376
$ sudo dd if=./core.3376 of=/dev/zram3
dd: writing to `/dev/zram3': No space left on device
2027297+0 records in
2027296+0 records out
1037975552 bytes (1,0 GB) copied, 6,79003 s, 153 MB/s

Core file does not fit completely into zram device, but it is dose not mater, let’s look at compression ratio:

$ cd /sys/block
$ echo `cat ./zram3/orig_data_size`/`cat ./zram3/compr_data_size`|bc
2.68475926964795164955

So, in most cases zram has compress ratio more than 2.5.
Huh, i think it is pretty cool.

Zoneminder jitter

After several years of torture with easycap i realize that it is time to change capture device. I found that other usb capture device that supported by linux cost to high, also i can not use PCI or full height PCI-e devices because of mATX form factor of my server.  Suddenly i found ImpactVCB 1381, it is what i wanted to found, it is supported by linux, PCI-e and has half height bracket.
Before i did not try it card i did not think, that it is can be so much difference in image quality between two cards. Unfortunately i do not have sample with  easycap, but you can trust me, difference is enough to throw easycap.
As always there is a fly in the ointment, zoneminder or haupage driver has bug and captured image sometimes jittering, it is looks like that:
Zoneminder jitter

I preferred to think, that it is bug in zoneminder, because i did not seen same issue when i captured video with mencoder.
Will hope it will be fixed in future releases.

You IP

Since the idiots in the Russian government passed a law similar to ‘SOPA’ i started to modify routing scheme at my home. Many times i used internet.ya.ru to determine my current outgoing IP address, but i wanted to use more minimalistic tool for this purpose. So i created my own tool with blackjack and hookers, there it is: https://ivanbayan.com/uip.php i using different routes for TLS and http traffic, so it is also available there  https://ivanbayan.com/uip.php.
This script produce simple image with you outgoing ip:

You ip

Addresses of TOR relays

Some time ago i wrote about how to block access from TOR network.
Few days ago i observed, that file with addresses of TOR relays (http://exitlist.torproject.org/exit-addresses) not available anymore, i did not found similar list, so i wrote my own script with blackjack and hookers. Output of this script not compatible with format of “exit-addresses”, and represents a simple list of ipv4 addresses of TOR relays.

Enjoy: https://ivanbayan.com/tor_exitnodes_v4.txt

How to fix ‘Timezone database is corrupt – this should *never* happen!’

Today i upgraded to wheezy. When i entered my blog i observed that it does not work anymore. I looked into logs and found next errors:

[26-Jun-2013 12:59:41 UTC] PHP Fatal error:  date(): Timezone database is corrupt - 
this should *never* happen! in ...
[26-Jun-2013 12:59:49 UTC] PHP Fatal error:  strtotime(): Timezone database is 
corrupt - this should *never* happen! in /html/wp-includes/functions.php on line 33...

After a little investigation I discovered that happens when you use php in chroot enviroment (i using php5-fpm with chroot, so it is my case). I tried to copy /usr/share/zoneinfo in chroot environment with parent dir structure and correct permissions, but nothing change. Somewhere i read that it problem can happen in debian, because maintainers of php packages, patch source files, the solution – is to install tzdatadb:

apt-get install php-pear php5-dev
pecl install timezonedb
echo 'extension=timezonedb.so'> /etc/php5/mods-available/timezonedb.ini
ln -sf /etc/php5/mods-available/timezonedb.ini /etc/php5/conf.d/30-timezonedb.ini
service php5-fpm restart

After that all work like a charm.

PS

strings /usr/sbin/php5-fpm|grep Quake| head -n8
Quake I save: ddm4 East side invertationa
Quake I save: d7 The incinerator plant
Quake I save: d12 Takahiro laboratories
Quake I save: e1m1 The slipgate complex
Quake I save: e1m2 Castle of the damned
Quake I save: e2m6 The dismal oubliette
Quake I save: e3m4 Satan's dark delight
Quake I save: e4m2 The tower of despair

Easter egg?

Kali linux on LiveUSB with working persistent partition

Few days ago i wanted to make liveusb with kali linux (i had backtrack before). I used this guide to install kali, but i observed, that persistence partition does not work. There is partitions on my usb drive:
Kali - old partition table
When init script found persistent partition and tried to mount  their return error “mount: mounting /dev/sdaX on /root/lib/live/mount/persistence/sdaX failed: Device or resource busy”.
I think this happened because official guide suggest to write iso9660 image on usb drive, and init script think that it is cd drive and mount whole usb device, not a partition where iso placed. This i found in boot.log:

There you can see, that after kali boot, usb drive (sda) still mounted, and i can not mount second partition:
Kali1
After that whole usb drive is busy.  I attached boot.log to this post with enabled debug, may be it will help someone to fix that.

I decided to make bootable usb disk instead of flashing iso on it. For doing that i used extlinux and original kali iso file.
First i create 2 partitions on usb drive, one for kali and second for persistent files:

Kali2

Do not forget to set bootable flag on first partition and correct label for persistent paririon.
After that, install mbr from extlinux:

$ dd if=/usr/lib/extlinux/mbr.bin of=/dev/sda
0+1 records in
0+1 records out
440 bytes (440 B) copied, 0.00126658 s, 347 kB/s

Copy kali linux on first partition:

$ mkdir /mnt/sr0 /mnt/kali
$ mount /dev/sr0 /mnt/sr0/
mount: block device /dev/sr0 is write-protected, mounting read-only
$ mount /dev/sda1 /mnt/kali/
$ rsync -a /mnt/sr0/* /mnt/kali

Also i modify boot menu and add entry with persistence boot option at live.cfg:

label live-686-pae-persistence
menu label ^Live persistence (686-pae)
menu default
linux /live/vmlinuz
initrd /live/initrd.img
append boot=live noconfig=sudo username=root hostname=android-53f31a089339194f persistence

After that you need to rename isolinux.cfg to extlinux.conf and install extlinux:

$ cp /mnt/kali/isolinux/isolinux.cfg /mnt/kali/isolinux/extlinux.conf
$ extlinux --install /mnt/kali/isolinux/
/mnt/kali/isolinux/ is device /dev/sda1

Mount persistence partition and create config:

$ mkdir /mnt/persist
$ mount /dev/sda2 /mnt/persist/
$ echo "/ union" > /mnt/persist/persistence.conf

After that you can reboot and check, that persistent partition work.
Kali3