Author: iwi

Linux from scratch

Or how-to easily cross-build any custom Linux Distribution entirely from source code. Normally it is not an easy task, because you have to deal with lot of different aspects of software development and integration, from infinite configuration options to compiler errors. From hardware specifications to device drivers and file-systems and I/O console and Task scheduler and almost everything is involved. Then this is not easy…, but we have one fantastic tool, which is able to solve many really boring tasks.

https://buildroot.org – “Buildroot is a simple, efficient and easy-to-use tool to generate embedded Linux systems through cross-compilation.”

This is an example, how-to build LinuxOS for Olimex low cost board with 64MB RAM and 450Mhz CPU.

$ git clone git://git.buildroot.net/buildroot buildroot_mx23
Cloning into 'buildroot_mx23'...
remote: Enumerating objects: 351177, done.
remote: Counting objects: 100% (351177/351177), done.
remote: Compressing objects: 100% (111770/111770), done.
remote: Total 351177 (delta 245634), reused 342867 (delta 237974)
Receiving objects: 100% (351177/351177), 74.68 MiB | 1.50 MiB/s, done.
Resolving deltas: 100% (245634/245634), done.

For the list of already configured boards:  

 $ make list-defconfigs

Select Olimex i.mx233 board configuration:

$ make olimex_imx233_olinuxino_defconfig
...
#
# configuration written to /home/iwi/Documents/buildroot_mx23/.config
#

Now, just build and wait. That’s all.

$ make
...

INFO: hdimage(sdcard.img): adding partition 'u-boot' (in MBR) from 'u-boot.sd' ...
INFO: hdimage(sdcard.img): adding partition 'kernel' (in MBR) from 'boot.vfat' ...
INFO: hdimage(sdcard.img): adding partition 'rootfs' (in MBR) from 'rootfs.ext2' ...
INFO: hdimage(sdcard.img): writing MBR

Successful build looks like this, otherwise please check carefully your host system pre-requisites: https://buildroot.org/downloads/manual/manual.html#requirement

The first build may take some time to download all the required source code, build cross-compiler and all host system tools and libraries, than you can build just newly selected packages, but hacking with tool-chain options, requires clean rebuild of everything.

# Insert SD card and unmount all automounted sdX partitions
$ umount /dev/sdX2
$ umount /dev/sdX3

# Write image file to SD card
$ sudo dd if=output/images/sdcard.img of=/dev/sdX bs=1M
97517568 bytes (98 MB, 93 MiB) copied, 12.0944 s, 8.1 MB/s

# Flush all disk buffers
sync

Default board configuration provides Linux OS with minimal set of features and programs tailored for embedded systems. This lightweight Linux system provides excellent starting point for smart IoT device development.

U-Boot 2017.11 (Dec 07 2019 - 04:29:38 +0100)

CPU:   Freescale i.MX23 rev1.4 at 454 MHz
BOOT:  SSP SD/MMC #0
DRAM:  64 MiB
No arch specific invalidate_icache_all available!
__led_init: failed requesting GPIO59!
MMC:   MXS MMC: 0
*** Warning - bad CRC, using default environment

In:    serial
Out:   serial
Err:   serial
Net:   Net Initialization Skipped
No ethernet found.
Hit any key to stop autoboot:  0
switch to partitions #0, OK
mmc0 is current device
** Unable to read file boot.scr **
reading uImage   
5292296 bytes read in 1640 ms (3.1 MiB/s)
Booting from mmc ...
reading imx23-olinuxino.dtb
10286 bytes read in 29 ms (345.7 KiB/s)
## Booting kernel from Legacy Image at 42000000 ...
   Image Name:   Linux-4.19.2
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    5292232 Bytes = 5 MiB
   Load Address: 42000000
   Entry Point:  42000000
   Verifying Checksum ... OK
## Flattened Device Tree blob at 41000000
   Booting using the fdt blob at 0x41000000
   Loading Kernel Image ... OK
   Loading Device Tree to 43b75000, end 43b7a82d ... OK

Starting kernel ...

