2 * Copyright (c) 2014, Texas Instruments Incorporated
\r
3 * All rights reserved.
\r
5 * Redistribution and use in source and binary forms, with or without
\r
6 * modification, are permitted provided that the following conditions
\r
9 * * Redistributions of source code must retain the above copyright
\r
10 * notice, this list of conditions and the following disclaimer.
\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
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
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
32 //*****************************************************************************
\r
34 // mpu.c - Driver for the mpu Module.
\r
36 //*****************************************************************************
\r
38 //*****************************************************************************
\r
40 //! \addtogroup mpu_api mpu
\r
43 //*****************************************************************************
\r
45 #include "inc/hw_regaccess.h"
\r
46 #include "inc/hw_memmap.h"
\r
48 #ifdef __MSP430_HAS_MPU__
\r
53 //*****************************************************************************
\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
59 //*****************************************************************************
\r
60 #define MPU_MAX_SEG_VALUE 0x13C1
\r
62 void MPU_initTwoSegments(uint16_t baseAddress,
\r
63 uint16_t seg1boundary,
\r
64 uint8_t seg1accmask,
\r
65 uint8_t seg2accmask)
\r
67 // Write MPU password to allow MPU register configuration
\r
68 HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | HWREG8(
\r
69 baseAddress + OFS_MPUCTL0);
\r
71 // Create two memory segmentations
\r
72 HWREG16(baseAddress + OFS_MPUSEGB1) = seg1boundary;
\r
73 HWREG16(baseAddress + OFS_MPUSEGB2) = seg1boundary;
\r
75 // Set access rights based on user's selection for segment1
\r
78 case MPU_EXEC | MPU_READ:
\r
79 HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEG1WE;
\r
80 HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG1XE + MPUSEG1RE;
\r
82 case MPU_READ | MPU_WRITE:
\r
83 HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEG1XE;
\r
84 HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG1RE + MPUSEG1WE;
\r
87 HWREG16(baseAddress + OFS_MPUSAM) &= ~(MPUSEG1XE + MPUSEG1WE);
\r
88 HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG1RE;
\r
90 case MPU_EXEC | MPU_READ | MPU_WRITE:
\r
91 HWREG16(baseAddress +
\r
92 OFS_MPUSAM) |= (MPUSEG1XE + MPUSEG1WE + MPUSEG1RE);
\r
94 case MPU_NO_READ_WRITE_EXEC:
\r
95 HWREG16(baseAddress +
\r
96 OFS_MPUSAM) &= ~(MPUSEG1XE + MPUSEG1WE + MPUSEG1RE);
\r
102 // Set access rights based on user's selection for segment2
\r
103 switch(seg2accmask)
\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
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
116 HWREG16(baseAddress + OFS_MPUSAM) &= ~(MPUSEG3XE + MPUSEG3WE +
\r
117 MPUSEG2XE + MPUSEG2WE);
\r
118 HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG3RE + MPUSEG2RE;
\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
125 case MPU_NO_READ_WRITE_EXEC:
\r
126 HWREG16(baseAddress + OFS_MPUSAM) &= ~(MPUSEG3XE + MPUSEG3WE +
\r
127 MPUSEG3RE + MPUSEG2XE +
\r
128 MPUSEG2WE + MPUSEG2RE);
\r
134 //Lock MPU to disable writing to all registers
\r
135 HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;
\r
138 void MPU_initThreeSegments(uint16_t baseAddress,
\r
139 MPU_initThreeSegmentsParam *param)
\r
141 // Write MPU password to allow MPU register configuration
\r
142 HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | HWREG8(
\r
143 baseAddress + OFS_MPUCTL0);
\r
145 // Create two memory segmentations
\r
146 HWREG16(baseAddress + OFS_MPUSEGB1) = param->seg1boundary;
\r
147 HWREG16(baseAddress + OFS_MPUSEGB2) = param->seg2boundary;
\r
149 // Set access rights based on user's selection for segment1
\r
150 switch(param->seg1accmask)
\r
152 case MPU_EXEC | MPU_READ:
\r
153 HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEG1WE;
\r
154 HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG1XE + MPUSEG1RE;
\r
156 case MPU_READ | MPU_WRITE:
\r
157 HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEG1XE;
\r
158 HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG1RE + MPUSEG1WE;
\r
161 HWREG16(baseAddress + OFS_MPUSAM) &= ~(MPUSEG1XE + MPUSEG1WE);
\r
162 HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG1RE;
\r
164 case MPU_EXEC | MPU_READ | MPU_WRITE:
\r
165 HWREG16(baseAddress +
\r
166 OFS_MPUSAM) |= (MPUSEG1XE + MPUSEG1WE + MPUSEG1RE);
\r
168 case MPU_NO_READ_WRITE_EXEC:
\r
169 HWREG16(baseAddress +
\r
170 OFS_MPUSAM) &= ~(MPUSEG1XE + MPUSEG1WE + MPUSEG1RE);
\r
176 // Set access rights based on user's selection for segment2
\r
177 switch(param->seg2accmask)
\r
179 case MPU_EXEC | MPU_READ:
\r
180 HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEG2WE;
\r
181 HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG2XE + MPUSEG2RE;
\r
183 case MPU_READ | MPU_WRITE:
\r
184 HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEG2XE;
\r
185 HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG2RE + MPUSEG2WE;
\r
188 HWREG16(baseAddress + OFS_MPUSAM) &= ~(MPUSEG2XE + MPUSEG2WE);
\r
189 HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG2RE;
\r
191 case MPU_EXEC | MPU_READ | MPU_WRITE:
\r
192 HWREG16(baseAddress +
\r
193 OFS_MPUSAM) |= (MPUSEG2XE + MPUSEG2WE + MPUSEG2RE);
\r
195 case MPU_NO_READ_WRITE_EXEC:
\r
196 HWREG16(baseAddress +
\r
197 OFS_MPUSAM) &= ~(MPUSEG2XE + MPUSEG2WE + MPUSEG2RE);
\r
203 // Set access rights based on user's selection for segment3
\r
204 switch(param->seg3accmask)
\r
206 case MPU_EXEC | MPU_READ:
\r
207 HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEG3WE;
\r
208 HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG3XE + MPUSEG3RE;
\r
210 case MPU_READ | MPU_WRITE:
\r
211 HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEG3XE;
\r
212 HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG3RE + MPUSEG3WE;
\r
215 HWREG16(baseAddress + OFS_MPUSAM) &= ~(MPUSEG3XE + MPUSEG3WE);
\r
216 HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEG3RE;
\r
218 case MPU_EXEC | MPU_READ | MPU_WRITE:
\r
219 HWREG16(baseAddress +
\r
220 OFS_MPUSAM) |= (MPUSEG3XE + MPUSEG3WE + MPUSEG3WE);
\r
222 case MPU_NO_READ_WRITE_EXEC:
\r
223 HWREG16(baseAddress +
\r
224 OFS_MPUSAM) &= ~(MPUSEG3XE + MPUSEG3WE + MPUSEG3WE);
\r
230 //Lock MPU to disable writing to all registers
\r
231 HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;
\r
234 void MPU_initInfoSegment(uint16_t baseAddress,
\r
237 // Write MPU password to allow MPU register configuration
\r
238 HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | HWREG8(
\r
239 baseAddress + OFS_MPUCTL0);
\r
241 // Set access rights based on user's selection for segment1
\r
244 case MPU_EXEC | MPU_READ:
\r
245 HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEGIWE;
\r
246 HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEGIXE + MPUSEGIRE;
\r
248 case MPU_READ | MPU_WRITE:
\r
249 HWREG16(baseAddress + OFS_MPUSAM) &= ~MPUSEGIXE;
\r
250 HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEGIRE + MPUSEGIWE;
\r
253 HWREG16(baseAddress + OFS_MPUSAM) &= ~(MPUSEGIXE + MPUSEGIWE);
\r
254 HWREG16(baseAddress + OFS_MPUSAM) |= MPUSEGIRE;
\r
256 case MPU_EXEC | MPU_READ | MPU_WRITE:
\r
257 HWREG16(baseAddress +
\r
258 OFS_MPUSAM) |= (MPUSEGIXE + MPUSEGIWE + MPUSEGIRE);
\r
260 case MPU_NO_READ_WRITE_EXEC:
\r
261 HWREG16(baseAddress +
\r
262 OFS_MPUSAM) &= ~(MPUSEGIXE + MPUSEGIWE + MPUSEGIRE);
\r
268 //Lock MPU to disable writing to all registers
\r
269 HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;
\r
272 void MPU_enableNMIevent(uint16_t baseAddress)
\r
274 HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | MPUSEGIE |
\r
275 HWREG8(baseAddress + OFS_MPUCTL0);
\r
277 //Lock MPU to disable writing to all registers
\r
278 HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;
\r
281 void MPU_start(uint16_t baseAddress)
\r
283 HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | MPUENA | HWREG8(
\r
284 baseAddress + OFS_MPUCTL0);
\r
286 //Lock MPU to disable writing to all registers
\r
287 HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;
\r
290 void MPU_enablePUCOnViolation(uint16_t baseAddress,
\r
293 HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | HWREG8(
\r
294 baseAddress + OFS_MPUCTL0);
\r
295 HWREG16(baseAddress + OFS_MPUSAM) |= segment;
\r
297 //Lock MPU to disable writing to all registers
\r
298 HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;
\r
301 void MPU_disablePUCOnViolation(uint16_t baseAddress,
\r
304 HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | HWREG8(
\r
305 baseAddress + OFS_MPUCTL0);
\r
306 HWREG16(baseAddress + OFS_MPUSAM) &= ~segment;
\r
308 //Lock MPU to disable writing to all registers
\r
309 HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;
\r
312 uint16_t MPU_getInterruptStatus(uint16_t baseAddress,
\r
313 uint16_t memAccFlag)
\r
315 return (HWREG16(baseAddress + OFS_MPUCTL1) & memAccFlag);
\r
318 uint16_t MPU_clearInterrupt(uint16_t baseAddress,
\r
319 uint16_t memAccFlag)
\r
321 HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | HWREG8(
\r
322 baseAddress + OFS_MPUCTL0);
\r
323 HWREG16(baseAddress + OFS_MPUCTL1) &= ~memAccFlag;
\r
325 //Lock MPU to disable writing to all registers
\r
326 HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;
\r
328 return (HWREG16(baseAddress + OFS_MPUCTL1) & memAccFlag);
\r
331 uint16_t MPU_clearAllInterrupts(uint16_t baseAddress)
\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
338 //Lock MPU to disable writing to all registers
\r
339 HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;
\r
341 return (HWREG16(baseAddress +
\r
342 OFS_MPUCTL1) & (MPUSEG1IFG + MPUSEG2IFG + MPUSEG3IFG));
\r
345 void MPU_lockMPU(uint16_t baseAddress)
\r
347 HWREG16(baseAddress + OFS_MPUCTL0) = MPUPW | MPULOCK |
\r
348 HWREG8(baseAddress + OFS_MPUCTL0);
\r
350 //Lock MPU to disable writing to all registers
\r
351 HWREG8(baseAddress + OFS_MPUCTL0_H) = 0x00;
\r
355 //*****************************************************************************
\r
357 //! Close the doxygen group for mpu_api
\r
360 //*****************************************************************************
\r