in Embedded, IOT, Linux

Embedded Linux S3C2440 Profiling

Summary

OProfile is a profiling system can do profiling on all parts of a running system from the kernel to shared libraries and to binaries. It can work in the background, collecting information at a low overhead, it is ideal for profiling the entire system to determine the bottle necks in a real running system.

OProfile can be run in two modes: Legacy mode and Operf mode. In legacy mode, the special OProfile kernel driver is required. Profiling is controlled by opcontrol script and oprofiled daemon. In operf mode, the operf program is used to control profiling instead of using opcontrol and oprofiled. Operf does not require the Oprofile kernel driver, it interfaces with kernel to collect samples via the Linux Kernel Performance Events Subsystem (perf_events).

S3C2440 board does not provide the needed hardware supports to use the performance counters, which is used by Perf_events. So on S3C2440 board, OProfie falls back to use legacy mode and the timer interrupt for profiling, by using the real-time clock interrupt to collect samples. In timer mode, OProfile is not able to profile code that has interrupt disabled.

OProfile Applications and driver

When configure buildroot, oprofile is selected and application binaries is located in /home/iot/mini2440/buildroot-2013.02/output/target/usr/bin as below.

[root@localhost bin]# pwd
/home/iot/mini2440/buildroot-2013.02/output/target/usr/bin
[root@localhost bin]# ls op*
opannotate  oparchive  op-check-perfevents  opcontrol  openvt  operf  opgprof  ophelp  opimport  opjitconv  opreport  oprofiled
[root@localhost bin]# ll op*
-rwxr-xr-x. 1 root root 398876 Dec 28 14:59 opannotate
-rwxr-xr-x. 1 root root 305316 Dec 28 14:59 oparchive
-rwxr-xr-x. 1 root root   4164 Dec 28 14:59 op-check-perfevents
-rwxr-xr-x. 1 root root  53899 Dec 28 14:59 opcontrol
lrwxrwxrwx. 1 root root     17 Dec 28 14:59 openvt -> ../../bin/busybox
-rwxr-xr-x. 1 root root 162700 Dec 28 14:59 operf
-rwxr-xr-x. 1 root root 336900 Dec 28 14:59 opgprof
-rwxr-xr-x. 1 root root  43424 Dec 28 14:59 ophelp
-rwxr-xr-x. 1 root root  43400 Dec 28 14:59 opimport
-rwxr-xr-x. 1 root root  29224 Dec 28 14:59 opjitconv
-rwxr-xr-x. 1 root root 505812 Dec 28 14:59 opreport
-rwxr-xr-x. 1 root root  92940 Dec 28 14:59 oprofiled

The libraries required by the applications are located in the directory /home/iot/mini2440/buildroot-2013.02/output/target/lib and /home/iot/mini2440/buildroot-2013.02/output/target/usr/lib.

[root@localhost lib]# ls
ld-uClibc-0.9.32.1.so  libcrypt.so.0      libdl.so.0     libm-0.9.32.1.so    libnsl.so.0             libresolv-0.9.32.1.so  librt.so.0                libuClibc-0.9.32.1.so
ld-uClibc.so.0         libc.so.0          libgcc_s.so    libm.so.0           libpthread-0.9.32.1.so  libresolv.so.0         libthread_db-0.9.32.1.so  libutil-0.9.32.1.so
libcrypt-0.9.32.1.so   libdl-0.9.32.1.so  libgcc_s.so.1  libnsl-0.9.32.1.so  libpthread.so.0         librt-0.9.32.1.so      libthread_db.so.1         libutil.so.0
[root@localhost lib]# pwd
/home/iot/mini2440/buildroot-2013.02/output/target/lib
[root@localhost lib]# cd ../usr/lib/
[root@localhost lib]# pwd
/home/iot/mini2440/buildroot-2013.02/output/target/usr/lib
[root@localhost lib]# ls
ldscripts                  libfreetype.so.6.10.0  libid3tag.so.0      libkmod.so        libncurses.so.5.9              libpopt.so.0         libstdc++.so.6.0.17-gdb.py  libz.so.1
libbfd-2.20.1.20100303.so  libgomp.so             libid3tag.so.0.3.0  libkmod.so.2      libopcodes-2.20.1.20100303.so  libpopt.so.0.0.0     libsysfs.so                 libz.so.1.2.7
libbfd.so                  libgomp.so.1           libintl.so          libkmod.so.2.2.2  libopcodes.so                  libreadline.so       libsysfs.so.2               oprofile
libelf.so                  libgomp.so.1.0.0       libintl.so.8        libmad.so         libpng14.so                    libreadline.so.6     libsysfs.so.2.0.1           terminfo
libelf.so.0                libhistory.so          libintl.so.8.1.2    libmad.so.0       libpng14.so.14                 libreadline.so.6.2   libts-1.0.so.0              ts
libelf.so.0.8.12           libhistory.so.6        libjpeg.so          libmad.so.0.2.1   libpng14.so.14.12.0            libstdc++.so         libts-1.0.so.0.0.0
libfreetype.so             libhistory.so.6.2      libjpeg.so.8        libncurses.so     libpng.so                      libstdc++.so.6       libts.so
libfreetype.so.6           libid3tag.so           libjpeg.so.8.4.0    libncurses.so.5   libpopt.so                     libstdc++.so.6.0.17  libz.so
[root@localhost lib]#

Check the library dependency of the profile applications as below,

