登录 免费注册 首页 | 行业黑名单 | 帮助
维库电子市场网
技术交流 | 电路欣赏 | 工控天地 | 数字广电 | 通信技术 | 电源技术 | 测控之家 | EMC技术 | ARM技术 | EDA技术 | PCB技术 | 嵌入式系统
驱动编程 | 集成电路 | 器件替换 | 模拟技术 | 新手园地 | 单 片 机 | DSP技术 | MCU技术 | IC 设计 | IC 产业 | CAN-bus/DeviceNe

使能Dcache后,DMA接收数据不正确,请帮忙

作者:ligenzhu 栏目:DSP技术
使能Dcache后,DMA接收数据不正确,请帮忙
为了提高运行速度,我使能了指令Cache和数据Cache,结果发现,使能指令
Cache后,程序速度确实提高了一些;但是在使能数据Cache后,DMA接收出现异常。(呵呵,我做了点灯测试试验,使能数据Cache后,速度居然提高了6倍)。

在我的主程序中,添加如下代码使能指令Cache和数据Cache。
#include <cplb.h>
#pragma retain_name //use cache,improve program speed
int __cplb_ctrl =
CPLB_ENABLE_ICPLBS|
CPLB_ENABLE_ICACHE|
CPLB_ENABLE_DCPLBS|
CPLB_ENABLE_DCACHE;
在我的子程序中,有如下代码:
unsigned CHAR ucBuf[126]; //define DMA recieve buffer and size
InitDMARead(ucBuf, 126); //initialize DMA and enable DMA
// send message to sensor, and Request Registers
FPSWriteData(0x80);
FPSWriteData(0x01); // Reset the sensor
FPSWriteData(0x81);
FPSWriteData(0x02); // Request Registers
// Wait for DMA to finish reading the data
while ((*pDMA5_IRQ_STATUS & DMA_DONE) == 0) { }
*pDMA5_IRQ_STATUS = 0x000f; //clear bit DMA_DONE;
*pDMA5_CONFIG = 0x00a2; //DMA disable, 8 bit transfer, write operation
for( i = 0; i < 126; i++ ) // DISPLAY register.
{
printf("%2x ",ucBuf[i]);
}

问题是使能数据Cache后,DMA接收的数据不正确,但是我把接收的Buffer尺寸改为1725后,居然接收正常。
unsigned CHAR ucBuf[126]; ---> unsigned CHAR ucBuf[1725];
试着改为其它大小,发现接收的数据也不正确,(里面有时候有部分正确)。
其实我接收的只是126字节,我用示波器测量过了,我的命令确实正确发到了外围接口芯片上,而且外围接口芯片回来的数据用示波器测量也是正确的。
我也不知道发生了什么事情,请大家帮忙。

thanks.


2楼: >>参与讨论
hardfire
DMA是从哪到哪?PPI<-->SDRAM?
看看是否有需要用SSYNC的地方。


3楼: >>参与讨论
ligenzhu
DMA是从SPI到SDRAM中的
void InitDMARead(unsigned CHAR * pDstBuf, unsigned int uiNumBytesToRead)
{
    // Set destination address for DMA
    *pDMA5_START_ADDR = pDstBuf;
   // Set the count to read in the DMA
   *pDMA5_X_COUNT = uiNumBytesToRead;
   *pDMA5_X_MODIFY = 1;

   // Set the DMA Enable bit, Increment Destination, Don’t Increment Source, 8-bit Trasnfers
   *pDMA5_CONFIG = 0x00a3;  //DMA enable, 8 bit transfer, write operation
    
   // Initialize the SPI PORT: Slave, 8-bit Xfer, Clock SPI Opposite
   *pSPI_CTL = 0x4412; //spi slave, spi 8 bit, DMA reciever
    
   // DMA is now ready to receive the data...
}


