## 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 <linux/module.h>       /* Required by all modules */
#include <linux/kernel.h>       /* Required for KERN_INFO */
#include <linux/init.h>         /* 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 <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
/*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 Ububtu 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 <linux/module.h>       /* Required by all modules */
#include <linux/kernel.h>       /* Required for KERN_INFO */
#include <linux/init.h>         /* 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");
}}}