Debugging and analysis of the implementation of mymsg and myprintk under proc in imx257

Publisher:AdventureSeekerLatest update time:2024-08-13 Source: cnblogsKeywords:proc Reading articles on mobile phones Scan QR code
Read articles on your mobile phone anytime, anywhere

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

6f992ded9e4cdc4c1381cd7a0ec21101_wyT7+CWKue25qOB4vAAAAAElFTkSuQmCC.png

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

[1] [2] [3] [4]
Keywords:proc Reference address:Debugging and analysis of the implementation of mymsg and myprintk under proc in imx257

Previous article:Debug analysis: PC pointer analysis error based on kernel error information
Next article:iMX257 pin configuration function/memory read and write function

Latest Microcontroller Articles
Change More Related Popular Components

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

About Us Customer Service Contact Information Datasheet Sitemap LatestNews


Room 1530, 15th Floor, Building B, No.18 Zhongguancun Street, Haidian District, Beijing, Postal Code: 100190 China Telephone: 008610 8235 0740

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号