PolarFire® SoC mpfs-mmuart-interrupt 串口2 中断处理过程
一、demo: mpfs-mmuart-interrupt
串口1 是本地中断 , 参考 PolarFire® SoC mpfs-mmuart-interrupt 串口1 初始化过程 - 所长 - 博客园
以串口2中断是 全局中断,为例子,总过程如下:
中断触发 → trap_vector → trap_from_machine_mode → handle_m_ext_interrupt → PLIC_mmuart2_IRQHandler → mmuart2_plic_IRQHandler→uart_isr→rx_handler→uart2_rx_handler
二、/mpfs-mmuart-interrupt/src/platform/mpfs_hal/startup_gcc/mss_entry.S
中断触发 → trap_vector → trap_from_machine_mode
3、trap_from_machine_mode 函数 在 /mpfs-mmuart-interrupt/src/platform/mpfs_hal/common/mss_mtrap.c
void trap_from_machine_mode(uintptr_t * regs, uintptr_t dummy, uintptr_t mepc) {
// 读取 csr 寄存器, 该寄存器 标识 中断和异常的 原因 volatile uintptr_t mcause = read_csr(mcause); if (((mcause & MCAUSE_INT) == MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) >=\ IRQ_M_LOCAL_MIN)&& ((mcause & MCAUSE_CAUSE) <= IRQ_M_LOCAL_MAX)) {
// 本地中断处理 handle_local_interrupt((uint8_t)(mcause & MCAUSE_CAUSE)); } else if (((mcause & MCAUSE_INT) == MCAUSE_INT) && ((mcause & MCAUSE_CAUSE)\ == IRQ_M_EXT)) {
// 外部中断处理 handle_m_ext_interrupt(); } else if (((mcause & MCAUSE_INT) == MCAUSE_INT) && ((mcause & MCAUSE_CAUSE)\ == IRQ_M_SOFT)) {
// 软件中断处理 handle_m_soft_interrupt(); } else if (((mcause & MCAUSE_INT) == MCAUSE_INT) && ((mcause & MCAUSE_CAUSE)\ == IRQ_M_TIMER)) {
// mtime 中断处理 handle_m_timer_interrupt(); } else if (((mcause & MCAUSE_INT) == MCAUSE_INT) && ((mcause & MCAUSE_CAUSE)\ == IRQ_M_BEU )) {
// 总线错误中断 handle_local_beu_interrupt(); } else { uint32_t i = 0U;
// 死循环 while(1U) { /* wait for watchdog */ i++; if(i == 0x1000U) { i = (uint32_t)mcause; /* so mcause is not optimised out */ } } switch(mcause) { case CAUSE_LOAD_PAGE_FAULT: break; case CAUSE_STORE_PAGE_FAULT: break; case CAUSE_FETCH_ACCESS: break; case CAUSE_LOAD_ACCESS: break; case CAUSE_STORE_ACCESS: break; default: bad_trap(regs, dummy, mepc); break; } } }
4、trap_from_machine_mode → handle_m_ext_interrupt → PLIC_mmuart2_IRQHandler → mmuart2_plic_IRQHandler→uart_isr→rx_handler→uart2_rx_handler
void handle_m_ext_interrupt(void) { volatile uint32_t int_num = PLIC_ClaimIRQ(); if (PLIC_INVALID_INT_OFFSET == int_num) { return; } uint8_t disable = EXT_IRQ_KEEP_ENABLED; disable = ext_irq_handler_table[int_num](); PLIC_CompleteIRQ(int_num); if(EXT_IRQ_DISABLE == disable) { PLIC_DisableIRQ((PLIC_IRQn_Type)int_num); } }
void uart2_rx_handler(mss_uart_instance_t *this_uart) {
uint32_t hart_id = read_csr(mhartid);
int8_t info_string2[50];
irq_cnt++;
sprintf(info_string2, "UART2 Interrupt count = 0x%x \r\n\r\n", irq_cnt);
/* This will execute when interrupt from hart 2 is raised */
g_rx_size2 = MSS_UART_get_rx(this_uart, g_rx_buff2, sizeof(g_rx_buff2));
MSS_UART_polled_tx(p_uartmap_u54_2, info_string2,
strlen(info_string2));
}
浙公网安备 33010602011771号