各位大神,能否为小弟解答一个问题?我现在仿照合众达seed642自己做了一块基于DM642的板子, 没有使用cpld,flash用的是Am29LV033C,4M的,22根地址线,DM642只有20根地址线,所以我用 了两个GPIO口来扩充。现在想实现flash的烧写,但手中的例程都是基于cpld的,而且看不太明白, 请大神帮我看看,万分感谢。我是DSP新手,还望诸位见谅~ |
noaming:
你好,首先CPLD和FLASH并没关系,对FLASH的读写不受CPLD的影响,因为访问FLASH走的EMIF总线。那个例程的CPLD是意在读取存储在FLASH里的程序到CPLD里运行。所以你只用分析\evmdm642\evmdm642\flashburn\FBTC642里面的代码就可以了。至少FLASH低位空间访问是没有问题的。高位需要GPIO来模拟,这时候需要改这部分代码了。
shu wei xiao:
回复 noaming:
首先,谢谢您抽出时间来回复我。我先看看您说的这个代码,有问题我再向您请教。
shu wei xiao:
回复 noaming:
您好,我最近研读了一下有关seed开发板上有关flash烧写的程序,理解了七七八八吧,但是有一个地方我有点不明白,请您帮我看看行吗?
下面是我感到困惑的地方:
for(page = 0;page<8;page++) { /*取FLASh的首址*/ addr = SEEDDM642_FLASH_BASE; /* Set Flash page*/ SEEDDM642_rset(SEEDDM642_FLASHPAGE, page); /*等待延时*/ SEEDDM642_waitusec(1); /*将数据写入第0页,每页512K*/ limit = 8; for (i = 0; i < limit; i++) { for (j = 0; j < 128; j++) { startaddr = addr; /*每次写入512个字节,以16位的数据为基数*/ for (k = 0; k < 256; k++) { buffer[k] = (addr + i + page) & 0xffff; addr += 2; } SEEDDM642_FLASH_write((Uint32)buffer, startaddr, 512); } }
以上是我摘录了其中一段,我明白seed642开发板个是利用19位地址线来连接flash(AMD29LV033C),
合众达的处理是运用cpld扩展例外三根地址线,将flash分成8页,每页有512k的大小,
我了解到该款flash的扇区大小为64K,因此上面程序中分别套用的两个循环,for (j = 0; j < 128; j++)和for (k = 0; k < 256; k++)
就能解释的通了。
我的问题是buffer[k] = (addr + i + page) & 0xffff;是怎么回事呢?合众达定义的这个数组是个int型说明以16位来进行赋值,
但是这样的问题就在于i和page的作用是什么呢?如当i和page取1时,这个数组取的数又是什么呢?因为这样按位求出的结果
貌似有误,还请大神指教
shu wei xiao:
回复 noaming:
您好,我最近研读了一下有关seed开发板上有关flash烧写的程序,理解了七七八八吧,但是有一个地方我有点不明白,请您帮我看看行吗?
下面是我感到困惑的地方:
for(page = 0;page<8;page++){/*取FLASh的首址*/addr = SEEDDM642_FLASH_BASE;/* Set Flash page*/SEEDDM642_rset(SEEDDM642_FLASHPAGE, page); /*等待延时*/SEEDDM642_waitusec(1);/*将数据写入第0页,每页512K*/limit = 8;for (i = 0; i < limit; i++){for (j = 0; j < 128; j++){startaddr = addr;/*每次写入512个字节,以16位的数据为基数*/for (k = 0; k < 256; k++){buffer[k] = (addr + i + page) & 0xffff;addr += 2;}SEEDDM642_FLASH_write((Uint32)buffer, startaddr, 512);}}
以上是我摘录了其中一段,我明白seed642开发板个是利用19位地址线来连接flash(AMD29LV033C),
合众达的处理是运用cpld扩展例外三根地址线,将flash分成8页,每页有512k的大小,
我了解到该款flash的扇区大小为64K,因此上面程序中分别套用的两个循环,for (j = 0; j < 128; j++)和for (k = 0; k < 256; k++)
就能解释的通了。
我的问题是buffer[k] = (addr + i + page) & 0xffff;是怎么回事呢?合众达定义的这个数组是个int型说明以16位来进行赋值,
但是这样的问题就在于i和page的作用是什么呢?如当i和page取1时,这个数组取的数又是什么呢?因为这样按位求出的结果
貌似有误,还请大神指教
KITCHEN:
你好,我现在也是在调试一个DM642的板子,现在遇见问题了,是不能擦除FLASH,flash的型号是AM29LV033C。我的硬件连接没有问题,请问你知道这个可能是什么原因么?
shu wei xiao:
回复 KITCHEN:
请问你的不能擦除是什么意思?我不是很明白,你可以先看看内存相应位置的数据是否改变,比如0x90000000以后的区域,你的硬件是怎么连接的?用的FPGA选通?还是I/O口模拟啊?
KITCHEN:
回复 shu wei xiao:
使用CPLD选通的。就是说FLASH的扇区擦除指令,dsp是正常发送出去了的。六个周期的指令序列嘛。可是貌似flash貌似没有正确接收到指令。导致flash的扇区内嵌擦除程序不工作。我吧我的程序给你看看。
FLASH型号:Am29LV033C我用一个合纵达提供的flash擦除和烧写的例程的时候,一直会死在擦除和写FLASH的函数的While循环那以下是擦除函数和写函数,麻烦大家看看,一块讨论讨论,我会关注本帖的,谢谢大家void SEEDDM642_FLASH_erase(Uint32 start, Uint32 length){ Int16 i; Uint8 *pdata; Uint32 sector_base, end; /* Calculate extents of range to erase */ end = start + length – 1; /* Walk through each sector, erase any sectors within range */ sector_base = SEEDDM642_FLASH_BASE; for (i = 0; i < SEEDDM642_FLASH_SECTORS; i++) { if ((start <= sector_base) && (sector_end[i] <= end)) { /* Start sector erase sequence */ *((Uint8 *)SEEDDM642_FLASH_BASE) = 0xAA; // SEEDDM642_wait(1000); *((Uint8 *)SEEDDM642_FLASH_BASE) = 0x55; // SEEDDM642_wait(1000); *((Uint8 *)SEEDDM642_FLASH_BASE) = 0x80; //SEEDDM642_wait(1000); *((Uint8 *)SEEDDM642_FLASH_BASE) = 0xAA; // SEEDDM642_wait(1000); *((Uint8 *)SEEDDM642_FLASH_BASE) = 0x55; // SEEDDM642_wait(1000); // *((Uint8 *)SEEDDM642_FLASH_BASE) = 0x10; /* Start erase at sector address */ pdata = (Uint8 *)sector_base; *pdata = 0x30; SEEDDM642_wait(1000); /* Wait for erase to complete */ while (1) { if (*pdata & 0xff)//程序死在这个while循环中 { break; } } /* Put back in read mode */ *((Uint8 *)SEEDDM642_FLASH_BASE) = 0xf0; } /* Advance to next sector */ sector_base = sector_end[i] + 1; }}烧写函数void SEEDDM642_FLASH_write(Uint32 src, Uint32 dst, Uint32 length){ Uint8 *psrc, *pdst; Uint32 i; /* Establish source and destination */ psrc = (Uint8 *)src; pdst = (Uint8 *)dst; for (i = 0; i < length; i++) { // Program one 8-bit word *((Uint8 *)SEEDDM642_FLASH_BASE) = 0xaa; *((Uint8 *)SEEDDM642_FLASH_BASE) = 0x55; *((Uint8 *)SEEDDM642_FLASH_BASE) = 0xa0; *pdst = *psrc; // Wait for operation to complete while(1)///这个循环也死 { if (*pdst == *psrc) { break; } } // SEEDDM642_waitusec(10000); pdst++; psrc++; } /* Put back in read mode */ *((Uint16 *)SEEDDM642_FLASH_BASE) = 0xf0; }
shu wei xiao:
回复 KITCHEN:
你好,你这个程序就是合众达给的例程吧?有几个问题,你可以参考一下。据我的经验(不一定对哈),分页执行的话,只能每次操作512K的数据,如果大于512K则不行,但是你说的是一直死在那个循环里,这个就有几种解释了,第一,你的flash工作了,但是你没有注意到,这个问题你可以通过查看寄存器是否为FFFFFFFF,即查看是否进行了擦除来验证,如果flash工作了,这个是最理想的情况,那么说明你的CPLD确实配置上有误,可能是分页不对等等。第二,你的flash没有工作,那么可能是你的片子坏了,或者是有其他什么原因导致了你的硬件出错,这两天我也是被这个问题所困,我通过用示波器测量发现,SDRAM的低八位工作不正常,导致flash的八位数据位有误,也是死在那些循环里。
KITCHEN:
回复 shu wei xiao:
是的,是合纵达的例程。我知道分页的,而且我的CPLD的分页是正确的,我觉得是我的flash在我的的DSP发送完6个周期的擦除指令后没有自动调用其内部的擦除程序进行擦除。而我能保证的是我的六个周期的擦除指令时正确的发送了过去的。擦看寄存器的时候寄出去全部是0x00000000.换了几个片子了,感觉也不是片子坏了。
KITCHEN:
回复 KITCHEN:
我的QQ 405211631 有时间的话我们一起聊一聊吧,我最近在用他的EMIF读取FIFO,感觉也遇到了一些问题,你看我们能互相学习一下么?