[    0.000000] Booting Linux on physical CPU 0x0
[    0.000000] Linux version 4.19.2 (iwi@nqdev) (gcc version 8.3.0 (Buildroot 2020.02-git-00204-g2ca0accc21)) #1 Sat Dec 7 04:31:14 CET 2019
[    0.000000] CPU: ARM926EJ-S [41069265] revision 5 (ARMv5TEJ), cr=0005317f
[    0.000000] CPU: VIVT data cache, VIVT instruction cache
[    0.000000] OF: fdt: Machine model: i.MX23 Olinuxino Low Cost Board
[    0.000000] Memory policy: Data cache writeback
[    0.000000] random: get_random_bytes called from start_kernel+0x84/0x474 with crng_init=0
[    0.000000] Built 1 zonelists, mobility grouping on.  Total pages: 16256
[    0.000000] Kernel command line: console=ttyAMA0,115200 root=/dev/mmcblk0p3 rw rootwait
[    0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
[    0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
[    0.000000] Memory: 46644K/65536K available (7200K kernel code, 633K rwdata, 2364K rodata, 364K init, 7454K bss, 18892K reserved, 0K cma-reserved)
[    0.000000] Virtual kernel memory layout:
[    0.000000]     vector  : 0xffff0000 - 0xffff1000   (   4 kB)
[    0.000000]     fixmap  : 0xffc00000 - 0xfff00000   (3072 kB)
[    0.000000]     vmalloc : 0xc4800000 - 0xff800000   ( 944 MB)
[    0.000000]     lowmem  : 0xc0000000 - 0xc4000000   (  64 MB)
[    0.000000]     modules : 0xbf000000 - 0xc0000000   (  16 MB)
[    0.000000]       .text : 0x(ptrval) - 0x(ptrval)   (7202 kB)
[    0.000000]       .init : 0x(ptrval) - 0x(ptrval)   ( 364 kB)
[    0.000000]       .data : 0x(ptrval) - 0x(ptrval)   ( 634 kB)
[    0.000000]        .bss : 0x(ptrval) - 0x(ptrval)   (7455 kB)
[    0.000000] SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1
[    0.000000] Running RCU self tests
[    0.000000] NR_IRQS: 16, nr_irqs: 16, preallocated irqs: 16
[    0.000000] clocksource: mxs_timer: mask: 0xffff max_cycles: 0xffff, max_idle_ns: 911346093 ns
[    0.000000] Console: colour dummy device 80x30
[    0.000000] Lock dependency validator: Copyright (c) 2006 Red Hat, Inc., Ingo Molnar
[    0.000000] ... MAX_LOCKDEP_SUBCLASSES:  8
[    0.000000] ... MAX_LOCK_DEPTH:          48
[    0.000000] ... MAX_LOCKDEP_KEYS:        8191
[    0.000000] ... CLASSHASH_SIZE:          4096
[    0.000000] ... MAX_LOCKDEP_ENTRIES:     32768
[    0.000000] ... MAX_LOCKDEP_CHAINS:      65536
[    0.000000] ... CHAINHASH_SIZE:          32768
[    0.000000]  memory used by lock dependency info: 4655 kB
[    0.000000]  per task-struct memory footprint: 1536 bytes
[    0.000000] sched_clock: 32 bits at 100 Hz, resolution 10000000ns, wraps every 21474836475000000ns
[    0.070000] Calibrating delay loop... 226.09 BogoMIPS (lpj=1130496)
[    0.070000] pid_max: default: 32768 minimum: 301
[    0.070000] Mount-cache hash table entries: 1024 (order: 0, 4096 bytes)
[    0.070000] Mountpoint-cache hash table entries: 1024 (order: 0, 4096 bytes)
[    0.080000] CPU: Testing write buffer coherency: ok
[    0.090000] Setting up static identity map for 0x40008400 - 0x40008458
[    0.100000] devtmpfs: initialized
[    0.140000] clocksource: jiffies: mask: 0xffffffff max_cycles: 0xffffffff, max_idle_ns: 19112604462750000 ns
[    0.140000] futex hash table entries: 256 (order: 1, 11264 bytes)
[    0.150000] pinctrl core: initialized pinctrl subsystem
[    0.160000] NET: Registered protocol family 16
[    0.170000] DMA: preallocated 256 KiB pool for atomic coherent allocations
[    0.320000] Serial: AMBA PL011 UART driver
[    0.320000] 80070000.serial: ttyAMA0 at MMIO 0x80070000 (irq = 17, base_baud = 0) is a PL011 rev2
[    0.530000] console [ttyAMA0] enabled
[    0.640000] mxs-dma 80004000.dma-apbh: initialized
[    0.660000] mxs-dma 80024000.dma-apbx: initialized
[    0.670000] SCSI subsystem initialized
[    0.680000] usbcore: registered new interface driver usbfs
[    0.690000] usbcore: registered new interface driver hub
[    0.690000] usbcore: registered new device driver usb
[    0.700000] pps_core: LinuxPPS API ver. 1 registered
[    0.710000] pps_core: Software ver. 5.3.6 - Copyright 2005-2007 Rodolfo Giometti <giometti@linux.it>
[    0.710000] PTP clock support registered
[    0.720000] Advanced Linux Sound Architecture Driver Initialized.
[    0.740000] clocksource: Switched to clocksource mxs_timer
[    1.790000] NET: Registered protocol family 2
[    1.800000] tcp_listen_portaddr_hash hash table entries: 128 (order: 0, 5120 bytes)
[    1.810000] TCP established hash table entries: 1024 (order: 0, 4096 bytes)
[    1.820000] TCP bind hash table entries: 1024 (order: 3, 36864 bytes)
[    1.820000] TCP: Hash tables configured (established 1024 bind 1024)
[    1.830000] UDP hash table entries: 256 (order: 2, 20480 bytes)
[    1.840000] UDP-Lite hash table entries: 256 (order: 2, 20480 bytes)
[    1.850000] NET: Registered protocol family 1
[    1.860000] RPC: Registered named UNIX socket transport module.
[    1.870000] RPC: Registered udp transport module.
[    1.870000] RPC: Registered tcp transport module.
[    1.880000] RPC: Registered tcp NFSv4.1 backchannel transport module.
[    1.910000] Initialise system trusted keyrings
[    1.910000] workingset: timestamp_bits=30 max_order=14 bucket_order=0
[    2.020000] NFS: Registering the id_resolver key type
[    2.030000] Key type id_resolver registered
[    2.030000] Key type id_legacy registered
[    2.040000] jffs2: version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
[    2.100000] jitterentropy: Initialization failed with host not compliant with requirements: 2
[    2.110000] Key type asymmetric registered
[    2.120000] Asymmetric key parser 'x509' registered
[    2.120000] Block layer SCSI generic (bsg) driver version 0.4 loaded (major 248)
[    2.130000] io scheduler noop registered (default)
[    2.140000] io scheduler mq-deadline registered
[    2.140000] io scheduler kyber registered
[    2.160000] 8006c000.serial: ttyAPP0 at MMIO 0x8006c000 (irq = 147, base_baud = 1500000) is a 8006c000.serial
[    2.170000] mxs-auart 8006c000.serial: Found APPUART 3.0.0
[    2.210000] libphy: Fixed MDIO Bus: probed
[    2.220000] usbcore: registered new interface driver asix
[    2.230000] usbcore: registered new interface driver ax88179_178a
[    2.240000] usbcore: registered new interface driver cdc_ether
[    2.240000] usbcore: registered new interface driver smsc95xx
[    2.250000] usbcore: registered new interface driver net1080
[    2.260000] usbcore: registered new interface driver cdc_subset
[    2.260000] usbcore: registered new interface driver zaurus
[    2.270000] usbcore: registered new interface driver cdc_ncm
[    2.280000] ehci_hcd: USB 2.0 'Enhanced' Host Controller (EHCI) Driver
[    2.280000] usbcore: registered new interface driver usb-storage
[    2.300000] imx_usb 80080000.usb: Linked as a consumer to regulator.1
[    2.310000] ci_hdrc ci_hdrc.0: EHCI Host Controller
[    2.320000] ci_hdrc ci_hdrc.0: new USB bus registered, assigned bus number 1
[    2.360000] ci_hdrc ci_hdrc.0: USB 2.0 started, EHCI 1.00
[    2.380000] hub 1-0:1.0: USB hub found
[    2.390000] hub 1-0:1.0: 1 port detected
[    2.410000] stmp3xxx-rtc 8005c000.rtc: rtc core: registered 8005c000.rtc as rtc0
[    2.420000] i2c /dev entries driver
[    2.440000] stmp3xxx_rtc_wdt stmp3xxx_rtc_wdt: initialized watchdog with heartbeat 19s
[    2.450000] mxs-mmc 80010000.ssp: 80010000.ssp supply vmmc not found, using dummy regulator
[    2.460000] mxs-mmc 80010000.ssp: Linked as a consumer to regulator.0
[    2.500000] mxs-mmc 80010000.ssp: initialized
[    2.510000] random: fast init done
[    2.530000] imx23-pinctrl 80018000.pinctrl: pin SSP1_DETECT already requested by 80010000.ssp; cannot claim for leds
[    2.540000] imx23-pinctrl 80018000.pinctrl: pin-65 (leds) status -22
[    2.540000] imx23-pinctrl 80018000.pinctrl: could not request pin 65 (SSP1_DETECT) from group led_gpio2_1.0  on device 80018000.pinctrl
[    2.560000] leds-gpio leds: Error applying setting, reverse things back
[    2.560000] leds-gpio: probe of leds failed with error -22
[    2.580000] mxs-dcp 80028000.dcp: Failed to register sha1 hash!
[    2.590000] mxs-dcp: probe of 80028000.dcp failed with error -22
[    2.610000] usbcore: registered new interface driver usbhid
[    2.610000] usbhid: USB HID core driver
[    2.630000] mmc0: host does not support reading read-only switch, assuming write-enable
[    2.650000] mmc0: new high speed SDHC card at address aaaa
[    2.680000] NET: Registered protocol family 17
[    2.690000] mmcblk0: mmc0:aaaa SU16G 14.8 GiB
[    2.700000] Key type dns_resolver registered
[    2.720000] registered taskstats version 1
[    2.730000] Loading compiled-in X.509 certificates
[    2.750000]  mmcblk0: p1 p2 p3
[    2.840000] stmp3xxx-rtc 8005c000.rtc: setting system clock to 1970-01-01 00:00:51 UTC (51)
[    2.850000] cfg80211: Loading compiled-in X.509 certificates for regulatory database
[    2.890000] cfg80211: Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7'
[    2.900000] ALSA device list:
[    2.900000]   No soundcards found.
[    2.910000] uart-pl011 80070000.serial: no DMA platform data
[    2.920000] platform regulatory.0: Direct firmware load for regulatory.db failed with error -2
[    2.930000] cfg80211: failed to load regulatory.db
[    2.950000] EXT4-fs (mmcblk0p3): mounting ext2 file system using the ext4 subsystem
[    3.000000] EXT4-fs (mmcblk0p3): mounted filesystem without journal. Opts: (null)
[    3.010000] VFS: Mounted root (ext2 filesystem) on device 179:3.
[    3.020000] devtmpfs: mounted
[    3.040000] Freeing unused kernel memory: 364K
[    3.040000] This architecture does not have kernel memory protection.
[    3.050000] Run /sbin/init as init process
[    3.350000] EXT4-fs (mmcblk0p3): re-mounted. Opts: block_validity,barrier,user_xattr
Starting syslogd: OK
Starting klogd: OK
Running sysctl: OK
Starting mdev... OK
Initializing random number generator: OK
Saving random seed: [   12.930000] random: dd: uninitialized urandom read (512 bytes read)
OK
Starting network: OK

Welcome to Buildroot
buildroot login: 

Login is “root”, without password.

# Customize user prompt, save to "~/.profile" 
$ nano ~/.profile
PS1="\\u@\\h:\\w$ "

Directory listing for binaries

root@buildroot:/bin$ ls
arch           dnsdomainname  linux64        nuke           sh
ash            dumpkmap       ln             pidof          sleep
base64         echo           login          ping           stty
busybox        egrep          ls             pipe_progress  su
cat            false          lsattr         printenv       sync
chattr         fdflush        mkdir          ps             tar
chgrp          fgrep          mknod          pwd            touch
chmod          getopt         mktemp         resume         true
chown          grep           more           rm             umount
cp             gunzip         mount          rmdir          uname
cpio           gzip           mountpoint     run-parts      usleep
date           hostname       mt             sed            vi
dd             kill           mv             setarch        watch
df             link           netstat        setpriv        zcat
dmesg          linux32        nice           setserial

root@buildroot:/sbin$ ls
arp                init               makedevs           setconsole
blkid              insmod             mdev               start-stop-daemon
devmem             ip                 mkdosfs            sulogin
fdisk              ipaddr             mke2fs             swapoff
freeramdisk        iplink             mkswap             swapon
fsck               ipneigh            modprobe           switch_root
fstrim             iproute            nameif             sysctl
getty              iprule             pivot_root         syslogd
halt               iptunnel           poweroff           tc
hdparm             klogd              reboot             udhcpc
hwclock            ldconfig           rmmod              uevent
ifconfig           loadkmap           route              vconfig
ifdown             losetup            run-init           watchdog
ifup               lsmod              runlevel

root@buildroot:/usr/bin$ ls
[            du           killall      nproc        sha512sum    unlink
[[           eject        last         nslookup     shred        unlzma
ar           env          ldd          od           sort         unlzop
awk          expr         less         openvt       strings      unxz
basename     factor       logger       passwd       svc          unzip
bc           fallocate    logname      paste        svok         uptime
bunzip2      find         lsof         patch        tail         uudecode
bzcat        flock        lspci        printf       tee          uuencode
chrt         fold         lsscsi       readlink     telnet       vlock
chvt         free         lsusb        realpath     test         w
cksum        fuser        lzcat        renice       tftp         wc
clear        getconf      lzma         reset        time         wget
cmp          head         lzopcat      resize       top          which
crontab      hexdump      md5sum       seq          tr           who
cut          hexedit      mesg         setfattr     traceroute   whoami
dc           hostid       microcom     setkeycodes  truncate     xargs
deallocvt    id           mkfifo       setsid       ts           xxd
diff         install      mkpasswd     sha1sum      tty          xz
dirname      ipcrm        nl           sha256sum    uniq         xzcat
dos2unix     ipcs         nohup        sha3sum      unix2dos     yes

root@buildroot:/usr/sbin$ ls
addgroup     delgroup     fdformat     i2cset       nologin      ubirename
adduser      deluser      fsfreeze     i2ctransfer  partprobe
arping       dnsd         i2cdetect    inetd        rdate
chroot       ether-wake   i2cdump      killall5     readprofile
crond        fbset        i2cget       loadfont     setlogcons

Disk and RAM reports:

root@buildroot:/$ df -h
Filesystem                Size      Used Available Use% Mounted on
/dev/root                58.1M      5.6M     49.5M  10% /
devtmpfs                 22.8M         0     22.8M   0% /dev
tmpfs                    23.0M         0     23.0M   0% /dev/shm
tmpfs                    23.0M     20.0K     22.9M   0% /tmp
tmpfs                    23.0M     20.0K     22.9M   0% /run

root@buildroot:/$ cat /proc/meminfo 
MemTotal:          47008 kB
MemFree:           26812 kB
MemAvailable:      36784 kB
Buffers:             232 kB
Cached:             2004 kB
SwapCached:            0 kB
Active:             2072 kB
Inactive:            684 kB
Active(anon):        544 kB
Inactive(anon):       16 kB
Active(file):       1528 kB
Inactive(file):      668 kB
Unevictable:           0 kB
Mlocked:               0 kB
SwapTotal:             0 kB
SwapFree:              0 kB
Dirty:                28 kB
Writeback:             0 kB
AnonPages:           536 kB
Mapped:             1068 kB
Shmem:                40 kB
Slab:              14296 kB
SReclaimable:      11204 kB
SUnreclaim:         3092 kB
KernelStack:         280 kB
PageTables:           88 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:       23504 kB
Committed_AS:       1780 kB
VmallocTotal:     966656 kB
VmallocUsed:           0 kB
VmallocChunk:          0 kB
Percpu:               32 kB

Disk space is not a big issue, but RAM memory is really limiting factor for this system. Also CPU is low profile ARM926 Running at 454 MHz. This computational power is just enough for mp3 player or light web server or something like photo frame, also because current linux support for this architecture is incomplete and can’t take full advantages of all available peripherals. Anyhow, fast or slow is your system, everything depends on what you intent to do with this system.

root@buildroot:/$ cat /proc/cpuinfo 
processor       : 0
model name      : ARM926EJ-S rev 5 (v5l)
BogoMIPS        : 226.09
Features        : swp half thumb fastmult edsp java 
CPU implementer : 0x41
CPU architecture: 5TEJ
CPU variant     : 0x0
CPU part        : 0x926
CPU revision    : 5

Hardware        : Freescale MXS (Device Tree)
Revision        : 0000
Serial          : 0000000000000000

Back to buildroot configuration. This setup lacks of wifi support and some useful tools like nano and mc. Moreover if you want to adapt kernel configuration to your hardware, add extra drivers and packages:

# Buildroot configuration
$ make menuconfig

# For kernel and drivers configuration
$ make linux-menuconfig

# For busybox configuration
$ make busybox-menuconfig

Useful tool-chain and system settings:

# Select full featured GNU stdc library
Toolchain  ---> C library (glibc)  ---> (X) glibc
# Enable c++ compiler
[*] Enable C++ support
# Select kernel version
Custom kernel headers series (5.4.x)  ---> (X) 5.4.x
# Remote system debugging  
[*] Build cross gdb for the host

Select Python, c++, gdb, sudo, mc, ecc...

Network connecction:

# Wifi network
root@mx23:~$ wpa_passphrase ESSID_NAME ESSID_PASS > /root/home_conn.conf

# Connect to home network 
root@mx23:~$ wpa_supplicant -B -i wlan0 -c /root/home_conn.conf

# Run DHCP client
root@mx23:~$ udhcpc -i wlan0
# Enable root login for open SSH server 
root@mx23:~$ nano /etc/ssh/sshd_config
PermitRootLogin yes

Finally, a small swap file is always a good idea:

# Make 128 MB swapfile
root@mx23:~$ fallocate -l 128M /swapfile
root@mx23:~$ chmod 600 /swapfile
root@mx23:~$ mkswap /swapfile
root@mx23:~$ swapon /swapfile

# Add swap info to fstab 
root@mx23:~$ nano /etc/fstab
/swapfile       none            swap    defaults        0       0

Next:
Code::blocks IDE and Remote debugging
OpenOCD and Serial JTAG

Serial UART console

Most simple and common way to connect almost any embedded device is serial port. You can find one inside any Smart TV or Media Center, WiFi Router and almost any kind of complex electronic device provides this port. The reason to expose this port may be different, but usually is used for maintenance, debug and diagnostics. Be careful with [un]authorized accesses to any device, please check device documentation and contact support first.

For everything you would like to know about serial communication, please refer to this article: https://www.freebsd.org/doc/en_US.ISO8859-1/articles/serial-uart/index.html

Original specification for DB9 and DB25 connectors defines a lot of control and synchronization signals like DTR – “Data Terminal Ready” or DSR – “Data Set Ready” or RI – “Ring Indicator”. Signals used especially for synchronization with ancient and slow terminals with small buffers. Now, many devices successfully use only TX and RX pins for serial communication and all other pins are simply useless.

Actually there are many ways to connect to the serial port, for example you can use “USB to Serial” converter or “Serial Bluetooth” module, almost any embedded development kit should support UART / USART connection. Before selecting your converter, check signal levels, is common to find 5v and 3.3v devices. Do not mix, unless your 3.3Volt device is specifically tolerant to 5volt signals. Otherwise signal level converter is required. Some old device or also special purpose serial devices may use +/-12 volt signal.

This kind of serial connection is not intended for high bandwidth or long range communications. Rather that, it’s simple and robust enough to fulfill most of the basic but essential communication tasks.

Common baud-rates and maximum theoretical data throughput:


7bit data
No parity
8bit data
No parity
8bit data
1bit parity
Baud-rateChar/sChar/sChar/s
300333027
600676055
1200133120109
1800200180164
2400267240218
4800533480436
7200800720655
96001067960873
14400160014401309
19200213319201745
38400426738403491
57600640057605236
115200128001152010473
128000142221280011636
153600170671536013964
230400256002304020945
256000284442560023273
460800512004608041891
9216001024009216083782
1382400153600138240125673

Although simple serial console I/O is powerful enough for many tasks where the error is negligible, big data transfer requires error handling and synchronization, like XON / XOFF or parity bit. Is also a good practice to add CRC to the entire data block, over then simple parity check. Because this type of communication may suffer of erasures and multi bit errors.

A lot of software and protocols was developed to support serial communication remote console and file transfer, like “[X|Y|Z]MODEM” or “Kermit”, “minicom” and “Putty” and many others more or less famous.

A simple and elegant way to connect router’s serial console is through HC-06 Slave bluetooth module.
This module exposes the SPP (Serial Port Profile) protocol for remote devices. Then, any Bluetooth Master near the router can connect it, obviously knowing the correct pin.

TL-MR3220 serial port connected to bluetooth HC-06 module. Supply of 3.3v is provided by router board red wire. Black is ground, TX and RX (Green and White) for serial I/O.

Router board console via bluetooth with Putty.

First, configure HC-06 module for 115200 bps 8 bit data, no parity bit and one stop bit, then connect it to the router. If provided power supply is sufficient to power-up bluetooth module, we will see blinking red led. Module consumption under 3.3v is around 4mA – 8mA for idle state and 20mA – 40mA for normal operation.

Python setup script for HC-06 serial bluetooth module: https://github.com/netquote/hc_utils

Bluetooth module connection with level shifter (5v to 3.3v) and FTDI Serial to USB converter
$ python3 hc_setup.py /dev/ttyUSB0 -p N --set-pin 1234 --set-name BTS00 --set-rate 115200 --set-parity N

 Guessing bit-rate and parity on /dev/ttyUSB0 …
   Rate: 1200, parity: N 
   Rate: 2400, parity: N 
   Rate: 4800, parity: N 
   Rate: 9600, parity: N 
   Rate: 19200, parity: N 
   Rate: 38400, parity: N 
   Rate: 57600, parity: N 
   Rate: 115200, parity: N 
 AT device detected.
 Open serial port: /dev/ttyUSB0, bit-rate: 115200, parity: N 
 Device version: linvorV1.8 
 Set name OK
 Set pin OK
 Set baud 115200 
 Set parity  None

Deal with serial ports from source code is pretty straightforward, like write and read simple file, but port configuration procedure is dependent on OS / HW nor language used.

Example Python script for basic serial I/O:

#!/usr/bin/env python

# Import pySerial library
from serial import *

# Open serial port at "115200,8,N,1", timeout 3s 
ser = Serial(port='/dev/ttyUSB0',
             baudrate=115200,
             bytesize=EIGHTBITS,
             parity=PARITY_NONE,
             stopbits=STOPBITS_ONE,
             timeout=3) 

# Write a string
ser.write(b'Hello!\n')

# Read 30 bytes
print(ser.read(30))

# Close port
ser.close()             

This Python demo script should work on both, Linux and Windows platforms, just change device name to “COM1” on Windows.

Another way to deal with serial communication is “kermit” from: http://www.kermitproject.org
Old-school scriptable tool for almost any modem and communication related tasks.

; Kermit script for router firmware update via serial line
; Router: TL-MR3220 v1.2 (original bootloader)
; File: "wrt_ser_upload.ksc"

set line /dev/rfcomm3
set speed 115200
set carrier-watch off
set flow-control none
set handshake none
set prefixing all

; Echo serial line to console
SET INPUT ECHO ON

; Clear console input buffer
LINEOUT \21
; Wait for console prompt
INPUT 3 :/#
; System reboot request 
LINEOUT reboot

; Wait for U-Boot prompt 
INPUT 180 Autobooting in 1 seconds
; Login into u-boot console
OUTPUT tpl

; Wait for u-boot prompt
INPUT 3 ar7240>
; Prepare U-Boot for incomming file
LINEOUT loadb 0x81000000

; Wait for u-boot ACK
INPUT 3 Ready for binary (kermit) download
; Send new firmware file
SEND ~/openwrt-18.06/bin/targets/ar71xx/tiny/openwrt-ar71xx-tiny-tl-mr3220-v1-squashfs-factory.bin

; Wait for u-boot prompt
INPUT 3 ar7240>
; Erase target flash memory 
LINEOUT erase 0x9f020000 +0x3c0000
; Erase completed  
INPUT 60 Erased 60 sectors

; Wait for u-boot prompt
INPUT 3 ar7240>
; Write new firmware to flash
LINEOUT cp.b 0x81000000 0x9f020000 0x3c0000
; Wait for done
INPUT 60 done

; Wait for u-boot prompt
INPUT 3 ar7240>
; Boot into new system 
LINEOUT bootm 0x9f020000

; Quit
QUIT 0

This Kermit script updates OpenWRT firmware for TL-MR3220 router v1.2

Kermit file transfer

Router documentation:
https://openwrt.org/toh/tp-link/tl-mr3420
Kermit documentation:
http://www.kermitproject.org
http://www.columbia.edu/kermit/ek.html
https://www.emcraft.com/stm32f429discovery/loading-linux-images-over-uart
HC-06 bluetooth module documentation:
http://www.martyncurrey.com/bluetooth-modules/
http://wiki.pinguino.cc/index.php/SPP_Bluetooth_Modules
https://mcuoneclipse.com/2014/03/30/getting-bluetooth-working-with-jy-mcu-bt_board-v1-06/
HC-06 Firmware reference:
https://www.instructables.com/id/Upgrade-Your-3-Bluetooth-Module-to-Have-HID-Firmwa/
http://dangerousprototypes.com/blog/2012/10/05/open-source-bluetooth-module-firmware/
http://elasticsheep.com/2012/06/bluetooth-module-firmware-dump/
https://github.com/pfalcon/blutunode
http://byron76.blogspot.com/search/label/bluetooth

TP-Link MR3420 setup OpenWRT v18.06

OpenWrt is a powerful Linux distribution for embedded devices. Especially for routers with reduced memory and performance. This objective has contributed to an extreme level of optimization of this distribution, allowing also a high margin of flexibility and really easy setup.
This distribution usually fits on many embedded devices, the complete list can be found at this link: http://wiki.openwrt.org/toh/start

Don’t expect magics from this configuration, you can’t install all the available software, simply because we don’t have enough RAM / ROM memory. Sometimes it is possible to overcome some limitations, for example extending the RAM memory with the ZRAM or SWAP file, extending the root filesystem with a USB flash memory device. However, a stable and robust configuration requires a careful evaluation of the installed services and their impact on system resources. Software as imagemagick or ffmpeg, which tries to allocate a large amount of memory, will likely fail with the segmentation error.
However, everything comes from source and everything is customizable. You can even avoid to install web interface and configure everything by ssh console and UCI command line tool, or build your own web GUI or Service supported by a solid and flexible cross-build system.
Thanks to the excellent work of all OpenWrt team, time to time, we have a new and fresh release to build.
Check your system requirements first: http://wiki.openwrt.org/doc/howto/buildroot.exigence
This new release includes linux kernel updates, different security and bug fixes.

Clone v18.06 branche:

git clone -b openwrt-18.06 git://git.openwrt.org/openwrt/openwrt.git openwrt-18.06

Or master branche:

git clone git://git.openwrt.org/openwrt/openwrt.git openwrt

Next, update feeds:

cd openwrt-18.06/
./scripts/feeds update -a

Configure build system:

make menuconfig

Select router options:
Install LUCI web interface:

./scripts/feeds install luci

Select Luci web interface from menuconfig:

LuCI --->  1. Collections --->  <*> luci

Choose packages carefully, because we have only 4mb of storage. This amount of memory is enough for many specialized device with a limited set of features like a router or AP. In order to take advantage of many of the packages provided by OpenWrt, it is essential to extend the memory with external USB storage. Blockmount package and root overlay filesystem can do this trick: https://openwrt.org/docs/techref/block_mount

Select block-mount:

Base system --->  <*> block-mount
Kernel modules --->  USB Support --->  <*> kmod-usb-storage
Kernel modules --->  Filesystems --->  <*> kmod-fs-ext4

Another solution is to remove all ip-v6 support. Is configured by default and also supported from kernel side. Hacking on Kernel configuration is especially useful when support for specific hardware is required or simply to enable debugging features or disable something to save space. 

Linux kernel configuration:

make kernel_menuconfig

Careful with kernel settings, most of them are unsafe. Don’t touch things, if you are not aware about what are they really doing. At best, you’ll get a slow kernel with a lot of useless code.

Build firmware:

make -j8

Finally, we can find all binary files in “bin/targets/ar71xx/tiny/”

1,2K giu 13 12:04 config.seed
2,8K giu 13 12:07 openwrt-ar71xx-tiny-device-tl-mr3420-v1.manifest
2,7M giu 13 12:07 openwrt-ar71xx-tiny-root.squashfs
3,8M giu 13 12:07 openwrt-ar71xx-tiny-tl-mr3420-v1-squashfs-factory.bin
3,6M giu 13 12:07 openwrt-ar71xx-tiny-tl-mr3420-v1-squashfs-sysupgrade.bin
1,2M giu 13 12:07 openwrt-ar71xx-tiny-uImage-lzma.bin
3,5M giu 13 12:07 openwrt-ar71xx-tiny-vmlinux.bin
3,5M giu 13 12:07 openwrt-ar71xx-tiny-vmlinux.elf
1,2M giu 13 12:07 openwrt-ar71xx-tiny-vmlinux.lzma
1,2M giu 13 12:07 openwrt-ar71xx-tiny-vmlinux-lzma.elf
4,0K giu 13 12:07 packages
1,1K giu 13 12:07 sha256sums

To program the device for the first time is sufficient to upload “factory.bin” to the router, from it’s own classic web interface as usual. For subsequent upgrades from LUCI web interface use “sysupgrade.bin”.

Wait for the router to reboot, connect to “192.168.1.1” with any browser or ssh, then you will be able to set up root password. First Login: http://wiki.openwrt.org/doc/howto/firstlogin
 

Next topics:
1) Serial debug console
2) Customize your build
3) Remote development

Reference:
All documentation and howto: http://wiki.openwrt.org/doc/start
Multiple builds in one single checkout: http://wiki.openwrt.org/doc/devel/env
Detailed build instructions: http://wiki.openwrt.org/doc/howto/build
Easy patch management: http://wiki.openwrt.org/doc/devel/patches
Creating packages: http://wiki.openwrt.org/doc/devel/packages

TP-LINK MR3420 hardware

TL-MR3420 is Wireless N Router with USB 2.0 Port for UMTS/HSPA/EVDO USB Modem.

Model Name
TL-MR3420
Dimensions
6.9 x 4.4 x 1.2 in. (174 x 111 x 30 mm)
Power
9VDC / 0.85A
Ports
#1 – USB 2.0
#1 – Ethernet WAN 10/100Mbps
#4 – Ethernet LAN 10/100Mbps
Antennas
#2 – 3dBi Detachable Omni Directional Antennas
Wireless Transmit Power
20dBm (Max. EIRP)
CPU
Atheros AR7241@400MHz
RAM
32 MB
Flash
4 MB

Arduino Nano v3 internal temperature sensor

Calibration data:

Download data & formulas in excel.
Atmega documentation says:
The voltage sensitivity is approximately 1 mV/°C and the accuracy of the temperature measurement is +/- 10°C.
Measured temperature is a sum of ambient temperature and chip’s TDP.

In fact it rises up for few minutes after the chip is powered and may change in base of load.

// Read Atmega328P internal temperature sensor //
long read_temp()
{
  // Read temperature sensor against 1.1V reference
  ADMUX = _BV(REFS1) | _BV(REFS0) | _BV(MUX3);
  // Start AD conversion
  ADCSRA |= _BV(ADEN) | _BV(ADSC);
  // Detect end-of-conversion
  while (bit_is_set(ADCSRA,ADSC));
  // return raw data
  return ADCL | (ADCH &lt;&lt; 8);
}

// Convert raw temperature data to °C
double conv_temp(long raw_temp)
{
  // f(x) = (raw - offset) / coeff
  return((raw_temp - 324.31) / 1.22);
}

void setup()
{
  Serial.begin(115200);
}

void loop()
{
  Serial.println(conv_temp(read_temp()), 1);
  delay(500);
}

Datasheet Atmega 328P – https://www.microchip.com/wwwproducts/en/ATmega328p

It is a curious fact that putting chips in the freezer, after a few minutes when the temperature drops below zero, the chip stops working.

Gentoo default Python interpreter

Gentoo default Python interpreter is set to version 3.1:
~ # eselect python list
Available Python interpreters:
[1] python2.6
[2] python3.1 *

Command to change default interpreter:
~ # eselect python set 1
And now interpreter version is 2.6:
~ # eselect python list
Available Python interpreters:
[1] python2.6 *
[2] python3.1

Installing version 2.7:
~ # nano /etc/portage/package.accept_keywords
=dev-lang/python-2.7*
^X (Ctrl+X) --> exit & save
~ # emerge --ask =dev-lang/python-2.7*

Rebuild Python modules:
~ # python-updater
* Starting Python Updater...
* Main active version of Python: 2.7
* Active version of Python 2: 2.7
* Active version of Python 3: 3.1

Happy python coding!

Gentoo web2py daemon

Gentoo RC init script for web2py framework

Save as “/etc/init.d/web2py”

#!/sbin/runscript
# Gentoo web2py init script

WORK_PATH="/home/web2py"
WORK_FILE="web2py.py"

PYTHON="/usr/bin/python2.6"
PIDFILE="/var/run/web2py.pid"

PASSWORD="<recycle>"
SRV_ADDR="0.0.0.0"
SRV_PORT="8000"
SRV_CRT=""
SRV_KEY=""

depend(){
  need net
}

start() {
  ebegin "Starting web2py"
  start-stop-daemon --start --quiet --background --chdir "$WORK_PATH" \
                    --pidfile $PIDFILE --exec "$PYTHON" \
                    -- "$WORK_PATH/$WORK_FILE" \
                    --nogui --password="$PASSWORD" \
                    --pid_filename="$PIDFILE" \
                    --ip=$SRV_ADDR --port=$SRV_PORT \
                    --ssl_certificate="$SRV_CRT" --ssl_private_key="$SRV_KEY"
  eend $?
}

stop() {
  ebegin "Stopping web2py"
  start-stop-daemon --stop --pidfile $PIDFILE
  eend $?
}

To make a file executable:
chmode +x /etc/init.d/web2py
Add to default runlevel:
rc-update add web2py default
Start daemon:
rc-config start web2py

Remove Windows 7 password

This is the most easiest way to remove password of Windows system. Works on all Windows [NT/XP/Vista/Seven] – [32/64] versions.

DANGER!
If used on users that have EFS encrypted files, and the system is XP or newer, all encrypted files for that user will be UNREADABLE! If you don’t know if you have encrypted files or not, you most likely don’t have them. (except maybe on corporate systems)

It’s floppy based Linux distribution, partially derived from floppyfw.
Boot [CD/Floppy] downloads and instructions can be found at:
http://pogostick.net/~pnh/ntpasswd/

This floppy image is in the SYSRESCUECD, also instructions to make Boot USB Pen Drive: http://www.sysresccd.org/Sysresccd-manual-en_How_to_install_SystemRescueCd_on_an_USB-stick

Python GUI calc

Python GUI experiment. Simple calculator application made with Tk.
It’s a first choice because it’s integrated into Python, simple to use and powerful enough for most cases. It’s also cross platform like an interpreter.
However, there are many other libraries for GUI:
http://wiki.python.org/moin/GuiProgramming

#!/usr/bin/python

# Python GUI calculator 
# (C) 2011 - netquote.it
# Original code by Emanuele Chiabrera
# Enhanced by Toropov Ivan 

from Tkinter import *

# button text list
cmdlst = ['7', '8', '9', '+', '%',
          '4', '5', '6', '-', '**',
          '1', '2', '3', '*', '//',
          '.', '0', 'CL', '/', '=']

class MyButton(Button):
    
    backref = None
    
    def Click(self):
        # back reference
        self.backref.BtnCmd(self["text"])


class CalcApp:

    def __init__(self, master):
        frame = Frame(master)
        
        self.textbox = Entry(width=30, takefocus=1)
        self.textbox.pack(side=TOP)
        self.textbox.focus_force()

        self.buttons = []
        for n, c in enumerate(cmdlst):
            self.buttons.append(MyButton(frame, text=c, width=5))
            self.buttons[n]["command"] = self.buttons[n].Click
            self.buttons[n].backref = self
            self.buttons[n].grid(row=n/5, column=n%5)

        frame.pack()

    def BtnCmd(self, cmd):
        if cmd == '=':
            try:
                res = eval(self.textbox.get())
            except:
                res = "Error!"
            self.textbox.delete(0, END)
            self.textbox.insert(0, str(res))
        elif cmd == 'CL':
            self.textbox.delete(0, END)
        else:
            self.textbox.insert(END, cmd)

root = Tk()
root.title("EWCalc")

calcapp = CalcApp(root)
root.mainloop()

What comes out:

Voltage Drop Protection

DC motor drive circuit with automatic load regulation. Main concept is to cut off power from DC Motor and sustain the voltage in the circuit. Also detect low-battery state.

Components:
#1 – Dual Op-Amp CA158 (Like LM358)
#1 – Trimmer 4.7 kΩ (voltage limit regulator)
#1 – NPN-MOSFET IRF530 (14A, 100V)
#1 – Capacitor C 0,1 µF
#1 – Capacitor C 0,33 µF
#1 – Led (Green – Bat ok)
#1 – Led (Red – Bat low)
#2 – Resistor R 220 Ω
#3 – Resistor R 15 kΩ
#1 – Brushed DC-Motor Permax 400 (6V)