This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Custom Kernel Module Fatal Error



Hello,

I'm having trouble compiling a custom kernel module. I've fixed my makefile issues (I believe) to allow the makefile to start to compile the my module. However, the cross compilation fails with the error message "fatal error: stdio.h: No such file or directory".

I have compiled the file just as a standard C file and the program runs without difficulty. I'm trying to build it as a kernel module just to get myself more familiar with the environment.

From the error message that is in the shell, my guess is that it has something to do with my KERNELDIR. I've pasted the output of the shell below.

tim@mccubuntu1:~/LEDblink$ make
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- -C /home/tim/ti-sdk-am335x-evm-06.00.00.00/board-support/linux-3.2.0-psp04.06.00.11 M=/home/tim/LEDblink modules
make[1]: Entering directory `/home/tim/ti-sdk-am335x-evm-06.00.00.00/board-support/linux-3.2.0-psp04.06.00.11'
  CC [M]  /home/tim/LEDblink/LEDblink.o
/home/tim/LEDblink/LEDblink.c:1:19: fatal error: stdio.h: No such file or directory
compilation terminated.
make[2]: *** [/home/tim/LEDblink/LEDblink.o] Error 1
make[1]: *** [_module_/home/tim/LEDblink] Error 2
make[1]: Leaving directory `/home/tim/ti-sdk-am335x-evm-06.00.00.00/board-support/linux-3.2.0-psp04.06.00.11'
make: *** [LEDblink.ko] Error 2

I have also tried replacing my CROSS_COMPILE variable with the absolute location of the compiler (/home/tim/ti-sdk-am335x-evm-06.00.00.00/linux-devkit/sysroots/i686-arago-linux/usr/bin/arm-linux-gnueabihf-) but gotten the same result.

This is confusing to me. I would have thought that including something like stdio.h would be fairly straightforward since its pretty much a standard in any C program.

Any thoughts on what I'm doing wrong are appreciated.

EDIT: I'm using an AM335x EVM starter kit

  • Hi Tim,

    You don't find "stdio.h" in kernel drivers instead you will get kernel.h module.h etc.,

    "stdio.h" is used only in 'C' applications.

    start to compile the my module. However, the cross compilation fails with the error message "fatal error: stdio.h: No such file or directory".

    Could you attach your kernel module here.

  • Kernel code is not quite the same as user space code. Standard IO is not allowed for reasons that I have forgotten. The kernel uses printk() instead of printf().

  • Hi Guys,

    Thanks again for your help. I've looked at what you've been saying and I've re-thought how I'm trying to do things. I was trying before to use the printf to write to the user space to control LEDs. As I learn more about how things work, I realize this isn't going to work.

    So, I've re-worked my attempt at a driver to use the GPIO calls specified in the GPIO driver guide. I have now successfully compiled my driver, but I'm not able to insert it into the kernel. "insmod LEDblink.ko" returns "Unknown symbol in module".

    After doing some searching around, I've found people use the "dmesg" command for more info. Dmesg teslls me that in my module:

    Unknown symbol gpio_export(err0)
    Unknown symbol gpio_direction_output(err0)
    Unknown symbol gpio_request(err0)

    If my module was compiled correctly, and gives me a *.ko file, why would the module then not know where to find the gpio functions? I don't think its an issue of the kernel, I can control my GPIOs from the user space. I've attached my kernel module file to this post.

    Any thoughts on what I'm missing or how to successfully install the module into the kernel are appreciated.

    4786.LEDblink.c

  • I would guess that your kernel has not been compiled with gpio drivers. You should enable the GPIO driver and the GPIO sysfs interface as well. What you are trying to do in your LEDblink.c is typically done from userspace via the sysfs interface.

    cd /sys/class/gpio
    echo 36 > export
    cd /sys/class/gpio/gpio36
    echo out > direction
    echo 1 > value
    cd /sys/class/gpio
    echo 36 > unexport
    
    

    Unless you plan on doing a lot more driver-like stuff, I don't think you need a kernel driver.

  • Hi Norman,

    I understand that this is usually done in the user space. However, this is just the process that I'm goiing through to get myself familiar with writing and compiling drivers. I will probably have to write more complex drivers in the future so this is just my form of baby steps to get me where I need to go.

    I know that I have control of the GPIO from the sysfs interface, so that leads me to believe that the kernel has been compiled with the GPIO drivers. Any other thoughts?

  • Okay, I understand that your test code is a stub for more complicated things.

    That's odd. Usually insmod will complain about wrong kernel version or something like that. If you have "/sys/class/gpio" on your board then the kernel should have those GPIO functions exported. The "/proc/kallsyms" file contains all symbols exported by the kernel. There should be lots, you can use grep the narrow down the list., eg "grep gpio /proc/kallsyms". That's all I got for now.

  • Hi Norman,

    That's odd. Every single one of the functions that I'm using in my module is in the /proc/kallsyms. For instance, the grep output of "grep gpio_export /proc/kallsyms" produces "c01e02fc T gpio_export". I'm assuming the c01e02fc is an identifier of some sort, but I'm not sure what the T is. Does this mean its just a function, or is it that the function is restricted in some fashion?

  • The "proc/kallsym" format is detailed in the man page for "nm". Do a "man nm" on your host. It would  say that "T" means "The symbol is in the text (code) section." That is as expected. I don't think there is any restrictions. If you figure it out, please post.

  • Hi Norman,

    I did some more googling and came across somebody on the Ubuntu forums who had a similar issue with a different driver they were making. Fortunately their solution worked for me as well.

    For anyone who reads this in the future, there are a few things that are missing from the file posted above.

    1. Firstly, you need to include <linux/init.h> This comes into play when using __init and __exit. See post number three for these.

    2. When declaring functions, they need to be declared as "static".

    3. Functions that are called on load or unload need to be declared as __init for functions on load and __exit on unload. For instance, a proper function declaration for loading is:

    static int __init LEDblinkstart(void){

    4. Before declaring functions, a license needs to be specified in the file. Probably the most common license is the GPL (general public license). The declaration is below:

    MODULE_LICENSE("GPL");

    5. Down at the bottom of the file, you need to include the "module_init()" and "module_exit()" functions. The parameters that are passed to the init and exit functions are the names of the functions to be called for initialization and cleanup. For instance:

    module_init(LEDblinkstart);
    module_exit(LEDblinkcleanup);

    For anyone that is trying to do this in the future, I've attached my makefile and LEDblink.c files that work below. If you are opening the makefile in windows, its better to open it with wordpad instead of notepad. Notepad gives the makefile funky formatting.

    1184.LEDblink.c
    2476.Makefile.txt

  • Thanks for posting the solution. I've never given any thought to all that module stuff. Most of it seems cosmetic. Guess not. Never occurred to me that some of it is mandatory.  I have seen the case where linux refuses to load a module because the module has a proprietary license attribute.

  • Hi Tim,

    Thanks for your solution and hope it could help others too.

    Hi Norman,

    Thanks a lot for your support.