1.Example source code.
MINI2440&TQ2440 例子源码 https://download.csdn.net/download/bruce_iphone/5580591
Sugest: Copy the source code into kernel source directory, such as linux-2.6.32.2/arch/arm/mach-s3c2440/.And opend with vscode. So it can easy to goto function body, easy to understand code.
2.First step, compile kernel.
cp config_mini2440_t35 .config
make zImage (Note: not bzImage, because vivi-boot use zImage, only uboot use bzImage)
error:(if use high vertion than ubuntu16.04.1(64bit), because of Perl version high than v5.22.1)
Can't use 'defined(@array)' (Maybe you should just omit the defined()?) at kernel/timeconst.pl line 373.
Solution: This is Perl(a compiler) bug,not support grammar 'defined(@array)'. Modify line 373 "if (!defined(@val)) {" to "if (!@val) {"
3.Compile driver program.
The system default include directory is KERN_DIR\arch\arm\include\, if need to include some include file, just add in this directory.
Just input "make", so will generate *.ko file.
4.Run with system.
If compile with system. you can compile the dirver program into kernel. Or not need to start up with application program.
Add several lines int /etc/init.d/rcS, then add a file in /etc/rc.d/init.d/ whith file is run the driver program and application progam.
For example:
add lines as below in /etc/init.d/rcS
/etc/rc.d/init.d/leds start
echo " " > /dev/tty1
echo "Starting leds service..." > /dev/tty1
echo " "
sleep 1
add leds in /etc/rc.d/init.d/
#!/bin/sh
base=led-player
# See how we were called.
case "$1" in
start)
/usr/bin/$base &
;;
stop)
pid=`/bin/pidof $base`
if [ -n "$pid" ]; then
kill -9 $pid
fi
;;
esac
exit 0
5.Auto create device note.
Make sure support mdev or udev, test method as below:
Maybe need to add (I am not sure) /etc/init.d/rcS add a line command: echo /sbin/mdev > /proc/sys/kernel/hotplug.
Error 1: "error: implicit declaration of function 'class_create' " (when use new kernel that such as linux3.8 version to compile)
Solution: add "#include <linux/device.h>".
Error 2: "error: implicit declaration of function 'class_device_create' " (when use new kernel that such as linux3.8 version to compile)
Solution: Use device_create() function to instead class_device_create() function.
Base source code is: (below code is compile successful)
#include <linux/fs.h>
#include <linux/device.h>
static struct class *firstdrv_class;
static struct class_device *firstdrv_class_dev;
int major;
static struct file_operations first_drv_fops = {
.owner = THIS_MODULE, /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
};
static int first_drv_init(void)
{
major = register_chrdev(0, "first_drv", &first_drv_fops); // 注册, 告诉内核
firstdrv_class = class_create(THIS_MODULE, "firstdrv");
firstdrv_class_dev = device_create(firstdrv_class, NULL, MKDEV(major, 0), NULL, "xyz"); /* /dev/xyz */
}
static void first_drv_exit(void)
{
unregister_chrdev(major, "first_drv"); // 卸载
device_unregister(firstdrv_class_dev);
class_destroy(firstdrv_class);
}
module_init(first_drv_init);
module_exit(first_drv_exit);
MODULE_LICENSE("GPL");
Makefile is
KERN_DIR = /home/hui/linux-all/linux-2.6.32.2
all:
make -C $(KERN_DIR) M=`pwd` modules
clean:
make -C $(KERN_DIR) M=`pwd` modules clean
rm -rf modules.order
obj-m += first_drv.o
Application program:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
/* firstdrvtest on
* firstdrvtest off
*/
int main(int argc, char **argv)
{
int fd;
int val = 1;
fd = open("/dev/xyz", O_RDWR);
if (fd < 0)
{
printf("can't open!\n");
}
if (argc != 2)
{
printf("Usage :\n");
printf("%s <on|off>\n", argv[0]);
return 0;
}
if (strcmp(argv[1], "on") == 0)
{
val = 1;
}
else
{
val = 0;
}
write(fd, &val, 4);
return 0;
}
6.run
Error:
Solution: add "MODULE_LICENSE("GPL");" in source code.
If create device note auto, will find the note already in /dev/
At lastst, you can run the application programe.
(end)