Use of DMA

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Use of DMA

1,190 Views
arnogir
Senior Contributor II

Hello

I'm working on a K70 with MQX 4.1.

I use the LCDC controller of the K70.

I want modify my controller driver to use the DMA to copy a new image to the image buffer used by the LCDC (given by LCDC_LSSAR)

Then currently I have the following code: (This code copy a picture from  pGet to pPut (LSSAR = Pput)

for(Row = Top; Row < (Top + Height); Row++) { #if defined(PEG_MULT_SOFT_SURFACES) pGet = (PEGCOLOR *)mpCompositeBuffer; #else #if (PEG_ORIENTATION == PEG_ORIENTATION_ROTATE_CW) pGet = (PEGCOLOR *)(pSurface->pScanPointers[mHRes-1]); #else pGet = (PEGCOLOR *)(pSurface->pScanPointers[0] - mVRes); #endif #endif pPut = (PEGCOLOR *)mpVidMemBase; pGet += (mVRes * Row + Left); pPut += (mVRes * Row + Left); for(Column = 0; Column < Width ; Column++) { pPut[Column] = pGet[Column];  } }

The picture is 480x800 pixel of two bytes (65K color) with mVRes = 800. Top, Left, Width, Height allow to indicate wich part of the picture refresh.

Then I want use the DMA because this copy take about 30ms!

I have the following code:

lcd_dma_tcd.SRC_ADDR  = (uint32_t)pGet; lcd_dma_tcd.SRC_WIDTH  = 2; lcd_dma_tcd.SRC_OFFSET  = 0;  lcd_dma_tcd.SRC_MODULO  = 0; lcd_dma_tcd.DST_ADDR  = (uint32_t)pPut; lcd_dma_tcd.DST_WIDTH  = 2; lcd_dma_tcd.DST_OFFSET  = 0;  lcd_dma_tcd.DST_MODULO  = 0; lcd_dma_tcd.LOOP_BYTES  = Width * 2; lcd_dma_tcd.LOOP_COUNT  = Height; lcd_dma_tcd.LOOP_SRC_OFFSET = (mVRes - Width) *2; lcd_dma_tcd.LOOP_DST_OFFSET = (mVRes - Width) *2; dma_channel_claim(&lcd_dma_channel_handle, 0); dma_channel_setup(lcd_dma_channel_handle, 1,0); dma_callback_reg(lcd_dma_channel_handle,(DMA_EOT_CALLBACK)(my_CallBack),&Copy); dma_request_source(lcd_dma_channel_handle, 54); dma_transfer_submit(lcd_dma_channel_handle, &lcd_dma_tcd, &lcd_dma_tcd_seq); dma_request_enable(lcd_dma_channel_handle);


But transfer not start. I don't now where is my mistake?

I try with a simpliest code to copy a simple buffer but nothing work.

thank for your help.

12 Replies

718 Views
arnogir
Senior Contributor II

Hi,

Finaly, bellow is the used code to copy my picture. In fact, I decide to copy always all the picture even if PEG ask copy only a specific zone.

Then I have the code bellow:

static DMA_TCD lcd_dma_tcd; static DMA_CHANNEL_HANDLE lcd_dma_channel_handle; static uint32_t lcd_dma_tcd_seq; static uint32_t lcd_dma_tcd_remaining; pGet = (PEGCOLOR *)(pSurface->pScanPointers[0]); pPut = (PEGCOLOR *)mpVidMemBase; lcd_dma_tcd.SRC_ADDR  = (uint32_t)pGet; lcd_dma_tcd.SRC_WIDTH  = 16; lcd_dma_tcd.SRC_OFFSET  = 16; lcd_dma_tcd.SRC_MODULO  = 0; lcd_dma_tcd.DST_ADDR  = (uint32_t)pPut; lcd_dma_tcd.DST_WIDTH  = 16; lcd_dma_tcd.DST_OFFSET  = 16; lcd_dma_tcd.DST_MODULO  = 0; lcd_dma_tcd.LOOP_BYTES  = 960; lcd_dma_tcd.LOOP_COUNT  = 800; lcd_dma_tcd.LOOP_SRC_OFFSET = 0; lcd_dma_tcd.LOOP_DST_OFFSET = 0; Row = dma_channel_claim(&lcd_dma_channel_handle, 6); /* DES get available channel handle */ Row = dma_channel_setup(lcd_dma_channel_handle, 1,0); /* DES setup to use slot #1 */ Row = dma_callback_reg(lcd_dma_channel_handle,(DMA_EOT_CALLBACK)(LcdDma_CallBack),NULL); Row = dma_request_source(lcd_dma_channel_handle, 54); /* DES DMAMUX "always enabled" */ /* ensure that the semaphore is at zero count */ while (_lwsem_poll(&lcd_dma_sem)) {} Row = dma_transfer_submit(lcd_dma_channel_handle, &lcd_dma_tcd, &lcd_dma_tcd_seq); Row = dma_request_enable(lcd_dma_channel_handle); //DES start DMA transfer   /* Wait DMA callBack post semaphore */ _lwsem_wait(&lcd_dma_sem);

This copy take about 22ms (May be can you confirm this time and justify it?)

But I have a problem.

I use spi bus and as soon as first dma transfer is done for the lcd panel, all spi write/read are blocked in _dspi_dma_transfer by a lwsem_wait(xx)...

It seem they wait DMA interrupt which never come!..

I don't know why. My SPI are configured to use channel  0,1,2,3:

#define BSP_DSPI0_DMA_RX_CHANNEL (0) #define BSP_DSPI0_DMA_TX_CHANNEL (1) #define BSP_DSPI0_DMA_RX_SOURCE (16) #define BSP_DSPI0_DMA_TX_SOURCE (17) #define BSP_DSPI1_DMA_RX_CHANNEL (2) #define BSP_DSPI1_DMA_TX_CHANNEL (3) #define BSP_DSPI1_DMA_RX_SOURCE (18) #define BSP_DSPI1_DMA_TX_SOURCE (19)

Do you have an idea to help me:smileycry:

0 Kudos

718 Views
arnogir
Senior Contributor II

Nobody to help me?:smileyplain:

0 Kudos

718 Views
DavidS
NXP Employee
NXP Employee

I am trying to get back to this.

Sorry for delay.

Regards,

David

0 Kudos

718 Views
arnogir
Senior Contributor II

Thank for your help,

I will wait your back.

:smileyhappy:

0 Kudos

718 Views
DavidS
NXP Employee
NXP Employee

Hi Arno,

In general the current implementation of the eDMA driver does have a size limitation.

I have studied the code and found a workaround that you can try.

Please note that the DMA is setup to transfer 32-bits (4 bytes) at a time. Please check to see if Endian-ness is not affecting your image. If it is then code needs additional modifications.

I’m attaching the two test files I have. Hello.c from the hello2 MQX4.1.1\mqx\examples.

And edma.c from the BSP. The change was to use the minor loop NBYTES 32-bit register to transfer the entire contiguous memory block rather than the major loop counter that is limited to 15 bits.

The hello.c has many comments to explain the test setup.

Regards,

David

718 Views
arnogir
Senior Contributor II

Hi,

Thank for your support.

I will test this.

Else have you an explication why other SPI transfert (using DMA) are stopped when I'm using DMA for IMAGE transfert?

0 Kudos

718 Views
arnogir
Senior Contributor II

Hello

I find the following text in the MQX 4.1.1 ReleaseNote

http://cache.freescale.com/files/soft_dev_tools/doc/support_info/MQX_Release_Notes.pdf?fasp=1

5 Known Issues and Limitations

...

DSPI issues related to the DMA usage

When the DSPI uses the eDMA, it may transfer data incorrectly or fail when eDMA is used for another purpose. If the DSPI

driver is the only user of eDMA, it should operate correctly. This behavior is a result of the silicon design of the DSPI. DMA

usage can be disabled in the DSPI driver by redefining the macro BSPCFG_DSPIx_USE_DMA to 0 in user_config.h.

So this explain my problem, but not indicate to me if this problem will be correct in a futur version?

0 Kudos

718 Views
DavidS
NXP Employee
NXP Employee

Hi Arno,

The eDMA example for the image transfer is setup to move the entire image in one transfer which consumes a relatively big amount of time (as compared to transferring a smaller block) which would block other eDMA transfers.

You can alter the Bandwidth Control setting for the image transfer by changing the BWC field in the DMA_TCD_CSR register.

Regards,

David

0 Kudos

718 Views
arnogir
Senior Contributor II

Hi,

I have other problem.

I use the DMA to transfer data corresponding to a picture to display on a LCD screen.

My picture has 800 x 480 pixels. Each pixel is codded on 2 bytes (65k Colors)

Then my picture take in a buffer 780000 Bytes.

My driver function must be capable to copy all the picture or only a part.

Then my pointer source pGet point on the first pixel to copy. Same for pPut which is the destination buffer.

Width is the number of pixel on a line to copy and Height is the number of (partial) line to copy.

I have the following code:

lcd_dma_tcd.SRC_ADDR  = (uint32_t)pGet;

  lcd_dma_tcd.SRC_WIDTH  = 2;

  lcd_dma_tcd.SRC_OFFSET  = 2; 

  lcd_dma_tcd.SRC_MODULO  = 0;

  lcd_dma_tcd.DST_ADDR  = (uint32_t)pPut;

  lcd_dma_tcd.DST_WIDTH  = 2;

  lcd_dma_tcd.DST_OFFSET  = 2; 

  lcd_dma_tcd.DST_MODULO  = 0;

  lcd_dma_tcd.LOOP_BYTES  = Width * 2;

  lcd_dma_tcd.LOOP_COUNT  = Height;

  lcd_dma_tcd.LOOP_SRC_OFFSET = (mHRes - Width) *2;

  lcd_dma_tcd.LOOP_DST_OFFSET = (mHRes - Width) *2;

This code work when the size of picture to refresh  is small.

But if my picture take a big part or all the picture (800x480) I have many problem:

lcd_dma_tcd.LOOP_BYTES  = Width * 2; = 800*2 = 1600. But It seems the MQX (and/or DMA hardware) limit to 1024 bytes...:smileyconfused:

To try, When width = 800 and height = 480, I have the following code:

  lcd_dma_tcd.SRC_ADDR  = (uint32_t)pGet;

  lcd_dma_tcd.SRC_WIDTH  = 2;

  lcd_dma_tcd.SRC_OFFSET  = 2; 

  lcd_dma_tcd.SRC_MODULO  = 0;

  lcd_dma_tcd.DST_ADDR  = (uint32_t)pPut;

  lcd_dma_tcd.DST_WIDTH  = 2;

  lcd_dma_tcd.DST_OFFSET  = 2; 

  lcd_dma_tcd.DST_MODULO  = 0;

  lcd_dma_tcd.LOOP_BYTES  = 800;

  lcd_dma_tcd.LOOP_COUNT  = 960;

  lcd_dma_tcd.LOOP_SRC_OFFSET = 0;

  lcd_dma_tcd.LOOP_DST_OFFSET = 0;

But the software bug, transfert is not complete, only some pixel are copied.

Then, do you have an Idea to can make a copy on a complete buffer / and on a partial buffer which represent only a specified rectangular zone on the picture?

Another point: the speed transfer.

I don't find where the DMA clock is configured. My CPU Clock is 150MHz. But when I Copy an entire buffer (780KByte) this seems take between 150 to 200ms. If clock is 150MHz, this couls take 0.78/150 = 5ms.. ??

0 Kudos

718 Views
DavidS
NXP Employee
NXP Employee

Hi Arno,

Attached is my example of getting the DMA complete callback function to be called.

I started with the mqx/examples/hello2 project and used the TWR-K70F120M (and CW10.6) for MQX4.1.1.

Hope this helps.

Regards,

David

0 Kudos

718 Views
arnogir
Senior Contributor II

Hi,

In fact, my system use SPI which is configured to use DAM channel 0 to 3, then there was a conflict on my new request on channel 0 was rejected...

I use now the channel 6 and all work correctly now!

Thank for your help.:smileyhappy:

0 Kudos

718 Views
arnogir
Senior Contributor II

Hi,

Then the only difference is the call to:

_int_install_unexpected_isr();
_int_install_exception_isr();

What is the aim of this two command?

I will try by adding its...but I like understand what  I do, then the aim of these commands.

Thank:smileyhappy:

0 Kudos