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)
This commit is contained in:
zhangjun 2017-07-30 19:46:28 +08:00
parent 2d56a27c20
commit b032dff161
6 changed files with 132 additions and 128 deletions

View File

@ -15,17 +15,16 @@ static void led_thread_entry(void* parameter)
unsigned int count=0; unsigned int count=0;
rt_hw_led_init(); rt_hw_led_init();
rt_kprintf("core freq at %d Hz\n", get_cpu_freq());
while (1) while (1)
{ {
/* led1 on */ /* led1 on */
#ifndef RT_USING_FINSH #ifndef RT_USING_FINSH
/* rt_kprintf("led on, count : %d\r\n",count);*/ /* rt_kprintf("led on, count : %d\r\n",count);*/
#endif #endif
rt_kprintf("core freq at %d Hz\n", get_cpu_freq());
count++; count++;
rt_thread_delay( RT_TIMER_TICK_PER_SECOND/2 ); /* sleep 0.5 second and switch to other thread */ 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 */ /* led1 off */
#ifndef RT_USING_FINSH #ifndef RT_USING_FINSH
@ -33,10 +32,10 @@ static void led_thread_entry(void* parameter)
#endif #endif
rt_hw_led_off(0); 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; static struct rt_thread led_thread;
void rt_application_init() void rt_application_init()
{ {

View File

@ -14,11 +14,6 @@ static struct mem_desc hw_mem_desc[] =
}; };
#endif #endif
static void rt_systick_handler(int vector, void *param)
{
rt_tick_increase();
return;
}
#include <encoding.h> #include <encoding.h>
static void rt_hw_timer_init(void) 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_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 << BLUE_LED_OFFSET) ;
GPIO_REG(GPIO_OUTPUT_VAL) &= ~((0x1<< RED_LED_OFFSET) | (0x1<< GREEN_LED_OFFSET)) ; GPIO_REG(GPIO_OUTPUT_VAL) &= ~((0x1<< RED_LED_OFFSET) | (0x1<< GREEN_LED_OFFSET)) ;
rt_hw_interrupt_enable(1);
/* enable timer interrupt*/
CLINT_REG(CLINT_MTIME) = 0x0; set_csr(mie, MIP_MTIP);
CLINT_REG(CLINT_MTIMECMP) = 0x10000;
volatile uint64_t * mtimecmp = (uint64_t*) (CLINT_CTRL_ADDR + CLINT_MTIMECMP); volatile uint64_t * mtimecmp = (uint64_t*) (CLINT_CTRL_ADDR + CLINT_MTIMECMP);
CLINT_REG(CLINT_MTIME) = 0x0;
/* CLINT_REG(CLINT_MTIMECMP) = 0x10000;*/
*mtimecmp = 0x20000; *mtimecmp = 0x20000;
return; return;
} }

View File

