Hi community,
We have a board using IMX6UL. It is needed to transfer data between CPU and FPGA via EIM interface, and with DMA mode. The kernel version we used is 3.14.38.
Because the weim.DATA pin is used for lcdif.data, I configure the EIM interface to multiplexed mode(MUM=1), 16-bit datawidth(DSZ=001), and synchronous read/write(SRD=1, SWR=1), BCLK divide EIM clock by 1(BCD=1) . The EIM register is configured as follow:
EIM_CSnGCR1:0x7111019F
EIM_CSnGCR2:0x00000808
EIM_CSnRCR1:0x03000000
EIM_CSnRCR2:0x00000000
EIM_CSnWCR1:0x01012480
EIM_CSnWCR2:0x00000000
EIM_WCR:0x00000028
I modified the test module (mxc_sdma_memcopy_test) which get from community.(See attach) Now I can capture singnal on EIM interface from FPGA. And the timing is basically my expected.
Now I have two problem:
1、There is a interval every 32 bytes data when transfer data between memory and EIM with SDMA.
No matter I configure the burst length to 4/8/16/32 words, it is a interval erery 32-byte transfer. For my configure, 32-byte is 16 words(DSZ=001, 1 word is 2 byte),so when I configure the burst length to 32 words,one burst read or write is also only 16 words.
What is the reason of this interval? How can I eliminate or shorten this interval?
2、The timing of EIM interface when transfer from EIM to memory with SDMA is as my expected, but when I check the data in rbuf after transfer , the read data is error: some data is read twice and some data is lost. As follow is the timing I capture at FPGA:
The expected read data is:
dst data_0 : 00070006
dst data_1 : 00090008
dst data_2 : 000b000a
dst data_3 : 000d000c
dst data_4 : 00150014
dst data_5 : 00170016
dst data_6 : 00190018
dst data_7 : 001b001a
But the print result is:
dst data_0 : 00070006
dst data_1 : 00080007
dst data_2 : 00090008
dst data_3 : 000a0009
dst data_4 : 000c000c
dst data_5 : 000d000d
dst data_6 : 0000000e
dst data_7 : 000f0000
The second burst transfer data is almost lost. Is there something wrong with my configure for EIM? Or there is something I
should change when using SDMA for transfer from EIM to memory?
Attach my SDMA test module and the wave capture from FPGA.
Original Attachment has been moved to: mxc_sdma_memcopy_test.c.zip
Hi community:
I have solved the question 2 above, after I set the EIM_clk to 66MHz, other clk frequence is not ok. Then wen can transfer data between IMX6UL and FPGA. Finally, the EIM interface is configured multiplexed mode(MUM=1), 16-bit datawidth(DSZ=001), synchronous read and write, we used the BCLK for FPGA to capture the data, the burst length is still 8 words(16 byte). Burst read is monitored WAIT signal to start, burst write is fix latency So, the EIM register is finally configured as follow:
EIM_CSnGCR1:0x0111019F
EIM_CSnGCR2:0x00001010
EIM_CSnRCR1:0x02000000
EIM_CSnRCR2:0x00000000
EIM_CSnWCR1:0x01008280
EIM_CSnWCR2:0x00000000
The question 1 above is still exist.
Recently we found another data error promble while reading some address. For example, we first write 128 byte increasing num to the address begin from 0x21d00, then read back, there will be error data every 8 words(16 byte),it's a burst length. The following is the contrast data printed by the software. The value after "error" is the word number, the value after "w=" is the written data, and the value after "r=" is the readout data.
Error 8: w=0008, r=0807
Error 9: w=0009, r=0008
Error a: w=000a, r=0009
Error b: w=000b, r=000a
Error c: w=000c, r=000b
Error d: w=000d, r=000c
Error e: w=000e, r=000d
Error f: w=000f, r=000e
Error 18: w=0018, r=0817
Error 19: w=0019, r=0018
Error 1a: w=001a, r=0019
Error 1b: w=001b, r=001a
Error 1c: w=001c, r=001b
Error 1d: w=001d, r=001c
Error 1e: w=001e, r=001d
Error 1f: w=001f, r=001e
Error 28: w=0028, r=0827
Error 29: w=0029, r=0028
Error 2a: w=002a, r=0029
Error 2b: w=002b, r=002a
Error 2c: w=002c, r=002b
Error 2d: w=002d, r=002c
Error 2e: w=002e, r=002d
Error 2f: w=002f, r=002e
Error 38: w=0038, r=0837
Error 39: w=0039, r=0038
Error 3a: w=003a, r=0039
Error 3b: w=003b, r=003a
Error 3c: w=003c, r=003b
Error 3d: w=003d, r=003c
Error 3e: w=003e, r=003d
Error 3f: w=003f, r=003e
From the above error, in the 8 error words, the last 7 data error is like that be delay one clk cycle. And only some address segment have such read error.
Follow is the timing wave captured at FPGA.
On the data_from_fpga bus, the data in the blue box is the 8 words expected to be read one burst read. The timing wave is normal, the bus is not be delay and there's no a "0807" word before the "0008" words.The words "0807" can be seen from wr_data bus(wr_data is EIM_AD[15:0] input to FPGA and latch). But it appears on the bus 2 clk cycle before the word "0008", I can't understand why the word is sampled by the burst read.
Does anyone have similar promble?
If there is something wrong I configure the EIM, or SDMA?
This promble is solved.
The reason is: "When BCD=0 value of BCS=0 results in a half clock delay after the start of access. "
In my design, the BCD should be 0, So I change the BCS to 01,(EIM_CSnGCR1:0x0111419F)
Now the data read back is right.
Hi
Did your first question be solved? I also met the same problem about the interval.
Hi!!
I have same problem
I want to make interface i.mx6 solo and FPGA use EIM(with sdma).
I've already tested with that using eim.
But, it is not working very well.
In my case, give inturrupt signal to eim at 200us , then also give data in time.
Dma process is over time on interrupt time.
So i did change like below, use multiple dma channle.
But also not working very well.
| | | | | | <= inturrupts (200us interval)
dma channel 0 |-----|
dma channel 1 |-----|
dma channel 2 |-----|
....
However, this method did not work well because of the schemeler of dma.
How can I make dma without being pushed back to match the interrupt signal?
When did u make use eim to FPGA , can u help me?
In your case, how to make dma code.. ? hint plz.
Hi, we have use EIM to communicate with FPGA, and with DMA, but there‘s some promble, I will post later.
final, The EIM register is configured as follow:
EIM_CSnGCR1:0x0111019F
EIM_CSnGCR2:0x00001010
EIM_CSnRCR1:0x02000000
EIM_CSnRCR2:0x00000000
EIM_CSnWCR1:0x01008280
EIM_CSnWCR2:0x00000000
The relate DMA code is :
static int fpga_dma_reg_transfer(struct fpga_dev *fe, u32 addr, void *buf, u32 len, int is_write)
{
unsigned reg_addr = fe->phys_param_base + (addr << FPGA_ADDR_SHIFT);
int align_req = 32;
int align_size = (len + align_req - 1) / align_req * align_req;
// printk("fpga_dma_reg_transfer, fe:%p, addr:%x, len:%d, is_write:%d, align_size:%d\n", fe, addr, len, is_write, align_size);
if (align_size <= fe->max_param_size)
{
struct dma_async_tx_descriptor *dma_m2m_desc = NULL;
dmaengine_slave_config(fe->dma_m2m_chan_reg, &fe->dma_m2m_config);
if (is_write == 1)
{
dma_m2m_desc = fe->dma_m2m_chan_reg->device->device_prep_dma_memcpy(fe->dma_m2m_chan_reg,
reg_addr,
(dma_addr_t)buf,
align_size,
0);
}
else
{
dma_m2m_desc = fe->dma_m2m_chan_reg->device->device_prep_dma_memcpy(fe->dma_m2m_chan_reg,
(dma_addr_t)buf,
reg_addr,
align_size,
0);
}
if (dma_m2m_desc != NULL)
{
dma_m2m_desc->callback = dma_m2m_callback;
dma_m2m_desc->callback_param = &fe->dma_m2m_ok_reg;
dmaengine_submit(dma_m2m_desc);
dma_async_issue_pending(fe->dma_m2m_chan_reg);
wait_for_completion(&fe->dma_m2m_ok_reg);
return len;
}
}
return -EFAULT;
}
Hope help you.
Hi rooftree:
How do you get the fe->phys_param_base in your dma code? ioremap?
when i use sdma transfer data from mem to fpga (sdma config mem_to_mem, ioremap the base) it is not work.But don't use sdma just memcpy it is work well
hint plz.
Hi
please refer to example patch on
Measure SDMA Memory To Memory Copy Performance on i.MX6Q
for data corruption one can check max. EIM frequency (104MHz) given in
sect.4.9.3 External Interface Module (EIM) i.MX6UL Datasheet
http://cache.freescale.com/files/32bit/doc/data_sheet/IMX6ULCEC.pdf
To avoid intervals, check that SDMA source memory address was aligned
according to burst size.
Best regards
igor
-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------
igorpadykov,thanks your reply.
The EIM frequency I used is 88MHz,it is not exceed 104MHz。
And the source memory address, is 0x88xx0000,for example, the SDMA driver print:
"imx-sdma 20ee000.sdma: memcpy : 0x50000000->0x88a20000, len=61440, channel = 3"
I think it is aligned more than the burst size.
Hi ,
Iam working in SRAM through EIM interface in i.MX53 processor.when i read the value from devmem2 command,
I get 0xFFFFFFFF but when i write values to it like 0xAAAA5555 and then read it shows as 0xAAAAAAAAA
debian@arm:~$ sudo ./devmem2 0xF0000000 w 0xAAAA5555
/dev/mem opened.
Memory mapped at address 0xb6f15000.
Value at address 0xF0000000 (0xb6f15000): 0x10101010
Written 0xAAAA5555; readback 0xAAAAAAAA
If I read the next value , it gives the previous value .For Example, if i read value for 0xF0000004, 0xF0000008 etc it shows value of F0000000 as 0xAAAAAAAA
debian@arm:~$ sudo ./devmem2 0xf0000004
/dev/mem opened.
Memory mapped at address 0xb6fc0000.
Value at address 0xF0000004 (0xb6fc0004): 0xAAAAAAAA
debian@arm:~$
debian@arm:~$
debian@arm:~$
debian@arm:~$ sudo ./devmem2 0xf0000008
/dev/mem opened.
Memory mapped at address 0xb6f39000.
Value at address 0xF0000008 (0xb6f39008): 0xAAAAAAAA
debian@arm:~$
Please suggest how to proceed
I will tell you my view on this. Most likely it will not help you to improve the performance, but at least you will understand where the limitations are coming from.
The static memory interface IP block from ARM is intended to work as an interface to NOR flash memory or to SRAM. The access of this memory is done through a memory controller and through bridges which synchronize the two worlds to each other. To optimize the read access, the memory controller performs burst reads and stores the values in buffers. In case you read one byte from the ARM side, you will get it. But when reading this byte, the memory controller in fact reads more ( = the burst). And if you now read with the ARM from subsequent addresses, the memory controller can just take it from the buffer. Let's call it a very simple small cache.
For an SRAM or NOR flash these additional read cycles have no meaning, you can only profit from it. For an FPGA interface this means that you need to design it in such a way that additional reads have no effect, neither for the FPGA (auto increment for example) nor for the result you may get when you read two subsequent address locations on the FPGA..
I can't provide you with any timing behavior, burst length etc, but maybe you find some information on the ARM website when you go to these respective IP blocks.
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0215e/index.html
Writing is of course not done in unpredictable bursts, this would not work with SRAM or NOR flash.
Hope this helps a little bit to understand what's going one here.