From 555e8ccf7a554eb269e905b0adc59fca7948d840 Mon Sep 17 00:00:00 2001 From: cnlohr <lohr85@gmail.com> Date: Sun, 12 Mar 2023 23:52:18 -0400 Subject: [PATCH] Add examples using the external crystal/oscillator --- ch32v003fun/ch32v003fun.c | 31 ++++++++++++ ch32v003fun/ch32v003fun.h | 5 ++ examples/external_crystal/Makefile | 51 ++++++++++++++++++++ examples/external_crystal/external_crystal.c | 36 ++++++++++++++ 4 files changed, 123 insertions(+) create mode 100644 examples/external_crystal/Makefile create mode 100644 examples/external_crystal/external_crystal.c diff --git a/ch32v003fun/ch32v003fun.c b/ch32v003fun/ch32v003fun.c index c1d3dc2..e40153e 100644 --- a/ch32v003fun/ch32v003fun.c +++ b/ch32v003fun/ch32v003fun.c @@ -819,6 +819,37 @@ void SystemInit48HSI( void ) while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08); // Wait till PLL is used as system clock source } + +void SystemInitHSE( int HSEBYP ) +{ + // Values lifted from the EVT. There is little to no documentation on what this does. + RCC->CTLR = RCC_HSION | RCC_HSEON | RCC_PLLON | HSEBYP; // Enable HSE and keep HSI+PLL on. + while(!(RCC->CTLR&RCC_HSERDY)); + // Not using PLL. + FLASH->ACTLR = FLASH_ACTLR_LATENCY_0; // 1 Cycle Latency + RCC->INTR = 0x009F0000; // Clear PLL, CSSC, HSE, HSI and LSI ready flags. + RCC->CFGR0 = RCC_HPRE_DIV1 | RCC_SW_HSE; // HCLK = SYSCLK = APB1 and use HSE for System Clock. + while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x04); // Wait till HSE is used as system clock source + RCC->CTLR = RCC_HSEON | HSEBYP; // Turn off HSI + PLL. +} + + +void SystemInitHSEPLL( int HSEBYP ) +{ + // Values lifted from the EVT. There is little to no documentation on what this does. + RCC->CTLR = RCC_HSION | RCC_HSEON | RCC_PLLON | HSEBYP; // Enable HSE and keep HSI+PLL on. + while(!(RCC->CTLR&RCC_HSERDY)); + RCC->CFGR0 = RCC_SW_HSE | RCC_HPRE_DIV1; // HCLK = SYSCLK = APB1 and use HSE for System Clock. + RCC->CTLR = RCC_HSEON | HSEBYP; // Turn off PLL and HSI. + RCC->CFGR0 = RCC_SW_HSE | RCC_HPRE_DIV1 | RCC_PLLSRC_HSE_Mul2; // Use PLL with HSE. + RCC->CTLR = RCC_HSEON | RCC_PLLON | HSEBYP; // Turn PLL Back on.. + while((RCC->CTLR & RCC_PLLRDY) == 0); // Wait till PLL is ready + RCC->CFGR0 = RCC_SW_PLL | RCC_HPRE_DIV1 | RCC_PLLSRC_HSE_Mul2; // Select PLL as system clock source + while ((RCC->CFGR0 & (uint32_t)RCC_SWS) != (uint32_t)0x08); // Wait till PLL is used as system clock source +} + + + void SetupUART( int uartBRR ) { // Enable GPIOD and UART. diff --git a/ch32v003fun/ch32v003fun.h b/ch32v003fun/ch32v003fun.h index 5639341..3115d7c 100644 --- a/ch32v003fun/ch32v003fun.h +++ b/ch32v003fun/ch32v003fun.h @@ -4833,6 +4833,11 @@ void SystemInit(void) __attribute__((used)); // Useful functions void SystemInit48HSI( void ); +// NOTE: HSEBYP is ORed with RCC_CTLR. Set it to RCC_HSEBYP or 0. +// If you are using an external oscillator, set it to RCC_HSEBYP. Otherwise, if you are using a crystal, it must be 0. +void SystemInitHSE( int HSEBYP ); +void SystemInitHSEPLL( int HSEBYP ); + #define UART_BAUD_RATE 115200 #define OVER8DIV 4 diff --git a/examples/external_crystal/Makefile b/examples/external_crystal/Makefile new file mode 100644 index 0000000..4f4b542 --- /dev/null +++ b/examples/external_crystal/Makefile @@ -0,0 +1,51 @@ +TARGET:=external_crystal + +all : flash + +PREFIX:=riscv64-unknown-elf + +GPIO_Toggle:=EXAM/GPIO/GPIO_Toggle/User + +EVT:=../../ch32v003evt + +MINICHLINK:=../../minichlink + +ifeq ($(OS),Windows_NT) +# On Windows, all the major RISC-V GCC installs are missing the -ec libgcc. +LIB_GCC=../../misc/libgcc.a +else +LIB_GCC=-lgcc +endif + +CH32V003FUN:=../../ch32v003fun + +CFLAGS:= \ + -g -Os -flto -ffunction-sections \ + -static-libgcc $(LIB_GCC) \ + -march=rv32ec \ + -mabi=ilp32e \ + -I/usr/include/newlib \ + -I$(CH32V003FUN) \ + -nostdlib \ + -I. -DTINYVECTOR + +LDFLAGS:=-T $(CH32V003FUN)/ch32v003fun.ld -Wl,--gc-sections + +SYSTEM_C:=$(CH32V003FUN)/ch32v003fun.c + +$(TARGET).elf : $(SYSTEM_C) $(TARGET).c + $(PREFIX)-gcc -o $@ $^ $(CFLAGS) $(LDFLAGS) + +$(TARGET).bin : $(TARGET).elf + $(PREFIX)-size $^ + $(PREFIX)-objdump -S $^ > $(TARGET).lst + $(PREFIX)-objdump -t $^ > $(TARGET).map + $(PREFIX)-objcopy -O binary $< $(TARGET).bin + $(PREFIX)-objcopy -O ihex $< $(TARGET).hex + +flash : $(TARGET).bin + $(MINICHLINK)/minichlink -w $< flash -b + +clean : + rm -rf $(TARGET).elf $(TARGET).bin $(TARGET).hex $(TARGET).lst $(TARGET).map $(TARGET).hex + diff --git a/examples/external_crystal/external_crystal.c b/examples/external_crystal/external_crystal.c new file mode 100644 index 0000000..55de9d2 --- /dev/null +++ b/examples/external_crystal/external_crystal.c @@ -0,0 +1,36 @@ +// XXX XXX XXX XXX XXX THIS IS UNTESTED XXX XXX XXX XXX XXX + +// Could be defined here, or in the processor defines. +#define SYSTEM_CORE_CLOCK 24000000 + +#include "ch32v003fun.h" +#include <stdio.h> + +#define APB_CLOCK SYSTEM_CORE_CLOCK + +uint32_t count; + +int main() +{ + SystemInitHSE( 0 ); + + // Enable GPIOD. + RCC->APB2PCENR |= RCC_APB2Periph_GPIOD; + + // GPIO D0 Push-Pull, 10MHz Output + GPIOD->CFGLR &= ~(0xf<<(4*0)); + GPIOD->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*0); + + // GPIO D0 Push-Pull, 10MHz Output + GPIOD->CFGLR &= ~(0xf<<(4*4)); + GPIOD->CFGLR |= (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)<<(4*4); + + while(1) + { + GPIOD->BSHR = 1 | (1<<4); // Turn on GPIOD0 + Delay_Ms( 200 ); + GPIOD->BSHR = (1<<16) | (1<<(16+4)); // Turn off GPIOD0 + Delay_Ms( 200 ); + count++; + } +} -- GitLab