| /* | |
| * 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 ); | |
| } | |
| } |