How to call module_init macro?
I am writing a simple char device driver. The function which we pass to module_init() is called at the time of module installation. When we insert the module using insmod command the function passes to module_init() is gets called. Is there any other method to call this module_init() function.
1 Answer 1
If you are talking about using something else than insmod , then no: insmod is the only way I know to initialize your module.
Otherwise, this module_init thing is a macro and isn’t really a function call (you cannot call a function from global scope in C). It expands to some predefined «module constructor» that calls your initializing function, depending on if you’re compiling as a dynamic module or as an object built into the kernel. Its role is to avoid having to #ifdef a lot when developing a module and making the development process easier (see this).
So if, for some reason (but I discourage you doing this), you want to call your initializing function from your module code, then just call it directly. For example:
static void some_other_function(void) < // . initialize(); // . >static int initialize(void) < // your initialization code >module_init(initialize);
Edit: removed __init following Eugene’s comment.
However, I recommend only the module_init expansion calls your initialization function and that other common code be in a separate function:
static void some_other_function(void) < // . something_that_might_get_called_afterwards_also(); // . >static int __init initialize(void) < // your initialization code (done only once) something_that_might_get_called_afterwards_also(); // some other one-time code >module_init(initialize);
Linux module init not called
Previous questionIt is related to, but the driver is not recognized yet and I am in trouble.
I understand the association between the device tree and the driver, but the driver’s init and probe functions are not called even though they are related. There is nothing that seems to be an error.
(I try to output to dmesg wherever it passes, but it is not output)
The debug output level has been adjusted.
By the way, using modprobe seems to be recognized correctly (I just saw it with lsmod).
The device tree compatibility is the same.
I don’t think the device tree is wrong, as it will only change the contents of compatible and associate it with another (original) driver that matches it.
At this time, I don’t understand why the init function and probe function are not called.
If there are any hints such as the reason why the kernel does not call the init function or probe function, please let me know.
Was self resolved. First of all, spi.c and spidev.c seem to be required, and in the device tree it seems that spi.c needs to be spi.c and spidev.c as a child needs to be hung under it.
My own driver came to be recognized by hanging it on a further child node of spidev.c. However, the behavior of spidev.c and my driver are similar (I originally intended to replace them), so the mechanism is not clear (the one I hate the most).
Related articles
- c language self-made boot loader function stops working when newly defined
- a function that changes the movement depending on the key input
- i want to make a program that makes the if statement a function and judges whether the numerical value input from the keyboard i
- it is a program that calls a simple self-made function made in c language with the main function, but i want to make it smarter
- about scanf function
- formatted input/output-fscan function, fprintf function
- characters in the printf function are not output
- i want to create a function that retrieves and displays multiple characters for date and time
- i want to create a function that gets the date and time and displays it
- external function a function that returns the number of times it is called
- when «*» is included in the argument of the c language function
- the value output by the function is not reflected properly in main
- i don’t know the function that rotates and returns the 8×8 dot character
- c language gpa calculation function
- i am practicing my own function in c language
- function call i want to understand the meaning of the problem statement
- pass the array to the function in the sort program and sort it by the function side
- call a function in a c language function
- function to remove specified points from adjacency list
Linux custom device driver probe and init functions are not being called
I have built a custom hardware configuration in Vivado for Xilinx SoC board, and used petalinux to create a custom driver to control the hardware logic. It seems like after running insmod command, the driver is never initialized and the ->probe() function is not called. I am new to this domain, and wondering if anyone ran into a similar issue and has some pointers on where and what to check in order to see where the issue is. Any advice would be very helpful! Running the dmesg command after inserting the driver into the kernel:
root@plzwork3:/proc/device-tree/amba_pl@0/simpleMultiplier@a0000000# dmesg [ 3351.680317] Hello module world. [ 3351.683735] Module parameters were (0xdeadbeef) and "default"
/ < amba_pl: amba_pl@0 < #address-cells = ; #size-cells = ; compatible = "simple-bus"; ranges ; simpleMultiplier_0: simpleMultiplier@a0000000 < clock-names = "axiliteregport_aclk"; clocks = ; compatible = "xlnx,simpleMultiplier-1.0"; reg = ; xlnx,axiliteregport-addr-width = ; xlnx,axiliteregport-data-width = ; >; >; >;
#ifdef CONFIG_OF static struct of_device_id simpmod_of_match[] = < < .compatible = "xlnx,simpleMultiplier-1.0", >, < /* end of list */ >, >;
#include #include #include #include #include #include #include #include #include #include #include #include /* Standard module information, edit as appropriate */ MODULE_LICENSE("GPL"); MODULE_AUTHOR ("Xilinx Inc."); MODULE_DESCRIPTION("simpmod - loadable module template generated by petalinux-create -t modules"); #define DRIVER_NAME "simpmod" #define CLASS_NAME "CLASS_TUT" static char ker_buf[100]; static int currLen = 0; // Parts of the math operation (2,2,+) is 2+2 static int operand_1 = 0; static int operand_2 = 0; static int result = 0; static struct class *driver_class = NULL; static dev_t first; static struct cdev c_dev; // Global variable for the character device static struct device *ourDevice; // Pointer to the IP registers volatile unsigned int *regA; volatile unsigned int *regB; volatile unsigned int *regC; // Structure to hold device specific data struct simpmod_local < int irq; unsigned long mem_start; unsigned long mem_end; void __iomem *base_addr; >; // Character callbacks prototype static int dev_open(struct inode *inod, struct file *fil); static ssize_t dev_read(struct file *fil, char *buf, size_t len, loff_t *off); static ssize_t dev_write(struct file *fil, const char *buf, size_t len, loff_t *off); static int dev_release(struct inode *inod, struct file *fil); static struct file_operations fops = < .read=dev_read, .write=dev_write, .open=dev_open, .release=dev_release, >; static irqreturn_t simpmod_irq(int irq, void *lp) < printk("simpmod interrupt\n"); return IRQ_HANDLED; >static int simpmod_probe(struct platform_device *pdev)< struct resource *r_irq; /* Interrupt resources */ struct resource *r_mem; /* IO mem resources */ struct device *dev = &pdev->dev; static struct simpmod_local *lp = NULL; int rc = 0; printk("Device Tree Probing\n"); // Get data of type IORESOURCE_MEM(reg-addr) from the device-tree // Other types defined here: // http://lxr.free-electrons.com/source/include/linux/ioport.h#L33 r_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); if (!r_mem) < dev_err(dev, "invalid address\n"); return -ENODEV; >// Allocate memory (continuous physical)to hold simpmod_local struct lp = (struct simpmod_local *) kmalloc(sizeof(struct simpmod_local), GFP_KERNEL); if (!lp) < printk("Cound not allocate simpmod device\n"); return -ENOMEM; >dev_set_drvdata(dev, lp); // Save data on simpmod_local strucutre lp->mem_start = r_mem->start; lp->mem_end = r_mem->end; // Ask the kernel the memory region defined on the device-tree and // prevent other drivers to overlap on this region // This is needed before the ioremap if (!request_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1, DRIVER_NAME)) < dev_err(dev, "Couldn't lock memory region at %p\n", (void *)lp->mem_start); rc = -EBUSY; goto error1; > // Get an virtual address from the device physical address with a // range size: lp->mem_end - lp->mem_start + 1 lp->base_addr = ioremap(lp->mem_start, lp->mem_end - lp->mem_start + 1); if (!lp->base_addr) < dev_err(dev, "simpmod: Could not allocate iomem\n"); rc = -EIO; goto error2; >// ****************** NORMAL Device diver ************************* // register a range of char device numbers if (alloc_chrdev_region(&first, 0, 1, "Leonardo") < 0)< printk(KERN_ALERT "alloc_chrdev_region failed\n"); return -1; >// Create class (/sysfs) driver_class = class_create(THIS_MODULE, CLASS_NAME); if (driver_class == NULL) < printk(KERN_ALERT "Create class failed\n"); unregister_chrdev_region(first, 1); return -1; >ourDevice = device_create(driver_class, NULL, first, NULL, "tutDevice"); if ( ourDevice == NULL) < printk(KERN_ALERT "Create device failed\n"); class_destroy(driver_class); unregister_chrdev_region(first, 1); return -1; >// Create a character device /dev/tutDevice cdev_init(&c_dev, &fops); if (cdev_add(&c_dev, first, 1) == -1) < printk(KERN_ALERT "Create character device failed\n"); device_destroy(driver_class, first); class_destroy(driver_class); unregister_chrdev_region(first, 1); return -1;petalinux-config -c rootfs >// Create the attribute file on /sysfs/class/CLASS_TUT/ called // parCrtl and isBusy // Get data of type IORESOURCE_IRQ(interrupt) from the device-tree r_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!r_irq) < printk("no IRQ found\n"); printk("simpmod at 0x%08x mapped to 0x%08x\n", (unsigned int __force)lp->mem_start, (unsigned int __force)lp->base_addr); // Configuring pointers to the IP registers regA = (unsigned int __force)lp->base_addr + 0x10; regB = (unsigned int __force)lp->base_addr + 0x18; regC = (unsigned int __force)lp->base_addr + 0x26; printk("regA: 0x%08x\n",(unsigned int)regA); printk("regB: 0x%08x\n",(unsigned int)regB); printk("regC: 0x%08x\n",(unsigned int)regC); return 0; > lp->irq = r_irq->start; rc = request_irq(lp->irq, &simpmod_irq, 0, DRIVER_NAME, lp); if (rc) < dev_err(dev, "testmodule: Could not allocate interrupt %d.\n", lp->irq); goto error3; > return 0; error3: free_irq(lp->irq, lp); error2: release_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1); error1: kfree(lp); dev_set_drvdata(dev, NULL); return rc; > static int simpmod_remove(struct platform_device *pdev)< struct device *dev = &pdev->dev; struct simpmod_local *lp = dev_get_drvdata(dev); free_irq(lp->irq, lp); release_mem_region(lp->mem_start, lp->mem_end - lp->mem_start + 1); kfree(lp); dev_set_drvdata(dev, NULL); return 0; > // Indicate which type of hardware we handle on this case(simpleAlu-1.0) #ifdef CONFIG_OF static struct of_device_id simpmod_of_match[] = < < .compatible = "xlnx,simpleMultiplier-1.0", >, < /* end of list */ >, >; MODULE_DEVICE_TABLE(of, simpmod_of_match); #else # define simpmod_of_match #endif static struct platform_driver simpmod_driver = < .driver = < .name = DRIVER_NAME, .owner = THIS_MODULE, .of_match_table = simpmod_of_match, >, .probe = simpmod_probe, .remove = simpmod_remove, >; static int __init simpmod_init(void) < printk("Simple device driver.\n"); printk("Hussam was here, and he init the module\n"); return platform_driver_register(&simpmod_driver); > static void __exit simpmod_exit(void) < platform_driver_unregister(&simpmod_driver); printk(KERN_ALERT "Goodbye module world.\n"); >static int dev_open(struct inode *inod, struct file *fil) < printk(KERN_ALERT "Character device opened\n"); return 0; >// Just send to the user a string with the value of result static ssize_t dev_read(struct file *fil, char *buf, size_t len, loff_t *off) < // Return the result only once (otherwise a simple cat will loop) // Copy from kernel space to user space printk(KERN_ALERT "Reading device rx: %d\n",(int)len); int n = sprintf(ker_buf, "%d\n", *regC); // Copy back to user the result (to,from,size) copy_to_user(buf,ker_buf,n); printk(KERN_ALERT "Returning %s rx: %d\n",ker_buf,n); return n; >// Parse the input stream ex: "50,2,*" to some operand variables. static ssize_t dev_write(struct file *fil, const char *buf, size_t len, loff_t *off)< // Get data from user space to kernel space copy_from_user(ker_buf,buf,len); sscanf (ker_buf,"%d,%d,%c",&operand_1,&operand_2); ker_buf[len] = 0; // Change the IP registers to the parsed operands (on rega and regb) *regA = (unsigned int)operand_1; *regB = (unsigned int)operand_2; printk(KERN_ALERT "Receiving math operation \n",operand_1,operand_2); return len; > static int dev_release(struct inode *inod, struct file *fil) < printk(KERN_ALERT "Device closed\n"); return 0; >module_init(simpmod_init); module_exit(simpmod_exit);
Init not called during modprobe
I know that the driver and device must have the same name and I’ve made sure I’ve done that. However, when modprobe’ing my driver, nothing happens even though I’ve done a number of printk’s in the init function. When modprobing, I get:
root@localhost:~# dmesg --clear root@localhost:~# modprobe mcp3202 root@localhost:~# dmesg [ 41.828678] kobject: 'mcp3202' (bf03968c): kobject_add_internal: parent: 'module', set: 'module' [ 41.828747] kobject: 'holders' (ded9d980): kobject_add_internal: parent: 'mcp3202', set: '' [ 41.828890] kobject: 'notes' (dd1947c0): kobject_add_internal: parent: 'mcp3202', set: '' [ 41.829028] kobject: 'mcp3202' (bf03968c): kobject_uevent_env [ 41.829053] kobject: 'mcp3202' (bf03968c): fill_kobj_path: path = '/module/mcp3202' root@localhost:~#
static struct platform_device mcp3202_device = < .name = "mcp3202", .id = 0, .num_resources = 0, >; static strict of_device_id mcp3202_id[] = < < .compatible = "microchip,mcp3202", >, < >>; MODULE_DEVICE_TABLE(of,mcp3202_id); static struct platform_driver mcp3202_driver = < .driver = < .name = "mcp3202", .owner = THIS_MODULE, .of_match_table = mcp3202_id, >, .probe = mcp3202_probe, .remove = mcp3202_remove, >; module_init(mcp3202_init); module_exit(mcp3202_exit);
static int __init mcp3202_init(void)
My understanding is as long as the names match (dev/drv), the mcp3202_init will be called regardless of what is defined in the .dts for this device. Anyone have any clues what I’m missing? Thanks!