Difference between revisions of "CH32V307"

From Stm32World Wiki
Jump to navigation Jump to search
Line 33: Line 33:
 
     DAC_Cmd(DAC_Channel_2, ENABLE);
 
     DAC_Cmd(DAC_Channel_2, ENABLE);
 
</nowiki>
 
</nowiki>
 +
 +
=== Execution Speed ===
 +
While executing some tests, I noticed that an extra layer of function call added much more time than should be the case.
 +
 +
In the '''TIM7_IRQHandler''' I did
 +
<nowiki>
 +
__attribute__((interrupt("WCH-Interrupt-fast"))) void TIM7_IRQHandler() {
 +
    GET_INT_SP();
 +
    rt_interrupt_enter();
 +
    GPIO_WriteBit(GPIOA, GPIO_Pin_7, Bit_SET);
 +
    GPIO_WriteBit(GPIOA, GPIO_Pin_7, Bit_RESET);
 +
    set_testpoint(0);
 +
    clear_testpoint(0);
 +
    demiurge_tick();
 +
    TIM7->INTFR = 0;
 +
    rt_interrupt_leave();
 +
    FREE_INT_SP();
 +
}
 +
</nowiki>
 +
 +
and the '''set_testpoint(0)''' and '''clear_testpoint(0)''' functions as follows;
 +
 +
<nowiki>
 +
void set_testpoint(int point)
 +
{
 +
    GPIO_WriteBit(GPIOA, GPIO_Pin_7, Bit_SET);
 +
}
 +
void clear_testpoint(int point)
 +
{
 +
    GPIO_WriteBit(GPIOA, GPIO_Pin_7, Bit_RESET);
 +
}
 +
</nowiki>
 +
 +
It is clear that there is literally only one extra call. In assembler we can see that the compiler has not inlined any of this code;
 +
 +
 +
  21                    __attribute__((interrupt("WCH-Interrupt-fast"))) void TIM7_IRQHandler() {
 +
  22 002c 73110134          GET_INT_SP();
 +
  23                        rt_interrupt_enter();
 +
  33                            csrrw sp,mscratch,sp
 +
  34                    # 0 "" 2
 +
  35                    #NO_APP
 +
  36 0030 37140140              li      s0,1073811456
 +
  37 0034 97000000              call    rt_interrupt_enter
 +
  37      E7800000
 +
  38 003c 13050480              addi    a0,s0,-2048
 +
  39 0040 0546                  li      a2,1
 +
  40 0042 93050008              li      a1,128
 +
  41 0046 97000000              call    GPIO_WriteBit
 +
  41      E7800000
 +
  42 004e 0146                  li      a2,0
 +
  43 0050 93050008              li      a1,128
 +
  44 0054 13050480              addi    a0,s0,-2048
 +
  45 0058 97000000              call    GPIO_WriteBit
 +
  45      E7800000
 +
  46 0060 0145                  li      a0,0
 +
  47 0062 97000000              call    set_testpoint
 +
  47      E7800000
 +
  48 006a 0145                  li      a0,0
 +
  49 006c 97000000              call    clear_testpoint
 +
  49      E7800000
 +
  50 0074 97000000              call    demiurge_tick
 +
  50      E7800000
 +
  51 007c B7170040              li      a5,1073745920
 +
  52 0080 23980740              sh      zero,1040(a5)
 +
  53 0084 97000000              call    rt_interrupt_leave
 +
  53      E7800000
 +
-------
 +
  29                    set_testpoint:
 +
  30 0000 17030000              call    t0,__riscv_save_0
 +
  30      E7020300
 +
  31 0008 37150140              li      a0,1073811456
 +
  32 000c 0546                  li      a2,1
 +
  33 000e 93050008              li      a1,128
 +
  34 0012 13050580              addi    a0,a0,-2048
 +
  35 0016 97000000              call    GPIO_WriteBit
 +
  35      E7800000
 +
  36 001e 17030000              tail    __riscv_restore_0
 +
  36      67000300
 +
  38                            .section        .text.clear_testpoint,"ax",@progbits
 +
  39                            .align  1
 +
  40                            .globl  clear_testpoint
 +
  42                    clear_testpoint:
 +
  43 0000 17030000              call    t0,__riscv_save_0
 +
  43      E7020300
 +
  44 0008 37150140              li      a0,1073811456
 +
  45 000c 0146                  li      a2,0
 +
  46 000e 93050008              li      a1,128
 +
  47 0012 13050580              addi    a0,a0,-2048
 +
  48 0016 97000000              call    GPIO_WriteBit
 +
  48      E7800000
 +
  49 001e 17030000              tail    __riscv_restore_0
 +
  49      67000300
 +
 +
 +
But on the oscilloscope, I get a 70ns pulse first and a 220ns pulse there after. So why does
 +
 +
  46 0060 0145                  li      a0,0
 +
  47 0062 97000000              call    set_testpoint
 +
 +
 +
take 150ns to execute?  For the '''GPIO_WriteBit''' we have 5 32-bit and 1 16-bit instruction, and inside '''GPIO_WriteBit''' we get 3 assembly instructions. At 144MHz, each fetch cycle is ~7ns, so 7*9 = 63ns which is very close to what I observe. So the
 +
 +
  li a0,0
 +
  call set_testpoint
 +
 +
should only take 14 or may 21 ns, not 150ns!!!
 +
 +
'''So why is this happening??'''

Revision as of 21:48, 2 July 2022


Miscellaneous Links

Development Notes

DAC

  • The output impedance is a concern. Without the Output Buffer enabled, >100kohm impedance for the load is needed. Even WITH Output Buffer enabled, a 1kohm load is not really possible, both high and low end of range is not reached, which is a bit strange. 10kohm hasn't been tested yet, but datasheet indicates that a 5kohm load should be fine.
  • For fastest write to DAC output, this is used;
DAC->RD12BDHR = dac_value1 + (dac_value2 << 16);

  • Simple initialization is;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_DAC, ENABLE );

    DAC_InitTypeDef DAC_InitType={0};
    DAC_InitType.DAC_Trigger=DAC_Trigger_None;
    DAC_InitType.DAC_WaveGeneration=DAC_WaveGeneration_None;
    DAC_InitType.DAC_OutputBuffer=DAC_OutputBuffer_Enable;
    DAC_Init(DAC_Channel_1,&DAC_InitType);
    DAC_Init(DAC_Channel_2,&DAC_InitType);

    DAC_Cmd(DAC_Channel_1, ENABLE);
    DAC_Cmd(DAC_Channel_2, ENABLE);

