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

error = wait_event_interruptible(mylog_wait,!is_mylog_empty());

/* If copy_to_user is correct, the string is obtained successfully*/

while( !error && (mylog_getc(&c)) && i < count ){

error = __put_user(c, buf); //Equivalent to copy_to_user

buf++;

i++;

}

if(!error)

error = i;

return error;

}


When the application uses cat to read /proc/mymsg, if the program is started in a non-blocking manner and buff is empty, it returns directly, otherwise it puts the program into an interruptible sleep.


The condition for waking up is that buff is not empty. When the program is awakened, the copy_to_user function is called to copy the data to the user process for printing.


8. Modify the test driver err_led.c.


First, import the myprintk function externally, and then modify all the printk functions of the test driver to myprintk function.


1 extern int myprintk(const char *fmt, ...); //Introduce external declaration

2

3 static int key_open(struct inode *inode, struct file *file)

4 {

5 myprintk("<0>function open!nn"); //Change printk to myprintk

6 return 0;

7 }


9. Compile and test:


Pay attention to the order in which you load the drivers.


① Load the mymsg.ko driver


② Load the test/err_led.ko driver: Found that the err_led light on the board is flashing, wait for the led to finish flashing


③ Read cat /proc/mymsg: It is found that the message that our err_led wants to print is successfully printed, as shown below


④ Uninstall test/err_led.ko: Found that err_led on the board is flashing, wait until the flashing is finished


⑤ Read cat /proc/mymsg: There is an additional goodbye message at the end of the message, success


⑥Uninstall mymsg.ko driver

1c5bffea79d2618b23cf1ce4a4ba0d9f_1U2H2dwpL9AAAAAASUVORK5CYII=.png

Attach the driver mymsg_4.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_w = ​​0;

20

21 static DECLARE_WAIT_QUEUE_HEAD(mylog_wait);

twenty two

23 //Judge whether it is empty

24 static int is_mylog_empty(void)

25 {

26 return (mylog_r == mylog_w);

27 }

28 //Judge whether it is full

29 static int is_mylog_full(void)

30 {

31 return (((mylog_w + 1) % MYLOG_BUF_LEN) == mylog_r);

32 }

33 //Write characters

34 static void mylog_putc(char c)

35 {

36 if(is_mylog_full)

37 {

38 //Discard a data

39 mylog_r = (mylog_r + 1) % MYLOG_BUF_LEN;

40 }

41 mylog_buf[mylog_w] = c;

42 mylog_w = ​​(mylog_w + 1) % MYLOG_BUF_LEN;

43

44 /* Wake up the process waiting for data */

45 wake_up_interruptible(&mylog_wait);

46 }

47 //Read characters

48 static int mylog_getc(char *p)

49 {

50 if(is_mylog_empty())

51 return 0;

52 *p = mylog_buf[mylog_r];

53 mylog_r = (mylog_r + 1) % MYLOG_BUF_LEN;

54 return 1;

55 }

56

57 //Print output Refer to sprintf in vsprintf.c

58 int myprintk(const char *fmt, ...)

59 {

60 va_list args;

61 int i,j;

62

63 va_start(args, fmt);

64 i = vsnprintf(tmp_buf, INT_MAX, fmt, args);

65 va_end(args);

66 for(j = 0; j

67 {

68 mylog_putc(tmp_buf[j]);

69 }

70 return 1;

71 }

72 EXPORT_SYMBOL(myprintk);

73

74 //Realize the read function, refer to kmsg.c

75 static ssize_t mymsg_read(struct file *file, char __user *buf,size_t count, loff_t *ppos)

76 {

77 int error;

78 int i = 0; //The number of data read

79 char c;

80

81 //Open with non-blocking mode and the data queue is empty

82 if ((file->f_flags & O_NONBLOCK) && is_mylog_empty())

83 return -EAGAIN;

84

85 //Wait until the queue is not empty

86 error = wait_event_interruptible(mylog_wait,!is_mylog_empty());

87

88 /* If copy_to_user is correct, the string is obtained successfully*/

89 while( !error && (mylog_getc(&c)) && i < count ){

90 error = __put_user(c, buf); //Equivalent to copy_to_user

91 buf++;

92 i++;

93 }

94 if(!error)

95 error = i;

96 return error;

97 }

98

99 //Define file_operation structure

100 static struct file_operations proc_mymsg_operations = {

101 .read = mymsg_read,

102 };

103 //Entry function

104 static int mymsg_init(void)

105 {

106 //sprintf(mylog_buf, "%s", "abcdefghijklmnn"); //Simulate the data of forged buf

107 //Create proc entry

108 myentry = create_proc_entry("mymsg",S_IRUSR,NULL); //S_IRUSR:400 read only

109

110 if(myentry)

111 myentry->proc_fops = &proc_mymsg_operations;

112

113

114 return 0;

115 }

116 //Export function

117 static void mymsg_exit(void)

118 {

119 remove_proc_entry("mymsg", NULL);

120 }

121

122 module_init(mymsg_init);

123 module_exit(mymsg_exit);

124

125 MODULE_LICENSE("GPL");

126 MODULE_AUTHOR("Lover Cher");

127

128

129 /*

130 1. Ring Buffer

131 Empty: R == W

132 write: buf[W] = val;

133 W = (W+1) % 10;

134 Read: val = buf[R]

135 R = (R+1) % 10

136

137

138

139 */


Attached is the test driver 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

21 static struct class *drv_class = NULL;

22 static struct class_device *drv_class_dev = NULL;

twenty three

24 //Register base address;

25 static unsigned long base_iomux; //iomux base address 0X 43FA C000 - 0X 43FA FFFF

26 static unsigned long base_gpio3; //gpio3 0X 53FA 4000 - 0X 53FA 7FFF

27 //MUX_CTL mode selection configuration register

28 #define MUX_CTL (*(volatile unsigned long *)(base_iomux + 0x0060))

29 //PAD_CTL GPIO common function settings

30 #define PAD_CTL (*(volatile unsigned long *)(base_iomux + 0x0270))

31 //GPIO DR data register DR

32 #define DR_GPIO3 (*(volatile unsigned long *)(base_gpio3 + 0x0000))

33 // GPIO GDIR direction control register GDIR

34 #define GDIR_GPIO3 (*(volatile unsigned long *)(base_gpio3 + 0x0004))

35

36

37 extern int myprintk(const char *fmt, ...);

38

39 static int key_open(struct inode *inode, struct file *file)

40 {

41 myprintk("<0>function open!nn");

42 return 0;

43 }

44

45 static int key_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)

