📄 rs485driver_v1.0.c
字号:
#include <linux/module.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <asm/uaccess.h>
#include <linux/ioctl.h>
#include <asm/arch/io.h>
#include <asm/arch/hardware.h>
#include <asm/arch/at91rm9200dk.h>
#include <asm/arch/AT91RM9200_TC.h>
#include <linux/devfs_fs_kernel.h>
#include <asm/arch/AT91RM9200_USART.h>
#include <asm/arch/AT91RM9200_SYS.h>
#include <asm/types.h>
#include <asm/arch/memory.h>
#define MAJOR_NUM 222
#define DEVICE_NAME "RS_485"
#define RS485_IOC_MAGIC 0xd0
#define RS485_MAXNR 2
#define GET_CHAR _IO(RS485_IOC_MAGIC, 0)
#define GET_STRING _IO(RS485_IOC_MAGIC, 1)
#define PUT_CHAR _IO(RS485_IOC_MAGIC, 1)
#define PUT_STRING _IO(RS485_IOC_MAGIC, 3)
#define DMA_TO_DEVICE 1
#define DMA_FROM_DEVICE 2
/*
unsigned long copy_to_user(void *to, const void *from,
unsigned long count);
unsigned long copy_from_user(void *to, const void *from,
unsigned long count);*/
/*dam_map_single函数原型*/
/*dma_addr_t dma_map_single(struct device *dev,void *buf,size_t size,enum dam_data_directions)*/
static int RS485_NUM[257];
unsigned char RxBuffer[256],TxBuffer[256];
unsigned char TestBuffer[]="My name is quzegang";
//unsigned char *pSendAddress=&TestBuffer[0];
//unsigned long pA;
//unsigned int *pF=(unsigned long)pV-0xc000000;
//pA=__virt_to_bus(TestBuffer);
AT91PS_SYS SYS = (AT91PS_SYS) AT91C_VA_BASE_SYS;
AT91PS_USART US3 = (AT91PS_USART)AT91C_VA_BASE_US3;
void PDC_Init(void)
{
US3->US_RPR=0;
US3->US_RCR=0;
US3->US_TPR=0;
US3->US_TCR=0;
US3->US_RNPR=0;
US3->US_RNCR=0;
US3->US_TNPR=0;
US3->US_TNCR=0;
printk("KERNEL:The PDC init over!!\n");
}
void SetHighLevel_PB0(void)
{
SYS->PIOB_PER|=(0x1<<0); /*使能PB0于GPIO口模式*/
SYS->PIOB_OER|=(0x1<<0); /*使能PB0为GPIO输出模*/
SYS->PIOB_SODR|=(0x1<<0); /*输出高电平*/
}
void SetLowLevel_PB0(void)
{
SYS->PIOB_PER|=(0x1<<0); /*使能PB0于GPIO口模式*/
SYS->PIOB_OER|=(0x1<<0); /*使能PBO为GPIO输出模式*/
SYS->PIOB_CODR|=(0x1<<0); /*输出低电平*/
}
/*
**其中PA6/RXD3为RS485接受端,PA5/TXD3为RS485发送端,
**PB0/RTS3为接受和发送控制端口。PA5,PA6工作外设在第
**二功能,PB0工作在GPIO模式
*/
void US3_Init(void)
{
SYS->PIOA_PDR|=((0x1<<5)|(0x1<<6));/*禁止PA5于PA6工作于GPIO模式*/
SYS->PIOA_BSR|=((0x1<<5)|(0x1<<6));/*设置它们于B外设模式,即串口模式*/
SYS->PMC_PCER|=(0x1<<9); /*使能时钟*/
US3->US_CR =0xcf; /*使能串口接受与发送*/
//US3->US_IDR=0xffffffff; /*禁止所有中断*/
US3->US_BRGR=33; /*波特率设置*/
US3->US_TTGR=0; /*设置时间保护*/
US3->US_PTCR=0x00000202;/*禁止PDC传输与接受请求(应该直接赋值)*/
US3->US_MR=0x000008c1; /*设置工作模式为485*/
printk("KERNEL:The US3->RS485 init over!!!!\n");
}
void Delay(int Seconds)
{
int i;
for (i=0;i<Seconds;i++)
{
;
}
}
char RS485_TxBuffer(void)
{
PDC_Init();
US3_Init();
SetHighLevel_PB0();
US3->US_CR=(0x1<<6);
US3->US_PTCR|=(0x1<<8);
US3->US_TPR=(unsigned long)(__virt_to_phys(&TestBuffer[0]));
US3->US_TCR=20;
US3->US_TNPR=0;
US3->US_TNCR=0;
Delay(900);
printk("KERNEL:The UnSendNumber is %d __________\n",US3->US_TCR);
return (US3->US_TCR);
}
void RS485_RxBuffer(void)
{
//PDC_Init();
US3_Init();
SetLowLevel_PB0();
US3->US_CR=(0x1<<4);
US3->US_PTCR|=(0x1<<0);
US3->US_RPR=(unsigned int)RxBuffer;
US3->US_RCR=256;
US3->US_RNPR=0;
US3->US_RNCR=0;
Delay(90000000);
}
int RS485_open(struct inode*,struct file*);
int RS485_release(struct inode*,struct file*);
/*int RS485_ioctl(struct inode*,struct file*, unsigned int, unsigned long);*/
int RS485_read(struct file*,char*,size_t ,loff_t *);
int RS485_write(struct file*,const char*,size_t,loff_t*);
static struct file_operations RS485_fops= {
/*ioctl :RS485_ioctl,*/
owner :THIS_MODULE,
read :RS485_read,
write :RS485_write,
open :RS485_open,
release:RS485_release,
};
int __init RS485_init(void)
{
int ret;
ret = register_chrdev(MAJOR_NUM, DEVICE_NAME, &RS485_fops);
if (ret < 0)
{
printk(KERN_WARNING "RS485: can't get major %d\n", MAJOR_NUM);
return ret;
}
printk("now ,ok ,you can use\n");
return 0;
}
void __exit RS485_exit(void)
{
unregister_chrdev(MAJOR_NUM, DEVICE_NAME);
}
module_init(RS485_init);
module_exit(RS485_exit);
int RS485_open(struct inode *inode,struct file *filp)
{
int minor;
minor=MINOR(inode->i_rdev);
printk("Now begin ,good luck!\n");
printk("**************************************\n");
printk("*Now,We are going to test RS485: *\n");
printk("*Richisland,quzegang,07/09/24,NanJing*\n");
printk("**************************************\n");
RS485_NUM[minor]++;
return 0; /*succes*/
}
int RS485_release(struct inode *inode,struct file *filp)
{
int minor;
minor=MINOR(inode->i_rdev);
if(RS485_NUM[minor])
RS485_NUM[minor]--;
return 0;
}
int RS485_read(struct file *filp,char *buf,size_t count ,loff_t *offp)
{
int UnReadNumber;
#ifdef DEBUG
printk("\nmy_read is called.User buffer is %p,size is %d\n",buf,count);
#endif
if (verify_area(VERIFY_WRITE,buf,count)==-EFAULT)
{
printk("There are something wrong with read!!!!\n");
return -EFAULT;
}
else
{
RS485_RxBuffer();
UnReadNumber=copy_to_user(buf,RxBuffer,256);
printk("The UnCopyNumber is %d\n",UnReadNumber);
return UnReadNumber;
}
}
int RS485_write(struct file*filp,const char *buf,size_t count,loff_t *f_pos)
{
int UnWriteNumber,UnSendNumber,i;
#ifdef DEBUG
printk("\nmy_write is called.User buffer is %p,size is %d\n",buf,count);
#endif
if (verify_area(VERIFY_WRITE,buf,count)==-EFAULT)
{
printk("There are something wrong with write\n");
return -EFAULT;
}
else
{
UnWriteNumber=copy_from_user(TxBuffer,buf,256);
UnSendNumber=RS485_TxBuffer();
printk("KERNEL:Data below is from user program:\n");
for(i=0;i<256;i++)
{
printk("%d,",TxBuffer[i]);
}
printk("\nKERNEL:The UnWriteNumber is %d\n",UnWriteNumber);
printk("KERNEL:now begin to write\n");/*为了传输完,实际在上面开始传输*/
printk("KERNEL:The UnSendNumber is %d\n",UnSendNumber);
return UnSendNumber;
}
}
/*int RS485_ioctl(struct inode *inode,struct file *file, unsigned int cmd,unsigned long arg)
{
int a,b,i;
if (_IOC_TYPE(cmd)!=RS485_IOC_MAGIC)
{
return -ENOTTY;
}
if (_IOC_NR(cmd)>=RS485_MAXNR)
{
return -ENOTTY;
}
switch (cmd)
{
case GET_CHAR:
RS485_GetBuffer();
a=copy_to_user((unsigned char*)arg,RxBuffer,256);
while ( !(US3->US_CSR&(0x1<<9)) );
Delay(8);
for(i=0;i<256;i++)
printk("I=%d\n",RxBuffer[i]);
return (RS485_GetBuffer());
break;
case PUT_CHAR:
b=copy_from_user(TxBuffer,(unsigned char*)arg,256);
for(i=0;i<256;i++)
printk("F=%d\n",TxBuffer[i]);
RS485_PutBuffer();
Delay(8);
return (RS485_PutBuffer());
break;
default:
return 0;
break;
}
}*/
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Richisland ,nanjing ,Quzegang");
MODULE_DESCRIPTION("RS485 driver for AT91RM9200");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -