]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/Common/ARMv8M/mpu_demo/mpu_demo.c
6dea6db9dd917e14ac62d0a20cb55e467a08d1b9
[freertos] / FreeRTOS / Demo / Common / ARMv8M / mpu_demo / mpu_demo.c
1 /*\r
2  * FreeRTOS Kernel V10.2.1\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 portDONT_DISCARD void vHandleMemoryFault( uint32_t * pulFaultStackAddress )\r
166 {\r
167 uint32_t ulPC;\r
168 uint16_t usOffendingInstruction;\r
169 \r
170         /* Is this an expected fault? */\r
171         if( ucROTaskFaultTracker[ 0 ] == 1 )\r
172         {\r
173                 /* Read program counter. */\r
174                 ulPC = pulFaultStackAddress[ 6 ];\r
175 \r
176                 /* Read the offending instruction. */\r
177                 usOffendingInstruction = *( uint16_t * )ulPC;\r
178 \r
179                 /* From ARM docs:\r
180                  * If the value of bits[15:11] of the halfword being decoded is one of\r
181                  * the following, the halfword is the first halfword of a 32-bit\r
182                  * instruction:\r
183                  * - 0b11101.\r
184                  * - 0b11110.\r
185                  * - 0b11111.\r
186                  * Otherwise, the halfword is a 16-bit instruction.\r
187                  */\r
188 \r
189                 /* Extract bits[15:11] of the offending instruction. */\r
190                 usOffendingInstruction = usOffendingInstruction & 0xF800;\r
191                 usOffendingInstruction = ( usOffendingInstruction >> 11 );\r
192 \r
193                 /* Determine if the offending instruction is a 32-bit instruction or\r
194                  * a 16-bit instruction. */\r
195                 if( usOffendingInstruction == 0x001F ||\r
196                         usOffendingInstruction == 0x001E ||\r
197                         usOffendingInstruction == 0x001D )\r
198                 {\r
199                         /* Since the offending instruction is a 32-bit instruction,\r
200                          * increment the program counter by 4 to move to the next\r
201                          * instruction. */\r
202                         ulPC += 4;\r
203                 }\r
204                 else\r
205                 {\r
206                         /* Since the offending instruction is a 16-bit instruction,\r
207                          * increment the program counter by 2 to move to the next\r
208                          * instruction. */\r
209                         ulPC += 2;\r
210                 }\r
211 \r
212                 /* Save the new program counter on the stack. */\r
213                 pulFaultStackAddress[ 6 ] = ulPC;\r
214 \r
215                 /* Mark the fault as handled. */\r
216                 ucROTaskFaultTracker[ 0 ] = 0;\r
217         }\r
218         else\r
219         {\r
220                 /* This is an unexpected fault - loop forever. */\r
221                 for( ; ; )\r
222                 {\r
223                 }\r
224         }\r
225 }\r
226 /*-----------------------------------------------------------*/\r