📄 spi.c
字号:
/****************************************Copyright (c)**************************************************
** 西安傅立叶电子有限公司
** 研 发 部
** http://www.FFTChina.com
**-----------------------------------------文件信息-----------------------------------------------------
**文 件 名: cantest.c
**创 建 人:
**最后修改日期: 2005年6月30日
**描 述: CAN模块测试驱动程序(查询模式)
**------------------------------------------------------------------------------------------------------
********************************************************************************************************/
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/capability.h>
#include <linux/smp_lock.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/poll.h>
#include <asm/hardware.h>
#include <asm/io.h>
#include <linux/irq.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/init.h>
#if LINUX_KERNEL_VERSION >= KERNEL_VERSION(2,4,0)
#include "linux/smp_lock.h"
#endif
#define BIT_DMA1 (0x1<<18)
#define FFTspi_MAJOR 18
#define ClearPending(bit) {SRCPND = bit;INTPND = bit;INTPND;}
char kernel_version[]=UTS_RELEASE;
devfs_handle_t dev_handle3;
volatile int tx_dma1Done,rx_dma1Done;
int SpiMode = 1;
unsigned char SPI_BUFFER[128];
#define DEBUG
void SPI_Port_Init(int MASorSLV,unsigned long arg)
{
GPEUP&=~(0x3800); //config clk pull up
GPEUP|=0x2000; //spiclk
GPECON=((GPECON&0xf03fffff)|0xa800000);//config spi pin func
GPGUP|=0x4; // nSS0 config pull up
if(MASorSLV==1)
{
GPGCON=((GPGCON&0xffffffcf)|0x10); // Master(GPIO_Output)
GPGDAT|=0x4; // Activate nSS
}
else
GPGCON=((GPGCON&0xffffffcf)|0x30); // Slave(nSS)
//Step1. SPI init
SPPRE0=arg; //50/2(arg+1);
//if PCLK=50Mhz,SPICLK=25Mhz //2 divide
}
/*******************************************************
** 函数原形:irq_handler(int irq, void *dev_id, struct pt_regs *regs)
** 参数: irq : 中断号
** dev_id : 申请时告诉系统的设备标识
** regs : 中断发生时的寄存器内容
** 函数说明:中断服务程序
*******************************************************/
void Dma1Tx_Int(int irq, void *dev_id, struct pt_regs *regs)
{
#ifdef DEBUG
printk("ok int\n");
#endif
tx_dma1Done=1;
rx_dma1Done=1;
INTMSK|=BIT_DMA1;
ClearPending(BIT_DMA1);
}
/*******************************************************
*函数原形:read_fftspi(struct file *file, char *buf, size_t count,loff_t *f_pos)
*参数: buf : 传入该函数的数据缓冲区指针
* count:CAN的通道号
*返回值 : 0
*函数说明:读出接收到的CAN数据
*******************************************************/
static int read_fftspi(struct file *file, char *buffer, size_t count,loff_t *f_pos)
{
int flags,i;
unsigned char *dmabuf;
unsigned int dmasize = count;
unsigned int dmaphys = 0;
unsigned char *rx_ptr;
do {
dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA,dmasize, &dmaphys);
if (!dmabuf)
printk("erro dmabuf\n");
} while (!dmabuf && dmasize);
rx_dma1Done=0;
local_irq_save(flags);
INTMSK=INTMSK&(~(BIT_DMA1)); //forbid
SPCON0=(2<<5)|(SpiMode<<4)|(SpiMode<<3)|(1<<2)|(0<<1)|(1<<0);//DMA1,en-SCK,master,low,A,TAGD
if(SpiMode)GPGDAT&=0xfffffffb;
SPPIN0=(0<<2)|(1<<1)|(0<<0);//dis-ENMUL,SBO,release
//Step2. DMA1 init
DISRC1=(unsigned)0x59000014;//Address of SPRDAT Register
DISRCC1=(1<<1)|(1); //APB(SPI), fix
DIDST1=DMA_BASE_ADDR(dmaphys); //Address of Memory
DIDSTC1=(0<<1)|(0); //AHB(Memory), inc
DCON1=(1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(3<<24)|(1<<23)|(1<<22)|(0<<20)|(dmasize);
//handshake, sync PCLK, TC int, single tx, single service, SPI, H/W request,
//off-reload, byte, 128Bytes
DMTRIG1=(0<<2)|(1<<1)|(0); //run, DMA1 channel on, no-sw trigger
local_irq_restore(flags);
while(rx_dma1Done==0);
while(!(SPSTA0&0x1)); //Check Rx ready stat
rx_ptr = dmabuf ;//¿ʒՉ눫һ¿ꀕµٖ·
*(rx_ptr + dmasize)=SPRDAT0;
#ifdef DEBUG
for(i=1; i <=dmasize; i++)
{
printk("get dat is %c\n",*(rx_ptr+i));
}
#endif
copy_to_user(buffer,dmabuf+1,count);
if(SpiMode)GPGDAT|=0x4; // Deactivate nSS
consistent_free(dmabuf,dmasize,dmaphys);
return 0;
}
/*******************************************************
*函数原形:write_fftspi(struct file *file,const char *buf,size_t count,loff_t *f_pos)
*参数: buf : 传入该函数的数据缓冲区指针
* count:CAN的通道号
*返回值 : 0 说明成功写入
*函数说明:向CAN总线发送数据
*******************************************************/
static int write_fftspi(struct file *file,const char *buf,size_t count,loff_t *f_pos)
{
int i,flags;
unsigned char *dmabuf;
int dmasize = count;
int dmaphys = 0;
unsigned char *tx_ptr;
do {
dmabuf = consistent_alloc(GFP_KERNEL|GFP_DMA,dmasize, &dmaphys);
if (!dmabuf)
printk("erro dmabuf\n");
} while (!dmabuf && dmasize);
copy_from_user(dmabuf, buf,dmasize);
tx_ptr = dmabuf ;//
#ifdef DEBUG
for(i=0; i < dmasize; i++)
{
printk("send dat is %c\n",*(tx_ptr+i));
}
#endif
tx_dma1Done=0;
local_irq_save(flags);
INTMSK=INTMSK&(~(BIT_DMA1)); //forbid
SPCON0=(2<<5)|(SpiMode<<4)|(SpiMode<<3)|(1<<2)|(0<<1)|(0<<0);//DMA1,en-SCK,master,low,B,normal
SPPIN0=(0<<2)|(1<<1)|(0<<0);//dis-ENMUL,SBO,release
DISRC1=DMA_BASE_ADDR(dmaphys); //Address of Memory
DISRCC1=(0<<1)|(0); //AHB(Memory), inc
DIDST1=(unsigned)0x59000010; //Address of SPTDAT Register
DIDSTC1=(1<<1)|(1); //APB(SPI), fix
DCON1=(1<<31)|(0<<30)|(1<<29)|(0<<28)|(0<<27)|(3<<24)|(1<<23)|(1<<22)|(0<<20)|(dmasize); //handshake, sync PCLK, TC int, single tx, single service, SPI, H/W request,off-reload, byte, 128Bytes
if(SpiMode) GPGDAT&=0xfffffffb; // Activate nSS nSS active
DMTRIG1=(0<<2)|(1<<1)|(0); //run, DMA1 channel on, no-sw trigger
local_irq_restore(flags);
while(tx_dma1Done==0);
while(!(SPSTA0&0x1));
consistent_free(dmabuf,dmasize,dmaphys);
#ifdef DEBUGSR
while(!(SPSTA0&0x1)); //Check Rx ready stat
{
i = SPRDAT0;
printk("get dat is %c\n",i);
}
#endif
if(SpiMode)GPGDAT|=0x4; // Deactivate nSS
return 0;
}
/*******************************************************
*函数原形:open_fftspi(struct inode *inode,struct file *file)
*参数:
*返回值 :
*函数说明:
*******************************************************/
static int open_fftspi(struct inode *inode,struct file *file)
{
MOD_INC_USE_COUNT;
return 0;
}
/*******************************************************
*函数原形:open_fftspi(struct inode *inode,struct file *file)
*参数:
*返回值 :
*函数说明:
*******************************************************/
static int release_fftspi(struct inode *inode,struct file *file)
{
MOD_DEC_USE_COUNT;
return 0;
}
/***************************************************************************************************
** function descrp:
** arg: cmd: 0: slave mode 1: master mode
arg: Baud rate = 50M / 2 / (arg + 1)
** detail:
**************************************************************************************************/
static int ioctl_fftspi(struct inode *inode,struct file *file,unsigned int cmd,unsigned long arg)
{
int flags;
local_irq_save(flags);
SpiMode = cmd;
SPI_Port_Init(cmd,arg);
local_irq_restore(flags);
return 0;
}
/*******************************************************
*函数原形:open_fftspi(struct inode *inode,struct file *file)
*参数:
*返回值 :
*函数说明:
*******************************************************/
static unsigned int s3c2410_kbd_poll(struct file *filp, struct poll_table_struct *wait)
{
return 0;
}
/***************************************
** 函数指针结构: file_operations
** 说明 :
***************************************/
struct file_operations fftspi_fops={
read : read_fftspi,
write: write_fftspi,
ioctl: ioctl_fftspi,
open : open_fftspi,
release: release_fftspi,
poll : s3c2410_kbd_poll,
};
/******************************************************
** 初始化模块:在加载模块时候调用
** 函数原形 : init_module(void)
** 说 明 :不用修改
******************************************************/
static int __init fftspi0_init_module(void)
{
int result;
dev_handle3 = devfs_register( NULL, "fftspi", DEVFS_FL_DEFAULT, FFTspi_MAJOR, 0, S_IFCHR, &fftspi_fops, NULL);
result = request_irq(IRQ_DMA1,Dma1Tx_Int,SA_INTERRUPT,"fftspidma",NULL);
if (result < 0)
{
printk(KERN_INFO "test: can't install interrupt\n");
}
printk("congraulation,fftspi are successful registed\n");
return 0;
}
/*******************************************************
** 函数原形 : cleanup_module(void)
** 说明 : 在卸载模块时调用
******************************************************/
static void __exit fftclrspi0_module(void)
{
SPCON0=(0<<5)|(0<<4)|(1<<3)|(1<<2)|(1<<1)|(0<<0);//poll,dis-SCK,master,low,B,normal
devfs_unregister (dev_handle3);
free_irq(IRQ_DMA1, NULL);
printk("exit fftspi\n");
}
MODULE_LICENSE("GPL");
module_init(fftspi0_init_module);
module_exit(fftclrspi0_module);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -