Step1: Driver loading function: ***_init;
This function is executed only once when driving the hardware, and its function is to initialize the hardware, such as configuring the output direction of the IO port, configuring the IO pull-up, etc. This function is passed into the module_init(***_init); function so that it is automatically executed when the driver is loaded;
Step 2: Write open, read, write, and release functions;
The purpose of these three functions is to pass in the file_operations structure; these three functions are called as excuses when the application calls the driver.
The function of open is to load the driver when writing an application; its prototype is pen(strpath, authority), such as: fd = open("/dev/led",O_RDWR); //The open function loads the driver, and the return value is a descriptor. When the return value is 0, the driver is loaded successfully.
The prototype of the Write function is: (structfile *filp, const char __user *buf, size_t count,loff_t *f_pos)
Step 3: Assign the function in step 2 to the operations structure
struct file_operations led_fops =
{
.owner = THIS_MODULE,
.open = led_open,
.read = led_read,
.write = led_write,
.release = led_release,
};
Step4: Register the character device driver module in the ***_init function; the following is the registration LED driver function:
register_chrdev(LED_MAJOR,"led",&led_fops);
int register_chrdev(unsigned int major,const char *name,struct file_operations *fops);
If the parameter major is equal to 0, it means that the major device number dynamically allocated by the system is used; if it is not 0, it means static registration.
To unregister a character device, you can use the unregister_chrdev function.
Step 5: Unregister the character device driver module:
In led_exit (you can use any name, just pass the function name to module_exit) use unregister_chrdev(LED_MAJOR,"led"); function to unregister the driver. And assign it to module_exit(led_exit);
A living example
1. Check the user manual
LED1, LED2, LED3, LED4 are connected to GPK4, GPK5, GPK6, GPK7 respectively
2. Check the 6410 chip manual
There are 3 more steps to follow:
1. Set GPIO to OUTPUT.
Set GPK4, GPK5, GPK6, GPK7 to output=0001
That is, 19:28 of GPKCON0 are configured as 0001
2. Set the GPIO data.
Set bits 4:7 of GPKDATA to 0
3. Set GPKUP to pull up.
Set bits 4:7 of GPKUP to 10
3. Code
led_driver.cStep1: driver loading function: ***_init;
This function is executed only once when driving the hardware, and its function is to initialize the hardware, such as configuring the output direction of the IO port, configuring the IO pull-up, etc. This function is passed into the module_init(***_init); function so that it is automatically executed when the driver is loaded;
Step 2: Write open, read, write, and release functions;
The purpose of these three functions is to pass in the file_operations structure; these three functions are called as excuses when the application calls the driver.
The function of open is to load the driver when writing an application; its prototype is pen(strpath, authority), such as: fd = open("/dev/led",O_RDWR); //The open function loads the driver, and the return value is a descriptor. When the return value is 0, the driver is loaded successfully.
The prototype of the Write function is: (structfile *filp, const char __user *buf, size_t count,loff_t *f_pos)
Step 3: Assign the function in step 2 to the operations structure
struct file_operations led_fops =
{
.owner = THIS_MODULE,
.open = led_open,
.read = led_read,
.write = led_write,
.release = led_release,
};
Step4: Register the character device driver module in the ***_init function; the following is the registration LED driver function:
register_chrdev(LED_MAJOR,"led",&led_fops);
int register_chrdev(unsigned int major,const char *name,struct file_operations *fops);
If the parameter major is equal to 0, it means that the major device number dynamically allocated by the system is used; if it is not 0, it means static registration.
To unregister a character device, you can use the unregister_chrdev function.
Step 5: Unregister the character device driver module:
In led_exit (you can use any name, just pass the function name to module_exit) use unregister_chrdev(LED_MAJOR,"led"); function to unregister the driver. And assign it to module_exit(led_exit);
A living example
1. Check the user manual
LED1, LED2, LED3, LED4 are connected to GPK4, GPK5, GPK6, GPK7 respectively
2. Check the 6410 chip manual
There are 3 more steps to follow:
1. Set GPIO to OUTPUT.
Set GPK4, GPK5, GPK6, GPK7 to output=0001
That is, 19:28 of GPKCON0 are configured as 0001
2. Set the GPIO data.
Set bits 4:7 of GPKDATA to 0
3. Set GPKUP to pull up.
Set bits 4:7 of GPKUP to 10
3. Code
led_driver.c
#include #include #include #include #include #include #include #include #define LED_MAJOR 243 #define LED_ON 1 #define LED_OFF 0 #define LED_1_ON 2 #define LED_1_OFF 3 #define LED_2_ON 4 #define LED_2_OFF 5 #define LED_3_ON 6 #define LED_3_OFF 7 #define LED_4_ON 8 #define LED_4_OFF 9 static int led_open (struct inode *inode,struct file *filp) { unsigned tmp; tmp = readl(S3C64XX_GPKCON); tmp = (tmp&0x0000ffff)| 0x1111ffff; writel(tmp, S3C64XX_GPKCON); printk("#########open#######n"); return 0; } static int led_read (struct file *filp, char __user *buf, size_t count,loff_t *f_pos) { return count; } static int led_write (struct file *filp, const char __user *buf, size_t count,loff_t *f_pos) { char wbuf[10]; unsigned tmp; if(copy_from_user(wbuf,buf,count)) return -EFAULT; switch(wbuf[0]) { case LED_ON: tmp = readl(S3C64XX_GPKDAT); tmp &= (0x0f); writel(tmp, S3C64XX_GPKDAT); printk("turn on!n"); break; case LED_OFF: tmp = readl(S3C64XX_GPKDAT); tmp |= (0xf0); writel(tmp, S3C64XX_GPKDAT); printk("turn off!n"); break; case LED_1_ON: tmp = readl(S3C64XX_GPKDAT); tmp &= (0xef); writel(tmp, S3C64XX_GPKDAT); printk("turn off!n"); break; case LED_1_OFF: tmp = readl(S3C64XX_GPKDAT); tmp |= (0xf0); writel(tmp, S3C64XX_GPKDAT); printk("turn on!n"); break; case LED_2_ON: tmp = readl(S3C64XX_GPKDAT); tmp &= (0xdf); writel(tmp, S3C64XX_GPKDAT); printk("turn off!n"); break; case LED_2_OFF: tmp = readl(S3C64XX_GPKDAT); tmp |= (0xf0); writel(tmp, S3C64XX_GPKDAT); printk("turn on!n"); break; case LED_3_ON: tmp = readl(S3C64XX_GPKDAT); tmp &= (0xbf); writel(tmp, S3C64XX_GPKDAT); printk("turn off!n"); break; case LED_3_OFF: tmp = readl(S3C64XX_GPKDAT); tmp |= (0xf0); writel(tmp, S3C64XX_GPKDAT); printk("turn on!n"); break; case LED_4_ON: tmp = readl(S3C64XX_GPKDAT); tmp &= (0x7f); writel(tmp, S3C64XX_GPKDAT); printk("turn off!n"); break; case LED_4_OFF: tmp = readl(S3C64XX_GPKDAT); tmp |= (0xf0); writel(tmp, S3C64XX_GPKDAT); printk("turn on!n"); break; default : break; } return 0; } int led_release (struct inode *inode, struct file *filp) { printk("#########release######n"); return 0; } struct file_operations led_fops = { .owner = THIS_MODULE, .open = led_open, .read = led_read, .write = led_write, .release = led_release, }; int __init led_init (void) { int rc; printk ("Test led devn"); rc = register_chrdev(LED_MAJOR,"led",&led_fops); if (rc <0) { printk ("register %s char dev errorn","led"); return -1; } printk ("ok!n"); return 0; } void __exit led_exit (void) { unregister_chrdev(LED_MAJOR,"led"); printk ("module exitn");
Previous article:Tips for getting started with ARM and embedded systems
Next article:Samsung S3C2440 ARM920T core processor register arrangement-very useful information
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- Rambus Launches Industry's First HBM 4 Controller IP: What Are the Technical Details Behind It?
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- #RecommendChinaCore# Activity sharing summary
- STM32F030 MCU ADC cannot be interrupted after DMA is enabled
- Seeing the Japanese team play football, I feel that the World Cup is for us Chinese
- 5 yuan a clamp meter
- Classic foreign power electronics tutorials
- 2.4G antenna design reference on PCB board
- Why do I think Jiali Chuang’s marketing has failed?
- I have some questions about CORTEX-M TARGET DRIVER SETUP.
- Notepad++ displays Chinese characters normally, but keil4 and source insight4 display garbled characters?
- [New ways to play with SAMR21] 15. WS2812 colored lights