CH32V307 : Using a newer riscv toolchain

 The CH32V307 (and siblings) has a nice interrupt extension : Fast Interrupt

As the name implies, it saves/restores  more registers automatically before  executing the actual interrupt. It is, of course much faster than doing it manually.

It is used internally by SysTick (maybe SW_Handler too)

To use it, WCH has  modified their GCC 8.2 to add a new attribute :  __attribute__((interrupt("WCH-Interrupt-fast")))

For example :

  void SysTick_Handler(void) __attribute__((interrupt("WCH-Interrupt-fast")));

It is easy to use, but forces you to use the gcc 8.1 based wch compiler (or another compiler that merged the patch) and is causing problem with random gcc and/or clang.

NB : Clang is a better choice, if you use rust, else no LTO for you.

After looking into it, it appears that WCH-Interrupt-fast is about the same as using __attribute__((interrupt(naked))) + exiting the function with "mret"

Doing that,  we can use any gcc and it works (or seems to).

Regarding clang, it is a bit more complicated. The naked functions cant use "complicated" C code, so we have to split the function in 2 parts :

void SysTick_Handler_( void )
{
    SysTick->SR=0;
    if( xTaskIncrementTick() != pdFALSE )
    {
        portYIELD();
    }
}
void SysTick_Handler( void )
{
    GET_INT_SP();
    portDISABLE_INTERRUPTS();
    //SysTick_Handler_();
    asm("jal SysTick_Handler_");
    portENABLE_INTERRUPTS();
    FREE_INT_SP();
    __asm__("mret");
}
and that compiles with any riscv gcc or clang (and seems to work)

So now i'm using a brand new 12.2.0 riscv-gcc coming from riscv-gnu-toolchain

The C++/runtime part of clang is problematic. More on that later.







 

Comments

Popular posts from this blog

Component tester with STM32 : Part 1 ADC, Resistor

Fixing the INA3221

INA3221, weird wiring