

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/cdev.h>
#include <linux/fs.h>
#include <linux/errno.h>
#include <asm/current.h>
#include <linux/sched.h>
#include <linux/device.h>
#include <linux/err.h>
#include <asm/uaccess.h>
#include <linux/delay.h>
#include <linux/uaccess.h>
#include <asm-generic/ioctl.h>

#include <linux/interrupt.h>
#include <linux/irqreturn.h>
#include <linux/wait.h>

#include "stm32f4xx.h"
#include "stm32f4xx_hal_gpio.h"
#include "stm32_hal_legacy.h"
#include "stm32f4xx_hal_iwdg.h"
#include "driver.h"

#define DEVNAME "watchdog"
dev_t devno;
struct cdev cdev;
IWDG_HandleTypeDef IwdgHandle;

static int iwdg_open(struct inode *inode, struct file *filep);
static int iwdg_close(struct inode *inode, struct file *filep);
static ssize_t iwdg_read(struct file *filep, char __user *buf, size_t size, loff_t *offset);
static ssize_t iwdg_write(struct file *filep, const char __user *buf, size_t size, loff_t *offset);
static int iwdg_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg);

static struct file_operations iwdg_ops = 
{
	.owner = THIS_MODULE,
	.open = iwdg_open,
	.release = iwdg_close,
	.ioctl = iwdg_ioctl,
	.read = iwdg_read,
	.write = iwdg_write,
	
};

static int iwdg_open(struct inode *inode, struct file *filep)
{
	return 0;
}

static int iwdg_close(struct inode *inode, struct file *filep)
{
	return 0;
}


void iwdg_hw_init(void)
{

  IwdgHandle.Instance = IWDG;
  IwdgHandle.Init.Prescaler = IWDG_PRESCALER_128;	//4ms
  IwdgHandle.Init.Reload    = 2500;	//10s	//最大4095

  if (HAL_IWDG_Init(&IwdgHandle) != HAL_OK)
  {
    /* Initialization Error */
   	printk("Init iwdg error!\n");
  }
}

static int iwdg_ioctl(struct inode *inode, struct file *filep, unsigned int cmd, unsigned long arg)
{
	int retval = 0;
	switch(cmd)
	{
	case FEED_WATCHDOG:
		if (HAL_IWDG_Refresh(&IwdgHandle) != HAL_OK)
		{
			printk("Feed IWDG error!\n");
			return -1;
		}
		break;
	case START_IWATCHDOG:
		iwdg_hw_init();
		printk("Independent Watch dog start...\n");
		break;
	case STOP_IWATCHDOG:
		break;
	default:
		printk("---> Invalid action\n");
		return -1;
		break;

	}	
	return retval;
}

static ssize_t iwdg_read(struct file *filep, char __user *buf, size_t size, loff_t *offset)
{
	return 0;
}

static ssize_t iwdg_write(struct file *filep, const char __user *buf, size_t size, loff_t *offset)
{
	return 0;
}

static int __init iwdg_init(void)
{
	printk("iwdg module start...\n");
    devno = MKDEV(MAJOR_IWDG, 0);
	register_chrdev_region(devno, 1, DEVNAME);
	     
	cdev_add(&cdev, devno, 1);
	cdev_init(&cdev, &iwdg_ops);

	//iwdg_hw_init();	

	return 0;
}

static void __exit iwdg_exit(void)
{
	unregister_chrdev_region(devno, 1);
	cdev_del(&cdev);
}

module_init(iwdg_init);
module_exit(iwdg_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jimbo");
MODULE_DESCRIPTION("this is watchdog module");