@ -75,87 +75,82 @@ void rt_hw_led_on(int led)
{ {
/* /*
// Make sure the HFROSC is on before the next line: // Make sure the HFROSC is on before the next line:
PRCI_REG(PRCI_HFROSCCFG) |= ROSC_EN(1); PRCI_REG(PRCI_HFROSCCFG) |= ROSC_EN(1);
// Run off 16 MHz Crystal for accuracy. Note that the // Run off 16 MHz Crystal for accuracy. Note that the
// first line is // first line is
PRCI_REG(PRCI_PLLCFG) = (PLL_REFSEL(1) | PLL_BYPASS(1)); PRCI_REG(PRCI_PLLCFG) = (PLL_REFSEL(1) | PLL_BYPASS(1));
PRCI_REG(PRCI_PLLCFG) |= (PLL_SEL(1)); PRCI_REG(PRCI_PLLCFG) |= (PLL_SEL(1));
// Turn off HFROSC to save power // Turn off HFROSC to save power
PRCI_REG(PRCI_HFROSCCFG) &= ~(ROSC_EN(1)); 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){ // Wait a bit to avoid corruption on the UART.
// (In some cases, switching to the IOF can lead
if(r > 0 && b == 0){ // to output glitches, so need to let the UART
r--; // reciever time out and resynchronize to the real
g++; // start of the stream.
} volatile int i=0;
if(g > 0 && r == 0){ while(i < 10000){i++;}
g--;
b++; _puts(sifive_msg);
} //_puts("Config String:\n\r");
if(b > 0 && g == 0){ //_puts(*((const char **) 0x100C));
r++; //_puts("\n\r");
b--; _puts(led_msg);
} uint16_t r=0xFF;
uint16_t g=0;
uint32_t G = g; uint16_t b=0;
uint32_t R = r; char c = 0;
uint32_t B = b;
// Set up RGB PWM
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. PWM1_REG(PWM_CFG) = 0;
// To balance the power consumption, make one left, one right, and one center aligned.
// Check for user input PWM1_REG(PWM_CFG) = (PWM_CFG_ENALWAYS) | (PWM_CFG_CMP2CENTER);
if (c == 0){ PWM1_REG(PWM_COUNT) = 0;
if (_getc(&c) != 0){
_putc(c); // Period is approximately 244 Hz
_puts("\n\r"); // the LEDs are intentionally left somewhat dim,
// as the full brightness can be painful to look at.
if ((c == 'y') || (c == 'Y')){ PWM1_REG(PWM_CMP0) = 0;
_puts("PASS\n\r"); */
} else{ if(r > 0 && b == 0){
_puts("FAIL\n\r"); 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; return;
} }
void rt_hw_led_off(int led) void rt_hw_led_off(int led)

View File

@ -32,9 +32,21 @@
rt_hw_interrupt_disable: rt_hw_interrupt_disable:
addi sp, sp, -12 addi sp, sp, -12
sw a5, (sp) sw a5, (sp)
li a5, 0x800
csrr a0, mie csrr a0, mie
li a5, MIP_MEIP|MIP_MTIP|MIP_MSIP blt a0, a5, 1f
/* csrrc a5, mstatus, MSTATUS_MIE*/ /* 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) lw a5, (sp)
addi sp, sp, 12 addi sp, sp, 12
ret ret
@ -46,9 +58,12 @@ rt_hw_interrupt_disable:
rt_hw_interrupt_enable: rt_hw_interrupt_enable:
addi sp, sp, -12 addi sp, sp, -12
sw a5, (sp) 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 csrrs a5, mie, a5
/* csrrsi a5, mstatus, MSTATUS_MIE*/ /* csrrs a5, mie, 128*/
1:
lw a5, (sp) lw a5, (sp)
addi sp, sp, 12 addi sp, sp, 12
ret ret
@ -98,8 +113,8 @@ rt_hw_context_switch:
*Remain in M-mode after mret *Remain in M-mode after mret
*enable interrupt in M-mode *enable interrupt in M-mode
*/ */
li t0, MSTATUS_MPIE|MSTATUS_MPP li t0, 136
csrs mstatus, t0 csrrs t0, mstatus, t0
LOAD sp, (a1) LOAD sp, (a1)
LOAD x30, 1*REGBYTES(sp) LOAD x30, 1*REGBYTES(sp)

View File

@ -187,26 +187,6 @@ extern void handle_m_ext_interrupt();
extern void handle_m_time_interrupt(); extern void handle_m_time_interrupt();
#endif #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() void _init()
{ {

View File

@ -36,7 +36,10 @@ _start:
la gp, __global_pointer$ la gp, __global_pointer$
.option pop .option pop
la sp, _sp la sp, _sp
csrrsi a5, mstatus, 0 /*
*disable all interrupt at startup
*/
csrrc a5, mstatus, 0xb
#if defined(ENABLE_SMP) #if defined(ENABLE_SMP)
smp_pause(t0, t1) smp_pause(t0, t1)
@ -69,6 +72,7 @@ _start:
la a0, __libc_fini_array la a0, __libc_fini_array
call atexit call atexit
call __libc_init_array call __libc_init_array
/*call _init directly in rt-thread*/
call _init call _init
#ifndef __riscv_float_abi_soft #ifndef __riscv_float_abi_soft
@ -175,17 +179,31 @@ trap_entry:
call rt_interrupt_enter 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 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 call rt_interrupt_leave
la a0, rt_thread_switch_interrupt_flag # Remain in M-mode after mret
lw a1, (a0) 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 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 x30, 1*REGBYTES(sp)
LOAD x31, 2*REGBYTES(sp) LOAD x31, 2*REGBYTES(sp)
@ -225,12 +243,13 @@ trap_entry:
mret mret
rt_hw_context_switch_interrupt_do: rt_hw_context_switch_interrupt_do:
/*clear rt_thread_switch_interrupt_flag*/
la a0, rt_thread_switch_interrupt_flag la a0, rt_thread_switch_interrupt_flag
lw a5, (a0)
li a5, 0 li a5, 0
sw a5, (a0) sw a5, (a0)
LOAD a0, rt_interrupt_from_thread
STORE sp, (a0)
LOAD a0, rt_interrupt_to_thread LOAD a0, rt_interrupt_to_thread
LOAD sp, (a0) LOAD sp, (a0)
LOAD x30, 1*REGBYTES(sp) LOAD x30, 1*REGBYTES(sp)