4楼: >>参与讨论
hardfire
共同研究
我看linux下的spi_read代码一开始就执行:
// TODO: remove this LINE as soon GFP_DMA MEMORY allocation is in place

blackfin_dcache_invalidate_range(buf, buf+(count)*2);
你看看。


5楼: >>参与讨论
ligenzhu
确实是BF531的一个BUG,在执行DMA时,需要把相应DATACache关掉。
6. 05000158 - Instruction DMA can cause data cache fills to fail (boot implications):
DESCRIPTION:
After a DMA or core MMR DTEST register access has occurred to the L1 instruction MEMORY, a data cache fill to the corresponding PORT
may get corrupted data. This situation can ONLY occur if stalls are introduced because the core is accessing the same data MEMORY bank as
the data cache fill.
This data cache fill can occur many cycles after the L1 Instruction MEMORY DMA or MMR access. One example of the failure is when a
program that enables data cache is booted. The Instruction DMA that occurred during the boot may prime the processor to be
susceptible to data corruption in a data cache fill that occurs sometime during the main program's execution.
For PORT A, data locations 0xFF80xxxx and instruction locations 0xFFA00000 -0xFFA07FFF (where applicable) are subject to the failure. For
PORT B, data locations 0xFF90xxxx and instruction locations 0xFFA08000 - 0xFFA0FFFF (where applicable) are subject to the failure.
The problem will also occur if the last DMA transaction was to the L1 instruction MEMORY while a low priority data cache fill is ongoing.
WORKAROUND:
The best workaround for this issue is to set bit 9 of any DCPLB Data register that you use. This bit is shown as a reserved bit in the
HARDWARE Reference Manual, but the documentation is being updated to describe the functionality of this bit.
A second workaround would be to perform a SOFTWARE.html">SOFTWARE core reset at the beginning of the program:
P0.H = HI(SYSCR); // Check SYSTEM Reset Configuration Register
P0.L = LO(SYSCR);
R0.L = W[P0];
CC = BITTST(R0,4); // Check NO BOOT ON SOFTWARE RESET Bit
IF CC JUMP _No_Boot_Set;
BITSET(R0,4); // Set NO BOOT ON SOFTWARE RESET Bit
W[P0] = R0;
SSYNC; // Ensure write completes before executing RAISE
RAISE 1;
_No_Boot_Set:
BITCLR(R0,4); // Reset SYSCR to original VALUE
W[P0] = R0;
If the program will be performing both data caching and L1 Instruction MEMORY DMA, perform a Data DMA to the data SRAM which
shares a data PORT with the Instruction SRAM after performing an Instruction DMA. Do not perform any access that would cause data
caching or victimization from the time the Instruction DMA begins until after the Data DMA has completed. Also, an MMR DTEST access to
the corresponding data bank could also clear out the problem if the original problem was caused by the Instruction MEMORY DMA.
If the program will access the L1 Instruction MEMORY through the core MMR DTEST register, follow this access with a core MMR DTEST
register access to the corresponding Data Bank.
If the processor is either not DMAing to instruction MEMORY or not using data cache, you will not encounter this problem.
The VisualDSP++ runtime libraries cache supPORT functions contain a workaround for this anomaly where necessary.

6楼: >>参与讨论
hardfire
有些疑问一起讨论
L1 I MEM只能用64bit DMA访问,可见enable I cache后,DMA操作是时刻在发生的;
而linux下同时也enable 了D cache,那这样岂不是动辄就要diable D cache?
有些看晕了。

7楼: >>参与讨论
ligenzhu
那倒不用。
可以把DMA所用的BUFFER不让它使用BUFFER。
例如调用下面这个函数一样。
blackfin_dcache_invalidate_range(buf, buf+(count)*2);

不过它的源码没有找到,我只能全部把它关掉了,然后再打开。
下面是我的代码的一部分。我想只要把那段内存空间不全能L1 Cache映射就可
以了,只是没有验证成功。

