Wednesday, April 29, 2015
Tuesday, March 10, 2015
Cross-compile kernel modules for Raspberry Pi
This is a quick note on how to cross-compile third party kernel modules for Raspberry Pi. The aim is to keep the stock kernel while compiling a module with matching version.
On Raspberry Pi
Update software on the Raspberry Pi
Also, install rpi-update to upgrade the firmware and kernel. Then reboot.
Check the version of kernel
Also, we need to know the configuration used to compile the kernel. Execute the following command to save it to .config. Transfer the file to the cross-compile machine. We will use it later when compiling the kernel.
Here the kernel version is 3.18.9. We can now work on a desktop computer for cross-compiling. First we need to compile the kernel source in order to generate the Module.symvers file. We need this file when compiling third-party modules. For the following example, I will be using a Ubuntu x64 machine.
On the cross-compile machine
Create a folder and download the Rapberry Pi kernel source.
Check the Makefile and make sure the version is same as the kernel running on your Raspberry Pi.
Create another folder and download the compiler and tools
Set an environment variable KERNEL_SRC to point to the location of the source, e.g.
Set an environment variable CCPREFIX to the prefix of the path of tools, e.g.
Change directory to the kernel source and clean the tree
Copy the .config file we created earlier on Raspberry Pi to the kernel source directory, e.g.
We can start to compile the kernel now. In theory we only needed to build the modules. However, here we build the whole kernel and modules just for fun
Once it is done, we can go ahead to build our third party modules, e.g.
Note that you may need to modify the module's Makefile, e.g.
Here, the "-C" path is pointing to the root of the kernel source we just built.
On Raspberry Pi
Update software on the Raspberry Pi
$ sudo apt-get update
$ sudo apt-get upgrade
Also, install rpi-update to upgrade the firmware and kernel. Then reboot.
$ sudo apt-get install rpi-update
$ sudo rpi-update
$ sudo sh -c “sync; sync; shutdown -r now”
Check the version of kernel
$ uname -a
Linux fax1 3.18.9+ #767 PREEMPT Sat Mar 7 21:41:13 GMT 2015 armv6l GNU/Linux
Also, we need to know the configuration used to compile the kernel. Execute the following command to save it to .config. Transfer the file to the cross-compile machine. We will use it later when compiling the kernel.
$ zcat /proc/config.gz > .config
Here the kernel version is 3.18.9. We can now work on a desktop computer for cross-compiling. First we need to compile the kernel source in order to generate the Module.symvers file. We need this file when compiling third-party modules. For the following example, I will be using a Ubuntu x64 machine.
On the cross-compile machine
Create a folder and download the Rapberry Pi kernel source.
$ git clone https://github.com/raspberrypi/linux.git
Check the Makefile and make sure the version is same as the kernel running on your Raspberry Pi.
Create another folder and download the compiler and tools
$ git clone https://github.com/raspberrypi/tools
Set an environment variable KERNEL_SRC to point to the location of the source, e.g.
$ KERNEL_SRC=/home/cho/work/rpi/linux
Set an environment variable CCPREFIX to the prefix of the path of tools, e.g.
$ CCPREFIX=/home/cho/work/rpi-tools/tools/arm-bcm2708/arm-bcm2708-linux-gnueabi/bin/arm-bcm2708-linux-gnueabi-
Change directory to the kernel source and clean the tree
$ cd /home/cho/work/rpi/linux
$ make mrproper
Copy the .config file we created earlier on Raspberry Pi to the kernel source directory, e.g.
$ cp ~/download/.config /home/cho/work/rpi/linux
We can start to compile the kernel now. In theory we only needed to build the modules. However, here we build the whole kernel and modules just for fun
$ cd /home/cho/work/rpi/linux
$ ARCH=arm CROSS_COMPILE=${CCPREFIX} make oldconfig
Once it is done, we can go ahead to build our third party modules, e.g.
$ cd /home/cho/work/tsc2007/raspi/tsc2007
$ ARCH=arm CROSS_COMPILE=${CCPREFIX} make
Note that you may need to modify the module's Makefile, e.g.
obj-m += tsc2007.o obj-m += tsc_raspi.o all: make -C /home/cho/work/rpi/linux M=$(PWD) modules clean: make -C /home/cho/work/rpi/linux M=$(PWD) clean
Here, the "-C" path is pointing to the root of the kernel source we just built.
Thursday, June 12, 2014
FreeBSD and CPU scaling
Recently built a new FreeBSD machine with AMD Athlon 5350. Found that if powerd is enabled, the machine will randomly reboot itself. Forcing the lowest CPU frequency to max by setting debug.cpufreq.lowest=2050 in /boot/loader.conf can prevent that. So I suspect it is related to the CPU scaling or C-state.
This problem can be avoided if disabling the C6 state in BIOS.
For reference, the motherboard is ASRock AM1H-ITX.
Here are the CPU freq under normal powerd management.
Update: 14 Jun
Found a matching bug report and reported my findings too. Basically, either C6 in BIOS or powerd in FreeBSD need to be disabled to get around the issue. Or, with C6 and powerd enable, the issue can be avoided if CPU throttling is disabled. Add this to /boot/loader.conf:
But this can affect the reported lowest CPU freq.
Throttling disabled:
This problem can be avoided if disabling the C6 state in BIOS.
For reference, the motherboard is ASRock AM1H-ITX.
Here are the CPU freq under normal powerd management.
$ sysctl dev.cpu.0.freq_levels
dev.cpu.0.freq_levels: 2050/5021 1850/4590 1650/3675 1443/3215 1400/2937 1225/2569 1200/2266 1050/1982 1000/1880 875/1645 800/1527 700/1336 600/1145 500/954 400/763 300/572 200/381 100/190
Update: 14 Jun
Found a matching bug report and reported my findings too. Basically, either C6 in BIOS or powerd in FreeBSD need to be disabled to get around the issue. Or, with C6 and powerd enable, the issue can be avoided if CPU throttling is disabled. Add this to /boot/loader.conf:
hint.acpi_throttle.0.disabled=1
But this can affect the reported lowest CPU freq.
Throttling disabled:
root@bart:~ # sysctl dev.cpu | grep freq
dev.cpu.0.freq: 800
dev.cpu.0.freq_levels: 2050/5021 1850/4590 1650/3675 1400/2937 1200/2266 1000/1880 800/1527
Saturday, May 10, 2014
When Java 8 meets Project Euler
Here is a Java implementation of a Project Euler problem. Used lambda expression and steam features of Java 8.
package net.clarenceho.euler; import java.util.stream.IntStream; public class Multiples3and5 { public static void main(String args[]) { System.out.println("The answer is " + Multiples3and5.dividableStream(1000).sum()); } static boolean dividable(int i) { boolean result = false; if (i % 3 == 0 || i % 5 == 0) { result = true; } return result; } static IntStream dividableStream(int max) { return IntStream.range(1, max) .filter(i -> dividable(i)); } }
Saturday, February 15, 2014
OpenCL on UDOO
For those who interested to try OpenCL on UDOO, here is the device info
Number of platforms: 1 CL_PLATFORM_PROFILE: EMBEDDED_PROFILE CL_PLATFORM_VERSION: OpenCL 1.1 CL_PLATFORM_VENDOR: Vivante Corporation CL_PLATFORM_EXTENSIONS: Number of devices: 1 CL_DEVICE_TYPE: CL_DEVICE_TYPE_GPU CL_DEVICE_VENDOR_ID: 5654870 CL_DEVICE_MAX_COMPUTE_UNITS: 4 CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS: 3 CL_DEVICE_MAX_WORK_ITEM_SIZES: 1024 1024 1024 CL_DEVICE_MAX_WORK_GROUP_SIZE: 1024 CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR: 4 CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT: 4 CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT: 4 CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG: 0 CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT: 4 CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE: 0 CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF: 0 CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR: 4 CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT: 4 CL_DEVICE_NATIVE_VECTOR_WIDTH_INT: 4 CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG: 0 CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT: 4 CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE: 0 CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF: 0 CL_DEVICE_MAX_CLOCK_FREQUENCY: 500 CL_DEVICE_ADDRESS_BITS: 32 CL_DEVICE_MAX_MEM_ALLOC_SIZE: 33554432 CL_DEVICE_IMAGE_SUPPORT: 1 CL_DEVICE_MAX_READ_IMAGE_ARGS: 8 CL_DEVICE_MAX_WRITE_IMAGE_ARGS: 8 CL_DEVICE_IMAGE2D_MAX_WIDTH: 8192 CL_DEVICE_IMAGE2D_MAX_WIDTH: 8192 CL_DEVICE_IMAGE2D_MAX_HEIGHT: 8192 CL_DEVICE_IMAGE3D_MAX_WIDTH: 0 CL_DEVICE_IMAGE3D_MAX_HEIGHT: 0 CL_DEVICE_IMAGE3D_MAX_DEPTH: 0 CL_DEVICE_MAX_SAMPLERS: 8 CL_DEVICE_MAX_PARAMETER_SIZE: 256 CL_DEVICE_MEM_BASE_ADDR_ALIGN: 1024 CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE: 128 CL_DEVICE_SINGLE_FP_CONFIG: CL_FP_ROUND_TO_ZERO CL_DEVICE_SINGLE_FP_CONFIG: CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: CL_READ_WRITE_CACHE CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: 64 CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: 4096 CL_DEVICE_GLOBAL_MEM_SIZE: 67108864 CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: 4096 CL_DEVICE_MAX_CONSTANT_ARGS: 9 CL_DEVICE_LOCAL_MEM_TYPE: CL_LOCAL | CL_GLOBAL CL_DEVICE_LOCAL_MEM_SIZE: 1024 CL_DEVICE_ERROR_CORRECTION_SUPPORT: 1 CL_DEVICE_HOST_UNIFIED_MEMORY: 1 CL_DEVICE_PROFILING_TIMER_RESOLUTION: 1000 CL_DEVICE_ENDIAN_LITTLE: 1 CL_DEVICE_AVAILABLE: 1 CL_DEVICE_COMPILER_AVAILABLE: 1 CL_DEVICE_EXECUTION_CAPABILITIES: CL_EXEC_KERNEL CL_DEVICE_QUEUE_PROPERTIES: CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE | CL_QUEUE_PROFILING_ENABLE CL_DEVICE_PLATFORM: 0x2ace9530 CL_DEVICE_NAME: Vivante OpenCL Device CL_DEVICE_VENDOR: Vivante Corporation CL_DRIVER_VERSION: OpenCL 1.1 CL_DEVICE_PROFILE: EMBEDDED_PROFILE CL_DEVICE_VERSION: OpenCL 1.1 CL_DEVICE_OPENCL_C_VERSION: OpenCL C 1.1 CL_DEVICE_EXTENSIONS: cl_khr_byte_addressable_store
Sunday, December 15, 2013
DIY DAC for Beaglebone Black
I ordered the PCM5102 DAC chip long time ago, planning to follow the discussion in a forum to build a DAC for my BBB. Finally got a chance a few weeks ago as I was taking sick leave to stay at home :P. Here is the summary:
Hardware
Software
Issues
Hardware
- The chip I used is PCM5102. There are discussions in the forum that there might be timing issue on the I2S signal with BBB. But audio seems to be not affected.
- The schematic shown in the discussion forum was with headphone amplifier. Since I already owned too many DIY headphone amplifiers, I only implemented the PCM5102 part. In fact, it is quite similar to the "Typical Application Circuits" shown in the datashet.
- Only some minor variations on components, e.g. the power capacitors, as I used whatever I could find in my spare-parts box
- Two LM3940 used to convert 5V to 3.3v for PCM5102, one to analog and one to the rest of the chip. Granted that LM3940 is not very good at ripple and noise handling, but it should be cleaner than the 3.3v on BBB.
- Pin 11 of PCM5102 set as high so filter runs in low latency mode
- The BBB connects to my home wifi network with a dongle (Ralink RT8070 chipset)
Software
- My Beaglebone Black is running Debian with 3.8.13-bone30 kernel
- To support UPnP such that I can control the playlist etc from my phones, tablets, and other computers etc, gmediarenderer was compiled and installed
- With normal UPnP setup, the controller needs to be connected to the renderer all the time so that it can send instructions to play one song after another. This is undesirable as I wanted to use mobile devices to setup a playlist and then disconnect. One solution is to add an OpenHome renderer. This way, the playlist and play controls (e.g. random and loop) can be set and stored centrally.
- As I paid for the BubbleUPnp on my Android devices, I chose to install the BubbleUPnP Server as the OpenHome renderer on BBB. It is a Java application. As mentioned in my previous post, I have the Oracle JDK 8 Early Access ARM VM on my BBB.
- The gmediarenderer and BubbleUPnP JVM take around 15% CPU while playing music. My NAS (acting as UPnp server to serve music files) transcodes FLAC to WAV
- I did test FLAC files on the setup using ffmpeg. The performance is OK too.
Issues
- Of my 2 BBBs, only one works with the DIY DAC. Dont know if it is a hardware defect or something else
- Do not set the playback volume to 100% on BBB. Seems that the PCM5102 charge pump is not providing rail-to-rail voltage. Setting the volume to 100% will cause clipping
- Using ffmpeg to play back audio at 44.1kHz will produce occasional distortion. Can be prevented by upsampling the music in ffmpeg to 48k, 88.2k etc. No such issue with gmediarenderer
Wednesday, December 4, 2013
Updating kernel of Beaglebone Black Debian
Notes to self. To update the kernel of Beaglebone Black Debian:
PS. Using GPIO
- wget http://rcn-ee.net/deb/raring-armhf/v3.8.13-bonexx/install-me.sh
- sudo /bin/bash install-me.sh
PS. Using GPIO
Tuesday, November 19, 2013
PostgreSQL BuildFarm
One of my BeagleBone Black boards is currently running two PostgreSQL BuildFarm instances: one with gcc and one with clang.
A great way to show your support to open source software.
A great way to show your support to open source software.
Saturday, September 14, 2013
Using the Power Button on Beaglebone Black for Shutdown
By default, when pressing the Power button on Beaglebone Black (BBB) for 8 seconds, the board will be powered off. However, this is not properly shutting down the OS.
Instead, I would like to use the power button to issue the shutdown command. After some research, found that the power button generates events that can be captured by monitoring /dev/input/event0.
Here is the script:
The script reads the first 16 bytes and see if it contains 0x74, which is the code for power button. If so, it will execute the shutdown command. Otherwise, sleep for awhile and monitor again.
The script is add to /etc/rc.local in order to be executed after every reboot
Instead, I would like to use the power button to issue the shutdown command. After some research, found that the power button generates events that can be captured by monitoring /dev/input/event0.
Here is the script:
#!/bin/sh BTN=/dev/input/event0 while true; do BTNVAL=`hexdump -e '8/2 "%x " "n"' -n 16 $BTN | grep ' 74 ' | awk '{print $7}'` if [ "$BTNVAL" = "1" ] then echo "Power button pressed" /bin/sync; /bin/sync; /sbin/shutdown -h now exit 0 fi sleep 1 done
The script reads the first 16 bytes and see if it contains 0x74, which is the code for power button. If so, it will execute the shutdown command. Otherwise, sleep for awhile and monitor again.
The script is add to /etc/rc.local in order to be executed after every reboot
/root/scripts/pwrbtncheck.sh > /dev/null 2>&1 &
Wednesday, September 4, 2013
DIY Constant Current Charger for AA / AAA NiMH Battery
Normally I use my MH-C9000 to recharge and condition my AA / AAA batteries. However, it wont charge some of my older batch batteries. Maybe the internal resistance is just too high.
Even with low capacity, these old batteries are good for mouse etc low power devices. So instead of throwing them away, they are charged with a slow constant current charger. Here is a simple design of such charger.
Pros:
Cons:
Even with low capacity, these old batteries are good for mouse etc low power devices. So instead of throwing them away, they are charged with a slow constant current charger. Here is a simple design of such charger.
- The design is powered by +5v. I usually use a phone charger or a computer USB port
- The yellow LED has a +2v drop. With a 0.7v Base-Emitter voltage of BC337, that means there is 1.3v across R2
- With R2 = 12 ohm, the charging current is around 1.3v / 12 ohm = 0.108A
- With a 1000mAh battery, the charging rate is around 0.1C. Good for slow charging
Pros:
- Simple to make. I just used components I found in my DIY junk box. Resistors and transistors can be replaced by other parts. Just make sure you calculate the charging current correctly
Cons:
- No terminate logic. Batteries will be charged until removed. Make sure you don't overcharge your batteries
When the +5v power source is removed, the battery will be powering the LED. Adding a diode could solve the issue. But to keep it simple, I left that out and simply remove the batteries after charging
Subscribe to:
Posts (Atom)