Visible to Intel only — GUID: iga1464291562605
Ixiasoft
Visible to Intel only — GUID: iga1464291562605
Ixiasoft
4.3.3.4.1. MPU Utilities
You can find helpful MPU utility functions and macros in the mpu_utils.c and mpu_utils.h files in each software example. The following functions are the most important for you to understand:
- nios2_mpu_data_init()—A system-specific function. In your own code, write an equivalent function to specify the MPU data regions in your design.
- nios2_mpu_inst_init()—A system-specific function. In your own code, write an equivalent function to specify the MPU instruction regions in your design.
- nios2_mpu_load_region()—Configures an MPU region with specific parameters.
- nios2_mpu_enable()—Enables the entire MPU.
- nios2_mpu_disable()—Disables the entire MPU.
Each utility function makes use of the Nios2MPURegion data structure shown in the example below.
Nios2MPURegion Data Structure
typedef struct { unsigned int base; unsigned int index; unsigned int mask; unsigned int c; unsigned int perm; } Nios2MPURegion;
The example below shows nios2_mpu_inst_init() for the mpu_basic software example. The constants NIOS2_MPU_NUM_INST_REGIONS and NIOS2_MPU_REGION_USES_LIMIT are defined in system.h.
In nios2_mpu_inst_init() in the mpu_basic Software Example, region[0] grants execution access to the instr_ram memory in both user and supervisor modes, as shown in Figure 41. region[1] grants execution access to the break and trace memory (starting at 0x1000) in both modes. The other two MPU instruction regions grant no execution permissions to the entire Nios® II address space. Because their priorities, 2 and 3, are lower than the first two regions, the code stored in the instr_ram runs, and the break and trace features work correctly. However, if code attempts to execute outside those regions, the MPU triggers an exception.
The final statement in nios2_mpu_inst_init() calls nios2_mpu_load_region() to configure the region with the information contained in the structure.
nios2_mpu_inst_init() in the mpu_basic Software Example
void nios2_mpu_inst_init() { unsigned int mask; Nios2MPURegion region[NIOS2_MPU_NUM_INST_REGIONS]; //Main instruction region. region[0].index = 0; region[0].base = 0x400; // Byte Address 0x10000 #ifdef NIOS2_MPU_REGION_USES_LIMIT region[0].mask = 0x500; // Byte Address 0x14000 #else region[0].mask = 0x1ffff00; #endif region[0].c = 1; region[0].perm = MPU_INST_PERM_SUPER_EXEC_USER_EXEC; //Instruction region for break address. region[1].index = 1; region[1].base = 0x40; // Byte Address 0x1000 #ifdef NIOS2_MPU_REGION_USES_LIMIT region[1].mask = 0x60; // Byte Address 0x1800 #else region[1].mask = 0x1ffffe0; #endif region[1].c = 1; region[1].perm = MPU_INST_PERM_SUPER_EXEC_USER_EXEC; //Rest of the regions are maximally sized and permissive. #ifdef NIOS2_MPU_REGION_USES_LIMIT mask = 0x2000000; #else mask = 0x0; #endif unsigned int num_of_region = NIOS2_MPU_NUM_INST_REGIONS; unsigned int index; for (index = 2; index < num_of_region; index++){ region[index].base = 0x0; region[index].index = index; region[index].mask = mask; region[index].c = 0; region[index].perm = MPU_INST_PERM_SUPER_NONE_USER_NONE; } nios2_mpu_load_region(region, num_of_region, 0); }
The example below shows the function prototype for nios2_mpu_load_region().
nios2_mpu_load_region()
void nios2_mpu_load_region ( Nios2MPURegion region[], unsigned int num_of_region, unsigned int d);
- Nios2MPURegion—An array of data structures, each representing an MPU region
- num_of_region—The number of regions
- d—The region type (instruction or data)
nios2_mpu_load_region() configures the MPU according to the arguments passed by the calling function.
The MPU is disabled by default at system restart. After the MPU is configured, the example uses nios2_mpu_enable() and nios2_mpu_disable() to enable and disable the MPU. Whenever you reconfigure the MPU, you must first disable it, and re-enable it after configuring.
The software examples accompanying this section are commented to help you understand how each example works. Most of the complexity of managing the MPU and its regions is embodied in the MPU utility functions and macros in mpu_utils.c and mpu_utils.h, allowing you to focus on the top-level software flow.