[root@localhost lib]# cd /home/iot/mini2440/buildroot-2013.02/output/target/usr/bin/
[root@localhost bin]# pwd
/home/iot/mini2440/buildroot-2013.02/output/target/usr/bin
[root@localhost bin]# arm-linux-readelf -d op* | grep library
readelf: Error: Unable to read in 0x4f20 bytes of section headers
readelf: Error: Not an ELF file - it has the wrong magic bytes at the start
 0x00000001 (NEEDED)                     Shared library: [libpopt.so.0]
 0x00000001 (NEEDED)                     Shared library: [libbfd-2.20.1.20100303.so]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.0]
 0x00000001 (NEEDED)                     Shared library: [libintl.so.8]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.0]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libc.so.0]
 0x00000001 (NEEDED)                     Shared library: [libpopt.so.0]
 0x00000001 (NEEDED)                     Shared library: [libbfd-2.20.1.20100303.so]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.0]
 0x00000001 (NEEDED)                     Shared library: [libintl.so.8]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.0]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libc.so.0]
 0x00000001 (NEEDED)                     Shared library: [libpopt.so.0]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.0]
 0x00000001 (NEEDED)                     Shared library: [libintl.so.8]
 0x00000001 (NEEDED)                     Shared library: [libc.so.0]
 0x00000001 (NEEDED)                     Shared library: [libc.so.0]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.0]
 0x00000001 (NEEDED)                     Shared library: [libintl.so.8]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.0]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libc.so.0]
 0x00000001 (NEEDED)                     Shared library: [libpopt.so.0]
 0x00000001 (NEEDED)                     Shared library: [libbfd-2.20.1.20100303.so]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.0]
 0x00000001 (NEEDED)                     Shared library: [libintl.so.8]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.0]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libc.so.0]
 0x00000001 (NEEDED)                     Shared library: [libpopt.so.0]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.0]
 0x00000001 (NEEDED)                     Shared library: [libintl.so.8]
 0x00000001 (NEEDED)                     Shared library: [libc.so.0]
 0x00000001 (NEEDED)                     Shared library: [libpopt.so.0]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.0]
 0x00000001 (NEEDED)                     Shared library: [libintl.so.8]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.0]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libc.so.0]
 0x00000001 (NEEDED)                     Shared library: [libbfd-2.20.1.20100303.so]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.0]
 0x00000001 (NEEDED)                     Shared library: [libintl.so.8]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libc.so.0]
 0x00000001 (NEEDED)                     Shared library: [libpopt.so.0]
 0x00000001 (NEEDED)                     Shared library: [libbfd-2.20.1.20100303.so]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.0]
 0x00000001 (NEEDED)                     Shared library: [libintl.so.8]
 0x00000001 (NEEDED)                     Shared library: [libstdc++.so.6]
 0x00000001 (NEEDED)                     Shared library: [libm.so.0]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libc.so.0]
 0x00000001 (NEEDED)                     Shared library: [libpopt.so.0]
 0x00000001 (NEEDED)                     Shared library: [libdl.so.0]
 0x00000001 (NEEDED)                     Shared library: [libintl.so.8]
 0x00000001 (NEEDED)                     Shared library: [libgcc_s.so.1]
 0x00000001 (NEEDED)                     Shared library: [libc.so.0]
[root@localhost bin]#

Configure and Compile Busybox to support Oprofile

The opcontrol script requires math function, need to configure the Busybox to support math in the shell scripts.

[root@localhost busybox-1.19.4]# pwd
/home/iot/mini2440/busybox-1.19.4
[root@localhost busybox-1.19.4]# make menuconfig
  HOSTLD  scripts/kconfig/mconf
  HOSTCC  scripts/kconfig/lxdialog/checklist.o
  HOSTCC  scripts/kconfig/lxdialog/inputbox.o
  HOSTCC  scripts/kconfig/lxdialog/lxdialog.o
  HOSTCC  scripts/kconfig/lxdialog/menubox.o
  HOSTCC  scripts/kconfig/lxdialog/msgbox.o
  HOSTCC  scripts/kconfig/lxdialog/textbox.o
  HOSTCC  scripts/kconfig/lxdialog/util.o
  HOSTCC  scripts/kconfig/lxdialog/yesno.o
  HOSTLD  scripts/kconfig/lxdialog/lxdialog
scripts/kconfig/mconf Config.in
#
# using defaults found in .config
#


*** End of configuration.
*** Execute 'make' to build the project or try 'make help'.

Under Coreutils,

[*] tr
[*]   Enable character classes (such as [:upper:]) (NEW)
[*]   Enable equivalence classes (NEW)
[*] dirname
[*] expr
[*] false
[*] fold
[*] mv
[*] sleep
[*]   Enable multiple arguments and s/m/h/d suffixes (NEW)
[*]     Enable fractional arguments (NEW)

Under Process Utilities,

[*] pidof
[*]   Enable argument for single shot (-s) (NEW)
[*]   Enable argument for omitting pids (-o) (NEW)

Under Shells,

[*] POSIX math support
[*]   Extend POSIX math support to 64 bit (NEW)

Under Editors,

[*] awk
[*]   Enable math functions (requires libm) (NEW)
[*] Allow vi and awk to execute shell commands

Download the Kernel Image to S3C2440 board

Recompile and install Busybox,

[root@localhost busybox-1.19.4]# make clean
  CLEAN   applets
  CLEAN   .tmp_versions _install
  CLEAN   busybox busybox_unstripped.map busybox_unstripped.out busybox_unstripped busybox.links .kernelrelease
