Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CH59x bringup and blinky #534

Merged
merged 6 commits into from
Mar 12, 2025
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 166 additions & 4 deletions ch32fun/ch32fun.c
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,24 @@ void USBPD_WKUP_IRQHandler( void ) __attribute__((section(".text.vector_handler
void TIM2_CC_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void TIM2_TRG_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void TIM2_BRK_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
// CH59x
void TMR0_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void GPIOA_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void GPIOB_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void SPI0_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void USB_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void TMR1_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void TMR2_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void UART0_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void UART1_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void ADC_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void I2C_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void PWMX_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void TMR3_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void UART2_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void UART3_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));
void WDOG_BAT_IRQHandler( void ) __attribute__((section(".text.vector_handler"))) __attribute((weak,alias("DefaultIRQHandler"))) __attribute__((used));



void InterruptVector() __attribute__((naked)) __attribute((section(".init"))) __attribute((weak,alias("InterruptVectorDefault"))) __attribute((naked));
Expand Down Expand Up @@ -1060,7 +1078,7 @@ asm volatile(
" mret\n" : : [main]"r"(main) );
}

#elif defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x)
#elif defined(CH32V10x) || defined(CH32V20x) || defined(CH32V30x) || defined(CH59x)

void handle_reset( void )
{
Expand Down Expand Up @@ -1472,7 +1490,7 @@ void DelaySysTick( uint32_t n )
#ifdef CH32V003
uint32_t targend = SysTick->CNT + n;
while( ((int32_t)( SysTick->CNT - targend )) < 0 );
#elif defined(CH32V20x) || defined(CH32V30x)
#elif defined(CH32V20x) || defined(CH32V30x) || defined(CH59x)
uint64_t targend = SysTick->CNT + n;
while( ((int64_t)( SysTick->CNT - targend )) < 0 );
#elif defined(CH32V10x) || defined(CH32X03x)
Expand All @@ -1483,6 +1501,144 @@ void DelaySysTick( uint32_t n )
#endif
}

#if defined(CH59x)
/**
* @brief Enter safe access mode.
*
* @NOTE: After enter safe access mode, about 16 system frequency cycles
* are in safe mode, and one or more secure registers can be rewritten
* within the valid period. The safe mode will be automatically
* terminated after the above validity period is exceeded.
*/
vu32 IRQ_STA = 0;
__attribute__( ( always_inline ) ) RV_STATIC_INLINE void sys_safe_access_enable(void)
{
if(read_csr(0x800) & 0x08)
{
IRQ_STA = read_csr(0x800);
write_csr(0x800, (IRQ_STA&(~0x08)));
}
ADD_N_NOPS(2);
R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG1;
R8_SAFE_ACCESS_SIG = SAFE_ACCESS_SIG2;
ADD_N_NOPS(2);
}

__attribute__( ( always_inline ) ) RV_STATIC_INLINE void sys_safe_access_disable(void)
{
R8_SAFE_ACCESS_SIG = 0;
write_csr(0x800, read_csr(0x800) | (IRQ_STA & 0x08));
IRQ_STA = 0;
ADD_N_NOPS(2);
}

void SetSysClock(SYS_CLKTypeDef sc)
{
sys_safe_access_enable();
R8_PLL_CONFIG &= ~(1 << 5); //
sys_safe_access_disable();
if(sc & 0x20) // HSE div
{
sys_safe_access_enable();
R32_CLK_SYS_CFG = (0 << 6) | (sc & 0x1f) | RB_TX_32M_PWR_EN | RB_PLL_PWR_EN;
ADD_N_NOPS(4);
sys_safe_access_disable();
sys_safe_access_enable();
ADD_N_NOPS(2);
R8_FLASH_CFG = 0X51;
sys_safe_access_disable();
}

else if(sc & 0x40) // PLL div
{
sys_safe_access_enable();
R32_CLK_SYS_CFG = (1 << 6) | (sc & 0x1f) | RB_TX_32M_PWR_EN | RB_PLL_PWR_EN;
ADD_N_NOPS(4);
sys_safe_access_disable();
sys_safe_access_enable();
R8_FLASH_CFG = 0X52;
sys_safe_access_disable();
}
else
{
sys_safe_access_enable();
R32_CLK_SYS_CFG |= RB_CLK_SYS_MOD;
sys_safe_access_disable();
}
sys_safe_access_enable();
R8_PLL_CONFIG |= 1 << 7;
sys_safe_access_disable();
}
void GPIOA_ModeCfg(uint32_t pin, GPIOModeTypeDef mode)
{
switch(mode)
{
case GPIO_ModeIN_Floating:
R32_PA_PD_DRV &= ~pin;
R32_PA_PU &= ~pin;
R32_PA_DIR &= ~pin;
break;
case GPIO_ModeIN_PU:
R32_PA_PD_DRV &= ~pin;
R32_PA_PU |= pin;
R32_PA_DIR &= ~pin;
break;
case GPIO_ModeIN_PD:
R32_PA_PD_DRV |= pin;
R32_PA_PU &= ~pin;
R32_PA_DIR &= ~pin;
break;
case GPIO_ModeOut_PP_5mA:
R32_PA_PD_DRV &= ~pin;
R32_PA_DIR |= pin;
break;
case GPIO_ModeOut_PP_20mA:
R32_PA_PD_DRV |= pin;
R32_PA_DIR |= pin;
break;
default:
break;
}
}

