From b032dff1616fe64a4dfec63e593f0fac634ef3ab Mon Sep 17 00:00:00 2001 From: zhangjun <2281979437@qq.com> Date: Sun, 30 Jul 2017 19:46:28 +0800 Subject: [PATCH] fix bug in rt_hw_context_switch_interrupt_do save sp to old thread clear rt_thread_switch_interrupt_flag always enable interrupt after rt_hw_context_switch judeg the type of interrupt in trap_entry, then call handler(Machine timer interrupt of Machine external interrupt) --- bsp/risc-v/applications/applications.c | 9 +- bsp/risc-v/drivers/board.c | 14 +-- bsp/risc-v/drivers/led.c | 157 ++++++++++++------------- libcpu/risc-v/e310/context_gcc.S | 27 ++++- libcpu/risc-v/e310/init.c | 20 ---- libcpu/risc-v/e310/start_gcc.S | 37 ++++-- 6 files changed, 134 insertions(+), 130 deletions(-) diff --git a/bsp/risc-v/applications/applications.c b/bsp/risc-v/applications/applications.c index c26b4903d..bba2b5805 100644 --- a/bsp/risc-v/applications/applications.c +++ b/bsp/risc-v/applications/applications.c @@ -15,17 +15,16 @@ static void led_thread_entry(void* parameter) unsigned int count=0; rt_hw_led_init(); - rt_kprintf("core freq at %d Hz\n", get_cpu_freq()); while (1) { /* led1 on */ #ifndef RT_USING_FINSH /* rt_kprintf("led on, count : %d\r\n",count);*/ #endif + rt_kprintf("core freq at %d Hz\n", get_cpu_freq()); count++; rt_thread_delay( RT_TIMER_TICK_PER_SECOND/2 ); /* sleep 0.5 second and switch to other thread */ - while(1); - rt_hw_led_on(0); +/* rt_hw_led_on(0);*/ /* led1 off */ #ifndef RT_USING_FINSH @@ -33,10 +32,10 @@ static void led_thread_entry(void* parameter) #endif rt_hw_led_off(0); - rt_thread_delay( RT_TIMER_TICK_PER_SECOND*2); +/* rt_thread_delay( RT_TIMER_TICK_PER_SECOND*2);*/ } } -static rt_uint8_t led_stack[ 2048 ]; +static rt_uint8_t led_stack[ 1024]; static struct rt_thread led_thread; void rt_application_init() { diff --git a/bsp/risc-v/drivers/board.c b/bsp/risc-v/drivers/board.c index da324a83b..3915d4bac 100644 --- a/bsp/risc-v/drivers/board.c +++ b/bsp/risc-v/drivers/board.c @@ -14,11 +14,6 @@ static struct mem_desc hw_mem_desc[] = }; #endif -static void rt_systick_handler(int vector, void *param) -{ - rt_tick_increase(); - return; -} #include static void rt_hw_timer_init(void) { @@ -26,11 +21,12 @@ static void rt_hw_timer_init(void) GPIO_REG(GPIO_OUTPUT_EN) |= ((0x1<< RED_LED_OFFSET)| (0x1<< GREEN_LED_OFFSET) | (0x1 << BLUE_LED_OFFSET)) ; GPIO_REG(GPIO_OUTPUT_VAL) |= (0x1 << BLUE_LED_OFFSET) ; GPIO_REG(GPIO_OUTPUT_VAL) &= ~((0x1<< RED_LED_OFFSET) | (0x1<< GREEN_LED_OFFSET)) ; - rt_hw_interrupt_enable(1); - - CLINT_REG(CLINT_MTIME) = 0x0; - CLINT_REG(CLINT_MTIMECMP) = 0x10000; + +/* enable timer interrupt*/ + set_csr(mie, MIP_MTIP); volatile uint64_t * mtimecmp = (uint64_t*) (CLINT_CTRL_ADDR + CLINT_MTIMECMP); + CLINT_REG(CLINT_MTIME) = 0x0; +/* CLINT_REG(CLINT_MTIMECMP) = 0x10000;*/ *mtimecmp = 0x20000; return; } diff --git a/bsp/risc-v/drivers/led.c b/bsp/risc-v/drivers/led.c index 900bb40f7..6aa3ddcd4 100644 --- a/bsp/risc-v/drivers/led.c +++ b/bsp/risc-v/drivers/led.c @@ -75,87 +75,82 @@ void rt_hw_led_on(int led) { /* - // Make sure the HFROSC is on before the next line: - PRCI_REG(PRCI_HFROSCCFG) |= ROSC_EN(1); - // Run off 16 MHz Crystal for accuracy. Note that the - // first line is - PRCI_REG(PRCI_PLLCFG) = (PLL_REFSEL(1) | PLL_BYPASS(1)); - PRCI_REG(PRCI_PLLCFG) |= (PLL_SEL(1)); - // Turn off HFROSC to save power - PRCI_REG(PRCI_HFROSCCFG) &= ~(ROSC_EN(1)); - */ - - - // Wait a bit to avoid corruption on the UART. - // (In some cases, switching to the IOF can lead - // to output glitches, so need to let the UART - // reciever time out and resynchronize to the real - // start of the stream. - volatile int i=0; - while(i < 10000){i++;} - - _puts(sifive_msg); - //_puts("Config String:\n\r"); - //_puts(*((const char **) 0x100C)); - //_puts("\n\r"); - _puts(led_msg); - uint16_t r=0xFF; - uint16_t g=0; - uint16_t b=0; - char c = 0; - - // Set up RGB PWM - - /* - PWM1_REG(PWM_CFG) = 0; - // To balance the power consumption, make one left, one right, and one center aligned. - PWM1_REG(PWM_CFG) = (PWM_CFG_ENALWAYS) | (PWM_CFG_CMP2CENTER); - PWM1_REG(PWM_COUNT) = 0; - - // Period is approximately 244 Hz - // the LEDs are intentionally left somewhat dim, - // as the full brightness can be painful to look at. - PWM1_REG(PWM_CMP0) = 0; - */ - - - while(1){ - - if(r > 0 && b == 0){ - r--; - g++; - } - if(g > 0 && r == 0){ - g--; - b++; - } - if(b > 0 && g == 0){ - r++; - b--; - } - - uint32_t G = g; - uint32_t R = r; - uint32_t B = b; - - PWM1_REG(PWM_CMP1) = G << 4; // PWM is low on the left, GPIO is low on the left side, LED is ON on the left. - PWM1_REG(PWM_CMP2) = (B << 1) << 4; // PWM is high on the middle, GPIO is low in the middle, LED is ON in the middle. - PWM1_REG(PWM_CMP3) = 0xFFFF - (R << 4); // PWM is low on the left, GPIO is low on the right, LED is on on the right. - - // Check for user input - if (c == 0){ - if (_getc(&c) != 0){ - _putc(c); - _puts("\n\r"); - - if ((c == 'y') || (c == 'Y')){ - _puts("PASS\n\r"); - } else{ - _puts("FAIL\n\r"); - } - } - } - } + // Make sure the HFROSC is on before the next line: + PRCI_REG(PRCI_HFROSCCFG) |= ROSC_EN(1); + // Run off 16 MHz Crystal for accuracy. Note that the + // first line is + PRCI_REG(PRCI_PLLCFG) = (PLL_REFSEL(1) | PLL_BYPASS(1)); + PRCI_REG(PRCI_PLLCFG) |= (PLL_SEL(1)); + // Turn off HFROSC to save power + PRCI_REG(PRCI_HFROSCCFG) &= ~(ROSC_EN(1)); + */ + + + // Wait a bit to avoid corruption on the UART. + // (In some cases, switching to the IOF can lead + // to output glitches, so need to let the UART + // reciever time out and resynchronize to the real + // start of the stream. + volatile int i=0; + while(i < 10000){i++;} + + _puts(sifive_msg); + //_puts("Config String:\n\r"); + //_puts(*((const char **) 0x100C)); + //_puts("\n\r"); + _puts(led_msg); + uint16_t r=0xFF; + uint16_t g=0; + uint16_t b=0; + char c = 0; + + // Set up RGB PWM + + /* + PWM1_REG(PWM_CFG) = 0; + // To balance the power consumption, make one left, one right, and one center aligned. + PWM1_REG(PWM_CFG) = (PWM_CFG_ENALWAYS) | (PWM_CFG_CMP2CENTER); + PWM1_REG(PWM_COUNT) = 0; + + // Period is approximately 244 Hz + // the LEDs are intentionally left somewhat dim, + // as the full brightness can be painful to look at. + PWM1_REG(PWM_CMP0) = 0; + */ + if(r > 0 && b == 0){ + r--; + g++; + } + if(g > 0 && r == 0){ + g--; + b++; + } + if(b > 0 && g == 0){ + r++; + b--; + } + + uint32_t G = g; + uint32_t R = r; + uint32_t B = b; + + PWM1_REG(PWM_CMP1) = G << 4; // PWM is low on the left, GPIO is low on the left side, LED is ON on the left. + PWM1_REG(PWM_CMP2) = (B << 1) << 4; // PWM is high on the middle, GPIO is low in the middle, LED is ON in the middle. + PWM1_REG(PWM_CMP3) = 0xFFFF - (R << 4); // PWM is low on the left, GPIO is low on the right, LED is on on the right. + + // Check for user input + if (c == 0){ + if (_getc(&c) != 0){ + _putc(c); + _puts("\n\r"); + + if ((c == 'y') || (c == 'Y')){ + _puts("PASS\n\r"); + } else{ + _puts("FAIL\n\r"); + } + } + } return; } void rt_hw_led_off(int led) diff --git a/libcpu/risc-v/e310/context_gcc.S b/libcpu/risc-v/e310/context_gcc.S index ea2e205e4..eee3cc128 100644 --- a/libcpu/risc-v/e310/context_gcc.S +++ b/libcpu/risc-v/e310/context_gcc.S @@ -32,9 +32,21 @@ rt_hw_interrupt_disable: addi sp, sp, -12 sw a5, (sp) + li a5, 0x800 csrr a0, mie - li a5, MIP_MEIP|MIP_MTIP|MIP_MSIP -/* csrrc a5, mstatus, MSTATUS_MIE*/ + blt a0, a5, 1f +/* interrupt is enable before disable it*/ + addi a0, a0, 1 + + li a5, 0x1 + addi a5, a5, -2048 + csrrc a5, mie, a5 +/* csrrc a5, mie, 128*/ + j 2f +/* interrupt is disabled before disable it*/ +1: + li a0, 0 +2: lw a5, (sp) addi sp, sp, 12 ret @@ -46,9 +58,12 @@ rt_hw_interrupt_disable: rt_hw_interrupt_enable: addi sp, sp, -12 sw a5, (sp) - li a5, MIP_MEIP|MIP_MTIP|MIP_MSIP + beqz a0, 1f + li a5, 0x1 + addi a5, a5, -2048 csrrs a5, mie, a5 -/* csrrsi a5, mstatus, MSTATUS_MIE*/ +/* csrrs a5, mie, 128*/ +1: lw a5, (sp) addi sp, sp, 12 ret @@ -98,8 +113,8 @@ rt_hw_context_switch: *Remain in M-mode after mret *enable interrupt in M-mode */ - li t0, MSTATUS_MPIE|MSTATUS_MPP - csrs mstatus, t0 + li t0, 136 + csrrs t0, mstatus, t0 LOAD sp, (a1) LOAD x30, 1*REGBYTES(sp) diff --git a/libcpu/risc-v/e310/init.c b/libcpu/risc-v/e310/init.c index 3a2b39614..a8db52980 100644 --- a/libcpu/risc-v/e310/init.c +++ b/libcpu/risc-v/e310/init.c @@ -187,26 +187,6 @@ extern void handle_m_ext_interrupt(); extern void handle_m_time_interrupt(); #endif -uintptr_t handle_trap(uintptr_t mcause, uintptr_t epc) -{ - if (0){ -#ifdef USE_PLIC - // External Machine-Level interrupt from PLIC - } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_EXT)) { - handle_m_ext_interrupt(); -#endif -#ifdef USE_M_TIME - // External Machine-Level interrupt from PLIC - } else if ((mcause & MCAUSE_INT) && ((mcause & MCAUSE_CAUSE) == IRQ_M_TIMER)){ - handle_m_time_interrupt(); -#endif - } - else { - write(1, "trap\n", 5); - _exit(1 + mcause); - } - return epc; -} void _init() { diff --git a/libcpu/risc-v/e310/start_gcc.S b/libcpu/risc-v/e310/start_gcc.S index b986f3f5e..e7aaddcae 100644 --- a/libcpu/risc-v/e310/start_gcc.S +++ b/libcpu/risc-v/e310/start_gcc.S @@ -36,7 +36,10 @@ _start: la gp, __global_pointer$ .option pop la sp, _sp - csrrsi a5, mstatus, 0 +/* + *disable all interrupt at startup + */ + csrrc a5, mstatus, 0xb #if defined(ENABLE_SMP) smp_pause(t0, t1) @@ -69,6 +72,7 @@ _start: la a0, __libc_fini_array call atexit call __libc_init_array + /*call _init directly in rt-thread*/ call _init #ifndef __riscv_float_abi_soft @@ -175,17 +179,31 @@ trap_entry: call rt_interrupt_enter + csrr a0, mcause + lui a5, 0x80000 + not a5, a5 + and a5, a5, a0 + li a4, 11 + mv s1, a1 + /*Machine external interrupt*/ + bne a5, a4, 1f call rt_hw_trap_irq - call handle_m_time_interrupt +1: + /*Machine software interrupt*/ + li a4, 7 + bne a5, a4, 2f + call rt_systick_handler +2: call rt_interrupt_leave - la a0, rt_thread_switch_interrupt_flag - lw a1, (a0) + # Remain in M-mode after mret + li t0, 136 + csrrs t0, mstatus, t0 + + la a0, rt_thread_switch_interrupt_flag + lw a1, (a0) bnez a1, rt_hw_context_switch_interrupt_do - # Remain in M-mode after mret - li t0, MSTATUS_MPP - csrs mstatus, t0 LOAD x30, 1*REGBYTES(sp) LOAD x31, 2*REGBYTES(sp) @@ -225,12 +243,13 @@ trap_entry: mret rt_hw_context_switch_interrupt_do: - + /*clear rt_thread_switch_interrupt_flag*/ la a0, rt_thread_switch_interrupt_flag - lw a5, (a0) li a5, 0 sw a5, (a0) + LOAD a0, rt_interrupt_from_thread + STORE sp, (a0) LOAD a0, rt_interrupt_to_thread LOAD sp, (a0) LOAD x30, 1*REGBYTES(sp) -- GitLab