📄 sw4.c
字号:
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/interrupt.h> /* for in_interrupt */
#include <linux/timer.h>
#include <linux/init.h>
#include <linux/delay.h> /* for udelay */
#include <linux/modversions.h>
#include <linux/miscdevice.h>
#include <linux/version.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/hardware.h>
#define IRQ_KBD IRQ_EINT1 //linux在初始化的时候已经把每个中断向量的地址准备好
IRQ_EINT1是外部1号中断
#define GPIO_SimpleINT_EINT2 (GPIO_MODE_ALT0 | GPIO_PULLUP_EN | GPIO_F2) //通用输入输出口设置For ringing
#define ZLGCSDIS() (GPBDAT |=(0x01 << 6))//片选置成无效
#define ZLGCSEN() (GPBDAT &=~(0x01 << 6))// 片选置成有效
#define ZLGMO() (GPBDAT &=~(0x01 << 0))//置成输出方向
#define ZLGMI() (GPBDAT |=(0x01 << 0))// 置成输入方向
#define Keypad_MAJOR 97//定义键盘设备号
devfs_handle_t dev_handle; /* register handle to store device fs */
static unsigned char Keycode = 0;
static unsigned char haveData = 0;
static DECLARE_WAIT_QUEUE_HEAD(keypad);// 经过宏展开后就是定义了一个keypad等待队列头变量,核心运行过程中,经常会因为某些条件不满足而需要挂起当前线程,直至条件满足了才继续执行
static unsigned char spiRead();
static void spi_Init();
static void ZLG_interrupt(int nr, void *devid, struct pt_regs *regs);
ssize_t keypad_read (struct file * file ,char * buf, size_t count, loff_t * f_ops)
{
interruptible_sleep_on(&keypad);//挂起程序
copy_to_user(buf, &Keycode, sizeof Keycode);
haveData = 0;
return 1;
}
ssize_t SimpleINT_open (struct inode * inode ,struct file * file)
{
printk("s3c2410:device open operation!\n");
return 0;
}
struct file_operations Keypad_ops ={
open: SimpleINT_open,
read: keypad_read,
// poll: keypad_select,
};
//中断处理函数
static void ZLG_interrupt(int nr, void *devid, struct pt_regs *regs)
{
Keycode = spiRead();
haveData = 1;
wake_up_interruptible(&keypad);//唤醒程序
}
static int __init keypad_init(void)//键盘初始化程序
{
int ret = -ENODEV;
spi_Init();//spi外围串口初始化程序
set_external_irq(IRQ_KBD,EXT_FALLING_EDGE, GPIO_PULLUP_EN);
//请求中断
ret = devfs_register_chrdev(Keypad_MAJOR, "Keypad", &Keypad_ops);
//字符设备注册,主设备号,设备名,函数关联结构体
if( ret < 0 ){
printk (" Keypad: init_module failed with %d\n", ret);
return ret;
}
ret = request_irq(IRQ_KBD, ZLG_interrupt, SA_INTERRUPT,
"Keypad", NULL);// 注册中断服务程序,把中断向量和中断服务程序对应起来。
if (ret) {
devfs_unregister_chrdev(Keypad_MAJOR, "Keypad");//取消注册
printk(KERN_INFO "request Keypad IRQ failed (%d)\n", IRQ_KBD);
return ret;
}
dev_handle = devfs_register( NULL, "Keypad", DEVFS_FL_DEFAULT,
Keypad_MAJOR, 0, S_IFCHR, &Keypad_ops, NULL);
//登记设备入口点,获得文件句柄
return ret;
}
int spiWrite(u8 keycode)
{
ZLGCSEN();
ZLGMO();
udelay(60);
while((SPSTA1 & 0x01)== 0);
SPTDAT1 = keycode;//数据寄存器
while((SPSTA1 & 0x01)== 0);
ZLGCSDIS();
return 0;
}
static unsigned char spiRead(void)
{
unsigned char code;
ZLGCSEN();
ZLGMO();
udelay(60);
while((SPSTA1 & 0x01)== 0);
SPTDAT1 = 0x15;
while((SPSTA1 & 0x01)== 0);
udelay(30);
ZLGMI();
SPTDAT1 = 0xff;//状态寄存器
while((SPSTA1 & 0x01)== 0);
ZLGCSDIS();
ZLGMO();
code = SPSTA1; //状态寄存器
return code;
}
static void spi_Init()//spi外围串口初始化程序
{
// Setup IO port for SPI interface & Keyboard
// Setup EINT1 (KBDINT)
GPFCON &= ~(0x3 << 2); // Clear GPF1
GPFCON |= (0x2 << 2); // Set GPF1 to EINT1 for Keyboard interrupt
EXTINT0 &= ~(0x7 << 4); // Clear EINT1
EXTINT0 |= (0x2 << 4); // fallig edge triggered for EINT1
// setup SPI interface
GPGCON &= ~((0x3 << 10) | (0x3 << 12) | (0x3 << 14)); // Clear GPG5,6,7
GPGCON |= ((0x3 << 10) | (0x3 << 12) | (0x3 << 14));
// setup _SS signal(nSS_KBD)
GPBCON &= ~(0x3 << 12); // Clear GPB6
GPBCON |= (0x01 << 12); // Set Port GPB6 to output for nSS signal
ZLGCSDIS(); // Set /SS high
// setup Dir signal (KEYBOARD) CPU->7289
GPBCON &= ~(0x3 << 0); // Clear GPB0
GPBCON |= (0x01 << 0); // Set Port GPB0 to output for _PWR_OK signal
ZLGMO();
// Setup SPI registers
SPCON1 = (0<<5)|(0X01 << 4)|(0X01 << 3)|(0x0<<2)|(0<<1);
// Developer MUST change the value of prescaler properly whenever value of PCLK is changed.
SPPRE1 = 255; // 99.121K = 203M/4/2/(255+1) PCLK=50.75Mhz FCLK=203Mhz SPICLK=99.121Khz
spiWrite(0xa4); //send init command
printk("Key Pad Init complete:\n");
}
/*static int keypad_select(struct file *file, struct poll_table_struct *wait)
{
if(haveData)
return 1;
return 0;
}*/
int __init sw4_init_module()
{
int ret = -ENODEV;
ret = keypad_init();//键盘初始化
if (ret)
return ret;
return 0;
}
void __exit sw4_cleanup_module()
{
free_irq(IRQ_KBD, NULL);// 释放中断
devfs_unregister_chrdev( Keypad_MAJOR, "Keypad" );//注销设备号
devfs_unregister( dev_handle );//注销设备文件句柄
return;
}
module_init(sw4_init_module);//内核特殊的宏,指明次函数为模块
module_exit(sw4_cleanup_module);
MODULE_LICENSE("GPL");//采用GPL软件许可证
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -