T113裸跑不能产生中断请教:
-
T113就配置TIMER0做tick时钟:
#define TIMER_IRQ_CON_BASE (0x02050000) #define TIMER0_BASE (0x02050010) #define TIMER1_BASE (0x02050020) #define timer0 ((timer_t *)(TIMER0_BASE)) #define timer1 ((timer_t *)(TIMER1_BASE)) /* for R528/T113 */ #define T113_GIC_BASE (0x03021000) #define T113_CPUIF_BASE (0x03022000) #define PRESCALER_VALUE 1UL #define OS_CFG_TICK_RATE_HZ 1000 #define GPTIM_LOAD_CONST ((24000000 / OS_CFG_TICK_RATE_HZ) /(PRESCALER_VALUE) ) timer_irq_con_t * timer_irq_con = (timer_irq_con_t * )TIMER_IRQ_CON_BASE; void BSP_OS_TickInit (void) { timer0->INTV_VALUE = GPTIM_LOAD_CONST; timer0->CUR_VALUE = GPTIM_LOAD_CONST; bsp_int_vect_set(INT_TIMER0, /* Assign ISR handler. */ 1u, /* 中断的优先级 */ 3u, /* 中断的目标CPU */ 0u, /* 参数 */ BSP_OS_TickISR_Handler); /* 周期连续模式 */ timer0->CTRL_REG = (1 << 2); irq_enable(INT_TIMER0); timer_irq_con->TMR_IRQ_STA = 1;/*clear int sta */ timer_irq_con->TMR_IRQ_EN |= 1;/*enable timer0 int */ timer0->CTRL_REG |= 1;/*enable timer0 */ }
运行后timer0的计数正常,中断标志也已经置1了,但就是不产生中断。请教各位大佬,问题该如何定位。
gic模块的代码基本上是提取uboot的代码,代码在V3s上是能够正常运行的,只是迁移时根据T113的地址分布更改了各模块的基地址:
/* * (C) Copyright 2007-2013 * Allwinner Technology Co., Ltd. <www.allwinnertech.com> * Jerry Wang <wangflord@allwinnertech.com> * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ #include "v3s_map.h" #include "reg-ccu.h" #include "gic.h" #include "v3s_irq_id.h" #include <stdio.h> #include <stdint.h> #include "bsp_sys.h" struct _irq_handler { void *m_data; void (*m_func)( void * data); }; struct _irq_handler sunxi_int_handlers[NUMBER_OF_INT_VECTORS]@"OcramData"; /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void default_isr(void *data) { sysprintf("default_isr(): called from IRQ %d\n", (uint32_t)data); while(1); } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int irq_enable(int irq_no) { uint32_t reg_val; uint32_t offset; if (irq_no >= NUMBER_OF_INT_VECTORS) { printf("irq NO.(%d) > NUMBER_OF_INT_VECTORS(%d) !!\n", irq_no, NUMBER_OF_INT_VECTORS); return -1; } if(irq_no == INT_NMI) { *(volatile unsigned int *)(0x01f00c00 + 0x10) |= 1; *(volatile unsigned int *)(0x01f00c00 + 0x40) |= 1; } offset = irq_no >> 5; // 除32 reg_val = readl(GIC_SET_EN(offset)); reg_val |= 1 << (irq_no & 0x1f); writel(reg_val, GIC_SET_EN(offset)); return 0; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int irq_disable(int irq_no) { uint32_t reg_val; uint32_t offset; if (irq_no >= NUMBER_OF_INT_VECTORS) { sysprintf("irq NO.(%d) > NUMBER_OF_INT_VECTORS(%d) !!\n", irq_no, NUMBER_OF_INT_VECTORS); return -1; } if(irq_no == INT_NMI) { *(volatile unsigned int *)(0x01f00c00 + 0x10) |= 1; *(volatile unsigned int *)(0x01f00c00 + 0x40) &= ~1; } offset = irq_no >> 5; // 除32 reg_val = (1 << (irq_no & 0x1f)); writel(reg_val, GIC_CLR_EN(offset)); return 0; } void irq_int_prio_set (uint32_t int_id, uint32_t prio) { if (int_id >= NUMBER_OF_INT_VECTORS) { sysprintf("irq NO.(%d) > NUMBER_OF_INT_VECTORS(%d) !!\n", int_id, NUMBER_OF_INT_VECTORS); return ; } if (prio > BSP_INT_PRIO_LVL_MAX) { prio = BSP_INT_PRIO_LVL_MAX; return; } CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); // uint32_t * prio_r = (uint32_t *)GIC_SGI_PRIO((int_id>>5)); //prio_r[int_id] = (uint8_t)((prio << (8UL - __GIC_PRIO_BITS)) & (uint8_t)0xFFUL); uint32_t reg_val, addr, offset; /* dispatch the usb interrupt to CPU1 */ addr = GIC_SGI_PRIO(int_id>>2); reg_val = readl(addr); offset = 8 * (int_id & 3); reg_val &= ~(0xff<<offset); reg_val |= ((prio << (8UL - __GIC_PRIO_BITS)) << offset); writel(reg_val, addr); CPU_CRITICAL_EXIT(); } void irq_int_target_cpu_set (uint32_t int_id, uint8_t int_target_cpu) { if (int_id >= NUMBER_OF_INT_VECTORS) { sysprintf("irq NO.(%d) > NUMBER_OF_INT_VECTORS(%d) !!\n", int_id, NUMBER_OF_INT_VECTORS); return ; } CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); uint32_t reg_val, addr, offset; /* dispatch the usb interrupt to CPU1 */ addr = GIC_SGI_PROC_TARG(int_id>>2); reg_val = readl(addr); offset = 8 * (int_id & 3); reg_val &= ~(0xff<<offset); reg_val |= (int_target_cpu <<offset); writel(reg_val, addr); CPU_CRITICAL_EXIT(); return ; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void gic_sgi_handler(uint32_t irq_no) { sysprintf("SGI irq %d coming... \n", irq_no); } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void gic_ppi_handler(uint32_t irq_no) { sysprintf("PPI irq %d coming... \n", irq_no); } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void gic_spi_handler(uint32_t irq_no) { if (sunxi_int_handlers[irq_no].m_func != default_isr) { sunxi_int_handlers[irq_no].m_func(sunxi_int_handlers[irq_no].m_data); } } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void gic_clear_pending(uint32_t irq_no) { uint32_t reg_val; uint32_t offset; offset = irq_no >> 5; // 除32 reg_val = readl(GIC_PEND_CLR(offset)); reg_val |= (1 << (irq_no & 0x1f)); writel(reg_val, GIC_PEND_CLR(offset)); return ; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ void irq_install_handler (int irq, interrupt_handler_t handle_irq, void *data) { CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); if (irq >= NUMBER_OF_INT_VECTORS || !handle_irq) { CPU_CRITICAL_EXIT(); return; } sunxi_int_handlers[irq].m_data = data; sunxi_int_handlers[irq].m_func = handle_irq; CPU_CRITICAL_EXIT(); } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ void irq_free_handler(int irq) { CPU_SR_ALLOC(); CPU_CRITICAL_ENTER(); if (irq >= NUMBER_OF_INT_VECTORS) { CPU_CRITICAL_EXIT(); return; } sunxi_int_handlers[irq].m_data = NULL; sunxi_int_handlers[irq].m_func = default_isr; CPU_CRITICAL_EXIT(); } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ void BSP_IntHandler (void) { u32 idnum; idnum = readl(GIC_INT_ACK_REG); if ((idnum == 1023) ||(idnum == 1022)) { sysprintf("spurious irq !!\n"); return; } if (idnum >= NUMBER_OF_INT_VECTORS) { sysprintf("irq NO.(%d) > NUMBER_OF_INT_VECTORS(%d) !!\n", idnum, NUMBER_OF_INT_VECTORS-32); return; } // u32 int_cpu = (idnum >> 10) & 0x0f; if (idnum < 16) gic_sgi_handler(idnum); else if (idnum < 32) gic_ppi_handler(idnum); else gic_spi_handler(idnum); if(idnum == INT_NMI) { *(volatile unsigned int *)(0x01f00c00 + 0x10) |= 1; } writel(idnum, GIC_END_INT_REG);/*write GICC_EOIR, to cause priority drop on the GIC CPU interface*/ writel(idnum, GIC_DEACT_INT_REG);/* write to the GICC_DIR, to deactivate the interrupt*/ gic_clear_pending(idnum); return; } //#endif /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void gic_distributor_init(void) { uint32_t cpumask = 0x01010101; uint32_t gic_irqs; uint32_t i; writel(0, GIC_DIST_CON); /* check GIC hardware configutation */ gic_irqs = ((readl(GIC_CON_TYPE) & 0x1f) + 1) * 32; if (gic_irqs > 1020) { gic_irqs = 1020; } if (gic_irqs < NUMBER_OF_INT_VECTORS) { sysprintf("GIC parameter config error, only support %d" " irqs < %d(spec define)!!\n", gic_irqs, NUMBER_OF_INT_VECTORS); return ; } /* set trigger type to be level-triggered, active low */ for (i=0; i<NUMBER_OF_INT_VECTORS; i+=16) { writel(0, GIC_IRQ_MOD_CFG(i>>4)); } /* set priority */ for (i=GIC_SRC_SPI(0); i<NUMBER_OF_INT_VECTORS; i+=4) { writel(0xffffffff, GIC_SPI_PRIO((i-32)>>2)); } /* set processor target */ for (i=32; i<NUMBER_OF_INT_VECTORS; i+=4) { writel(cpumask, GIC_SPI_PROC_TARG((i-32)>>2)); } /* disable all interrupts */ for (i=32; i<NUMBER_OF_INT_VECTORS; i+=32) { writel(0xffffffff, GIC_CLR_EN(i>>5)); } /* clear all interrupt active state */ for (i=32; i<NUMBER_OF_INT_VECTORS; i+=32) { writel(0xffffffff, GIC_ACT_CLR(i>>5)); } writel(1, GIC_DIST_CON); return ; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ static void gic_cpuif_init(void) { uint32_t i; writel(0, GIC_CPU_IF_CTRL); /* * Deal with the banked PPI and SGI interrupts - disable all * PPI interrupts, ensure all SGI interrupts are enabled. */ writel(0xffff0000, GIC_CLR_EN(0)); writel(0x0000ffff, GIC_SET_EN(0)); /* Set priority on PPI and SGI interrupts */ for (i=0; i<16; i+=4) { writel(0xffffffff, GIC_SGI_PRIO(i>>2)); } for (i=16; i<32; i+=4) { writel(0xffffffff, GIC_PPI_PRIO((i-16)>>2)); } /* Priority level is implementation defined. To determine the number of priority bits implemented write 0xFF to an IPRIORITYR priority field and read back the value stored.*/ // GIC_SetPriority((IRQn_Type)0U, 0xFFU); //priority_field = GIC_GetPriority((IRQn_Type)0U); writel(0xff, GIC_INT_PRIO_MASK); writel(1, GIC_CPU_IF_CTRL); return ; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int arch_interrupt_init (void) { int i; for (i=0; i<NUMBER_OF_INT_VECTORS; i++) { sunxi_int_handlers[i].m_func = default_isr; } gic_distributor_init(); gic_cpuif_init(); return 0; } /* ************************************************************************************************************ * * function * * name : * * parmeters : * * return : * * note : * * ************************************************************************************************************ */ int arch_interrupt_exit(void) { gic_distributor_init(); gic_cpuif_init(); return 0; } void bsp_int_vect_set( uint32_t int_id, uint32_t int_prio, uint8_t int_target_list, void * pParam, system_irq_handler_t int_fnct) { irq_install_handler (int_id, int_fnct, pParam); irq_int_prio_set(int_id,int_prio); irq_int_target_cpu_set(int_id,int_target_list); }
-
将完整的IAR裸机测试项目上传。T113_test.rar
-
@l13819506056 串口可正常交互嘛?
-
@mangogeek 串口是可以打印输出的(非中断方式)。
-
感觉你可以尝试用uboot来run你这个代码测试下,起码uboot给你准备了个正常的环境。然后再对比中断相关的寄存器和你纯裸跑有无差异。
-
@mangogeek 在staru.s中添加下面一段后,中断就正常了。
/* Set vector base address register */
ldr r0, =__vector_table
mcr p15, 0, r0, c12, c0, 0
mrc p15, 0, r0, c1, c0, 0
bic r0, #(1 << 13)
mcr p15, 0, r0, c1, c0, 0/* Enable SMP mode for dcache, by setting bit 6 of auxiliary ctl reg */ mrc p15, 0, r0, c1, c0, 1 orr r0, r0, #(1 << 6) mcr p15, 0, r0, c1, c0, 1 /* enable branch prediction */ mrc p15, 0, r0, c1, c0, 0 orr r0, r0, #(1<<11) mcr p15, 0, r0, c1, c0, 0 /* Enable neon/vfp unit */ mrc p15, 0, r0, c1, c0, 2 orr r0, r0, #(0xf << 20) mcr p15, 0, r0, c1, c0, 2 isb mov r0, #0x40000000 vmsr fpexc, r0
-
@l13819506056 我实验T113中断时,只要一中断,就会产生SWI异常,很神奇,我是裸奔,根本没执行swi相关指令。一直理解不了。
-
@tripod9 我也是裸奔,没遇到这个问题。请教你裸奔,主频最高能跑到多少MHz?我这里最高就只能跑到800MHz,高于800M值,切换主频源时CPU就跑飞了。
-
@l13819506056 频率是1.008G ,是否方便提供一个简单的可以测试中断的裸机程序。我debug下,现在我实验后发现总是产生swi异常,不知哪里在触发。
-
正在打算入坑, 不知能否逃过此劫.
-
@musich 这些坑都已经解决掉了。
-
@l13819506056 你好,这段代码加在启动文件的哪个位置啊
Copyright © 2024 深圳全志在线有限公司 粤ICP备2021084185号 粤公网安备44030502007680号