[root@localhost busybox-1.19.4]# make
[root@localhost busybox-1.19.4]# make install

Create Rootfs

[root@localhost rootfilesystem]# pwd
/home/iot/mini2440/rootfilesystem
[root@localhost rootfilesystem]#

Modify the shell script create_rootfs_bash.sh.

Add following line,

ln -s /proc/mounts etc/mtab

after,

ln -s bin/busybox init

Copy the applications, to include below lines,

cp /home/iot/mini2440/myapp/thread_demo* usr/bin

cp $TARGET_DIR/usr/bin/gdbserver usr/bin
cp $TARGET_DIR/usr/bin/op* usr/bin
cp $TARGET_DIR/usr/bin/ldd usr/bin
cp $TARGET_DIR/usr/bin/objcopy usr/bin
cp $TARGET_DIR/usr/bin/objdump usr/bin

And copy the libraries, to include below lines,

cp -P $TARGET_DIR/lib/* lib/
cp -P $TARGET_DIR/usr/lib/libpopt* usr/lib
cp -P $TARGET_DIR/usr/lib/libbfd* usr/lib
cp -P $TARGET_DIR/usr/lib/libintl* usr/lib
cp -P $TARGET_DIR/usr/lib/libstdc++* usr/lib
cp -P $TARGET_DIR/usr/lib/libz* usr/lib
cp -P $TARGET_DIR/usr/lib/libopcodes* usr/lib

The whole create root file system bash is as below,

echo "------Create rootfs --------"
rm -fr rootfs
rm initramfs.cpio
mkdir rootfs
pushd rootfs

echo "--------Create root,dev....----------"
mkdir root dev etc boot tmp usr var sys proc lib mnt home
mkdir etc/init.d etc/rc.d etc/sysconfig lib/modules
mkdir usr/sbin usr/bin usr/lib usr/modules
echo "---------Copy from busybox, rootfs-base, libs -----------"
cp -aP /home/iot/mini2440/busybox-1.19.4/_install/* .
ln -s bin/busybox init
ln -s /proc/mounts etc/mtab
cp -arP ../rootfs-base/* /home/iot/mini2440/rootfilesystem/rootfs/
cp /home/iot/mini2440/linux-3.8.7/System.map boot/

#Copy applications
cp /home/iot/mini2440/myapp/greeting usr/bin
cp /home/iot/mini2440/myapp/thread_demo* usr/bin

cp $TARGET_DIR/usr/bin/gdbserver usr/bin
cp $TARGET_DIR/usr/bin/op* usr/bin
cp $TARGET_DIR/usr/bin/ldd usr/bin
cp $TARGET_DIR/usr/bin/objcopy usr/bin
cp $TARGET_DIR/usr/bin/objdump usr/bin

cp /home/iot/mini2440/buildroot-2013.02/output/target/usr/bin/gdbserver usr/bin

cp /home/iot/mini2440/buildroot-2013.02/output/target/usr/bin/ldd usr/bin

cp -P /home/iot/mini2440/buildroot-2013.02/output/target/lib/* lib/

cp -P $TARGET_DIR/lib/* lib/
cp -P $TARGET_DIR/usr/lib/libpopt* usr/lib
cp -P $TARGET_DIR/usr/lib/libbfd* usr/lib
cp -P $TARGET_DIR/usr/lib/libintl* usr/lib
cp -P $TARGET_DIR/usr/lib/libstdc++* usr/lib
cp -P $TARGET_DIR/usr/lib/libz* usr/lib
cp -P $TARGET_DIR/usr/lib/libopcodes* usr/lib

chown -R root.root ../rootfs

echo "---------make node dev/console dev/null-----------------"
mknod -m 600 dev/console c 5 1
mknod -m 600 dev/null c 1 3
chmod 666 dev/console
chmod 666 dev/null
mknod /dev/ptmx c 5 2
mkdir mnt/etc mnt/yaffs mnt/data mnt/temp
mkdir var/lib var/lock var/run var/tmp
chmod 1777 tmp
chmod 1777 var/tmp

#Create cpio image
find . | cpio -H newc -o > ../initramfs.cpio

#Move out of working directory
popd

Run the shell script create_rootfs_bash.sh.

[root@localhost rootfilesystem]# pwd
/home/iot/mini2440/rootfilesystem
[root@localhost rootfilesystem]# ./create_rootfs_bash.sh
------Create rootfs --------
/home/iot/mini2440/rootfilesystem/rootfs /home/iot/mini2440/rootfilesystem
--------Create root,dev....----------
---------Copy from busybox, rootfs-base, libs -----------
---------make node dev/console dev/null-----------------
mknod: ‘/dev/ptmx’: File exists
14172 blocks
/home/iot/mini2440/rootfilesystem
[root@localhost rootfilesystem]#

The result is as below,

[root@localhost rootfilesystem]# ll -h
total 9.2M
-rwxr-xr-x.  1 root root 1.9K Dec 28 15:14 create_rootfs_bash.sh
-rw-r--r--.  1 root root 7.0M May 28 11:28 initramfs.cpio
-rwx------.  1 root root  16K Dec 28 14:19 mkyaffs2image-128M
drwxr-xr-x. 16 root root 4.0K May 28 11:28 rootfs
drwxr-xr-x.  3 root root 4.0K Dec 28 14:19 rootfs-base
-rw-------.  1 root root 2.0M Dec 28 14:19 rootfs.img
drwxr-xr-x.  7 root root 4.0K Dec 28 14:19 yaffs2-4e188b0
-rw-r--r--.  1 root root 285K Dec 28 14:19 yaffs2-4e188b0.tar.gz
[root@localhost rootfilesystem]#

Recompile the Kernel Image

Use make command,

[root@localhost linux-3.8.7]# pwd
/home/iot/mini2440/linux-3.8.7
[root@localhost linux-3.8.7]# make clean
  CLEAN   .
  CLEAN   arch/arm/kernel
  CLEAN   drivers/tty/vt
  CLEAN   drivers/video/logo
  CLEAN   kernel
  CLEAN   lib
  CLEAN   usr
  CLEAN   arch/arm/boot/compressed
  CLEAN   arch/arm/boot
  CLEAN   .tmp_versions
[root@localhost linux-3.8.7]# make

Created the new zImage file.

[root@localhost boot]# ll -h
total 17M
drwxrwxr-x. 2 root root 4.0K Apr 13  2013 bootp
drwxrwxr-x. 2 root root 4.0K May 28 11:36 compressed
drwxrwxr-x. 3 root root  12K Apr 13  2013 dts
-rwxr-xr-x. 1 root root  12M May 28 11:36 Image
-rw-rw-r--. 1 root root 1.3K Apr 13  2013 install.sh
-rw-rw-r--. 1 root root 3.1K Apr 13  2013 Makefile
-rwxr-xr-x. 1 root root 5.3M May 28 11:36 zImage
[root@localhost boot]#
[root@localhost boot]# pwd
/home/iot/mini2440/linux-3.8.7/arch/arm/boot

#check again,
[root@localhost linux-3.8.7]# ll ./arch/arm/boot/zImage
-rwxr-xr-x. 1 root root 5518192 May 28 11:36 ./arch/arm/boot/zImage
[root@localhost linux-3.8.7]# ll -h ./arch/arm/boot/zImage
-rwxr-xr-x. 1 root root 5.3M May 28 11:36 ./arch/arm/boot/zImage
[root@localhost linux-3.8.7]# pwd
/home/iot/mini2440/linux-3.8.7
[root@localhost linux-3.8.7]#

Download the kernel image to Embedded Linux S3C2440 board

The newly generated zImage is more than 5M, but the default setting in the bootloader, it only copy 5M bytes from kernel partition to RAM, so we need to change the setting, using command part add kernel 0x00060000 0x00600000 0, the first number in command is the starting address of kernel stored in the NAND flash. The second number in the command is the number of bytes the bootloader will copy from kernel partition to RAM, it must be greater than the size of the zImage.

The procedure is as below, use option q to enter vivi shell.

##### FriendlyARM BIOS 2.0 for 2440 #####
[x] format NAND FLASH for Linux
[v] Download vivi 
[k] Download linux kernel 
[y] Download root_yaffs image 
[a] Absolute User Application
[n] Download Nboot for WinCE 
[l] Download WinCE boot-logo
[w] Download WinCE NK.bin 
[d] Download & Run 
[z] Download zImage into RAM 
[g] Boot linux from RAM 
[f] Format the nand flash 
[b] Boot the system 
[s] Set the boot parameters 
[u] Backup NAND Flash to HOST through USB(upload) 
[r] Restore NAND Flash from HOST through USB 
[q] Goto shell of vivi 
[i] Version: 1026-2K
Enter your selection: q

Supervivi> part del kernel
deleted 'kernel' partition
Supervivi> part add kernel 0x00060000 0x00600000 0
kernel: offset = 0x00060000, size = 0x00600000, flag = 0
Supervivi> part show
Number of partitions: 4
name            :       offset          size            flag
------------------------------------------------------------
vivi            :       0x00000000      0x00040000      0
param           :       0x00040000      0x00020000      0
root            :       0x00660000      0x3fa80000      0
kernel          :       0x00060000      0x00600000      0
Supervivi> param show
Number of parameters: 9
name                    :          hex             integer
-------------------------------------------------------------
mach_type               :       000007cf                 1999
media_type              :       00000003                    3
boot_mem_base           :       30000000            805306368
baudrate                :       0001c200               115200
xmodem                  :       00000001                    1
xmodem_one_nak          :       00000000                    0
xmodem_initial_timeout  :       000493e0               300000
xmodem_timeout          :       000f4240              1000000
boot_delay              :       01000000             16777216
Linux command line: noinitrd init=/init console=ttySAC0,115200
Supervivi> param save
Found block size = 0x00020000
Erasing...    ... done
Writing...    ... done
Written 49152 bytes
Saved vivi private data
Supervivi> menu

##### FriendlyARM BIOS 2.0 for 2440 #####
[x] format NAND FLASH for Linux
[v] Download vivi 
[k] Download linux kernel 
[y] Download root_yaffs image 
[a] Absolute User Application
[n] Download Nboot for WinCE 
[l] Download WinCE boot-logo
[w] Download WinCE NK.bin 
[d] Download & Run 
[z] Download zImage into RAM 
[g] Boot linux from RAM 
[f] Format the nand flash 
[b] Boot the system 
[s] Set the boot parameters 
[u] Backup NAND Flash to HOST through USB(upload) 
[r] Restore NAND Flash from HOST through USB 
[q] Goto shell of vivi 
[i] Version: 1026-2K
Enter your selection: 

Download the zImage at the host side,

[root@localhost mini2440]# ./download_image.sh
csum = 0x62cc
send_file: addr = 0x33f80000, len = 0x00543370
[root@localhost mini2440]#

Download the zImage at Embedded Linux S3C2440 board side,

“`shell##### FriendlyARM BIOS 2.0 for 2440 #####
[x] format NAND FLASH for Linux
[v] Download vivi
[k] Download linux kernel
[y] Download root_yaffs image
[a] Absolute User Application
[n] Download Nboot for WinCE
[l] Download WinCE boot-logo
[w] Download WinCE NK.bin
[d] Download & Run
[z] Download zImage into RAM
[g] Boot linux from RAM
[f] Format the nand flash
[b] Boot the system
[s] Set the boot parameters
[u] Backup NAND Flash to HOST through USB(upload)
[r] Restore NAND Flash from HOST through USB
[q] Goto shell of vivi
[i] Version: 1026-2K
Enter your selection: k
USB host is connected. Waiting a download.

Now, Downloading [ADDRESS:30000000h,TOTAL:5518202]
RECEIVED FILE SIZE: 5518202 (19KB/S, 280S)
Downloaded file at 0x30000000, size = 5518192 bytes
Found block size = 0x00560000
Erasing… … done
Writing… … done
Written 5518192 bytes

FriendlyARM BIOS 2.0 for 2440

[x] format NAND FLASH for Linux
[v] Download vivi
[k] Download linux kernel
[y] Download root_yaffs image
[a] Absolute User Application
[n] Download Nboot for WinCE
[l] Download WinCE boot-logo
[w] Download WinCE NK.bin
[d] Download & Run
[z] Download zImage into RAM
[g] Boot linux from RAM
[f] Format the nand flash
[b] Boot the system
[s] Set the boot parameters
[u] Backup NAND Flash to HOST through USB(upload)
[r] Restore NAND Flash from HOST through USB
[q] Goto shell of vivi
[i] Version: 1026-2K
Enter your selection:


The booting message is as below, it includes below two lines, `oprofile: no performance counters` `oprofile: using timer interrupt.` ```shell ##### FriendlyARM BIOS 2.0 for 2440 ##### [x] format NAND FLASH for Linux [v] Download vivi [k] Download linux kernel [y] Download root_yaffs image [a] Absolute User Application [n] Download Nboot for WinCE [l] Download WinCE boot-logo [w] Download WinCE NK.bin [d] Download & Run [z] Download zImage into RAM [g] Boot linux from RAM [f] Format the nand flash [b] Boot the system [s] Set the boot parameters [u] Backup NAND Flash to HOST through USB(upload) [r] Restore NAND Flash from HOST through USB [q] Goto shell of vivi [i] Version: 1026-2K Enter your selection: b Copy linux kernel from 0x00060000 to 0x30008000, size = 0x00600000 ... done zImage magic = 0x016f2818 Setup linux parameters at 0x30000100 linux command line is: "noinitrd init=/init console=ttySAC0,115200" MACH_TYPE = 1999 NOW, Booting Linux...... Uncompressing Linux... done, booting the kernel. Booting Linux on physical CPU 0x0 Linux version 3.8.7-FriendlyARM (root@localhost.localdomain) (gcc version 4.7.2 (Buildroot 2013.02) ) #8 Tue May 28 11:36:17 SGT 2019 CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177 CPU: VIVT data cache, VIVT instruction cache Machine: MINI2440 ATAG_INITRD is deprecated; please update your bootloader. Memory policy: ECC disabled, Data cache writeback CPU S3C2440A (id 0x32440001) S3C24XX Clocks, Copyright 2004 Simtec Electronics S3C244X: core 405.000 MHz, memory 101.250 MHz, peripheral 50.625 MHz CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on Built 1 zonelists in Zone order, mobility grouping on. Total pages: 16256 Kernel command line: noinitrd init=/init console=ttySAC0,115200 PID hash table entries: 256 (order: -2, 1024 bytes) Dentry cache hash table entries: 8192 (order: 3, 32768 bytes) Inode-cache hash table entries: 4096 (order: 2, 16384 bytes) __ex_table already sorted, skipping sort Memory: 64MB = 64MB total Memory: 52708k/52708k available, 12828k reserved, 0K highmem Virtual kernel memory layout: vector : 0xffff0000 - 0xffff1000 ( 4 kB) fixmap : 0xfff00000 - 0xfffe0000 ( 896 kB) vmalloc : 0xc4800000 - 0xff000000 ( 936 MB) lowmem : 0xc0000000 - 0xc4000000 ( 64 MB) modules : 0xbf000000 - 0xc0000000 ( 16 MB) .text : 0xc0008000 - 0xc0462ee4 (4460 kB) .init : 0xc0463000 - 0xc0b7153c (7226 kB) .data : 0xc0b72000 - 0xc0baf028 ( 245 kB) .bss : 0xc0baf028 - 0xc0befba0 ( 259 kB) SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, Nodes=1 NR_IRQS:85 irq: clearing subpending status 00000003 irq: clearing subpending status 00000002 sched_clock: 32 bits at 200 Hz, resolution 5000000ns, wraps every 4294967291ms Console: colour dummy device 80x30 Calibrating delay loop... 201.52 BogoMIPS (lpj=503808) pid_max: default: 32768 minimum: 301 Mount-cache hash table entries: 512 CPU: Testing write buffer coherency: ok Setting up static identity map for 0x30334630 - 0x3033466c NET: Registered protocol family 16 DMA: preallocated 256 KiB pool for atomic coherent allocations MINI2440: Option string mini2440=0tb MINI2440: 't' ignored, touchscreen not compiled in MINI2440: LCD [0:240x320] 1:800x480 2:1024x768 3:320x240 S3C2440: Initialising architecture S3C2440: IRQ Support S3C244X: Clock Support, DVS off bio: create slab <bio-0> at 0 SCSI subsystem initialized usbcore: registered new interface driver usbfs usbcore: registered new interface driver hub usbcore: registered new device driver usb Linux video capture interface: v2.00 NET: Registered protocol family 2 TCP established hash table entries: 512 (order: 0, 4096 bytes) TCP bind hash table entries: 512 (order: -1, 2048 bytes) TCP: Hash tables configured (established 512 bind 512) TCP: reno registered UDP hash table entries: 256 (order: 0, 4096 bytes) UDP-Lite hash table entries: 256 (order: 0, 4096 bytes) NET: Registered protocol family 1 RPC: Registered named UNIX socket transport module. RPC: Registered udp transport module. RPC: Registered tcp transport module. RPC: Registered tcp NFSv4.1 backchannel transport module. NetWinder Floating Point Emulator V0.97 (double precision) NFS: Registering the id_resolver key type Key type id_resolver registered Key type id_legacy registered jffs2: version 2.2. (NAND) �© 2001-2006 Red Hat, Inc. msgmni has been set to 102 alg: No test for stdrng (krng) Block layer SCSI generic (bsg) driver version 0.4 loaded (major 253) io scheduler noop registered io scheduler deadline registered io scheduler cfq registered (default) Console: switching to colour frame buffer device 30x20 s3c2410-lcd s3c2410-lcd: fb0: s3c2410fb frame buffer device s3c2440-uart.0: ttySAC0 at MMIO 0x50000000 (irq = 70) is a S3C2440 console [ttySAC0] enabled s3c2440-uart.1: ttySAC1 at MMIO 0x50004000 (irq = 73) is a S3C2440 s3c2440-uart.2: ttySAC2 at MMIO 0x50008000 (irq = 76) is a S3C2440 brd: module loaded loop: module loaded Loading iSCSI transport class v2.0-870. s3c24xx-nand s3c2440-nand: Tacls=1, 9ns Twrph0=3 29ns, Twrph1=2 19ns s3c24xx-nand s3c2440-nand: NAND soft ECC NAND device: Manufacturer ID: 0xec, Chip ID: 0xda (Samsung NAND 256MiB 3,3V 8-bit), 256MiB, page size: 2048, OOB size: 64 Creating 4 MTD partitions on "nand": 0x000000000000-0x000000040000 : "u-boot" 0x000000040000-0x000000060000 : "u-boot-env" 000000060000-0x000000560000 : "kernel" 0x000000560000-0x000010000000 : "root" dm9000 Ethernet Driver, V1.31 dm9000_probe Set bwscon and bankcon4 dm9000 dm9000: read wrong id 0x01010101 dm9000 dm9000: eth%d: Invalid ethernet MAC address. Please set using ifconfig Now use the default MAC address: 08:90:90:90:90:90 eth0: dm9000e at c48bc300,c48be304 IRQ 51 MAC: 08:90:90:90:90:90 (chip) usbcore: registered new interface driver cdc_ether usbcore: registered new interface driver rndis_host ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver Initializing USB Mass Storage driver... usbcore: registered new interface driver usb-storage USB Mass Storage support registered. mousedev: PS/2 mouse device common for all mice s3c-rtc s3c2410-rtc: rtc disabled, re-enabling s3c-rtc s3c2410-rtc: rtc core: registered s3c as rtc0 s3c-rtc s3c2410-rtc: warning: invalid RTC value so initializing it oprofile: no performance counters oprofile: using timer interrupt. TCP: cubic registered Initializing XFRM netlink socket NET: Registered protocol family 17 Key type dns_resolver registered console [netcon0] enabled netconsole: network logging started s3c-rtc s3c2410-rtc: setting system clock to 2000-01-01 00:00:00 UTC (946684800) Freeing init memory: 7224K starting pid 450, tty '': '/etc/init.d/rcS' * Mounting /proc... * Mounting /dev... * Mounting /sys... * Mounting /dev/pts... * Mounting /dev/shm... * Starting system loggers... * Creating devices... * Configuring loopback interface... * Setting hostname... eth0 up dm9000 dm9000 eth0: link down starting pid 466, tty '': '/usr/sbin/telnetd -l /bin/login' starting pid 467, tty '': '-/bin/login' mini2440 login: dm9000 dm9000 eth0: link up, 100Mbps, full-duplex, lpa 0xC1E1 Login timed out after 60 seconds process '-/bin/login' (pid 467) exited. Scheduling for restart. starting pid 470, tty '': '-/bin/login' mini2440 login: root -sh: can't access tty; job control turned off [root@mini2440 /root]#

Yes, check carefully, you can find below message in the booting message,

oprofile: no performance counters
oprofile: using timer interrupt.

Test on Profiling

Login as root and OProfile applications are in the directory /usr/bin.
So we use legacy mode and clock/timer interrupt to collect samples.

[root@localhost ~]# telnet 192.168.0.11
Trying 192.168.0.11...
Connected to 192.168.0.11.
Escape character is '^]'.

mini2440 login: root
[root@mini2440 /root]# cd /usr/bin
[root@mini2440 bin]# operf
Your kernel's Performance Events Subsystem does not support your processor type.
Please use the opcontrol command instead of operf.
[root@mini2440 bin]#

Set up the OProfile, need to tell OProfile where the vmlinux file is corresponding to the running kernel. As we don’t profile the kernel itself, use below command to inform OProfile we don’t have vmlinux file.

[root@mini2440 bin]# opcontrol --no-vmlinux
[root@mini2440 bin]#

You can choose to create separate sample files by specifying one of the below options,

none No profile separation(default)
lib Create per-application profiles for libraries
kernel Create per-application profiles for the kernel and kernel modules
thread Create profiles for each thread and each task
cpu Create profile for each CPU
All All of the above options

We specify separate by thread.

[root@mini2440 bin]# opcontrol --separate=thread
[root@mini2440 bin]#

We start profiling, run an application and stop the daemon. Key in several commands in one line so they are executed one after another, it will avoid affecting the results by time of hitting the keyboard.

[root@mini2440 bin]# ls op* thread*
op-check-perfevents         operf                       opreport                    thread_demo_FIFO_max_min    thread_demo_RR_max_max.c
opannotate                  opgprof                     oprofiled                   thread_demo_FIFO_max_min.c  thread_demo_RR_max_min
oparchive                   ophelp                      thread_demo.c               thread_demo_FIFO_min_max    thread_demo_RR_max_min.c
opcontrol                   opimport                    thread_demo_FIFO_max_max    thread_demo_FIFO_min_max.c  thread_demo_RR_min_max
openvt                      opjitconv                   thread_demo_FIFO_max_max.c  thread_demo_RR_max_max      thread_demo_RR_min_max.c

Commands and the output,

[root@mini2440 bin]# opcontrol --start; ./thread_demo_RR_max_max;opcontrol --dump;opcontrol --shutdown
Using 2.6+ OProfile kernel interface.
Using log file /var/lib/oprofile/samples/oprofiled.log
Daemon started.
Profiler running.
min/max prio (1, 99)
count1 = 6680, count2 = 3321
Stopping profiling.
Killing daemon.
[root@mini2440 bin]#

Collect the results of the application.

[root@mini2440 bin]# opreport -l ./thread_demo_RR_max_max
Using /var/lib/oprofile/samples/ for samples directory.
CPU: CPU with timer interrupt, speed 301 MHz (estimated)
Profiling through timer interrupt
Processes with a thread ID of 597
Processes with a thread ID of 598
samples  %        samples  %        symbol name
282      100.000  0              0  thread_func1
0              0  140      100.000  thread_func2
[root@mini2440 bin]#

thread_func1 is only called in thread 597 and thread_func2 is only called in thread 598. So thread_func1 is not sampled in thread 598 and thread_func2 is not sampled in thread 597. main() function is not shown because the main thread is sequentially and short and not hit by the timer interrupt.

Collect the results for the whole system.

[root@mini2440 bin]# opreport --merge tgid
Using /var/lib/oprofile/samples/ for samples directory.
CPU: CPU with timer interrupt, speed 301 MHz (estimated)
Profiling through timer interrupt
          TIMER:0|
  samples|      %|
------------------
      422 53.5533 thread_demo_RR_max_max
      323 40.9898 no-vmlinux
       16  2.0305 busybox
       14  1.7766 libuClibc-0.9.32.1.so
       11  1.3959 ld-uClibc-0.9.32.1.so
        2  0.2538 oprofiled
[root@mini2440 bin]#

Output Annotated Source (Opannotate)

The opannotate utility generates annotated source files or assembly listings, optionally mixed with the source code. If include the source file, the profiled application needs to have debug information, that is to use -g option when compiling the application using GCC. If the binary doesn’t contain sufficient debug information, you can still use opannotate --assembly to get annotated assembly as long as the binary has symbol information.

We already used the -g option when we compiled the thread_demo* applications, so the applications already contains both debugging information and symbol information.

Use below command to annotate the source of our applications. -s/--source option means to output annotated source, it requires debugging information to be available in the binaries.

[root@mini2440 bin]# opannotate -s ./thread_demo_RR_max_max
Using /var/lib/oprofile/samples/ for session-dir
/*
 * Command line: opannotate -s ./thread_demo_RR_max_max
 *
 * Interpretation of command line:
 * Output annotated source file with samples
 * Output all files
 *
 * CPU: CPU with timer interrupt, speed 301 MHz (estimated)
 * Profiling through timer interrupt
 * Processes with a thread ID of 597
 * Processes with a thread ID of 598
 */
