1 /*
2 * FreeRTOS+FAT V2.3.3
3 * Copyright (C) 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * https://www.FreeRTOS.org
23 * https://github.com/FreeRTOS
24 *
25 */
26
27 /*
28 * uncached_memory.c
29 *
30 * This module will declare 1 MB of memory and switch off the caching for it.
31 *
32 * pucGetUncachedMemory( ulSize ) returns a trunc of this memory with a length
33 * rounded up to a multiple of 4 KB.
34 *
35 * ucIsCachedMemory( pucBuffer ) returns non-zero if a given pointer is NOT
36 * within the range of the 1 MB non-cached memory.
37 *
38 */
39
40 /*
41 * After "_end", 1 MB of uncached memory will be allocated for DMA transfers.
42 * Both the DMA descriptors as well as all EMAC TX-buffers will be allocated in
43 * uncached memory.
44 */
45
46 /* Standard includes. */
47 #include <stdint.h>
48 #include <stdio.h>
49 #include <stdlib.h>
50
51 /* FreeRTOS includes. */
52 #include "FreeRTOS.h"
53 #include "task.h"
54 #include "queue.h"
55
56 /* FreeRTOS+TCP includes. */
57 #include "FreeRTOS_IP.h"
58 #include "FreeRTOS_Sockets.h"
59 #include "FreeRTOS_IP_Private.h"
60
61 #include "Zynq/x_topology.h"
62 #include "xstatus.h"
63
64 #include "xparameters.h"
65 #include "xparameters_ps.h"
66 #include "xil_exception.h"
67 #include "xil_mmu.h"
68
69 #include "uncached_memory.h"
70
71 #if ( ipconfigULTRASCALE == 1 )
72 /* Reserve 2 MB of memory. */
73 #define uncMINIMAL_MEMORY_SIZE 0x200000U
74 #ifndef uncMEMORY_SIZE
75 #define uncMEMORY_SIZE uncMINIMAL_MEMORY_SIZE
76 #endif
77 #define DDR_MEMORY_END ( XPAR_PSU_DDR_0_S_AXI_HIGHADDR )
78 #define uncMEMORY_ATTRIBUTE NORM_NONCACHE | INNER_SHAREABLE
79 #else
80 /* Reserve 1 MB of memory. */
81 #define uncMINIMAL_MEMORY_SIZE 0x100000U
82 #ifndef uncMEMORY_SIZE
83 #define uncMEMORY_SIZE uncMINIMAL_MEMORY_SIZE
84 #endif
85 #define DDR_MEMORY_END ( XPAR_PS7_DDR_0_S_AXI_HIGHADDR + 1 )
86 #define uncMEMORY_ATTRIBUTE 0x1C02
87 #endif /* ( ipconfigULTRASCALE == 1 ) */
88
89 /* Make sure that each pointer has an alignment of 4 KB. */
90 #define uncALIGNMENT_SIZE 0x1000uL
91
92 static void vInitialiseUncachedMemory( void );
93
94 static uint8_t pucUncachedMemory[ uncMEMORY_SIZE ] __attribute__( ( aligned( uncMEMORY_SIZE ) ) );
95 static uint8_t * pucHeadOfMemory;
96 static uint32_t ulMemorySize;
97 static uint8_t * pucStartOfMemory = NULL;
98
99 /* The linker file defines some pseudo variables. '_end' is one of them.
100 * It is located at the first free byte in RAM. */
101 extern u8 _end;
102
103 /*-----------------------------------------------------------*/
104
ucIsCachedMemory(const uint8_t * pucBuffer)105 uint8_t ucIsCachedMemory( const uint8_t * pucBuffer )
106 {
107 uint8_t ucReturn;
108
109 if( ( pucStartOfMemory != NULL ) &&
110 ( pucBuffer >= pucStartOfMemory ) &&
111 ( pucBuffer < ( pucStartOfMemory + uncMEMORY_SIZE ) ) )
112 {
113 ucReturn = pdFALSE;
114 }
115 else
116 {
117 ucReturn = pdTRUE;
118 }
119
120 return ucReturn;
121 }
122 /*-----------------------------------------------------------*/
123
pucGetUncachedMemory(uint32_t ulSize)124 uint8_t * pucGetUncachedMemory( uint32_t ulSize )
125 {
126 uint8_t * pucReturn;
127 uint32_t ulSkipSize;
128
129 if( pucStartOfMemory == NULL )
130 {
131 vInitialiseUncachedMemory();
132 }
133
134 if( ( pucStartOfMemory == NULL ) || ( ulSize > ulMemorySize ) )
135 {
136 pucReturn = NULL;
137 }
138 else
139 {
140 pucReturn = pucHeadOfMemory;
141 /* Make sure that the next pointer return will have a good alignment. */
142 ulSkipSize = ( ulSize + uncALIGNMENT_SIZE ) & ~( uncALIGNMENT_SIZE - 1uL );
143 pucHeadOfMemory += ulSkipSize;
144 ulMemorySize -= ulSkipSize;
145 }
146
147 return pucReturn;
148 }
149 /*-----------------------------------------------------------*/
150
vInitialiseUncachedMemory()151 static void vInitialiseUncachedMemory()
152 {
153 /* At the end of program's space... */
154 pucStartOfMemory = pucUncachedMemory;
155
156 if( ( ( uintptr_t ) pucStartOfMemory ) + uncMEMORY_SIZE > DDR_MEMORY_END )
157 {
158 FreeRTOS_printf( ( "vInitialiseUncachedMemory: Can not allocate uncached memory\n" ) );
159 }
160 else
161 {
162 /* Some objects want to be stored in uncached memory. Hence the 1 MB
163 * address range that starts after "_end" is made uncached by setting
164 * appropriate attributes in the translation table. */
165 uint32_t ulBytesLeft = uncMEMORY_SIZE;
166 uint8_t * puc = pucStartOfMemory;
167
168 while( ulBytesLeft > 0U )
169 {
170 uint32_t ulCurrentSize = ( ulBytesLeft > uncMINIMAL_MEMORY_SIZE ) ? uncMINIMAL_MEMORY_SIZE : ulBytesLeft;
171 Xil_SetTlbAttributes( ( uintptr_t ) puc, uncMEMORY_ATTRIBUTE );
172 ulBytesLeft -= ulCurrentSize;
173 puc += ulCurrentSize;
174 }
175
176 /* For experiments in the SDIO driver, make the remaining uncached memory
177 * public */
178 pucHeadOfMemory = pucStartOfMemory;
179 ulMemorySize = uncMEMORY_SIZE;
180 memset( pucStartOfMemory, '\0', uncMEMORY_SIZE );
181 }
182 }
183