void GPIOB_ModeCfg(uint32_t pin, GPIOModeTypeDef mode)
{
switch(mode)
{
case GPIO_ModeIN_Floating:
R32_PB_PD_DRV &= ~pin;
R32_PB_PU &= ~pin;
R32_PB_DIR &= ~pin;
break;

case GPIO_ModeIN_PU:
R32_PB_PD_DRV &= ~pin;
R32_PB_PU |= pin;
R32_PB_DIR &= ~pin;
break;

case GPIO_ModeIN_PD:
R32_PB_PD_DRV |= pin;
R32_PB_PU &= ~pin;
R32_PB_DIR &= ~pin;
break;

case GPIO_ModeOut_PP_5mA:
R32_PB_PD_DRV &= ~pin;
R32_PB_DIR |= pin;
break;

case GPIO_ModeOut_PP_20mA:
R32_PB_PD_DRV |= pin;
R32_PB_DIR |= pin;
break;

default:
break;
}
}
#endif

void SystemInit( void )
{
#if defined(CH32V30x) && defined(TARGET_MCU_MEMORY_SPLIT)
Expand Down Expand Up @@ -1541,7 +1697,9 @@ void SystemInit( void )
#endif
#endif

#if defined(FUNCONF_USE_HSI) && FUNCONF_USE_HSI
#if defined(CH59x)
SetSysClock(CLK_SOURCE_PLL_60MHz);
#elif defined(FUNCONF_USE_HSI) && FUNCONF_USE_HSI
#if defined(CH32V30x) || defined(CH32V20x) || defined(CH32V10x)
EXTEN->EXTEN_CTR |= EXTEN_PLL_HSI_PRE;
#endif
Expand Down Expand Up @@ -1600,9 +1758,11 @@ void SystemInit( void )
#endif
#endif

#if !defined(CH59x)
RCC->INTR = 0x009F0000; // Clear PLL, CSSC, HSE, HSI and LSI ready flags.
#endif

#if defined(FUNCONF_USE_PLL) && FUNCONF_USE_PLL
#if defined(FUNCONF_USE_PLL) && FUNCONF_USE_PLL && !defined(CH59x)
while((RCC->CTLR & RCC_PLLRDY) == 0); // Wait till PLL is ready
uint32_t tmp32 = RCC->CFGR0 & ~(0x03); // clr the SW
RCC->CFGR0 = tmp32 | RCC_SW_PLL; // Select PLL as system clock source
Expand All @@ -1617,6 +1777,7 @@ void SystemInit( void )
#endif
}

#if defined(FUNCONF_INIT_ANALOG) && FUNCONF_INIT_ANALOG
void funAnalogInit( void )
{
//RCC->CFGR0 &= ~(0x1F<<11); // Assume ADCPRE = 0
Expand Down Expand Up @@ -1655,6 +1816,7 @@ int funAnalogRead( int nAnalogNumber )
// get result
return ADC1->RDATAR;
}
#endif

// C++ Support

Expand Down
18 changes: 16 additions & 2 deletions ch32fun/ch32fun.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,10 @@
#define FUNCONF_DEBUG_HARDFAULT 1
#endif

