最简陋的arm定时器1s定时程序

               

最简陋的arm定时器1s定时程序

#include <linux/version.h>
#include <linux/config.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
#include <linux/fcntl.h>
#include <linux/slab.h>
#include <linux/poll.h>
#include <asm/system.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/delay.h>
#include <linux/miscdevice.h>
#include <linux/sched.h>
#include <asm/arch/hardware.h>//这个头文件里的__REG()宏返回的就是寄存器的虚拟地址,在下面程序里(驱动程序里用的都是虚拟地址,不能用物理地址)
#include <asm/delay.h>
#include <asm/arch/irqs.h>
#include <asm/arch/S3C2410.h>

#define KERNEL_DEBUG

#define DEVICE_NAME "mytimer"
#define CB_MAJOR 232

#define TIMER_OUT GPIO_C12    //用一个GPIO口告诉外设定时到
static devfs_handle_t devfs_h;
char timer_out=0;
void initial_timer()
{    int bb;
    //powermanagement MPLL M=0x52,P=2,S=3
    //MPLLCON=0x00052023;//这句在系统启动后似乎不能加上,估计启动后不能重写这个寄存器
    /*    
    bb=MPLLCON;//这里读到的值是5c040,若采用这个值则16和256分频后为48828.125Hz    
    printk("MPLLCO=%x/n",bb);
    */
    //mux=11, 16分频
    TCFG1=0x00000003;
    
    //prescalor=256
    TCFG0=0x000000FF;
    
    TCNTB0=0xBEBC;//48828
    TCMPB0=0xBEBC/2;
    
    bb=TCON;
    TCON=bb|0x2;//set the manual update bit
   
    bb=TCON;
    TCON=bb|0x4;//set the inverter bit
    //start timer0
    bb=(bb&0xD)|0x9;//reset manual update bit,set the start bit and reload bit
    TCON=bb;
}
//以下几个接口都是空壳
static ssize_t timer_read(struct file *file,char *buffer,size_t count,loff_t *ppos)
{    return 0;
}

static ssize_t timer_write(struct file *file, const char *buffer, size_t count)
{
    return 0;
}

static int timer_ioctl(struct inode *inode, struct file *file ,unsigned int cmd, unsigned long arg)
{
    return 0;
}
//发生中断时执行此函数
static void timer_irq(int irq,void *dev_id,struct pt_regs *reg)
{
    int found=0;
    printk("into the ISR/n");
    if(irq==IRQ_TIMER0)
    {    printk("time out irq%d",irq);
        found=1;
    }
    if(!found)
    {
        printk("Bad irq%d",irq);
        return;
    }
    if(timer_out==0)
    {    timer_out=1;
        write_gpio_bit(TIMER_OUT,0);
    }
    else
    {    timer_out=0;
        write_gpio_bit(TIMER_OUT,1);
    }
}

static struct file_operations timer_fops={
    owner: THIS_MODULE,
    write: timer_write,
    //poll:     timer_select,
    read: timer_read,
    ioctl: timer_ioctl,    
};

//整个驱动的初始化入口
static int __init timer_init(void)
{
    int ret;
    ret=register_chrdev(CB_MAJOR,DEVICE_NAME,&timer_fops);
    printk("get to timer!/n");
    set_gpio_ctrl(GPIO_MODE_OUT|GPIO_PULLUP_EN|TIMER_OUT);
    write_gpio_bit(TIMER_OUT,1);
    
    initial_timer();
    printk("after initial_timer()/n");
    if(ret<0)
    {
        printk(DEVICE_NAME" can't register major number/n");
        return ret;
    }
    //关联中断和中断函数
    if(request_irq(IRQ_TIMER0,&timer_irq,SA_INTERRUPT,DEVICE_NAME,&timer_irq))
    {
        printk(DEVICE_NAME "can't request irqs/n");
        return -1;
    }
  //关联设备和fops结构    
 devfs_h=devfs_register(NULL,DEVICE_NAME,DEVFS_FL_DEFAULT,CB_MAJOR,0,S_IFCHR|S_IRUSR|S_IWUSR,&timer_fops,NULL);
    return 0;
}

static void __exit timer_exit(void)
{
    devfs_unregister(devfs_h);
    free_irq(IRQ_TIMER0,timer_irq);
    unregister_chrdev(CB_MAJOR, DEVICE_NAME);
}
module_init(timer_init);
module_exit(timer_exit);
           

再分享一下我老师大神的人工智能教程吧。零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到我们人工智能的队伍中来!https://blog.csdn.net/jiangjunshow

猜你喜欢

转载自blog.csdn.net/hffyfdt/article/details/86659979