xref: /FreeRTOS-Plus-TCP-v3.1.0/source/portable/NetworkInterface/xilinx_ultrascale/uncached_memory.c (revision 37bdfe577f3b728058de714e2e747d3c78803f26)
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 "x_emacpsif.h"
63 #include "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 #if ( ipconfigULTRASCALE == 1 )
74     #if defined( __aarch64__ ) || defined( ARMA53_32 )
75         #ifndef uncMEMORY_SIZE
76             /* Reserve 2 MB of memory. */
77             #define uncMEMORY_SIZE     0x200000U
78         #endif
79         #define DDR_MEMORY_END         ( XPAR_PSU_DDR_0_S_AXI_HIGHADDR )
80         #define uncMEMORY_ATTRIBUTE    NORM_NONCACHE | INNER_SHAREABLE
81     #elif defined( ARMR5 )
82         #ifndef uncMEMORY_SIZE
83             /* Reserve 1 MB of memory. */
84             #define uncMEMORY_SIZE     0x100000U
85         #endif
86         #define uncMEMORY_SIZE         0x100000U
87         #define DDR_MEMORY_END         ( XPAR_PSU_R5_DDR_0_S_AXI_HIGHADDR )
88         #define uncMEMORY_ATTRIBUTE    STRONG_ORDERD_SHARED | PRIV_RW_USER_RW
89     #else /* if defined( __aarch64__ ) || defined( ARMA53_32 ) */
90         #error Please define the specific target Zynq Ultrascale+ architecture
91     #endif /* if defined( __aarch64__ ) || defined( ARMA53_32 ) */
92 #else /* if ( ipconfigULTRASCALE == 1 ) */
93     #ifndef uncMEMORY_SIZE
94         /* Reserve 1 MB of memory. */
95         #define uncMEMORY_SIZE     0x100000U
96     #endif
97     #define DDR_MEMORY_END         ( XPAR_PS7_DDR_0_S_AXI_HIGHADDR + 1 )
98     #define uncMEMORY_ATTRIBUTE    0x1C02
99 #endif /* ( ipconfigULTRASCALE == 1 ) */
100 
101 /* Make sure that each pointer has an alignment of 4 KB. */
102 #define uncALIGNMENT_SIZE    0x1000uL
103 
104 static void vInitialiseUncachedMemory( void );
105 
106 static uint8_t pucUncachedMemory[ uncMEMORY_SIZE ] __attribute__( ( aligned( uncMEMORY_SIZE ) ) );
107 static uint8_t * pucHeadOfMemory;
108 static uint32_t ulMemorySize;
109 static uint8_t * pucStartOfMemory = NULL;
110 
111 /* The linker file defines some pseudo variables. '_end' is one of them.
112  * It is located at the first free byte in RAM. */
113 extern u8 _end;
114 
115 /*-----------------------------------------------------------*/
116 
ucIsCachedMemory(const uint8_t * pucBuffer)117 uint8_t ucIsCachedMemory( const uint8_t * pucBuffer )
118 {
119     uint8_t ucReturn;
120 
121     if( ( pucStartOfMemory != NULL ) &&
122         ( pucBuffer >= pucStartOfMemory ) &&
123         ( pucBuffer < ( pucStartOfMemory + uncMEMORY_SIZE ) ) )
124     {
125         ucReturn = pdFALSE;
126     }
127     else
128     {
129         ucReturn = pdTRUE;
130     }
131 
132     return ucReturn;
133 }
134 /*-----------------------------------------------------------*/
135 
pucGetUncachedMemory(uint32_t ulSize)136 uint8_t * pucGetUncachedMemory( uint32_t ulSize )
137 {
138     uint8_t * pucReturn;
139     uint32_t ulSkipSize;
140 
141     if( pucStartOfMemory == NULL )
142     {
143         vInitialiseUncachedMemory();
144     }
145 
146     if( ( pucStartOfMemory == NULL ) || ( ulSize > ulMemorySize ) )
147     {
148         pucReturn = NULL;
149     }
150     else
151     {
152         pucReturn = pucHeadOfMemory;
153         /* Make sure that the next pointer return will have a good alignment. */
154         ulSkipSize = ( ulSize + uncALIGNMENT_SIZE ) & ~( uncALIGNMENT_SIZE - 1uL );
155         pucHeadOfMemory += ulSkipSize;
156         ulMemorySize -= ulSkipSize;
157     }
158 
159     return pucReturn;
160 }
161 /*-----------------------------------------------------------*/
162 
vInitialiseUncachedMemory()163 static void vInitialiseUncachedMemory()
164 {
165     /* At the end of program's space... */
166     pucStartOfMemory = pucUncachedMemory;
167 
168     if( ( ( uintptr_t ) pucStartOfMemory ) + uncMEMORY_SIZE > DDR_MEMORY_END )
169     {
170         FreeRTOS_printf( ( "vInitialiseUncachedMemory: Can not allocate uncached memory\n" ) );
171     }
172     else
173     {
174         /* Some objects want to be stored in uncached memory. Hence the 1 MB
175          * address range that starts after "_end" is made uncached by setting
176          * appropriate attributes in the translation table. */
177         Xil_SetTlbAttributes( ( uintptr_t ) pucStartOfMemory, uncMEMORY_ATTRIBUTE );
178 
179         /* For experiments in the SDIO driver, make the remaining uncached memory
180          * public */
181         pucHeadOfMemory = pucStartOfMemory;
182         ulMemorySize = uncMEMORY_SIZE;
183         memset( pucStartOfMemory, '\0', uncMEMORY_SIZE );
184     }
185 }
186