### Example Performance Report Source: https://github.com/openwch/ch32v20x/blob/main/EVT/EXAM/APPLICATION/CoreMark/coremark/README.md An example of a reported CoreMark performance result, including iterations, compiler, and memory details. ```text CoreMark 1.0 : 128 / GCC 4.1.2 -O2 -fprofile-use / Heap in TCRAM / FORK:2 ``` -------------------------------- ### Example Performance Report (Simplified) Source: https://github.com/openwch/ch32v20x/blob/main/EVT/EXAM/APPLICATION/CoreMark/coremark/README.md A simplified example of a reported CoreMark performance result. ```text CoreMark 1.0 : 1400 / GCC 3.4 -O4 ``` -------------------------------- ### Main Application: ADC and DMA Execution Source: https://context7.com/openwch/ch32v20x/llms.txt The main function initializes the system, ADC, and DMA, then starts the ADC conversion and waits for DMA transfer completion. Finally, it prints the converted ADC values. ```c int main(void) { u16 i; SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init(115200); ADC_Function_Init(); printf("Calibration offset: %d\r\n", Calibrattion_Val); DMA_Tx_Init(DMA1_Channel1, (u32)&ADC1->RDATAR, (u32)TxBuf, SAMPLES); DMA_Cmd(DMA1_Channel1, ENABLE); ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 1, ADC_SampleTime_239Cycles5); ADC_SoftwareStartConvCmd(ADC1, ENABLE); while (DMA_GetFlagStatus(DMA1_FLAG_TC1) == RESET); /* wait for 1024 samples */ ADC_SoftwareStartConvCmd(ADC1, DISABLE); for (i = 0; i < SAMPLES; i++) { printf("%04d\r\n", Get_ConversionVal(TxBuf[i])); Delay_Ms(1); } while (1) {} } /* Output: 1024 lines of 12-bit ADC values, e.g.: 2048 2051 2047 ... */ ``` -------------------------------- ### Profile Guided Optimization Compilation Source: https://github.com/openwch/ch32v20x/blob/main/EVT/EXAM/APPLICATION/CoreMark/coremark/README.md Compile the benchmark with profile guided optimization enabled. Set XCFLAGS to include DTOTAL_DATA_SIZE and DPROFILE_RUN. ```makefile % make XCFLAGS="-DTOTAL_DATA_SIZE=1200 -DPROFILE_RUN=1" REBUILD=1 run3.log ``` -------------------------------- ### Configuring CoreMark for systems without malloc support Source: https://github.com/openwch/ch32v20x/blob/main/EVT/EXAM/APPLICATION/CoreMark/coremark/README.md When malloc is not available or command-line arguments are not supported, define TOTAL_DATA_SIZE via the compiler to set the buffer size. This example sets it to 6000 bytes and indicates that main has no arguments. ```makefile % make XCFLAGS="-DTOTAL_DATA_SIZE=6000 -DMAIN_HAS_NOARGC=1" ``` -------------------------------- ### Example Scaling Results Report Source: https://github.com/openwch/ch32v20x/blob/main/EVT/EXAM/APPLICATION/CoreMark/coremark/README.md An example of a reported CoreMark scaling result, showing CoreMark/MHz, compiler, and memory/cache ratios. ```text CoreMark/MHz 1.0 : 1.47 / GCC 4.1.2 -O2 / DDR3(Heap) 30:1 Memory 1:1 Cache ``` -------------------------------- ### Compiling CoreMark without make Source: https://github.com/openwch/ch32v20x/blob/main/EVT/EXAM/APPLICATION/CoreMark/coremark/README.md Manually compile the necessary C files using gcc if 'make' is not available. This example compiles for a performance run with 1000 iterations and redirects output to run1.log. ```c % gcc -O2 -o coremark.exe core_list_join.c core_main.c core_matrix.c core_state.c core_util.c simple/core_portme.c -DPERFORMANCE_RUN=1 -DITERATIONS=1000 % ./coremark.exe > run1.log ``` -------------------------------- ### Parallel execution with multiple threads Source: https://github.com/openwch/ch32v20x/blob/main/EVT/EXAM/APPLICATION/CoreMark/coremark/README.md Compile the benchmark for parallel execution on multiple cores using XCFLAGS to specify the number of threads. This example uses the POSIX Threads API. ```makefile % make XCFLAGS="-DMULTITHREAD=4 -DUSE_PTHREAD" ``` -------------------------------- ### I2C Master Transmission in 7-bit Mode Source: https://context7.com/openwch/ch32v20x/llms.txt Demonstrates I2C master mode operation. Generates START, sends the slave address with transmit direction, transmits data bytes, and generates STOP. Ensure the bus is not busy before starting. ```c int main(void) { u8 i; SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init(460800); IIC_Init(80000, SLAVE_ADDR); #if (I2C_MODE == HOST_MODE) while (I2C_GetFlagStatus(I2C1, I2C_FLAG_BUSY) != RESET); I2C_GenerateSTART(I2C1, ENABLE); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, SLAVE_ADDR, I2C_Direction_Transmitter); while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); for (i = 0; i < SIZE; i++) { while (I2C_GetFlagStatus(I2C1, I2C_FLAG_TXE) == RESET); I2C_SendData(I2C1, TxData[i]); } while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); I2C_GenerateSTOP(I2C1, ENABLE); printf("I2C master sent %d bytes\r\n", SIZE); #else i = 0; while (!I2C_CheckEvent(I2C1, I2C_EVENT_SLAVE_RECEIVER_ADDRESS_MATCHED)); while (i < SIZE) { if (I2C_GetFlagStatus(I2C1, I2C_FLAG_RXNE) != RESET) RxData[i++] = I2C_ReceiveData(I2C1); } for (i = 0; i < SIZE; i++) printf("%02x ", RxData[i]); printf("\r\n"); #endif while (1) {} } ``` -------------------------------- ### Initialize and Feed Independent Watchdog (IWDG) Source: https://context7.com/openwch/ch32v20x/llms.txt Configures and enables the IWDG with a specified prescaler and reload value. The watchdog must be 'fed' by calling IWDG_ReloadCounter before its timeout period expires to prevent a system reset. The example uses a button press to feed the watchdog. ```c #include "debug.h" #define KEY0 GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) void KEY_Init(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; /* pull-down input */ GPIO_Init(GPIOA, &GPIO_InitStructure); } void IWDG_Feed_Init(u16 prer, u16 rlr) { /* timeout = (4 * 2^prer * rlr) / 40000 s prer=IWDG_Prescaler_32, rlr=4000 → (4*32*4000)/40000 = 12.8 s Here we use prer=32, rlr=4000 → ~3.2 s */ IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); IWDG_SetPrescaler(prer); IWDG_SetReload(rlr); IWDG_ReloadCounter(); /* load the counter before enabling */ IWDG_Enable(); } int main(void) { SystemCoreClockUpdate(); USART_Printf_Init(115200); Delay_Init(); KEY_Init(); /* IWDG resets if not fed within ~3.2 s */ IWDG_Feed_Init(IWDG_Prescaler_32, 4000); while (1) { if (KEY0 == 1) { Delay_Ms(10); /* debounce */ printf("Feed dog\r\n"); IWDG_ReloadCounter(); /* reset countdown */ } } } ``` -------------------------------- ### Configure USART Peripheral Source: https://context7.com/openwch/ch32v20x/llms.txt Initializes the USART peripheral for both transmit and receive operations, including GPIO configuration and interrupt setup. Ensure the appropriate peripheral clocks are enabled before calling this function. ```c #include "debug.h" void USARTx_CFG(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; USART_InitTypeDef USART_InitStructure = {0}; NVIC_InitTypeDef NVIC_InitStructure = {0}; RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* USART2 TX=PA2, RX=PA3 */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); USART_InitStructure.USART_BaudRate = 115200; USART_InitStructure.USART_WordLength = USART_WordLength_8b; USART_InitStructure.USART_StopBits = USART_StopBits_1; USART_InitStructure.USART_Parity = USART_Parity_No; USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_Init(USART2, &USART_InitStructure); /* Enable RX-not-empty interrupt */ USART_ITConfig(USART2, USART_IT_RXNE, ENABLE); NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); USART_Cmd(USART2, ENABLE); } ``` -------------------------------- ### Initialize DMA for Peripheral to Memory Transfer Source: https://context7.com/openwch/ch32v20x/llms.txt Configures a DMA channel for transferring data from a peripheral to memory. This setup is typically used for continuous data acquisition where the CPU should not be involved in the transfer. ```c void DMA_Tx_Init(DMA_Channel_TypeDef *ch, u32 periph, u32 mem, u16 len) { DMA_InitTypeDef DMA_InitStructure = {0}; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); DMA_DeInit(ch); DMA_InitStructure.DMA_PeripheralBaseAddr = periph; DMA_InitStructure.DMA_MemoryBaseAddr = mem; DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize = len; DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh; DMA_InitStructure.DMA_M2M = DMA_M2M_Disable; DMA_Init(ch, &DMA_InitStructure); } ``` -------------------------------- ### System Initialization Source: https://context7.com/openwch/ch32v20x/llms.txt Initializes the system by configuring NVIC priority groups and updating the SystemCoreClock variable. It also sets up the SysTick for delay functions and redirects printf output. ```APIDOC ## System Initialization — `SystemCoreClockUpdate` / `NVIC_PriorityGroupConfig` Called at the start of every application to synchronize the `SystemCoreClock` global variable with the actual PLL/HSE/HSI configuration and to set the NVIC preemption/sub-priority split before any interrupts are enabled. ```c #include "debug.h" int main(void) { /* Group 1: 1-bit preemption, 3-bit sub-priority (values 0-1 / 0-7) */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); /* Refresh SystemCoreClock from hardware registers */ SystemCoreClockUpdate(); /* Calibrate the SysTick-based delay using the updated clock value */ Delay_Init(); /* Route printf to USART1 TX (PA9) at 115200 baud */ USART_Printf_Init(115200); printf("SystemClk: %d Hz\r\n", SystemCoreClock); printf("ChipID: %08x\r\n", DBGMCU_GetCHIPID()); while (1) {} } /* Expected output: SystemClk: 144000000 Hz ChipID: 20380500 */ ``` ``` -------------------------------- ### C++ Project Support with LED Toggle (C++) Source: https://context7.com/openwch/ch32v20x/llms.txt Demonstrates C++ project support using a class to control an LED. The CH32V203 toolchain supports C++ with `extern "C"` guards for clean linkage. ```cpp // User/main.cpp #include "debug.h" // C++ class wrapping a GPIO LED class LED { public: LED(GPIO_TypeDef *port, uint16_t pin) : m_port(port), m_pin(pin) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef cfg = {0}; cfg.GPIO_Pin = m_pin; cfg.GPIO_Mode = GPIO_Mode_Out_PP; cfg.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(m_port, &cfg); } void on() { GPIO_SetBits(m_port, m_pin); } void off() { GPIO_ResetBits(m_port, m_pin); } void toggle() { m_port->OUTDR ^= m_pin; } private: GPIO_TypeDef *m_port; uint16_t m_pin; }; int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init(115200); LED led(GPIOA, GPIO_Pin_0); while (1) { led.toggle(); Delay_Ms(500); } } ``` -------------------------------- ### Configure GPIO Pins for Input and Output Source: https://context7.com/openwch/ch32v20x/llms.txt Initializes GPIO pins for push-pull output and floating input modes. Ensure the appropriate peripheral clock is enabled before calling this function. ```c #include "debug.h" void GPIO_Toggle_INIT(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* PA0 push-pull output at 50 MHz */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* PA1 floating input */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); } int main(void) { u8 state = 0; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); SystemCoreClockUpdate(); USART_Printf_Init(115200); GPIO_Toggle_INIT(); while (1) { Delay_Ms(250); /* Toggle PA0 */ GPIO_WriteBit(GPIOA, GPIO_Pin_0, (state == 0) ? (state = Bit_SET) : (state = Bit_RESET)); /* Read PA1 */ u8 in = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1); printf("PA1=%d\r\n", in); } } ``` -------------------------------- ### GPIO Initialization and Control Source: https://context7.com/openwch/ch32v20x/llms.txt Configure GPIO pins for output or input, and control their state. This includes enabling clocks, setting pin modes, and reading/writing pin states. ```APIDOC ## GPIO — `GPIO_Init` / `GPIO_WriteBit` / `GPIO_ReadInputDataBit` General-purpose I/O configuration and control. Clock the desired GPIO port via `RCC_APB2PeriphClockCmd`, fill `GPIO_InitTypeDef` with the pin mask, mode (`GPIO_Mode_Out_PP`, `GPIO_Mode_IN_FLOATING`, `GPIO_Mode_AIN`, etc.) and speed, then call `GPIO_Init`. Use `GPIO_SetBits` / `GPIO_ResetBits` / `GPIO_WriteBit` for output and `GPIO_ReadInputDataBit` for input. ### Example Usage: ```c #include "debug.h" void GPIO_Toggle_INIT(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); /* PA0 push-pull output at 50 MHz */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); /* PA1 floating input */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); } int main(void) { u8 state = 0; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init(115200); GPIO_Toggle_INIT(); while (1) { Delay_Ms(250); /* Toggle PA0 */ GPIO_WriteBit(GPIOA, GPIO_Pin_0, (state == 0) ? (state = Bit_SET) : (state = Bit_RESET)); /* Read PA1 */ u8 in = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1); printf("PA1=%d\r\n", in); } } ``` ``` -------------------------------- ### RTC Calendar Functions Source: https://context7.com/openwch/ch32v20x/llms.txt Provides functions to initialize, set, get, and manage alarms for the RTC. It uses a 32.768 kHz crystal to maintain a Unix-epoch second counter and can decode/encode calendar date/time. ```APIDOC ## RTC Calendar — `RTC_Init` / `RTC_Set` / `RTC_Get` / `RTC_Alarm_Set` Uses the 32.768 kHz LSE crystal to maintain a Unix-epoch second counter. `RTC_Set` converts a calendar date/time to a Unix timestamp and loads `RTC_SetCounter`. `RTC_Get` decodes the live counter back to year/month/day/hour/minute/second. An alarm can be scheduled with `RTC_Alarm_Set` which fires an `RTC_IT_ALR` interrupt. ### Functions - **`RTC_Init(void)`**: Initializes the RTC peripheral. Returns 0 on success, non-zero on failure. - **`RTC_Set(u16 y, u8 mo, u8 d, u8 h, u8 mi, u8 s)`**: Sets the RTC to a specific calendar date and time. Parameters: `y` (year), `mo` (month), `d` (day), `h` (hour), `mi` (minute), `s` (second). Returns 0 on success, non-zero on failure. - **`RTC_Get(void)`**: Updates the global `calendar` object with the current time from the RTC. The `calendar` object has fields: `w_year`, `w_month`, `w_date`, `week`, `hour`, `min`, `sec`. ### Example Usage ```c #include "debug.h" typedef struct { vu16 w_year; vu8 w_month, w_date, week, hour, min, sec; } _calendar_obj; _calendar_obj calendar; extern u8 RTC_Init(void); extern u8 RTC_Set(u16 y, u8 mo, u8 d, u8 h, u8 mi, u8 s); extern u8 RTC_Get(void); int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init(115200); if (RTC_Init() != 0) { printf("RTC Init FAIL\r\n"); while (1); } /* Adjust time to 2024-06-01 08:00:00 */ RTC_Set(2024, 6, 1, 8, 0, 0); while (1) { Delay_Ms(1000); RTC_Get(); printf("%04d-%02d-%02d %d %02d:%02d:%02d\r\n", calendar.w_year, calendar.w_month, calendar.w_date, calendar.week, calendar.hour, calendar.min, calendar.sec); } } /* Output (increments each second): 2024-06-01 6 08:00:01 2024-06-01 6 08:00:02 ... */ ``` ``` -------------------------------- ### System Initialization and Debug Output Source: https://context7.com/openwch/ch32v20x/llms.txt Configures NVIC priority groups, updates the system core clock, initializes delay functions, and sets up printf output to USART1. Ensure SystemCoreClockUpdate() is called before Delay_Init(). ```c #include "debug.h" int main(void) { /* Group 1: 1-bit preemption, 3-bit sub-priority (values 0-1 / 0-7) */ NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); /* Refresh SystemCoreClock from hardware registers */ SystemCoreClockUpdate(); /* Calibrate the SysTick-based delay using the updated clock value */ Delay_Init(); /* Route printf to USART1 TX (PA9) at 115200 baud */ USART_Printf_Init(115200); printf("SystemClk: %d Hz\r\n", SystemCoreClock); printf("ChipID: %08x\r\n", DBGMCU_GetCHIPID()); while (1) {} } /* Expected output: SystemClk: 144000000 Hz ChipID: 20380500 */ ``` -------------------------------- ### Performance Run Compilation Source: https://github.com/openwch/ch32v20x/blob/main/EVT/EXAM/APPLICATION/CoreMark/coremark/README.md Use this command to compile and run the benchmark for performance testing. Ensure XCFLAGS is set to DPERFORMANCE_RUN=1. ```makefile % make XCFLAGS="-DPERFORMANCE_RUN=1" REBUILD=1 run1.log ``` -------------------------------- ### Initialize ADC1 with DMA and Configure GPIO Source: https://context7.com/openwch/ch32v20x/llms.txt Configures ADC1 for continuous conversion mode with DMA transfer. Hardware calibration is performed to correct offset errors. Ensure the ADC clock is configured appropriately. ```c #include "debug.h" #define SAMPLES 1024 u16 TxBuf[SAMPLES]; vs16 Calibrattion_Val = 0; void ADC_Function_Init(void) { ADC_InitTypeDef ADC_InitStructure = {0}; GPIO_InitTypeDef GPIO_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2PeriphClock_GPIOA | RCC_APB2Periph_ADC1, ENABLE); RCC_ADCCLKConfig(RCC_PCLK2_Div8); /* ADC clock ≤ 14 MHz */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; /* PA1 = ADC_CH1 */ GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN; GPIO_Init(GPIOA, &GPIO_InitStructure); ADC_InitStructure.ADC_Mode = ADC_Mode_Independent; ADC_InitStructure.ADC_ScanConvMode = DISABLE; ADC_InitStructure.ADC_ContinuousConvMode = ENABLE; ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right; ADC_InitStructure.ADC_NbrOfChannel = 1; ADC_Init(ADC1, &ADC_InitStructure); ADC_DMACmd(ADC1, ENABLE); ADC_Cmd(ADC1, ENABLE); ADC_BufferCmd(ADC1,DISABLE); ADC_ResetCalibration(ADC1); while (ADC_GetResetCalibrationStatus(ADC1)); ADC_StartCalibration(ADC1); while (ADC_GetCalibrationStatus(ADC1)); Calibrattion_Val = Get_CalibrationValue(ADC1); } ``` -------------------------------- ### Cross-compiling CoreMark Source: https://github.com/openwch/ch32v20x/blob/main/EVT/EXAM/APPLICATION/CoreMark/coremark/README.md Adjust core_portme.mak, core_portme.h, and core_portme.c for cross-compilation. Copy default port folders and modify them for your specific platform. ```makefile % make PORT_DIR= ``` -------------------------------- ### Running CoreMark with custom iterations Source: https://github.com/openwch/ch32v20x/blob/main/EVT/EXAM/APPLICATION/CoreMark/coremark/README.md Override the default benchmark run time (10-100 seconds) by specifying the number of iterations using the ITERATIONS flag. This is recommended for simulators, power measurements, or when timing cannot be restarted. ```makefile % make ITERATIONS=10 ``` -------------------------------- ### Software Delay Functions Source: https://context7.com/openwch/ch32v20x/llms.txt Initializes software delay routines based on the SysTick counter and provides functions for microsecond and millisecond delays. Delay_Init() must be called after SystemCoreClockUpdate(). ```c #include "debug.h" int main(void) { SystemCoreClockUpdate(); Delay_Init(); /* compute p_us and p_ms from SystemCoreClock */ while (1) { Delay_Us(500); /* block for 500 µs */ Delay_Ms(250); /* block for 250 ms */ } } ``` -------------------------------- ### Configure and Read System Clocks Source: https://context7.com/openwch/ch32v20x/llms.txt Initializes system clocks, retrieves current clock frequencies, and configures PA8 to output the system clock (MCO). This is useful for oscilloscope verification. ```c #include "debug.h" int main(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; RCC_ClocksTypeDef RCC_ClocksStatus = {0}; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); SystemCoreClockUpdate(); USART_Printf_Init(115200); RCC_GetClocksFreq(&RCC_ClocksStatus); printf("SYSCLK = %d Hz\r\n", RCC_ClocksStatus.SYSCLK_Frequency); printf("HCLK = %d Hz\r\n", RCC_ClocksStatus.HCLK_Frequency); printf("PCLK1 = %d Hz\r\n", RCC_ClocksStatus.PCLK1_Frequency); printf("PCLK2 = %d Hz\r\n", RCC_ClocksStatus.PCLK2_Frequency); /* Output SYSCLK on PA8 (MCO pin) for oscilloscope verification */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); RCC_MCOConfig(RCC_MCO_SYSCLK); while (1) {} } /* Output: SYSCLK = 144000000 Hz HCLK = 144000000 Hz PCLK1 = 36000000 Hz PCLK2 = 144000000 Hz */ ``` -------------------------------- ### Initialize and Use RTC Calendar Source: https://context7.com/openwch/ch32v20x/llms.txt Initializes the RTC using the LSE crystal, sets a specific date and time, and then continuously retrieves and prints the current time. Ensure RTC_Init returns 0 for success. ```c #include "debug.h" typedef struct { vu16 w_year; vu8 w_month, w_date, week, hour, min, sec; } _calendar_obj; _calendar_obj calendar; extern u8 RTC_Init(void); extern u8 RTC_Set(u16 y, u8 mo, u8 d, u8 h, u8 mi, u8 s); extern u8 RTC_Get(void); int main(void) { NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init(115200); if (RTC_Init() != 0) { printf("RTC Init FAIL\r\n"); while (1); } /* Adjust time to 2024-06-01 08:00:00 */ RTC_Set(2024, 6, 1, 8, 0, 0); while (1) { Delay_Ms(1000); RTC_Get(); printf("%04d-%02d-%02d %d %02d:%02d:%02d\r\n", calendar.w_year, calendar.w_month, calendar.w_date, calendar.week, calendar.hour, calendar.min, calendar.sec); } } /* Output (increments each second): 2024-06-01 6 08:00:01 2024-06-01 6 08:00:02 ... */ ``` -------------------------------- ### Enter Sleep Mode with EXTI Wake-up (C) Source: https://context7.com/openwch/ch32v20x/llms.txt Configures the system to enter low-power sleep mode and wake up using an external interrupt on PA0. Ensure unused GPIO pins are configured as pull-down inputs to minimize leakage. ```c #include "debug.h" void EXTI0_INT_INIT(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; EXTI_InitTypeDef EXTI_InitStructure = {0}; NVIC_InitTypeDef NVIC_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); EXTI_InitStructure.EXTI_Line = EXTI_Line0; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } int main(void) { GPIO_InitTypeDef GPIO_InitStructure = {0}; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); SystemCoreClockUpdate(); Delay_Init(); Delay_Ms(1000); /* Pull down all unused pins to minimize current */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD | RCC_APB2Periph_AFIO, ENABLE); GPIO_PinRemapConfig(GPIO_Remap_SWJ_Disable, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_All; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_Init(GPIOD, &GPIO_InitStructure); USART_Printf_Init(115200); EXTI0_INT_INIT(); printf("Entering sleep...\r\n"); __WFI(); /* CPU halts here; peripherals keep running */ printf("Woke up from EXTI0\r\n"); while (1) { Delay_Ms(1000); printf("Running\r\n"); } } ``` -------------------------------- ### Validation Run Compilation Source: https://github.com/openwch/ch32v20x/blob/main/EVT/EXAM/APPLICATION/CoreMark/coremark/README.md Use this command to compile and run the benchmark for validation. Ensure XCFLAGS is set to DVALIDATION_RUN=1. ```makefile % make XCFLAGS="-DVALIDATION_RUN=1" REBUILD=1 run2.log ``` -------------------------------- ### Forcing a rebuild with REBUILD Source: https://github.com/openwch/ch32v20x/blob/main/EVT/EXAM/APPLICATION/CoreMark/coremark/README.md Use the REBUILD flag to force a complete rebuild of the benchmark executable, overwriting any existing compiled files. ```makefile % make REBUILD ``` -------------------------------- ### Delay Functions Source: https://context7.com/openwch/ch32v20x/llms.txt Provides software delay routines using the RISC-V SysTick counter. `Delay_Init()` must be called after `SystemCoreClockUpdate()`, and `Delay_Us()` or `Delay_Ms()` can be used for blocking delays. ```APIDOC ## Delay Functions — `Delay_Init` / `Delay_Us` / `Delay_Ms` Software delay routines backed by the RISC-V SysTick counter. `Delay_Init()` must be called once after `SystemCoreClockUpdate()` to derive the per-tick multipliers. `Delay_Us` and `Delay_Ms` block until the requested interval elapses by polling the SysTick `SR` flag. ```c #include "debug.h" int main(void) { SystemCoreClockUpdate(); Delay_Init(); /* compute p_us and p_ms from SystemCoreClock */ while (1) { Delay_Us(500); /* block for 500 µs */ Delay_Ms(250); /* block for 250 ms */ } } ``` ``` -------------------------------- ### Initialize I2C Peripheral for 7-bit Mode Source: https://context7.com/openwch/ch32v20x/llms.txt Configures the I2C1 peripheral for master or slave operation with 7-bit addressing. Ensure correct GPIO remapping and clock enable for I2C and AFIO. ```c #include "debug.h" #define I2C_MODE HOST_MODE /* or SLAVE_MODE on the second board */ #define HOST_MODE 0 #define SLAVE_MODE 1 #define SIZE 6 #define SLAVE_ADDR 0x02 u8 TxData[SIZE] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; u8 RxData[SIZE]; void IIC_Init(u32 speed, u16 ownAddr) { GPIO_InitTypeDef GPIO_InitStructure = {0}; I2C_InitTypeDef I2C_InitStructure = {0}; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE); GPIO_PinRemapConfig(GPIO_Remap_I2C1, ENABLE); /* SCL→PB8, SDA→PB9 */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStructure); I2C_InitStructure.I2C_ClockSpeed = speed; I2C_InitStructure.I2C_Mode = I2C_Mode_I2C; I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_16_9; I2C_InitStructure.I2C_OwnAddress1 = ownAddr; I2C_InitStructure.I2C_Ack = I2C_Ack_Enable; I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; I2C_Init(I2C1, &I2C_InitStructure); I2C_Cmd(I2C1, ENABLE); } ``` -------------------------------- ### CoreMark Log File Format Source: https://github.com/openwch/ch32v20x/blob/main/EVT/EXAM/APPLICATION/CoreMark/coremark/README.md The standard format of a CoreMark log file, detailing run parameters, performance metrics, and validation status. ```text 2K performance run parameters for coremark. (Run type) CoreMark Size : 666 (Buffer size) Total ticks : 25875 (platform dependent value) Total time (secs) : 25.875000 (actual time in seconds) Iterations/Sec : 3864.734300 (Performance value to report) Iterations : 100000 (number of iterations used) Compiler version : GCC3.4.4 (Compiler and version) Compiler flags : -O2 (Compiler and linker flags) Memory location : Code in flash, data in on chip RAM seedcrc : 0xe9f5 (identifier for the input seeds) [0]crclist : 0xe714 (validation for list part) [0]crcmatrix : 0x1fd7 (validation for matrix part) [0]crcstate : 0x8e3a (validation for state part) [0]crcfinal : 0x33ff (iteration dependent output) Correct operation validated. See README.md for run and reporting rules. (*Only when run is successful*) CoreMark 1.0 : 6508.490622 / GCC3.4.4 -O2 / Heap (*Only on a successful performance run*) ``` -------------------------------- ### Main Function with Polling Transmit and Interrupt Receive Source: https://context7.com/openwch/ch32v20x/llms.txt Initializes the system and USART, then demonstrates polling for transmitting a message. It continuously checks for received bytes via interrupt and echoes them back. ```c int main(void) { const u8 msg[] = "Hello from CH32V203\r\n"; u8 i; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1); SystemCoreClockUpdate(); Delay_Init(); USART_Printf_Init(115200); USARTx_CFG(); /* Polling transmit of message via USART2 */ for (i = 0; i < sizeof(msg) - 1; i++) { USART_SendData(USART2, msg[i]); while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET) {} } while (1) { if (rx_byte) { printf("Echo: %c\r\n", rx_byte); rx_byte = 0; } } } ``` -------------------------------- ### Enabling debug mode with CORE_DEBUG Source: https://github.com/openwch/ch32v20x/blob/main/EVT/EXAM/APPLICATION/CoreMark/coremark/README.md Define CORE_DEBUG=1 using XCFLAGS to compile for a debug run, which can help resolve incorrect CRC issues. ```makefile % make XCFLAGS="-DCORE_DEBUG=1" ```