diff --git a/bsp/ls1cdev/libraries/ls1c_gpio.c b/bsp/ls1cdev/libraries/ls1c_gpio.c index 11d696d48e..d0f0633b4e 100644 --- a/bsp/ls1cdev/libraries/ls1c_gpio.c +++ b/bsp/ls1cdev/libraries/ls1c_gpio.c @@ -204,4 +204,63 @@ unsigned int gpio_get(unsigned int gpio) } +/** + * 设置中断类型 + * @gpio gpio引脚 + * @type 触发中断的条件。高电平触发、低电平触发、上升沿触发 or 下降沿触发 + */ +void gpio_set_irq_type(unsigned int gpio, gpio_irq_type_t type) +{ + volatile unsigned int *int_pol; // 中断极性选择寄存器 + volatile unsigned int *int_edge; // 中断边沿选择寄存器 + unsigned int port = GPIO_GET_PORT(gpio); + unsigned int pin = GPIO_GET_PIN(gpio); + + // 获取寄存器地址 + switch (port) + { + case 0: // GPIO[31:0] + int_pol = (volatile unsigned int *)LS1C_INT2_POL; + int_edge = (volatile unsigned int *)LS1C_INT2_EDGE; + break; + + case 1: // GPIO[63:32] + int_pol = (volatile unsigned int *)LS1C_INT3_POL; + int_edge = (volatile unsigned int *)LS1C_INT3_EDGE; + break; + + case 2: // GPIO[95:64] + int_pol = (volatile unsigned int *)LS1C_INT4_POL; + int_edge = (volatile unsigned int *)LS1C_INT4_EDGE; + break; + } + + // 设置中断类型 + switch (type) + { + case IRQ_TYPE_EDGE_RISING: + *int_pol |= (1 << pin); + *int_edge |= (1 << pin); + break; + + case IRQ_TYPE_EDGE_FALLING: + *int_pol &= ~(1 << pin); + *int_edge |= (1 << pin); + break; + + case IRQ_TYPE_LEVEL_HIGH: + *int_pol |= (1 << pin); + *int_edge &= ~(1 << pin); + break; + + case IRQ_TYPE_LEVEL_LOW: + *int_pol &= ~(1 << pin); + *int_edge &= ~(1 << pin); + break; + } + + return ; +} + + diff --git a/bsp/ls1cdev/libraries/ls1c_gpio.h b/bsp/ls1cdev/libraries/ls1c_gpio.h index d20085cf4a..1609684bd3 100644 --- a/bsp/ls1cdev/libraries/ls1c_gpio.h +++ b/bsp/ls1cdev/libraries/ls1c_gpio.h @@ -29,6 +29,19 @@ typedef enum{ }gpio_level_t; +typedef enum { + // 上升沿触发 + IRQ_TYPE_EDGE_RISING = 0x00000001, + // 下降沿触发 + IRQ_TYPE_EDGE_FALLING = 0x00000002, + IRQ_TYPE_EDGE_BOTH = (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING), + // 高电平触发 + IRQ_TYPE_LEVEL_HIGH = 0x00000004, + // 低电平触发 + IRQ_TYPE_LEVEL_LOW = 0x00000008, + IRQ_TYPE_LEVEL_MASK = (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH), +}gpio_irq_type_t; + /* @@ -73,6 +86,13 @@ unsigned int gpio_get(unsigned int gpio); +/** + * 设置中断类型 + * @gpio gpio引脚 + * @type 触发中断的条件。高电平触发、低电平触发、上升沿触发 or 下降沿触发 + */ +void gpio_set_irq_type(unsigned int gpio, gpio_irq_type_t type); + #endif diff --git a/bsp/ls1cdev/libraries/ls1c_public.c b/bsp/ls1cdev/libraries/ls1c_public.c index 652fd2e219..84518f0bd0 100644 --- a/bsp/ls1cdev/libraries/ls1c_public.c +++ b/bsp/ls1cdev/libraries/ls1c_public.c @@ -77,3 +77,41 @@ unsigned int reg_read_32(volatile unsigned int *addr) +/** + * ffs - find first bit set + * @x: the word to search + * + * This is defined the same way as + * the libc and compiler builtin ffs routines, therefore + * differs in spirit from the above ffz (man ffs). + */ +int ls1c_ffs(int x) +{ + int r = 1; + + if (!x) + return 0; + if (!(x & 0xffff)) { + x >>= 16; + r += 16; + } + if (!(x & 0xff)) { + x >>= 8; + r += 8; + } + if (!(x & 0xf)) { + x >>= 4; + r += 4; + } + if (!(x & 3)) { + x >>= 2; + r += 2; + } + if (!(x & 1)) { + x >>= 1; + r += 1; + } + return r; +} + + diff --git a/bsp/ls1cdev/libraries/ls1c_public.h b/bsp/ls1cdev/libraries/ls1c_public.h index d3b410c421..3ecabeafaa 100644 --- a/bsp/ls1cdev/libraries/ls1c_public.h +++ b/bsp/ls1cdev/libraries/ls1c_public.h @@ -73,6 +73,12 @@ void reg_write_32(unsigned int data, volatile unsigned int *addr); unsigned int reg_read_32(volatile unsigned int *addr); +/** + * ffs - find first bit set + * @x: the word to search + */ +int ls1c_ffs(int x); + #endif diff --git a/bsp/ls1cdev/libraries/ls1c_regs.h b/bsp/ls1cdev/libraries/ls1c_regs.h index 22ac433fda..fb67086d34 100644 --- a/bsp/ls1cdev/libraries/ls1c_regs.h +++ b/bsp/ls1cdev/libraries/ls1c_regs.h @@ -74,13 +74,41 @@ +// 中断配置寄存器 +#define LS1C_INT0_SR (0xbfd01040) +#define LS1C_INT0_EN (0xbfd01044) +#define LS1C_INT0_SET (0xbfd01048) +#define LS1C_INT0_CLR (0xbfd0104c) +#define LS1C_INT0_POL (0xbfd01050) +#define LS1C_INT0_EDGE (0xbfd01054) +#define LS1c_INT1_SR (0xbfd01058) +#define LS1C_INT1_EN (0xbfd0105c) +#define LS1C_INT1_SET (0xbfd01060) +#define LS1C_INT1_CLR (0xbfd01064) +#define LS1C_INT1_POL (0xbfd01068) +#define LS1C_INT1_EDGE (0xbfd0106c) +#define LS1C_INT2_SR (0xbfd01070) +#define LS1C_INT2_EN (0xbfd01074) +#define LS1C_INT2_SET (0xbfd01078) +#define LS1C_INT2_CLR (0xbfd0107c) +#define LS1C_INT2_POL (0xbfd01080) +#define LS1C_INT2_EDGE (0xbfd01084) +#define LS1C_INT3_SR (0xbfd01088) +#define LS1C_INT3_EN (0xbfd0108c) +#define LS1C_INT3_SET (0xbfd01090) +#define LS1C_INT3_CLR (0xbfd01094) +#define LS1C_INT3_POL (0xbfd01098) +#define LS1C_INT3_EDGE (0xbfd0109c) - - - +#define LS1C_INT4_SR (0xbfd010a0) +#define LS1C_INT4_EN (0xbfd010a4) +#define LS1C_INT4_SET (0xbfd010a8) +#define LS1C_INT4_CLR (0xbfd010ac) +#define LS1C_INT4_POL (0xbfd010b0) +#define LS1C_INT4_EDGE (0xbfd010b4) diff --git a/bsp/ls1cdev/rtconfig.h b/bsp/ls1cdev/rtconfig.h index 8bca3ee9a0..410fd29254 100644 --- a/bsp/ls1cdev/rtconfig.h +++ b/bsp/ls1cdev/rtconfig.h @@ -6,7 +6,7 @@ // #define RT_NAME_MAX 10 // -#define RT_ALIGN_SIZE 4 +#define RT_ALIGN_SIZE 8 // // 8 // 32 @@ -14,7 +14,7 @@ // #define RT_THREAD_PRIORITY_MAX 32 // -#define RT_TICK_PER_SECOND 100 +#define RT_TICK_PER_SECOND 1000 //
#define RT_DEBUG // diff --git a/bsp/ls1cdev/rtconfig.py b/bsp/ls1cdev/rtconfig.py index e4eb2f962a..c8da0ea477 100644 --- a/bsp/ls1cdev/rtconfig.py +++ b/bsp/ls1cdev/rtconfig.py @@ -12,7 +12,8 @@ if os.getenv('RTT_CC'): if CROSS_TOOL == 'gcc': PLATFORM = 'gcc' - EXEC_PATH = '/opt/opt/gcc-4.3-ls232/bin' +# EXEC_PATH = '/opt/opt/gcc-4.3-ls232/bin' + EXEC_PATH = r'D:\mgc\embedded\codebench\bin' else: print '================ERROR===========================' print 'Not support %s yet!' % CROSS_TOOL diff --git a/libcpu/mips/loongson_1c/interrupt.c b/libcpu/mips/loongson_1c/interrupt.c index b39b579731..cc0b8e4e9c 100644 --- a/libcpu/mips/loongson_1c/interrupt.c +++ b/libcpu/mips/loongson_1c/interrupt.c @@ -18,8 +18,10 @@ #include #include #include "ls1c.h" +#include "ls1c_public.h" -#define MAX_INTR 32 + +#define MAX_INTR (LS1C_NR_IRQS) extern rt_uint32_t rt_interrupt_nest; rt_uint32_t rt_interrupt_from_thread; @@ -50,13 +52,26 @@ static void rt_hw_interrupt_handler(int vector, void *param) void rt_hw_interrupt_init(void) { rt_int32_t idx; + rt_int32_t i; + rt_uint32_t c0_status = 0; - /* pci active low */ - ls1c_hw0_icregs->int_pol = -1; //must be done here 20110802 lgnq - /* make all interrupts level triggered */ - (ls1c_hw0_icregs+0)->int_edge = 0x0000e000; - /* mask all interrupts */ - (ls1c_hw0_icregs+0)->int_clr = 0xffffffff; + // 设置协处理器0的状态寄存器SR的IM7-2,允许中断 + c0_status = read_c0_status(); + c0_status |= 0xFC00; + write_c0_status(c0_status); + + // 龙芯1c的中断分为五组 + for (i=0; i<5; i++) + { + /* disable */ + (ls1c_hw0_icregs+i)->int_en = 0x0; + /* pci active low */ + (ls1c_hw0_icregs+i)->int_pol = -1; //must be done here 20110802 lgnq + /* make all interrupts level triggered */ + (ls1c_hw0_icregs+i)->int_edge = 0x00000000; + /* mask all interrupts */ + (ls1c_hw0_icregs+i)->int_clr = 0xffffffff; + } rt_memset(irq_handle_table, 0x00, sizeof(irq_handle_table)); for (idx = 0; idx < MAX_INTR; idx ++) @@ -115,6 +130,51 @@ rt_isr_handler_t rt_hw_interrupt_install(int vector, rt_isr_handler_t handler, return old_handler; } + +/** + * 执行中断处理函数 + * @IRQn 中断号 + */ +void ls1c_do_IRQ(int IRQn) +{ + rt_isr_handler_t irq_func; + void *param; + + // 找到中断处理函数 + irq_func = irq_handle_table[IRQn].handler; + param = irq_handle_table[IRQn].param; + + // 执行中断处理函数 + irq_func(IRQn, param); + +#ifdef RT_USING_INTERRUPT_INFO + irq_handle_table[IRQn].counter++; +#endif + + return ; +} + + +void ls1c_irq_dispatch(int n) +{ + rt_uint32_t intstatus, irq; + + /* Receive interrupt signal, compute the irq */ + intstatus = (ls1c_hw0_icregs+n)->int_isr & (ls1c_hw0_icregs+n)->int_en; + if (0 == intstatus) + return ; + + // 执行中断处理函数 + irq = ls1c_ffs(intstatus) - 1; + ls1c_do_IRQ((n<<5) + irq); + + /* ack interrupt */ + (ls1c_hw0_icregs+n)->int_clr |= (1 << irq); + + return ; +} + + void rt_interrupt_dispatch(void *ptreg) { int irq; @@ -139,50 +199,25 @@ void rt_interrupt_dispatch(void *ptreg) { rt_hw_timer_handler(); } - - if (pending_im & CAUSEF_IP2) + else if (pending_im & CAUSEF_IP2) { - /* the hardware interrupt */ - status = ls1c_hw0_icregs->int_isr; - if (!status) - return; - - for (irq = MAX_INTR; irq > 0; --irq) - { - if ((status & (1 << irq))) - { - status &= ~(1 << irq); - - irq_func = irq_handle_table[irq].handler; - param = irq_handle_table[irq].param; - - /* do interrupt */ - irq_func(irq, param); - -#ifdef RT_USING_INTERRUPT_INFO - irq_handle_table[irq].counter++; -#endif /* RT_USING_INTERRUPT_INFO */ - - /* ack interrupt */ - ls1c_hw0_icregs->int_clr |= (1 << irq); - } - } + ls1c_irq_dispatch(0); } else if (pending_im & CAUSEF_IP3) { - rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__); + ls1c_irq_dispatch(1); } else if (pending_im & CAUSEF_IP4) { - rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__); + ls1c_irq_dispatch(2); } else if (pending_im & CAUSEF_IP5) { - rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__); + ls1c_irq_dispatch(3); } else if (pending_im & CAUSEF_IP6) { - rt_kprintf("%s %d\r\n", __FUNCTION__, __LINE__); + ls1c_irq_dispatch(4); } } diff --git a/libcpu/mips/loongson_1c/ls1c.h b/libcpu/mips/loongson_1c/ls1c.h index 8b50da5ac9..a203810c37 100644 --- a/libcpu/mips/loongson_1c/ls1c.h +++ b/libcpu/mips/loongson_1c/ls1c.h @@ -20,7 +20,7 @@ #define LS1C_ACPI_IRQ 0 #define LS1C_HPET_IRQ 1 -#define LS1C_UART0_IRQ 2 +//#define LS1C_UART0_IRQ 3 // linux中是3,v1.4版本的1c手册中是2,暂屏蔽,待确认 #define LS1C_UART1_IRQ 4 #define LS1C_UART2_IRQ 5 #define LS1C_CAN0_IRQ 6 @@ -32,41 +32,55 @@ #define LS1C_KB_IRQ 12 #define LS1C_DMA0_IRQ 13 #define LS1C_DMA1_IRQ 14 -#define LS1C_NAND_IRQ 15 -#define LS1C_I2C0_IRQ 16 -#define LS1C_I2C1_IRQ 17 -#define LS1C_PWM0_IRQ 18 -#define LS1C_PWM1_IRQ 19 -#define LS1C_PWM2_IRQ 20 -#define LS1C_PWM3_IRQ 21 -#define LS1C_LPC_IRQ 22 -#define LS1C_EHCI_IRQ 32 -#define LS1C_OHCI_IRQ 33 -#define LS1C_GMAC1_IRQ 34 -#define LS1C_GMAC2_IRQ 35 -#define LS1C_SATA_IRQ 36 -#define LS1C_GPU_IRQ 37 -#define LS1C_PCI_INTA_IRQ 38 -#define LS1C_PCI_INTB_IRQ 39 -#define LS1C_PCI_INTC_IRQ 40 -#define LS1C_PCI_INTD_IRQ 41 +#define LS1C_DMA2_IRQ 15 +#define LS1C_NAND_IRQ 16 +#define LS1C_PWM0_IRQ 17 +#define LS1C_PWM1_IRQ 18 +#define LS1C_PWM2_IRQ 19 +#define LS1C_PWM3_IRQ 20 +#define LS1C_RTC_INT0_IRQ 21 +#define LS1C_RTC_INT1_IRQ 22 +#define LS1C_RTC_INT2_IRQ 23 +#define LS1C_UART3_IRQ 29 +#define LS1C_ADC_IRQ 30 +#define LS1C_SDIO_IRQ 31 + + +#define LS1C_EHCI_IRQ (32+0) +#define LS1C_OHCI_IRQ (32+1) +#define LS1C_OTG_IRQ (32+2) +#define LS1C_MAC_IRQ (32+3) +#define LS1C_CAM_IRQ (32+4) +#define LS1C_UART4_IRQ (32+5) +#define LS1C_UART5_IRQ (32+6) +#define LS1C_UART6_IRQ (32+7) +#define LS1C_UART7_IRQ (32+8) +#define LS1C_UART8_IRQ (32+9) +#define LS1C_UART9_IRQ (32+13) +#define LS1C_UART10_IRQ (32+14) +#define LS1C_UART11_IRQ (32+15) +#define LS1C_I2C2_IRQ (32+17) +#define LS1C_I2C1_IRQ (32+18) +#define LS1C_I2C0_IRQ (32+19) + #define LS1C_GPIO_IRQ 64 #define LS1C_GPIO_FIRST_IRQ 64 #define LS1C_GPIO_IRQ_COUNT 96 #define LS1C_GPIO_LAST_IRQ (LS1C_GPIO_FIRST_IRQ + LS1C_GPIO_IRQ_COUNT-1) -#define INT_PCI_INTA (1<<6) -#define INT_PCI_INTB (1<<7) -#define INT_PCI_INTC (1<<8) -#define INT_PCI_INTD (1<<9) #define LS1C_LAST_IRQ 159 -#define MIPS_CPU_TIMER_IRQ 167 #define LS1C_INTREG_BASE 0xbfd01040 -#define LS1C_DMA_IRQ_BASE 168 -#define LS1C_DMA_IRQ_COUNT 16 +// 龙芯1c的中断分为五组,每组32个 +#define LS1C_NR_IRQS (32*5) + + +// GPIO编号和中断号之间的互相转换 +#define LS1C_GPIO_TO_IRQ(GPIOn) (LS1C_GPIO_FIRST_IRQ + (GPIOn)) +#define LS1C_IRQ_TO_GPIO(IRQn) ((IRQn) - LS1C_GPIO_FIRST_IRQ) + struct ls1c_intc_regs {