Monday, March 26, 2018

Installing older version of GCC in Debian

I was compiling caffe today, and found that CUDA requires GCC version of <= 5. I have no other options but to install a older version of GCC on my Debian rig.

However, directly apt-get in result the following error:

Package gcc-4.9 is not available, but is referred to by another package.
This may mean that the package is missing, has been obsoleted, or is only available from another source

E: Package 'gcc-4.9' has no installation candidate


To install older GCC (in this case GCC-4.9) on my Debian 9, I need to do add the ubuntu-toolchain test repository:
sudo vi /etc/apt/sources.list
Add the following lines:
deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main
deb-src http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu xenial main
Note that I used xenial because gcc-4.9 is available on xenial:
https://launchpad.net/~ubuntu-toolchain-r/+archive/ubuntu/test
Notice that gcc-4.9 is only available on 16.04, 14.04.1, and 12.04, I have chosen the latest one (16.04), which is xenial:


Now, I can install gcc-4.9 successfully:

sudo apt-get install gcc-4.9
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer required:
  libxnvctrl0 nvidia-settings
Use 'sudo apt autoremove' to remove them.
Suggested packages:
  gcc-4.9-multilib gcc-4.9-doc gcc-4.9-locales libgcc1-dbg libgomp1-dbg libitm1-dbg libatomic1-dbg libasan1-dbg
  liblsan0-dbg libtsan0-dbg libubsan0-dbg libcilkrts5-dbg libquadmath0-dbg
The following NEW packages will be installed:
  gcc-4.9
0 upgraded, 1 newly installed, 0 to remove and 218 not upgraded.
Need to get 0 B/5,684 kB of archives.
After this operation, 18.4 MB of additional disk space will be used.
Selecting previously unselected package gcc-4.9.
(Reading database ... 235901 files and directories currently installed.)
Preparing to unpack .../gcc-4.9_4.9.4-2ubuntu1~16.04_amd64.deb ...
Unpacking gcc-4.9 (4.9.4-2ubuntu1~16.04) ...
Setting up gcc-4.9 (4.9.4-2ubuntu1~16.04) ...
Processing triggers for man-db (2.7.6.1-2) ...
gcc-4.9 --version
gcc-4.9 (Ubuntu 4.9.4-2ubuntu1~16.04) 4.9.4
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

Thursday, February 15, 2018

TL-WR703N Flash OpenWrt over U-Boot

Here is the U-Boot commands to flash the OpenWrt firmware over U-Boot.
  1. Obtain IP:
    dhcp
    
  2. Note down the IP of the WR703N (i.e. 192.168.0.59), and the TFTP server (i.e. 192.168.0.134), press CTRL+C, then:
    setenv ipaddr 192.168.0.59
    setenv serverip 192.168.0.134
    
  3. Write the OpenWrt image to RAM address 0x80800000:
    tftpboot 0x80800000 wrt.bin
    
  4. Erase the FLASH from block 0x9F020000, for 0x3C0000 bytes in size, this is the size of the OpenWrt image:
    Note that 0x9F000000 is the start of FLASH, there are 64KiB U-Boot code + 64 KiB Data, so the OpenWrt image starts at 0x9F020000.
    erase 0x9F020000 +0x3C0000
    
  5. Finally, we copy back the downloaded image from RAM back to the flash:
    cp.b 0x80800000 0x9F020000 0x3C0000
    

Thursday, January 18, 2018

Rebuild Banana/Raspberry Pi OS after SD Card Corruption

My Banana Pi M1+ just suffered SD Card corruption, the OS simply won't boot. I have to plug the SD card to a Linux machine and run fsck:

fsck -f -y /dev/sda2
Funny thing is, it appears to be fixed at the first run, but after I run fsck again, more errors are popping up for fixing.
I have to run fsck few times until no more new errors come up.

Then, I booted up the system, after running it awhile, I saw kernel error messages firing everywhere, saying some issues about kernel modules and man (man pages) binary.
I am now quite sure that there is a SD card corruption which corrupted some system files. Mounting the SD card on a Linux machine again, I copied the whole /lib folder from the original image to my SD card OS partition, which hope fixes the kernel module issues.
Then, I mounted the FAT boot partition, and copied the original kernel and initrd to the SD card.
After booting to the OS, I immediately try to rebuild the system by reinstalling "base" packages:

