led.c檔
#include <linux/config.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/delay.h>
#include <linux/poll.h>
#include <linux/string.h>
#include <linux/ioport.h>
#include <asm/uaccess.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <linux/miscdevice.h>
#include <asm/delay.h>
#include <asm/arch/regs-gpio.h>
#include <asm/arch/regs-mem.h>
#define LED_R 1
#define LED_L 2
#define LED_AA 3
#define LED_BB 4
#define LED_MAJOR 210 //裝置預設號碼
#define led_name "led" //裝置號碼
static int __iomem * LED8X8_Address; //led點矩陣記憶體位置指標
u16 LED8X8_Disp1[8] = {0x00,0x02,0x02,0x02,0x02,0x02,0xfe,0x00};
u16 LED8X8_Disp2[8] = {0x00,0x1e,0x12,0x12,0x12,0x12,0xfe,0x00};
u16 LED8X8_Disp3[8] = {0x00,0x9e,0x92,0x92,0x92,0x92,0xf2,0x00};
u16 LED8X8_Disp4[8] = {0x00,0xf2,0x92,0x92,0x92,0x92,0x9e,0x00};
u16 LED8X8_Disp5[8] = {0x00,0x92,0x92,0x92,0x92,0x92,0xfe,0x00};
u16 LED8X8_Disp6[8] = {0x00,0xf2,0x92,0x92,0x92,0x92,0x9e,0x00};
u16 LED8X8_Disp7[8] = {0x00,0x92,0x92,0x92,0x92,0x92,0xfe,0x00};
u16 LED8X8_Disp8[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0xfe,0x00};
#define MS_DELAY(s) Delay(s<<3)
void Delay(int time) //延遲副程式
{
#define S 3C 2440A _FCLK 400000000 //2440的工作時脈(倍頻)
volatile int i, j = 0;
volatile static int loop = S 3C 2440A _FCLK/100000;
for(;time > 0;time--)
for(i=0;i < loop; i++) { j++; }
}
void LED8X8_Display( u16 *LED8X8, u32 d )//left
{
u 16 m ,i ;
while( d-- ){
for( i = 16; i > 0; i-- ) {
for( m = 0; m < 8; m++ ) {
*LED8X8_Address = ( (1<<(i+m))&0xff00 ) | ( (~(LED8X8[m])) & 0x00ff ) ;
MS_DELAY( 2) ;
}}
break ;
}
}
void ALED8X8_Display( u16 *LED8X8, u32 d ) //right
{
u 16 m ,j;
while( d-- ) {
for( j = 0; j < 16; j++ ){
for( m = 0; m < 8; m++ ) {
*LED8X8_Address = ( (1<<(j+m))&0xff00 ) | ( (~(LED8X8[m])) & 0x00ff ) ;
MS_DELAY( 2) ;
}}
break ;
}
}
static void led_LL() //8*8left
{
LED8X8_Display( LED8X8_Disp1,30) ;
LED8X8_Display( LED8X8_Disp2,30) ;
LED8X8_Display( LED8X8_Disp3,30) ;
LED8X8_Display( LED8X8_Disp4,30) ;
LED8X8_Display( LED8X8_Disp5,30) ;
LED8X8_Display( LED8X8_Disp6,30) ;
LED8X8_Display( LED8X8_Disp7,30) ;
LED8X8_Display( LED8X8_Disp8,30) ;
*LED8X8_Address = 0xffff ;
}
static void led_RR() //8*8right
{
ALED8X8_Display(LED8X8_Disp1,30) ;
ALED8X8_Display(LED8X8_Disp2,30) ;
ALED8X8_Display(LED8X8_Disp3,30) ;
ALED8X8_Display(LED8X8_Disp4,30) ;
ALED8X8_Display(LED8X8_Disp5,30) ;
ALED8X8_Display( LED8X8_Disp6,30) ;
ALED8X8_Display( LED8X8_Disp7,30) ;
ALED8X8_Display( LED8X8_Disp8,30) ;
*LED8X8_Address = 0xffff ;
}
static void led_A() //4led on
{
int gpfdat,count;
gpfdat = __raw_readl(S 3C 2410_GPFDAT);
for(count=4;count<8;count++){
gpfdat &=~(1<<count);
__raw_writel(gpfdat,S 3C 2410_GPFDAT);
Delay(1000);
}
}
static void led_B() //4led off
{
int gpfdat,count;
gpfdat = __raw_readl(S 3C 2410_GPFDAT);
for(count=4;count<8;count++){
gpfdat |=1<<count;
__raw_writel(gpfdat,S 3C 2410_GPFDAT);
Delay(1000);
}
}
static ssize_t led_read(struct file *filp,char *buf,size_t count,loff_t *l)
{
return count;
}
static ssize_t led_write(struct file *filp,const char *buf,size_t count,loff_t *f_ops)
{
return count;
}
static int led_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
{
int ret = 0;
int num;
switch(cmd)
{
case LED_R:
led_RR();
break;
case LED_L:
led_LL();
break;
case LED_AA:
led_A();
break;
case LED_BB:
led_B();
break;
}
return 0;
}
static int led_open(struct inode *inode, struct file *filp)
{
s 3c 2410_gpio_cfgpin(S 3C 2410_GPF4, S 3C 2410_GPF4_OUTP);
s 3c 2410_gpio_cfgpin(S 3C 2410_GPF5, S 3C 2410_GPF5_OUTP);
s 3c 2410_gpio_cfgpin(S 3C 2410_GPF6, S 3C 2410_GPF6_OUTP);
s 3c 2410_gpio_cfgpin(S 3C 2410_GPF7, S 3C 2410_GPF7_OUTP);
return 0;
}
static int led_release(struct inode *inode, struct file *filp)
{
return 0;
}
static struct file_operations led_fops = //led檔案作業結構
{
owner: THIS_MODULE, //指向擁有此結構的模組
read : led_read,
write : led_write,
ioctl : led_ioctl, //led I/O控制
open : led_open, //應用程式開啟檔案的動作
release : led_release,
};
static int __init led_init(void)
{
int retval;
int bwscon;
int bankcon1;
retval = register_chrdev(LED_MAJOR,led_name,&led_fops); //註冊字元裝置函式,MAJOR是主裝置號碼,Name是驅動程式名稱,fops是檔案作業結構
if(retval < 0)
{
printk(KERN_WARNING"Can't get major %d\n",LED_MAJOR);
return retval;
}
s 3c 2410_gpio_cfgpin(S 3C 2410_GPA12, S 3C 2410_GPA12_nGCS1);
bwscon = __raw_readl(S 3C 2410_BWSCON);
bwscon&= ~(0xF << 4); //設定bank1記憶體
bwscon|= (0x6 << 4);
__raw_writel(bwscon, S 3C 2410_BWSCON); //寫入設定
bankcon1 = __raw_readl(S 3C 2410_BANKCON1); //取得bankcon1控制暫存器
bankcon1 =((0x3<<13)+(0x3<<11)+(0x7<<8)+(0x3<<6) //設定工作時序
+(0x3<<4)+(0x3<<2)+(0x0));
__raw_writel(bankcon1, S 3C 2410_BANKCON1);
LED8X8_Address = ioremap(0x08000000,4);
if (LED8X8_Address == 0) {
printk(KERN_INFO "failed to ioremap() region\n");
return -EINVAL;
}
printk("LED driver register success!\n");
return 0;
}
static void __exit led_exit(void) //卸載函式
{
unregister_chrdev(LED_MAJOR,led_name); //註銷函式將裝置移出系統 ,MAJOR為設備號碼,Name為裝置名稱
printk("LED driver release success!\n");
}
module_init(led_init); //巨集函式,作用是指出模組初始函式位置,必設
module_exit(led_exit); //巨集函式,作用是註銷註冊軟體介面,將資源還給系統,必設
MODULE_LICENSE("GPL"); //不打會有warning
MODULE_AUTHOR("usb lab");//目的碼資訊檔
MODULE_DESCRIPTION("led driver"); //目的碼資訊檔
LED_run檔
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/signal.h>
#include <sys/stat.h>
#include <sys/types.h>
int main(){
int fd;
int val=-1;
fd=open("/dev/led",O_RDONLY);
if(fd<0){
printf("can not open device\n");
exit(1);
}
while(1){
printf("please select number to run program\n");
printf("BY ME TEST \n");
printf("1:Right \n 2:Left\n 3:POEWR ON\n 4:POWER OFF\n 5:Exit\n");
scanf("%d",&val);
if(val==1)ioctl(fd,1,10);
else if(val==2) ioctl(fd,2,10);
else if(val==3) ioctl(fd,3,10);
else if(val==4) ioctl(fd,4,10);
else if(val==5){
close(fd);
break;
}
}
return 0;
}
Makefile檔
#2.6 Makefile
CC= /usr/local/arm/ 3.4.1 /bin/arm-linux-gcc
S 3C 2440_KERNEL_DIR = /home/Kernel/linux- 2.6.14 .7-2440
ifneq ($(KERNELRELEASE),)
obj-m := led.o
else
KERNELDIR ?= $(S 3C 2440_KERNEL_DIR)
PWD := $(shell pwd)
default: A B
A:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
B:
$(CC) -o LED LED_run.c
clean:
rm -rf *.o *.mod.* *.ko *.o.* .*.*.cmd
endif
VM模擬器下跑LINUX作業系統,使用RS-232傳輸
(LINUX指令)編寫程式
先解壓縮cross- 3.4.1 .tar,才會有交叉編輯環境。
cd / usr/local /arm/ 3.4.1 /
tar jvxf cross- 3.4.1 .tar.bz2
export PATH=$PWD/usr/local/arm/ 3.4.1 / bin:$PATH
$PATH
撰寫的3個檔
Makefile
LED_run .c
led.c
1.Led.c 2.LED_run 3.Makefile 必須放在同一資料夾
放置同一資料夾:cd /home/LED終端機執行指令
cd /home/LED
make開啟另一終端機當平台
minicom 按s傳送 led.ok and LED 兩檔案
cd /tmp
insmod ./led.ko //掛載
cat /porc/devices
mknod /dev/led c 210 0
ls /dev
./LED //執行
rmmod led.ko //卸載
rm LED led.ko //移除
Download