This repository has been archived on 2023-07-17. You can view files and clone it, but cannot push or open issues or pull requests.
bl_mcu_sdk/drivers/bl702_driver/startup/interrupt.c

366 lines
15 KiB
C

/**
* @file interrupt.c
* @brief
*
* Copyright (c) 2021 Bouffalolab team
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership. The
* ASF licenses this file to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the
* License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
*/
#include "bl702_common.h"
#include "bflb_platform.h"
pFunc __Interrupt_Handlers[IRQn_LAST] = { 0 };
void Interrupt_Handler_Stub(void);
void clic_msip_handler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void clic_mtimer_handler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void clic_mext_handler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void clic_csoft_handler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void BMX_ERR_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void BMX_TO_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void L1C_BMX_ERR_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void L1C_BMX_TO_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void SEC_BMX_ERR_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void RF_TOP_INT0_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void RF_TOP_INT1_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void DMA_BMX_ERR_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void SEC_GMAC_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void SEC_CDET_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void SEC_PKA_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void SEC_TRNG_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void SEC_AES_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void SEC_SHA_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void DMA_ALL_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void MJPEG_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void CAM_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void I2S_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void IRTX_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void IRRX_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void USB_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void EMAC_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void SF_CTRL_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void GPADC_DMA_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void EFUSE_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void SPI_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void UART0_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void UART1_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void I2C_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void PWM_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void TIMER_CH0_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void TIMER_CH1_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void TIMER_WDT_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void KYS_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void QDEC0_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void QDEC1_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void QDEC2_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void GPIO_INT0_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void TOUCH_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void M154_REQ_ENH_ACK_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void M154_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void M154_AES_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void PDS_WAKEUP_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void HBN_OUT0_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void HBN_OUT1_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void BOR_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void WIFI_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void BZ_PHY_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void BLE_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void MAC_TXRX_TIMER_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void MAC_TXRX_MISC_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void MAC_RX_TRG_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void MAC_TX_TRG_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void MAC_GEN_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void MAC_PORT_TRG_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
void WIFI_IPC_PUBLIC_IRQHandler_Wrapper(void) __attribute__((weak, alias("Interrupt_Handler_Stub")));
const pFunc __Vectors[] __attribute__((section(".init"), aligned(64))) = {
0, /* */
0, /* */
0, /* */
clic_msip_handler_Wrapper, /* 3 */
0, /* */
0, /* */
0, /* */
clic_mtimer_handler_Wrapper, /* 7 */
(pFunc)0x00000001, /* */
0, /* */
(pFunc)0x00000102, /* */ //disable log as default
clic_mext_handler_Wrapper, /* 11 */
clic_csoft_handler_Wrapper, /* 12 */
0, /* */
0, /* */
0, /* */
BMX_ERR_IRQHandler_Wrapper, /* 16 + 0 */
BMX_TO_IRQHandler_Wrapper, /* 16 + 1 */
L1C_BMX_ERR_IRQHandler_Wrapper, /* 16 + 2 */
L1C_BMX_TO_IRQHandler_Wrapper, /* 16 + 3 */
SEC_BMX_ERR_IRQHandler_Wrapper, /* 16 + 4 */
RF_TOP_INT0_IRQHandler_Wrapper, /* 16 + 5 */
RF_TOP_INT1_IRQHandler_Wrapper, /* 16 + 6 */
0, /* 16 + 7 */
DMA_BMX_ERR_IRQHandler_Wrapper, /* 16 + 8 */
SEC_GMAC_IRQHandler_Wrapper, /* 16 + 9 */
SEC_CDET_IRQHandler_Wrapper, /* 16 + 10 */
SEC_PKA_IRQHandler_Wrapper, /* 16 + 11 */
SEC_TRNG_IRQHandler_Wrapper, /* 16 + 12 */
SEC_AES_IRQHandler_Wrapper, /* 16 + 13 */
SEC_SHA_IRQHandler_Wrapper, /* 16 + 14 */
DMA_ALL_IRQHandler_Wrapper, /* 16 + 15 */
MJPEG_IRQHandler_Wrapper, /* 16 + 16 */
CAM_IRQHandler_Wrapper, /* 16 + 17 */
I2S_IRQHandler_Wrapper, /* 16 + 18 */
IRTX_IRQHandler_Wrapper, /* 16 + 19 */
IRRX_IRQHandler_Wrapper, /* 16 + 20 */
USB_IRQHandler_Wrapper, /* 16 + 21 */
EMAC_IRQHandler_Wrapper, /* 16 + 22 */
SF_CTRL_IRQHandler_Wrapper, /* 16 + 23 */
0, /* 16 + 24 */
GPADC_DMA_IRQHandler_Wrapper, /* 16 + 25 */
EFUSE_IRQHandler_Wrapper, /* 16 + 26 */
SPI_IRQHandler_Wrapper, /* 16 + 27 */
0, /* 16 + 28 */
UART0_IRQHandler_Wrapper, /* 16 + 29 */
UART1_IRQHandler_Wrapper, /* 16 + 30 */
0, /* 16 + 31 */
I2C_IRQHandler_Wrapper, /* 16 + 32 */
0, /* 16 + 33 */
PWM_IRQHandler_Wrapper, /* 16 + 34 */
0, /* 16 + 35 */
TIMER_CH0_IRQHandler_Wrapper, /* 16 + 36 */
TIMER_CH1_IRQHandler_Wrapper, /* 16 + 37 */
TIMER_WDT_IRQHandler_Wrapper, /* 16 + 38 */
KYS_IRQHandler_Wrapper, /* 16 + 39 */
QDEC0_IRQHandler_Wrapper, /* 16 + 40 */
QDEC1_IRQHandler_Wrapper, /* 16 + 41 */
QDEC2_IRQHandler_Wrapper, /* 16 + 42 */
0, /* 16 + 43 */
GPIO_INT0_IRQHandler_Wrapper, /* 16 + 44 */
TOUCH_IRQHandler_Wrapper, /* 16 + 45 */
0, /* 16 + 46 */
M154_REQ_ENH_ACK_IRQHandler_Wrapper, /* 16 + 47 */
M154_IRQHandler_Wrapper, /* 16 + 48 */
M154_AES_IRQHandler_Wrapper, /* 16 + 49 */
PDS_WAKEUP_IRQHandler_Wrapper, /* 16 + 50 */
HBN_OUT0_IRQHandler_Wrapper, /* 16 + 51 */
HBN_OUT1_IRQHandler_Wrapper, /* 16 + 52 */
BOR_IRQHandler_Wrapper, /* 16 + 53 */
WIFI_IRQHandler_Wrapper, /* 16 + 54 */
BZ_PHY_IRQHandler_Wrapper, /* 16 + 55 */
BLE_IRQHandler_Wrapper, /* 16 + 56 */
MAC_TXRX_TIMER_IRQHandler_Wrapper, /* 16 + 57 */
MAC_TXRX_MISC_IRQHandler_Wrapper, /* 16 + 58 */
MAC_RX_TRG_IRQHandler_Wrapper, /* 16 + 59 */
MAC_TX_TRG_IRQHandler_Wrapper, /* 16 + 60 */
MAC_GEN_IRQHandler_Wrapper, /* 16 + 61 */
MAC_PORT_TRG_IRQHandler_Wrapper, /* 16 + 62 */
WIFI_IPC_PUBLIC_IRQHandler_Wrapper, /* 16 + 63 */
};
void Trap_Handler(void)
{
unsigned long cause;
unsigned long epc;
unsigned long tval;
uint8_t isecall = 0;
MSG("Trap_Handler\r\n");
cause = read_csr(mcause);
MSG("mcause=%08x\r\n", (uint32_t)cause);
epc = read_csr(mepc);
MSG("mepc:%08x\r\n", (uint32_t)epc);
tval = read_csr(mtval);
MSG("mtval:%08x\r\n", (uint32_t)tval);
cause = (cause & 0x3ff);
switch (cause) {
case 1:
MSG("Instruction access fault\r\n");
break;
case 2:
MSG("Illegal instruction\r\n");
break;
case 3:
MSG("Breakpoint\r\n");
break;
case 4:
MSG("Load address misaligned\r\n");
break;
case 5:
MSG("Load access fault\r\n");
break;
case 6:
MSG("Store/AMO address misaligned\r\n");
break;
case 7:
MSG("Store/AMO access fault\r\n");
break;
case 8:
MSG("Environment call from U-mode\r\n");
epc += 4;
write_csr(mepc, epc);
break;
case 11:
MSG("Environment call from M-mode\r\n");
epc += 4;
write_csr(mepc, epc);
isecall = 1;
break;
default:
MSG("Cause num=%d\r\n", (uint32_t)cause);
epc += 4;
write_csr(mepc, epc);
break;
}
if (!isecall) {
while (1)
;
}
}
void Interrupt_Handler(void)
{
pFunc interruptFun;
uint32_t num = 0;
volatile uint32_t ulMEPC = 0UL, ulMCAUSE = 0UL;
/* Store a few register values that might be useful when determining why this
function was called. */
__asm volatile("csrr %0, mepc"
: "=r"(ulMEPC));
__asm volatile("csrr %0, mcause"
: "=r"(ulMCAUSE));
if ((ulMCAUSE & 0x80000000) == 0) {
/*Exception*/
MSG("Exception should not be here\r\n");
} else {
num = ulMCAUSE & 0x3FF;
if (num < IRQn_LAST) {
interruptFun = __Interrupt_Handlers[num];
if (NULL != interruptFun) {
interruptFun();
} else {
MSG("Interrupt num:%d IRQHandler not installed\r\n", (unsigned int)num);
if (num >= IRQ_NUM_BASE) {
MSG("Peripheral Interrupt num:%d \r\n", (unsigned int)num - IRQ_NUM_BASE);
}
while (1)
;
}
} else {
MSG("Unexpected interrupt num:%d\r\n", (unsigned int)num);
}
}
}
void handle_trap(void)
{
#define MCAUSE_INT_MASK 0x80000000 // [31]=1 interrupt, else exception
#define MCAUSE_CODE_MASK 0x7FFFFFFF // low bits show code
unsigned long mcause_value = read_csr(mcause);
if (mcause_value & MCAUSE_INT_MASK) {
// Branch to interrupt handler here
Interrupt_Handler();
} else {
// Branch to exception handle
Trap_Handler();
}
}
void __IRQ_ALIGN64 Trap_Handler_Stub(void)
{
Trap_Handler();
}
void __IRQ Interrupt_Handler_Stub(void)
{
Interrupt_Handler();
}
void FreeRTOS_Interrupt_Handler(void)
{
Interrupt_Handler();
}
void Interrupt_Handler_Register(IRQn_Type irq, pFunc interruptFun)
{
if (irq < IRQn_LAST) {
__Interrupt_Handlers[irq] = interruptFun;
}
}
void System_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
{
}
void clic_enable_interrupt(uint32_t source)
{
*(volatile uint8_t *)(CLIC_HART0_ADDR + CLIC_INTIE + source) = 1;
}
void clic_disable_interrupt(uint32_t source)
{
*(volatile uint8_t *)(CLIC_HART0_ADDR + CLIC_INTIE + source) = 0;
}
void clic_clear_pending(uint32_t source)
{
*(volatile uint8_t *)(CLIC_HART0_ADDR + CLIC_INTIP + source) = 0;
}
void clic_set_pending(uint32_t source)
{
*(volatile uint8_t *)(CLIC_HART0_ADDR + CLIC_INTIP + source) = 1;
}
void clic_set_intcfg(uint32_t source, uint32_t intcfg)
{
*(volatile uint8_t *)(CLIC_HART0_ADDR + CLIC_INTCFG + source) = intcfg;
}
uint8_t clic_get_intcfg(uint32_t source)
{
return *(volatile uint8_t *)(CLIC_HART0_ADDR + CLIC_INTCFG + source);
}
void clic_set_cliccfg(uint32_t cfg)
{
*(volatile uint8_t *)(CLIC_HART0_ADDR + CLIC_CFG) = cfg;
}
uint8_t clic_get_cliccfg(void)
{
return *(volatile uint8_t *)(CLIC_HART0_ADDR + CLIC_CFG);
}