控制LED灯的亮灭
head.h
# ifndef __HEAD_H__
# define __HEAD_H__
# define PHY_LED1_MODER 0X50006000
# define PHY_LED1_ODR 0X50006014
# define PHY_LED2_MODER 0X50007000
# define PHY_LED2_ODR 0X50007014
# define PHY_LED3_MODER 0X50006000
# define PHY_LED3_ODR 0X50006014
# define PHY_RCC 0X50000A28
# endif
test.c
# include <stdio.h>
# include <stdlib.h>
# include <sys/types.h>
# include <sys/stat.h>
# include <fcntl.h>
# include <unistd.h>
# include <string.h>
int main ( int argc, char const * argv[ ] )
{
char buf[ 128 ] = { 0 } ;
int fd = open ( "/dev/mychrdev" , O_RDWR) ;
if ( fd < 0 )
{
printf ( "打开设备文件失败\n" ) ;
exit ( - 1 ) ;
}
while ( 1 )
{
printf ( "请输入控制命令--11:LED1开灯 10:LED1关灯\n21:LED2开灯 20:LED2关灯\n31:LED3开灯 30:LED3关灯>>>" ) ;
fgets ( buf, sizeof ( buf) , stdin ) ;
buf[ strlen ( buf) - 1 ] = '\0' ;
write ( fd, buf, sizeof ( buf) ) ;
}
close ( fd) ;
return 0 ;
}
mychrdev.c
# include <linux/init.h>
# include <linux/module.h>
# include <linux/fs.h>
# include <linux/uaccess.h>
# include <linux/io.h>
# include "head.h"
int major;
char kbuf[ 128 ] = { 0 } ;
unsigned int * vir_led1_moder;
unsigned int * vir_led1_odr;
unsigned int * vir_led2_moder;
unsigned int * vir_led2_odr;
unsigned int * vir_led3_moder;
unsigned int * vir_led3_odr;
unsigned int * vir_rcc;
int mycdev_open ( struct inode * inode, struct file * file)
{
printk ( "%s:%s:%d\n" , __FILE__ , __func__ , __LINE__ ) ;
return 0 ;
}
ssize_t mycdev_read ( struct file * file, char * ubuf, size_t size, loff_t * lof)
{
int ret;
if ( sizeof ( kbuf) < size)
size = sizeof ( kbuf) ;
ret = copy_to_user ( ubuf, kbuf, size) ;
if ( ret)
{
printk ( "copy to user filed\n" ) ;
return - EIO;
}
printk ( "%s:%s:%d\n" , __FILE__ , __func__ , __LINE__ ) ;
return 0 ;
}
ssize_t mycdev_write ( struct file * file, const char * ubuf, size_t size, loff_t * lof)
{
int ret;
if ( sizeof ( kbuf) < size)
size = sizeof ( kbuf) ;
ret = copy_from_user ( kbuf, ubuf, size) ;
if ( ret)
{
printk ( "copy from user filed\n" ) ;
return - EIO;
}
if ( kbuf[ 0 ] == '1' && kbuf[ 1 ] == '1' )
{
( * vir_led1_odr) |= ( 0x1 << 10 ) ;
}
else if ( kbuf[ 0 ] == '1' && kbuf[ 1 ] == '0' )
{
( * vir_led1_odr) &= ( ~ ( 0x1 << 10 ) ) ;
}
if ( kbuf[ 0 ] == '2' && kbuf[ 1 ] == '1' )
{
( * vir_led2_odr) |= ( 0x1 << 10 ) ;
}
else if ( kbuf[ 0 ] == '2' && kbuf[ 1 ] == '0' )
{
( * vir_led2_odr) &= ( ~ ( 0x1 << 10 ) ) ;
}
if ( kbuf[ 0 ] == '3' && kbuf[ 1 ] == '1' )
{
( * vir_led3_odr) |= ( 0x1 << 8 ) ;
}
else if ( kbuf[ 0 ] == '3' && kbuf[ 1 ] == '0' )
{
( * vir_led3_odr) &= ( ~ ( 0x1 << 8 ) ) ;
}
printk ( "%s:%s:%d\n" , __FILE__ , __func__ , __LINE__ ) ;
return 0 ;
}
int mycdev_close ( struct inode * inode, struct file * file)
{
printk ( "%s:%s:%d\n" , __FILE__ , __func__ , __LINE__ ) ;
return 0 ;
}
struct file_operations fops =
{
. open = mycdev_open,
. read = mycdev_read,
. write = mycdev_write,
. release = mycdev_close,
} ;
static int __init mycdev_init ( void )
{
major = register_chrdev ( 0 , "mychrdev" , & fops) ;
if ( major < 0 )
{
printk ( "字符驱动设备注册失败\n" ) ;
return major;
}
printk ( "字符驱动注册成功major = %d\n" , major) ;
vir_led1_moder = ioremap ( PHY_LED1_MODER, 4 ) ;
if ( vir_led1_moder== NULL )
{
printk ( "MODER寄存器地址映射失败\n" ) ;
return - EFAULT;
}
vir_led1_odr = ioremap ( PHY_LED1_ODR, 4 ) ;
if ( vir_led1_odr== NULL )
{
printk ( "ODR寄存器地址映射失败\n" ) ;
return - EFAULT;
}
vir_led2_moder = ioremap ( PHY_LED2_MODER, 4 ) ;
if ( vir_led2_moder== NULL )
{
printk ( "MODER寄存器地址映射失败\n" ) ;
return - EFAULT;
}
vir_led2_odr = ioremap ( PHY_LED2_ODR, 4 ) ;
if ( vir_led2_odr== NULL )
{
printk ( "ODR寄存器地址映射失败\n" ) ;
return - EFAULT;
}
vir_led3_moder = ioremap ( PHY_LED3_MODER, 4 ) ;
if ( vir_led3_moder== NULL )
{
printk ( "MODER寄存器地址映射失败\n" ) ;
return - EFAULT;
}
vir_led3_odr = ioremap ( PHY_LED3_ODR, 4 ) ;
if ( vir_led3_odr== NULL )
{
printk ( "ODR寄存器地址映射失败\n" ) ;
return - EFAULT;
}
vir_rcc = ioremap ( PHY_RCC, 4 ) ;
if ( vir_rcc== NULL )
{
printk ( "MODER寄存器地址映射失败\n" ) ;
return - EFAULT;
}
printk ( "寄存器地址映射成功\n" ) ;
( * vir_rcc) |= ( 0x1 << 4 ) ;
( * vir_rcc) |= ( 0x1 << 5 ) ;
( * vir_led1_moder) &= ( ~ ( 0x3 << 20 ) ) ;
( * vir_led1_moder) |= ( 0x1 << 20 ) ;
( * vir_led1_odr) &= ( ~ ( 0x1 << 10 ) ) ;
( * vir_led2_moder) &= ( ~ ( 0x3 << 20 ) ) ;
( * vir_led2_moder) |= ( 0x1 << 20 ) ;
( * vir_led2_odr) &= ( ~ ( 0x1 << 10 ) ) ;
( * vir_led3_moder) &= ( ~ ( 0x3 << 16 ) ) ;
( * vir_led3_moder) |= ( 0x1 << 16 ) ;
( * vir_led3_odr) &= ( ~ ( 0x1 << 8 ) ) ;
return 0 ;
}
static void __exit mycdev_exit ( void )
{
iounmap ( vir_led1_moder) ;
iounmap ( vir_led1_odr) ;
iounmap ( vir_led2_moder) ;
iounmap ( vir_led2_odr) ;
iounmap ( vir_led3_moder) ;
iounmap ( vir_led3_odr) ;
iounmap ( vir_rcc) ;
unregister_chrdev ( major, "mychrdev" ) ;
}
module_init ( mycdev_init) ;
module_exit ( mycdev_exit) ;
MODULE_LICENSE ( "GPL" ) ;
效果展示