#include <defbf533.h>
#include <cdefbf533.h>
#include <stdio.h>
#include "main.h"

#define DCPLB_CNT 10
#define ICPLB_CNT 9

/************************************************/
/*                                                */
/*          Entries for the DCPLBx_ADDR            */
/*                                                */
/************************************************/
#pragma align4
section ("data1")
unsigned int D_cplb_addrs[DCPLB_CNT] =
    {
        0xff800000,    
        0xff900000,
        0x00000000,    
        0x00400000,    
        0x00800000,
        0x00C00000,
        0x01000000,    
        0x01400000,    
        0x01800000,
        0x01C00000
    };
        
/************************************************/
/*                                                */
/*          Entries for the DCPLBx_DATA            */
/*                                                */
/************************************************/
#pragma align4
section ("data1")
unsigned int D_cplb_data[DCPLB_CNT] =
    {
        0x2001f,
        0x2001f,
        0x3D01f,
        0x3D01f,
        0x3D01f,
        0x3D01f,
        0x3D01f,
        0x3D01f,
        0x3D01f,
        0x3D01f
    };
        
/************************************************/
/*                                                */
/*          Entries for the ICPLBx_ADDR            */
/*                                                */
/************************************************/
#pragma align4
section ("data1")
unsigned int I_cplb_addrs[9] =
    {
        0xFFA00000,
        0x00000000,
        0x00400000,
        0x00800000,
        0x00C00000,
        0x01000000,
        0x01400000,
        0x01800000,
        0x01C00000
    };
        
/************************************************/
/*                                                */
/*          Entries for the ICPLBx_DATA            */
/*                                                */
/************************************************/
#pragma align4
section ("data1")
unsigned int I_cplb_data[9] =
    {
        0x00020003,
        0x00031005,
        0x00031005,
        0x00031005,
        0x00031005,
        0x00031005,
        0x00031005,
        0x00031005,
        0x00031005
    };

    
/********************************/
/*                                */
/*    LOCK CONTROL for the ICache */
/*         1: LOCK the way        */
/*         0: Don't LOCK             */
/*                                */
/**
8楼: >>参与讨论
hardfire
uClinux-dist/linux-2.6.x/arch/blackfin/mach-common/cache.S
/* Throw away all D-cached data in specified region without any obligation to
* write them BACK. However, we must clean the D-cached entries around the
* boundaries of the start and/or end address is not cache aligned.
*
* Start: start address,
* end  : end address.
*/

ENTRY(_blackfin_dcache_invalidate_range)
    R2 = -L1_CACHE_BYTES;
    R2 = R0 & R2;
    P0 = R2;
    P1 = R1;
    CSYNC;
    FLUSHINV[P0];
1:
    FLUSHINV[P0++];
    CC = P0 < P1 (iu);
    IF CC JUMP 1b (bp);

    /* If the data crosses a cache LINE, then we'll be pointing to
     * the last cache LINE, but won't have flushed/invalidated it yet,
     * so do one more.
     */
    FLUSHINV[P0];
    SSYNC;
    RTS;


9楼: >>参与讨论
ligenzhu
你这里有没有BF531的汇编指令集呀,
没有对照,看得不太明白。。。

10楼: >>参与讨论
hardfire
指令手册PROGRAMMING reference有啊
http://www.analog.com/processors/blackfin/technicalLibrary/manuals/index.html

ADSP-BF53x/BF56x Blackfin Processor PROGRAMMING Reference (Revision 1.1, February 2006) (pdf, 3.40 MB)
就是啊。

参与讨论
昵称:
讨论内容:
 
 
相关帖子
原理图?
BF533外接DAC遇到的问题
如何修改配置,优化程序,提高BF531的处理速度?
Telnet问题
关于PPI FIFO
免费注册为维库电子开发网会员,参与电子工程师社区讨论,点此进入


Copyright © 1998-2006 www.dzsc.com 浙ICP证030469号