opannotate (warning): unable to open for reading: /home/iot/mini2440/myapp/thread_demo_RR_max_max.c
/*
 * Total samples for file : "/home/iot/mini2440/myapp/thread_demo_RR_max_max.c"
 *
 *    282 100.000   140 100.000
 */


 /* thread_func1 total:    282 100.000     0       0 */
 /* thread_func2 total:      0       0   140 100.000 */
[root@mini2440 bin]#

Above output returns opannotate (warning): unable to open for reading: /home/iot/mini2440/myapp/thread_demo_RR_max_max.c, it is because when we cross-compile the application on the host, the source file is in the directory /home/iot/mini2440/myapp. This path is contained in the debug information of the application. However on the target S3C2440 there is no such directoy and the source code is in /usr/bin. We need to use -b and -d options to tell opannotate where to find the source on the target.
Usage --base-dirs/-b [path], it is to point oprofile to a different location for source files when the debug information specifies an absolute path on your target system for the source which does not exist. The prefixed is stripped the debug source file paths, then searched int he search dirs specified by --search-dirs, used the option `–search-dirs/-d [path].

The new command and the output is as below opannotate -s ./thread_demo_RR_max_max -b /home/iot/mini2440/myapp -d /usr/bin, we didn’t use -a here to include the assembly annotations.

[root@mini2440 bin]# opannotate -s ./thread_demo_RR_max_max -b /home/iot/mini2440/myapp -d /usr/bin
Using /var/lib/oprofile/samples/ for session-dir
/*
 * Command line: opannotate -s ./thread_demo_RR_max_max -b /home/iot/mini2440/myapp -d /usr/bin
 *
 * Interpretation of command line:
 * Output annotated source file with samples
 * Output all files
 *
 * CPU: CPU with timer interrupt, speed 301 MHz (estimated)
 * Profiling through timer interrupt
 * Processes with a thread ID of 597
 * Processes with a thread ID of 598
 */
/*
 * Total samples for file : "/home/iot/mini2440/myapp/thread_demo_RR_max_max.c"
 *
 *    282 100.000   140 100.000
 */


                               :#include <stdio.h>
                               :#include <pthread.h>
                               :#include <stdlib.h>
                               :#include <errno.h>
                               :#include <assert.h>
                               :#include <sched.h>
                               :
                               :#define DEMO_POLICY   SCHED_RR   //SCHED_FIFO
                               :
                               :int count1 = 0;
                               :int count2 = 0;
                               :
                               :int times = 10000;
                               :
                               :void *thread_func1(void)
 /* thread_func1 total:    282 100.000     0       0 */
                               :
                               :        while(times > 0)
                               :        {
                               :                int i = 0;
                               :
   185 65.6028     0       0   :                for(i=0; i< 20000; i++)
    97 34.3972     0       0   :                        i++;
                               :
                               :                count1 ++;
                               :
                               :                times --;
                               :
                               :        }
                               :
                               :        return (void*) NULL;
                               :}
                               :
                               :void *thread_func2(void)
 /* thread_func2 total:      0       0   140 100.000 */
                               :
                               :        while(times > 0)
                               :        {
                               :                int i = 0;
                               :
     0       0   101 72.1429   :                for(i=0; i< 20000; i++)
     0       0    39 27.8571   :                i++;
                               :
                               :                count2 ++;
                               :
                               :                times --;
                               :
                               :        }
                               :
                               :        return (void*) NULL;
                               :}
                               :
                               :
                               :int main()
                               :{
                               :
                               :        int res;
                               :        pthread_t thread_1;
                               :        pthread_t thread_2;
                               :
                               :        pthread_attr_t thread_1_attr;
                               :        pthread_attr_t thread_2_attr;
                               :
                               :        int min_prio;
                               :        int max_prio;
                               :
                               :        struct sched_param param1;
                               :        struct sched_param param2;
                               :
                               :        struct timespec tp;
                               :
                               :        /* get max, min prop for policy FIFO/RR */
                               :        max_prio = sched_get_priority_max(DEMO_POLICY);
                               :        min_prio = sched_get_priority_min(DEMO_POLICY);
                               :
                               :        printf("min/max prio (%d, %d)\n", min_prio, max_prio);
                               :
                               :        res = pthread_attr_init(&thread_1_attr);
                               :        assert(res == 0);
                               :
                               :        res = pthread_attr_init(&thread_2_attr);
                               :        assert(res == 0);
                               :
                               :        /* Set sched policy */
                               :        res = pthread_attr_setinheritsched(&thread_1_attr, PTHREAD_EXPLICIT_SCHED);
                               :        assert(res == 0);
                               :
                               :        res = pthread_attr_setinheritsched(&thread_2_attr, PTHREAD_EXPLICIT_SCHED);
                               :        assert(res == 0);
                               :
                               :        res = pthread_attr_setschedpolicy(&thread_1_attr, DEMO_POLICY);
                               :        assert(res == 0);
                               :
                               :        res = pthread_attr_setschedpolicy(&thread_2_attr, DEMO_POLICY);
                               :        assert(res == 0);
                               :
                               :        /* Set thread priority */
                               :        param1.sched_priority = max_prio;  // min_prio
                               :        param2.sched_priority = max_prio;  // max_prio
                               :
                               :        res = pthread_attr_setschedparam(&thread_1_attr,&param1);
                               :        assert(res == 0);
                               :
                               :        res = pthread_attr_setschedparam(&thread_2_attr,&param2);
                               :        assert(res == 0);
                               :
                               :        /* Create threads */
                               :        res = pthread_create(&thread_1, &thread_1_attr, (void *)thread_func1, NULL);
                               :        assert(res == 0);
                               :
                               :        res = pthread_create(&thread_2, &thread_2_attr, (void *)thread_func2, NULL);
                               :        assert(res == 0);
                               :
                               :        pthread_join(thread_1, NULL);
                               :        pthread_join(thread_2, NULL);
                               :
                               :        printf("count1 = %d, count2 = %d\n", count1, count2);
                               :
                               :        exit(0);
                               :
                               :
                               :}
                               :
[root@mini2440 bin]#

Reference

Embedded Linux S3C2440 environment setup
Embedded Linux S3C2440 Environment Startup
Embedded Linux S3C2440 Build and Boot an Image
Embedded Linux S3C2440 Application Development and Debugging
Embedded Linux S3C2440 Networking
Embedded Linux S3C2440 – Kernel Module
Embedded Linux S3C2440 – Kernel Debugging
Embedded Linux S3C2440 – Multi-thread Scheduling

Write a Comment

Comment