summaryrefslogtreecommitdiff
path: root/FreeRTOS-Plus/Source/FreeRTOS-Plus-TCP/portable/NetworkInterface/Zynq/uncached_memory.c
blob: b43e50ec20f4bc5f410b39d1653cc6d0767b3982 (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
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
 * 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 );
	}
}