ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Воскресенье
24 ноября
1077025 Топик полностью
klen (14.02.2021 04:56, просмотров: 438) ответил evgeniy1294 на Понятно чем. Там два (в какой-то степени три) способа обработки прерываний: отдельный обработчик на прерывание, общий обработчик на прерывания, третьим вариантом можно считать возможность цепочечной обработки прерываний через CSR_JALMNXTI. Дополнительно необходимо сохранить текущий контекст. В примерах от gigadevice используется 3-й вариант, вполне может быть за 50 тактов.
я примерно также сделал как у GigaDevice исходниках, только я пока не понял как отдельные заводить, еще не до конца разобрался - потроха у riscv как у большого процессора. в Вашем варианте 

судя по всему сохранние контекста уже пользователь прерывания делает, тоесть ручками в обработчике и на этом можно типо поэкономить, так?

void trap_handler( const trap_context_t*);

  constexpr size_t context_size = sizeof(context_t) ;

  constexpr size_t irq_context_ext_regs = 3 ;  // mepc msubm mcause
  constexpr size_t trap_context_ext_regs = 3 ; // mepc msubm mstatus

  constexpr size_t irq_context_size = sizeof(context_t) + irq_context_ext_regs ;
  constexpr size_t trap_context_size = sizeof(context_t) + trap_context_ext_regs ;

  __inline_static__ void     global_interrupt_disable(){ asm volatile ("csrc %0, %1" :: "I"(CSR_MSTATUS), "I"(MSTATUS_MIE) :); }
  __inline_static__ void     global_interrupt_enable() { asm volatile ("csrs %0, %1" :: "I"(CSR_MSTATUS), "I"(MSTATUS_MIE) :); }
  __inline_static__ uint32_t mcause() { uint32_t val ; __asm__ volatile ("csrr %0, mcause" : "=r"(val)); return val ; }

  // сохранение контекста
  __inline_static__ void save_context()
  {

    // сохранение регистров cpu
    #ifdef __riscv_flen
       #if (__riscv_flen==64 )
         __asm__ volatile ("addi sp, sp, -20*%0 - 20*%1" :: "I"(sizeof_reg), "I"(FPsizeof_reg) ;
       #endif
    #else
         __asm__ volatile ("addi sp, sp, -20*%0   \n"  // смещение указателя стека (размещение на стеке)
    #endif
                           "sw x1,  0*%0  (sp) \n"  // адрес возврата
                           "sw x4,  1*%0  (sp) \n"  // tp
                           "sw x5,  2*%0  (sp) \n"  // t0
                           "sw x6,  3*%0  (sp) \n"  // t1
                           "sw x7,  4*%0  (sp) \n"  // t2
                           "sw x10, 5*%0  (sp) \n"  // a0
                           "sw x11, 6*%0  (sp) \n"  // a1
                           "sw x12, 7*%0  (sp) \n"  // a2
                           "sw x13, 8*%0  (sp) \n"  // a3
                           "sw x14, 9*%0  (sp) \n"  // a4
                           "sw x15, 10*%0 (sp) \n" :: "I"(sizeof_reg)) ;  //a5

    #ifndef __riscv_32e
         __asm__ volatile ("sw x16, 11*%0 (sp) \n"  // a6
                           "sw x17, 12*%0 (sp) \n"  // a7
                           "sw x28, 13*%0 (sp) \n"  // t3
                           "sw x29, 14*%0 (sp) \n"  // t4
                           "sw x30, 15*%0 (sp) \n"  // t5
                           "sw x31, 16*%0 (sp)" :: "I"(sizeof_reg)) ; // t6
    #endif

    // сохранение регистров fpu
    #ifdef __riscv_flen
       #if (__riscv_flen == 64)
           __asm__ volatile (F"sw f0,  (20*%0 +  0*%1)(sp) \n"
                             F"sw f1,  (20*%0 +  1*%1)(sp) \n"
                             F"sw f2,  (20*%0 +  2*%1)(sp) \n"
                             F"sw f3,  (20*%0 +  3*%1)(sp) \n"
                             F"sw f4,  (20*%0 +  4*%1)(sp) \n"
                             F"sw f5,  (20*%0 +  5*%1)(sp) \n"
                             F"sw f6,  (20*%0 +  6*%1)(sp) \n"
                             F"sw f7,  (20*%0 +  7*%1)(sp) \n"
                             F"sw f10, (20*%0 +  8*%1)(sp) \n"
                             F"sw f11, (20*%0 +  9*%1)(sp) \n"
                             F"sw f12, (20*%0 + 10*%1)(sp) \n"
                             F"sw f13, (20*%0 + 11*%1)(sp) \n"
                             F"sw f14, (20*%0 + 12*%1)(sp) \n"
                             F"sw f15, (20*%0 + 13*%1)(sp) \n"
                             F"sw f16, (20*%0 + 14*%1)(sp) \n"
                             F"sw f17, (20*%0 + 15*%1)(sp) \n"
                             F"sw f28, (20*%0 + 16*%1)(sp) \n"
                             F"sw f29, (20*%0 + 17*%1)(sp) \n"
                             F"sw f30, (20*%0 + 18*%1)(sp) \n"
                             F"sw f31, (20*%0 + 19*%1)(sp) \n" :: "I"(sizeof_reg), "I"(FPsizeof_reg)) ;
       #endif
    #endif
  }

  //--------------------------------------------------------------------
  //востановление контекста
  __inline_static__ void restore_context()
  {
         // востановление регистров cpu
         __asm__ volatile ("lw x1,   0*%0(sp) \n"
                           "lw x4,   1*%0(sp) \n"
                           "lw x5,   2*%0(sp) \n"
                           "lw x6,   3*%0(sp) \n"
                           "lw x7,   4*%0(sp) \n"
                           "lw x10,  5*%0(sp) \n"
                           "lw x11,  6*%0(sp) \n"
                           "lw x12,  7*%0(sp) \n"
                           "lw x13,  8*%0(sp) \n"
                           "lw x14,  9*%0(sp) \n"
                           "lw x15, 10*%0(sp)" :: "I"(sizeof_reg) );


     #ifndef __riscv_32e
         __asm__ volatile ("lw x16, 11*%0(sp) \n"
                           "lw x17, 12*%0(sp) \n"
                           "lw x28, 13*%0(sp) \n"
                           "lw x29, 14*%0(sp) \n"
                           "lw x30, 15*%0(sp) \n"
                           "lw x31, 16*%0(sp) \n" ::"I"(sizeof_reg) ) ;
     #endif


  #ifdef __riscv_flen
    #if (__riscv_flen==64)
     // востановление регистров fpu
    __asm__ volatile (FP"lw f0,  (20*sizeof_reg +  0*FPsizeof_reg)(sp) \n"
  	            FP"lw f1,  (20*sizeof_reg +  1*FPsizeof_reg)(sp) \n"
  	            FP"lw f2,  (20*sizeof_reg +  2*FPsizeof_reg)(sp) \n"
  	            FP"lw f3,  (20*sizeof_reg +  3*FPsizeof_reg)(sp) \n"
  	            FP"lw f4,  (20*sizeof_reg +  4*FPsizeof_reg)(sp) \n"
  	            FP"lw f5,  (20*sizeof_reg +  5*FPsizeof_reg)(sp) \n"
  	            FP"lw f6,  (20*sizeof_reg +  6*FPsizeof_reg)(sp) \n"
  	            FP"lw f7,  (20*sizeof_reg +  7*FPsizeof_reg)(sp) \n"
  	            FP"lw f10, (20*sizeof_reg +  8*FPsizeof_reg)(sp) \n"
  	            FP"lw f11, (20*sizeof_reg +  9*FPsizeof_reg)(sp) \n"
  	            FP"lw f12, (20*sizeof_reg + 10*FPsizeof_reg)(sp) \n"
  	            FP"lw f13, (20*sizeof_reg + 11*FPsizeof_reg)(sp) \n"
  	            FP"lw f14, (20*sizeof_reg + 12*FPsizeof_reg)(sp) \n"
  	            FP"lw f15, (20*sizeof_reg + 13*FPsizeof_reg)(sp) \n"
  	            FP"lw f16, (20*sizeof_reg + 14*FPsizeof_reg)(sp) \n"
  	            FP"lw f17, (20*sizeof_reg + 15*FPsizeof_reg)(sp) \n"
  	            FP"lw f28, (20*sizeof_reg + 16*FPsizeof_reg)(sp) \n"
  	            FP"lw f29, (20*sizeof_reg + 17*FPsizeof_reg)(sp) \n"
  	            FP"lw f30, (20*sizeof_reg + 18*FPsizeof_reg)(sp) \n"
  	            FP"lw f31, (20*sizeof_reg + 19*FPsizeof_reg)(sp) \n" :: "I"(sizeof_reg), "I"(FPsizeof_reg)) ;
    #endif
  #endif

    // смещение указателя стека (освобождение стека)
  #ifdef __riscv_flen
    #if(__riscv_flen == 64 )
      __asm__ volatile ("addi sp, sp, 20*%0  + 20*%1" :: "I"(sizeof_reg), "I"(FPsizeof_reg) );
    #endif
  #else

      __asm__ volatile ("addi sp, sp, 20*%0" :: "I"(sizeof_reg) ) ;
  #endif
  }



  // точка входа irq
  static __attribute__((unused,noinline,naked,aligned(64),section(".irq_entry"))) void irq_entry()
  {
    save_context();

    //сохранение регистров mcause mepc msubm
    __asm__ volatile ("csrrwi  x0, %0, 17 \n" // сохранение в стек mcause
                      "csrrwi  x0, %1, 18 \n" // сохранение в стек mepc
                      "csrrwi  x0, %2, 19 \n" // сохранение в стек msunb

    // хитрожопая CSR операция чтениия-записи JALMNXTI , понуждающая eclic выполнить установку mstatus.mie, записать регистр связи и запрыгнуть по
    // вектору наиболее приоритетного исключения
                      "csrrw   ra, %3, ra \n"
	              ::  "I"(CSR_PUSHMCAUSE), "I"(CSR_PUSHMEPC), "I"(CSR_PUSHMSUBM),  "I"(CSR_JALMNXTI) );

    // --- Critical section with interrupts disabled -----------------------
    riscv_global_interrupt_disable(); // Disable interrupts

    // востановление регистров msubm mepc mcause
    __asm__ volatile ("lw x5, 19*%0(sp) \n"
                      "csrw %1, x5      \n" // востановление со стека msunb
                      "lw x5, 18*%0(sp) \n"
                      "csrw %2, x5      \n" // востановление со стека mepc
                      "lw x5, 17*%0(sp) \n"
                      "csrw %3, x5      \n" // востановление со стека mepc
	              :: "I"(sizeof_reg), "I"(CSR_MSUBM),   "I"(CSR_MEPC),  "I"(CSR_MCAUSE) : "x5") ;

    restore_context();

    // выход m-mode
    __asm__ volatile ("mret \n");
  }


  // точка входа trap
  static __attribute__((unused,noinline,naked,aligned(64),section(".trap_entry"))) void trap_entry(); // In CLIC mode, the trap entry must be 64bytes aligned ??????
  void trap_entry()
  {
    // сохранения контекста процесса
    save_context();

    // сохранение регистров mepc mstatus msubm
    __asm__ volatile ("csrr  x5, %1     \n"
                      "sw x5, 17*%0(sp) \n" // сохранение в стек mepc
                      "csrr  x5, %2     \n"
                      "sw x5, 18*%0(sp) \n" // сохранение в стек msunb
                      "csrr  x5, %3     \n"
                      "sw x5, 19*%0(sp) \n" // сохранение в стек mstatus
	              :: "I"(sizeof_reg), "I"(CSR_MEPC), "I"(CSR_MSUBM), "I"(CSR_MSTATUS) : "x5" ) ;


    const trap_context_t* ctx = reinterpret_cast


/* https://pdfs.semanticscholar.org/f6d5/e754da444b7ede6e4eeaf0d61e8cbb82ade9.pdf 1.5 Control Transfer Instructions C.J performs an unconditional control transfer. The offset is sign-extended and added to thepctoform the jump target address. C.J can therefore target a±2 KiB range. C.J expands tojal x0,offset[11:1]. расчет опкода инструкции перехода cj #offset */ constexpr inline uint32_t cjump_opcode(const uint32_t offset) { return 0b01 | // op ((offset >> 5) & 0b1) << 2 | // 5й бит ((offset >> 1) & 0b111) << 3 | // 3_1й биты ((offset >> 7) & 0b1 ) << 6 | // 7й бит ((offset >> 6) & 0b1 ) << 7 | // 6й бит ((offset >> 10)& 0b1 ) << 8 | // 10й бит ((offset >> 8) & 0b11 ) << 9 | // 8й бит ((offset >> 4) & 0b11 ) << 11 | // 4й бит ((offset >> 11)& 0b11 ) << 12 | // 11й бит (0b101 << 13) ; // func3 }