Execution Speed

While executing some tests, I noticed that an extra layer of function call added much more time than should be the case.

In the TIM7_IRQHandler I did

__attribute__((interrupt("WCH-Interrupt-fast"))) void TIM7_IRQHandler() {
    GET_INT_SP();
    rt_interrupt_enter();
    GPIO_WriteBit(GPIOA, GPIO_Pin_7, Bit_SET);
    GPIO_WriteBit(GPIOA, GPIO_Pin_7, Bit_RESET);
    set_testpoint(0);
    clear_testpoint(0);
    demiurge_tick();
    TIM7->INTFR = 0;
    rt_interrupt_leave();
    FREE_INT_SP();
}

and the set_testpoint(0) and clear_testpoint(0) functions as follows;

void set_testpoint(int point)
{
    GPIO_WriteBit(GPIOA, GPIO_Pin_7, Bit_SET);
}
void clear_testpoint(int point)
{
    GPIO_WriteBit(GPIOA, GPIO_Pin_7, Bit_RESET);
}

It is clear that there is literally only one extra call. In assembler we can see that the compiler has not inlined any of this code;


 21                    __attribute__((interrupt("WCH-Interrupt-fast"))) void TIM7_IRQHandler() {
 22 002c 73110134          GET_INT_SP();
 23                        rt_interrupt_enter();
 33                            csrrw sp,mscratch,sp
 34                    # 0 "" 2
 35                     #NO_APP
 36 0030 37140140              li      s0,1073811456
 37 0034 97000000              call    rt_interrupt_enter
 37      E7800000 
 38 003c 13050480              addi    a0,s0,-2048
 39 0040 0546                  li      a2,1
 40 0042 93050008              li      a1,128
 41 0046 97000000              call    GPIO_WriteBit
 41      E7800000 
 42 004e 0146                  li      a2,0
 43 0050 93050008              li      a1,128
 44 0054 13050480              addi    a0,s0,-2048
 45 0058 97000000              call    GPIO_WriteBit
 45      E7800000 
 46 0060 0145                  li      a0,0
 47 0062 97000000              call    set_testpoint
 47      E7800000 
 48 006a 0145                  li      a0,0
 49 006c 97000000              call    clear_testpoint
 49      E7800000 
 50 0074 97000000              call    demiurge_tick
 50      E7800000 
 51 007c B7170040              li      a5,1073745920
 52 0080 23980740              sh      zero,1040(a5)
 53 0084 97000000              call    rt_interrupt_leave
 53      E7800000 
-------
 29                    set_testpoint:
 30 0000 17030000              call    t0,__riscv_save_0
 30      E7020300 
 31 0008 37150140              li      a0,1073811456
 32 000c 0546                  li      a2,1
 33 000e 93050008              li      a1,128
 34 0012 13050580              addi    a0,a0,-2048
 35 0016 97000000              call    GPIO_WriteBit
 35      E7800000 
 36 001e 17030000              tail    __riscv_restore_0
 36      67000300 
 38                            .section        .text.clear_testpoint,"ax",@progbits
 39                            .align  1
 40                            .globl  clear_testpoint
 42                    clear_testpoint:
 43 0000 17030000              call    t0,__riscv_save_0
 43      E7020300 
 44 0008 37150140              li      a0,1073811456
 45 000c 0146                  li      a2,0
 46 000e 93050008              li      a1,128
 47 0012 13050580              addi    a0,a0,-2048
 48 0016 97000000              call    GPIO_WriteBit
 48      E7800000 
 49 001e 17030000              tail    __riscv_restore_0
 49      67000300 


But on the oscilloscope, I get a 70ns pulse first and a 220ns pulse there after. So why does

 46 0060 0145                  li      a0,0
 47 0062 97000000              call    set_testpoint


take 150ns to execute? For the GPIO_WriteBit we have 5 32-bit and 1 16-bit instruction, and inside GPIO_WriteBit we get 3 assembly instructions. At 144MHz, each fetch cycle is ~7ns, so 7*9 = 63ns which is very close to what I observe. So the

  li a0,0
  call set_testpoint

should only take 14 or may 21 ns, not 150ns!!!

So why is this happening??