📄 lcd.c
字号:
#ifndef __KERNEL__#define __KERNEL__#endif#ifndef MODULE#define MODULE#endif#include <linux/kernel.h>#include <linux/module.h>#include <linux/init.h>#include <linux/delay.h>#include <linux/ioport.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/8xx_immap.h>/** Header files for the charcater device */#include <linux/fs.h>#include <linux/wrapper.h>#include "lcd.h"#define DEBUGstatic volatile immap_t *immap; /*define the struct immap_t pointer that represent memory map info */volatile unsigned long virt_base;/*lcd virtual address space base*/static int device_open_num = 0; /*record numbers of lcd device opening by usr */static int Major; /*the lcd device major number *//************************************************************************LCD hard interface functions*************************************************************************//**Initialize the driver -Register the character device*/static intlcd_init (void){ int ret; init_mem (); /* *Register the character device -lcd */ ret = register_chrdev (LCD_MAJOR, DEVICE_NAME, &lcd_ops); /* register lcd device faild */ if (ret < 0) { iounmap ((void *) virt_base); printk ("Lcd init_module register failed with %d\n major number\n", Major); return Major; } /*register successed */ Major = LCD_MAJOR; printk ("Lcd register major number :%d successed\n", Major); /* *Lcd function initial */ lcd_ctr_init (); writeb (LED_OFF, (LED_ADDR - LCD_BASE) + virt_base);/*turn off led */ //writeb (LED_OFF, LED_ADDR); /*turn off led */ return SUCCESS;}static intinit_mem (void){ immap = (immap_t *) (mfspr (IMMR) & 0xffff0000); immap->im_memctl.memc_br7 = BR7_SET; immap->im_memctl.memc_or7 = OR7_SET;#ifdef DEBUG printk ("br7 = 0x%08x\n", immap->im_memctl.memc_br7); printk ("or7 = 0x%08x\n", immap->im_memctl.memc_or7);#endif /*memory map */ virt_base = (unsigned long) ioremap (LCD_BASE, LCD_VIRT_LENGTH); return SUCCESS;}static voidlcd_ctr_init (void){ mdelay (15); lcd_set (FUNCTION_SET); mdelay (4); lcd_set (DISPLAY_OFF); lcd_set (DISPLAY_ON); lcd_set (INPUT_MODE_SET); lcd_set (DISPLAY_CLEAR);#ifdef DEBUG showch (0x48);#endif}static voidlcd_set (unsigned char command){ writeb (command, (LCD_DATA_ADDR-LCD_BASE)+virt_base); /*first output control command */ udelay (10); writeb (WRITE_REG | ENABLE_OFF, (LCD_CTRREG_ADDR - LCD_BASE) + virt_base); udelay (1); writeb (WRITE_REG | ENABLE_ON, (LCD_CTRREG_ADDR - LCD_BASE) + virt_base); udelay (1); writeb (WRITE_REG | ENABLE_OFF, (LCD_CTRREG_ADDR - LCD_BASE) + virt_base); mdelay (40); /*wait for command to ouput to lcd register */#ifdef DEBUG printk ("Lcd port output data finished\n");#endif}static voidshowch (unsigned char ch){ writeb (BIT_SWAP (ch), (LCD_DATA_ADDR - LCD_BASE) + virt_base); /*first output data to port */ udelay (10); writeb (WRITE_DATA | ENABLE_OFF, (LCD_CTRREG_ADDR - LCD_BASE) + virt_base); udelay (1); writeb (WRITE_DATA | ENABLE_ON, (LCD_CTRREG_ADDR - LCD_BASE) + virt_base); udelay (1); writeb (WRITE_DATA | ENABLE_OFF, (LCD_CTRREG_ADDR - LCD_BASE) + virt_base); mdelay (40); /*wait for date to ouput to lcd ram */}/*******************************************************Standard driver operation functions****************************************************************//**Called whenever a process attempt to open the lcd device*/static intdevice_open (struct inode *inode, struct file *lcd_device_file){ if (device_open_num) /*ensure open lcd device exclusively */ { return -EBUSY; /*lcd device has been open by other process */ } /* *Make sure that this module isn't removed while *the lcd is open by increasing the lcd usage count */ if (check_region (LCD_BASE, LCD_VIRT_LENGTH)) { printk ("%s memory already in use\n", DEVICE_NAME); return -EBUSY; } request_region (LCD_BASE, LCD_VIRT_LENGTH, DEVICE_NAME); device_open_num++; MOD_INC_USE_COUNT; lcd_set (DISPLAY_CLEAR); lcd_set (INPUT_MODE_SET);#ifdef DEBUG printk (DEVICE_NAME " open successed \n");#endif return SUCCESS;}/**Called whenever a process closes the lcd device*/static intdevice_release (struct inode *inode, struct file *lcd_device_file){ /* *Make sure that this module isn't removed while *the lcd is open by increasing the lcd usage count */ device_open_num--; MOD_DEC_USE_COUNT; release_region (LCD_BASE, LCD_VIRT_LENGTH);#ifdef DEBUG printk (DEVICE_NAME " closed successed \n");#endif return SUCCESS;}/**The Lcd device driver write function*/static ssize_tdevice_write (struct file *lcd_device_file, const char *buffer, /*buffer for data outputed to lcd */ size_t length, /*length of buffer */ loff_t * offset) /*file pointer offset */{ unsigned char ch; int error; int i = 0; int line_count = 0; while (i < length) { if (line_count < 16) { if (line_count == 8) lcd_set (CHANGE_LINE); if ((error = get_user (ch, buffer)) != 0) { return 0; } buffer++; i++; line_count++; showch (ch); } else { mdelay (2000); line_count = 0; lcd_set (DISPLAY_CLEAR); } } return length;}/*************************************** Linux Module functions*********************************************/#ifdef MODULE/**Initialize the lcd device driver module*/intinit_module (void){ return lcd_init ();}/**Cleanup the lcd device driver moudle*/voidcleanup_module (){ int ret;#ifdef DEBUG printk ("I realse myself from kernel\n");#endif /*unmap memory */ iounmap ((void *) virt_base); /* Unregister the device */ ret = unregister_chrdev (Major, DEVICE_NAME); if (ret < 0) { printk ("unregister char_dev :error%d\n", ret); } lcd_set (DISPLAY_OFF); lcd_set (DISPLAY_CLEAR); writeb (LED_ON, (LED_ADDR - LCD_BASE) + virt_base); /*turn on led */}#endif /*MODULE*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -