## page was renamed from ISELFInalProjectInfo = ISELFInalProjectInfo = Information about several subjects regarding the ISEL final project. == Linux Kernel == https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.13.5.tar.xz == Linux Device Drivers book == http://lwn.net/images/pdf/LDD3/ldd3_pdf.tar.bz2 == sysfs == http://lxr.free-electrons.com/source/Documentation/filesystems/sysfs.txt === What it is: === sysfs is a ram-based filesystem initially based on ramfs. It provides a means to export kernel data structures, their attributes, and the linkages between them to userspace. sysfs is tied inherently to the kobject infrastructure. Please read Documentation/kobject.txt for more information concerning the kobject interface. * /usr/src/linux-3.2.45/Documentation/filesystems/sysfs.txt === Create entry / attributes === https://godandme.wordpress.com/2011/04/05/how-to-make-a-sysfs-entry/ http://stackoverflow.com/questions/11063719/kernel-modules-parameters-in-sysfs-quick-reaction-for-changes http://stackoverflow.com/questions/11067262/getting-parent-for-kobject-add == IIO == Adapted from http://wiki.analog.com/software/linux/docs/iio/iio The Industrial I/O subsystem is intended to provide support for devices that in some sense are analog to digital or digital to analog convertors (ADCs, DACs). Devices that fall into this category are: * ADCs * Accelerometers * Gyros * IMUs * Capacitance to Digital Converters (CDCs) * Pressure Sensors * Color, Light and Proximity Sensors * Temperature Sensors * Magnetometers * DACs * DDS (Direct Digital Synthesis) * PLLs (Phase Locked Loops) * Variable/Programmable Gain Amplifiers (VGA, PGA) == SPI == == I2C == == ARM AT91SAM9260B == http://www.atmel.com/devices/sam9260.aspx A 210MHz ARM926-based processor with an extensive range of communication peripherals. It embeds FS USB host and device interfaces, a 10/100 Ethernet MAC and an image sensor interface, as well as standard peripherals such as a Multimedia Card Interface (MCI), I2S, USARTs, master/slave SPIs, 16-bit Timers, a TWI and four-channel 10-bit ADC. The external bus interface features controllers for SDRAM and static memories including NAND flash and CompactFlash. The SAM9260 is available in 217-ball LFBGA and 208-pin QFP packages. == Linux4SAM == http://www.at91.com/linux4sam/bin/view/Linux4SAM/WebHome http://www.at91.com/linux4sam/bin/view/Linux4SAM/GettingStarted http://www.at91.com/linux4sam/bin/view/Linux4SAM/IioAdcDriver == FXOS8700CQ == http://www.freescale.com/webapp/sps/site/prod_summary.jsp?code=FXOS8700CQ Freescale’s FXOS8700CQ 6-axis sensor combines industry leading accelerometer and magnetometer sensors in a small 3 x 3 x 1.2 mm QFN plastic package. The 14-bit accelerometer and 16-bit magnetometer are combined with a high-performance ASIC to enable an eCompass solution capable of a typical orientation resolution of 0.1 degrees and sub 5 degree compass heading accuracy for most applications. Datasheet: http://cache.freescale.com/files/sensors/doc/data_sheet/FXOS8700CQ.pdf == Hello world linux kernel module on Slackware 14 == * su * cd /usr/src/linux/ * mkdir helloWorld * cd helloWorld * nano Makefile {{{ obj-m = helloWorld.o KVERSION = $(shell uname -r) all: make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules clean: make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean }}} * nano helloWorld.c {{{#!highlight c #include /* Required by all modules */ #include /* Required for KERN_INFO */ #include /* Required for the macros */ static int __init helloworld_init(void) { printk(KERN_INFO "Hello world\n"); return 0; } static void __exit helloworld_exit(void) { printk(KERN_INFO "Bye all.\n"); } module_init(helloworld_init); module_exit(helloworld_exit); MODULE_LICENSE("GPL"); }}} * make clean * make * # tail -f /var/log/messages * insmod helloWorld.ko * dmesg * ls /sys/module # /sys/module/helloWorld should appear * rmmod helloWorld.ko == sysfs sample == Based on https://godandme.wordpress.com/2011/04/05/how-to-make-a-sysfs-entry/ Directory located in /usr/src/linux/sysfs_sample '''Makefile''' {{{ obj-m = sysfs_sample.o KVERSION = $(shell uname -r) all: make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules clean: make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean }}} '''sysfs_sample.c''' {{{#!highlight c /* indent -linux sysfs_sample.c make clean make insmod sysfs_sample.ko tail /var/log/messages cat /sys/module/sysfs_sample/sysfs_sample_attrs/first cat /sys/module/sysfs_sample/sysfs_sample_attrs/second cat /sys/module/sysfs_sample/sysfs_sample_attrs/operation echo "asdf" > /sys/module/sysfs_sample/sysfs_sample_attrs/operation cat /sys/module/sysfs_sample/sysfs_sample_attrs/operation dmesg rmmod sysfs_sample.ko */ #include #include #include #include #include /*A struct kobject represents a kernel object, maybe a device or so, such as the things that show up as directory in the sysfs filesystem.*/ struct kobject *sysfs_sample_kobject; struct int_attribute { struct attribute attr; int value; }; struct string_attribute { struct attribute attr; char value[64]; }; static struct int_attribute first_attribute = {.attr.name = "first",.attr.mode = 0666,.value = 11, }; static struct int_attribute second_attribute = {.attr.name = "second",.attr.mode = 0666,.value = 22, }; static struct string_attribute operation_attribute = {.attr.name = "operation",.attr.mode = 0666,.value = "add", }; static struct attribute *sysfs_sample_attributes[] = { &first_attribute.attr, &second_attribute.attr, &operation_attribute.attr, NULL }; /*Called when a read is performed on a attribute file in sysfs */ static ssize_t default_show(struct kobject *kobj, struct attribute *attr, char *buf) { struct int_attribute *intAttr; struct string_attribute *stringAttr; printk(KERN_INFO "Show called for kobject %s\n", kobj->name); printk(KERN_INFO "Attribute name: %s\n", attr->name); /* convert to proper struct based on name */ if (strcmp("operation", attr->name) != 0) { intAttr = container_of(attr, struct int_attribute, attr); return scnprintf(buf, PAGE_SIZE, "%d\n", intAttr->value); } else { stringAttr = container_of(attr, struct string_attribute, attr); return scnprintf(buf, PAGE_SIZE, "%s\n", stringAttr->value); } } /*Called when a write is performed on a attribute file in sysfs */ static ssize_t default_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t len) { struct int_attribute *intAttr; struct string_attribute *stringAttr; printk(KERN_INFO "Store called for kobject %s\n", kobj->name); if (strcmp("operation", attr->name) != 0) { intAttr = container_of(attr, struct int_attribute, attr); sscanf(buf, "%d", &(intAttr->value)); /*convert char to int */ return sizeof(int); } else { stringAttr = container_of(attr, struct string_attribute, attr); sscanf(buf, "%s", stringAttr->value); /*convert char to char */ printk(KERN_INFO "Sizeof %d\n", sizeof(stringAttr->value)); return sizeof(stringAttr->value); } } static struct sysfs_ops sysfs_sample_operations = {.show = default_show,.store = default_store, }; static struct kobj_type sysfs_sample_type = {.sysfs_ops = &sysfs_sample_operations,.default_attrs = sysfs_sample_attributes, }; /*Called on module initialization */ static int __init sysfsexample_module_init(void) { int err = -1; printk(KERN_INFO "sysfs_sample init called \n"); sysfs_sample_kobject = kzalloc(sizeof(*sysfs_sample_kobject), GFP_KERNEL); if (sysfs_sample_kobject) { kobject_init(sysfs_sample_kobject, &sysfs_sample_type); // if (kobject_add(sysfs_sample_kobject, NULL, "%s", "sysfs_sample")) { if (kobject_add (sysfs_sample_kobject, &THIS_MODULE->mkobj.kobj, "%s", "sysfs_sample_attrs")) { err = -1; printk(KERN_INFO "sysfs_sample creation failed\n"); kobject_put(sysfs_sample_kobject); sysfs_sample_kobject = NULL; } err = 0; } return err; } /*Called on module exit */ static void __exit sysfsexample_module_exit(void) { printk(KERN_INFO "sysfs_sample exit called \n"); if (sysfs_sample_kobject) { kobject_put(sysfs_sample_kobject); kfree(sysfs_sample_kobject); } } module_init(sysfsexample_module_init); module_exit(sysfsexample_module_exit); MODULE_LICENSE("GPL"); }}} == RTC device info == https://www.kernel.org/doc/Documentation/rtc.txt The interrupts are reported via /dev/rtc (major 10, minor 135, read only character device) The alarm and/or interrupt frequency are programmed into the RTC via various ioctl(2) calls as listed in ./include/linux/rtc.h The sysfs interface under /sys/class/rtc/rtcN provides access to various rtc attributes without requiring the use of ioctls. The ioctl() calls supported by /dev/rtc are also supported by the RTC class framework. == Sysfs support == From https://coherentmusings.wordpress.com/2014/02/19/adding-sysfs-support-to-a-driver/ {{{ As the Linux Kernel Development book mentions "The sysfs file system is currently the place for implementing functionality previously reserved for ioctl() calls on device nodes or the procfs filesystem" }}} === ARM Cross compiling === https://www.ailis.de/~k/archives/19-ARM-cross-compiling-howto.html http://frank.harvard.edu/~coldwell/toolchain/ * http://ftp.slackware.com/pub/slackware/slackware-14.0/source/d/binutils/binutils-2.22.52.0.2.tar.xz * http://ftp.slackware.com/pub/slackware/slackware-14.0/source/d/gcc/gcc-4.7.1.tar.xz * http://ftp.slackware.com/pub/slackware/slackware-14.0/source/l/glibc/glibc-2.15.tar.xz Based on gcc and glibc used on the embedded device * https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.13.5.tar.xz * http://ftp.gnu.org/gnu/binutils/binutils-2.24.tar.bz2 * http://ftp.gnu.org/gnu/gcc/gcc-4.8.4/gcc-4.8.4.tar.bz2 * http://ftp.gnu.org/gnu/glibc/glibc-2.20.tar.xz http://preshing.com/20141119/how-to-build-a-gcc-cross-compiler/ http://xathrya.web.id/blog/2013/02/28/building-gcc-arm-toolchain-on-slackware64/ === With emdebian Ubuntu lucid32 === * nano /etc/apt/sources.list * apt-get update * apt-get install linux-libc-dev-armel-cross libc6-armel-cross libc6-dev-armel-cross binutils-arm-linux-gnueabi gcc-4.4-arm-linux-gnueabi * apt-get install g++-4.4-arm-linux-gnueabi * apt-get install pdebuild-cross * apt-get install dpkg-cross qemu * cd /tmp * wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.13.5.tar.xz * tar xvif linux-3.13.5.tar.xz * mv linux-3.13.5 /usr/src * /usr/src/ * cd /usr/src * ln -s linux-3.13.5 linux * ls * cd linux * make ARCH=arm at91sam9260_9g20_defconfig # copy config for ARM at91sam9260 * make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- * export ARCH=arm * export CROSS_COMPILE=arm-linux-gnueabi- * export INSTALL_MOD_PATH=/lib/modules/arm/3.13.5/ * make modules * find . -name "*.ko" | xargs -i file {} * make modules_install # to /tmp/lib .... * mkdir -p /usr/src/linux/helloWorld * cd /usr/src/linux/helloWorld Makefile {{{ obj-m = helloWorld.o KVERSION=3.13.5 all: make -C /lib/modules/$(KVERSION)/build M=$(PWD) modules clean: make -C /lib/modules/$(KVERSION)/build M=$(PWD) clean }}} helloWorld.c {{{ #include /* Required by all modules */ #include /* Required for KERN_INFO */ #include /* Required for the macros */ static int __init helloworld_init(void) { printk(KERN_INFO "Hello world\n"); return 0; } static void __exit helloworld_exit(void) { printk(KERN_INFO "Bye all.\n"); } module_init(helloworld_init); module_exit(helloworld_exit); MODULE_LICENSE("GPL"); }}} * cd helloWorld * make clean * make == Simple hello ARM == {{{ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Description: Ubuntu 10.04.4 LTS Release: 10.04 Codename: lucid $arm-linux-gnueabi-gcc --version arm-linux-gnueabi-gcc (Debian 4.4.5-8) 4.4.5 $cat hello.c #include int main() { printf("Hello cross-compiling world!\n"); return 0; } $arm-linux-gnueabi-gcc -static hello.c -o hello $qemu-arm -cpu arm926 hello Hello cross-compiling world! $arm-linux-gnueabi-gcc hello.c -o hello $qemu-arm -L /usr/arm-linux-gnueabi/ hello Hello cross-compiling world! $file hello hello: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped export ARCH=arm export CROSS_COMPILE=arm-linux-gnueabi- export INSTALL_MOD_PATH=/lib/modules/arm/3.13.5/ cd /usr/src/linux/helloWorld/ cat helloWorld.c #include /* Required by all modules */ #include /* Required for KERN_INFO */ #include /* Required for the macros */ static int __init helloworld_init(void) { printk(KERN_INFO "Hello world\n"); return 0; } static void __exit helloworld_exit(void) { printk(KERN_INFO "Bye all.\n"); return; } module_init(helloworld_init); module_exit(helloworld_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("DonaldDuck"); make clean make scp helloworld.ko root@192.168.1.100:/tmp # on embedded system insmod helloworld.ko dmesg # should show an hello world rmmod -f helloworld }}} == Hard iron interference calibration == {{{#!highlight python ''' Based on the worked example 1 from AN4246 - Freescale Calibrating an eCompass in the Presence of Hard and Soft-Iron Interference http://www.freescale.com/files/sensors/doc/app_note/AN4246.pdf ''' import numpy as np import math def calculateBeta(measuresA): measures=np.array(measuresA) #print '# Measures #' #for i in measures: print i yMatrix=[] #calculate squares for each item for m in measures: yMatrix.append( (m[0]*m[0]) +(m[1]*m[1]) + (m[2]*m[2]) ) yMatrix=np.array(yMatrix) #print '# Y matrix #' #for i in yMatrix: print i xMatrix=[] for m in measures: xMatrix.append( [m[0],m[1],m[2],1] ) xMatrix=np.array(xMatrix) #print '# X Matrix #' #for j in xMatrix: print j #print "beta = ( X' * X )^-1 * X'*Measures " transposeX = np.matrix.transpose( xMatrix ) #print '# X Matrix transpose#' #for j in transposeX: print j r1 = np.dot(transposeX , xMatrix) #print "r1\n%s"%(r1) inv1 = np.linalg.inv(r1) #print "inv1\n%s"%(inv1) r2 = np.dot(inv1,transposeX) #print "r2\n%s"%(r2) beta = np.dot(r2,yMatrix) #print "beta\n%s"%(beta) #vx = beta[0]*0.5 #vy = beta[1]*0.5 #vz = beta[2]*0.5 #print " %f %f %f"%(vx, vy , vz) #B = math.sqrt( (beta[3]) + (vx*vx) + (vy*vy) + (vz*vz) ) #print "%f uT"%(B) #return B return beta ######################################################################## if __name__=='__main__': #acquired magnetometer measures measures=[] measures.append([167.4 , -242.4 ,91.7]) measures.append([140.3 , -221.9 ,86.8]) measures.append([152.4 , -230.4 ,-0.6]) measures.append([180.3 , -270.6 ,71.0]) measures.append([190.9 , -212.4 ,62.7]) measures.append([192.9 , -242.4 ,17.1]) Beta = calculateBeta(measures) print "%s "%(Beta) vx = Beta[0]*0.5 vy = Beta[1]*0.5 vz = Beta[2]*0.5 # subtract V from the measures ... for m in measures: # subtract the strong iron effect from the raw measure vector=[m[0]-vx,m[1]-vy,m[2]-vz] print "%s %s"%( vector, np.linalg.norm( vector ) ) }}}