summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/uncached_memory.c
blob: 5834adaf1ea1636216451f93af9cba5e3a811066 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#warning Temoporary file and a dependent on the Zynq network interface.

/*
 * 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.
 */

#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 "FreeRTOS.h"

#include "uncached_memory.h"

#include "Demo_Logging.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.
		 */
		Xil_SetTlbAttributes( ( uint32_t )pucStartOfMemory, 0xc02 ); // 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 );
	}
}