117
118 //MUX_CTL
119 MUX_CTL &= ~(0x07 << 0);
120 MUX_CTL |= (0X05 << 0); //Set to ALT5 GPIO3_23 ERR_LED
121 //PAD_CTL
122 PAD_CTL &= ~(0x01<<13 | 0x01<<3 | 0x03<<1 | 0x01<<0); //1.8v does not require pull-up or pull-down CMOS output slew rate
123 //GDIR_GPIO3 is configured as output mode
124 GDIR_GPIO3 &= ~(0x01 << 23);
125 GDIR_GPIO3 |= (0x01 << 23); //Configure to output mode
126
127 //DR_GPIO3 is configured as output 0 to light up ERR_LED
128 DR_GPIO3 &= ~(0x01 << 23); // Clear GPIO2_23
129 DR_GPIO3 &= ~(0x01 << 23); // Clear GPIO2_23
130 gpio_addr();
131 led_on_off();
132 return 0;
133 }
134
135 static void __exit key_irq_exit(void)
136 {
137 gpio_addr();
138 myprintk("<0>nGoodbye,%s!nn",Driver_NAME);
139 led_on_off();
140
141 unregister_chrdev(major,Driver_NAME);
142 device_unregister(drv_class_dev);
143 class_destroy(drv_class);
144
145 //Release IO port
146 iounmap(base_iomux);
147 iounmap(base_gpio3);
148 }
149
150
151 /* These two lines specify the driver's initialization function and uninstallation function*/
152 module_init(key_irq_init);
153 module_exit(key_irq_exit);
154
155 /* Describes some information about the driver, not required*/
156 MODULE_AUTHOR("Lover Cher");
157 MODULE_VERSION("0.1.0");
158 MODULE_DESCRIPTION("IMX257 key Driver");
159 MODULE_LICENSE("GPL");
5. Improve reading to allow the process to read more comprehensive content
There is a problem in the previous program. I wonder if you have noticed that if you read cat /proc/mymsg continuously, the content you read is incomplete.
To solve this problem, we introduce two sets of pointers and open up another set of pointers specifically for reading content.
1. Define another set of pointers specifically for reading
1 //Define the entry structure of proc
2 static struct proc_dir_entry *myentry;
3 static char mylog_buf[MYLOG_BUF_LEN]; //data buffer
4 static char tmp_buf[MYLOG_BUF_LEN]; //data buffer
5 static int mylog_r = 0;
6 static int mylog_r_forread = 0;
7 static int mylog_w = 0;
2. Add a judgment empty function specifically for reading messages
1 //Judge whether it is empty
2 static int is_mylog_empty(void)
3 {
4 return (mylog_r == mylog_w);
5 }
6
7 //Judge whether it is empty
8 static int is_mylog_empty_forread(void)
9 {
10 return (mylog_r_forread == mylog_w);
11 }
3. Add a character reading function specifically for reading messages
1 //Read characters
2 static int mylog_getc(char *p)
3 {
4 if(is_mylog_empty())
5 return 0;
6 *p = mylog_buf[mylog_r];
7 mylog_r = (mylog_r + 1) % MYLOG_BUF_LEN;
8 return 1;
9 }
10
11 static int mylog_getc_forread(char *p)
12 {
13 if(is_mylog_empty_forread())
14 return 0;
15 *p = mylog_buf[mylog_r_forread];
16 mylog_r_forread = (mylog_r_forread + 1) % MYLOG_BUF_LEN;
17 return 1;
18 }
4. Modify some functions in the mymsg_read function to functions specifically used for reading
1 //Use other drivers to write the printk function as myprintk, and it will be written into it
2
3 //Realize the read function, refer to kmsg.c
4 static ssize_t mymsg_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)
5 {
6 int error;
7 int i = 0; //The number of data read
8 char c;
9
10 //Open with non-blocking mode and the data queue is empty
11 if ((file->f_flags & O_NONBLOCK) && is_mylog_empty_forread())
12 return -EAGAIN;
13
14 //Wait until the queue is not empty
15 error = wait_event_interruptible(mylog_wait,!is_mylog_empty_forread());
16
17 /* If copy_to_user is correct, the string is obtained successfully*/
18 while( !error && (mylog_getc_forread(&c)) && i < count ){
19 error = __put_user(c, buf); //Equivalent to copy_to_user
20 buf++;
21 i++;
twenty two }
23 if(!error)
24 error = i;
25 return error;
26 }
5. Define a mymsg_open function to relocate the read pointer
1 static int mymsg_open(struct inode *inode, struct file *file)
2 {
3 mylog_r_forread = mylog_r;
4 return 0;
5 }
6
7
8 //Define file_operation structure
9 static struct file_operations proc_mymsg_operations = {
10. read = mymsg_read,
11.open = mymsg_open,
12 };
6. Compile and test:
As shown in the figure below: We read continuously, and the content read is comprehensive
Attach the driver mymsg_5.c
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10
11
12 #define MYLOG_BUF_LEN 1024
13
14 //Define the entry structure of proc
15 static struct proc_dir_entry *myentry;
16 static char mylog_buf[MYLOG_BUF_LEN]; //data buffer
17 static char tmp_buf[MYLOG_BUF_LEN]; //data buffer
18 static int mylog_r = 0;
19 static int mylog_r_forread = 0;
20 static int mylog_w = 0;
twenty one
22 static DECLARE_WAIT_QUEUE_HEAD(mylog_wait);
twenty three
24 //Judge whether it is empty
25 static int is_mylog_empty(void)
26 {
27 return (mylog_r == mylog_w);
28 }
29
30 //Judge whether it is empty
31 static int is_mylog_empty_forread(void)
32 {
33 return (mylog_r_forread == mylog_w);
34 }
35
36 //Judge whether it is full
37 static int is_mylog_full(void)
38 {
39 return (((mylog_w + 1) % MYLOG_BUF_LEN) == mylog_r);
40 }
41 //Write characters
42 static void mylog_putc(char c)
43 {
44 if(is_mylog_full())
45 {
46 //Discard a data
47 mylog_r = (mylog_r + 1) % MYLOG_BUF_LEN;
48 if(((mylog_r_forread + 1) % MYLOG_BUF_LEN) == mylog_r)
49 mylog_r_forread = mylog_r;
50 }
51 mylog_buf[mylog_w] = c;
52 mylog_w = (mylog_w + 1) % MYLOG_BUF_LEN;
53
54 /* Wake up the process waiting for data */
55 wake_up_interruptible(&mylog_wait);
56 }
57 //Read characters
58 static int mylog_getc(char *p)
59 {
60 if(is_mylog_empty())
61 return 0;
62 *p = mylog_buf[mylog_r];
63 mylog_r = (mylog_r + 1) % MYLOG_BUF_LEN;
64 return 1;
65 }
66
67 static int mylog_getc_forread(char *p)
68 {
69 if(is_mylog_empty_forread())
70 return 0;
71 *p = mylog_buf[mylog_r_forread];
72 mylog_r_forread = (mylog_r_forread + 1) % MYLOG_BUF_LEN;
73 return 1;
74 }
75
76
77 //Print output Refer to sprintf in vsprintf.c
78 int myprintk(const char *fmt, ...)
79 {
80 va_list args;
81 int i,j;
82
83 va_start(args, fmt);
84 i = vsnprintf(tmp_buf, INT_MAX, fmt, args);
85 va_end(args);
86 for(j = 0; j
87 {
88 mylog_putc(tmp_buf[j]);
89 }
90
91 return 1;
92 }
93
94 //Use other drivers to write the printk function as myprintk, and it will be written into
95
96 //Realize the read function, refer to kmsg.c
97 static ssize_t mymsg_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)
98 {
99 int error;
100 int i = 0; //The number of data read
101 char c;
102
103 //Open with non-blocking mode and the data queue is empty
104 if ((file->f_flags & O_NONBLOCK) && is_mylog_empty_forread())
105 return -EAGAIN;
106
107 //Wait until the queue is not empty
108 error = wait_event_interruptible(mylog_wait,!is_mylog_empty_forread());
109
110 /* If copy_to_user is correct, the string is obtained successfully*/
111 while( !error && (mylog_getc_forread(&c)) && i < count ){
112 error = __put_user(c, buf); //Equivalent to copy_to_user
113 buf++;
114 i++;
115 }
116 if(!error)
117 error = i;
118 return error;
119 }
120
121 static int mymsg_open(struct inode *inode, struct file *file)
122 {
123 mylog_r_forread = mylog_r;
124 return 0;
125 }
126
127
128 //Define file_operation structure
129 static struct file_operations proc_mymsg_operations = {
130 .read = mymsg_read,
131 .open = mymsg_open,
132 };
133 //Entry function
134 static int mymsg_init(void)
135 {
136 //sprintf(mylog_buf, "%s", "abcdefghijklmnn"); //Simulate the data of forged buf
137 //Create proc entry
138 myentry = create_proc_entry("mymsg",S_IRUSR,NULL); //S_IRUSR:400 read only
139
140 if(myentry)
141 myentry->proc_fops = &proc_mymsg_operations;
142
143
144 return 0;
145 }
146 //Export function
147 static void mymsg_exit(void)
148 {
149 remove_proc_entry("mymsg", NULL);
150 }
151
152 module_init(mymsg_init);
153 module_exit(mymsg_exit);
154
155 MODULE_LICENSE("GPL");
156 MODULE_AUTHOR("Lover Cher");
157
158 EXPORT_SYMBOL(myprintk);
159
160
161 /*
162 1. Ring Buffer
163 Empty: R == W
164 write: buf[W] = val;
165 W = (W+1) % 10;
166 Read: val = buf[R]
167 R = (R+1) % 10
168
169
170
171 */
Attached is the test program err_led.c
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8 #include
9 #include
10 #include
11 #include
12 #include
13 #include
14
15 #define Driver_NAME "err_led_dev"
16 #define DEVICE_NAME "err_led_dev"
17
18 static int major = 0;
19
20 //auto to create device node
Previous article:Debug analysis: PC pointer analysis error based on kernel error information
Next article:iMX257 pin configuration function/memory read and write function
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- CGD and Qorvo to jointly revolutionize motor control solutions
- CGD and Qorvo to jointly revolutionize motor control solutions
- Keysight Technologies FieldFox handheld analyzer with VDI spread spectrum module to achieve millimeter wave analysis function
- Infineon's PASCO2V15 XENSIV PAS CO2 5V Sensor Now Available at Mouser for Accurate CO2 Level Measurement
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- Advanced gameplay, Harting takes your PCB board connection to a new level!
- A new chapter in Great Wall Motors R&D: solid-state battery technology leads the future
- Naxin Micro provides full-scenario GaN driver IC solutions
- Interpreting Huawei’s new solid-state battery patent, will it challenge CATL in 2030?
- Are pure electric/plug-in hybrid vehicles going crazy? A Chinese company has launched the world's first -40℃ dischargeable hybrid battery that is not afraid of cold
- Revolutionizing radar design with electronically reconfigurable GaN power amplifiers
- EEWORLD University - MSP430FR2433 ADC wake-up and transmission exercises
- Disassemble a simple bracelet
- How UWB calculates location
- [Repost] When choosing a finished power module, should you use an isolated or non-isolated power solution?
- Qorvo Q&A on Connectivity: Reducing Wi-Fi Interference
- What device is used to heat the chip on the motherboard in low temperature outdoor conditions?
- CB5654 Development Board Evaluation 3 - Building a Development Environment
- Two-phase brushless DC motor speed control system based on DSP and CPLD
- 15. [Learn LPC1768 library functions]