/* * This file is part of the MicroPython project, http://micropython.org/ * * The MIT License (MIT) * * Copyright (c) 2019 Glenn Ruben Bakke * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include // Secure flash 32K. #define SECURE_32K_FLASH_PAGE_START (0) #define SECURE_32K_FLASH_PAGE_END (0) // Non-secure flash 992K. #define NONSECURE_32K_FLASH_PAGE_START (1) #define NONSECURE_32K_FLASH_PAGE_END (31) // Secure RAM 64K. #define SECURE_8K_RAM_BLOCK_START (0) #define SECURE_8K_RAM_BLOCK_END (7) // Non-secure RAM 128K + 64K BSD lib. #define NONSECURE_8K_RAM_BLOCK_START (8) #define NONSECURE_8K_RAM_BLOCK_END (31) #define PERIPHERAL_ID_GET(base_addr) (((uint32_t)(base_addr) >> 12) & 0xFF) #if !defined(__ARM_FEATURE_CMSE) #pragma warning "CMSE not enabled" #endif static void configure_flash(void) { for (uint8_t i = SECURE_32K_FLASH_PAGE_START; i <= SECURE_32K_FLASH_PAGE_END; i++) { uint32_t perm = 0; perm |= (SPU_FLASHREGION_PERM_EXECUTE_Enable << SPU_FLASHREGION_PERM_EXECUTE_Pos); perm |= (SPU_FLASHREGION_PERM_WRITE_Enable << SPU_FLASHREGION_PERM_WRITE_Pos); perm |= (SPU_FLASHREGION_PERM_READ_Enable << SPU_FLASHREGION_PERM_READ_Pos); perm |= (SPU_FLASHREGION_PERM_LOCK_Locked << SPU_FLASHREGION_PERM_LOCK_Pos); perm |= (SPU_FLASHREGION_PERM_SECATTR_Secure << SPU_FLASHREGION_PERM_SECATTR_Pos); NRF_SPU_S->FLASHREGION[i].PERM = perm; } for (uint8_t i = NONSECURE_32K_FLASH_PAGE_START; i <= NONSECURE_32K_FLASH_PAGE_END; i++) { uint32_t perm = 0; perm |= (SPU_FLASHREGION_PERM_EXECUTE_Enable << SPU_FLASHREGION_PERM_EXECUTE_Pos); perm |= (SPU_FLASHREGION_PERM_WRITE_Enable << SPU_FLASHREGION_PERM_WRITE_Pos); perm |= (SPU_FLASHREGION_PERM_READ_Enable << SPU_FLASHREGION_PERM_READ_Pos); perm |= (SPU_FLASHREGION_PERM_LOCK_Locked << SPU_FLASHREGION_PERM_LOCK_Pos); perm |= (SPU_FLASHREGION_PERM_SECATTR_Non_Secure << SPU_FLASHREGION_PERM_SECATTR_Pos); NRF_SPU_S->FLASHREGION[i].PERM = perm; } } static void configure_ram(void) { for (uint8_t i = SECURE_8K_RAM_BLOCK_START; i <= SECURE_8K_RAM_BLOCK_END; i++) { uint32_t perm = 0; perm |= (SPU_RAMREGION_PERM_EXECUTE_Enable << SPU_RAMREGION_PERM_EXECUTE_Pos); perm |= (SPU_RAMREGION_PERM_WRITE_Enable << SPU_RAMREGION_PERM_WRITE_Pos); perm |= (SPU_RAMREGION_PERM_READ_Enable << SPU_RAMREGION_PERM_READ_Pos); perm |= (SPU_RAMREGION_PERM_LOCK_Locked << SPU_RAMREGION_PERM_LOCK_Pos); perm |= (SPU_RAMREGION_PERM_SECATTR_Secure << SPU_RAMREGION_PERM_SECATTR_Pos); NRF_SPU_S->RAMREGION[i].PERM = perm; } for (uint8_t i = NONSECURE_8K_RAM_BLOCK_START; i <= NONSECURE_8K_RAM_BLOCK_END; i++) { uint32_t perm = 0; perm |= (SPU_RAMREGION_PERM_EXECUTE_Enable << SPU_RAMREGION_PERM_EXECUTE_Pos); perm |= (SPU_RAMREGION_PERM_WRITE_Enable << SPU_RAMREGION_PERM_WRITE_Pos); perm |= (SPU_RAMREGION_PERM_READ_Enable << SPU_RAMREGION_PERM_READ_Pos); perm |= (SPU_RAMREGION_PERM_LOCK_Locked << SPU_RAMREGION_PERM_LOCK_Pos); perm |= (SPU_RAMREGION_PERM_SECATTR_Non_Secure << SPU_RAMREGION_PERM_SECATTR_Pos); NRF_SPU_S->RAMREGION[i].PERM = perm; } } static void peripheral_setup(uint8_t peripheral_id) { NVIC_DisableIRQ(peripheral_id); uint32_t perm = 0; perm |= (SPU_PERIPHID_PERM_PRESENT_IsPresent << SPU_PERIPHID_PERM_PRESENT_Pos); perm |= (SPU_PERIPHID_PERM_SECATTR_NonSecure << SPU_PERIPHID_PERM_SECATTR_Pos); perm |= (SPU_PERIPHID_PERM_LOCK_Locked << SPU_PERIPHID_PERM_LOCK_Pos); NRF_SPU_S->PERIPHID[peripheral_id].PERM = perm; NVIC_SetTargetState(peripheral_id); } static void configure_peripherals(void) { NRF_SPU_S->GPIOPORT[0].PERM = 0; peripheral_setup(PERIPHERAL_ID_GET(NRF_REGULATORS_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_CLOCK_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_UARTE0_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_UARTE1_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_UARTE2_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_UARTE3_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_SAADC_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_TIMER0_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_TIMER1_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_TIMER2_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_RTC0_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_RTC1_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_DPPIC_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_WDT_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_EGU1_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_EGU2_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_EGU3_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_EGU4_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_EGU5_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_PWM0_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_PWM1_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_PWM2_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_PWM3_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_PDM_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_I2S_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_IPC_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_FPU_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_GPIOTE1_NS)); peripheral_setup(PERIPHERAL_ID_GET(NRF_NVMC_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_VMC_S)); peripheral_setup(PERIPHERAL_ID_GET(NRF_P0_NS)); } typedef void __attribute__((cmse_nonsecure_call)) nsfunc(void); static void jump_to_non_secure(void) { TZ_SAU_Disable(); SAU->CTRL |= SAU_CTRL_ALLNS_Msk; // Set NS vector table. uint32_t * vtor_ns = (uint32_t *)0x8000; SCB_NS->VTOR = (uint32_t)vtor_ns; // Allow for FPU to be used by NS. SCB->NSACR |= (1UL << SCB_NSACR_CP10_Pos) | (1UL << SCB_NSACR_CP11_Pos); // Set stack pointers. __TZ_set_MSP_NS(vtor_ns[0]); __TZ_set_PSP_NS(0); uint32_t control_ns = __TZ_get_CONTROL_NS(); control_ns &= ~(CONTROL_SPSEL_Msk | CONTROL_nPRIV_Msk); __TZ_set_CONTROL_NS(control_ns); // Cast NS Reset_Handler to a non-secure function. nsfunc *fp = (nsfunc *)vtor_ns[1]; fp = (nsfunc *)((intptr_t)(fp) & ~1); if (cmse_is_nsfptr(fp)) { __DSB(); __ISB(); // Jump to Non-Secure function. fp(); } } int main(void) { configure_flash(); configure_ram(); configure_peripherals(); jump_to_non_secure(); while (1) { ; } return 0; } void _start(void) {main();}