Closed hientv1999 closed 3 weeks ago
Have you compared the relevant register values after running the two versions of the program (at least until the initialisation has been done) to see if there are any differences?
Have you compared the relevant register values after running the two versions of the program (at least until the initialisation has been done) to see if there are any differences?
How can I check that? Is it as simple as printing the value of the registers via printf?
Have you compared the relevant register values after running the two versions of the program (at least until the initialisation has been done) to see if there are any differences?
How can I check that? Is it as simple as printing the value of the registers via printf?
Use the debugger to inspect the relevant memory mapped registers?
After the setup process, just before entering while loop, I read the registers related to ADC1. I found 2 registers having different values between 2 frameworks. On noneos, I got: RCC->CFGR0: 0x0 RCC->APB2PCENR: 0x4231
On ch32v003fun, I got: RCC->CFGR0: 0xa RCC->APB2PCENR: 0x4230
The other registers that are identical between 2 frameworks are:
EXTEN->EXTEN_CTR: 0x10040
RCC->APB2PRSTR: 0x0
ADC1->CTLR1: 0x2000580
ADC1->CTLR2: 0x7002
ADC1->RSQR1: 0x0
ADC1->ISQR: 0x119c00
ADC1->SAMPTR1: 0x0
ADC1->SAMPTR2: 0x600600
I tried copying the same register values from noneos to ch32v003fun project, but it crashed the printf message. I receive unreadable characters. Why then?
I found 2 registers having different values between 2 frameworks
Did you try decoding the different register values to understand the differences between the two programs?
I tried copying the same register values from noneos to ch32v003fun project, but it crashed the printf message. I receive unreadable characters. Why then?
Did you try debugging the code to understand what's going on/wrong?
I found 2 registers having different values between 2 frameworks
Did you try decoding the different register values to understand the differences between the two programs?
I tried copying the same register values from noneos to ch32v003fun project, but it crashed the printf message. I receive unreadable characters. Why then?
Did you try debugging the code to understand what's going on/wrong?
I haven't used the debugger yet so I have to figure out how to use it. But the only possible reason for this issue I can think of is the different in either SystemInit or the interrupt priority difference between 2 frameworks. I have even copied the same code for legacy functions for ADC from old framework to replicate the same code as much as possible and it still results in this difference ADC value reading.
I haven't used the debugger yet so I have to figure out how to use it. But the only possible reason for this issue I can think of is the different in either SystemInit or the interrupt priority difference between 2 frameworks. I have even copied the same code for legacy functions for ADC from old framework to replicate the same code as much as possible and it still results in this difference ADC value reading.
Surely this is also potentially relevant to the difference in behaviour?
After the setup process, just before entering while loop, I read the registers related to ADC1. I found 2 registers having different values between 2 frameworks.
On noneos, I got: RCC->CFGR0: 0x0 RCC->APB2PCENR: 0x4231
On ch32v003fun, I got: RCC->CFGR0: 0xa RCC->APB2PCENR: 0x4230
Can you please show me how I can read more information about the register? Like RCC_CFGR0 and RCC_APB2PCENR? Online datasheet doesn't tell. Maybe I didn't find the correct datasheet. Updated: I guess all RISC-V MCU uses the same register map? If so I use this as reference: https://www.manualslib.com/manual/2933885/Wch-Ch32v003-Series.html?page=20#manual
RCC->CFGR0: 0x0 on noneos meaning it uses HSI as system clock RCC->CFGR0: 0xa on ch32v003fun meaning it uses PLL as system clock.
I added #define FUNCONF_USE_HSI 1 to funconfig.h but it doesn't change the register value at all. Anything else I missed?
RCC->APB2PCENR: 0x4231 on noneos meaning I/O auxiliary function module clock is enable RCC->APB2PCENR: 0x4230 on ch32v003fun meaning I/0 auxiliary function module clock is disabled.
I don't know how to fix this difference
Can you please show me how I can read more information about the register? Like RCC_CFGR0 and RCC_APB2PCENR? Online datasheet doesn't tell. Maybe I didn't find the correct datasheet.
The datasheet/reference manual explains these registers in detail.
I realized all RISC-V uses the same register map so I found out it from another document. But thank you for sharing me the above document I've never seen it before.
RCC->CFGR0: 0x0 on noneos meaning it uses HSI as system clock RCC->CFGR0: 0xa on ch32v003fun meaning it uses PLL as system clock.
I added #define FUNCONF_USE_HSI 1 to funconfig.h but it doesn't change the register value at all. Anything else I missed?
RCC->APB2PCENR: 0x4231 on noneos meaning I/O auxiliary function module clock is enable RCC->APB2PCENR: 0x4230 on ch32v003fun meaning I/0 auxiliary function module clock is disabled.
I don't know how to fix this difference
By the way, 1 significant difference between 2 frameworks are interrupt void ADC1_IRQHandler() attribute((interrupt)); in ch32v003fun void ADC1_IRQHandler() attribute((interrupt("WCH-Interrupt-fast"))); in noneos Not sure if this can be the reason of the issue?
I realized all RISC-V uses the same register map
This is not correct. Different RISC-V implementations use different (often very different) memory maps and different memory mapped peripherals. When using a specific implementation, in particular a specific RISC-V based MCU, it's vital to use the documentation for that specific target.
I realized all RISC-V uses the same register map
This is not correct. Different RISC-V implementations use different (often very different) memory maps and different memory mapped peripherals. When using a specific implementation, in particular a specific RISC-V based MCU, it's vital to use the documentation for that specific target.
Ok I got it. But I just doubled check with CH32V003 datasheet and it the same. The above 2 comparisons are still valid. Do you have any idea how to fix?
RCC->CFGR0: 0x0 on noneos meaning it uses HSI as system clock RCC->CFGR0: 0xa on ch32v003fun meaning it uses PLL as system clock.
I added #define FUNCONF_USE_HSI 1 to funconfig.h but it doesn't change the register value at all. Anything else I missed?
Maybe you also need to ensure that FUNCONF_USE_PLL
is undefined or set to 0?
RCC->APB2PCENR: 0x4231 on noneos meaning I/O auxiliary function module clock is enable RCC->APB2PCENR: 0x4230 on ch32v003fun meaning I/0 auxiliary function module clock is disabled.
I don't know how to fix this difference
Maybe by just hacking ch32v003fun
temporarily if needed?
By the way, 1 significant difference between 2 frameworks are interrupt void ADC1_IRQHandler() attribute((interrupt)); in ch32v003fun void ADC1_IRQHandler() attribute((interrupt("WCH-Interrupt-fast"))); in noneos Not sure if this can be the reason of the issue?
Could be a factor alright. Again, try modifying ch32v003fun
to use the fast interrupt option temporarily and see if it makes a difference.
You should probably try these three changes one by one and then maybe in combination to see if they make any difference.
I would try the fast interrupt change first and on its own. Then the clocking change on its own and then with fast interrupt if necessary. Then the other one and other combinations of the three.
Thank you for the detail answer but honestly I don't know how to try the fast interrupt option. Simply doing interrupt("WCH-Interrupt-fast") will not work on ch32v003fun framework
Thank you for the detail answer but honestly I don't know how to try the fast interrupt option. Simply doing interrupt("WCH-Interrupt-fast") will not work on ch32v003fun framework
As far as I know only the custom GCC toolchain from WCH/MounRiver supports that non-standard attribute. And I'm not sure that they ever made the sources for their changes available or tried to upstream them to the master GCC project (where they probably wouldn't be accepted anyway).
By the way, in funconfig.h, I add
And on line 1329 of ch32v003func.c, I modify into RCC->APB2PCENR |= RCC_APB2Periph_GPIOD | RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO;
These make the register values the same as noneos framework now. However, the issue of ADC reading is still there.
Thank you for the detail answer but honestly I don't know how to try the fast interrupt option. Simply doing interrupt("WCH-Interrupt-fast") will not work on ch32v003fun framework
As far as I know only the custom GCC toolchain from WCH/MounRiver supports that non-standard attribute. And I'm not sure that they ever made the sources for their changes available or tried to upstream them to the master GCC project (where they probably wouldn't be accepted anyway).
Does that mean I have no solution for this problem? I didn't expect to encounter this awkward issue.
However, 1 positive thing after using HSI instead of PLL is that ADC reading is much more stable. The difference between min and max ADC reading in 50ms is way less. Not sure if because the clock is slower and the ADC circuitry has more time to sample the charge
Does that mean I have no solution for this problem? I didn't expect to encounter this awkward issue.
If the issue is that you definitely need the custom fast interrupt mechanism in order to do what you're trying to do (and that doesn't seem to have been ascertained for sure so far as far as I can see) then you'll need a toolchain with support for it. And, as far as I know, the only toolchain with that support is the custom WCH/MounRiver one.
By the way, in funconfig.h, I add #define FUNCONF_USE_HSI 1 #define FUNCONF_USE_PLL 0
And on line 1329 of ch32v003func.c, I modify into RCC->APB2PCENR |= RCC_APB2Periph_GPIOD | RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO;
These make the register values the same as noneos framework now. However, the issue of ADC reading is still there.
What if you try these changes one at a time as I previously suggested? Maybe only one of them makes a difference?
Does that mean I have no solution for this problem? I didn't expect to encounter this awkward issue.
If the issue is that you definitely need the custom fast interrupt mechanism in order to do what you're trying to do (and that doesn't seem to have been ascertained for sure so far as far as I can see) then you'll need a toolchain with support for it. And, as far as I know, the only toolchain with that support is the custom WCH/MounRiver one.
I think I have to accept the issue for now. Normally my mic range reading will vary from 10 to 1023. Now it starts from 670 to 1023. I will have less dynamic range, but the good thing is that it looks like the signal is more stable than in noneos framework, so the same resolution may be achieved.
By the way, in funconfig.h, I add #define FUNCONF_USE_HSI 1 #define FUNCONF_USE_PLL 0 And on line 1329 of ch32v003func.c, I modify into RCC->APB2PCENR |= RCC_APB2Periph_GPIOD | RCC_APB2Periph_USART1 | RCC_APB2Periph_AFIO; These make the register values the same as noneos framework now. However, the issue of ADC reading is still there.
What if you try these changes one at a time as I previously suggested? Maybe only one of them makes a difference?
I did try each fix. Still doesn't solve my ADC problem. However, one thing I noticed is that enabling the AFIO clock will make the ADC reading even higher (by 10 units), reducing my dynamic range further.
Same with HSI enable, if I enable HSI and disable PLL, my ADC reading will increase another 10 units. However, using HSI will make the signal much more stable. They only differ by 3-4 units for consecutive readings, compared to up to 12 units of difference in ADC consecutive readings with HSI disabled
I found the problem. Turn out I set the pin mode to be input float instead of input analog
I spent half a day but still cannot solve this problem. I used to program OPA + ADC in the noneos framework. It was to read the analog signal from a microphone. However, when I moved to ch32v003fun framework, with the same PCB, the analog output was much higher than in the noneos framework. In noneos I got 10-20 for the printf below. But in ch32v003fun, I constantly got 140-160 for the same printf. Both tests were conducted on the same PCB in the same room to keep ambient sound the same. I have checked if UART is affected by removing UART but it doesn't help. Sorry if the code is a bit long but I have simplified it as much as possible. Updated: 1 thing I noticed is that in ch32v003fun framework,if I increase the sample time to ADC_SampleTime_241Cycles, the return value from printf is lower than using a lower sample time like ADC_SampleTime_30Cycles. But this behavior doesn't exist in noneos framework. Below is my original code in noneos `
include
include
include
define BATT_ADC ADC_Channel_3
define MIC_ADC ADC_Channel_7
static u16 mic_adc_max = 0; static u16 mic_adc_min = 0;
void ADC1_IRQHandler() attribute((interrupt("WCH-Interrupt-fast"))); void ADC1_IRQHandler() { if ((ADC1->STATR & (ADC_IT_JEOC >> 8)) != (uint32_t)RESET){ u16 adc_value = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1); if (adc_value < mic_adc_min){ mic_adc_min = adc_value; } if (adc_value > mic_adc_max){ mic_adc_max = adc_value; } ADC_ClearITPendingBit(ADC1, ADC_IT_JEOC); } }
void ADC_config(u8 mic, u8 batt, u8 sampleTime){ // replace OPA_Init( &OPA_InitStructure ); uint32_t tmp = 0; tmp = EXTEN->EXTEN_CTR; tmp &= ~(uint32_t)(3<<17); tmp |= (CHP0 << 18) | (CHN0 << 17); EXTEN->EXTEN_CTR = tmp; // replace OPA_Cmd( ENABLE ); EXTEN->EXTEN_CTR |= (uint32_t)(1 << 16);
}
void ADC_start(){ mic_adc_max = 0; mic_adc_min = 1023; ADC1->CTLR2 |= ((uint32_t)0x00000001); // Enable ADC1 ADC1->CTLR2 |= ((uint32_t)0x00000008); // Reset calibration while (ADC1->CTLR2 & ((uint32_t)0x00000008)); // GetResetCalibrationStatus ADC1->CTLR2 |= ((uint32_t)0x00000004); // Start calibration while (ADC1->CTLR2 & ((uint32_t)0x00000004)); ADC1->CTLR2 |= ((uint32_t)0x00208000); // start injection
}
u16 mic_read_range(){ u16 range = mic_adc_max - mic_adc_min; mic_adc_max = 0; mic_adc_min = 1023; return range; }
int main() { SystemInit(); ADC_config(MIC_ADC, BATT_ADC, ADC_SampleTime_241Cycles); ADC_start(); while(1){ printf("%i", mic_read_range()); Delay_Ms(50); } } `
And below is the same code but modified to work with ch32v003fun `
include "ch32v003fun.h"
include "ch32v003_GPIO_branchless.h"
include
include
define BATT_ADC ADC_Channel_3
define MIC_ADC ADC_Channel_7
static u16 mic_adc_max = 0; static u16 mic_adc_min = 0;
uint16_t ADC_GetInjectedConversionValue(ADC_TypeDef *ADCx, uint8_t ADC_InjectedChannel) { __IO uint32_t tmp = 0;
}
void ADC_ClearITPendingBit(ADC_TypeDef *ADCx, uint16_t ADC_IT) { uint8_t itmask = 0;
}
void ADC1_IRQHandler() attribute((interrupt)); void ADC1_IRQHandler() { if ((ADC1->STATR & (ADC_IT_JEOC >> 8)) != (uint32_t)RESET){ u16 adc_value = ADC_GetInjectedConversionValue(ADC1, ADC_InjectedChannel_1); if (adc_value < mic_adc_min){ mic_adc_min = adc_value; } if (adc_value > mic_adc_max){ mic_adc_max = adc_value; } ADC_ClearITPendingBit(ADC1, ADC_IT_JEOC); } }
void ADC_InjectedChannelConfig(ADC_TypeDef *ADCx, uint8_t ADC_Channel, uint8_t Rank, uint8_t ADC_SampleTime) { uint32_t tmpreg1 = 0, tmpreg2 = 0, tmpreg3 = 0;
}
void ADC_config(u8 mic, u8 batt, u8 sampleTime){ // OPA init u32 temp = 0; temp = EXTEN->EXTEN_CTR; temp &= ~(u32)(3<<17); temp |= (CHP0 << 18) | (CHN0 << 17); EXTEN->EXTEN_CTR = temp; // turn on the op-amp EXTEN->EXTEN_CTR |= EXTEN_OPA_EN;
}
void ADC_start(){ mic_adc_max = 0; mic_adc_min = 1023; ADC1->CTLR2 |= ((uint32_t)0x00000001); // Enable ADC1 ADC1->CTLR2 |= ((uint32_t)0x00000008); // Reset calibration while (ADC1->CTLR2 & ((uint32_t)0x00000008)); // GetResetCalibrationStatus ADC1->CTLR2 |= ((uint32_t)0x00000004); // Start calibration while (ADC1->CTLR2 & ((uint32_t)0x00000004)); ADC1->CTLR2 |= ((uint32_t)0x00208000); // start injection
}
u16 mic_read_range(){ u16 range = mic_adc_max - mic_adc_min; mic_adc_max = 0; mic_adc_min = 1023; return range; }
int main() { SystemInit(); GPIO_port_enable(GPIO_port_A); GPIO_port_enable(GPIO_port_C); GPIO_port_enable(GPIO_port_D); ADC_config(MIC_ADC, BATT_ADC, ADC_SampleTime_241Cycles); ADC_start(); while(1){ printf("%i", mic_read_range()); Delay_Ms(50); } } `