How to replace the Kernel image in NOOBS with your custom Kernel

In one of the previous posts I have described Bringing up Rasberry Pi 3 with NOOBS. But after I brought up the Raspberry Pi (ver 3 B) with NOOBS I started having some difficultly with the NOOBS kernel version. Some of the Linux drivers I was working with works only with particular version of Linux Kernel and hence it became necessary for me to figure out how to replace the NOOBS kernel image with my own built shiny cross compiled image, so that I have the flexibility of using any version of Kernel I want. I think it could of use for you as well and hence writing the steps up here so that I can refer it later and also maybe someone out there finds it helpful. The original instructions are based out here. The rest of the post is based on Raspberry Pi version 3 B which is what I am working on right now. So the instructions are valid and tested for version 3. It may vary in other Pi hardware version, but the basic steps would remain by and large same.

Bring up Pi with NOOBS

Follow this link to first bring up your Raspberry Pi with NOOBS as described here.

Cross Compile the Kernel

Required utilities

Install the below software in your linux distribution. I am using Ubuntu hence the command to install the dependency software are as below.

$ sudo apt install git bc bison flex libssl-dev make
$ sudo apt install git bc bison flex libssl-dev make libc6-dev libncurses5-dev

Get Linux Source

git clone --depth=1 https://github.com/raspberrypi/linux

Get the toolchain

git clone https://github.com/raspberrypi/tools ~/tools

Set the tool PATH

$ echo PATH=\$PATH:~/tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin >> ~/.bashrc
$ source ~/.bashrc

Cross compile the kernel

cd linux/
KERNEL=kernel7

Generate the .config file

$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- bcm2709_defconfig

Compile

make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- zImage modules dtbs -j 12

Prepare the SD Card from Pi

Now, you will need the SD card where you have installed NOOBS. One of the mistakes I was doing is thinking installing NOOBS means copying the extracted NOOBS files into the SD card. It is stupid I know, but instructions may not be always very clear (or your head may not be working at all on a day). So make sure you actually have followed all the steps described here. What it will ensure is that the NOOBS actually creates all the partitions required in the SD card and then copy the right files into the right partitions. Once that is done the installation is complete. This is done by NOOBS right after you do the following steps as described in the above link:

  1. Copy the extracted NOOBS files into the sd card
  2. Inserted the SD card into the Rasberry Pi (I am using version 3 B).
  3. Powered up the Pi and be patient when NOOBS does the neccessary things for your to install the Rasbian.

Generally if you have followed all the steps described in the post Bringing up Rasberry Pi 3 with NOOBS then all you need to do is to eject the SD card from the Pi and insert it into you local linux machine (where you are doing the cross compilation).

Locate the SD card in Host

Once you have attached the SD card to you local PC (picture below in case of any confusion), go to the console (I am using a Ubuntu PC).

I use the above card reader, choose you own, it doesn’t matter but essentially, you would probably need a card reader. Now, in you console issue the below command to find out where your SD card has gone:

lsblk
sda 8:0 0 465.8G 0 disk
├─sda1 8:1 0 512M 0 part /boot/efi
└─sda2 8:2 0 465.3G 0 part /
sdc 8:32 1 29.7G 0 disk
├─sdc1 8:33 1 2.4G 0 part
├─sdc2 8:34 1 1K 0 part
├─sdc5 8:37 1 32M 0 part /media/vbhadra/SETTINGS
├─sdc6 8:38 1 256M 0 part /media/vbhadra/boot1
└─sdc7 8:39 1 27G 0 part /media/vbhadra/root
sr0 11:0 1 1024M 0 rom

It looks like as above (just the interesting bits copy pasted) after issuing lsblk command on my Ubuntu console.

Now, sda is your hard drive. So leave that alone. The rest is sdc which is the SD card media in this case. Under sdc you will see the 5 partitions that NOOBS has created for us. The most important partitions for us are sdc6 and sdc7. SDC6 is FAT partition called boot and SDC7 is an ext4 type partitions called root.

Mount SD card partitions on Host Linux

We need to install the newly built kernel modules to the SD card partitions. Also, we need to copy paste other stuffs to the SD card partitions. So for that purpose we are up to mounting these partitions sdc6 and sdc7 into suitable folders on the host PC (Ubuntu in my case). To do that follow the below steps on the host PC console:

~/temp/linux$ mkdir mnt
~/temp/linux$ mkdir mnt/fat32
~/temp/linux$ mkdir mnt/ext4
~/temp/linux$ sudo mount /dev/sdb6 mnt/fat32
~/temp/linux$ sudo mount /dev/sdc6 mnt/fat32
~/temp/linux$ sudo mount /dev/sdc7 mnt/ext4 

~/temp/linux$ ls mnt/
ext4/  fat32/ 

~/temp/linux$ ls mnt/fat32/
bcm2708-rpi-b.dtb       bcm2710-rpi-2-b.dtb       bcm2835-rpi-a-plus.dtb   bcm2835-rpi-zero-w.dtb    config.txt     fixup_cd.dat        kernel7.img       overlays      start_db.elf
bcm2708-rpi-b-plus.dtb  bcm2710-rpi-3-b.dtb       bcm2835-rpi-b.dtb        bcm2836-rpi-2-b.dtb       COPYING.linux  fixup.dat           kernel7l.img      start4cd.elf  start.elf
bcm2708-rpi-cm.dtb      bcm2710-rpi-3-b-plus.dtb  bcm2835-rpi-b-plus.dtb   bcm2837-rpi-3-b.dtb       fixup4cd.dat   fixup_db.dat        kernel8.img       start4db.elf  start_x.elf
bcm2708-rpi-zero.dtb    bcm2710-rpi-cm3.dtb       bcm2835-rpi-b-rev2.dtb   bcm2837-rpi-3-b-plus.dtb  fixup4.dat     fixup_x.dat         kernel.img        start4.elf
bcm2708-rpi-zero-w.dtb  bcm2711-rpi-4-b.dtb       bcm2835-rpi-cm1-io1.dtb  bootcode.bin              fixup4db.dat   issue.txt           LICENCE.broadcom  start4x.elf
bcm2709-rpi-2-b.dtb     bcm2835-rpi-a.dtb         bcm2835-rpi-zero.dtb     cmdline.txt               fixup4x.dat    kernel7-backup.img  os_config.json    start_cd.elf

~/temp/linux$ ls mnt/ext4/
bin  boot  dev  etc  home  lib  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
~/temp/linux$ mount 
/dev/sdc6 on /media/vbhadra/boot1 type vfat (rw,nosuid,nodev,relatime,uid=1000,gid=1000,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,showexec,utf8,flush,errors=remount-ro,uhelper=udisks2)
/dev/sdc7 on /media/vbhadra/root type ext4 (rw,nosuid,nodev,relatime,uhelper=udisks2)

Install the newly build module into SD card

~/temp/linux$ sudo env PATH=$PATH make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- INSTALL_MOD_PATH=mnt/ext4 modules_install

Copy the rest of the files into SD card

Copy the Kernel Image

~/temp/linux$ sudo cp mnt/fat32/$KERNEL.img mnt/fat32/$KERNEL-backup.img
~/temp/linux$ sudo cp arch/arm/boot/zImage mnt/fat32/$KERNEL.img

Copy the dtb file

