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 
62 #include <stddef.h>
63 #include "mpu_driver.h"
64 
65 /*******************************************************************************
66  * Variables
67  ******************************************************************************/
70 
71 /*******************************************************************************
72  * Code
73  *******************************************************************************/
74 /*FUNCTION**********************************************************************
75  *
76  * Function Name : MPU_DRV_Init
77  * Description : Sets the MPU regions according to user input, and then enables the MPU.
78  * Please note that access rights for region 0 will always be configured and
79  * regionCnt takes values between 1 and the maximum region count supported by the hardware.
80  * E.g. In S32K144 the number of supported regions is 8.
81  * The user must make sure that the clock is enabled.
82  *
83  * Implements : MPU_DRV_Init_Activity
84  *END**************************************************************************/
85 status_t MPU_DRV_Init(uint32_t instance,
86  uint8_t regionCnt,
87  const mpu_user_config_t *userConfigArr)
88 {
89  MPU_Type * base;
90  status_t retStatus = STATUS_SUCCESS;
91  uint8_t i;
92 
93  DEV_ASSERT(instance < MPU_INSTANCE_COUNT);
94  DEV_ASSERT(userConfigArr != NULL);
95  DEV_ASSERT((regionCnt > 0U) && (regionCnt <= MPU_RGD_COUNT));
96 
97  base = g_mpuBase[instance];
98 
99  /* Initializes the MPU module by its default */
100  MPU_HAL_Init(base);
101 
102  /*
103  * In region 0:
104  * Only bus master CORE, DMA can be changed access right (DEBUG is ignored).
105  * The start address, end address, process identifier and process identifier mask are ignored.
106  * Sets Master Access Right for region 0.
107  */
108  for (i = 0U; i < FEATURE_MPU_MASTER_COUNT; i++)
109  {
110  retStatus = MPU_DRV_SetMasterAccessRights(instance, 0U, &(userConfigArr[0U].masterAccRight[i]));
111  if (retStatus != STATUS_SUCCESS)
112  {
113  break;
114  }
115  }
116 
117  /*
118  * From region 1 to the next region.
119  * Initializes the regions, array index 1 is for region 1 and so on.
120  */
121  for (i = 1U; i < regionCnt; i++)
122  {
123  if (retStatus != STATUS_SUCCESS)
124  {
125  break;
126  }
127  else
128  {
129  retStatus = MPU_DRV_SetRegionConfig(instance, i, &userConfigArr[i]);
130  }
131  }
132 
133  if (STATUS_SUCCESS == retStatus)
134  {
135  /* Enables the MPU module operation */
136  MPU_HAL_Enable(base);
137  }
138 
139  return retStatus;
140 }
141 
142 /*FUNCTION**********************************************************************
143  *
144  * Function Name : MPU_DRV_Deinit
145  * Description : De-initializes the MPU region by resetting and disabling MPU module.
146  *
147  * Implements : MPU_DRV_Deinit_Activity
148  *END**************************************************************************/
149 void MPU_DRV_Deinit(uint32_t instance)
150 {
151  MPU_Type * base;
152 
153  DEV_ASSERT(instance < MPU_INSTANCE_COUNT);
154 
155  base = g_mpuBase[instance];
156 
157  /* Initialize the MPU module by its default */
158  MPU_HAL_Init(base);
159 }
160 
161 /*FUNCTION**********************************************************************
162  *
163  * Function Name : MPU_DRV_SetRegionAddr
164  * Description : Sets the region start address and end address.
165  *
166  * Implements : MPU_DRV_SetRegionAddr_Activity
167  *END**************************************************************************/
168 void MPU_DRV_SetRegionAddr(uint32_t instance,
169  uint8_t regionNum,
170  uint32_t startAddr,
171  uint32_t endAddr)
172 {
173  MPU_Type * base;
174 
175  DEV_ASSERT(instance < MPU_INSTANCE_COUNT);
176  DEV_ASSERT(regionNum < MPU_RGD_COUNT);
177  DEV_ASSERT(startAddr <= endAddr);
178 
179  base = g_mpuBase[instance];
180 
181  /* Sets a region's start and end addresses */
182  MPU_HAL_SetRegionAddr(base, regionNum, startAddr, endAddr);
183 
184  /* Re-enables the region descriptor valid bit */
185  MPU_HAL_SetRegionValidCmd(base, regionNum, true);
186 }
187 
188 /*FUNCTION**********************************************************************
189  *
190  * Function Name : MPU_DRV_SetRegionConfig
191  * Description : Sets the region configuration.
192  *
193  * Implements : MPU_DRV_SetRegionConfig_Activity
194  *END**************************************************************************/
196  uint8_t regionNum,
197  const mpu_user_config_t *userConfigPtr)
198 {
199  MPU_Type * base;
200  status_t returnCode = STATUS_SUCCESS;
203  uint8_t accRight;
204  uint8_t masterNum;
205  uint8_t i;
206 
207  DEV_ASSERT(instance < MPU_INSTANCE_COUNT);
208  DEV_ASSERT(userConfigPtr != NULL);
209  DEV_ASSERT((regionNum > 0U) && (regionNum < MPU_RGD_COUNT));
210 
211  base = g_mpuBase[instance];
212 
213  /* Configures region start and end address */
214  MPU_HAL_SetRegionAddr(base, regionNum, userConfigPtr->startAddr, userConfigPtr->endAddr);
215 
216  /* Configures region access rights */
217  for (i = 0U; i < FEATURE_MPU_MASTER_COUNT; i++)
218  {
219  accRight = (uint8_t)userConfigPtr->masterAccRight[i].accessRight;
220  masterNum = userConfigPtr->masterAccRight[i].masterNum;
221  /* Configures access rights for bus masters */
222  if (masterNum > FEATURE_MPU_MAX_LOW_MASTER_NUMBER)
223  {
224  if (masterNum > FEATURE_MPU_MAX_HIGH_MASTER_NUMBER)
225  {
226  returnCode = STATUS_ERROR;
227  break;
228  }
229  else
230  {
231  /* For masters which have only read and write permissions */
232  highAccRight.writeEnable = (((accRight & MPU_W_MASK) >> MPU_W_SHIFT) != 0U);
233  highAccRight.readEnable = (((accRight & MPU_R_MASK) >> MPU_R_SHIFT) != 0U);
234  MPU_HAL_SetHighMasterAccessRights(base, regionNum, masterNum, &highAccRight);
235  }
236  }
237  else
238  {
239  /* For masters which have separated privilege rights for user and supervisor mode accesses (e.g. master0~2 in S32K144) */
242  #if FEATURE_MPU_HAS_PROCESS_IDENTIFIER
243  lowAccRight.processIdentifierEnable = userConfigPtr->masterAccRight[i].processIdentifierEnable;
244  #endif
245  MPU_HAL_SetLowMasterAccessRights(base, regionNum, masterNum, &lowAccRight);
246  }
247  }
248 
249  if (STATUS_SUCCESS == returnCode)
250  {
251  #if FEATURE_MPU_HAS_PROCESS_IDENTIFIER
252  /* Sets Process Identifier */
253  MPU_HAL_SetProcessIdentifier(base, regionNum, userConfigPtr->processIdentifier);
254 
255  /* Sets Process Identifier mask */
256  MPU_HAL_SetProcessIdentifierMask(base, regionNum, userConfigPtr->processIdMask);
257  #endif
258 
259  /* Validate this region */
260  MPU_HAL_SetRegionValidCmd(base, regionNum, true);
261  }
262 
263  return returnCode;
264 }
265 
266 /*FUNCTION**********************************************************************
267  *
268  * Function Name : MPU_DRV_SetMasterAccessRights
269  * Description : Configures access permission.
270  *
271  * Implements : MPU_DRV_SetMasterAccessRights_Activity
272  *END**************************************************************************/
274  uint8_t regionNum,
275  const mpu_master_access_right_t *accessRightsPtr)
276 {
277  MPU_Type * base;
278  status_t returnCode = STATUS_SUCCESS;
281  uint8_t accRight;
282 
283  DEV_ASSERT(instance < MPU_INSTANCE_COUNT);
284  DEV_ASSERT(regionNum < MPU_RGD_COUNT);
285  DEV_ASSERT(accessRightsPtr != NULL);
286 
287  base = g_mpuBase[instance];
288 
289  accRight = (uint8_t)accessRightsPtr->accessRight;
290  if (accessRightsPtr->masterNum > FEATURE_MPU_MAX_LOW_MASTER_NUMBER)
291  {
292  if (accessRightsPtr->masterNum > FEATURE_MPU_MAX_HIGH_MASTER_NUMBER)
293  {
294  returnCode = STATUS_ERROR;
295  }
296  else
297  {
298  /* For masters which have only read and write permissions */
299  highAccRight.writeEnable = (((accRight & MPU_W_MASK) >> MPU_W_SHIFT) != 0U);
300  highAccRight.readEnable = (((accRight & MPU_R_MASK) >> MPU_R_SHIFT) != 0U);
301  MPU_HAL_SetAlternateHighMasterAccessRights(base, regionNum, accessRightsPtr->masterNum, &highAccRight);
302  }
303  }
304  else
305  {
306  /* For masters which have separated privilege rights for user and supervisor mode accesses (e.g. master0~2 in S32K144) */
309  #if FEATURE_MPU_HAS_PROCESS_IDENTIFIER
310  lowAccRight.processIdentifierEnable = accessRightsPtr->processIdentifierEnable;
311  #endif
312  MPU_HAL_SetAlternateLowMasterAccessRights(base, regionNum, accessRightsPtr->masterNum, &lowAccRight);
313  }
314 
315  return returnCode;
316 }
317 
318 /*FUNCTION**********************************************************************
319  *
320  * Function Name : MPU_DRV_GetDetailErrorAccessInfo
321  * Description : Gets the MPU access error detail information for a slave port.
322  *
323  * Implements : MPU_DRV_GetDetailErrorAccessInfo_Activity
324  *END**************************************************************************/
325 void MPU_DRV_GetDetailErrorAccessInfo(uint32_t instance,
326  uint8_t slavePortNum,
327  mpu_access_err_info_t *errInfoPtr)
328 {
329  MPU_Type * base;
330 
331  DEV_ASSERT(instance < MPU_INSTANCE_COUNT);
332  DEV_ASSERT(slavePortNum < FEATURE_MPU_SLAVE_COUNT);
333  DEV_ASSERT(errInfoPtr != NULL);
334 
335  base = g_mpuBase[instance];
336 
337  /* Check if there is access violation in the slave port */
338  if (MPU_HAL_GetSlavePortErrorStatus(base, slavePortNum))
339  {
340  /* Get the slave port detail error */
341  MPU_HAL_GetDetailErrorAccessInfo(base, slavePortNum, errInfoPtr);
342  }
343 }
344 
345 /*******************************************************************************
346  * EOF
347  *******************************************************************************/
MPU master access rights. Implements : mpu_master_access_right_t_Class.
Definition: mpu_driver.h:153
static void MPU_HAL_SetProcessIdentifierMask(MPU_Type *const base, uint8_t regionNum, uint8_t processIdentifierMask)
Sets the process identifier mask.
Definition: mpu_hal.h:286
void MPU_HAL_SetAlternateHighMasterAccessRights(MPU_Type *const base, uint8_t regionNum, uint8_t masterNum, const mpu_high_masters_access_rights_t *accessRightsPtr)
Sets access permission for master which has only read and write permissions in a specific region by a...
Definition: mpu_hal.c:305
const mpu_master_access_right_t * masterAccRight
Definition: mpu_driver.h:171
MPU access rights for master which have only read and write permissions Implements : mpu_high_masters...
Definition: mpu_hal.h:127
void MPU_DRV_Deinit(uint32_t instance)
De-initializes the MPU region by resetting and disabling MPU module.
Definition: mpu_driver.c:149
void MPU_HAL_SetHighMasterAccessRights(MPU_Type *const base, uint8_t regionNum, uint8_t masterNum, const mpu_high_masters_access_rights_t *accessRightsPtr)
Sets access permission for master which has only read and write permissions in a specific region...
Definition: mpu_hal.c:220
#define MPU_BASE_PTRS
Definition: S32K144.h:7571
bool MPU_HAL_GetSlavePortErrorStatus(const MPU_Type *const base, uint8_t slaveNum)
Gets the error status of a specified slave port.
Definition: mpu_hal.c:65
uint32_t startAddr
Definition: mpu_driver.h:169
void MPU_DRV_GetDetailErrorAccessInfo(uint32_t instance, uint8_t slavePortNum, mpu_access_err_info_t *errInfoPtr)
Gets the MPU access error detail information for a slave port.
Definition: mpu_driver.c:325
uint32_t endAddr
Definition: mpu_driver.h:170
#define MPU_SUPERVISOR_MASK
Definition: mpu_driver.h:48
MPU_Type *const g_mpuBase[]
Table of base addresses for MPU instances.
Definition: mpu_driver.c:69
#define FEATURE_MPU_MAX_LOW_MASTER_NUMBER
mpu_user_access_rights_t userAccessRights
Definition: mpu_hal.h:116
#define FEATURE_MPU_MASTER_COUNT
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:85
#define DEV_ASSERT(x)
Definition: devassert.h:78
#define MPU_USER_MASK
Definition: mpu_driver.h:46
static void MPU_HAL_Enable(MPU_Type *const base)
Enables the MPU module.
Definition: mpu_hal.h:146
void MPU_HAL_SetAlternateLowMasterAccessRights(MPU_Type *const base, uint8_t regionNum, uint8_t masterNum, const mpu_low_masters_access_rights_t *accessRightsPtr)
Sets access permission for master which has separated privilege rights for user and supervisor mode a...
Definition: mpu_hal.c:258
mpu_supervisor_access_rights_t
MPU access rights in supervisor mode Implements : mpu_supervisor_access_rights_t_Class.
Definition: mpu_hal.h:69
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:273
void MPU_HAL_SetLowMasterAccessRights(MPU_Type *const base, uint8_t regionNum, uint8_t masterNum, const mpu_low_masters_access_rights_t *accessRightsPtr)
Sets access permission for master which has separated privilege rights for user and supervisor mode a...
Definition: mpu_hal.c:170
status_t
Status return codes. Common error codes will be a unified enumeration (C enum) that will contain all ...
Definition: status.h:31
void MPU_HAL_Init(MPU_Type *const base)
Initializes the MPU module and all regions will be invalid after cleared access permission.
Definition: mpu_hal.c:342
static void MPU_HAL_SetRegionValidCmd(MPU_Type *const base, uint8_t regionNum, bool enable)
Sets the region valid value. When a region changed not by alternating registers should set the valid ...
Definition: mpu_hal.h:268
#define MPU_RGD_COUNT
Definition: S32K144.h:7531
mpu_supervisor_access_rights_t superAccessRights
Definition: mpu_hal.h:117
MPU user region configuration structure. This structure is used when calling the MPU_DRV_Init functio...
Definition: mpu_driver.h:167
mpu_user_access_rights_t
MPU access rights in user mode Implements : mpu_user_access_rights_t_Class.
Definition: mpu_hal.h:81
MPU detail error access info Implements : mpu_access_err_info_t_Class.
Definition: mpu_hal.h:97
mpu_access_rights_t accessRight
Definition: mpu_driver.h:156
#define MPU_W_MASK
Definition: mpu_driver.h:50
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:195
MPU access rights for masters which have separated privilege rights for user and supervisor mode acce...
Definition: mpu_hal.h:114
void MPU_HAL_SetRegionAddr(MPU_Type *const base, uint8_t regionNum, uint32_t startAddr, uint32_t endAddr)
Sets region start and end address. Please note that using this function will clear the valid bit of t...
Definition: mpu_hal.c:144
#define MPU_INSTANCE_COUNT
Definition: S32K144.h:7560
#define MPU_R_SHIFT
Definition: mpu_driver.h:53
#define MPU_SUPERVISOR_SHIFT
Definition: mpu_driver.h:49
void MPU_HAL_GetDetailErrorAccessInfo(MPU_Type *const base, uint8_t slaveNum, mpu_access_err_info_t *errInfoPtr)
Gets MPU detail error access info.
Definition: mpu_hal.c:91
#define FEATURE_MPU_MAX_HIGH_MASTER_NUMBER
#define MPU_USER_SHIFT
Definition: mpu_driver.h:47
static void MPU_HAL_SetProcessIdentifier(MPU_Type *const base, uint8_t regionNum, uint8_t processIdentifier)
Sets the process identifier.
Definition: mpu_hal.h:308
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:168
#define FEATURE_MPU_SLAVE_COUNT
#define MPU_R_MASK
Definition: mpu_driver.h:52
#define MPU_W_SHIFT
Definition: mpu_driver.h:51