如何通过2440spi总线读写外设的stm32 spi寄存器器

还没有帐号? 赶紧
用户版块帖子
SPI总线 通俗易懂讲解
UID:1352078
在线时间54小时
M币631专家1
SPI总线  MOTOROLA公司的SPI总线的基本信号线为3根传输线,即SI、SO、SCK。传输的速率由时钟信号SCK决定,SI为数据输入、SO为数据输出。采用SPI总线的系统如图8-27所示,它包含了一个主片和多个从片,主片通过发出片选信号-CS来控制对哪个从片进行通信,当某个从片的-CS信号有效时,能通过SI接收指令、数据,并通过SO发回数据。而未被选中的从片的SO端处于高阻状态。=740) window.open('http://wjxtyjksy./ch08/image068.gif');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="SPI总线 通俗易懂讲解" alt="SPI总线 通俗易懂讲解">图8-27 SPI总线的系统  主片在访问某一从片时,必须使该从片的片选信号有效;主片在SCK信号的同步下,通过SI线发出指令、地址信息;如需将数据输出,则接着写指令,由SCK同步在SI线上发出数据;如需读回数据,则接着读指令,由主片发出SCK,从片根据SCK的节拍通过SO发回数据。  因而对具有SPI接口的从片器件来讲,SCK、SI是输入信号,SO是输出信号。SCK用于主片和从片通信的同步。SI用于将信息传输到器件,输入的信息包括指令、地址和数据,指令、地址和数据的变化在SCK的低电平期间进行,并由SCK信号的上升沿锁存。SO用于将信息从器件传出,传出的信息包括状态和数据,信息在SCK信号的下降沿移出。  Microchip公司的25XX系列的串行E2PROM采用了SPI总线,该系列器件的性能如表8-2所示。表8-2 Microchip公司的25XX系列的串行E2PROM型号25XX04025XX08025XX16025XX320容量4K (512 X 8bit) 8K (1024 X 8bit)16K (4096 X 8bit)32K (4096 X 8bit)地址信号A0~A8A0~A9A0~A10A0~A11  以25XX320为例,该器件是4K字节的E2PROM,结构如图8-28所示,接口信号为SCK、SI和SO,此外还具有-CS、-WP、-HOLD信号线。其中-CS为器件选中信号,当此信号为低电平时器件被选中,高电平时器件处于等待状态。=740) window.open('http://wjxtyjksy./ch08/image070.gif');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="SPI总线 通俗易懂讲解" alt="SPI总线 通俗易懂讲解"> 图8-28 25XX320的结构  与并行接口电路不同的是,在并行接口电路中对器件进行操作的控制信号,在串行接口电路中只能用指令实现,25XX320的操作指令有数据读指令、写操作的允许和禁止指令、写数据指令和状态寄存器的读写指令。在器件的内部有一个8位的指令寄存器,在SCK的上升沿,通过SI信号线,指令输入到上述寄存器并被执行。表8-3 25系列串行存储器的指令指令名称指令格式描述READ 从选定的地址开始读存储器数据WRITE从选定的地址开始写存储器数据WRDI 禁止写操作WREN 允许写操作RDSR 读状态寄存器WRSR 写状态寄存器  器件的读操作时序如图8-29所示。当-CS信号有效时,在SCK信号的同步下,8位的读指令送入器件,接着送入16位地址(由于25XX320只使用地址信号A0~A11,地址的高4位无效)。在读指令和地址发出后,SCK继续发出时钟信号,此时存储在该地址的数据由SCK控制从SO引脚移出。在每个数据移出后,内部的地址指针自动加1,如继续对器件发送SCK信号,可读出下一个数据。当地址指针计到0FFFH之后,将回到0000H。读操作的结束由-CS信号变高实现。=740) window.open('http://wjxtyjksy./ch08/image072.gif');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="SPI总线 通俗易懂讲解" alt="SPI总线 通俗易懂讲解"> 图8-29 25系列串行存储器的读时序  25XX系列的串行EEPROM的写操作通过写允许及禁止指令控制,写操作必须在器件处于写允许状态时进行。  写允许及禁止指令均为8位的指令,指令的操作过程为:将-CS信号置为低电平,在SCK信号的作用下,通过SI引脚输入上述指令,在8位的指令送入器件之后,将-CS信号置为高电平,使器件锁存于写允许或写禁止状态。如在输入写允许指令后未将-CS信号置为高电平,则写允许状态未锁存,此时如直接进行写操作,数据将不能写入存储器。在上电、写禁止指令、写状态寄存器指令、写数据指令执行之后,器件的写允许状态将被复位,即处于写禁止状态。  写操作通常在写允许指令之后进行,其时序如图8-30所示。在写允许状态锁存后,将-CS变高;再将-CS变低,在SCK的同步下输入写操作指令并送入16位地址,紧接着发送需写入的数据,写入的数据一次最多可达32个,但必须保证在同一页内。一页数据的地址从XXXXXXXX XXX0 0000 开始,到XXXX XXXX XXX1 1111结束,当内部的地址指针计数器达到XXXX XXXX XXX11111后,继续发送时钟信号将使地址计数器回复到该页的第一个地址,即XXXX XXXX XXX0 0000H。=740) window.open('http://wjxtyjksy./ch08/image074.gif');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="SPI总线 通俗易懂讲解" alt="SPI总线 通俗易懂讲解"> 图8-30 25系列串行存储器的写时序  为了使数据有效写入,-CS信号只能在写入数据的最后一个字节的最低位写入后变高。如-CS信号在其他时间变高,将无法保证数据的完整写入。在写操作的过程中,能通过读状态指令将状态寄存器的内容读回,当写操作完成后,写允许锁存状态将被复位。优缺点SPI接口具有如下优点:&&&& 1) 支持全双工操作;&&&& 2) 操作简单;&&&& 3) 数据传输速率较高。缺点:&&&& 1) 需要占用主机较多的口线(每个从机都需要一根片选线);&&&& 2) 只支持单个主机。&&&&&&&& 3) 没有指定的流控制,没有应答机制确认是否接收到数据。 如果还是看不懂,那就再通俗点。 SPI总线协议介绍一、技术性能SPI接口是Motorola 首先提出的全双工三线同步串行外围接口,采用主从模式(MasterSlave)架构;支持多slave模式应用,一般仅支持单Master。时钟由Master控制,在时钟移位脉冲下,数据按位传输,高位在前,低位在后(MSBfirst);SPI接口有2根单向数据线,为全双工通信,目前应用中的数据速率可达几Mbps的水平。总线结构如下图所示。=740) window.open('http://hi.csdn.net/attachment//0_WTsN.gif');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="SPI总线 通俗易懂讲解" alt="SPI总线 通俗易懂讲解">二、接口定义SPI接口共有4根信号线,分别是:设备选择线、时钟线、串行输出数据线、串行输入数据线。=740) window.open('http://hi.csdn.net/attachment//0_ERD6.gif');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="SPI总线 通俗易懂讲解" alt="SPI总线 通俗易懂讲解">(1)MOSI:主器件数据输出,从器件数据输入(2)MISO:主器件数据输入,从器件数据输出(3)SCLK:时钟信号,由主器件产生(4)/SS:从器件使能信号,由主器件控制三、内部结构=740) window.open('http://hi.csdn.net/attachment//0_ew.gif');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="SPI总线 通俗易懂讲解" alt="SPI总线 通俗易懂讲解">四、 时钟极性和时钟相位在SPI操作中,最重要的两项设置就是时钟极性(CPOL或UCCKPL)和时钟相位(CPHA或UCCKPH)。时钟极性设置时钟空闲时的电平,时钟相位设置读取数据和发送数据的时钟沿。主机和从机的发送数据是同时完成的,两者的接收数据也是同时完成的。所以为了保证主从机正确通信,应使得它们的SPI具有相同的时钟极性和时钟相位。&&&&&& SPI接口时钟配置心得:在主设备这边配置SPI接口时钟的时候一定要弄清楚从设备的时钟要求,因为主设备这边的时钟极性和相位都是以从设备为基准的。因此在时钟极性的配置上一定要搞清楚从设备是在时钟的上升沿还是下降沿接收数据,是在时钟的下降沿还是上升沿输出数据。五、传输时序SPI接口在内部硬件实际上是两个简单的移位寄存器,传输的数据为8位,在主器件产生的从器件使能信号和移位脉冲下,按位传输,高位在前,低位在后。如下图所示,在SCLK的下降沿上数据改变,上升沿一位数据被存入移位寄存器。=740) window.open('http://hi.csdn.net/attachment//0_Uya.gif');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="SPI总线 通俗易懂讲解" alt="SPI总线 通俗易懂讲解">五、数据传输&&&&&& 在一个SPI时钟周期内,会完成如下操作:1)主机通过MOSI线发送1位数据,从机通过该线读取这1位数据;2)从机通过MISO线发送1位数据,主机通过该线读取这1位数据。这是通过移位寄存器来实现的。如下图所示,主机和从机各有一个移位寄存器,且二者连接成环。随着时钟脉冲,数据按照从高位到低位的方式依次移出主机寄存器和从机寄存器,并且依次移入从机寄存器和主机寄存器。当寄存器中的内容全部移出时,相当于完成了两个寄存器内容的交换。=740) window.open('http://hi.csdn.net/attachment//0_zzTN.gif');" style="max-width:100%;" onload="if(is_ie6&&this.offsetWidth>740)this.width=740;" title="SPI总线 通俗易懂讲解" alt="SPI总线 通俗易懂讲解">
写的比较详细,比较长,空了看看。
UID:83535
在线时间800小时
M币1208专家1
复杂。看起来头痛。公司有在用这个东西,但我没搞开发的。
UID:1166493
在线时间1337小时
M币2214专家3
经典,讲的透彻,学习了。
UID:1166493
在线时间1337小时
M币2214专家3
楼主,能介绍一下II2C总线吗?
UID:814619
在线时间205小时
M币993专家0
谢谢了,看这个好懂得多了。
UID:1352078
在线时间54小时
M币631专家1
是啊,我也是之前看了好多,都是云里雾里的,看了这个感觉很不错,好理解
UID:1352078
在线时间54小时
M币631专家1
回 爱玲珑 的帖子
:楼主,能介绍一下II2C总线吗? ( 21:03) 这两天会的!
UID:626008
在线时间596小时
M币7447专家1
谢谢了,看这个好懂得多了。
UID:1352078
在线时间54小时
M币631专家1
回 爱玲珑 的帖子
:楼主,能介绍一下II2C总线吗?&( 21:03)&发过了你看下I2C的,I2C很不好理解,特别是它和其他元件一起讲解的时候,容易混乱,单独看的话还好些,
UID:1352078
在线时间54小时
M币631专家1
回 louyj 的帖子
:谢谢了,看这个好懂得多了。 ( 19:40) 赶脚这个比I2C好理解多了
访问内容超出本站范围,不能确定是否安全
温馨提示:欢迎交流讨论,请勿发布纯表情、纯引用等灌水帖子;以免被删除
您目前还是游客,请
&回复后跳转到最后一页
Code by , Time now is:09-21 18:39, Total 0.122260(s) query 6,
Gzip enabled&主题 : 地址映射(在驱动程序里读写寄存器)
级别: 新手上路
金钱: 90 两
威望: 18 点
贡献值: 0 点
综合积分: 36 分
&地址映射(在驱动程序里读写寄存器)
在编写spi的驱动程序的时候遇到了很多问题,望那个高手指点一二。 我用spi+AD7888来进行数据采集。要对spi的相关的几个寄存器进行操作。也就是在驱动程序里要读写一些相关的寄存器,但是出现了问题。我的相关代码如下:///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////static int __init spi_adc_init(void){&&&&&&&&dev_t dev=0;&&&&base_addr=ioremap(S3C2410_PA_SPI,0x20); //remap physics address to vitrual address&&&&if(base_addr==NULL)//deal with error&&&&{ &&&&&&&&printk(KERN_ERR &K:Failed to remap register block\n&);&&&&&&&&return -ENOMEM;&&&&}&&&&&&&&if(adc_major)//major=0&&&&{&&&&&&&&dev=MKDEV(adc_major,adc_minor);&&&&&&&&ret=register_chrdev_region(dev,adc_number,DEVICE_NAME);&&&&}&&&&else//alloc device major &&&&{&&&&&&&&ret=alloc_chrdev_region(&dev,adc_minor,adc_number,DEVICE_NAME);&&&&&&&&adc_major=MAJOR(dev);&&&&}&&&&if(ret&0)&&&&{&&&&&&&&printk(KERN_WARNING &K:can't get major %d\n&,adc_major);&&&&&&&&&&&&}&&&&&&init_MUTEX(&devp-&sem);&&//inital semaphore sem=1&&&&adc_setup_cdev(&devp);&&&&printk(KERN_NOTICE &K:initial!\n&);return 0;}//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// base_addr=ioremap(S3C2410_PA_SPI,0x20); 这一句进行了地址映射。//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////*remap VA to PA*/static void __iomem *base_#define SPCON0&& (*(volatile unsigned long*)(base_addr+S3C2410_SPCON))#define SPSTA0&& (*(volatile unsigned long*)(base_addr+S3C2410_SPSTA))#define SPPRE0&& (*(volatile unsigned long*)(base_addr+S3C2410_SPPRE))#define SPTDAT0&&(*(volatile unsigned long*)(base_addr+S3C2410_SPTDAT))#define SPRDAT0&&(*(volatile unsigned long*)(base_addr+S3C2410_SPRDAT))//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////上面的代码进一步抽象相关的寄存器。(这里有没有什么问题)请高手指点。在下面的代码中我这样使用了这些寄存器。会不会有什么问题。static void configure_spi_register(void){ //set prescaler value baud=PCLK/2/(Prescaler+1)=2MHZ(AD7888 fsclk=2MHZ)&&&&&&&&char control_reg=0; &&&&SPPRE0=0x32;&&&&//poll,sck enable,major,sytle=A;regs-spi.h&&&&control_reg=S3C2410_SPCON_SMOD_POLL|&&&&&&&&&&&&&&&&&&&&S3C2410_SPCON_ENSCK|&&&&&&&&&&&&&&&&&&&& S3C2410_SPCON_MSTR|&&&&&&&&&&&&&&&&S3C2410_SPCON_CPOL_HIGH|&&&&&&&&&&&&&&&&S3C2410_SPCON_CPHA_FMTB|&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&(0&&0);&&&&SPCON0=control_&&&&for(i=0;i&10;i++)&&&&&&&&SPTDAT0=0&&&&printk(KERN_ALERT &K:spi registers configured!\n&);&& }在加载模块的时候出现了这样的问题: Unable to handle kernel NULL pointer dereference at virtual address pgd = c3b20000[] *pgd=33af6031, *pte=, *ppte=Internal error: Oops: 817 [#1]last sysfs file: /sys/devices/virtual/vc/vcs4/devModules linked in: spi_adc(+)CPU: 0&&&&Not tainted&&(2.6.32.2-FriendlyARM #1)PC is at spi_adc_init+0xa4/0x164 [spi_adc]LR is at __register_chrdev_region+0x17c/0x198pc : [&bf0030a4&]&&&&lr : [&c00a06f4&]&&&&psr: sp : c3af5f08&&ip : c3af5ec8&&fp : c3af5f34r10: bf003000&&r9 : &&r8 : bf0004c4r7 : bf000650&&r6 : bf000530&&r5 : 000a18b7&&r4 : r3 : &&r2 : &&r1 : &&r0 : Flags: nZCv&&IRQs on&&FIQs on&&Mode SVC_32&&ISA ARM&&Segment userControl: c000717f&&Table: 33b20000&&DAC: Process insmod (pid: 735, stack limit = 0xc3af4270)Stack: (0xc3af5f08 to 0xc3af6000)5f00:&&&&&&&&&&&&&&&&&& c482b828 0fd0bcb8 000015eb 000a18b7 bf0005305f20: c3af0 c3af5f7c c3af5f38 c003032c bf005f40: 015eb 000a18b7 bfeb 000a18b7 bf0005305f60: 310c8 c3af0 c3af5fa4 c3af5f80 c303005f80: c009b6b0 c009b5a0 00000 be9dee88 0fa85fa0: cd838 beb 000a18b7 5fc0: 00000 be9dee88
be9dee84 be9dee88 000005fe0:
be9deb54 1d3c24 b4c 33cc23ccBacktrace:[&bf003000&] (spi_adc_init+0x0/0x164 [spi_adc]) from [&c003032c&] (do_one_initcall+0x3c/0x1c8) r8:c:c3af4000 r6:bf:000a18b7 r4:000015eb[&c00302f0&] (do_one_initcall+0x0/0x1c8) from [&c0070344&] (sys_init_module+0xd0/0x204)[&c0070274&] (sys_init_module+0x0/0x204) from [&c0030f20&] (ret_fast_syscall+0x0/0x28) r7::be9dee88 r5::Code: eafffff8 e597300c e3a00 (e5831044)---[ end trace 6c173b036c7a3617 ]---Segmentation faultl但是模块加载上了:[root@FriendlyARM /mnt]# lsmodspi_adc 4139 1 - Loading 0xbf000000[root@FriendlyARM /mnt]# mknod /dev/spi_adc c 231 0[root@FriendlyARM /mnt]# cd /dev[root@FriendlyARM /dev]# lsadc&&&&&&&&&&&&&&&& root&&&&&&&&&&&&&&&&tty42audio&&&&&&&&&&&&&& rtc&&&&&&&&&&&&&&&& tty43backlight&&&&&&&&&& rtc0&&&&&&&&&&&&&&&&tty44buttons&&&&&&&&&&&& shm&&&&&&&&&&&&&&&& tty45camera&&&&&&&&&&&&&&spi_adc&&&&&&&&&&&& tty46这个问题困扰我很久了,希望得到牛人的指点。
级别: 骑士
金钱: 775 两
威望: 155 点
贡献值: 1 点
综合积分: 308 分
&LR is at __register_chrdev_region+0x17c/0x198&
级别: 新手上路
金钱: 90 两
威望: 18 点
贡献值: 0 点
综合积分: 36 分
&回 1楼(cole3) 的帖子
我还是不太明白,请大侠明说。这里的注册我是使用了LDD3里说的方法,我以前是用miscdevice的方法一注册的,也是出现的同样的错误。Unable to handle kernel NULL pointer dereference at virtual address pgd = c3b20000。。。。。。。。。。。。。。。。。。。。。。。。。。。。
级别: 论坛版主
发帖: 5407
金钱: 40120 两
威望: 17929 点
贡献值: 71 点
综合积分: 11054 分
目前最新的2.6.32.2内核里已经包含了对S3C2440 SPI Controller的支持,驱动源代码在drivers/spi/spi_s3c24xx.c. 论坛上也有很多这方面的帖子,你可以参考。如果你想别人帮你了解你的问题所在,最好把完整的内核模块源代码和相关的头文件附上来。
&If you have an apple and I have an apple and we exchange apples, then you and I willstill each have one apple. But if you have an idea and I have an idea and we exchangethese ideas, then each of us will have two ideas.&
级别: 新手上路
金钱: 90 两
威望: 18 点
贡献值: 0 点
综合积分: 36 分
&回 3楼(kasim) 的帖子
你好,麻烦你了,我看不明白内核中的spi子系统的代码,因为新手,所以只能当做一般的字符驱动来做了。以下是我的代码:注册驱动参考的LDD3的scull驱动的方法。#include &linux/module.h&#include &linux/kernel.h&#include &linux/fs.h&&&#include &linux/init.h&&&&&//module init#include &linux/errno.h&&& //error number#include &asm/uaccess.h&&& //copy_to_user copy_from_user#include &linux/delay.h&#include &asm/io.h&&&&&&&&& //iowrite8()#include &linux/gpio.h&#include &mach/regs-gpioj.h&&& //gpio-j#include &mach/regs-gpio.h&&&&&//gpio ports#include &plat/regs-spi.h&&&&& //spi registers#include &mach/hardware.h&#include &linux/cdev.h&#include &linux/device.h&#include &linux/miscdevice.h&#include &linux/semaphore.h&#define DEVICE_NAME&&&spi_adc&&& //device nameint adc_major=231;int adc_minor=0;int adc_number=1;#define CHANNAL_SELECT&&1&&//select channal commandstatic void configure_spi_pin(void);static void configure_spi_register(void);static void ad_convert(void);static void spi_tx_data(unsigned char data);static void spi_poll_done(void);unsigned char dataTX=0; //send data ,select channalunsigned char dataRX_0=0;//receive data 0unsigned char dataRX_1=0;//receive data 1unsigned int&&convert_data=0;//read data from ADstruct adc_dev{&&&&&&&&};struct adc_dev * /*remap PA to VA*/static void __iomem *base_/*spi ralate pin(GPJ12\GPG11\GPG12\GPG13) configure*/static void configure_spi_pin(void) {/*disable gpio pullup for spi*/&&&&s3c2410_gpio_pullup(S3C2440_GPJ12,1); //0=enable&&&&s3c2410_gpio_pullup(S3C2410_GPG(13),1);&&&&s3c2410_gpio_pullup(S3C2410_GPG(12),1);&&&&s3c2410_gpio_pullup(S3C2410_GPG(11),1);&&&&/*configure I/O ports as spi function*/&&&&s3c2410_gpio_cfgpin(S3C2440_GPJ12,S3C2440_GPJ12_OUTP);&&&&//CS&&&&s3c2410_gpio_cfgpin(S3C2410_GPE(13),S3C2410_GPE13_SPICLK0); //SPICLK0&&&&s3c2410_gpio_cfgpin(S3C2410_GPE(12),S3C2410_GPE12_SPIMOSI0);//SPIMOSI0&&&&s3c2410_gpio_cfgpin(S3C2410_GPE(11),S3C2410_GPE11_SPIMISO0);//SPIMISO0&&&&printk(KERN_ALERT &K:pins function configured!\n&);&&&&s3c2410_gpio_setpin(S3C2440_GPJ12,1);&&}static void configure_spi_register(void){ //set prescaler value baud=PCLK/2/(Prescaler+1)=2MHZ(AD7888 fsclk=2MHZ)&&&&&&&&char control_reg=0; && __raw_writeb(0x32,base_addr+S3C2410_SPPRE);&&&&//poll,sck enable,major,sytle=A;regs-spi.h&&&&control_reg=S3C2410_SPCON_SMOD_POLL|&&&&&&&&&&&&&&&&&&&&S3C2410_SPCON_ENSCK|&&&&&&&&&&&&&&&&&&&& S3C2410_SPCON_MSTR|&&&&&&&&&&&&&&&&S3C2410_SPCON_CPOL_HIGH|&&&&&&&&&&&&&&&&S3C2410_SPCON_CPHA_FMTB|&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&(0&&0);&&&&__raw_writeb(control_reg,base_addr+S3C2410_SPCON);&&&&for(i=0;i&10;i++)&&&&&&&&__raw_writeb(0xff,base_addr+S3C2410_SPTDAT);&&&&printk(KERN_ALERT &K:spi registers configured!\n&);&& }static void spi_poll_done(void){&&&&while(!(__raw_readb(base_addr+S3C2410_SPSTA)&0x01));&&}/*static void spi_tx_data(unsigned char data){ &&&& __raw_writeb(data,base_addr+S3C2410_SPTDAT);}*/static void ad_convert(void){&&&&configure_spi_register();&&&&s3c2410_gpio_setpin(S3C2440_GPJ12,0); &&&&spi_poll_done(); &&&&__raw_writeb(dataTX,base_addr+S3C2410_SPTDAT);;&&&&__raw_writeb(0xff,base_addr+S3C2410_SPTDAT);&&&&spi_poll_done();&&&&dataRX_0=__raw_readb(base_addr+S3C2410_SPRDAT);&&&&__raw_writeb(0xff,base_addr+S3C2410_SPTDAT);&&&&spi_poll_done();&&&&dataRX_1=__raw_readb(base_addr+S3C2410_SPRDAT);&&&&s3c2410_gpio_setpin(S3C2440_GPJ12,1); &&&&printk(KERN_ALERT &K: dataRX_0=%d\n&,dataRX_0);&&&&printk(KERN_ALERT &K: dataRX_1=%d\n&,dataRX_1);}static int spi_adc_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,unsigned long arg){switch(cmd)&&&&{&&&&&&&&case CHANNAL_SELECT:&&&&&&&&&&&&dataTX=&&&&&&&&&&&&printk(KERN_ALERT &K:receive data=%d from user space\n&,dataTX);&&&&&&&&&&&&&&&&&&&&default:&&&&&&&&&&&&return -ENOTTY;&&&&}&&&&dataTX&&=3;&&&&dataTX|=0X04;&&&&//DONTC ZERO ADD2 ADD1 ADD0 REF PM1 PM0&&&&//&&0&&&&0&&&&&&&&&&&&&&&&&& 1&& 0&& 0&&&&printk(KERN_ALERT &K:change dataTX=%d\n&,dataTX);return 0;}static int spi_adc_read(struct file *filp,char __user *buf,size_t count,loff_t *f_ops){&&&&struct adc_dev *dev=filp-&private_&&&&&&&&if(filp-&f_flags&O_NONBLOCK) //read block&&&&{&&&&&&&&ret= -EAGAIN;&&&&&&&&&&&&}&&&&if(down_interruptible(&dev-&sem)) //own the sem&&&&{&&&&&&&&return -ERESTARTSYS;&&&&}&&&&ad_convert();&&&&ad_convert();&&&&convert_data=dataRX_0;&&&&convert_data&&=8;&&&&convert_data+=dataRX_1;&&&&convert_data&=0x0&&&&printk(KERN_ALERT &K:send data=%d/tto user space\n&,convert_data);&&&&ret=copy_to_user(buf,&convert_data,count); //success ret=0&&&&up(&dev-&sem);&&//release samephore semout:}static int spi_adc_open(struct inode *inode,struct file *filp){&&&&struct adc_dev * //device information&&&&dev=container_of(inode-&i_cdev,struct adc_dev,cdev);&&&&filp-&private_data= //for other methors&&&&printk(KERN_ALERT &K:spi device opened\n&);&&&&configure_spi_pin();return 0;}static int spi_adc_close(struct inode *inode,struct file *filp){&&&&printk(KERN_ALERT &K:spi device closed\n&);&&&&s3c2410_gpio_setpin(S3C2440_GPJ12,1);&&//set CS high , chip select canceledreturn 0;}static struct file_operations spi_adc_fops={&&&&.owner&&&&=THIS_MODULE,&&&&.open&&&&=spi_adc_open,&&&&.ioctl&&&&=spi_adc_ioctl,&&&&.read&&&&=spi_adc_read,&&&&.release=spi_adc_close,};/*setup char device*/static void adc_setup_cdev(struct adc_dev *dev){&&&&&&&&int devno=MKDEV(adc_major,adc_minor);&&&&cdev_init(&dev-&cdev,&spi_adc_fops);&&&&dev-&cdev.owner=THIS_MODULE;&&&&dev-&cdev.ops=&spi_adc_&&&&err=cdev_add(&dev-&cdev,devno,adc_number);&&&&if(err)&&&&&&&&printk(KERN_NOTICE &K:Error %d\n&,err);}static int __init spi_adc_init(void){&&&&&&&&dev_t dev=0;//remap physics address to vitrual address&&&&base_addr=ioremap(S3C2410_PA_SPI,0x20); &&&&if(base_addr==NULL)//deal with error&&&&{ &&&&&&&&printk(KERN_ERR &K:Failed to remap register block\n&);&&&&&&&&return -ENOMEM;&&&&}&&&&&&&&if(adc_major)&&&&{&&&&&&&&dev=MKDEV(adc_major,adc_minor);&&&&&&&&ret=register_chrdev_region(dev,adc_number,&spi_adc&);&&&&}&&&&else//alloc device major &&&&{&&&&&&&&ret=alloc_chrdev_region(&dev,adc_minor,adc_number,&spi_adc&);&&&&&&&&adc_major=MAJOR(dev);&&&&}&&&&if(ret&0)&&&&{&&&&&&&&printk(KERN_WARNING &K:can't get major %d\n&,adc_major);&&&&&&&&&&&&}&&&&&&init_MUTEX(&devp-&sem);&&//inital semaphore sem=1&&&&adc_setup_cdev(devp);&&&&printk(KERN_NOTICE &K:initial!\n&);return 0;}static void __exit spi_adc_exit(void){ &&&&int devno=0;&&&&iounmap(base_addr);&&&&devno=MKDEV(adc_major,adc_minor);&&&&cdev_del(&devp-&cdev);&&&&unregister_chrdev_region(devno,adc_number);&&&&printk(KERN_NOTICE &K:exit!\n&);}module_init(spi_adc_init);module_exit(spi_adc_exit);MODULE_LICENSE(&Dual BSD/GPL&);MODULE_AUTHOR(&&);MODULE_DESCRIPTION(&serial adc7888 convert&);
级别: 新手上路
金钱: 90 两
威望: 18 点
贡献值: 0 点
综合积分: 36 分
没有人回答,我自己来答在驱动程序里读写寄存器分两步。第一步:把硬件的首地址映射到内核空间中去(ioremap())第二步:使用ioread8,iowrite8,........... 等一系统的io内存操作函数,以基地址加偏移的方法读写。在上面的这一段代码中,主要的问题是没有分配内存,也就是没有为cdev结构分配内存空间,即kmalloc()
级别: 新手上路
金钱: 85 两
威望: 17 点
贡献值: 0 点
综合积分: 34 分
为什么我映射后无法读写呢,写入的值和读出的值不一样
Powered by

我要回帖

更多关于 stm32 spi寄存器 的文章

 

随机推荐