xref: /FreeRTOS-Plus-TCP-v4.0.0/source/portable/NetworkInterface/Zynq/uncached_memory.c (revision 2d3f4daa567ffe71aeda2e0f6d0bc02850db0627)
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