Thursday, November 10, 2011

Module Interaction Through sysfs


For the past couple of weeks I have been writing my own kernel module for the Quad DAC mcp4728. Since I'm dealing with a DAC a user-space application must be able to change the output voltages when required. As we should all now know, user-space and kernel-space process cannot interact directly, this assumption lead me on to sysfs.

Sysfs gives a module a mechanism to interact with user-space, sysfs is a virtual file-system that exports information about devices and drivers from the kernel device model to user-space. Some of the entries in sysfs come as standard when you register a device, some you can add yourself. By creating files in the sysfs you are able link functions and ultimately variables within module to user-space.

In my case, the mcp4728 has four DACs ports A~D, with that in mind, I created four entries within sysfs named porta_voltage through to portd_voltage. I can then interact with these files from user-space using simple read/writes..simple. 

So how did I do it you may ask? Read chapter 14 of this book titled Linux Device Drivers, Third Edition and also look at the example in the kernel source located at samples/kobject/kobject-example.c, you will see the importance of the foor_show and foo_store functions. Put simply when you read the sysfs file foo_show is called in the module, and when you write to the file, foo_store is called. Simple.

Wednesday, October 19, 2011

Qt: Undefined reference to vtable


For the past few weeks I have been evaluating various tool-kits for developing glossy user interfaces that you would typically see on a smartphone these days. It had been to toss up between Inflexion from Mentor Graphics or Qt from Nokia. Obviously I have fallen on to the side of Qt for the option of using the SDK under LGPL.

So I have been climbing the learning curve, created a very slick user interface, putting my GIMP skills to the test, while putting it together very quickly using QtQuick. The next step was to link some C++ functions to the interface. Couldn't find much information, that was correct, that could help me link a C++ application to a QML file.

For a long time I was getting an error in Qt creator for an Undefined reference to vtable, what this means? I am unsure, I am know it is an error linked to the macro Q_OBJECT and the linker, I found that if I include the file main.moc after I have declared the classes then it ran without issue. Check out what Qt have to say about it here.

Using a combination of a few resources I'm posting my findings to hopefully help other Qt newbies in getting up and running quickly.

main.cpp (remember the headers!)
class MyClass : public QObject
{
    Q_OBJECT
public slots:
    void cppMethod(const QString &msg){
        qDebug() << "Called the C++ slot with" << msg;
    }
};
#include "main.moc"
int main(int argc, char *argv[])
{
    QApplication app(argc, argv);
    QDeclarativeView view;
    MyClass myClass;
    view.rootContext()->setContextProperty("myObject",&myClass);
    view.setSource(QUrl::fromLocalFile("qml/linkTest/main.qml"));
    view.show();
    return app.exec();
}
Extract from main.qml
MouseArea {
      id: mouse_area
      x: 4
      y: 9
      width: 442
      height: 91
      smooth: true

      onClicked: {
          menuView.currentIndex = index+5
          myObject.cppMethod("Hello from QML")
      }
}
 

Wednesday, September 21, 2011

GPIO Interrupts on the i.MX53


So I had been scouring the web for some information on how to use the GPIO pins as kernel interrupts. There is plenty of reference material on how to use sysfs interface to poll the pins manually but I couldn't figure out the interrupts, with some perserverance and  some digging through the source tree I came up with this.

Bear in mind my platform is the imx53 based DIMM-MX53 from Emtrion but the theory should still apply across the board including the IMXQSB.

static irqreturn_t button_interrupt(int irq, unsigned long data)
{
printk(KERN_INFO "Hello World\n");
tasklet_schedule(&my_tasklet);
return IRQ_HANDLED;
}

static int __init hello_start(void)
{
int ret;
 
printk(KERN_INFO "Loaded hello module....\n");
ret = request_irq(gpio_to_irq(42), button_interrupt,
IRQF_DISABLED | IRQF_TRIGGER_FALLING,
"hello", NULL);
if(ret){
printk(KERN_ERR "Failed to request IRQ\n");
return ret;
}
return 0;
}
The macro gpio_to_irq(x) changes the GPIO address to an IRQ, in my case I'm using the second 32 bit GPIO port and bit 10 (GPIO2-10). It is also worth noting that it is probably bad practice to request the IRQ during the initialisation but rather when you want to use the device, this way you will not hog any system resource.

This should be enough to get you going, enjoy.

Tuesday, September 20, 2011

My Time with Timesys


For the past few months I have been in the middle of a project at work which as brought me into the embedded Linux world. This has been an area I have touched on, craved to do more of and I finally have my wish. It is a dark world of hacking software and hardware, mailing lists and IRC channels. Well really it is not that dark but you do see corners of the internet that the average joe never gets too. Back on topic..

My target platform has been the i.MX53 from Freescale, this System-on-Chip is a powerful applications processor which is targeted at high-end devices such as tablets and smart-phones, the processor comes with a wealth of features and functionality, which I'm not going to go into, as I am sure that if you are reading this then, you have probably already downloaded the datasheets.

There are numerous dev kits on the market with BSPs, some good and some bad (you know who you are), but if I were to recommend one, then I'd check out the DIMM-MX53 from Emtrion. Their Linux BSP is packed full and is very easy to use. For example I have just added USB gadget support to my kit (this support does not come out of the box). If you have any questions about the development kit then I'll be happy answer them if I can.

For me, the best part of this development cycle has been the use of professional build tools and commercially supported Linux source code. Now your probably thinking why pay for Linux when it is free. The answer time. 

When I started work on the first i.MX53 kit I had (that didn't work out) I wasted about two weeks, building, patching, hacking and tweaking the BSP and RFS. Now the purist would argue that is all part of the opensource development cycle, which is fine, but when you need packages and tools that just work and support when you need it then I can only recommend using Timesys Linux

In a single afternoon, I had imported the kernel from the BSP, built a working kernel image and RFS with all the packages. This was impressive, for someone who, at the time, did not have much experience in building a system, I must admit I'm a lot more confident than I was. The great side effect is that it breaks you into the opensource mentality a lot more easily, the learning curve is not as steep but you will end up hacking the system in the end, downloading patches and in my case writing your own device drivers. The support and documentation from Timesys has a wealth of information to help anyone understand how the kernel works how applications interact with it and more importantly (for me) how to optimise it (as of today my kernel boots in 2.5 seconds, it will get quicker).

All I can say is check them out, some of their support documents can be view publicly. They also run a trial of there web based build tool which is a great way to assess what is possible. A paid subscriber will get access to the desktop version of the Factory build tool which is a lot more versatile.

I'll be posting more of what I find when using the Emtrion DIMM-MX53 SoM and Timesys Linux.