]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/ARMv8M/mpu_demo/mpu_demo.c
d3a81facaef8bc6627b8402a188b6d25ca7ddea0
[freertos] / FreeRTOS / Demo / Common / ARMv8M / mpu_demo / mpu_demo.c
1 /*\r
2  * FreeRTOS Kernel V10.2.0\r
3  * Copyright (C) 2019 Amazon.com, Inc. or its affiliates.  All Rights Reserved.\r
4  *\r
5  * Permission is hereby granted, free of charge, to any person obtaining a copy of\r
6  * this software and associated documentation files (the "Software"), to deal in\r
7  * the Software without restriction, including without limitation the rights to\r
8  * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\r
9  * the Software, and to permit persons to whom the Software is furnished to do so,\r
10  * subject to the following conditions:\r
11  *\r
12  * The above copyright notice and this permission notice shall be included in all\r
13  * copies or substantial portions of the Software.\r
14  *\r
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r
17  * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\r
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\r
19  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\r
20  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
21  *\r
22  * http://www.FreeRTOS.org\r
23  * http://aws.amazon.com/freertos\r
24  *\r
25  * 1 tab == 4 spaces!\r
26  */\r
27 \r
28 /* FreeRTOS includes. */\r
29 #include "FreeRTOS.h"\r
30 #include "task.h"\r
31 \r
32 /**\r
33  * @brief Size of the shared memory region.\r
34  */\r
35 #define SHARED_MEMORY_SIZE 32\r
36 \r
37 /**\r
38  * @brief Memory region shared between two tasks.\r
39  */\r
40 static uint8_t ucSharedMemory[ SHARED_MEMORY_SIZE ] __attribute__( ( aligned( 32 ) ) );\r
41 \r
42 /**\r
43  * @brief Memory region used to track Memory Fault intentionally caused by the\r
44  * RO Access task.\r
45  *\r
46  * RO Access task sets ucROTaskFaultTracker[ 0 ] to 1 before accessing illegal\r
47  * memory. Illegal memory access causes Memory Fault and the fault handler\r
48  * checks ucROTaskFaultTracker[ 0 ] to see if this is an expected fault. We\r
49  * recover gracefully from an expected fault by jumping to the next instruction.\r
50  *\r
51  * @note We are declaring a region of 32 bytes even though we need only one. The\r
52  * reason is that the size of an MPU region must be a multiple of 32 bytes.\r
53  */\r
54 static uint8_t ucROTaskFaultTracker[ SHARED_MEMORY_SIZE ] __attribute__( ( aligned( 32 ) ) ) = { 0 };\r
55 /*-----------------------------------------------------------*/\r
56 \r
57 /**\r
58  * @brief Implements the task which has Read Only access to the memory region\r
59  * ucSharedMemory.\r
60  *\r
61  * @param pvParameters[in] Parameters as passed during task creation.\r
62  */\r
63 static void prvROAccessTask( void * pvParameters );\r
64 \r
65 /**\r
66  * @brief Implements the task which has Read Write access to the memory region\r
67  * ucSharedMemory.\r
68  *\r
69  * @param pvParameters[in] Parameters as passed during task creation.\r
70  */\r
71 static void prvRWAccessTask( void * pvParameters );\r
72 \r
73 /*-----------------------------------------------------------*/\r
74 \r
75 static void prvROAccessTask( void * pvParameters )\r
76 {\r
77 uint8_t ucVal;\r
78 \r
79     /* Unused parameters. */\r
80     ( void ) pvParameters;\r
81 \r
82     for( ; ; )\r
83     {\r
84         /* This task has RO access to ucSharedMemory and therefore it can read\r
85          * it but cannot modify it. */\r
86         ucVal = ucSharedMemory[ 0 ];\r
87 \r
88         /* Silent compiler warnings about unused variables. */\r
89         ( void ) ucVal;\r
90 \r
91         /* Since this task has Read Only access to the ucSharedMemory region,\r
92          * writing to it results in Memory Fault. Set ucROTaskFaultTracker[ 0 ]\r
93          * to 1 to tell the Memory Fault Handler that this is an expected fault.\r
94          * The handler will recover from this fault gracefully by jumping to the\r
95          * next instruction. */\r
96         ucROTaskFaultTracker[ 0 ] = 1;\r
97 \r
98         /* Illegal access to generate Memory Fault. */\r
99         ucSharedMemory[ 0 ] = 0;\r
100 \r
101         /* Wait for a second. */\r
102         vTaskDelay( pdMS_TO_TICKS( 1000 ) );\r
103     }\r
104 }\r
105 /*-----------------------------------------------------------*/\r
106 \r
107 static void prvRWAccessTask( void * pvParameters )\r
108 {\r
109     /* Unused parameters. */\r
110     ( void ) pvParameters;\r
111 \r
112     for( ; ; )\r
113     {\r
114         /* This task has RW access to ucSharedMemory and therefore can write to\r
115          * it. */\r
116         ucSharedMemory[ 0 ] = 0;\r
117 \r
118         /* Wait for a second. */\r
119         vTaskDelay( pdMS_TO_TICKS( 1000 ) );\r
120     }\r
121 }\r
122 /*-----------------------------------------------------------*/\r
123 \r
124 void vStartMPUDemo( void )\r
125 {\r
126 static StackType_t xROAccessTaskStack[ configMINIMAL_STACK_SIZE ] __attribute__( ( aligned( 32 ) ) );\r
127 static StackType_t xRWAccessTaskStack[ configMINIMAL_STACK_SIZE ] __attribute__( ( aligned( 32 ) ) );\r
128 TaskParameters_t xROAccessTaskParameters =\r
129 {\r
130     .pvTaskCode     = prvROAccessTask,\r
131     .pcName         = "ROAccess",\r
132     .usStackDepth   = configMINIMAL_STACK_SIZE,\r
133     .pvParameters   = NULL,\r
134     .uxPriority     = tskIDLE_PRIORITY,\r
135     .puxStackBuffer = xROAccessTaskStack,\r
136     .xRegions       = {\r
137                         { ucSharedMemory,       32, tskMPU_REGION_READ_ONLY | tskMPU_REGION_EXECUTE_NEVER  },\r
138                         { ucROTaskFaultTracker, 32, tskMPU_REGION_READ_WRITE | tskMPU_REGION_EXECUTE_NEVER },\r
139                         { 0,                    0,  0                                                      },\r
140                       }\r
141 };\r
142 TaskParameters_t xRWAccessTaskParameters =\r
143 {\r
144     .pvTaskCode     = prvRWAccessTask,\r
145     .pcName         = "RWAccess",\r
146     .usStackDepth   = configMINIMAL_STACK_SIZE,\r
147     .pvParameters   = NULL,\r
148     .uxPriority     = tskIDLE_PRIORITY,\r
149     .puxStackBuffer = xRWAccessTaskStack,\r
150     .xRegions       = {\r
151                         { ucSharedMemory, 32, tskMPU_REGION_READ_WRITE | tskMPU_REGION_EXECUTE_NEVER },\r
152                         { 0,              0,  0                                                      },\r
153                         { 0,              0,  0                                                      },\r
154                       }\r
155 };\r
156 \r
157     /* Create an unprivileged task with RO access to ucSharedMemory. */\r
158     xTaskCreateRestricted( &( xROAccessTaskParameters ), NULL );\r
159 \r
160     /* Create an unprivileged task with RW access to ucSharedMemory. */\r
161     xTaskCreateRestricted( &( xRWAccessTaskParameters ), NULL );\r
162 }\r
163 /*-----------------------------------------------------------*/\r
164 \r
165 void vHandleMemoryFault( uint32_t * pulFaultStackAddress )\r
166 {\r
167 uint32_t ulPC;\r
168 \r
169     /* Is this an expected fault? */\r
170     if( ucROTaskFaultTracker[ 0 ] == 1 )\r
171     {\r
172         /* Read program counter. */\r
173         ulPC = pulFaultStackAddress[ 6 ];\r
174 \r
175         /* Increment the program counter by 2 to move to the next instruction. */\r
176         ulPC += 2;\r
177 \r
178         /* Save the new program counter on the stack. */\r
179         pulFaultStackAddress[ 6 ] = ulPC;\r
180 \r
181         /* Mark the fault as handled. */\r
182         ucROTaskFaultTracker[ 0 ] = 0;\r
183     }\r
184     else\r
185     {\r
186         /* This is an unexpected fault - loop forever. */\r
187         for( ; ; )\r
188         {\r
189         }\r
190     }\r
191 }\r
192 /*-----------------------------------------------------------*/\r