Original Attachment has been moved to: LCDConf_4.c.zip
typedef enum
{
enum_dma_fast_memcpy_width_byte=0,
enum_dma_fast_memcpy_width_halfword=1,
enum_dma_fast_memcpy_width_word=2,
enum_dma_fast_memcpy_width_numof
}enum_dma_fast_memcpy_width;
typedef struct _type_dma_fast_memcpy_params
{
uint32_t src_address;
uint32_t dst_address;
enum_dma_fast_memcpy_width width;
uint32_t num_of_elements;
type_wait_1ms_delay p_delay; // if you set this to NULL, the routine waits until the transfer ends without calling the delay routine
unsigned int ui_max_ms_to_wait;
unsigned int ui_num_elements_per_line; // if 0, the copy is continuous, else the src is continuous while the dst every ui_num_elements_per_line is increased by ui_dst_num_bytes_per_line
unsigned int ui_dst_num_bytes_per_line;// num bytes between lines in the destination buffer
}type_dma_fast_memcpy_params;
// copy from memory to memory using the DMA, which is faster because it uses the burst queue of up to 4 elements and this really speeds up the transfer by about 5 times
enum_dma_fast_memcpy_retcode v_do_dma_fast_memcpy(type_dma_fast_memcpy_params *p)
{
enum_dma_fast_memcpy_retcode retcode;
GPDMA_Channel_CFG_Type cfg;
unsigned int ui_num_of_full_linked_list_required;
unsigned int ui_spare_linked_list_size;
uint32_t src;
uint32_t dst;
uint32_t chunk_width;
uint32_t control_word;
uint32_t control_word_spare;
enum_dma_fast_memcpy_width width;
GPDMA_LLI_Type *p_ll;
uint32_t ui_num_elements_per_line;
uint32_t ui_timeout_ms;
unsigned char uc_continuous_copy;
retcode=enum_dma_fast_memcpy_retcode_OK;
switch(p->width)
{
case enum_dma_fast_memcpy_width_byte:
case enum_dma_fast_memcpy_width_halfword:
case enum_dma_fast_memcpy_width_word:
{
width=p->width;
break;
}
default:
{
return enum_dma_fast_memcpy_retcode_invalid_width;
}
}
dst=p->dst_address;
src=p->src_address;
if (p->ui_num_elements_per_line==0)
{
uc_continuous_copy=1;
ui_num_of_full_linked_list_required=p->num_of_elements/def_linked_list_chunk_size;
ui_num_elements_per_line=def_linked_list_chunk_size;
}
else
{
if (p->ui_num_elements_per_line>def_linked_list_chunk_size)
{
return enum_dma_fast_memcpy_retcode_too_long_line;
}
uc_continuous_copy=0;
ui_num_of_full_linked_list_required=p->num_of_elements/p->ui_num_elements_per_line;
ui_num_elements_per_line=p->ui_num_elements_per_line;
}
ui_spare_linked_list_size=p->num_of_elements-(ui_num_of_full_linked_list_required*ui_num_elements_per_line);
if (!ui_spare_linked_list_size)
{
if (ui_num_of_full_linked_list_required)
{
ui_num_of_full_linked_list_required--;
}
ui_spare_linked_list_size=ui_num_elements_per_line;
}
if (ui_num_of_full_linked_list_required+1>=def_max_linked_list)
{
if(uc_continuous_copy)
{
memcpy((char*)dst,(char*)src,uc_num_bytes_for_width[width]*p->num_of_elements);
}
return enum_dma_fast_memcpy_retcode_too_big_transfer_regular_memcpy_done;
}
memset(&cfg,0,sizeof(cfg));
ui_timeout_ms=p->ui_max_ms_to_wait;
control_word= 0 // by now, let the transfer size to zero
|(def_dma_burst_src(def_dma_burst_size_32))
|(def_dma_burst_dst(def_dma_burst_size_32))
|(def_dma_width_src(width))
|(def_dma_width_dst(width))
| def_dma_increment_src
| def_dma_increment_dst
;
control_word_spare=control_word;
control_word_spare|= ui_spare_linked_list_size | def_dma_generate_interrupt;
control_word |= ui_num_elements_per_line;
chunk_width=uc_num_bytes_for_width[width]*ui_num_elements_per_line;
{
unsigned int i;
for (i=0;i<ui_num_of_full_linked_list_required;i++)
{
p_ll=&linked_list;
p_ll->DstAddr=dst;
p_ll->SrcAddr=src;
src+=chunk_width;
if (uc_continuous_copy)
{
dst+=chunk_width;
}
else
{
dst+=p->ui_dst_num_bytes_per_line;
}
p_ll->NextLLI=(uint32_t)&linked_list[i+1]; // point to the next lli
p_ll->Control=control_word;
}
}
// set the final element of the list
{
p_ll=&linked_list[ui_num_of_full_linked_list_required];
p_ll->DstAddr=dst;
p_ll->SrcAddr=src;
p_ll->NextLLI=0; // 0 means this is the last element...
p_ll->Control=control_word_spare;
}
cfg.ChannelNum=enum_dma_channel_reserved_fast_memcpy;
cfg.TransferSize=ui_num_elements_per_line;
cfg.TransferWidth=width;
cfg.SrcMemAddr=p->src_address;
cfg.DstMemAddr=p->dst_address;
cfg.TransferType=GPDMA_TRANSFERTYPE_M2M_CONTROLLER_DMA;
cfg.DMALLI=(uint32_t)&linked_list[0];
// setup the transfer
if (GPDMA_Setup(&cfg)!=SUCCESS)
{
return enum_dma_fast_memcpy_retcode_unable_to_start;
}
{
uint32_t ui_expected_dma_count;
uint32_t ui_loop_before_delay;
// starting from now, we expect two more interrupts to come from the dma: the start of the transfer, and the end of the transfer
ui_expected_dma_count=ui_count_tc_dma_channel_reserved_fast_memcpy+2;
// start the transfer
GPDMA_ChannelCmd(enum_dma_channel_reserved_fast_memcpy,ENABLE);
ui_loop_before_delay=0;
// wait until the end of the transfer
while (ui_expected_dma_count!=ui_count_tc_dma_channel_reserved_fast_memcpy)
{
if (ui_loop_before_delay<30000)
{
ui_loop_before_delay++;
}
else
{
if (ui_timeout_ms)
{
if (p->p_delay)
{
p->p_delay();
}
else
{
TIM_Waitus(1000);
}
ui_timeout_ms--;
}
// timeout?
else
{
retcode=enum_dma_fast_memcpy_retcode_timeout;
break;
}
}
}
// clear the channel
GPDMA_ChannelCmd(enum_dma_channel_reserved_fast_memcpy,DISABLE);
}
return retcode;
}
void _custom_copy_framebuffer(int LayerIndex, int IndexSrc, int IndexDst)
{
unsigned long BufferSize, AddrSrc, AddrDst;
// int i;
// int BITSPERPIXEL=LCD_GetBitsPerPixelEx(i);
//
// Calculate the size of one frame buffer
//
BufferSize = (XSIZE_PHYS * YSIZE_PHYS* PIXEL_WIDTH);
//
// Calculate source- and destination address
//
Addrsrc=VRAM_ADDR_PHYS + BufferSize * IndexSrc;
AddrDst = VRAM_ADDR_PHYS + BufferSize * IndexDst;
// set the current frame buffer index
ui_framebuffer_idx=IndexDst;
{
type_dma_fast_memcpy_params dma_fast;
dma_fast.src_address=(uint32_t)(AddrSrc);
dma_fast.dst_address=(uint32_t)(AddrDst);
dma_fast.width=enum_dma_fast_memcpy_width_word;
dma_fast.num_of_elements=BufferSize/4;
dma_fast.ui_num_elements_per_line=0; // if 0, the copy is continuous, else the src is continuous while the dst every ui_num_elements_per_line is increased by ui_dst_num_bytes_per_line
dma_fast.ui_dst_num_bytes_per_line=XSIZE_PHYS*4;// num bytes between lines in the destination buffer
dma_fast.ui_max_ms_to_wait=100;
dma_fast.p_delay=v_execute_1ms_delay;
v_do_dma_fast_memcpy(&dma_fast);
}
}
|