~/temp/linux$ sudo cp arch/arm/boot/dts/*.dtb mnt/fat32/
~/temp/linux$ sudo cp arch/arm/boot/dts/overlays/*.dtb* mnt/fat32/overlays/
~/temp/linux$ sudo cp arch/arm/boot/dts/overlays/README mnt/fat32/overlays/

Umount the sd card partitions

~/temp/linux$ sudo umount mnt/fat32
~/temp/linux$ sudo umount mnt/ext4

Boot the Pi with the SD card

Take the SD card and insert it into the Pi back again. Then power up the Pi. The rest should be taken care by NOOBS. So wait and watch. You shouldn’t see any errors at all. In case of any error, please post it in the below comments section so that I can have a look. Once the Pi comes up open a console and check if your Pi is actually running your newly built kernel image. See the below section for that.

Verify the kernel version on Pi

pi@raspberrypi:~ $ uname -a 
Linux raspberrypi 4.19.106-v7+ #1 SMP Tue Mar 3 12:57:47 GMT 2020 armv7l GNU/Linux

As you might have already noticed the new kernel version is 4.19.106-v7+. Th earlier on my Pi was 4.19.75-v7+. Also, notice the time stamp. As it shows the time stamp in my Pi is showing today’s date and time, Tue Mar 3 12:57:47 GMT 2020, another proof that it is my cross built kernel which is running in Pi not the original NOOBS kernel which came with the NOOBS distribution.

All done, have fun!

Integrating LTE Device EM7565 into Raspberry Pi 3

Bring up Raspberry Pi

To bring up your Raspberry Pi (my Pi is version 3 B) please follow the below link:

How to bring up Pi using NOOS

Download Siera Wireless Linux drivers

I am going to integrate the EM7565 LTE device into my Raspberry Pi ver 3 B. So I would next like to download the Linux for the device. The recommended drivers are available from SieraWireless website. You might need to create a account with them. Check with your vendor dor the details of the account and then check where to find the driver links etc. In my case the driver archives were located here.

Cross Compile the Linux drivers

After you have successfully downloaded the linux drivers in the previous step, you should have a SierraLinuxQMIdriversS2.35N2.54.tar.bz2 file in your Download folder. In my case it is located at the default Download folder called ~/Download/SierraLinuxQMIdriversS2.35N2.54.tar.bz2. Extract this file with the below command:

Now, do a ls to see what you have got after extracting the driver archive.

$ ls -la 
total 128
drwxr-xr-x  4 vbhadra vbhadra  4096 Nov 21 05:58 .
drwxr-xr-x 29 vbhadra vbhadra 28672 Feb 26 14:37 ..
drwxr-xr-x  2 vbhadra vbhadra  4096 Nov 21 05:59 GobiNet
drwxr-xr-x  2 vbhadra vbhadra  4096 Nov 21 05:59 GobiSerial

So in my case two folder have been created GobiNet and GobiSerial. GobiNet would emulate the device as a serial (actually it emulates as 3 usb serial device, ttyUBB0, ttyUSB1, ttyUSB2) and GobiNet handles the data packets like a linux network driver. What you need to do is to cross compile these two drivers and then take the .ko files for both the driver to the Rasp Pi and dynamically insert those into the running kernel inside the Pi.

For cross compiling the drivers you may follow the instructions in the below:

How to cross compile Gobi drivers.

Transfer the Driver .ko files to Raspberry Pi

Attach the SD card to your Linux PC. Copy the .ko driver images into the sd card and then un-mount it as below:

vbhadra@vbhadra-8200-elit-convertable-microtower:~/rpi/GobiNet$ mount
...
...
/dev/sdb1 on /media/vbhadra/7EFE-4409 type vfat (rw,nosuid,nodev,relatime,uid=1000,gid=1000,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,showexec,utf8,flush,errors=remount-ro,uhelper=udisks2)

~/rpi/GobiNet$ cp GobiNet.ko /media/vbhadra/7EFE-4409/.
~/rpi/GobiSerial$ cp GobiSerial.ko /media/vbhadra/7EFE-4409/.
~/rpi/GobiNet$ umount /media/vbhadra/7EFE-4409

Now, take out the SD card from your local Linux PC and attach it to the Pi. Once attached Pi should detect it automatically. It is by default mounted under:

/media/pi/<sd card label>

I usually mount it in a more easier location. Like in the below commands I am mounting it in my home directory under a folder named usb:

pi@raspberrypi:~ $ mkdir usb
pi@raspberrypi:~ $ mount -t vfat /dev/sda1 usb/
pi@raspberrypi:~ $ ls usb/
 20-02-2020   detect_practice2.nnb   GobiNet_pi_build.ko   log_02142020_01.txt             log.txt            Makefile_GobiSerial   Pi              'System Volume Information'
 2.ppm        GobiNet.ko             GobiSerial.ko         log_02142020_over_weekend.txt   Makefile_GobiNet   myobject              scratchpad.txt

In the above case the SD card has been mounted by Pi kernel under /dev/sda and /dev/sda1 is the partition which I am mounting. It could be mounted by kernel under /dev/sdb, /dev/sdc… etc as well. If you are not sure, you can check with dmesg command.

Now, for EM7565 device and Gobi* drivers it is recommended that you disable two linux’s default drivers: qcserial and qmi_wwan, as these may interfere in the operation of the Gobi* drivers. To do that you have add the below two lines in the following file:

pi@raspberrypi:~ $ sudo touch /etc/modprobe.d/blacklist-modem.conf
pi@raspberrypi:~ $ sudo vim.tiny /etc/modprobe.d/blacklist-modem.conf
blacklist qcserial
blacklist qmi_wwan

Now, do a reboot of the Rasberry Pi system.

pi@raspberrypi:~ $ sudo shutdown -r now

Once it come back do the following:

pi@raspberrypi:~ $ export OUTPUTDIR=/lib/modules/`uname -r`/kernel/drivers/net/usb/
pi@raspberrypi:~ $ cp ~/usb/GobiNet.ko $OUTPUTDIR 
pi@raspberrypi:~ $ sudo cp ~/usb/GobiSerial.ko $OUTPUTDIR
pi@raspberrypi:~ $ sudo depmod
pi@raspberrypi:~ $ modprobe GobiSerial 
pi@raspberrypi:~ $ sudo modprobe GobiNet 
pi@raspberrypi:~ $ dmesg | grep -i "Gobi*"
[  318.763626] GobiSerial: loading out-of-tree module taints kernel.
[  318.764822] usbcore: registered new interface driver GobiSerial
[  318.764895] usbserial: USB Serial support registered for GobiSerial
[  318.764920] GobiSerial: 2019-11-22/SWI_2.39:GobiSerial
[  593.404829] GobiNet: 2019-11-22/SWI_2.60
[  593.405285] usbcore: registered new interface driver GobiNet

As you can see the Gobi* drivers have now been insmod-ed into the Pi linux kernel.

You can check the dmesg logs to confirm yours. Last few lines of your log file should look like the above.

Now, check if there has been any emulated ttyUSB nodes created with the below command:

pi@raspberrypi:~ $ dmesg | grep -i "ttyUSB*"
pi@raspberrypi:~ $ 

As you can see in my case there is still no ttyUSB* device node created.

The GobiSerial driver will create 3 ttyUSB* nodes as soon as you attach the device into the USB port. If it doesn’t, something is not quite right.

Attach the EM7565 LTE device to the USB port of the RaspPi

Now, attach your LTE EM7565 device to the Raspberry Pi USB port. It looks like the below in my setup:

Once you attach the device to the USB port, go back to your Pi console and type the below command and notice the outputs, it should look something like the below as I can see in my console:

pi@raspberrypi:~ $ dmesg
[64326.392221] Under-voltage detected! (0x00050005)
[64332.632157] Voltage normalised (0x00000000)
[64336.052097] usb 1-1.2: new high-speed USB device number 10 using dwc_otg
[64336.182652] usb 1-1.2: config 1 has an invalid interface number: 8 but max is 3
[64336.182670] usb 1-1.2: config 1 has no interface number 1
[64336.183359] usb 1-1.2: New USB device found, idVendor=1199, idProduct=9091, bcdDevice= 0.06
[64336.183371] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[64336.183381] usb 1-1.2: Product: Sierra Wireless EM7565 Qualcomm® Snapdragon™ X16 LTE-A
[64336.183391] usb 1-1.2: Manufacturer: Sierra Wireless, Incorporated
[64336.183400] usb 1-1.2: SerialNumber: UF92377624041506
[64336.184899] GobiSerial 1-1.2:1.0: GobiSerial converter detected
[64336.185236] usb 1-1.2: GobiSerial converter now attached to ttyUSB0
[64336.185902] GobiSerial 1-1.2:1.2: GobiSerial converter detected
[64336.186381] usb 1-1.2: GobiSerial converter now attached to ttyUSB1
[64336.187548] GobiSerial 1-1.2:1.3: GobiSerial converter detected
[64336.188063] usb 1-1.2: GobiSerial converter now attached to ttyUSB2
[64336.188763] QMAP Disabled
[64336.190634] GobiNet 1-1.2:1.8 eth1: register 'GobiNet' at usb-3f980000.usb-1.2, GobiNet Ethernet Device, 0a:af:20:e2:05:08
[64336.191368] USB Speed : USB 2.0
[64336.291051] usbcore: registered new interface driver cdc_wdm
[64336.294292] usbcore: registered new interface driver qmi_wwan
[64336.433554] IPv6: ADDRCONF(NETDEV_UP): eth1: link is not ready
[64357.572160] creating qcqmi0
[64357.572495] RawIP mode

Notice the below line, which obviously indicates the SieraWireless device EM7565 has been detected by the Kernel:

[64336.183391] usb 1-1.2: Manufacturer: Sierra Wireless, Incorporated

Also, notice that the GobiSerial driver is in action, and has created 3 different emulated USB ports, ttyUSB0, ttyUSB1 and ttyUSB2. The most important one at this point is the ttyUSB2 which we will need in a minute for issuing AT commands to configure the device.

[64336.184899] GobiSerial 1-1.2:1.0: GobiSerial converter detected
[64336.185236] usb 1-1.2: GobiSerial converter now attached to ttyUSB0
[64336.185902] GobiSerial 1-1.2:1.2: GobiSerial converter detected
[64336.186381] usb 1-1.2: GobiSerial converter now attached to ttyUSB1
[64336.187548] GobiSerial 1-1.2:1.3: GobiSerial converter detected
[64336.188063] usb 1-1.2: GobiSerial converter now attached to ttyUSB2

You can also double check the ttyUSB* ports with the blow command:

pi@raspberrypi:~ $ dmesg | grep -i "ttyUSB*" 
[64336.185236] usb 1-1.2: GobiSerial converter now attached to ttyUSB0
[64336.186381] usb 1-1.2: GobiSerial converter now attached to ttyUSB1
[64336.188063] usb 1-1.2: GobiSerial converter now attached to ttyUSB2

Also, note that the GobiNet driver is in action and has created an ethernet interface eth1 for data exchange as can be evident in the below log lines:

[64336.190634] GobiNet 1-1.2:1.8 eth1: register 'GobiNet' at usb-3f980000.usb-1.2, GobiNet Ethernet Device, 0a:af:20:e2:05:08
[64336.191368] USB Speed : USB 2.0

At this point we will open yet another terminal on the console and move there to open a serial communication channel with the device. But just to be vigilant on what’s going on the kernel log I do this on the current console:

pi@raspberrypi:~ $ tail -f /var/log/messages 
Sep 26 21:29:49 raspberrypi kernel: [64336.294292] usbcore: registered new interface driver qmi_wwan
Sep 26 21:29:49 raspberrypi mtp-probe: checking bus 1, device 10: "/sys/devices/platform/soc/3f980000.usb/usb1/1-1/1-1.2"
Sep 26 21:29:49 raspberrypi mtp-probe: bus: 1, device: 10 was not an MTP device
Sep 26 21:29:49 raspberrypi kernel: [64336.433554] IPv6: ADDRCONF(NETDEV_UP): eth1: link is not ready
Sep 26 21:30:10 raspberrypi kernel: [64357.572160] creating qcqmi0
Sep 26 21:30:10 raspberrypi kernel: [64357.572495] RawIP mode

As you can see the new ethernet interface eth1 is not yet ready:

Sep 26 21:29:49 raspberrypi kernel: [64336.433554] IPv6: ADDRCONF(NETDEV_UP): eth1: link is not ready

To check this let’s try another command to see what is the status of the eth1 interface:

pi@raspberrypi:~ $ ifconfig
eth0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether b8:27:eb:37:67:e0  txqueuelen 1000  (Ethernet)
        RX packets 306  bytes 353615 (345.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 172  bytes 17176 (16.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

eth1: flags=4227<UP,BROADCAST,NOARP,MULTICAST>  mtu 1500
        ether 0a:af:20:e2:05:08  txqueuelen 1000  (Ethernet)
        RX packets 22397  bytes 24982435 (23.8 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 12996  bytes 1190453 (1.1 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

wlan0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        ether b8:27:eb:62:32:b5  txqueuelen 1000  (Ethernet)
        RX packets 0  bytes 0 (0.0 B)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 0  bytes 0 (0.0 B)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

Notice in the above command the eth1 ethernet interface doesn’t have any IP assigned yet which is in line with our anticipation as we have not configured the device yet:

eth1: flags=4227 mtu 1500
ether 0a:af:20:e2:05:08 txqueuelen 1000 (Ethernet)
RX packets 22397 bytes 24982435 (23.8 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 12996 bytes 1190453 (1.1 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

Open serial terminal

Now, open another terminal window and move there. To open a serial port I prefer minicom which doesn’t come with my installation of NOOBS. So there is no minicom at this point in my Pi. I luckily had a ethernet line coming to my desk. Hence, I connected that and installed minicom as below:

pi@raspberrypi:~ $ sudo apt-get install minicom 

Need to find a way to install minicom if you want to use it. But maybe you can try miniterm. I am not sure and haven’t tried it at all. I will it to you to resolve. Once you have minicom (or any other terminal emulator of you choice), configure it as below:

Serial Device      : /dev/ttyUSB2                           Bps/Par/Bits       : 115200 8N1                             Hardware Flow Control : Yes                                 Software Flow Control : No                                   

Configure the device

In the serial console type the below commands:

Welcome to minicom 2.7.1

OPTIONS: I18n                                                                
Compiled on Aug 13 2017, 15:25:34.                                           
Port /dev/ttyUSB2                                                            
                                                                             
Press CTRL-A Z for help on special keys                                                                                                                   
ati                                                                          
Manufacturer: Sierra Wireless, Incorporated                                  
Model: EM7565                                                                
Revision: xxxx_01.08.04.00 xxx jenkins 2018/08/21 21:40:11            
IMEI: 353533100239139                                                        
IMEI SV:  8                             
FSN: XXXXXXXX                     
+GCAP: +CGSM                            
                                                                                
OK                                      
at+creg?
+CREG: 0,1

OK
at+cgreg?
+CGREG: 0,1

You need to find out your device manufacturer’s AT commands. It usually follows the same set of commands. However, it may vary from vendor to vendor. So check with them. As in the above you can the device manufacturer’s details and the firmware details are being displayed with the ati command. Below are few other commands which you can try as well:

at+cgdcont?
+CGDCONT: 1,"IPV4V6","","0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0",0,0,0,0

Insert a SIM

At this point I will insert an appropriate SIM into the device’s SIM slot.

Once you have inserted the SIM into the device slot go back to your minicom terminal and issue the below commands:

OK                                      
at+creg?
+CREG: 0,1

OK
at+cgreg?
+CGREG: 0,1

OK
at+cgdcont?
+CGDCONT: 1,"IPV4V6","","0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0",0,0,0,0

OK
at!scact=1,1
OK

at+cgdcont=1,"IPV4V6","wap.vodafone.co.uk" 
OK
at+cgdcont?
+CGDCONT: 1,"IPV4V6","wap.vodafone.co.uk","0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0",0,0,0,0

OK
at!scact=1,1

At this point you should have internet connectivity at you Rasp Pi. Try openning google.co.uk or something else and have fun. At the moment I am experimenting with the device and will possibly add on stuffs here. So watch this space.

Format a micro SD card using gparted utility

For formatting the micro SD card I usually use the gparted utility in Ubuntu. Format the micro SD with FAT 32 filesystem format. You need to have a SD card reader for attaching the SD card to the PC. I use the below SD card and the reader for my purposes:

Once you have attached your SD card with the linux PC you are ready to format it. I am using a Ubuntu PC for my purposes. Go to the console and run the below command:

~$ sudo gparted

Screenshot from 2020-02-11 16-58-29

What we are up to is delete everything in the SD card and get it ready for the NOOBS.

By default the gparted selects your hard drive (/dev/sda is actually your hard drive, did you know!).

Be very cautious, not to play around with your hard drive partitions, you might soon get into a funny situation.

Go to the top right corner of the gparted screen and change the drive from /dev/sda to /dev/sdb (if there are no other media attached to the PC). Look at the various field carefully and try to understand what they are. I cannot go into the details of all the fields here. I can see the below in my SD card (/dev/sdb) at the moment:

Screenshot from 2020-02-11 17-02-31

You can also see the same partitions with lsblk command on the console, I can see the below:

sda 8:0 0 465.8G 0 disk
├─sda1 8:1 0 512M 0 part /boot/efi
└─sda2 8:2 0 465.3G 0 part /
sdb 8:16 1 29.7G 0 disk
├─sdb1 8:17 1 2.4G 0 part
├─sdb2 8:18 1 1K 0 part
├─sdb5 8:21 1 32M 0 part
├─sdb6 8:22 1 256M 0 part
└─sdb7 8:23 1 27.1G 0 part

As you can see above the SD card has in total 5 partitions /dev/sdb1, /dev/sdb2, /dev/sdb5, /dev/sdb6, /dev/sdb7. I want to get rid of all of these. So what I do in gparted screen is to: Select/highlight each partition. Right click, and then Unmount. Once the selected/highlighted partition has been Unmounted, right click and Delete it. Unmount and Delete each of these partitions in the SD card. Now Click on the green Tick at the top of the gparted screen and Apply. At this point you would have unallocated partition like this:

Screenshot from 2020-02-11 17-09-51
Click on the Tick (Apply) button as above

Right click on the Unallocated partition and click on New. Leave everything as default except Filesystems as FAT32, the default is ext4.

Screenshot from 2020-02-11 17-11-49

After changing the file systems type it should look like the below:

Screenshot from 2020-02-11 17-13-02

Click Add. Then again click on the green Tick button at the top, then Apply. Once done, you should see something like the below:

Screenshot from 2020-02-11 17-14-07
Click on the Apply button
Click on Apply button
It looks like this in my PC

Once it is finished, close gparted and go back to your favorite file browser and locate the SD card, in my case it shows something like the below, an empty drive:

Screenshot from 2020-02-11 17-15-44

Now your SD card is formatted with FAT32 filesystem format.

Bringing up Rasberry Pi 3 with NOOBS

Getting Rasberry Pi up and running

I am using a NOOB version for getting up and running with the Rasberry Pi. The version of my Raspberry Pi is 3 Model B (see below):

20200211_163448

Format a micro SD card

You will possibly need to format a SD Card (if you are not lucky and have one already formatted properly for NOOBS). To format an SD Card I usually prefer gparted. I will format my SD card in FAT32 format for NOOBS. I prefer gparted for formatting media cards. You may follow the instructions in the below tutorial to use gparted if you like:

Get hold of NOOBS

To download an official distribution of NOOBS, go to the below link:

noobs

Click on the Download ZIP and you will get the latest vesion of the NOOBS. Or if you need a different NOOBS version other than the latest, you can get a copy of that in the below link:

http://downloads.raspberrypi.org/NOOBS/images/

For my purposes I have download the NOOBS_v3_2_1 version (hence, I go a NOOBS_v3_2_1.zip file in my ~/Download/ folder) from the above link. Choose the one you want and locate the zip file in your local machine.

Extract the zip file

Once you have downloaded the NOOB version you want, extract the NOOBS and you should have a folder called something like NOOBS_*_*. In my case it is NOOBS_v3_2_1. Go inside the folder using your file browser, select and copy everything (Ctrl-A, Ctr-C). Go back to the SD card and do a Ctrl-V. This will copy and paste everything that the NOOBS_v3_2_1 had into the SD card.

Be patient, it takes a while to copy the stuffs across into the SD card. I often make mistake of prematurely eject the drive and nothing works. So please be patient! There is a circular progress bar at the top on the file browser window which shows the progress of the copy (see the picture below), if you have not already noticed.

Once everything copied into the SD card, safely eject the drive and insert it into the SD card slot in Pi.

20200211_172622

Now, connect the below to the Pi:

  1. A keyboard.
  2. A monitor/TV
  3. A mouse (very useful)
  4. Connect the Pi using micro USB cable to the PC to power it up.

Once you have powered the Pi, the NOOBS will take care of booting the device and soon you should see something like this on the Monitor:

20200211_173226

Select the Raspberry Pi Full option from the menu shown above. You will require at least ~8GB I guess. Other option is to select the LibreELEC_RPi2 which I won’t recommend at this point. After you select one option from the menu, the “install” button will get activated. Click on Install. See the below pictures for reference:

Once you have clicked on the Install the installation starts:

20200211_173842

Wait for the installation to finish. After the installation the setup wizard comes up, follow the screens and setup the Country, Language and Timezone etc. Keep the default user account ‘pi‘ and password ‘raspberry‘. It may ask for restart, do restart.

Unknown symbol usb_serial* in GobiSerial LTE Linux Kernel driver

I was working with the SieraWireless LTE device drivers recently and I got into a strange issue with one of the drivers called GobiSerial. I have compiled this driver code in the same way as described here. But when I try to insert this in the Pi kernel I get the below error:

pi@raspberrypi:~ $ sudo insmod GobiSerial.ko
insmod: ERROR: could not insert module GobiSerial.ko: Unknown symbol in module
pi@raspberrypi:~ $ dmesg
[ 65.759262] GobiSerial: Unknown symbol usb_serial_generic_open (err -2)
[ 65.759290] GobiSerial: Unknown symbol usb_serial_suspend (err -2)
[ 65.759328] GobiSerial: Unknown symbol usb_serial_generic_resume (err -2)
[ 65.759348] GobiSerial: Unknown symbol usb_serial_deregister_drivers (err -2)
[ 65.759407] GobiSerial: Unknown symbol usb_serial_generic_write (err -2)
[ 65.759427] GobiSerial: Unknown symbol usb_serial_register_drivers (err -2)

To debug this issue first I would like to know if the symbols like usb_serial_generic_open exists in the Pi kernel or not. Apparently not, but just to verify that I would use the /proc/kallsyms tool provided by Linux Kernel. This utility prints all the symbols (exported) available in the kernel space. So I would try to grep the missing symbols from all the avialable symbols in the kernel like this:

pi@raspberrypi:~ $ cat /proc/kallsyms | grep -i "usb_serial_generic_open"
pi@raspberrypi:~ $

In the above command nothing is returned indicating my hunch the symbols are not present (exported/available) in the Pi Kernel.
Now, by the look of it the symbols should be coming from a Kernel module/driver usb_serial, this is my hunch by the look of the symbols which are missing. My next hunch is some Kernel module are not inserted unless there is a reason for it. Like if you haven’t inserted anything on the USB serial the usb_serial driver won’t be inserted into the kernel. Let’s try this. I will attach the SieraWireless LTE device into the USB port of the Pi. Before I do this I usually clean my Kernel messages buffer as below:

sudo dmesg -c

I do this so that when I insert the device I can only focus on the kernel messages coming out for this device. Now insert the device, wait for a second and then try the dmesg again, and you should be able to see something like this on the console:

[ 252.661876] usb 1-1.3: reset low-speed USB device number 4 using dwc_otg
[ 253.511884] usb 1-1.5: reset low-speed USB device number 5 using dwc_otg
[ 261.551829] usb 1-1.2: new high-speed USB device number 8 using dwc_otg
[ 261.682434] usb 1-1.2: config 1 has an invalid interface number: 8 but max is 3
[ 261.682451] usb 1-1.2: config 1 has no interface number 1
[ 261.683111] usb 1-1.2: New USB device found, idVendor=1199, idProduct=9091, bcdDevice= 0.06
[ 261.683123] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 261.683133] usb 1-1.2: Product: Sierra Wireless EM7565 Qualcomm® Snapdragon™ X16 LTE-A
[ 261.683143] usb 1-1.2: Manufacturer: Sierra Wireless, Incorporated
[ 261.683153] usb 1-1.2: SerialNumber: UF92377624041506
[ 261.686019] QMAP Disabled
[ 261.688132] GobiNet 1-1.2:1.8 eth1: register 'GobiNet' at usb-3f980000.usb-1.2, GobiNet Ethernet Device, d2:bd:e1:49:f1:08
[ 261.689996] USB Speed : USB 2.0
[ 261.805791] usbcore: registered new interface driver usbserial_generic
[ 261.805832] usbserial: USB Serial support registered for generic
[ 261.806590] usbcore: registered new interface driver cdc_wdm
[ 261.814689] usbcore: registered new interface driver qcserial
[ 261.814756] usbserial: USB Serial support registered for Qualcomm USB modem
[ 261.815707] qcserial 1-1.2:1.0: Qualcomm USB modem converter detected
[ 261.816223] usb 1-1.2: Qualcomm USB modem converter now attached to ttyUSB0
[ 261.819226] qcserial 1-1.2:1.2: Qualcomm USB modem converter detected
[ 261.819635] usb 1-1.2: Qualcomm USB modem converter now attached to ttyUSB1
[ 261.819970] qcserial 1-1.2:1.3: Qualcomm USB modem converter detected
[ 261.820236] usb 1-1.2: Qualcomm USB modem converter now attached to ttyUSB2
[ 261.820411] usbcore: registered new interface driver qmi_wwan
[ 261.920268] IPv6: ADDRCONF(NETDEV_UP): eth1: link is not ready

Looks like the default linux kernel serial drivers been just inserted. Curious huh? Now, check if our missing symbol is back in the Kernel or not as below:

pi@raspberrypi:~ $ cat /proc/kallsyms | grep -i "usb_serial_generic_open"
00000000 r __ksymtab_usb_serial_generic_open [usbserial]
00000000 r __kstrtab_usb_serial_generic_open [usbserial]
00000000 t usb_serial_generic_open [usbserial]

Hurray!! It is back. Now try inserting the GobiSerial driver module again:

pi@raspberrypi:~ $ sudo insmod GobiSerial.ko
pi@raspberrypi:~ $

Seems like the previous error didn’t appear. Lets check the dmesg again, and here we go:

[ 326.647915] usbserial: USB Serial support registered for GobiSerial
[ 326.647943] GobiSerial: 2019-11-22/SWI_2.39:GobiSerial

Issue resolved.
But soon I realized that attaching the device to the RPI hw is actually insmod-ing the qcserial and the qmi_wwan kernel modules which are Qualcomm drivers. But if you are dealing with the device EM7565, in the release notes it prohibits to have qcserial and qmi_wwan drivers in the kernel and prescribes to blacklist these in the below file:
/etc/modprobe.d/blacklist-modem.conf.


$ sudo vim /etc/modprobe.d/blacklist-modem.conf
# Uncomment these entries in order to blacklist unwanted modem drivers
# blacklist snd-atiixp-modem
# blacklist snd-intel8x0m
# blacklist snd-via82xx-modem
blacklist qcserial
blacklist qmi_wwan

If you do that these two drivers won’t be loaded when you attach your EM7565 device to the USB port. So, once I do that and restart the system my above resolution to the problem stops working again :(.

Actually qcserial driver is loading the usbserial and once you take the qcserial out of the equation, it all stops working again.

So finally what I did was to:

sudo insmod /lib/modules/4.19.75-v7+/kernel/drivers/usb/serial/usbserial.ko
sudo insmod GobiSerial.ko

and it works fine.

This works but not yet the best way to sort this problem. To sort this problem in the cleanest possible way would be to install the GobiNet and GobiSerial and then do a demod to resolve the dendencies. Follow the below steps for this:

$ export OUTPUTDIR=/lib/modules/`uname -r`/kernel/drivers/net/usb/
$ mkdir -p $OUTPUTDIR
$ cp -f GobiNet.ko $(OUTPUTDIR)
$ cp -f GobiSerial.ko $(OUTPUTDIR)
$ depmod
$ modprobe GobiNet
$ modprobe GobiSerial

Now, restart the system, and you should have everything in place.
To be sure do the below:

pi@raspberrypi:~ $ lsmod | grep -i "Gobi*"
GobiSerial 20480 1
usbserial 40960 3 GobiSerial
GobiNet 438272 0

When we do depmod, it resolves the dependancies of the various modules in the Kernel /lib/modules/ folder. Then at the time of modprobe the dependecy drivers/modules are loaded first and then the actual module of interest.

Cross compiling custom Linux Kenel driver for Rasberry Pi Platform

Getting Rasberry Pi up and running

To bring up your Raspberry Pi (ver 3 B) with NOOBS follow the instructions here.

Find the kernel version of NOOBS installation

Go to Pi and open a terminal. Then type the below:

pi@raspberrypi:~ $ uname -a
Linux raspberrypi 4.19.75-v7+ #1270 SMP Tue Sep 24 18:45:11 BST 2019 armv7l GNU/Linux

In the above it shows the kernel version this NOOBS installation has is 4.19.75-v7+. Now, for cross compilation we need the exact version of the Kernel source code, otherwise we will get the below error:

pi@raspberrypi:~ $ sudo insmod GobiNet.ko
insmod: ERROR: could not insert module GobiNet.ko: Invalid module format

Linux kernels for Raspberry Pi is located here:

https://github.com/raspberrypi/linux

Screenshot from 2020-02-12 12-33-57

By default the one coming right now is version 4.19.y. This doesn’t exactly match with the one we need i.e. 4.19.75-v7+. Next you can look into the Branches here:

https://github.com/raspberrypi/linux/branches

Screenshot from 2020-02-12 12-36-18

However, I cannot see the exact match. So now I look into the Releases tab. This looks like has the one we want:

https://github.com/raspberrypi/linux/releases

Screenshot from 2020-02-12 12-37-58

In this page I can see the Kernel release which was on the 24th Sep, 2019. This exactly matches with the one in NOOBS:

pi@raspberrypi:~ $ uname -a
Linux raspberrypi 4.19.75-v7+ #1270 SMP Tue Sep 24 18:45:11 BST 2019 armv7l GNU/Linux

Download this Kernel source code in your local machine (Ubuntu in my case). The tarball is called linux-raspberrypi-kernel_1.20190925-1.tar.gz. Extract the tarball with the below command:

tar -xvf linux-raspberrypi-kernel_1.20190925-1.tar.gz

In my setup after extraction the linux source is located in the below path:

/home/vbhadra/Downloads/linux-raspberrypi-kernel_1.20190925-1

Now, go inside the linux kernel source folder and do th below:

cd /home/vbhadra/Downloads/linux-raspberrypi-kernel_1.20190925-1
make mrproper


This will ensure we have started with a clean kernel source.
Now, come to your Pi again. What we need now is the kernel configuration which was used for the NOOBS kernel compilation. The Kernel configuration now a days kept in the kernel itself as a module. So to grab hold of the kernel .config file do the below in Pi:

pi@raspberrypi:~ $ sudo modprobe configs
pi@raspberrypi:~ $ zcat /proc/config.gz > /tmp/.config

Copy this .config file in a sd card and bring it back to the Ubuntu PC where your downloaded Kernel source tree lives. Then copy the .config file into the linux kernel source tree as below:

vbhadra@vbhadra-8200-elit-convertable-microtower:~/Downloads/linux-raspberrypi-kernel_1.20190925-1$ sudo mount /dev/sdb1 ~/usb/
vbhadra@vbhadra-8200-elit-convertable-microtower:~/Downloads/linux-raspberrypi-kernel_1.20190925-1$ ls -la ~/usb/
total 748
-rw-r–r– 1 vbhadra vbhadra 163003 Sep 26 02:23 .config
vbhadra@vbhadra-8200-elit-convertable-microtower:~/Downloads/linux-raspberrypi-kernel_1.20190925-1$ cp ~/usb/.config .

Download the Pi toolchain

You will need the toolchain to cross compile the Kernel and your module for Pi environment. Download the toolchain from the git hub with the below command:

git clone https://github.com/raspberrypi/tools ~/tools

Locate where your tools folder is. I usually create a rpi folder in my home folder and do everything there. So in my setup it is located here:
/home/vbhadra/rpi/tools
Now, you need to point where your tools (cross compiler) is for compiling the kernel. To do that do the below:

export CCPREFIX=/home/vbhadra/rpi/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-

Compile the kernel to create the Module.symvers file. To compile the kernel do the below in your Ubuntu setup:

make ARCH=arm CROSS\_COMPILE=${CCPREFIX} -j 12

Let the above compile the Kernel which will take a while, wait patiently!

Now check if you have got a file created called in your linux folder:

vbhadra@vbhadra-8200-elit-convertable-microtower:~/Downloads/linux-raspberrypi-kernel_1.20190925-1$ ls -la Module.symvers
-rw-r–r– 1 vbhadra vbhadra 841463 Feb 12 13:31 Module.symvers

Compile your module

I am trying to cross compile GobiNet and GobiSerial drivers fro SieraWireless LTE device EM7565.

You can grab hold of the driver rom SieraWireless website. This is not about any specific driver and their intricacies. We will only focus on the important bits to cross compile any custom driver for Raspberry Pi (hw version 3 B).

So One you have any driver code which has been compiled for any other platform (possibly) and you want to cross compile it, first thing you should do is to look at the driver Makefile. In this case, I have the below driver Makefile for GobiNet driver:

obj-m := GobiNet.o
GobiNet-objs := GobiUSBNet.o QMIDevice.o QMI.o
KDIR := /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
OUTPUTDIR=/lib/modules/`uname -r`/kernel/drivers/net/usb/
#KBUILD_CFLAGS += -DQOS_SIMULATE
#KBUILD_CFLAGS += -DTX_XMIT_SIERRA -DTX_URB_MONITOR
ifdef TX_URB_MONITOR
ifeq ($(TX_URB_MONITOR), 1)
KBUILD_CFLAGS += -DTX_XMIT_SIERRA -DTX_URB_MONITOR
else
TX_URB_MONITOR:=0
endif
else
TX_URB_MONITOR:=0
endif
ifeq ($(TX_URB_MONITOR), 1)
	ccflags-y:=-DTX_URB_MONITOR
	GobiNet-objs += usbnet_3_0_6.o \
	            usbnet_2_6_35.o usbnet_3_10_21.o usbnet_3_12_xx.o usbnet_4_4_xx.o
endif

RAWIP := 0
ifeq ($(RAWIP), 1)
	ccflags-y:=-DDATA_MODE_RP
endif

PI_KDIR := ~/k/linux-rpi-3.6.y
PI_CCPREFIX=~/toolchain/rpi/tools-master/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi- 

OW_KDIR := ~/openwrt/trunk/build_dir/target-mips_r2_uClibc-0.9.33.2/linux-ar71xx_generic/linux-3.8.11
OW_CCPREFIX=~/openwrt/trunk/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-

MARVELL_KDIR := ~/toolchain/qmi_mxwell/kernel-2.6.31
MARVELL_CCPREFIX := ~/toolchain/qmi_mxwell/toolchain/bin/arm-none-linux-gnueabi-

M64_KDIR := ~/toolchain/arm64bit/linux/linux-4.4.1-devel-16.04.1
M64_CCPREFIX := ~/toolchain/arm64bit/be/aarch64ebv8-marvell-linux-gnu-5.2.1_x86_64_20151117/bin/aarch64_be-marvell-linux-gnu-

PPC_KDIR := ~/toolchain/ppc/kernel_ppc
PPC_CCPREFIX :=~/toolchain/ppc/fsl/1.1/sysroots/i686-fslsdk-linux/usr/bin/ppc64e5500-fsl-linux/powerpc64-fsl-linux-

HIKEY9_KDIR := /farm/android/Hikey_9.0_Trunk/kernel/hikey-linaro
HIKEY9_CCPREFIX := /farm/android/Hikey_9.0_Trunk/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-

all:
	$(MAKE) -C $(KDIR) M=$(PWD) modules

m64:
	$(MAKE) ARCH=arm64 CROSS_COMPILE=${M64_CCPREFIX} -C $(M64_KDIR) M=$(PWD) modules

ppc:
	$(MAKE) ARCH=powerpc CROSS_COMPILE=${PPC_CCPREFIX} -C $(PPC_KDIR) M=$(PWD) modules

marvell:
	$(MAKE) ARCH=arm CROSS_COMPILE=${MARVELL_CCPREFIX} -C $(MARVELL_KDIR) M=$(PWD) modules

pi: 
	$(MAKE) ARCH=arm CROSS_COMPILE=${PI_CCPREFIX} -C $(PI_KDIR) M=$(PWD) modules

ow: 
	$(MAKE) ARCH=mips CROSS_COMPILE=${OW_CCPREFIX} -C $(OW_KDIR) M=$(PWD) modules

hikey9:
	$(MAKE) ARCH=arm64 CROSS_COMPILE=${HIKEY9_CCPREFIX} -C $(HIKEY9_KDIR) M=$(PWD) modules
install: all
	mkdir -p $(OUTPUTDIR)
	cp -f GobiNet.ko $(OUTPUTDIR)
	depmod
clean:
	rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module.* modules.order .cache.mk *.o.ur-safe

The only thing we are interested here is the target, in this file there is a target type called “pi”, that’s the one we want.
Look deeper into this target and associated macros:

pi:
$(MAKE) ARCH=arm CROSS_COMPILE=${PI_CCPREFIX} -C $(PI_KDIR) M=$(PWD) modules

Notice the CROSS_COMPILE is set to PI_CCPREFIX which is what you need to fix. In this example we have discussed about the tools we will use for asp Pi Kernel compilation. The same tool will come handy here as well. Point the PI_CCPREFIX to your tool/cross compiler path as below:

PI_CCPREFIX=/home/vbhadra/rpi/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-

Other important macro is this PI_KDIR. This points to the Kernel folder against which we are going to cross compile. Point this to your previosuly downloaded kernel source folder as below:

PI_KDIR := /home/vbhadra/Downloads/linux-raspberrypi-kernel_1.20190925-1

I also modified the clean target as below:

clean:
make -C $(PI_KDIR) M=$(PWD) clean

But this is not necessary.
Save these changes and go back to the driver folder and issue the make clean command to start with a clean slate and then issue make pi command as below:

~/rpi/GobiNet$ make clean
 #rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions Module.* modules.order .cache.mk *.o.ur-safe
 make -C /home/vbhadra/Downloads/linux-raspberrypi-kernel_1.20190925-1 M=/home/vbhadra/rpi/GobiNet clean
 make[1]: Entering directory '/home/vbhadra/Downloads/linux-raspberrypi-kernel_1.20190925-1'
 make[1]: Leaving directory '/home/vbhadra/Downloads/linux-raspberrypi-kernel_1.20190925-1'
 vbhadra@vbhadra-8200-elit-convertable-microtower:~/rpi/GobiNet$ make pi
 make ARCH=arm CROSS_COMPILE=/home/vbhadra/rpi/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-  -C /home/vbhadra/Downloads/linux-raspberrypi-kernel_1.20190925-1 M=/home/vbhadra/rpi/GobiNet modules
 make[1]: Entering directory '/home/vbhadra/Downloads/linux-raspberrypi-kernel_1.20190925-1'
 CC [M]  /home/vbhadra/rpi/GobiNet/GobiUSBNet.o
 In file included from ./include/net/sock.h:58:0,
 from ./include/net/inet_sock.h:26,
 from ./include/net/ip.h:31,
 from /home/vbhadra/rpi/GobiNet/GobiUSBNet.c:94:
 ./include/linux/memcontrol.h: In function 'task_in_memcg_oom':
 ./include/linux/memcontrol.h:546:2: warning: return makes integer from pointer without a cast [enabled by default]
 /home/vbhadra/rpi/GobiNet/GobiUSBNet.c: At top level:
 /home/vbhadra/rpi/GobiNet/GobiUSBNet.c:112:2: warning: #warning "Remove memcontrol.h task_in_memcg_oom warning : replace 'return p->memcg_in_oom;' to 'return p->memcg_in_oom==NULL ? 0 : 1;' in function task_in_memcg_oom" [-Wcpp]
 /home/vbhadra/rpi/GobiNet/GobiUSBNet.c:113:2: warning: #warning "Commnet '#define MEMCG_NOT_FIX' above after fix applied." [-Wcpp]
 CC [M]  /home/vbhadra/rpi/GobiNet/QMIDevice.o
 CC [M]  /home/vbhadra/rpi/GobiNet/QMI.o
 LD [M]  /home/vbhadra/rpi/GobiNet/GobiNet.o
 Building modules, stage 2.
 MODPOST 1 modules
 CC      /home/vbhadra/rpi/GobiNet/GobiNet.mod.o
 LD [M]  /home/vbhadra/rpi/GobiNet/GobiNet.ko
 make[1]: Leaving directory '/home/vbhadra/Downloads/linux-raspberrypi-kernel_1.20190925-1'


Check if there is a new kernel module been compiled called GobiNet.ko (in your case your define obj-m name). In this case the driver defined module name was GobiNet in the Makefile as below:

obj-m := GobiNet.o

So I will check if there is a GobiNet.ko been generated:

vbhadra@vbhadra-8200-elit-convertable-microtower:~/rpi/GobiNet$ ls -la GobiNet.ko
-rw-r–r– 1 vbhadra vbhadra 217987 Feb 21 11:17 GobiNet.ko


Copy this .ko file in a sdcard and insert into a Pi. Copy the .ko file from the sdcard to home folder in Pi. Then do the below insert it into the Pi Kernel:


pi@raspberrypi:~ $ sudo insmod GobiNet.ko
pi@raspberrypi:~ $ dmesg
[ 2526.062621] GobiNet: 2019-11-22/SWI_2.60
[ 2526.064306] usbcore: registered new interface driver GobiNet

As you can see now the cross compiled GobiNet driver is up and running in the Pi Kernel.

The other kernel driver for SieraWireless LTE EM7565 device is called GobiSerial. I have compiled this driver code in the same way. But when I try to insert this in the Pi kernel I get the below error:

pi@raspberrypi:~ $ sudo insmod GobiSerial.ko
insmod: ERROR: could not insert module GobiSerial.ko: Unknown symbol in module
pi@raspberrypi:~ $ dmesg
[ 65.759262] GobiSerial: Unknown symbol usb_serial_generic_open (err -2)
[ 65.759290] GobiSerial: Unknown symbol usb_serial_suspend (err -2)
[ 65.759328] GobiSerial: Unknown symbol usb_serial_generic_resume (err -2)
[ 65.759348] GobiSerial: Unknown symbol usb_serial_deregister_drivers (err -2)
[ 65.759407] GobiSerial: Unknown symbol usb_serial_generic_write (err -2)
[ 65.759427] GobiSerial: Unknown symbol usb_serial_register_drivers (err -2)


I resolved the problem in the following post here.

How to pipe one bash command output to another within a python script

I was recently working with something which required me to build a code base and flash it into the board (hw) and then once that is done open a serial console (where the hw is connected through USB) and issue further commands on the hw. Now, that is a regular job and I wrote a python script which does all the manual works of cleaning, building etc. But flashing the binary onto the hardware is where the problem started coming. The first time I flash the board there is no issue. However, once I opened a serial console, next time when I try to flash the binary the script finds the serial console to be already occupied.

Read More »

nuttx kernel make menuconfig error in Ubuntu

If you are working with nuttx kernel you might have issues trying to bring up the kernel menuconfig with the below command:

make menuconfig

I had to do the below to get it working in a newly installed Ubuntu system:

  • Make sure you have the right compiler tool chain installed, if not install it
 sudo apt-get install gcc-arm-none-eabi
  • Make sure you have the nuttx frontend tools installed in your Ubuntu, if not install it as below:
git clone https://bitbucket.org/nuttx/tools.git
cd tools/kconfig-frontends
./configure --prefix=/usr --enable-mconf --disable-nconf --disable-gconf
make
sudo make install

Now try the make menuconfig again from the console and you should be able to see the Kernel menuconfig page somewhat like this:Screenshot from 2019-10-25 10-53-26

Useful git command for developers

Git log

git log --pretty=format:"%h%x09%an%x09%ad%x09%s"

Adding it to the bash script

echo "alias gitl='git log --pretty=format:"%h%x09%an%x09%ad%x09%s"'" >> ~/.bashrc
source ~/.bashrc

From now on you can type:

gitl
3918a7c8        Vivek Bhadra    Wed Oct 23 14:02:16 2019 +0100  Integrating the esp8266 wifi module in SPRESENSE sdk.
cbce5ee6        Vivek Bhadra    Tue Oct 22 13:16:11 2019 +0100  Fixes.
d4fc23c7        Vivek Bhadra    Wed Oct 16 16:01:03 2019 +0100  Enhanced camera App for better user interactivity.
6cc05f93        Vivek Bhadra    Wed Oct 16 13:47:02 2019 +0100  Customized for delayed capture of 1 mins.

and see the formatted git log, change the format as you would like.

Checking your current git branch

git branch -av

Add it to the .bashrc

echo "alias gitb='git branch -av'" >> ~/.bashrc
source ~/.bashrc

Type:

gitb
* customize_for_12_demo             3918a7c8 Integrating the esp8266 wifi module in XYZ sdk.
  master                            ee8f2ddf Merge pull request #41 from XXX/release-v1.4.1
  remotes/origin/HEAD               -> origin/master
  remotes/origin/auto_build_doxygen a5681292 Updated readme and only build doc from master
  remotes/origin/master             ee8f2ddf Merge pull request #41 from XXX/release-v1.4.1
  remotes/origin/release_1.0.1      ec7f3dab Release tag XYZ_1.0.001 YYY.0.001 release.

on the console to check the git branch you are on.

Creating a patch from multiple commits

git format-patch -x --stdout > patch-ddmmyyy.patch
git format-patch --ignore-space-change --ignore-space-at-eol --ignore-all-space -n --stdout > ~/patch4-LH3-18466-19092019.patch

where n is the number of commits you want to get back.
–ignore-space-change
–ignore-space-at-eol
–ignore-all-space
the above options are self-explanatory.

How to remove untracked files in git?

  • Print out the list of files which will be removed (dry run)
git clean -n
  • Delete the untracked files from the repository
git clean -f

How to not display the untracked files with git status?

git status --untracked-files=no

or


git status -uno

Renaming a local branch in command line

switch to the branch you want to rename

git checkout branch-name

Then rename it as below:

git branch -m new-name

Genera Linux developer’s tips and tricks

Stop Ubuntu going into suspended mode

Disable suspend

$ sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target
Created symlink /etc/systemd/system/sleep.target → /dev/null.
Created symlink /etc/systemd/system/suspend.target → /dev/null.
Created symlink /etc/systemd/system/hibernate.target → /dev/null.
Created symlink /etc/systemd/system/hybrid-sleep.target → /dev/null.

Re-enable suspend

sudo systemctl unmask sleep.target suspend.target hibernate.target hybrid-sleep.target

Clone SD card

$ lsblk
sda 8:0 0 465.8G 0 disk
├─sda1 8:1 0 512M 0 part /boot/efi
└─sda2 8:2 0 465.3G 0 part /
sdb 8:16 1 29.7G 0 disk
├─sdb1 8:17 1 256M 0 part /media/vbhadra/boot
└─sdb2 8:18 1 14.6G 0 part /media/vbhadra/rootfs
sr0 11:0 1 1024M 0 rom

As can be seen above in my Ubuntu the SD card (which is attached to the PC using a SD card reader) has been detected in /dev/sdb which has two partitions /dev/sdb1 and /dev/sdb2. If you do not see the above your SD card might need some preparation, particularly it would require a formatting in FAT32 format. You can format your SD card following the instruction here. Remember there is no need to create the partitions yourself. Once you clone the whole Raspbian image into the SD card you would have these partitions already and use the SD card straight into a Pi. All you need is to format the SD card and create a big FAT32 partition occupying the whole card space.

$ sudo dd if=/dev/sdb of=raspbian.img bs=4M
7609+1 records in
7609+1 records out
31914983424 bytes (32 GB, 30 GiB) copied, 2414.63 s, 13.2 MB/s

To enable progress of dd command use status=progress along with the above command:

$ sudo dd if=/dev/sdb of=raspbian.img bs=4M status=progress

Copy disk image to SD card

Now, to do the opposite i.e. copying an image (e.g. raspbian) to SD card do the below:

$ sudo dd if=raspbian.img of=/dev/sdb bs=4M status=progress

Where raspbian.img is the name of the image you want to copy to the SD card, and in this case the image is in the current directory, otherwise you have to provide the absolute path of the image in the above command.

Introduction to Arduino

Install the arduino IDE
1. https://www.arduino.cc/en/Main/Software/
2. Select Linux 64 bit
3. Click Just Download

Unzip the downloaded file as below:
vbhadra@jupiter:~/Downloads$ tar -xf arduino-1.8.10-linux64.tar.xz

Run the arduino IDE
vbhadra@jupiter:~/Downloads$ cd arduino-1.8.10/
vbhadra@jupiter:~/Downloads/arduino-1.8.10$ ./arduino

Configure
1. Tools -> Board -> Board -> Arduino/Genuino Uno
Tools -> Port -> /dev/ttyACM0

Installing and uninstalling .zip user libraries in Arduino IDE
Install
Sketch -> Include Library -> Add .zip library
Uninstall
$ find ~/ -type d -iname Arduino
./Arduino
$ ls -la Arduino/
drwx—— 4 vbhadra vbhadra 4096 Oct 1 11:31 libraries
$ ls -la Arduino/libraries/
readme.txt xxxLPWA/ Vivek/

Remove the library folder you want to uninstall
$ sudo rm -rf Arduino/libraries/xxxLPWA/

Then modify your library code, create a .zip file and install it again.

Compile & verify the code
Sketch -> Verify & Compile
You should see “Done compiling”

Upload the code
Sketch -> Upload
You should see “Done Uploading”.

Troubleshooting
1. Issue 1:
An error occurred while uploading the sketchavrdude: ser_open(): can’t open device “/dev/ttyACM0”: Permission denied

-> Check if the port exist on the linux machine:

ls -l /dev/ttyACM*

-> Change the permission of the port as below:
sudo chmod a+rw /dev/ttyACM0

2. Junk characters in serial port

void setup()
{
  Serial.begin(9600);
  Serial.write("Hello World");
}

3. Mounting the SD card into the /mnt

mount -t vfat /dev/mmcsd0 /mnt

How to work in private branch in GIT

Time to time we have to work on source code which are downloaded from a git repository, modify the code, implement the functionality, test it, get the code reviewed and then push it up to the repository. Now, how do we achieve this with the following in mind:

1. I do not want to do a git pull on my local source code base frequently simply because it is cumbersome.

2. I however, want to catch up with the mainline code (let’s call it master branch) so that when I am ready to push the code up I do not have enormous amount of merge conflicts, or conflicting other features which somehow difficult to accommodate at the last minute. So to avoid any surprise I would like to catch up with the mainline (be it master branch)  time to time (I do it one a week at least).

3. I do not want to use merge command to catch up with the mainline code as it messes up with the git log.

All these points in mind I would recommend the below working principle:

1. git clone <git repository>

2. git checkout <branch name> (or by default you maybe already in the master branch. This would depend from source code to source code or repository to repository, so better check where you want to base your implementation.)

3. Now, after the above step 2, we are sitting at the branch where we want to start our implementation/bug fixing etc. Let’s call this “master” branch.

4. I would now like to create my private branch called “my_private”. To create a private branch do the below:

git checkout -b my_private

5. Now carry on with your implementations.

Multiple commits in private branch

While developing a new feature you might like to do it in a incremental way, i.e. when a little milestone is achieved you may like to commit it before carrying further. To do this do the below:

git add <file names>

git commit -m “commit message”

Now, if you carry on like this you would end up with multiple commits on your private branch. However, for doing review and pushing it up, it would be nice if all your changes/new implementations comes under one single commit. To achieve this you can use git interactive rebase command as below:

git rebase -i HEAD~n

where n stands for the number of commits (from the latest commits) to be included in the single commit.

This will bring up a screen which will look like as below:


pick 794969c79 Revert all commits that comprise 10x feature
pick 808bc82dd Added database version and product code into DiagnosticsPresenter.
pick 0b4d6973c Implementing Recent Tab
pick 0c284d078 Implementing Recent Tab

# Rebase 75ff6ea39..1f778b29d onto 75ff6ea39 (4 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

Leave the first pick but convert the second and all other picks to squash as below:


pick 794969c79 Revert all commits that comprise 10x feature
squash 808bc82dd Added database version and product code into DiagnosticsPresenter.
squash 0b4d6973c Implementing Recent Tab
squash 0c284d078 Implementing Recent Tab

# Rebase 75ff6ea39..1f778b29d onto 75ff6ea39 (4 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
# Note that empty commits are commented out

Write and save, and you will be presented with the screen where you can decide what you would like to have as the new single commit message. Save and exit and you would have all your local commits squished into one single commit as below:


107b084c0 vbhadra Mon Sep 9 10:36:26 2019 +0100 Rework Recents presenter to communicate with STEDs facade instead of other presenter.
1aef95ec0 Andrei Tucma Tue Sep 10 08:30:19 2019 +0100 ITC5 calibration: calibrate popover option only available for itc5
8f761ce9c Robert Fry Mon Sep 9 15:57:09 2019 +0100 Possible fix for internal GPS to show signal strength
475af1405 dlangford Mon Sep 9 15:43:23 2019 +0100 STEDS Message popup design change
eb1eaf342 Algirdas Balciunas Mon Sep 9 14:24:20 2019 +0100 GPS source switching fix
460b05fee Algirdas Balciunas Mon Sep 9 14:11:25 2019 +0100 Fixed ship/cargo values in AIS data dialog
d7a47f77b Algirdas Balciunas Mon Sep 9 10:29:52 2019 +0100 Fix for app slowdown on Atom devices

Now, let’s say you want to catch up with the master branch. Go back to your master branch as below:

git checkout master (remember your base code maybe from a branch which not called master. It doesn’t matter, just go to the branch where you started)

git status (this will tell you how many commits your master is behind the latest commit)

git pull (this will bring all the latest changes delivered by others into your local master branch)

Now, go back to your private branch:

git checkout my_private (move to my_private branch)

git rebase master  (this will rebase your my_private branch with the master)


107b084c0 vbhadra Mon Sep 9 10:36:26 2019 +0100 Rework Recents presenter to communicate with STEDs facade instead of other presenter.
1aef95ec0 Andrei Tucma Tue Sep 10 08:30:19 2019 +0100 ITC5 calibration: calibrate popover option only available for itc5
8f761ce9c Robert Fry Mon Sep 9 15:57:09 2019 +0100 Possible fix for internal GPS to show signal strength

Time to push up your changes

1. Go back to the master branch

2. Merge your private branch with master

3. git push


<strong>git checkout master</strong>

<strong>git merge my_private</strong>

<strong>git push</strong>

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Customizing Qt Creator 5.12.4

Install the custom Toolchain

Download and install the toolchain rpm

sudo alien ~/Downloads/<toolchain-name>.rpm

sudo dpkg -i ./<toolchain-name>.deb

Locate the arm compiler

sudo find / -iname arm-*-gnueabihf-g++ 2>/dev/null

/opt/toolchain/arm-cortexa9_neon-linux-gnueabihf-lh3/bin/arm-cortexa9_neon-linux-gnueabihf-g++

Settings

Go to the Projects Tab on the left pane.

BuildSettings

Click on the Manage Kit buttons.

ManageKits

If you want use your custom compiler and debugger etc then you have to create a manual kit.

A kit is a set of tools like compiler, QtVersion (qmake), debugger, device etc.

Before you can create a manual kit, you have to create place holders for your custom compiler, debugger etc.

Kit

image

Qt Version

Go tot the Qt Version Tab and select manual. Then click on Add button.

Here we are trying to specify the qmake binary we are going to use for the project.

In my case my qmake is located (comes from installation of the toolchain) at the below location:

/opt/toolchain/arm-cortexa9_neon-linux-gnueabihf-lh3/bin/qmake.

So in the add wizard I navigate to the above location and select qmake binary.

Qt automatically detects it as Qt Version 5.11.2. In the Kit section we are going to refer to this in near future.

Compilers

Next we have to choose our own custom C++ compiler.

In my case my C++11 compiler is located (comes from the toolchain installation) at the below location

/opt/toolchain/arm-cortexa9_neon-linux-gnueabihf-lh3/bin/arm-cortexa9_neon-linux-gnueabihf-g++.

Now, click on the Manual → C++ and click the Add button to start adding your own custom g++ compiler to the list.

This will ask you to provide a name to the custom compiler, give a name, e.g. “G++ for ATOM”, any other string you like.

Put the absolute path of the g++ binary which you want to add under the Compiler path:

/opt/toolchain/arm-cortexa9_neon-linux-gnueabihf-lh3/bin/arm-cortexa9_neon-linux-gnueabihf-g++

In the ABI, select arm-linux-generic-elf-32bit, leave the rest as default.

Apply, ok. Now you have your custom compiler in the list.

Debuggers

Go to the debugger tab.

Click on the Manual and Add.

Provide a suitable name, “ATOM GDB for Cortex A9”.

Specify the absolute path in the Path.

/opt/toolchain/arm-cortexa9_neon-linux-gnueabihf-lh3/bin/arm-cortexa9_neon-linux-gnueabihf-gdb

Apply, Ok.

Devices

In the Devices specify the details of the device where you want to run your generated binaries.

Custom Kit

Now go back to the Kits tab.

Select Manual.

Click on Add.

Provide a name for your custom Kit, e.g. ATOM.

In the Device Type, select Generic Linux Device.

In Device, select your own device, e.g. Custom Atom Device.

Compiler: C++: select your own created compiler from the drop down list.

Debugger: select the one you created previously.

Qt Version: select your own Qt Version as created previously.

Additional build arguments

Under Build & Run on the left hand panel, select the Build Option.

This will show you a loads of option on the right hand pane.

For our project we need to set the environment variable PRODUCT=ATOM.

To add this, click on the Details button along side qmake command under Build & Run.

This will look like below:

In the Additional Argument section specify, PRODUCT=ATOM.

Now, save it and try compiling your code. Make sure you clean it before giving it a try.

Git Rebasing

 

Problem Description

Suppose you have a local GIT repository where dev-stable-topic is the development branch and time to time the releases are made to the customer from a remote GIT repository which has a branch called release-stable from where the selective changes are merge in a controlled way. The remote repository is hosted in a separate linux server.

Read More »

Marketing Management Assignment – Feasibility Analysis: Launching a branch of a company in a new market/country/economic zone

Task

In your role as a Marketing Consultant, you have been asked by Wiggo*: a fictitious European supermarket (food retailer) chain (similar to Aldi and Lidl) to research and report on the feasibility of them launching in a new international market (this can be a country or economic zone of your choice and/or one you are familiar with).

Read More »

How to publish a topic with mqtt broker running on iot.eclipse.org server

As part of iot application development for IoT I had to play around with the SSL connection establishment  with the remote mqtt servers. The below briefly describes the issue I faced and how did I got over the problem while connecting to a remote mqtt server over SSL.

https://iot.eclipse.org/ is a publicly accessible which runs a MQTT server. As per the tutorial the MQTT server is accessible using the host name io.eclipse.org and the port 1883 in unsecured mode. The server can be securely accessed on the encrypted port 8883.

Read More »

How to install ssh service in Ubuntu Linux (12.04)

Check if sshd service is running in Ubuntu with the below command:


vbhadra@vbhadra-VirtualBox:~$ ps aux | grep ssh
vbhadra 1702 0.0 0.0 4088 204 ? Ss 11:49 0:00 /usr/bin/ssh-agent /usr/bin/dbus-launch --exit-with-session gnome-session --session=ubuntu
vbhadra 4358 0.0 0.0 4400 824 pts/3 S+ 14:10 0:00 grep --color=auto ssh
vbhadra@vbhadra-VirtualBox:~$ sudo netstat -natp | grep sshd
vbhadra@vbhadra-VirtualBox:~$ sudo netstat -natp | grep ssh
vbhadra@vbhadra-VirtualBox:~$

The above command and their output shows there is no sshd service running on my Ubuntu Linux.

Read More »

Installing ftp service in Ubuntu 12.04

This may be very simple but to keep things handy the below will install ftp service in you Ubutu Linux machine:


vbhadra@vbhadra-VirtualBox:~$ sudo apt-get install vsftpd
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed
vsftpd
0 to upgrade, 1 to newly install, 0 to remove and 318 not to upgrade.
Need to get 130 kB of archives.
After this operation, 353 kB of additional disk space will be used.
Get:1 http://gb.archive.ubuntu.com/ubuntu/ precise/main vsftpd i386 2.3.5-1ubuntu2 [130 kB]
Fetched 130 kB in 0s (927 kB/s)
Preconfiguring packages ...
Selecting previously unselected package vsftpd.
(Reading database ... 183924 files and directories currently installed.)
Unpacking vsftpd (from .../vsftpd_2.3.5-1ubuntu2_i386.deb) ...
Processing triggers for man-db ...
Processing triggers for ureadahead ...
Setting up vsftpd (2.3.5-1ubuntu2) ...
vsftpd start/running, process 4107
vbhadra@vbhadra-VirtualBox:~$

This has been tested on a Ubutnu 12.04 running on a virtual box.

Read More »

How to modify kernel command line

[/contact-form] You can modify the kernel command line from the below dts file: ~/repos/solaris_src/linux/arch/mips/boot/dts/xyx/xyz.dts chosen { – bootargs = “console=ttyS0,115200n8 loglevel=8 earlycon=uart8250,mmio32,0x1CC40000,115200 rootwait ro”; + bootargs = “mem=32M console=ttyS0,115200n8 loglevel=8 earlycon=uart8250,mmio32,0x1CC40000,115200 rootwait ro”; };  

Write a program to convert a decimal number to its binary equivalent using stack.

#include <iostream>
#include <sstream>
#include <stdio.h>
#include <string>

using namespace std;

template <typename T>
class Stack {
private:
    int top;
    T datastore[100];
public:
    Stack() : top(-1) {}
    bool is_stack_empty(void) {return (top == -1) ? true : false;}
    bool is_stack_full(void) {return (top >= 100) ? true : false;}
    void push(T elem)
    {
        if (!is_stack_full()) {
            top++;
            datastore[top] = elem;
        }
    }

    T pop()
    {
        if (is_stack_empty()) {
            cout << "Stack is empty" << endl;
        } else {
            int data = datastore[top];
            top--;
            return data;
        }
    }

    T peek(void)
    {
        if (is_stack_empty()) {
            cout << "Stack is empty" << endl;
        } else {
            int data = datastore[top];
            return data;
        }
    }
};

int main()
{
    Stack<int> s;
    int num;

    do {
        cout << "Enter a number ";
        cin >> num;
        cout << "Number entered is " << num << endl;
        while (num)
        {
            int n = num % 2;
            num = num/2;
            s.push(n);
        }

        cout << "The binary equivalent of the number is " << endl;
        while(!s.is_stack_empty()) {
            cout << s.pop();
        }
        cout << endl;
        cout << "Do you want to continue? (y/n) ";
        getchar();
    } while (getchar() == 'y');

    return 0;
}

Write a program to check if a word is a palindrome using stack.

#include <iostream>
#include <sstream>
#include <stdio.h>
#include <string>

using namespace std;

template <typename T>
class Stack {
private:
    int top;
    T datastore[100];
public:
    Stack() : top(-1) {}
    bool is_stack_empty(void) {return (top == -1) ? true : false;}
    bool is_stack_full(void) {return (top >= 100) ? true : false;}
    void push(T elem)
    {
        if (!is_stack_full()) {
            top++;
            datastore[top] = elem;
        }
    }

    T pop()
    {
        if (is_stack_empty()) {
            cout << "Stack is empty" << endl;
        } else {
            int data = datastore[top];
            top--;
            return data;
        }
    }

    T peek(void)
    {
        if (is_stack_empty()) {
            cout << "Stack is empty" << endl;
        } else {
            int data = datastore[top];
            return data;
        }
    }
};

int main()
{
    Stack<char> word;
    string str;
    string pali = "";

    cout << "Enter a word ";
    cin >> str;
    char w;
    for (auto i = 0; i < str.size(); ++i) {
        w = str[i];
        word.push(w);
    }
    while(!word.is_stack_empty()) {
        stringstream ss;
        char c = word.pop();
        ss << c;
        string s = ss.str();
        pali += s;
    }

    if (str == pali)
        cout << "The word is a palindrome " << endl;
    else
        cout << "The word is not a palindrome " << endl;


    return 0;
}

Browse Kernel code with Eclipse

This blog will try to demonstrate the steps required to use eclipse for browsing Linux kernel level source code, e.g. Linux kernel tree or device driver codes. If you have already worked with Linux kernel level source code you will know that the Linux kernel is written in C and Linux kernel space device drivers are also written in C. For c/c++ source code the eclipse version I use is called Eclipse-CDT (C/C++ Development Tooling). My development environment is Ubuntu Linux. So most of my references will be based on Ubuntu packages but these steps are pretty much similar in other Linux distros.

Read More »

How to run an external program from a python script

This blog will try to demonstrate how a python script can be used to automate the running of an external program with data input file located at a particular location.

Lets say we have the below c++ program which reads from a data file called myData.txt located for this example at user home i.e. ~/. The user home is usually /home/<username> for example /home/vbhadra in my case. Use your linux user name instead while trying it yourself. To find out what is your home directory you can use echo $HOME in linux command prompt. Our objective in this blog is to demonstrate the pythoin script which will run any external program binary with data input. So we will have a less focus on the c++ program.

Read More »

comepletion_done

Problem Statement

The main mlme processing kernel thread comes out of the wait_for_completion() immediately without waiting for the complete() to be called on the completion variable. As a result the mlme response was erroneous and the command to check the wifi link status “sudo iw wlan0 link” was returning error.

Read More »