2009年9月16日星期三
dm355压缩1027x768的视频
@0x000a3d45:[T:0x40018CMEMK Error: Failed to find a pool which fits 2740224
070] venc - App-> Application started.
CMEM Error: getPool: Failed to get a pool fitting a size 2740224
@0x000a6b2b:[T:0x40018070] venc - ERROR: can't open mpeg4enc
@0x000a7176:[T:0x40018070] venc - app done.
root@192.168.1.222:/opt/dvsdk#
root@192.168.1.222:/opt/dvsdk# ./venc foreman
_vga_422i.yuv 2.mpeg4@0x000aea7a:[T:0x40018070] venc - main> venc
这是因为cmemk.ko分配的缓冲区太小导致的,在loadmodules.sh里将其改大
增加两个3M的pool
启动的时候会报错,说cmemk.ko占用了内核的内存空间,
在uboot内核参数中中将mem=116M
改成mem=109M即可,
正常的进行1024x768的视频压缩。
DM355的启动方式
第一种是从片外的Asynchronous EMIF (AEMIF) 启动 是指从片外的三星OneNAND
器件启动
第二种方式是从片内的ROM启动,执行ROM中的ROM boot loader
(RBL),RBL支持三种片外介质,BTSEL决定RBL针对哪种介质进行启动
– BTSEL[1:0] = 00 - ARM NAND Boot
– BTSEL[1:0] = 10 - ARM MMC/SD Boot
– BTSEL[1:0] = 11 - ARM UART Boot
现在选择从片外的NAND启动,这种启动方式的具体步骤是RBL先从片外NAND上将UBL(user
boot loader)取进ARM内部的RAM中(copies a second stage user boot loader
(UBL) from NAND flash to ARM internal RAM (AIM) and transfers control to
the user-defined
UBL),然后执行,UBL进行的工作是从NAND中将剩下的数据取进DDR中并跳转到那里。
在NAND中存在两种代码,1是UBL,二是用户自己的代码APP,RBL是如何找到UBL的呢,原来对于RBL和APP在Nand中的存储必须符合一定的格式,在存储UBL或者APP代码的第一页是专门用来存储一个信息头,这个信息头的格式如下
/* Some of the parameters are modified runtime */
unsigned int ubldesc [] = {
0xA1ACED00, //Magic number
0x00000020, // Entry point for the UBL
0x00000007, // No. of pages for the UBL code
0x1, // Starting block of UBL in NAND
0x1 // Starting page of UBL in NAND
};
/* Some of the parameters are modified runtime */
unsigned int appdesc [] = {
0xB1ACED22, //Magic number
0x0000000A, // Start block in NAND
0x81080000, // Start address in DDR
0x81080000, // Entry point
0x00000200, // No. of pages for the complete Application
0x00000000 //compression flag
};
这个信息头分别包含了程序加载时的起始地址和入口点等等信息,当DM355复位时,片内ROM上的代码对NAND
CONTROLLER进行初始化并且在NAND中寻找UBL的Magic number
(事先已经约定好的),找到以后就根据信息头里提供的信息将UBL拷贝进片内RAM中(0x00000020,
// Entry point for the
UBL),然后进行执行,UBL的代码在光盘中有提供,其机制和RBL相同,只不过这个UBL是针对UBOOT的,如果不详执行UBOOT而是向执行自己的代码
那么需要将CCS编译出来的OUT文件转化成bin文件 下载到NAND中。
总结一下nand中存放的东西 UBL、uboot、LINUX的内核映像uimage、文件系统。
前两个的下载是用NAND_programmer进行,NAND_programmer的代码在光盘中也有,就是一段运行在DDR中的程序,将输入的UBL
和uboot文件加上信息头后存储到NAND中
后两个的下载用uboot就能实现。
DM355的I2C调试
DaVinci I2C WARNING: i2c: NACK detected
DaVinci I2C WARNING: i2c: RAR detected
这个报错是因为从设备没有反馈导致的,
后来发现是8574的地址写错了,导致I2C控制器老出现错误中断。
改正后测试I2C的SCL线的clock为400KHz。
为了和单片机连,需要降频。
修改drivers/i2c/buses/i2c-davinci.c文件
static int __init i2c_davinci_init(void)
{
int status;
struct device *dev = NULL;
DEB0("%s %s", __TIME__, __DATE__);
DEB1("i2c_davinci_init()");
/*
* NOTE: On DaVinci EVM, the i2c bus frequency is set to 20kHz
* so that the MSP430, which is doing software i2c, has
* some extra processing time
*/
if (machine_is_davinci_evm())
i2c_davinci_busFreq = 20;
else if (i2c_davinci_busFreq > 200)
i2c_davinci_busFreq = 400; /*Fast mode */
else
i2c_davinci_busFreq = 100; /*Standard mode */
i2c_clock = clk_get (dev, "I2CCLK");
}
DM355的UART调试
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_McBSP1, 1);
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_SPI, 1);
/* Turn on WatchDog timer LPSC. Needed for RESET to work */
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_TIMER2, 1);
/*add uart1 by xujiaxin*/
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_UART1,1);
/*end add*/
davinci_serial_init(&serial_device);
davinci_writel(0x56837210, DAVINCI_VPSS_REGS_BASE + 0x810);
davinci_writel(0x7b3c0004, DAVINCI_VPSS_REGS_BASE + 0x814);
/*enable uart1 by jiaxinxu*/
ptr_pgmgt = (volatile int *)IO_ADDRESS(DAVINCI_UART1_BASE+0x30);
ptr_ier = (volatile int *)IO_ADDRESS(DAVINCI_UART1_BASE+0x4);
*ptr_pgmgt=0x0;
*ptr_ier =0x0;
int del;
for(del=0;del<100000;del++)
*ptr_pgmgt=0x6001;
/*end enable*/
运行rs232程序,一开始函数在发送0x0a时老是会先发送一个0x0d,后来在程序中加入下面两句话
/*RAW格式 否则会出错*/
options.c_lflag&=~(ICANON|ECHO|ECHOE|ISIG);
options.c_oflag&=~OPOST;
就不会出错了。
board_setup_psc函数用来设置PSC模块,该模块的作用是开启某个模块的电源以及使能某个模块。
对UART2进行初始化的时候,必须注意UART2和SD1是复用的。没有改动前的内核初始化时自动的初始化SD1而不是UART2。需要进行一下几点动作才能将SD1的初始化屏蔽掉。
//choose uart2 instead of sd1 jiaxinxu
PINMUX3&=~0x0000ffff;
PINMUX3|= 0x0000a000;
将引脚功能置成UART2,
//conflict with uart2 by jiaxinxu
board_setup_psc(DAVINCI_GPSC_ARMDOMAIN, DAVINCI_LPSC_MMC_SD1, 0);
禁能PSC
#if defined(CONFIG_MMC_DAVINCI) || defined(CONFIG_MMC_DAVINCI_MODULE)
&mmc0_device,
//conflict with uart2 by jiaxinxu
//&mmc1_device,
DM355的SD卡虚拟成U盘
内核编译配置如usb. Txt内容。
在/etc/init.d/rcS中加入初始化语句。
insmod musb_hdrc.ko
insmod g_file_storage.ko file=/dev/mmcblk0p1
一开始插上USB以后老是显示无法初始化硬件,是因为USB小板上将D+和D-画反了
遇到的问题:
1.在拍照的过程中,拍摄100幅照片,第一次将USB插到主机上,会显示这100幅照片的大小都是0;但是在板子上输入ls –al /mnt/sdcard看 大小都是15.8K,是正确的。第二次插上USB以后有可能会有一些图像变正确,大小变为15.8K并且可以打开。其他的一些图像就坏掉了。
2.后来对这个问题进行进一步的研究,在不加载USB驱动的情况下拍摄100幅照片,拍摄完成后在串口终端上将SD卡上的数据拷贝到NFS上,再从Linux虚拟机下拷贝到windows上,看图片都是正确的,在串口终端上输入ls –al /mnt/sdcard看 大小都是15.8K。板子断电,拔下SD卡,通过读卡器插到pc机上,在windows下浏览,结果也都是正常。但是如果不进行上述的拷贝工作,只有一副照片m1.jpeg是正常的(随机的有可能其他几个是正常的,但不是所有的都正常),其他的都是0k。将SD卡再插回板子,上电再执行ls –al /mnt/sdcard,发现只有m1.jpeg是正常的,其他的都是0k。
解决办法:linux下,向磁盘写入数据会先将数据缓存在内存里,系统在合适的时候再将数据从内存中写到磁盘里。所以SD卡拔下之前要运行sync命令,保证内存中的数据完全写入磁盘里
DM355文件系统固化
mount –t yaffs2 /dev/mtdblock3 /mnt
然后
cp -rf /copytoflash4TECHV/* /mnt/
但是当拷贝的时候报错
status check failed: 2
status check failed: 2
nfs: server 192.168.1.147 not responding, still trying
这个问题没有解决
最后将文件系统的压缩文件考到SD卡中,将SD卡的文件考到mtd上 解压
mount -t yaffs2 /dev/mtdblock3 /mnt
mount /dev/mmcblk0p1 /tmp
cp /tmp/copyfl~1.gz /mnt/copy.tar.gz
tar xzvf copy.tar.gz
mv copyflash4TECHV/* ./
rm -rf copyflash4TECHV/
DM355的SPI调试
/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 的clk是4MHz
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