DM355的SPI调试

 

对于dm355evm   /dev文件夹下没有spi设备,只有一个eeprom设备,这个设备用spi接口进行控制。该设备的设备文件是/dev/mtdblock5.他的驱动程序是at25xxA_eeprom.c。为什么他的设备文件是/dev/mtdblock5呢?在at25xxA_eeprom.c中的eeprom_probe函数中,调用了    ret = add_mtd_device(mtd)将该eeprom加入了mtdblock的链表中。其源码如下:

 

DEBUG(0, "mtd: Giving out device %d to %s/n",i, mtd->name);一句打印出来是:

drivers/spi/spi.cmtd: Giving out device 5 to spi_eeprom

同样我们可以看到。

mtd: Giving out device 0 to bootloader

mtd: Giving out device 1 to params

mtd: Giving out device 2 to kernel

mtd: Giving out device 3 to filesystem1

mtd: Giving out device 4 to filesystem2

 

 如果不需要EEPROM那么可以将这个驱动程序进行一些修改  改成SPI的驱动程序

主要的底层驱动文件有四个spi.c spi.h dm355_spi_master.h dm355_spi_master.c

spi.c 和spi.h主要进行了SPI驱动的上层封装  dm355_spi_master.h dm355_spi_master.c则是对底层的寄存器进行访问

 

一开始调试的时候发现一个bug 当发送N个字节的时候老是会多发一个数 而且在最后一个数发送之前CS会有一个小毛刺。

后来去阅读代码

 

发现最后那个字节是作者故意加上的  为了防止这个毛刺对访问eeprom控制数据的影响。

看了DM355底层的spi寄存器,发现问题处在SPIDAT1寄存器上。

 

去网上查解决办法  搜到了DM355的勘误表 原来是一个芯片BUG  靠!

 

 

根据勘误表上的解决办法修改成功后的SPI

调用spi write连续写数(或spi read读数 C S是一直使能的。

但是 先写数再读数 CS中间是有一段不使能。

进行速度测试后的结果是:

SPI clk4MHz

Spi 读写速度是300000Bytes/s

linux下寄存器各字节分开访问的接口函数在include » asm-arm » arch-davinci 的io.h中

00001 /*
00002 * DaVinci IO address definitions
00003 *
00004 * Copied from include/asm/arm/arch-omap/io.h
00005 *
00006 * 2007 (c) MontaVista Software, Inc. This file is licensed under
00007 * the terms of the GNU General Public License version 2. This program
00008 * is licensed "as is" without any warranty of any kind, whether express
00009 * or implied.
00010 */
00011 #ifndef __ASM_ARCH_IO_H
00012 #define __ASM_ARCH_IO_H
00013
00014 #define IO_SPACE_LIMIT 0xffffffff
00015
00016 /*
00017 * ----------------------------------------------------------------------------
00018 * I/O mapping
00019 * ----------------------------------------------------------------------------
00020 */
00021 #define IO_PHYS         0x01c00000
00022 #define IO_OFFSET       0xfd000000 /* Virtual IO = 0xfec00000 */
00023 #define IO_SIZE         0x00400000
00024 #define IO_VIRT         (IO_PHYS + IO_OFFSET)
00025 #define io_p2v(pa)      ((pa) + IO_OFFSET)
00026 #define io_v2p(va)      ((va) - IO_OFFSET)
00027 #define IO_ADDRESS(x)   io_p2v(x)
00028
00029 /*
00030 * We don't actually have real ISA nor PCI buses, but there is so many
00031 * drivers out there that might just work if we fake them...
00032 */
00033 #define PCIO_BASE               0
00034 #define __io(a)                 ((void __iomem *)(PCIO_BASE + (a)))
00035 #define __mem_pci(a)            (a)
00036 #define __mem_isa(a)            (a)
00037
00038 #ifndef __ASSEMBLER__
00039
00040 /*
00041 * Functions to access the DaVinci IO region
00042 *
00043 * NOTE: - Use davinci_read/write[bwl] for physical register addresses
00044 *       - Use __raw_read/write[bwl]() for virtual register addresses
00045 *       - Use IO_ADDRESS(phys_addr) to convert registers to virtual addresses
00046 *       - DO NOT use hardcoded virtual addresses to allow changing the
00047 *         IO address space again if needed
00048 */
00049 #define davinci_readb(a)        (*(volatile unsigned char  *)IO_ADDRESS(a))
00050 #define davinci_readw(a)        (*(volatile unsigned short *)IO_ADDRESS(a))
00051 #define davinci_readl(a)        (*(volatile unsigned int   *)IO_ADDRESS(a))
00052
00053 #define davinci_writeb(v,a)     (*(volatile unsigned char  *)IO_ADDRESS(a) = (v))
00054 #define davinci_writew(v,a)     (*(volatile unsigned short *)IO_ADDRESS(a) = (v))
00055 #define davinci_writel(v,a)     (*(volatile unsigned int   *)IO_ADDRESS(a) = (v))
00056
00057 /* 16 bit uses LDRH/STRH, base +/- offset_8 */
00058 typedef struct { volatile u16 offset[256]; } __regbase16;
00059 #define __REGV16(vaddr)         ((__regbase16 *)((vaddr)&~0xff)) /
00060                                         ->offset[((vaddr)&0xff)>>1]
00061 #define __REG16(paddr)          __REGV16(io_p2v(paddr))
00062
00063 /* 8/32 bit uses LDR/STR, base +/- offset_12 */
00064 typedef struct { volatile u8 offset[4096]; } __regbase8;
00065 #define __REGV8(vaddr)          ((__regbase8  *)((vaddr)&~4095)) /
00066                                         ->offset[((vaddr)&4095)>>0]
00067 #define __REG8(paddr)           __REGV8(io_p2v(paddr))
00068
00069 typedef struct { volatile u32 offset[4096]; } __regbase32;
00070 #define __REGV32(vaddr)         ((__regbase32 *)((vaddr)&~4095)) /
00071                                         ->offset[((vaddr)&4095)>>2]
00072
00073 #define __REG(paddr)            __REGV32(io_p2v(paddr))
00074 #else
00075
00076 #define __REG(x)        (*((volatile unsigned long *)io_p2v(x)))
00077
00078 #endif /* __ASSEMBLER__ */
00079 #endif /* __ASM_ARCH_IO_H */

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值