Tool/software: Starterware
Hi,
I am working on a small project that uses the GrLib graphics library running on the AM3358 SoC. I have the framebuffer defined as follows:
typedef struct __attribute__((packed))
{
uint16_t lwidth; // display width
uint16_t lheight; // display height
uint16_t palette_data[16]; // pallete data
uint16_t raw_pixels[LINES][COLUMNS]; // pixels
uint32_t pad[7]; // 28 bytes pad
} DisplayBuffer;
DisplayBuffer pvDisplayData __attribute__ ((section (".LCDBUFF"))) __attribute__((aligned(SOC_CACHELINE_SIZE_MAX)));
The screen resolution is 1280*720, so the total buffer size is more 1280*720*2 bytes. This buffer is stored in the DDR memory of the BBB board.
At some point on my code, I want to clear the entire framebuffer to a certain pixel value. Since the buffer size is large, I have used the DMA engine to update the entire buffer. Because I have cache enabled, I have to invalidate the entire buffer before performing any graphics ops on the framebuffer. However, I have noticed that NOT all pixels are changed after calling CacheDataInvalidateBuff. See the code below:
void
GrOffScreen16BPPClearBuffer(tDisplay *pDisplay, unsigned int ulValue)
{
unsigned int i, j;
unsigned int er = 0;
/* Use DMA to rapidly clear framebuffer */
ulPixel[0] = ulValue & 0xFFFF; //The pixel value that will be copied to the entire framebuffer
DisplayBuffer *pDisplayBuffer = (DisplayBuffer *)pDisplay->pvDisplayData;
/* Clean cache to update the main memory */
#ifdef CACHE_ON
CacheDataCleanBuff(ulPixel, 64);
/* Clean framebuffer before updating it. I found out that this step is necessary, otherwise scanty random pixels won't change! Why?*/
CacheDataCleanBuff(pDisplayBuffer, sizeof(DisplayBuffer));
#endif
/* Clear framebuffer using DMA */
for(i = 0; i < pDisplayBuffer->lheight; i++){
DMASetupTransferB(33, (uint8_t *)ulPixel, (uint8_t *)&pDisplayBuffer->raw_pixels[i][0], 2, pDisplayBuffer->lwidth, 1, 0, 2);
DMATriggerTransfer(33); // This function blocks until the submitted DMA transfer completes
}
/* Invalidate cache */
#ifdef CACHE_ON
CacheDataInvalidateBuff(pDisplayBuffer, sizeof(DisplayBuffer));
#endif
/* Verify changes */
for(i = 0; i < pDisplayBuffer->lheight; i++){
for(j = 0; j < pDisplayBuffer->lwidth; j++){
if(pDisplayBuffer->raw_pixels[i][j] != ulValue){
er++; // increment counter if pixel mismatch found
}
}
}
}
I have to call CacheDataCleanBuff on the framebuffer BEFORE performing DMA transfer and calling CacheDataInvalidateBuff. The number of pixels that do not update is usually in the 100s. If I disable cache, no pixel mismatch occurs; the pixels mismatch counter always reads 0. If I need cache, I must call CacheDataCleanBuff on the framebuffer before submitting the DMA request. Why?
Regards,
Khalid