First batch:
sudo apt-get install --reinstall adduser base-files base-passwd bash bsdutils coreutils dash debconf debianutils diffutils dpkg e2fslibs e2fsprogs findutils gcc-6-base grep gzip hostname init init-system-helpers initscripts insserv libacl1 libapparmor1 libattr1 libaudit-common libaudit1 libblkid1 libbz2-1.0 libc-bin libc6 libcap2 libcap2-bin libcomerr2 libcryptsetup4 libdb5.3 libdebconfclient0 libdevmapper1.02.1 libfdisk1 libgcc1 libgcrypt20 libgpg-error0 libkmod2 liblzma5 libmount1 libncurses5 libncursesw5 libpam-modules libpam-modules-bin libpam-runtime libpam0g libpcre3 libprocps4 libseccomp2 libselinux1 libsemanage-common libsemanage1 libsepol1 libsmartcols1 libss2 libsystemd0 libtinfo5 libudev1 libustr-1.0-1 libuuid1 locales login lsb-base makedev mawk mount multiarch-support ncurses-base ncurses-bin passwd perl-base procps sed sensible-utils systemd systemd-sysv sysv-rc sysvinit-utils tar tzdata util-linux
Second batch:
sudo apt-get install --reinstall apt apt-utils busybox-initramfs bzip2 console-setup console-setup-linux cpio cron debconf-i18n dh-python distro-info-data eject file gcc-5-base gnupg gpgv ifupdown initramfs-tools initramfs-tools-bin initramfs-tools-core iproute2 iputils-ping isc-dhcp-client isc-dhcp-common kbd keyboard-configuration klibc-utils kmod less libapt-inst2.0 libapt-pkg5.0 libatm1 libbsd0 libdns-export162 libestr0 libexpat1 libffi6 libfribidi0 libgmp10 libgnutls-openssl27 libgnutls30 libhogweed4 libidn11 libisc-export160 libjson-c2 libklibc liblocale-gettext-perl liblz4-1 libmagic1 libmnl0 libmpdec2 libnettle6 libnewt0.52 libnih1 libp11-kit0 libpcre3 libpng12-0 libpopt0 libpython3-stdlib libpython3.5-minimal libpython3.5-stdlib libreadline6 libslang2 libsqlite3-0 libssl1.0.0 libssl1.0.2 libstdc++6 libtasn1-6 libtext-charwidth-perl libtext-iconv-perl libtext-wrapi18n-perl libusb-0.1-4 libxtables11 linux-base locales logrotate lsb-release mime-support net-tools netbase netcat-openbsd python3 python3-minimal python3.5 python3.5-minimal readline-common resolvconf rsyslog sudo ubuntu-keyring ubuntu-minimal ucf udev ureadahead vim-common vim-tiny
Fixing manpage issues:
sudo rm -rf /var/cache/man/*
sudo apt-get install --reinstall man-db manpages

It seems the system is running great now.

Wednesday, January 17, 2018

ESP32 SSH Server

I was always wondering whether it is possible to start a SSH server on my little ESP32 board, and I don't want to implement the SSH protocol by myself.

There are several lightweight SSH library out there, however, most of them require POSIX support, which is quite messy to port them to the ESP32.

Upon more research, I found that WolfSSH does not require much POSIX stuff, so I decided to port that to ESP32.

WolfSSH: https://github.com/hopkinskong/wolfssh-esp32
WolfSSL: https://github.com/hopkinskong/wolfssl-esp32

Now, I did not use ESP32 Hardware Crypto Acceleration, only the HW RNG is used for the crypto functions. Also, using PuTTY will unable to connect to the server due to some invalid crypto keys presented to the server.

Proof of concept of SSH<->UART1:
https://github.com/hopkinskong/esp32-ssh-server
Images:
Connection to the ESP32 SSH Server, prompting login:

Logged in, shows my Banana Pi U-Boot command prompt as I have connected the ESP32 UART1 to my Banana Pi Serial Console:

Shows it is my Banana Pi's U-Boot:
Booting Linux, I can now remotely serial debug my Banana Pi:
Note that when using PuTTY, the server will actively close the connection due to some key issues:

Sunday, August 6, 2017

Headphone loudness calculator with DIY PCM1794A DAC

These few months I was playing with my DIY PCM1794A DAC. I was using the output schematic specified in the datasheet PG. 25:


After hooking up the circuit to my headphone (ATH-CKS1000), I was found the sound level was incredibly loud (not enough to damage my hearing/headphone though..), with some calculations, I found out the reason:


  1. Note that the output is 2Vrms, U1/U2 is formed as an active I/V, converting IOUT-, IOUT+ to voltage. 
  2. At -FS, IOUT- gives out -2.3mA, IOUT+ gives out -10.1mA; At +FS, IOUT- gives out -10.1mA, IOUT+ gives out -2.3mA
  3. So for example, at -FS, U1 will gives out 750Ohm*(-2.3mA)=-1.725V, and U2 will gives out 750Ohm*(-10.1mA)=-7.575V
  4. You can refer to the following table for more details:
  5. U3 is configured as a differential amplifier, using -FS as an example again, U1 output -1.725V; U2 output -7.575V; Output of U3 = (270R/560R)*((-7.575V)-(-1.725V))-2.82V, formula:
  6. You can also confirm the findings from the above table.
  7. Output is ±2.821V, which is 1.995Vrms 
  8. Notice there is R7 (100Ohm) at the output, for my 16Ohm headphone connected in series with it, the output stage turns into a voltage divider network:
  9. So my headphone will receive MAX 2.821V * (16/(16+100))  0.3891V
  10. Power delivered to my headphone: 0.3891^2/16=9.462mW, which is less than the maximum input power 100mW. But don't get fooled by this! 9.462mW is already REALLY LOUD, you do not need the full 100mW!!
  11. The sensitivity of my headphone is 106dB/mW, so for 9.462mW, the actual output loudness is: 106+10*log(9.462)≈115.76dB SPL
  12. Taking the dB SPL chart from here, you can discover that 116dB SPL is already quite loud:

I have also made a small calculator here, you can try out different values:
Audio System Output
Vrms out
Series resistor (R7)/Total output impedance
Headphone
Impedance
Sensitivity (dB/mW)

Thursday, March 9, 2017

Linux on Cherry Trail Z8350/Z8300 SoC

I am currently playing with my new iWork1X tablet with Linux.

iWork1X Specification:

CPU: Intel Cherry Trail Z8350
RAM: 4GB
eMMC: SanDisk DF4064 64GB (Recognized as 58.2GiB)
WiFi/BT: RTL8723BS
Touchscreen: SiLead GSL3692, 10 points

Kernel under development: https://github.com/hopkinskong/linux_cherrytrail


Wednesday, January 25, 2017

Installing Linux (Ubuntu) on existing Windows NTFS partition

I need to install Ubuntu 16.04.1 on the computer, it should work on newer versions of Ubuntu too. But I am only allowed to write everything on an existing NTFS partition (i.e. The Windows Partition). I am not allowed to re-partition the NTFS partition, I am also not allowed to modify the partition table of the hard disk in any way, and even, I am not allowed to modify the MBR.

Seems Impossible? No.
I can write and modify any data in the NTFS partition, and this is more than enough.

The following serves a log for me, you can try this out if you want. It basically creates a RAW image file on the NTFS partition, and formatted it as EXT4. We then fire up the Ubuntu Live CD and mount the image as loopback file system, and hence, install Ubuntu on it. About the bootloader part, I used Grub2Win to add an entry for GRUB in the Windows 7 bootmgr BCD record. Grub2Win should work on EFI partitions too (Tested by the author of Grub2Win, it works.). After successfully booted into GRUB, it is just the matter of accessing the kernel and initrd on the image file, and pass the correct cmdline into the kernel.

Image Creation
  1. Boot up the Ubuntu Live CD, or use existing linux machine to do this.
    Please transfer the image back to the NTFS partition if you are using another linux machine.
  2. Mount the NTFS partition. Simply clicking the partition on the file manger would have mounted the partition.
  3. Create an ext4 image file on <ntfs_partition>/linux/linux.img:
    cd /media/ubuntu/<your_ntfs_partition>/
    mkdir linux
    cd linux/
    dd if=/dev/zero of=./linux.img bs=1M count=32768 # This will create a 32GB Image for the Ubuntu system
    mkfs.ext4 ./linux.img
    

Installing Ubuntu on the image
  1. We need to trick the Ubuntu installer our image file is a real partition.
    I have created a virtual block device on /dev/sdb (You should adjust this accordingly), and mounting our image onto it:
    sudo mknod /dev/sdb b 7 200 # Make sure you have picked up a device name that is not in use (i.e. I only got sda, so i used sdb)
    # Also pick a minor number (200 used in here) that is not in use by checking "ls -la /dev" for existing loopback device(s).
    # Now do losetup
    sudo losetup /dev/sdb ./linux.img
    
  2. Now execute the Ubuntu installer, and install Ubuntu on /dev/sdb. You may prompted with this:
  3. Make sure you have clicked No, as our image file is mounted and reside on /dev/sda, unmounting /dev/sda will unmount our image file.
  4. Press "Something else":
  5. Select /dev/sdb and press Change...
  6. Select Ext4, and modify the mount point to /:
  7. You should then have the following configurations:
  8. I am not creating any swap space, but you can do so by creating one more swap image with mkswap and mount it with the method mentioned above. Press Continue here.
  9. We have already formatted it before with mkfs.ext4 above, so there is nothing in that partition. Press Continue here.
  10. Again, we have already formatted it before with mkfs.ext4 above, there is no files in the partition which would interfere the installation. Press Continue here.
  11. Configure timezone, keyboard layout, name, computer name, account, etc. as usual.
  12. Installing the system:
  13. At the end of the installation, there is an error about GRUB installation. Just select Continue without a bootloader. as we will install our own bootloader (Grub2Win) later.
  14. Do not restart yet, press Continue Testing
  15. We need to get the file names of the kernel and initrd. Mount the image and list the files under /boot:
    sudo mkdir /media/ubuntu/rfs
    sudo mount -o loop /dev/sdb /media/ubuntu/rfs
    ls -al /media/ubuntu/rfs/boot
    
  16. Mark down the file names for the kernel and initial ramdisk. In my case, it's vmlinuz-4.4.0-31-generic for the kernel and initrd.img-4.4.0-31-generic for the initrd.

Installing and configuring the bootloader
  1. Download and install Grub2Win
  2. Launch Grub2Win, press Manage Boot Menu
  3. Press Add A New Entry
  4. Select ubuntu as OS Type and fill up the Title
  5. Select I Will Enter My Own Custom Configuration Code
  6. Press Edit Custom Code
  7. A notepad will then popped up. Enter the following contents into the notepad.
    Please modify the disk and partition number hd0, msdos1, and the kernel and initrd file name according to your system setup and the file names you marked down in the previous step.
    You should also modify the root parameter passed to the cmdline to the linux block device path of your NTFS partition.
        echo **********************************
        echo * Ubuntu IMG boot by HopkinsKong *
        echo **********************************
    
        echo Booting linux...
    
        set gfxpayload=1024x768
        loopback loop0 (hd0,1)/linux/linux.img
        set root=(loop0)
        linux /boot/vmlinuz-4.4.0-31-generic root=/dev/sda1 loop=/linux/linux.img rw verbose nosplash
        initrd /boot/initrd.img-4.4.0-31-generic
    
    
  8. After saving and closing the notepad, you should get the following in the Grub2Win screen. Press the Apply button and the OK button to apply our new boot configuration.
  9. I prefer my Ubuntu boot entry have a higher order in the menu. So I pressed the up arrow button until my boot entry is at the top.
  10. The final boot menu would look something like this. Press Apply to save it and return to the main screen.
  11. At the main screen, press OK to save all the changes to the disk.

That's it! After rebooting the machine, there is a new boot entry to boot into Grub2Win besides Windows. And we can boot into Ubuntu with it.

Please note that you may need to update your boot configurations (i.e Update the file names for the kernel and initrd) after a kernel upgrade.

UPDATE: Thanks for the suggestions from the author of Grub2Win, the Grub boot script is now modified to fix some possibile issue on some graphic cards.