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