#if !defined( FUNCONF_INIT_ANALOG )
#define FUNCONF_INIT_ANALOG 1
#endif

#if defined( CH32X03x ) && FUNCONF_USE_PLL
#error No PLL on the X03x
#endif
Expand Down Expand Up @@ -160,6 +164,8 @@
#endif
#elif defined(CH32V30x)
#define HSE_VALUE (8000000)
#elif defined(CH59x)
#define HSE_VALUE (32000000)
#endif
#endif

Expand Down Expand Up @@ -348,6 +354,8 @@ typedef enum {RESET = 0, SET = !RESET} FlagStatus, ITStatus;
#include "ch32v20xhw.h"
#elif defined( CH32V30x )
#include "ch32v30xhw.h"
#elif defined( CH59x )
#include "ch59xhw.h"
#endif

#if defined(__riscv) || defined(__riscv__) || defined( CH32V003FUN_BASE )
Expand Down Expand Up @@ -817,11 +825,16 @@ extern "C" {
// and take two cycles, so you typically would use 0, 2, 4, etc.
#define ADD_N_NOPS( n ) asm volatile( ".rept " #n "\nc.nop\n.endr" );

#define FUN_HIGH 0x1
#define FUN_LOW 0x0
#if defined(CH59x)
#define funDigitalWrite( pin, value ) { if(value==FUN_HIGH){GPIOA_SetBits(pin);} else if(value==FUN_LOW){GPIOA_ResetBits(pin);} }
void GPIOA_ModeCfg(uint32_t pin, GPIOModeTypeDef mode);
#define funPinMode( pin, mode ) GPIOA_ModeCfg(pin, mode)
#else
// Arduino-like GPIO Functionality
#define GpioOf( pin ) ((GPIO_TypeDef *)(GPIOA_BASE + 0x400 * ((pin)>>4)))

#define FUN_HIGH 0x1
#define FUN_LOW 0x0
#define FUN_OUTPUT (GPIO_Speed_10MHz | GPIO_CNF_OUT_PP)
#define FUN_INPUT (GPIO_CNF_IN_FLOATING)

Expand All @@ -846,6 +859,7 @@ extern "C" {
#define funGpioInitC() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOC ); }
#define funGpioInitD() { RCC->APB2PCENR |= ( RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOD ); }
#define funDigitalRead( pin ) ((int)((GpioOf(pin)->INDR >> ((pin)&0xf)) & 1))
#endif


#define ANALOG_0 0
Expand Down
17 changes: 14 additions & 3 deletions ch32fun/ch32fun.ld
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,20 @@ MEMORY
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 32K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 6K
#elif TARGET_MCU_LD == 7
/* CH32V005, CH32V006, CH32V007 */
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 62K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
/* CH32V005, CH32V006, CH32V007 */
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 62K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
#elif TARGET_MCU_LD == 8
/* CH591/2 */
#if MCU_PACKAGE == 1
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 192K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 24K
#elif MCU_PACKAGE == 2
FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 448K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 24K
#else
#error "Unknown MCU package"
#endif
#else
#error "Unknown MCU target"
#endif
Expand Down
21 changes: 21 additions & 0 deletions ch32fun/ch32fun.mk
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,27 @@ else
endif

TARGET_MCU_LD:=3
else ifeq ($(findstring CH59,$(TARGET_MCU)),CH59) # CH592 1
TARGET_MCU_PACKAGE?=CH592F
CFLAGS_ARCH+=-march=rv32imac_zicsr \
-mabi=ilp32 \
-DCH59x=1

# MCU Flash/RAM split
ifeq ($(findstring 591, $(TARGET_MCU_PACKAGE)), 591)
MCU_PACKAGE:=1
else ifeq ($(findstring 592, $(TARGET_MCU_PACKAGE)), 592)
MCU_PACKAGE:=2
endif

# Package
ifeq ($(findstring D, $(TARGET_MCU_PACKAGE)), D)
CFLAGS+=-DCH59xD
else ifeq ($(findstring F, $(TARGET_MCU_PACKAGE)), F)
CFLAGS+=-DCH59xF
endif

TARGET_MCU_LD:=8
else
ERROR:=$(error Unknown MCU $(TARGET_MCU))
endif
Expand Down
Loading
Loading