]> git.sur5r.net Git - freertos/blob - FreeRTOS/Demo/MSP430FR5969_LaunchPad/driverlib/MSP430FR5xx_6xx/mpu.c
Complete large memory model MSP430FR5969 demo - including CLI and run-time stats.
[freertos] / FreeRTOS / Demo / MSP430FR5969_LaunchPad / driverlib / MSP430FR5xx_6xx / mpu.c
1 /* --COPYRIGHT--,BSD\r
2  * Copyright (c) 2014, Texas Instruments Incorporated\r
3  * All rights reserved.\r
4  *\r
5  * Redistribution and use in source and binary forms, with or without\r
6  * modification, are permitted provided that the following conditions\r
7  * are met:\r
8  *\r
9  * *  Redistributions of source code must retain the above copyright\r
10  *    notice, this list of conditions and the following disclaimer.\r
11  *\r
12  * *  Redistributions in binary form must reproduce the above copyright\r
13  *    notice, this list of conditions and the following disclaimer in the\r
14  *    documentation and/or other materials provided with the distribution.\r
15  *\r
16  * *  Neither the name of Texas Instruments Incorporated nor the names of\r
17  *    its contributors may be used to endorse or promote products derived\r
18  *    from this software without specific prior written permission.\r
19  *\r
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"\r
21  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,\r
22  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\r
23  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\r
24  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\r
25  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\r
26  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;\r
27  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,\r
28  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR\r
29  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,\r
30  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\r
31  * --/COPYRIGHT--*/\r
32 //*****************************************************************************\r
33 //\r
34 // mpu.c - Driver for the mpu Module.\r
35 //\r
36 //*****************************************************************************\r
37 \r
38 //*****************************************************************************\r
39 //\r
40 //! \addtogroup mpu_api mpu\r
41 //! @{\r
42 //\r
43 //*****************************************************************************\r
44 \r
45 #include "inc/hw_regaccess.h"\r
46 #include "inc/hw_memmap.h"\r
47 \r
48 #ifdef __MSP430_HAS_MPU__\r
49 #include "mpu.h"\r
50 \r
51 #include <assert.h>\r
52 \r
53 //*****************************************************************************\r
54 //\r
55 // The following value is used by createTwoSegments, createThreeSegments to\r
56 // check the user has passed a valid segmentation value. This value was\r
57 // obtained from the User's Guide.\r
58 //\r
59 //*****************************************************************************\r
60 #define MPU_MAX_SEG_VALUE                                                0x13C1\r
61 \r
62 void MPU_initTwoSegments(uint16_t baseAddress,\r
63                          uint16_t seg1boundary,\r
64                          uint8_t seg1accmask,\r
65                          uint8_t seg2accmask)\r
66 {\r
67     // Write MPU password to allow MPU register configuration\r
68     HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | HWREG8(\r
69         baseAddress + OFS_MPUCTL0);\r
70 \r
71     // Create two memory segmentations\r
72     HWREG16(baseAddress + OFS_MPUSEGB1) = seg1boundary;\r
73     HWREG16(baseAddress + OFS_MPUSEGB2) = seg1boundary;\r
74 \r
75     // Set access rights based on user's selection for segment1\r
76     switch(seg1accmask)\r
77     {\r
78     case MPU_EXEC | MPU_READ:\r
79         HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEG1WE;\r
80         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG1XE + MPUSEG1RE;\r
81         break;\r
82     case MPU_READ | MPU_WRITE:\r
83         HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEG1XE;\r
84         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG1RE + MPUSEG1WE;\r
85         break;\r
86     case MPU_READ:\r
87         HWREG16(baseAddress + OFS_MPUSAM) &= ~(MPUSEG1XE + MPUSEG1WE);\r
88         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG1RE;\r
89         break;\r
90     case MPU_EXEC | MPU_READ | MPU_WRITE:\r
91         HWREG16(baseAddress +\r
92                 OFS_MPUSAM) |= (MPUSEG1XE + MPUSEG1WE + MPUSEG1RE);\r
93         break;\r
94     case MPU_NO_READ_WRITE_EXEC:\r
95         HWREG16(baseAddress +\r
96                 OFS_MPUSAM) &= ~(MPUSEG1XE + MPUSEG1WE + MPUSEG1RE);\r
97         break;\r
98     default:\r
99         break;\r
100     }\r
101 \r
102     // Set access rights based on user's selection for segment2\r
103     switch(seg2accmask)\r
104     {\r
105     case MPU_EXEC | MPU_READ:\r
106         HWREG16(baseAddress + OFS_MPUSAM) &= ~(MPUSEG3WE + MPUSEG2WE);\r
107         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG3XE + MPUSEG3RE +\r
108                                              MPUSEG2XE + MPUSEG2RE;\r
109         break;\r
110     case MPU_READ | MPU_WRITE:\r
111         HWREG16(baseAddress + OFS_MPUSAM) &= ~(MPUSEG3XE + MPUSEG2XE);\r
112         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG3RE + MPUSEG3WE +\r
113                                              MPUSEG2RE + MPUSEG2WE;\r
114         break;\r
115     case MPU_READ:\r
116         HWREG16(baseAddress + OFS_MPUSAM) &= ~(MPUSEG3XE + MPUSEG3WE +\r
117                                                MPUSEG2XE + MPUSEG2WE);\r
118         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG3RE + MPUSEG2RE;\r
119         break;\r
120     case MPU_EXEC | MPU_READ | MPU_WRITE:\r
121         HWREG16(baseAddress + OFS_MPUSAM) |= (MPUSEG3XE + MPUSEG3WE +\r
122                                               MPUSEG3RE + MPUSEG2XE +\r
123                                               MPUSEG2WE + MPUSEG2RE);\r
124         break;\r
125     case MPU_NO_READ_WRITE_EXEC:\r
126         HWREG16(baseAddress + OFS_MPUSAM) &= ~(MPUSEG3XE + MPUSEG3WE +\r
127                                                MPUSEG3RE + MPUSEG2XE +\r
128                                                MPUSEG2WE + MPUSEG2RE);\r
129         break;\r
130     default:\r
131         break;\r
132     }\r
133 \r
134     //Lock MPU to disable writing to all registers\r
135     HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;\r
136 }\r
137 \r
138 void MPU_initThreeSegments(uint16_t baseAddress,\r
139                            MPU_initThreeSegmentsParam *param)\r
140 {\r
141     // Write MPU password to allow MPU register configuration\r
142     HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | HWREG8(\r
143         baseAddress + OFS_MPUCTL0);\r
144 \r
145     // Create two memory segmentations\r
146     HWREG16(baseAddress + OFS_MPUSEGB1) = param->seg1boundary;\r
147     HWREG16(baseAddress + OFS_MPUSEGB2) = param->seg2boundary;\r
148 \r
149     // Set access rights based on user's selection for segment1\r
150     switch(param->seg1accmask)\r
151     {\r
152     case MPU_EXEC | MPU_READ:\r
153         HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEG1WE;\r
154         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG1XE + MPUSEG1RE;\r
155         break;\r
156     case MPU_READ | MPU_WRITE:\r
157         HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEG1XE;\r
158         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG1RE + MPUSEG1WE;\r
159         break;\r
160     case MPU_READ:\r
161         HWREG16(baseAddress + OFS_MPUSAM) &= ~(MPUSEG1XE + MPUSEG1WE);\r
162         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG1RE;\r
163         break;\r
164     case MPU_EXEC | MPU_READ | MPU_WRITE:\r
165         HWREG16(baseAddress +\r
166                 OFS_MPUSAM) |= (MPUSEG1XE + MPUSEG1WE + MPUSEG1RE);\r
167         break;\r
168     case MPU_NO_READ_WRITE_EXEC:\r
169         HWREG16(baseAddress +\r
170                 OFS_MPUSAM) &= ~(MPUSEG1XE + MPUSEG1WE + MPUSEG1RE);\r
171         break;\r
172     default:\r
173         break;\r
174     }\r
175 \r
176     // Set access rights based on user's selection for segment2\r
177     switch(param->seg2accmask)\r
178     {\r
179     case MPU_EXEC | MPU_READ:\r
180         HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEG2WE;\r
181         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG2XE + MPUSEG2RE;\r
182         break;\r
183     case MPU_READ | MPU_WRITE:\r
184         HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEG2XE;\r
185         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG2RE + MPUSEG2WE;\r
186         break;\r
187     case MPU_READ:\r
188         HWREG16(baseAddress + OFS_MPUSAM) &= ~(MPUSEG2XE + MPUSEG2WE);\r
189         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG2RE;\r
190         break;\r
191     case MPU_EXEC | MPU_READ | MPU_WRITE:\r
192         HWREG16(baseAddress +\r
193                 OFS_MPUSAM) |= (MPUSEG2XE + MPUSEG2WE + MPUSEG2RE);\r
194         break;\r
195     case MPU_NO_READ_WRITE_EXEC:\r
196         HWREG16(baseAddress +\r
197                 OFS_MPUSAM) &= ~(MPUSEG2XE + MPUSEG2WE + MPUSEG2RE);\r
198         break;\r
199     default:\r
200         break;\r
201     }\r
202 \r
203     // Set access rights based on user's selection for segment3\r
204     switch(param->seg3accmask)\r
205     {\r
206     case MPU_EXEC | MPU_READ:\r
207         HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEG3WE;\r
208         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG3XE + MPUSEG3RE;\r
209         break;\r
210     case MPU_READ | MPU_WRITE:\r
211         HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEG3XE;\r
212         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG3RE + MPUSEG3WE;\r
213         break;\r
214     case MPU_READ:\r
215         HWREG16(baseAddress + OFS_MPUSAM) &= ~(MPUSEG3XE + MPUSEG3WE);\r
216         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG3RE;\r
217         break;\r
218     case MPU_EXEC | MPU_READ | MPU_WRITE:\r
219         HWREG16(baseAddress +\r
220                 OFS_MPUSAM) |= (MPUSEG3XE + MPUSEG3WE + MPUSEG3WE);\r
221         break;\r
222     case MPU_NO_READ_WRITE_EXEC:\r
223         HWREG16(baseAddress +\r
224                 OFS_MPUSAM) &= ~(MPUSEG3XE + MPUSEG3WE + MPUSEG3WE);\r
225         break;\r
226     default:\r
227         break;\r
228     }\r
229 \r
230     //Lock MPU to disable writing to all registers\r
231     HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;\r
232 }\r
233 \r
234 void MPU_initInfoSegment(uint16_t baseAddress,\r
235                          uint8_t accmask)\r
236 {\r
237     // Write MPU password to allow MPU register configuration\r
238     HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | HWREG8(\r
239         baseAddress + OFS_MPUCTL0);\r
240 \r
241     // Set access rights based on user's selection for segment1\r
242     switch(accmask)\r
243     {\r
244     case MPU_EXEC | MPU_READ:\r
245         HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEGIWE;\r
246         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEGIXE + MPUSEGIRE;\r
247         break;\r
248     case MPU_READ | MPU_WRITE:\r
249         HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEGIXE;\r
250         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEGIRE + MPUSEGIWE;\r
251         break;\r
252     case MPU_READ:\r
253         HWREG16(baseAddress + OFS_MPUSAM) &= ~(MPUSEGIXE + MPUSEGIWE);\r
254         HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEGIRE;\r
255         break;\r
256     case MPU_EXEC | MPU_READ | MPU_WRITE:\r
257         HWREG16(baseAddress +\r
258                 OFS_MPUSAM) |= (MPUSEGIXE + MPUSEGIWE + MPUSEGIRE);\r
259         break;\r
260     case MPU_NO_READ_WRITE_EXEC:\r
261         HWREG16(baseAddress +\r
262                 OFS_MPUSAM) &= ~(MPUSEGIXE + MPUSEGIWE + MPUSEGIRE);\r
263         break;\r
264     default:\r
265         break;\r
266     }\r
267 \r
268     //Lock MPU to disable writing to all registers\r
269     HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;\r
270 }\r
271 \r
272 void MPU_enableNMIevent(uint16_t baseAddress)\r
273 {\r
274     HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | MPUSEGIE |\r
275                                          HWREG8(baseAddress + OFS_MPUCTL0);\r
276 \r
277     //Lock MPU to disable writing to all registers\r
278     HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;\r
279 }\r
280 \r
281 void MPU_start(uint16_t baseAddress)\r
282 {\r
283     HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | MPUENA | HWREG8(\r
284         baseAddress + OFS_MPUCTL0);\r
285 \r
286     //Lock MPU to disable writing to all registers\r
287     HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;\r
288 }\r
289 \r
290 void MPU_enablePUCOnViolation(uint16_t baseAddress,\r
291                               uint16_t segment)\r
292 {\r
293     HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | HWREG8(\r
294         baseAddress + OFS_MPUCTL0);\r
295     HWREG16(baseAddress + OFS_MPUSAM) |= segment;\r
296 \r
297     //Lock MPU to disable writing to all registers\r
298     HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;\r
299 }\r
300 \r
301 void MPU_disablePUCOnViolation(uint16_t baseAddress,\r
302                                uint16_t segment)\r
303 {\r
304     HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | HWREG8(\r
305         baseAddress + OFS_MPUCTL0);\r
306     HWREG16(baseAddress + OFS_MPUSAM) &= ~segment;\r
307 \r
308     //Lock MPU to disable writing to all registers\r
309     HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;\r
310 }\r
311 \r
312 uint16_t MPU_getInterruptStatus(uint16_t baseAddress,\r
313                                 uint16_t memAccFlag)\r
314 {\r
315     return (HWREG16(baseAddress + OFS_MPUCTL1) & memAccFlag);\r
316 }\r
317 \r
318 uint16_t MPU_clearInterrupt(uint16_t baseAddress,\r
319                             uint16_t memAccFlag)\r
320 {\r
321     HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | HWREG8(\r
322         baseAddress + OFS_MPUCTL0);\r
323     HWREG16(baseAddress + OFS_MPUCTL1) &= ~memAccFlag;\r
324 \r
325     //Lock MPU to disable writing to all registers\r
326     HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;\r
327 \r
328     return (HWREG16(baseAddress + OFS_MPUCTL1) & memAccFlag);\r
329 }\r
330 \r
331 uint16_t MPU_clearAllInterrupts(uint16_t baseAddress)\r
332 {\r
333     HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | HWREG8(\r
334         baseAddress + OFS_MPUCTL0);\r
335     HWREG16(baseAddress +\r
336             OFS_MPUCTL1) &= ~(MPUSEG1IFG + MPUSEG2IFG + MPUSEG3IFG);\r
337 \r
338     //Lock MPU to disable writing to all registers\r
339     HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;\r
340 \r
341     return (HWREG16(baseAddress +\r
342                     OFS_MPUCTL1) & (MPUSEG1IFG + MPUSEG2IFG + MPUSEG3IFG));\r
343 }\r
344 \r
345 void MPU_lockMPU(uint16_t baseAddress)\r
346 {\r
347     HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | MPULOCK |\r
348                                          HWREG8(baseAddress + OFS_MPUCTL0);\r
349 \r
350     //Lock MPU to disable writing to all registers\r
351     HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;\r
352 }\r
353 \r
354 #endif\r
355 //*****************************************************************************\r
356 //\r
357 //! Close the doxygen group for mpu_api\r
358 //! @}\r
359 //\r
360 //*****************************************************************************\r