uclinux custom device driver not loading, possibly multiple problems
Linux - KernelThis forum is for all discussion relating to the Linux kernel.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
If you have any problems with the registration process or your account login, please contact us. If you need to reset your password, click here.
Having a problem logging in? Please visit this page to clear all LQ-related cookies.
Get a virtual cloud desktop with the Linux distro that you want in less than five minutes with Shells! With over 10 pre-installed distros to choose from, the worry-free installation life is here! Whether you are a digital nomad or just looking for flexibility, Shells can put your Linux machine on the device that you want to use.
Exclusive for LQ members, get up to 45% off per month. Click here for more info.
uclinux custom device driver not loading, possibly multiple problems
I am pretty new at this, and I have been reading all I can, but I can't seem to put all of the pieces together. Any help is greatly appreciated.
I am trying to write a simple driver called io1, for uClinux, targetting a Coldfire 5282LITE board, and I want it to load on boot. It never has to unload for this app.
The result so far (when loaded onto the board) is that io1 exists in /dev, but it does not exist in /proc/devices or /proc/modules. Also, the open("/dev/io1", O_RDWR) command in the c app that tries to use the driver fails.
This is what I have done:
1. place IO1 folder in linux-2.6.x/drivers/char
IO1 folder contains Makefile,io1.c (source of both shown below)
2. Add option for IO1 to menuconfig
edit linux-2.6.x/drivers/char/Kconfig, add the lines (before config VT):
----
config CONFIG_IO1
bool 'IO1 custom driver' if EMBEDDED
default y
----
4. tell linux to initialize the driver on boot
----
#ifdef CONFIG_IO1
extern void IO1_init(void);
#endif
----
#ifdef CONFIG_IO1
IO1_init();
#endif
----
at appropriate places
Add above text to drivers/char/mem.c, the init call should go in the chr_device_init() function, the extern at the top
5. edit vendors/Freescale/5282LITE/Makefile, add
----
io1,c,62,0 \
----
under ppp,c,108,0 (note beginning tab and ending slash), there IS one driver after this line (hence the \) note that linux-2.6.x/Documentation/devices.txt specifies major number 62 to be local/experimental use
6. make the image
sudo make menuconfig
verify device driver->char drivers->IO1 custom driver is checked also verify loadable module support:-> enable loadable module support is checked also verify loadable module support:-> enable module unloading is checked sudo make dep sudo make romfs sudo make clean sudo make
_________________
Notice io1 on the 2nd output line of ls -C /dev
_________________
If I remove the #ifdef and #endif lines from step 4, I get a compile error - reference to undefined function IO_init(). I have no idea why CONFIG_IO1 might not be set, and I have no idea why, even if it was, I would get the reference to undefined function error.
_________________
Makefile (yes, just one line)
int __init IO1_init (void)
{
u8 data;
if (register_chrdev(IO1_MAJOR,"io1",&IO1_fops)) {
printk("io1 driver: Failed to get major %d\n", IO1_MAJOR); return -EIO; } printk("Registered device io1: major %d\n",IO1_MAJOR);
data=0x00;
printk("WRITE Port Mode: %x hex\n", data); outb(data, OUTMOD);
data=0x0F;
printk("WRITE Data Direction: %x hex\n", data); outb(data, OUTDIR);
I know that's a lot, and I apologize. I am trying to give everything I can to help anyone help me.
Does ANYBODY have ANY thoughts on this? I have been spinning my wheels way too long. Thank you in advance!
Hmm... my novice sense tells me that I do not know how to answer this question. I will try to educate myself on this matter and respond when possible. Thank you so far!
I'll explain it a bit, so it will be easier for you to search. If you add your code to the kernel, you can use all kernel structures and functions. The code exists even if it's not needed, takes RAM and so on.
Module can only use functions and structures that are exported from the kernel. It's more stand-alone and loaded only when needed.
I would say, then that for this application, it is best to compile this as part of the kernel. Resources are not an issue, and this driver should be as hidden as possible to any future user (loading/unloading is not desirable). AND that may make it easier to use the kernel functions, as you say.
I can't seem to find much info on drivers that AREN'T modules, and I can't seem to find what portions are module macros.
I assume these things:
#include <linux/module.h>
module_init(IO1_init);
module_exit(IO1_cleanup);
MODULE_LICENSE("GPL");
Do these things look OK for initializing the driver at the beginning of execution if I remove those macros? I am having trouble figuring out what deleting the above lines will actually do, so I think I am missing something.
----
#ifdef CONFIG_IO1
extern void IO1_init(void);
#endif
----
#ifdef CONFIG_IO1
IO1_init();
#endif
----
at appropriate places
Add above text to drivers/char/mem.c, the init call should go in the chr_device_init() function, the extern at the top
The difference is mostly in the macros you show: module_init and module_exit. They're wrappers which run your functions and performs some module-related stuff (which you do not need). Remove the include file and the three following lines. Then you have to run IO1_init and IO1_cleanup at appropriate places. Your ifdefs look fine.
when I make, I get undefined reference to IO1_init. It is not the extern line, but the other one that is causing the error. Note that I did change the extern definition from void to init to match the IO1_init function in the driver, and I placed i= in the second fuctional reference. (i is an int) The error occurs with or without these int changes.
Of course, I had to comment out the ifdef lines in the char driver makefile also:
#ifdef CONFIG_IO1
obj-y += IO1/io1.o
#endif
Having done this, I get
"drivers/char/IO1/io1.o: No such file: No such file or directory"
on make.
In drivers/char, I have placed a directory called IO1. In this directory, I have the driver source, io1.c, and the Makefile, which is simply 1 line:
obj-m := io1.o
I must have gotten this from one of the tutorials I was trying to follow because I really don't know what it is doing. As such, I also do not know why io1.o does not exist on Make of the entire kernel/file system.
I will worry about why the ifdef's need commented later. If you could help on this, I would once again be very appreciative.
You should add to the Makefile in char/ something like
obj-y := IO1/
Also, change that obj-m to obj-y (to make it always included, for the short time).
I did try what you said, and I never have gotten this to work. I am going to try a whole different route I think. I do appreciate all of your efforts, though, Mara. Thank you for being so helpful and tolerating a novice!
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.