pinebuds/platform/cmsis/cmsis_nvic.c
2022-08-15 17:20:27 +08:00

221 lines
6.8 KiB
C

/* mbed Microcontroller Library
* CMSIS-style functionality to support dynamic vectors
*******************************************************************************
* Copyright (c) 2011 ARM Limited. All rights reserved.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* 3. Neither the name of ARM Limited nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*******************************************************************************
*/
#ifndef __ARM_ARCH_ISA_ARM
#include "cmsis_nvic.h"
#include "plat_types.h"
#include "plat_addr_map.h"
#include "hal_location.h"
#ifdef __ARMCC_VERSION
#include "link_sym_armclang.h"
#endif
STATIC_ASSERT(NVIC_NUM_VECTORS * 4 <= VECTOR_SECTION_SIZE, "ERROR: VECTOR_SECTION_SIZE too small!");
// The vector table must be aligned to NVIC_NUM_VECTORS-word boundary, rounding up to the next power of two
// -- 0x100 for 33~64 vectors, and 0x200 for 65~128 vectors
#ifdef __ARMCC_VERSION
#define VECTOR_LOC __attribute__((section(".bss.vector_table")))
#else
#define VECTOR_LOC __attribute__((section(".vector_table")))
#endif
#define FAULT_HANDLER __attribute__((weak,alias("NVIC_default_handler")))
static uint32_t VECTOR_LOC vector_table[NVIC_NUM_VECTORS];
void NVIC_DisableAllIRQs(void)
{
int i;
for (i = 0; i < (USER_IRQn_QTY + 31) / 32; i++) {
NVIC->ICER[i] = ~0UL;
}
SCB->VTOR = 0;
}
static void NAKED BOOT_TEXT_FLASH_LOC NVIC_default_handler(void)
{
asm volatile("_loop:; nop; nop; nop; nop; b _loop;");
}
void FAULT_HANDLER Reset_Handler(void);
void FAULT_HANDLER NMI_Handler(void);
void FAULT_HANDLER HardFault_Handler(void);
void FAULT_HANDLER MemManage_Handler(void);
void FAULT_HANDLER BusFault_Handler(void);
void FAULT_HANDLER UsageFault_Handler(void);
void FAULT_HANDLER SecureFault_Handler(void);
void FAULT_HANDLER SVC_Handler(void);
void FAULT_HANDLER DebugMon_Handler(void);
void FAULT_HANDLER PendSV_Handler(void);
void FAULT_HANDLER SysTick_Handler(void);
extern uint32_t __rom_stack[];
extern uint32_t __stack[];
static const uint32_t BOOT_RODATA_FLASH_LOC fault_handlers[NVIC_USER_IRQ_OFFSET] = {
#if defined(ROM_BUILD) && !defined(ROM_IN_FLASH)
(uint32_t)__rom_stack,
#else
(uint32_t)__stack,
#endif
(uint32_t)Reset_Handler,
(uint32_t)NMI_Handler,
(uint32_t)HardFault_Handler,
(uint32_t)MemManage_Handler,
(uint32_t)BusFault_Handler,
(uint32_t)UsageFault_Handler,
(uint32_t)SecureFault_Handler,
(uint32_t)NVIC_default_handler,
(uint32_t)NVIC_default_handler,
(uint32_t)NVIC_default_handler,
(uint32_t)SVC_Handler,
(uint32_t)DebugMon_Handler,
(uint32_t)NVIC_default_handler,
(uint32_t)PendSV_Handler,
(uint32_t)SysTick_Handler,
};
void BOOT_TEXT_FLASH_LOC NVIC_InitVectors(void)
{
int i;
for (i = 0; i < NVIC_NUM_VECTORS; i++) {
vector_table[i] = (i < ARRAY_SIZE(fault_handlers)) ?
fault_handlers[i] : (uint32_t)NVIC_default_handler;
}
SCB->VTOR = (uint32_t)vector_table;
__DSB();
}
void NVIC_SetDefaultFaultHandler(NVIC_DEFAULT_FAULT_HANDLER_T handler)
{
int i;
for (i = 1; i < ARRAY_SIZE(fault_handlers); i++) {
if (vector_table[i] == (uint32_t)NVIC_default_handler) {
vector_table[i] = (uint32_t)handler;
}
}
}
IRQn_Type NVIC_GetCurrentActiveIRQ(void)
{
IRQn_Type irq = (__get_IPSR() & IPSR_ISR_Msk) - NVIC_USER_IRQ_OFFSET;
return irq;
}
#ifdef CORE_SLEEP_POWER_DOWN
void SRAM_TEXT_LOC NVIC_PowerDownSleep(uint32_t *buf, uint32_t cnt)
{
int i;
uint32_t idx;
__IO uint32_t *regs;
idx = 0;
for (i = 0; i < (NVIC_NUM_VECTORS - NVIC_USER_IRQ_OFFSET + 31) / 32; i++) {
buf[idx++] = NVIC->ISER[i];
}
#if (__CORTEX_M <= 4)
regs = (__IO uint32_t *)&NVIC->IP[0];
#else
regs = (__IO uint32_t *)&NVIC->IPR[0];
#endif
for (i = 0; i < (NVIC_NUM_VECTORS - NVIC_USER_IRQ_OFFSET + 3) / 4; i++) {
buf[idx++] = regs[i];
}
buf[idx++] = SCnSCB->ACTLR;
buf[idx++] = SCB->ICSR;
buf[idx++] = SCB->AIRCR;
buf[idx++] = SCB->SCR;
buf[idx++] = SCB->CCR;
#if (__CORTEX_M <= 4)
regs = (__IO uint32_t *)&SCB->SHP[0];
#else
regs = (__IO uint32_t *)&SCB->SHPR[0];
#endif
buf[idx++] = regs[0];
buf[idx++] = regs[1];
buf[idx++] = regs[2];
buf[idx++] = SCB->SHCSR;
buf[idx++] = SysTick->CTRL;
buf[idx++] = SysTick->LOAD;
if (idx > cnt) {
do { asm volatile("nop \n nop \n nop \n nop"); } while (1);
}
}
void SRAM_TEXT_LOC NVIC_PowerDownWakeup(uint32_t *buf, uint32_t cnt)
{
int i;
uint32_t idx;
__IO uint32_t *regs;
idx = 0;
for (i = 0; i < (NVIC_NUM_VECTORS - NVIC_USER_IRQ_OFFSET + 31) / 32; i++) {
NVIC->ISER[i] = buf[idx++];
}
#if (__CORTEX_M <= 4)
regs = (__IO uint32_t *)&NVIC->IP[0];
#else
regs = (__IO uint32_t *)&NVIC->IPR[0];
#endif
for (i = 0; i < (NVIC_NUM_VECTORS - NVIC_USER_IRQ_OFFSET + 3) / 4; i++) {
regs[i] = buf[idx++];
}
SCnSCB->ACTLR = buf[idx++];
SCB->ICSR = buf[idx++];
SCB->AIRCR = buf[idx++];
SCB->SCR = buf[idx++];
SCB->CCR = buf[idx++];
#if (__CORTEX_M <= 4)
regs = (__IO uint32_t *)&SCB->SHP[0];
#else
regs = (__IO uint32_t *)&SCB->SHPR[0];
#endif
regs[0] = buf[idx++];
regs[1] = buf[idx++];
regs[2] = buf[idx++];
SCB->SHCSR = buf[idx++];
SysTick->CTRL = buf[idx++];
SysTick->LOAD = buf[idx++];
SCB->VTOR = (uint32_t)vector_table;
SysTick->VAL = 0;
}
#endif
#endif