/* | |
* uncached_memory.c | |
* | |
* This module will declare 1 MB of memory and switch off the caching for it. | |
* | |
* pucGetUncachedMemory( ulSize ) returns a trunc of this memory with a length | |
* rounded up to a multiple of 4 KB | |
* | |
* ucIsCachedMemory( pucBuffer ) returns non-zero if a given pointer is NOT | |
* within the range of the 1 MB non-cached memory. | |
* | |
*/ | |
/* | |
* After "_end", 1 MB of uncached memory will be allocated for DMA transfers. | |
* Both the DMA descriptors as well as all EMAC TX-buffers will be allocated in | |
* uncached memory. | |
*/ | |
/* Standard includes. */ | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
/* FreeRTOS includes. */ | |
#include "FreeRTOS.h" | |
#include "task.h" | |
#include "queue.h" | |
/* FreeRTOS+TCP includes. */ | |
#include "FreeRTOS_IP.h" | |
#include "FreeRTOS_Sockets.h" | |
#include "FreeRTOS_IP_Private.h" | |
#include "Zynq/x_emacpsif.h" | |
#include "Zynq/x_topology.h" | |
#include "xstatus.h" | |
#include "xparameters.h" | |
#include "xparameters_ps.h" | |
#include "xil_exception.h" | |
#include "xil_mmu.h" | |
#include "uncached_memory.h" | |
#define UNCACHED_MEMORY_SIZE 0x100000ul | |
#define DDR_MEMORY_END (XPAR_PS7_DDR_0_S_AXI_HIGHADDR+1) | |
static void vInitialiseUncachedMemory( void ); | |
static uint8_t *pucHeadOfMemory; | |
static uint32_t ulMemorySize; | |
static uint8_t *pucStartOfMemory = NULL; | |
uint8_t ucIsCachedMemory( const uint8_t *pucBuffer ) | |
{ | |
uint8_t ucReturn; | |
if( ( pucStartOfMemory != NULL ) && | |
( pucBuffer >= pucStartOfMemory ) && | |
( pucBuffer < ( pucStartOfMemory + UNCACHED_MEMORY_SIZE ) ) ) | |
{ | |
ucReturn = pdFALSE; | |
} | |
else | |
{ | |
ucReturn = pdTRUE; | |
} | |
return ucReturn; | |
} | |
uint8_t *pucGetUncachedMemory( uint32_t ulSize ) | |
{ | |
uint8_t *pucReturn; | |
if( pucStartOfMemory == NULL ) | |
{ | |
vInitialiseUncachedMemory( ); | |
} | |
if( ( pucStartOfMemory == NULL ) || ( ulSize > ulMemorySize ) ) | |
{ | |
pucReturn = NULL; | |
} | |
else | |
{ | |
uint32_t ulSkipSize; | |
pucReturn = pucHeadOfMemory; | |
ulSkipSize = ( ulSize + 0x1000ul ) & ~0xffful; | |
pucHeadOfMemory += ulSkipSize; | |
ulMemorySize -= ulSkipSize; | |
} | |
return pucReturn; | |
} | |
extern u8 _end; | |
static void vInitialiseUncachedMemory( ) | |
{ | |
/* At the end of program's space... */ | |
pucStartOfMemory = (uint8_t *) &_end; | |
/* | |
* Align the start address to 1 MB boundary. | |
*/ | |
pucStartOfMemory = (uint8_t *)( ( ( uint32_t )pucStartOfMemory + UNCACHED_MEMORY_SIZE ) & ( ~( UNCACHED_MEMORY_SIZE - 1 ) ) ); | |
if( ( ( u32 )pucStartOfMemory ) + UNCACHED_MEMORY_SIZE > DDR_MEMORY_END ) | |
{ | |
// vLoggingPrintf("vInitialiseUncachedMemory: Can not allocate uncached memory\n" ); | |
} | |
else | |
{ | |
/* | |
* Some objects want to be stored in uncached memory. Hence the 1 MB | |
* address range that starts after "_end" is made uncached | |
* by setting appropriate attributes in the translation table. | |
*/ | |
/* FIXME claudio rossi. Modified to prevent data abort exception (misaligned access) | |
* when application is compiled with -O1 or more optimization flag. | |
*/ | |
/* Xil_SetTlbAttributes( ( uint32_t )pucStartOfMemory, 0xc02 ); // addr, attr */ | |
Xil_SetTlbAttributes( ( uint32_t )pucStartOfMemory, 0x1c02 ); // addr, attr | |
/* For experiments in the SDIO driver, make the remaining uncached memory public */ | |
pucHeadOfMemory = pucStartOfMemory; | |
ulMemorySize = UNCACHED_MEMORY_SIZE; | |
memset( pucStartOfMemory, '\0', UNCACHED_MEMORY_SIZE ); | |
} | |
} |