46 {

47 return 0;

48 }

49

50 static ssize_t key_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos)

51 {

52 myprintk("<0>function write!nn");

53 return 1;

54 }

55

56 static int key_release(struct inode *inode, struct file *filp)

57 {

58 myprintk("<0>function write!nn");

59 return 0;

60 }

61

62 static int key_ioctl(struct inode *inode,struct file *flip,unsigned int command,unsigned long arg)

63 {

64 myprintk("<0>function ioctl!nn");

65 return 0;

66 }

67 static struct file_operations key_fops = {

68 .owner = THIS_MODULE, /* This is a macro that pushes to the __this_module variable that is automatically created when compiling the module*/

69 .open = key_open,

70 .read = key_read,

71 .write = key_write,

72.release= key_release,

73 .ioctl = key_ioctl,

74 };

75

76 void gpio_addr(void){

77 myprintk("<0>addr base_iomux : %x n",base_iomux);

78 myprintk("<0>addr base_gpio3 : %x n",base_gpio3);

79 myprintk("<0>addr MUX_CTL : %x n",&MUX_CTL);

80 myprintk("<0>addr PAD_CTL : %x n",&PAD_CTL);

81 myprintk("<0>addr GDIR_GPIO3 : %x n",&GDIR_GPIO3);

82 myprintk("<0>addr DR_GPIO3 : %x n",&DR_GPIO3);

83 }

84

85 void led_on_off(void){

86 ssleep(1);

87 DR_GPIO3 |= (0x01 << 23); //Set GPIO2_23 to 1

88 ssleep(1);

89 DR_GPIO3 &= ~(0x01 << 23); // Clear GPIO2_23

90 ssleep(1);

91 DR_GPIO3 |= (0x01 << 23); //Set GPIO2_23 to 1

92 ssleep(1);

93 DR_GPIO3 &= ~(0x01 << 23); // Clear GPIO2_23

94 ssleep(1);

95 DR_GPIO3 |= (0x01 << 23); //Set GPIO2_23 to 1

96 ssleep(1);

97 DR_GPIO3 &= ~(0x01 << 23); // Clear GPIO2_23

98 ssleep(1);

99 DR_GPIO3 |= (0x01 << 23); //Set GPIO2_23 to 1

100 ssleep(1);

101 DR_GPIO3 &= ~(0x01 << 23); //Clear GPIO2_23

102 ssleep(1);

103 DR_GPIO3 |= (0x01 << 23); //Set GPIO2_23 to 1

104 }

105

106 static int __init key_irq_init(void)

107 {

108 myprintk("<0>nHello,this is %s module!nn",Driver_NAME);

109 //register and mknod

110 major = register_chrdev(0,Driver_NAME,&key_fops);

111 drv_class = class_create(THIS_MODULE,Driver_NAME);

112 drv_class_dev = device_create(drv_class,NULL,MKDEV(major,0),NULL,DEVICE_NAME); /*/dev/key_query*/

113

114 //IO port application ioremap can directly access these addresses through pointers

115 base_iomux = ioremap(0x43FAC000,0xFFF);

116 base_gpio3 = ioremap(0x53FA4000,0xFFF);

[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号