ВходНаше всё Теги codebook 无线电组件 Поиск Опросы Закон Четверг
9 мая
1300031 Топик полностью
VladislavS. (10.04.2023 08:32, просмотров: 327) ответил klen на проект выходного дня....вроде заработало! свежак KGP для riscv32-kgp-elf с поддержкой CH32Vxxx (QingKeV4, QingKeV4B, QingKeV4C, QingKeV4F)
Тема прерываний GD32VF103 не раскрыта. У него есть режим с общим входом в прерывание и с переходом сразу по таблице векторов прерываний. 

1. Для случая общего входа в прерывания обработчик как-то так выглядит (это макет кода)

void __attribute__((used, aligned(4), naked)) CommonIRQHandler()
{
  riscv::StackMove(-19*4);
  Nuclei::push_mcause(0);
  Nuclei::push_mepc(1);
  Nuclei::push_msubm(2);
  // Тут сохранить регистры
  Nuclei::CallIRQ(); //csrrw ra, jalsnxti, ra
  __disable_irq();
  // Тут восстановить регистры
  riscv::CSR<Nuclei::CSR_REGS::msubm>::write(riscv::StackRead(8));
  riscv::CSR<Nuclei::CSR_REGS::mepc>::write(riscv::StackRead(4));
  riscv::CSR<Nuclei::CSR_REGS::mcause>::write(riscv::StackRead(0));
  riscv::StackMove(19*4);
  riscv::mret();
}

При таком подходе обработчик прерываний можно naked делать. Способ самый простой, но не самый быстрый - полное сохранение всех регистров избыточно.


2. При векторизированной обработке каждый обработчик можно как-то так сделать

template <typename F>
void TVecoredIRQFunc(F f)
{  
  riscv::StackMove(-12);
  Nuclei::push_mcause(0);
  Nuclei::push_mepc(1);
  Nuclei::push_msubm(2);
  __enable_irq();
  f();
  __disable_irq();
  riscv::CSR::write(riscv::StackRead(8));
  riscv::CSR::write(riscv::StackRead(4));
  riscv::CSR::write(riscv::StackRead(0));
  riscv::StackMove(12);
}
 

С виду всё красиво, но реально f() будет сохранять свои регистры до riscv::StackMove(-12) что удлиняет время нахождения в состоянии запрета прерываний. Плюс лишняя StackMove в этом же состоянии. Тут напрашивается чтобы пролог и эпилог считал компилятор, тогда это будет работать быстрее.