S32 SDK
mpu_driver.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016, Freescale Semiconductor, Inc.
3  * Copyright 2016-2017 NXP
4  * All rights reserved.
5  *
6  * THIS SOFTWARE IS PROVIDED BY NXP "AS IS" AND ANY EXPRESSED OR
7  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
8  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
9  * IN NO EVENT SHALL NXP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
10  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
11  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
12  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
14  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
15  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
16  * THE POSSIBILITY OF SUCH DAMAGE.
17  */
18 
40 #include <stddef.h>
41 #include "mpu_hw_access.h"
42 
43 /*******************************************************************************
44  * Variables
45  ******************************************************************************/
48 
49 /*******************************************************************************
50  * Code
51  *******************************************************************************/
52 /*FUNCTION**********************************************************************
53  *
54  * Function Name : MPU_DRV_Init
55  * Description : Sets the MPU regions according to user input, and then enables the MPU.
56  * Please note that access rights for region 0 will always be configured and
57  * regionCnt takes values between 1 and the maximum region count supported by the hardware.
58  * E.g. In S32K144 the number of supported regions is 8.
59  * The user must make sure that the clock is enabled.
60  *
61  * Implements : MPU_DRV_Init_Activity
62  *END**************************************************************************/
63 status_t MPU_DRV_Init(uint32_t instance,
64  uint8_t regionCnt,
65  const mpu_user_config_t *userConfigArr)
66 {
67  DEV_ASSERT(instance < MPU_INSTANCE_COUNT);
68  DEV_ASSERT((regionCnt > 0U) && (regionCnt <= MPU_RGD_COUNT));
69  DEV_ASSERT(userConfigArr != NULL);
70 
71  MPU_Type * base = s_mpuBase[instance];
72  status_t retStatus = STATUS_SUCCESS;
73  uint8_t regionNum = 0U;
74 
75  /* De-initializes all region descriptor */
76  MPU_DRV_Deinit(instance);
77 
78  for (regionNum = 0U; regionNum < regionCnt; regionNum++)
79  {
80  /* Sets region configuration */
81  retStatus = MPU_DRV_SetRegionConfig(instance, regionNum, &userConfigArr[regionNum]);
82 
83  if (retStatus != STATUS_SUCCESS)
84  {
85  break;
86  }
87  }
88 
89  if (retStatus == STATUS_SUCCESS)
90  {
91  /* Enables the MPU module operation */
92  MPU_Enable(base, true);
93  }
94 
95  return retStatus;
96 }
97 
98 /*FUNCTION**********************************************************************
99  *
100  * Function Name : MPU_DRV_Deinit
101  * Description : De-initializes the MPU region by resetting and disabling MPU module.
102  *
103  * Implements : MPU_DRV_Deinit_Activity
104  *END**************************************************************************/
105 void MPU_DRV_Deinit(uint32_t instance)
106 {
107  DEV_ASSERT(instance < MPU_INSTANCE_COUNT);
108 
109  MPU_Type * base = s_mpuBase[instance];
110  uint8_t regionNum = 0U;
111  uint8_t slaveNum = 0U;
112 
113  /* Disables the entire MPU module */
114  MPU_Enable(base, false);
115 
116  for (slaveNum = 0U; slaveNum < FEATURE_MPU_SLAVE_COUNT; slaveNum++)
117  {
118  /* Clears slave error flag */
119  MPU_ClearErrorFlag(base, slaveNum);
120  }
121 
122  /* De-initializes all region descriptors */
123  for (regionNum = 0U; regionNum < MPU_RGD_COUNT; regionNum++)
124  {
125  /* Resets the region configuration to default */
126  MPU_InitRegion(base, regionNum);
127  }
128 }
129 
130 /*FUNCTION**********************************************************************
131  *
132  * Function Name : MPU_DRV_SetRegionAddr
133  * Description : Sets the region start address and end address.
134  *
135  * Implements : MPU_DRV_SetRegionAddr_Activity
136  *END**************************************************************************/
137 void MPU_DRV_SetRegionAddr(uint32_t instance,
138  uint8_t regionNum,
139  uint32_t startAddr,
140  uint32_t endAddr)
141 {
142  DEV_ASSERT(instance < MPU_INSTANCE_COUNT);
143  DEV_ASSERT(regionNum < MPU_RGD_COUNT);
144  DEV_ASSERT(startAddr <= endAddr);
145 
146  MPU_Type * base = s_mpuBase[instance];
147 
148  /* Sets a region's start and end addresses */
149  MPU_SetRegionAddr(base, regionNum, startAddr, endAddr);
150 
151  /* Re-enables the region descriptor valid bit */
152  MPU_SetRegionValidCmd(base, regionNum, true);
153 }
154 
155 /*FUNCTION**********************************************************************
156  *
157  * Function Name : MPU_DRV_SetRegionConfig
158  * Description : Sets the region configuration.
159  *
160  * Implements : MPU_DRV_SetRegionConfig_Activity
161  *END**************************************************************************/
163  uint8_t regionNum,
164  const mpu_user_config_t *userConfigPtr)
165 {
166  DEV_ASSERT(instance < MPU_INSTANCE_COUNT);
167  DEV_ASSERT(regionNum < MPU_RGD_COUNT);
168  DEV_ASSERT(userConfigPtr != NULL);
169  DEV_ASSERT(userConfigPtr->startAddr <= userConfigPtr->endAddr);
170 
171  MPU_Type * base = s_mpuBase[instance];
172  uint8_t masterIdx = 0U;
173  status_t returnCode = STATUS_SUCCESS;
174 
175  /* Sets access right for masters */
176  for (masterIdx = 0U; masterIdx < FEATURE_MPU_MASTER_COUNT; masterIdx++)
177  {
178  if (userConfigPtr->masterAccRight[masterIdx].masterNum <= FEATURE_MPU_MAX_HIGH_MASTER_NUMBER)
179  {
180  MPU_SetMasterAccessRight(base,
181  regionNum,
182  &userConfigPtr->masterAccRight[masterIdx]);
183  }
184  else
185  {
186  returnCode = STATUS_ERROR;
187  break;
188  }
189  }
190 
191  /* Configures address, process identifier except region 0 */
192  if (regionNum > 0U)
193  {
194  if (returnCode == STATUS_SUCCESS)
195  {
196  /* Sets a region's start and end addresses */
197  MPU_SetRegionAddr(base, regionNum, userConfigPtr->startAddr, userConfigPtr->endAddr);
198 
199  #if FEATURE_MPU_HAS_PROCESS_IDENTIFIER
200  /* Sets process identifier */
201  MPU_SetProcessIdentifier(base, regionNum, userConfigPtr->processIdentifier);
202 
203  /* Sets process identifier mask */
204  MPU_SetProcessIdentifierMask(base, regionNum, userConfigPtr->processIdMask);
205  #endif
206 
207  /* Enables the region descriptor valid bit */
208  MPU_SetRegionValidCmd(base, regionNum, true);
209  }
210  }
211 
212  return returnCode;
213 }
214 
215 /*FUNCTION**********************************************************************
216  *
217  * Function Name : MPU_DRV_SetMasterAccessRights
218  * Description : Configures access permission.
219  *
220  * Implements : MPU_DRV_SetMasterAccessRights_Activity
221  *END**************************************************************************/
223  uint8_t regionNum,
224  const mpu_master_access_right_t *accessRightsPtr)
225 {
226  DEV_ASSERT(instance < MPU_INSTANCE_COUNT);
227  DEV_ASSERT(regionNum < MPU_RGD_COUNT);
228  DEV_ASSERT(accessRightsPtr != NULL);
229 
230  MPU_Type * base = s_mpuBase[instance];
231  status_t returnCode = STATUS_SUCCESS;
232 
233  /* Sets access rights for master */
234  if (accessRightsPtr->masterNum <= FEATURE_MPU_MAX_HIGH_MASTER_NUMBER)
235  {
236  MPU_SetMasterAccessRight(base, regionNum, accessRightsPtr);
237  }
238  else
239  {
240  returnCode = STATUS_ERROR;
241  }
242 
243  return returnCode;
244 }
245 
246 /*FUNCTION**********************************************************************
247  *
248  * Function Name : MPU_DRV_GetDetailErrorAccessInfo
249  * Description : Checks and gets the MPU access error detail information
250  * for a slave port.
251  *
252  * Implements : MPU_DRV_GetDetailErrorAccessInfo_Activity
253  *END**************************************************************************/
254 bool MPU_DRV_GetDetailErrorAccessInfo(uint32_t instance,
255  uint8_t slavePortNum,
256  mpu_access_err_info_t *errInfoPtr)
257 {
258  DEV_ASSERT(instance < MPU_INSTANCE_COUNT);
259  DEV_ASSERT(slavePortNum < FEATURE_MPU_SLAVE_COUNT);
260  DEV_ASSERT(errInfoPtr != NULL);
261 
262  MPU_Type * base = s_mpuBase[instance];
263  /* Gets slaver port error status */
264  bool errorStatus = MPU_GetErrorStatus(base, slavePortNum);
265 
266  /* Check if there is access violation in the slave port */
267  if (errorStatus)
268  {
269  /* Get the slave port detail error */
270  MPU_GetErrorInfo(base, slavePortNum, errInfoPtr);
271 
272  /* Clears slave port error flag */
273  MPU_ClearErrorFlag(base, slavePortNum);
274  }
275 
276  return errorStatus;
277 }
278 
279 /*FUNCTION**********************************************************************
280  *
281  * Function Name : MPU_DRV_GetDefaultRegionConfig
282  * Description : Gets default region configuration.
283  *
284  * Implements : MPU_DRV_GetDefaultRegionConfig_Activity
285  *END**************************************************************************/
287 {
288  DEV_ASSERT(masterAccRight != NULL);
289 
290  uint8_t masterIdx = 0U;
291  uint8_t masterNum[FEATURE_MPU_MASTER_COUNT] = FEATURE_MPU_MASTER;
292  mpu_user_config_t regionConfig;
293 
294  /* Allocates entire memory */
295  regionConfig.startAddr = 0x0U;
296  regionConfig.endAddr = 0xFFFFFFFFU;
297 
298  /* All access rights of masters are allowed */
299  for (masterIdx = 0U; masterIdx < FEATURE_MPU_MASTER_COUNT; masterIdx++)
300  {
301  MPU_GetDefaultMasterAccRight(masterNum[masterIdx], &masterAccRight[masterIdx]);
302  }
303  regionConfig.masterAccRight = masterAccRight;
304 
305 #if FEATURE_MPU_HAS_PROCESS_IDENTIFIER
306  /* Disables process identifier */
307  regionConfig.processIdentifier = 0U;
308  regionConfig.processIdMask = 0U;
309 #endif
310 
311  return regionConfig;
312 }
313 
314 /*FUNCTION**********************************************************************
315  *
316  * Function Name : MPU_DRV_EnableRegion
317  * Description : Enables/Disables region descriptor.
318  * Please note that region 0 should not be disabled.
319  *
320  * Implements : MPU_DRV_EnableRegion_Activity
321  *END**************************************************************************/
322 void MPU_DRV_EnableRegion(uint32_t instance,
323  uint8_t regionNum,
324  bool enable)
325 {
326  DEV_ASSERT(instance < MPU_INSTANCE_COUNT);
327  DEV_ASSERT(regionNum < MPU_RGD_COUNT);
328  DEV_ASSERT(regionNum > 0U);
329 
330  MPU_Type * base = s_mpuBase[instance];
331 
332  /* Enables/Disables region descriptor */
333  MPU_SetRegionValidCmd(base, regionNum, enable);
334 }
335 
336 /*******************************************************************************
337  * EOF
338  *******************************************************************************/
MPU master access rights. Implements : mpu_master_access_right_t_Class.
Definition: mpu_driver.h:176
const mpu_master_access_right_t * masterAccRight
Definition: mpu_driver.h:194
void MPU_DRV_Deinit(uint32_t instance)
De-initializes the MPU region by resetting and disabling MPU module.
Definition: mpu_driver.c:105
#define MPU_BASE_PTRS
Definition: S32K142.h:7499
#define FEATURE_MPU_SLAVE_COUNT
uint32_t startAddr
Definition: mpu_driver.h:192
mpu_user_config_t MPU_DRV_GetDefaultRegionConfig(mpu_master_access_right_t *masterAccRight)
Gets default region configuration.
Definition: mpu_driver.c:286
uint32_t endAddr
Definition: mpu_driver.h:193
static MPU_Type *const s_mpuBase[MPU_INSTANCE_COUNT]
Table of base addresses for MPU instances.
Definition: mpu_driver.c:47
bool MPU_DRV_GetDetailErrorAccessInfo(uint32_t instance, uint8_t slavePortNum, mpu_access_err_info_t *errInfoPtr)
Checks and gets the MPU access error detail information for a slave port.
Definition: mpu_driver.c:254
#define FEATURE_MPU_MASTER
status_t MPU_DRV_Init(uint32_t instance, uint8_t regionCnt, const mpu_user_config_t *userConfigArr)
The function sets the MPU regions according to user input and then enables the MPU. Please note that access rights for region 0 will always be configured and regionCnt takes values between 1 and the maximum region count supported by the hardware. e.g. In S32K144 the number of supported regions is 8. The user must make sure that the clock is enabled.
Definition: mpu_driver.c:63
#define DEV_ASSERT(x)
Definition: devassert.h:77
status_t MPU_DRV_SetMasterAccessRights(uint32_t instance, uint8_t regionNum, const mpu_master_access_right_t *accessRightsPtr)
Configures access permission.
Definition: mpu_driver.c:222
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:44
#define FEATURE_MPU_MASTER_COUNT
#define MPU_RGD_COUNT
Definition: S32K142.h:7459
MPU user region configuration structure. This structure is used when calling the MPU_DRV_Init functio...
Definition: mpu_driver.h:190
#define FEATURE_MPU_MAX_HIGH_MASTER_NUMBER
MPU detail error access info Implements : mpu_access_err_info_t_Class.
Definition: mpu_driver.h:66
status_t MPU_DRV_SetRegionConfig(uint32_t instance, uint8_t regionNum, const mpu_user_config_t *userConfigPtr)
Sets the region configuration.
Definition: mpu_driver.c:162
#define MPU_INSTANCE_COUNT
Definition: S32K142.h:7488
void MPU_DRV_EnableRegion(uint32_t instance, uint8_t regionNum, bool enable)
Enables/Disables region descriptor. Please note that region 0 should not be disabled.
Definition: mpu_driver.c:322
void MPU_DRV_SetRegionAddr(uint32_t instance, uint8_t regionNum, uint32_t startAddr, uint32_t endAddr)
Sets the region start and end address.
Definition: mpu_driver.c:137