я примерно также сделал как у 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 }
-
- Не, я об оптимизации сильно не задумывался. Чтобы включить
отдельный обработчик для прерывания нужно как минимум установить
соответствующий аттрибут как Vectored. evgeniy1294(543 знак., 14.02.2021 14:07, ссылка, ссылка)
- спасибо, надо будит покурить эту тему с пристьрастием. посмотрел
Ваши перлы по диаганали... люди разные а дурь видимо одинаковая,
такой же воласипЭд ваяю - klen(14.02.2021 14:43)
- Это для учебных и развлекательных целей - evgeniy1294(14.02.2021 15:33)
- спасибо, надо будит покурить эту тему с пристьрастием. посмотрел
Ваши перлы по диаганали... люди разные а дурь видимо одинаковая,
такой же воласипЭд ваяю - klen(14.02.2021 14:43)
- Не, я об оптимизации сильно не задумывался. Чтобы включить
отдельный обработчик для прерывания нужно как минимум установить
соответствующий аттрибут как Vectored. evgeniy1294(543 знак., 14.02.2021 14:07, ссылка, ссылка)