CH32V307
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 maybe 21 ns, not 150ns!!!
So why is this happening??
Hypotheses
- Different memory types, fetch happening at different speeds. Perhaps because the code is inside a IRQ Handler.
- Because it is Saturday and was raining earlier.