This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Starterware/AM3358: CacheDataInvalidateBuff doesn't invalidate the entire buffer

Part Number: AM3358

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