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