3.15作业

这段代码是一个简单的Linux内核设备驱动程序,用于控制LED状态。它打开名为/myled的字符设备,读写操作用于切换LED的状态。内核函数如open、read、write和release被实现。驱动程序还使用ioremap进行内存映射来访问GPIO寄存器以控制LED的亮灭。

1 #include <stdio.h>

2 #include <sys/types.h>

3 #include <sys/stat.h>

4 #include <fcntl.h>

5 #include <unistd.h>

6 #include <errno.h>

7 #include <string.h>

8

9 int main(int argc,const char * argv[])

10 {

11 char buf[128] = {0};

12 int fd = -1;

13 fd = open("/dev/myled",O_RDWR);

14 if(fd == -1)

15 {

16 perror("open is error\n");

17 return -1;

18 }

19

20 while(1)

21 {

22 buf[0] = !buf[0];

23 write(fd,buf,1);

24 sleep(1);

25 }

26

27 close(fd);

28 return 0;

29 }

10 #define CNAME "myled"

11 int major;

12

13 int kbuf[128]={};

14 unsigned int* rccp;

15 unsigned int* led1moderp;

16 unsigned int* led1odp;

17

18 unsigned int* led2moderp;

19 unsigned int* led2odp;

20

21 unsigned int* led3moderp;

22 unsigned int* led3odp;

23

24 int (myled_open) (struct inode *inode, struct file *file)

25 {

26 printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

27 return 0;

28 }

29

30 ssize_t (myled_read) (struct file *file, char __user *ubuf, size_t size,loff_t *loff)

31 {

32

33 printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

34 int ret;

35 if(size > sizeof(kbuf)) size = sizeof(kbuf);

36

37 ret=copy_to_user(ubuf,kbuf,size);

38 if(ret)

39 {

40 printk("copy to user is error\n");

41 return -EIO;

42 }

43 return size;

44

45 }

46

47 ssize_t (myled_write) (struct file *file, const char __user *ubuf, size_t size,loff_t *loff)

48 {

49

50 int ret;

51 printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

52 //1.校验传输数据的大小,如果用户空间写的数据比内核空间数据大小大,需要更正大小

53 if(size > sizeof(kbuf)) size = sizeof(kbuf);

54 //2.将数据从用户空间拷贝到内核空间

55 ret = copy_from_user(kbuf,ubuf,size);

56 if(ret) //3.判断是否错误

57 {

58 printk("copy from user is error\n");

59 return -EIO;

60 }

61 //4.打印传递数据内容

62 printk("copy from user kbuf:%s\n",kbuf);

63 if(kbuf[0] == 1)

64 {

65 *led1odp |= (0x1 << 10); //LED1点亮

66 *led2odp |= (0x1 << 10); //LED1点亮

67 *led3odp |= (0x1 << 8); //LED1点亮

68 }

69 else

70 {

71 *led1odp &= (~(0x1 << 10)); //LED1写灭;

72 *led2odp &= (~(0x1 << 10)); //LED1写灭;

73 *led3odp &= (~(0x1 << 8)); //LED1写灭;

74 }

75

76 return size; //5.返回拷贝数据大小

77 }

78

79 int (myled_release) (struct inode *inode, struct file *file)

80 {

81

82 printk("%s:%s:%d\n",__FILE__,__func__,__LINE__);

83 }

84

85 const struct file_operations fops=

86 {

87

88 .open=myled_open,

89 .read=myled_read,

90 .write=myled_write,

91 .release=myled_release,

92 };

93

94

95 static int __init demo_init(void)

96 {

97 major=register_chrdev(0,CNAME,&fops);

98

99 if(major<0)

100 {

101 printk("register_chrdev is error\n");

102 }

103 else

104 {

105 printk("register_chrdev is %d\n",major);

106 }

107

108

109

110 rccp=ioremap(RCC,4);

111

112 led1moderp=ioremap(GPIOE_MOD,4);

113

114 led1odp=ioremap(GPIOE_ODR,4);

115

116 led2moderp=ioremap(GPIOF_MOD,4);

117

118 led2odp=ioremap(GPIOF_ODR,4);

119

120 led3moderp=ioremap(GPIOE_MOD,4);

121

122 led3odp=ioremap(GPIOE_ODR,4);

123

124 *rccp |= 0x3<<4;

125 *led1moderp &= (~(0x3<<20));

126 *led1moderp |= ((0x1<<20));

127 *led1odp &= (~(0x1<<10));

128

129 *led2moderp &= (~(0x3<<20));

130 *led2moderp |= ((0x1<<20));

131 *led2odp &= (~(0x1<<10));

132

133 *led3moderp &= (~(0x3<<16));

134 *led3moderp |= ((0x1<<16));

135 *led3odp &= (~(0x1<<8));

136

137

138 return 0;

139 }

140

141 static void __exit demo_exit(void)

142 {

143 iounmap(rccp);

144 iounmap(led1moderp);

145 iounmap(led1odp);

146 iounmap(led2moderp);

147 iounmap(led2odp);

148 iounmap(led3moderp);

149 iounmap(led3odp);

150 unregister_chrdev(major,CNAME);

151 }

152

153

154

155

156

157 module_init(demo_init);

158 module_exit(demo_exit);

159

160 MODULE_LICENSE("GPL");

161

162

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值