я примерно также сделал как у 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, ссылка, ссылка)