//***************************************************************************** // // This example demonstrates how to configure MPU regions for different levels // of memory protection. The following memory map is set up: // // 0000.0000 - 0000.1C00 - rgn 0: executable read-only, flash // 0000.1C00 - 0000.2000 - rgn 0: no access, flash (disabled sub-region 7) // 0100.0000 - 0100.8000 - rgn 1: executable read-only, ROM // 2000.0000 - 2000.8000 - rgn 2: read-write, RAM // 2000.8000 - 2000.A000 - rgn 3: read-only, RAM (disabled sub-rgn 4 of rgn 1) // 2000.A000 - 2000.FFFF - rgn 2: read-write, RAM // 4000.0000 - 4001.0000 - rgn 4: read-write, peripherals // 4001.0000 - 4002.0000 - rgn 4: no access (disabled sub-region 1) // 4002.0000 - 4006.0000 - rgn 4: read-write, peripherals // 4006.0000 - 4008.0000 - rgn 4: no access (disabled sub-region 6, 7) // E000.E000 - E000.F000 - rgn 5: read-write, NVIC // // The example code will attempt to perform the following operations and check // the faulting behavior: // // - write to flash (should fault) // - read from the disabled area of flash (should fault) // - read from the read-only area of RAM (should not fault) // - write to the read-only section of RAM (should fault) // //***************************************************************************** int main(void) { unsigned int bFail = 0; // // Set the clocking to run directly from the crystal. // ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // // Initialize the UART and write status. // ROM_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA); GPIOPinConfigure(GPIO_PA0_U0RX); GPIOPinConfigure(GPIO_PA1_U0TX); ROM_GPIOPinTypeUART(GPIO_PORTA_BASE, GPIO_PIN_0 | GPIO_PIN_1); UARTStdioInit(0); UARTprintf("\033[2JMPU example\n"); // // Configure an executable, read-only MPU region for flash. It is an 8 KB // region with the last 1 KB disabled to result in a 7 KB executable // region. This region is needed so that the program can execute from // flash. // ROM_MPURegionSet(0, FLASH_BASE, MPU_RGN_SIZE_8K | MPU_RGN_PERM_EXEC | MPU_RGN_PERM_PRV_RO_USR_RO | MPU_SUB_RGN_DISABLE_7 | MPU_RGN_ENABLE); // // Configure an executable, read-only MPU region for ROM. This region is // needed so that the program can execute DriverLib from ROM. // ROM_MPURegionSet(1, 0x01000000, MPU_RGN_SIZE_32K | MPU_RGN_PERM_EXEC | MPU_RGN_PERM_PRV_RO_USR_RO | MPU_RGN_ENABLE); // // Configure a read-write MPU region for RAM. It is a 64+32 KB region. // There is a 8 KB sub-region in the middle that is disabled in order to // open up a hole in which different permissions can be applied. // ROM_MPURegionSet(2, SRAM_BASE, MPU_RGN_SIZE_64K | MPU_RGN_PERM_NOEXEC | MPU_RGN_PERM_PRV_RW_USR_RW | MPU_SUB_RGN_DISABLE_4 | MPU_RGN_ENABLE); ROM_MPURegionSet(3, SRAM_BASE + 65536, MPU_RGN_SIZE_32K | MPU_RGN_PERM_NOEXEC | MPU_RGN_PERM_PRV_RW_USR_RW | MPU_SUB_RGN_DISABLE_4 | MPU_RGN_ENABLE); // // Configure a read-only MPU region for the 8 KB of RAM that is disabled in // the previous region. This region is used for demonstrating read-only // permissions. // ROM_MPURegionSet(4, SRAM_BASE + 0x8000, MPU_RGN_SIZE_2K | MPU_RGN_PERM_NOEXEC | MPU_RGN_PERM_PRV_RO_USR_RO | MPU_RGN_ENABLE); // // Configure a read-write MPU region for peripherals. The region is 512 KB // total size, with several sub-regions disabled to prevent access to areas // where there are no peripherals. This region is needed because the // program needs access to some peripherals. // ROM_MPURegionSet(5, 0x40000000, MPU_RGN_SIZE_512K | MPU_RGN_PERM_NOEXEC | MPU_RGN_PERM_PRV_RW_USR_RW | MPU_SUB_RGN_DISABLE_1 | MPU_SUB_RGN_DISABLE_6 | MPU_SUB_RGN_DISABLE_7 | MPU_RGN_ENABLE); // // Configure a read-write MPU region for access to the NVIC. The region is // 4 KB in size. This region is needed because NVIC registers are needed // in order to control the MPU. // ROM_MPURegionSet(6, NVIC_BASE, MPU_RGN_SIZE_4K | MPU_RGN_PERM_NOEXEC | MPU_RGN_PERM_PRV_RW_USR_RW | MPU_RGN_ENABLE); // // Need to clear the NVIC fault status register to make sure there is no // status hanging around from a previous program. // g_ulFaultStatus = HWREG(NVIC_FAULT_STAT); HWREG(NVIC_FAULT_STAT) = g_ulFaultStatus; // // Enable the MPU fault. // ROM_IntEnable(FAULT_MPU); // // Enable the MPU. This will begin to enforce the memory protection // regions. The MPU is configured so that when in the hard fault or NMI // exceptions, a default map will be used. Neither of these should occur // in this example program. // ROM_MPUEnable(MPU_CONFIG_HARDFLT_NMI); // // Attempt to write to the flash. This should cause a protection fault due // to the fact that this region is read-only. // UARTprintf("Check flash write..."); g_ulMPUFaultCount = 0; HWREG(0x100) = 0x12345678; // // Verify that the fault occurred, at the expected address. // if((g_ulMPUFaultCount == 1) && (g_ulFaultStatus == 0x82) && (g_ulMMAR == 0x100)) { UARTprintf("OK\n"); } else { bFail = 1; UARTprintf("Fail\n"); } // // The MPU was disabled when the previous fault occurred, so it needs to be // re-enabled. // ROM_MPUEnable(MPU_CONFIG_HARDFLT_NMI); // // Attempt to read from the disabled section of flash, the upper 1 KB of // the 8 KB region. // UARTprintf("Check flash read..."); g_ulMPUFaultCount = 0; g_ulValue = HWREG(0x1C10); // // Verify that the fault occurred, at the expected address. // if((g_ulMPUFaultCount == 1) && (g_ulFaultStatus == 0x82) && (g_ulMMAR == 0x1C10)) { UARTprintf("OK\n"); } else { bFail = 1; UARTprintf("Fail\n"); } // // The MPU was disabled when the previous fault occurred, so it needs to be // re-enabled. // ROM_MPUEnable(MPU_CONFIG_HARDFLT_NMI); // // Attempt to read from the read-only area of RAM, the middle 8 KB of the // 64 KB region. // UARTprintf("Check RAM read..."); g_ulMPUFaultCount = 0; g_ulValue = HWREG(0x20008440); // // Verify that the RAM read did not cause a fault. // if(g_ulMPUFaultCount == 0) { UARTprintf("OK\n"); } else { bFail = 1; UARTprintf("Fail\n"); } // // The MPU should not have been disabled since the last access was not // supposed to cause a fault. But if it did cause a fault, then the MPU // will be disabled, so re-enable it here anyway, just in case. // ROM_MPUEnable(MPU_CONFIG_HARDFLT_NMI); // // Attempt to write to the read-only area of RAM, the middle 8 KB of the // 64 KB region. // UARTprintf("Check RAM write..."); g_ulMPUFaultCount = 0; HWREG(0x20008460) = 0xabcdef00; // // Verify that the RAM write caused a fault. // if((g_ulMPUFaultCount == 1) && (g_ulFaultStatus == 0x82) && (g_ulMMAR == 0x20008460)) { UARTprintf("OK\n"); } else { bFail = 1; UARTprintf("Fail\n"); } // // Display the results of the example program. // if(bFail) { UARTprintf("Failure!\n"); } else { UARTprintf("Success!\n"); } // // Disable the MPU, so there are no lingering side effects if another // program is run. // ROM_MPUDisable(); // // Finished. // while(1) { } }
//***************************************************************************** // // This example demonstrates how to configure MPU regions for different levels // of memory protection. The following memory map is set up: // // 0000.0000 - 0000.1C00 - rgn 0: executable read-only, flash // 0000.1C00 - 0000.2000 - rgn 0: no access, flash (disabled sub-region 7) // 2000.0000 - 2000.4000 - rgn 1: read-write, RAM // 2000.4000 - 2000.6000 - rgn 2: read-only, RAM (disabled sub-rgn 4 of rgn 1) // 2000.6000 - 2000.7FFF - rgn 1: read-write, RAM // 4000.0000 - 4001.0000 - rgn 3: read-write, peripherals // 4001.0000 - 4002.0000 - rgn 3: no access (disabled sub-region 1) // 4002.0000 - 4006.0000 - rgn 3: read-write, peripherals // 4006.0000 - 4008.0000 - rgn 3: no access (disabled sub-region 6, 7) // E000.E000 - E000.F000 - rgn 4: read-write, NVIC // 0100.0000 - 0100.FFFF - rgn 5: executable read-only, ROM // // The example code will attempt to perform the following operations and check // the faulting behavior: // // - write to flash (should fault) // - read from the disabled area of flash (should fault) // - read from the read-only area of RAM (should not fault) // - write to the read-only section of RAM (should fault) // //***************************************************************************** int main(void) { unsigned int bFail = 0; // Enable lazy stacking for interrupt handlers. This allows floating-point // instructions to be used within interrupt handlers, but at the expense of // extra stack usage. ROM_FPULazyStackingEnable(); // Set the clocking to run directly from the crystal. ROM_SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN | SYSCTL_XTAL_16MHZ); // Initialize the UART and write status. ConfigureUART(); UARTprintf("\033[2JMPU example\n"); // Configure an executable, read-only MPU region for flash. It is a 16 KB // region with the last 2 KB disabled to result in a 14 KB executable // region. This region is needed so that the program can execute from // flash. ROM_MPURegionSet(0, FLASH_BASE, MPU_RGN_SIZE_16K | MPU_RGN_PERM_EXEC | MPU_RGN_PERM_PRV_RO_USR_RO | MPU_SUB_RGN_DISABLE_7 | MPU_RGN_ENABLE); // Configure a read-write MPU region for RAM. It is a 32 KB region. There // is a 4 KB sub-region in the middle that is disabled in order to open up // a hole in which different permissions can be applied. ROM_MPURegionSet(1, SRAM_BASE, MPU_RGN_SIZE_32K | MPU_RGN_PERM_NOEXEC | MPU_RGN_PERM_PRV_RW_USR_RW | MPU_SUB_RGN_DISABLE_4 | MPU_RGN_ENABLE); // Configure a read-only MPU region for the 4 KB of RAM that is disabled in // the previous region. This region is used for demonstrating read-only // permissions. ROM_MPURegionSet(2, SRAM_BASE + 0x4000, MPU_RGN_SIZE_2K | MPU_RGN_PERM_NOEXEC | MPU_RGN_PERM_PRV_RO_USR_RO | MPU_RGN_ENABLE); // Configure a read-write MPU region for peripherals. The region is 512 KB // total size, with several sub-regions disabled to prevent access to areas // where there are no peripherals. This region is needed because the // program needs access to some peripherals. ROM_MPURegionSet(3, 0x40000000, MPU_RGN_SIZE_512K | MPU_RGN_PERM_NOEXEC | MPU_RGN_PERM_PRV_RW_USR_RW | MPU_SUB_RGN_DISABLE_1 | MPU_SUB_RGN_DISABLE_6 | MPU_SUB_RGN_DISABLE_7 | MPU_RGN_ENABLE); // Configure a read-write MPU region for access to the NVIC. The region is // 4 KB in size. This region is needed because NVIC registers are needed // in order to control the MPU. ROM_MPURegionSet(4, NVIC_BASE, MPU_RGN_SIZE_4K | MPU_RGN_PERM_NOEXEC | MPU_RGN_PERM_PRV_RW_USR_RW | MPU_RGN_ENABLE); // Configure an executable, read-only MPU region for ROM. It is a 64 KB // region. This region is needed so that ROM library calls work. ROM_MPURegionSet(5, (uint32_t)ROM_APITABLE & 0xFFFF0000, MPU_RGN_SIZE_64K | MPU_RGN_PERM_EXEC | MPU_RGN_PERM_PRV_RO_USR_RO | MPU_RGN_ENABLE); // Need to clear the NVIC fault status register to make sure there is no // status hanging around from a previous program. g_ui32FaultStatus = HWREG(NVIC_FAULT_STAT); HWREG(NVIC_FAULT_STAT) = g_ui32FaultStatus; // Enable the MPU fault. ROM_IntEnable(FAULT_MPU); // Enable the MPU. This will begin to enforce the memory protection // regions. The MPU is configured so that when in the hard fault or NMI // exceptions, a default map will be used. Neither of these should occur // in this example program. ROM_MPUEnable(MPU_CONFIG_HARDFLT_NMI); // Attempt to write to the flash. This should cause a protection fault due // to the fact that this region is read-only. UARTprintf("Flash write... "); g_ui32MPUFaultCount = 0; HWREG(0x100) = 0x12345678; // Verify that the fault occurred, at the expected address. if((g_ui32MPUFaultCount == 1) && (g_ui32FaultStatus == 0x82) && (g_ui32MMAR == 0x100)) { UARTprintf(" OK\n"); } else { bFail = 1; UARTprintf("NOK\n"); } // The MPU was disabled when the previous fault occurred, so it needs to be // re-enabled. ROM_MPUEnable(MPU_CONFIG_HARDFLT_NMI); // Attempt to read from the disabled section of flash, the upper 2 KB of // the 16 KB region. UARTprintf("Flash read... "); g_ui32MPUFaultCount = 0; g_ui32Value = HWREG(0x3820); // Verify that the fault occurred, at the expected address. if((g_ui32MPUFaultCount == 1) && (g_ui32FaultStatus == 0x82) && (g_ui32MMAR == 0x3820)) { UARTprintf(" OK\n"); } else { bFail = 1; UARTprintf("NOK\n"); } // The MPU was disabled when the previous fault occurred, so it needs to be // re-enabled. ROM_MPUEnable(MPU_CONFIG_HARDFLT_NMI); // Attempt to read from the read-only area of RAM, the middle 4 KB of the // 32 KB region. UARTprintf("RAM read... "); g_ui32MPUFaultCount = 0; g_ui32Value = HWREG(0x20004440); // Verify that the RAM read did not cause a fault. if(g_ui32MPUFaultCount == 0) { UARTprintf(" OK\n"); } else { bFail = 1; UARTprintf("NOK\n"); } // The MPU should not have been disabled since the last access was not // supposed to cause a fault. But if it did cause a fault, then the MPU // will be disabled, so re-enable it here anyway, just in case. ROM_MPUEnable(MPU_CONFIG_HARDFLT_NMI); // Attempt to write to the read-only area of RAM, the middle 4 KB of the // 32 KB region. UARTprintf("RAM write... "); g_ui32MPUFaultCount = 0; HWREG(0x20004460) = 0xabcdef00; // // Verify that the RAM write caused a fault. // if((g_ui32MPUFaultCount == 1) && (g_ui32FaultStatus == 0x82) && (g_ui32MMAR == 0x20004460)) { UARTprintf(" OK\n"); } else { bFail = 1; UARTprintf("NOK\n"); } // Display the results of the example program. if(bFail) { UARTprintf("Failure!\n"); } else { UARTprintf("Success!\n"); } // Disable the MPU, so there are no lingering side effects if another // program is run. ROM_MPUDisable(); // Loop forever. while(1); }